]> git.saurik.com Git - apple/mdnsresponder.git/blobdiff - mDNSShared/dnssd_clientshim.c
mDNSResponder-258.18.tar.gz
[apple/mdnsresponder.git] / mDNSShared / dnssd_clientshim.c
index 98b187f1e02185b8c96acb988bd62e600bf40454..17f2e93921941870822f5d64942111ea6a444a5b 100644 (file)
@@ -1,52 +1,30 @@
-/*
+/* -*- Mode: C; tab-width: 4 -*-
+ *
  * Copyright (c) 2003 Apple Computer, Inc. All rights reserved.
  * 
- * @APPLE_LICENSE_HEADER_START@
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
  * 
- * Copyright (c) 1999-2003 Apple Computer, Inc.  All Rights Reserved.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  * 
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- * 
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
  * limitations under the License.
- * 
- * @APPLE_LICENSE_HEADER_END@
 
  * This file defines a simple shim layer between a client calling the "/usr/include/dns_sd.h" APIs
- * and an implementation of mDNSCore ("mDNSClientAPI.h" APIs) in the same address space.
- * When the client calls a dns_sd.h function, the shim calls the corresponding mDNSClientAPI.h
+ * and an implementation of mDNSCore ("mDNSEmbeddedAPI.h" APIs) in the same address space.
+ * When the client calls a dns_sd.h function, the shim calls the corresponding mDNSEmbeddedAPI.h
  * function, and when mDNSCore calls the shim's callback, we call through to the client's callback.
  * The shim is responsible for two main things:
  * - converting string parameters between C string format and native DNS format,
  * - and for allocating and freeing memory.
-
-       Change History (most recent first):
-
-$Log: dnssd_clientshim.c,v $
-Revision 1.3  2004/05/27 06:26:31  cheshire
-Add shim for DNSServiceQueryRecord()
-
-Revision 1.2  2004/05/20 18:41:24  cheshire
-Fix build broken by removal of 'kDNSServiceFlagsRemove' from dns_sd.h
-
-Revision 1.1  2004/03/12 21:30:29  cheshire
-Build a System-Context Shared Library from mDNSCore, for the benefit of developers
-like Muse Research who want to be able to use mDNS/DNS-SD from GPL-licensed code.
-
  */
 
 #include "dns_sd.h"                            // Defines the interface to the client layer above
-#include "mDNSClientAPI.h"             // The interface we're building on top of
+#include "mDNSEmbeddedAPI.h"           // The interface we're building on top of
 extern mDNS mDNSStorage;               // We need to pass the address of this storage to the lower-layer functions
 
 #if MDNS_BUILDINGSHAREDLIBRARY || MDNS_BUILDINGSTUBLIBRARY
@@ -75,9 +53,10 @@ typedef struct
        mDNS_DirectOP_Dispose  *disposefn;
        DNSServiceRegisterReply callback;
        void                   *context;
-       mDNSBool                autoname;
-       mDNSBool                autorename;
+       mDNSBool                autoname;               // Set if this name is tied to the Computer Name
+       mDNSBool                autorename;             // Set if we just got a name conflict and now need to automatically pick a new name
        domainlabel             name;
+       domainname              host;
        ServiceRecordSet        s;
        } mDNS_DirectOP_Register;
 
