source: rtems-libbsd/mDNSResponder/mDNSShared/dnssd_clientshim.c @ e36ca10

55-freebsd-126-freebsd-12
Last change on this file since e36ca10 was e36ca10, checked in by Sebastian Huber <sebastian.huber@…>, on 09/19/18 at 06:49:34

mDNSResponder: Update to v567

The sources can be obtained via:

https://opensource.apple.com/tarballs/mDNSResponder/mDNSResponder-567.tar.gz

Update #3522.

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