]> git.saurik.com Git - apple/mdnsresponder.git/commitdiff
mDNSResponder-320.14.tar.gz mac-os-x-1073 v320.14
authorApple <opensource@apple.com>
Wed, 16 Nov 2011 00:40:14 +0000 (00:40 +0000)
committerApple <opensource@apple.com>
Wed, 16 Nov 2011 00:40:14 +0000 (00:40 +0000)
17 files changed:
Clients/dns-sd.c
Makefile
mDNSCore/mDNS.c
mDNSCore/mDNSEmbeddedAPI.h
mDNSCore/uDNS.c
mDNSMacOSX/mDNSMacOSX.c
mDNSPosix/Identify.c
mDNSPosix/Makefile
mDNSPosix/ReadMe.txt
mDNSPosix/Responder.c
mDNSPosix/Services.txt
mDNSPosix/mDNSPosix.c
mDNSPosix/mDNSUNP.c
mDNSPosix/mDNSUNP.h
mDNSShared/CommonServices.h
mDNSShared/dns_sd.h
mDNSShared/uds_daemon.c

index c73c22160e3caa05ef69513036391cf65939b67c..bf6cc1039057a7ba6a8f3e17f62a3b8971158e3a 100644 (file)
@@ -170,11 +170,7 @@ cl dns-sd.c -I../mDNSShared -DNOT_HAVE_GETOPT ws2_32.lib ..\mDNSWindows\DLL\Rele
        #include <arpa/inet.h>          // For inet_addr()
        #include <net/if.h>                     // For if_nametoindex()
        static const char kFilePathSep = '/';
-// #ifndef NOT_HAVE_SA_LEN
-//     #define SA_LEN(addr) ((addr)->sa_len)
-// #else
-    #define SA_LEN(addr) (((addr)->sa_family == AF_INET6)? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in))
-// #endif
+       #define SA_LEN(addr) ((addr)->sa_len)
 #endif
 
 #if (TEST_NEW_CLIENTSTUB && !defined(__APPLE_API_PRIVATE))
index 7233229afe30d47466a191e201631165ee8b12a1..2201ed0190497039a2bf0e2683e693e24ee684e0 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -16,7 +16,7 @@
 
 include /Developer/Makefiles/pb_makefiles/platform.make
 
-MVERS = "mDNSResponder-320.10.80"
+MVERS = "mDNSResponder-320.14.0"
 
 DDNSWRITECONFIG = "$(DSTROOT)/Library/Application Support/Bonjour/ddnswriteconfig"
 
index ede13e9c794c8c04c41af861c3ce4b9266d70dc3..a07b8ee6389cbdb44d3126a0d3f1ef54ac0f077e 100755 (executable)
@@ -7074,11 +7074,15 @@ exit:
                        // *not* on a Microsoft Active Directory network, and there is no authoritative server for "local". Note that this is not
                        // in conflict with the mDNS spec, because that spec says, "Multicast DNS Zones have no SOA record," so it's okay to cache
                        // negative answers for "local. SOA" from a uDNS server, because the mDNS spec already says that such records do not exist :-)
+                       //
+                       // By suppressing negative responses, it might take longer to timeout a .local question as it might be expecting a
+                       // response e.g., we deliver a positive "A" response and suppress negative "AAAA" response and the upper layer may
+                       // be waiting longer to get the AAAA response before returning the "A" response to the application. To handle this
+                       // case without creating the negative cache entries, we generate a negative response and let the layer above us
+                       // do the appropriate thing. This negative response is also needed for appending new search domains.
                        if (!InterfaceID && q.qtype != kDNSType_SOA && IsLocalDomain(&q.qname))
                                {
-                               // If we did not find a positive answer and we can append search domains to this question,
-                               // generate a negative response (without creating a cache entry) to append search domains.
-                               if (qptr->AppendSearchDomains && !rr)
+                               if (!rr)
                                        {
                                        LogInfo("mDNSCoreReceiveResponse: Generate negative response for %##s (%s)", q.qname.c, DNSTypeName(q.qtype));
                                        m->CurrentQuestion = qptr;
@@ -10859,6 +10863,30 @@ mDNSlocal void mDNS_PurgeBeforeResolve(mDNS *const m, DNSQuestion *q)
                }
        }
 
+// Check for a positive unicast response to the question but with qtype
+mDNSexport mDNSBool mDNS_CheckForCacheRecord(mDNS *const m, DNSQuestion *q, mDNSu16 qtype)
+       {
+       DNSQuestion question;
+       const mDNSu32 slot = HashSlot(&q->qname);
+       CacheGroup *const cg = CacheGroupForName(m, slot, q->qnamehash, &q->qname);
+       CacheRecord *rp;
+
+       // Create an identical question but with qtype
+       mDNS_SetupQuestion(&question, q->InterfaceID, &q->qname, qtype, mDNSNULL, mDNSNULL);
+       question.qDNSServer = q->qDNSServer;
+
+       for (rp = cg ? cg->members : mDNSNULL; rp; rp = rp->next)
+               {
+               if (!rp->resrec.InterfaceID && rp->resrec.RecordType != kDNSRecordTypePacketNegative && 
+                       SameNameRecordAnswersQuestion(&rp->resrec, &question))
+                       {
+                       LogInfo("mDNS_CheckForCacheRecord: Found %s", CRDisplayString(m, rp));
+                       return mDNStrue;
+                       }
+               }
+       return mDNSfalse;
+       }
+
 mDNSlocal void CacheRecordResetDNSServer(mDNS *const m, DNSQuestion *q, DNSServer *new)
        {
        const mDNSu32 slot = HashSlot(&q->qname);
index 3d6c12a4ec300f5e8d6f0ac1a94c3a702abb8eb6..6756fe262f653ac245fb7559b719ca50020142b0 100755 (executable)
@@ -1466,10 +1466,11 @@ enum { NoAnswer_Normal = 0, NoAnswer_Suspended = 1, NoAnswer_Fail = 2 };
 #define MD5_LEN     16
 
 #define AutoTunnelUnregistered(X) (                                              \
-       (X)->AutoTunnelHostRecord.resrec.RecordType == kDNSRecordTypeUnregistered && \
-       (X)->AutoTunnelDeviceInfo.resrec.RecordType == kDNSRecordTypeUnregistered && \
-       (X)->AutoTunnelService.   resrec.RecordType == kDNSRecordTypeUnregistered && \
-       (X)->AutoTunnel6Record.   resrec.RecordType == kDNSRecordTypeUnregistered    )
+       (X)->AutoTunnelHostRecord. resrec.RecordType == kDNSRecordTypeUnregistered && \
+       (X)->AutoTunnelDeviceInfo. resrec.RecordType == kDNSRecordTypeUnregistered && \
+       (X)->AutoTunnelService.    resrec.RecordType == kDNSRecordTypeUnregistered && \
+       (X)->AutoTunnel6Record.    resrec.RecordType == kDNSRecordTypeUnregistered && \
+       (X)->AutoTunnel6MetaRecord.resrec.RecordType == kDNSRecordTypeUnregistered    )
 
 // Internal data structure to maintain authentication information
 typedef struct DomainAuthInfo