@@ -196,7 +175,7 @@ mDNSlocal void RegCallback(mDNS *const m, ServiceRecordSet *const sr, mStatus re
        char namestr[MAX_DOMAIN_LABEL+1];               // Unescaped name: up to 63 bytes plus C-string terminating NULL.
        char typestr[MAX_ESCAPED_DOMAIN_NAME];
        char domstr [MAX_ESCAPED_DOMAIN_NAME];
-    if (!DeconstructServiceName(&sr->RR_SRV.resrec.name, &name, &type, &dom)) return;
+    if (!DeconstructServiceName(sr->RR_SRV.resrec.name, &name, &type, &dom)) return;
     if (!ConvertDomainLabelToCString_unescaped(&name, namestr)) return;
     if (!ConvertDomainNameToCString(&type, typestr)) return;
     if (!ConvertDomainNameToCString(&dom, domstr)) return;
@@ -254,6 +233,7 @@ DNSServiceErrorType DNSServiceRegister
        (void)interfaceIndex;   // Unused
 
        // Check parameters
+       if (!name) name = "";
        if (!name[0]) n = mDNSStorage.nicelabel;
        else if (!MakeDomainLabelFromLiteralString(&n, name))                              { errormsg = "Bad Instance Name"; goto badparam; }
        if (!regtype || !*regtype || !MakeDomainNameFromDNSNameString(&t, regtype))        { errormsg = "Bad Service Type";  goto badparam; }
@@ -275,11 +255,12 @@ DNSServiceErrorType DNSServiceRegister
        x->autoname = (!name[0]);
        x->autorename = mDNSfalse;
        x->name = n;
+       x->host = h;
 
        // Do the operation
        err = mDNS_RegisterService(&mDNSStorage, &x->s,
                &x->name, &t, &d,               // Name, type, domain
-               &h, port,                               // Host and port
+               &x->host, port,                 // Host and port
                txtRecord, txtLen,              // TXT data, length
                SubTypes, NumSubTypes,  // Subtypes
                mDNSInterface_Any,              // Interface ID
@@ -370,7 +351,7 @@ static void DNSServiceBrowseDispose(mDNS_DirectOP *op)
        mDNSPlatformMemFree(x);
        }
 
-mDNSlocal void FoundInstance(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, mDNSBool AddRecord)
+mDNSlocal void FoundInstance(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord)
        {
        DNSServiceFlags flags = AddRecord ? kDNSServiceFlagsAdd : (DNSServiceFlags)0;
        domainlabel name;
@@ -387,7 +368,7 @@ mDNSlocal void FoundInstance(mDNS *const m, DNSQuestion *question, const Resourc
        if (!DeconstructServiceName(&answer->rdata->u.name, &name, &type, &domain))
                {
                LogMsg("FoundInstance: %##s PTR %##s received from network is not valid DNS-SD service pointer",
-                       answer->name.c, answer->rdata->u.name.c);
+                       answer->name->c, answer->rdata->u.name.c);
                return;
                }
 
@@ -431,7 +412,7 @@ DNSServiceErrorType DNSServiceBrowse
        x->q.QuestionContext = x;
 
        // Do the operation
-       err = mDNS_StartBrowse(&mDNSStorage, &x->q, &t, &d, mDNSInterface_Any, FoundInstance, x);
+       err = mDNS_StartBrowse(&mDNSStorage, &x->q, &t, &d, mDNSInterface_Any, (flags & kDNSServiceFlagsForceMulticast) != 0, FoundInstance, x);
        if (err) { mDNSPlatformMemFree(x); errormsg = "mDNS_StartBrowse"; goto fail; }
 
        // Succeeded: Wrap up and return
@@ -456,7 +437,7 @@ static void DNSServiceResolveDispose(mDNS_DirectOP *op)
        mDNSPlatformMemFree(x);
        }
 
-mDNSlocal void FoundServiceInfo(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, mDNSBool AddRecord)
+mDNSlocal void FoundServiceInfo(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord)
        {
        mDNS_DirectOP_Resolve *x = (mDNS_DirectOP_Resolve*)question->QuestionContext;
        (void)m;        // Unused
@@ -472,10 +453,10 @@ mDNSlocal void FoundServiceInfo(mDNS *const m, DNSQuestion *question, const Reso
                if (x->SRV && x->TXT && x->callback)
                        {
                        char fullname[MAX_ESCAPED_DOMAIN_NAME], targethost[MAX_ESCAPED_DOMAIN_NAME];
-                   ConvertDomainNameToCString(&answer->name, fullname);
+                   ConvertDomainNameToCString(answer->name, fullname);
                    ConvertDomainNameToCString(&x->SRV->rdata->u.srv.target, targethost);
                        x->callback((DNSServiceRef)x, 0, 0, kDNSServiceErr_NoError, fullname, targethost,
-                               x->SRV->rdata->u.srv.port.NotAnInteger, x->TXT->rdlength, (char*)x->TXT->rdata->u.txt.c, x->context);
+                               x->SRV->rdata->u.srv.port.NotAnInteger, x->TXT->rdlength, (unsigned char*)x->TXT->rdata->u.txt.c, x->context);
                        }
                }
        }
@@ -521,18 +502,27 @@ DNSServiceErrorType DNSServiceResolve
        x->qSRV.ThisQInterval       = -1;               // So that DNSServiceResolveDispose() knows whether to cancel this question
        x->qSRV.InterfaceID         = mDNSInterface_Any;
        x->qSRV.Target              = zeroAddr;
