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