@@ -1481,7 +1482,8 @@ typedef struct DomainAuthInfo
        AuthRecord       AutoTunnelTarget;              // Opaque hostname of tunnel endpoint; used as SRV target for AutoTunnelService record
        AuthRecord       AutoTunnelDeviceInfo;  // Device info of tunnel endpoint
        AuthRecord       AutoTunnelService;             // Service record (possibly NAT-Mapped) of IKE daemon implementing tunnel endpoint
-       AuthRecord       AutoTunnel6Record;     // AutoTunnel AAAA Record obtained from Connectivityd
+       AuthRecord       AutoTunnel6Record;     // AutoTunnel AAAA record obtained from awacsd
+       AuthRecord       AutoTunnel6MetaRecord; // Notify remote peers to connect to the relay servers for potential outbound connections from this host
        NATTraversalInfo AutoTunnelNAT;
        domainname       domain;
        domainname       keyname;
@@ -2737,6 +2739,7 @@ extern AuthGroup *AuthGroupForName(AuthHash *r, const mDNSu32 slot, const mDNSu3
 extern AuthGroup *AuthGroupForRecord(AuthHash *r, const mDNSu32 slot, const ResourceRecord *const rr);
 extern AuthGroup *InsertAuthRecord(mDNS *const m, AuthHash *r, AuthRecord *rr);
 extern AuthGroup *RemoveAuthRecord(mDNS *const m, AuthHash *r, AuthRecord *rr);
+extern mDNSBool mDNS_CheckForCacheRecord(mDNS *const m, DNSQuestion *q, mDNSu16 qtype);
 
 // For now this AutoTunnel stuff is specific to Mac OS X.
 // In the future, if there's demand, we may see if we can abstract it out cleanly into the platform layer
@@ -2946,7 +2949,7 @@ struct CompileTimeAssertionChecks_mDNS
        char sizecheck_DNSServer           [(sizeof(DNSServer)            <=   320) ? 1 : -1];
        char sizecheck_NetworkInterfaceInfo[(sizeof(NetworkInterfaceInfo) <=  6850) ? 1 : -1];
        char sizecheck_ServiceRecordSet    [(sizeof(ServiceRecordSet)     <=  5500) ? 1 : -1];
-       char sizecheck_DomainAuthInfo      [(sizeof(DomainAuthInfo)       <=  7808) ? 1 : -1];
+       char sizecheck_DomainAuthInfo      [(sizeof(DomainAuthInfo)       <=  7968) ? 1 : -1];
        char sizecheck_ServiceInfoQuery    [(sizeof(ServiceInfoQuery)     <=  3200) ? 1 : -1];
 #if APPLE_OSX_mDNSResponder
        char sizecheck_ClientTunnel        [(sizeof(ClientTunnel)         <=  1148) ? 1 : -1];
index 47559a4bbc1fe4084a1e9b2693d45e8da93853bf..5c4e3a1748463f44c91bf8e37071dc16b79ef18a 100755 (executable)
@@ -384,12 +384,13 @@ mDNSexport mStatus mDNS_SetSecretForDomain(mDNS *m, DomainAuthInfo *info,
 
        // Caution: Only zero AutoTunnelHostRecord.namestorage and AutoTunnelNAT.clientContext AFTER we've determined that this is a NEW DomainAuthInfo
        // being added to the list. Otherwise we risk smashing our AutoTunnel host records and NATOperation that are already active and in use.
-       info->AutoTunnelHostRecord.resrec.RecordType = kDNSRecordTypeUnregistered;
-       info->AutoTunnelHostRecord.namestorage.c[0] = 0;
-       info->AutoTunnelTarget    .resrec.RecordType = kDNSRecordTypeUnregistered;
-       info->AutoTunnelDeviceInfo.resrec.RecordType = kDNSRecordTypeUnregistered;
-       info->AutoTunnelService   .resrec.RecordType = kDNSRecordTypeUnregistered;
-       info->AutoTunnel6Record   .resrec.RecordType = kDNSRecordTypeUnregistered;
+       info->AutoTunnelHostRecord .resrec.RecordType = kDNSRecordTypeUnregistered;
+       info->AutoTunnelHostRecord .namestorage.c[0] = 0;
+       info->AutoTunnelTarget     .resrec.RecordType = kDNSRecordTypeUnregistered;
+       info->AutoTunnelDeviceInfo .resrec.RecordType = kDNSRecordTypeUnregistered;
+       info->AutoTunnelService    .resrec.RecordType = kDNSRecordTypeUnregistered;
+       info->AutoTunnel6Record    .resrec.RecordType = kDNSRecordTypeUnregistered;
+       info->AutoTunnel6MetaRecord.resrec.RecordType = kDNSRecordTypeUnregistered;
        info->AutoTunnelNAT.clientContext = mDNSNULL;
        info->next = mDNSNULL;
        *p = info;
index 1ee1c1f325595e57340c533cc7ba5cf584acb4e7..07146cf44bb1a945410115a739abec332c3d258f 100644 (file)
@@ -204,6 +204,8 @@ static mDNSu8 SPMetricTotalPower    = 99;
 mDNSexport domainname ActiveDirectoryPrimaryDomain;
 mDNSexport int        ActiveDirectoryPrimaryDomainLabelCount;
 mDNSexport mDNSAddr   ActiveDirectoryPrimaryDomainServer;
+
+static mDNSBool AWACSDConnected = mDNSfalse;
 #endif // APPLE_OSX_mDNSResponder
 
 // Used by AutoTunnel
@@ -3699,6 +3701,41 @@ mDNSlocal void DeregisterAutoTunnelDevInfoRecord(mDNS *m, DomainAuthInfo *info)
        }
 #endif
 
+// pre-declaration
+mDNSlocal void AutoTunnelRecordCallback(mDNS *const m, AuthRecord *const rr, mStatus result);
+
+// Notify remote peers to connect to the relay servers for potential outbound connections from this host.
+// Caller should hold the lock. We don't call mDNS_Register (which acquires the lock) in this function because
+// sometimes the caller may already be holding the lock e.g., SetupLocalAutoTunnelInterface_internal and sometimes
+// not e.g., AutoTunnelHostNameChanged
+mDNSlocal void RegisterAutoTunnel6MetaRecord(mDNS *m, DomainAuthInfo *info)
+       {
+       mStatus err;
+
+       if (!m->mDNS_busy) LogMsg("RegisterAutoTunnel6MetaRecord: ERROR!! Lock not held");
+       
+       if (!AWACSDConnected)
+               {
+               LogInfo("RegisterAutoTunnel6MetaRecord no need to register");
+               return;
+               }
+
+       if (info->AutoTunnel6MetaRecord.resrec.RecordType == kDNSRecordTypeUnregistered)
+               {
+               mDNS_SetupResourceRecord(&info->AutoTunnel6MetaRecord, mDNSNULL, mDNSInterface_Any, kDNSType_PTR, kStandardTTL, kDNSRecordTypeUnregistered, AuthRecordAny, AutoTunnelRecordCallback, info);
+               AssignDomainName (&info->AutoTunnel6MetaRecord.namestorage, (const domainname*) "\x0C" "_autotunnel6");
+               AppendDomainName (&info->AutoTunnel6MetaRecord.namestorage, &info->domain);
+
+               info->AutoTunnel6MetaRecord.resrec.rdata->u.name.c[0] = 0;
+               AppendDomainLabel(&info->AutoTunnel6MetaRecord.resrec.rdata->u.name, &m->hostlabel);
+               AppendDomainName (&info->AutoTunnel6MetaRecord.resrec.rdata->u.name, &info->domain);
+               info->AutoTunnel6MetaRecord.resrec.RecordType = kDNSRecordTypeShared;
+
+               err = mDNS_Register_internal(m, &info->AutoTunnel6MetaRecord);
+               if (err) LogMsg("RegisterAutoTunnel6MetaRecord error %d registering %##s", err, info->AutoTunnel6MetaRecord.namestorage.c);
+               else LogInfo("RegisterAutoTunnel6MetaRecord registering %##s %##s", info->AutoTunnel6MetaRecord.namestorage.c, info->AutoTunnel6MetaRecord.resrec.rdata->u.name.c);
+               }
+       }
 
 // Caller should hold the lock. We don't call mDNS_Register (which acquires the lock) in this function because
 // sometimes the caller may already be holding the lock e.g., SetupLocalAutoTunnelInterface_internal and sometimes
@@ -3786,6 +3823,24 @@ mDNSlocal void RegisterAutoTunnel6Record(mDNS *m, DomainAuthInfo *info)
        UpdateAutoTunnelDomainStatus(m, info);
        }
 
