2 * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
23 Change History (most recent first):
25 $Log: mDNSMacOS9.c,v $
26 Revision 1.44 2005/09/16 21:06:50 cheshire
27 Use mDNS_TimeNow_NoLock macro, instead of writing "mDNSPlatformRawTime() + m->timenow_adjust" all over the place
29 Revision 1.43 2004/12/17 23:37:49 cheshire
30 <rdar://problem/3485365> Guard against repeating wireless dissociation/re-association
31 (and other repetitive configuration changes)
33 Revision 1.42 2004/12/16 20:43:39 cheshire
34 interfaceinfo.fMask should be interfaceinfo.fNetmask
36 Revision 1.41 2004/10/16 00:17:00 cheshire
37 <rdar://problem/3770558> Replace IP TTL 255 check with local subnet source address check
39 Revision 1.40 2004/09/27 23:56:27 cheshire
40 Fix infinite loop where mDNSPlatformUnlock() called mDNS_TimeNow(),
41 and then mDNS_TimeNow() called mDNSPlatformUnlock()
43 Revision 1.39 2004/09/21 21:02:54 cheshire
44 Set up ifname before calling mDNS_RegisterInterface()
46 Revision 1.38 2004/09/17 01:08:50 cheshire
47 Renamed mDNSClientAPI.h to mDNSEmbeddedAPI.h
48 The name "mDNSClientAPI.h" is misleading to new developers looking at this code. The interfaces
49 declared in that file are ONLY appropriate to single-address-space embedded applications.
50 For clients on general-purpose computers, the interfaces defined in dns_sd.h should be used.
52 Revision 1.37 2004/09/17 00:19:10 cheshire
53 For consistency with AllDNSLinkGroupv6, rename AllDNSLinkGroup to AllDNSLinkGroupv4
55 Revision 1.36 2004/09/16 21:59:16 cheshire
56 For consistency with zerov6Addr, rename zeroIPAddr to zerov4Addr
58 Revision 1.35 2004/09/16 00:24:49 cheshire
59 <rdar://problem/3803162> Fix unsafe use of mDNSPlatformTimeNow()
61 Revision 1.34 2004/09/14 23:42:36 cheshire
62 <rdar://problem/3801296> Need to seed random number generator from platform-layer data
64 Revision 1.33 2004/09/14 23:16:31 cheshire
65 Fix compile error: mDNS_SetFQDNs has been renamed to mDNS_SetFQDN
67 Revision 1.32 2004/09/14 21:03:16 cheshire
70 Revision 1.31 2004/08/14 03:22:42 cheshire
71 <rdar://problem/3762579> Dynamic DNS UI <-> mDNSResponder glue
72 Add GetUserSpecifiedDDNSName() routine
73 Convert ServiceRegDomain to domainname instead of C string
74 Replace mDNS_GenerateFQDN/mDNS_GenerateGlobalFQDN with mDNS_SetFQDNs
76 Revision 1.30 2004/07/29 19:26:03 ksekar
77 Plaform-level changes for NATPMP support
79 Revision 1.29 2004/05/26 20:53:16 cheshire
80 Remove unncecessary "return( -1 );" at the end of mDNSPlatformUTC()
82 Revision 1.28 2004/05/20 18:39:06 cheshire
83 Fix build broken by addition of mDNSPlatformUTC requirement
85 Revision 1.27 2004/04/21 02:49:11 cheshire
86 To reduce future confusion, renamed 'TxAndRx' to 'McastTxRx'
88 Revision 1.26 2004/04/09 17:43:03 cheshire
89 Make sure to set the McastTxRx field so that duplicate suppression works correctly
91 Revision 1.25 2004/03/15 18:55:38 cheshire
92 Comment out debugging message
94 Revision 1.24 2004/03/12 21:30:26 cheshire
95 Build a System-Context Shared Library from mDNSCore, for the benefit of developers
96 like Muse Research who want to be able to use mDNS/DNS-SD from GPL-licensed code.
98 Revision 1.23 2004/02/09 23:24:43 cheshire
99 Need to set TTL 255 to interoperate with peers that check TTL (oops!)
101 Revision 1.22 2004/01/27 20:15:23 cheshire
102 <rdar://problem/3541288>: Time to prune obsolete code for listening on port 53
104 Revision 1.21 2004/01/24 04:59:16 cheshire
105 Fixes so that Posix/Linux, OS9, Windows, and VxWorks targets build again
107 Revision 1.20 2003/11/14 20:59:09 cheshire
108 Clients can't use AssignDomainName macro because mDNSPlatformMemCopy is defined in mDNSPlatformFunctions.h.
109 Best solution is just to combine mDNSEmbeddedAPI.h and mDNSPlatformFunctions.h into a single file.
111 Revision 1.19 2003/08/18 23:09:20 cheshire
112 <rdar://problem/3382647> mDNSResponder divide by zero in mDNSPlatformRawTime()
114 Revision 1.18 2003/08/12 19:56:24 cheshire
120 #include <stdarg.h> // For va_list support
122 #include <LowMem.h> // For LMGetCurApName()
123 #include <TextUtils.h> // For smSystemScript
124 #include <UnicodeConverter.h> // For ConvertFromPStringToUnicode()
126 #include "mDNSEmbeddedAPI.h" // Defines the interface provided to the client layer above
128 #include "mDNSMacOS9.h" // Defines the specific types needed to run mDNS on this platform
130 // ***************************************************************************
133 static const TSetBooleanOption kReusePortOption
=
134 { kOTBooleanOptionSize
, INET_IP
, IP_REUSEPORT
, 0, true };
136 // IP_RCVDSTADDR with TSetByteOption/kOTOneByteOptionSize works on OS 9, OS X Classic, and OS 9 Carbon,
137 // but gives error #-3151 (kOTBadOptionErr) on OS X Carbon.
138 // If we instead use TSetBooleanOption/kOTBooleanOptionSize then OTOptionManagement on OS X Carbon
139 // no longer returns -3151 but it still doesn't actually work -- no destination addresses
140 // are delivered by OTRcvUData. I think it's just a bug in OS X Carbon.
141 static const TSetByteOption kRcvDestAddrOption
=
142 { kOTOneByteOptionSize
, INET_IP
, IP_RCVDSTADDR
, 0, true };
143 //static const TSetBooleanOption kRcvDestAddrOption =
144 // { kOTBooleanOptionSize, INET_IP, IP_RCVDSTADDR, 0, true };
146 static const TSetByteOption kSetUnicastTTLOption
=
147 { kOTOneByteOptionSize
, INET_IP
, IP_TTL
, 0, 255 };
149 static const TSetByteOption kSetMulticastTTLOption
=
150 { kOTOneByteOptionSize
, INET_IP
, IP_MULTICAST_TTL
, 0, 255 };
152 static const TIPAddMulticastOption kAddLinkMulticastOption
=
153 { sizeof(TIPAddMulticastOption
), INET_IP
, IP_ADD_MEMBERSHIP
, 0, { 224, 0, 0,251 }, { 0,0,0,0 } };
155 //static const TIPAddMulticastOption kAddAdminMulticastOption =
156 // { sizeof(TIPAddMulticastOption), INET_IP, IP_ADD_MEMBERSHIP, 0, { 239,255,255,251 }, { 0,0,0,0 } };
158 // Bind endpoint to port number. Don't specify any specific IP address --
159 // we want to receive unicasts on all interfaces, as well as multicasts.
160 typedef struct { OTAddressType fAddressType
; mDNSIPPort fPort
; mDNSv4Addr fHost
; UInt8 fUnused
[8]; } mDNSInetAddress
;
161 //static const mDNSInetAddress mDNSPortInetAddress = { AF_INET, { 0,0 }, { 0,0,0,0 } }; // For testing legacy client support
162 #define MulticastDNSPortAsNumber 5353
163 static const mDNSInetAddress mDNSPortInetAddress
= { AF_INET
, { MulticastDNSPortAsNumber
>> 8, MulticastDNSPortAsNumber
& 0xFF }, { 0,0,0,0 } };
164 static const TBind mDNSbindReq
= { sizeof(mDNSPortInetAddress
), sizeof(mDNSPortInetAddress
), (UInt8
*)&mDNSPortInetAddress
, 0 };
166 static const TNetbuf zeroTNetbuf
= { 0 };
168 // ***************************************************************************
171 mDNSlocal
void SafeDebugStr(unsigned char *buffer
)
174 // Don't want semicolons in MacsBug messages -- they signify commands to execute
175 for (i
=1; i
<= buffer
[0]; i
++) if (buffer
[i
] == ';') buffer
[i
] = '.';
180 mDNSexport
void debugf_(const char *format
, ...)
182 unsigned char buffer
[256];
184 va_start(ptr
,format
);
185 buffer
[0] = (unsigned char)mDNS_vsnprintf((char*)buffer
+1, 255, format
, ptr
);
187 #if MDNS_ONLYSYSTEMTASK
188 buffer
[1+buffer
[0]] = 0;
189 fprintf(stderr
, "%s\n", buffer
+1);
192 SafeDebugStr(buffer
);
197 #if MDNS_BUILDINGSHAREDLIBRARY >= 2
198 // When building the non-debug version of the Extension, intended to go on end-user systems, we don't want
199 // MacsBug breaks for *anything*, not even for the serious LogMsg messages that on OS X would be written to syslog
200 mDNSexport
void LogMsg(const char *format
, ...) { (void)format
; }
202 mDNSexport
void LogMsg(const char *format
, ...)
204 unsigned char buffer
[256];
206 va_start(ptr
,format
);
207 buffer
[0] = (unsigned char)mDNS_vsnprintf((char*)buffer
+1, 255, format
, ptr
);
209 #if MDNS_ONLYSYSTEMTASK
210 buffer
[1+buffer
[0]] = 0;
211 fprintf(stderr
, "%s\n", buffer
+1);
214 SafeDebugStr(buffer
);
219 mDNSexport mStatus
mDNSPlatformSendUDP(const mDNS
*const m
, const void *const msg
, const mDNSu8
*const end
,
220 mDNSInterfaceID InterfaceID
, const mDNSAddr
*dst
, mDNSIPPort dstPort
)
222 // Note: If we did multi-homing, we'd have to use the InterfaceID parameter to specify from which interface to send this response
223 #pragma unused(InterfaceID)
225 InetAddress InetDest
;
228 if (dst
->type
!= mDNSAddrType_IPv4
) return(mStatus_NoError
);
230 InetDest
.fAddressType
= AF_INET
;
231 InetDest
.fPort
= dstPort
.NotAnInteger
;
232 InetDest
.fHost
= dst
->ip
.v4
.NotAnInteger
;
234 senddata
.addr
.maxlen
= sizeof(InetDest
);
235 senddata
.addr
.len
= sizeof(InetDest
);
236 senddata
.addr
.buf
= (UInt8
*)&InetDest
;
237 senddata
.opt
= zeroTNetbuf
;
238 senddata
.udata
.maxlen
= (UInt32
)((UInt8
*)end
- (UInt8
*)msg
);
239 senddata
.udata
.len
= (UInt32
)((UInt8
*)end
- (UInt8
*)msg
);
240 senddata
.udata
.buf
= (UInt8
*)msg
;
242 return(OTSndUData(m
->p
->ep
, &senddata
));
245 mDNSlocal OSStatus
readpacket(mDNS
*m
)
247 mDNSAddr senderaddr
, destaddr
;
248 mDNSInterfaceID interface
;
249 mDNSIPPort senderport
;
257 recvdata
.addr
.maxlen
= sizeof(sender
);
258 recvdata
.addr
.len
= 0;
259 recvdata
.addr
.buf
= (UInt8
*)&sender
;
260 recvdata
.opt
.maxlen
= sizeof(options
);
261 recvdata
.opt
.len
= 0;
262 recvdata
.opt
.buf
= (UInt8
*)&options
;
263 recvdata
.udata
.maxlen
= sizeof(packet
);
264 recvdata
.udata
.len
= 0;
265 recvdata
.udata
.buf
= (UInt8
*)&packet
;
267 err
= OTRcvUData(m
->p
->ep
, &recvdata
, &flags
);
268 if (err
&& err
!= kOTNoDataErr
) debugf("OTRcvUData error %d", err
);
270 if (err
) return(err
);
272 senderaddr
.type
= mDNSAddrType_IPv4
;
273 senderaddr
.ip
.v4
.NotAnInteger
= sender
.fHost
;
274 senderport
.NotAnInteger
= sender
.fPort
;
276 destaddr
.type
= mDNSAddrType_IPv4
;
277 destaddr
.ip
.v4
= zerov4Addr
;
279 #if OTCARBONAPPLICATION
280 // IP_RCVDSTADDR is known to fail on OS X Carbon, so we'll just assume the packet was probably multicast
281 destaddr
.ip
.v4
= AllDNSLinkGroupv4
;
284 if (recvdata
.opt
.len
)
289 err
= OTNextOption(recvdata
.opt
.buf
, recvdata
.opt
.len
, &c
);
290 if (err
|| !c
) break;
291 if (c
->level
== INET_IP
&& c
->name
== IP_RCVDSTADDR
&& c
->len
- kOTOptionHeaderSize
== sizeof(destaddr
.ip
.v4
))
292 mDNSPlatformMemCopy(c
->value
, &destaddr
.ip
.v4
, sizeof(destaddr
.ip
.v4
));
296 interface
= m
->HostInterfaces
->InterfaceID
;
298 if (flags
& T_MORE
) debugf("ERROR: OTRcvUData() buffer too small (T_MORE set)");
299 else if (recvdata
.addr
.len
< sizeof(InetAddress
)) debugf("ERROR: recvdata.addr.len (%d) too short", recvdata
.addr
.len
);
300 else mDNSCoreReceive(m
, &packet
, recvdata
.udata
.buf
+ recvdata
.udata
.len
, &senderaddr
, senderport
, &destaddr
, MulticastDNSPort
, interface
);
305 mDNSexport mStatus
mDNSPlatformTCPConnect(const mDNSAddr
*dst
, mDNSOpaque16 dstport
, mDNSInterfaceID InterfaceID
,
306 TCPConnectionCallback callback
, void *context
, int *descriptor
)
309 (void)dstport
; // Unused
310 (void)InterfaceID
; // Unused
311 (void)callback
; // Unused
312 (void)context
; // Unused
313 (void)descriptor
; // Unused
314 return(mStatus_UnsupportedErr
);
317 mDNSexport
void mDNSPlatformTCPCloseConnection(int sd
)
322 mDNSexport
int mDNSPlatformReadTCP(int sd
, void *buf
, int buflen
)
326 (void)buflen
; // Unused
330 mDNSexport
int mDNSPlatformWriteTCP(int sd
, const char *msg
, int len
)
338 mDNSlocal
void mDNSOptionManagement(mDNS
*const m
)
342 // Make sure the length in the TNetbuf agrees with the length in the TOptionHeader
343 m
->p
->optReq
.opt
.len
= m
->p
->optBlock
.h
.len
;
344 m
->p
->optReq
.opt
.maxlen
= m
->p
->optBlock
.h
.len
;
345 if (m
->p
->optReq
.opt
.maxlen
< 4)
346 m
->p
->optReq
.opt
.maxlen
= 4;
348 err
= OTOptionManagement(m
->p
->ep
, &m
->p
->optReq
, NULL
);
349 if (err
) LogMsg("OTOptionManagement failed %d", err
);
352 mDNSlocal
void mDNSinitComplete(mDNS
*const m
, mStatus result
)
354 m
->mDNSPlatformStatus
= result
;
355 mDNSCoreInitComplete(m
, mStatus_NoError
);
358 mDNSlocal
pascal void mDNSNotifier(void *contextPtr
, OTEventCode code
, OTResult result
, void *cookie
)
360 mDNS
*const m
= (mDNS
*const)contextPtr
;
361 if (!m
) debugf("mDNSNotifier FATAL ERROR! No context");
367 InetInterfaceInfo interfaceinfo
;
368 if (result
) { LogMsg("T_OPENCOMPLETE failed %d", result
); mDNSinitComplete(m
, result
); return; }
369 //debugf("T_OPENCOMPLETE");
370 m
->p
->ep
= (EndpointRef
)cookie
;
371 //debugf("OTInetGetInterfaceInfo");
372 // (In future may want to loop over all interfaces instead of just using kDefaultInetInterface)
373 err
= OTInetGetInterfaceInfo(&interfaceinfo
, kDefaultInetInterface
);
374 if (err
) { LogMsg("OTInetGetInterfaceInfo failed %d", err
); mDNSinitComplete(m
, err
); return; }
376 // Make our basic standard host resource records (address, PTR, etc.)
377 m
->p
->interface
.InterfaceID
= (mDNSInterfaceID
)&m
->p
->interface
;
378 m
->p
->interface
.ip
.type
= mDNSAddrType_IPv4
;
379 m
->p
->interface
.ip
.ip
.v4
.NotAnInteger
= interfaceinfo
.fAddress
;
380 m
->p
->interface
.mask
.type
= mDNSAddrType_IPv4
;
381 m
->p
->interface
.mask
.ip
.v4
.NotAnInteger
= interfaceinfo
.fNetmask
;
382 m
->p
->interface
.ifname
[0] = 0;
383 m
->p
->interface
.Advertise
= m
->AdvertiseLocalAddresses
;
384 m
->p
->interface
.McastTxRx
= mDNStrue
;
387 case T_OPTMGMTCOMPLETE
:
389 // IP_RCVDSTADDR is known to fail on OS X Carbon, so we don't want to abort for that error
390 // (see comment above at the definition of kRcvDestAddrOption)
391 #if OTCARBONAPPLICATION
392 if (result
&& m
->p
->mOTstate
== mOT_RcvDestAddr
)
393 LogMsg("Carbon IP_RCVDSTADDR option failed %d; continuing anyway", result
);
396 if (result
) { LogMsg("T_OPTMGMTCOMPLETE/T_BINDCOMPLETE %d failed %d", m
->p
->mOTstate
, result
); mDNSinitComplete(m
, result
); return; }
397 //LogMsg("T_OPTMGMTCOMPLETE/T_BINDCOMPLETE %d", m->p->mOTstate);
398 switch (++m
->p
->mOTstate
)
400 case mOT_ReusePort
: m
->p
->optBlock
.b
= kReusePortOption
; mDNSOptionManagement(m
); break;
401 case mOT_RcvDestAddr
: m
->p
->optBlock
.i
= kRcvDestAddrOption
; mDNSOptionManagement(m
); break;
402 case mOT_SetUTTL
: m
->p
->optBlock
.i
= kSetUnicastTTLOption
; mDNSOptionManagement(m
); break;
403 case mOT_SetMTTL
: m
->p
->optBlock
.i
= kSetMulticastTTLOption
; mDNSOptionManagement(m
); break;
404 case mOT_LLScope
: m
->p
->optBlock
.m
= kAddLinkMulticastOption
; mDNSOptionManagement(m
); break;
405 // case mOT_AdminScope: m->p->optBlock.m = kAddAdminMulticastOption; mDNSOptionManagement(m); break;
406 case mOT_Bind
: OTBind(m
->p
->ep
, (TBind
*)&mDNSbindReq
, NULL
); break;
407 case mOT_Ready
: mDNSinitComplete(m
, mStatus_NoError
);
408 // Can't do mDNS_RegisterInterface until *after* mDNSinitComplete has set m->mDNSPlatformStatus to mStatus_NoError
409 mDNS_RegisterInterface(m
, &m
->p
->interface
, 0);
411 default: LogMsg("Unexpected m->p->mOTstate %d", m
->p
->mOTstate
-1);
417 while (readpacket(m
) == kOTNoError
) continue; // Read packets until we run out
420 case kOTProviderWillClose
: LogMsg("kOTProviderWillClose"); break;
421 case kOTProviderIsClosed
: // Machine is going to sleep, shutting down, or reconfiguring IP
422 LogMsg("kOTProviderIsClosed");
423 if (m
->p
->mOTstate
== mOT_Ready
)
425 m
->p
->mOTstate
= mOT_Closed
;
426 mDNS_DeregisterInterface(m
, &m
->p
->interface
);
428 if (m
->p
->ep
) { OTCloseProvider(m
->p
->ep
); m
->p
->ep
= NULL
; }
429 break; // Do we need to do anything?
431 default: debugf("mDNSNotifier: Unexpected OTEventCode %X", code
);
436 #if MDNS_ONLYSYSTEMTASK
438 static Boolean ONLYSYSTEMTASKevent
;
439 static void *ONLYSYSTEMTASKcontextPtr
;
440 static OTEventCode ONLYSYSTEMTASKcode
;
441 static OTResult ONLYSYSTEMTASKresult
;
442 static void *ONLYSYSTEMTASKcookie
;
444 mDNSlocal
pascal void CallmDNSNotifier(void *contextPtr
, OTEventCode code
, OTResult result
, void *cookie
)
446 ONLYSYSTEMTASKcontextPtr
= contextPtr
;
447 ONLYSYSTEMTASKcode
= code
;
448 ONLYSYSTEMTASKresult
= result
;
449 ONLYSYSTEMTASKcookie
= cookie
;
454 mDNSlocal
pascal void CallmDNSNotifier(void *contextPtr
, OTEventCode code
, OTResult result
, void *cookie
)
456 mDNS
*const m
= (mDNS
*const)contextPtr
;
457 if (!m
) debugf("mDNSNotifier FATAL ERROR! No context");
458 if (m
->p
->nesting
) LogMsg("CallmDNSNotifier ERROR! OTEnterNotifier is supposed to suppress notifier callbacks");
459 mDNSNotifier(contextPtr
, code
, result
, cookie
);
464 static OTNotifyUPP CallmDNSNotifierUPP
;
466 mDNSlocal OSStatus
mDNSOpenEndpoint(const mDNS
*const m
)
469 // m->optReq is pre-set to point to the shared m->optBlock
470 // m->optBlock is filled in by each OTOptionManagement call
471 m
->p
->optReq
.opt
.maxlen
= sizeof(m
->p
->optBlock
);
472 m
->p
->optReq
.opt
.len
= sizeof(m
->p
->optBlock
);
473 m
->p
->optReq
.opt
.buf
= (UInt8
*)&m
->p
->optBlock
;
474 m
->p
->optReq
.flags
= T_NEGOTIATE
;
476 // Open an endpoint and start answering queries
477 //printf("Opening endpoint now...\n");
479 m
->p
->mOTstate
= mOT_Start
;
480 err
= OTAsyncOpenEndpoint(OTCreateConfiguration(kUDPName
), 0, NULL
, CallmDNSNotifierUPP
, (void*)m
);
481 if (err
) { LogMsg("ERROR: OTAsyncOpenEndpoint(UDP) failed with error <%d>", err
); return(err
); }
485 // Define these here because they're not in older versions of OpenTransport.h
488 xOTStackIsLoading
= 0x27000001, /* Sent before Open Transport attempts to load the TCP/IP protocol stack.*/
489 xOTStackWasLoaded
= 0x27000002, /* Sent after the TCP/IP stack has been successfully loaded.*/
490 xOTStackIsUnloading
= 0x27000003 /* Sent before Open Transport unloads the TCP/IP stack.*/
493 static mDNS
*ClientNotifierContext
;
495 mDNSlocal
pascal void ClientNotifier(void *contextPtr
, OTEventCode code
, OTResult result
, void *cookie
)
497 mDNS
*const m
= ClientNotifierContext
;
499 #pragma unused(contextPtr) // Usually zero (except one in the 'xOTStackIsLoading' case)
500 #pragma unused(cookie) // Usually 'ipv4' (except for kOTPortNetworkChange)
501 #pragma unused(result) // Usually zero
505 case xOTStackIsLoading
: break;
506 case xOTStackWasLoaded
: if (m
->p
->mOTstate
== mOT_Closed
)
508 LogMsg("kOTStackWasLoaded: Re-opening endpoint");
510 LogMsg("kOTStackWasLoaded: ERROR: m->p->ep already set");
511 m
->mDNSPlatformStatus
= mStatus_Waiting
;
512 m
->p
->mOTstate
= mOT_Reset
;
513 #if !MDNS_ONLYSYSTEMTASK
518 LogMsg("kOTStackWasLoaded (no action)");
520 case xOTStackIsUnloading
: break;
521 case kOTPortNetworkChange
: break;
522 default: debugf("ClientNotifier unknown code %X, %X, %d", contextPtr
, code
, result
); break;
526 #if TARGET_API_MAC_CARBON
528 mDNSlocal
void GetUserSpecifiedComputerName(domainlabel
*const namelabel
)
530 CFStringRef cfs
= CSCopyMachineName();
531 CFStringGetPascalString(cfs
, namelabel
->c
, sizeof(*namelabel
), kCFStringEncodingUTF8
);
537 mDNSlocal OSStatus
ConvertStringHandleToUTF8(const StringHandle machineName
, UInt8
*const utf8
, ByteCount maxlen
)
540 TextEncoding utf8TextEncoding
, SystemTextEncoding
;
541 UnicodeMapping theMapping
;
542 TextToUnicodeInfo textToUnicodeInfo
;
543 ByteCount unicodelen
= 0;
545 if (maxlen
> 255) maxlen
= 255; // Can't put more than 255 in a Pascal String
547 utf8TextEncoding
= CreateTextEncoding(kTextEncodingUnicodeDefault
, kTextEncodingDefaultVariant
, kUnicodeUTF8Format
);
548 UpgradeScriptInfoToTextEncoding(smSystemScript
, kTextLanguageDontCare
, kTextRegionDontCare
, NULL
, &SystemTextEncoding
);
549 theMapping
.unicodeEncoding
= utf8TextEncoding
;
550 theMapping
.otherEncoding
= SystemTextEncoding
;
551 theMapping
.mappingVersion
= kUnicodeUseLatestMapping
;
552 status
= CreateTextToUnicodeInfo(&theMapping
, &textToUnicodeInfo
);
555 status
= ConvertFromPStringToUnicode(textToUnicodeInfo
, *machineName
, maxlen
, &unicodelen
, (UniCharArrayPtr
)&(utf8
[1]));
556 DisposeTextToUnicodeInfo(&textToUnicodeInfo
);
558 utf8
[0] = (UInt8
)unicodelen
;
562 mDNSlocal
void GetUserSpecifiedComputerName(domainlabel
*const namelabel
)
564 StringHandle machineName
= GetString(-16413); // Get machine name set in file sharing
567 char machineNameState
= HGetState((Handle
)machineName
);
568 HLock((Handle
)machineName
);
569 ConvertStringHandleToUTF8(machineName
, namelabel
->c
, MAX_DOMAIN_LABEL
);
570 HSetState((Handle
)machineName
, machineNameState
);
576 static pascal void mDNSTimerTask(void *arg
)
578 #if MDNS_ONLYSYSTEMTASK
580 ONLYSYSTEMTASKevent
= true;
582 mDNS
*const m
= (mDNS
*const)arg
;
583 if (!m
->p
->ep
) LogMsg("mDNSTimerTask NO endpoint");
584 if (m
->mDNS_busy
) LogMsg("mDNS_busy");
585 if (m
->p
->nesting
) LogMsg("mDNSTimerTask ERROR! OTEnterNotifier is supposed to suppress timer callbacks too");
587 // If our timer fires at a time when we have no endpoint, ignore it --
588 // once we reopen our endpoint and get our T_BINDCOMPLETE message we'll call
589 // mDNS_RegisterInterface(), which does a lock/unlock, which retriggers the timer.
590 // Likewise, if m->mDNS_busy or m->p->nesting, we'll catch this on the unlock
591 if (m
->p
->ep
&& m
->mDNS_busy
== 0 && m
->p
->nesting
== 0) mDNS_Execute(m
);
596 long sleep
, wake
, mode
;
599 mDNSexport mStatus
mDNSPlatformInit(mDNS
*const m
)
601 OSStatus err
= InitOpenTransport();
603 ClientNotifierContext
= m
;
604 // Note: OTRegisterAsClient returns kOTNotSupportedErr when running as Carbon code on OS X
605 // -- but that's okay, we don't need a ClientNotifier when running as Carbon code on OS X
606 OTRegisterAsClient(NULL
, NewOTNotifyUPP(ClientNotifier
));
608 m
->p
->OTTimerTask
= OTCreateTimerTask(NewOTProcessUPP(mDNSTimerTask
), m
);
612 sleep
= TickCount() + 600;
613 wake
= TickCount() + 1200;
617 // Set up the nice label
618 m
->nicelabel
.c
[0] = 0;
619 GetUserSpecifiedComputerName(&m
->nicelabel
);
620 // m->nicelabel = *(domainlabel*)"\pStu"; // For conflict testing
621 if (m
->nicelabel
.c
[0] == 0) MakeDomainLabelFromLiteralString(&m
->nicelabel
, "Macintosh");
623 // Set up the RFC 1034-compliant label
624 m
->hostlabel
.c
[0] = 0;
625 ConvertUTF8PstringToRFC1034HostLabel(m
->nicelabel
.c
, &m
->hostlabel
);
626 if (m
->hostlabel
.c
[0] == 0) MakeDomainLabelFromLiteralString(&m
->hostlabel
, "Macintosh");
630 // When it's finished mDNSOpenEndpoint asynchronously calls mDNSinitComplete() and then mDNS_RegisterInterface()
631 CallmDNSNotifierUPP
= NewOTNotifyUPP(CallmDNSNotifier
);
632 err
= mDNSOpenEndpoint(m
);
635 LogMsg("mDNSOpenEndpoint failed %d", err
);
636 if (m
->p
->OTTimerTask
) OTDestroyTimerTask(m
->p
->OTTimerTask
);
637 OTUnregisterAsClient();
638 CloseOpenTransport();
643 extern void mDNSPlatformClose (mDNS
*const m
)
645 if (m
->p
->mOTstate
== mOT_Ready
)
647 m
->p
->mOTstate
= mOT_Closed
;
648 mDNS_DeregisterInterface(m
, &m
->p
->interface
);
650 if (m
->p
->ep
) { OTCloseProvider (m
->p
->ep
); m
->p
->ep
= NULL
; }
651 if (m
->p
->OTTimerTask
) { OTDestroyTimerTask(m
->p
->OTTimerTask
); m
->p
->OTTimerTask
= 0; }
653 OTUnregisterAsClient();
654 CloseOpenTransport();
657 #if MDNS_ONLYSYSTEMTASK
658 extern void mDNSPlatformIdle(mDNS
*const m
);
659 mDNSexport
void mDNSPlatformIdle(mDNS
*const m
)
661 while (ONLYSYSTEMTASKcontextPtr
)
663 void *contextPtr
= ONLYSYSTEMTASKcontextPtr
;
664 ONLYSYSTEMTASKcontextPtr
= NULL
;
665 mDNSNotifier(contextPtr
, ONLYSYSTEMTASKcode
, ONLYSYSTEMTASKresult
, ONLYSYSTEMTASKcookie
);
667 if (ONLYSYSTEMTASKevent
)
669 ONLYSYSTEMTASKevent
= false;
673 if (m
->p
->mOTstate
== mOT_Reset
)
676 printf("******************************************************************************\n");
678 printf("Reopening endpoint\n");
680 m
->ResourceRecords
= NULL
;
686 case 0: if ((long)TickCount() - sleep
>= 0) { mDNSCoreMachineSleep(m
, 1); mode
++; }
688 case 1: if ((long)TickCount() - wake
>= 0) { mDNSCoreMachineSleep(m
, 0); mode
++; }
695 mDNSexport
void mDNSPlatformLock(const mDNS
*const m
)
697 if (!m
) { DebugStr("\pmDNSPlatformLock m NULL!"); return; }
698 if (!m
->p
) { DebugStr("\pmDNSPlatformLock m->p NULL!"); return; }
700 // If we try to call OTEnterNotifier and fail because we're already running at
701 // Notifier context, then make sure we don't do the matching OTLeaveNotifier() on exit.
702 // If we haven't even opened our endpoint yet, then just increment m->p->nesting for the same reason
703 if (m
->p
->mOTstate
== mOT_Ready
&& !m
->p
->ep
) DebugStr("\pmDNSPlatformLock: m->p->mOTstate == mOT_Ready && !m->p->ep");
704 if (!m
->p
->ep
|| m
->p
->nesting
|| OTEnterNotifier(m
->p
->ep
) == false) m
->p
->nesting
++;
707 mDNSlocal
void ScheduleNextTimerCallback(const mDNS
*const m
)
709 if (m
->mDNSPlatformStatus
== mStatus_NoError
)
711 SInt32 interval
= m
->NextScheduledEvent
- mDNS_TimeNow_NoLock(m
);
712 if (interval
< 1) interval
= 1;
713 else if (interval
> 0x70000000 / 1000) interval
= 0x70000000 / mDNSPlatformOneSecond
;
714 else interval
= (interval
* 1000 + mDNSPlatformOneSecond
-1)/ mDNSPlatformOneSecond
;
715 OTScheduleTimerTask(m
->p
->OTTimerTask
, (OTTimeout
)interval
);
719 mDNSexport
void mDNSPlatformUnlock(const mDNS
*const m
)
721 if (!m
) { DebugStr("\pmDNSPlatformUnlock m NULL!"); return; }
722 if (!m
->p
) { DebugStr("\pmDNSPlatformUnlock m->p NULL!"); return; }
724 if (m
->p
->ep
&& m
->mDNS_busy
== 0) ScheduleNextTimerCallback(m
);
726 if (m
->p
->nesting
) m
->p
->nesting
--;
727 else OTLeaveNotifier(m
->p
->ep
);
730 mDNSexport
void mDNSPlatformStrCopy(const void *src
, void *dst
) { OTStrCopy((char*)dst
, (char*)src
); }
731 mDNSexport UInt32
mDNSPlatformStrLen (const void *src
) { return(OTStrLength((char*)src
)); }
732 mDNSexport
void mDNSPlatformMemCopy(const void *src
, void *dst
, UInt32 len
) { OTMemcpy(dst
, src
, len
); }
733 mDNSexport mDNSBool
mDNSPlatformMemSame(const void *src
, const void *dst
, UInt32 len
) { return(OTMemcmp(dst
, src
, len
)); }
734 mDNSexport
void mDNSPlatformMemZero( void *dst
, UInt32 len
) { OTMemzero(dst
, len
); }
735 mDNSexport
void * mDNSPlatformMemAllocate(mDNSu32 len
) { return(OTAllocMem(len
)); }
736 mDNSexport
void mDNSPlatformMemFree(void *mem
) { OTFreeMem(mem
); }
737 mDNSexport mDNSu32
mDNSPlatformRandomSeed(void) { return(TickCount()); }
738 mDNSexport mStatus
mDNSPlatformTimeInit(void) { return(mStatus_NoError
); }
739 mDNSexport SInt32
mDNSPlatformRawTime() { return((SInt32
)TickCount()); }
740 mDNSexport SInt32 mDNSPlatformOneSecond
= 60;
742 mDNSexport mDNSs32
mDNSPlatformUTC(void)
744 // Classic Mac OS since Midnight, 1st Jan 1904
745 // Standard Unix counts from 1970
746 // This value adjusts for the 66 years and 17 leap-days difference
747 mDNSu32 SecsSince1904
;
748 MachineLocation ThisLocation
;
749 #define TIME_ADJUST (((1970 - 1904) * 365 + 17) * 24 * 60 * 60)
750 #define ThisLocationGMTdelta ((ThisLocation.u.gmtDelta << 8) >> 8)
751 GetDateTime(&SecsSince1904
);
752 ReadLocation(&ThisLocation
);
753 return((mDNSs32
)(SecsSince1904
- ThisLocationGMTdelta
- TIME_ADJUST
));