]> git.saurik.com Git - apple/mdnsresponder.git/blame - mDNSShared/dnssd_clientshim.c
mDNSResponder-567.tar.gz
[apple/mdnsresponder.git] / mDNSShared / dnssd_clientshim.c
CommitLineData
67c8f8a1
A
1/* -*- Mode: C; tab-width: 4 -*-
2 *
8e92c31c 3 * Copyright (c) 2003 Apple Computer, Inc. All rights reserved.
83fb1e36 4 *
67c8f8a1
A
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
83fb1e36 8 *
67c8f8a1 9 * http://www.apache.org/licenses/LICENSE-2.0
83fb1e36 10 *
67c8f8a1
A
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
8e92c31c 15 * limitations under the License.
8e92c31c
A
16
17 * This file defines a simple shim layer between a client calling the "/usr/include/dns_sd.h" APIs
7f0064bd
A
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
8e92c31c
A
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.
8e92c31c
A
24 */
25
83fb1e36
A
26#include "dns_sd.h" // Defines the interface to the client layer above
27#include "mDNSEmbeddedAPI.h" // The interface we're building on top of
28extern mDNS mDNSStorage; // We need to pass the address of this storage to the lower-layer functions
8e92c31c
A
29
30#if MDNS_BUILDINGSHAREDLIBRARY || MDNS_BUILDINGSTUBLIBRARY
31#pragma export on
32#endif
33
34//*************************************************************************************************************
35// General Utility Functions
36
37// All mDNS_DirectOP structures start with the pointer to the type-specific disposal function.
38// Optional type-specific data follows these three fields
39// When the client starts an operation, we return the address of the corresponding mDNS_DirectOP
40// as the DNSServiceRef for the operation
41// We stash the value in core context fields so we can get it back to recover our state in our callbacks,
42// and pass it though to the client for it to recover its state
43
44typedef struct mDNS_DirectOP_struct mDNS_DirectOP;
83fb1e36 45typedef void mDNS_DirectOP_Dispose (mDNS_DirectOP *op);
8e92c31c 46struct mDNS_DirectOP_struct
83fb1e36
A
47{
48 mDNS_DirectOP_Dispose *disposefn;
49};
8e92c31c
A
50
51typedef struct
83fb1e36
A
52{
53 mDNS_DirectOP_Dispose *disposefn;
54 DNSServiceRegisterReply callback;
55 void *context;
56 mDNSBool autoname; // Set if this name is tied to the Computer Name
57 mDNSBool autorename; // Set if we just got a name conflict and now need to automatically pick a new name
58 domainlabel name;
59 domainname host;
60 ServiceRecordSet s;
61} mDNS_DirectOP_Register;
8e92c31c
A
62
63typedef struct
83fb1e36
A
64{
65 mDNS_DirectOP_Dispose *disposefn;
66 DNSServiceBrowseReply callback;
67 void *context;
68 DNSQuestion q;
69} mDNS_DirectOP_Browse;
8e92c31c
A
70
71typedef struct
83fb1e36
A
72{
73 mDNS_DirectOP_Dispose *disposefn;
74 DNSServiceResolveReply callback;
75 void *context;
76 const ResourceRecord *SRV;
77 const ResourceRecord *TXT;
78 DNSQuestion qSRV;
79 DNSQuestion qTXT;
80} mDNS_DirectOP_Resolve;
8e92c31c
A
81
82typedef struct
83fb1e36
A
83{
84 mDNS_DirectOP_Dispose *disposefn;
85 DNSServiceQueryRecordReply callback;
86 void *context;
87 DNSQuestion q;
88} mDNS_DirectOP_QueryRecord;
8e92c31c
A
89
90int DNSServiceRefSockFD(DNSServiceRef sdRef)
83fb1e36
A
91{
92 (void)sdRef; // Unused
93 return(0);
94}
8e92c31c
A
95
96DNSServiceErrorType DNSServiceProcessResult(DNSServiceRef sdRef)
83fb1e36
A
97{
98 (void)sdRef; // Unused
99 return(kDNSServiceErr_NoError);
100}
8e92c31c
A
101
102void DNSServiceRefDeallocate(DNSServiceRef sdRef)
83fb1e36
A
103{
104 mDNS_DirectOP *op = (mDNS_DirectOP *)sdRef;
105 //LogMsg("DNSServiceRefDeallocate");
106 op->disposefn(op);
107}
8e92c31c
A
108
109//*************************************************************************************************************
110// Domain Enumeration
111
112// Not yet implemented, so don't include in stub library
113// We DO include it in the actual Extension, so that if a later client compiled to use this
114// is run against this Extension, it will get a reasonable error code instead of just
115// failing to launch (Strong Link) or calling an unresolved symbol and crashing (Weak Link)
116#if !MDNS_BUILDINGSTUBLIBRARY
117DNSServiceErrorType DNSServiceEnumerateDomains
83fb1e36
A
118(
119 DNSServiceRef *sdRef,
120 DNSServiceFlags flags,
121 uint32_t interfaceIndex,
122 DNSServiceDomainEnumReply callback,
123 void *context /* may be NULL */
124)
125{
126 (void)sdRef; // Unused
127 (void)flags; // Unused
128 (void)interfaceIndex; // Unused
129 (void)callback; // Unused
130 (void)context; // Unused
131 return(kDNSServiceErr_Unsupported);
132}
8e92c31c
A
133#endif
134
135//*************************************************************************************************************
136// Register Service
137
138mDNSlocal void FreeDNSServiceRegistration(mDNS_DirectOP_Register *x)
83fb1e36
A
139{
140 while (x->s.Extras)
141 {
142 ExtraResourceRecord *extras = x->s.Extras;
143 x->s.Extras = x->s.Extras->next;
144 if (extras->r.resrec.rdata != &extras->r.rdatastorage)
145 mDNSPlatformMemFree(extras->r.resrec.rdata);
146 mDNSPlatformMemFree(extras);
147 }
148
149 if (x->s.RR_TXT.resrec.rdata != &x->s.RR_TXT.rdatastorage)
150 mDNSPlatformMemFree(x->s.RR_TXT.resrec.rdata);
151
152 if (x->s.SubTypes) mDNSPlatformMemFree(x->s.SubTypes);
153
154 mDNSPlatformMemFree(x);
155}
8e92c31c
A
156
157static void DNSServiceRegisterDispose(mDNS_DirectOP *op)
83fb1e36
A
158{
159 mDNS_DirectOP_Register *x = (mDNS_DirectOP_Register*)op;
160 x->autorename = mDNSfalse;
161 // If mDNS_DeregisterService() returns mStatus_NoError, that means that the service was found in the list,
162 // is sending its goodbye packet, and we'll get an mStatus_MemFree message when we can free the memory.
163 // If mDNS_DeregisterService() returns an error, it means that the service had already been removed from
164 // the list, so we should go ahead and free the memory right now
165 if (mDNS_DeregisterService(&mDNSStorage, &x->s) != mStatus_NoError)
166 FreeDNSServiceRegistration(x);
167}
8e92c31c
A
168
169mDNSlocal void RegCallback(mDNS *const m, ServiceRecordSet *const sr, mStatus result)
83fb1e36
A
170{
171 mDNS_DirectOP_Register *x = (mDNS_DirectOP_Register*)sr->ServiceContext;
8e92c31c
A
172
173 domainlabel name;
174 domainname type, dom;
83fb1e36
A
175 char namestr[MAX_DOMAIN_LABEL+1]; // Unescaped name: up to 63 bytes plus C-string terminating NULL.
176 char typestr[MAX_ESCAPED_DOMAIN_NAME];
177 char domstr [MAX_ESCAPED_DOMAIN_NAME];
283ee3ff 178 if (!DeconstructServiceName(sr->RR_SRV.resrec.name, &name, &type, &dom)) return;
8e92c31c
A
179 if (!ConvertDomainLabelToCString_unescaped(&name, namestr)) return;
180 if (!ConvertDomainNameToCString(&type, typestr)) return;
181 if (!ConvertDomainNameToCString(&dom, domstr)) return;
182
83fb1e36
A
183 if (result == mStatus_NoError)
184 {
185 if (x->callback)
186 x->callback((DNSServiceRef)x, 0, result, namestr, typestr, domstr, x->context);
187 }
188 else if (result == mStatus_NameConflict)
189 {
190 if (x->autoname) mDNS_RenameAndReregisterService(m, sr, mDNSNULL);
191 else if (x->callback)
192 x->callback((DNSServiceRef)x, 0, result, namestr, typestr, domstr, x->context);
193 }
194 else if (result == mStatus_MemFree)
195 {
196 if (x->autorename)
197 {
198 x->autorename = mDNSfalse;
199 x->name = mDNSStorage.nicelabel;
200 mDNS_RenameAndReregisterService(m, &x->s, &x->name);
201 }
202 else
203 FreeDNSServiceRegistration(x);
204 }
205}
8e92c31c
A
206
207DNSServiceErrorType DNSServiceRegister
83fb1e36
A
208(
209 DNSServiceRef *sdRef,
210 DNSServiceFlags flags,
211 uint32_t interfaceIndex,
212 const char *name, /* may be NULL */
213 const char *regtype,
214 const char *domain, /* may be NULL */
215 const char *host, /* may be NULL */
216 uint16_t notAnIntPort,
217 uint16_t txtLen,
218 const void *txtRecord, /* may be NULL */
219 DNSServiceRegisterReply callback, /* may be NULL */
220 void *context /* may be NULL */
221)
222{
223 mStatus err = mStatus_NoError;
224 const char *errormsg = "Unknown";
225 domainlabel n;
226 domainname t, d, h, srv;
227 mDNSIPPort port;
228 unsigned int size = sizeof(RDataBody);
229 AuthRecord *SubTypes = mDNSNULL;
230 mDNSu32 NumSubTypes = 0;
231 mDNS_DirectOP_Register *x;
232 (void)flags; // Unused
233 (void)interfaceIndex; // Unused
234
235 // Check parameters
236 if (!name) name = "";
237 if (!name[0]) n = mDNSStorage.nicelabel;
238 else if (!MakeDomainLabelFromLiteralString(&n, name)) { errormsg = "Bad Instance Name"; goto badparam; }
239 if (!regtype || !*regtype || !MakeDomainNameFromDNSNameString(&t, regtype)) { errormsg = "Bad Service Type"; goto badparam; }
240 if (!MakeDomainNameFromDNSNameString(&d, (domain && *domain) ? domain : "local.")) { errormsg = "Bad Domain"; goto badparam; }
241 if (!MakeDomainNameFromDNSNameString(&h, (host && *host ) ? host : "")) { errormsg = "Bad Target Host"; goto badparam; }
242 if (!ConstructServiceName(&srv, &n, &t, &d)) { errormsg = "Bad Name"; goto badparam; }
243 port.NotAnInteger = notAnIntPort;
244
245 // Allocate memory, and handle failure
246 if (size < txtLen)
247 size = txtLen;
248 x = (mDNS_DirectOP_Register *)mDNSPlatformMemAllocate(sizeof(*x) - sizeof(RDataBody) + size);
249 if (!x) { err = mStatus_NoMemoryErr; errormsg = "No memory"; goto fail; }
250
251 // Set up object
252 x->disposefn = DNSServiceRegisterDispose;
253 x->callback = callback;
254 x->context = context;
255 x->autoname = (!name[0]);
256 x->autorename = mDNSfalse;
257 x->name = n;
258 x->host = h;
259
260 // Do the operation
261 err = mDNS_RegisterService(&mDNSStorage, &x->s,
262 &x->name, &t, &d, // Name, type, domain
263 &x->host, port, // Host and port
264 txtRecord, txtLen, // TXT data, length
265 SubTypes, NumSubTypes, // Subtypes
266 mDNSInterface_Any, // Interface ID
267 RegCallback, x, 0); // Callback, context, flags
268 if (err) { mDNSPlatformMemFree(x); errormsg = "mDNS_RegisterService"; goto fail; }
269
270 // Succeeded: Wrap up and return
271 *sdRef = (DNSServiceRef)x;
272 return(mStatus_NoError);
8e92c31c
A
273
274badparam:
83fb1e36 275 err = mStatus_BadParamErr;
8e92c31c 276fail:
83fb1e36
A
277 LogMsg("DNSServiceBrowse(\"%s\", \"%s\") failed: %s (%ld)", regtype, domain, errormsg, err);
278 return(err);
279}
8e92c31c
A
280
281//*************************************************************************************************************
282// Add / Update / Remove records from existing Registration
283
284// Not yet implemented, so don't include in stub library
285// We DO include it in the actual Extension, so that if a later client compiled to use this
286// is run against this Extension, it will get a reasonable error code instead of just
287// failing to launch (Strong Link) or calling an unresolved symbol and crashing (Weak Link)
288#if !MDNS_BUILDINGSTUBLIBRARY
289DNSServiceErrorType DNSServiceAddRecord
83fb1e36
A
290(
291 DNSServiceRef sdRef,
292 DNSRecordRef *RecordRef,
293 DNSServiceFlags flags,
294 uint16_t rrtype,
295 uint16_t rdlen,
296 const void *rdata,
297 uint32_t ttl
298)
299{
300 (void)sdRef; // Unused
301 (void)RecordRef; // Unused
302 (void)flags; // Unused
303 (void)rrtype; // Unused
304 (void)rdlen; // Unused
305 (void)rdata; // Unused
306 (void)ttl; // Unused
307 return(kDNSServiceErr_Unsupported);
308}
8e92c31c
A
309
310DNSServiceErrorType DNSServiceUpdateRecord
83fb1e36
A
311(
312 DNSServiceRef sdRef,
313 DNSRecordRef RecordRef, /* may be NULL */
314 DNSServiceFlags flags,
315 uint16_t rdlen,
316 const void *rdata,
317 uint32_t ttl
318)
319{
320 (void)sdRef; // Unused
321 (void)RecordRef; // Unused
322 (void)flags; // Unused
323 (void)rdlen; // Unused
324 (void)rdata; // Unused
325 (void)ttl; // Unused
326 return(kDNSServiceErr_Unsupported);
327}
8e92c31c
A
328
329DNSServiceErrorType DNSServiceRemoveRecord
83fb1e36
A
330(
331 DNSServiceRef sdRef,
332 DNSRecordRef RecordRef,
333 DNSServiceFlags flags
334)
335{
336 (void)sdRef; // Unused
337 (void)RecordRef; // Unused
338 (void)flags; // Unused
339 return(kDNSServiceErr_Unsupported);
340}
8e92c31c
A
341#endif
342
343//*************************************************************************************************************
344// Browse for services
345
346static void DNSServiceBrowseDispose(mDNS_DirectOP *op)
83fb1e36
A
347{
348 mDNS_DirectOP_Browse *x = (mDNS_DirectOP_Browse*)op;
349 //LogMsg("DNSServiceBrowseDispose");
350 mDNS_StopBrowse(&mDNSStorage, &x->q);
351 mDNSPlatformMemFree(x);
352}
8e92c31c 353
67c8f8a1 354mDNSlocal void FoundInstance(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord)
83fb1e36
A
355{
356 DNSServiceFlags flags = AddRecord ? kDNSServiceFlagsAdd : (DNSServiceFlags)0;
357 domainlabel name;
358 domainname type, domain;
359 char cname[MAX_DOMAIN_LABEL+1]; // Unescaped name: up to 63 bytes plus C-string terminating NULL.
360 char ctype[MAX_ESCAPED_DOMAIN_NAME];
361 char cdom [MAX_ESCAPED_DOMAIN_NAME];
362 mDNS_DirectOP_Browse *x = (mDNS_DirectOP_Browse*)question->QuestionContext;
363 (void)m; // Unused
364
365 if (answer->rrtype != kDNSType_PTR)
366 { LogMsg("FoundInstance: Should not be called with rrtype %d (not a PTR record)", answer->rrtype); return; }
367
368 if (!DeconstructServiceName(&answer->rdata->u.name, &name, &type, &domain))
369 {
370 LogMsg("FoundInstance: %##s PTR %##s received from network is not valid DNS-SD service pointer",
371 answer->name->c, answer->rdata->u.name.c);
372 return;
373 }
374
375 ConvertDomainLabelToCString_unescaped(&name, cname);
376 ConvertDomainNameToCString(&type, ctype);
377 ConvertDomainNameToCString(&domain, cdom);
378 if (x->callback)
379 x->callback((DNSServiceRef)x, flags, 0, 0, cname, ctype, cdom, x->context);
380}
8e92c31c
A
381
382DNSServiceErrorType DNSServiceBrowse
83fb1e36
A
383(
384 DNSServiceRef *sdRef,
385 DNSServiceFlags flags,
386 uint32_t interfaceIndex,
387 const char *regtype,
388 const char *domain, /* may be NULL */
389 DNSServiceBrowseReply callback,
390 void *context /* may be NULL */
391)
392{
393 mStatus err = mStatus_NoError;
394 const char *errormsg = "Unknown";
395 domainname t, d;
396 mDNS_DirectOP_Browse *x;
397 (void)flags; // Unused
398 (void)interfaceIndex; // Unused
399
400 // Check parameters
401 if (!regtype[0] || !MakeDomainNameFromDNSNameString(&t, regtype)) { errormsg = "Illegal regtype"; goto badparam; }
402 if (!MakeDomainNameFromDNSNameString(&d, *domain ? domain : "local.")) { errormsg = "Illegal domain"; goto badparam; }
403
404 // Allocate memory, and handle failure
405 x = (mDNS_DirectOP_Browse *)mDNSPlatformMemAllocate(sizeof(*x));
406 if (!x) { err = mStatus_NoMemoryErr; errormsg = "No memory"; goto fail; }
407
408 // Set up object
409 x->disposefn = DNSServiceBrowseDispose;
410 x->callback = callback;
411 x->context = context;
412 x->q.QuestionContext = x;
413
414 // Do the operation
51601d48 415 err = mDNS_StartBrowse(&mDNSStorage, &x->q, &t, &d, mDNSNULL, mDNSInterface_Any, flags, (flags & kDNSServiceFlagsForceMulticast) != 0, (flags & kDNSServiceFlagsBackgroundTrafficClass) != 0, FoundInstance, x);
83fb1e36
A
416 if (err) { mDNSPlatformMemFree(x); errormsg = "mDNS_StartBrowse"; goto fail; }
417
418 // Succeeded: Wrap up and return
419 *sdRef = (DNSServiceRef)x;
420 return(mStatus_NoError);
8e92c31c
A
421
422badparam:
83fb1e36 423 err = mStatus_BadParamErr;
8e92c31c 424fail:
83fb1e36
A
425 LogMsg("DNSServiceBrowse(\"%s\", \"%s\") failed: %s (%ld)", regtype, domain, errormsg, err);
426 return(err);
427}
8e92c31c
A
428
429//*************************************************************************************************************
430// Resolve Service Info
431
432static void DNSServiceResolveDispose(mDNS_DirectOP *op)
83fb1e36
A
433{
434 mDNS_DirectOP_Resolve *x = (mDNS_DirectOP_Resolve*)op;
435 if (x->qSRV.ThisQInterval >= 0) mDNS_StopQuery(&mDNSStorage, &x->qSRV);
436 if (x->qTXT.ThisQInterval >= 0) mDNS_StopQuery(&mDNSStorage, &x->qTXT);
437 mDNSPlatformMemFree(x);
438}
8e92c31c 439
67c8f8a1 440mDNSlocal void FoundServiceInfo(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord)
83fb1e36
A
441{
442 mDNS_DirectOP_Resolve *x = (mDNS_DirectOP_Resolve*)question->QuestionContext;
443 (void)m; // Unused
444 if (!AddRecord)
445 {
446 if (answer->rrtype == kDNSType_SRV && x->SRV == answer) x->SRV = mDNSNULL;
447 if (answer->rrtype == kDNSType_TXT && x->TXT == answer) x->TXT = mDNSNULL;
448 }
449 else
450 {
451 if (answer->rrtype == kDNSType_SRV) x->SRV = answer;
452 if (answer->rrtype == kDNSType_TXT) x->TXT = answer;
453 if (x->SRV && x->TXT && x->callback)
454 {
455 char fullname[MAX_ESCAPED_DOMAIN_NAME], targethost[MAX_ESCAPED_DOMAIN_NAME];
456 ConvertDomainNameToCString(answer->name, fullname);
457 ConvertDomainNameToCString(&x->SRV->rdata->u.srv.target, targethost);
458 x->callback((DNSServiceRef)x, 0, 0, kDNSServiceErr_NoError, fullname, targethost,
459 x->SRV->rdata->u.srv.port.NotAnInteger, x->TXT->rdlength, (unsigned char*)x->TXT->rdata->u.txt.c, x->context);
460 }
461 }
462}
8e92c31c
A
463
464DNSServiceErrorType DNSServiceResolve
83fb1e36
A
465(
466 DNSServiceRef *sdRef,
467 DNSServiceFlags flags,
468 uint32_t interfaceIndex,
469 const char *name,
470 const char *regtype,
471 const char *domain,
472 DNSServiceResolveReply callback,
473 void *context /* may be NULL */
474)
475{
476 mStatus err = mStatus_NoError;
477 const char *errormsg = "Unknown";
478 domainlabel n;
479 domainname t, d, srv;
480 mDNS_DirectOP_Resolve *x;
481
482 (void)flags; // Unused
483 (void)interfaceIndex; // Unused
484
485 // Check parameters
486 if (!name[0] || !MakeDomainLabelFromLiteralString(&n, name )) { errormsg = "Bad Instance Name"; goto badparam; }
487 if (!regtype[0] || !MakeDomainNameFromDNSNameString(&t, regtype)) { errormsg = "Bad Service Type"; goto badparam; }
488 if (!domain[0] || !MakeDomainNameFromDNSNameString(&d, domain )) { errormsg = "Bad Domain"; goto badparam; }
489 if (!ConstructServiceName(&srv, &n, &t, &d)) { errormsg = "Bad Name"; goto badparam; }
490
491 // Allocate memory, and handle failure
492 x = (mDNS_DirectOP_Resolve *)mDNSPlatformMemAllocate(sizeof(*x));
493 if (!x) { err = mStatus_NoMemoryErr; errormsg = "No memory"; goto fail; }
494
495 // Set up object
496 x->disposefn = DNSServiceResolveDispose;
497 x->callback = callback;
498 x->context = context;
499 x->SRV = mDNSNULL;
500 x->TXT = mDNSNULL;
501
502 x->qSRV.ThisQInterval = -1; // So that DNSServiceResolveDispose() knows whether to cancel this question
503 x->qSRV.InterfaceID = mDNSInterface_Any;
504 x->qSRV.flags = 0;
505 x->qSRV.Target = zeroAddr;
506 AssignDomainName(&x->qSRV.qname, &srv);
507 x->qSRV.qtype = kDNSType_SRV;
508 x->qSRV.qclass = kDNSClass_IN;
509 x->qSRV.LongLived = mDNSfalse;
510 x->qSRV.ExpectUnique = mDNStrue;
511 x->qSRV.ForceMCast = mDNSfalse;
512 x->qSRV.ReturnIntermed = mDNSfalse;
513 x->qSRV.SuppressUnusable = mDNSfalse;
514 x->qSRV.SearchListIndex = 0;
515 x->qSRV.AppendSearchDomains = 0;
516 x->qSRV.RetryWithSearchDomains = mDNSfalse;
517 x->qSRV.TimeoutQuestion = 0;
518 x->qSRV.WakeOnResolve = 0;
51601d48 519 x->qSRV.UseBackgroundTrafficClass = (flags & kDNSServiceFlagsBackgroundTrafficClass) != 0;
83fb1e36
A
520 x->qSRV.ValidationRequired = 0;
521 x->qSRV.ValidatingResponse = 0;
51601d48 522 x->qSRV.ProxyQuestion = 0;
83fb1e36 523 x->qSRV.qnameOrig = mDNSNULL;
51601d48
A
524 x->qSRV.AnonInfo = mDNSNULL;
525 x->qSRV.pid = mDNSPlatformGetPID();
83fb1e36
A
526 x->qSRV.QuestionCallback = FoundServiceInfo;
527 x->qSRV.QuestionContext = x;
528
529 x->qTXT.ThisQInterval = -1; // So that DNSServiceResolveDispose() knows whether to cancel this question
530 x->qTXT.InterfaceID = mDNSInterface_Any;
531 x->qTXT.flags = 0;
532 x->qTXT.Target = zeroAddr;
533 AssignDomainName(&x->qTXT.qname, &srv);
534 x->qTXT.qtype = kDNSType_TXT;
535 x->qTXT.qclass = kDNSClass_IN;
536 x->qTXT.LongLived = mDNSfalse;
537 x->qTXT.ExpectUnique = mDNStrue;
538 x->qTXT.ForceMCast = mDNSfalse;
539 x->qTXT.ReturnIntermed = mDNSfalse;
540 x->qTXT.SuppressUnusable = mDNSfalse;
541 x->qTXT.SearchListIndex = 0;
542 x->qTXT.AppendSearchDomains = 0;
543 x->qTXT.RetryWithSearchDomains = mDNSfalse;
544 x->qTXT.TimeoutQuestion = 0;
545 x->qTXT.WakeOnResolve = 0;
51601d48 546 x->qTXT.UseBackgroundTrafficClass = (flags & kDNSServiceFlagsBackgroundTrafficClass) != 0;
83fb1e36
A
547 x->qTXT.ValidationRequired = 0;
548 x->qTXT.ValidatingResponse = 0;
51601d48 549 x->qTXT.ProxyQuestion = 0;
83fb1e36 550 x->qTXT.qnameOrig = mDNSNULL;
51601d48
A
551 x->qTXT.AnonInfo = mDNSNULL;
552 x->qTXT.pid = mDNSPlatformGetPID();
83fb1e36
A
553 x->qTXT.QuestionCallback = FoundServiceInfo;
554 x->qTXT.QuestionContext = x;
555
556 err = mDNS_StartQuery(&mDNSStorage, &x->qSRV);
557 if (err) { DNSServiceResolveDispose((mDNS_DirectOP*)x); errormsg = "mDNS_StartQuery qSRV"; goto fail; }
558 err = mDNS_StartQuery(&mDNSStorage, &x->qTXT);
559 if (err) { DNSServiceResolveDispose((mDNS_DirectOP*)x); errormsg = "mDNS_StartQuery qTXT"; goto fail; }
560
561 // Succeeded: Wrap up and return
562 *sdRef = (DNSServiceRef)x;
563 return(mStatus_NoError);
8e92c31c
A
564
565badparam:
83fb1e36 566 err = mStatus_BadParamErr;
8e92c31c 567fail:
83fb1e36
A
568 LogMsg("DNSServiceResolve(\"%s\", \"%s\", \"%s\") failed: %s (%ld)", name, regtype, domain, errormsg, err);
569 return(err);
570}
8e92c31c
A
571
572//*************************************************************************************************************
573// Connection-oriented calls
574
575// Not yet implemented, so don't include in stub library
576// We DO include it in the actual Extension, so that if a later client compiled to use this
577// is run against this Extension, it will get a reasonable error code instead of just
578// failing to launch (Strong Link) or calling an unresolved symbol and crashing (Weak Link)
579#if !MDNS_BUILDINGSTUBLIBRARY
580DNSServiceErrorType DNSServiceCreateConnection(DNSServiceRef *sdRef)
83fb1e36
A
581{
582 (void)sdRef; // Unused
583 return(kDNSServiceErr_Unsupported);
584}
8e92c31c
A
585
586DNSServiceErrorType DNSServiceRegisterRecord
83fb1e36
A
587(
588 DNSServiceRef sdRef,
589 DNSRecordRef *RecordRef,
590 DNSServiceFlags flags,
591 uint32_t interfaceIndex,
592 const char *fullname,
593 uint16_t rrtype,
594 uint16_t rrclass,
595 uint16_t rdlen,
596 const void *rdata,
597 uint32_t ttl,
598 DNSServiceRegisterRecordReply callback,
599 void *context /* may be NULL */
600)
601{
602 (void)sdRef; // Unused
603 (void)RecordRef; // Unused
604 (void)flags; // Unused
605 (void)interfaceIndex; // Unused
606 (void)fullname; // Unused
607 (void)rrtype; // Unused
608 (void)rrclass; // Unused
609 (void)rdlen; // Unused
610 (void)rdata; // Unused
611 (void)ttl; // Unused
612 (void)callback; // Unused
613 (void)context; // Unused
614 return(kDNSServiceErr_Unsupported);
615}
8e92c31c
A
616#endif
617
618//*************************************************************************************************************
619// DNSServiceQueryRecord
620
621static void DNSServiceQueryRecordDispose(mDNS_DirectOP *op)
83fb1e36
A
622{
623 mDNS_DirectOP_QueryRecord *x = (mDNS_DirectOP_QueryRecord*)op;
624 if (x->q.ThisQInterval >= 0) mDNS_StopQuery(&mDNSStorage, &x->q);
625 mDNSPlatformMemFree(x);
626}
8e92c31c 627
67c8f8a1 628mDNSlocal void DNSServiceQueryRecordResponse(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord)
83fb1e36
A
629{
630 mDNS_DirectOP_QueryRecord *x = (mDNS_DirectOP_QueryRecord*)question->QuestionContext;
631 char fullname[MAX_ESCAPED_DOMAIN_NAME];
632 (void)m; // Unused
633 ConvertDomainNameToCString(answer->name, fullname);
634 x->callback((DNSServiceRef)x, AddRecord ? kDNSServiceFlagsAdd : (DNSServiceFlags)0, 0, kDNSServiceErr_NoError,
635 fullname, answer->rrtype, answer->rrclass, answer->rdlength, answer->rdata->u.data, answer->rroriginalttl, x->context);
636}
8e92c31c
A
637
638DNSServiceErrorType DNSServiceQueryRecord
83fb1e36
A
639(
640 DNSServiceRef *sdRef,
641 DNSServiceFlags flags,
642 uint32_t interfaceIndex,
643 const char *fullname,
644 uint16_t rrtype,
645 uint16_t rrclass,
646 DNSServiceQueryRecordReply callback,
647 void *context /* may be NULL */
648)
649{
650 mStatus err = mStatus_NoError;
651 const char *errormsg = "Unknown";
652 mDNS_DirectOP_QueryRecord *x;
653
654 (void)flags; // Unused
655 (void)interfaceIndex; // Unused
656
657 // Allocate memory, and handle failure
658 x = (mDNS_DirectOP_QueryRecord *)mDNSPlatformMemAllocate(sizeof(*x));
659 if (!x) { err = mStatus_NoMemoryErr; errormsg = "No memory"; goto fail; }
660
661 // Set up object
662 x->disposefn = DNSServiceQueryRecordDispose;
663 x->callback = callback;
664 x->context = context;
665
666 x->q.ThisQInterval = -1; // So that DNSServiceResolveDispose() knows whether to cancel this question
667 x->q.InterfaceID = mDNSInterface_Any;
668 x->q.flags = flags;
669 x->q.Target = zeroAddr;
670 MakeDomainNameFromDNSNameString(&x->q.qname, fullname);
671 x->q.qtype = rrtype;
672 x->q.qclass = rrclass;
673 x->q.LongLived = (flags & kDNSServiceFlagsLongLivedQuery) != 0;
674 x->q.ExpectUnique = mDNSfalse;
675 x->q.ForceMCast = (flags & kDNSServiceFlagsForceMulticast) != 0;
676 x->q.ReturnIntermed = (flags & kDNSServiceFlagsReturnIntermediates) != 0;
677 x->q.SuppressUnsable = (flags & kDNSServiceFlagsSuppressUnusable) != 0;
678 x->q.SearchListIndex = 0;
679 x->q.AppendSearchDomains = 0;
680 x->q.RetryWithSearchDomains = mDNSfalse;
51601d48 681 x->q.TimeoutQuestion = 0;
83fb1e36 682 x->q.WakeOnResolve = 0;
51601d48
A
683 x->q.UseBackgroundTrafficClass = (flags & kDNSServiceFlagsBackgroundTrafficClass) != 0;
684 x->q.ValidationRequired = 0;
685 x->q.ValidatingResponse = 0;
686 x->q.ProxyQuestion = 0;
83fb1e36 687 x->q.qnameOrig = mDNSNULL;
51601d48
A
688 x->q.AnonInfo = mDNSNULL;
689 x->q.pid = mDNSPlatformGetPID();
83fb1e36
A
690 x->q.QuestionCallback = DNSServiceQueryRecordResponse;
691 x->q.QuestionContext = x;
692
693 err = mDNS_StartQuery(&mDNSStorage, &x->q);
694 if (err) { DNSServiceResolveDispose((mDNS_DirectOP*)x); errormsg = "mDNS_StartQuery"; goto fail; }
695
696 // Succeeded: Wrap up and return
697 *sdRef = (DNSServiceRef)x;
698 return(mStatus_NoError);
8e92c31c 699
8e92c31c 700fail:
83fb1e36
A
701 LogMsg("DNSServiceQueryRecord(\"%s\", %d, %d) failed: %s (%ld)", fullname, rrtype, rrclass, errormsg, err);
702 return(err);
703}
8e92c31c
A
704
705//*************************************************************************************************************
263eeeab
A
706// DNSServiceGetAddrInfo
707
708static void DNSServiceGetAddrInfoDispose(mDNS_DirectOP *op)
83fb1e36
A
709{
710 mDNS_DirectOP_GetAddrInfo *x = (mDNS_DirectOP_GetAddrInfo*)op;
711 if (x->aQuery) DNSServiceRefDeallocate(x->aQuery);
712 mDNSPlatformMemFree(x);
713}
263eeeab
A
714
715static void DNSSD_API DNSServiceGetAddrInfoResponse(
83fb1e36
A
716 DNSServiceRef inRef,
717 DNSServiceFlags inFlags,
718 uint32_t inInterfaceIndex,
719 DNSServiceErrorType inErrorCode,
720 const char * inFullName,
721 uint16_t inRRType,
722 uint16_t inRRClass,
723 uint16_t inRDLen,
724 const void * inRData,
725 uint32_t inTTL,
726 void * inContext )
727{
728 mDNS_DirectOP_GetAddrInfo * x = (mDNS_DirectOP_GetAddrInfo*)inContext;
729 struct sockaddr_in sa4;
730
731 mDNSPlatformMemZero(&sa4, sizeof(sa4));
732 if (inErrorCode == kDNSServiceErr_NoError && inRRType == kDNSServiceType_A)
733 {
734 sa4.sin_family = AF_INET;
735 mDNSPlatformMemCopy(&sa4.sin_addr.s_addr, inRData, 4);
736 }
737
738 x->callback((DNSServiceRef)x, inFlags, inInterfaceIndex, inErrorCode, inFullName,
739 (const struct sockaddr *) &sa4, inTTL, x->context);
740}
263eeeab
A
741
742DNSServiceErrorType DNSSD_API DNSServiceGetAddrInfo(
83fb1e36
A
743 DNSServiceRef * outRef,
744 DNSServiceFlags inFlags,
745 uint32_t inInterfaceIndex,
746 DNSServiceProtocol inProtocol,
747 const char * inHostName,
748 DNSServiceGetAddrInfoReply inCallback,
749 void * inContext )
750{
751 const char * errormsg = "Unknown";
752 DNSServiceErrorType err;
753 mDNS_DirectOP_GetAddrInfo * x;
754
755 // Allocate memory, and handle failure
756 x = (mDNS_DirectOP_GetAddrInfo *)mDNSPlatformMemAllocate(sizeof(*x));
757 if (!x) { err = mStatus_NoMemoryErr; errormsg = "No memory"; goto fail; }
758
759 // Set up object
760 x->disposefn = DNSServiceGetAddrInfoDispose;
761 x->callback = inCallback;
762 x->context = inContext;
763 x->aQuery = mDNSNULL;
764
765 // Start the query.
766 // (It would probably be more efficient to code this using mDNS_StartQuery directly,
767 // instead of wrapping DNSServiceQueryRecord, which then unnecessarily allocates
768 // more memory and then just calls through to mDNS_StartQuery. -- SC June 2010)
769 err = DNSServiceQueryRecord(&x->aQuery, inFlags, inInterfaceIndex, inHostName, kDNSServiceType_A,
770 kDNSServiceClass_IN, DNSServiceGetAddrInfoResponse, x);
771 if (err) { DNSServiceGetAddrInfoDispose((mDNS_DirectOP*)x); errormsg = "DNSServiceQueryRecord"; goto fail; }
772
773 *outRef = (DNSServiceRef)x;
774 return(mStatus_NoError);
775
263eeeab 776fail:
83fb1e36
A
777 LogMsg("DNSServiceGetAddrInfo(\"%s\", %d) failed: %s (%ld)", inHostName, inProtocol, errormsg, err);
778 return(err);
779}
263eeeab
A
780
781//*************************************************************************************************************
8e92c31c
A
782// DNSServiceReconfirmRecord
783
784// Not yet implemented, so don't include in stub library
785// We DO include it in the actual Extension, so that if a later client compiled to use this
786// is run against this Extension, it will get a reasonable error code instead of just
787// failing to launch (Strong Link) or calling an unresolved symbol and crashing (Weak Link)
788#if !MDNS_BUILDINGSTUBLIBRARY
67c8f8a1 789DNSServiceErrorType DNSSD_API DNSServiceReconfirmRecord
83fb1e36
A
790(
791 DNSServiceFlags flags,
792 uint32_t interfaceIndex,
793 const char *fullname,
794 uint16_t rrtype,
795 uint16_t rrclass,
796 uint16_t rdlen,
797 const void *rdata
798)
799{
800 (void)flags; // Unused
801 (void)interfaceIndex; // Unused
802 (void)fullname; // Unused
803 (void)rrtype; // Unused
804 (void)rrclass; // Unused
805 (void)rdlen; // Unused
806 (void)rdata; // Unused
807 return(kDNSServiceErr_Unsupported);
808}
509d285a
A
809
810#endif // !MDNS_BUILDINGSTUBLIBRARY