-       AssignDomainName(x->qSRV.qname, srv);
+       AssignDomainName(&x->qSRV.qname, &srv);
        x->qSRV.qtype               = kDNSType_SRV;
        x->qSRV.qclass              = kDNSClass_IN;
+       x->qSRV.LongLived           = mDNSfalse;
+       x->qSRV.ExpectUnique        = mDNStrue;
+       x->qSRV.ForceMCast          = mDNSfalse;
+       x->qSRV.ReturnIntermed      = mDNSfalse;
        x->qSRV.QuestionCallback    = FoundServiceInfo;
        x->qSRV.QuestionContext     = x;
 
        x->qTXT.ThisQInterval       = -1;               // So that DNSServiceResolveDispose() knows whether to cancel this question
        x->qTXT.InterfaceID         = mDNSInterface_Any;
        x->qTXT.Target              = zeroAddr;
-       AssignDomainName(x->qTXT.qname, srv);
+       AssignDomainName(&x->qTXT.qname, &srv);
        x->qTXT.qtype               = kDNSType_TXT;
        x->qTXT.qclass              = kDNSClass_IN;
+       x->qTXT.LongLived           = mDNSfalse;
+       x->qTXT.ExpectUnique        = mDNStrue;
+       x->qTXT.ForceMCast          = mDNSfalse;
+       x->qTXT.ReturnIntermed      = mDNSfalse;
+       x->qTXT.SuppressUnusable    = mDNSfalse;
        x->qTXT.QuestionCallback    = FoundServiceInfo;
        x->qTXT.QuestionContext     = x;
 
@@ -608,12 +598,12 @@ static void DNSServiceQueryRecordDispose(mDNS_DirectOP *op)
        mDNSPlatformMemFree(x);
        }
 
-mDNSlocal void DNSServiceQueryRecordResponse(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, mDNSBool AddRecord)
+mDNSlocal void DNSServiceQueryRecordResponse(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord)
        {
        mDNS_DirectOP_QueryRecord *x = (mDNS_DirectOP_QueryRecord*)question->QuestionContext;
        char fullname[MAX_ESCAPED_DOMAIN_NAME];
        (void)m;        // Unused
-       ConvertDomainNameToCString(&answer->name, fullname);
+       ConvertDomainNameToCString(answer->name, fullname);
        x->callback((DNSServiceRef)x, AddRecord ? kDNSServiceFlagsAdd : (DNSServiceFlags)0, 0, kDNSServiceErr_NoError,
                fullname, answer->rrtype, answer->rrclass, answer->rdlength, answer->rdata->u.data, answer->rroriginalttl, x->context);
        }
@@ -652,6 +642,11 @@ DNSServiceErrorType DNSServiceQueryRecord
        MakeDomainNameFromDNSNameString(&x->q.qname, fullname);
        x->q.qtype               = rrtype;
        x->q.qclass              = rrclass;
+       x->q.LongLived           = (flags & kDNSServiceFlagsLongLivedQuery) != 0;
+       x->q.ExpectUnique        = mDNSfalse;
+       x->q.ForceMCast          = (flags & kDNSServiceFlagsForceMulticast) != 0;
+       x->q.ReturnIntermed      = (flags & kDNSServiceFlagsReturnIntermediates) != 0;
+       x->q.SuppressUnsable     = (flags & kDNSServiceFlagsSuppressUnusable) != 0;
        x->q.QuestionCallback    = DNSServiceQueryRecordResponse;
        x->q.QuestionContext     = x;
 
@@ -662,13 +657,87 @@ DNSServiceErrorType DNSServiceQueryRecord
        *sdRef = (DNSServiceRef)x;
        return(mStatus_NoError);
 
-badparam:
-       err = mStatus_BadParamErr;
 fail:
        LogMsg("DNSServiceQueryRecord(\"%s\", %d, %d) failed: %s (%ld)", fullname, rrtype, rrclass, errormsg, err);
        return(err);
        }
 
