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.19 2003/08/18 23:09:20 cheshire
27 <rdar://problem/3382647> mDNSResponder divide by zero in mDNSPlatformTimeNow()
29 Revision 1.18 2003/08/12 19:56:24 cheshire
34 #include <LowMem.h> // For LMGetCurApName()
35 #include <TextUtils.h> // For smSystemScript
36 #include <UnicodeConverter.h> // For ConvertFromPStringToUnicode()
39 #include <stdarg.h> // For va_list support
41 #include "mDNSClientAPI.h" // Defines the interface provided to the client layer above
42 #include "mDNSPlatformFunctions.h" // Defines the interface to the supporting layer below
44 #include "mDNSMacOS9.h" // Defines the specific types needed to run mDNS on this platform
46 // ***************************************************************************
49 static const TSetBooleanOption kReusePortOption
=
50 { sizeof(TSetBooleanOption
), INET_IP
, IP_REUSEPORT
, 0, true };
52 // IP_RCVDSTADDR gives error #-3151 (kOTBadOptionErr)
53 static const TSetBooleanOption kRcvDestAddrOption
=
54 { sizeof(TSetBooleanOption
), INET_IP
, IP_REUSEPORT
, 0, true };
56 static const TIPAddMulticastOption kAddLinkMulticastOption
=
57 { sizeof(TIPAddMulticastOption
), INET_IP
, IP_ADD_MEMBERSHIP
, 0, { 224, 0, 0,251 }, { 0,0,0,0 } };
59 static const TIPAddMulticastOption kAddAdminMulticastOption
=
60 { sizeof(TIPAddMulticastOption
), INET_IP
, IP_ADD_MEMBERSHIP
, 0, { 239,255,255,251 }, { 0,0,0,0 } };
62 // Bind endpoint to port number. Don't specify any specific IP address --
63 // we want to receive unicasts on all interfaces, as well as multicasts.
64 typedef struct { OTAddressType fAddressType
; mDNSIPPort fPort
; mDNSv4Addr fHost
; UInt8 fUnused
[8]; } mDNSInetAddress
;
65 //static const mDNSInetAddress mDNSPortInetAddress = { AF_INET, { 0,0 }, { 0,0,0,0 } }; // For testing legacy client support
66 #define MulticastDNSPortAsNumber 5353
67 static const mDNSInetAddress mDNSPortInetAddress
= { AF_INET
, { MulticastDNSPortAsNumber
>> 8, MulticastDNSPortAsNumber
& 0xFF }, { 0,0,0,0 } };
68 static const TBind mDNSbindReq
= { sizeof(mDNSPortInetAddress
), sizeof(mDNSPortInetAddress
), (UInt8
*)&mDNSPortInetAddress
, 0 };
70 static const TNetbuf zeroTNetbuf
= { 0 };
72 // ***************************************************************************
76 mDNSexport
void debugf_(const char *format
, ...)
78 unsigned char buffer
[256];
81 buffer
[0] = (unsigned char)mDNS_vsnprintf((char*)buffer
+1, 255, format
, ptr
);
83 #if __ONLYSYSTEMTASK__
84 buffer
[1+buffer
[0]] = 0;
85 fprintf(stderr
, "%s\n", buffer
+1);
93 mDNSexport
void LogMsg(const char *format
, ...)
95 unsigned char buffer
[256];
98 buffer
[0] = (unsigned char)mDNS_vsnprintf((char*)buffer
+1, 255, format
, ptr
);
100 #if __ONLYSYSTEMTASK__
101 buffer
[1+buffer
[0]] = 0;
102 fprintf(stderr
, "%s\n", buffer
+1);
109 mDNSexport mStatus
mDNSPlatformSendUDP(const mDNS
*const m
, const DNSMessage
*const msg
, const mDNSu8
*const end
,
110 mDNSInterfaceID InterfaceID
, mDNSIPPort srcPort
, const mDNSAddr
*dst
, mDNSIPPort dstPort
)
112 // Note: If we did multi-homing, we'd have to use the InterfaceID parameter to specify from which interface to send this response
113 #pragma unused(InterfaceID, srcPort)
115 InetAddress InetDest
;
118 InetDest
.fAddressType
= AF_INET
;
119 InetDest
.fPort
= dstPort
.NotAnInteger
;
120 InetDest
.fHost
= dst
->ip
.v4
.NotAnInteger
;
122 senddata
.addr
.maxlen
= sizeof(InetDest
);
123 senddata
.addr
.len
= sizeof(InetDest
);
124 senddata
.addr
.buf
= (UInt8
*)&InetDest
;
125 senddata
.opt
= zeroTNetbuf
;
126 senddata
.udata
.maxlen
= (UInt32
)((UInt8
*)end
- (UInt8
*)msg
);
127 senddata
.udata
.len
= (UInt32
)((UInt8
*)end
- (UInt8
*)msg
);
128 senddata
.udata
.buf
= (UInt8
*)msg
;
130 return(OTSndUData(m
->p
->ep
, &senddata
));
133 mDNSlocal OSStatus
readpacket(mDNS
*m
)
135 mDNSAddr senderaddr
, destaddr
;
136 mDNSInterfaceID interface
;
137 mDNSIPPort senderport
;
145 recvdata
.addr
.maxlen
= sizeof(sender
);
146 recvdata
.addr
.len
= 0;
147 recvdata
.addr
.buf
= (UInt8
*)&sender
;
148 recvdata
.opt
.maxlen
= sizeof(options
);
149 recvdata
.opt
.len
= 0;
150 recvdata
.opt
.buf
= (UInt8
*)&options
;
151 recvdata
.udata
.maxlen
= sizeof(packet
);
152 recvdata
.udata
.len
= 0;
153 recvdata
.udata
.buf
= (UInt8
*)&packet
;
155 err
= OTRcvUData(m
->p
->ep
, &recvdata
, &flags
);
156 if (err
&& err
!= kOTNoDataErr
) debugf("OTRcvUData error %d", err
);
158 if (err
) return(err
);
160 senderaddr
.type
= mDNSAddrType_IPv4
;
161 senderaddr
.ip
.v4
.NotAnInteger
= sender
.fHost
;
162 senderport
.NotAnInteger
= sender
.fPort
;
163 destaddr
.type
= mDNSAddrType_IPv4
;
164 destaddr
.ip
.v4
= AllDNSLinkGroup
; // For now, until I work out how to get the dest address, assume it was sent to AllDNSLinkGroup
165 interface
= m
->HostInterfaces
->InterfaceID
;
167 if (recvdata
.opt
.len
) debugf("readpacket: got some option data at %X, len %d", options
, recvdata
.opt
.len
);
169 if (flags
& T_MORE
) debugf("ERROR: OTRcvUData() buffer too small (T_MORE set)");
170 else if (recvdata
.addr
.len
< sizeof(InetAddress
)) debugf("ERROR: recvdata.addr.len (%d) too short", recvdata
.addr
.len
);
171 else if (recvdata
.udata
.len
< sizeof(DNSMessageHeader
)) debugf("ERROR: recvdata.udata.len (%d) too short", recvdata
.udata
.len
);
172 else mDNSCoreReceive(m
, &packet
, recvdata
.udata
.buf
+ recvdata
.udata
.len
, &senderaddr
, senderport
, &destaddr
, MulticastDNSPort
, interface
, 255);
178 mDNSlocal
void mDNSOptionManagement(mDNS
*const m
)
182 // Make sure the length in the TNetbuf agrees with the length in the TOptionHeader
183 m
->p
->optReq
.opt
.len
= m
->p
->optBlock
.h
.len
;
184 err
= OTOptionManagement(m
->p
->ep
, &m
->p
->optReq
, NULL
);
185 if (err
) debugf("OTOptionManagement failed %d", err
);
188 mDNSlocal
void mDNSinitComplete(mDNS
*const m
, mStatus result
)
190 m
->mDNSPlatformStatus
= result
;
191 mDNSCoreInitComplete(m
, mStatus_NoError
);
194 mDNSlocal
pascal void mDNSNotifier(void *contextPtr
, OTEventCode code
, OTResult result
, void *cookie
)
196 mDNS
*const m
= (mDNS
*const)contextPtr
;
197 if (!m
) debugf("mDNSNotifier FATAL ERROR! No context");
203 InetInterfaceInfo interfaceinfo
;
204 if (result
) { debugf("T_OPENCOMPLETE failed %d", result
); mDNSinitComplete(m
, result
); return; }
205 //debugf("T_OPENCOMPLETE");
206 m
->p
->ep
= (EndpointRef
)cookie
;
207 //debugf("OTInetGetInterfaceInfo");
208 // (In future may want to loop over all interfaces instead of just using kDefaultInetInterface)
209 err
= OTInetGetInterfaceInfo(&interfaceinfo
, kDefaultInetInterface
);
210 if (err
) { debugf("OTInetGetInterfaceInfo failed %d", err
); mDNSinitComplete(m
, err
); return; }
212 // Make our basic standard host resource records (address, PTR, etc.)
213 m
->p
->interface
.ip
.type
= mDNSAddrType_IPv4
;
214 m
->p
->interface
.ip
.ip
.v4
.NotAnInteger
= interfaceinfo
.fAddress
;
215 m
->p
->interface
.Advertise
= m
->AdvertiseLocalAddresses
;
216 m
->p
->interface
.InterfaceID
= (mDNSInterfaceID
)&m
->p
->interface
;
217 mDNS_RegisterInterface(m
, &m
->p
->interface
);
220 case T_OPTMGMTCOMPLETE
:
221 if (result
) { debugf("T_OPTMGMTCOMPLETE failed %d", result
); mDNSinitComplete(m
, result
); return; }
222 //debugf("T_OPTMGMTCOMPLETE");
223 switch (++m
->p
->mOTstate
)
225 case mOT_ReusePort
: m
->p
->optBlock
.b
= kReusePortOption
; mDNSOptionManagement(m
); break;
226 case mOT_RcvDestAddr
: m
->p
->optBlock
.b
= kRcvDestAddrOption
; mDNSOptionManagement(m
); break;
227 case mOT_LLScope
: m
->p
->optBlock
.m
= kAddLinkMulticastOption
; mDNSOptionManagement(m
); break;
228 case mOT_AdminScope
: m
->p
->optBlock
.m
= kAddAdminMulticastOption
; mDNSOptionManagement(m
); break;
229 case mOT_Bind
: OTBind(m
->p
->ep
, (TBind
*)&mDNSbindReq
, NULL
); break;
234 if (result
) { debugf("T_BINDCOMPLETE failed %d", result
); return; }
235 if (m
->p
->mOTstate
!= mOT_Bind
) { debugf("T_BINDCOMPLETE in wrong mDNS state %d", m
->p
->mOTstate
); return; }
237 //debugf("T_BINDCOMPLETE");
238 mDNSinitComplete(m
, mStatus_NoError
);
243 while (readpacket(m
) == kOTNoError
) continue; // Read packets until we run out
246 case kOTProviderWillClose
:
247 case kOTProviderIsClosed
: // Machine is going to sleep, shutting down, or reconfiguring IP
248 if (m
->p
->ep
) { OTCloseProvider(m
->p
->ep
); m
->p
->ep
= NULL
; }
249 break; // Do we need to do anything?
251 default: debugf("mDNSNotifier: Unexpected OTEventCode %X", code
);
256 #if __ONLYSYSTEMTASK__
258 static Boolean ONLYSYSTEMTASKevent
;
259 static void *ONLYSYSTEMTASKcontextPtr
;
260 static OTEventCode ONLYSYSTEMTASKcode
;
261 static OTResult ONLYSYSTEMTASKresult
;
262 static void *ONLYSYSTEMTASKcookie
;
264 mDNSlocal
pascal void CallmDNSNotifier(void *contextPtr
, OTEventCode code
, OTResult result
, void *cookie
)
266 ONLYSYSTEMTASKcontextPtr
= contextPtr
;
267 ONLYSYSTEMTASKcode
= code
;
268 ONLYSYSTEMTASKresult
= result
;
269 ONLYSYSTEMTASKcookie
= cookie
;
274 mDNSlocal
pascal void CallmDNSNotifier(void *contextPtr
, OTEventCode code
, OTResult result
, void *cookie
)
276 mDNS
*const m
= (mDNS
*const)contextPtr
;
277 if (!m
) debugf("mDNSNotifier FATAL ERROR! No context");
279 // Increment m->p->nesting to indicate to mDNSPlatformLock that there's no need
280 // to call OTEnterNotifier() (because we're already in OTNotifier context)
281 if (m
->p
->nesting
) DebugStr("\pCallmDNSNotifier ERROR! OTEnterNotifier is supposed to suppress notifier callbacks");
283 mDNSNotifier(contextPtr
, code
, result
, cookie
);
285 ScheduleNextTimerCallback(m
);
290 mDNSlocal OSStatus
mDNSOpenEndpoint(const mDNS
*const m
)
293 TEndpointInfo endpointinfo
;
294 // m->optReq is pre-set to point to the shared m->optBlock
295 // m->optBlock is filled in by each OTOptionManagement call
296 m
->p
->optReq
.opt
.maxlen
= sizeof(m
->p
->optBlock
);
297 m
->p
->optReq
.opt
.len
= sizeof(m
->p
->optBlock
);
298 m
->p
->optReq
.opt
.buf
= (UInt8
*)&m
->p
->optBlock
;
299 m
->p
->optReq
.flags
= T_NEGOTIATE
;
301 // Open an endpoint and start answering queries
302 //printf("Opening endpoint now...\n");
304 m
->p
->mOTstate
= mOT_Start
;
305 // err = OTAsyncOpenEndpoint(OTCreateConfiguration("udp(RxICMP=1)"), 0, &endpointinfo, CallmDNSNotifier, (void*)m); // works
306 // err = OTAsyncOpenEndpoint(OTCreateConfiguration("udp(RxICMP)"), 0, &endpointinfo, CallmDNSNotifier, (void*)m); // -3151 bad option
307 // err = OTAsyncOpenEndpoint(OTCreateConfiguration("udp,ip(RxICMP=1)"), 0, &endpointinfo, CallmDNSNotifier, (void*)m); // -3151
308 // err = OTAsyncOpenEndpoint(OTCreateConfiguration("udp,ip"), 0, &endpointinfo, CallmDNSNotifier, (void*)m); // works
309 // err = OTAsyncOpenEndpoint(OTCreateConfiguration("udp,rawip"), 0, &endpointinfo, CallmDNSNotifier, (void*)m); // -3221 invalid arg
310 err
= OTAsyncOpenEndpoint(OTCreateConfiguration(kUDPName
), 0, &endpointinfo
, NewOTNotifyUPP(CallmDNSNotifier
), (void*)m
);
311 if (err
) { debugf("ERROR: OTAsyncOpenEndpoint(UDP) failed with error <%d>", err
); return(err
); }
316 // Define these here because they're not in older versions of OpenTransport.h
319 xOTStackIsLoading
= 0x27000001, /* Sent before Open Transport attempts to load the TCP/IP protocol stack.*/
320 xOTStackWasLoaded
= 0x27000002, /* Sent after the TCP/IP stack has been successfully loaded.*/
321 xOTStackIsUnloading
= 0x27000003 /* Sent before Open Transport unloads the TCP/IP stack.*/
324 static mDNS
*ClientNotifierContext
;
326 mDNSlocal
pascal void ClientNotifier(void *contextPtr
, OTEventCode code
, OTResult result
, void *cookie
)
328 mDNS
*const m
= ClientNotifierContext
;
330 #pragma unused(contextPtr) // Usually zero (except one in the 'xOTStackIsLoading' case)
331 #pragma unused(cookie) // Usually 'ipv4' (except for kOTPortNetworkChange)
332 #pragma unused(result) // Usually zero
336 case xOTStackIsLoading
: break;
337 case xOTStackWasLoaded
: m
->mDNSPlatformStatus
= mStatus_Waiting
; m
->p
->mOTstate
= mOT_Reset
; break;
338 case xOTStackIsUnloading
: break;
339 case kOTPortNetworkChange
: break;
340 default: debugf("ClientNotifier unknown code %X, %X, %d", contextPtr
, code
, result
); break;
344 #if TARGET_API_MAC_CARBON
346 mDNSlocal
void GetUserSpecifiedComputerName(domainlabel
*const namelabel
)
348 CFStringRef cfs
= CSCopyMachineName();
349 CFStringGetPascalString(cfs
, namelabel
->c
, sizeof(*namelabel
), kCFStringEncodingUTF8
);
355 mDNSlocal OSStatus
ConvertStringHandleToUTF8(const StringHandle machineName
, UInt8
*const utf8
, ByteCount maxlen
)
358 TextEncoding utf8TextEncoding
, SystemTextEncoding
;
359 UnicodeMapping theMapping
;
360 TextToUnicodeInfo textToUnicodeInfo
;
361 ByteCount unicodelen
= 0;
363 if (maxlen
> 255) maxlen
= 255; // Can't put more than 255 in a Pascal String
365 utf8TextEncoding
= CreateTextEncoding(kTextEncodingUnicodeDefault
, kTextEncodingDefaultVariant
, kUnicodeUTF8Format
);
366 UpgradeScriptInfoToTextEncoding(smSystemScript
, kTextLanguageDontCare
, kTextRegionDontCare
, NULL
, &SystemTextEncoding
);
367 theMapping
.unicodeEncoding
= utf8TextEncoding
;
368 theMapping
.otherEncoding
= SystemTextEncoding
;
369 theMapping
.mappingVersion
= kUnicodeUseLatestMapping
;
370 status
= CreateTextToUnicodeInfo(&theMapping
, &textToUnicodeInfo
);
373 status
= ConvertFromPStringToUnicode(textToUnicodeInfo
, *machineName
, maxlen
, &unicodelen
, (UniCharArrayPtr
)&(utf8
[1]));
374 DisposeTextToUnicodeInfo(&textToUnicodeInfo
);
376 utf8
[0] = (UInt8
)unicodelen
;
380 mDNSlocal
void GetUserSpecifiedComputerName(domainlabel
*const namelabel
)
382 StringHandle machineName
= GetString(-16413); // Get machine name set in file sharing
385 char machineNameState
= HGetState((Handle
)machineName
);
386 HLock((Handle
)machineName
);
387 ConvertStringHandleToUTF8(machineName
, namelabel
->c
, MAX_DOMAIN_LABEL
);
388 HSetState((Handle
)machineName
, machineNameState
);
394 static pascal void mDNSTimerTask(void *arg
)
396 #if __ONLYSYSTEMTASK__
398 ONLYSYSTEMTASKevent
= true;
400 mDNS
*const m
= (mDNS
*const)arg
;
401 // Increment m->p->nesting to indicate to mDNSPlatformLock that there's no need
402 // to call OTEnterNotifier() (because we're already in OTNotifier context)
403 if (m
->p
->nesting
) DebugStr("\pmDNSTimerTask ERROR! OTEnterNotifier is supposed to suppress timer callbacks too");
407 ScheduleNextTimerCallback(m
);
412 long sleep
, wake
, mode
;
415 mDNSexport mStatus
mDNSPlatformInit(mDNS
*const m
)
419 // Set up the nice label
420 m
->nicelabel
.c
[0] = 0;
421 GetUserSpecifiedComputerName(&m
->nicelabel
);
422 // m->nicelabel = *(domainlabel*)"\pStu"; // For conflict testing
423 if (m
->nicelabel
.c
[0] == 0) MakeDomainLabelFromLiteralString(&m
->nicelabel
, "Macintosh");
425 // Set up the RFC 1034-compliant label
426 m
->hostlabel
.c
[0] = 0;
427 ConvertUTF8PstringToRFC1034HostLabel(m
->nicelabel
.c
, &m
->hostlabel
);
428 if (m
->hostlabel
.c
[0] == 0) MakeDomainLabelFromLiteralString(&m
->hostlabel
, "Macintosh");
430 mDNS_GenerateFQDN(m
);
432 ClientNotifierContext
= m
;
434 #if !TARGET_API_MAC_CARBON
435 err
= OTRegisterAsClient(LMGetCurApName(), NewOTNotifyUPP(ClientNotifier
));
436 if (err
) debugf("OTRegisterAsClient failed %d", err
);
439 err
= mDNSOpenEndpoint(m
);
440 if (err
) { debugf("mDNSOpenEndpoint failed %d", err
); return(err
); }
442 m
->p
->OTTimerTask
= OTCreateTimerTask(NewOTProcessUPP(mDNSTimerTask
), m
);
446 sleep
= TickCount() + 600;
447 wake
= TickCount() + 1200;
454 extern void mDNSPlatformClose (mDNS
*const m
)
456 if (m
->p
->OTTimerTask
) { OTDestroyTimerTask(m
->p
->OTTimerTask
); m
->p
->OTTimerTask
= 0; }
457 if (m
->p
->ep
) { OTCloseProvider (m
->p
->ep
); m
->p
->ep
= NULL
; }
458 CloseOpenTransport();
461 extern void mDNSPlatformIdle(mDNS
*const m
);
462 mDNSexport
void mDNSPlatformIdle(mDNS
*const m
)
464 #if __ONLYSYSTEMTASK__
465 while (ONLYSYSTEMTASKcontextPtr
)
467 void *contextPtr
= ONLYSYSTEMTASKcontextPtr
;
468 ONLYSYSTEMTASKcontextPtr
= NULL
;
469 mDNSNotifier(contextPtr
, ONLYSYSTEMTASKcode
, ONLYSYSTEMTASKresult
, ONLYSYSTEMTASKcookie
);
471 if (ONLYSYSTEMTASKevent
)
473 ONLYSYSTEMTASKevent
= false;
478 if (m
->p
->mOTstate
== mOT_Reset
)
481 printf("******************************************************************************\n");
483 printf("Reopening endpoint\n");
485 m
->ResourceRecords
= NULL
;
491 case 0: if ((long)TickCount() - sleep
>= 0) { mDNSCoreMachineSleep(m
, 1); mode
++; }
493 case 1: if ((long)TickCount() - wake
>= 0) { mDNSCoreMachineSleep(m
, 0); mode
++; }
500 mDNSexport
void mDNSPlatformLock(const mDNS
*const m
)
502 if (!m
) { DebugStr("\pmDNSPlatformLock m NULL!"); return; }
503 if (!m
->p
) { DebugStr("\pmDNSPlatformLock m->p NULL!"); return; }
504 if (!m
->p
->ep
) { DebugStr("\pmDNSPlatformLock m->p->ep NULL!"); return; }
506 // If we try to call OTEnterNotifier and fail because we're already running at
507 // Notifier context, then make sure we don't do the matching OTLeaveNotifier() on exit.
508 if (m
->p
->nesting
|| OTEnterNotifier(m
->p
->ep
) == false) m
->p
->nesting
++;
511 mDNSlocal
void ScheduleNextTimerCallback(const mDNS
*const m
)
514 interval
= m
->NextScheduledEvent
- mDNSPlatformTimeNow();
515 if (interval
< 0) interval
= 0;
516 else if (interval
> 0x7FFFFFFF / 1000) interval
= 0x7FFFFFFF / mDNSPlatformOneSecond
;
517 else interval
= interval
* 1000 / mDNSPlatformOneSecond
;
518 //debugf("mDNSPlatformScheduleTask Interval %d", interval);
519 OTScheduleTimerTask(m
->p
->OTTimerTask
, (OTTimeout
)interval
);
522 mDNSexport
void mDNSPlatformUnlock(const mDNS
*const m
)
524 if (!m
) { DebugStr("\pmDNSPlatformUnlock m NULL!"); return; }
525 if (!m
->p
) { DebugStr("\pmDNSPlatformUnlock m->p NULL!"); return; }
526 if (!m
->p
->ep
) { DebugStr("\pmDNSPlatformUnlock m->p->ep NULL!"); return; }
527 if (m
->p
->nesting
) m
->p
->nesting
--;
530 ScheduleNextTimerCallback(m
);
531 OTLeaveNotifier(m
->p
->ep
);
535 mDNSexport
void mDNSPlatformStrCopy(const void *src
, void *dst
) { OTStrCopy((char*)dst
, (char*)src
); }
536 mDNSexport UInt32
mDNSPlatformStrLen (const void *src
) { return(OTStrLength((char*)src
)); }
537 mDNSexport
void mDNSPlatformMemCopy(const void *src
, void *dst
, UInt32 len
) { OTMemcpy(dst
, src
, len
); }
538 mDNSexport mDNSBool
mDNSPlatformMemSame(const void *src
, const void *dst
, UInt32 len
) { return(OTMemcmp(dst
, src
, len
)); }
539 mDNSexport
void mDNSPlatformMemZero( void *dst
, UInt32 len
) { OTMemzero(dst
, len
); }
540 mDNSexport
void * mDNSPlatformMemAllocate(mDNSu32 len
) { return(OTAllocMem(len
)); }
541 mDNSexport
void mDNSPlatformMemFree (void *mem
) { OTFreeMem(mem
); }
542 mDNSexport mStatus
mDNSPlatformTimeInit(mDNSs32
*timenow
) { *timenow
= mDNSPlatformTimeNow(); return(mStatus_NoError
); }
543 mDNSexport SInt32
mDNSPlatformTimeNow() { return((SInt32
)TickCount()); }
544 mDNSexport SInt32 mDNSPlatformOneSecond
= 60;