1 /* -*- Mode: C; tab-width: 4 -*-
3 * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved.
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
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 Change History (most recent first):
19 $Log: mDNSMacOS9.c,v $
20 Revision 1.51 2007/09/12 19:23:17 cheshire
21 Get rid of unnecessary mDNSPlatformTCPIsConnected() routine
23 Revision 1.50 2007/04/05 20:40:37 cheshire
24 Remove unused mDNSPlatformTCPGetFlags()
26 Revision 1.49 2007/03/22 18:31:48 cheshire
27 Put dst parameter first in mDNSPlatformStrCopy/mDNSPlatformMemCopy, like conventional Posix strcpy/memcpy
29 Revision 1.48 2007/03/20 17:07:15 cheshire
30 Rename "struct uDNS_TCPSocket_struct" to "TCPSocket", "struct uDNS_UDPSocket_struct" to "UDPSocket"
32 Revision 1.47 2006/12/19 22:43:54 cheshire
35 Revision 1.46 2006/08/14 23:24:29 cheshire
36 Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
38 Revision 1.45 2006/03/19 02:00:14 cheshire
39 <rdar://problem/4073825> Improve logic for delaying packets after repeated interface transitions
41 Revision 1.44 2005/09/16 21:06:50 cheshire
42 Use mDNS_TimeNow_NoLock macro, instead of writing "mDNSPlatformRawTime() + m->timenow_adjust" all over the place
44 Revision 1.43 2004/12/17 23:37:49 cheshire
45 <rdar://problem/3485365> Guard against repeating wireless dissociation/re-association
46 (and other repetitive configuration changes)
48 Revision 1.42 2004/12/16 20:43:39 cheshire
49 interfaceinfo.fMask should be interfaceinfo.fNetmask
51 Revision 1.41 2004/10/16 00:17:00 cheshire
52 <rdar://problem/3770558> Replace IP TTL 255 check with local subnet source address check
54 Revision 1.40 2004/09/27 23:56:27 cheshire
55 Fix infinite loop where mDNSPlatformUnlock() called mDNS_TimeNow(),
56 and then mDNS_TimeNow() called mDNSPlatformUnlock()
58 Revision 1.39 2004/09/21 21:02:54 cheshire
59 Set up ifname before calling mDNS_RegisterInterface()
61 Revision 1.38 2004/09/17 01:08:50 cheshire
62 Renamed mDNSClientAPI.h to mDNSEmbeddedAPI.h
63 The name "mDNSClientAPI.h" is misleading to new developers looking at this code. The interfaces
64 declared in that file are ONLY appropriate to single-address-space embedded applications.
65 For clients on general-purpose computers, the interfaces defined in dns_sd.h should be used.
67 Revision 1.37 2004/09/17 00:19:10 cheshire
68 For consistency with AllDNSLinkGroupv6, rename AllDNSLinkGroup to AllDNSLinkGroupv4
70 Revision 1.36 2004/09/16 21:59:16 cheshire
71 For consistency with zerov6Addr, rename zeroIPAddr to zerov4Addr
73 Revision 1.35 2004/09/16 00:24:49 cheshire
74 <rdar://problem/3803162> Fix unsafe use of mDNSPlatformTimeNow()
76 Revision 1.34 2004/09/14 23:42:36 cheshire
77 <rdar://problem/3801296> Need to seed random number generator from platform-layer data
79 Revision 1.33 2004/09/14 23:16:31 cheshire
80 Fix compile error: mDNS_SetFQDNs has been renamed to mDNS_SetFQDN
82 Revision 1.32 2004/09/14 21:03:16 cheshire
85 Revision 1.31 2004/08/14 03:22:42 cheshire
86 <rdar://problem/3762579> Dynamic DNS UI <-> mDNSResponder glue
87 Add GetUserSpecifiedDDNSName() routine
88 Convert ServiceRegDomain to domainname instead of C string
89 Replace mDNS_GenerateFQDN/mDNS_GenerateGlobalFQDN with mDNS_SetFQDNs
91 Revision 1.30 2004/07/29 19:26:03 ksekar
92 Plaform-level changes for NAT-PMP support
94 Revision 1.29 2004/05/26 20:53:16 cheshire
95 Remove unncecessary "return( -1 );" at the end of mDNSPlatformUTC()
97 Revision 1.28 2004/05/20 18:39:06 cheshire
98 Fix build broken by addition of mDNSPlatformUTC requirement
100 Revision 1.27 2004/04/21 02:49:11 cheshire
101 To reduce future confusion, renamed 'TxAndRx' to 'McastTxRx'
103 Revision 1.26 2004/04/09 17:43:03 cheshire
104 Make sure to set the McastTxRx field so that duplicate suppression works correctly
106 Revision 1.25 2004/03/15 18:55:38 cheshire
107 Comment out debugging message
109 Revision 1.24 2004/03/12 21:30:26 cheshire
110 Build a System-Context Shared Library from mDNSCore, for the benefit of developers
111 like Muse Research who want to be able to use mDNS/DNS-SD from GPL-licensed code.
113 Revision 1.23 2004/02/09 23:24:43 cheshire
114 Need to set TTL 255 to interoperate with peers that check TTL (oops!)
116 Revision 1.22 2004/01/27 20:15:23 cheshire
117 <rdar://problem/3541288>: Time to prune obsolete code for listening on port 53
119 Revision 1.21 2004/01/24 04:59:16 cheshire
120 Fixes so that Posix/Linux, OS9, Windows, and VxWorks targets build again
122 Revision 1.20 2003/11/14 20:59:09 cheshire
123 Clients can't use AssignDomainName macro because mDNSPlatformMemCopy is defined in mDNSPlatformFunctions.h.
124 Best solution is just to combine mDNSEmbeddedAPI.h and mDNSPlatformFunctions.h into a single file.
126 Revision 1.19 2003/08/18 23:09:20 cheshire
127 <rdar://problem/3382647> mDNSResponder divide by zero in mDNSPlatformRawTime()
129 Revision 1.18 2003/08/12 19:56:24 cheshire
135 #include <stdarg.h> // For va_list support
137 #include <LowMem.h> // For LMGetCurApName()
138 #include <TextUtils.h> // For smSystemScript
139 #include <UnicodeConverter.h> // For ConvertFromPStringToUnicode()
141 #include "mDNSEmbeddedAPI.h" // Defines the interface provided to the client layer above
143 #include "mDNSMacOS9.h" // Defines the specific types needed to run mDNS on this platform
145 // ***************************************************************************
148 static const TSetBooleanOption kReusePortOption
=
149 { kOTBooleanOptionSize
, INET_IP
, IP_REUSEPORT
, 0, true };
151 // IP_RCVDSTADDR with TSetByteOption/kOTOneByteOptionSize works on OS 9, OS X Classic, and OS 9 Carbon,
152 // but gives error #-3151 (kOTBadOptionErr) on OS X Carbon.
153 // If we instead use TSetBooleanOption/kOTBooleanOptionSize then OTOptionManagement on OS X Carbon
154 // no longer returns -3151 but it still doesn't actually work -- no destination addresses
155 // are delivered by OTRcvUData. I think it's just a bug in OS X Carbon.
156 static const TSetByteOption kRcvDestAddrOption
=
157 { kOTOneByteOptionSize
, INET_IP
, IP_RCVDSTADDR
, 0, true };
158 //static const TSetBooleanOption kRcvDestAddrOption =
159 // { kOTBooleanOptionSize, INET_IP, IP_RCVDSTADDR, 0, true };
161 static const TSetByteOption kSetUnicastTTLOption
=
162 { kOTOneByteOptionSize
, INET_IP
, IP_TTL
, 0, 255 };
164 static const TSetByteOption kSetMulticastTTLOption
=
165 { kOTOneByteOptionSize
, INET_IP
, IP_MULTICAST_TTL
, 0, 255 };
167 static const TIPAddMulticastOption kAddLinkMulticastOption
=
168 { sizeof(TIPAddMulticastOption
), INET_IP
, IP_ADD_MEMBERSHIP
, 0, { 224, 0, 0,251 }, { 0,0,0,0 } };
170 //static const TIPAddMulticastOption kAddAdminMulticastOption =
171 // { sizeof(TIPAddMulticastOption), INET_IP, IP_ADD_MEMBERSHIP, 0, { 239,255,255,251 }, { 0,0,0,0 } };
173 // Bind endpoint to port number. Don't specify any specific IP address --
174 // we want to receive unicasts on all interfaces, as well as multicasts.
175 typedef struct { OTAddressType fAddressType
; mDNSIPPort fPort
; mDNSv4Addr fHost
; UInt8 fUnused
[8]; } mDNSInetAddress
;
176 //static const mDNSInetAddress mDNSPortInetAddress = { AF_INET, { 0,0 }, { 0,0,0,0 } }; // For testing legacy client support
177 #define MulticastDNSPortAsNumber 5353
178 static const mDNSInetAddress mDNSPortInetAddress
= { AF_INET
, { MulticastDNSPortAsNumber
>> 8, MulticastDNSPortAsNumber
& 0xFF }, { 0,0,0,0 } };
179 static const TBind mDNSbindReq
= { sizeof(mDNSPortInetAddress
), sizeof(mDNSPortInetAddress
), (UInt8
*)&mDNSPortInetAddress
, 0 };
181 static const TNetbuf zeroTNetbuf
= { 0 };
183 // ***************************************************************************
186 mDNSlocal
void SafeDebugStr(unsigned char *buffer
)
189 // Don't want semicolons in MacsBug messages -- they signify commands to execute
190 for (i
=1; i
<= buffer
[0]; i
++) if (buffer
[i
] == ';') buffer
[i
] = '.';
195 mDNSexport
void debugf_(const char *format
, ...)
197 unsigned char buffer
[256];
199 va_start(ptr
,format
);
200 buffer
[0] = (unsigned char)mDNS_vsnprintf((char*)buffer
+1, 255, format
, ptr
);
202 #if MDNS_ONLYSYSTEMTASK
203 buffer
[1+buffer
[0]] = 0;
204 fprintf(stderr
, "%s\n", buffer
+1);
207 SafeDebugStr(buffer
);
212 #if MDNS_BUILDINGSHAREDLIBRARY >= 2
213 // When building the non-debug version of the Extension, intended to go on end-user systems, we don't want
214 // MacsBug breaks for *anything*, not even for the serious LogMsg messages that on OS X would be written to syslog
215 mDNSexport
void LogMsg(const char *format
, ...) { (void)format
; }
217 mDNSexport
void LogMsg(const char *format
, ...)
219 unsigned char buffer
[256];
221 va_start(ptr
,format
);
222 buffer
[0] = (unsigned char)mDNS_vsnprintf((char*)buffer
+1, 255, format
, ptr
);
224 #if MDNS_ONLYSYSTEMTASK
225 buffer
[1+buffer
[0]] = 0;
226 fprintf(stderr
, "%s\n", buffer
+1);
229 SafeDebugStr(buffer
);
234 mDNSexport mStatus
mDNSPlatformSendUDP(const mDNS
*const m
, const void *const msg
, const mDNSu8
*const end
,
235 mDNSInterfaceID InterfaceID
, const mDNSAddr
*dst
, mDNSIPPort dstPort
)
237 // Note: If we did multi-homing, we'd have to use the InterfaceID parameter to specify from which interface to send this response
238 #pragma unused(InterfaceID)
240 InetAddress InetDest
;
243 if (dst
->type
!= mDNSAddrType_IPv4
) return(mStatus_NoError
);
245 InetDest
.fAddressType
= AF_INET
;
246 InetDest
.fPort
= dstPort
.NotAnInteger
;
247 InetDest
.fHost
= dst
->ip
.v4
.NotAnInteger
;
249 senddata
.addr
.maxlen
= sizeof(InetDest
);
250 senddata
.addr
.len
= sizeof(InetDest
);
251 senddata
.addr
.buf
= (UInt8
*)&InetDest
;
252 senddata
.opt
= zeroTNetbuf
;
253 senddata
.udata
.maxlen
= (UInt32
)((UInt8
*)end
- (UInt8
*)msg
);
254 senddata
.udata
.len
= (UInt32
)((UInt8
*)end
- (UInt8
*)msg
);
255 senddata
.udata
.buf
= (UInt8
*)msg
;
257 return(OTSndUData(m
->p
->ep
, &senddata
));
260 mDNSlocal OSStatus
readpacket(mDNS
*m
)
262 mDNSAddr senderaddr
, destaddr
;
263 mDNSInterfaceID interface
;
264 mDNSIPPort senderport
;
272 recvdata
.addr
.maxlen
= sizeof(sender
);
273 recvdata
.addr
.len
= 0;
274 recvdata
.addr
.buf
= (UInt8
*)&sender
;
275 recvdata
.opt
.maxlen
= sizeof(options
);
276 recvdata
.opt
.len
= 0;
277 recvdata
.opt
.buf
= (UInt8
*)&options
;
278 recvdata
.udata
.maxlen
= sizeof(packet
);
279 recvdata
.udata
.len
= 0;
280 recvdata
.udata
.buf
= (UInt8
*)&packet
;
282 err
= OTRcvUData(m
->p
->ep
, &recvdata
, &flags
);
283 if (err
&& err
!= kOTNoDataErr
) debugf("OTRcvUData error %d", err
);
285 if (err
) return(err
);
287 senderaddr
.type
= mDNSAddrType_IPv4
;
288 senderaddr
.ip
.v4
.NotAnInteger
= sender
.fHost
;
289 senderport
.NotAnInteger
= sender
.fPort
;
291 destaddr
.type
= mDNSAddrType_IPv4
;
292 destaddr
.ip
.v4
= zerov4Addr
;
294 #if OTCARBONAPPLICATION
295 // IP_RCVDSTADDR is known to fail on OS X Carbon, so we'll just assume the packet was probably multicast
296 destaddr
.ip
.v4
= AllDNSLinkGroup_v4
.ip
.v4
;
299 if (recvdata
.opt
.len
)
304 err
= OTNextOption(recvdata
.opt
.buf
, recvdata
.opt
.len
, &c
);
305 if (err
|| !c
) break;
306 if (c
->level
== INET_IP
&& c
->name
== IP_RCVDSTADDR
&& c
->len
- kOTOptionHeaderSize
== sizeof(destaddr
.ip
.v4
))
307 mDNSPlatformMemCopy(&destaddr
.ip
.v4
, c
->value
, sizeof(destaddr
.ip
.v4
));
311 interface
= m
->HostInterfaces
->InterfaceID
;
313 if (flags
& T_MORE
) debugf("ERROR: OTRcvUData() buffer too small (T_MORE set)");
314 else if (recvdata
.addr
.len
< sizeof(InetAddress
)) debugf("ERROR: recvdata.addr.len (%d) too short", recvdata
.addr
.len
);
315 else mDNSCoreReceive(m
, &packet
, recvdata
.udata
.buf
+ recvdata
.udata
.len
, &senderaddr
, senderport
, &destaddr
, MulticastDNSPort
, interface
);
320 mDNSexport TCPSocket
*mDNSPlatformTCPSocket(mDNS
* const m
, TCPSocketFlags flags
, mDNSIPPort
* port
)
323 (void)flags
; // Unused
324 (void)port
; // Unused
328 mDNSexport TCPSocket
*mDNSPlatformTCPAccept(TCPSocketFlags flags
, int sd
)
330 (void)flags
; // Unused
335 mDNSexport
int mDNSPlatformTCPGetFD(TCPSocket
*sock
)
337 (void)sock
; // Unused
341 mDNSexport mStatus
mDNSPlatformTCPConnect(TCPSocket
*sock
, const mDNSAddr
* dst
, mDNSOpaque16 dstport
, mDNSInterfaceID InterfaceID
,
342 TCPConnectionCallback callback
, void * context
)
344 (void)sock
; // Unused
346 (void)dstport
; // Unused
347 (void)InterfaceID
; // Unused
348 (void)callback
; // Unused
349 (void)context
; // Unused
350 return(mStatus_UnsupportedErr
);
353 mDNSexport
void mDNSPlatformTCPCloseConnection(TCPSocket
*sd
)
358 mDNSexport
long mDNSPlatformReadTCP(TCPSocket
*sock
, void *buf
, unsigned long buflen
, mDNSBool
*closed
)
360 (void)sock
; // Unused
362 (void)buflen
; // Unused
363 (void)closed
; // Unused
367 mDNSexport
long mDNSPlatformWriteTCP(TCPSocket
*sock
, const char *msg
, unsigned long len
)
369 (void)sock
; // Unused
375 mDNSexport UDPSocket
*mDNSPlatformUDPSocket(mDNS
* const m
, mDNSIPPort port
)
378 (void)port
; // Unused
382 mDNSexport
void mDNSPlatformUDPClose(UDPSocket
*sock
)
384 (void)sock
; // Unused
387 mDNSlocal
void mDNSOptionManagement(mDNS
*const m
)
391 // Make sure the length in the TNetbuf agrees with the length in the TOptionHeader
392 m
->p
->optReq
.opt
.len
= m
->p
->optBlock
.h
.len
;
393 m
->p
->optReq
.opt
.maxlen
= m
->p
->optBlock
.h
.len
;
394 if (m
->p
->optReq
.opt
.maxlen
< 4)
395 m
->p
->optReq
.opt
.maxlen
= 4;
397 err
= OTOptionManagement(m
->p
->ep
, &m
->p
->optReq
, NULL
);
398 if (err
) LogMsg("OTOptionManagement failed %d", err
);
401 mDNSlocal
void mDNSinitComplete(mDNS
*const m
, mStatus result
)
403 m
->mDNSPlatformStatus
= result
;
404 mDNSCoreInitComplete(m
, mStatus_NoError
);
407 mDNSlocal
pascal void mDNSNotifier(void *contextPtr
, OTEventCode code
, OTResult result
, void *cookie
)
409 mDNS
*const m
= (mDNS
*const)contextPtr
;
410 if (!m
) debugf("mDNSNotifier FATAL ERROR! No context");
416 InetInterfaceInfo interfaceinfo
;
417 if (result
) { LogMsg("T_OPENCOMPLETE failed %d", result
); mDNSinitComplete(m
, result
); return; }
418 //debugf("T_OPENCOMPLETE");
419 m
->p
->ep
= (EndpointRef
)cookie
;
420 //debugf("OTInetGetInterfaceInfo");
421 // (In future may want to loop over all interfaces instead of just using kDefaultInetInterface)
422 err
= OTInetGetInterfaceInfo(&interfaceinfo
, kDefaultInetInterface
);
423 if (err
) { LogMsg("OTInetGetInterfaceInfo failed %d", err
); mDNSinitComplete(m
, err
); return; }
425 // Make our basic standard host resource records (address, PTR, etc.)
426 m
->p
->interface
.InterfaceID
= (mDNSInterfaceID
)&m
->p
->interface
;
427 m
->p
->interface
.ip
.type
= mDNSAddrType_IPv4
;
428 m
->p
->interface
.ip
.ip
.v4
.NotAnInteger
= interfaceinfo
.fAddress
;
429 m
->p
->interface
.mask
.type
= mDNSAddrType_IPv4
;
430 m
->p
->interface
.mask
.ip
.v4
.NotAnInteger
= interfaceinfo
.fNetmask
;
431 m
->p
->interface
.ifname
[0] = 0;
432 m
->p
->interface
.Advertise
= m
->AdvertiseLocalAddresses
;
433 m
->p
->interface
.McastTxRx
= mDNStrue
;
436 case T_OPTMGMTCOMPLETE
:
438 // IP_RCVDSTADDR is known to fail on OS X Carbon, so we don't want to abort for that error
439 // (see comment above at the definition of kRcvDestAddrOption)
440 #if OTCARBONAPPLICATION
441 if (result
&& m
->p
->mOTstate
== mOT_RcvDestAddr
)
442 LogMsg("Carbon IP_RCVDSTADDR option failed %d; continuing anyway", result
);
445 if (result
) { LogMsg("T_OPTMGMTCOMPLETE/T_BINDCOMPLETE %d failed %d", m
->p
->mOTstate
, result
); mDNSinitComplete(m
, result
); return; }
446 //LogMsg("T_OPTMGMTCOMPLETE/T_BINDCOMPLETE %d", m->p->mOTstate);
447 switch (++m
->p
->mOTstate
)
449 case mOT_ReusePort
: m
->p
->optBlock
.b
= kReusePortOption
; mDNSOptionManagement(m
); break;
450 case mOT_RcvDestAddr
: m
->p
->optBlock
.i
= kRcvDestAddrOption
; mDNSOptionManagement(m
); break;
451 case mOT_SetUTTL
: m
->p
->optBlock
.i
= kSetUnicastTTLOption
; mDNSOptionManagement(m
); break;
452 case mOT_SetMTTL
: m
->p
->optBlock
.i
= kSetMulticastTTLOption
; mDNSOptionManagement(m
); break;
453 case mOT_LLScope
: m
->p
->optBlock
.m
= kAddLinkMulticastOption
; mDNSOptionManagement(m
); break;
454 // case mOT_AdminScope: m->p->optBlock.m = kAddAdminMulticastOption; mDNSOptionManagement(m); break;
455 case mOT_Bind
: OTBind(m
->p
->ep
, (TBind
*)&mDNSbindReq
, NULL
); break;
456 case mOT_Ready
: mDNSinitComplete(m
, mStatus_NoError
);
457 // Can't do mDNS_RegisterInterface until *after* mDNSinitComplete has set m->mDNSPlatformStatus to mStatus_NoError
458 mDNS_RegisterInterface(m
, &m
->p
->interface
, mDNSfalse
);
460 default: LogMsg("Unexpected m->p->mOTstate %d", m
->p
->mOTstate
-1);
466 while (readpacket(m
) == kOTNoError
) continue; // Read packets until we run out
469 case kOTProviderWillClose
: LogMsg("kOTProviderWillClose"); break;
470 case kOTProviderIsClosed
: // Machine is going to sleep, shutting down, or reconfiguring IP
471 LogMsg("kOTProviderIsClosed");
472 if (m
->p
->mOTstate
== mOT_Ready
)
474 m
->p
->mOTstate
= mOT_Closed
;
475 mDNS_DeregisterInterface(m
, &m
->p
->interface
, mDNSfalse
);
477 if (m
->p
->ep
) { OTCloseProvider(m
->p
->ep
); m
->p
->ep
= NULL
; }
478 break; // Do we need to do anything?
480 default: debugf("mDNSNotifier: Unexpected OTEventCode %X", code
);
485 #if MDNS_ONLYSYSTEMTASK
487 static Boolean ONLYSYSTEMTASKevent
;
488 static void *ONLYSYSTEMTASKcontextPtr
;
489 static OTEventCode ONLYSYSTEMTASKcode
;
490 static OTResult ONLYSYSTEMTASKresult
;
491 static void *ONLYSYSTEMTASKcookie
;
493 mDNSlocal
pascal void CallmDNSNotifier(void *contextPtr
, OTEventCode code
, OTResult result
, void *cookie
)
495 ONLYSYSTEMTASKcontextPtr
= contextPtr
;
496 ONLYSYSTEMTASKcode
= code
;
497 ONLYSYSTEMTASKresult
= result
;
498 ONLYSYSTEMTASKcookie
= cookie
;
503 mDNSlocal
pascal void CallmDNSNotifier(void *contextPtr
, OTEventCode code
, OTResult result
, void *cookie
)
505 mDNS
*const m
= (mDNS
*const)contextPtr
;
506 if (!m
) debugf("mDNSNotifier FATAL ERROR! No context");
507 if (m
->p
->nesting
) LogMsg("CallmDNSNotifier ERROR! OTEnterNotifier is supposed to suppress notifier callbacks");
508 mDNSNotifier(contextPtr
, code
, result
, cookie
);
513 static OTNotifyUPP CallmDNSNotifierUPP
;
515 mDNSlocal OSStatus
mDNSOpenEndpoint(const mDNS
*const m
)
518 // m->optReq is pre-set to point to the shared m->optBlock
519 // m->optBlock is filled in by each OTOptionManagement call
520 m
->p
->optReq
.opt
.maxlen
= sizeof(m
->p
->optBlock
);
521 m
->p
->optReq
.opt
.len
= sizeof(m
->p
->optBlock
);
522 m
->p
->optReq
.opt
.buf
= (UInt8
*)&m
->p
->optBlock
;
523 m
->p
->optReq
.flags
= T_NEGOTIATE
;
525 // Open an endpoint and start answering queries
526 //printf("Opening endpoint now...\n");
528 m
->p
->mOTstate
= mOT_Start
;
529 err
= OTAsyncOpenEndpoint(OTCreateConfiguration(kUDPName
), 0, NULL
, CallmDNSNotifierUPP
, (void*)m
);
530 if (err
) { LogMsg("ERROR: OTAsyncOpenEndpoint(UDP) failed with error <%d>", err
); return(err
); }
534 // Define these here because they're not in older versions of OpenTransport.h
537 xOTStackIsLoading
= 0x27000001, /* Sent before Open Transport attempts to load the TCP/IP protocol stack.*/
538 xOTStackWasLoaded
= 0x27000002, /* Sent after the TCP/IP stack has been successfully loaded.*/
539 xOTStackIsUnloading
= 0x27000003 /* Sent before Open Transport unloads the TCP/IP stack.*/
542 static mDNS
*ClientNotifierContext
;
544 mDNSlocal
pascal void ClientNotifier(void *contextPtr
, OTEventCode code
, OTResult result
, void *cookie
)
546 mDNS
*const m
= ClientNotifierContext
;
548 #pragma unused(contextPtr) // Usually zero (except one in the 'xOTStackIsLoading' case)
549 #pragma unused(cookie) // Usually 'ipv4' (except for kOTPortNetworkChange)
550 #pragma unused(result) // Usually zero
554 case xOTStackIsLoading
: break;
555 case xOTStackWasLoaded
: if (m
->p
->mOTstate
== mOT_Closed
)
557 LogMsg("kOTStackWasLoaded: Re-opening endpoint");
559 LogMsg("kOTStackWasLoaded: ERROR: m->p->ep already set");
560 m
->mDNSPlatformStatus
= mStatus_Waiting
;
561 m
->p
->mOTstate
= mOT_Reset
;
562 #if !MDNS_ONLYSYSTEMTASK
567 LogMsg("kOTStackWasLoaded (no action)");
569 case xOTStackIsUnloading
: break;
570 case kOTPortNetworkChange
: break;
571 default: debugf("ClientNotifier unknown code %X, %X, %d", contextPtr
, code
, result
); break;
575 #if TARGET_API_MAC_CARBON
577 mDNSlocal
void GetUserSpecifiedComputerName(domainlabel
*const namelabel
)
579 CFStringRef cfs
= CSCopyMachineName();
580 CFStringGetPascalString(cfs
, namelabel
->c
, sizeof(*namelabel
), kCFStringEncodingUTF8
);
586 mDNSlocal OSStatus
ConvertStringHandleToUTF8(const StringHandle machineName
, UInt8
*const utf8
, ByteCount maxlen
)
589 TextEncoding utf8TextEncoding
, SystemTextEncoding
;
590 UnicodeMapping theMapping
;
591 TextToUnicodeInfo textToUnicodeInfo
;
592 ByteCount unicodelen
= 0;
594 if (maxlen
> 255) maxlen
= 255; // Can't put more than 255 in a Pascal String
596 utf8TextEncoding
= CreateTextEncoding(kTextEncodingUnicodeDefault
, kTextEncodingDefaultVariant
, kUnicodeUTF8Format
);
597 UpgradeScriptInfoToTextEncoding(smSystemScript
, kTextLanguageDontCare
, kTextRegionDontCare
, NULL
, &SystemTextEncoding
);
598 theMapping
.unicodeEncoding
= utf8TextEncoding
;
599 theMapping
.otherEncoding
= SystemTextEncoding
;
600 theMapping
.mappingVersion
= kUnicodeUseLatestMapping
;
601 status
= CreateTextToUnicodeInfo(&theMapping
, &textToUnicodeInfo
);
604 status
= ConvertFromPStringToUnicode(textToUnicodeInfo
, *machineName
, maxlen
, &unicodelen
, (UniCharArrayPtr
)&(utf8
[1]));
605 DisposeTextToUnicodeInfo(&textToUnicodeInfo
);
607 utf8
[0] = (UInt8
)unicodelen
;
611 mDNSlocal
void GetUserSpecifiedComputerName(domainlabel
*const namelabel
)
613 StringHandle machineName
= GetString(-16413); // Get machine name set in file sharing
616 char machineNameState
= HGetState((Handle
)machineName
);
617 HLock((Handle
)machineName
);
618 ConvertStringHandleToUTF8(machineName
, namelabel
->c
, MAX_DOMAIN_LABEL
);
619 HSetState((Handle
)machineName
, machineNameState
);
625 static pascal void mDNSTimerTask(void *arg
)
627 #if MDNS_ONLYSYSTEMTASK
629 ONLYSYSTEMTASKevent
= true;
631 mDNS
*const m
= (mDNS
*const)arg
;
632 if (!m
->p
->ep
) LogMsg("mDNSTimerTask NO endpoint");
633 if (m
->mDNS_busy
) LogMsg("mDNS_busy");
634 if (m
->p
->nesting
) LogMsg("mDNSTimerTask ERROR! OTEnterNotifier is supposed to suppress timer callbacks too");
636 // If our timer fires at a time when we have no endpoint, ignore it --
637 // once we reopen our endpoint and get our T_BINDCOMPLETE message we'll call
638 // mDNS_RegisterInterface(), which does a lock/unlock, which retriggers the timer.
639 // Likewise, if m->mDNS_busy or m->p->nesting, we'll catch this on the unlock
640 if (m
->p
->ep
&& m
->mDNS_busy
== 0 && m
->p
->nesting
== 0) mDNS_Execute(m
);
645 long sleep
, wake
, mode
;
648 mDNSexport mStatus
mDNSPlatformInit(mDNS
*const m
)
650 OSStatus err
= InitOpenTransport();
652 ClientNotifierContext
= m
;
653 // Note: OTRegisterAsClient returns kOTNotSupportedErr when running as Carbon code on OS X
654 // -- but that's okay, we don't need a ClientNotifier when running as Carbon code on OS X
655 OTRegisterAsClient(NULL
, NewOTNotifyUPP(ClientNotifier
));
657 m
->p
->OTTimerTask
= OTCreateTimerTask(NewOTProcessUPP(mDNSTimerTask
), m
);
661 sleep
= TickCount() + 600;
662 wake
= TickCount() + 1200;
666 // Set up the nice label
667 m
->nicelabel
.c
[0] = 0;
668 GetUserSpecifiedComputerName(&m
->nicelabel
);
669 // m->nicelabel = *(domainlabel*)"\pStu"; // For conflict testing
670 if (m
->nicelabel
.c
[0] == 0) MakeDomainLabelFromLiteralString(&m
->nicelabel
, "Macintosh");
672 // Set up the RFC 1034-compliant label
673 m
->hostlabel
.c
[0] = 0;
674 ConvertUTF8PstringToRFC1034HostLabel(m
->nicelabel
.c
, &m
->hostlabel
);
675 if (m
->hostlabel
.c
[0] == 0) MakeDomainLabelFromLiteralString(&m
->hostlabel
, "Macintosh");
679 // When it's finished mDNSOpenEndpoint asynchronously calls mDNSinitComplete() and then mDNS_RegisterInterface()
680 CallmDNSNotifierUPP
= NewOTNotifyUPP(CallmDNSNotifier
);
681 err
= mDNSOpenEndpoint(m
);
684 LogMsg("mDNSOpenEndpoint failed %d", err
);
685 if (m
->p
->OTTimerTask
) OTDestroyTimerTask(m
->p
->OTTimerTask
);
686 OTUnregisterAsClient();
687 CloseOpenTransport();
692 extern void mDNSPlatformClose (mDNS
*const m
)
694 if (m
->p
->mOTstate
== mOT_Ready
)
696 m
->p
->mOTstate
= mOT_Closed
;
697 mDNS_DeregisterInterface(m
, &m
->p
->interface
, mDNSfalse
);
699 if (m
->p
->ep
) { OTCloseProvider (m
->p
->ep
); m
->p
->ep
= NULL
; }
700 if (m
->p
->OTTimerTask
) { OTDestroyTimerTask(m
->p
->OTTimerTask
); m
->p
->OTTimerTask
= 0; }
702 OTUnregisterAsClient();
703 CloseOpenTransport();
706 #if MDNS_ONLYSYSTEMTASK
707 extern void mDNSPlatformIdle(mDNS
*const m
);
708 mDNSexport
void mDNSPlatformIdle(mDNS
*const m
)
710 while (ONLYSYSTEMTASKcontextPtr
)
712 void *contextPtr
= ONLYSYSTEMTASKcontextPtr
;
713 ONLYSYSTEMTASKcontextPtr
= NULL
;
714 mDNSNotifier(contextPtr
, ONLYSYSTEMTASKcode
, ONLYSYSTEMTASKresult
, ONLYSYSTEMTASKcookie
);
716 if (ONLYSYSTEMTASKevent
)
718 ONLYSYSTEMTASKevent
= false;
722 if (m
->p
->mOTstate
== mOT_Reset
)
725 printf("******************************************************************************\n");
727 printf("Reopening endpoint\n");
729 m
->ResourceRecords
= NULL
;
735 case 0: if ((long)TickCount() - sleep
>= 0) { mDNSCoreMachineSleep(m
, 1); mode
++; }
737 case 1: if ((long)TickCount() - wake
>= 0) { mDNSCoreMachineSleep(m
, 0); mode
++; }
744 mDNSexport
void mDNSPlatformLock(const mDNS
*const m
)
746 if (!m
) { DebugStr("\pmDNSPlatformLock m NULL!"); return; }
747 if (!m
->p
) { DebugStr("\pmDNSPlatformLock m->p NULL!"); return; }
749 // If we try to call OTEnterNotifier and fail because we're already running at
750 // Notifier context, then make sure we don't do the matching OTLeaveNotifier() on exit.
751 // If we haven't even opened our endpoint yet, then just increment m->p->nesting for the same reason
752 if (m
->p
->mOTstate
== mOT_Ready
&& !m
->p
->ep
) DebugStr("\pmDNSPlatformLock: m->p->mOTstate == mOT_Ready && !m->p->ep");
753 if (!m
->p
->ep
|| m
->p
->nesting
|| OTEnterNotifier(m
->p
->ep
) == false) m
->p
->nesting
++;
756 mDNSlocal
void ScheduleNextTimerCallback(const mDNS
*const m
)
758 if (m
->mDNSPlatformStatus
== mStatus_NoError
)
760 SInt32 interval
= m
->NextScheduledEvent
- mDNS_TimeNow_NoLock(m
);
761 if (interval
< 1) interval
= 1;
762 else if (interval
> 0x70000000 / 1000) interval
= 0x70000000 / mDNSPlatformOneSecond
;
763 else interval
= (interval
* 1000 + mDNSPlatformOneSecond
-1)/ mDNSPlatformOneSecond
;
764 OTScheduleTimerTask(m
->p
->OTTimerTask
, (OTTimeout
)interval
);
768 mDNSexport
void mDNSPlatformUnlock(const mDNS
*const m
)
770 if (!m
) { DebugStr("\pmDNSPlatformUnlock m NULL!"); return; }
771 if (!m
->p
) { DebugStr("\pmDNSPlatformUnlock m->p NULL!"); return; }
773 if (m
->p
->ep
&& m
->mDNS_busy
== 0) ScheduleNextTimerCallback(m
);
775 if (m
->p
->nesting
) m
->p
->nesting
--;
776 else OTLeaveNotifier(m
->p
->ep
);
779 mDNSexport
void mDNSPlatformStrCopy( void *dst
, const void *src
) { OTStrCopy((char*)dst
, (char*)src
); }
780 mDNSexport UInt32
mDNSPlatformStrLen ( const void *src
) { return(OTStrLength((char*)src
)); }
781 mDNSexport
void mDNSPlatformMemCopy( void *dst
, const void *src
, UInt32 len
) { OTMemcpy(dst
, src
, len
); }
782 mDNSexport mDNSBool
mDNSPlatformMemSame(const void *dst
, const void *src
, UInt32 len
) { return(OTMemcmp(dst
, src
, len
)); }
783 mDNSexport
void mDNSPlatformMemZero( void *dst
, UInt32 len
) { OTMemzero(dst
, len
); }
784 mDNSexport
void * mDNSPlatformMemAllocate(mDNSu32 len
) { return(OTAllocMem(len
)); }
785 mDNSexport
void mDNSPlatformMemFree(void *mem
) { OTFreeMem(mem
); }
786 mDNSexport mDNSu32
mDNSPlatformRandomSeed(void) { return(TickCount()); }
787 mDNSexport mStatus
mDNSPlatformTimeInit(void) { return(mStatus_NoError
); }
788 mDNSexport SInt32
mDNSPlatformRawTime() { return((SInt32
)TickCount()); }
789 mDNSexport SInt32 mDNSPlatformOneSecond
= 60;
791 mDNSexport mDNSs32
mDNSPlatformUTC(void)
793 // Classic Mac OS since Midnight, 1st Jan 1904
794 // Standard Unix counts from 1970
795 // This value adjusts for the 66 years and 17 leap-days difference
796 mDNSu32 SecsSince1904
;
797 MachineLocation ThisLocation
;
798 #define TIME_ADJUST (((1970 - 1904) * 365 + 17) * 24 * 60 * 60)
799 #define ThisLocationGMTdelta ((ThisLocation.u.gmtDelta << 8) >> 8)
800 GetDateTime(&SecsSince1904
);
801 ReadLocation(&ThisLocation
);
802 return((mDNSs32
)(SecsSince1904
- ThisLocationGMTdelta
- TIME_ADJUST
));