+//*************************************************************************************************************
+// DNSServiceGetAddrInfo
+
+static void DNSServiceGetAddrInfoDispose(mDNS_DirectOP *op)
+       {
+       mDNS_DirectOP_GetAddrInfo *x = (mDNS_DirectOP_GetAddrInfo*)op;
+       if (x->aQuery) DNSServiceRefDeallocate(x->aQuery);
+       mDNSPlatformMemFree(x);
+       }
+
+static void DNSSD_API DNSServiceGetAddrInfoResponse(
+       DNSServiceRef           inRef,
+       DNSServiceFlags         inFlags,
+       uint32_t                        inInterfaceIndex,
+       DNSServiceErrorType     inErrorCode,
+       const char *            inFullName,
+       uint16_t                        inRRType,
+       uint16_t                        inRRClass,
+       uint16_t                        inRDLen,
+       const void *            inRData,
+       uint32_t                        inTTL,
+       void *                          inContext )
+       {
+       mDNS_DirectOP_GetAddrInfo *             x = (mDNS_DirectOP_GetAddrInfo*)inContext;
+       struct sockaddr_in                              sa4;
+       
+       mDNSPlatformMemZero(&sa4, sizeof(sa4));
+       if (inErrorCode == kDNSServiceErr_NoError && inRRType == kDNSServiceType_A)
+               {
+               sa4.sin_family = AF_INET;
+               mDNSPlatformMemCopy(&sa4.sin_addr.s_addr, inRData, 4);
+               }
+       
+       x->callback((DNSServiceRef)x, inFlags, inInterfaceIndex, inErrorCode, inFullName, 
+               (const struct sockaddr *) &sa4, inTTL, x->context);
+       }
+
+DNSServiceErrorType DNSSD_API DNSServiceGetAddrInfo(
+       DNSServiceRef *                         outRef,
+       DNSServiceFlags                         inFlags,
+       uint32_t                                        inInterfaceIndex,
+       DNSServiceProtocol                      inProtocol,
+       const char *                            inHostName,
+       DNSServiceGetAddrInfoReply      inCallback,
+       void *                                          inContext )
+       {
+       const char *                                    errormsg = "Unknown";
+       DNSServiceErrorType                             err;
+       mDNS_DirectOP_GetAddrInfo *             x;
+       
+       // Allocate memory, and handle failure
+       x = (mDNS_DirectOP_GetAddrInfo *)mDNSPlatformMemAllocate(sizeof(*x));
+       if (!x) { err = mStatus_NoMemoryErr; errormsg = "No memory"; goto fail; }
+       
+       // Set up object
+       x->disposefn = DNSServiceGetAddrInfoDispose;
+       x->callback  = inCallback;
+       x->context   = inContext;
+       x->aQuery    = mDNSNULL;
+       
+       // Start the query.
+       // (It would probably be more efficient to code this using mDNS_StartQuery directly,
+       // instead of wrapping DNSServiceQueryRecord, which then unnecessarily allocates
+       // more memory and then just calls through to mDNS_StartQuery. -- SC June 2010)
+       err = DNSServiceQueryRecord(&x->aQuery, inFlags, inInterfaceIndex, inHostName, kDNSServiceType_A, 
+               kDNSServiceClass_IN, DNSServiceGetAddrInfoResponse, x);
+       if (err) { DNSServiceGetAddrInfoDispose((mDNS_DirectOP*)x); errormsg = "DNSServiceQueryRecord"; goto fail; }
+       
+       *outRef = (DNSServiceRef)x;
+       return(mStatus_NoError);
+       
+fail:
+       LogMsg("DNSServiceGetAddrInfo(\"%s\", %d) failed: %s (%ld)", inHostName, inProtocol, errormsg, err);
+       return(err);
+       }
+
 //*************************************************************************************************************
 // DNSServiceReconfirmRecord
 
@@ -677,7 +746,7 @@ fail:
 // is run against this Extension, it will get a reasonable error code instead of just
 // failing to launch (Strong Link) or calling an unresolved symbol and crashing (Weak Link)
 #if !MDNS_BUILDINGSTUBLIBRARY
-void DNSServiceReconfirmRecord
+DNSServiceErrorType DNSSD_API DNSServiceReconfirmRecord
        (
        DNSServiceFlags                    flags,
        uint32_t                           interfaceIndex,
@@ -695,5 +764,6 @@ void DNSServiceReconfirmRecord
        (void)rrclass;                  // Unused
        (void)rdlen;                    // Unused
        (void)rdata;                    // Unused
+       return(kDNSServiceErr_Unsupported);
        }
 #endif