]> git.saurik.com Git - apple/mdnsresponder.git/blob - mDNSShared/dnssd_clientshim.c
mDNSResponder-214.3.2.tar.gz
[apple/mdnsresponder.git] / mDNSShared / dnssd_clientshim.c
1 /* -*- Mode: C; tab-width: 4 -*-
2 *
3 * Copyright (c) 2003 Apple Computer, Inc. All rights reserved.
4 *
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
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
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.
16
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.
24
25 Change History (most recent first):
26
27 $Log: dnssd_clientshim.c,v $
28 Revision 1.16 2007/11/30 20:12:24 cheshire
29 Removed unused "badparam:" label
30
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
34
35 Revision 1.14 2007/07/17 19:15:26 cheshire
36 <rdar://problem/5297410> Crash in DNSServiceRegister() in dnssd_clientshim.c
37
38 Revision 1.13 2007/01/04 20:57:49 cheshire
39 Rename ReturnCNAME to ReturnIntermed (for ReturnIntermediates)
40
41 Revision 1.12 2006/12/19 22:43:55 cheshire
42 Fix compiler warnings
43
44 Revision 1.11 2006/10/27 01:30:23 cheshire
45 Need explicitly to set ReturnIntermed = mDNSfalse
46
47 Revision 1.10 2006/08/14 23:24:56 cheshire
48 Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
49
50 Revision 1.9 2006/07/24 23:45:55 cheshire
51 <rdar://problem/4605276> DNSServiceReconfirmRecord() should return error code
52
53 Revision 1.8 2004/12/16 20:47:34 cheshire
54 <rdar://problem/3324626> Cache memory management improvements
55
56 Revision 1.7 2004/12/10 04:08:43 cheshire
57 Added comments about autoname and autorename
58
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
63
64 Revision 1.5 2004/09/21 23:29:51 cheshire
65 <rdar://problem/3680045> DNSServiceResolve should delay sending packets
66
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.
72
73 Revision 1.3 2004/05/27 06:26:31 cheshire
74 Add shim for DNSServiceQueryRecord()
75
76 Revision 1.2 2004/05/20 18:41:24 cheshire
77 Fix build broken by removal of 'kDNSServiceFlagsRemove' from dns_sd.h
78
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.
82
83 */
84
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
88
89 #if MDNS_BUILDINGSHAREDLIBRARY || MDNS_BUILDINGSTUBLIBRARY
90 #pragma export on
91 #endif
92
93 //*************************************************************************************************************
94 // General Utility Functions
95
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
102
103 typedef struct mDNS_DirectOP_struct mDNS_DirectOP;
104 typedef void mDNS_DirectOP_Dispose(mDNS_DirectOP *op);
105 struct mDNS_DirectOP_struct
106 {
107 mDNS_DirectOP_Dispose *disposefn;
108 };
109
110 typedef struct
111 {
112 mDNS_DirectOP_Dispose *disposefn;
113 DNSServiceRegisterReply callback;
114 void *context;
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
117 domainlabel name;
118 domainname host;
119 ServiceRecordSet s;
120 } mDNS_DirectOP_Register;
121
122 typedef struct
123 {
124 mDNS_DirectOP_Dispose *disposefn;
125 DNSServiceBrowseReply callback;
126 void *context;
127 DNSQuestion q;
128 } mDNS_DirectOP_Browse;
129
130 typedef struct
131 {
132 mDNS_DirectOP_Dispose *disposefn;
133 DNSServiceResolveReply callback;
134 void *context;
135 const ResourceRecord *SRV;
136 const ResourceRecord *TXT;
137 DNSQuestion qSRV;
138 DNSQuestion qTXT;
139 } mDNS_DirectOP_Resolve;
140
141 typedef struct
142 {
143 mDNS_DirectOP_Dispose *disposefn;
144 DNSServiceQueryRecordReply callback;
145 void *context;
146 DNSQuestion q;
147 } mDNS_DirectOP_QueryRecord;
148
149 int DNSServiceRefSockFD(DNSServiceRef sdRef)
150 {
151 (void)sdRef; // Unused
152 return(0);
153 }
154
155 DNSServiceErrorType DNSServiceProcessResult(DNSServiceRef sdRef)
156 {
157 (void)sdRef; // Unused
158 return(kDNSServiceErr_NoError);
159 }
160
161 void DNSServiceRefDeallocate(DNSServiceRef sdRef)
162 {
163 mDNS_DirectOP *op = (mDNS_DirectOP *)sdRef;
164 //LogMsg("DNSServiceRefDeallocate");
165 op->disposefn(op);
166 }
167
168 //*************************************************************************************************************
169 // Domain Enumeration
170
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
177 (
178 DNSServiceRef *sdRef,
179 DNSServiceFlags flags,
180 uint32_t interfaceIndex,
181 DNSServiceDomainEnumReply callback,
182 void *context /* may be NULL */
183 )
184 {
185 (void)sdRef; // Unused
186 (void)flags; // Unused
187 (void)interfaceIndex; // Unused
188 (void)callback; // Unused
189 (void)context; // Unused
190 return(kDNSServiceErr_Unsupported);
191 }
192 #endif
193
194 //*************************************************************************************************************
195 // Register Service
196
197 mDNSlocal void FreeDNSServiceRegistration(mDNS_DirectOP_Register *x)
198 {
199 while (x->s.Extras)
200 {
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);
206 }
207
208 if (x->s.RR_TXT.resrec.rdata != &x->s.RR_TXT.rdatastorage)
209 mDNSPlatformMemFree(x->s.RR_TXT.resrec.rdata);
210
211 if (x->s.SubTypes) mDNSPlatformMemFree(x->s.SubTypes);
212
213 mDNSPlatformMemFree(x);
214 }
215
216 static void DNSServiceRegisterDispose(mDNS_DirectOP *op)
217 {
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);
226 }
227
228 mDNSlocal void RegCallback(mDNS *const m, ServiceRecordSet *const sr, mStatus result)
229 {
230 mDNS_DirectOP_Register *x = (mDNS_DirectOP_Register*)sr->ServiceContext;
231
232 domainlabel name;
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;
241
242 if (result == mStatus_NoError)
243 {
244 if (x->callback)
245 x->callback((DNSServiceRef)x, 0, result, namestr, typestr, domstr, x->context);
246 }
247 else if (result == mStatus_NameConflict)
248 {
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);
252 }
253 else if (result == mStatus_MemFree)
254 {
255 if (x->autorename)
256 {
257 x->autorename = mDNSfalse;
258 x->name = mDNSStorage.nicelabel;
259 mDNS_RenameAndReregisterService(m, &x->s, &x->name);
260 }
261 else
262 FreeDNSServiceRegistration(x);
263 }
264 }
265
266 DNSServiceErrorType DNSServiceRegister
267 (
268 DNSServiceRef *sdRef,
269 DNSServiceFlags flags,
270 uint32_t interfaceIndex,
271 const char *name, /* may be NULL */
272 const char *regtype,
273 const char *domain, /* may be NULL */
274 const char *host, /* may be NULL */
275 uint16_t notAnIntPort,
276 uint16_t txtLen,
277 const void *txtRecord, /* may be NULL */
278 DNSServiceRegisterReply callback, /* may be NULL */
279 void *context /* may be NULL */
280 )
281 {
282 mStatus err = mStatus_NoError;
283 const char *errormsg = "Unknown";
284 domainlabel n;
285 domainname t, d, h, srv;
286 mDNSIPPort port;
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
293
294 // Check parameters
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;
303
304 // Allocate memory, and handle failure
305 if (size < txtLen)
306 size = txtLen;
307 x = (mDNS_DirectOP_Register *)mDNSPlatformMemAllocate(sizeof(*x) - sizeof(RDataBody) + size);
308 if (!x) { err = mStatus_NoMemoryErr; errormsg = "No memory"; goto fail; }
309
310 // Set up object
311 x->disposefn = DNSServiceRegisterDispose;
312 x->callback = callback;
313 x->context = context;
314 x->autoname = (!name[0]);
315 x->autorename = mDNSfalse;
316 x->name = n;
317 x->host = h;
318
319 // Do the operation
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; }
328
329 // Succeeded: Wrap up and return
330 *sdRef = (DNSServiceRef)x;
331 return(mStatus_NoError);
332
333 badparam:
334 err = mStatus_BadParamErr;
335 fail:
336 LogMsg("DNSServiceBrowse(\"%s\", \"%s\") failed: %s (%ld)", regtype, domain, errormsg, err);
337 return(err);
338 }
339
340 //*************************************************************************************************************
341 // Add / Update / Remove records from existing Registration
342
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
349 (
350 DNSServiceRef sdRef,
351 DNSRecordRef *RecordRef,
352 DNSServiceFlags flags,
353 uint16_t rrtype,
354 uint16_t rdlen,
355 const void *rdata,
356 uint32_t ttl
357 )
358 {
359 (void)sdRef; // Unused
360 (void)RecordRef; // Unused
361 (void)flags; // Unused
362 (void)rrtype; // Unused
363 (void)rdlen; // Unused
364 (void)rdata; // Unused
365 (void)ttl; // Unused
366 return(kDNSServiceErr_Unsupported);
367 }
368
369 DNSServiceErrorType DNSServiceUpdateRecord
370 (
371 DNSServiceRef sdRef,
372 DNSRecordRef RecordRef, /* may be NULL */
373 DNSServiceFlags flags,
374 uint16_t rdlen,
375 const void *rdata,
376 uint32_t ttl
377 )
378 {
379 (void)sdRef; // Unused
380 (void)RecordRef; // Unused
381 (void)flags; // Unused
382 (void)rdlen; // Unused
383 (void)rdata; // Unused
384 (void)ttl; // Unused
385 return(kDNSServiceErr_Unsupported);
386 }
387
388 DNSServiceErrorType DNSServiceRemoveRecord
389 (
390 DNSServiceRef sdRef,
391 DNSRecordRef RecordRef,
392 DNSServiceFlags flags
393 )
394 {
395 (void)sdRef; // Unused
396 (void)RecordRef; // Unused
397 (void)flags; // Unused
398 return(kDNSServiceErr_Unsupported);
399 }
400 #endif
401
402 //*************************************************************************************************************
403 // Browse for services
404
405 static void DNSServiceBrowseDispose(mDNS_DirectOP *op)
406 {
407 mDNS_DirectOP_Browse *x = (mDNS_DirectOP_Browse*)op;
408 //LogMsg("DNSServiceBrowseDispose");
409 mDNS_StopBrowse(&mDNSStorage, &x->q);
410 mDNSPlatformMemFree(x);
411 }
412
413 mDNSlocal void FoundInstance(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord)
414 {
415 DNSServiceFlags flags = AddRecord ? kDNSServiceFlagsAdd : (DNSServiceFlags)0;
416 domainlabel name;
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;
422 (void)m; // Unused
423
424 if (answer->rrtype != kDNSType_PTR)
425 { LogMsg("FoundInstance: Should not be called with rrtype %d (not a PTR record)", answer->rrtype); return; }
426
427 if (!DeconstructServiceName(&answer->rdata->u.name, &name, &type, &domain))
428 {
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);
431 return;
432 }
433
434 ConvertDomainLabelToCString_unescaped(&name, cname);
435 ConvertDomainNameToCString(&type, ctype);
436 ConvertDomainNameToCString(&domain, cdom);
437 if (x->callback)
438 x->callback((DNSServiceRef)x, flags, 0, 0, cname, ctype, cdom, x->context);
439 }
440
441 DNSServiceErrorType DNSServiceBrowse
442 (
443 DNSServiceRef *sdRef,
444 DNSServiceFlags flags,
445 uint32_t interfaceIndex,
446 const char *regtype,
447 const char *domain, /* may be NULL */
448 DNSServiceBrowseReply callback,
449 void *context /* may be NULL */
450 )
451 {
452 mStatus err = mStatus_NoError;
453 const char *errormsg = "Unknown";
454 domainname t, d;
455 mDNS_DirectOP_Browse *x;
456 (void)flags; // Unused
457 (void)interfaceIndex; // Unused
458
459 // Check parameters
460 if (!regtype[0] || !MakeDomainNameFromDNSNameString(&t, regtype)) { errormsg = "Illegal regtype"; goto badparam; }
461 if (!MakeDomainNameFromDNSNameString(&d, *domain ? domain : "local.")) { errormsg = "Illegal domain"; goto badparam; }
462
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; }
466
467 // Set up object
468 x->disposefn = DNSServiceBrowseDispose;
469 x->callback = callback;
470 x->context = context;
471 x->q.QuestionContext = x;
472
473 // Do the operation
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; }
476
477 // Succeeded: Wrap up and return
478 *sdRef = (DNSServiceRef)x;
479 return(mStatus_NoError);
480
481 badparam:
482 err = mStatus_BadParamErr;
483 fail:
484 LogMsg("DNSServiceBrowse(\"%s\", \"%s\") failed: %s (%ld)", regtype, domain, errormsg, err);
485 return(err);
486 }
487
488 //*************************************************************************************************************
489 // Resolve Service Info
490
491 static void DNSServiceResolveDispose(mDNS_DirectOP *op)
492 {
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);
497 }
498
499 mDNSlocal void FoundServiceInfo(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord)
500 {
501 mDNS_DirectOP_Resolve *x = (mDNS_DirectOP_Resolve*)question->QuestionContext;
502 (void)m; // Unused
503 if (!AddRecord)
504 {
505 if (answer->rrtype == kDNSType_SRV && x->SRV == answer) x->SRV = mDNSNULL;
506 if (answer->rrtype == kDNSType_TXT && x->TXT == answer) x->TXT = mDNSNULL;
507 }
508 else
509 {
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)
513 {
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);
519 }
520 }
521 }
522
523 DNSServiceErrorType DNSServiceResolve
524 (
525 DNSServiceRef *sdRef,
526 DNSServiceFlags flags,
527 uint32_t interfaceIndex,
528 const char *name,
529 const char *regtype,
530 const char *domain,
531 DNSServiceResolveReply callback,
532 void *context /* may be NULL */
533 )
534 {
535 mStatus err = mStatus_NoError;
536 const char *errormsg = "Unknown";
537 domainlabel n;
538 domainname t, d, srv;
539 mDNS_DirectOP_Resolve *x;
540
541 (void)flags; // Unused
542 (void)interfaceIndex; // Unused
543
544 // Check parameters
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; }
549
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; }
553
554 // Set up object
555 x->disposefn = DNSServiceResolveDispose;
556 x->callback = callback;
557 x->context = context;
558 x->SRV = mDNSNULL;
559 x->TXT = mDNSNULL;
560
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;
573
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;
586
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; }
591
592 // Succeeded: Wrap up and return
593 *sdRef = (DNSServiceRef)x;
594 return(mStatus_NoError);
595
596 badparam:
597 err = mStatus_BadParamErr;
598 fail:
599 LogMsg("DNSServiceResolve(\"%s\", \"%s\", \"%s\") failed: %s (%ld)", name, regtype, domain, errormsg, err);
600 return(err);
601 }
602
603 //*************************************************************************************************************
604 // Connection-oriented calls
605
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)
612 {
613 (void)sdRef; // Unused
614 return(kDNSServiceErr_Unsupported);
615 }
616
617 DNSServiceErrorType DNSServiceRegisterRecord
618 (
619 DNSServiceRef sdRef,
620 DNSRecordRef *RecordRef,
621 DNSServiceFlags flags,
622 uint32_t interfaceIndex,
623 const char *fullname,
624 uint16_t rrtype,
625 uint16_t rrclass,
626 uint16_t rdlen,
627 const void *rdata,
628 uint32_t ttl,
629 DNSServiceRegisterRecordReply callback,
630 void *context /* may be NULL */
631 )
632 {
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
642 (void)ttl; // Unused
643 (void)callback; // Unused
644 (void)context; // Unused
645 return(kDNSServiceErr_Unsupported);
646 }
647 #endif
648
649 //*************************************************************************************************************
650 // DNSServiceQueryRecord
651
652 static void DNSServiceQueryRecordDispose(mDNS_DirectOP *op)
653 {
654 mDNS_DirectOP_QueryRecord *x = (mDNS_DirectOP_QueryRecord*)op;
655 if (x->q.ThisQInterval >= 0) mDNS_StopQuery(&mDNSStorage, &x->q);
656 mDNSPlatformMemFree(x);
657 }
658
659 mDNSlocal void DNSServiceQueryRecordResponse(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord)
660 {
661 mDNS_DirectOP_QueryRecord *x = (mDNS_DirectOP_QueryRecord*)question->QuestionContext;
662 char fullname[MAX_ESCAPED_DOMAIN_NAME];
663 (void)m; // Unused
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);
667 }
668
669 DNSServiceErrorType DNSServiceQueryRecord
670 (
671 DNSServiceRef *sdRef,
672 DNSServiceFlags flags,
673 uint32_t interfaceIndex,
674 const char *fullname,
675 uint16_t rrtype,
676 uint16_t rrclass,
677 DNSServiceQueryRecordReply callback,
678 void *context /* may be NULL */
679 )
680 {
681 mStatus err = mStatus_NoError;
682 const char *errormsg = "Unknown";
683 mDNS_DirectOP_QueryRecord *x;
684
685 (void)flags; // Unused
686 (void)interfaceIndex; // Unused
687
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; }
691
692 // Set up object
693 x->disposefn = DNSServiceQueryRecordDispose;
694 x->callback = callback;
695 x->context = context;
696
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);
701 x->q.qtype = rrtype;
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;
709
710 err = mDNS_StartQuery(&mDNSStorage, &x->q);
711 if (err) { DNSServiceResolveDispose((mDNS_DirectOP*)x); errormsg = "mDNS_StartQuery"; goto fail; }
712
713 // Succeeded: Wrap up and return
714 *sdRef = (DNSServiceRef)x;
715 return(mStatus_NoError);
716
717 fail:
718 LogMsg("DNSServiceQueryRecord(\"%s\", %d, %d) failed: %s (%ld)", fullname, rrtype, rrclass, errormsg, err);
719 return(err);
720 }
721
722 //*************************************************************************************************************
723 // DNSServiceReconfirmRecord
724
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
731 (
732 DNSServiceFlags flags,
733 uint32_t interfaceIndex,
734 const char *fullname,
735 uint16_t rrtype,
736 uint16_t rrclass,
737 uint16_t rdlen,
738 const void *rdata
739 )
740 {
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);
749 }
750 #endif