]> git.saurik.com Git - apple/mdnsresponder.git/blob - mDNSVxWorks/mDNSVxWorksIPv4Only.c
mDNSResponder-107.6.tar.gz
[apple/mdnsresponder.git] / mDNSVxWorks / mDNSVxWorksIPv4Only.c
1 /* -*- Mode: C; tab-width: 4 -*-
2 *
3 * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16
17 Contains: mDNS platform plugin for VxWorks.
18
19 Copyright: Copyright (C) 2002-2004 Apple Computer, Inc., All Rights Reserved.
20
21 Change History (most recent first):
22
23 $Log: mDNSVxWorksIPv4Only.c,v $
24 Revision 1.29 2006/08/14 23:25:18 cheshire
25 Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
26
27 Revision 1.28 2006/03/19 02:00:12 cheshire
28 <rdar://problem/4073825> Improve logic for delaying packets after repeated interface transitions
29
30 Revision 1.27 2004/12/17 23:37:49 cheshire
31 <rdar://problem/3485365> Guard against repeating wireless dissociation/re-association
32 (and other repetitive configuration changes)
33
34 Revision 1.26 2004/10/28 02:00:35 cheshire
35 <rdar://problem/3841770> Call pipeDevDelete when disposing of commandPipe
36
37 Revision 1.25 2004/10/16 00:17:01 cheshire
38 <rdar://problem/3770558> Replace IP TTL 255 check with local subnet source address check
39
40 Revision 1.24 2004/09/21 21:02:56 cheshire
41 Set up ifname before calling mDNS_RegisterInterface()
42
43 Revision 1.23 2004/09/17 01:08:57 cheshire
44 Renamed mDNSClientAPI.h to mDNSEmbeddedAPI.h
45 The name "mDNSClientAPI.h" is misleading to new developers looking at this code. The interfaces
46 declared in that file are ONLY appropriate to single-address-space embedded applications.
47 For clients on general-purpose computers, the interfaces defined in dns_sd.h should be used.
48
49 Revision 1.22 2004/09/17 00:19:11 cheshire
50 For consistency with AllDNSLinkGroupv6, rename AllDNSLinkGroup to AllDNSLinkGroupv4
51
52 Revision 1.21 2004/09/16 00:24:50 cheshire
53 <rdar://problem/3803162> Fix unsafe use of mDNSPlatformTimeNow()
54
55 Revision 1.20 2004/09/14 23:42:36 cheshire
56 <rdar://problem/3801296> Need to seed random number generator from platform-layer data
57
58 Revision 1.19 2004/09/14 23:16:09 cheshire
59 mDNS_SetFQDNs has been renamed to mDNS_SetFQDN
60
61 Revision 1.18 2004/08/14 03:22:42 cheshire
62 <rdar://problem/3762579> Dynamic DNS UI <-> mDNSResponder glue
63 Add GetUserSpecifiedDDNSName() routine
64 Convert ServiceRegDomain to domainname instead of C string
65 Replace mDNS_GenerateFQDN/mDNS_GenerateGlobalFQDN with mDNS_SetFQDNs
66
67 Revision 1.17 2004/07/29 19:26:03 ksekar
68 Plaform-level changes for NATPMP support
69
70 Revision 1.16 2004/04/22 05:11:28 bradley
71 Added mDNSPlatformUTC for TSIG signed dynamic updates.
72
73 Revision 1.15 2004/04/21 02:49:12 cheshire
74 To reduce future confusion, renamed 'TxAndRx' to 'McastTxRx'
75
76 Revision 1.14 2004/04/09 17:43:04 cheshire
77 Make sure to set the McastTxRx field so that duplicate suppression works correctly
78
79 Revision 1.13 2004/01/27 20:15:24 cheshire
80 <rdar://problem/3541288>: Time to prune obsolete code for listening on port 53
81
82 Revision 1.12 2004/01/24 09:12:37 bradley
83 Avoid TOS socket options to workaround a TOS routing problem with VxWorks and multiple interfaces
84 when sending unicast responses, which resulted in packets going out the wrong interface.
85
86 Revision 1.11 2004/01/24 04:59:16 cheshire
87 Fixes so that Posix/Linux, OS9, Windows, and VxWorks targets build again
88
89 Revision 1.10 2003/11/14 21:27:09 cheshire
90 <rdar://problem/3484766>: Security: Crashing bug in mDNSResponder
91 Fix code that should use buffer size MAX_ESCAPED_DOMAIN_NAME (1005) instead of 256-byte buffers.
92
93 Revision 1.9 2003/11/14 20:59:09 cheshire
94 Clients can't use AssignDomainName macro because mDNSPlatformMemCopy is defined in mDNSPlatformFunctions.h.
95 Best solution is just to combine mDNSEmbeddedAPI.h and mDNSPlatformFunctions.h into a single file.
96
97 Revision 1.8 2003/10/28 10:08:27 bradley
98 Removed legacy port 53 support as it is no longer needed.
99
100 Revision 1.7 2003/08/20 05:58:54 bradley
101 Removed dependence on modified mDNSCore: define structures/prototypes locally.
102
103 Revision 1.6 2003/08/18 23:19:05 cheshire
104 <rdar://problem/3382647> mDNSResponder divide by zero in mDNSPlatformRawTime()
105
106 Revision 1.5 2003/08/15 00:05:04 bradley
107 Updated to use name/InterfaceID from new AuthRecord resrec field. Added output of new record sizes.
108
109 Revision 1.4 2003/08/14 02:19:55 cheshire
110 <rdar://problem/3375491> Split generic ResourceRecord type into two separate types: AuthRecord and CacheRecord
111
112 Revision 1.3 2003/08/12 19:56:27 cheshire
113 Update to APSL 2.0
114
115 Revision 1.2 2003/08/05 23:58:34 cheshire
116 Update code to compile with the new mDNSCoreReceive() function that requires a TTL
117 Right now this platform layer just reports 255 instead of returning the real value -- we should fix this
118
119 Revision 1.1 2003/08/02 10:06:48 bradley
120 mDNS platform plugin for VxWorks.
121
122
123 Notes for non-Apple platforms:
124
125 TARGET_NON_APPLE should be defined to 1 to avoid relying on Apple-only header files, macros, or functions.
126
127 To Do:
128
129 - Add support for IPv6 (needs VxWorks IPv6 support).
130 */
131
132 // Set up the debug library to use the default category (see DebugServicesLite.h for details).
133
134 #if( !TARGET_NON_APPLE )
135 #define DEBUG_USE_DEFAULT_CATEGORY 1
136 #endif
137
138 #include <stdarg.h>
139 #include <stddef.h>
140 #include <stdio.h>
141 #include <stdlib.h>
142 #include <string.h>
143
144 #include <sys/types.h>
145 #include <arpa/inet.h>
146 #include <fcntl.h>
147 #include <netinet/if_ether.h>
148 #include <netinet/in.h>
149 #include <netinet/ip.h>
150 #include <sys/ioctl.h>
151 #include <sys/socket.h>
152 #include <unistd.h>
153
154 #include "vxWorks.h"
155 #include "ifLib.h"
156 #include "inetLib.h"
157 #include "pipeDrv.h"
158 #include "selectLib.h"
159 #include "semLib.h"
160 #include "sockLib.h"
161 #include "sysLib.h"
162 #include "taskLib.h"
163 #include "tickLib.h"
164
165 #include "config.h"
166
167 #if( !TARGET_NON_APPLE )
168 #include "ACP/ACPUtilities.h"
169 #include "Support/DebugServicesLite.h"
170 #include "Support/MiscUtilities.h"
171 #endif
172
173 #include "mDNSEmbeddedAPI.h"
174
175 #include "mDNSVxWorks.h"
176
177 #if 0
178 #pragma mark == Preprocessor ==
179 #endif
180
181 //===========================================================================================================================
182 // Preprocessor
183 //===========================================================================================================================
184
185 #if( !TARGET_NON_APPLE )
186 debug_log_new_default_category( mdns );
187 #endif
188
189 #if 0
190 #pragma mark == Constants ==
191 #endif
192
193 //===========================================================================================================================
194 // Constants
195 //===========================================================================================================================
196
197 #define DEBUG_NAME "[mDNS] "
198
199 #define kMDNSDefaultName "My-Device"
200
201 #define kMDNSTaskName "tMDNS"
202 #define kMDNSTaskPriority 102
203 #define kMDNSTaskStackSize 49152
204
205 #define kMDNSPipeName "/pipe/mDNS"
206 #define kMDNSPipeMessageQueueSize 32
207 #define kMDNSPipeMessageSize 1
208
209 #define kInvalidSocketRef -1
210
211 typedef uint8_t MDNSPipeCommandCode;
212 enum
213 {
214 kMDNSPipeCommandCodeInvalid = 0,
215 kMDNSPipeCommandCodeReschedule = 1,
216 kMDNSPipeCommandCodeReconfigure = 2,
217 kMDNSPipeCommandCodeQuit = 3
218 };
219
220 #if 0
221 #pragma mark == Structures ==
222 #endif
223
224 //===========================================================================================================================
225 // Structures
226 //===========================================================================================================================
227
228 typedef int MDNSSocketRef;
229
230 struct MDNSInterfaceItem
231 {
232 MDNSInterfaceItem * next;
233 char name[ 32 ];
234 MDNSSocketRef multicastSocketRef;
235 MDNSSocketRef sendingSocketRef;
236 NetworkInterfaceInfo hostSet;
237 mDNSBool hostRegistered;
238
239 int sendMulticastCounter;
240 int sendUnicastCounter;
241 int sendErrorCounter;
242
243 int recvCounter;
244 int recvErrorCounter;
245 int recvLoopCounter;
246 };
247
248 #if 0
249 #pragma mark == Macros ==
250 #endif
251
252 //===========================================================================================================================
253 // Macros
254 //===========================================================================================================================
255
256 #if( TARGET_NON_APPLE )
257
258 // Do-nothing versions of the debugging macros for non-Apple platforms.
259
260 #define check(assertion)
261 #define check_string( assertion, cstring )
262 #define check_noerr(err)
263 #define check_noerr_string( error, cstring )
264 #define check_errno( assertion, errno_value )
265 #define debug_string( cstring )
266 #define require( assertion, label ) do { if( !(assertion) ) goto label; } while(0)
267 #define require_string( assertion, label, string ) require(assertion, label)
268 #define require_quiet( assertion, label ) require( assertion, label )
269 #define require_noerr( error, label ) do { if( (error) != 0 ) goto label; } while(0)
270 #define require_noerr_quiet( assertion, label ) require_noerr( assertion, label )
271 #define require_noerr_action( error, label, action ) do { if( (error) != 0 ) { {action;}; goto label; } } while(0)
272 #define require_noerr_action_quiet( assertion, label, action ) require_noerr_action( assertion, label, action )
273 #define require_action( assertion, label, action ) do { if( !(assertion) ) { {action;}; goto label; } } while(0)
274 #define require_action_quiet( assertion, label, action ) require_action( assertion, label, action )
275 #define require_action_string( assertion, label, action, cstring ) do { if( !(assertion) ) { {action;}; goto label; } } while(0)
276 #define require_errno( assertion, errno_value, label ) do { if( !(assertion) ) goto label; } while(0)
277 #define require_errno_action( assertion, errno_value, label, action ) do { if( !(assertion) ) { {action;}; goto label; } } while(0)
278
279 #define dlog( ARGS... )
280
281 #define DEBUG_UNUSED( X ) (void)( X )
282 #endif
283
284 #if 0
285 #pragma mark == Prototypes ==
286 #endif
287
288 //===========================================================================================================================
289 // Prototypes
290 //===========================================================================================================================
291
292 // ifIndexToIfp is in net/if.c, but not exported by net/if.h so provide it here.
293
294 extern struct ifnet * ifIndexToIfp(int ifIndex);
295
296 // Platform Internals
297
298 mDNSlocal void SetupNames( mDNS * const inMDNS );
299 mDNSlocal mStatus SetupInterfaceList( mDNS * const inMDNS );
300 mDNSlocal mStatus TearDownInterfaceList( mDNS * const inMDNS );
301 mDNSlocal mStatus SetupInterface( mDNS * const inMDNS, const struct ifaddrs *inAddr, MDNSInterfaceItem **outItem );
302 mDNSlocal mStatus TearDownInterface( mDNS * const inMDNS, MDNSInterfaceItem *inItem );
303 mDNSlocal mStatus
304 SetupSocket(
305 mDNS * const inMDNS,
306 const struct ifaddrs * inAddr,
307 mDNSIPPort inPort,
308 MDNSSocketRef * outSocketRef );
309
310 // Commands
311
312 mDNSlocal mStatus SetupCommandPipe( mDNS * const inMDNS );
313 mDNSlocal mStatus TearDownCommandPipe( mDNS * const inMDNS );
314 mDNSlocal mStatus SendCommand( const mDNS * const inMDNS, MDNSPipeCommandCode inCommandCode );
315 mDNSlocal mStatus ProcessCommand( mDNS * const inMDNS );
316 mDNSlocal void ProcessCommandReconfigure( mDNS *inMDNS );
317
318 // Threads
319
320 mDNSlocal mStatus SetupTask( mDNS * const inMDNS );
321 mDNSlocal mStatus TearDownTask( mDNS * const inMDNS );
322 mDNSlocal void Task( mDNS *inMDNS );
323 mDNSlocal mStatus TaskInit( mDNS *inMDNS );
324 mDNSlocal void TaskSetupReadSet( mDNS *inMDNS, fd_set *outReadSet, int *outMaxSocket );
325 mDNSlocal void TaskSetupTimeout( mDNS *inMDNS, mDNSs32 inNextTaskTime, struct timeval *outTimeout );
326 mDNSlocal void TaskProcessPacket( mDNS *inMDNS, MDNSInterfaceItem *inItem, MDNSSocketRef inSocketRef );
327
328 // Utilities
329
330 #if( TARGET_NON_APPLE )
331 mDNSlocal void GenerateUniqueHostName( char *outName, long *ioSeed );
332 mDNSlocal void GenerateUniqueDNSName( char *outName, long *ioSeed );
333 #endif
334
335 // Platform Accessors
336
337 #ifdef __cplusplus
338 extern "C" {
339 #endif
340
341 typedef struct mDNSPlatformInterfaceInfo mDNSPlatformInterfaceInfo;
342 struct mDNSPlatformInterfaceInfo
343 {
344 const char * name;
345 mDNSAddr ip;
346 };
347
348 mDNSexport mStatus mDNSPlatformInterfaceNameToID( mDNS * const inMDNS, const char *inName, mDNSInterfaceID *outID );
349 mDNSexport mStatus mDNSPlatformInterfaceIDToInfo( mDNS * const inMDNS, mDNSInterfaceID inID, mDNSPlatformInterfaceInfo *outInfo );
350
351 #ifdef __cplusplus
352 }
353 #endif
354
355 #if 0
356 #pragma mark == Globals ==
357 #endif
358
359 //===========================================================================================================================
360 // Globals
361 //===========================================================================================================================
362
363 mDNSlocal mDNS * gMDNSPtr = NULL;
364 mDNSlocal mDNS_PlatformSupport gMDNSPlatformSupport;
365 mDNSlocal mDNSs32 gMDNSTicksToMicrosecondsMultiplier = 0;
366
367 // Platform support
368
369 mDNSs32 mDNSPlatformOneSecond;
370
371 #if 0
372 #pragma mark -
373 #pragma mark == Public APIs ==
374 #endif
375
376 //===========================================================================================================================
377 // mDNSReconfigure
378 //===========================================================================================================================
379
380 void mDNSReconfigure( void )
381 {
382 // Send a "reconfigure" command to the MDNS task.
383
384 if( gMDNSPtr )
385 {
386 SendCommand( gMDNSPtr, kMDNSPipeCommandCodeReconfigure );
387 }
388 }
389
390 #if 0
391 #pragma mark -
392 #pragma mark == Platform Support ==
393 #endif
394
395 //===========================================================================================================================
396 // mDNSPlatformInit
397 //===========================================================================================================================
398
399 mStatus mDNSPlatformInit( mDNS * const inMDNS )
400 {
401 mStatus err;
402
403 dlog( kDebugLevelInfo, DEBUG_NAME "platform init\n" );
404
405 // Initialize variables.
406
407 memset( &gMDNSPlatformSupport, 0, sizeof( gMDNSPlatformSupport ) );
408 inMDNS->p = &gMDNSPlatformSupport;
409 inMDNS->p->commandPipe = ERROR;
410 inMDNS->p->task = ERROR;
411 inMDNS->p->rescheduled = 1; // Default to rescheduled until fully initialized.
412 mDNSPlatformOneSecond = sysClkRateGet();
413 gMDNSTicksToMicrosecondsMultiplier = ( 1000000L / mDNSPlatformOneSecond );
414
415 // Allocate semaphores.
416
417 inMDNS->p->lockID = semMCreate( SEM_Q_FIFO );
418 require_action( inMDNS->p->lockID, exit, err = mStatus_NoMemoryErr );
419
420 inMDNS->p->readyEvent = semBCreate( SEM_Q_FIFO, SEM_EMPTY );
421 require_action( inMDNS->p->readyEvent, exit, err = mStatus_NoMemoryErr );
422
423 inMDNS->p->quitEvent = semBCreate( SEM_Q_FIFO, SEM_EMPTY );
424 require_action( inMDNS->p->quitEvent, exit, err = mStatus_NoMemoryErr );
425
426 gMDNSPtr = inMDNS;
427
428 // Set up the task and wait for it to initialize. Initialization is done from the task instead of here to avoid
429 // stack space issues. Some of the initialization may require a larger stack than the current task supports.
430
431 err = SetupTask( inMDNS );
432 require_noerr( err, exit );
433
434 err = semTake( inMDNS->p->readyEvent, WAIT_FOREVER );
435 require_noerr( err, exit );
436 err = inMDNS->p->taskInitErr;
437 require_noerr( err, exit );
438
439 mDNSCoreInitComplete( inMDNS, err );
440
441 exit:
442 if( err )
443 {
444 mDNSPlatformClose( inMDNS );
445 }
446 dlog( kDebugLevelInfo, DEBUG_NAME "platform init done (err=%ld)\n", err );
447 return( err );
448 }
449
450 //===========================================================================================================================
451 // mDNSPlatformClose
452 //===========================================================================================================================
453
454 void mDNSPlatformClose( mDNS * const inMDNS )
455 {
456 mStatus err;
457
458 dlog( kDebugLevelInfo, DEBUG_NAME "platform close\n" );
459 check( inMDNS );
460
461 // Tear everything down.
462
463 err = TearDownTask( inMDNS );
464 check_noerr( err );
465
466 err = TearDownInterfaceList( inMDNS );
467 check_noerr( err );
468
469 err = TearDownCommandPipe( inMDNS );
470 check_noerr( err );
471
472 gMDNSPtr = NULL;
473
474 // Release semaphores.
475
476 if( inMDNS->p->quitEvent )
477 {
478 semDelete( inMDNS->p->quitEvent );
479 inMDNS->p->quitEvent = 0;
480 }
481 if( inMDNS->p->readyEvent )
482 {
483 semDelete( inMDNS->p->readyEvent );
484 inMDNS->p->readyEvent = 0;
485 }
486 if( inMDNS->p->lockID )
487 {
488 semDelete( inMDNS->p->lockID );
489 inMDNS->p->lockID = 0;
490 }
491
492 dlog( kDebugLevelInfo, DEBUG_NAME "platform close done\n" );
493 }
494
495 //===========================================================================================================================
496 // mDNSPlatformSendUDP
497 //===========================================================================================================================
498
499 mStatus
500 mDNSPlatformSendUDP(
501 const mDNS * const inMDNS,
502 const void * const inMsg,
503 const mDNSu8 * const inMsgEnd,
504 mDNSInterfaceID inInterfaceID,
505 const mDNSAddr * inDstIP,
506 mDNSIPPort inDstPort )
507 {
508 mStatus err;
509 MDNSInterfaceItem * item;
510 struct sockaddr_in addr;
511 int n;
512
513 dlog( kDebugLevelChatty, DEBUG_NAME "platform send UDP\n" );
514
515 // Check parameters.
516
517 check( inMDNS );
518 check( inMsg );
519 check( inMsgEnd );
520 check( inInterfaceID );
521 check( inDstIP );
522 if( inDstIP->type != mDNSAddrType_IPv4 )
523 {
524 err = mStatus_BadParamErr;
525 goto exit;
526 }
527
528 #if( DEBUG )
529 // Make sure the InterfaceID is valid.
530
531 for( item = inMDNS->p->interfaceList; item; item = item->next )
532 {
533 if( item == (MDNSInterfaceItem *) inInterfaceID )
534 {
535 break;
536 }
537 }
538 require_action( item, exit, err = mStatus_NoSuchNameErr );
539 #endif
540
541 // Send the packet.
542
543 item = (MDNSInterfaceItem *) inInterfaceID;
544 check( item->sendingSocketRef != kInvalidSocketRef );
545
546 memset( &addr, 0, sizeof( addr ) );
547 addr.sin_family = AF_INET;
548 addr.sin_port = inDstPort.NotAnInteger;
549 addr.sin_addr.s_addr = inDstIP->ip.v4.NotAnInteger;
550
551 n = inMsgEnd - ( (const mDNSu8 * const) inMsg );
552 n = sendto( item->sendingSocketRef, (char *) inMsg, n, 0, (struct sockaddr *) &addr, sizeof( addr ) );
553 check_errno( n, errno );
554
555 item->sendErrorCounter += ( n < 0 );
556 item->sendMulticastCounter += ( inDstPort.NotAnInteger == MulticastDNSPort.NotAnInteger );
557 item->sendUnicastCounter += ( inDstPort.NotAnInteger != MulticastDNSPort.NotAnInteger );
558
559 dlog( kDebugLevelChatty, DEBUG_NAME "sent (to=%u.%u.%u.%u:%hu)\n",
560 inDstIP->ip.v4.b[ 0 ], inDstIP->ip.v4.b[ 1 ], inDstIP->ip.v4.b[ 2 ], inDstIP->ip.v4.b[ 3 ],
561 htons( inDstPort.NotAnInteger ) );
562 err = mStatus_NoError;
563
564 exit:
565 dlog( kDebugLevelChatty, DEBUG_NAME "platform send UDP done\n" );
566 return( err );
567 }
568
569 //===========================================================================================================================
570 // Connection-oriented (TCP) functions
571 //===========================================================================================================================
572
573 mDNSexport mStatus mDNSPlatformTCPConnect(const mDNSAddr *dst, mDNSOpaque16 dstport, mDNSInterfaceID InterfaceID,
574 TCPConnectionCallback callback, void *context, int *descriptor)
575 {
576 (void)dst; // Unused
577 (void)dstport; // Unused
578 (void)InterfaceID; // Unused
579 (void)callback; // Unused
580 (void)context; // Unused
581 (void)descriptor; // Unused
582 return(mStatus_UnsupportedErr);
583 }
584
585 mDNSexport void mDNSPlatformTCPCloseConnection(int sd)
586 {
587 (void)sd; // Unused
588 }
589
590 mDNSexport int mDNSPlatformReadTCP(int sd, void *buf, int buflen)
591 {
592 (void)sd; // Unused
593 (void)buf; // Unused
594 (void)buflen; // Unused
595 return(0);
596 }
597
598 mDNSexport int mDNSPlatformWriteTCP(int sd, const char *msg, int len)
599 {
600 (void)sd; // Unused
601 (void)msg; // Unused
602 (void)len; // Unused
603 return(0);
604 }
605
606 //===========================================================================================================================
607 // mDNSPlatformLock
608 //===========================================================================================================================
609
610 void mDNSPlatformLock( const mDNS * const inMDNS )
611 {
612 check( inMDNS->p->lockID );
613
614 if( inMDNS->p->lockID )
615 {
616 #if( TARGET_NON_APPLE )
617 semTake( inMDNS->p->lockID, WAIT_FOREVER );
618 #else
619 semTakeDeadlockDetect( inMDNS->p->lockID, WAIT_FOREVER );
620 #endif
621 }
622 }
623
624 //===========================================================================================================================
625 // mDNSPlatformUnlock
626 //===========================================================================================================================
627
628 void mDNSPlatformUnlock( const mDNS * const inMDNS )
629 {
630 check( inMDNS );
631 check( inMDNS->p );
632 check( inMDNS->p->lockID );
633 check_string( inMDNS->p->task != ERROR, "mDNS task not started" );
634
635 // When an API routine is called, "m->NextScheduledEvent" is reset to "timenow" before calling mDNSPlatformUnlock()
636 // Since our main mDNS_Execute() loop is on a different thread, we need to wake up that thread to:
637 // (a) handle immediate work (if any) resulting from this API call
638 // (b) calculate the next sleep time between now and the next interesting event
639
640 if( ( mDNS_TimeNow(inMDNS) - inMDNS->NextScheduledEvent ) >= 0 )
641 {
642 // We only need to send the reschedule event when called from a task other than the mDNS task since if we are
643 // called from mDNS task, we'll loop back and call mDNS_Execute. This avoids filling up the command queue.
644
645 if( ( inMDNS->p->rescheduled++ == 0 ) && ( taskIdSelf() != inMDNS->p->task ) )
646 {
647 SendCommand( inMDNS, kMDNSPipeCommandCodeReschedule );
648 }
649 }
650
651 if( inMDNS->p->lockID )
652 {
653 semGive( inMDNS->p->lockID );
654 }
655 }
656
657 //===========================================================================================================================
658 // mDNSPlatformStrLen
659 //===========================================================================================================================
660
661 mDNSu32 mDNSPlatformStrLen( const void *inSrc )
662 {
663 check( inSrc );
664
665 return( (mDNSu32) strlen( (const char *) inSrc ) );
666 }
667
668 //===========================================================================================================================
669 // mDNSPlatformStrCopy
670 //===========================================================================================================================
671
672 void mDNSPlatformStrCopy( const void *inSrc, void *inDst )
673 {
674 check( inSrc );
675 check( inDst );
676
677 strcpy( (char *) inDst, (const char*) inSrc );
678 }
679
680 //===========================================================================================================================
681 // mDNSPlatformMemCopy
682 //===========================================================================================================================
683
684 void mDNSPlatformMemCopy( const void *inSrc, void *inDst, mDNSu32 inSize )
685 {
686 check( inSrc );
687 check( inDst );
688
689 memcpy( inDst, inSrc, inSize );
690 }
691
692 //===========================================================================================================================
693 // mDNSPlatformMemSame
694 //===========================================================================================================================
695
696 mDNSBool mDNSPlatformMemSame( const void *inSrc, const void *inDst, mDNSu32 inSize )
697 {
698 check( inSrc );
699 check( inDst );
700
701 return( memcmp( inSrc, inDst, inSize ) == 0 );
702 }
703
704 //===========================================================================================================================
705 // mDNSPlatformMemZero
706 //===========================================================================================================================
707
708 void mDNSPlatformMemZero( void *inDst, mDNSu32 inSize )
709 {
710 check( inDst );
711
712 memset( inDst, 0, inSize );
713 }
714
715 //===========================================================================================================================
716 // mDNSPlatformMemAllocate
717 //===========================================================================================================================
718
719 mDNSexport void * mDNSPlatformMemAllocate( mDNSu32 inSize )
720 {
721 void * mem;
722
723 check( inSize > 0 );
724
725 mem = malloc( inSize );
726 check( mem );
727
728 return( mem );
729 }
730
731 //===========================================================================================================================
732 // mDNSPlatformMemFree
733 //===========================================================================================================================
734
735 mDNSexport void mDNSPlatformMemFree( void *inMem )
736 {
737 check( inMem );
738
739 free( inMem );
740 }
741
742 //===========================================================================================================================
743 // mDNSPlatformRandomSeed
744 //===========================================================================================================================
745
746 mDNSexport mDNSu32 mDNSPlatformRandomSeed(void)
747 {
748 return( tickGet() );
749 }
750
751 //===========================================================================================================================
752 // mDNSPlatformTimeInit
753 //===========================================================================================================================
754
755 mDNSexport mStatus mDNSPlatformTimeInit( void )
756 {
757 // No special setup is required on VxWorks -- we just use tickGet().
758 return( mStatus_NoError );
759 }
760
761 //===========================================================================================================================
762 // mDNSPlatformRawTime
763 //===========================================================================================================================
764
765 mDNSs32 mDNSPlatformRawTime( void )
766 {
767 return( (mDNSs32) tickGet() );
768 }
769
770 //===========================================================================================================================
771 // mDNSPlatformUTC
772 //===========================================================================================================================
773
774 mDNSexport mDNSs32 mDNSPlatformUTC( void )
775 {
776 return( -1 );
777 }
778
779 //===========================================================================================================================
780 // mDNSPlatformInterfaceNameToID
781 //===========================================================================================================================
782
783 mStatus mDNSPlatformInterfaceNameToID( mDNS * const inMDNS, const char *inName, mDNSInterfaceID *outID )
784 {
785 mStatus err;
786 MDNSInterfaceItem * ifd;
787
788 check( inMDNS );
789 check( inMDNS->p );
790 check( inName );
791
792 // Search for an interface with the specified name,
793
794 for( ifd = inMDNS->p->interfaceList; ifd; ifd = ifd->next )
795 {
796 if( strcmp( ifd->name, inName ) == 0 )
797 {
798 break;
799 }
800 }
801 if( !ifd )
802 {
803 err = mStatus_NoSuchNameErr;
804 goto exit;
805 }
806
807 // Success!
808
809 if( outID )
810 {
811 *outID = (mDNSInterfaceID) ifd;
812 }
813 err = mStatus_NoError;
814
815 exit:
816 return( err );
817 }
818
819 //===========================================================================================================================
820 // mDNSPlatformInterfaceIDToInfo
821 //===========================================================================================================================
822
823 mStatus mDNSPlatformInterfaceIDToInfo( mDNS * const inMDNS, mDNSInterfaceID inID, mDNSPlatformInterfaceInfo *outInfo )
824 {
825 mStatus err;
826 MDNSInterfaceItem * ifd;
827
828 check( inMDNS );
829 check( inID );
830 check( outInfo );
831
832 // Search for an interface with the specified ID,
833
834 for( ifd = inMDNS->p->interfaceList; ifd; ifd = ifd->next )
835 {
836 if( ifd == (MDNSInterfaceItem *) inID )
837 {
838 break;
839 }
840 }
841 if( !ifd )
842 {
843 err = mStatus_NoSuchNameErr;
844 goto exit;
845 }
846
847 // Success!
848
849 outInfo->name = ifd->name;
850 outInfo->ip = ifd->hostSet.ip;
851 err = mStatus_NoError;
852
853 exit:
854 return( err );
855 }
856
857 //===========================================================================================================================
858 // debugf_
859 //===========================================================================================================================
860
861 #if( MDNS_DEBUGMSGS )
862 mDNSexport void debugf_( const char *format, ... )
863 {
864 char buffer[ 512 ];
865 va_list args;
866 mDNSu32 length;
867
868 va_start( args, format );
869 length = mDNS_vsnprintf( buffer, sizeof( buffer ), format, args );
870 va_end( args );
871
872 dlog( kDebugLevelInfo, "%s\n", buffer );
873 }
874 #endif
875
876 //===========================================================================================================================
877 // verbosedebugf_
878 //===========================================================================================================================
879
880 #if( MDNS_DEBUGMSGS > 1 )
881 mDNSexport void verbosedebugf_( const char *format, ... )
882 {
883 char buffer[ 512 ];
884 va_list args;
885 mDNSu32 length;
886
887 va_start( args, format );
888 length = mDNS_vsnprintf( buffer, sizeof( buffer ), format, args );
889 va_end( args );
890
891 dlog( kDebugLevelVerbose, "%s\n", buffer );
892 }
893 #endif
894
895 //===========================================================================================================================
896 // LogMsg
897 //===========================================================================================================================
898
899 void LogMsg( const char *inFormat, ... )
900 {
901 char buffer[ 512 ];
902 va_list args;
903 mDNSu32 length;
904
905 va_start( args, inFormat );
906 length = mDNS_vsnprintf( buffer, sizeof( buffer ), inFormat, args );
907 va_end( args );
908
909 dlog( kDebugLevelWarning, "%s\n", buffer );
910 }
911
912 #if 0
913 #pragma mark -
914 #pragma mark == Platform Internals ==
915 #endif
916
917 //===========================================================================================================================
918 // SetupNames
919 //===========================================================================================================================
920
921 mDNSlocal void SetupNames( mDNS * const inMDNS )
922 {
923 char tempCString[ 128 ];
924 mDNSu8 tempPString[ 128 ];
925 mDNSu8 * namePtr;
926
927 // Set up the host name.
928
929 tempCString[ 0 ] = '\0';
930 GenerateUniqueHostName( tempCString, NULL );
931 check( tempCString[ 0 ] != '\0' );
932 if( tempCString[ 0 ] == '\0' )
933 {
934 // No name so use the default.
935
936 strcpy( tempCString, kMDNSDefaultName );
937 }
938 inMDNS->nicelabel.c[ 0 ] = strlen( tempCString );
939 memcpy( &inMDNS->nicelabel.c[ 1 ], tempCString, inMDNS->nicelabel.c[ 0 ] );
940 check( inMDNS->nicelabel.c[ 0 ] > 0 );
941
942 // Set up the DNS name.
943
944 tempCString[ 0 ] = '\0';
945 GenerateUniqueDNSName( tempCString, NULL );
946 if( tempCString[ 0 ] != '\0' )
947 {
948 tempPString[ 0 ] = strlen( tempCString );
949 memcpy( &tempPString[ 1 ], tempCString, tempPString[ 0 ] );
950 namePtr = tempPString;
951 }
952 else
953 {
954 // No DNS name so use the host name.
955
956 namePtr = inMDNS->nicelabel.c;
957 }
958 ConvertUTF8PstringToRFC1034HostLabel( namePtr, &inMDNS->hostlabel );
959 if( inMDNS->hostlabel.c[ 0 ] == 0 )
960 {
961 // Nice name has no characters that are representable as an RFC 1034 name (e.g. Japanese) so use the default.
962
963 MakeDomainLabelFromLiteralString( &inMDNS->hostlabel, kMDNSDefaultName );
964 }
965 check( inMDNS->hostlabel.c[ 0 ] > 0 );
966
967 mDNS_SetFQDN( inMDNS );
968
969 dlog( kDebugLevelInfo, DEBUG_NAME "nice name \"%.*s\"\n", inMDNS->nicelabel.c[ 0 ], &inMDNS->nicelabel.c[ 1 ] );
970 dlog( kDebugLevelInfo, DEBUG_NAME "host name \"%.*s\"\n", inMDNS->hostlabel.c[ 0 ], &inMDNS->hostlabel.c[ 1 ] );
971 }
972
973 //===========================================================================================================================
974 // SetupInterfaceList
975 //===========================================================================================================================
976
977 mDNSlocal mStatus SetupInterfaceList( mDNS * const inMDNS )
978 {
979 mStatus err;
980 struct ifaddrs * addrs;
981 struct ifaddrs * p;
982 uint32_t flagMask;
983 uint32_t flagTest;
984 MDNSInterfaceItem ** next;
985 MDNSInterfaceItem * item;
986
987 addrs = NULL;
988
989 dlog( kDebugLevelVerbose, DEBUG_NAME "setting up interface list\n" );
990 check( inMDNS );
991
992 // Tear down any existing interfaces that may be set up.
993
994 TearDownInterfaceList( inMDNS );
995 inMDNS->p->interfaceList = NULL;
996 next = &inMDNS->p->interfaceList;
997
998 // Set up each interface that is active, multicast-capable, and not the loopback interface or point-to-point.
999
1000 flagMask = IFF_UP | IFF_MULTICAST | IFF_LOOPBACK | IFF_POINTOPOINT;
1001 flagTest = IFF_UP | IFF_MULTICAST;
1002
1003 err = getifaddrs( &addrs );
1004 require_noerr( err, exit );
1005
1006 for( p = addrs; p; p = p->ifa_next )
1007 {
1008 if( ( p->ifa_flags & flagMask ) == flagTest )
1009 {
1010 err = SetupInterface( inMDNS, p, &item );
1011 require_noerr( err, exit );
1012
1013 *next = item;
1014 next = &item->next;
1015 }
1016 }
1017 err = mStatus_NoError;
1018
1019 exit:
1020 if( addrs )
1021 {
1022 freeifaddrs( addrs );
1023 }
1024 if( err )
1025 {
1026 TearDownInterfaceList( inMDNS );
1027 }
1028 dlog( kDebugLevelVerbose, DEBUG_NAME "setting up interface list done (err=%ld)\n", err );
1029 return( err );
1030 }
1031
1032 //===========================================================================================================================
1033 // TearDownInterfaceList
1034 //===========================================================================================================================
1035
1036 mDNSlocal mStatus TearDownInterfaceList( mDNS * const inMDNS )
1037 {
1038 dlog( kDebugLevelVerbose, DEBUG_NAME "tearing down interface list\n" );
1039 check( inMDNS );
1040
1041 // Tear down all the interfaces.
1042
1043 while( inMDNS->p->interfaceList )
1044 {
1045 MDNSInterfaceItem * item;
1046
1047 item = inMDNS->p->interfaceList;
1048 inMDNS->p->interfaceList = item->next;
1049
1050 TearDownInterface( inMDNS, item );
1051 }
1052
1053 dlog( kDebugLevelVerbose, DEBUG_NAME "tearing down interface list done\n" );
1054 return( mStatus_NoError );
1055 }
1056
1057 //===========================================================================================================================
1058 // SetupInterface
1059 //===========================================================================================================================
1060
1061 mDNSlocal mStatus SetupInterface( mDNS * const inMDNS, const struct ifaddrs *inAddr, MDNSInterfaceItem **outItem )
1062 {
1063 mStatus err;
1064 MDNSInterfaceItem * item;
1065 MDNSSocketRef socketRef;
1066 const struct sockaddr_in * ipv4, *mask;
1067
1068 dlog( kDebugLevelVerbose, DEBUG_NAME "setting up interface (name=%s)\n", inAddr->ifa_name );
1069 check( inMDNS );
1070 check( inAddr );
1071 check( inAddr->ifa_addr );
1072 ipv4 = (const struct sockaddr_in *) inAddr->ifa_addr;
1073 mask = (const struct sockaddr_in *) inAddr->ifa_netmask;
1074 check( outItem );
1075
1076 // Allocate memory for the info item.
1077
1078 item = (MDNSInterfaceItem *) calloc( 1, sizeof( *item ) );
1079 require_action( item, exit, err = mStatus_NoMemoryErr );
1080 strcpy( item->name, inAddr->ifa_name );
1081 item->multicastSocketRef = kInvalidSocketRef;
1082 item->sendingSocketRef = kInvalidSocketRef;
1083
1084 // Set up the multicast DNS (port 5353) socket for this interface.
1085
1086 err = SetupSocket( inMDNS, inAddr, MulticastDNSPort, &socketRef );
1087 require_noerr( err, exit );
1088 item->multicastSocketRef = socketRef;
1089
1090 // Set up the sending socket for this interface.
1091
1092 err = SetupSocket( inMDNS, inAddr, zeroIPPort, &socketRef );
1093 require_noerr( err, exit );
1094 item->sendingSocketRef = socketRef;
1095
1096 // Register this interface with mDNS.
1097
1098 item->hostSet.InterfaceID = (mDNSInterfaceID) item;
1099 item->hostSet.ip .type = mDNSAddrType_IPv4;
1100 item->hostSet.ip .ip.v4.NotAnInteger = ipv4->sin_addr.s_addr;
1101 item->hostSet.mask.type = mDNSAddrType_IPv4;
1102 item->hostSet.mask.ip.v4.NotAnInteger = mask->sin_addr.s_addr;
1103 item->hostSet.ifname[0] = 0;
1104 item->hostSet.Advertise = inMDNS->AdvertiseLocalAddresses;
1105 item->hostSet.McastTxRx = mDNStrue;
1106
1107 err = mDNS_RegisterInterface( inMDNS, &item->hostSet, mDNSfalse );
1108 require_noerr( err, exit );
1109 item->hostRegistered = mDNStrue;
1110
1111 dlog( kDebugLevelInfo, DEBUG_NAME "Registered IP address: %u.%u.%u.%u\n",
1112 item->hostSet.ip.ip.v4.b[ 0 ], item->hostSet.ip.ip.v4.b[ 1 ],
1113 item->hostSet.ip.ip.v4.b[ 2 ], item->hostSet.ip.ip.v4.b[ 3 ] );
1114
1115 // Success!
1116
1117 *outItem = item;
1118 item = NULL;
1119
1120 exit:
1121 if( item )
1122 {
1123 TearDownInterface( inMDNS, item );
1124 }
1125 dlog( kDebugLevelVerbose, DEBUG_NAME "setting up interface done (name=%s, err=%ld)\n", inAddr->ifa_name, err );
1126 return( err );
1127 }
1128
1129 //===========================================================================================================================
1130 // TearDownInterface
1131 //===========================================================================================================================
1132
1133 mDNSlocal mStatus TearDownInterface( mDNS * const inMDNS, MDNSInterfaceItem *inItem )
1134 {
1135 MDNSSocketRef socketRef;
1136
1137 check( inMDNS );
1138 check( inItem );
1139
1140 // Deregister this interface with mDNS.
1141
1142 dlog( kDebugLevelInfo, DEBUG_NAME "Deregistering IP address: %u.%u.%u.%u\n",
1143 inItem->hostSet.ip.ip.v4.b[ 0 ], inItem->hostSet.ip.ip.v4.b[ 1 ],
1144 inItem->hostSet.ip.ip.v4.b[ 2 ], inItem->hostSet.ip.ip.v4.b[ 3 ] );
1145
1146 if( inItem->hostRegistered )
1147 {
1148 inItem->hostRegistered = mDNSfalse;
1149 mDNS_DeregisterInterface( inMDNS, &inItem->hostSet, mDNSfalse );
1150 }
1151
1152 // Close the multicast socket.
1153
1154 socketRef = inItem->multicastSocketRef;
1155 inItem->multicastSocketRef = kInvalidSocketRef;
1156 if( socketRef != kInvalidSocketRef )
1157 {
1158 dlog( kDebugLevelVerbose, DEBUG_NAME "tearing down multicast socket %d\n", socketRef );
1159 close( socketRef );
1160 }
1161
1162 // Close the sending socket.
1163
1164 socketRef = inItem->sendingSocketRef;
1165 inItem->sendingSocketRef = kInvalidSocketRef;
1166 if( socketRef != kInvalidSocketRef )
1167 {
1168 dlog( kDebugLevelVerbose, DEBUG_NAME "tearing down sending socket %d\n", socketRef );
1169 close( socketRef );
1170 }
1171
1172 // Free the memory used by the interface info.
1173
1174 free( inItem );
1175 return( mStatus_NoError );
1176 }
1177
1178 //===========================================================================================================================
1179 // SetupSocket
1180 //===========================================================================================================================
1181
1182 mDNSlocal mStatus
1183 SetupSocket(
1184 mDNS * const inMDNS,
1185 const struct ifaddrs * inAddr,
1186 mDNSIPPort inPort,
1187 MDNSSocketRef * outSocketRef )
1188 {
1189 mStatus err;
1190 MDNSSocketRef socketRef;
1191 int option;
1192 unsigned char optionByte;
1193 struct ip_mreq mreq;
1194 const struct sockaddr_in * ipv4;
1195 struct sockaddr_in addr;
1196 mDNSv4Addr ip;
1197
1198 dlog( kDebugLevelVerbose, DEBUG_NAME "setting up socket done\n" );
1199 check( inMDNS );
1200 check( inAddr );
1201 check( inAddr->ifa_addr );
1202 ipv4 = (const struct sockaddr_in *) inAddr->ifa_addr;
1203 check( outSocketRef );
1204
1205 // Set up a UDP socket for multicast DNS.
1206
1207 socketRef = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP );
1208 require_errno_action( socketRef, errno, exit, err = mStatus_UnknownErr );
1209
1210 // A port of zero means this socket is for sending and should be set up for sending. Otherwise, it is for receiving
1211 // and should be set up for receiving. The reason for separate sending vs receiving sockets is to workaround problems
1212 // with VxWorks IP stack when using dynamic IP configuration such as DHCP (problems binding to wildcard IP when the
1213 // IP address later changes). Since we have to bind the Multicast DNS address to workaround these issues we have to
1214 // use a separate sending socket since it is illegal to send a packet with a multicast source address (RFC 1122).
1215
1216 if( inPort.NotAnInteger != zeroIPPort.NotAnInteger )
1217 {
1218 // Turn on reuse port option so multiple servers can listen for Multicast DNS packets.
1219
1220 option = 1;
1221 err = setsockopt( socketRef, SOL_SOCKET, SO_REUSEADDR, (char *) &option, sizeof( option ) );
1222 check_errno( err, errno );
1223
1224 // Join the all-DNS multicast group so we receive Multicast DNS packets.
1225
1226 ip.NotAnInteger = ipv4->sin_addr.s_addr;
1227 mreq.imr_multiaddr.s_addr = AllDNSLinkGroupv4.NotAnInteger;
1228 mreq.imr_interface.s_addr = ip.NotAnInteger;
1229 err = setsockopt( socketRef, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *) &mreq, sizeof( mreq ) );
1230 check_errno( err, errno );
1231
1232 // Bind to the multicast DNS address and port 5353.
1233
1234 memset( &addr, 0, sizeof( addr ) );
1235 addr.sin_family = AF_INET;
1236 addr.sin_port = inPort.NotAnInteger;
1237 addr.sin_addr.s_addr = AllDNSLinkGroupv4.NotAnInteger;
1238 err = bind( socketRef, (struct sockaddr *) &addr, sizeof( addr ) );
1239 check_errno( err, errno );
1240
1241 dlog( kDebugLevelVerbose, DEBUG_NAME "setting up socket done (%s, %u.%u.%u.%u:%u, %d)\n",
1242 inAddr->ifa_name, ip.b[ 0 ], ip.b[ 1 ], ip.b[ 2 ], ip.b[ 3 ], ntohs( inPort.NotAnInteger ), socketRef );
1243 }
1244 else
1245 {
1246 // Bind to the interface address and multicast DNS port.
1247
1248 ip.NotAnInteger = ipv4->sin_addr.s_addr;
1249 memset( &addr, 0, sizeof( addr ) );
1250 addr.sin_family = AF_INET;
1251 addr.sin_port = MulticastDNSPort.NotAnInteger;
1252 addr.sin_addr.s_addr = ip.NotAnInteger;
1253 err = bind( socketRef, (struct sockaddr *) &addr, sizeof( addr ) );
1254 check_errno( err, errno );
1255
1256 // Direct multicast packets to the specified interface.
1257
1258 addr.sin_addr.s_addr = ip.NotAnInteger;
1259 err = setsockopt( socketRef, IPPROTO_IP, IP_MULTICAST_IF, (char *) &addr.sin_addr, sizeof( addr.sin_addr ) );
1260 check_errno( err, errno );
1261
1262 // Set the TTL of outgoing unicast packets to 255 (helps against spoofing).
1263
1264 option = 255;
1265 err = setsockopt( socketRef, IPPROTO_IP, IP_TTL, (char *) &option, sizeof( option ) );
1266 check_errno( err, errno );
1267
1268 // Set the TTL of outgoing multicast packets to 255 (helps against spoofing).
1269
1270 optionByte = 255;
1271 err = setsockopt( socketRef, IPPROTO_IP, IP_MULTICAST_TTL, (char *) &optionByte, sizeof( optionByte ) );
1272 check_errno( err, errno );
1273
1274 // WARNING: Setting this option causes unicast responses to be routed to the wrong interface so they are
1275 // WARNING: disabled. These options were only hints to improve 802.11 performance (and not implemented) anyway.
1276
1277 #if 0
1278 // Mark packets as high-throughput/low-delay (i.e. lowest reliability) to maximize 802.11 multicast rate.
1279
1280 option = IPTOS_LOWDELAY | IPTOS_THROUGHPUT;
1281 err = setsockopt( socketRef, IPPROTO_IP, IP_TOS, (char *) &option, sizeof( option ) );
1282 check_errno( err, errno );
1283 #endif
1284
1285 dlog( kDebugLevelVerbose, DEBUG_NAME "setting up sending socket done (%s, %u.%u.%u.%u, %d)\n",
1286 inAddr->ifa_name, ip.b[ 0 ], ip.b[ 1 ], ip.b[ 2 ], ip.b[ 3 ], socketRef );
1287 }
1288
1289 // Success!
1290
1291 *outSocketRef = socketRef;
1292 socketRef = kInvalidSocketRef;
1293 err = mStatus_NoError;
1294
1295 exit:
1296 if( socketRef != kInvalidSocketRef )
1297 {
1298 close( socketRef );
1299 }
1300 return( err );
1301 }
1302
1303 #if 0
1304 #pragma mark -
1305 #pragma mark == Commands ==
1306 #endif
1307
1308 //===========================================================================================================================
1309 // SetupCommandPipe
1310 //===========================================================================================================================
1311
1312 mDNSlocal mStatus SetupCommandPipe( mDNS * const inMDNS )
1313 {
1314 mStatus err;
1315
1316 // Clean up any leftover command pipe.
1317
1318 TearDownCommandPipe( inMDNS );
1319
1320 // Create the pipe device and open it.
1321
1322 pipeDevCreate( kMDNSPipeName, kMDNSPipeMessageQueueSize, kMDNSPipeMessageSize );
1323
1324 inMDNS->p->commandPipe = open( kMDNSPipeName, O_RDWR, 0 );
1325 require_errno_action( inMDNS->p->commandPipe, errno, exit, err = mStatus_UnsupportedErr );
1326
1327 err = mStatus_NoError;
1328
1329 exit:
1330 return( err );
1331 }
1332
1333 //===========================================================================================================================
1334 // TearDownCommandPipe
1335 //===========================================================================================================================
1336
1337 mDNSlocal mStatus TearDownCommandPipe( mDNS * const inMDNS )
1338 {
1339 if( inMDNS->p->commandPipe != ERROR )
1340 {
1341 close( inMDNS->p->commandPipe );
1342 #ifdef _WRS_VXWORKS_5_X
1343 // pipeDevDelete is not defined in older versions of VxWorks
1344 pipeDevDelete( kMDNSPipeName, FALSE );
1345 #endif
1346 inMDNS->p->commandPipe = ERROR;
1347 }
1348 return( mStatus_NoError );
1349 }
1350
1351 //===========================================================================================================================
1352 // SendCommand
1353 //===========================================================================================================================
1354
1355 mDNSlocal mStatus SendCommand( const mDNS * const inMDNS, MDNSPipeCommandCode inCommandCode )
1356 {
1357 mStatus err;
1358
1359 require_action( inMDNS->p->commandPipe != ERROR, exit, err = mStatus_NotInitializedErr );
1360
1361 err = write( inMDNS->p->commandPipe, &inCommandCode, sizeof( inCommandCode ) );
1362 require_errno( err, errno, exit );
1363
1364 err = mStatus_NoError;
1365
1366 exit:
1367 return( err );
1368 }
1369
1370 //===========================================================================================================================
1371 // ProcessCommand
1372 //===========================================================================================================================
1373
1374 mDNSlocal mStatus ProcessCommand( mDNS * const inMDNS )
1375 {
1376 mStatus err;
1377 MDNSPipeCommandCode commandCode;
1378
1379 require_action( inMDNS->p->commandPipe != ERROR, exit, err = mStatus_NotInitializedErr );
1380
1381 // Read the command code from the pipe and dispatch it.
1382
1383 err = read( inMDNS->p->commandPipe, &commandCode, sizeof( commandCode ) );
1384 require_errno( err, errno, exit );
1385
1386 switch( commandCode )
1387 {
1388 case kMDNSPipeCommandCodeReschedule:
1389
1390 // Reschedule event. Do nothing here, but this will cause mDNS_Execute to run before waiting again.
1391
1392 dlog( kDebugLevelChatty, DEBUG_NAME "reschedule\n" );
1393 break;
1394
1395 case kMDNSPipeCommandCodeReconfigure:
1396 ProcessCommandReconfigure( inMDNS );
1397 break;
1398
1399 case kMDNSPipeCommandCodeQuit:
1400
1401 // Quit requested. Set quit flag and bump the config ID to let the thread exit normally.
1402
1403 dlog( kDebugLevelVerbose, DEBUG_NAME "processing pipe quit command\n" );
1404 inMDNS->p->quit = mDNStrue;
1405 ++inMDNS->p->configID;
1406 break;
1407
1408 default:
1409 dlog( kDebugLevelError, DEBUG_NAME "unknown pipe command code (code=0x%08X)\n", commandCode );
1410 err = mStatus_BadParamErr;
1411 goto exit;
1412 break;
1413 }
1414 err = mStatus_NoError;
1415
1416 exit:
1417 return( err );
1418 }
1419
1420 //===========================================================================================================================
1421 // ProcessCommandReconfigure
1422 //===========================================================================================================================
1423
1424 mDNSlocal void ProcessCommandReconfigure( mDNS *inMDNS )
1425 {
1426 mStatus err;
1427
1428 dlog( kDebugLevelVerbose, DEBUG_NAME "processing pipe reconfigure command\n" );
1429
1430 // Tear down the existing interfaces and set up new ones using the new IP info.
1431
1432 mDNSPlatformLock( inMDNS );
1433
1434 err = TearDownInterfaceList( inMDNS );
1435 check_noerr( err );
1436
1437 err = SetupInterfaceList( inMDNS );
1438 check_noerr( err );
1439
1440 mDNSPlatformUnlock( inMDNS );
1441
1442 // Inform clients of the change.
1443
1444 if( inMDNS->MainCallback )
1445 {
1446 inMDNS->MainCallback( inMDNS, mStatus_ConfigChanged );
1447 }
1448
1449 // Force mDNS to update.
1450
1451 mDNSCoreMachineSleep( inMDNS, mDNSfalse );
1452
1453 // Bump the config ID so the main processing loop detects the configuration change.
1454
1455 ++inMDNS->p->configID;
1456 }
1457
1458 #if 0
1459 #pragma mark -
1460 #pragma mark == Threads ==
1461 #endif
1462
1463 //===========================================================================================================================
1464 // SetupTask
1465 //===========================================================================================================================
1466
1467 mDNSlocal mStatus SetupTask( mDNS * const inMDNS )
1468 {
1469 mStatus err;
1470 int task;
1471
1472 dlog( kDebugLevelVerbose, DEBUG_NAME "setting up thread\n" );
1473 check( inMDNS );
1474
1475 // Create our main thread. Note: The task will save off its ID in the globals. We cannot do it here because the
1476 // task invokes code that needs it and the task may begin execution before taskSpawn returns the task ID.
1477 // This also means code in this thread context cannot rely on the task ID until the task has fully initialized.
1478
1479 task = taskSpawn( kMDNSTaskName, kMDNSTaskPriority, 0, kMDNSTaskStackSize, (FUNCPTR) Task,
1480 (int) inMDNS, 0, 0, 0, 0, 0, 0, 0, 0, 0 );
1481 require_action( task != ERROR, exit, err = mStatus_NoMemoryErr );
1482
1483 err = mStatus_NoError;
1484
1485 exit:
1486 dlog( kDebugLevelVerbose, DEBUG_NAME "setting up thread done (err=%ld, id=%d)\n", err, task );
1487 return( err );
1488 }
1489
1490 //===========================================================================================================================
1491 // TearDownTask
1492 //===========================================================================================================================
1493
1494 mDNSlocal mStatus TearDownTask( mDNS * const inMDNS )
1495 {
1496 mStatus err;
1497
1498 dlog( kDebugLevelVerbose, DEBUG_NAME "tearing down thread\n" );
1499 check( inMDNS );
1500
1501 // Send a quit command to cause the thread to exit.
1502
1503 SendCommand( inMDNS, kMDNSPipeCommandCodeQuit );
1504
1505 // Wait for the thread to signal it has exited. Timeout in 10 seconds to handle a hung thread.
1506
1507 if( inMDNS->p->quitEvent )
1508 {
1509 err = semTake( inMDNS->p->quitEvent, sysClkRateGet() * 10 );
1510 check_noerr( err );
1511 }
1512 err = mStatus_NoError;
1513
1514 dlog( kDebugLevelVerbose, DEBUG_NAME "tearing down thread done (err=%ld)\n", err );
1515 return( err );
1516 }
1517
1518 //===========================================================================================================================
1519 // Task
1520 //===========================================================================================================================
1521
1522 mDNSlocal void Task( mDNS *inMDNS )
1523 {
1524 mStatus err;
1525 fd_set allReadSet;
1526 MDNSInterfaceItem * item;
1527 int maxSocket;
1528 long configID;
1529 struct timeval timeout;
1530
1531 dlog( kDebugLevelVerbose, DEBUG_NAME "task starting\n" );
1532 check( inMDNS );
1533
1534 // Set up everything up.
1535
1536 err = TaskInit( inMDNS );
1537 require_noerr( err, exit );
1538
1539 // Main Processing Loop.
1540
1541 while( !inMDNS->p->quit )
1542 {
1543 // Set up the read set here to avoid the overhead of setting it up each iteration of the main processing loop.
1544 // If the configuration changes, the server ID will be bumped, causing this code to set up the read set again.
1545
1546 TaskSetupReadSet( inMDNS, &allReadSet, &maxSocket );
1547 configID = inMDNS->p->configID;
1548 dlog( kDebugLevelVerbose, DEBUG_NAME "task starting processing loop (configID=%ld)\n", configID );
1549
1550 while( configID == inMDNS->p->configID )
1551 {
1552 mDNSs32 nextTaskTime;
1553 fd_set readSet;
1554 int n;
1555
1556 // Give the mDNS core a chance to do its work. Reset the rescheduled flag before calling mDNS_Execute
1557 // so anything that needs processing during or after causes a re-schedule to wake up the thread. The
1558 // reschedule flag is set to 1 after processing a waking up to prevent redundant reschedules while
1559 // processing packets. This introduces a window for a race condition because the thread wake-up and
1560 // reschedule set are not atomic, but this would be benign. Even if the reschedule flag is "corrupted"
1561 // like this, it would only result in a redundant reschedule since it will loop back to mDNS_Execute.
1562
1563 inMDNS->p->rescheduled = 0;
1564 nextTaskTime = mDNS_Execute( inMDNS );
1565 TaskSetupTimeout( inMDNS, nextTaskTime, &timeout );
1566
1567 // Wait until something occurs (e.g. command, incoming packet, or timeout).
1568
1569 readSet = allReadSet;
1570 n = select( maxSocket + 1, &readSet, NULL, NULL, &timeout );
1571 inMDNS->p->rescheduled = 1;
1572 check_errno( n, errno );
1573 dlog( kDebugLevelChatty - 1, DEBUG_NAME "task select result = %d\n", n );
1574 if( n == 0 )
1575 {
1576 // Next task timeout occurred. Loop back up to give mDNS core a chance to work.
1577
1578 dlog( kDebugLevelChatty, DEBUG_NAME "next task timeout occurred (%ld)\n", mDNS_TimeNow(inMDNS) );
1579 continue;
1580 }
1581
1582 // Scan the read set to determine if any sockets have something pending and process them.
1583
1584 n = 0;
1585 for( item = inMDNS->p->interfaceList; item; item = item->next )
1586 {
1587 if( FD_ISSET( item->multicastSocketRef, &readSet ) )
1588 {
1589 TaskProcessPacket( inMDNS, item, item->multicastSocketRef );
1590 ++n;
1591 }
1592 }
1593
1594 // Check for a pending command and process it.
1595
1596 if( FD_ISSET( inMDNS->p->commandPipe, &readSet ) )
1597 {
1598 ProcessCommand( inMDNS );
1599 ++n;
1600 }
1601 check( n > 0 );
1602 }
1603 }
1604
1605 exit:
1606 // Signal we've quit.
1607
1608 check( inMDNS->p->quitEvent );
1609 semGive( inMDNS->p->quitEvent );
1610
1611 dlog( kDebugLevelInfo, DEBUG_NAME "task ended\n" );
1612 }
1613
1614 //===========================================================================================================================
1615 // TaskInit
1616 //===========================================================================================================================
1617
1618 mDNSlocal mStatus TaskInit( mDNS *inMDNS )
1619 {
1620 mStatus err;
1621
1622 dlog( kDebugLevelVerbose, DEBUG_NAME "task init\n" );
1623 check( inMDNS->p->readyEvent );
1624
1625 inMDNS->p->task = taskIdSelf();
1626
1627 err = SetupCommandPipe( inMDNS );
1628 require_noerr( err, exit );
1629
1630 SetupNames( inMDNS );
1631
1632 err = SetupInterfaceList( inMDNS );
1633 require_noerr( err, exit );
1634
1635 exit:
1636 // Signal the "ready" semaphore to indicate the task initialization code has completed (success or not).
1637
1638 inMDNS->p->taskInitErr = err;
1639 semGive( inMDNS->p->readyEvent );
1640
1641 dlog( kDebugLevelVerbose, DEBUG_NAME "task init done (err=%ld)\n", err );
1642 return( err );
1643 }
1644
1645 //===========================================================================================================================
1646 // TaskSetupReadSet
1647 //===========================================================================================================================
1648
1649 mDNSlocal void TaskSetupReadSet( mDNS *inMDNS, fd_set *outReadSet, int *outMaxSocket )
1650 {
1651 MDNSInterfaceItem * item;
1652 int maxSocket;
1653
1654 dlog( kDebugLevelVerbose, DEBUG_NAME "task setting up read set\n" );
1655 check( inMDNS );
1656 check( outReadSet );
1657 check( outMaxSocket );
1658
1659 // Initialize the read set. Default the max socket to -1 so "maxSocket + 1" (as needed by select) is zero. This
1660 // should never happen since we should always have at least one interface, but it's just to be safe.
1661
1662 FD_ZERO( outReadSet );
1663 maxSocket = -1;
1664
1665 // Add all the receiving sockets to the read set.
1666
1667 for( item = inMDNS->p->interfaceList; item; item = item->next )
1668 {
1669 FD_SET( item->multicastSocketRef, outReadSet );
1670 if( item->multicastSocketRef > maxSocket )
1671 {
1672 maxSocket = item->multicastSocketRef;
1673 }
1674 }
1675
1676 // Add the command pipe to the read set.
1677
1678 FD_SET( inMDNS->p->commandPipe, outReadSet );
1679 if( inMDNS->p->commandPipe > maxSocket )
1680 {
1681 maxSocket = inMDNS->p->commandPipe;
1682 }
1683 check( maxSocket > 0 );
1684 *outMaxSocket = maxSocket;
1685
1686 dlog( kDebugLevelVerbose, DEBUG_NAME "task setting up read set done (maxSocket=%d)\n", maxSocket );
1687 }
1688
1689 //===========================================================================================================================
1690 // TaskSetupTimeout
1691 //===========================================================================================================================
1692
1693 mDNSlocal void TaskSetupTimeout( mDNS *inMDNS, mDNSs32 inNextTaskTime, struct timeval *outTimeout )
1694 {
1695 mDNSs32 delta;
1696
1697 // Calculate how long to wait before performing idle processing.
1698
1699 delta = inNextTaskTime - mDNS_TimeNow(inMDNS);
1700 if( delta <= 0 )
1701 {
1702 // The next task time is now or in the past. Set the timeout to fire immediately.
1703
1704 outTimeout->tv_sec = 0;
1705 outTimeout->tv_usec = 0;
1706 }
1707 else
1708 {
1709 // Calculate the seconds and microseconds until the timeout should occur. Add one to the ticks remainder
1710 // before multiplying to account for integer rounding error and avoid firing the timeout too early.
1711
1712 outTimeout->tv_sec = delta / mDNSPlatformOneSecond;
1713 outTimeout->tv_usec = ( ( delta % mDNSPlatformOneSecond ) + 1 ) * gMDNSTicksToMicrosecondsMultiplier;
1714
1715 // Check if the microseconds is more than 1 second. If so, bump the seconds instead.
1716
1717 if( outTimeout->tv_usec >= 1000000L )
1718 {
1719 outTimeout->tv_sec += 1;
1720 outTimeout->tv_usec = 0;
1721 }
1722 }
1723
1724 dlog( kDebugLevelChatty, DEBUG_NAME "next task in %ld:%ld seconds (%ld)\n",
1725 outTimeout->tv_sec, outTimeout->tv_usec, inNextTaskTime );
1726 }
1727 //===========================================================================================================================
1728 // TaskProcessPacket
1729 //===========================================================================================================================
1730
1731 mDNSlocal void TaskProcessPacket( mDNS *inMDNS, MDNSInterfaceItem *inItem, MDNSSocketRef inSocketRef )
1732 {
1733 int n;
1734 DNSMessage packet;
1735 struct sockaddr_in addr;
1736 int addrSize;
1737 mDNSu8 * packetEndPtr;
1738 mDNSAddr srcAddr;
1739 mDNSIPPort srcPort;
1740 mDNSAddr dstAddr;
1741 mDNSIPPort dstPort;
1742
1743 // Receive the packet.
1744
1745 addrSize = sizeof( addr );
1746 n = recvfrom( inSocketRef, (char *) &packet, sizeof( packet ), 0, (struct sockaddr *) &addr, &addrSize );
1747 check( n >= 0 );
1748 if( n >= 0 )
1749 {
1750 // Set up the src/dst/interface info.
1751
1752 srcAddr.type = mDNSAddrType_IPv4;
1753 srcAddr.ip.v4.NotAnInteger = addr.sin_addr.s_addr;
1754 srcPort.NotAnInteger = addr.sin_port;
1755 dstAddr.type = mDNSAddrType_IPv4;
1756 dstAddr.ip.v4 = AllDNSLinkGroupv4;
1757 dstPort = MulticastDNSPort;
1758
1759 dlog( kDebugLevelChatty, DEBUG_NAME "packet received\n" );
1760 dlog( kDebugLevelChatty, DEBUG_NAME " size = %d\n", n );
1761 dlog( kDebugLevelChatty, DEBUG_NAME " src = %u.%u.%u.%u:%hu\n",
1762 srcAddr.ip.v4.b[ 0 ], srcAddr.ip.v4.b[ 1 ], srcAddr.ip.v4.b[ 2 ], srcAddr.ip.v4.b[ 3 ],
1763 ntohs( srcPort.NotAnInteger ) );
1764 dlog( kDebugLevelChatty, DEBUG_NAME " dst = %u.%u.%u.%u:%hu\n",
1765 dstAddr.ip.v4.b[ 0 ], dstAddr.ip.v4.b[ 1 ], dstAddr.ip.v4.b[ 2 ], dstAddr.ip.v4.b[ 3 ],
1766 ntohs( dstPort.NotAnInteger ) );
1767 dlog( kDebugLevelChatty, DEBUG_NAME " interface = 0x%08X\n", (int) inItem->hostSet.InterfaceID );
1768 dlog( kDebugLevelChatty, DEBUG_NAME "--\n" );
1769
1770 // Dispatch the packet to mDNS.
1771
1772 packetEndPtr = ( (mDNSu8 *) &packet ) + n;
1773 mDNSCoreReceive( inMDNS, &packet, packetEndPtr, &srcAddr, srcPort, &dstAddr, dstPort, inItem->hostSet.InterfaceID );
1774 }
1775
1776 // Update counters.
1777
1778 inItem->recvCounter += 1;
1779 inItem->recvErrorCounter += ( n < 0 );
1780 }
1781
1782 #if 0
1783 #pragma mark -
1784 #pragma mark == Utilities ==
1785 #endif
1786
1787 #if( TARGET_NON_APPLE )
1788 //===========================================================================================================================
1789 // GenerateUniqueHostName
1790 //
1791 // Non-Apple platform stub routine to generate a unique name for the device. Should be implemented to return a unique name.
1792 //===========================================================================================================================
1793
1794 mDNSlocal void GenerateUniqueHostName( char *outName, long *ioSeed )
1795 {
1796 DEBUG_UNUSED( ioSeed );
1797
1798 // $$$ Non-Apple Platforms: Fill in appropriate name for device.
1799
1800 mDNSPlatformStrCopy( kMDNSDefaultName, outName );
1801 }
1802
1803 //===========================================================================================================================
1804 // GenerateUniqueDNSName
1805 //
1806 // Non-Apple platform stub routine to generate a unique RFC 1034-compatible DNS name for the device. Should be
1807 // implemented to return a unique name.
1808 //===========================================================================================================================
1809
1810 mDNSlocal void GenerateUniqueDNSName( char *outName, long *ioSeed )
1811 {
1812 DEBUG_UNUSED( ioSeed );
1813
1814 // $$$ Non-Apple Platforms: Fill in appropriate DNS name for device.
1815
1816 mDNSPlatformStrCopy( kMDNSDefaultName, outName );
1817 }
1818 #endif
1819
1820 #if 0
1821 #pragma mark -
1822 #endif
1823
1824 //===========================================================================================================================
1825 // getifaddrs
1826 //===========================================================================================================================
1827
1828 int getifaddrs( struct ifaddrs **outAddrs )
1829 {
1830 int err;
1831 struct ifaddrs * head;
1832 struct ifaddrs ** next;
1833 struct ifaddrs * ifa;
1834 int i;
1835 struct ifnet * ifp;
1836 char ipString[ INET_ADDR_LEN ];
1837 int n;
1838
1839 head = NULL;
1840 next = &head;
1841
1842 i = 1;
1843 for( ;; )
1844 {
1845 ifp = ifIndexToIfp( i );
1846 if( !ifp )
1847 {
1848 break;
1849 }
1850 ++i;
1851
1852 // Allocate and initialize the ifaddrs structure and attach it to the linked list.
1853
1854 ifa = (struct ifaddrs *) calloc( 1, sizeof( struct ifaddrs ) );
1855 require_action( ifa, exit, err = ENOMEM );
1856
1857 *next = ifa;
1858 next = &ifa->ifa_next;
1859
1860 // Fetch the name.
1861
1862 ifa->ifa_name = (char *) malloc( 16 );
1863 require_action( ifa->ifa_name, exit, err = ENOMEM );
1864
1865 n = sprintf( ifa->ifa_name, "%s%d", ifp->if_name, ifp->if_unit );
1866 require_action( n < 16, exit, err = ENOBUFS );
1867
1868 // Fetch the address.
1869
1870 ifa->ifa_addr = (struct sockaddr *) calloc( 1, sizeof( struct sockaddr_in ) );
1871 require_action( ifa->ifa_addr, exit, err = ENOMEM );
1872
1873 ipString[ 0 ] = '\0';
1874 #if( TARGET_NON_APPLE )
1875 err = ifAddrGet( ifa->ifa_name, ipString );
1876 require_noerr( err, exit );
1877 #else
1878 err = ifAddrGetNonAlias( ifa->ifa_name, ipString );
1879 require_noerr( err, exit );
1880 #endif
1881
1882 err = sock_pton( ipString, AF_INET, ifa->ifa_addr, 0, NULL );
1883 require_noerr( err, exit );
1884
1885 // Fetch flags.
1886
1887 ifa->ifa_flags = ifp->if_flags;
1888 }
1889
1890 // Success!
1891
1892 if( outAddrs )
1893 {
1894 *outAddrs = head;
1895 head = NULL;
1896 }
1897 err = 0;
1898
1899 exit:
1900 if( head )
1901 {
1902 freeifaddrs( head );
1903 }
1904 return( err );
1905 }
1906
1907 //===========================================================================================================================
1908 // freeifaddrs
1909 //===========================================================================================================================
1910
1911 void freeifaddrs( struct ifaddrs *inAddrs )
1912 {
1913 struct ifaddrs * p;
1914 struct ifaddrs * q;
1915
1916 // Free each piece of the structure. Set to null after freeing to handle macro-aliased fields.
1917
1918 for( p = inAddrs; p; p = q )
1919 {
1920 q = p->ifa_next;
1921
1922 if( p->ifa_name )
1923 {
1924 free( p->ifa_name );
1925 p->ifa_name = NULL;
1926 }
1927 if( p->ifa_addr )
1928 {
1929 free( p->ifa_addr );
1930 p->ifa_addr = NULL;
1931 }
1932 if( p->ifa_netmask )
1933 {
1934 free( p->ifa_netmask );
1935 p->ifa_netmask = NULL;
1936 }
1937 if( p->ifa_dstaddr )
1938 {
1939 free( p->ifa_dstaddr );
1940 p->ifa_dstaddr = NULL;
1941 }
1942 if( p->ifa_data )
1943 {
1944 free( p->ifa_data );
1945 p->ifa_data = NULL;
1946 }
1947 free( p );
1948 }
1949 }
1950
1951 //===========================================================================================================================
1952 // sock_pton
1953 //===========================================================================================================================
1954
1955 int sock_pton( const char *inString, int inFamily, void *outAddr, size_t inAddrSize, size_t *outAddrSize )
1956 {
1957 int err;
1958
1959 if( inFamily == AF_INET )
1960 {
1961 struct sockaddr_in * ipv4;
1962
1963 if( inAddrSize == 0 )
1964 {
1965 inAddrSize = sizeof( struct sockaddr_in );
1966 }
1967 if( inAddrSize < sizeof( struct sockaddr_in ) )
1968 {
1969 err = EINVAL;
1970 goto exit;
1971 }
1972
1973 ipv4 = (struct sockaddr_in *) outAddr;
1974 err = inet_aton( (char *) inString, &ipv4->sin_addr );
1975 if( err == 0 )
1976 {
1977 ipv4->sin_family = AF_INET;
1978 if( outAddrSize )
1979 {
1980 *outAddrSize = sizeof( struct sockaddr_in );
1981 }
1982 }
1983 }
1984 #if( defined( AF_INET6 ) )
1985 else if( inFamily == AF_INET6 ) // $$$ TO DO: Add IPv6 support.
1986 {
1987 err = EAFNOSUPPORT;
1988 goto exit;
1989 }
1990 #endif
1991 else
1992 {
1993 err = EAFNOSUPPORT;
1994 goto exit;
1995 }
1996
1997 exit:
1998 return( err );
1999 }
2000
2001 //===========================================================================================================================
2002 // sock_ntop
2003 //===========================================================================================================================
2004
2005 char * sock_ntop( const void *inAddr, size_t inAddrSize, char *inBuffer, size_t inBufferSize )
2006 {
2007 const struct sockaddr * addr;
2008
2009 addr = (const struct sockaddr *) inAddr;
2010 if( addr->sa_family == AF_INET )
2011 {
2012 struct sockaddr_in * ipv4;
2013
2014 if( inAddrSize == 0 )
2015 {
2016 inAddrSize = sizeof( struct sockaddr_in );
2017 }
2018 if( inAddrSize < sizeof( struct sockaddr_in ) )
2019 {
2020 errno = EINVAL;
2021 inBuffer = NULL;
2022 goto exit;
2023 }
2024 if( inBufferSize < 16 )
2025 {
2026 errno = ENOBUFS;
2027 inBuffer = NULL;
2028 goto exit;
2029 }
2030
2031 ipv4 = (struct sockaddr_in *) addr;
2032 inet_ntoa_b( ipv4->sin_addr, inBuffer );
2033 }
2034 #if( defined( AF_INET6 ) )
2035 else if( addr->sa_family == AF_INET6 ) // $$$ TO DO: Add IPv6 support.
2036 {
2037 errno = EAFNOSUPPORT;
2038 inBuffer = NULL;
2039 goto exit;
2040 }
2041 #endif
2042 else
2043 {
2044 errno = EAFNOSUPPORT;
2045 inBuffer = NULL;
2046 goto exit;
2047 }
2048
2049 exit:
2050 return( inBuffer );
2051 }
2052
2053 #if 0
2054 #pragma mark -
2055 #pragma mark == Debugging ==
2056 #endif
2057
2058 #if( DEBUG )
2059
2060 void mDNSShow( BOOL inShowRecords );
2061 void mDNSShowRecords( void );
2062 void mDNSShowTXT( const void *inTXT, size_t inTXTSize );
2063
2064 //===========================================================================================================================
2065 // mDNSShow
2066 //===========================================================================================================================
2067
2068 void mDNSShow( BOOL inShowRecords )
2069 {
2070 MDNSInterfaceItem * item;
2071 mDNSAddr ip;
2072 int n;
2073
2074 if( !gMDNSPtr )
2075 {
2076 printf( "### mDNS not initialized\n" );
2077 return;
2078 }
2079
2080 // Globals
2081
2082 printf( "\n-- mDNS globals --\n" );
2083 printf( " sizeof( mDNS ) = %d\n", (int) sizeof( mDNS ) );
2084 printf( " sizeof( ResourceRecord ) = %d\n", (int) sizeof( ResourceRecord ) );
2085 printf( " sizeof( AuthRecord ) = %d\n", (int) sizeof( AuthRecord ) );
2086 printf( " sizeof( CacheRecord ) = %d\n", (int) sizeof( CacheRecord ) );
2087 printf( " gMDNSPtr = 0x%08lX\n", (unsigned long) gMDNSPtr );
2088 printf( " gMDNSTicksToMicrosecondsMultiplier = %ld\n", gMDNSTicksToMicrosecondsMultiplier );
2089 printf( " lockID = 0x%08lX\n", (unsigned long) gMDNSPtr->p->lockID );
2090 printf( " readyEvent = 0x%08lX\n", (unsigned long) gMDNSPtr->p->readyEvent );
2091 printf( " taskInitErr = %ld\n", gMDNSPtr->p->taskInitErr );
2092 printf( " quitEvent = 0x%08lX\n", (unsigned long) gMDNSPtr->p->quitEvent );
2093 printf( " commandPipe = %d\n", gMDNSPtr->p->commandPipe );
2094 printf( " task = 0x%08lX\n", (unsigned long) gMDNSPtr->p->task );
2095 printf( " quit = %d\n", gMDNSPtr->p->quit );
2096 printf( " configID = %ld\n", gMDNSPtr->p->configID );
2097 printf( " rescheduled = %d\n", gMDNSPtr->p->rescheduled );
2098 printf( " nicelabel = \"%.*s\"\n", gMDNSPtr->nicelabel.c[ 0 ], (char *) &gMDNSPtr->nicelabel.c[ 1 ] );
2099 printf( " hostLabel = \"%.*s\"\n", gMDNSPtr->hostlabel.c[ 0 ], (char *) &gMDNSPtr->hostlabel.c[ 1 ] );
2100 printf( "\n");
2101
2102 // Interfaces
2103
2104 printf( "\n-- mDNS interfaces --\n" );
2105 n = 1;
2106 for( item = gMDNSPtr->p->interfaceList; item; item = item->next )
2107 {
2108 printf( " -- interface %u --\n", n );
2109 printf( " name = \"%s\"\n", item->name );
2110 printf( " multicastSocketRef = %d\n", item->multicastSocketRef );
2111 printf( " sendingSocketRef = %d\n", item->sendingSocketRef );
2112 ip = item->hostSet.ip;
2113 printf( " hostSet.ip = %u.%u.%u.%u\n", ip.ip.v4.b[ 0 ], ip.ip.v4.b[ 1 ],
2114 ip.ip.v4.b[ 2 ], ip.ip.v4.b[ 3 ] );
2115 printf( " hostSet.advertise = %s\n", item->hostSet.Advertise ? "YES" : "NO" );
2116 printf( " hostRegistered = %s\n", item->hostRegistered ? "YES" : "NO" );
2117 printf( " --\n" );
2118 printf( " sendMulticastCounter = %d\n", item->sendMulticastCounter );
2119 printf( " sendUnicastCounter = %d\n", item->sendUnicastCounter );
2120 printf( " sendErrorCounter = %d\n", item->sendErrorCounter );
2121 printf( " recvCounter = %d\n", item->recvCounter );
2122 printf( " recvErrorCounter = %d\n", item->recvErrorCounter );
2123 printf( " recvLoopCounter = %d\n", item->recvLoopCounter );
2124 printf( "\n" );
2125 ++n;
2126 }
2127
2128 // Resource Records
2129
2130 if( inShowRecords )
2131 {
2132 mDNSShowRecords();
2133 }
2134 }
2135
2136 //===========================================================================================================================
2137 // mDNSShowRecords
2138 //===========================================================================================================================
2139
2140 void mDNSShowRecords( void )
2141 {
2142 MDNSInterfaceItem * item;
2143 int n;
2144 AuthRecord * record;
2145 char name[ MAX_ESCAPED_DOMAIN_NAME ];
2146
2147 printf( "\n-- mDNS resource records --\n" );
2148 n = 1;
2149 for( record = gMDNSPtr->ResourceRecords; record; record = record->next )
2150 {
2151 item = (MDNSInterfaceItem *) record->resrec.InterfaceID;
2152 ConvertDomainNameToCString( &record->resrec.name, name );
2153 printf( " -- record %d --\n", n );
2154 printf( " interface = 0x%08X (%s)\n", (int) item, item ? item->name : "<any>" );
2155 printf( " name = \"%s\"\n", name );
2156 printf( "\n" );
2157 ++n;
2158 }
2159 printf( "\n");
2160 }
2161
2162 //===========================================================================================================================
2163 // mDNSShowTXT
2164 //===========================================================================================================================
2165
2166 void mDNSShowTXT( const void *inTXT, size_t inTXTSize )
2167 {
2168 const mDNSu8 * p;
2169 const mDNSu8 * end;
2170 int i;
2171 mDNSu8 size;
2172
2173 printf( "\nTXT record (%u bytes):\n\n", inTXTSize );
2174
2175 p = (const mDNSu8 *) inTXT;
2176 end = p + inTXTSize;
2177 i = 0;
2178
2179 while( p < end )
2180 {
2181 size = *p++;
2182 if( ( p + size ) > end )
2183 {
2184 printf( "\n### MALFORMED TXT RECORD (length byte too big for record)\n\n" );
2185 break;
2186 }
2187 printf( "%2d (%3d bytes): \"%.*s\"\n", i, size, size, p );
2188 p += size;
2189 ++i;
2190 }
2191 printf( "\n" );
2192 }
2193 #endif // DEBUG