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.15 2007/07/27 19:30:41 cheshire
29 Changed mDNSQuestionCallback parameter from mDNSBool to QC_result,
30 to properly reflect tri-state nature of the possible responses
32 Revision 1.14 2007/07/17 19:15:26 cheshire
33 <rdar://problem/5297410> Crash in DNSServiceRegister() in dnssd_clientshim.c
35 Revision 1.13 2007/01/04 20:57:49 cheshire
36 Rename ReturnCNAME to ReturnIntermed (for ReturnIntermediates)
38 Revision 1.12 2006/12/19 22:43:55 cheshire
41 Revision 1.11 2006/10/27 01:30:23 cheshire
42 Need explicitly to set ReturnIntermed = mDNSfalse
44 Revision 1.10 2006/08/14 23:24:56 cheshire
45 Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
47 Revision 1.9 2006/07/24 23:45:55 cheshire
48 <rdar://problem/4605276> DNSServiceReconfirmRecord() should return error code
50 Revision 1.8 2004/12/16 20:47:34 cheshire
51 <rdar://problem/3324626> Cache memory management improvements
53 Revision 1.7 2004/12/10 04:08:43 cheshire
54 Added comments about autoname and autorename
56 Revision 1.6 2004/10/19 21:33:22 cheshire
57 <rdar://problem/3844991> Cannot resolve non-local registrations using the mach API
58 Added flag 'kDNSServiceFlagsForceMulticast'. Passing through an interface id for a unicast name
59 doesn't force multicast unless you set this flag to indicate explicitly that this is what you want
61 Revision 1.5 2004/09/21 23:29:51 cheshire
62 <rdar://problem/3680045> DNSServiceResolve should delay sending packets
64 Revision 1.4 2004/09/17 01:08:55 cheshire
65 Renamed mDNSClientAPI.h to mDNSEmbeddedAPI.h
66 The name "mDNSClientAPI.h" is misleading to new developers looking at this code. The interfaces
67 declared in that file are ONLY appropriate to single-address-space embedded applications.
68 For clients on general-purpose computers, the interfaces defined in dns_sd.h should be used.
70 Revision 1.3 2004/05/27 06:26:31 cheshire
71 Add shim for DNSServiceQueryRecord()
73 Revision 1.2 2004/05/20 18:41:24 cheshire
74 Fix build broken by removal of 'kDNSServiceFlagsRemove' from dns_sd.h
76 Revision 1.1 2004/03/12 21:30:29 cheshire
77 Build a System-Context Shared Library from mDNSCore, for the benefit of developers
78 like Muse Research who want to be able to use mDNS/DNS-SD from GPL-licensed code.
82 #include "dns_sd.h" // Defines the interface to the client layer above
83 #include "mDNSEmbeddedAPI.h" // The interface we're building on top of
84 extern mDNS mDNSStorage
; // We need to pass the address of this storage to the lower-layer functions
86 #if MDNS_BUILDINGSHAREDLIBRARY || MDNS_BUILDINGSTUBLIBRARY
90 //*************************************************************************************************************
91 // General Utility Functions
93 // All mDNS_DirectOP structures start with the pointer to the type-specific disposal function.
94 // Optional type-specific data follows these three fields
95 // When the client starts an operation, we return the address of the corresponding mDNS_DirectOP
96 // as the DNSServiceRef for the operation
97 // We stash the value in core context fields so we can get it back to recover our state in our callbacks,
98 // and pass it though to the client for it to recover its state
100 typedef struct mDNS_DirectOP_struct mDNS_DirectOP
;
101 typedef void mDNS_DirectOP_Dispose(mDNS_DirectOP
*op
);
102 struct mDNS_DirectOP_struct
104 mDNS_DirectOP_Dispose
*disposefn
;
109 mDNS_DirectOP_Dispose
*disposefn
;
110 DNSServiceRegisterReply callback
;
112 mDNSBool autoname
; // Set if this name is tied to the Computer Name
113 mDNSBool autorename
; // Set if we just got a name conflict and now need to automatically pick a new name
117 } mDNS_DirectOP_Register
;
121 mDNS_DirectOP_Dispose
*disposefn
;
122 DNSServiceBrowseReply callback
;
125 } mDNS_DirectOP_Browse
;
129 mDNS_DirectOP_Dispose
*disposefn
;
130 DNSServiceResolveReply callback
;
132 const ResourceRecord
*SRV
;
133 const ResourceRecord
*TXT
;
136 } mDNS_DirectOP_Resolve
;
140 mDNS_DirectOP_Dispose
*disposefn
;
141 DNSServiceQueryRecordReply callback
;
144 } mDNS_DirectOP_QueryRecord
;
146 int DNSServiceRefSockFD(DNSServiceRef sdRef
)
148 (void)sdRef
; // Unused
152 DNSServiceErrorType
DNSServiceProcessResult(DNSServiceRef sdRef
)
154 (void)sdRef
; // Unused
155 return(kDNSServiceErr_NoError
);
158 void DNSServiceRefDeallocate(DNSServiceRef sdRef
)
160 mDNS_DirectOP
*op
= (mDNS_DirectOP
*)sdRef
;
161 //LogMsg("DNSServiceRefDeallocate");
165 //*************************************************************************************************************
166 // Domain Enumeration
168 // Not yet implemented, so don't include in stub library
169 // We DO include it in the actual Extension, so that if a later client compiled to use this
170 // is run against this Extension, it will get a reasonable error code instead of just
171 // failing to launch (Strong Link) or calling an unresolved symbol and crashing (Weak Link)
172 #if !MDNS_BUILDINGSTUBLIBRARY
173 DNSServiceErrorType DNSServiceEnumerateDomains
175 DNSServiceRef
*sdRef
,
176 DNSServiceFlags flags
,
177 uint32_t interfaceIndex
,
178 DNSServiceDomainEnumReply callback
,
179 void *context
/* may be NULL */
182 (void)sdRef
; // Unused
183 (void)flags
; // Unused
184 (void)interfaceIndex
; // Unused
185 (void)callback
; // Unused
186 (void)context
; // Unused
187 return(kDNSServiceErr_Unsupported
);
191 //*************************************************************************************************************
194 mDNSlocal
void FreeDNSServiceRegistration(mDNS_DirectOP_Register
*x
)
198 ExtraResourceRecord
*extras
= x
->s
.Extras
;
199 x
->s
.Extras
= x
->s
.Extras
->next
;
200 if (extras
->r
.resrec
.rdata
!= &extras
->r
.rdatastorage
)
201 mDNSPlatformMemFree(extras
->r
.resrec
.rdata
);
202 mDNSPlatformMemFree(extras
);
205 if (x
->s
.RR_TXT
.resrec
.rdata
!= &x
->s
.RR_TXT
.rdatastorage
)
206 mDNSPlatformMemFree(x
->s
.RR_TXT
.resrec
.rdata
);
208 if (x
->s
.SubTypes
) mDNSPlatformMemFree(x
->s
.SubTypes
);
210 mDNSPlatformMemFree(x
);
213 static void DNSServiceRegisterDispose(mDNS_DirectOP
*op
)
215 mDNS_DirectOP_Register
*x
= (mDNS_DirectOP_Register
*)op
;
216 x
->autorename
= mDNSfalse
;
217 // If mDNS_DeregisterService() returns mStatus_NoError, that means that the service was found in the list,
218 // is sending its goodbye packet, and we'll get an mStatus_MemFree message when we can free the memory.
219 // If mDNS_DeregisterService() returns an error, it means that the service had already been removed from
220 // the list, so we should go ahead and free the memory right now
221 if (mDNS_DeregisterService(&mDNSStorage
, &x
->s
) != mStatus_NoError
)
222 FreeDNSServiceRegistration(x
);
225 mDNSlocal
void RegCallback(mDNS
*const m
, ServiceRecordSet
*const sr
, mStatus result
)
227 mDNS_DirectOP_Register
*x
= (mDNS_DirectOP_Register
*)sr
->ServiceContext
;
230 domainname type
, dom
;
231 char namestr
[MAX_DOMAIN_LABEL
+1]; // Unescaped name: up to 63 bytes plus C-string terminating NULL.
232 char typestr
[MAX_ESCAPED_DOMAIN_NAME
];
233 char domstr
[MAX_ESCAPED_DOMAIN_NAME
];
234 if (!DeconstructServiceName(sr
->RR_SRV
.resrec
.name
, &name
, &type
, &dom
)) return;
235 if (!ConvertDomainLabelToCString_unescaped(&name
, namestr
)) return;
236 if (!ConvertDomainNameToCString(&type
, typestr
)) return;
237 if (!ConvertDomainNameToCString(&dom
, domstr
)) return;
239 if (result
== mStatus_NoError
)
242 x
->callback((DNSServiceRef
)x
, 0, result
, namestr
, typestr
, domstr
, x
->context
);
244 else if (result
== mStatus_NameConflict
)
246 if (x
->autoname
) mDNS_RenameAndReregisterService(m
, sr
, mDNSNULL
);
247 else if (x
->callback
)
248 x
->callback((DNSServiceRef
)x
, 0, result
, namestr
, typestr
, domstr
, x
->context
);
250 else if (result
== mStatus_MemFree
)
254 x
->autorename
= mDNSfalse
;
255 x
->name
= mDNSStorage
.nicelabel
;
256 mDNS_RenameAndReregisterService(m
, &x
->s
, &x
->name
);
259 FreeDNSServiceRegistration(x
);
263 DNSServiceErrorType DNSServiceRegister
265 DNSServiceRef
*sdRef
,
266 DNSServiceFlags flags
,
267 uint32_t interfaceIndex
,
268 const char *name
, /* may be NULL */
270 const char *domain
, /* may be NULL */
271 const char *host
, /* may be NULL */
272 uint16_t notAnIntPort
,
274 const void *txtRecord
, /* may be NULL */
275 DNSServiceRegisterReply callback
, /* may be NULL */
276 void *context
/* may be NULL */
279 mStatus err
= mStatus_NoError
;
280 const char *errormsg
= "Unknown";
282 domainname t
, d
, h
, srv
;
284 unsigned int size
= sizeof(RDataBody
);
285 AuthRecord
*SubTypes
= mDNSNULL
;
286 mDNSu32 NumSubTypes
= 0;
287 mDNS_DirectOP_Register
*x
;
288 (void)flags
; // Unused
289 (void)interfaceIndex
; // Unused
292 if (!name
) name
= "";
293 if (!name
[0]) n
= mDNSStorage
.nicelabel
;
294 else if (!MakeDomainLabelFromLiteralString(&n
, name
)) { errormsg
= "Bad Instance Name"; goto badparam
; }
295 if (!regtype
|| !*regtype
|| !MakeDomainNameFromDNSNameString(&t
, regtype
)) { errormsg
= "Bad Service Type"; goto badparam
; }
296 if (!MakeDomainNameFromDNSNameString(&d
, (domain
&& *domain
) ? domain
: "local.")) { errormsg
= "Bad Domain"; goto badparam
; }
297 if (!MakeDomainNameFromDNSNameString(&h
, (host
&& *host
) ? host
: "")) { errormsg
= "Bad Target Host"; goto badparam
; }
298 if (!ConstructServiceName(&srv
, &n
, &t
, &d
)) { errormsg
= "Bad Name"; goto badparam
; }
299 port
.NotAnInteger
= notAnIntPort
;
301 // Allocate memory, and handle failure
304 x
= (mDNS_DirectOP_Register
*)mDNSPlatformMemAllocate(sizeof(*x
) - sizeof(RDataBody
) + size
);
305 if (!x
) { err
= mStatus_NoMemoryErr
; errormsg
= "No memory"; goto fail
; }
308 x
->disposefn
= DNSServiceRegisterDispose
;
309 x
->callback
= callback
;
310 x
->context
= context
;
311 x
->autoname
= (!name
[0]);
312 x
->autorename
= mDNSfalse
;
317 err
= mDNS_RegisterService(&mDNSStorage
, &x
->s
,
318 &x
->name
, &t
, &d
, // Name, type, domain
319 &x
->host
, port
, // Host and port
320 txtRecord
, txtLen
, // TXT data, length
321 SubTypes
, NumSubTypes
, // Subtypes
322 mDNSInterface_Any
, // Interface ID
323 RegCallback
, x
); // Callback and context
324 if (err
) { mDNSPlatformMemFree(x
); errormsg
= "mDNS_RegisterService"; goto fail
; }
326 // Succeeded: Wrap up and return
327 *sdRef
= (DNSServiceRef
)x
;
328 return(mStatus_NoError
);
331 err
= mStatus_BadParamErr
;
333 LogMsg("DNSServiceBrowse(\"%s\", \"%s\") failed: %s (%ld)", regtype
, domain
, errormsg
, err
);
337 //*************************************************************************************************************
338 // Add / Update / Remove records from existing Registration
340 // Not yet implemented, so don't include in stub library
341 // We DO include it in the actual Extension, so that if a later client compiled to use this
342 // is run against this Extension, it will get a reasonable error code instead of just
343 // failing to launch (Strong Link) or calling an unresolved symbol and crashing (Weak Link)
344 #if !MDNS_BUILDINGSTUBLIBRARY
345 DNSServiceErrorType DNSServiceAddRecord
348 DNSRecordRef
*RecordRef
,
349 DNSServiceFlags flags
,
356 (void)sdRef
; // Unused
357 (void)RecordRef
; // Unused
358 (void)flags
; // Unused
359 (void)rrtype
; // Unused
360 (void)rdlen
; // Unused
361 (void)rdata
; // Unused
363 return(kDNSServiceErr_Unsupported
);
366 DNSServiceErrorType DNSServiceUpdateRecord
369 DNSRecordRef RecordRef
, /* may be NULL */
370 DNSServiceFlags flags
,
376 (void)sdRef
; // Unused
377 (void)RecordRef
; // Unused
378 (void)flags
; // Unused
379 (void)rdlen
; // Unused
380 (void)rdata
; // Unused
382 return(kDNSServiceErr_Unsupported
);
385 DNSServiceErrorType DNSServiceRemoveRecord
388 DNSRecordRef RecordRef
,
389 DNSServiceFlags flags
392 (void)sdRef
; // Unused
393 (void)RecordRef
; // Unused
394 (void)flags
; // Unused
395 return(kDNSServiceErr_Unsupported
);
399 //*************************************************************************************************************
400 // Browse for services
402 static void DNSServiceBrowseDispose(mDNS_DirectOP
*op
)
404 mDNS_DirectOP_Browse
*x
= (mDNS_DirectOP_Browse
*)op
;
405 //LogMsg("DNSServiceBrowseDispose");
406 mDNS_StopBrowse(&mDNSStorage
, &x
->q
);
407 mDNSPlatformMemFree(x
);
410 mDNSlocal
void FoundInstance(mDNS
*const m
, DNSQuestion
*question
, const ResourceRecord
*const answer
, QC_result AddRecord
)
412 DNSServiceFlags flags
= AddRecord
? kDNSServiceFlagsAdd
: (DNSServiceFlags
)0;
414 domainname type
, domain
;
415 char cname
[MAX_DOMAIN_LABEL
+1]; // Unescaped name: up to 63 bytes plus C-string terminating NULL.
416 char ctype
[MAX_ESCAPED_DOMAIN_NAME
];
417 char cdom
[MAX_ESCAPED_DOMAIN_NAME
];
418 mDNS_DirectOP_Browse
*x
= (mDNS_DirectOP_Browse
*)question
->QuestionContext
;
421 if (answer
->rrtype
!= kDNSType_PTR
)
422 { LogMsg("FoundInstance: Should not be called with rrtype %d (not a PTR record)", answer
->rrtype
); return; }
424 if (!DeconstructServiceName(&answer
->rdata
->u
.name
, &name
, &type
, &domain
))
426 LogMsg("FoundInstance: %##s PTR %##s received from network is not valid DNS-SD service pointer",
427 answer
->name
->c
, answer
->rdata
->u
.name
.c
);
431 ConvertDomainLabelToCString_unescaped(&name
, cname
);
432 ConvertDomainNameToCString(&type
, ctype
);
433 ConvertDomainNameToCString(&domain
, cdom
);
435 x
->callback((DNSServiceRef
)x
, flags
, 0, 0, cname
, ctype
, cdom
, x
->context
);
438 DNSServiceErrorType DNSServiceBrowse
440 DNSServiceRef
*sdRef
,
441 DNSServiceFlags flags
,
442 uint32_t interfaceIndex
,
444 const char *domain
, /* may be NULL */
445 DNSServiceBrowseReply callback
,
446 void *context
/* may be NULL */
449 mStatus err
= mStatus_NoError
;
450 const char *errormsg
= "Unknown";
452 mDNS_DirectOP_Browse
*x
;
453 (void)flags
; // Unused
454 (void)interfaceIndex
; // Unused
457 if (!regtype
[0] || !MakeDomainNameFromDNSNameString(&t
, regtype
)) { errormsg
= "Illegal regtype"; goto badparam
; }
458 if (!MakeDomainNameFromDNSNameString(&d
, *domain
? domain
: "local.")) { errormsg
= "Illegal domain"; goto badparam
; }
460 // Allocate memory, and handle failure
461 x
= (mDNS_DirectOP_Browse
*)mDNSPlatformMemAllocate(sizeof(*x
));
462 if (!x
) { err
= mStatus_NoMemoryErr
; errormsg
= "No memory"; goto fail
; }
465 x
->disposefn
= DNSServiceBrowseDispose
;
466 x
->callback
= callback
;
467 x
->context
= context
;
468 x
->q
.QuestionContext
= x
;
471 err
= mDNS_StartBrowse(&mDNSStorage
, &x
->q
, &t
, &d
, mDNSInterface_Any
, (flags
& kDNSServiceFlagsForceMulticast
) != 0, FoundInstance
, x
);
472 if (err
) { mDNSPlatformMemFree(x
); errormsg
= "mDNS_StartBrowse"; goto fail
; }
474 // Succeeded: Wrap up and return
475 *sdRef
= (DNSServiceRef
)x
;
476 return(mStatus_NoError
);
479 err
= mStatus_BadParamErr
;
481 LogMsg("DNSServiceBrowse(\"%s\", \"%s\") failed: %s (%ld)", regtype
, domain
, errormsg
, err
);
485 //*************************************************************************************************************
486 // Resolve Service Info
488 static void DNSServiceResolveDispose(mDNS_DirectOP
*op
)
490 mDNS_DirectOP_Resolve
*x
= (mDNS_DirectOP_Resolve
*)op
;
491 if (x
->qSRV
.ThisQInterval
>= 0) mDNS_StopQuery(&mDNSStorage
, &x
->qSRV
);
492 if (x
->qTXT
.ThisQInterval
>= 0) mDNS_StopQuery(&mDNSStorage
, &x
->qTXT
);
493 mDNSPlatformMemFree(x
);
496 mDNSlocal
void FoundServiceInfo(mDNS
*const m
, DNSQuestion
*question
, const ResourceRecord
*const answer
, QC_result AddRecord
)
498 mDNS_DirectOP_Resolve
*x
= (mDNS_DirectOP_Resolve
*)question
->QuestionContext
;
502 if (answer
->rrtype
== kDNSType_SRV
&& x
->SRV
== answer
) x
->SRV
= mDNSNULL
;
503 if (answer
->rrtype
== kDNSType_TXT
&& x
->TXT
== answer
) x
->TXT
= mDNSNULL
;
507 if (answer
->rrtype
== kDNSType_SRV
) x
->SRV
= answer
;
508 if (answer
->rrtype
== kDNSType_TXT
) x
->TXT
= answer
;
509 if (x
->SRV
&& x
->TXT
&& x
->callback
)
511 char fullname
[MAX_ESCAPED_DOMAIN_NAME
], targethost
[MAX_ESCAPED_DOMAIN_NAME
];
512 ConvertDomainNameToCString(answer
->name
, fullname
);
513 ConvertDomainNameToCString(&x
->SRV
->rdata
->u
.srv
.target
, targethost
);
514 x
->callback((DNSServiceRef
)x
, 0, 0, kDNSServiceErr_NoError
, fullname
, targethost
,
515 x
->SRV
->rdata
->u
.srv
.port
.NotAnInteger
, x
->TXT
->rdlength
, (unsigned char*)x
->TXT
->rdata
->u
.txt
.c
, x
->context
);
520 DNSServiceErrorType DNSServiceResolve
522 DNSServiceRef
*sdRef
,
523 DNSServiceFlags flags
,
524 uint32_t interfaceIndex
,
528 DNSServiceResolveReply callback
,
529 void *context
/* may be NULL */
532 mStatus err
= mStatus_NoError
;
533 const char *errormsg
= "Unknown";
535 domainname t
, d
, srv
;
536 mDNS_DirectOP_Resolve
*x
;
538 (void)flags
; // Unused
539 (void)interfaceIndex
; // Unused
542 if (!name
[0] || !MakeDomainLabelFromLiteralString(&n
, name
)) { errormsg
= "Bad Instance Name"; goto badparam
; }
543 if (!regtype
[0] || !MakeDomainNameFromDNSNameString(&t
, regtype
)) { errormsg
= "Bad Service Type"; goto badparam
; }
544 if (!domain
[0] || !MakeDomainNameFromDNSNameString(&d
, domain
)) { errormsg
= "Bad Domain"; goto badparam
; }
545 if (!ConstructServiceName(&srv
, &n
, &t
, &d
)) { errormsg
= "Bad Name"; goto badparam
; }
547 // Allocate memory, and handle failure
548 x
= (mDNS_DirectOP_Resolve
*)mDNSPlatformMemAllocate(sizeof(*x
));
549 if (!x
) { err
= mStatus_NoMemoryErr
; errormsg
= "No memory"; goto fail
; }
552 x
->disposefn
= DNSServiceResolveDispose
;
553 x
->callback
= callback
;
554 x
->context
= context
;
558 x
->qSRV
.ThisQInterval
= -1; // So that DNSServiceResolveDispose() knows whether to cancel this question
559 x
->qSRV
.InterfaceID
= mDNSInterface_Any
;
560 x
->qSRV
.Target
= zeroAddr
;
561 AssignDomainName(&x
->qSRV
.qname
, &srv
);
562 x
->qSRV
.qtype
= kDNSType_SRV
;
563 x
->qSRV
.qclass
= kDNSClass_IN
;
564 x
->qSRV
.LongLived
= mDNSfalse
;
565 x
->qSRV
.ExpectUnique
= mDNStrue
;
566 x
->qSRV
.ForceMCast
= mDNSfalse
;
567 x
->qSRV
.ReturnIntermed
= mDNSfalse
;
568 x
->qSRV
.QuestionCallback
= FoundServiceInfo
;
569 x
->qSRV
.QuestionContext
= x
;
571 x
->qTXT
.ThisQInterval
= -1; // So that DNSServiceResolveDispose() knows whether to cancel this question
572 x
->qTXT
.InterfaceID
= mDNSInterface_Any
;
573 x
->qTXT
.Target
= zeroAddr
;
574 AssignDomainName(&x
->qTXT
.qname
, &srv
);
575 x
->qTXT
.qtype
= kDNSType_TXT
;
576 x
->qTXT
.qclass
= kDNSClass_IN
;
577 x
->qTXT
.LongLived
= mDNSfalse
;
578 x
->qTXT
.ExpectUnique
= mDNStrue
;
579 x
->qTXT
.ForceMCast
= mDNSfalse
;
580 x
->qTXT
.ReturnIntermed
= mDNSfalse
;
581 x
->qTXT
.QuestionCallback
= FoundServiceInfo
;
582 x
->qTXT
.QuestionContext
= x
;
584 err
= mDNS_StartQuery(&mDNSStorage
, &x
->qSRV
);
585 if (err
) { DNSServiceResolveDispose((mDNS_DirectOP
*)x
); errormsg
= "mDNS_StartQuery qSRV"; goto fail
; }
586 err
= mDNS_StartQuery(&mDNSStorage
, &x
->qTXT
);
587 if (err
) { DNSServiceResolveDispose((mDNS_DirectOP
*)x
); errormsg
= "mDNS_StartQuery qTXT"; goto fail
; }
589 // Succeeded: Wrap up and return
590 *sdRef
= (DNSServiceRef
)x
;
591 return(mStatus_NoError
);
594 err
= mStatus_BadParamErr
;
596 LogMsg("DNSServiceResolve(\"%s\", \"%s\", \"%s\") failed: %s (%ld)", name
, regtype
, domain
, errormsg
, err
);
600 //*************************************************************************************************************
601 // Connection-oriented calls
603 // Not yet implemented, so don't include in stub library
604 // We DO include it in the actual Extension, so that if a later client compiled to use this
605 // is run against this Extension, it will get a reasonable error code instead of just
606 // failing to launch (Strong Link) or calling an unresolved symbol and crashing (Weak Link)
607 #if !MDNS_BUILDINGSTUBLIBRARY
608 DNSServiceErrorType
DNSServiceCreateConnection(DNSServiceRef
*sdRef
)
610 (void)sdRef
; // Unused
611 return(kDNSServiceErr_Unsupported
);
614 DNSServiceErrorType DNSServiceRegisterRecord
617 DNSRecordRef
*RecordRef
,
618 DNSServiceFlags flags
,
619 uint32_t interfaceIndex
,
620 const char *fullname
,
626 DNSServiceRegisterRecordReply callback
,
627 void *context
/* may be NULL */
630 (void)sdRef
; // Unused
631 (void)RecordRef
; // Unused
632 (void)flags
; // Unused
633 (void)interfaceIndex
; // Unused
634 (void)fullname
; // Unused
635 (void)rrtype
; // Unused
636 (void)rrclass
; // Unused
637 (void)rdlen
; // Unused
638 (void)rdata
; // Unused
640 (void)callback
; // Unused
641 (void)context
; // Unused
642 return(kDNSServiceErr_Unsupported
);
646 //*************************************************************************************************************
647 // DNSServiceQueryRecord
649 static void DNSServiceQueryRecordDispose(mDNS_DirectOP
*op
)
651 mDNS_DirectOP_QueryRecord
*x
= (mDNS_DirectOP_QueryRecord
*)op
;
652 if (x
->q
.ThisQInterval
>= 0) mDNS_StopQuery(&mDNSStorage
, &x
->q
);
653 mDNSPlatformMemFree(x
);
656 mDNSlocal
void DNSServiceQueryRecordResponse(mDNS
*const m
, DNSQuestion
*question
, const ResourceRecord
*const answer
, QC_result AddRecord
)
658 mDNS_DirectOP_QueryRecord
*x
= (mDNS_DirectOP_QueryRecord
*)question
->QuestionContext
;
659 char fullname
[MAX_ESCAPED_DOMAIN_NAME
];
661 ConvertDomainNameToCString(answer
->name
, fullname
);
662 x
->callback((DNSServiceRef
)x
, AddRecord
? kDNSServiceFlagsAdd
: (DNSServiceFlags
)0, 0, kDNSServiceErr_NoError
,
663 fullname
, answer
->rrtype
, answer
->rrclass
, answer
->rdlength
, answer
->rdata
->u
.data
, answer
->rroriginalttl
, x
->context
);
666 DNSServiceErrorType DNSServiceQueryRecord
668 DNSServiceRef
*sdRef
,
669 DNSServiceFlags flags
,
670 uint32_t interfaceIndex
,
671 const char *fullname
,
674 DNSServiceQueryRecordReply callback
,
675 void *context
/* may be NULL */
678 mStatus err
= mStatus_NoError
;
679 const char *errormsg
= "Unknown";
680 mDNS_DirectOP_QueryRecord
*x
;
682 (void)flags
; // Unused
683 (void)interfaceIndex
; // Unused
685 // Allocate memory, and handle failure
686 x
= (mDNS_DirectOP_QueryRecord
*)mDNSPlatformMemAllocate(sizeof(*x
));
687 if (!x
) { err
= mStatus_NoMemoryErr
; errormsg
= "No memory"; goto fail
; }
690 x
->disposefn
= DNSServiceQueryRecordDispose
;
691 x
->callback
= callback
;
692 x
->context
= context
;
694 x
->q
.ThisQInterval
= -1; // So that DNSServiceResolveDispose() knows whether to cancel this question
695 x
->q
.InterfaceID
= mDNSInterface_Any
;
696 x
->q
.Target
= zeroAddr
;
697 MakeDomainNameFromDNSNameString(&x
->q
.qname
, fullname
);
699 x
->q
.qclass
= rrclass
;
700 x
->q
.LongLived
= (flags
& kDNSServiceFlagsLongLivedQuery
) != 0;
701 x
->q
.ExpectUnique
= mDNSfalse
;
702 x
->q
.ForceMCast
= (flags
& kDNSServiceFlagsForceMulticast
) != 0;
703 x
->q
.ReturnIntermed
= (flags
& kDNSServiceFlagsReturnIntermediates
) != 0;
704 x
->q
.QuestionCallback
= DNSServiceQueryRecordResponse
;
705 x
->q
.QuestionContext
= x
;
707 err
= mDNS_StartQuery(&mDNSStorage
, &x
->q
);
708 if (err
) { DNSServiceResolveDispose((mDNS_DirectOP
*)x
); errormsg
= "mDNS_StartQuery"; goto fail
; }
710 // Succeeded: Wrap up and return
711 *sdRef
= (DNSServiceRef
)x
;
712 return(mStatus_NoError
);
715 err
= mStatus_BadParamErr
;
717 LogMsg("DNSServiceQueryRecord(\"%s\", %d, %d) failed: %s (%ld)", fullname
, rrtype
, rrclass
, errormsg
, err
);
721 //*************************************************************************************************************
722 // DNSServiceReconfirmRecord
724 // Not yet implemented, so don't include in stub library
725 // We DO include it in the actual Extension, so that if a later client compiled to use this
726 // is run against this Extension, it will get a reasonable error code instead of just
727 // failing to launch (Strong Link) or calling an unresolved symbol and crashing (Weak Link)
728 #if !MDNS_BUILDINGSTUBLIBRARY
729 DNSServiceErrorType DNSSD_API DNSServiceReconfirmRecord
731 DNSServiceFlags flags
,
732 uint32_t interfaceIndex
,
733 const char *fullname
,
740 (void)flags
; // Unused
741 (void)interfaceIndex
; // Unused
742 (void)fullname
; // Unused
743 (void)rrtype
; // Unused
744 (void)rrclass
; // Unused
745 (void)rdlen
; // Unused
746 (void)rdata
; // Unused
747 return(kDNSServiceErr_Unsupported
);