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