+mDNSlocal void DeregisterAutoTunnel6MetaRecord(mDNS *m, DomainAuthInfo *info)
+       {
+       LogInfo("DeregisterAutoTunnel6MetaRecord %##s", info->domain.c);
+
+       if (info->AutoTunnel6MetaRecord.resrec.RecordType > kDNSRecordTypeDeregistering)
+               {
+               mStatus err = mDNS_Deregister(m, &info->AutoTunnel6MetaRecord);
+               if (err)
+                       {
+                       info->AutoTunnel6MetaRecord.resrec.RecordType = kDNSRecordTypeUnregistered;
+                       info->AutoTunnel6MetaRecord.resrec.rdata->u.name.c[0] = 0;
+                       LogMsg("DeregisterAutoTunnel6MetaRecord error %d deregistering %##s", err, info->AutoTunnel6MetaRecord.namestorage.c);
+                       }
+               else LogInfo("DeregisterAutoTunnel6MetaRecord: Deregistered record");
+               }
+       else LogInfo("DeregisterAutoTunnel6MetaRecord: Not deregistering record state:%d", info->AutoTunnel6MetaRecord.resrec.RecordType);
+       }
+
 mDNSlocal void DeregisterAutoTunnel6Record(mDNS *m, DomainAuthInfo *info)
        {
        LogInfo("DeregisterAutoTunnel6Record %##s", info->domain.c);
@@ -3846,6 +3901,12 @@ mDNSlocal void AutoTunnelRecordCallback(mDNS *const m, AuthRecord *const rr, mSt
                        info->AutoTunnel6Record.resrec.rdata->u.ipv6 = zerov6Addr;
                        RegisterAutoTunnel6Record(m,info);
                        }
+               else if (rr == &info->AutoTunnel6MetaRecord)
+                       {
+                       LogInfo("AutoTunnelRecordCallback: Calling RegisterAutoTunnel6MetaRecord");
+                       info->AutoTunnel6MetaRecord.resrec.rdata->u.name.c[0] = 0;
+                       RegisterAutoTunnel6MetaRecord(m,info);
+                       }
                }
        }
 
@@ -3858,6 +3919,7 @@ mDNSlocal void AutoTunnelDeleteAuthInfoState(mDNS *m, DomainAuthInfo *info)
        DeregisterAutoTunnelDevInfoRecord(m, info);
        DeregisterAutoTunnelServiceRecords(m, info);
        DeregisterAutoTunnel6Record(m, info);
+       DeregisterAutoTunnel6MetaRecord(m, info);
        UpdateAnonymousRacoonConfig(m);         // Determine whether we need racoon to accept incoming connections
        UpdateAutoTunnelDomainStatus(m, info);
        }
@@ -3900,11 +3962,13 @@ mDNSlocal void AutoTunnelHostNameChanged(mDNS *m, DomainAuthInfo *info)
 #endif
        DeregisterAutoTunnelServiceRecords(m, info);
        DeregisterAutoTunnel6Record(m, info);
+       DeregisterAutoTunnel6MetaRecord(m, info);
        RegisterAutoTunnelServiceRecords(m, info);
 
        mDNS_Lock(m);
        RegisterAutoTunnelDevInfoRecord(m, info);
        RegisterAutoTunnel6Record(m, info);
+       RegisterAutoTunnel6MetaRecord(m, info);
        m->NextSRVUpdate = NonZeroTime(m->timenow);
        mDNS_Unlock(m);
        }
@@ -5596,7 +5660,6 @@ mDNSlocal void UpdateBTMMRelayConnection(mDNS *const m)
        {
        DomainAuthInfo *BTMMDomain = mDNSNULL;
        DomainAuthInfo *FoundInList;
-       static mDNSBool AWACSDConnected = mDNSfalse;
        char AllUsers[1024];    // maximum size of mach message
        char AllPass[1024];     // maximum size of mach message
        char username[MAX_DOMAIN_LABEL + 1];
@@ -5635,6 +5698,14 @@ mDNSlocal void UpdateBTMMRelayConnection(mDNS *const m)
                LogInfo("UpdateBTMMRelayConnection: AWS_Connect for user %s", AllUsers);
                AWACS_Connect(AllUsers, AllPass, "hello.connectivity.me.com");
                AWACSDConnected = mDNStrue;
+               
+               // We have to do this after AWACSDConnected is true
+               for (FoundInList = m->AuthInfoList; FoundInList; FoundInList = FoundInList->next)
+                       if (!FoundInList->deltime && FoundInList->AutoTunnel && IsBTMMDomain(&FoundInList->domain))
+                               {
+                               LogInfo("UpdateBTMMRelayConnection RegisterAutoTunnel6MetaRecord: %##s", FoundInList->domain.c);
+                               RegisterAutoTunnel6MetaRecord(m, FoundInList);
+                               }
                }
        else
                {
@@ -6633,7 +6704,9 @@ mDNSlocal void AddAutoTunnel6Record(mDNS *const m, char *ifname, CFDictionaryRef
                // this case as though the dictionary does not have the value
                RemoveAutoTunnel6Record(m);
                // If awacsd crashes or exits for some reason, restart the relay connection
+               mDNS_Lock(m);
                UpdateBTMMRelayConnection(m);
+               mDNS_Unlock(m);
                return;
                }
        
@@ -6697,7 +6770,9 @@ mDNSlocal void ParseBackToMyMac(mDNS *const m, CFDictionaryRef connd)
                RemoveAutoTunnel6Record(m);
                m->AutoTunnelRelayAddrOut = zerov6Addr;
                // We don't have a utun interface, start the relay connection if possible
+               mDNS_Lock(m);
                UpdateBTMMRelayConnection(m);
+               mDNS_Unlock(m);
                }
        else
                {
@@ -7960,15 +8035,32 @@ mDNSlocal void mDNSMacOSXParseEtcHosts(mDNS *const m, int fd, AuthHash *auth)
 
                len = strlen(buf);
                if (!len) break;        // sanity check
-
+               //Check for end of line code(mostly only \n but pre-OS X Macs could have only \r)  
                if (buf[len - 1] == '\r' || buf[len - 1] == '\n')
+                       {
                        buf[len - 1] = '\0';
-
+                       len = len - 1;
+                       }
                // fgets always null terminates and hence even if we have no
-               // newline at the end, it is null terminated. The callee expects
-               // the length to be such that buf[length] to be zero and hence
-               // we pass len - 1.
-               mDNSMacOSXParseEtcHostsLine(m, buf, len - 1, auth);
+                // newline at the end, it is null terminated. The callee                                                                                                          
+                // (mDNSMacOSXParseEtcHostsLine) expects the length to be such that
+                // buf[length] is zero and hence we decrement len to reflect that.
+               if (len)
+                       {
+                       //Additional check when end of line code is 2 chars ie\r\n(DOS, other old OSes)
+                       //here we need to check for just \r but taking extra caution.
+                       if (buf[len - 1] == '\r' || buf[len - 1] == '\n')
+                               {
+                               buf[len - 1] = '\0';
+                               len = len - 1;
+                               }
+                       }
+               if (!len) //Sanity Check: len should never be zero
+                       {
+                       LogMsg("mDNSMacOSXParseEtcHosts: Length is zero!");
+                       continue;
+                       }
+               mDNSMacOSXParseEtcHostsLine(m, buf, len, auth);
                }
        fclose(fp);
        }
