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