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.7 2004/12/10 04:08:43 cheshire
35 Added comments about autoname and autorename
37 Revision 1.6 2004/10/19 21:33:22 cheshire
38 <rdar://problem/3844991> Cannot resolve non-local registrations using the mach API
39 Added flag 'kDNSServiceFlagsForceMulticast'. Passing through an interface id for a unicast name
40 doesn't force multicast unless you set this flag to indicate explicitly that this is what you want
42 Revision 1.5 2004/09/21 23:29:51 cheshire
43 <rdar://problem/3680045> DNSServiceResolve should delay sending packets
45 Revision 1.4 2004/09/17 01:08:55 cheshire
46 Renamed mDNSClientAPI.h to mDNSEmbeddedAPI.h
47 The name "mDNSClientAPI.h" is misleading to new developers looking at this code. The interfaces
48 declared in that file are ONLY appropriate to single-address-space embedded applications.
49 For clients on general-purpose computers, the interfaces defined in dns_sd.h should be used.
51 Revision 1.3 2004/05/27 06:26:31 cheshire
52 Add shim for DNSServiceQueryRecord()
54 Revision 1.2 2004/05/20 18:41:24 cheshire
55 Fix build broken by removal of 'kDNSServiceFlagsRemove' from dns_sd.h
57 Revision 1.1 2004/03/12 21:30:29 cheshire
58 Build a System-Context Shared Library from mDNSCore, for the benefit of developers
59 like Muse Research who want to be able to use mDNS/DNS-SD from GPL-licensed code.
63 #include "dns_sd.h" // Defines the interface to the client layer above
64 #include "mDNSEmbeddedAPI.h" // The interface we're building on top of
65 extern mDNS mDNSStorage
; // We need to pass the address of this storage to the lower-layer functions
67 #if MDNS_BUILDINGSHAREDLIBRARY || MDNS_BUILDINGSTUBLIBRARY
71 //*************************************************************************************************************
72 // General Utility Functions
74 // All mDNS_DirectOP structures start with the pointer to the type-specific disposal function.
75 // Optional type-specific data follows these three fields
76 // When the client starts an operation, we return the address of the corresponding mDNS_DirectOP
77 // as the DNSServiceRef for the operation
78 // We stash the value in core context fields so we can get it back to recover our state in our callbacks,
79 // and pass it though to the client for it to recover its state
81 typedef struct mDNS_DirectOP_struct mDNS_DirectOP
;
82 typedef void mDNS_DirectOP_Dispose(mDNS_DirectOP
*op
);
83 struct mDNS_DirectOP_struct
85 mDNS_DirectOP_Dispose
*disposefn
;
90 mDNS_DirectOP_Dispose
*disposefn
;
91 DNSServiceRegisterReply callback
;
93 mDNSBool autoname
; // Set if this name is tied to the Computer Name
94 mDNSBool autorename
; // Set if we just got a name conflict and now need to automatically pick a new name
97 } mDNS_DirectOP_Register
;
101 mDNS_DirectOP_Dispose
*disposefn
;
102 DNSServiceBrowseReply callback
;
105 } mDNS_DirectOP_Browse
;
109 mDNS_DirectOP_Dispose
*disposefn
;
110 DNSServiceResolveReply callback
;
112 const ResourceRecord
*SRV
;
113 const ResourceRecord
*TXT
;
116 } mDNS_DirectOP_Resolve
;
120 mDNS_DirectOP_Dispose
*disposefn
;
121 DNSServiceQueryRecordReply callback
;
124 } mDNS_DirectOP_QueryRecord
;
126 int DNSServiceRefSockFD(DNSServiceRef sdRef
)
128 (void)sdRef
; // Unused
132 DNSServiceErrorType
DNSServiceProcessResult(DNSServiceRef sdRef
)
134 (void)sdRef
; // Unused
135 return(kDNSServiceErr_NoError
);
138 void DNSServiceRefDeallocate(DNSServiceRef sdRef
)
140 mDNS_DirectOP
*op
= (mDNS_DirectOP
*)sdRef
;
141 //LogMsg("DNSServiceRefDeallocate");
145 //*************************************************************************************************************
146 // Domain Enumeration
148 // Not yet implemented, so don't include in stub library
149 // We DO include it in the actual Extension, so that if a later client compiled to use this
150 // is run against this Extension, it will get a reasonable error code instead of just
151 // failing to launch (Strong Link) or calling an unresolved symbol and crashing (Weak Link)
152 #if !MDNS_BUILDINGSTUBLIBRARY
153 DNSServiceErrorType DNSServiceEnumerateDomains
155 DNSServiceRef
*sdRef
,
156 DNSServiceFlags flags
,
157 uint32_t interfaceIndex
,
158 DNSServiceDomainEnumReply callback
,
159 void *context
/* may be NULL */
162 (void)sdRef
; // Unused
163 (void)flags
; // Unused
164 (void)interfaceIndex
; // Unused
165 (void)callback
; // Unused
166 (void)context
; // Unused
167 return(kDNSServiceErr_Unsupported
);
171 //*************************************************************************************************************
174 mDNSlocal
void FreeDNSServiceRegistration(mDNS_DirectOP_Register
*x
)
178 ExtraResourceRecord
*extras
= x
->s
.Extras
;
179 x
->s
.Extras
= x
->s
.Extras
->next
;
180 if (extras
->r
.resrec
.rdata
!= &extras
->r
.rdatastorage
)
181 mDNSPlatformMemFree(extras
->r
.resrec
.rdata
);
182 mDNSPlatformMemFree(extras
);
185 if (x
->s
.RR_TXT
.resrec
.rdata
!= &x
->s
.RR_TXT
.rdatastorage
)
186 mDNSPlatformMemFree(x
->s
.RR_TXT
.resrec
.rdata
);
188 if (x
->s
.SubTypes
) mDNSPlatformMemFree(x
->s
.SubTypes
);
190 mDNSPlatformMemFree(x
);
193 static void DNSServiceRegisterDispose(mDNS_DirectOP
*op
)
195 mDNS_DirectOP_Register
*x
= (mDNS_DirectOP_Register
*)op
;
196 x
->autorename
= mDNSfalse
;
197 // If mDNS_DeregisterService() returns mStatus_NoError, that means that the service was found in the list,
198 // is sending its goodbye packet, and we'll get an mStatus_MemFree message when we can free the memory.
199 // If mDNS_DeregisterService() returns an error, it means that the service had already been removed from
200 // the list, so we should go ahead and free the memory right now
201 if (mDNS_DeregisterService(&mDNSStorage
, &x
->s
) != mStatus_NoError
)
202 FreeDNSServiceRegistration(x
);
205 mDNSlocal
void RegCallback(mDNS
*const m
, ServiceRecordSet
*const sr
, mStatus result
)
207 mDNS_DirectOP_Register
*x
= (mDNS_DirectOP_Register
*)sr
->ServiceContext
;
210 domainname type
, dom
;
211 char namestr
[MAX_DOMAIN_LABEL
+1]; // Unescaped name: up to 63 bytes plus C-string terminating NULL.
212 char typestr
[MAX_ESCAPED_DOMAIN_NAME
];
213 char domstr
[MAX_ESCAPED_DOMAIN_NAME
];
214 if (!DeconstructServiceName(&sr
->RR_SRV
.resrec
.name
, &name
, &type
, &dom
)) return;
215 if (!ConvertDomainLabelToCString_unescaped(&name
, namestr
)) return;
216 if (!ConvertDomainNameToCString(&type
, typestr
)) return;
217 if (!ConvertDomainNameToCString(&dom
, domstr
)) return;
219 if (result
== mStatus_NoError
)
222 x
->callback((DNSServiceRef
)x
, 0, result
, namestr
, typestr
, domstr
, x
->context
);
224 else if (result
== mStatus_NameConflict
)
226 if (x
->autoname
) mDNS_RenameAndReregisterService(m
, sr
, mDNSNULL
);
227 else if (x
->callback
)
228 x
->callback((DNSServiceRef
)x
, 0, result
, namestr
, typestr
, domstr
, x
->context
);
230 else if (result
== mStatus_MemFree
)
234 x
->autorename
= mDNSfalse
;
235 x
->name
= mDNSStorage
.nicelabel
;
236 mDNS_RenameAndReregisterService(m
, &x
->s
, &x
->name
);
239 FreeDNSServiceRegistration(x
);
243 DNSServiceErrorType DNSServiceRegister
245 DNSServiceRef
*sdRef
,
246 DNSServiceFlags flags
,
247 uint32_t interfaceIndex
,
248 const char *name
, /* may be NULL */
250 const char *domain
, /* may be NULL */
251 const char *host
, /* may be NULL */
252 uint16_t notAnIntPort
,
254 const void *txtRecord
, /* may be NULL */
255 DNSServiceRegisterReply callback
, /* may be NULL */
256 void *context
/* may be NULL */
259 mStatus err
= mStatus_NoError
;
260 const char *errormsg
= "Unknown";
262 domainname t
, d
, h
, srv
;
264 unsigned int size
= sizeof(RDataBody
);
265 AuthRecord
*SubTypes
= mDNSNULL
;
266 mDNSu32 NumSubTypes
= 0;
267 mDNS_DirectOP_Register
*x
;
268 (void)flags
; // Unused
269 (void)interfaceIndex
; // Unused
272 if (!name
[0]) n
= mDNSStorage
.nicelabel
;
273 else if (!MakeDomainLabelFromLiteralString(&n
, name
)) { errormsg
= "Bad Instance Name"; goto badparam
; }
274 if (!regtype
|| !*regtype
|| !MakeDomainNameFromDNSNameString(&t
, regtype
)) { errormsg
= "Bad Service Type"; goto badparam
; }
275 if (!MakeDomainNameFromDNSNameString(&d
, (domain
&& *domain
) ? domain
: "local.")) { errormsg
= "Bad Domain"; goto badparam
; }
276 if (!MakeDomainNameFromDNSNameString(&h
, (host
&& *host
) ? host
: "")) { errormsg
= "Bad Target Host"; goto badparam
; }
277 if (!ConstructServiceName(&srv
, &n
, &t
, &d
)) { errormsg
= "Bad Name"; goto badparam
; }
278 port
.NotAnInteger
= notAnIntPort
;
280 // Allocate memory, and handle failure
283 x
= (mDNS_DirectOP_Register
*)mDNSPlatformMemAllocate(sizeof(*x
) - sizeof(RDataBody
) + size
);
284 if (!x
) { err
= mStatus_NoMemoryErr
; errormsg
= "No memory"; goto fail
; }
287 x
->disposefn
= DNSServiceRegisterDispose
;
288 x
->callback
= callback
;
289 x
->context
= context
;
290 x
->autoname
= (!name
[0]);
291 x
->autorename
= mDNSfalse
;
295 err
= mDNS_RegisterService(&mDNSStorage
, &x
->s
,
296 &x
->name
, &t
, &d
, // Name, type, domain
297 &h
, port
, // Host and port
298 txtRecord
, txtLen
, // TXT data, length
299 SubTypes
, NumSubTypes
, // Subtypes
300 mDNSInterface_Any
, // Interface ID
301 RegCallback
, x
); // Callback and context
302 if (err
) { mDNSPlatformMemFree(x
); errormsg
= "mDNS_RegisterService"; goto fail
; }
304 // Succeeded: Wrap up and return
305 *sdRef
= (DNSServiceRef
)x
;
306 return(mStatus_NoError
);
309 err
= mStatus_BadParamErr
;
311 LogMsg("DNSServiceBrowse(\"%s\", \"%s\") failed: %s (%ld)", regtype
, domain
, errormsg
, err
);
315 //*************************************************************************************************************
316 // Add / Update / Remove records from existing Registration
318 // Not yet implemented, so don't include in stub library
319 // We DO include it in the actual Extension, so that if a later client compiled to use this
320 // is run against this Extension, it will get a reasonable error code instead of just
321 // failing to launch (Strong Link) or calling an unresolved symbol and crashing (Weak Link)
322 #if !MDNS_BUILDINGSTUBLIBRARY
323 DNSServiceErrorType DNSServiceAddRecord
326 DNSRecordRef
*RecordRef
,
327 DNSServiceFlags flags
,
334 (void)sdRef
; // Unused
335 (void)RecordRef
; // Unused
336 (void)flags
; // Unused
337 (void)rrtype
; // Unused
338 (void)rdlen
; // Unused
339 (void)rdata
; // Unused
341 return(kDNSServiceErr_Unsupported
);
344 DNSServiceErrorType DNSServiceUpdateRecord
347 DNSRecordRef RecordRef
, /* may be NULL */
348 DNSServiceFlags flags
,
354 (void)sdRef
; // Unused
355 (void)RecordRef
; // Unused
356 (void)flags
; // Unused
357 (void)rdlen
; // Unused
358 (void)rdata
; // Unused
360 return(kDNSServiceErr_Unsupported
);
363 DNSServiceErrorType DNSServiceRemoveRecord
366 DNSRecordRef RecordRef
,
367 DNSServiceFlags flags
370 (void)sdRef
; // Unused
371 (void)RecordRef
; // Unused
372 (void)flags
; // Unused
373 return(kDNSServiceErr_Unsupported
);
377 //*************************************************************************************************************
378 // Browse for services
380 static void DNSServiceBrowseDispose(mDNS_DirectOP
*op
)
382 mDNS_DirectOP_Browse
*x
= (mDNS_DirectOP_Browse
*)op
;
383 //LogMsg("DNSServiceBrowseDispose");
384 mDNS_StopBrowse(&mDNSStorage
, &x
->q
);
385 mDNSPlatformMemFree(x
);
388 mDNSlocal
void FoundInstance(mDNS
*const m
, DNSQuestion
*question
, const ResourceRecord
*const answer
, mDNSBool AddRecord
)
390 DNSServiceFlags flags
= AddRecord
? kDNSServiceFlagsAdd
: (DNSServiceFlags
)0;
392 domainname type
, domain
;
393 char cname
[MAX_DOMAIN_LABEL
+1]; // Unescaped name: up to 63 bytes plus C-string terminating NULL.
394 char ctype
[MAX_ESCAPED_DOMAIN_NAME
];
395 char cdom
[MAX_ESCAPED_DOMAIN_NAME
];
396 mDNS_DirectOP_Browse
*x
= (mDNS_DirectOP_Browse
*)question
->QuestionContext
;
399 if (answer
->rrtype
!= kDNSType_PTR
)
400 { LogMsg("FoundInstance: Should not be called with rrtype %d (not a PTR record)", answer
->rrtype
); return; }
402 if (!DeconstructServiceName(&answer
->rdata
->u
.name
, &name
, &type
, &domain
))
404 LogMsg("FoundInstance: %##s PTR %##s received from network is not valid DNS-SD service pointer",
405 answer
->name
.c
, answer
->rdata
->u
.name
.c
);
409 ConvertDomainLabelToCString_unescaped(&name
, cname
);
410 ConvertDomainNameToCString(&type
, ctype
);
411 ConvertDomainNameToCString(&domain
, cdom
);
413 x
->callback((DNSServiceRef
)x
, flags
, 0, 0, cname
, ctype
, cdom
, x
->context
);
416 DNSServiceErrorType DNSServiceBrowse
418 DNSServiceRef
*sdRef
,
419 DNSServiceFlags flags
,
420 uint32_t interfaceIndex
,
422 const char *domain
, /* may be NULL */
423 DNSServiceBrowseReply callback
,
424 void *context
/* may be NULL */
427 mStatus err
= mStatus_NoError
;
428 const char *errormsg
= "Unknown";
430 mDNS_DirectOP_Browse
*x
;
431 (void)flags
; // Unused
432 (void)interfaceIndex
; // Unused
435 if (!regtype
[0] || !MakeDomainNameFromDNSNameString(&t
, regtype
)) { errormsg
= "Illegal regtype"; goto badparam
; }
436 if (!MakeDomainNameFromDNSNameString(&d
, *domain
? domain
: "local.")) { errormsg
= "Illegal domain"; goto badparam
; }
438 // Allocate memory, and handle failure
439 x
= (mDNS_DirectOP_Browse
*)mDNSPlatformMemAllocate(sizeof(*x
));
440 if (!x
) { err
= mStatus_NoMemoryErr
; errormsg
= "No memory"; goto fail
; }
443 x
->disposefn
= DNSServiceBrowseDispose
;
444 x
->callback
= callback
;
445 x
->context
= context
;
446 x
->q
.QuestionContext
= x
;
449 err
= mDNS_StartBrowse(&mDNSStorage
, &x
->q
, &t
, &d
, mDNSInterface_Any
, (flags
& kDNSServiceFlagsForceMulticast
) != 0, FoundInstance
, x
);
450 if (err
) { mDNSPlatformMemFree(x
); errormsg
= "mDNS_StartBrowse"; goto fail
; }
452 // Succeeded: Wrap up and return
453 *sdRef
= (DNSServiceRef
)x
;
454 return(mStatus_NoError
);
457 err
= mStatus_BadParamErr
;
459 LogMsg("DNSServiceBrowse(\"%s\", \"%s\") failed: %s (%ld)", regtype
, domain
, errormsg
, err
);
463 //*************************************************************************************************************
464 // Resolve Service Info
466 static void DNSServiceResolveDispose(mDNS_DirectOP
*op
)
468 mDNS_DirectOP_Resolve
*x
= (mDNS_DirectOP_Resolve
*)op
;
469 if (x
->qSRV
.ThisQInterval
>= 0) mDNS_StopQuery(&mDNSStorage
, &x
->qSRV
);
470 if (x
->qTXT
.ThisQInterval
>= 0) mDNS_StopQuery(&mDNSStorage
, &x
->qTXT
);
471 mDNSPlatformMemFree(x
);
474 mDNSlocal
void FoundServiceInfo(mDNS
*const m
, DNSQuestion
*question
, const ResourceRecord
*const answer
, mDNSBool AddRecord
)
476 mDNS_DirectOP_Resolve
*x
= (mDNS_DirectOP_Resolve
*)question
->QuestionContext
;
480 if (answer
->rrtype
== kDNSType_SRV
&& x
->SRV
== answer
) x
->SRV
= mDNSNULL
;
481 if (answer
->rrtype
== kDNSType_TXT
&& x
->TXT
== answer
) x
->TXT
= mDNSNULL
;
485 if (answer
->rrtype
== kDNSType_SRV
) x
->SRV
= answer
;
486 if (answer
->rrtype
== kDNSType_TXT
) x
->TXT
= answer
;
487 if (x
->SRV
&& x
->TXT
&& x
->callback
)
489 char fullname
[MAX_ESCAPED_DOMAIN_NAME
], targethost
[MAX_ESCAPED_DOMAIN_NAME
];
490 ConvertDomainNameToCString(&answer
->name
, fullname
);
491 ConvertDomainNameToCString(&x
->SRV
->rdata
->u
.srv
.target
, targethost
);
492 x
->callback((DNSServiceRef
)x
, 0, 0, kDNSServiceErr_NoError
, fullname
, targethost
,
493 x
->SRV
->rdata
->u
.srv
.port
.NotAnInteger
, x
->TXT
->rdlength
, (char*)x
->TXT
->rdata
->u
.txt
.c
, x
->context
);
498 DNSServiceErrorType DNSServiceResolve
500 DNSServiceRef
*sdRef
,
501 DNSServiceFlags flags
,
502 uint32_t interfaceIndex
,
506 DNSServiceResolveReply callback
,
507 void *context
/* may be NULL */
510 mStatus err
= mStatus_NoError
;
511 const char *errormsg
= "Unknown";
513 domainname t
, d
, srv
;
514 mDNS_DirectOP_Resolve
*x
;
516 (void)flags
; // Unused
517 (void)interfaceIndex
; // Unused
520 if (!name
[0] || !MakeDomainLabelFromLiteralString(&n
, name
)) { errormsg
= "Bad Instance Name"; goto badparam
; }
521 if (!regtype
[0] || !MakeDomainNameFromDNSNameString(&t
, regtype
)) { errormsg
= "Bad Service Type"; goto badparam
; }
522 if (!domain
[0] || !MakeDomainNameFromDNSNameString(&d
, domain
)) { errormsg
= "Bad Domain"; goto badparam
; }
523 if (!ConstructServiceName(&srv
, &n
, &t
, &d
)) { errormsg
= "Bad Name"; goto badparam
; }
525 // Allocate memory, and handle failure
526 x
= (mDNS_DirectOP_Resolve
*)mDNSPlatformMemAllocate(sizeof(*x
));
527 if (!x
) { err
= mStatus_NoMemoryErr
; errormsg
= "No memory"; goto fail
; }
530 x
->disposefn
= DNSServiceResolveDispose
;
531 x
->callback
= callback
;
532 x
->context
= context
;
536 x
->qSRV
.ThisQInterval
= -1; // So that DNSServiceResolveDispose() knows whether to cancel this question
537 x
->qSRV
.InterfaceID
= mDNSInterface_Any
;
538 x
->qSRV
.Target
= zeroAddr
;
539 AssignDomainName(x
->qSRV
.qname
, srv
);
540 x
->qSRV
.qtype
= kDNSType_SRV
;
541 x
->qSRV
.qclass
= kDNSClass_IN
;
542 x
->qSRV
.LongLived
= mDNSfalse
;
543 x
->qSRV
.ExpectUnique
= mDNStrue
;
544 x
->qSRV
.ForceMCast
= mDNSfalse
;
545 x
->qSRV
.QuestionCallback
= FoundServiceInfo
;
546 x
->qSRV
.QuestionContext
= x
;
548 x
->qTXT
.ThisQInterval
= -1; // So that DNSServiceResolveDispose() knows whether to cancel this question
549 x
->qTXT
.InterfaceID
= mDNSInterface_Any
;
550 x
->qTXT
.Target
= zeroAddr
;
551 AssignDomainName(x
->qTXT
.qname
, srv
);
552 x
->qTXT
.qtype
= kDNSType_TXT
;
553 x
->qTXT
.qclass
= kDNSClass_IN
;
554 x
->qTXT
.LongLived
= mDNSfalse
;
555 x
->qTXT
.ExpectUnique
= mDNStrue
;
556 x
->qTXT
.ForceMCast
= mDNSfalse
;
557 x
->qTXT
.QuestionCallback
= FoundServiceInfo
;
558 x
->qTXT
.QuestionContext
= x
;
560 err
= mDNS_StartQuery(&mDNSStorage
, &x
->qSRV
);
561 if (err
) { DNSServiceResolveDispose((mDNS_DirectOP
*)x
); errormsg
= "mDNS_StartQuery qSRV"; goto fail
; }
562 err
= mDNS_StartQuery(&mDNSStorage
, &x
->qTXT
);
563 if (err
) { DNSServiceResolveDispose((mDNS_DirectOP
*)x
); errormsg
= "mDNS_StartQuery qTXT"; goto fail
; }
565 // Succeeded: Wrap up and return
566 *sdRef
= (DNSServiceRef
)x
;
567 return(mStatus_NoError
);
570 err
= mStatus_BadParamErr
;
572 LogMsg("DNSServiceResolve(\"%s\", \"%s\", \"%s\") failed: %s (%ld)", name
, regtype
, domain
, errormsg
, err
);
576 //*************************************************************************************************************
577 // Connection-oriented calls
579 // Not yet implemented, so don't include in stub library
580 // We DO include it in the actual Extension, so that if a later client compiled to use this
581 // is run against this Extension, it will get a reasonable error code instead of just
582 // failing to launch (Strong Link) or calling an unresolved symbol and crashing (Weak Link)
583 #if !MDNS_BUILDINGSTUBLIBRARY
584 DNSServiceErrorType
DNSServiceCreateConnection(DNSServiceRef
*sdRef
)
586 (void)sdRef
; // Unused
587 return(kDNSServiceErr_Unsupported
);
590 DNSServiceErrorType DNSServiceRegisterRecord
593 DNSRecordRef
*RecordRef
,
594 DNSServiceFlags flags
,
595 uint32_t interfaceIndex
,
596 const char *fullname
,
602 DNSServiceRegisterRecordReply callback
,
603 void *context
/* may be NULL */
606 (void)sdRef
; // Unused
607 (void)RecordRef
; // Unused
608 (void)flags
; // Unused
609 (void)interfaceIndex
; // Unused
610 (void)fullname
; // Unused
611 (void)rrtype
; // Unused
612 (void)rrclass
; // Unused
613 (void)rdlen
; // Unused
614 (void)rdata
; // Unused
616 (void)callback
; // Unused
617 (void)context
; // Unused
618 return(kDNSServiceErr_Unsupported
);
622 //*************************************************************************************************************
623 // DNSServiceQueryRecord
625 static void DNSServiceQueryRecordDispose(mDNS_DirectOP
*op
)
627 mDNS_DirectOP_QueryRecord
*x
= (mDNS_DirectOP_QueryRecord
*)op
;
628 if (x
->q
.ThisQInterval
>= 0) mDNS_StopQuery(&mDNSStorage
, &x
->q
);
629 mDNSPlatformMemFree(x
);
632 mDNSlocal
void DNSServiceQueryRecordResponse(mDNS
*const m
, DNSQuestion
*question
, const ResourceRecord
*const answer
, mDNSBool AddRecord
)
634 mDNS_DirectOP_QueryRecord
*x
= (mDNS_DirectOP_QueryRecord
*)question
->QuestionContext
;
635 char fullname
[MAX_ESCAPED_DOMAIN_NAME
];
637 ConvertDomainNameToCString(&answer
->name
, fullname
);
638 x
->callback((DNSServiceRef
)x
, AddRecord
? kDNSServiceFlagsAdd
: (DNSServiceFlags
)0, 0, kDNSServiceErr_NoError
,
639 fullname
, answer
->rrtype
, answer
->rrclass
, answer
->rdlength
, answer
->rdata
->u
.data
, answer
->rroriginalttl
, x
->context
);
642 DNSServiceErrorType DNSServiceQueryRecord
644 DNSServiceRef
*sdRef
,
645 DNSServiceFlags flags
,
646 uint32_t interfaceIndex
,
647 const char *fullname
,
650 DNSServiceQueryRecordReply callback
,
651 void *context
/* may be NULL */
654 mStatus err
= mStatus_NoError
;
655 const char *errormsg
= "Unknown";
656 mDNS_DirectOP_QueryRecord
*x
;
658 (void)flags
; // Unused
659 (void)interfaceIndex
; // Unused
661 // Allocate memory, and handle failure
662 x
= (mDNS_DirectOP_QueryRecord
*)mDNSPlatformMemAllocate(sizeof(*x
));
663 if (!x
) { err
= mStatus_NoMemoryErr
; errormsg
= "No memory"; goto fail
; }
666 x
->disposefn
= DNSServiceQueryRecordDispose
;
667 x
->callback
= callback
;
668 x
->context
= context
;
670 x
->q
.ThisQInterval
= -1; // So that DNSServiceResolveDispose() knows whether to cancel this question
671 x
->q
.InterfaceID
= mDNSInterface_Any
;
672 x
->q
.Target
= zeroAddr
;
673 MakeDomainNameFromDNSNameString(&x
->q
.qname
, fullname
);
675 x
->q
.qclass
= rrclass
;
676 x
->q
.LongLived
= (flags
& kDNSServiceFlagsLongLivedQuery
) != 0;
677 x
->q
.ExpectUnique
= mDNSfalse
;
678 x
->q
.ForceMCast
= (flags
& kDNSServiceFlagsForceMulticast
) != 0;
679 x
->q
.QuestionCallback
= DNSServiceQueryRecordResponse
;
680 x
->q
.QuestionContext
= x
;
682 err
= mDNS_StartQuery(&mDNSStorage
, &x
->q
);
683 if (err
) { DNSServiceResolveDispose((mDNS_DirectOP
*)x
); errormsg
= "mDNS_StartQuery"; goto fail
; }
685 // Succeeded: Wrap up and return
686 *sdRef
= (DNSServiceRef
)x
;
687 return(mStatus_NoError
);
690 err
= mStatus_BadParamErr
;
692 LogMsg("DNSServiceQueryRecord(\"%s\", %d, %d) failed: %s (%ld)", fullname
, rrtype
, rrclass
, errormsg
, err
);
696 //*************************************************************************************************************
697 // DNSServiceReconfirmRecord
699 // Not yet implemented, so don't include in stub library
700 // We DO include it in the actual Extension, so that if a later client compiled to use this
701 // is run against this Extension, it will get a reasonable error code instead of just
702 // failing to launch (Strong Link) or calling an unresolved symbol and crashing (Weak Link)
703 #if !MDNS_BUILDINGSTUBLIBRARY
704 void DNSServiceReconfirmRecord
706 DNSServiceFlags flags
,
707 uint32_t interfaceIndex
,
708 const char *fullname
,
715 (void)flags
; // Unused
716 (void)interfaceIndex
; // Unused
717 (void)fullname
; // Unused
718 (void)rrtype
; // Unused
719 (void)rrclass
; // Unused
720 (void)rdlen
; // Unused
721 (void)rdata
; // Unused