index 66f7410ae8ed4ae0cfc548e2dd5ae40adb3ab5fb..2ca9fc6f2dfffe1fabdd63035e5783905539dfc1 100644 (file)
@@ -335,13 +335,8 @@ mDNSexport int main(int argc, char **argv)
                        if (StopNow == 2) break;
                        }
 #endif
-               else {
-                       if (strlen(arg) >= sizeof(hostname)) {
-                               fprintf(stderr, "hostname must be < %d characters\n", (int)sizeof(hostname));
-                               goto usage;
-                       }
+               else
                        strcpy(hostname, arg);
-               }
        
                // Now we have the host name; get its A, AAAA, and HINFO
                if (hostname[0]) DoQuery(&q, hostname, kDNSQType_ANY, &target, InfoCallback);
@@ -373,6 +368,6 @@ mDNSexport int main(int argc, char **argv)
        return(0);
 
 usage:
-       fprintf(stderr, "Usage: %s <dot-local hostname> or <IPv4 address> or <IPv6 address> ...\n", progname);
+       fprintf(stderr, "%s <dot-local hostname> or <IPv4 address> or <IPv6 address> ...\n", progname);
        return(-1);
        }
index 55d7f8d7b717b0f1e9dfd550bc0cb090b6578bbe..6ca90136778e9bba9dee9cbe1c8e670d61d639b6 100755 (executable)
@@ -99,18 +99,12 @@ STRIP = strip
 endif
 else
 
-# any target that contains the string "linux"
-ifeq ($(findstring linux,$(os)),linux)
-CFLAGS_OS = -D_GNU_SOURCE -DHAVE_IPV6 -DNOT_HAVE_SA_LEN -DUSES_NETLINK -DHAVE_LINUX -DTARGET_OS_LINUX -fno-strict-aliasing
-LD = gcc -shared
+ifeq ($(os),linux)
+CFLAGS_OS = -DNOT_HAVE_SA_LEN -DUSES_NETLINK -DHAVE_LINUX -DTARGET_OS_LINUX
 FLEXFLAGS_OS = -l
 JAVACFLAGS_OS += -I$(JDK)/include/linux
-
-# uClibc does not support Name Service Switch
-ifneq ($(os),linux-uclibc)
 OPTIONALTARG = nss_mdns
 OPTINSTALL   = InstalledNSS
-endif
 else
 
 ifeq ($(os),netbsd)
@@ -120,9 +114,11 @@ else
 
 ifeq ($(os),freebsd)
 # If not already defined, set LOCALBASE to /usr/local
+# FreeBSD requires the startup script to end in ".sh"
 LOCALBASE?=/usr/local
 INSTBASE=$(LOCALBASE)
-CFLAGS_OS = -DHAVE_IPV6
+STARTUPSCRIPTNAME=mdns.sh
+CFLAGS_OS =
 # FreeBSD 4 requires threaded code to be compiled and linked using the "-pthread" option,
 # and requires that the "-lpthread" link option NOT be used
 # This appies only to FreeBSD -- "man cc" on FreeBSD says:
@@ -144,8 +140,7 @@ ifeq ($(os),x)
 # We have to define __MAC_OS_X_VERSION_MIN_REQUIRED=__MAC_OS_X_VERSION_10_4 or on Leopard
 # we get build failures: â€˜daemon’ is deprecated (declared at /usr/include/stdlib.h:283)
 CFLAGS_OS = -DHAVE_IPV6 -no-cpp-precomp -Werror -Wdeclaration-after-statement \
-       -D__MAC_OS_X_VERSION_MIN_REQUIRED=__MAC_OS_X_VERSION_10_4 \
-       -D__APPLE_USE_RFC_2292 #-Wunreachable-code
+       -D__MAC_OS_X_VERSION_MIN_REQUIRED=__MAC_OS_X_VERSION_10_4 #-Wunreachable-code
 CC = gcc
 LD = $(CC) -dynamiclib
 LINKOPTS = -lSystem
@@ -155,7 +150,7 @@ JAVACFLAGS_OS = -dynamiclib -I/System/Library/Frameworks/JavaVM.framework/Header
 else
 
 $(error ERROR: Must specify target OS on command-line, e.g. "make os=x [target]".\
-Supported operating systems include: x, linux, linux-uclibc, netbsd, freebsd, openbsd, solaris) 
+Supported operating systems include: x, linux, netbsd, freebsd, openbsd, solaris) 
 endif
 endif
 endif
index c2f56412a60dc8645912dba62ef9651cb5aac826..d4bff853b4c1b13801a209b2fb04b8ed85d4cde2 100755 (executable)
@@ -297,16 +297,6 @@ Networking, Communications, Hardware
 
 6 Aug 2002
 
-Impact: A local network user may cause a denial of the Bonjour service
-Description: An error handling issue exists in the Bonjour Namespace
-Provider. A local network user may send a maliciously crafted multicast
-DNS packet leading to an unexpected termination of the Bonjour service.
-This update addresses the issue by performing additional validation of
-multicast DNS packets. This issue does not affect systems running Mac OS
-X or Windows.
-CVE-ID
-CVE-2011-0220 : JaeSeung Song of the Department of Computing at Imperial
-College London
 
 To Do List
 ----------
