2 * Copyright (c) 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 * This file defines a simple shim layer between a client calling the "/usr/include/dns_sd.h" APIs
24 * and an implementation of mDNSCore ("mDNSEmbeddedAPI.h" APIs) in the same address space.
25 * When the client calls a dns_sd.h function, the shim calls the corresponding mDNSEmbeddedAPI.h
26 * function, and when mDNSCore calls the shim's callback, we call through to the client's callback.
27 * The shim is responsible for two main things:
28 * - converting string parameters between C string format and native DNS format,
29 * - and for allocating and freeing memory.
31 Change History (most recent first):
33 $Log: dnssd_clientshim.c,v $
34 Revision 1.8 2004/12/16 20:47:34 cheshire
35 <rdar://problem/3324626> Cache memory management improvements
37 Revision 1.7 2004/12/10 04:08:43 cheshire
38 Added comments about autoname and autorename
40 Revision 1.6 2004/10/19 21:33:22 cheshire
41 <rdar://problem/3844991> Cannot resolve non-local registrations using the mach API
42 Added flag 'kDNSServiceFlagsForceMulticast'. Passing through an interface id for a unicast name
43 doesn't force multicast unless you set this flag to indicate explicitly that this is what you want
45 Revision 1.5 2004/09/21 23:29:51 cheshire
46 <rdar://problem/3680045> DNSServiceResolve should delay sending packets
48 Revision 1.4 2004/09/17 01:08:55 cheshire
49 Renamed mDNSClientAPI.h to mDNSEmbeddedAPI.h
50 The name "mDNSClientAPI.h" is misleading to new developers looking at this code. The interfaces
51 declared in that file are ONLY appropriate to single-address-space embedded applications.
52 For clients on general-purpose computers, the interfaces defined in dns_sd.h should be used.
54 Revision 1.3 2004/05/27 06:26:31 cheshire
55 Add shim for DNSServiceQueryRecord()
57 Revision 1.2 2004/05/20 18:41:24 cheshire
58 Fix build broken by removal of 'kDNSServiceFlagsRemove' from dns_sd.h
60 Revision 1.1 2004/03/12 21:30:29 cheshire
61 Build a System-Context Shared Library from mDNSCore, for the benefit of developers
62 like Muse Research who want to be able to use mDNS/DNS-SD from GPL-licensed code.
66 #include "dns_sd.h" // Defines the interface to the client layer above
67 #include "mDNSEmbeddedAPI.h" // The interface we're building on top of
68 extern mDNS mDNSStorage
; // We need to pass the address of this storage to the lower-layer functions
70 #if MDNS_BUILDINGSHAREDLIBRARY || MDNS_BUILDINGSTUBLIBRARY
74 //*************************************************************************************************************
75 // General Utility Functions
77 // All mDNS_DirectOP structures start with the pointer to the type-specific disposal function.
78 // Optional type-specific data follows these three fields
79 // When the client starts an operation, we return the address of the corresponding mDNS_DirectOP
80 // as the DNSServiceRef for the operation
81 // We stash the value in core context fields so we can get it back to recover our state in our callbacks,
82 // and pass it though to the client for it to recover its state
84 typedef struct mDNS_DirectOP_struct mDNS_DirectOP
;
85 typedef void mDNS_DirectOP_Dispose(mDNS_DirectOP
*op
);
86 struct mDNS_DirectOP_struct
88 mDNS_DirectOP_Dispose
*disposefn
;
93 mDNS_DirectOP_Dispose
*disposefn
;
94 DNSServiceRegisterReply callback
;
96 mDNSBool autoname
; // Set if this name is tied to the Computer Name
97 mDNSBool autorename
; // Set if we just got a name conflict and now need to automatically pick a new name
100 } mDNS_DirectOP_Register
;
104 mDNS_DirectOP_Dispose
*disposefn
;
105 DNSServiceBrowseReply callback
;
108 } mDNS_DirectOP_Browse
;
112 mDNS_DirectOP_Dispose
*disposefn
;
113 DNSServiceResolveReply callback
;
115 const ResourceRecord
*SRV
;
116 const ResourceRecord
*TXT
;
119 } mDNS_DirectOP_Resolve
;
123 mDNS_DirectOP_Dispose
*disposefn
;
124 DNSServiceQueryRecordReply callback
;
127 } mDNS_DirectOP_QueryRecord
;
129 int DNSServiceRefSockFD(DNSServiceRef sdRef
)
131 (void)sdRef
; // Unused
135 DNSServiceErrorType
DNSServiceProcessResult(DNSServiceRef sdRef
)
137 (void)sdRef
; // Unused
138 return(kDNSServiceErr_NoError
);
141 void DNSServiceRefDeallocate(DNSServiceRef sdRef
)
143 mDNS_DirectOP
*op
= (mDNS_DirectOP
*)sdRef
;
144 //LogMsg("DNSServiceRefDeallocate");
148 //*************************************************************************************************************
149 // Domain Enumeration
151 // Not yet implemented, so don't include in stub library
152 // We DO include it in the actual Extension, so that if a later client compiled to use this
153 // is run against this Extension, it will get a reasonable error code instead of just
154 // failing to launch (Strong Link) or calling an unresolved symbol and crashing (Weak Link)
155 #if !MDNS_BUILDINGSTUBLIBRARY
156 DNSServiceErrorType DNSServiceEnumerateDomains
158 DNSServiceRef
*sdRef
,
159 DNSServiceFlags flags
,
160 uint32_t interfaceIndex
,
161 DNSServiceDomainEnumReply callback
,
162 void *context
/* may be NULL */
165 (void)sdRef
; // Unused
166 (void)flags
; // Unused
167 (void)interfaceIndex
; // Unused
168 (void)callback
; // Unused
169 (void)context
; // Unused
170 return(kDNSServiceErr_Unsupported
);
174 //*************************************************************************************************************
177 mDNSlocal
void FreeDNSServiceRegistration(mDNS_DirectOP_Register
*x
)
181 ExtraResourceRecord
*extras
= x
->s
.Extras
;
182 x
->s
.Extras
= x
->s
.Extras
->next
;
183 if (extras
->r
.resrec
.rdata
!= &extras
->r
.rdatastorage
)
184 mDNSPlatformMemFree(extras
->r
.resrec
.rdata
);
185 mDNSPlatformMemFree(extras
);
188 if (x
->s
.RR_TXT
.resrec
.rdata
!= &x
->s
.RR_TXT
.rdatastorage
)
189 mDNSPlatformMemFree(x
->s
.RR_TXT
.resrec
.rdata
);
191 if (x
->s
.SubTypes
) mDNSPlatformMemFree(x
->s
.SubTypes
);
193 mDNSPlatformMemFree(x
);
196 static void DNSServiceRegisterDispose(mDNS_DirectOP
*op
)
198 mDNS_DirectOP_Register
*x
= (mDNS_DirectOP_Register
*)op
;
199 x
->autorename
= mDNSfalse
;
200 // If mDNS_DeregisterService() returns mStatus_NoError, that means that the service was found in the list,
201 // is sending its goodbye packet, and we'll get an mStatus_MemFree message when we can free the memory.
202 // If mDNS_DeregisterService() returns an error, it means that the service had already been removed from
203 // the list, so we should go ahead and free the memory right now
204 if (mDNS_DeregisterService(&mDNSStorage
, &x
->s
) != mStatus_NoError
)
205 FreeDNSServiceRegistration(x
);
208 mDNSlocal
void RegCallback(mDNS
*const m
, ServiceRecordSet
*const sr
, mStatus result
)
210 mDNS_DirectOP_Register
*x
= (mDNS_DirectOP_Register
*)sr
->ServiceContext
;
213 domainname type
, dom
;
214 char namestr
[MAX_DOMAIN_LABEL
+1]; // Unescaped name: up to 63 bytes plus C-string terminating NULL.
215 char typestr
[MAX_ESCAPED_DOMAIN_NAME
];
216 char domstr
[MAX_ESCAPED_DOMAIN_NAME
];
217 if (!DeconstructServiceName(sr
->RR_SRV
.resrec
.name
, &name
, &type
, &dom
)) return;
218 if (!ConvertDomainLabelToCString_unescaped(&name
, namestr
)) return;
219 if (!ConvertDomainNameToCString(&type
, typestr
)) return;
220 if (!ConvertDomainNameToCString(&dom
, domstr
)) return;
222 if (result
== mStatus_NoError
)
225 x
->callback((DNSServiceRef
)x
, 0, result
, namestr
, typestr
, domstr
, x
->context
);
227 else if (result
== mStatus_NameConflict
)
229 if (x
->autoname
) mDNS_RenameAndReregisterService(m
, sr
, mDNSNULL
);
230 else if (x
->callback
)
231 x
->callback((DNSServiceRef
)x
, 0, result
, namestr
, typestr
, domstr
, x
->context
);
233 else if (result
== mStatus_MemFree
)
237 x
->autorename
= mDNSfalse
;
238 x
->name
= mDNSStorage
.nicelabel
;
239 mDNS_RenameAndReregisterService(m
, &x
->s
, &x
->name
);
242 FreeDNSServiceRegistration(x
);
246 DNSServiceErrorType DNSServiceRegister
248 DNSServiceRef
*sdRef
,
249 DNSServiceFlags flags
,
250 uint32_t interfaceIndex
,
251 const char *name
, /* may be NULL */
253 const char *domain
, /* may be NULL */
254 const char *host
, /* may be NULL */
255 uint16_t notAnIntPort
,
257 const void *txtRecord
, /* may be NULL */
258 DNSServiceRegisterReply callback
, /* may be NULL */
259 void *context
/* may be NULL */
262 mStatus err
= mStatus_NoError
;
263 const char *errormsg
= "Unknown";
265 domainname t
, d
, h
, srv
;
267 unsigned int size
= sizeof(RDataBody
);
268 AuthRecord
*SubTypes
= mDNSNULL
;
269 mDNSu32 NumSubTypes
= 0;
270 mDNS_DirectOP_Register
*x
;
271 (void)flags
; // Unused
272 (void)interfaceIndex
; // Unused
275 if (!name
[0]) n
= mDNSStorage
.nicelabel
;
276 else if (!MakeDomainLabelFromLiteralString(&n
, name
)) { errormsg
= "Bad Instance Name"; goto badparam
; }
277 if (!regtype
|| !*regtype
|| !MakeDomainNameFromDNSNameString(&t
, regtype
)) { errormsg
= "Bad Service Type"; goto badparam
; }
278 if (!MakeDomainNameFromDNSNameString(&d
, (domain
&& *domain
) ? domain
: "local.")) { errormsg
= "Bad Domain"; goto badparam
; }
279 if (!MakeDomainNameFromDNSNameString(&h
, (host
&& *host
) ? host
: "")) { errormsg
= "Bad Target Host"; goto badparam
; }
280 if (!ConstructServiceName(&srv
, &n
, &t
, &d
)) { errormsg
= "Bad Name"; goto badparam
; }
281 port
.NotAnInteger
= notAnIntPort
;
283 // Allocate memory, and handle failure
286 x
= (mDNS_DirectOP_Register
*)mDNSPlatformMemAllocate(sizeof(*x
) - sizeof(RDataBody
) + size
);
287 if (!x
) { err
= mStatus_NoMemoryErr
; errormsg
= "No memory"; goto fail
; }
290 x
->disposefn
= DNSServiceRegisterDispose
;
291 x
->callback
= callback
;
292 x
->context
= context
;
293 x
->autoname
= (!name
[0]);
294 x
->autorename
= mDNSfalse
;
298 err
= mDNS_RegisterService(&mDNSStorage
, &x
->s
,
299 &x
->name
, &t
, &d
, // Name, type, domain
300 &h
, port
, // Host and port
301 txtRecord
, txtLen
, // TXT data, length
302 SubTypes
, NumSubTypes
, // Subtypes
303 mDNSInterface_Any
, // Interface ID
304 RegCallback
, x
); // Callback and context
305 if (err
) { mDNSPlatformMemFree(x
); errormsg
= "mDNS_RegisterService"; goto fail
; }
307 // Succeeded: Wrap up and return
308 *sdRef
= (DNSServiceRef
)x
;
309 return(mStatus_NoError
);
312 err
= mStatus_BadParamErr
;
314 LogMsg("DNSServiceBrowse(\"%s\", \"%s\") failed: %s (%ld)", regtype
, domain
, errormsg
, err
);
318 //*************************************************************************************************************
319 // Add / Update / Remove records from existing Registration
321 // Not yet implemented, so don't include in stub library
322 // We DO include it in the actual Extension, so that if a later client compiled to use this
323 // is run against this Extension, it will get a reasonable error code instead of just
324 // failing to launch (Strong Link) or calling an unresolved symbol and crashing (Weak Link)
325 #if !MDNS_BUILDINGSTUBLIBRARY
326 DNSServiceErrorType DNSServiceAddRecord
329 DNSRecordRef
*RecordRef
,
330 DNSServiceFlags flags
,
337 (void)sdRef
; // Unused
338 (void)RecordRef
; // Unused
339 (void)flags
; // Unused
340 (void)rrtype
; // Unused
341 (void)rdlen
; // Unused
342 (void)rdata
; // Unused
344 return(kDNSServiceErr_Unsupported
);
347 DNSServiceErrorType DNSServiceUpdateRecord
350 DNSRecordRef RecordRef
, /* may be NULL */
351 DNSServiceFlags flags
,
357 (void)sdRef
; // Unused
358 (void)RecordRef
; // Unused
359 (void)flags
; // Unused
360 (void)rdlen
; // Unused
361 (void)rdata
; // Unused
363 return(kDNSServiceErr_Unsupported
);
366 DNSServiceErrorType DNSServiceRemoveRecord
369 DNSRecordRef RecordRef
,
370 DNSServiceFlags flags
373 (void)sdRef
; // Unused
374 (void)RecordRef
; // Unused
375 (void)flags
; // Unused
376 return(kDNSServiceErr_Unsupported
);
380 //*************************************************************************************************************
381 // Browse for services
383 static void DNSServiceBrowseDispose(mDNS_DirectOP
*op
)
385 mDNS_DirectOP_Browse
*x
= (mDNS_DirectOP_Browse
*)op
;
386 //LogMsg("DNSServiceBrowseDispose");
387 mDNS_StopBrowse(&mDNSStorage
, &x
->q
);
388 mDNSPlatformMemFree(x
);
391 mDNSlocal
void FoundInstance(mDNS
*const m
, DNSQuestion
*question
, const ResourceRecord
*const answer
, mDNSBool AddRecord
)
393 DNSServiceFlags flags
= AddRecord
? kDNSServiceFlagsAdd
: (DNSServiceFlags
)0;
395 domainname type
, domain
;
396 char cname
[MAX_DOMAIN_LABEL
+1]; // Unescaped name: up to 63 bytes plus C-string terminating NULL.
397 char ctype
[MAX_ESCAPED_DOMAIN_NAME
];
398 char cdom
[MAX_ESCAPED_DOMAIN_NAME
];
399 mDNS_DirectOP_Browse
*x
= (mDNS_DirectOP_Browse
*)question
->QuestionContext
;
402 if (answer
->rrtype
!= kDNSType_PTR
)
403 { LogMsg("FoundInstance: Should not be called with rrtype %d (not a PTR record)", answer
->rrtype
); return; }
405 if (!DeconstructServiceName(&answer
->rdata
->u
.name
, &name
, &type
, &domain
))
407 LogMsg("FoundInstance: %##s PTR %##s received from network is not valid DNS-SD service pointer",
408 answer
->name
->c
, answer
->rdata
->u
.name
.c
);
412 ConvertDomainLabelToCString_unescaped(&name
, cname
);
413 ConvertDomainNameToCString(&type
, ctype
);
414 ConvertDomainNameToCString(&domain
, cdom
);
416 x
->callback((DNSServiceRef
)x
, flags
, 0, 0, cname
, ctype
, cdom
, x
->context
);
419 DNSServiceErrorType DNSServiceBrowse
421 DNSServiceRef
*sdRef
,
422 DNSServiceFlags flags
,
423 uint32_t interfaceIndex
,
425 const char *domain
, /* may be NULL */
426 DNSServiceBrowseReply callback
,
427 void *context
/* may be NULL */
430 mStatus err
= mStatus_NoError
;
431 const char *errormsg
= "Unknown";
433 mDNS_DirectOP_Browse
*x
;
434 (void)flags
; // Unused
435 (void)interfaceIndex
; // Unused
438 if (!regtype
[0] || !MakeDomainNameFromDNSNameString(&t
, regtype
)) { errormsg
= "Illegal regtype"; goto badparam
; }
439 if (!MakeDomainNameFromDNSNameString(&d
, *domain
? domain
: "local.")) { errormsg
= "Illegal domain"; goto badparam
; }
441 // Allocate memory, and handle failure
442 x
= (mDNS_DirectOP_Browse
*)mDNSPlatformMemAllocate(sizeof(*x
));
443 if (!x
) { err
= mStatus_NoMemoryErr
; errormsg
= "No memory"; goto fail
; }
446 x
->disposefn
= DNSServiceBrowseDispose
;
447 x
->callback
= callback
;
448 x
->context
= context
;
449 x
->q
.QuestionContext
= x
;
452 err
= mDNS_StartBrowse(&mDNSStorage
, &x
->q
, &t
, &d
, mDNSInterface_Any
, (flags
& kDNSServiceFlagsForceMulticast
) != 0, FoundInstance
, x
);
453 if (err
) { mDNSPlatformMemFree(x
); errormsg
= "mDNS_StartBrowse"; goto fail
; }
455 // Succeeded: Wrap up and return
456 *sdRef
= (DNSServiceRef
)x
;
457 return(mStatus_NoError
);
460 err
= mStatus_BadParamErr
;
462 LogMsg("DNSServiceBrowse(\"%s\", \"%s\") failed: %s (%ld)", regtype
, domain
, errormsg
, err
);
466 //*************************************************************************************************************
467 // Resolve Service Info
469 static void DNSServiceResolveDispose(mDNS_DirectOP
*op
)
471 mDNS_DirectOP_Resolve
*x
= (mDNS_DirectOP_Resolve
*)op
;
472 if (x
->qSRV
.ThisQInterval
>= 0) mDNS_StopQuery(&mDNSStorage
, &x
->qSRV
);
473 if (x
->qTXT
.ThisQInterval
>= 0) mDNS_StopQuery(&mDNSStorage
, &x
->qTXT
);
474 mDNSPlatformMemFree(x
);
477 mDNSlocal
void FoundServiceInfo(mDNS
*const m
, DNSQuestion
*question
, const ResourceRecord
*const answer
, mDNSBool AddRecord
)
479 mDNS_DirectOP_Resolve
*x
= (mDNS_DirectOP_Resolve
*)question
->QuestionContext
;
483 if (answer
->rrtype
== kDNSType_SRV
&& x
->SRV
== answer
) x
->SRV
= mDNSNULL
;
484 if (answer
->rrtype
== kDNSType_TXT
&& x
->TXT
== answer
) x
->TXT
= mDNSNULL
;
488 if (answer
->rrtype
== kDNSType_SRV
) x
->SRV
= answer
;
489 if (answer
->rrtype
== kDNSType_TXT
) x
->TXT
= answer
;
490 if (x
->SRV
&& x
->TXT
&& x
->callback
)
492 char fullname
[MAX_ESCAPED_DOMAIN_NAME
], targethost
[MAX_ESCAPED_DOMAIN_NAME
];
493 ConvertDomainNameToCString(answer
->name
, fullname
);
494 ConvertDomainNameToCString(&x
->SRV
->rdata
->u
.srv
.target
, targethost
);
495 x
->callback((DNSServiceRef
)x
, 0, 0, kDNSServiceErr_NoError
, fullname
, targethost
,
496 x
->SRV
->rdata
->u
.srv
.port
.NotAnInteger
, x
->TXT
->rdlength
, (char*)x
->TXT
->rdata
->u
.txt
.c
, x
->context
);
501 DNSServiceErrorType DNSServiceResolve
503 DNSServiceRef
*sdRef
,
504 DNSServiceFlags flags
,
505 uint32_t interfaceIndex
,
509 DNSServiceResolveReply callback
,
510 void *context
/* may be NULL */
513 mStatus err
= mStatus_NoError
;
514 const char *errormsg
= "Unknown";
516 domainname t
, d
, srv
;
517 mDNS_DirectOP_Resolve
*x
;
519 (void)flags
; // Unused
520 (void)interfaceIndex
; // Unused
523 if (!name
[0] || !MakeDomainLabelFromLiteralString(&n
, name
)) { errormsg
= "Bad Instance Name"; goto badparam
; }
524 if (!regtype
[0] || !MakeDomainNameFromDNSNameString(&t
, regtype
)) { errormsg
= "Bad Service Type"; goto badparam
; }
525 if (!domain
[0] || !MakeDomainNameFromDNSNameString(&d
, domain
)) { errormsg
= "Bad Domain"; goto badparam
; }
526 if (!ConstructServiceName(&srv
, &n
, &t
, &d
)) { errormsg
= "Bad Name"; goto badparam
; }
528 // Allocate memory, and handle failure
529 x
= (mDNS_DirectOP_Resolve
*)mDNSPlatformMemAllocate(sizeof(*x
));
530 if (!x
) { err
= mStatus_NoMemoryErr
; errormsg
= "No memory"; goto fail
; }
533 x
->disposefn
= DNSServiceResolveDispose
;
534 x
->callback
= callback
;
535 x
->context
= context
;
539 x
->qSRV
.ThisQInterval
= -1; // So that DNSServiceResolveDispose() knows whether to cancel this question
540 x
->qSRV
.InterfaceID
= mDNSInterface_Any
;
541 x
->qSRV
.Target
= zeroAddr
;
542 AssignDomainName(&x
->qSRV
.qname
, &srv
);
543 x
->qSRV
.qtype
= kDNSType_SRV
;
544 x
->qSRV
.qclass
= kDNSClass_IN
;
545 x
->qSRV
.LongLived
= mDNSfalse
;
546 x
->qSRV
.ExpectUnique
= mDNStrue
;
547 x
->qSRV
.ForceMCast
= mDNSfalse
;
548 x
->qSRV
.QuestionCallback
= FoundServiceInfo
;
549 x
->qSRV
.QuestionContext
= x
;
551 x
->qTXT
.ThisQInterval
= -1; // So that DNSServiceResolveDispose() knows whether to cancel this question
552 x
->qTXT
.InterfaceID
= mDNSInterface_Any
;
553 x
->qTXT
.Target
= zeroAddr
;
554 AssignDomainName(&x
->qTXT
.qname
, &srv
);
555 x
->qTXT
.qtype
= kDNSType_TXT
;
556 x
->qTXT
.qclass
= kDNSClass_IN
;
557 x
->qTXT
.LongLived
= mDNSfalse
;
558 x
->qTXT
.ExpectUnique
= mDNStrue
;
559 x
->qTXT
.ForceMCast
= mDNSfalse
;
560 x
->qTXT
.QuestionCallback
= FoundServiceInfo
;
561 x
->qTXT
.QuestionContext
= x
;
563 err
= mDNS_StartQuery(&mDNSStorage
, &x
->qSRV
);
564 if (err
) { DNSServiceResolveDispose((mDNS_DirectOP
*)x
); errormsg
= "mDNS_StartQuery qSRV"; goto fail
; }
565 err
= mDNS_StartQuery(&mDNSStorage
, &x
->qTXT
);
566 if (err
) { DNSServiceResolveDispose((mDNS_DirectOP
*)x
); errormsg
= "mDNS_StartQuery qTXT"; goto fail
; }
568 // Succeeded: Wrap up and return
569 *sdRef
= (DNSServiceRef
)x
;
570 return(mStatus_NoError
);
573 err
= mStatus_BadParamErr
;
575 LogMsg("DNSServiceResolve(\"%s\", \"%s\", \"%s\") failed: %s (%ld)", name
, regtype
, domain
, errormsg
, err
);
579 //*************************************************************************************************************
580 // Connection-oriented calls
582 // Not yet implemented, so don't include in stub library
583 // We DO include it in the actual Extension, so that if a later client compiled to use this
584 // is run against this Extension, it will get a reasonable error code instead of just
585 // failing to launch (Strong Link) or calling an unresolved symbol and crashing (Weak Link)
586 #if !MDNS_BUILDINGSTUBLIBRARY
587 DNSServiceErrorType
DNSServiceCreateConnection(DNSServiceRef
*sdRef
)
589 (void)sdRef
; // Unused
590 return(kDNSServiceErr_Unsupported
);
593 DNSServiceErrorType DNSServiceRegisterRecord
596 DNSRecordRef
*RecordRef
,
597 DNSServiceFlags flags
,
598 uint32_t interfaceIndex
,
599 const char *fullname
,
605 DNSServiceRegisterRecordReply callback
,
606 void *context
/* may be NULL */
609 (void)sdRef
; // Unused
610 (void)RecordRef
; // Unused
611 (void)flags
; // Unused
612 (void)interfaceIndex
; // Unused
613 (void)fullname
; // Unused
614 (void)rrtype
; // Unused
615 (void)rrclass
; // Unused
616 (void)rdlen
; // Unused
617 (void)rdata
; // Unused
619 (void)callback
; // Unused
620 (void)context
; // Unused
621 return(kDNSServiceErr_Unsupported
);
625 //*************************************************************************************************************
626 // DNSServiceQueryRecord
628 static void DNSServiceQueryRecordDispose(mDNS_DirectOP
*op
)
630 mDNS_DirectOP_QueryRecord
*x
= (mDNS_DirectOP_QueryRecord
*)op
;
631 if (x
->q
.ThisQInterval
>= 0) mDNS_StopQuery(&mDNSStorage
, &x
->q
);
632 mDNSPlatformMemFree(x
);
635 mDNSlocal
void DNSServiceQueryRecordResponse(mDNS
*const m
, DNSQuestion
*question
, const ResourceRecord
*const answer
, mDNSBool AddRecord
)
637 mDNS_DirectOP_QueryRecord
*x
= (mDNS_DirectOP_QueryRecord
*)question
->QuestionContext
;
638 char fullname
[MAX_ESCAPED_DOMAIN_NAME
];
640 ConvertDomainNameToCString(answer
->name
, fullname
);
641 x
->callback((DNSServiceRef
)x
, AddRecord
? kDNSServiceFlagsAdd
: (DNSServiceFlags
)0, 0, kDNSServiceErr_NoError
,
642 fullname
, answer
->rrtype
, answer
->rrclass
, answer
->rdlength
, answer
->rdata
->u
.data
, answer
->rroriginalttl
, x
->context
);
645 DNSServiceErrorType DNSServiceQueryRecord
647 DNSServiceRef
*sdRef
,
648 DNSServiceFlags flags
,
649 uint32_t interfaceIndex
,
650 const char *fullname
,
653 DNSServiceQueryRecordReply callback
,
654 void *context
/* may be NULL */
657 mStatus err
= mStatus_NoError
;
658 const char *errormsg
= "Unknown";
659 mDNS_DirectOP_QueryRecord
*x
;
661 (void)flags
; // Unused
662 (void)interfaceIndex
; // Unused
664 // Allocate memory, and handle failure
665 x
= (mDNS_DirectOP_QueryRecord
*)mDNSPlatformMemAllocate(sizeof(*x
));
666 if (!x
) { err
= mStatus_NoMemoryErr
; errormsg
= "No memory"; goto fail
; }
669 x
->disposefn
= DNSServiceQueryRecordDispose
;
670 x
->callback
= callback
;
671 x
->context
= context
;
673 x
->q
.ThisQInterval
= -1; // So that DNSServiceResolveDispose() knows whether to cancel this question
674 x
->q
.InterfaceID
= mDNSInterface_Any
;
675 x
->q
.Target
= zeroAddr
;
676 MakeDomainNameFromDNSNameString(&x
->q
.qname
, fullname
);
678 x
->q
.qclass
= rrclass
;
679 x
->q
.LongLived
= (flags
& kDNSServiceFlagsLongLivedQuery
) != 0;
680 x
->q
.ExpectUnique
= mDNSfalse
;
681 x
->q
.ForceMCast
= (flags
& kDNSServiceFlagsForceMulticast
) != 0;
682 x
->q
.QuestionCallback
= DNSServiceQueryRecordResponse
;
683 x
->q
.QuestionContext
= x
;
685 err
= mDNS_StartQuery(&mDNSStorage
, &x
->q
);
686 if (err
) { DNSServiceResolveDispose((mDNS_DirectOP
*)x
); errormsg
= "mDNS_StartQuery"; goto fail
; }
688 // Succeeded: Wrap up and return
689 *sdRef
= (DNSServiceRef
)x
;
690 return(mStatus_NoError
);
693 err
= mStatus_BadParamErr
;
695 LogMsg("DNSServiceQueryRecord(\"%s\", %d, %d) failed: %s (%ld)", fullname
, rrtype
, rrclass
, errormsg
, err
);
699 //*************************************************************************************************************
700 // DNSServiceReconfirmRecord
702 // Not yet implemented, so don't include in stub library
703 // We DO include it in the actual Extension, so that if a later client compiled to use this
704 // is run against this Extension, it will get a reasonable error code instead of just
705 // failing to launch (Strong Link) or calling an unresolved symbol and crashing (Weak Link)
706 #if !MDNS_BUILDINGSTUBLIBRARY
707 void DNSServiceReconfirmRecord
709 DNSServiceFlags flags
,
710 uint32_t interfaceIndex
,
711 const char *fullname
,
718 (void)flags
; // Unused
719 (void)interfaceIndex
; // Unused
720 (void)fullname
; // Unused
721 (void)rrtype
; // Unused
722 (void)rrclass
; // Unused
723 (void)rdlen
; // Unused
724 (void)rdata
; // Unused