1 /* -*- Mode: C; tab-width: 4 -*-
3 * Copyright (c) 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 * This file defines a simple shim layer between a client calling the "/usr/include/dns_sd.h" APIs
18 * and an implementation of mDNSCore ("mDNSEmbeddedAPI.h" APIs) in the same address space.
19 * When the client calls a dns_sd.h function, the shim calls the corresponding mDNSEmbeddedAPI.h
20 * function, and when mDNSCore calls the shim's callback, we call through to the client's callback.
21 * The shim is responsible for two main things:
22 * - converting string parameters between C string format and native DNS format,
23 * - and for allocating and freeing memory.
25 Change History (most recent first):
27 $Log: dnssd_clientshim.c,v $
28 Revision 1.16 2007/11/30 20:12:24 cheshire
29 Removed unused "badparam:" label
31 Revision 1.15 2007/07/27 19:30:41 cheshire
32 Changed mDNSQuestionCallback parameter from mDNSBool to QC_result,
33 to properly reflect tri-state nature of the possible responses
35 Revision 1.14 2007/07/17 19:15:26 cheshire
36 <rdar://problem/5297410> Crash in DNSServiceRegister() in dnssd_clientshim.c
38 Revision 1.13 2007/01/04 20:57:49 cheshire
39 Rename ReturnCNAME to ReturnIntermed (for ReturnIntermediates)
41 Revision 1.12 2006/12/19 22:43:55 cheshire
44 Revision 1.11 2006/10/27 01:30:23 cheshire
45 Need explicitly to set ReturnIntermed = mDNSfalse
47 Revision 1.10 2006/08/14 23:24:56 cheshire
48 Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
50 Revision 1.9 2006/07/24 23:45:55 cheshire
51 <rdar://problem/4605276> DNSServiceReconfirmRecord() should return error code
53 Revision 1.8 2004/12/16 20:47:34 cheshire
54 <rdar://problem/3324626> Cache memory management improvements
56 Revision 1.7 2004/12/10 04:08:43 cheshire
57 Added comments about autoname and autorename
59 Revision 1.6 2004/10/19 21:33:22 cheshire
60 <rdar://problem/3844991> Cannot resolve non-local registrations using the mach API
61 Added flag 'kDNSServiceFlagsForceMulticast'. Passing through an interface id for a unicast name
62 doesn't force multicast unless you set this flag to indicate explicitly that this is what you want
64 Revision 1.5 2004/09/21 23:29:51 cheshire
65 <rdar://problem/3680045> DNSServiceResolve should delay sending packets
67 Revision 1.4 2004/09/17 01:08:55 cheshire
68 Renamed mDNSClientAPI.h to mDNSEmbeddedAPI.h
69 The name "mDNSClientAPI.h" is misleading to new developers looking at this code. The interfaces
70 declared in that file are ONLY appropriate to single-address-space embedded applications.
71 For clients on general-purpose computers, the interfaces defined in dns_sd.h should be used.
73 Revision 1.3 2004/05/27 06:26:31 cheshire
74 Add shim for DNSServiceQueryRecord()
76 Revision 1.2 2004/05/20 18:41:24 cheshire
77 Fix build broken by removal of 'kDNSServiceFlagsRemove' from dns_sd.h
79 Revision 1.1 2004/03/12 21:30:29 cheshire
80 Build a System-Context Shared Library from mDNSCore, for the benefit of developers
81 like Muse Research who want to be able to use mDNS/DNS-SD from GPL-licensed code.
85 #include "dns_sd.h" // Defines the interface to the client layer above
86 #include "mDNSEmbeddedAPI.h" // The interface we're building on top of
87 extern mDNS mDNSStorage
; // We need to pass the address of this storage to the lower-layer functions
89 #if MDNS_BUILDINGSHAREDLIBRARY || MDNS_BUILDINGSTUBLIBRARY
93 //*************************************************************************************************************
94 // General Utility Functions
96 // All mDNS_DirectOP structures start with the pointer to the type-specific disposal function.
97 // Optional type-specific data follows these three fields
98 // When the client starts an operation, we return the address of the corresponding mDNS_DirectOP
99 // as the DNSServiceRef for the operation
100 // We stash the value in core context fields so we can get it back to recover our state in our callbacks,
101 // and pass it though to the client for it to recover its state
103 typedef struct mDNS_DirectOP_struct mDNS_DirectOP
;
104 typedef void mDNS_DirectOP_Dispose(mDNS_DirectOP
*op
);
105 struct mDNS_DirectOP_struct
107 mDNS_DirectOP_Dispose
*disposefn
;
112 mDNS_DirectOP_Dispose
*disposefn
;
113 DNSServiceRegisterReply callback
;
115 mDNSBool autoname
; // Set if this name is tied to the Computer Name
116 mDNSBool autorename
; // Set if we just got a name conflict and now need to automatically pick a new name
120 } mDNS_DirectOP_Register
;
124 mDNS_DirectOP_Dispose
*disposefn
;
125 DNSServiceBrowseReply callback
;
128 } mDNS_DirectOP_Browse
;
132 mDNS_DirectOP_Dispose
*disposefn
;
133 DNSServiceResolveReply callback
;
135 const ResourceRecord
*SRV
;
136 const ResourceRecord
*TXT
;
139 } mDNS_DirectOP_Resolve
;
143 mDNS_DirectOP_Dispose
*disposefn
;
144 DNSServiceQueryRecordReply callback
;
147 } mDNS_DirectOP_QueryRecord
;
149 int DNSServiceRefSockFD(DNSServiceRef sdRef
)
151 (void)sdRef
; // Unused
155 DNSServiceErrorType
DNSServiceProcessResult(DNSServiceRef sdRef
)
157 (void)sdRef
; // Unused
158 return(kDNSServiceErr_NoError
);
161 void DNSServiceRefDeallocate(DNSServiceRef sdRef
)
163 mDNS_DirectOP
*op
= (mDNS_DirectOP
*)sdRef
;
164 //LogMsg("DNSServiceRefDeallocate");
168 //*************************************************************************************************************
169 // Domain Enumeration
171 // Not yet implemented, so don't include in stub library
172 // We DO include it in the actual Extension, so that if a later client compiled to use this
173 // is run against this Extension, it will get a reasonable error code instead of just
174 // failing to launch (Strong Link) or calling an unresolved symbol and crashing (Weak Link)
175 #if !MDNS_BUILDINGSTUBLIBRARY
176 DNSServiceErrorType DNSServiceEnumerateDomains
178 DNSServiceRef
*sdRef
,
179 DNSServiceFlags flags
,
180 uint32_t interfaceIndex
,
181 DNSServiceDomainEnumReply callback
,
182 void *context
/* may be NULL */
185 (void)sdRef
; // Unused
186 (void)flags
; // Unused
187 (void)interfaceIndex
; // Unused
188 (void)callback
; // Unused
189 (void)context
; // Unused
190 return(kDNSServiceErr_Unsupported
);
194 //*************************************************************************************************************
197 mDNSlocal
void FreeDNSServiceRegistration(mDNS_DirectOP_Register
*x
)
201 ExtraResourceRecord
*extras
= x
->s
.Extras
;
202 x
->s
.Extras
= x
->s
.Extras
->next
;
203 if (extras
->r
.resrec
.rdata
!= &extras
->r
.rdatastorage
)
204 mDNSPlatformMemFree(extras
->r
.resrec
.rdata
);
205 mDNSPlatformMemFree(extras
);
208 if (x
->s
.RR_TXT
.resrec
.rdata
!= &x
->s
.RR_TXT
.rdatastorage
)
209 mDNSPlatformMemFree(x
->s
.RR_TXT
.resrec
.rdata
);
211 if (x
->s
.SubTypes
) mDNSPlatformMemFree(x
->s
.SubTypes
);
213 mDNSPlatformMemFree(x
);
216 static void DNSServiceRegisterDispose(mDNS_DirectOP
*op
)
218 mDNS_DirectOP_Register
*x
= (mDNS_DirectOP_Register
*)op
;
219 x
->autorename
= mDNSfalse
;
220 // If mDNS_DeregisterService() returns mStatus_NoError, that means that the service was found in the list,
221 // is sending its goodbye packet, and we'll get an mStatus_MemFree message when we can free the memory.
222 // If mDNS_DeregisterService() returns an error, it means that the service had already been removed from
223 // the list, so we should go ahead and free the memory right now
224 if (mDNS_DeregisterService(&mDNSStorage
, &x
->s
) != mStatus_NoError
)
225 FreeDNSServiceRegistration(x
);
228 mDNSlocal
void RegCallback(mDNS
*const m
, ServiceRecordSet
*const sr
, mStatus result
)
230 mDNS_DirectOP_Register
*x
= (mDNS_DirectOP_Register
*)sr
->ServiceContext
;
233 domainname type
, dom
;
234 char namestr
[MAX_DOMAIN_LABEL
+1]; // Unescaped name: up to 63 bytes plus C-string terminating NULL.
235 char typestr
[MAX_ESCAPED_DOMAIN_NAME
];
236 char domstr
[MAX_ESCAPED_DOMAIN_NAME
];
237 if (!DeconstructServiceName(sr
->RR_SRV
.resrec
.name
, &name
, &type
, &dom
)) return;
238 if (!ConvertDomainLabelToCString_unescaped(&name
, namestr
)) return;
239 if (!ConvertDomainNameToCString(&type
, typestr
)) return;
240 if (!ConvertDomainNameToCString(&dom
, domstr
)) return;
242 if (result
== mStatus_NoError
)
245 x
->callback((DNSServiceRef
)x
, 0, result
, namestr
, typestr
, domstr
, x
->context
);
247 else if (result
== mStatus_NameConflict
)
249 if (x
->autoname
) mDNS_RenameAndReregisterService(m
, sr
, mDNSNULL
);
250 else if (x
->callback
)
251 x
->callback((DNSServiceRef
)x
, 0, result
, namestr
, typestr
, domstr
, x
->context
);
253 else if (result
== mStatus_MemFree
)
257 x
->autorename
= mDNSfalse
;
258 x
->name
= mDNSStorage
.nicelabel
;
259 mDNS_RenameAndReregisterService(m
, &x
->s
, &x
->name
);
262 FreeDNSServiceRegistration(x
);
266 DNSServiceErrorType DNSServiceRegister
268 DNSServiceRef
*sdRef
,
269 DNSServiceFlags flags
,
270 uint32_t interfaceIndex
,
271 const char *name
, /* may be NULL */
273 const char *domain
, /* may be NULL */
274 const char *host
, /* may be NULL */
275 uint16_t notAnIntPort
,
277 const void *txtRecord
, /* may be NULL */
278 DNSServiceRegisterReply callback
, /* may be NULL */
279 void *context
/* may be NULL */
282 mStatus err
= mStatus_NoError
;
283 const char *errormsg
= "Unknown";
285 domainname t
, d
, h
, srv
;
287 unsigned int size
= sizeof(RDataBody
);
288 AuthRecord
*SubTypes
= mDNSNULL
;
289 mDNSu32 NumSubTypes
= 0;
290 mDNS_DirectOP_Register
*x
;
291 (void)flags
; // Unused
292 (void)interfaceIndex
; // Unused
295 if (!name
) name
= "";
296 if (!name
[0]) n
= mDNSStorage
.nicelabel
;
297 else if (!MakeDomainLabelFromLiteralString(&n
, name
)) { errormsg
= "Bad Instance Name"; goto badparam
; }
298 if (!regtype
|| !*regtype
|| !MakeDomainNameFromDNSNameString(&t
, regtype
)) { errormsg
= "Bad Service Type"; goto badparam
; }
299 if (!MakeDomainNameFromDNSNameString(&d
, (domain
&& *domain
) ? domain
: "local.")) { errormsg
= "Bad Domain"; goto badparam
; }
300 if (!MakeDomainNameFromDNSNameString(&h
, (host
&& *host
) ? host
: "")) { errormsg
= "Bad Target Host"; goto badparam
; }
301 if (!ConstructServiceName(&srv
, &n
, &t
, &d
)) { errormsg
= "Bad Name"; goto badparam
; }
302 port
.NotAnInteger
= notAnIntPort
;
304 // Allocate memory, and handle failure
307 x
= (mDNS_DirectOP_Register
*)mDNSPlatformMemAllocate(sizeof(*x
) - sizeof(RDataBody
) + size
);
308 if (!x
) { err
= mStatus_NoMemoryErr
; errormsg
= "No memory"; goto fail
; }
311 x
->disposefn
= DNSServiceRegisterDispose
;
312 x
->callback
= callback
;
313 x
->context
= context
;
314 x
->autoname
= (!name
[0]);
315 x
->autorename
= mDNSfalse
;
320 err
= mDNS_RegisterService(&mDNSStorage
, &x
->s
,
321 &x
->name
, &t
, &d
, // Name, type, domain
322 &x
->host
, port
, // Host and port
323 txtRecord
, txtLen
, // TXT data, length
324 SubTypes
, NumSubTypes
, // Subtypes
325 mDNSInterface_Any
, // Interface ID
326 RegCallback
, x
); // Callback and context
327 if (err
) { mDNSPlatformMemFree(x
); errormsg
= "mDNS_RegisterService"; goto fail
; }
329 // Succeeded: Wrap up and return
330 *sdRef
= (DNSServiceRef
)x
;
331 return(mStatus_NoError
);
334 err
= mStatus_BadParamErr
;
336 LogMsg("DNSServiceBrowse(\"%s\", \"%s\") failed: %s (%ld)", regtype
, domain
, errormsg
, err
);
340 //*************************************************************************************************************
341 // Add / Update / Remove records from existing Registration
343 // Not yet implemented, so don't include in stub library
344 // We DO include it in the actual Extension, so that if a later client compiled to use this
345 // is run against this Extension, it will get a reasonable error code instead of just
346 // failing to launch (Strong Link) or calling an unresolved symbol and crashing (Weak Link)
347 #if !MDNS_BUILDINGSTUBLIBRARY
348 DNSServiceErrorType DNSServiceAddRecord
351 DNSRecordRef
*RecordRef
,
352 DNSServiceFlags flags
,
359 (void)sdRef
; // Unused
360 (void)RecordRef
; // Unused
361 (void)flags
; // Unused
362 (void)rrtype
; // Unused
363 (void)rdlen
; // Unused
364 (void)rdata
; // Unused
366 return(kDNSServiceErr_Unsupported
);
369 DNSServiceErrorType DNSServiceUpdateRecord
372 DNSRecordRef RecordRef
, /* may be NULL */
373 DNSServiceFlags flags
,
379 (void)sdRef
; // Unused
380 (void)RecordRef
; // Unused
381 (void)flags
; // Unused
382 (void)rdlen
; // Unused
383 (void)rdata
; // Unused
385 return(kDNSServiceErr_Unsupported
);
388 DNSServiceErrorType DNSServiceRemoveRecord
391 DNSRecordRef RecordRef
,
392 DNSServiceFlags flags
395 (void)sdRef
; // Unused
396 (void)RecordRef
; // Unused
397 (void)flags
; // Unused
398 return(kDNSServiceErr_Unsupported
);
402 //*************************************************************************************************************
403 // Browse for services
405 static void DNSServiceBrowseDispose(mDNS_DirectOP
*op
)
407 mDNS_DirectOP_Browse
*x
= (mDNS_DirectOP_Browse
*)op
;
408 //LogMsg("DNSServiceBrowseDispose");
409 mDNS_StopBrowse(&mDNSStorage
, &x
->q
);
410 mDNSPlatformMemFree(x
);
413 mDNSlocal
void FoundInstance(mDNS
*const m
, DNSQuestion
*question
, const ResourceRecord
*const answer
, QC_result AddRecord
)
415 DNSServiceFlags flags
= AddRecord
? kDNSServiceFlagsAdd
: (DNSServiceFlags
)0;
417 domainname type
, domain
;
418 char cname
[MAX_DOMAIN_LABEL
+1]; // Unescaped name: up to 63 bytes plus C-string terminating NULL.
419 char ctype
[MAX_ESCAPED_DOMAIN_NAME
];
420 char cdom
[MAX_ESCAPED_DOMAIN_NAME
];
421 mDNS_DirectOP_Browse
*x
= (mDNS_DirectOP_Browse
*)question
->QuestionContext
;
424 if (answer
->rrtype
!= kDNSType_PTR
)
425 { LogMsg("FoundInstance: Should not be called with rrtype %d (not a PTR record)", answer
->rrtype
); return; }
427 if (!DeconstructServiceName(&answer
->rdata
->u
.name
, &name
, &type
, &domain
))
429 LogMsg("FoundInstance: %##s PTR %##s received from network is not valid DNS-SD service pointer",
430 answer
->name
->c
, answer
->rdata
->u
.name
.c
);
434 ConvertDomainLabelToCString_unescaped(&name
, cname
);
435 ConvertDomainNameToCString(&type
, ctype
);
436 ConvertDomainNameToCString(&domain
, cdom
);
438 x
->callback((DNSServiceRef
)x
, flags
, 0, 0, cname
, ctype
, cdom
, x
->context
);
441 DNSServiceErrorType DNSServiceBrowse
443 DNSServiceRef
*sdRef
,
444 DNSServiceFlags flags
,
445 uint32_t interfaceIndex
,
447 const char *domain
, /* may be NULL */
448 DNSServiceBrowseReply callback
,
449 void *context
/* may be NULL */
452 mStatus err
= mStatus_NoError
;
453 const char *errormsg
= "Unknown";
455 mDNS_DirectOP_Browse
*x
;
456 (void)flags
; // Unused
457 (void)interfaceIndex
; // Unused
460 if (!regtype
[0] || !MakeDomainNameFromDNSNameString(&t
, regtype
)) { errormsg
= "Illegal regtype"; goto badparam
; }
461 if (!MakeDomainNameFromDNSNameString(&d
, *domain
? domain
: "local.")) { errormsg
= "Illegal domain"; goto badparam
; }
463 // Allocate memory, and handle failure
464 x
= (mDNS_DirectOP_Browse
*)mDNSPlatformMemAllocate(sizeof(*x
));
465 if (!x
) { err
= mStatus_NoMemoryErr
; errormsg
= "No memory"; goto fail
; }
468 x
->disposefn
= DNSServiceBrowseDispose
;
469 x
->callback
= callback
;
470 x
->context
= context
;
471 x
->q
.QuestionContext
= x
;
474 err
= mDNS_StartBrowse(&mDNSStorage
, &x
->q
, &t
, &d
, mDNSInterface_Any
, (flags
& kDNSServiceFlagsForceMulticast
) != 0, FoundInstance
, x
);
475 if (err
) { mDNSPlatformMemFree(x
); errormsg
= "mDNS_StartBrowse"; goto fail
; }
477 // Succeeded: Wrap up and return
478 *sdRef
= (DNSServiceRef
)x
;
479 return(mStatus_NoError
);
482 err
= mStatus_BadParamErr
;
484 LogMsg("DNSServiceBrowse(\"%s\", \"%s\") failed: %s (%ld)", regtype
, domain
, errormsg
, err
);
488 //*************************************************************************************************************
489 // Resolve Service Info
491 static void DNSServiceResolveDispose(mDNS_DirectOP
*op
)
493 mDNS_DirectOP_Resolve
*x
= (mDNS_DirectOP_Resolve
*)op
;
494 if (x
->qSRV
.ThisQInterval
>= 0) mDNS_StopQuery(&mDNSStorage
, &x
->qSRV
);
495 if (x
->qTXT
.ThisQInterval
>= 0) mDNS_StopQuery(&mDNSStorage
, &x
->qTXT
);
496 mDNSPlatformMemFree(x
);
499 mDNSlocal
void FoundServiceInfo(mDNS
*const m
, DNSQuestion
*question
, const ResourceRecord
*const answer
, QC_result AddRecord
)
501 mDNS_DirectOP_Resolve
*x
= (mDNS_DirectOP_Resolve
*)question
->QuestionContext
;
505 if (answer
->rrtype
== kDNSType_SRV
&& x
->SRV
== answer
) x
->SRV
= mDNSNULL
;
506 if (answer
->rrtype
== kDNSType_TXT
&& x
->TXT
== answer
) x
->TXT
= mDNSNULL
;
510 if (answer
->rrtype
== kDNSType_SRV
) x
->SRV
= answer
;
511 if (answer
->rrtype
== kDNSType_TXT
) x
->TXT
= answer
;
512 if (x
->SRV
&& x
->TXT
&& x
->callback
)
514 char fullname
[MAX_ESCAPED_DOMAIN_NAME
], targethost
[MAX_ESCAPED_DOMAIN_NAME
];
515 ConvertDomainNameToCString(answer
->name
, fullname
);
516 ConvertDomainNameToCString(&x
->SRV
->rdata
->u
.srv
.target
, targethost
);
517 x
->callback((DNSServiceRef
)x
, 0, 0, kDNSServiceErr_NoError
, fullname
, targethost
,
518 x
->SRV
->rdata
->u
.srv
.port
.NotAnInteger
, x
->TXT
->rdlength
, (unsigned char*)x
->TXT
->rdata
->u
.txt
.c
, x
->context
);
523 DNSServiceErrorType DNSServiceResolve
525 DNSServiceRef
*sdRef
,
526 DNSServiceFlags flags
,
527 uint32_t interfaceIndex
,
531 DNSServiceResolveReply callback
,
532 void *context
/* may be NULL */
535 mStatus err
= mStatus_NoError
;
536 const char *errormsg
= "Unknown";
538 domainname t
, d
, srv
;
539 mDNS_DirectOP_Resolve
*x
;
541 (void)flags
; // Unused
542 (void)interfaceIndex
; // Unused
545 if (!name
[0] || !MakeDomainLabelFromLiteralString(&n
, name
)) { errormsg
= "Bad Instance Name"; goto badparam
; }
546 if (!regtype
[0] || !MakeDomainNameFromDNSNameString(&t
, regtype
)) { errormsg
= "Bad Service Type"; goto badparam
; }
547 if (!domain
[0] || !MakeDomainNameFromDNSNameString(&d
, domain
)) { errormsg
= "Bad Domain"; goto badparam
; }
548 if (!ConstructServiceName(&srv
, &n
, &t
, &d
)) { errormsg
= "Bad Name"; goto badparam
; }
550 // Allocate memory, and handle failure
551 x
= (mDNS_DirectOP_Resolve
*)mDNSPlatformMemAllocate(sizeof(*x
));
552 if (!x
) { err
= mStatus_NoMemoryErr
; errormsg
= "No memory"; goto fail
; }
555 x
->disposefn
= DNSServiceResolveDispose
;
556 x
->callback
= callback
;
557 x
->context
= context
;
561 x
->qSRV
.ThisQInterval
= -1; // So that DNSServiceResolveDispose() knows whether to cancel this question
562 x
->qSRV
.InterfaceID
= mDNSInterface_Any
;
563 x
->qSRV
.Target
= zeroAddr
;
564 AssignDomainName(&x
->qSRV
.qname
, &srv
);
565 x
->qSRV
.qtype
= kDNSType_SRV
;
566 x
->qSRV
.qclass
= kDNSClass_IN
;
567 x
->qSRV
.LongLived
= mDNSfalse
;
568 x
->qSRV
.ExpectUnique
= mDNStrue
;
569 x
->qSRV
.ForceMCast
= mDNSfalse
;
570 x
->qSRV
.ReturnIntermed
= mDNSfalse
;
571 x
->qSRV
.QuestionCallback
= FoundServiceInfo
;
572 x
->qSRV
.QuestionContext
= x
;
574 x
->qTXT
.ThisQInterval
= -1; // So that DNSServiceResolveDispose() knows whether to cancel this question
575 x
->qTXT
.InterfaceID
= mDNSInterface_Any
;
576 x
->qTXT
.Target
= zeroAddr
;
577 AssignDomainName(&x
->qTXT
.qname
, &srv
);
578 x
->qTXT
.qtype
= kDNSType_TXT
;
579 x
->qTXT
.qclass
= kDNSClass_IN
;
580 x
->qTXT
.LongLived
= mDNSfalse
;
581 x
->qTXT
.ExpectUnique
= mDNStrue
;
582 x
->qTXT
.ForceMCast
= mDNSfalse
;
583 x
->qTXT
.ReturnIntermed
= mDNSfalse
;
584 x
->qTXT
.QuestionCallback
= FoundServiceInfo
;
585 x
->qTXT
.QuestionContext
= x
;
587 err
= mDNS_StartQuery(&mDNSStorage
, &x
->qSRV
);
588 if (err
) { DNSServiceResolveDispose((mDNS_DirectOP
*)x
); errormsg
= "mDNS_StartQuery qSRV"; goto fail
; }
589 err
= mDNS_StartQuery(&mDNSStorage
, &x
->qTXT
);
590 if (err
) { DNSServiceResolveDispose((mDNS_DirectOP
*)x
); errormsg
= "mDNS_StartQuery qTXT"; goto fail
; }
592 // Succeeded: Wrap up and return
593 *sdRef
= (DNSServiceRef
)x
;
594 return(mStatus_NoError
);
597 err
= mStatus_BadParamErr
;
599 LogMsg("DNSServiceResolve(\"%s\", \"%s\", \"%s\") failed: %s (%ld)", name
, regtype
, domain
, errormsg
, err
);
603 //*************************************************************************************************************
604 // Connection-oriented calls
606 // Not yet implemented, so don't include in stub library
607 // We DO include it in the actual Extension, so that if a later client compiled to use this
608 // is run against this Extension, it will get a reasonable error code instead of just
609 // failing to launch (Strong Link) or calling an unresolved symbol and crashing (Weak Link)
610 #if !MDNS_BUILDINGSTUBLIBRARY
611 DNSServiceErrorType
DNSServiceCreateConnection(DNSServiceRef
*sdRef
)
613 (void)sdRef
; // Unused
614 return(kDNSServiceErr_Unsupported
);
617 DNSServiceErrorType DNSServiceRegisterRecord
620 DNSRecordRef
*RecordRef
,
621 DNSServiceFlags flags
,
622 uint32_t interfaceIndex
,
623 const char *fullname
,
629 DNSServiceRegisterRecordReply callback
,
630 void *context
/* may be NULL */
633 (void)sdRef
; // Unused
634 (void)RecordRef
; // Unused
635 (void)flags
; // Unused
636 (void)interfaceIndex
; // Unused
637 (void)fullname
; // Unused
638 (void)rrtype
; // Unused
639 (void)rrclass
; // Unused
640 (void)rdlen
; // Unused
641 (void)rdata
; // Unused
643 (void)callback
; // Unused
644 (void)context
; // Unused
645 return(kDNSServiceErr_Unsupported
);
649 //*************************************************************************************************************
650 // DNSServiceQueryRecord
652 static void DNSServiceQueryRecordDispose(mDNS_DirectOP
*op
)
654 mDNS_DirectOP_QueryRecord
*x
= (mDNS_DirectOP_QueryRecord
*)op
;
655 if (x
->q
.ThisQInterval
>= 0) mDNS_StopQuery(&mDNSStorage
, &x
->q
);
656 mDNSPlatformMemFree(x
);
659 mDNSlocal
void DNSServiceQueryRecordResponse(mDNS
*const m
, DNSQuestion
*question
, const ResourceRecord
*const answer
, QC_result AddRecord
)
661 mDNS_DirectOP_QueryRecord
*x
= (mDNS_DirectOP_QueryRecord
*)question
->QuestionContext
;
662 char fullname
[MAX_ESCAPED_DOMAIN_NAME
];
664 ConvertDomainNameToCString(answer
->name
, fullname
);
665 x
->callback((DNSServiceRef
)x
, AddRecord
? kDNSServiceFlagsAdd
: (DNSServiceFlags
)0, 0, kDNSServiceErr_NoError
,
666 fullname
, answer
->rrtype
, answer
->rrclass
, answer
->rdlength
, answer
->rdata
->u
.data
, answer
->rroriginalttl
, x
->context
);
669 DNSServiceErrorType DNSServiceQueryRecord
671 DNSServiceRef
*sdRef
,
672 DNSServiceFlags flags
,
673 uint32_t interfaceIndex
,
674 const char *fullname
,
677 DNSServiceQueryRecordReply callback
,
678 void *context
/* may be NULL */
681 mStatus err
= mStatus_NoError
;
682 const char *errormsg
= "Unknown";
683 mDNS_DirectOP_QueryRecord
*x
;
685 (void)flags
; // Unused
686 (void)interfaceIndex
; // Unused
688 // Allocate memory, and handle failure
689 x
= (mDNS_DirectOP_QueryRecord
*)mDNSPlatformMemAllocate(sizeof(*x
));
690 if (!x
) { err
= mStatus_NoMemoryErr
; errormsg
= "No memory"; goto fail
; }
693 x
->disposefn
= DNSServiceQueryRecordDispose
;
694 x
->callback
= callback
;
695 x
->context
= context
;
697 x
->q
.ThisQInterval
= -1; // So that DNSServiceResolveDispose() knows whether to cancel this question
698 x
->q
.InterfaceID
= mDNSInterface_Any
;
699 x
->q
.Target
= zeroAddr
;
700 MakeDomainNameFromDNSNameString(&x
->q
.qname
, fullname
);
702 x
->q
.qclass
= rrclass
;
703 x
->q
.LongLived
= (flags
& kDNSServiceFlagsLongLivedQuery
) != 0;
704 x
->q
.ExpectUnique
= mDNSfalse
;
705 x
->q
.ForceMCast
= (flags
& kDNSServiceFlagsForceMulticast
) != 0;
706 x
->q
.ReturnIntermed
= (flags
& kDNSServiceFlagsReturnIntermediates
) != 0;
707 x
->q
.QuestionCallback
= DNSServiceQueryRecordResponse
;
708 x
->q
.QuestionContext
= x
;
710 err
= mDNS_StartQuery(&mDNSStorage
, &x
->q
);
711 if (err
) { DNSServiceResolveDispose((mDNS_DirectOP
*)x
); errormsg
= "mDNS_StartQuery"; goto fail
; }
713 // Succeeded: Wrap up and return
714 *sdRef
= (DNSServiceRef
)x
;
715 return(mStatus_NoError
);
718 LogMsg("DNSServiceQueryRecord(\"%s\", %d, %d) failed: %s (%ld)", fullname
, rrtype
, rrclass
, errormsg
, err
);
722 //*************************************************************************************************************
723 // DNSServiceReconfirmRecord
725 // Not yet implemented, so don't include in stub library
726 // We DO include it in the actual Extension, so that if a later client compiled to use this
727 // is run against this Extension, it will get a reasonable error code instead of just
728 // failing to launch (Strong Link) or calling an unresolved symbol and crashing (Weak Link)
729 #if !MDNS_BUILDINGSTUBLIBRARY
730 DNSServiceErrorType DNSSD_API DNSServiceReconfirmRecord
732 DNSServiceFlags flags
,
733 uint32_t interfaceIndex
,
734 const char *fullname
,
741 (void)flags
; // Unused
742 (void)interfaceIndex
; // Unused
743 (void)fullname
; // Unused
744 (void)rrtype
; // Unused
745 (void)rrclass
; // Unused
746 (void)rdlen
; // Unused
747 (void)rdata
; // Unused
748 return(kDNSServiceErr_Unsupported
);