index 38639ea1a917e5e9fc92eb5e5e9a15c3b8ba9607..21109b835cd495636d9c05cfe7145d6b721a10a0 100755 (executable)
@@ -453,12 +453,11 @@ static mStatus RegisterOneService(const char *  richTextName,
 
         if (gMDNSPlatformPosixVerboseLevel > 0) {
             fprintf(stderr, 
-                    "%s: Registered service %d, name \"%s\", type \"%s\", domain \"%s\",  port %ld\n", 
+                    "%s: Registered service %d, name '%s', type '%s', port %ld\n", 
                     gProgramName, 
                     thisServ->serviceID, 
                     richTextName,
                     serviceType,
-                    serviceDomain,
                     portNumber);
         }
     } else {
@@ -469,143 +468,108 @@ static mStatus RegisterOneService(const char *  richTextName,
     return status;
 }
 
-static mDNSBool ReadALine(char *buf, size_t bufSize, FILE *fp, mDNSBool skipBlankLines)
+static mDNSBool ReadALine(char *buf, size_t bufSize, FILE *fp)
+// Read a line, skipping over any blank lines or lines starting with '#'
 {
-       size_t  len;
-       mDNSBool readNextLine;
-
+       mDNSBool good, skip;
        do {
-               readNextLine = mDNSfalse;
-
-               if (fgets(buf, bufSize, fp) == NULL)
-                       return mDNSfalse;       // encountered EOF or an error condition
-
-               // These first characters indicate a blank line.
-               if (buf[0] == ' ' || buf[0] == '\t' || buf[0] == '\r' || buf[0] == '\n') {
-                       if (!skipBlankLines)
-                               return mDNSfalse;
-                       readNextLine = mDNStrue;
-               }
-               // always skip comment lines
-               if (buf[0] == '#')
-                       readNextLine = mDNStrue;
-
-       } while (readNextLine);
-
-       len = strlen( buf);
-       if ( buf[len - 1] == '\r' || buf[len - 1] == '\n')
-               buf[len - 1] = '\0';
-
-    return mDNStrue;
+               good = (fgets(buf, bufSize, fp) != NULL);
+               skip = (good && (buf[0] == '#'));
+       } while (good && skip);
+       if (good)
+       {
+               int             len = strlen( buf);
+               if ( buf[len - 1] == '\r' || buf[len - 1] == '\n')
+                       buf[len - 1] = '\0';
+       }
+    return good;
 }
 
 static mStatus RegisterServicesInFile(const char *filePath)
 {
     mStatus     status = mStatus_NoError;
     FILE *      fp = fopen(filePath, "r");
+    int         junk;
     
     if (fp == NULL) {
-        return mStatus_UnknownErr;
+        status = mStatus_UnknownErr;
     }
-
-       if (gMDNSPlatformPosixVerboseLevel > 1)
-               fprintf(stderr, "Parsing %s for services\n", filePath);
-
-       do {
-               char nameBuf[256];
-               char * name = nameBuf; 
-               char type[256];
-               const char *dom = kDefaultServiceDomain;
-               char rawText[1024];
-               mDNSu8  text[sizeof(RDataBody)];
-               unsigned int textLen = 0;
-               char port[256];
-               char *p;
-
-               // Read the service name, type, port, and optional text record fields.
-               // Skip blank lines while looking for the next service name.
-               if (! ReadALine(name, sizeof(nameBuf), fp, mDNStrue))
-                       break;
-
-               // Special case that allows service name to begin with a '#'
-               // character by escaping it with a '\' to distiguish it from
-               // a comment line.  Remove the leading '\' here before
-               // registering the service.
-               if (name[0] == '\\' && name[1] == '#')
-                       name++;
-
-               if (gMDNSPlatformPosixVerboseLevel > 1)
-                       fprintf(stderr, "Service name: \"%s\"\n", name);
-
-               // Don't skip blank lines in calls to ReadAline() after finding the
-               // service name since the next blank line indicates the end
-               // of this service record.
-               if (! ReadALine(type, sizeof(type), fp, mDNSfalse))
-                       break;
-
-               // see if a domain name is specified
-               p = type;
-               while (*p && *p != ' ' && *p != '\t') p++;
-               if (*p) {
-                       *p = 0; // NULL terminate the <type>.<protocol> string
-                       // skip any leading whitespace before domain name
-                       p++;
-                       while (*p && (*p == ' ' || *p == '\t')) p++;
-                       if (*p)
-                               dom = p;
-               }
-               if (gMDNSPlatformPosixVerboseLevel > 1) {
-                       fprintf(stderr, "Service type: \"%s\"\n", type);
-                       fprintf(stderr, "Service domain: \"%s\"\n", dom);
-               }
-
-               if (! ReadALine(port, sizeof(port), fp, mDNSfalse))
-                       break;
-               if (gMDNSPlatformPosixVerboseLevel > 1)
-                       fprintf(stderr, "Service port: %s\n", port);
-
-               if (   ! CheckThatRichTextNameIsUsable(name, mDNStrue)
-                       || ! CheckThatServiceTypeIsUsable(type, mDNStrue)
-                       || ! CheckThatPortNumberIsUsable(atol(port), mDNStrue))
-                       break;
-
-               // read the TXT record fields
-               while (1) {
-                       int len;
-                       if (!ReadALine(rawText, sizeof(rawText), fp, mDNSfalse)) break;
-                       if (gMDNSPlatformPosixVerboseLevel > 1)
-                               fprintf(stderr, "Text string: \"%s\"\n", rawText);
-                       len = strlen(rawText);
-                       if (len <= 255)
-                               {
-                               unsigned int newlen = textLen + 1 + len;
-                               if (len == 0 || newlen >= sizeof(text)) break;
-                               text[textLen] = len;
-                               mDNSPlatformMemCopy(text + textLen + 1, rawText, len);
-                               textLen = newlen;
+    if (status == mStatus_NoError) {
+        mDNSBool good = mDNStrue;
+        do {
+                       int         ch;
+                       char name[256];
+                       char type[256];
+                       const char *dom = kDefaultServiceDomain;
+                       char rawText[1024];
+                       mDNSu8  text[sizeof(RDataBody)];
+                       unsigned int textLen = 0;
+                       char port[256];
+
+            // Skip over any blank lines.
+            do ch = fgetc(fp); while ( ch == '\n' || ch == '\r' );
+            if (ch != EOF) good = (ungetc(ch, fp) == ch);
+            
+            // Read three lines, check them for validity, and register the service.
+                       good = ReadALine(name, sizeof(name), fp);               
+                       if (good) {
+                               good = ReadALine(type, sizeof(type), fp);
+                       }
+                       if (good) {
+                               char *p = type;
+                               while (*p && *p != ' ') p++;
+                               if (*p) {
+                                       *p = 0;
+                                       dom = p+1;
                                }
-                       else
-                               fprintf(stderr, "%s: TXT attribute too long for name = %s, type = %s, port = %s\n", 
-                                       gProgramName, name, type, port);
-               }
-
-               status = RegisterOneService(name, type, dom, text, textLen, atol(port));
-               if (status != mStatus_NoError) {
-                       // print error, but try to read and register other services in the file
-                       fprintf(stderr, "%s: Failed to register service, name \"%s\", type \"%s\", domain \"%s\", port %s\n", 
-                                       gProgramName, name, type, dom, port);
-               }
-
-       } while (!feof(fp));
+                       }
+                       if (good) {
+                               good = ReadALine(port, sizeof(port), fp);
+                       }
+                       if (good) {
+                               good =     CheckThatRichTextNameIsUsable(name, mDNSfalse)
+                                               && CheckThatServiceTypeIsUsable(type, mDNSfalse)
+                                               && CheckThatPortNumberIsUsable(atol(port), mDNSfalse);
+                       }
+                       if (good) {
+                               while (1) {
+                                       int len;
+                                       if (!ReadALine(rawText, sizeof(rawText), fp)) break;
+                                       len = strlen(rawText);
+                                       if (len <= 255)
+                                               {
+                                               unsigned int newlen = textLen + 1 + len;
+                                               if (len == 0 || newlen >= sizeof(text)) break;
+                                               text[textLen] = len;
+                                               mDNSPlatformMemCopy(text + textLen + 1, rawText, len);
+                                               textLen = newlen;
+                                               }
+                                       else
+                                               fprintf(stderr, "%s: TXT attribute too long for name = %s, type = %s, port = %s\n", 
+                                                       gProgramName, name, type, port);
+                               }
+                       }
+                       if (good) {
+                               status = RegisterOneService(name, type, dom, text, textLen, atol(port));
+                               if (status != mStatus_NoError) {
+                                       fprintf(stderr, "%s: Failed to register service, name = %s, type = %s, port = %s\n", 
+                                                       gProgramName, name, type, port);
+                                       status = mStatus_NoError;       // keep reading
+                               }
+                       }
+        } while (good && !feof(fp));
 
-       if (!feof(fp)) {
-               fprintf(stderr, "%s: Error reading service file %s\n", gProgramName, filePath);
-               status = mStatus_UnknownErr;
-       }
+        if ( ! good ) {
+            fprintf(stderr, "%s: Error reading service file %s\n", gProgramName, filePath);
+        }
+    }
     
-       assert(0 == fclose(fp));
+    if (fp != NULL) {
+        junk = fclose(fp);
+        assert(junk == 0);
+    }
     
-       return status;
+    return status;
 }
 
 static mStatus RegisterOurServices(void)
index f8d69786a4ec57953fbdfed0c694422ea517dc73..f5870bb96a028fa82b88ae31ba60ad85734c9714 100755 (executable)
@@ -1,36 +1,15 @@
-#
-# Example services file parsed by mDNSResponderPosix.
-# 
-# Lines beginning with '#' are comments/ignored.
-# Blank lines indicate the end of a service record specification.
-# The first character of the service name can be a '#' if you escape it with 
-# backslash to distinguish if from a comment line.
-# ie, "\#serviceName" will be registered as "#serviceName".
-# Note that any line beginning with white space is considered a blank line.
-#
-# The record format is:
-# 
-# <service name>
-# <type>.<protocol> <optional domain>
-# <port number>
-# <zero or more strings for the text record, one string per line>
-#
-# <One or more blank lines between records>
-# 
-# Examples shown below.
-
-serviceName1
+Tweedlebug
 _afpovertcp._tcp.
 548
 name=val1
 
-serviceName2
+Tweedlebug2
 _afpovertcp._tcp. local.
 548
 name=val2
 name2=anotherattribute
 
-serviceName3
+Tweedlebug3
 _afpovertcp._tcp.
 548
 name=val3
index 74a21618edde52ede63005c8fce5bbb24d4b35fb..3db5266ff217d9d060f4a451d2e7e7cc5ddbcffc 100755 (executable)
@@ -159,12 +159,8 @@ mDNSexport mStatus mDNSPlatformSendUDP(const mDNS *const m, const void *const ms
        assert(msg != NULL);
        assert(end != NULL);
        assert((((char *) end) - ((char *) msg)) > 0);
+       assert(dstPort.NotAnInteger != 0);
 
-       if (dstPort.NotAnInteger == 0) 
-               {
-               LogMsg("mDNSPlatformSendUDP: Invalid argument -dstPort is set to 0");
-               return PosixErrorToStatus(EINVAL);
-               }
        if (dst->type == mDNSAddrType_IPv4)
                {
                struct sockaddr_in *sin = (struct sockaddr_in*)&to;
@@ -718,7 +714,7 @@ mDNSlocal int SetupSocket(struct sockaddr *intfAddr, mDNSIPPort port, int interf
        #if defined(IPV6_PKTINFO)
                if (err == 0)
                        {
-                               err = setsockopt(*sktPtr, IPPROTO_IPV6, IPV6_2292_PKTINFO, &kOn, sizeof(kOn));
+                               err = setsockopt(*sktPtr, IPPROTO_IPV6, IPV6_PKTINFO, &kOn, sizeof(kOn));
                                if (err < 0) { err = errno; perror("setsockopt - IPV6_PKTINFO"); }
                        }
        #else
@@ -727,7 +723,7 @@ mDNSlocal int SetupSocket(struct sockaddr *intfAddr, mDNSIPPort port, int interf
        #if defined(IPV6_HOPLIMIT)
                if (err == 0)
                        {
-                               err = setsockopt(*sktPtr, IPPROTO_IPV6, IPV6_2292_HOPLIMIT, &kOn, sizeof(kOn));
+                               err = setsockopt(*sktPtr, IPPROTO_IPV6, IPV6_HOPLIMIT, &kOn, sizeof(kOn));
                                if (err < 0) { err = errno; perror("setsockopt - IPV6_HOPLIMIT"); }
                        }
        #endif
@@ -845,7 +841,6 @@ mDNSlocal int SetupOneInterface(mDNS *const m, struct sockaddr *intfAddr, struct
                // Set up the fields required by the mDNS core.
                SockAddrTomDNSAddr(intfAddr, &intf->coreIntf.ip, NULL);
                SockAddrTomDNSAddr(intfMask, &intf->coreIntf.mask, NULL);
-
                //LogMsg("SetupOneInterface: %#a %#a",  &intf->coreIntf.ip,  &intf->coreIntf.mask);
                strncpy(intf->coreIntf.ifname, intfName, sizeof(intf->coreIntf.ifname));
                intf->coreIntf.ifname[sizeof(intf->coreIntf.ifname)-1] = 0;
index 8027676cfe3bafc7d58bc271f03846533a77210b..e8fc649a5d99a12588a82a6abd33c86161950e10 100755 (executable)
@@ -82,7 +82,7 @@ void plen_to_mask(int plen, char *addr) {
 /* Gets IPv6 interface information from the /proc filesystem in linux*/
 struct ifi_info *get_ifi_info_linuxv6(int family, int doaliases)
        {
-               struct ifi_info *ifi, *ifihead, **ifipnext, *ifipold, **ifiptr;
+       struct ifi_info *ifi, *ifihead, **ifipnext;
        FILE *fp;
        char addr[8][5];
        int flags, myflags, index, plen, scope;
@@ -92,8 +92,6 @@ struct ifi_info *get_ifi_info_linuxv6(int family, int doaliases)
        struct sockaddr_in6 *sin6;
        struct in6_addr *addrptr;
        int err;
-       int sockfd = -1;
-       struct ifreq ifr;
 
        res0=NULL;
        ifihead = NULL;
@@ -101,10 +99,6 @@ struct ifi_info *get_ifi_info_linuxv6(int family, int doaliases)
        lastname[0] = 0;
 
        if ((fp = fopen(PROC_IFINET6_PATH, "r")) != NULL) {
-               sockfd = socket(AF_INET6, SOCK_DGRAM, 0);
-               if (sockfd < 0) {
-                       goto gotError;
-               }
                while (fscanf(fp,
                                          "%4s%4s%4s%4s%4s%4s%4s%4s %02x %02x %02x %02x %8s\n",
                                          addr[0],addr[1],addr[2],addr[3],
@@ -121,10 +115,8 @@ struct ifi_info *get_ifi_info_linuxv6(int family, int doaliases)
                        ifi = (struct ifi_info*)calloc(1, sizeof(struct ifi_info));
                        if (ifi == NULL) {
                                goto gotError;
-                       }
-                       
-                       ifipold   = *ifipnext;       /* need this later */
-                       ifiptr    = ifipnext;
+                               }
+
                        *ifipnext = ifi;            /* prev points to this new one */
                        ifipnext = &ifi->ifi_next;  /* pointer to next one goes here */
 
@@ -169,25 +161,9 @@ struct ifi_info *get_ifi_info_linuxv6(int family, int doaliases)
                        /* Add interface index */
                        ifi->ifi_index = index;
 
-                       /* Add interface flags*/
-                       memcpy(ifr.ifr_name, ifname, IFNAMSIZ);
-                       if (ioctl(sockfd, SIOCGIFFLAGS, &ifr) < 0) {
-                               if (errno == EADDRNOTAVAIL) {
-                                       /* 
-                                        * If the main interface is configured with no IP address but 
-                                        * an alias interface exists with an IP address, you get 
-                                        * EADDRNOTAVAIL for the main interface 
-                                        */
-                                       free(ifi->ifi_addr);
-                                       free(ifi);
-                                       ifipnext  = ifiptr; 
-                                       *ifipnext = ifipold;
-                                       continue;
-                               } else {
-                                       goto gotError;
-                               }
-                       }
-                       ifi->ifi_flags = ifr.ifr_flags;
+                       /* If interface is in /proc then it is up*/
+                       ifi->ifi_flags = IFF_UP;
+
                        freeaddrinfo(res0);
                        res0=NULL;
                        }
@@ -204,9 +180,6 @@ struct ifi_info *get_ifi_info_linuxv6(int family, int doaliases)
                res0=NULL;
                }
        done:
-       if (sockfd != -1) {
-               assert(close(sockfd) == 0);
-       }
        return(ifihead);    /* pointer to first structure in linked list */
        }
 #endif // defined(AF_INET6) && HAVE_IPV6 && HAVE_LINUX
@@ -214,7 +187,7 @@ struct ifi_info *get_ifi_info_linuxv6(int family, int doaliases)
 struct ifi_info *get_ifi_info(int family, int doaliases)
 {
     int                 junk;
-    struct ifi_info     *ifi, *ifihead, **ifipnext, *ifipold, **ifiptr;
+    struct ifi_info     *ifi, *ifihead, **ifipnext;
     int                 sockfd, sockf6, len, lastlen, flags, myflags;
 #ifdef NOT_HAVE_IF_NAMETOINDEX
     int                 index = 200;
@@ -306,11 +279,9 @@ struct ifi_info *get_ifi_info(int family, int doaliases)
         if (ifi == NULL) {
             goto gotError;
         }
-               ifipold   = *ifipnext;       /* need this later */
-               ifiptr    = ifipnext;
-               *ifipnext = ifi;             /* prev points to this new one */
-               ifipnext  = &ifi->ifi_next;  /* pointer to next one goes here */
-               
+        *ifipnext = ifi;            /* prev points to this new one */
+        ifipnext = &ifi->ifi_next;  /* pointer to next one goes here */
+
         ifi->ifi_flags = flags;     /* IFF_xxx values */
         ifi->ifi_myflags = myflags; /* IFI_xxx values */
 #ifndef NOT_HAVE_IF_NAMETOINDEX
@@ -339,23 +310,7 @@ struct ifi_info *get_ifi_info(int family, int doaliases)
                 memcpy(ifi->ifi_addr, sinptr, sizeof(struct sockaddr_in));
 
 #ifdef  SIOCGIFNETMASK
-                               if (ioctl(sockfd, SIOCGIFNETMASK, &ifrcopy) < 0) {
-                                       if (errno == EADDRNOTAVAIL) {
-                                               /* 
-                                                * If the main interface is configured with no IP address but 
-                                                * an alias interface exists with an IP address, you get 
-                                                * EADDRNOTAVAIL for the main interface 
-                                                */
-                                               free(ifi->ifi_addr);
-                                               free(ifi);
-                                               ifipnext  = ifiptr; 
-                                               *ifipnext = ifipold;
-                                               continue;
-                                       } else {
-                                               goto gotError;
-                                       }                               
-                               }
-
+                               if (ioctl(sockfd, SIOCGIFNETMASK, &ifrcopy) < 0) goto gotError;
                                ifi->ifi_netmask = (struct sockaddr*)calloc(1, sizeof(struct sockaddr_in));
                                if (ifi->ifi_netmask == NULL) goto gotError;
                                sinptr = (struct sockaddr_in *) &ifrcopy.ifr_addr;
@@ -430,22 +385,7 @@ struct ifi_info *get_ifi_info(int family, int doaliases)
                                memset(&ifr6, 0, sizeof(ifr6));
                                memcpy(&ifr6.ifr_name,           &ifr->ifr_name, sizeof(ifr6.ifr_name          ));
                                memcpy(&ifr6.ifr_ifru.ifru_addr, &ifr->ifr_addr, sizeof(ifr6.ifr_ifru.ifru_addr));
-                               if (ioctl(sockf6, SIOCGIFNETMASK_IN6, &ifr6) < 0) {
-                                       if (errno == EADDRNOTAVAIL) {
-                                               /* 
-                                                * If the main interface is configured with no IP address but 
-                                                * an alias interface exists with an IP address, you get 
-                                                * EADDRNOTAVAIL for the main interface 
-                                                */
-                                               free(ifi->ifi_addr);
-                                               free(ifi);
-                                               ifipnext  = ifiptr; 
-                                               *ifipnext = ifipold;
-                                               continue;
-                                       } else {
-                                               goto gotError;
-                                       }                               
-                               }
+                               if (ioctl(sockf6, SIOCGIFNETMASK_IN6, &ifr6) < 0) goto gotError;
                                ifi->ifi_netmask = (struct sockaddr*)calloc(1, sizeof(struct sockaddr_in6));
                                if (ifi->ifi_netmask == NULL) goto gotError;
                                sinptr6 = (struct sockaddr_in6 *) &ifr6.ifr_ifru.ifru_addr;
@@ -636,9 +576,9 @@ struct in_pktinfo
         }
 #endif
 
-#if defined(IPV6_PKTINFO) && HAVE_IPV6 
-               if (cmptr->cmsg_level == IPPROTO_IPV6 && 
-            cmptr->cmsg_type  == IPV6_2292_PKTINFO) {
+#if defined(IPV6_PKTINFO) && HAVE_IPV6
+        if (cmptr->cmsg_level == IPPROTO_IPV6 && 
+            cmptr->cmsg_type == IPV6_PKTINFO) {
             struct sockaddr_in6 *sin6 = (struct sockaddr_in6*)&pktp->ipi_addr;
                        struct in6_pktinfo *ip6_info = (struct in6_pktinfo*)CMSG_DATA(cmptr);
                        
@@ -657,7 +597,7 @@ struct in_pktinfo
 
 #if defined(IPV6_HOPLIMIT) && HAVE_IPV6
         if (cmptr->cmsg_level == IPPROTO_IPV6 && 
-            cmptr->cmsg_type == IPV6_2292_HOPLIMIT) {
+            cmptr->cmsg_type == IPV6_HOPLIMIT) {
                        *ttl = *(int*)CMSG_DATA(cmptr);
             continue;
         }
index 6b04601f5095287e926f656e4b5200887e10614f..59b5501b37bf5c58a42879893a8f275f3eb94753 100755 (executable)
 
 #ifdef HAVE_LINUX
 #include <linux/socket.h>
-#define IPV6_2292_PKTINFO  IPV6_2292PKTINFO
-#define IPV6_2292_HOPLIMIT IPV6_2292HOPLIMIT
-#else
-// The following are the supported non-linux posix OSes -
-// netbsd, freebsd and openbsd.
-#if HAVE_IPV6
-#define IPV6_2292_PKTINFO  19
-#define IPV6_2292_HOPLIMIT 20
-#endif 
 #endif
 
 #ifdef  __cplusplus
index be49257df3328cdaec97b66b6601aaad6eee0d66..1261f1d5ab3e0e3cb5ce4f65bbeff6f7ac6dadf7 100644 (file)
        #endif
 #endif
 
-// FreeBSD
-
-#if( !defined( TARGET_OS_FREEBSD ) )
-       #if( defined( __FreeBSD__ ) )
-               #define TARGET_OS_FREEBSD               1
-       #else
-               #define TARGET_OS_FREEBSD               0
-       #endif
-#endif
-
 // Linux
 
 #if( !defined( TARGET_OS_LINUX ) )
        
        // No predefined macro for VxWorks so just assume VxWorks if nothing else is set.
        
-       #if( !macintosh && !__MACH__  && !defined( __FreeBSD__ ) && !defined( __linux__ ) && !defined ( __SVR4 ) && !defined ( __sun ) && !defined( __PALMOS_TRAPS__ ) && !defined( __PALMOS_ARMLET__ ) && !defined( _WIN32 ) )
+       #if( !macintosh && !__MACH__  && !defined( __linux__ ) && !defined ( __SVR4 ) && !defined ( __sun ) && !defined( __PALMOS_TRAPS__ ) && !defined( __PALMOS_ARMLET__ ) && !defined( _WIN32 ) )
                #define TARGET_OS_VXWORKS               1
        #else
                #define TARGET_OS_VXWORKS               0
        #include        <libkern/OSTypes.h>
        #include        <sys/types.h>
        
-#elif( TARGET_OS_FREEBSD )
-
-       // FreeBSD
-       #include        <stdint.h>
-       #include        <pthread.h>
-       #include        <netinet/in.h>
-       #include        <arpa/inet.h>
-       #include        <sys/socket.h>
-
 #elif( TARGET_OS_LINUX )
        
        // Linux
 // - Windows
 
 #if( TARGET_LANGUAGE_C_LIKE )
-       #if( !defined(_SSIZE_T) && ( TARGET_OS_WIN32 || !defined( _BSD_SSIZE_T_DEFINED_ ) ) && !TARGET_OS_FREEBSD && !TARGET_OS_LINUX && !TARGET_OS_VXWORKS && !TARGET_OS_MAC)
+       #if( !defined(_SSIZE_T) && ( TARGET_OS_WIN32 || !defined( _BSD_SSIZE_T_DEFINED_ ) ) && !TARGET_OS_LINUX && !TARGET_OS_VXWORKS && !TARGET_OS_MAC)
                typedef int                                             ssize_t;
        #endif
 #endif
index 607ebcd11846639f5dd2e2c2c6ce7f55c5337614..45735c38a06162c4db04ada5efeeffd0a38d1732 100644 (file)
@@ -77,7 +77,7 @@
  */
 
 #ifndef _DNS_SD_H
-#define _DNS_SD_H 3201080
+#define _DNS_SD_H 3201400
 
 #ifdef  __cplusplus
     extern "C" {
index cfdc1bda411a1e2851e8b362fb0cdf06e248a363..c3673a7a940eb3810f69027048e629973db25cc3 100644 (file)
@@ -2504,6 +2504,9 @@ mDNSlocal mStatus SendAdditionalQuery(DNSQuestion *q, request_state *request, mS
                        *q2               = *q;
                        q2->InterfaceID   = mDNSInterface_Unicast;
                        q2->ExpectUnique  = mDNStrue;
+                       // Always set the QuestionContext to indicate that this question should be stopped
+                       // before freeing. Don't rely on "q".
+                       q2->QuestionContext = request;
                        // If the query starts as a single label e.g., somehost, and we have search domains with .local,
                        // queryrecord_result_callback calls this function when .local is appended to "somehost".
                        // At that time, the name in "q" is pointing at somehost.local and its qnameOrig pointing at
@@ -2727,8 +2730,26 @@ mDNSlocal void queryrecord_result_callback(mDNS *const m, DNSQuestion *question,
                        {
                        if (!answer->InterfaceID && IsLocalDomain(answer->name))
                                {
-                               LogInfo("queryrecord_result_callback:Question %##s (%s) answering local with unicast", question->qname.c, DNSTypeName(question->qtype));
-                               return;
+                               mDNSu16 qtype;
+                               // Sanity check: "q" will be set only if "question" is the .local unicast query.
+                               if (!q)
+                                       {
+                                       LogMsg("queryrecord_result_callback: ERROR!! answering multicast question with unicast cache record");
+                                       return;
+                                       }
+                               // Deliver negative response for A/AAAA if there was a positive response for AAAA/A respectively.
+                               if (question->qtype != kDNSType_A && question->qtype != kDNSType_AAAA)
+                                       {
+                                       LogInfo("queryrecord_result_callback:Question %##s (%s) not answering local question with negative unicast response", question->qname.c, DNSTypeName(question->qtype));
+                                       return;
+                                       }
+                               qtype = (question->qtype == kDNSType_A ? kDNSType_AAAA : kDNSType_A);
+                               if (!mDNS_CheckForCacheRecord(m, question, qtype))
+                                       {
+                                       LogInfo("queryrecord_result_callback:Question %##s (%s) not answering local question with negative unicast response (can't find positive record)", question->qname.c, DNSTypeName(question->qtype));
+                                       return;
+                                       }
+                               LogInfo("queryrecord_result_callback:Question %##s (%s) answering local with negative unicast response (found positive record)", question->qname.c, DNSTypeName(question->qtype));
                                }
                        error = kDNSServiceErr_NoSuchRecord;
                        }
@@ -3994,11 +4015,6 @@ mDNSexport int udsserver_init(dnssd_sock_t skts[], mDNSu32 count)
                        // determine whether sa_len is defined on a particular platform.
                        laddr.sun_len = sizeof(struct sockaddr_un);
                        #endif
-                       if (strlen(MDNS_UDS_SERVERPATH) >= sizeof(laddr.sun_path))
-                               {
-                                       LogMsg("ERROR: MDNS_UDS_SERVERPATH must be < %d characters", (int)sizeof(laddr.sun_path));
-                                       goto error;
-                               }
                        mDNSPlatformStrCopy(laddr.sun_path, MDNS_UDS_SERVERPATH);
                        ret = bind(listenfd, (struct sockaddr *) &laddr, sizeof(laddr));
                        umask(mask);