diff options
author | Toomas Soome <tsoome@me.com> | 2016-06-21 15:45:49 +0300 |
---|---|---|
committer | Robert Mustacchi <rm@joyent.com> | 2016-07-22 07:39:00 -0700 |
commit | cda73f64f20b8a0afc4909f5ea1f055ec7913856 (patch) | |
tree | 6f93e00913bd2c9f2aab6396979ba091da82dde6 | |
parent | 6da83bb0b886fae280a129718d645576517b62c6 (diff) | |
download | illumos-joyent-cda73f64f20b8a0afc4909f5ea1f055ec7913856.tar.gz |
7139 Sync mDNS with mDNSResponder-625.41.2
Reviewed by: Dan McDonald <danmcd@omniti.com>
Reviewed by: Andy Stormont <astormont@racktopsystems.com>
Approved by: Robert Mustacchi <rm@joyent.com>
30 files changed, 1067 insertions, 954 deletions
diff --git a/usr/src/cmd/cmd-inet/usr.bin/dns-sd/ClientCommon.c b/usr/src/cmd/cmd-inet/usr.bin/dns-sd/ClientCommon.c index 68f354ccac..cb59e7b9b8 100644 --- a/usr/src/cmd/cmd-inet/usr.bin/dns-sd/ClientCommon.c +++ b/usr/src/cmd/cmd-inet/usr.bin/dns-sd/ClientCommon.c @@ -1,8 +1,8 @@ /* -*- Mode: C; tab-width: 4 -*- * - * Copyright (c) 2008 Apple Inc. All rights reserved. + * Copyright (c) 2008-2011 Apple Inc. All rights reserved. * - * Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc. + * Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Inc. * ("Apple") in consideration of your agreement to the following terms, and your * use, installation, modification or redistribution of this Apple software * constitutes acceptance of these terms. If you do not agree with these terms, @@ -16,7 +16,7 @@ * the Apple Software in its entirety and without modifications, you must retain * this notice and the following text and disclaimers in all such redistributions of * the Apple Software. Neither the name, trademarks, service marks or logos of - * Apple Computer, Inc. may be used to endorse or promote products derived from the + * Apple Inc. may be used to endorse or promote products derived from the * Apple Software without specific prior written permission from Apple. Except as * expressly stated in this notice, no other rights or licenses, express or implied, * are granted by Apple herein, including but not limited to any patent rights that diff --git a/usr/src/cmd/cmd-inet/usr.bin/dns-sd/Makefile b/usr/src/cmd/cmd-inet/usr.bin/dns-sd/Makefile index 01c94af04d..293a4f5976 100644 --- a/usr/src/cmd/cmd-inet/usr.bin/dns-sd/Makefile +++ b/usr/src/cmd/cmd-inet/usr.bin/dns-sd/Makefile @@ -37,12 +37,11 @@ $(PROG): $(OBJS) $(LINK.c) $(OBJS) -o $@ $(LDLIBS) $(POST_PROCESS) -install: all $(ROOTPROG) +install: all $(ROOTPROG) clean: $(RM) $(OBJS) -lint: lint_SRCS +lint: lint_SRCS include ../../../Makefile.targ - diff --git a/usr/src/cmd/cmd-inet/usr.bin/dns-sd/dns-sd.c b/usr/src/cmd/cmd-inet/usr.bin/dns-sd/dns-sd.c index 3be1426794..9199887c5e 100644 --- a/usr/src/cmd/cmd-inet/usr.bin/dns-sd/dns-sd.c +++ b/usr/src/cmd/cmd-inet/usr.bin/dns-sd/dns-sd.c @@ -1,8 +1,8 @@ /* -*- Mode: C; tab-width: 4 -*- * - * Copyright (c) 2002-2013 Apple Inc. All rights reserved. + * Copyright (c) 2002-2015 Apple Inc. All rights reserved. * - * Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc. + * Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Inc. * ("Apple") in consideration of your agreement to the following terms, and your * use, installation, modification or redistribution of this Apple software * constitutes acceptance of these terms. If you do not agree with these terms, @@ -16,7 +16,7 @@ * the Apple Software in its entirety and without modifications, you must retain * this notice and the following text and disclaimers in all such redistributions of * the Apple Software. Neither the name, trademarks, service marks or logos of - * Apple Computer, Inc. may be used to endorse or promote products derived from the + * Apple Inc. may be used to endorse or promote products derived from the * Apple Software without specific prior written permission from Apple. Except as * expressly stated in this notice, no other rights or licenses, express or implied, * are granted by Apple herein, including but not limited to any patent rights that @@ -57,14 +57,6 @@ // aren't in the system's /usr/lib/libSystem.dylib. //#define TEST_NEW_CLIENTSTUB 1 -// When building mDNSResponder for Mac OS X 10.4 and earlier, /usr/lib/libSystem.dylib is built using its own private -// copy of dnssd_clientstub.c, which is old and doesn't have all the entry points defined in the latest version, so -// when we're building dns-sd.c on Mac OS X 10.4 or earlier, we automatically set TEST_NEW_CLIENTSTUB so that we'll -// embed a copy of the latest dnssd_clientstub.c instead of trying to link to the incomplete version in libSystem.dylib -#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ <= 1040 -#define TEST_NEW_CLIENTSTUB 1 -#endif - #include <ctype.h> #include <stdio.h> // For stdout, stderr #include <stdlib.h> // For exit() @@ -185,14 +177,6 @@ static const char kFilePathSep = '/'; #include <dispatch/private.h> #endif -// The "+0" is to cope with the case where _DNS_SD_H is defined but empty (e.g. on Mac OS X 10.4 and earlier) -#if _DNS_SD_H+0 >= 116 -#define HAS_NAT_PMP_API 1 -#define HAS_ADDRINFO_API 1 -#else -#define kDNSServiceFlagsReturnIntermediates 0 -#endif - //************************************************************************************************************* // Globals @@ -421,7 +405,6 @@ done: #endif //_DNS_SD_LIBDISPATCH } -#if HAS_NAT_PMP_API | HAS_ADDRINFO_API static DNSServiceProtocol GetProtocol(const char *s) { if (!strcasecmp(s, "v4" )) return(kDNSServiceProtocol_IPv4); @@ -434,7 +417,6 @@ static DNSServiceProtocol GetProtocol(const char *s) else if (!strcasecmp(s, "tcpudp" )) return(kDNSServiceProtocol_UDP | kDNSServiceProtocol_TCP); else return(atoi(s)); } -#endif //************************************************************************************************************* @@ -494,18 +476,14 @@ static void print_usage(const char *arg0, int print_all) fprintf(stderr, "%s -q <name> <rrtype> <rrclass> (Generic query for any record type)\n", arg0); fprintf(stderr, "%s -D <name> <rrtype> <rrclass>(Validate query for any record type with DNSSEC)\n", arg0); fprintf(stderr, "%s -Z <Type> <Domain> (Output results in Zone File format)\n", arg0); -#if HAS_ADDRINFO_API fprintf(stderr, "%s -G v4/v6/v4v6 <name> (Get address information for hostname)\n", arg0); fprintf(stderr, "%s -g v4/v6/v4v6 <name> (Validate address info for hostname with DNSSEC)\n", arg0); -#endif fprintf(stderr, "%s -V (Get version of currently running daemon / system service)\n", arg0); if (print_all) //Print all available options for dns-sd tool { fprintf(stderr, "%s -C <FQDN> <rrtype> <rrclass> (Query; reconfirming each result)\n", arg0); -#if HAS_NAT_PMP_API fprintf(stderr, "%s -X udp/tcp/udptcp <IntPort> <ExtPort> <TTL> (NAT Port Mapping)\n", arg0); -#endif fprintf(stderr, "%s -A (Test Adding/Updating/Deleting a record)\n", arg0); fprintf(stderr, "%s -U (Test updating a TXT record)\n", arg0); fprintf(stderr, "%s -N (Test adding a large NULL record)\n", arg0); @@ -1041,15 +1019,15 @@ static void DNSSD_API qr_reply(DNSServiceRef sdref, const DNSServiceFlags flags, case kDNSServiceType_CNAME: case kDNSServiceType_PTR: case kDNSServiceType_DNAME: - p += snprintd(p, sizeof(rdb), &rd); + snprintd(p, sizeof(rdb), &rd); break; case kDNSServiceType_SOA: p += snprintd(p, rdb + sizeof(rdb) - p, &rd); // mname p += snprintf(p, rdb + sizeof(rdb) - p, " "); p += snprintd(p, rdb + sizeof(rdb) - p, &rd); // rname - p += snprintf(p, rdb + sizeof(rdb) - p, " Ser %d Ref %d Ret %d Exp %d Min %d", - ntohl(((uint32_t*)rd)[0]), ntohl(((uint32_t*)rd)[1]), ntohl(((uint32_t*)rd)[2]), ntohl(((uint32_t*)rd)[3]), ntohl(((uint32_t*)rd)[4])); + snprintf(p, rdb + sizeof(rdb) - p, " Ser %d Ref %d Ret %d Exp %d Min %d", + ntohl(((uint32_t*)rd)[0]), ntohl(((uint32_t*)rd)[1]), ntohl(((uint32_t*)rd)[2]), ntohl(((uint32_t*)rd)[3]), ntohl(((uint32_t*)rd)[4])); break; case kDNSServiceType_AAAA: @@ -1060,9 +1038,9 @@ static void DNSSD_API qr_reply(DNSServiceRef sdref, const DNSServiceFlags flags, case kDNSServiceType_SRV: p += snprintf(p, rdb + sizeof(rdb) - p, "%d %d %d ", // priority, weight, port - ntohs(*(unsigned short*)rd), ntohs(*(unsigned short*)(rd+2)), ntohs(*(unsigned short*)(rd+4))); + ntohs(*(unsigned short*)rd), ntohs(*(unsigned short*)(rd+2)), ntohs(*(unsigned short*)(rd+4))); rd += 6; - p += snprintd(p, rdb + sizeof(rdb) - p, &rd); // target host + snprintd(p, rdb + sizeof(rdb) - p, &rd); // target host break; case kDNSServiceType_DS: @@ -1124,7 +1102,6 @@ static void DNSSD_API qr_reply(DNSServiceRef sdref, const DNSServiceFlags flags, fflush(stdout); } -#if HAS_NAT_PMP_API static void DNSSD_API port_mapping_create_reply(DNSServiceRef sdref, DNSServiceFlags flags, uint32_t ifIndex, DNSServiceErrorType errorCode, uint32_t publicAddress, uint32_t protocol, uint16_t privatePort, uint16_t publicPort, uint32_t ttl, void *context) { (void)sdref; // Unused @@ -1146,9 +1123,7 @@ static void DNSSD_API port_mapping_create_reply(DNSServiceRef sdref, DNSServiceF if (!(flags & kDNSServiceFlagsMoreComing)) fflush(stdout); } -#endif -#if HAS_ADDRINFO_API static void DNSSD_API addrinfo_reply(DNSServiceRef sdref, const DNSServiceFlags flags, uint32_t interfaceIndex, DNSServiceErrorType errorCode, const char *hostname, const struct sockaddr *address, uint32_t ttl, void *context) { char *op = (flags & kDNSServiceFlagsAdd) ? "Add" : "Rmv"; @@ -1218,7 +1193,6 @@ static void DNSSD_API addrinfo_reply(DNSServiceRef sdref, const DNSServiceFlags if (!(flags & kDNSServiceFlagsMoreComing)) fflush(stdout); } -#endif //************************************************************************************************************* // The main test function @@ -1362,6 +1336,7 @@ static DNSServiceErrorType RegisterProxyAddressRecord(DNSServiceRef sdref, const // Any DNSService* call will initialize WinSock for us, so we make sure // DNSServiceCreateConnection() is called before getip() is. struct sockaddr_storage hostaddr; + memset(&hostaddr, 0, sizeof(hostaddr)); getip(ip, &hostaddr); flags |= kDNSServiceFlagsUnique; if (hostaddr.ss_family == AF_INET) @@ -1553,12 +1528,8 @@ int main(int argc, char **argv) if (argc < 2) goto Fail; // Minimum command line is the command name and one argument operation = getfirstoption(argc, argv, "EFBZLlRPQqCAUNTMISVHhD" - #if HAS_NAT_PMP_API "X" - #endif - #if HAS_ADDRINFO_API "Gg" - #endif , &opi); if (operation == -1) goto Fail; @@ -1592,6 +1563,7 @@ int main(int argc, char **argv) if (dom[0] == '.' && dom[1] == 0) dom[0] = 0; // We allow '.' on the command line as a synonym for empty string printf("Browsing for %s%s%s\n", typ, dom[0] ? "." : "", dom); err = DNSServiceCreateConnection(&client); + if (err) { fprintf(stderr, "DNSServiceCreateConnection returned %d\n", err); return(err); } sc1 = client; err = DNSServiceBrowse(&sc1, kDNSServiceFlagsShareConnection, opinterface, typ, dom, zonedata_browse, NULL); break; @@ -1694,7 +1666,6 @@ int main(int argc, char **argv) break; } -#if HAS_NAT_PMP_API case 'X': { if (argc == opi) // If no arguments, just fetch IP address err = DNSServiceNATPortMappingCreate(&client, 0, 0, 0, 0, 0, 0, port_mapping_create_reply, NULL); @@ -1711,9 +1682,7 @@ int main(int argc, char **argv) else goto Fail; break; } -#endif -#if HAS_ADDRINFO_API case 'g': case 'G': { flags |= kDNSServiceFlagsReturnIntermediates; @@ -1731,7 +1700,6 @@ int main(int argc, char **argv) err = DNSServiceGetAddrInfo(&client, flags, opinterface, GetProtocol(argv[opi+0]), argv[opi+1], addrinfo_reply, NULL); break; } -#endif case 'S': { Opaque16 registerPort = { { 0x23, 0x45 } }; // 9029 decimal diff --git a/usr/src/cmd/cmd-inet/usr.lib/mdnsd/CryptoAlg.c b/usr/src/cmd/cmd-inet/usr.lib/mdnsd/CryptoAlg.c index 38533fc886..0008405ddd 100644 --- a/usr/src/cmd/cmd-inet/usr.lib/mdnsd/CryptoAlg.c +++ b/usr/src/cmd/cmd-inet/usr.lib/mdnsd/CryptoAlg.c @@ -1,6 +1,6 @@ /* -*- Mode: C; tab-width: 4 -*- * - * Copyright (c) 2011 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2011-2012 Apple Inc. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/usr/src/cmd/cmd-inet/usr.lib/mdnsd/CryptoAlg.h b/usr/src/cmd/cmd-inet/usr.lib/mdnsd/CryptoAlg.h index 6cb3dc9d24..c21507e4b1 100644 --- a/usr/src/cmd/cmd-inet/usr.lib/mdnsd/CryptoAlg.h +++ b/usr/src/cmd/cmd-inet/usr.lib/mdnsd/CryptoAlg.h @@ -1,6 +1,6 @@ /* -*- Mode: C; tab-width: 4 -*- * - * Copyright (c) 2011 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2011-2012 Apple Inc. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,6 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + #ifndef __CRYPTO_ALG_H #define __CRYPTO_ALG_H diff --git a/usr/src/cmd/cmd-inet/usr.lib/mdnsd/DNSCommon.c b/usr/src/cmd/cmd-inet/usr.lib/mdnsd/DNSCommon.c index a0dbfcd728..607293e838 100644 --- a/usr/src/cmd/cmd-inet/usr.lib/mdnsd/DNSCommon.c +++ b/usr/src/cmd/cmd-inet/usr.lib/mdnsd/DNSCommon.c @@ -1,6 +1,6 @@ /* -*- Mode: C; tab-width: 4 -*- * - * Copyright (c) 2002-2013 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2002-2015 Apple Inc. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -513,7 +513,7 @@ mDNSexport char *GetRRDisplayString_rdb(const ResourceRecord *const rr, const RD expTimeBuf, inceptTimeBuf, swap16(rrsig->keyTag), ((domainname *)(&rrsig->signerName))->c); len = DomainNameLength((domainname *)&rrsig->signerName); - length += baseEncode(buffer + length, RemSpc, (const mDNSu8 *)(rd->data + len + RRSIG_FIXED_SIZE), + baseEncode(buffer + length, RemSpc, (const mDNSu8 *)(rd->data + len + RRSIG_FIXED_SIZE), rr->rdlength - (len + RRSIG_FIXED_SIZE), ENC_BASE64); } break; @@ -521,7 +521,7 @@ mDNSexport char *GetRRDisplayString_rdb(const ResourceRecord *const rr, const RD rdataDNSKey *rrkey = (rdataDNSKey *)rd->data; length += mDNS_snprintf(buffer+length, RemSpc, "\t%d %d %s %u ", swap16(rrkey->flags), rrkey->proto, DNSSECAlgName(rrkey->alg), (unsigned int)keytag((mDNSu8 *)rrkey, rr->rdlength)); - length += baseEncode(buffer + length, RemSpc, (const mDNSu8 *)(rd->data + DNSKEY_FIXED_SIZE), + baseEncode(buffer + length, RemSpc, (const mDNSu8 *)(rd->data + DNSKEY_FIXED_SIZE), rr->rdlength - DNSKEY_FIXED_SIZE, ENC_BASE64); } break; @@ -1481,6 +1481,7 @@ mDNSexport void mDNS_SetupQuestion(DNSQuestion *const q, const mDNSInterfaceID I q->qnameOrig = mDNSNULL; q->AnonInfo = mDNSNULL; q->pid = mDNSPlatformGetPID(); + q->euid = 0; q->DisallowPID = mDNSfalse; q->ServiceID = -1; q->QuestionCallback = callback; @@ -2357,13 +2358,9 @@ mDNSexport mDNSu8 *putRData(const DNSMessage *const msg, mDNSu8 *ptr, const mDNS case kDNSType_NSEC: { // For NSEC records, rdlength represents the exact number of bytes // of in memory storage. - int len = rr->rdlength; mDNSu8 *nsec = (mDNSu8 *)rdb->data; domainname *name = (domainname *)nsec; - int dlen; - - dlen = DomainNameLength(name); - len -= dlen; + const int dlen = DomainNameLength(name); nsec += dlen; // This function is called when we are sending a NSEC record as part of mDNS, // or to copy the data to any other buffer needed which could be a mDNS or uDNS @@ -2376,7 +2373,6 @@ mDNSexport mDNSu8 *putRData(const DNSMessage *const msg, mDNSu8 *ptr, const mDNS int i, j, wlen; wlen = *(nsec + 1); nsec += 2; // Skip the window number and len - len -= 2; // For our simplified use of NSEC synthetic records: // @@ -2406,6 +2402,7 @@ mDNSexport mDNSu8 *putRData(const DNSMessage *const msg, mDNSu8 *ptr, const mDNS else { int win, wlen; + int len = rr->rdlength - dlen; // Sanity check whether the bitmap is good while (len) @@ -2607,7 +2604,7 @@ mDNSexport mDNSu8 *putDeleteAllRRSets(DNSMessage *msg, mDNSu8 *ptr, const domain } // for dynamic updates -mDNSexport mDNSu8 *putUpdateLease(DNSMessage *msg, mDNSu8 *end, mDNSu32 lease) +mDNSexport mDNSu8 *putUpdateLease(DNSMessage *msg, mDNSu8 *ptr, mDNSu32 lease) { AuthRecord rr; mDNS_SetupResourceRecord(&rr, mDNSNULL, mDNSInterface_Any, kDNSType_OPT, kStandardTTL, kDNSRecordTypeKnownUnique, AuthRecordAny, mDNSNULL, mDNSNULL); @@ -2616,13 +2613,13 @@ mDNSexport mDNSu8 *putUpdateLease(DNSMessage *msg, mDNSu8 *end, mDNSu32 lease) rr.resrec.rdestimate = sizeof(rdataOPT); rr.resrec.rdata->u.opt[0].opt = kDNSOpt_Lease; rr.resrec.rdata->u.opt[0].u.updatelease = lease; - end = PutResourceRecordTTLJumbo(msg, end, &msg->h.numAdditionals, &rr.resrec, 0); - if (!end) { LogMsg("ERROR: putUpdateLease - PutResourceRecordTTL"); return mDNSNULL; } - return end; + ptr = PutResourceRecordTTLJumbo(msg, ptr, &msg->h.numAdditionals, &rr.resrec, 0); + if (!ptr) { LogMsg("ERROR: putUpdateLease - PutResourceRecordTTL"); return mDNSNULL; } + return ptr; } // for dynamic updates -mDNSexport mDNSu8 *putUpdateLeaseWithLimit(DNSMessage *msg, mDNSu8 *end, mDNSu32 lease, mDNSu8 *limit) +mDNSexport mDNSu8 *putUpdateLeaseWithLimit(DNSMessage *msg, mDNSu8 *ptr, mDNSu32 lease, mDNSu8 *limit) { AuthRecord rr; mDNS_SetupResourceRecord(&rr, mDNSNULL, mDNSInterface_Any, kDNSType_OPT, kStandardTTL, kDNSRecordTypeKnownUnique, AuthRecordAny, mDNSNULL, mDNSNULL); @@ -2631,9 +2628,9 @@ mDNSexport mDNSu8 *putUpdateLeaseWithLimit(DNSMessage *msg, mDNSu8 *end, mDNSu32 rr.resrec.rdestimate = sizeof(rdataOPT); rr.resrec.rdata->u.opt[0].opt = kDNSOpt_Lease; rr.resrec.rdata->u.opt[0].u.updatelease = lease; - end = PutResourceRecordTTLWithLimit(msg, end, &msg->h.numAdditionals, &rr.resrec, 0, limit); - if (!end) { LogMsg("ERROR: putUpdateLease - PutResourceRecordTTLWithLimit"); return mDNSNULL; } - return end; + ptr = PutResourceRecordTTLWithLimit(msg, ptr, &msg->h.numAdditionals, &rr.resrec, 0, limit); + if (!ptr) { LogMsg("ERROR: putUpdateLeaseWithLimit - PutResourceRecordTTLWithLimit"); return mDNSNULL; } + return ptr; } mDNSexport mDNSu8 *putDNSSECOption(DNSMessage *msg, mDNSu8 *end, mDNSu8 *limit) @@ -2650,7 +2647,7 @@ mDNSexport mDNSu8 *putDNSSECOption(DNSMessage *msg, mDNSu8 *end, mDNSu8 *limit) // set the DO bit ttl |= 0x8000; end = PutResourceRecordTTLWithLimit(msg, end, &msg->h.numAdditionals, &rr.resrec, ttl, limit); - if (!end) { LogMsg("ERROR: putUpdateLease - PutResourceRecordTTLWithLimit"); return mDNSNULL; } + if (!end) { LogMsg("ERROR: putDNSSECOption - PutResourceRecordTTLWithLimit"); return mDNSNULL; } return end; } @@ -3441,12 +3438,7 @@ mDNSexport const mDNSu8 *GetLargeResourceRecord(mDNS *const m, const DNSMessage mDNSu16 pktrdlength; if (largecr == &m->rec && m->rec.r.resrec.RecordType) - { - LogMsg("GetLargeResourceRecord: m->rec appears to be already in use for %s", CRDisplayString(m, &m->rec.r)); -#if ForceAlerts - *(long*)0 = 0; -#endif - } + LogFatalError("GetLargeResourceRecord: m->rec appears to be already in use for %s", CRDisplayString(m, &m->rec.r)); rr->next = mDNSNULL; rr->resrec.name = &largecr->namestorage; @@ -3713,7 +3705,7 @@ mDNSexport void DumpPacket(mDNS *const m, mStatus status, mDNSBool sent, char *t } ptr = DumpRecords(m, msg, ptr, end, msg->h.numAnswers, IsUpdate ? "Prerequisites" : "Answers"); ptr = DumpRecords(m, msg, ptr, end, msg->h.numAuthorities, IsUpdate ? "Updates" : "Authorities"); - ptr = DumpRecords(m, msg, ptr, end, msg->h.numAdditionals, "Additionals"); + DumpRecords(m, msg, ptr, end, msg->h.numAdditionals, "Additionals"); LogMsg("--------------"); } @@ -3725,11 +3717,8 @@ mDNSexport void DumpPacket(mDNS *const m, mStatus status, mDNSBool sent, char *t // Stub definition of TCPSocket_struct so we can access flags field. (Rest of TCPSocket_struct is platform-dependent.) struct TCPSocket_struct { TCPSocketFlags flags; /* ... */ }; - -struct UDPSocket_struct -{ - mDNSIPPort port; // MUST BE FIRST FIELD -- mDNSCoreReceive expects every UDPSocket_struct to begin with mDNSIPPort port -}; +// Stub definition of UDPSocket_struct so we can access port field. (Rest of UDPSocket_struct is platform-dependent.) +struct UDPSocket_struct { mDNSIPPort port; /* ... */ }; // Note: When we sign a DNS message using DNSDigest_SignMessage(), the current real-time clock value is used, which // is why we generally defer signing until we send the message, to ensure the signature is as fresh as possible. @@ -3821,10 +3810,10 @@ mDNSexport mStatus mDNSSendDNSMessage(mDNS *const m, DNSMessage *const msg, mDNS // Dump the packet with the HINFO and TSIG if (mDNS_PacketLoggingEnabled && !mDNSOpaque16IsZero(msg->h.id)) { mDNSIPPort port = MulticastDNSPort; - DumpPacket(m, status, mDNStrue, sock && - (sock->flags & kTCPSocketFlags_UseTLS) ? - "TLS" : sock ? "TCP" : "UDP", mDNSNULL, - src ? src->port : port, dst, dstport, msg, end); + DumpPacket(m, status, mDNStrue, + sock && (sock->flags & kTCPSocketFlags_UseTLS) ? + "TLS" : sock ? "TCP" : "UDP", mDNSNULL, + src ? src->port : port, dst, dstport, msg, end); } // put the number of additionals back the way it was @@ -3849,12 +3838,7 @@ mDNSexport void mDNS_Lock_(mDNS *const m, const char * const functionname) // If that client callback does mDNS API calls, mDNS_reentrancy and mDNS_busy will both be one // If mDNS_busy != mDNS_reentrancy that's a bad sign if (m->mDNS_busy != m->mDNS_reentrancy) - { - LogMsg("%s: mDNS_Lock: Locking failure! mDNS_busy (%ld) != mDNS_reentrancy (%ld)", functionname, m->mDNS_busy, m->mDNS_reentrancy); -#if ForceAlerts - *(long*)0 = 0; -#endif - } + LogFatalError("%s: mDNS_Lock: Locking failure! mDNS_busy (%ld) != mDNS_reentrancy (%ld)", functionname, m->mDNS_busy, m->mDNS_reentrancy); // If this is an initial entry into the mDNSCore code, set m->timenow // else, if this is a re-entrant entry into the mDNSCore code, m->timenow should already be set @@ -3935,82 +3919,89 @@ mDNSlocal mDNSs32 GetNextScheduledEvent(const mDNS *const m) return(e); } +#define LogTSE TSE++,LogMsg + mDNSexport void ShowTaskSchedulingError(mDNS *const m) { + int TSE = 0; AuthRecord *rr; mDNS_Lock(m); - LogMsg("Task Scheduling Error: Continuously busy for more than a second"); + LogMsg("Task Scheduling Error: *** Continuously busy for more than a second"); // Note: To accurately diagnose *why* we're busy, the debugging code here needs to mirror the logic in GetNextScheduledEvent above if (m->NewQuestions && (!m->NewQuestions->DelayAnswering || m->timenow - m->NewQuestions->DelayAnswering >= 0)) - LogMsg("Task Scheduling Error: NewQuestion %##s (%s)", + LogTSE("Task Scheduling Error: NewQuestion %##s (%s)", m->NewQuestions->qname.c, DNSTypeName(m->NewQuestions->qtype)); if (m->NewLocalOnlyQuestions) - LogMsg("Task Scheduling Error: NewLocalOnlyQuestions %##s (%s)", + LogTSE("Task Scheduling Error: NewLocalOnlyQuestions %##s (%s)", m->NewLocalOnlyQuestions->qname.c, DNSTypeName(m->NewLocalOnlyQuestions->qtype)); if (m->NewLocalRecords) { rr = AnyLocalRecordReady(m); - if (rr) LogMsg("Task Scheduling Error: NewLocalRecords %s", ARDisplayString(m, rr)); + if (rr) LogTSE("Task Scheduling Error: NewLocalRecords %s", ARDisplayString(m, rr)); } - if (m->NewLocalOnlyRecords) LogMsg("Task Scheduling Error: NewLocalOnlyRecords"); + if (m->NewLocalOnlyRecords) LogTSE("Task Scheduling Error: NewLocalOnlyRecords"); - if (m->SPSProxyListChanged) LogMsg("Task Scheduling Error: SPSProxyListChanged"); - if (m->LocalRemoveEvents) LogMsg("Task Scheduling Error: LocalRemoveEvents"); + if (m->SPSProxyListChanged) LogTSE("Task Scheduling Error: SPSProxyListChanged"); - if (m->timenow - m->NextScheduledEvent >= 0) - LogMsg("Task Scheduling Error: m->NextScheduledEvent %d", m->timenow - m->NextScheduledEvent); + if (m->LocalRemoveEvents) LogTSE("Task Scheduling Error: LocalRemoveEvents"); #ifndef UNICAST_DISABLED if (m->timenow - m->NextuDNSEvent >= 0) - LogMsg("Task Scheduling Error: m->NextuDNSEvent %d", m->timenow - m->NextuDNSEvent); + LogTSE("Task Scheduling Error: m->NextuDNSEvent %d", m->timenow - m->NextuDNSEvent); if (m->timenow - m->NextScheduledNATOp >= 0) - LogMsg("Task Scheduling Error: m->NextScheduledNATOp %d", m->timenow - m->NextScheduledNATOp); + LogTSE("Task Scheduling Error: m->NextScheduledNATOp %d", m->timenow - m->NextScheduledNATOp); if (m->NextSRVUpdate && m->timenow - m->NextSRVUpdate >= 0) - LogMsg("Task Scheduling Error: m->NextSRVUpdate %d", m->timenow - m->NextSRVUpdate); + LogTSE("Task Scheduling Error: m->NextSRVUpdate %d", m->timenow - m->NextSRVUpdate); #endif if (m->timenow - m->NextCacheCheck >= 0) - LogMsg("Task Scheduling Error: m->NextCacheCheck %d", m->timenow - m->NextCacheCheck); + LogTSE("Task Scheduling Error: m->NextCacheCheck %d", m->timenow - m->NextCacheCheck); if (m->timenow - m->NextScheduledSPS >= 0) - LogMsg("Task Scheduling Error: m->NextScheduledSPS %d", m->timenow - m->NextScheduledSPS); + LogTSE("Task Scheduling Error: m->NextScheduledSPS %d", m->timenow - m->NextScheduledSPS); if (m->timenow - m->NextScheduledKA >= 0) - LogMsg("Task Scheduling Error: m->NextScheduledKA %d", m->timenow - m->NextScheduledKA); + LogTSE("Task Scheduling Error: m->NextScheduledKA %d", m->timenow - m->NextScheduledKA); if (!m->DelaySleep && m->SleepLimit && m->timenow - m->NextScheduledSPRetry >= 0) - LogMsg("Task Scheduling Error: m->NextScheduledSPRetry %d", m->timenow - m->NextScheduledSPRetry); + LogTSE("Task Scheduling Error: m->NextScheduledSPRetry %d", m->timenow - m->NextScheduledSPRetry); if (m->DelaySleep && m->timenow - m->DelaySleep >= 0) - LogMsg("Task Scheduling Error: m->DelaySleep %d", m->timenow - m->DelaySleep); + LogTSE("Task Scheduling Error: m->DelaySleep %d", m->timenow - m->DelaySleep); if (m->SuppressSending && m->timenow - m->SuppressSending >= 0) - LogMsg("Task Scheduling Error: m->SuppressSending %d", m->timenow - m->SuppressSending); + LogTSE("Task Scheduling Error: m->SuppressSending %d", m->timenow - m->SuppressSending); if (m->timenow - m->NextScheduledQuery >= 0) - LogMsg("Task Scheduling Error: m->NextScheduledQuery %d", m->timenow - m->NextScheduledQuery); + LogTSE("Task Scheduling Error: m->NextScheduledQuery %d", m->timenow - m->NextScheduledQuery); if (m->timenow - m->NextScheduledProbe >= 0) - LogMsg("Task Scheduling Error: m->NextScheduledProbe %d", m->timenow - m->NextScheduledProbe); + LogTSE("Task Scheduling Error: m->NextScheduledProbe %d", m->timenow - m->NextScheduledProbe); if (m->timenow - m->NextScheduledResponse >= 0) - LogMsg("Task Scheduling Error: m->NextScheduledResponse %d", m->timenow - m->NextScheduledResponse); + LogTSE("Task Scheduling Error: m->NextScheduledResponse %d", m->timenow - m->NextScheduledResponse); + if (m->timenow - m->NextScheduledStopTime >= 0) + LogTSE("Task Scheduling Error: m->NextScheduledStopTime %d", m->timenow - m->NextScheduledStopTime); + + if (m->timenow - m->NextScheduledEvent >= 0) + LogTSE("Task Scheduling Error: m->NextScheduledEvent %d", m->timenow - m->NextScheduledEvent); + + if (m->NetworkChanged && m->timenow - m->NetworkChanged >= 0) + LogTSE("Task Scheduling Error: NetworkChanged %d", m->timenow - m->NetworkChanged); + + if (!TSE) LogMsg("Task Scheduling Error: *** No likely causes identified"); + else LogMsg("Task Scheduling Error: *** %d potential cause%s identified (significant only if the same cause consistently appears)", TSE, TSE > 1 ? "s" : ""); mDNS_Unlock(m); } -mDNSexport void mDNS_Unlock_(mDNS *const m, const char * const functionname) +mDNSexport void mDNS_Unlock_(mDNS *const m, const char *const functionname) { // Decrement mDNS_busy m->mDNS_busy--; // Check for locking failures if (m->mDNS_busy != m->mDNS_reentrancy) - { - LogMsg("%s: mDNS_Unlock: Locking failure! mDNS_busy (%ld) != mDNS_reentrancy (%ld)", functionname, m->mDNS_busy, m->mDNS_reentrancy); -#if ForceAlerts - *(long*)0 = 0; -#endif - } + LogFatalError("%s: mDNS_Unlock: Locking failure! mDNS_busy (%ld) != mDNS_reentrancy (%ld)", functionname, m->mDNS_busy, m->mDNS_reentrancy); // If this is a final exit from the mDNSCore code, set m->NextScheduledEvent and clear m->timenow if (m->mDNS_busy == 0) diff --git a/usr/src/cmd/cmd-inet/usr.lib/mdnsd/DNSCommon.h b/usr/src/cmd/cmd-inet/usr.lib/mdnsd/DNSCommon.h index b92f5a9ab4..e51b06dd7a 100644 --- a/usr/src/cmd/cmd-inet/usr.lib/mdnsd/DNSCommon.h +++ b/usr/src/cmd/cmd-inet/usr.lib/mdnsd/DNSCommon.h @@ -220,7 +220,7 @@ extern mDNSu8 *putDeletionRecord(DNSMessage *msg, mDNSu8 *ptr, ResourceRecord *r extern mDNSu8 *putDeletionRecordWithLimit(DNSMessage *msg, mDNSu8 *ptr, ResourceRecord *rr, mDNSu8 *limit); extern mDNSu8 *putDeleteRRSetWithLimit(DNSMessage *msg, mDNSu8 *ptr, const domainname *name, mDNSu16 rrtype, mDNSu8 *limit); extern mDNSu8 *putDeleteAllRRSets(DNSMessage *msg, mDNSu8 *ptr, const domainname *name); -extern mDNSu8 *putUpdateLease(DNSMessage *msg, mDNSu8 *end, mDNSu32 lease); +extern mDNSu8 *putUpdateLease(DNSMessage *msg, mDNSu8 *ptr, mDNSu32 lease); extern mDNSu8 *putUpdateLeaseWithLimit(DNSMessage *msg, mDNSu8 *ptr, mDNSu32 lease, mDNSu8 *limit); extern mDNSu8 *putHINFO(const mDNS *const m, DNSMessage *const msg, mDNSu8 *ptr, DomainAuthInfo *authInfo, mDNSu8 *limit); @@ -297,16 +297,16 @@ extern void mDNS_Unlock_(mDNS *const m, const char * const functionname); #define mDNS_Unlock(X) mDNS_Unlock_((X), __func__) -#define mDNS_CheckLock(X) { if ((X)->mDNS_busy != (X)->mDNS_reentrancy+1) \ - LogMsg("%s: Lock not held! mDNS_busy (%ld) mDNS_reentrancy (%ld)", __func__, (X)->mDNS_busy, (X)->mDNS_reentrancy); } +#define mDNS_CheckLock(X) \ + if ((X)->mDNS_busy != (X)->mDNS_reentrancy+1) LogMsg("%s: Lock not held! mDNS_busy (%ld) mDNS_reentrancy (%ld)", __func__, (X)->mDNS_busy, (X)->mDNS_reentrancy) #define mDNS_DropLockBeforeCallback() do { m->mDNS_reentrancy++; \ - if (m->mDNS_busy != m->mDNS_reentrancy) LogMsg("%s: Locking Failure! mDNS_busy (%ld) != mDNS_reentrancy (%ld)", __func__, m->mDNS_busy, m->mDNS_reentrancy); \ -} while (0) + if (m->mDNS_busy != m->mDNS_reentrancy) LogMsg("%s: Locking Failure! mDNS_busy (%ld) != mDNS_reentrancy (%ld)", __func__, m->mDNS_busy, m->mDNS_reentrancy); \ + } while (0) #define mDNS_ReclaimLockAfterCallback() do { \ - if (m->mDNS_busy != m->mDNS_reentrancy) LogMsg("%s: Unlocking Failure! mDNS_busy (%ld) != mDNS_reentrancy (%ld)", __func__, m->mDNS_busy, m->mDNS_reentrancy); \ - m->mDNS_reentrancy--; } while (0) + if (m->mDNS_busy != m->mDNS_reentrancy) LogMsg("%s: Unlocking Failure! mDNS_busy (%ld) != mDNS_reentrancy (%ld)", __func__, m->mDNS_busy, m->mDNS_reentrancy); \ + m->mDNS_reentrancy--; } while (0) #ifdef __cplusplus } diff --git a/usr/src/cmd/cmd-inet/usr.lib/mdnsd/DNSDigest.c b/usr/src/cmd/cmd-inet/usr.lib/mdnsd/DNSDigest.c index 33798d3833..57a4012034 100644 --- a/usr/src/cmd/cmd-inet/usr.lib/mdnsd/DNSDigest.c +++ b/usr/src/cmd/cmd-inet/usr.lib/mdnsd/DNSDigest.c @@ -1,6 +1,6 @@ /* -*- Mode: C; tab-width: 4 -*- * - * Copyright (c) 2002-2011 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2002-2011 Apple Inc. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,7 +15,6 @@ * limitations under the License. */ - #ifdef __cplusplus extern "C" { #endif diff --git a/usr/src/cmd/cmd-inet/usr.lib/mdnsd/GenLinkedList.c b/usr/src/cmd/cmd-inet/usr.lib/mdnsd/GenLinkedList.c index 45dbb7cbd3..1c6cb5be7c 100644 --- a/usr/src/cmd/cmd-inet/usr.lib/mdnsd/GenLinkedList.c +++ b/usr/src/cmd/cmd-inet/usr.lib/mdnsd/GenLinkedList.c @@ -1,6 +1,6 @@ /* -*- Mode: C; tab-width: 4 -*- * - * Copyright (c) 2003 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2003-2011 Apple Inc. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,13 +13,6 @@ * 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. - - File: GenLinkedList.c - - Contains: implementation of generic linked lists. - - Version: 1.0 - Tabs: 4 spaces */ #include "GenLinkedList.h" diff --git a/usr/src/cmd/cmd-inet/usr.lib/mdnsd/PlatformCommon.c b/usr/src/cmd/cmd-inet/usr.lib/mdnsd/PlatformCommon.c index cf8e404637..afba1c66bf 100644 --- a/usr/src/cmd/cmd-inet/usr.lib/mdnsd/PlatformCommon.c +++ b/usr/src/cmd/cmd-inet/usr.lib/mdnsd/PlatformCommon.c @@ -1,6 +1,6 @@ /* -*- Mode: C; tab-width: 4 -*- * - * Copyright (c) 2004 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2004-2015 Apple Inc. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -64,8 +64,12 @@ mDNSexport void mDNSPlatformSourceAddrForDest(mDNSAddr *const src, const mDNSAdd } else return; - if ((connect(sock, &addr.s, inner_len)) < 0) - { if (errno != ENETUNREACH) LogMsg("mDNSPlatformSourceAddrForDest: connect %#a failed errno %d (%s)", dst, errno, strerror(errno)); goto exit; } + if ((connect(sock, &addr.s, inner_len)) < 0) { + if (errno != ENETUNREACH) + LogMsg("mDNSPlatformSourceAddrForDest: connect %#a failed errno %d (%s)", dst, errno, + strerror(errno)); + goto exit; + } if ((getsockname(sock, &addr.s, &len)) < 0) { LogMsg("mDNSPlatformSourceAddrForDest: getsockname failed errno %d (%s)", errno, strerror(errno)); goto exit; } @@ -190,10 +194,13 @@ mDNSexport void mDNSPlatformWriteLogMsg(const char *ident, const char *buffer, m if (ident && ident[0] && mDNSPlatformClockDivisor) syslog(syslog_level, "%8d.%03d: %s", (int)(t/1000), ms, buffer); else -#elif APPLE_OSX_mDNSResponder - mDNSPlatformLogToFile(syslog_level, buffer); +#endif + { +#if APPLE_OSX_mDNSResponder + mDNSPlatformLogToFile(syslog_level, buffer); #else - syslog(syslog_level, "%s", buffer); + syslog(syslog_level, "%s", buffer); #endif + } } } diff --git a/usr/src/cmd/cmd-inet/usr.lib/mdnsd/PosixDaemon.c b/usr/src/cmd/cmd-inet/usr.lib/mdnsd/PosixDaemon.c index cfd9d0a30e..55edb0475d 100644 --- a/usr/src/cmd/cmd-inet/usr.lib/mdnsd/PosixDaemon.c +++ b/usr/src/cmd/cmd-inet/usr.lib/mdnsd/PosixDaemon.c @@ -50,7 +50,7 @@ extern int daemon(int, int); #include "PlatformCommon.h" #ifndef MDNSD_USER -#define MDNSD_USER "nobody" +#define MDNSD_USER "nobody" #endif #define CONFIG_FILE "/etc/mdnsd.conf" diff --git a/usr/src/cmd/cmd-inet/usr.lib/mdnsd/anonymous.c b/usr/src/cmd/cmd-inet/usr.lib/mdnsd/anonymous.c index 94b102ecb7..184de13788 100644 --- a/usr/src/cmd/cmd-inet/usr.lib/mdnsd/anonymous.c +++ b/usr/src/cmd/cmd-inet/usr.lib/mdnsd/anonymous.c @@ -1,6 +1,6 @@ /* -*- Mode: C; tab-width: 4 -*- * - * Copyright (c) 2012 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2012-2013 Apple Inc. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -27,6 +27,14 @@ #define ANON_NSEC3_ITERATIONS 1 +struct AnonInfoResourceRecord_struct +{ + ResourceRecord resrec; + RData rdatastorage; +}; + +typedef struct AnonInfoResourceRecord_struct AnonInfoResourceRecord; + mDNSlocal mDNSBool InitializeNSEC3Record(ResourceRecord *rr, const mDNSu8 *AnonData, int len, mDNSu32 salt) { const mDNSu8 *ptr; @@ -118,9 +126,10 @@ mDNSlocal ResourceRecord *ConstructNSEC3Record(const domainname *service, const mDNSlocal ResourceRecord *CopyNSEC3ResourceRecord(AnonymousInfo *si, const ResourceRecord *rr) { - int len; + AnonInfoResourceRecord *anonRR; domainname *name; - ResourceRecord *nsec3rr; + mDNSu32 neededLen; + mDNSu32 extraLen; if (rr->rdlength < MCAST_NSEC3_RDLENGTH) { @@ -128,22 +137,26 @@ mDNSlocal ResourceRecord *CopyNSEC3ResourceRecord(AnonymousInfo *si, const Resou return mDNSNULL; } // Allocate space for the name and the rdata along with the ResourceRecord - len = DomainNameLength(rr->name); - nsec3rr = mDNSPlatformMemAllocate(sizeof(ResourceRecord) + len + sizeof(RData)); - if (!nsec3rr) + neededLen = rr->rdlength + DomainNameLength(rr->name); + extraLen = (neededLen > sizeof(RDataBody)) ? (neededLen - sizeof(RDataBody)) : 0; + anonRR = (AnonInfoResourceRecord *)mDNSPlatformMemAllocate(sizeof(AnonInfoResourceRecord) + extraLen); + if (!anonRR) return mDNSNULL; - *nsec3rr = *rr; - name = (domainname *)((mDNSu8 *)nsec3rr + sizeof(ResourceRecord)); - nsec3rr->name = (const domainname *)name; + anonRR->resrec = *rr; + + anonRR->rdatastorage.MaxRDLength = rr->rdlength; + mDNSPlatformMemCopy(anonRR->rdatastorage.u.data, rr->rdata->u.data, rr->rdlength); + + name = (domainname *)(anonRR->rdatastorage.u.data + rr->rdlength); AssignDomainName(name, rr->name); - nsec3rr->rdata = (RData *)((mDNSu8 *)nsec3rr->name + len); - mDNSPlatformMemCopy(nsec3rr->rdata->u.data, rr->rdata->u.data, rr->rdlength); + anonRR->resrec.name = name; + anonRR->resrec.rdata = &anonRR->rdatastorage; - si->nsec3RR = nsec3rr; + si->nsec3RR = (ResourceRecord *)anonRR; - return nsec3rr; + return si->nsec3RR; } // When a service is started or a browse is started with the Anonymous data, we allocate a new random diff --git a/usr/src/cmd/cmd-inet/usr.lib/mdnsd/anonymous.h b/usr/src/cmd/cmd-inet/usr.lib/mdnsd/anonymous.h index 2f2b4f8c4e..b60812ea0d 100644 --- a/usr/src/cmd/cmd-inet/usr.lib/mdnsd/anonymous.h +++ b/usr/src/cmd/cmd-inet/usr.lib/mdnsd/anonymous.h @@ -1,6 +1,6 @@ /* -*- Mode: C; tab-width: 4 -*- * - * Copyright (c) 2012 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2012 Apple Inc. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/usr/src/cmd/cmd-inet/usr.lib/mdnsd/dnssec.h b/usr/src/cmd/cmd-inet/usr.lib/mdnsd/dnssec.h index 1a8d95351b..b770af8de0 100644 --- a/usr/src/cmd/cmd-inet/usr.lib/mdnsd/dnssec.h +++ b/usr/src/cmd/cmd-inet/usr.lib/mdnsd/dnssec.h @@ -1,6 +1,6 @@ /* -*- Mode: C; tab-width: 4 -*- * - * Copyright (c) 2011 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2011-2013 Apple Inc. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,6 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + #ifndef __DNSSEC_H #define __DNSSEC_H diff --git a/usr/src/cmd/cmd-inet/usr.lib/mdnsd/mDNS.c b/usr/src/cmd/cmd-inet/usr.lib/mdnsd/mDNS.c index 2f9227eabd..69236e0b88 100644 --- a/usr/src/cmd/cmd-inet/usr.lib/mdnsd/mDNS.c +++ b/usr/src/cmd/cmd-inet/usr.lib/mdnsd/mDNS.c @@ -1,6 +1,6 @@ /* -*- Mode: C; tab-width: 4 -*- * - * Copyright (c) 2002-2013 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2002-2015 Apple Inc. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -47,7 +47,6 @@ #include "dns_sd.h" // for kDNSServiceFlags* definitions #if APPLE_OSX_mDNSResponder - #include <WebFilterDNS/WebFilterDNS.h> #if !NO_WCF @@ -63,6 +62,10 @@ void WCFConnectionDealloc(WCFConnection* c) __attribute__((weak_import)); #define NO_WCF 1 #endif // APPLE_OSX_mDNSResponder +#if TARGET_OS_EMBEDDED +#include "Metrics.h" +#endif + // Forward declarations mDNSlocal void BeginSleepProcessing(mDNS *const m); mDNSlocal void RetrySPSRegistrations(mDNS *const m); @@ -80,6 +83,7 @@ mDNSlocal void DeadvertiseAllInterfaceRecords(mDNS *const m); mDNSlocal void FreeNSECRecords(mDNS *const m, CacheRecord *NSECRecords); mDNSlocal void mDNSParseNSEC3Records(mDNS *const m, const DNSMessage *const response, const mDNSu8 *end, const mDNSInterfaceID InterfaceID, CacheRecord **NSEC3Records); +mDNSlocal mDNSu8 *GetValueForMACAddr(mDNSu8 *ptr, mDNSu8 *limit, mDNSEthAddr *eth); // *************************************************************************** @@ -146,10 +150,6 @@ mDNSlocal void SetNextQueryStopTime(mDNS *const m, const DNSQuestion *const q) { mDNS_CheckLock(m); -#if ForceAlerts - if (m->mDNS_busy != m->mDNS_reentrancy+1) *(long*)0 = 0; -#endif - if (m->NextScheduledStopTime - q->StopTime > 0) m->NextScheduledStopTime = q->StopTime; } @@ -158,10 +158,6 @@ mDNSexport void SetNextQueryTime(mDNS *const m, const DNSQuestion *const q) { mDNS_CheckLock(m); -#if ForceAlerts - if (m->mDNS_busy != m->mDNS_reentrancy+1) *(long*)0 = 0; -#endif - if (ActiveQuestion(q)) { // Depending on whether this is a multicast or unicast question we want to set either: @@ -352,7 +348,7 @@ mDNSlocal CacheGroup *CacheGroupForRecord(const mDNS *const m, const mDNSu32 slo return(CacheGroupForName(m, slot, rr->namehash, rr->name)); } -mDNSexport mDNSBool mDNS_AddressIsLocalSubnet(mDNS *const m, const mDNSInterfaceID InterfaceID, const mDNSAddr *addr, mDNSBool *myself) +mDNSexport mDNSBool mDNS_AddressIsLocalSubnet(mDNS *const m, const mDNSInterfaceID InterfaceID, const mDNSAddr *addr) { NetworkInterfaceInfo *intf; @@ -363,44 +359,19 @@ mDNSexport mDNSBool mDNS_AddressIsLocalSubnet(mDNS *const m, const mDNSInterface for (intf = m->HostInterfaces; intf; intf = intf->next) if (intf->ip.type == addr->type && intf->InterfaceID == InterfaceID && intf->McastTxRx) if (((intf->ip.ip.v4.NotAnInteger ^ addr->ip.v4.NotAnInteger) & intf->mask.ip.v4.NotAnInteger) == 0) - { - if (myself) - { - if (mDNSSameIPv4Address(intf->ip.ip.v4, addr->ip.v4)) - *myself = mDNStrue; - else - *myself = mDNSfalse; - if (*myself) - debugf("mDNS_AddressIsLocalSubnet: IPv4 %#a returning true", addr); - else - debugf("mDNS_AddressIsLocalSubnet: IPv4 %#a returning false", addr); - } return(mDNStrue); - } } if (addr->type == mDNSAddrType_IPv6) { + if (mDNSv6AddressIsLinkLocal(&addr->ip.v6)) return(mDNStrue); for (intf = m->HostInterfaces; intf; intf = intf->next) if (intf->ip.type == addr->type && intf->InterfaceID == InterfaceID && intf->McastTxRx) if ((((intf->ip.ip.v6.l[0] ^ addr->ip.v6.l[0]) & intf->mask.ip.v6.l[0]) == 0) && (((intf->ip.ip.v6.l[1] ^ addr->ip.v6.l[1]) & intf->mask.ip.v6.l[1]) == 0) && (((intf->ip.ip.v6.l[2] ^ addr->ip.v6.l[2]) & intf->mask.ip.v6.l[2]) == 0) && (((intf->ip.ip.v6.l[3] ^ addr->ip.v6.l[3]) & intf->mask.ip.v6.l[3]) == 0)) - { - if (myself) - { - if (mDNSSameIPv6Address(intf->ip.ip.v6, addr->ip.v6)) - *myself = mDNStrue; - else - *myself = mDNSfalse; - if (*myself) - debugf("mDNS_AddressIsLocalSubnet: IPv6 %#a returning true", addr); - else - debugf("mDNS_AddressIsLocalSubnet: IPv6 %#a returning false", addr); - } return(mDNStrue); - } } return(mDNSfalse); @@ -475,11 +446,20 @@ mDNSexport void AnswerQuestionByFollowingCNAME(mDNS *const m, DNSQuestion *q, Re const mDNSu32 c = q->CNAMEReferrals + 1; // Stash a copy of the new q->CNAMEReferrals value UDPSocket *sock = q->LocalSocket; mDNSOpaque16 id = q->TargetQID; +#if TARGET_OS_EMBEDDED + domainname *originalQName; +#endif // if there is a message waiting at the socket, we want to process that instead // of throwing it away. If we have a CNAME response that answers // both A and AAAA question and while answering it we don't want to throw // away the response where the actual addresses are present. + // This is a stupid hack and we should get rid of it. + // The chance of there being a second unicast UDP packet already waiting in the kernel before we’ve + // finished processing the previous one is virtually nil, and will only happen by luck on very rare + // occasions when running on a machine with a fast network connection and a slow or busy processor. + // The idea that we’d rely for correctness on this random chance event occurring is ridiculous. + // -- SC if (mDNSPlatformPeekUDP(m, q->LocalSocket)) { LogInfo("AnswerQuestionByFollowingCNAME: Preserving UDP socket for %##s (%s)", q->qname.c, DNSTypeName(q->qtype)); @@ -508,6 +488,31 @@ mDNSexport void AnswerQuestionByFollowingCNAME(mDNS *const m, DNSQuestion *q, Re LogInfo("AnswerQuestionByFollowingCNAME: %p %##s (%s) following CNAME referral %d for %s", q, q->qname.c, DNSTypeName(q->qtype), q->CNAMEReferrals, RRDisplayString(m, rr)); +#if TARGET_OS_EMBEDDED + if (q->metrics.originalQName) + { + originalQName = q->metrics.originalQName; + q->metrics.originalQName = mDNSNULL; + } + else + { + mDNSu16 qNameLen; + + qNameLen = DomainNameLength(&q->qname); + if ((qNameLen > 0) && (qNameLen <= MAX_DOMAIN_NAME)) + { + originalQName = mDNSPlatformMemAllocate(qNameLen); + if (originalQName) + { + mDNSPlatformMemCopy(originalQName->c, q->qname.c, qNameLen); + } + } + else + { + originalQName = mDNSNULL; + } + } +#endif mDNS_StopQuery_internal(m, q); // Stop old query AssignDomainName(&q->qname, &rr->rdata->u.name); // Update qname q->qnamehash = DomainNameHashValue(&q->qname); // and namehash @@ -524,6 +529,9 @@ mDNSexport void AnswerQuestionByFollowingCNAME(mDNS *const m, DNSQuestion *q, Re // Record how many times we've done this. We need to do this *after* mDNS_StartQuery_internal, // because mDNS_StartQuery_internal re-initializes CNAMEReferrals to zero q->CNAMEReferrals = c; +#if TARGET_OS_EMBEDDED + q->metrics.originalQName = originalQName; +#endif if (sock) { // We have a message waiting and that should answer this question. @@ -933,7 +941,7 @@ mDNSlocal void SetTargetToHostName(mDNS *const m, AuthRecord *const rr) { const domainname *const n = SetUnicastTargetToHostName(m, rr); if (n) newname = n; - else { target->c[0] = 0; SetNewRData(&rr->resrec, mDNSNULL, 0); return; } + else { if (target) target->c[0] = 0; SetNewRData(&rr->resrec, mDNSNULL, 0); return; } } if (target && SameDomainName(target, newname)) @@ -1133,26 +1141,61 @@ mDNSlocal AuthRecord *CheckAuthSameRecord(AuthHash *r, AuthRecord *rr) mDNSlocal void DecrementAutoTargetServices(mDNS *const m, AuthRecord *const rr) { + if (RRLocalOnly(rr)) + { + // A sanity check, this should be prevented in calling code. + LogInfo("DecrementAutoTargetServices: called for RRLocalOnly() record: %s", ARDisplayString(m, rr)); + return; + } + if (!AuthRecord_uDNS(rr) && rr->resrec.rrtype == kDNSType_SRV && rr->AutoTarget == Target_AutoHost) { - m->AutoTargetServices--; - LogInfo("DecrementAutoTargetServices: AutoService Record %s, AutoTargetServices %d", ARDisplayString(m, rr), m->AutoTargetServices); - if (!m->AutoTargetServices) + // If about to get rid of the last advertised service + if (m->AutoTargetServices == 1) DeadvertiseAllInterfaceRecords(m); + + m->AutoTargetServices--; + LogInfo("DecrementAutoTargetServices: AutoTargetServices %d Record %s", m->AutoTargetServices, ARDisplayString(m, rr)); + } + +#if TARGET_OS_WATCH + if (!AuthRecord_uDNS(rr)) + { + if (m->NumAllInterfaceRecords + m->NumAllInterfaceQuestions == 1) + m->NetworkChanged = m->timenow; + m->NumAllInterfaceRecords--; + LogInfo("DecrementAutoTargetServices: NumAllInterfaceRecords %d NumAllInterfaceQuestions %d %s", + m->NumAllInterfaceRecords, m->NumAllInterfaceQuestions, ARDisplayString(m, rr)); } +#endif } mDNSlocal void IncrementAutoTargetServices(mDNS *const m, AuthRecord *const rr) { - if (!AuthRecord_uDNS(rr) && rr->resrec.rrtype == kDNSType_SRV && rr->AutoTarget == Target_AutoHost) + if (RRLocalOnly(rr)) + { + // A sanity check, this should be prevented in calling code. + LogInfo("IncrementAutoTargetServices: called for RRLocalOnly() record: %s", ARDisplayString(m, rr)); + return; + } + +#if TARGET_OS_WATCH + if (!AuthRecord_uDNS(rr)) { - int count = m->AutoTargetServices; + m->NumAllInterfaceRecords++; + LogInfo("IncrementAutoTargetServices: NumAllInterfaceRecords %d NumAllInterfaceQuestions %d %s", + m->NumAllInterfaceRecords, m->NumAllInterfaceQuestions, ARDisplayString(m, rr)); + if (m->NumAllInterfaceRecords + m->NumAllInterfaceQuestions == 1) + m->NetworkChanged = m->timenow; + } +#endif - // Bump up before calling AdvertiseAllInterfaceRecords. AdvertiseInterface - // returns without doing anything if the count is zero. + if (!AuthRecord_uDNS(rr) && rr->resrec.rrtype == kDNSType_SRV && rr->AutoTarget == Target_AutoHost) + { m->AutoTargetServices++; - LogInfo("IncrementAutoTargetServices: AutoService Record %s, AutoTargetServices %d", ARDisplayString(m, rr), m->AutoTargetServices); - if (!count) + LogInfo("IncrementAutoTargetServices: AutoTargetServices %d Record %s", m->AutoTargetServices, ARDisplayString(m, rr)); + // If this is the first advertised service + if (m->AutoTargetServices == 1) AdvertiseAllInterfaceRecords(m); } } @@ -1378,6 +1421,7 @@ mDNSexport mStatus mDNS_Register_internal(mDNS *const m, AuthRecord *const rr) // (kDNSRecordTypeDeregistering) so that we deliver RMV events to the application. But this causes more // complications and not clear whether there are any benefits. See rdar:9304275 for details. // Hence, just bail out. + // This comment is doesn’t make any sense. -- SC if (rr->resrec.RecordType & kDNSRecordTypeUniqueMask) { if (CheckAuthRecordConflict(&m->rrauth, rr)) @@ -1443,11 +1487,12 @@ mDNSexport mStatus mDNS_Register_internal(mDNS *const m, AuthRecord *const rr) { AuthGroup *ag; ag = InsertAuthRecord(m, &m->rrauth, rr); - if (ag && !ag->NewLocalOnlyRecords) { + if (ag && !ag->NewLocalOnlyRecords) + { m->NewLocalOnlyRecords = mDNStrue; ag->NewLocalOnlyRecords = rr; } - // No probing for LocalOnly records, Acknowledge them right away + // No probing for LocalOnly records; acknowledge them right away if (rr->resrec.RecordType == kDNSRecordTypeUnique) rr->resrec.RecordType = kDNSRecordTypeVerified; AcknowledgeRecord(m, rr); return(mStatus_NoError); @@ -1459,15 +1504,15 @@ mDNSexport mStatus mDNS_Register_internal(mDNS *const m, AuthRecord *const rr) } } - // If this is a keepalive record, fetch the MAC address of the remote host. + // If this is a non-sleep proxy keepalive record, fetch the MAC address of the remote host. // This is used by the in-NIC proxy to send the keepalive packets. - if (mDNS_KeepaliveRecord(&rr->resrec)) + if (!rr->WakeUp.HMAC.l[0] && mDNS_KeepaliveRecord(&rr->resrec)) { + mDNSAddr raddr; // Set the record type to known unique to prevent probing keep alive records. // Also make sure we do not announce the keepalive records. rr->resrec.RecordType = kDNSRecordTypeKnownUnique; rr->AnnounceCount = 0; - mDNSAddr raddr; getKeepaliveRaddr(m, rr, &raddr); // This is an asynchronous call. Once the remote MAC address is available, helper will schedule an // asynchronous task to update the resource record @@ -1476,8 +1521,9 @@ mDNSexport mStatus mDNS_Register_internal(mDNS *const m, AuthRecord *const rr) if (!AuthRecord_uDNS(rr)) // This check is superfluous, given that for unicast records we (currently) bail out above { - // We have inserted the record in the list. See if we have to advertise the A/AAAA,HINFO,PTR records. + // We have inserted the record in the list. See if we have to advertise the A/AAAA, HINFO, PTR records. IncrementAutoTargetServices(m, rr); + // For records that are not going to probe, acknowledge them right away if (rr->resrec.RecordType != kDNSRecordTypeUnique && rr->resrec.RecordType != kDNSRecordTypeDeregistering) AcknowledgeRecord(m, rr); @@ -2373,8 +2419,8 @@ mDNSlocal void SendResponses(mDNS *const m) LogSPS("SendResponses: Sending wakeup %2d for %.6a %s", rr->AnnounceCount-3, &rr->WakeUp.IMAC, ARDisplayString(m, rr)); SendWakeup(m, rr->resrec.InterfaceID, &rr->WakeUp.IMAC, &rr->WakeUp.password); for (r2 = rr; r2; r2=r2->next) - if (r2->AnnounceCount && r2->resrec.InterfaceID == rr->resrec.InterfaceID && mDNSSameEthAddress(&r2->WakeUp.IMAC, &rr->WakeUp.IMAC) && - !mDNSSameEthAddress(&zeroEthAddr, &r2->WakeUp.HMAC)) + if ((r2->resrec.RecordType == kDNSRecordTypeDeregistering) && r2->AnnounceCount && (r2->resrec.InterfaceID == rr->resrec.InterfaceID) && + mDNSSameEthAddress(&r2->WakeUp.IMAC, &rr->WakeUp.IMAC) && !mDNSSameEthAddress(&zeroEthAddr, &r2->WakeUp.HMAC)) { // For now we only want to send a single Unsolicited Neighbor Advertisement restoring the address to the original // owner, because these packets can cause some IPv6 stacks to falsely conclude that there's an address conflict. @@ -2544,7 +2590,7 @@ mDNSlocal void SendResponses(mDNS *const m) if ((rr->SendRNow == intf->InterfaceID) && ((rr->resrec.InterfaceID == mDNSInterface_Any) && !mDNSPlatformValidRecordForInterface(rr, intf))) { - LogInfo("SendResponses: Not sending %s, on %s", ARDisplayString(m, rr), InterfaceNameForID(m, rr->SendRNow)); + // LogInfo("SendResponses: Not sending %s, on %s", ARDisplayString(m, rr), InterfaceNameForID(m, rr->SendRNow)); rr->SendRNow = GetNextActiveInterfaceID(intf); } else if (rr->SendRNow == intf->InterfaceID) @@ -2929,10 +2975,10 @@ mDNSexport mStatus mDNS_Reconfirm_internal(mDNS *const m, CacheRecord *const rr, // BuildQuestion puts a question into a DNS Query packet and if successful, updates the value of queryptr. // It also appends to the list of known answer records that need to be included, // and updates the forcast for the size of the known answer section. -mDNSlocal mDNSBool BuildQuestion(mDNS *const m, DNSMessage *query, mDNSu8 **queryptr, DNSQuestion *q, - CacheRecord ***kalistptrptr, mDNSu32 *answerforecast) +mDNSlocal mDNSBool BuildQuestion(mDNS *const m, const NetworkInterfaceInfo *intf, DNSMessage *query, mDNSu8 **queryptr, + DNSQuestion *q, CacheRecord ***kalistptrptr, mDNSu32 *answerforecast) { - mDNSBool ucast = (q->LargeAnswers || q->RequestUnicast) && m->CanReceiveUnicastOn5353; + mDNSBool ucast = (q->LargeAnswers || q->RequestUnicast) && m->CanReceiveUnicastOn5353 && intf->SupportsUnicastMDNSResponse; mDNSu16 ucbit = (mDNSu16)(ucast ? kDNSQClass_UnicastResponse : 0); const mDNSu8 *const limit = query->data + NormalMaxDNSMessageData; mDNSu8 anoninfo_space = q->AnonInfo ? AnonInfoSpace(q->AnonInfo) : 0; @@ -3072,27 +3118,27 @@ mDNSlocal const CacheRecord *FindSPSInCache1(mDNS *const m, const DNSQuestion *c #endif // SPC_DISABLED } -mDNSlocal void CheckAndSwapSPS(const CacheRecord *sps1, const CacheRecord *sps2) +mDNSlocal void CheckAndSwapSPS(const CacheRecord **sps1, const CacheRecord **sps2) { const CacheRecord *swap_sps; mDNSu32 metric1, metric2; - if (!sps1 || !sps2) return; - metric1 = SPSMetric(sps1->resrec.rdata->u.name.c); - metric2 = SPSMetric(sps2->resrec.rdata->u.name.c); - if (!SPSFeatures(sps1->resrec.rdata->u.name.c) && SPSFeatures(sps2->resrec.rdata->u.name.c) && (metric2 >= metric1)) + if (!(*sps1) || !(*sps2)) return; + metric1 = SPSMetric((*sps1)->resrec.rdata->u.name.c); + metric2 = SPSMetric((*sps2)->resrec.rdata->u.name.c); + if (!SPSFeatures((*sps1)->resrec.rdata->u.name.c) && SPSFeatures((*sps2)->resrec.rdata->u.name.c) && (metric2 >= metric1)) { - swap_sps = sps1; - sps1 = sps2; - sps2 = swap_sps; + swap_sps = *sps1; + *sps1 = *sps2; + *sps2 = swap_sps; } } mDNSlocal void ReorderSPSByFeature(const CacheRecord *sps[3]) { - CheckAndSwapSPS(sps[0], sps[1]); - CheckAndSwapSPS(sps[0], sps[2]); - CheckAndSwapSPS(sps[1], sps[2]); + CheckAndSwapSPS(&sps[0], &sps[1]); + CheckAndSwapSPS(&sps[0], &sps[2]); + CheckAndSwapSPS(&sps[1], &sps[2]); } @@ -3136,7 +3182,7 @@ mDNSlocal mDNSBool SuppressOnThisInterface(const DupSuppressInfo ds[DupSuppressI return(mDNSfalse); } -mDNSlocal int RecordDupSuppressInfo(DupSuppressInfo ds[DupSuppressInfoSize], mDNSs32 Time, mDNSInterfaceID InterfaceID, mDNSs32 Type) +mDNSlocal void RecordDupSuppressInfo(DupSuppressInfo ds[DupSuppressInfoSize], mDNSs32 Time, mDNSInterfaceID InterfaceID, mDNSs32 Type) { int i, j; @@ -3156,8 +3202,6 @@ mDNSlocal int RecordDupSuppressInfo(DupSuppressInfo ds[DupSuppressInfoSize], mDN ds[i].Time = Time; ds[i].InterfaceID = InterfaceID; ds[i].Type = Type; - - return(i); } mDNSlocal void mDNSSendWakeOnResolve(mDNS *const m, DNSQuestion *q) @@ -3175,7 +3219,6 @@ mDNSlocal void mDNSSendWakeOnResolve(mDNS *const m, DNSQuestion *q) // Split MAC@IPAddress and pass them separately len = d->c[0]; - i = 1; cnt = 0; for (i = 1; i < len; i++) { @@ -3570,7 +3613,7 @@ mDNSlocal void SendQueries(mDNS *const m) } // If we're suppressing this question, or we successfully put it, update its SendQNow state else if ((Suppress = SuppressOnThisInterface(q->DupSuppress, intf)) || - BuildQuestion(m, &m->omsg, &queryptr, q, &kalistptr, &answerforecast)) + BuildQuestion(m, intf, &m->omsg, &queryptr, q, &kalistptr, &answerforecast)) { // We successfully added the question to the packet. Make sure that // we also send the NSEC3 record if required. BuildQuestion accounted for @@ -3594,7 +3637,7 @@ mDNSlocal void SendQueries(mDNS *const m) q->WakeOnResolveCount--; } - // use brackground traffic class if any included question requires it + // use background traffic class if any included question requires it if (q->UseBackgroundTrafficClass) { useBackgroundTrafficClass = mDNStrue; @@ -3607,7 +3650,7 @@ mDNSlocal void SendQueries(mDNS *const m) for (ar = m->ResourceRecords; ar; ar=ar->next) if (ar->SendRNow == intf->InterfaceID) { - mDNSBool ucast = (ar->ProbeCount >= DefaultProbeCountForTypeUnique-1) && m->CanReceiveUnicastOn5353; + mDNSBool ucast = (ar->ProbeCount >= DefaultProbeCountForTypeUnique-1) && m->CanReceiveUnicastOn5353 && intf->SupportsUnicastMDNSResponse; mDNSu16 ucbit = (mDNSu16)(ucast ? kDNSQClass_UnicastResponse : 0); const mDNSu8 *const limit = m->omsg.data + (m->omsg.h.numQuestions ? NormalMaxDNSMessageData : AbsoluteMaxDNSMessageData); // We forecast: compressed name (2) type (2) class (2) TTL (4) rdlength (2) rdata (n) @@ -3905,6 +3948,31 @@ mDNSexport void AnswerCurrentQuestionWithResourceRecord(mDNS *const m, CacheReco return; } +#if TARGET_OS_EMBEDDED + if ((AddRecord == QC_add) && Question_uDNS(q) && (!q->metrics.answered || (q->metrics.querySendCount > 0))) + { + uDNSMetrics * metrics; + const domainname * queryName; + mDNSu32 responseLatencyMs; + mDNSBool isForCellular; + + metrics = &q->metrics; + queryName = metrics->originalQName ? metrics->originalQName : &q->qname; + if (metrics->querySendCount > 0) + { + responseLatencyMs = ((m->timenow - metrics->firstQueryTime) * 1000) / mDNSPlatformOneSecond; + } + else + { + responseLatencyMs = 0; + } + isForCellular = (q->qDNSServer && q->qDNSServer->cellIntf); + + MetricsUpdateUDNSStats(queryName, mDNStrue, metrics->querySendCount, responseLatencyMs, isForCellular); + metrics->answered = mDNStrue; + metrics->querySendCount = 0; + } +#endif // Note: Use caution here. In the case of records with rr->DelayDelivery set, AnswerCurrentQuestionWithResourceRecord(... mDNStrue) // may be called twice, once when the record is received, and again when it's time to notify local clients. // If any counters or similar are added here, care must be taken to ensure that they are not double-incremented by this. @@ -4086,6 +4154,7 @@ mDNSlocal void CacheRecordAdd(mDNS *const m, CacheRecord *rr) { if (ResourceRecordAnswersQuestion(&rr->resrec, q)) { + mDNSIPPort zp = zeroIPPort; // If this question is one that's actively sending queries, and it's received ten answers within one // second of sending the last query packet, then that indicates some radical network topology change, // so reset its exponential backoff back to the start. We must be at least at the eight-second interval @@ -4108,7 +4177,7 @@ mDNSlocal void CacheRecordAdd(mDNS *const m, CacheRecord *rr) verbosedebugf("CacheRecordAdd %p %##s (%s) %lu %#a:%d question %p", rr, rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype), rr->resrec.rroriginalttl, rr->resrec.rDNSServer ? &rr->resrec.rDNSServer->addr : mDNSNULL, mDNSVal16(rr->resrec.rDNSServer ? - rr->resrec.rDNSServer->port : zeroIPPort), q); + rr->resrec.rDNSServer->port : zp), q); q->CurrentAnswers++; q->unansweredQueries = 0; @@ -4898,7 +4967,7 @@ mDNSexport mDNSs32 mDNS_TimeNow(const mDNS *const m) // had its Sleep Proxy client list change, and defer to actual BPF reconfiguration to mDNS_Execute(). // (GetNextScheduledEvent() returns "now" when m->SPSProxyListChanged is set) #define SetSPSProxyListChanged(X) do { \ - if (m->SPSProxyListChanged && m->SPSProxyListChanged != (X)) mDNSPlatformUpdateProxyList(m, m->SPSProxyListChanged); \ + if (m->SPSProxyListChanged && m->SPSProxyListChanged != (X)) mDNSPlatformUpdateProxyList(m, m->SPSProxyListChanged); \ m->SPSProxyListChanged = (X); } while(0) // Called from mDNS_Execute() to expire stale proxy records @@ -5572,26 +5641,34 @@ mDNSexport void mDNS_UpdateAllowSleep(mDNS *const m) break; } - // Disallow sleep if there is no sleep proxy server - const CacheRecord *cr = FindSPSInCache1(m, &intf->NetWakeBrowse, mDNSNULL, mDNSNULL); - if ( cr == mDNSNULL) - { - allowSleep = mDNSfalse; - mDNS_snprintf(reason, sizeof(reason), "No sleep proxy server on %s", intf->ifname); - LogInfo("mDNS_UpdateAllowSleep: Sleep disabled because %s has no sleep proxy server", intf->ifname); - break; - } - else if (m->SPSType != 0) + // If the interface can be an in-NIC Proxy, we should check if it can accomodate all the records + // that will be offloaded. If not, we should prevent sleep. + // This check will be possible once the lower layers provide an API to query the space available for offloads on the NIC. +#if APPLE_OSX_mDNSResponder + if (!SupportsInNICProxy(intf)) +#endif { - mDNSu32 mymetric = LocalSPSMetric(m); - mDNSu32 metric = SPSMetric(cr->resrec.rdata->u.name.c); - if (metric >= mymetric) + // Disallow sleep if there is no sleep proxy server + const CacheRecord *cr = FindSPSInCache1(m, &intf->NetWakeBrowse, mDNSNULL, mDNSNULL); + if ( cr == mDNSNULL) { allowSleep = mDNSfalse; - mDNS_snprintf(reason, sizeof(reason), "No sleep proxy server with better metric on %s", intf->ifname); - LogInfo("mDNS_UpdateAllowSleep: Sleep disabled because %s has no sleep proxy server with a better metric", intf->ifname); + mDNS_snprintf(reason, sizeof(reason), "No sleep proxy server on %s", intf->ifname); + LogInfo("mDNS_UpdateAllowSleep: Sleep disabled because %s has no sleep proxy server", intf->ifname); break; } + else if (m->SPSType != 0) + { + mDNSu32 mymetric = LocalSPSMetric(m); + mDNSu32 metric = SPSMetric(cr->resrec.rdata->u.name.c); + if (metric >= mymetric) + { + allowSleep = mDNSfalse; + mDNS_snprintf(reason, sizeof(reason), "No sleep proxy server with better metric on %s", intf->ifname); + LogInfo("mDNS_UpdateAllowSleep: Sleep disabled because %s has no sleep proxy server with a better metric", intf->ifname); + break; + } + } } } } @@ -5622,7 +5699,7 @@ mDNSlocal mDNSBool mDNSUpdateOkToSend(mDNS *const m, AuthRecord *rr, NetworkInte // updateid and we should have returned from above. // // Note: scopeid is the same as intf->InterfaceID. It is passed in so that we don't have to call the - // platform function to extract the value from "intf" everytime. + // platform function to extract the value from "intf" every time. if ((scopeid >= (sizeof(rr->updateIntID) * mDNSNBBY) || bit_get_opaque64(rr->updateIntID, scopeid)) && (!rr->resrec.InterfaceID || rr->resrec.InterfaceID == intf->InterfaceID)) @@ -5633,35 +5710,41 @@ mDNSlocal mDNSBool mDNSUpdateOkToSend(mDNS *const m, AuthRecord *rr, NetworkInte mDNSexport void UpdateRMACCallback(mDNS *const m, void *context) { - IPAddressMACMapping *addrmap = (IPAddressMACMapping *)context ; - m->CurrentRecord = m->ResourceRecords; - - if (!addrmap) - { - LogMsg("UpdateRMACCallback: Address mapping is NULL"); - return; - } - - while (m->CurrentRecord) - { - AuthRecord *rr = m->CurrentRecord; - // If this is a keepalive record and the remote IP address matches, update the RData - if (mDNS_KeepaliveRecord(&rr->resrec)) - { - mDNSAddr raddr; - getKeepaliveRaddr(m, rr, &raddr); - if (mDNSSameAddress(&raddr, &addrmap->ipaddr)) - { - UpdateKeepaliveRData(m, rr, mDNSNULL, mDNStrue, (char *)(addrmap->ethaddr)); - } - } - m->CurrentRecord = rr->next; - } - - if (addrmap) - { - mDNSPlatformMemFree(addrmap); - } + IPAddressMACMapping *addrmap = (IPAddressMACMapping *)context ; + m->CurrentRecord = m->ResourceRecords; + + if (!addrmap) + { + LogMsg("UpdateRMACCallback: Address mapping is NULL"); + return; + } + + while (m->CurrentRecord) + { + AuthRecord *rr = m->CurrentRecord; + // If this is a non-sleep proxy keepalive record and the remote IP address matches, update the RData + if (!rr->WakeUp.HMAC.l[0] && mDNS_KeepaliveRecord(&rr->resrec)) + { + mDNSAddr raddr; + getKeepaliveRaddr(m, rr, &raddr); + if (mDNSSameAddress(&raddr, &addrmap->ipaddr)) + { + // Update the MAC address only if it is not a zero MAC address + mDNSEthAddr macAddr; + mDNSu8 *ptr = GetValueForMACAddr((mDNSu8 *)(addrmap->ethaddr), (mDNSu8 *) (addrmap->ethaddr + sizeof(addrmap->ethaddr)), &macAddr); + if (ptr != mDNSNULL && !mDNSEthAddressIsZero(macAddr)) + { + UpdateKeepaliveRData(m, rr, mDNSNULL, mDNStrue, (char *)(addrmap->ethaddr)); + } + } + } + m->CurrentRecord = rr->next; + } + + if (addrmap) + { + mDNSPlatformMemFree(addrmap); + } } mDNSexport mStatus UpdateKeepaliveRData(mDNS *const m, AuthRecord *rr, NetworkInterfaceInfo *const intf, mDNSBool updateMac, char *ethAddr) @@ -6128,29 +6211,49 @@ mDNSexport mDNSBool mDNSCoreHaveAdvertisedMulticastServices(mDNS *const m) return mDNSfalse; } +#define WAKE_ONLY_SERVICE 1 +#define AC_ONLY_SERVICE 2 + #ifdef APPLE_OSX_mDNSResponder -// This function is used only in the case of local NIC proxy. For external -// sleep proxy server, we do this in SPSInitRecordsBeforeUpdate when we -// walk the resource records. -mDNSlocal void SendGoodbyesForWakeOnlyService(mDNS *const m, mDNSBool *WakeOnlyService) +mDNSlocal void SendGoodbyesForSelectServices(mDNS *const m, mDNSBool *servicePresent, mDNSu32 serviceType) { AuthRecord *rr; - - *WakeOnlyService = mDNSfalse; + *servicePresent = mDNSfalse; // Mark all the records we need to deregister and send them for (rr = m->ResourceRecords; rr; rr=rr->next) { - if ((rr->AuthFlags & AuthFlagsWakeOnly) && - rr->resrec.RecordType == kDNSRecordTypeShared && rr->RequireGoodbye) + // If the service type is wake only service and the auth flags match and requires a goodbye + // OR if the service type is AC only and it is not a keepalive record, + // mark the records we need to deregister and send them + if ((serviceType == WAKE_ONLY_SERVICE && (rr->AuthFlags & AuthFlagsWakeOnly) && + rr->resrec.RecordType == kDNSRecordTypeShared && rr->RequireGoodbye) || + (serviceType == AC_ONLY_SERVICE && !mDNS_KeepaliveRecord(&rr->resrec))) { rr->ImmedAnswer = mDNSInterfaceMark; - *WakeOnlyService = mDNStrue; + *servicePresent = mDNStrue; } } } +#endif + +#ifdef APPLE_OSX_mDNSResponder +// This function is used only in the case of local NIC proxy. For external +// sleep proxy server, we do this in SPSInitRecordsBeforeUpdate when we +// walk the resource records. +mDNSlocal void SendGoodbyesForWakeOnlyService(mDNS *const m, mDNSBool *WakeOnlyService) +{ + return SendGoodbyesForSelectServices(m, WakeOnlyService, WAKE_ONLY_SERVICE); +} #endif // APPLE_OSx_mDNSResponder +#ifdef APPLE_OSX_mDNSResponder +mDNSlocal void SendGoodbyesForACOnlyServices(mDNS *const m, mDNSBool *acOnlyService) +{ + return SendGoodbyesForSelectServices(m, acOnlyService, AC_ONLY_SERVICE); +} +#endif + mDNSlocal void SendSleepGoodbyes(mDNS *const m, mDNSBool AllInterfaces, mDNSBool unicast) { AuthRecord *rr; @@ -6246,6 +6349,7 @@ mDNSlocal void BeginSleepProcessing(mDNS *const m) { mDNSBool SendGoodbyes = mDNStrue; mDNSBool WakeOnlyService = mDNSfalse; + mDNSBool ACOnlyService = mDNSfalse; mDNSBool invokeKACallback = mDNStrue; const CacheRecord *sps[3] = { mDNSNULL }; mDNSOpaque64 updateIntID = zeroOpaque64; @@ -6302,9 +6406,12 @@ mDNSlocal void BeginSleepProcessing(mDNS *const m) #if APPLE_OSX_mDNSResponder else if (SupportsInNICProxy(intf)) { - if (ActivateLocalProxy(m, intf) == mStatus_NoError) + mDNSBool keepaliveOnly = mDNSfalse; + if (ActivateLocalProxy(m, intf, &keepaliveOnly) == mStatus_NoError) { SendGoodbyesForWakeOnlyService(m, &WakeOnlyService); + if (keepaliveOnly) + SendGoodbyesForACOnlyServices(m, &ACOnlyService); SendGoodbyes = mDNSfalse; invokeKACallback = mDNSfalse; LogSPS("BeginSleepProcessing: %-6s using local proxy", intf->ifname); @@ -6348,9 +6455,9 @@ mDNSlocal void BeginSleepProcessing(mDNS *const m) { #if ForceAlerts if (intf->SPSAddr[i].type) - { LogMsg("BeginSleepProcessing: %s %d intf->SPSAddr[i].type %d", intf->ifname, i, intf->SPSAddr[i].type); *(long*)0 = 0; } + LogFatalError("BeginSleepProcessing: %s %d intf->SPSAddr[i].type %d", intf->ifname, i, intf->SPSAddr[i].type); if (intf->NetWakeResolve[i].ThisQInterval >= 0) - { LogMsg("BeginSleepProcessing: %s %d intf->NetWakeResolve[i].ThisQInterval %d", intf->ifname, i, intf->NetWakeResolve[i].ThisQInterval); *(long*)0 = 0; } + LogFatalError("BeginSleepProcessing: %s %d intf->NetWakeResolve[i].ThisQInterval %d", intf->ifname, i, intf->NetWakeResolve[i].ThisQInterval); #endif intf->SPSAddr[i].type = mDNSAddrType_None; if (intf->NetWakeResolve[i].ThisQInterval >= 0) mDNS_StopQuery(m, &intf->NetWakeResolve[i]); @@ -6410,10 +6517,10 @@ mDNSlocal void BeginSleepProcessing(mDNS *const m) LogSPS("BeginSleepProcessing: Not registering with Sleep Proxy Server on all interfaces"); SendSleepGoodbyes(m, mDNSfalse, mDNSfalse); } - else if (WakeOnlyService) + else if (WakeOnlyService || ACOnlyService) { // If we saw WakeOnly service above, send the goodbyes now. - LogSPS("BeginSleepProcessing: Sending goodbyes for WakeOnlyServices"); + LogSPS("BeginSleepProcessing: Sending goodbyes for %s", WakeOnlyService? "WakeOnlyService" : "AC Only Service"); SendResponses(m); } } @@ -6487,11 +6594,7 @@ mDNSexport void mDNSCoreMachineSleep(mDNS *const m, mDNSBool sleep) { m->SleepState = SleepState_Awake; m->SleepSeqNum++; - // If the machine wakes and then immediately tries to sleep again (e.g. a maintenance wake) - // then we enforce a minimum delay of 16 seconds before we begin sleep processing. - // This is to allow time for the Ethernet link to come up, DHCP to get an address, mDNS to issue queries, etc., - // before we make our determination of whether there's a Sleep Proxy out there we should register with. - m->DelaySleep = NonZeroTime(m->timenow + mDNSPlatformOneSecond * 16); + m->DelaySleep = 0; } if (m->SPSState == 3) @@ -7117,7 +7220,7 @@ mDNSlocal mDNSu8 *ProcessQuery(mDNS *const m, const DNSMessage *const query, con const mDNSAddr *srcaddr, const mDNSInterfaceID InterfaceID, mDNSBool LegacyQuery, mDNSBool QueryWasMulticast, mDNSBool QueryWasLocalUnicast, DNSMessage *const response) { - mDNSBool FromLocalSubnet = srcaddr && mDNS_AddressIsLocalSubnet(m, InterfaceID, srcaddr, mDNSNULL); + mDNSBool FromLocalSubnet = srcaddr && mDNS_AddressIsLocalSubnet(m, InterfaceID, srcaddr); AuthRecord *ResponseRecords = mDNSNULL; AuthRecord **nrp = &ResponseRecords; @@ -7667,9 +7770,9 @@ exit: DNSQuestion *q = DupQuestions; DupQuestions = q->NextInDQList; q->NextInDQList = mDNSNULL; - i = RecordDupSuppressInfo(q->DupSuppress, m->timenow, InterfaceID, srcaddr->type); - debugf("ProcessQuery: Recorded DSI for %##s (%s) on %p/%s %d", q->qname.c, DNSTypeName(q->qtype), InterfaceID, - srcaddr->type == mDNSAddrType_IPv4 ? "v4" : "v6", i); + RecordDupSuppressInfo(q->DupSuppress, m->timenow, InterfaceID, srcaddr->type); + debugf("ProcessQuery: Recorded DSI for %##s (%s) on %p/%s", q->qname.c, DNSTypeName(q->qtype), InterfaceID, + srcaddr->type == mDNSAddrType_IPv4 ? "v4" : "v6"); } if (McastNSEC3Records) @@ -7687,7 +7790,7 @@ mDNSlocal void mDNSCoreReceiveQuery(mDNS *const m, const DNSMessage *const msg, { mDNSu8 *responseend = mDNSNULL; mDNSBool QueryWasLocalUnicast = srcaddr && dstaddr && - !mDNSAddrIsDNSMulticast(dstaddr) && mDNS_AddressIsLocalSubnet(m, InterfaceID, srcaddr, mDNSNULL); + !mDNSAddrIsDNSMulticast(dstaddr) && mDNS_AddressIsLocalSubnet(m, InterfaceID, srcaddr); if (!InterfaceID && dstaddr && mDNSAddrIsDNSMulticast(dstaddr)) { @@ -7779,10 +7882,10 @@ mDNSlocal DNSQuestion *ExpectingUnicastResponseForRecord(mDNS *const m, mDNSIPPort srcp; if (!tcp) { - if (q->LocalSocket) - srcp = q->LocalSocket->port; + if (q->LocalSocket) + srcp = q->LocalSocket->port; else - srcp = zeroIPPort; + srcp = zeroIPPort; } else { @@ -7808,111 +7911,6 @@ mDNSlocal DNSQuestion *ExpectingUnicastResponseForRecord(mDNS *const m, return(mDNSNULL); } -// Return a pointer to the primary service name, skipping subtype name if present. -mDNSlocal const domainname *getPrimaryServiceName(const domainname *domainName) -{ - const domainname *primaryName = domainName; - const domainname *subName = SkipLeadingLabels(domainName, 1); - - if (SameDomainLabel(subName->c, (const mDNSu8 *)mDNSSubTypeLabel)) - { - // skip "<sub type name>._sub" portion of name - primaryName = SkipLeadingLabels(domainName, 2); - debugf("getPrimaryServiceName: returning %##s for _sub type", primaryName); - } - - return primaryName; -} - -// This function is not called if the packet is from us, which implies that we accept all multicast packets coming from us. -mDNSlocal mDNSBool ExpectingMulticastResponseForRecord(mDNS *const m, CacheRecord *rr, const mDNSAddr *srcaddr, mDNSBool recordAccepted, - CacheRecord **McastNSEC3Records) -{ - DNSQuestion *q; - - // Accept A and AAAA if we accepted something before in the same packet as most likely related to the - // service records that we may have accepted. - if (recordAccepted && (rr->resrec.rrtype == kDNSType_A || rr->resrec.rrtype == kDNSType_AAAA)) - { - LogInfo("ExpectingMulticastResponseForRecord:A:AAAA: accepting %s, from %#a due to same packet %d", CRDisplayString(m, rr), srcaddr, m->PktNum); - return mDNStrue; - } - for (q = m->Questions; q; q=q->next) - { - if (!q->DuplicateOf && mDNSOpaque16IsZero(q->TargetQID)) - { - mDNSBool ret; - // 1. If a resource record answers question, cache it. This also will cache NSECs if it asserts - // non-existence of q->qtype. If we have any matching NSEC3 Records for the question, send - // it along with the resource record. Do it only for questions that are expecting to - // discover only its peers (q->AnonInfo not NULL) - if (q->AnonInfo && McastNSEC3Records && !rr->resrec.AnonInfo) - { - InitializeAnonInfoForCR(m, McastNSEC3Records, rr); - } - ret = ResourceRecordAnswersQuestion(&rr->resrec, q); - if (ret) - { - // The record and the question belong to the same subset. Set the - // anonymous data in the cache record. - if (q->AnonInfo && rr->resrec.AnonInfo) - { - SetAnonData(q, &rr->resrec, mDNSfalse); - } - LogInfo("ExpectingMulticastResponseForRecord: Name and Type match, accepting %s, from %#a", CRDisplayString(m, rr), srcaddr); - if (rr->resrec.rrtype == kDNSType_NSEC) - LogInfo("ExpectingMulticastResponseForRecord: record %s, question %##s (%s)", CRDisplayString(m, rr), q->qname.c, DNSTypeName(q->qtype)); - return mDNStrue; - } - if (rr->resrec.rrtype == kDNSType_SRV || rr->resrec.rrtype == kDNSType_TXT) - { - // Point to the service type in the record name - const domainname *name = SkipLeadingLabels(rr->resrec.name, 1); - - // If question is for a sub type, just compare against the primary service type - const domainname *primaryName = getPrimaryServiceName(&q->qname); - - // 2. If the SRV or TXT record matches the service name, then cache it. If the TXT or SRV record is - // before the PTR record in the packet, PTR record may not be in the cache yet and hence the logic - // in (3) below will fail to cache it. - if (q->qtype == kDNSType_PTR && name && SameDomainName(primaryName, name)) - { - LogInfo("ExpectingMulticastResponseForRecord: Accepting %s due to PTR match, question %##s from %#a, pktnum %d", - CRDisplayString(m, rr), q->qname.c, srcaddr, m->PktNum); - return mDNStrue; - } - - if (name) - { - const mDNSu32 slot = HashSlot(name); - const mDNSu32 namehash = DomainNameHashValue(name); - CacheGroup *cg = CacheGroupForName(m, slot, namehash, name); - CacheRecord *cr; - - // 3. Same as in (2), but look in the cache in case we don't have the PTR question. - - for (cr = cg ? cg->members : mDNSNULL; cr; cr=cr->next) - { - if (cr->resrec.rrtype == kDNSType_PTR) - { - primaryName = getPrimaryServiceName(cr->resrec.name); - - if (SameDomainName(primaryName, name)) - { - LogInfo("ExpectingMulticastResponseForRecord: accepting %s, from %#a, pktnum %d", - CRDisplayString(m, rr), srcaddr, m->PktNum); - return mDNStrue; - } - } - } - } - } - } - } - debugf("ExpectingMulticastResponseForRecord: discarding %s, from %#a, pktnum %d", CRDisplayString(m, rr), srcaddr, m->PktNum); - return(mDNSfalse); -} - // Certain data types need more space for in-memory storage than their in-packet rdlength would imply // Currently this applies only to rdata types containing more than one domainname, // or types where the domainname is not the last item in the structure. @@ -8458,7 +8456,8 @@ mDNSlocal void mDNSCoreReceiveNoUnicastAnswers(mDNS *const m, const DNSMessage * name = (const domainname *)(name->c + 1 + name->c[0]); hash = DomainNameHashValue(name); slot = HashSlot(name); - cg = CacheGroupForName(m, slot, hash, name); + // For now, we don't need to update cg here, because we'll do it again immediately, back up at the start of this loop + //cg = CacheGroupForName(m, slot, hash, name); } } } @@ -8660,7 +8659,7 @@ mDNSlocal CacheRecord* mDNSCoreReceiveCacheCheck(mDNS *const m, const DNSMessage mDNSlocal void mDNSParseNSEC3Records(mDNS *const m, const DNSMessage *const response, const mDNSu8 *end, const mDNSInterfaceID InterfaceID, CacheRecord **NSEC3Records) { - const mDNSu8 *ptr = response->data; + const mDNSu8 *ptr; CacheRecord *rr; int i; @@ -8709,24 +8708,6 @@ mDNSlocal void mDNSCoreResetRecord(mDNS *const m) } } -#define DEVICE_INFO_RECORD_LABELS 4 - -// Determine if the record is an instance of _device-info._tcp.local. -mDNSlocal mDNSBool IsDeviceInfoRecord(const domainname *d) -{ - const domainname *afterInstance; - - if (CountLabels(d) != DEVICE_INFO_RECORD_LABELS) - return mDNSfalse; - - // skip the instance name - afterInstance = SkipLeadingLabels(d, 1); - if (SameDomainName(afterInstance, &LocalDeviceInfoName)) - return mDNStrue; - - return mDNSfalse; -} - // Note: mDNSCoreReceiveResponse calls mDNS_Deregister_internal which can call a user callback, which may change // the record list and/or question list. // Any code walking either list must use the CurrentQuestion and/or CurrentRecord mechanism to protect against this. @@ -8739,9 +8720,8 @@ mDNSlocal void mDNSCoreReceiveResponse(mDNS *const m, const mDNSInterfaceID InterfaceID) { int i; - mDNSBool myself; mDNSBool ResponseMCast = dstaddr && mDNSAddrIsDNSMulticast(dstaddr); - mDNSBool ResponseSrcLocal = !srcaddr || mDNS_AddressIsLocalSubnet(m, InterfaceID, srcaddr, &myself); + mDNSBool ResponseSrcLocal = !srcaddr || mDNS_AddressIsLocalSubnet(m, InterfaceID, srcaddr); DNSQuestion *llqMatch = mDNSNULL; DNSQuestion *unicastQuestion = mDNSNULL; uDNS_LLQType LLQType = uDNS_recvLLQResponse(m, response, end, srcaddr, srcport, &llqMatch); @@ -8759,12 +8739,11 @@ mDNSlocal void mDNSCoreReceiveResponse(mDNS *const m, mDNSu8 rcode = '\0'; mDNSBool rrsigsCreated = mDNSfalse; mDNSBool DNSSECQuestion = mDNSfalse; - mDNSBool recordAccepted = mDNSfalse; NetworkInterfaceInfo *llintf = FirstIPv4LLInterfaceForID(m, InterfaceID); // All records in a DNS response packet are treated as equally valid statements of truth. If we want // to guard against spoof responses, then the only credible protection against that is cryptographic - // security, e.g. DNSSEC., not worring about which section in the spoof packet contained the record + // security, e.g. DNSSEC., not worrying about which section in the spoof packet contained the record. int firstauthority = response->h.numAnswers; int firstadditional = firstauthority + response->h.numAuthorities; int totalrecords = firstadditional + response->h.numAdditionals; @@ -9000,64 +8979,69 @@ mDNSlocal void mDNSCoreReceiveResponse(mDNS *const m, // Even though it is AcceptableResponse, we still need a DNSServer pointer for the resource records that // we create. - if (!mDNSOpaque16IsZero(response->h.id)) - { - DNSQuestion *q = ExpectingUnicastResponseForRecord(m, srcaddr, ResponseSrcLocal, dstport, response->h.id, &m->rec.r, !dstaddr); - - // Initialize the DNS server on the resource record which will now filter what questions we answer with - // this record. - // - // We could potentially lookup the DNS server based on the source address, but that may not work always - // and that's why ExpectingUnicastResponseForRecord does not try to verify whether the response came - // from the DNS server that queried. We follow the same logic here. If we can find a matching quetion based - // on the "id" and "source port", then this response answers the question and assume the response - // came from the same DNS server that we sent the query to. - - if (q != mDNSNULL) - { - AcceptableResponse = mDNStrue; - if (!InterfaceID) - { - debugf("mDNSCoreReceiveResponse: InterfaceID %p %##s (%s)", q->InterfaceID, q->qname.c, DNSTypeName(q->qtype)); - m->rec.r.resrec.rDNSServer = uDNSServer = q->qDNSServer; - } - else - LogInfo("mDNSCoreReceiveResponse: InterfaceID %p %##s (%s)", q->InterfaceID, q->qname.c, DNSTypeName(q->qtype)); - } - else - { - // If we can't find a matching question, we need to see whether we have seen records earlier that matched - // the question. The code below does that. So, make this record unacceptable for now - if (!InterfaceID) - { - debugf("mDNSCoreReceiveResponse: Can't find question for record name %##s", m->rec.r.resrec.name->c); - AcceptableResponse = mDNSfalse; - } - } - } - else if (ExpectingMulticastResponseForRecord(m, &m->rec.r, srcaddr, recordAccepted, &McastNSEC3Records)) - { - recordAccepted = mDNStrue; - AcceptableResponse = mDNStrue; - LogInfo("mDNSCoreReceiveResponse: Accepting record in response to QU question %s, InterfaceID %p", CRDisplayString(m, &m->rec.r), - InterfaceID); - } - else if (IsDeviceInfoRecord(m->rec.r.resrec.name)) - { - recordAccepted = mDNStrue; - AcceptableResponse = mDNStrue; - LogInfo("mDNSCoreReceiveResponse: Accepting _device-info record %s, InterfaceID %p", - CRDisplayString(m, &m->rec.r), InterfaceID); - } + DNSQuestion *q = ExpectingUnicastResponseForRecord(m, srcaddr, ResponseSrcLocal, dstport, response->h.id, &m->rec.r, !dstaddr); + + // Initialize the DNS server on the resource record which will now filter what questions we answer with + // this record. + // + // We could potentially lookup the DNS server based on the source address, but that may not work always + // and that's why ExpectingUnicastResponseForRecord does not try to verify whether the response came + // from the DNS server that queried. We follow the same logic here. If we can find a matching quetion based + // on the "id" and "source port", then this response answers the question and assume the response + // came from the same DNS server that we sent the query to. + + if (q != mDNSNULL) + { + AcceptableResponse = mDNStrue; + if (!InterfaceID) + { + debugf("mDNSCoreReceiveResponse: InterfaceID %p %##s (%s)", q->InterfaceID, q->qname.c, DNSTypeName(q->qtype)); + m->rec.r.resrec.rDNSServer = uDNSServer = q->qDNSServer; + } + else + LogInfo("mDNSCoreReceiveResponse: InterfaceID %p %##s (%s)", q->InterfaceID, q->qname.c, DNSTypeName(q->qtype)); + } + else + { + // If we can't find a matching question, we need to see whether we have seen records earlier that matched + // the question. The code below does that. So, make this record unacceptable for now + if (!InterfaceID) + { + debugf("mDNSCoreReceiveResponse: Can't find question for record name %##s", m->rec.r.resrec.name->c); + AcceptableResponse = mDNSfalse; + } + } } } else if (llintf && llintf->IgnoreIPv4LL && m->rec.r.resrec.rrtype == kDNSType_A) { - CacheRecord *const rr = &m->rec.r; - RDataBody2 *const rdb = (RDataBody2 *)rr->smallrdatastorage.data; - - // If we are supposed to ignore link-local addresses on this interface, drop - // all "A" records that have link-local address in them. + // There are some routers (rare, thankfully) that generate bogus ARP responses for + // any IPv4 address they don’t recognize, including RFC 3927 IPv4 link-local addresses. + // To work with these broken routers, client devices need to blacklist these broken + // routers and ignore their bogus ARP responses. Some devices implement a technique + // such as the one described in US Patent 7436783, which lets clients detect and + // ignore these broken routers: <https://www.google.com/patents/US7436783> + + // OS X and iOS do not implement this defensive mechanism, instead taking a simpler + // approach of just detecting these broken routers and completely disabling IPv4 + // link-local communication on interfaces where a broken router is detected. + // OS X and iOS set the IFEF_ARPLL interface flag on interfaces + // that are deemed “safe” for IPv4 link-local communication; + // the flag is cleared on interfaces where a broken router is detected. + + // OS X and iOS will not even try to communicate with an IPv4 + // link-local destination on an interface without the IFEF_ARPLL flag set. + // This can cause some badly written applications to freeze for a long time if they + // attempt to connect to an IPv4 link-local destination address and then wait for + // that connection attempt to time out before trying other candidate addresses. + + // To mask this client bug, we suppress acceptance of IPv4 link-local address + // records on interfaces where we know the OS will be unwilling even to attempt + // communication with those IPv4 link-local destination addresses. + // <rdar://problem/9400639> kSuppress IPv4LL answers on interfaces without IFEF_ARPLL + + const CacheRecord *const rr = &m->rec.r; + const RDataBody2 *const rdb = (RDataBody2 *)rr->smallrdatastorage.data; if (mDNSv4AddressIsLinkLocal(&rdb->ipv4)) { LogInfo("mDNSResponder: Dropping LinkLocal packet %s", CRDisplayString(m, &m->rec.r)); @@ -9116,7 +9100,7 @@ mDNSlocal void mDNSCoreReceiveResponse(mDNS *const m, if (rr->ProbeCount > DefaultProbeCountForTypeUnique) LogInfo("mDNSCoreReceiveResponse: Already reset to Probing: %s", ARDisplayString(m, rr)); else if (rr->ProbeCount == DefaultProbeCountForTypeUnique) - LogMsg("mDNSCoreReceiveResponse: Ignoring response received before we even began probing: %s", ARDisplayString(m, rr)); + LogInfo("mDNSCoreReceiveResponse: Ignoring response received before we even began probing: %s", ARDisplayString(m, rr)); else { LogMsg("mDNSCoreReceiveResponse: Received from %#a:%d %s", srcaddr, mDNSVal16(srcport), CRDisplayString(m, &m->rec.r)); @@ -9202,27 +9186,6 @@ mDNSlocal void mDNSCoreReceiveResponse(mDNS *const m, rr = mDNSCoreReceiveCacheCheck(m, response, LLQType, slot, cg, unicastQuestion, &cfp, &NSECCachePtr, InterfaceID); } - // If mDNSOppCaching is set (which affects only multicast), enable opportunistic caching in which case we cache - // everything that was received over multicast. Otherwise, we are selective about the caching. - // - // Cache everything that is from ourselves (that's how we answer any questions looking for them). Otherwise call - // ExpectingMulticastResponseForRecord which decides whether to cache this record or not. - // - if (!m->mDNSOppCaching && !rr && !myself && mDNSOpaque16IsZero(response->h.id)) - { - if (!ExpectingMulticastResponseForRecord(m, &m->rec.r, srcaddr, recordAccepted, &McastNSEC3Records)) - { - //LogMsg("mDNSCoreReceiveResponse: discarding %s", CRDisplayString(m, &m->rec.r)); - mDNSCoreResetRecord(m); - continue; - } - else - { - recordAccepted = mDNStrue; - } - } - - // If packet resource record not in our cache, add it now // (unless it is just a deletion of a record we never had, in which case we don't care) if (!rr && m->rec.r.resrec.rroriginalttl > 0) @@ -9360,15 +9323,22 @@ exit: // goodbye announcement with the cache flush bit set (or a case-change on record rdata, // which we treat as a goodbye followed by an addition) and in that case it would be // inappropriate to synchronize all the other records to a TTL of 0 (or 1). + // We suppress the message for the specific case of correcting from 240 to 60 for type TXT, // because certain early Bonjour devices are known to have this specific mismatch, and // there's no point filling syslog with messages about something we already know about. // We also don't log this for uDNS responses, since a caching name server is obliged // to give us an aged TTL to correct for how long it has held the record, // so our received TTLs are expected to vary in that case + + // We also suppress log message in the case of SRV records that are recieved + // with a TTL of 4500 that are already cached with a TTL of 120 seconds, since + // this behavior was observed for a number of discoveryd based AppleTV's in iOS 8 + // GM builds. if (r2->resrec.rroriginalttl != r1->resrec.rroriginalttl && r1->resrec.rroriginalttl > 1) { if (!(r2->resrec.rroriginalttl == 240 && r1->resrec.rroriginalttl == 60 && r2->resrec.rrtype == kDNSType_TXT) && + !(r2->resrec.rroriginalttl == 120 && r1->resrec.rroriginalttl == 4500 && r2->resrec.rrtype == kDNSType_SRV) && mDNSOpaque16IsZero(response->h.id)) LogInfo("Correcting TTL from %4d to %4d for %s", r2->resrec.rroriginalttl, r1->resrec.rroriginalttl, CRDisplayString(m, r2)); @@ -9555,7 +9525,7 @@ mDNSlocal mDNSu8 *GetValueForMACAddr(mDNSu8 *ptr, mDNSu8 *limit, mDNSEthAddr *et int i; mDNSs8 hval = 0; int colons = 0; - mDNSu8 val = 0; + mDNSu16 val = 0; /* need to use 16 bit int to detect overflow */ for (i = 0; ptr < limit && *ptr != ' ' && i < 17; i++, ptr++) { @@ -9567,7 +9537,12 @@ mDNSlocal mDNSu8 *GetValueForMACAddr(mDNSu8 *ptr, mDNSu8 *limit, mDNSEthAddr *et } else if (*ptr == ':') { - eth->b[colons] = val; + if (colons >=5 || val > 255) + { + LogMsg("GetValueForMACAddr: Address malformed colons %d val %d", colons, val); + return mDNSNULL; + } + eth->b[colons] = (mDNSs8)val; colons++; val = 0; } @@ -9577,7 +9552,7 @@ mDNSlocal mDNSu8 *GetValueForMACAddr(mDNSu8 *ptr, mDNSu8 *limit, mDNSEthAddr *et LogMsg("GetValueForMACAddr: Address malformed colons %d", colons); return mDNSNULL; } - eth->b[colons] = val; + eth->b[colons] = (mDNSs8)val; return ptr; } @@ -9698,6 +9673,11 @@ mDNSlocal mDNSu8 *GetValueForIPv4Addr(mDNSu8 *ptr, mDNSu8 *limit, mDNSv4Addr *v4 val = val * 10 + *ptr - '0'; else if (*ptr == '.') { + if (val > 255 || dots >= 3) + { + LogMsg("GetValueForIPv4Addr: something wrong ptr(%p) %c, limit %p, dots %d", ptr, *ptr, limit, dots); + return mDNSNULL; + } v4->b[dots++] = val; val = 0; } @@ -9740,6 +9720,37 @@ mDNSlocal mDNSu8 *GetValueForKeepalive(mDNSu8 *ptr, mDNSu8 *limit, mDNSu32 *valu return ptr; } +mDNSexport mDNSBool mDNSValidKeepAliveRecord(AuthRecord *rr) +{ + mDNSAddr laddr, raddr; + mDNSEthAddr eth; + mDNSIPPort lport, rport; + mDNSu32 timeout, seq, ack; + mDNSu16 win; + + if (!mDNS_KeepaliveRecord(&rr->resrec)) + { + return mDNSfalse; + } + + timeout = seq = ack = 0; + win = 0; + laddr = raddr = zeroAddr; + lport = rport = zeroIPPort; + + mDNS_ExtractKeepaliveInfo(rr, &timeout, &laddr, &raddr, ð, &seq, &ack, &lport, &rport, &win); + + if (mDNSAddressIsZero(&laddr) || mDNSIPPortIsZero(lport) || + mDNSAddressIsZero(&raddr) || mDNSIPPortIsZero(rport) || + mDNSEthAddressIsZero(eth)) + { + return mDNSfalse; + } + + return mDNStrue; +} + + mDNSlocal void mDNS_ExtractKeepaliveInfo(AuthRecord *ar, mDNSu32 *timeout, mDNSAddr *laddr, mDNSAddr *raddr, mDNSEthAddr *eth, mDNSu32 *seq, mDNSu32 *ack, mDNSIPPort *lport, mDNSIPPort *rport, mDNSu16 *win) { @@ -9916,16 +9927,18 @@ mDNSlocal void mDNS_SendKeepalives(mDNS *const m) mDNSlocal void mDNS_SendKeepaliveACK(mDNS *const m, AuthRecord *ar) { - if (ar != mDNSNULL) - { - LogInfo("mDNS_SendKeepalivesACK: AuthRecord is NULL"); - return; - } - mDNSu32 timeout, seq, ack; + mDNSu32 timeout, seq, ack, seqInc; mDNSu16 win; mDNSAddr laddr, raddr; mDNSEthAddr eth; mDNSIPPort lport, rport; + mDNSu8 *ptr; + + if (ar == mDNSNULL) + { + LogInfo("mDNS_SendKeepalivesACK: AuthRecord is NULL"); + return; + } timeout = seq = ack = 0; win = 0; @@ -9940,6 +9953,17 @@ mDNSlocal void mDNS_SendKeepaliveACK(mDNS *const m, AuthRecord *ar) LogInfo("mDNS_SendKeepaliveACK: not a valid record %s for keepalive", ARDisplayString(m, ar)); return; } + + // To send a keepalive ACK, we need to add one to the sequence number from the keepalive + // record, which is the TCP connection's "next" sequence number minus one. Otherwise, the + // keepalive ACK also ends up being a keepalive probe. Also, seq is in network byte order, so + // it's converted to host byte order before incrementing it by one. + ptr = (mDNSu8 *)&seq; + seqInc = (mDNSu32)((ptr[0] << 24) | (ptr[1] << 16) | (ptr[2] << 8) | ptr[3]) + 1; + ptr[0] = (mDNSu8)((seqInc >> 24) & 0xFF); + ptr[1] = (mDNSu8)((seqInc >> 16) & 0xFF); + ptr[2] = (mDNSu8)((seqInc >> 8) & 0xFF); + ptr[3] = (mDNSu8)((seqInc ) & 0xFF); LogMsg("mDNS_SendKeepaliveACK: laddr %#a raddr %#a lport %d rport %d", &laddr, &raddr, mDNSVal16(lport), mDNSVal16(rport)); mDNSPlatformSendKeepalive(&laddr, &raddr, &lport, &rport, seq, ack, win); } @@ -10106,6 +10130,8 @@ mDNSlocal void mDNSCoreReceiveUpdateR(mDNS *const m, const DNSMessage *const msg { mDNSu32 updatelease = 60 * 60; // If SPS fails to indicate lease time, assume one hour const mDNSu8 *ptr = LocateOptRR(msg, end, DNSOpt_LeaseData_Space); + mDNSAddr spsaddr; + char *ifname; if (ptr) { ptr = GetLargeResourceRecord(m, msg, ptr, end, 0, kDNSRecordTypePacketAdd, &m->rec); @@ -10155,8 +10181,7 @@ mDNSlocal void mDNSCoreReceiveUpdateR(mDNS *const m, const DNSMessage *const msg } // Update the dynamic store with the IP Address and MAC address of the sleep proxy - char *ifname = InterfaceNameForID(m, InterfaceID); - mDNSAddr spsaddr; + ifname = InterfaceNameForID(m, InterfaceID); mDNSPlatformMemCopy(&spsaddr, srcaddr, sizeof (mDNSAddr)); mDNSPlatformStoreSPSMACAddr(&spsaddr, ifname); } @@ -10169,12 +10194,7 @@ mDNSexport void MakeNegativeCacheRecord(mDNS *const m, CacheRecord *const cr, const domainname *const name, const mDNSu32 namehash, const mDNSu16 rrtype, const mDNSu16 rrclass, mDNSu32 ttl_seconds, mDNSInterfaceID InterfaceID, DNSServer *dnsserver) { if (cr == &m->rec.r && m->rec.r.resrec.RecordType) - { - LogMsg("MakeNegativeCacheRecord: m->rec appears to be already in use for %s", CRDisplayString(m, &m->rec.r)); -#if ForceAlerts - *(long*)0 = 0; -#endif - } + LogFatalError("MakeNegativeCacheRecord: m->rec appears to be already in use for %s", CRDisplayString(m, &m->rec.r)); // Create empty resource record cr->resrec.RecordType = kDNSRecordTypePacketNegative; @@ -10282,7 +10302,7 @@ mDNSexport void mDNSCoreReceive(mDNS *const m, void *const pkt, const mDNSu8 *co // Track the number of multicast packets received from a source outside our subnet. // Check the destination address to avoid accounting for spurious packets that // comes in with message id zero. - if (!mDNS_AddressIsLocalSubnet(m, InterfaceID, srcaddr, mDNSNULL) && + if (!mDNS_AddressIsLocalSubnet(m, InterfaceID, srcaddr) && mDNSAddressIsAllDNSLinkGroup(dstaddr)) { m->RemoteSubnet++; @@ -10489,8 +10509,8 @@ mDNSexport McastResolver *mDNS_AddMcastResolver(mDNS *const m, const domainname { if ((*p)->interface == interface && SameDomainName(&(*p)->domain, d)) { - if (!((*p)->flags & DNSServer_FlagDelete)) LogMsg("Note: Mcast Resolver domain %##s (%p) registered more than once", d->c, interface); - (*p)->flags &= ~DNSServer_FlagDelete; + if (!((*p)->flags & McastResolver_FlagDelete)) LogMsg("Note: Mcast Resolver domain %##s (%p) registered more than once", d->c, interface); + (*p)->flags &= ~McastResolver_FlagDelete; tmp = *p; *p = tmp->next; tmp->next = mDNSNULL; @@ -10508,7 +10528,7 @@ mDNSexport McastResolver *mDNS_AddMcastResolver(mDNS *const m, const domainname else { (*p)->interface = interface; - (*p)->flags = DNSServer_FlagNew; + (*p)->flags = McastResolver_FlagNew; (*p)->timeout = timeout; AssignDomainName(&(*p)->domain, d); (*p)->next = mDNSNULL; @@ -10714,9 +10734,10 @@ mDNSexport mDNSu32 SetValidDNSServers(mDNS *m, DNSQuestion *question) // // Note: DNS configuration change will help pick the new dns servers but currently it does not affect the timeout - if (curr->scoped && curr->interface == mDNSInterface_Any) + // Skip DNSServers that are InterfaceID Scoped but have no valid interfaceid set OR DNSServers that are ServiceID Scoped but have no valid serviceid set + if ((curr->scoped == kScopeInterfaceID && curr->interface == mDNSInterface_Any) || (curr->scoped == kScopeServiceID && curr->serviceID <= 0)) { - debugf("SetValidDNSServers: Scoped DNS server %#a (Domain %##s) with Interface Any", &curr->addr, curr->domain.c); + LogInfo("SetValidDNSServers: ScopeType[%d] Skipping DNS server %#a (Domain %##s) Interface:[%p] Serviceid:[%d]", curr->scoped, &curr->addr, curr->domain.c, curr->interface, curr->serviceID); continue; } @@ -11367,6 +11388,9 @@ mDNSlocal void InitDNSConfig(mDNS *const m, DNSQuestion *const question) question->triedAllServersOnce = 0; question->noServerResponse = 0; question->StopTime = 0; +#if TARGET_OS_EMBEDDED + mDNSPlatformMemZero(&question->metrics, sizeof(question->metrics)); +#endif // Need not initialize the DNS Configuration for Local Only OR P2P Questions if (question->InterfaceID == mDNSInterface_LocalOnly || question->InterfaceID == mDNSInterface_P2P) @@ -11415,6 +11439,7 @@ mDNSlocal mDNSBool InitCommonState(mDNS *const m, DNSQuestion *const question) { mDNSBool purge; int i; + mDNSBool isCellBlocked = mDNSfalse; // Note: In the case where we already have the answer to this question in our cache, that may be all the client // wanted, and they may immediately cancel their question. In this case, sending an actual query on the wire would @@ -11463,14 +11488,14 @@ mDNSlocal mDNSBool InitCommonState(mDNS *const m, DNSQuestion *const question) question->FlappingInterface1 = mDNSNULL; question->FlappingInterface2 = mDNSNULL; - // if kDNSServiceFlagsServiceIndex flag is SET by the client, then do NOT call mDNSPlatformGetServiceID() + // if kDNSServiceFlagsServiceIndex flag is SET by the client, then do NOT call mDNSPlatformGetDNSRoutePolicy() // since we would already have the question->ServiceID in that case. if (!(question->flags & kDNSServiceFlagsServiceIndex)) - question->ServiceID = mDNSPlatformGetServiceID(m, question); + mDNSPlatformGetDNSRoutePolicy(m, question, &isCellBlocked); else - LogInfo("InitCommonState: Query for %##s (%s), PID[%d], ServiceID %d is already set by client", question->qname.c, - DNSTypeName(question->qtype), question->pid, question->ServiceID); - + LogInfo("InitCommonState: Query for %##s (%s), PID[%d], EUID[%d], ServiceID[%d] is already set by client", question->qname.c, + DNSTypeName(question->qtype), question->pid, question->euid, question->ServiceID); + InitDNSConfig(m, question); question->AuthInfo = GetAuthInfoForQuestion(m, question); @@ -11480,10 +11505,10 @@ mDNSlocal mDNSBool InitCommonState(mDNS *const m, DNSQuestion *const question) // If ServiceID is 0 or the policy disallows making DNS requests, // set DisallowPID - question->DisallowPID = (question->ServiceID == 0 || (mDNSPlatformAllowPID(m, question) == 0)); + question->DisallowPID = (question->ServiceID == 0 || (isCellBlocked && question->qDNSServer && question->qDNSServer->cellIntf)); if (question->DisallowPID) LogInfo("InitCommonState: Query suppressed for %##s (%s), PID %d/ServiceID %d not allowed", question->qname.c, - DNSTypeName(question->qtype), question->pid, question->ServiceID); + DNSTypeName(question->qtype), question->pid, question->ServiceID); question->NextInDQList = mDNSNULL; question->SendQNow = mDNSNULL; @@ -11602,7 +11627,7 @@ mDNSlocal void InitDNSSECProxyState(mDNS *const m, DNSQuestion *const question) { if (question->qDNSServer->cellIntf) { - LogInfo("InitDNSSECProxyState: Turning off validation for %##s (%s); going over cell", question->qname.c, DNSTypeName(question->qtype)); + debugf("InitDNSSECProxyState: Turning off validation for %##s (%s); going over cell", question->qname.c, DNSTypeName(question->qtype)); question->ValidationRequired = mDNSfalse; } if (DNSSECOptionalQuestion(question) && !(question->qDNSServer->req_DO)) @@ -11739,6 +11764,13 @@ mDNSexport mStatus mDNS_StartQuery_internal(mDNS *const m, DNSQuestion *const qu } else { +#if TARGET_OS_WATCH + m->NumAllInterfaceQuestions++; + LogInfo("mDNS_StartQuery_internal: NumAllInterfaceRecords %d NumAllInterfaceQuestions %d %##s (%s)", + m->NumAllInterfaceRecords, m->NumAllInterfaceQuestions, question->qname.c, DNSTypeName(question->qtype)); + if (m->NumAllInterfaceRecords + m->NumAllInterfaceQuestions == 1) + m->NetworkChanged = m->timenow; +#endif if (purge) { LogInfo("mDNS_StartQuery_internal: Purging for %##s", question->qname.c); @@ -11783,14 +11815,35 @@ mDNSexport mStatus mDNS_StopQuery_internal(mDNS *const m, DNSQuestion *const que #if !ForceAlerts if (question->ThisQInterval >= 0) // Only log error message if the query was supposed to be active #endif - LogMsg("mDNS_StopQuery_internal: Question %##s (%s) not found in active list", - question->qname.c, DNSTypeName(question->qtype)); -#if ForceAlerts - *(long*)0 = 0; -#endif + LogFatalError("mDNS_StopQuery_internal: Question %##s (%s) not found in active list", question->qname.c, DNSTypeName(question->qtype)); return(mStatus_BadReferenceErr); } +#if TARGET_OS_WATCH + if (question->InterfaceID != mDNSInterface_LocalOnly && question->InterfaceID != mDNSInterface_P2P && mDNSOpaque16IsZero(question->TargetQID)) + { + if (m->NumAllInterfaceRecords + m->NumAllInterfaceQuestions == 1) + m->NetworkChanged = m->timenow; + m->NumAllInterfaceQuestions--; + LogInfo("mDNS_StopQuery_internal: NumAllInterfaceRecords %d NumAllInterfaceQuestions %d %##s (%s)", + m->NumAllInterfaceRecords, m->NumAllInterfaceQuestions, question->qname.c, DNSTypeName(question->qtype)); + } +#endif + +#if TARGET_OS_EMBEDDED + if (Question_uDNS(question) && !question->metrics.answered) + { + uDNSMetrics * metrics; + const domainname * queryName; + mDNSBool isForCellular; + + metrics = &question->metrics; + queryName = metrics->originalQName ? metrics->originalQName : &question->qname; + isForCellular = (question->qDNSServer && question->qDNSServer->cellIntf); + + MetricsUpdateUDNSStats(queryName, mDNSfalse, metrics->querySendCount, 0, isForCellular); + } +#endif // Take care to cut question from list *before* calling UpdateQuestionDuplicates UpdateQuestionDuplicates(m, question); // But don't trash ThisQInterval until afterwards. @@ -11913,6 +11966,13 @@ mDNSexport mStatus mDNS_StopQuery_internal(mDNS *const m, DNSQuestion *const que FreeAnonInfo(question->AnonInfo); question->AnonInfo = mDNSNULL; } +#if TARGET_OS_EMBEDDED + if (question->metrics.originalQName) + { + mDNSPlatformMemFree(question->metrics.originalQName); + question->metrics.originalQName = mDNSNULL; + } +#endif return(mStatus_NoError); } @@ -12365,6 +12425,7 @@ mDNSexport mStatus mDNS_GetDomains(mDNS *const m, DNSQuestion *const question, m question->qnameOrig = mDNSNULL; question->AnonInfo = mDNSNULL; question->pid = mDNSPlatformGetPID(); + question->euid = 0; question->QuestionCallback = Callback; question->QuestionContext = Context; if (DomainType > mDNS_DomainTypeMax) return(mStatus_BadParamErr); @@ -12481,26 +12542,20 @@ mDNSlocal void AdvertiseInterface(mDNS *const m, NetworkInterfaceInfo *set) { char buffer[MAX_REVERSE_MAPPING_NAME]; NetworkInterfaceInfo *primary; + mDNSu8 recordType; - if (!set->McastTxRx) - { - LogInfo("AdvertiseInterface: Returning, not multicast capable %s", set->ifname); - return; - } -#if TARGET_OS_EMBEDDED - if (!m->AutoTargetServices) + if (m->AutoTargetServices == 0) { LogInfo("AdvertiseInterface: Returning due to AutoTargetServices zero for %s", set->ifname); return; } -#endif primary = FindFirstAdvertisedInterface(m); if (!primary) primary = set; // If no existing advertised interface, this new NetworkInterfaceInfo becomes our new primary // If interface is marked as a direct link, we can assume the address record is unique // and does not need to go through the probe phase of the probe/announce packet sequence. - mDNSu8 recordType = (set->DirectLink ? kDNSRecordTypeKnownUnique : kDNSRecordTypeUnique); + recordType = (set->DirectLink ? kDNSRecordTypeKnownUnique : kDNSRecordTypeUnique); if (set->DirectLink) LogInfo("AdvertiseInterface: Marking address record as kDNSRecordTypeKnownUnique for %s", set->ifname); @@ -12575,22 +12630,19 @@ mDNSlocal void AdvertiseInterface(mDNS *const m, NetworkInterfaceInfo *set) mDNSlocal void DeadvertiseInterface(mDNS *const m, NetworkInterfaceInfo *set) { - NetworkInterfaceInfo *intf; - - // If we still have address records referring to this one, update them - NetworkInterfaceInfo *primary = FindFirstAdvertisedInterface(m); - AuthRecord *A = primary ? &primary->RR_A : mDNSNULL; - for (intf = m->HostInterfaces; intf; intf = intf->next) - if (intf->RR_A.RRSet == &set->RR_A) - intf->RR_A.RRSet = A; + if (m->AutoTargetServices == 0) + { + LogInfo("DeadvertiseInterface: Returning due to AutoTargetServices zero for %s", set->ifname); + return; + } // Unregister these records. // When doing the mDNS_Exit processing, we first call DeadvertiseInterface for each interface, so by the time the platform // support layer gets to call mDNS_DeregisterInterface, the address and PTR records have already been deregistered for it. // Also, in the event of a name conflict, one or more of our records will have been forcibly deregistered. // To avoid unnecessary and misleading warning messages, we check the RecordType before calling mDNS_Deregister_internal(). - if (set->RR_A.resrec.RecordType) mDNS_Deregister_internal(m, &set->RR_A, mDNS_Dereg_normal); - if (set->RR_PTR.resrec.RecordType) mDNS_Deregister_internal(m, &set->RR_PTR, mDNS_Dereg_normal); + if (set->RR_A .resrec.RecordType) mDNS_Deregister_internal(m, &set->RR_A, mDNS_Dereg_normal); + if (set->RR_PTR .resrec.RecordType) mDNS_Deregister_internal(m, &set->RR_PTR, mDNS_Dereg_normal); if (set->RR_HINFO.resrec.RecordType) mDNS_Deregister_internal(m, &set->RR_HINFO, mDNS_Dereg_normal); #if APPLE_OSX_mDNSResponder @@ -12614,7 +12666,6 @@ mDNSlocal void AdvertiseAllInterfaceRecords(mDNS *const m) mDNSlocal void DeadvertiseAllInterfaceRecords(mDNS *const m) { -#if TARGET_OS_EMBEDDED NetworkInterfaceInfo *intf; for (intf = m->HostInterfaces; intf; intf = intf->next) { @@ -12624,15 +12675,11 @@ mDNSlocal void DeadvertiseAllInterfaceRecords(mDNS *const m) DeadvertiseInterface(m, intf); } } -#else - (void) m; //unused -#endif } mDNSexport void mDNS_SetFQDN(mDNS *const m) { domainname newmname; - NetworkInterfaceInfo *intf; AuthRecord *rr; newmname.c[0] = 0; @@ -12645,14 +12692,8 @@ mDNSexport void mDNS_SetFQDN(mDNS *const m) else { AssignDomainName(&m->MulticastHostname, &newmname); - - // 1. Stop advertising our address records on all interfaces - for (intf = m->HostInterfaces; intf; intf = intf->next) - if (intf->Advertise) DeadvertiseInterface(m, intf); - - // 2. Start advertising our address records using the new name - for (intf = m->HostInterfaces; intf; intf = intf->next) - if (intf->Advertise) AdvertiseInterface(m, intf); + DeadvertiseAllInterfaceRecords(m); + AdvertiseAllInterfaceRecords(m); } // 3. Make sure that any AutoTarget SRV records (and the like) get updated @@ -12971,6 +13012,9 @@ mDNSexport void mDNS_DeregisterInterface(mDNS *const m, NetworkInterfaceInfo *se { NetworkInterfaceInfo **p = &m->HostInterfaces; mDNSBool revalidate = mDNSfalse; + NetworkInterfaceInfo *primary; + NetworkInterfaceInfo *intf; + AuthRecord *A; mDNS_Lock(m); @@ -12987,14 +13031,13 @@ mDNSexport void mDNS_DeregisterInterface(mDNS *const m, NetworkInterfaceInfo *se if (!set->InterfaceActive) { // If this interface not the active member of its set, update the v4/v6Available flags for the active member - NetworkInterfaceInfo *intf; for (intf = m->HostInterfaces; intf; intf = intf->next) if (intf->InterfaceActive && intf->InterfaceID == set->InterfaceID) UpdateInterfaceProtocols(m, intf); } else { - NetworkInterfaceInfo *intf = FirstInterfaceForID(m, set->InterfaceID); + intf = FirstInterfaceForID(m, set->InterfaceID); if (intf) { LogInfo("mDNS_DeregisterInterface: Another representative of InterfaceID %d %s (%#a) exists;" @@ -13027,7 +13070,7 @@ mDNSexport void mDNS_DeregisterInterface(mDNS *const m, NetworkInterfaceInfo *se if (set->McastTxRx && flapping) { - LogMsg("DeregisterInterface: Frequent transitions for interface %s (%#a)", set->ifname, &set->ip); + LogMsg("mDNS_DeregisterInterface: Frequent transitions for interface %s (%#a)", set->ifname, &set->ip); m->mDNSStats.InterfaceDownFlap++; } @@ -13068,6 +13111,15 @@ mDNSexport void mDNS_DeregisterInterface(mDNS *const m, NetworkInterfaceInfo *se } } + // If we still have address records referring to this one, update them. + // This is safe, because this NetworkInterfaceInfo has already been unlinked from the list, + // so the call to FindFirstAdvertisedInterface() won’t accidentally find it. + primary = FindFirstAdvertisedInterface(m); + A = primary ? &primary->RR_A : mDNSNULL; + for (intf = m->HostInterfaces; intf; intf = intf->next) + if (intf->RR_A.RRSet == &set->RR_A) + intf->RR_A.RRSet = A; + // If we were advertising on this interface, deregister those address and reverse-lookup records now if (set->Advertise) DeadvertiseInterface(m, set); @@ -13390,8 +13442,6 @@ mDNSexport mStatus mDNS_AddRecordToService(mDNS *const m, ServiceRecordSet *sr, e = &sr->Extras; while (*e) e = &(*e)->next; - if (ttl == 0) ttl = kStandardTTL; - extra->r.DependentOn = &sr->RR_SRV; debugf("mDNS_AddRecordToService adding record to %##s %s %d", @@ -14045,11 +14095,13 @@ mDNSexport void mDNSCoreReceiveRawPacket(mDNS *const m, const mDNSu8 *const p, c else if (end >= p+34 && mDNSSameOpaque16(eth->ethertype, Ethertype_IPv4) && (pkt->v4.flagsfrags.b[0] & 0x1F) == 0 && pkt->v4.flagsfrags.b[1] == 0) { const mDNSu8 *const trans = p + 14 + (pkt->v4.vlen & 0xF) * 4; + const mDNSu8 * transEnd = p + 14 + mDNSVal16(pkt->v4.totlen); + if (transEnd > end) transEnd = end; debugf("Got IPv4 %02X from %.4a to %.4a", pkt->v4.protocol, &pkt->v4.src, &pkt->v4.dst); src.type = mDNSAddrType_IPv4; src.ip.v4 = pkt->v4.src; dst.type = mDNSAddrType_IPv4; dst.ip.v4 = pkt->v4.dst; - if (end >= trans + RequiredCapLen(pkt->v4.protocol)) - mDNSCoreReceiveRawTransportPacket(m, ð->src, &src, &dst, pkt->v4.protocol, p, (TransportLayerPacket*)trans, end, InterfaceID, 0); + if (transEnd >= trans + RequiredCapLen(pkt->v4.protocol)) + mDNSCoreReceiveRawTransportPacket(m, ð->src, &src, &dst, pkt->v4.protocol, p, (TransportLayerPacket*)trans, transEnd, InterfaceID, 0); } // Is IPv6? Length must be at least 14 + 28 = 42 bytes else if (end >= p+54 && mDNSSameOpaque16(eth->ethertype, Ethertype_IPv6)) @@ -14180,6 +14232,7 @@ mDNSexport mStatus mDNS_Init(mDNS *const m, mDNS_PlatformSupport *const p, if (!rrcachestorage) rrcachesize = 0; m->p = p; + m->NetworkChanged = 0; m->CanReceiveUnicastOn5353 = mDNSfalse; // Assume we can't receive unicasts on 5353, unless platform layer tells us otherwise m->AdvertiseLocalAddresses = AdvertiseLocalAddresses; m->DivertMulticastAdvertisements = mDNSfalse; @@ -14302,13 +14355,20 @@ mDNSexport mStatus mDNS_Init(mDNS *const m, mDNS_PlatformSupport *const p, m->WABBrowseQueriesCount = 0; m->WABLBrowseQueriesCount = 0; m->WABRegQueriesCount = 0; -#if !TARGET_OS_EMBEDDED - m->mDNSOppCaching = mDNStrue; +#if TARGET_OS_EMBEDDED || TARGET_OS_WATCH + m->AutoTargetServices = 0; #else - m->mDNSOppCaching = mDNSfalse; + m->AutoTargetServices = 1; +#endif +#if TARGET_OS_WATCH + m->NumAllInterfaceRecords = 0; + m->NumAllInterfaceQuestions = 0; +#else + // Initialize to 1 for these targets to prevent not joining multicast group for interfaces when + // both of these values are zero. + m->NumAllInterfaceRecords = 1; + m->NumAllInterfaceQuestions = 1; #endif - m->AutoTargetServices = 0; - // NAT traversal fields m->LLQNAT.clientCallback = mDNSNULL; m->LLQNAT.clientContext = mDNSNULL; @@ -14545,6 +14605,10 @@ mDNSlocal void SetConfigState(mDNS *const m, mDNSBool delete) ptr->penaltyTime = 0; NumUnicastDNSServers--; ptr->flags |= DNSServer_FlagDelete; +#if APPLE_OSX_mDNSResponder + if (ptr->flags & DNSServer_FlagUnreachable) + NumUnreachableDNSServers--; +#endif } // We handle the mcast resolvers here itself as mDNSPlatformSetDNSConfig looks at // mcast resolvers. Today we get both mcast and ucast configuration using the same @@ -14559,6 +14623,10 @@ mDNSlocal void SetConfigState(mDNS *const m, mDNSBool delete) ptr->penaltyTime = 0; NumUnicastDNSServers++; ptr->flags &= ~DNSServer_FlagDelete; +#if APPLE_OSX_mDNSResponder + if (ptr->flags & DNSServer_FlagUnreachable) + NumUnreachableDNSServers++; +#endif } for (mr = m->McastResolvers; mr; mr = mr->next) mr->flags &= ~McastResolver_FlagDelete; @@ -14607,7 +14675,7 @@ mDNSexport mStatus uDNS_SetupDNSConfig(mDNS *const m) // affecting them as they never change. while (*mres) { - if (((*mres)->flags & DNSServer_FlagDelete) != 0) + if (((*mres)->flags & McastResolver_FlagDelete) != 0) { mr = *mres; *mres = (*mres)->next; @@ -14668,6 +14736,7 @@ mDNSexport mStatus uDNS_SetupDNSConfig(mDNS *const m) tport = t->port; else tport = zeroIPPort; + if (s) sport = s->port; else @@ -14724,8 +14793,9 @@ mDNSexport mStatus uDNS_SetupDNSConfig(mDNS *const m) } else { + mDNSIPPort zp = zeroIPPort; debugf("uDNS_SetupDNSConfig: Not Updating DNS server question %p %##s (%s) DNS server %#a:%d %p %d", - q, q->qname.c, DNSTypeName(q->qtype), t ? &t->addr : mDNSNULL, mDNSVal16(t ? t->port : zeroIPPort), q->DuplicateOf, q->SuppressUnusable); + q, q->qname.c, DNSTypeName(q->qtype), t ? &t->addr : mDNSNULL, mDNSVal16(t ? t->port : zp), q->DuplicateOf, q->SuppressUnusable); for (qptr = q->next ; qptr; qptr = qptr->next) if (qptr->DuplicateOf == q) { qptr->validDNSServers = q->validDNSServers; qptr->qDNSServer = q->qDNSServer; } } @@ -14943,7 +15013,6 @@ mDNSlocal void DeregLoop(mDNS *const m, AuthRecord *const start) mDNSexport void mDNS_StartExit(mDNS *const m) { - NetworkInterfaceInfo *intf; AuthRecord *rr; mDNS_Lock(m); @@ -14983,9 +15052,7 @@ mDNSexport void mDNS_StartExit(mDNS *const m) } #endif - for (intf = m->HostInterfaces; intf; intf = intf->next) - if (intf->Advertise) - DeadvertiseInterface(m, intf); + DeadvertiseAllInterfaceRecords(m); // Shut down all our active NAT Traversals while (m->NATTraversals) @@ -15045,6 +15112,7 @@ mDNSexport void mDNS_StartExit(mDNS *const m) mDNSexport void mDNS_FinalExit(mDNS *const m) { mDNSu32 rrcache_active = 0; + mDNSu32 rrcache_totalused = m->rrcache_totalused; mDNSu32 slot; AuthRecord *rr; @@ -15067,9 +15135,9 @@ mDNSexport void mDNS_FinalExit(mDNS *const m) ReleaseCacheGroup(m, &m->rrcache_hash[slot]); } } - debugf("mDNS_FinalExit: RR Cache was using %ld records, %lu active", m->rrcache_totalused, rrcache_active); + debugf("mDNS_FinalExit: RR Cache was using %ld records, %lu active", rrcache_totalused, rrcache_active); if (rrcache_active != m->rrcache_active) - LogMsg("*** ERROR *** rrcache_active %lu != m->rrcache_active %lu", rrcache_active, m->rrcache_active); + LogMsg("*** ERROR *** rrcache_totalused %lu; rrcache_active %lu != m->rrcache_active %lu", rrcache_totalused, rrcache_active, m->rrcache_active); for (rr = m->ResourceRecords; rr; rr = rr->next) LogMsg("mDNS_FinalExit failed to send goodbye for: %p %02X %s", rr, rr->resrec.RecordType, ARDisplayString(m, rr)); diff --git a/usr/src/cmd/cmd-inet/usr.lib/mdnsd/mDNSDebug.c b/usr/src/cmd/cmd-inet/usr.lib/mdnsd/mDNSDebug.c index cb4da6ecef..1243ae77a7 100644 --- a/usr/src/cmd/cmd-inet/usr.lib/mdnsd/mDNSDebug.c +++ b/usr/src/cmd/cmd-inet/usr.lib/mdnsd/mDNSDebug.c @@ -1,6 +1,6 @@ /* -*- Mode: C; tab-width: 4 -*- * - * Copyright (c) 2003 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2003-2015 Apple Inc. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,13 +13,6 @@ * 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. - - File: mDNSDebug.c - - Contains: Implementation of debugging utilities. Requires a POSIX environment. - - Version: 1.0 - */ #include "mDNSDebug.h" diff --git a/usr/src/cmd/cmd-inet/usr.lib/mdnsd/mDNSDebug.h b/usr/src/cmd/cmd-inet/usr.lib/mdnsd/mDNSDebug.h index 8bf4e5ada8..7bd783c568 100644 --- a/usr/src/cmd/cmd-inet/usr.lib/mdnsd/mDNSDebug.h +++ b/usr/src/cmd/cmd-inet/usr.lib/mdnsd/mDNSDebug.h @@ -1,6 +1,6 @@ /* -*- Mode: C; tab-width: 4 -*- * - * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2002-2015 Apple Inc. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -148,12 +148,18 @@ extern void LogMsgWithLevel(mDNSLogLevel_t logLevel, const char *format, ...) IS // (or completely overhauled to use the new "log to a separate file" facility) #define LogMsgNoIdent LogMsg +#if APPLE_OSX_mDNSResponder +extern void LogFatalError(const char *format, ...); +#else +#define LogFatalError LogMsg +#endif + #if APPLE_OSX_mDNSResponder && MACOSX_MDNS_MALLOC_DEBUGGING >= 1 extern void *mallocL(char *msg, unsigned int size); extern void freeL(char *msg, void *x); -extern void LogMemCorruption(const char *format, ...); extern void uds_validatelists(void); extern void udns_validatelists(void *const v); +extern void LogMemCorruption(const char *format, ...); #else #define mallocL(X,Y) malloc(Y) #define freeL(X,Y) free(Y) diff --git a/usr/src/cmd/cmd-inet/usr.lib/mdnsd/mDNSEmbeddedAPI.h b/usr/src/cmd/cmd-inet/usr.lib/mdnsd/mDNSEmbeddedAPI.h index 75e6fc0991..0b3e646423 100644 --- a/usr/src/cmd/cmd-inet/usr.lib/mdnsd/mDNSEmbeddedAPI.h +++ b/usr/src/cmd/cmd-inet/usr.lib/mdnsd/mDNSEmbeddedAPI.h @@ -1,6 +1,6 @@ /* -*- Mode: C; tab-width: 4 -*- * - * Copyright (c) 2002-2013 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2002-2015 Apple Inc. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -70,6 +70,7 @@ #include "mDNSDebug.h" #if APPLE_OSX_mDNSResponder #include <uuid/uuid.h> +#include <TargetConditionals.h> #endif #ifdef __cplusplus @@ -90,20 +91,14 @@ extern "C" { // In order to disable the above features pass the option to your compiler, e.g. -D UNICAST_DISABLED -// Additionally, the LIMITED_RESOURCES_TARGET compile option will eliminate caching and -// and reduce the maximum DNS message sizes. +// Additionally, the LIMITED_RESOURCES_TARGET compile option will reduce the maximum DNS message sizes. #ifdef LIMITED_RESOURCES_TARGET // Don't support jumbo frames -#define AbsoluteMaxDNSMessageData 1500 -// By the time you add IPv6 header (40 bytes) UDP header (8 bytes) and DNS message header (12 bytes) -// this makes 1560 which is 60 bytes over the standard Ethernet MTU. D'oh! - +// 40 (IPv6 header) + 8 (UDP header) + 12 (DNS message header) + 1440 (DNS message body) = 1500 total +#define AbsoluteMaxDNSMessageData 1440 // StandardAuthRDSize is 264 (256+8), which is large enough to hold a maximum-sized SRV record (6 + 256 bytes) #define MaximumRDSize 264 -// Don't cache anything -#define AUTH_HASH_SLOTS 1 -#define CACHE_HASH_SLOTS 1 #endif // *************************************************************************** @@ -560,7 +555,7 @@ typedef packedstruct { mDNSu8 vlen; mDNSu8 tos; - mDNSu16 totlen; + mDNSOpaque16 totlen; mDNSOpaque16 id; mDNSOpaque16 flagsfrags; mDNSu8 ttl; @@ -1324,8 +1319,11 @@ enum enum { - DNSServer_FlagDelete = 1, - DNSServer_FlagNew = 2 + DNSServer_FlagDelete = 0x1, + DNSServer_FlagNew = 0x2, +#if APPLE_OSX_mDNSResponder + DNSServer_FlagUnreachable = 0x4, +#endif }; enum @@ -1417,7 +1415,7 @@ struct ResourceRecord_struct // that are interface-specific (e.g. address records, especially linklocal addresses) const domainname *name; RData *rdata; // Pointer to storage for this rdata - DNSServer *rDNSServer; // Unicast DNS server authoritative for this entry;null for multicast + DNSServer *rDNSServer; // Unicast DNS server authoritative for this entry; null for multicast AnonymousInfo *AnonInfo; // Anonymous Information }; @@ -1506,7 +1504,7 @@ struct AuthRecord_struct AuthRecord *next; // Next in list; first element of structure for efficiency reasons // Field Group 1: Common ResourceRecord fields - ResourceRecord resrec; // 36 bytes when compiling for 32-bit; 48 when compiling for 64-bit + ResourceRecord resrec; // 36 bytes when compiling for 32-bit; 48 when compiling for 64-bit (now 44/64) // Field Group 2: Persistent metadata for Authoritative Records AuthRecord *Additional1; // Recommended additional record to include in response (e.g. SRV for PTR record) @@ -1638,7 +1636,7 @@ typedef struct ARListElem struct CacheRecord_struct { CacheRecord *next; // Next in list; first element of structure for efficiency reasons - ResourceRecord resrec; // 36 bytes when compiling for 32-bit; 48 when compiling for 64-bit + ResourceRecord resrec; // 36 bytes when compiling for 32-bit; 48 when compiling for 64-bit (now 44/64) // Transient state for Cache Records CacheRecord *NextInKAList; // Link to the next element in the chain of known answers to send @@ -1662,13 +1660,12 @@ struct CacheRecord_struct CacheRecord *soa; // SOA record to return for proxy questions mDNSAddr sourceAddress; // node from which we received this record - // Size to here is 76 bytes when compiling 32-bit; 104 bytes when compiling 64-bit + // Size to here is 76 bytes when compiling 32-bit; 104 bytes when compiling 64-bit (now 160 bytes for 64-bit) RData_small smallrdatastorage; // Storage for small records is right here (4 bytes header + 68 bytes data = 72 bytes) }; // Should match the CacheGroup_struct members, except namestorage[]. Only used to calculate -// the size of the namestorage array in CacheGroup_struct so that -// sizeof(CacheGroup) == sizeof(CacheRecord) +// the size of the namestorage array in CacheGroup_struct so that sizeof(CacheGroup) == sizeof(CacheRecord) struct CacheGroup_base { CacheGroup *next; @@ -1891,6 +1888,17 @@ typedef enum { DNSSECValNotRequired = 0, DNSSECValRequired, DNSSECValInProgress, // RFC 4122 defines it to be 16 bytes #define UUID_SIZE 16 +#if TARGET_OS_EMBEDDED +typedef struct +{ + domainname * originalQName; // Name of original A/AAAA record if this question is for a CNAME record. + mDNSu32 querySendCount; // Number of queries that have been sent to DNS servers so far. + mDNSs32 firstQueryTime; // The time when the first query was sent to a DNS server. + mDNSBool answered; // Has this question been answered? + +} uDNSMetrics; +#endif + struct DNSQuestion_struct { // Internal state fields. These are used internally by mDNSCore; the client layer needn't be concerned with them. @@ -2001,9 +2009,13 @@ struct DNSQuestion_struct mDNSu8 ProxyDNSSECOK; // Proxy Question with EDNS0 DNSSEC OK bit set mDNSs32 pid; // Process ID of the client that is requesting the question mDNSu8 uuid[UUID_SIZE]; // Unique ID of the client that is requesting the question (valid only if pid is zero) + mDNSu32 euid; // Effective User Id of the client that is requesting the question domainname *qnameOrig; // Copy of the original question name if it is not fully qualified mDNSQuestionCallback *QuestionCallback; void *QuestionContext; +#if TARGET_OS_EMBEDDED + uDNSMetrics metrics; // Data used for collecting unicast DNS query metrics. +#endif }; typedef struct @@ -2149,6 +2161,8 @@ struct NetworkInterfaceInfo_struct mDNSu8 SendGoodbyes; // Send goodbyes on this interface while sleeping mDNSBool DirectLink; // a direct link, indicating we can skip the probe for // address records + mDNSBool SupportsUnicastMDNSResponse; // Indicates that the interface supports unicast responses + // to Bonjour queries. Generally true for an interface. }; #define SLE_DELETE 0x00000001 @@ -2263,6 +2277,7 @@ typedef struct mDNSu32 CacheRefreshed; // Number of times the cache was refreshed due to a response mDNSu32 WakeOnResolves; // Number of times we did a wake on resolve } mDNSStatistics; + extern void LogMDNSStatistics(mDNS *const m); struct mDNS_struct @@ -2273,6 +2288,7 @@ struct mDNS_struct // all required data is passed as parameters to that function. mDNS_PlatformSupport *p; // Pointer to platform-specific data of indeterminite size + mDNSs32 NetworkChanged; mDNSBool CanReceiveUnicastOn5353; mDNSBool AdvertiseLocalAddresses; mDNSBool DivertMulticastAdvertisements; // from interfaces that do not advertise local addresses to local-only @@ -2372,7 +2388,7 @@ struct mDNS_struct mDNSs32 ProbeFailTime; mDNSu32 NumFailedProbes; mDNSs32 SuppressProbes; - Platform_t mDNS_plat; + Platform_t mDNS_plat; // Why is this here in the “only required for mDNS Responder” section? -- SC // Unicast-specific data mDNSs32 NextuDNSEvent; // uDNS next event @@ -2458,9 +2474,10 @@ struct mDNS_struct TrustAnchor *TrustAnchors; int notifyToken; - int uds_listener_skt; // Listening socket for incoming UDS clients - mDNSBool mDNSOppCaching; // Opportunistic Caching + int uds_listener_skt; // Listening socket for incoming UDS clients. This should not be here -- it's private to uds_daemon.c and nothing to do with mDNSCore -- SC mDNSu32 AutoTargetServices; // # of services that have AutoTarget set + mDNSu32 NumAllInterfaceRecords; // Right now we count *all* multicast records here. Later we may want to change to count interface-specific records separately. (This count includes records on the DuplicateRecords list too.) + mDNSu32 NumAllInterfaceQuestions; // Right now we count *all* multicast questions here. Later we may want to change to count interface-specific questions separately. DNSSECStatistics DNSSECStats; mDNSStatistics mDNSStats; @@ -2472,8 +2489,8 @@ struct mDNS_struct }; #define FORALL_CACHERECORDS(SLOT,CG,CR) \ - for ((SLOT) = 0; (SLOT) < CACHE_HASH_SLOTS; (SLOT)++) \ - for ((CG)=m->rrcache_hash[(SLOT)]; (CG); (CG)=(CG)->next) \ + for ((SLOT) = 0; (SLOT) < CACHE_HASH_SLOTS; (SLOT)++) \ + for ((CG)=m->rrcache_hash[(SLOT)]; (CG); (CG)=(CG)->next) \ for ((CR) = (CG)->members; (CR); (CR)=(CR)->next) // *************************************************************************** @@ -2534,6 +2551,9 @@ extern const mDNSOpaque64 zeroOpaque64; extern mDNSBool StrictUnicastOrdering; extern mDNSu8 NumUnicastDNSServers; +#if APPLE_OSX_mDNSResponder +extern mDNSu8 NumUnreachableDNSServers; +#endif #define localdomain (*(const domainname *)"\x5" "local") #define DeviceInfoName (*(const domainname *)"\xC" "_device-info" "\x4" "_tcp") @@ -2654,7 +2674,6 @@ extern mStatus mDNS_Init (mDNS *const m, mDNS_PlatformSupport *const p, extern void mDNS_ConfigChanged(mDNS *const m); extern void mDNS_GrowCache (mDNS *const m, CacheEntity *storage, mDNSu32 numrecords); -extern void mDNS_GrowAuth (mDNS *const m, AuthEntity *storage, mDNSu32 numrecords); extern void mDNS_StartExit (mDNS *const m); extern void mDNS_FinalExit (mDNS *const m); #define mDNS_Close(m) do { mDNS_StartExit(m); mDNS_FinalExit(m); } while(0) @@ -2790,7 +2809,7 @@ extern mStatus mDNS_AdvertiseDomains(mDNS *const m, AuthRecord *rr, mDNS_DomainT #define mDNS_StopAdvertiseDomains mDNS_Deregister extern mDNSOpaque16 mDNS_NewMessageID(mDNS *const m); -extern mDNSBool mDNS_AddressIsLocalSubnet(mDNS *const m, const mDNSInterfaceID InterfaceID, const mDNSAddr *addr, mDNSBool *myself); +extern mDNSBool mDNS_AddressIsLocalSubnet(mDNS *const m, const mDNSInterfaceID InterfaceID, const mDNSAddr *addr); extern DNSServer *GetServerForQuestion(mDNS *m, DNSQuestion *question); extern mDNSu32 SetValidDNSServers(mDNS *m, DNSQuestion *question); @@ -3201,6 +3220,7 @@ extern mStatus mDNSPlatformGetPrimaryInterface(mDNS *const m, mDNSAddr *v4, m extern void mDNSPlatformDynDNSHostNameStatusChanged(const domainname *const dname, const mStatus status); extern void mDNSPlatformSetAllowSleep(mDNS *const m, mDNSBool allowSleep, const char *reason); +extern void mDNSPlatformPreventSleep(mDNS *const m, mDNSu32 timeout, const char *reason); extern void mDNSPlatformSendWakeupPacket(mDNS *const m, mDNSInterfaceID InterfaceID, char *EthAddr, char *IPAddr, int iteration); extern mDNSBool mDNSPlatformInterfaceIsD2D(mDNSInterfaceID InterfaceID); @@ -3323,11 +3343,13 @@ extern void RemoveAutoTunnel6Record(mDNS *const m); extern mDNSBool RecordReadyForSleep(mDNS *const m, AuthRecord *rr); // For now this LocalSleepProxy 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 -extern mStatus ActivateLocalProxy(mDNS *const m, NetworkInterfaceInfo *const intf); +extern mStatus ActivateLocalProxy(mDNS *const m, NetworkInterfaceInfo *const intf, mDNSBool *keepaliveOnly); extern void mDNSPlatformUpdateDNSStatus(mDNS *const m, DNSQuestion *q); extern void mDNSPlatformTriggerDNSRetry(mDNS *const m, DNSQuestion *v4q, DNSQuestion *v6q); extern void mDNSPlatformLogToFile(int log_level, const char *buffer); extern mDNSBool SupportsInNICProxy(NetworkInterfaceInfo *const intf); +extern mStatus SymptomReporterDNSServerReachable(mDNS *const m, const mDNSAddr *addr); +extern mStatus SymptomReporterDNSServerUnreachable(DNSServer *s); #endif typedef void ProxyCallback (mDNS *const m, void *socket, void *const msg, const mDNSu8 *const end, const mDNSAddr *const srcaddr, @@ -3342,10 +3364,10 @@ extern mDNSu8 *DNSProxySetAttributes(DNSQuestion *q, DNSMessageHeader *h, DNSMes extern void mDNSPlatformSleepAssertion(mDNS *const m, double timeout); #endif -extern mDNSBool mDNSPlatformAllowPID(mDNS *const m, DNSQuestion *q); -extern mDNSs32 mDNSPlatformGetServiceID(mDNS *const m, DNSQuestion *q); +extern void mDNSPlatformGetDNSRoutePolicy(mDNS *const m, DNSQuestion *q, mDNSBool *isBlocked); extern void mDNSPlatformSetuDNSSocktOpt(UDPSocket *src, const mDNSAddr *dst, DNSQuestion *q); extern mDNSs32 mDNSPlatformGetPID(void); +extern mDNSBool mDNSValidKeepAliveRecord(AuthRecord *rr); // *************************************************************************** #if 0 @@ -3562,21 +3584,18 @@ struct CompileTimeAssertionChecks_mDNS char sizecheck_AuthRecord [(sizeof(AuthRecord) <= 1208) ? 1 : -1]; char sizecheck_CacheRecord [(sizeof(CacheRecord) <= 232) ? 1 : -1]; char sizecheck_CacheGroup [(sizeof(CacheGroup) <= 232) ? 1 : -1]; - char sizecheck_DNSQuestion [(sizeof(DNSQuestion) <= 832) ? 1 : -1]; + char sizecheck_DNSQuestion [(sizeof(DNSQuestion) <= 864) ? 1 : -1]; -// Checks commented out when sizeof(DNSQuestion) change cascaded into having to change yet another -// set of hardcoded size values because these structures contain one or more DNSQuestion -// instances. -// char sizecheck_ZoneData [(sizeof(ZoneData) <= 1648) ? 1 : -1]; + char sizecheck_ZoneData [(sizeof(ZoneData) <= 1700) ? 1 : -1]; char sizecheck_NATTraversalInfo [(sizeof(NATTraversalInfo) <= 200) ? 1 : -1]; char sizecheck_HostnameInfo [(sizeof(HostnameInfo) <= 3050) ? 1 : -1]; char sizecheck_DNSServer [(sizeof(DNSServer) <= 340) ? 1 : -1]; -// char sizecheck_NetworkInterfaceInfo[(sizeof(NetworkInterfaceInfo) <= 6988) ? 1 : -1]; + char sizecheck_NetworkInterfaceInfo[(sizeof(NetworkInterfaceInfo) <= 7184) ? 1 : -1]; char sizecheck_ServiceRecordSet [(sizeof(ServiceRecordSet) <= 5540) ? 1 : -1]; char sizecheck_DomainAuthInfo [(sizeof(DomainAuthInfo) <= 7888) ? 1 : -1]; -// char sizecheck_ServiceInfoQuery [(sizeof(ServiceInfoQuery) <= 3302) ? 1 : -1]; + char sizecheck_ServiceInfoQuery [(sizeof(ServiceInfoQuery) <= 3488) ? 1 : -1]; #if APPLE_OSX_mDNSResponder -// char sizecheck_ClientTunnel [(sizeof(ClientTunnel) <= 1160) ? 1 : -1]; + char sizecheck_ClientTunnel [(sizeof(ClientTunnel) <= 1208) ? 1 : -1]; #endif }; diff --git a/usr/src/cmd/cmd-inet/usr.lib/mdnsd/mDNSPosix.c b/usr/src/cmd/cmd-inet/usr.lib/mdnsd/mDNSPosix.c index 5a385e6299..f16e82044a 100644 --- a/usr/src/cmd/cmd-inet/usr.lib/mdnsd/mDNSPosix.c +++ b/usr/src/cmd/cmd-inet/usr.lib/mdnsd/mDNSPosix.c @@ -1,6 +1,6 @@ /* -*- Mode: C; tab-width: 4 -*- * - * Copyright (c) 2002-2004 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2002-2015 Apple Inc. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -132,18 +132,6 @@ mDNSlocal void SockAddrTomDNSAddr(const struct sockaddr *const sa, mDNSAddr *ipA } } -/* - * Apple source is using this to set mobile platform - * specific options. - */ -/*ARGSUSED*/ -mDNSexport void mDNSPlatformSetuDNSSocktOpt(UDPSocket *src, const mDNSAddr *dst, DNSQuestion *q) -{ - (void)src; /* unused */ - (void)dst; /* unused */ - (void)q; /* unused */ -} - #if COMPILER_LIKES_PRAGMA_MARK #pragma mark ***** Send and Receive #endif @@ -210,7 +198,7 @@ mDNSexport mStatus mDNSPlatformSendUDP(const mDNS *const m, const void *const ms if (errno == EHOSTDOWN || errno == ENETDOWN || errno == EHOSTUNREACH || errno == ENETUNREACH) return(mStatus_TransientErr); /* dont report ENETUNREACH */ - if (errno == ENETUNREACH) return(mStatus_TransientErr); + if (errno == ENETUNREACH) return(mStatus_TransientErr); if (MessageCount < 1000) { @@ -456,15 +444,19 @@ mDNSexport void FreeEtcHosts(mDNS *const m, AuthRecord *const rr, mStatus result #pragma mark ***** DDNS Config Platform Functions #endif +/* + * Stub to set or get DNS config. Even if it actually does not do anything, it has to + * make sure the data is zeroed properly. + */ mDNSexport mDNSBool mDNSPlatformSetDNSConfig(mDNS *const m, mDNSBool setservers, mDNSBool setsearch, domainname *const fqdn, DNameListElem **RegDomains, DNameListElem **BrowseDomains, mDNSBool ackConfig) { (void) m; (void) setservers; - (void) fqdn; + if (fqdn) fqdn->c[0] = 0; (void) setsearch; - (void) RegDomains; - (void) BrowseDomains; + if (RegDomains) *RegDomains = NULL; + if (BrowseDomains) *BrowseDomains = NULL; (void) ackConfig; return mDNStrue; @@ -531,7 +523,7 @@ mDNSexport int ParseDNSServers(mDNS *m, const char *filePath) numOfServers++; } } - fclose(fp); + fclose(fp); return (numOfServers > 0) ? 0 : -1; } @@ -655,10 +647,22 @@ mDNSlocal int SetupSocket(struct sockaddr *intfAddr, mDNSIPPort port, int interf // ... with a shared UDP port, if it's for multicast receiving if (err == 0 && port.NotAnInteger) { - #if defined(SO_REUSEPORT) - err = setsockopt(*sktPtr, SOL_SOCKET, SO_REUSEPORT, &kOn, sizeof(kOn)); - #elif defined(SO_REUSEADDR) + // <rdar://problem/20946253> + // We test for SO_REUSEADDR first, as suggested by Jonny Törnbom from Axis Communications + // Linux kernel versions 3.9 introduces support for socket option + // SO_REUSEPORT, however this is not implemented the same as on *BSD + // systems. Linux version implements a "port hijacking" prevention + // mechanism, limiting processes wanting to bind to an already existing + // addr:port to have the same effective UID as the first who bound it. What + // this meant for us was that the daemon ran as one user and when for + // instance mDNSClientPosix was executed by another user, it wasn't allowed + // to bind to the socket. Our suggestion was to switch the order in which + // SO_REUSEPORT and SO_REUSEADDR was tested so that SO_REUSEADDR stays on + // top and SO_REUSEPORT to be used only if SO_REUSEADDR doesn't exist. + #if defined(SO_REUSEADDR) && !defined(__MAC_OS_X_VERSION_MIN_REQUIRED) err = setsockopt(*sktPtr, SOL_SOCKET, SO_REUSEADDR, &kOn, sizeof(kOn)); + #elif defined(SO_REUSEPORT) + err = setsockopt(*sktPtr, SOL_SOCKET, SO_REUSEPORT, &kOn, sizeof(kOn)); #else #error This platform has no way to avoid address busy errors on multicast. #endif @@ -667,9 +671,9 @@ mDNSlocal int SetupSocket(struct sockaddr *intfAddr, mDNSIPPort port, int interf // Enable inbound packets on IFEF_AWDL interface. // Only done for multicast sockets, since we don't expect unicast socket operations // on the IFEF_AWDL interface. Operation is a no-op for other interface types. - #ifdef SO_RECV_ANYIF + #ifdef SO_RECV_ANYIF if (setsockopt(*sktPtr, SOL_SOCKET, SO_RECV_ANYIF, &kOn, sizeof(kOn)) < 0) perror("setsockopt - SO_RECV_ANYIF"); - #endif + #endif } // We want to receive destination addresses and interface identifiers. @@ -756,11 +760,11 @@ mDNSlocal int SetupSocket(struct sockaddr *intfAddr, mDNSIPPort port, int interf struct ipv6_mreq imr6; struct sockaddr_in6 bindAddr6; #if defined(IPV6_RECVPKTINFO) // Solaris - if (err == 0) - { - err = setsockopt(*sktPtr, IPPROTO_IPV6, IPV6_RECVPKTINFO, &kOn, sizeof(kOn)); - if (err < 0) { err = errno; perror("setsockopt - IPV6_RECVPKTINFO"); } - } + if (err == 0) + { + err = setsockopt(*sktPtr, IPPROTO_IPV6, IPV6_RECVPKTINFO, &kOn, sizeof(kOn)); + if (err < 0) { err = errno; perror("setsockopt - IPV6_RECVPKTINFO"); } + } #elif defined(IPV6_PKTINFO) if (err == 0) { @@ -771,11 +775,11 @@ mDNSlocal int SetupSocket(struct sockaddr *intfAddr, mDNSIPPort port, int interf #warning This platform has no way to get the destination interface information for IPv6 -- will only work for single-homed hosts #endif #if defined(IPV6_RECVHOPLIMIT) - if (err == 0) - { - err = setsockopt(*sktPtr, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &kOn, sizeof(kOn)); - if (err < 0) { err = errno; perror("setsockopt - IPV6_RECVHOPLIMIT"); } - } + if (err == 0) + { + err = setsockopt(*sktPtr, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &kOn, sizeof(kOn)); + if (err < 0) { err = errno; perror("setsockopt - IPV6_RECVHOPLIMIT"); } + } #elif defined(IPV6_HOPLIMIT) if (err == 0) { @@ -882,7 +886,7 @@ mDNSlocal int SetupOneInterface(mDNS *const m, struct sockaddr *intfAddr, struct assert(intfMask != NULL); // Allocate the interface structure itself. - intf = (PosixNetworkInterface*)malloc(sizeof(*intf)); + intf = (PosixNetworkInterface*)calloc(1, sizeof(*intf)); if (intf == NULL) { assert(0); err = ENOMEM; } // And make a copy of the intfName. @@ -937,6 +941,7 @@ mDNSlocal int SetupOneInterface(mDNS *const m, struct sockaddr *intfAddr, struct if (strcmp(intfName, STRINGIFY(DIRECTLINK_INTERFACE_NAME)) == 0) intf->coreIntf.DirectLink = mDNStrue; #endif + intf->coreIntf.SupportsUnicastMDNSResponse = mDNStrue; // The interface is all ready to go, let's register it with the mDNS core. if (err == 0) @@ -1206,11 +1211,6 @@ mDNSlocal mDNSu32 ProcessRoutingNotification(int sd) case RTM_NEWADDR: case RTM_DELADDR: case RTM_IFINFO: - if (pRSMsg->ifam_type == RTM_IFINFO) - result |= 1 << ((struct if_msghdr*) pRSMsg)->ifm_index; - else - result |= 1 << pRSMsg->ifam_index; - break; /* * ADD & DELETE are happening when IPv6 announces are changing, * and for some reason it will stop mdnsd to announce IPv6 @@ -1218,7 +1218,11 @@ mDNSlocal mDNSu32 ProcessRoutingNotification(int sd) */ case RTM_ADD: case RTM_DELETE: - result |= 1; + if (pRSMsg->ifam_type == RTM_IFINFO) + result |= 1 << ((struct if_msghdr*) pRSMsg)->ifm_index; + else + result |= 1 << pRSMsg->ifam_index; + break; } return result; @@ -1335,7 +1339,8 @@ mDNSexport mStatus mDNSPlatformInit(mDNS *const m) // Failure to observe interface changes is non-fatal. if (err != mStatus_NoError) { - fprintf(stderr, "mDNS(%d) WARNING: Unable to detect interface changes (%d).\n", (int)getpid(), err); + fprintf(stderr, "mDNS(%d) WARNING: Unable to detect interface changes (%d).\n", + (int)getpid(), err); err = mStatus_NoError; } } @@ -1624,21 +1629,15 @@ mDNSexport mDNSBool mDNSPlatformInterfaceIsD2D(mDNSInterfaceID InterfaceID) return mDNSfalse; } -mDNSexport mDNSBool mDNSPlatformAllowPID(mDNS *const m, DNSQuestion *q) +mDNSexport void mDNSPlatformGetDNSRoutePolicy(mDNS *const m, DNSQuestion *q, mDNSBool *isCellBlocked) { (void) m; - (void) q; - return mDNStrue; -} -mDNSexport mDNSs32 mDNSPlatformGetServiceID(mDNS *const m, DNSQuestion *q) -{ - (void) m; - (void) q; - return -1; + q->ServiceID = -1; + *isCellBlocked = mDNSfalse; } -mDNSexport void mDNSPlatformSetDelegatePID(UDPSocket *src, const mDNSAddr *dst, DNSQuestion *q) +mDNSexport void mDNSPlatformSetuDNSSocktOpt(UDPSocket *src, const mDNSAddr *dst, DNSQuestion *q) { (void) src; (void) dst; diff --git a/usr/src/cmd/cmd-inet/usr.lib/mdnsd/mDNSUNP.c b/usr/src/cmd/cmd-inet/usr.lib/mdnsd/mDNSUNP.c index 026eaae565..0b174e8301 100644 --- a/usr/src/cmd/cmd-inet/usr.lib/mdnsd/mDNSUNP.c +++ b/usr/src/cmd/cmd-inet/usr.lib/mdnsd/mDNSUNP.c @@ -87,14 +87,12 @@ void plen_to_mask(int plen, char *addr) { struct ifi_info *get_ifi_info_linuxv6(int family, int doaliases) { struct ifi_info *ifi, *ifihead, **ifipnext, *ifipold, **ifiptr; - FILE *fp; + FILE *fp = NULL; char addr[8][5]; int flags, myflags, index, plen, scope; char ifname[9], lastname[IFNAMSIZ]; char addr6[32+7+1]; /* don't forget the seven ':' */ struct addrinfo hints, *res0; - struct sockaddr_in6 *sin6; - struct in6_addr *addrptr; int err; int sockfd = -1; struct ifreq ifr; @@ -154,18 +152,13 @@ struct ifi_info *get_ifi_info_linuxv6(int family, int doaliases) char ipv6addr[INET6_ADDRSTRLEN]; plen_to_mask(plen, ipv6addr); ifi->ifi_netmask = calloc(1, sizeof(struct sockaddr_in6)); - if (ifi->ifi_addr == NULL) { + if (ifi->ifi_netmask == NULL) { goto gotError; } - sin6=calloc(1, sizeof(struct sockaddr_in6)); - addrptr=calloc(1, sizeof(struct in6_addr)); - inet_pton(family, ipv6addr, addrptr); - sin6->sin6_family=family; - sin6->sin6_addr=*addrptr; - sin6->sin6_scope_id=scope; - memcpy(ifi->ifi_netmask, sin6, sizeof(struct sockaddr_in6)); - free(sin6); + ((struct sockaddr_in6 *)ifi->ifi_netmask)->sin6_family=family; + ((struct sockaddr_in6 *)ifi->ifi_netmask)->sin6_scope_id=scope; + inet_pton(family, ipv6addr, &((struct sockaddr_in6 *)ifi->ifi_netmask)->sin6_addr); /* Add interface name */ memcpy(ifi->ifi_name, ifname, IFI_NAME); @@ -183,6 +176,7 @@ struct ifi_info *get_ifi_info_linuxv6(int family, int doaliases) * EADDRNOTAVAIL for the main interface */ free(ifi->ifi_addr); + free(ifi->ifi_netmask); free(ifi); ifipnext = ifiptr; *ifipnext = ifipold; @@ -211,6 +205,9 @@ done: if (sockfd != -1) { assert(close(sockfd) == 0); } + if (fp != NULL) { + fclose(fp); + } return(ifihead); /* pointer to first structure in linked list */ } #endif // defined(AF_INET6) && HAVE_IPV6 && HAVE_LINUX @@ -218,7 +215,7 @@ done: #if HAVE_SOLARIS /* - * Converts prefix length to network mask. Assumes + * Converts prefix length to network mask. Assumes * addr points to a zeroed out buffer and prefix <= sizeof(addr) * Unlike plen_to_mask returns netmask in binary form and not * in text form. @@ -231,10 +228,10 @@ static void plen_to_netmask(int prefix, unsigned char *addr) { } /* - * This function goes through all the IP interfaces associated with a - * physical interface and finds the best matched one for use by mDNS. + * This function goes through all the IP interfaces associated with a + * physical interface and finds the best matched one for use by mDNS. * Returns NULL when none of the IP interfaces associated with a physical - * interface are usable. Otherwise returns the best matched interface + * interface are usable. Otherwise returns the best matched interface * information and a pointer to the best matched lifreq. */ struct ifi_info * @@ -253,7 +250,7 @@ select_src_ifi_info_solaris(int sockfd, int numifs, *best_lifr = NULL; - /* + /* * Check all logical interfaces associated with the physical * interface and figure out which one works best for us. */ @@ -266,7 +263,7 @@ select_src_ifi_info_solaris(int sockfd, int numifs, if ((chptr = strchr(cmpifname, ':')) != NULL) *chptr = '\0'; - /* + /* * Check ifname to see if the logical interface is associated * with the physical interface we are interested in. */ @@ -286,7 +283,7 @@ select_src_ifi_info_solaris(int sockfd, int numifs, if ((ifflags & IFF_UP) == 0) continue; /* - * Avoid address if any of the following flags are set: + * Avoid address if any of the following flags are set: * IFF_NOXMIT: no packets transmitted over interface * IFF_NOLOCAL: no address * IFF_PRIVATE: is not advertised @@ -294,17 +291,17 @@ select_src_ifi_info_solaris(int sockfd, int numifs, if (ifflags & (IFF_NOXMIT | IFF_NOLOCAL | IFF_PRIVATE)) continue; - /* A DHCP client will have IFF_UP set yet the address is zero. Ignore */ + /* A DHCP client will have IFF_UP set yet the address is zero. Ignore */ if (lifr->lifr_addr.ss_family == AF_INET) { - struct sockaddr_in *sinptr; + struct sockaddr_in *sinptr; - sinptr = (struct sockaddr_in *) &lifr->lifr_addr; - if (sinptr->sin_addr.s_addr == INADDR_ANY) - continue; - } + sinptr = (struct sockaddr_in *) &lifr->lifr_addr; + if (sinptr->sin_addr.s_addr == INADDR_ANY) + continue; + } if (*best_lifr != NULL) { - /* + /* * Check if we found a better interface by checking * the flags. If flags are identical we prefer * the new found interface. @@ -343,7 +340,7 @@ select_src_ifi_info_solaris(int sockfd, int numifs, if (ifi == NULL) return(NULL); - ifi->ifi_flags = best_lifrflags; + ifi->ifi_flags = best_lifrflags; ifi->ifi_index = if_nametoindex((*best_lifr)->lifr_name); if (strlcpy(ifi->ifi_name, (*best_lifr)->lifr_name, sizeof(ifi->ifi_name)) >= sizeof(ifi->ifi_name)) { free(ifi); @@ -388,7 +385,7 @@ again: if (ioctl(sockfd, SIOCGLIFNUM, &lifn) < 0) goto gotError; /* - * Pad interface count to detect & retrieve any + * Pad interface count to detect & retrieve any * additional interfaces between IFNUM & IFCONF calls. */ lifn.lifn_count += 4; @@ -416,7 +413,7 @@ again: if (lifrp->lifr_addr.ss_family != family) continue; - /* + /* * See if we have already processed the interface * by checking the interface names. */ @@ -425,12 +422,12 @@ again: if ((cptr = strchr(ifname, ':')) != NULL) *cptr = '\0'; - /* + /* * If any of the interfaces found so far share the physical * interface name then we have already processed the interface. */ for (ifi = ifihead; ifi != NULL; ifi = ifi->ifi_next) { - + /* Retrieve physical interface name */ (void) strlcpy(cmpifname, ifi->ifi_name, sizeof(cmpifname)); @@ -444,7 +441,7 @@ again: if (ifi != NULL) continue; /* already processed */ - /* + /* * New interface, find the one with the preferred source * address for our use in Multicast DNS. */ @@ -496,7 +493,7 @@ again: } ifi->ifi_netmask = malloc(sizeof(struct sockaddr_in)); - if (ifi->ifi_netmask == NULL) + if (ifi->ifi_netmask == NULL) goto gotError; sinptr = (struct sockaddr_in *) &lifrcopy.lifr_addr; sinptr->sin_family = AF_INET; @@ -928,11 +925,11 @@ recvfrom_flags(int fd, void *ptr, size_t nbytes, int *flagsp, int nameLen = (sdl->sdl_nlen < IFI_NAME - 1) ? sdl->sdl_nlen : (IFI_NAME - 1); strncpy(pktp->ipi_ifname, sdl->sdl_data, nameLen); #endif - /* - * the is memcpy used for sparc? no idea;) - * pktp->ipi_ifindex = sdl->sdl_index; + /* + * the is memcpy used for sparc? no idea;) + * pktp->ipi_ifindex = sdl->sdl_index; */ - (void) memcpy(&pktp->ipi_ifindex, CMSG_DATA(cmptr), sizeof(uint_t)); + (void) memcpy(&pktp->ipi_ifindex, CMSG_DATA(cmptr), sizeof(uint_t)); #ifdef HAVE_BROKEN_RECVIF_NAME if (sdl->sdl_index == 0) { pktp->ipi_ifindex = *(uint_t*)sdl; diff --git a/usr/src/cmd/cmd-inet/usr.lib/mdnsd/nsec.h b/usr/src/cmd/cmd-inet/usr.lib/mdnsd/nsec.h index 3dbb841f15..198f57db92 100644 --- a/usr/src/cmd/cmd-inet/usr.lib/mdnsd/nsec.h +++ b/usr/src/cmd/cmd-inet/usr.lib/mdnsd/nsec.h @@ -1,6 +1,6 @@ /* -*- Mode: C; tab-width: 4 -*- * - * Copyright (c) 2011 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2011-2012 Apple Inc. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,6 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + #ifndef __NSEC_H #define __NSEC_H diff --git a/usr/src/cmd/cmd-inet/usr.lib/mdnsd/uDNS.c b/usr/src/cmd/cmd-inet/usr.lib/mdnsd/uDNS.c index f3206a49e1..6ce0158b56 100644 --- a/usr/src/cmd/cmd-inet/usr.lib/mdnsd/uDNS.c +++ b/usr/src/cmd/cmd-inet/usr.lib/mdnsd/uDNS.c @@ -1,6 +1,6 @@ /* -*- Mode: C; tab-width: 4 -*- * - * Copyright (c) 2002-2013 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2002-2015 Apple Inc. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -51,6 +51,9 @@ mDNSBool StrictUnicastOrdering = mDNSfalse; // arbitrary limitation of 64 DNSServers can be removed. mDNSu8 NumUnicastDNSServers = 0; #define MAX_UNICAST_DNS_SERVERS 64 +#if APPLE_OSX_mDNSResponder +mDNSu8 NumUnreachableDNSServers = 0; +#endif #define SetNextuDNSEvent(m, rr) { \ if ((m)->NextuDNSEvent - ((rr)->LastAPTime + (rr)->ThisAPInterval) >= 0) \ @@ -162,6 +165,12 @@ mDNSexport DNSServer *mDNS_AddDNSServer(mDNS *const m, const domainname *d, cons if (tmp) { +#if APPLE_OSX_mDNSResponder + if (tmp->flags & DNSServer_FlagDelete) + { + tmp->flags &= ~DNSServer_FlagUnreachable; + } +#endif tmp->flags &= ~DNSServer_FlagDelete; *p = tmp; // move to end of list, to ensure ordering from platform layer } @@ -212,6 +221,7 @@ mDNSexport void PenalizeDNSServer(mDNS *const m, DNSQuestion *q, mDNSOpaque16 re { DNSServer *new; DNSServer *orig = q->qDNSServer; + mDNSu8 rcode = '\0'; mDNS_CheckLock(m); @@ -223,9 +233,12 @@ mDNSexport void PenalizeDNSServer(mDNS *const m, DNSQuestion *q, mDNSOpaque16 re if (mDNSOpaque16IsZero(q->responseFlags)) q->responseFlags = responseFlags; + rcode = (mDNSu8)(responseFlags.b[1] & kDNSFlag1_RC_Mask); + // After we reset the qDNSServer to NULL, we could get more SERV_FAILS that might end up // peanlizing again. - if (!q->qDNSServer) goto end; + if (!q->qDNSServer) + goto end; // If strict ordering of unicast servers needs to be preserved, we just lookup // the next best match server below @@ -244,6 +257,10 @@ mDNSexport void PenalizeDNSServer(mDNS *const m, DNSQuestion *q, mDNSOpaque16 re { LogInfo("PenalizeDNSServer: Not Penalizing PTR question"); } + else if ((rcode == kDNSFlag1_RC_FormErr) || (rcode == kDNSFlag1_RC_ServFail) || (rcode == kDNSFlag1_RC_NotImpl) || (rcode == kDNSFlag1_RC_Refused)) + { + LogInfo("PenalizeDNSServer: Not Penalizing DNS Server since it at least responded with rcode %d", rcode); + } else { LogInfo("PenalizeDNSServer: Penalizing question type %d", q->qtype); @@ -607,10 +624,10 @@ mDNSlocal mStatus uDNS_SendNATMsg(mDNS *m, NATTraversalInfo *info, mDNSBool useP req.reservedMapOp[1] = 0; req.reservedMapOp[2] = 0; - if (info->Protocol) - req.intPort = info->IntPort; + if (info->Protocol) + req.intPort = info->IntPort; else - req.intPort = DiscardPort; + req.intPort = DiscardPort; req.extPort = info->RequestedPort; // Since we only support IPv4, even if using the all-zeros address, map it, so @@ -813,11 +830,8 @@ mDNSexport mStatus mDNS_StartNATOperation_internal(mDNS *const m, NATTraversalIn { if (traversal == *n) { - LogMsg("Error! Tried to add a NAT traversal that's already in the active list: request %p Prot %d Int %d TTL %d", + LogFatalError("Error! Tried to add a NAT traversal that's already in the active list: request %p Prot %d Int %d TTL %d", traversal, traversal->Protocol, mDNSVal16(traversal->IntPort), traversal->NATLease); - #if ForceAlerts - *(long*)0 = 0; - #endif return(mStatus_AlreadyRegistered); } if (traversal->Protocol && traversal->Protocol == (*n)->Protocol && mDNSSameIPPort(traversal->IntPort, (*n)->IntPort) && @@ -1841,9 +1855,9 @@ mDNSlocal void GetZoneData_QuestionCallback(mDNS *const m, DNSQuestion *question LogMsg("GetZoneData_QuestionCallback: Question %##s (%s) ThisQInterval %d not -1", question->qname.c, DNSTypeName(question->qtype), question->ThisQInterval); zd->Addr.type = mDNSAddrType_IPv4; if (answer->rdlength == 4) - zd->Addr.ip.v4 = answer->rdata->u.ipv4; + zd->Addr.ip.v4 = answer->rdata->u.ipv4; else - zd->Addr.ip.v4 = zerov4Addr; + zd->Addr.ip.v4 = zerov4Addr; // In order to simulate firewalls blocking our outgoing TCP connections, returning immediate ICMP errors or TCP resets, // the code below will make us try to connect to loopback, resulting in an immediate "port unreachable" failure. // This helps us test to make sure we handle this case gracefully @@ -1898,6 +1912,7 @@ mDNSlocal mStatus GetZoneData_StartQuery(mDNS *const m, ZoneData *zd, mDNSu16 qt zd->question.qnameOrig = mDNSNULL; zd->question.AnonInfo = mDNSNULL; zd->question.pid = mDNSPlatformGetPID(); + zd->question.euid = 0; zd->question.QuestionCallback = GetZoneData_QuestionCallback; zd->question.QuestionContext = zd; @@ -2587,6 +2602,7 @@ mDNSlocal void GetStaticHostname(mDNS *m) q->qnameOrig = mDNSNULL; q->AnonInfo = mDNSNULL; q->pid = mDNSPlatformGetPID(); + q->euid = 0; q->QuestionCallback = FoundStaticHostname; q->QuestionContext = mDNSNULL; @@ -4000,6 +4016,10 @@ mDNSexport void uDNS_ReceiveMsg(mDNS *const m, DNSMessage *const msg, const mDNS msg->h.numAnswers, msg->h.numAnswers == 1 ? ", " : "s,", msg->h.numAuthorities, msg->h.numAuthorities == 1 ? "y, " : "ies,", msg->h.numAdditionals, msg->h.numAdditionals == 1 ? "" : "s", end - msg->data); +#if APPLE_OSX_mDNSResponder + if (NumUnreachableDNSServers > 0) + SymptomReporterDNSServerReachable(m, srcaddr); +#endif if (QR_OP == StdR) { @@ -4150,7 +4170,7 @@ mDNSexport void LLQGotZoneData(mDNS *const m, mStatus err, const ZoneData *zoneI q->servAddr = zeroAddr; q->servPort = zeroIPPort; - if (!err && zoneInfo && !mDNSIPPortIsZero(zoneInfo->Port) && !mDNSAddressIsZero(&zoneInfo->Addr) && zoneInfo->Host.c[0]) + if (!err && !mDNSIPPortIsZero(zoneInfo->Port) && !mDNSAddressIsZero(&zoneInfo->Addr) && zoneInfo->Host.c[0]) { q->servAddr = zoneInfo->Addr; q->servPort = zoneInfo->Port; @@ -4247,10 +4267,14 @@ mDNSlocal void PrivateQueryGotZoneData(mDNS *const m, mStatus err, const ZoneDat // Called in normal callback context (i.e. mDNS_busy and mDNS_reentrancy are both 1) mDNSexport void RecordRegistrationGotZoneData(mDNS *const m, mStatus err, const ZoneData *zoneData) { - AuthRecord *newRR = (AuthRecord*)zoneData->ZoneDataContext; + AuthRecord *newRR; AuthRecord *ptr; int c1, c2; + if (!zoneData) { LogMsg("ERROR: RecordRegistrationGotZoneData invoked with NULL result and no error"); return; } + + newRR = (AuthRecord*)zoneData->ZoneDataContext; + if (newRR->nta != zoneData) LogMsg("RecordRegistrationGotZoneData: nta (%p) != zoneData (%p) %##s (%s)", newRR->nta, zoneData, newRR->resrec.name->c, DNSTypeName(newRR->resrec.rrtype)); @@ -4276,8 +4300,6 @@ mDNSexport void RecordRegistrationGotZoneData(mDNS *const m, mStatus err, const return; } - if (!zoneData) { LogMsg("ERROR: RecordRegistrationGotZoneData invoked with NULL result and no error"); return; } - if (newRR->resrec.rrclass != zoneData->ZoneClass) { LogMsg("ERROR: New resource record's class (%d) does not match zone class (%d)", newRR->resrec.rrclass, zoneData->ZoneClass); @@ -4665,7 +4687,7 @@ mDNSlocal void handle_unanswered_query(mDNS *const m) // Note: req_DO affects only DNSSEC_VALIDATION_SECURE_OPTIONAL questions; // DNSSEC_VALIDATION_SECURE questions ignores req_DO. - if (q->qDNSServer && !q->qDNSServer->DNSSECAware && q->qDNSServer->req_DO) + if (!q->qDNSServer->DNSSECAware && q->qDNSServer->req_DO) { q->qDNSServer->retransDO++; if (q->qDNSServer->retransDO == MAX_DNSSEC_RETRANSMISSIONS) @@ -4723,6 +4745,9 @@ mDNSexport void uDNS_CheckCurrentQuestion(mDNS *const m) LogInfo("uDNS_CheckCurrentQuestion: Sent %d unanswered queries for %##s (%s) to %#a:%d (%##s)", q->unansweredQueries, q->qname.c, DNSTypeName(q->qtype), &orig->addr, mDNSVal16(orig->port), orig->domain.c); +#if APPLE_OSX_mDNSResponder + SymptomReporterDNSServerUnreachable(orig); +#endif PenalizeDNSServer(m, q, zeroID); q->noServerResponse = 1; } @@ -4752,7 +4777,7 @@ mDNSexport void uDNS_CheckCurrentQuestion(mDNS *const m) { mDNSIPPort zp = zeroIPPort; LogInfo("uDNS_checkCurrentQuestion: Retrying question %p %##s (%s) DNS Server %#a:%d ThisQInterval %d", - q, q->qname.c, DNSTypeName(q->qtype), new ? &new->addr : mDNSNULL, mDNSVal16(new ? new->port : zp), q->ThisQInterval); + q, q->qname.c, DNSTypeName(q->qtype), new ? &new->addr : mDNSNULL, mDNSVal16(new? new->port : zp), q->ThisQInterval); DNSServerChangeForQuestion(m, q, new); } for (qptr = q->next ; qptr; qptr = qptr->next) @@ -4798,9 +4823,10 @@ mDNSexport void uDNS_CheckCurrentQuestion(mDNS *const m) } else { + mDNSIPPort zp = zeroIPPort; debugf("uDNS_CheckCurrentQuestion sending %p %##s (%s) %#a:%d UnansweredQueries %d", q, q->qname.c, DNSTypeName(q->qtype), - q->qDNSServer ? &q->qDNSServer->addr : mDNSNULL, mDNSVal16(q->qDNSServer ? q->qDNSServer->port : zeroIPPort), q->unansweredQueries); + q->qDNSServer ? &q->qDNSServer->addr : mDNSNULL, mDNSVal16(q->qDNSServer ? q->qDNSServer->port : zp), q->unansweredQueries); if (!q->LocalSocket) { q->LocalSocket = mDNSPlatformUDPSocket(m, zeroIPPort); @@ -4808,7 +4834,19 @@ mDNSexport void uDNS_CheckCurrentQuestion(mDNS *const m) mDNSPlatformSetuDNSSocktOpt(q->LocalSocket, &q->qDNSServer->addr, q); } if (!q->LocalSocket) err = mStatus_NoMemoryErr; // If failed to make socket (should be very rare), we'll try again next time - else err = mDNSSendDNSMessage(m, &m->omsg, end, q->qDNSServer->interface, q->LocalSocket, &q->qDNSServer->addr, q->qDNSServer->port, mDNSNULL, mDNSNULL, q->UseBackgroundTrafficClass); + else + { + err = mDNSSendDNSMessage(m, &m->omsg, end, q->qDNSServer->interface, q->LocalSocket, &q->qDNSServer->addr, q->qDNSServer->port, mDNSNULL, mDNSNULL, q->UseBackgroundTrafficClass); +#if TARGET_OS_EMBEDDED + if (!err) + { + if (q->metrics.querySendCount++ == 0) + { + q->metrics.firstQueryTime = m->timenow; + } + } +#endif + } } } @@ -4885,7 +4923,7 @@ mDNSexport void uDNS_CheckCurrentQuestion(mDNS *const m) if (qptr->DuplicateOf == q) { qptr->validDNSServers = q->validDNSServers; qptr->qDNSServer = q->qDNSServer; } { mDNSIPPort zp = zeroIPPort; - LogInfo("uDNS_checkCurrentQuestion: Tried all DNS servers, retry question %p SuppressUnusable %d %##s (%s) with DNS Server %#a:%d after 60 seconds, ThisQInterval %d", + LogInfo("uDNS_checkCurrentQuestion: Tried all DNS servers, retry question %p SuppressUnusable %d %##s (%s) with DNS Server %#a:%d after 60 seconds, ThisQInterval %d", q, q->SuppressUnusable, q->qname.c, DNSTypeName(q->qtype), q->qDNSServer ? &q->qDNSServer->addr : mDNSNULL, mDNSVal16(q->qDNSServer ? q->qDNSServer->port : zp), q->ThisQInterval); } @@ -5023,7 +5061,7 @@ mDNSexport void CheckNATMappings(mDNS *m) if (!mDNSIPv4AddressIsZero(EffectiveAddress) || cur->retryInterval > NATMAP_INIT_RETRY * 8) { const mStatus EffectiveResult = cur->NewResult ? cur->NewResult : mDNSv4AddrIsRFC1918(&EffectiveAddress) ? mStatus_DoubleNAT : mStatus_NoError; - mDNSIPPort ExternalPort; + mDNSIPPort ExternalPort; if (HaveRoutable) ExternalPort = cur->IntPort; diff --git a/usr/src/cmd/cmd-inet/usr.lib/mdnsd/uds_daemon.c b/usr/src/cmd/cmd-inet/usr.lib/mdnsd/uds_daemon.c index 613d78552e..9af68dc95d 100644 --- a/usr/src/cmd/cmd-inet/usr.lib/mdnsd/uds_daemon.c +++ b/usr/src/cmd/cmd-inet/usr.lib/mdnsd/uds_daemon.c @@ -1,6 +1,6 @@ /* -*- Mode: C; tab-width: 4 -*- * - * Copyright (c) 2003-2013 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2003-2015 Apple Inc. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -171,6 +171,7 @@ struct request_state struct reply_state *replies; // corresponding (active) reply list req_termination_fn terminate; DNSServiceFlags flags; + mDNSu32 interfaceIndex; union { @@ -317,10 +318,8 @@ mDNSlocal char *AnonDataToString(const mDNSu8 *ad, int adlen, char *adstr, int a mDNSlocal void FatalError(char *errmsg) { - char* ptr = NULL; LogMsg("%s: %s", errmsg, dnssd_strerror(dnssd_errno)); - *ptr = 0; // On OS X abort() doesn't generate a crash log, but writing to zero does - abort(); // On platforms where writing to zero doesn't generate an exception, abort instead + abort(); } mDNSlocal mDNSu32 dnssd_htonl(mDNSu32 l) @@ -546,10 +545,20 @@ mDNSlocal reply_state *create_reply(const reply_op_t op, const size_t datalen, r // Append a reply to the list in a request object // If our request is sharing a connection, then we append our reply_state onto the primary's list +// If the request does not want asynchronous replies, then the reply is freed instead of being appended to any list. mDNSlocal void append_reply(request_state *req, reply_state *rep) { - request_state *r = req->primary ? req->primary : req; - reply_state **ptr = &r->replies; + request_state *r; + reply_state **ptr; + + if (req->no_reply) + { + freeL("reply_state/append_reply", rep); + return; + } + + r = req->primary ? req->primary : req; + ptr = &r->replies; while (*ptr) ptr = &(*ptr)->next; *ptr = rep; rep->next = NULL; @@ -662,6 +671,7 @@ mDNSlocal AuthRecord *read_rr_from_ipc_msg(request_state *request, int GetTTL, i AuthRecType artype; request->flags = flags; + request->interfaceIndex = interfaceIndex; if (str_err) { LogMsg("ERROR: read_rr_from_ipc_msg - get_string"); return NULL; } @@ -1066,7 +1076,7 @@ mDNSlocal void regrecord_callback(mDNS *const m, AuthRecord *rr, mStatus result) if (result != mStatus_MemFree) LogMsg("regrecord_callback: error %d received after parent termination", result); // We come here when the record is being deregistered either from DNSServiceRemoveRecord or connection_termination. - // If the record has been updated, we need to free the rdata. Everytime we call mDNS_Update, it calls update_callback + // If the record has been updated, we need to free the rdata. Every time we call mDNS_Update, it calls update_callback // with the old rdata (so that we can free it) and stores the new rdata in "rr->resrec.rdata". This means, we need // to free the latest rdata for which the update_callback was never called with. if (rr->resrec.rdata != &rr->rdatastorage) freeL("RData/regrecord_callback", rr->resrec.rdata); @@ -1151,13 +1161,14 @@ mDNSlocal void set_peer_pid(request_state *request) return; mDNSPlatformStrCopy(request->pid_name, proc.pbsi_comm); request->process_id = p; + debugf("set_peer_pid: Client PEERPID is %d %s", p, request->pid_name); #else // !LOCAL_PEERPID request->pid_name[0] = '\0'; request->process_id = -1; + LogInfo("set_peer_pid: Not Supported on this version of OS"); if (request->sd < 0) return; - LogInfo("set_peer_pid: Not Supported on this version of OS"); #endif // LOCAL_PEERPID } @@ -1979,7 +1990,6 @@ mDNSlocal mDNSBool PreDefinedInterfaceIndex(mDNSu32 interfaceIndex) case kDNSServiceInterfaceIndexUnicast: case kDNSServiceInterfaceIndexP2P: return mDNStrue; - break; default: return mDNSfalse; } @@ -1993,6 +2003,7 @@ mDNSlocal mStatus handle_regservice_request(request_state *request) domainname d, srv; mStatus err; char *AnonData = mDNSNULL; + const char *msgTXTData; DNSServiceFlags flags = get_flags(&request->msgptr, request->msgend); mDNSu32 interfaceIndex = get_uint32(&request->msgptr, request->msgend); @@ -2016,7 +2027,7 @@ mDNSlocal mStatus handle_regservice_request(request_state *request) // If it's one of the specially defined inteface index values, just return an error. if (PreDefinedInterfaceIndex(interfaceIndex)) { - LogMsg("ERROR: handle_regservice_request: bad interfaceIndex %d", interfaceIndex); + LogInfo("handle_regservice_request: bad interfaceIndex %d", interfaceIndex); return(mStatus_BadParamErr); } @@ -2033,6 +2044,7 @@ mDNSlocal mStatus handle_regservice_request(request_state *request) { LogMsg("ERROR: handle_regservice_request - Couldn't read name/regtype/domain"); return(mStatus_BadParamErr); } request->flags = flags; + request->interfaceIndex = interfaceIndex; request->u.servicereg.InterfaceID = InterfaceID; request->u.servicereg.instances = NULL; request->u.servicereg.txtlen = 0; @@ -2047,21 +2059,23 @@ mDNSlocal mStatus handle_regservice_request(request_state *request) } request->u.servicereg.txtlen = get_uint16(&request->msgptr, request->msgend); + msgTXTData = get_rdata(&request->msgptr, request->msgend, request->u.servicereg.txtlen); + + if (!request->msgptr) { LogMsg("%3d: DNSServiceRegister(unreadable parameters)", request->sd); return(mStatus_BadParamErr); } + if (request->u.servicereg.txtlen) { request->u.servicereg.txtdata = mallocL("service_info txtdata", request->u.servicereg.txtlen); if (!request->u.servicereg.txtdata) FatalError("ERROR: handle_regservice_request - malloc"); - mDNSPlatformMemCopy(request->u.servicereg.txtdata, get_rdata(&request->msgptr, request->msgend, request->u.servicereg.txtlen), request->u.servicereg.txtlen); + mDNSPlatformMemCopy(request->u.servicereg.txtdata, msgTXTData, request->u.servicereg.txtlen); } - if (!request->msgptr) { LogMsg("%3d: DNSServiceRegister(unreadable parameters)", request->sd); return(mStatus_BadParamErr); } - // Check for sub-types after the service type request->u.servicereg.num_subtypes = ChopSubTypes(request->u.servicereg.type_as_string, &AnonData); // Note: Modifies regtype string to remove trailing subtypes if (request->u.servicereg.num_subtypes < 0) { LogMsg("ERROR: handle_regservice_request - ChopSubTypes failed %s", request->u.servicereg.type_as_string); - return(mStatus_BadParamErr); + goto bad_param; } if (AnonData) { @@ -2069,7 +2083,7 @@ mDNSlocal mStatus handle_regservice_request(request_state *request) if (AnonDataLen > MAX_ANONYMOUS_DATA) { LogMsg("ERROR: handle_regservice_request: AnonDataLen %d", AnonDataLen); - return(mStatus_BadParamErr); + goto bad_param; } request->u.servicereg.AnonData = mDNStrue; } @@ -2080,7 +2094,7 @@ mDNSlocal mStatus handle_regservice_request(request_state *request) // Don't try to construct "domainname t" until *after* ChopSubTypes has worked its magic if (!*request->u.servicereg.type_as_string || !MakeDomainNameFromDNSNameString(&request->u.servicereg.type, request->u.servicereg.type_as_string)) - { LogMsg("ERROR: handle_regservice_request - type_as_string bad %s", request->u.servicereg.type_as_string); return(mStatus_BadParamErr); } + { LogMsg("ERROR: handle_regservice_request - type_as_string bad %s", request->u.servicereg.type_as_string); goto bad_param; } if (!name[0]) { @@ -2096,7 +2110,7 @@ mDNSlocal mStatus handle_regservice_request(request_state *request) name[newlen] = 0; } if (!MakeDomainLabelFromLiteralString(&request->u.servicereg.name, name)) - { LogMsg("ERROR: handle_regservice_request - name bad %s", name); return(mStatus_BadParamErr); } + { LogMsg("ERROR: handle_regservice_request - name bad %s", name); goto bad_param; } request->u.servicereg.autoname = mDNSfalse; } @@ -2104,7 +2118,7 @@ mDNSlocal mStatus handle_regservice_request(request_state *request) { request->u.servicereg.default_domain = mDNSfalse; if (!MakeDomainNameFromDNSNameString(&d, domain)) - { LogMsg("ERROR: handle_regservice_request - domain bad %s", domain); return(mStatus_BadParamErr); } + { LogMsg("ERROR: handle_regservice_request - domain bad %s", domain); goto bad_param; } } else { @@ -2113,19 +2127,16 @@ mDNSlocal mStatus handle_regservice_request(request_state *request) } // We don't allow the anonymous and the regular ones to coexist - if (!CheckForMixedRegistrations(&request->u.servicereg.type, &d, request->u.servicereg.AnonData)) - { - return(mStatus_BadParamErr); - } + if (!CheckForMixedRegistrations(&request->u.servicereg.type, &d, request->u.servicereg.AnonData)) { goto bad_param; } if (!ConstructServiceName(&srv, &request->u.servicereg.name, &request->u.servicereg.type, &d)) { LogMsg("ERROR: handle_regservice_request - Couldn't ConstructServiceName from, “%#s” “%##s” “%##s”", - request->u.servicereg.name.c, request->u.servicereg.type.c, d.c); return(mStatus_BadParamErr); + request->u.servicereg.name.c, request->u.servicereg.type.c, d.c); goto bad_param; } if (!MakeDomainNameFromDNSNameString(&request->u.servicereg.host, host)) - { LogMsg("ERROR: handle_regservice_request - host bad %s", host); return(mStatus_BadParamErr); } + { LogMsg("ERROR: handle_regservice_request - host bad %s", host); goto bad_param; } request->u.servicereg.autorename = (flags & kDNSServiceFlagsNoAutoRename ) == 0; request->u.servicereg.allowremotequery = (flags & kDNSServiceFlagsAllowRemoteQuery) != 0; @@ -2172,6 +2183,11 @@ mDNSlocal mStatus handle_regservice_request(request_state *request) } return(err); + +bad_param: + freeL("handle_regservice_request (txtdata)", request->u.servicereg.txtdata); + request->u.servicereg.txtdata = NULL; + return mStatus_BadParamErr; } // *************************************************************************** @@ -2459,9 +2475,13 @@ mDNSlocal void UpdateDeviceInfoRecord(mDNS *const m) { int num_autoname = 0; request_state *req; + + // Don't need to register the device info record for kDNSServiceInterfaceIndexLocalOnly registrations. for (req = all_requests; req; req = req->next) - if (req->terminate == regservice_termination_callback && req->u.servicereg.autoname) + { + if (req->terminate == regservice_termination_callback && req->u.servicereg.autoname && req->interfaceIndex != kDNSServiceInterfaceIndexLocalOnly) num_autoname++; + } // If DeviceInfo record is currently registered, see if we need to deregister it if (m->DeviceInfo.resrec.RecordType != kDNSRecordTypeUnregistered) @@ -2606,7 +2626,7 @@ mDNSlocal mStatus handle_browse_request(request_state *request) // If it's one of the specially defined inteface index values, just return an error. if (PreDefinedInterfaceIndex(interfaceIndex)) { - LogMsg("ERROR: handle_browse_request: bad interfaceIndex %d", interfaceIndex); + LogInfo("handle_browse_request: bad interfaceIndex %d", interfaceIndex); return(mStatus_BadParamErr); } @@ -2622,6 +2642,7 @@ mDNSlocal mStatus handle_browse_request(request_state *request) if (!request->msgptr) { LogMsg("%3d: DNSServiceBrowse(unreadable parameters)", request->sd); return(mStatus_BadParamErr); } request->flags = flags; + request->interfaceIndex = interfaceIndex; typedn.c[0] = 0; NumSubTypes = ChopSubTypes(regtype, &AnonData); // Note: Modifies regtype string to remove trailing subtypes if (NumSubTypes < 0 || NumSubTypes > 1) @@ -2804,7 +2825,7 @@ mDNSlocal mStatus handle_resolve_request(request_state *request) // If it's one of the specially defined inteface index values, just return an error. if (PreDefinedInterfaceIndex(interfaceIndex)) { - LogMsg("ERROR: handle_resolve_request: bad interfaceIndex %d", interfaceIndex); + LogInfo("handle_resolve_request: bad interfaceIndex %d", interfaceIndex); return(mStatus_BadParamErr); } @@ -2827,6 +2848,7 @@ mDNSlocal mStatus handle_resolve_request(request_state *request) mDNSPlatformMemZero(&request->u.resolve, sizeof(request->u.resolve)); request->flags = flags; + request->interfaceIndex = interfaceIndex; // format questions request->u.resolve.qsrv.InterfaceID = InterfaceID; @@ -2854,6 +2876,7 @@ mDNSlocal mStatus handle_resolve_request(request_state *request) request->u.resolve.qsrv.qnameOrig = mDNSNULL; request->u.resolve.qsrv.AnonInfo = mDNSNULL; request->u.resolve.qsrv.pid = request->process_id; + request->u.resolve.qsrv.euid = request->uid; request->u.resolve.qsrv.QuestionCallback = resolve_result_callback; request->u.resolve.qsrv.QuestionContext = request; @@ -2882,6 +2905,7 @@ mDNSlocal mStatus handle_resolve_request(request_state *request) request->u.resolve.qtxt.qnameOrig = mDNSNULL; request->u.resolve.qtxt.AnonInfo = mDNSNULL; request->u.resolve.qtxt.pid = request->process_id; + request->u.resolve.qtxt.euid = request->uid; request->u.resolve.qtxt.QuestionCallback = resolve_result_callback; request->u.resolve.qtxt.QuestionContext = request; @@ -3167,6 +3191,7 @@ mDNSlocal mStatus SendAdditionalQuery(DNSQuestion *q, request_state *request, mS q2->TimeoutQuestion = 0; q2->AnonInfo = mDNSNULL; q2->pid = request->process_id; + q2->euid = request->uid; } LogOperation("%3d: DNSServiceQueryRecord(%##s, %s) unicast", request->sd, q2->qname.c, DNSTypeName(q2->qtype)); err = mDNS_StartQuery(&mDNSStorage, q2); @@ -3346,15 +3371,16 @@ mDNSlocal void queryrecord_result_reply(mDNS *const m, request_state *req, DNSQu (x.cr_version == XUCRED_VERSION)) { struct sockaddr_storage addr; - const RDataBody2 *const rdb = (RDataBody2 *)answer->rdata->u.data; addr.ss_len = 0; if (answer->rrtype == kDNSType_A || answer->rrtype == kDNSType_AAAA) { if (answer->rrtype == kDNSType_A) { - struct sockaddr_in *sin = (struct sockaddr_in *)&addr; + struct sockaddr_in *const sin = (struct sockaddr_in *)&addr; sin->sin_port = 0; - if (!putRData(mDNSNULL, (mDNSu8 *)&sin->sin_addr, (mDNSu8 *)(&sin->sin_addr + sizeof(rdb->ipv4)), answer)) + // Instead of this stupid call to putRData it would be much simpler to just assign the value in the sensible way, like this: + // sin->sin_addr.s_addr = answer->rdata->u.ipv4.NotAnInteger; + if (!putRData(mDNSNULL, (mDNSu8 *)&sin->sin_addr, (mDNSu8 *)(&sin->sin_addr + sizeof(mDNSv4Addr)), answer)) LogMsg("queryrecord_result_reply: WCF AF_INET putRData failed"); else { @@ -3364,9 +3390,14 @@ mDNSlocal void queryrecord_result_reply(mDNS *const m, request_state *req, DNSQu } else if (answer->rrtype == kDNSType_AAAA) { - struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&addr; + struct sockaddr_in6 *const sin6 = (struct sockaddr_in6 *)&addr; sin6->sin6_port = 0; - if (!putRData(mDNSNULL, (mDNSu8 *)&sin6->sin6_addr, (mDNSu8 *)(&sin6->sin6_addr + sizeof(rdb->ipv6)), answer)) + // Instead of this stupid call to putRData it would be much simpler to just assign the value in the sensible way, like this: + // sin6->sin6_addr.__u6_addr.__u6_addr32[0] = answer->rdata->u.ipv6.l[0]; + // sin6->sin6_addr.__u6_addr.__u6_addr32[1] = answer->rdata->u.ipv6.l[1]; + // sin6->sin6_addr.__u6_addr.__u6_addr32[2] = answer->rdata->u.ipv6.l[2]; + // sin6->sin6_addr.__u6_addr.__u6_addr32[3] = answer->rdata->u.ipv6.l[3]; + if (!putRData(mDNSNULL, (mDNSu8 *)&sin6->sin6_addr, (mDNSu8 *)(&sin6->sin6_addr + sizeof(mDNSv6Addr)), answer)) LogMsg("queryrecord_result_reply: WCF AF_INET6 putRData failed"); else { @@ -3662,7 +3693,7 @@ mDNSlocal void queryrecord_termination_callback(request_state *request) mDNSlocal void SetQuestionPolicy(DNSQuestion *q, request_state *req) { int i; - + q->euid = req->uid; // The policy is either based on pid or UUID. Pass a zero pid // to the "core" if the UUID is valid. If we always pass the pid, // then the "core" needs to determine whether the uuid is valid @@ -3685,6 +3716,8 @@ mDNSlocal void SetQuestionPolicy(DNSQuestion *q, request_state *req) { q->pid = req->process_id; } + + //debugf("SetQuestionPolicy: q->euid[%d] q->pid[%d] uuid is valid : %s", q->euid, q->pid, req->validUUID ? "true" : "false"); } mDNSlocal mStatus handle_queryrecord_request(request_state *request) @@ -3703,9 +3736,11 @@ mDNSlocal mStatus handle_queryrecord_request(request_state *request) if (interfaceIndex && !InterfaceID) { // If it's one of the specially defined inteface index values, just return an error. - if (PreDefinedInterfaceIndex(interfaceIndex)) + // Also, caller should return an error immediately if lo0 (index 1) is not configured + // into the current active interfaces. See background in Radar 21967160. + if (PreDefinedInterfaceIndex(interfaceIndex) || interfaceIndex == 1) { - LogMsg("ERROR: handle_queryrecord_request: bad interfaceIndex %d", interfaceIndex); + LogInfo("handle_queryrecord_request: bad interfaceIndex %d", interfaceIndex); return(mStatus_BadParamErr); } @@ -3723,6 +3758,7 @@ mDNSlocal mStatus handle_queryrecord_request(request_state *request) { LogMsg("%3d: DNSServiceQueryRecord(unreadable parameters)", request->sd); return(mStatus_BadParamErr); } request->flags = flags; + request->interfaceIndex = interfaceIndex; mDNSPlatformMemZero(&request->u.queryrecord, sizeof(request->u.queryrecord)); q->InterfaceID = InterfaceID; @@ -3792,12 +3828,14 @@ mDNSlocal mStatus handle_queryrecord_request(request_state *request) q->qnameOrig = mDNSNULL; SetQuestionPolicy(q, request); - LogOperation("%3d: DNSServiceQueryRecord(%X, %d, %##s, %s) START PID[%d](%s)", + LogOperation("%3d: DNSServiceQueryRecord(%X, %d, %##s, %s) START PID[%d](%s)", request->sd, flags, interfaceIndex, q->qname.c, DNSTypeName(q->qtype), request->process_id, request->pid_name); err = mDNS_StartQuery(&mDNSStorage, q); - if (err) + if (err) + { LogMsg("%3d: ERROR: DNSServiceQueryRecord %##s %s mDNS_StartQuery: %d", request->sd, q->qname.c, DNSTypeName(q->qtype), (int)err); + } else { request->terminate = queryrecord_termination_callback; @@ -3911,6 +3949,9 @@ mDNSlocal mStatus handle_enum_request(request_state *request) if (!request->msgptr) { LogMsg("%3d: DNSServiceEnumerateDomains(unreadable parameters)", request->sd); return(mStatus_BadParamErr); } + request->flags = flags; + request->interfaceIndex = interfaceIndex; + // mark which kind of enumeration we're doing so that we know what domain enumeration queries to stop request->u.enumeration.flags = reg; @@ -4084,7 +4125,7 @@ mDNSlocal void handle_connection_delegate_request(request_state *request) if (proc_pidinfo(request->process_id, PROC_PIDT_SHORTBSDINFO, 1, &proc, PROC_PIDT_SHORTBSDINFO_SIZE) == 0) return; mDNSPlatformStrCopy(request->pid_name, proc.pbsi_comm); - //LogMsg("handle_connection_delegate_request: process id %d, name %s", request->process_id, request->pid_name); + debugf("handle_connection_delegate_request: process id %d, name %s", request->process_id, request->pid_name); } #endif #ifdef LOCAL_PEEREUUID @@ -4118,7 +4159,7 @@ mDNSlocal void handle_getpid_request(request_state *request) const DNSQuestion *q = NULL; PIDInfo pi; - LogOperation("%3d: DNSServiceGetPID START", request->sd); + LogMsg("%3d: DNSServiceGetPID START", request->sd); for (req = all_requests; req; req=req->next) { @@ -4135,7 +4176,7 @@ mDNSlocal void handle_getpid_request(request_state *request) if (port == srcport) { pid = req->process_id; - LogInfo("DNSServiceGetPID: srcport %d, pid %d [%s] question %##s", htons(srcport), pid, req->pid_name, q->qname.c); + LogMsg("DNSServiceGetPID: srcport %d, pid %d [%s] question %##s", htons(srcport), pid, req->pid_name, q->qname.c); break; } } @@ -4154,7 +4195,7 @@ mDNSlocal void handle_getpid_request(request_state *request) #if APPLE_OSX_mDNSResponder pid = getpid(); #endif // APPLE_OSX_mDNSResponder - LogInfo("DNSServiceGetPID: srcport %d, pid %d [%s], question %##s", htons(srcport), pid, "_mDNSResponder", q->qname.c); + LogMsg("DNSServiceGetPID: srcport %d, pid %d [%s], question %##s", htons(srcport), pid, "_mDNSResponder", q->qname.c); break; } } @@ -4164,7 +4205,7 @@ mDNSlocal void handle_getpid_request(request_state *request) pi.err = 0; pi.pid = pid; send_all(request->sd, (const char *)&pi, sizeof(PIDInfo)); - LogOperation("%3d: DNSServiceGetPID STOP", request->sd); + LogMsg("%3d: DNSServiceGetPID STOP", request->sd); } // *************************************************************************** @@ -4262,6 +4303,8 @@ mDNSlocal mStatus handle_port_mapping_request(request_state *request) if (!(protocol & (kDNSServiceProtocol_UDP | kDNSServiceProtocol_TCP))) return(mStatus_BadParamErr); } + request->flags = flags; + request->interfaceIndex = interfaceIndex; request->u.pm.NATinfo.Protocol = !protocol ? NATOp_AddrRequest : (protocol == kDNSServiceProtocol_UDP) ? NATOp_MapUDP : NATOp_MapTCP; // u.pm.NATinfo.IntPort = already set above request->u.pm.NATinfo.RequestedPort = request->u.pm.ReqExt; @@ -4385,6 +4428,7 @@ mDNSlocal mStatus handle_addrinfo_request(request_state *request) domainname d; mStatus err = 0; mDNSs32 serviceIndex = -1; // default unscoped value for ServiceID is -1 + mDNSInterfaceID InterfaceID; DNSServiceFlags flags = get_flags(&request->msgptr, request->msgend); @@ -4402,7 +4446,7 @@ mDNSlocal mStatus handle_addrinfo_request(request_state *request) mDNSPlatformMemZero(&request->u.addrinfo, sizeof(request->u.addrinfo)); - mDNSInterfaceID InterfaceID = mDNSPlatformInterfaceIDfromInterfaceIndex(&mDNSStorage, interfaceIndex); + InterfaceID = mDNSPlatformInterfaceIDfromInterfaceIndex(&mDNSStorage, interfaceIndex); // The request is scoped to a specific interface index, but the // interface is not currently in our list. @@ -4411,7 +4455,7 @@ mDNSlocal mStatus handle_addrinfo_request(request_state *request) // If it's one of the specially defined inteface index values, just return an error. if (PreDefinedInterfaceIndex(interfaceIndex)) { - LogMsg("ERROR: handle_addrinfo_request: bad interfaceIndex %d", interfaceIndex); + LogInfo("handle_addrinfo_request: bad interfaceIndex %d", interfaceIndex); return(mStatus_BadParamErr); } @@ -4420,6 +4464,9 @@ mDNSlocal mStatus handle_addrinfo_request(request_state *request) InterfaceID = (mDNSInterfaceID)(uintptr_t)interfaceIndex; LogInfo("handle_addrinfo_request: query pending for interface index %d", interfaceIndex); } + + request->flags = flags; + request->interfaceIndex = interfaceIndex; request->u.addrinfo.interface_id = InterfaceID; request->u.addrinfo.flags = flags; request->u.addrinfo.protocol = get_uint32(&request->msgptr, request->msgend); @@ -4558,8 +4605,7 @@ mDNSlocal mStatus handle_addrinfo_request(request_state *request) } } - LogOperation("%3d: DNSServiceGetAddrInfo(%X, %d, %d, %##s) START PID[%d](%s)", request->sd, flags, interfaceIndex, - request->u.addrinfo.protocol, d.c, request->process_id, request->pid_name); + LogOperation("%3d: DNSServiceGetAddrInfo(%X, %d, %d, %##s) START PID[%d](%s)", request->sd, flags, interfaceIndex, request->u.addrinfo.protocol, d.c, request->process_id, request->pid_name); return(err); } @@ -4664,12 +4710,10 @@ mDNSlocal void read_msg(request_state *req) #if !defined(_WIN32) cmsg = CMSG_FIRSTHDR(&msg); #if DEBUG_64BIT_SCM_RIGHTS - LogMsg("%3d: Expecting %d %d %d %d", req->sd, sizeof(cbuf), sizeof(cbuf), SOL_SOCKET, SCM_RIGHTS); - LogMsg("%3d: Got %d %d %d %d", req->sd, msg.msg_controllen, cmsg->cmsg_len, cmsg->cmsg_level, cmsg->cmsg_type); + LogMsg("%3d: Expecting %d %d %d %d", req->sd, sizeof(cbuf), sizeof(cbuf), SOL_SOCKET, SCM_RIGHTS); + LogMsg("%3d: Got %d %d %d %d", req->sd, msg.msg_controllen, cmsg ? cmsg->cmsg_len : -1, cmsg ? cmsg->cmsg_level : -1, cmsg ? cmsg->cmsg_type : -1); #endif // DEBUG_64BIT_SCM_RIGHTS - if (msg.msg_controllen != 0 && - cmsg->cmsg_level == SOL_SOCKET && - cmsg->cmsg_type == SCM_RIGHTS) + if (cmsg && cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) { #if APPLE_OSX_mDNSResponder // Strictly speaking BPF_fd belongs solely in the platform support layer, but because @@ -4689,7 +4733,7 @@ mDNSlocal void read_msg(request_state *req) #endif // DEBUG_64BIT_SCM_RIGHTS if (req->data_bytes < req->hdr.datalen) { - LogMsg("%3d: Client(PID [%d](%s)) sent error socket %d via SCM_RIGHTS with req->data_bytes %d < req->hdr.datalen %d", + LogMsg("%3d: Client(PID [%d](%s)) sent result code socket %d via SCM_RIGHTS with req->data_bytes %d < req->hdr.datalen %d", req->sd, req->process_id, req->pid_name, req->errsd, req->data_bytes, req->hdr.datalen); req->ts = t_error; return; @@ -4756,7 +4800,7 @@ mDNSlocal void read_msg(request_state *req) #if !defined(USE_TCP_LOOPBACK) got_errfd: #endif - LogOperation("%3d: Error socket %d created %08X %08X", req->sd, req->errsd, req->hdr.client_context.u32[1], req->hdr.client_context.u32[0]); + LogOperation("%3d: Result code socket %d created %08X %08X", req->sd, req->errsd, req->hdr.client_context.u32[1], req->hdr.client_context.u32[0]); #if defined(_WIN32) if (ioctlsocket(req->errsd, FIONBIO, &opt) != 0) #else @@ -4861,9 +4905,6 @@ mDNSlocal void request_callback(int fd, short filter, void *info) return; } - // check if client wants silent operation - if (req->hdr.ipc_flags & IPC_FLAGS_NOREPLY) req->no_reply = 1; - // If req->terminate is already set, this means this operation is sharing an existing connection if (req->terminate && !LightweightOp(req->hdr.op)) { @@ -4901,6 +4942,9 @@ mDNSlocal void request_callback(int fd, short filter, void *info) req = newreq; } + // Check if the request wants no asynchronous replies. + if (req->hdr.ipc_flags & IPC_FLAGS_NOREPLY) req->no_reply = 1; + // If we're shutting down, don't allow new client requests // We do allow "cancel" and "getproperty" during shutdown if (mDNSStorage.ShutdownTime && req->hdr.op != cancel_request && req->hdr.op != getproperty_request) @@ -4958,7 +5002,7 @@ mDNSlocal void request_callback(int fd, short filter, void *info) send_all(req->errsd, (const char *)&err_netorder, sizeof(err_netorder)); if (req->errsd != req->sd) { - LogOperation("%3d: Error socket %d closed %08X %08X (%d)", + LogOperation("%3d: Result code socket %d closed %08X %08X (%d)", req->sd, req->errsd, req->hdr.client_context.u32[1], req->hdr.client_context.u32[0], err); dnssd_close(req->errsd); req->errsd = req->sd; @@ -5023,11 +5067,14 @@ mDNSlocal void connect_callback(int fd, short filter, void *info) #if APPLE_OSX_mDNSResponder struct xucred x; socklen_t xucredlen = sizeof(x); - if (getsockopt(sd, 0, LOCAL_PEERCRED, &x, &xucredlen) >= 0 && x.cr_version == XUCRED_VERSION) request->uid = x.cr_uid; - else my_perror("ERROR: getsockopt, LOCAL_PEERCRED"); + if (getsockopt(sd, 0, LOCAL_PEERCRED, &x, &xucredlen) >= 0 && x.cr_version == XUCRED_VERSION) + request->uid = x.cr_uid; // save the effective userid of the client + else + my_perror("ERROR: getsockopt, LOCAL_PEERCRED"); + debugf("LOCAL_PEERCRED %d %u %u %d", xucredlen, x.cr_version, x.cr_uid, x.cr_ngroups); #endif // APPLE_OSX_mDNSResponder - LogOperation("%3d: Adding FD for uid %u", request->sd, request->uid); + LogOperation("%3d: connect_callback: Adding FD for uid %u", request->sd, request->uid); udsSupportAddFDToEventLoop(sd, request_callback, request, &request->platform_data); } } @@ -5068,7 +5115,7 @@ mDNSlocal mDNSBool uds_socket_setup(dnssd_sock_t skt) } else { - LogInfo("%3d: Listening for incoming Unix Domain Socket client requests", skt); + LogOperation("%3d: Listening for incoming Unix Domain Socket client requests", skt); mDNSStorage.uds_listener_skt = skt; } return mDNStrue; @@ -5248,8 +5295,8 @@ mDNSlocal void LogClientInfo(mDNS *const m, request_state *req) prefix, num_records, num_records != 1 ? "s" : "", num_ops, num_ops != 1 ? "s" : "", req->process_id, req->pid_name); for (p = req->u.reg_recs; p; p=p->next) - LogMsgNoIdent(" -> DNSServiceRegisterRecord %3d %s PID[%d](%s)", p->key, ARDisplayString(m, p->rr), - req->process_id, req->pid_name); + LogMsgNoIdent(" -> DNSServiceRegisterRecord 0x%08X %2d %3d %s PID[%d](%s)", + req->flags, req->interfaceIndex, p->key, ARDisplayString(m, p->rr), req->process_id, req->pid_name); for (r = req->next; r; r=r->next) if (r->primary == req) LogClientInfo(m, r); } else if (req->terminate == regservice_termination_callback) @@ -5257,32 +5304,34 @@ mDNSlocal void LogClientInfo(mDNS *const m, request_state *req) service_instance *ptr; char anonstr[256]; for (ptr = req->u.servicereg.instances; ptr; ptr = ptr->next) - LogMsgNoIdent("%s DNSServiceRegister %##s%s %u/%u PID[%d](%s)", - (ptr == req->u.servicereg.instances) ? prefix : " ", ptr->srs.RR_SRV.resrec.name->c, - AnonDataToString(ptr->srs.AnonData, 0, anonstr, sizeof(anonstr)), mDNSVal16(req->u.servicereg.port), - SRS_PORT(&ptr->srs), req->process_id, req->pid_name); + LogMsgNoIdent("%s DNSServiceRegister 0x%08X %2d %##s%s %u/%u PID[%d](%s)", + (ptr == req->u.servicereg.instances) ? prefix : " ", req->flags, req->interfaceIndex, ptr->srs.RR_SRV.resrec.name->c, + AnonDataToString(ptr->srs.AnonData, 0, anonstr, sizeof(anonstr)), mDNSVal16(req->u.servicereg.port), + SRS_PORT(&ptr->srs), req->process_id, req->pid_name); } else if (req->terminate == browse_termination_callback) { browser_t *blist; char anonstr[256]; for (blist = req->u.browser.browsers; blist; blist = blist->next) - LogMsgNoIdent("%s DNSServiceBrowse %##s%s PID[%d](%s)", - (blist == req->u.browser.browsers) ? prefix : " ",blist->q.qname.c, - AnonDataToString(req->u.browser.AnonData, 0, anonstr, sizeof(anonstr)), req->process_id, req->pid_name); + LogMsgNoIdent("%s DNSServiceBrowse 0x%08X %2d %##s%s PID[%d](%s)", + (blist == req->u.browser.browsers) ? prefix : " ", req->flags, req->interfaceIndex, blist->q.qname.c, + AnonDataToString(req->u.browser.AnonData, 0, anonstr, sizeof(anonstr)), req->process_id, req->pid_name); } else if (req->terminate == resolve_termination_callback) - LogMsgNoIdent("%s DNSServiceResolve %##s PID[%d](%s)", - prefix, req->u.resolve.qsrv.qname.c, req->process_id, req->pid_name); + LogMsgNoIdent("%s DNSServiceResolve 0x%08X %2d %##s PID[%d](%s)", + prefix, req->flags, req->interfaceIndex, req->u.resolve.qsrv.qname.c, req->process_id, req->pid_name); else if (req->terminate == queryrecord_termination_callback) - LogMsgNoIdent("%s DNSServiceQueryRecord %##s (%s) PID[%d](%s)", - prefix, req->u.queryrecord.q.qname.c, DNSTypeName(req->u.queryrecord.q.qtype), req->process_id, req->pid_name); + LogMsgNoIdent("%s DNSServiceQueryRecord 0x%08X %2d %##s (%s) PID[%d](%s)", + prefix, req->flags, req->interfaceIndex, req->u.queryrecord.q.qname.c, DNSTypeName(req->u.queryrecord.q.qtype), req->process_id, req->pid_name); else if (req->terminate == enum_termination_callback) - LogMsgNoIdent("%s DNSServiceEnumerateDomains %##s PID[%d](%s)", prefix, req->u.enumeration.q_all.qname.c, - req->process_id, req->pid_name); + LogMsgNoIdent("%s DNSServiceEnumerateDomains 0x%08X %2d %##s PID[%d](%s)", + prefix, req->flags, req->interfaceIndex, req->u.enumeration.q_all.qname.c, req->process_id, req->pid_name); else if (req->terminate == port_mapping_termination_callback) - LogMsgNoIdent("%s DNSServiceNATPortMapping %s%s Int %5d Req %5d Ext %.4a:%5d Req TTL %5d Granted TTL %5d PID[%d](%s)", + LogMsgNoIdent("%s DNSServiceNATPortMapping 0x%08X %2d %s%s Int %5d Req %5d Ext %.4a:%5d Req TTL %5d Granted TTL %5d PID[%d](%s)", prefix, + req->flags, + req->interfaceIndex, req->u.pm.NATinfo.Protocol & NATOp_MapTCP ? "TCP" : " ", req->u.pm.NATinfo.Protocol & NATOp_MapUDP ? "UDP" : " ", mDNSVal16(req->u.pm.NATinfo.IntPort), @@ -5293,7 +5342,8 @@ mDNSlocal void LogClientInfo(mDNS *const m, request_state *req) req->u.pm.NATinfo.Lifetime, req->process_id, req->pid_name); else if (req->terminate == addrinfo_termination_callback) - LogMsgNoIdent("%s DNSServiceGetAddrInfo %s%s %##s PID[%d](%s)", prefix, + LogMsgNoIdent("%s DNSServiceGetAddrInfo 0x%08X %2d %s%s %##s PID[%d](%s)", + prefix, req->flags, req->interfaceIndex, req->u.addrinfo.protocol & kDNSServiceProtocol_IPv4 ? "v4" : " ", req->u.addrinfo.protocol & kDNSServiceProtocol_IPv6 ? "v6" : " ", req->u.addrinfo.q4.qname.c, req->process_id, req->pid_name); @@ -5527,19 +5577,22 @@ mDNSlocal void LogOneAuthRecord(mDNS *const m, const AuthRecord *ar, mDNSs32 now char anstr[256]; if (AuthRecord_uDNS(ar)) { - LogMsgNoIdent("%7d %7d %7d %7d %s", + LogMsgNoIdent("%7d %7d %7d %7d %s %s", ar->ThisAPInterval / mDNSPlatformOneSecond, (ar->LastAPTime + ar->ThisAPInterval - now) / mDNSPlatformOneSecond, ar->expire ? (ar->expire - now) / mDNSPlatformOneSecond : 0, - ar->state, ARDisplayString(m, ar)); + ar->state, + ar->AllowRemoteQuery ? "☠" : " ", + ARDisplayString(m, ar)); } else { - LogMsgNoIdent("%7d %7d %7d %7s %s%s", + LogMsgNoIdent("%7d %7d %7d %7s %s %s%s", ar->ThisAPInterval / mDNSPlatformOneSecond, ar->AnnounceCount ? (ar->LastAPTime + ar->ThisAPInterval - now) / mDNSPlatformOneSecond : 0, ar->TimeExpire ? (ar->TimeExpire - now) / mDNSPlatformOneSecond : 0, ifname ? ifname : "ALL", + ar->AllowRemoteQuery ? "☠" : " ", ARDisplayString(m, ar), AnonInfoToString(ar->resrec.AnonInfo, anstr, sizeof(anstr))); } } @@ -5992,11 +6045,8 @@ foundparent:; LogMsgNoIdent("m->WABBrowseQueriesCount %d", m->WABBrowseQueriesCount); LogMsgNoIdent("m->WABLBrowseQueriesCount %d", m->WABLBrowseQueriesCount); LogMsgNoIdent("m->WABRegQueriesCount %d", m->WABRegQueriesCount); - LogMsgNoIdent("m->mDNSOppCaching %d", m->mDNSOppCaching); LogMsgNoIdent("m->AutoTargetServices %d", m->AutoTargetServices); -#define LogTimer(MSG,T) LogMsgNoIdent( MSG " %08X %11d %08X %11d", (T), (T), (T)-now, (T)-now) - LogMsgNoIdent(" ABS (hex) ABS (dec) REL (hex) REL (dec)"); LogMsgNoIdent("m->timenow %08X %11d", now, now); LogMsgNoIdent("m->timenow_adjust %08X %11d", m->timenow_adjust, m->timenow_adjust); @@ -6101,7 +6151,6 @@ mDNSlocal int send_msg(request_state *const req) { reply_state *const rep = req->replies; // Send the first waiting reply ssize_t nwriten; - if (req->no_reply) return(t_complete); ConvertHeaderBytes(rep->mhdr); nwriten = send(req->sd, (char *)&rep->mhdr + rep->nwriten, rep->totallen - rep->nwriten, 0); @@ -6163,7 +6212,7 @@ mDNSexport mDNSs32 udsserver_idle(mDNSs32 nextevent) } else if (result == t_terminated || result == t_error) { - LogMsg("%3d: Could not write data to clientPID[%d](%s) because of error - aborting connection", r->sd, r->process_id, r->pid_name); + LogMsg("%3d: Could not write data to client PID[%d](%s) because of error - aborting connection", r->sd, r->process_id, r->pid_name); LogClientInfo(&mDNSStorage, r); abort_request(r); } @@ -6219,7 +6268,7 @@ struct CompileTimeAssertionChecks_uds_daemon char sizecheck_request_state [(sizeof(request_state) <= 2000) ? 1 : -1]; char sizecheck_registered_record_entry[(sizeof(registered_record_entry) <= 60) ? 1 : -1]; char sizecheck_service_instance [(sizeof(service_instance) <= 6552) ? 1 : -1]; - char sizecheck_browser_t [(sizeof(browser_t) <= 1096) ? 1 : -1]; + char sizecheck_browser_t [(sizeof(browser_t) <= 1128) ? 1 : -1]; char sizecheck_reply_hdr [(sizeof(reply_hdr) <= 12) ? 1 : -1]; char sizecheck_reply_state [(sizeof(reply_state) <= 64) ? 1 : -1]; }; diff --git a/usr/src/cmd/cmd-inet/usr.lib/mdnsd/uds_daemon.h b/usr/src/cmd/cmd-inet/usr.lib/mdnsd/uds_daemon.h index ca361172d1..6cc9197d63 100644 --- a/usr/src/cmd/cmd-inet/usr.lib/mdnsd/uds_daemon.h +++ b/usr/src/cmd/cmd-inet/usr.lib/mdnsd/uds_daemon.h @@ -1,6 +1,6 @@ /* -*- Mode: C; tab-width: 4 -*- * - * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2002-2013 Apple Inc. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,13 +13,6 @@ * 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. - - File: uds_daemon.h - - Contains: Interfaces necessary to talk to uds_daemon.c. - - Version: 1.0 - */ #include "mDNSEmbeddedAPI.h" @@ -29,6 +22,8 @@ #define SRS_PORT(S) mDNSVal16((S)->RR_SRV.resrec.rdata->u.srv.port) +#define LogTimer(MSG,T) LogMsgNoIdent( MSG " %08X %11d %08X %11d", (T), (T), (T)-now, (T)-now) + extern int udsserver_init(dnssd_sock_t skts[], mDNSu32 count); extern mDNSs32 udsserver_idle(mDNSs32 nextevent); extern void udsserver_info(mDNS *const m); // print out info about current state diff --git a/usr/src/lib/libdns_sd/README b/usr/src/lib/libdns_sd/README index 81491ffd91..9bae6c7404 100644 --- a/usr/src/lib/libdns_sd/README +++ b/usr/src/lib/libdns_sd/README @@ -21,8 +21,7 @@ # # CDDL HEADER END # -# Copyright 2016 Toomas Soome <tsoome@me.com> -# +Updated from upstream version mDNSResponder-625.41.2 Updated from upstream version mDNSResponder-576.30.4 Multicast DNS and Service Discovery support in Solaris using the diff --git a/usr/src/lib/libdns_sd/common/dns_sd.h b/usr/src/lib/libdns_sd/common/dns_sd.h index 3831527313..cf32ea1eda 100644 --- a/usr/src/lib/libdns_sd/common/dns_sd.h +++ b/usr/src/lib/libdns_sd/common/dns_sd.h @@ -1,6 +1,6 @@ /* -*- Mode: C; tab-width: 4 -*- * - * Copyright (c) 2003-2013 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2003-2015 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -10,7 +10,7 @@ * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of its + * 3. Neither the name of Apple Inc. ("Apple") nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -66,7 +66,7 @@ */ #ifndef _DNS_SD_H -#define _DNS_SD_H 5763004 +#define _DNS_SD_H 6254102 #ifdef __cplusplus extern "C" { @@ -497,12 +497,18 @@ enum * as the "serviceIndex". */ - kDNSServiceFlagsDenyExpensive = 0x20000000 + kDNSServiceFlagsDenyExpensive = 0x20000000, /* * This flag is meaningful only for Unicast DNS queries. When set, the kernel will restrict * DNS resolutions on interfaces defined as expensive for that request. */ + kDNSServiceFlagsPathEvaluationDone = 0x40000000 + /* + * This flag is meaningful for only Unicast DNS queries. + * When set, it indicates that Network PathEvaluation has already been performed. + */ + }; #define kDNSServiceOutputFlags (kDNSServiceFlagsValidate | kDNSServiceFlagsValidateOptional | kDNSServiceFlagsMoreComing | kDNSServiceFlagsAdd | kDNSServiceFlagsDefault) @@ -724,9 +730,8 @@ enum * DNS server." Normally, most clients will use 0 for interface index to * automatically get the default sensible behaviour. * - * If the client passes a positive interface index, then for multicast names that - * indicates to do the operation only on that one interface. For unicast names the - * interface index is ignored unless kDNSServiceFlagsForceMulticast is also set. + * If the client passes a positive interface index, then that indicates to do the + * operation only on that one specified interface. * * If the client passes kDNSServiceInterfaceIndexLocalOnly when registering * a service, then that service will be found *only* by other local clients @@ -2606,34 +2611,6 @@ DNSServiceErrorType DNSSD_API DNSServiceSleepKeepalive ); #endif -#ifdef APPLE_OSX_mDNSResponder -/* DNSServiceCreateDelegateConnection() - * - * Create a delegate connection to the daemon allowing efficient registration of - * multiple individual records. - * - * Parameters: - * - * sdRef: A pointer to an uninitialized DNSServiceRef. Deallocating - * the reference (via DNSServiceRefDeallocate()) severs the - * connection and deregisters all records registered on this connection. - * - * pid : Process ID of the delegate - * - * uuid: UUID of the delegate - * - * Note that only one of the two arguments (pid or uuid) can be specified. If pid - * is zero, uuid will be assumed to be a valid value; otherwise pid will be used. - * - * return value: Returns kDNSServiceErr_NoError on success, otherwise returns - * an error code indicating the specific failure that occurred (in which - * case the DNSServiceRef is not initialized). kDNSServiceErr_NotAuth is - * returned to indicate that the calling process does not have entitlements - * to use this API. - */ -DNSServiceErrorType DNSSD_API DNSServiceCreateDelegateConnection(DNSServiceRef *sdRef, int32_t pid, uuid_t uuid); -#endif - #ifdef __APPLE_API_PRIVATE #define kDNSServiceCompPrivateDNS "PrivateDNS" diff --git a/usr/src/lib/libdns_sd/common/dnssd_clientlib.c b/usr/src/lib/libdns_sd/common/dnssd_clientlib.c index c22e54db61..649d403f02 100644 --- a/usr/src/lib/libdns_sd/common/dnssd_clientlib.c +++ b/usr/src/lib/libdns_sd/common/dnssd_clientlib.c @@ -1,6 +1,6 @@ /* -*- Mode: C; tab-width: 4 -*- * - * Copyright (c) 2004, Apple Computer, Inc. All rights reserved. + * Copyright (c) 2004-2011 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -10,7 +10,7 @@ * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of its + * 3. Neither the name of Apple Inc. ("Apple") nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * diff --git a/usr/src/lib/libdns_sd/common/dnssd_clientstub.c b/usr/src/lib/libdns_sd/common/dnssd_clientstub.c index 6c44dae48d..b0fd9f9983 100644 --- a/usr/src/lib/libdns_sd/common/dnssd_clientstub.c +++ b/usr/src/lib/libdns_sd/common/dnssd_clientstub.c @@ -1,6 +1,6 @@ /* -*- Mode: C; tab-width: 4 -*- * - * Copyright (c) 2003-2004, Apple Computer, Inc. All rights reserved. + * Copyright (c) 2003-2015 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -10,7 +10,7 @@ * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of its + * 3. Neither the name of Apple Inc. ("Apple") nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -30,14 +30,15 @@ #include <stdlib.h> #include <fcntl.h> +#include "dnssd_ipc.h" + #if APPLE_OSX_mDNSResponder #include <mach-o/dyld.h> #include <uuid/uuid.h> #include <TargetConditionals.h> +#include "dns_sd_private.h" #endif -#include "dnssd_ipc.h" - #if defined(_WIN32) #define _SSIZE_T @@ -75,7 +76,7 @@ static void syslog( int priority, const char * message, ...) va_start( args, message ); len = _vscprintf( message, args ) + 1; buffer = malloc( len * sizeof(char) ); - if ( buffer ) { vsprintf( buffer, message, args ); OutputDebugString( buffer ); free( buffer ); } + if ( buffer ) { vsnprintf( buffer, len, message, args ); OutputDebugString( buffer ); free( buffer ); } WSASetLastError( err ); } #else @@ -285,7 +286,7 @@ static int more_bytes(dnssd_sock_t sd) // two ints and not just one. int nfdbits = sizeof (int) * 8; int nints = (sd/nfdbits) + 1; - fs = (fd_set *)calloc(nints, sizeof(int)); + fs = (fd_set *)calloc(nints, (size_t)sizeof(int)); if (fs == NULL) { syslog(LOG_WARNING, "dnssd_clientstub more_bytes: malloc failed"); @@ -356,7 +357,7 @@ static ipc_msg_hdr *create_hdr(uint32_t op, size_t *len, char **data_start, int struct timeval tv; if (gettimeofday(&tv, NULL) < 0) { syslog(LOG_WARNING, "dnssd_clientstub create_hdr: gettimeofday failed %d %s", dnssd_errno, dnssd_strerror(dnssd_errno)); return NULL; } - sprintf(ctrl_path, "%s%d-%.3lx-%.6lu", CTL_PATH_PREFIX, (int)getpid(), + snprintf(ctrl_path, sizeof(ctrl_path), "%s%d-%.3lx-%.6lu", CTL_PATH_PREFIX, (int)getpid(), (unsigned long)(tv.tv_sec & 0xFFF), (unsigned long)(tv.tv_usec)); *len += strlen(ctrl_path) + 1; #else @@ -406,7 +407,11 @@ static void FreeDNSServiceOp(DNSServiceOp *x) // We don't use our DNSServiceRefValid macro here because if we're cleaning up after a socket() call failed // then sockfd could legitimately contain a failing value (e.g. dnssd_InvalidSocket) if ((x->sockfd ^ x->validator) != ValidatorBits) + { + static DNSServiceOp *op_were_not_going_to_free_but_we_need_to_fool_the_analyzer; syslog(LOG_WARNING, "dnssd_clientstub attempt to dispose invalid DNSServiceRef %p %08X %08X", x, x->sockfd, x->validator); + op_were_not_going_to_free_but_we_need_to_fool_the_analyzer = x; + } else { x->next = NULL; @@ -531,6 +536,11 @@ static DNSServiceErrorType ConnectToServer(DNSServiceRef *ref, DNSServiceFlags f char* uds_serverpath = getenv(MDNS_UDS_SERVERPATH_ENVVAR); if (uds_serverpath == NULL) uds_serverpath = MDNS_UDS_SERVERPATH; + else if (strlen(uds_serverpath) >= MAX_CTLPATH) + { + uds_serverpath = MDNS_UDS_SERVERPATH; + syslog(LOG_WARNING, "dnssd_clientstub ConnectToServer: using default path since env len is invalid"); + } #endif *ref = NULL; sdr->sockfd = socket(AF_DNSSD, SOCK_STREAM, 0); @@ -579,8 +589,10 @@ static DNSServiceErrorType ConnectToServer(DNSServiceRef *ref, DNSServiceFlags f } else { + #if !defined(USE_TCP_LOOPBACK) syslog(LOG_WARNING, "dnssd_clientstub ConnectToServer: connect() failed path:%s Socket:%d Err:%d Errno:%d %s", uds_serverpath, sdr->sockfd, err, dnssd_errno, dnssd_strerror(dnssd_errno)); + #endif dnssd_close(sdr->sockfd); FreeDNSServiceOp(sdr); return kDNSServiceErr_ServiceNotRunning; @@ -598,21 +610,25 @@ static DNSServiceErrorType ConnectToServer(DNSServiceRef *ref, DNSServiceFlags f static DNSServiceErrorType deliver_request(ipc_msg_hdr *hdr, DNSServiceOp *sdr) { + if (!hdr) + { + syslog(LOG_WARNING, "dnssd_clientstub deliver_request: !hdr"); + return kDNSServiceErr_Unknown; + } + uint32_t datalen = hdr->datalen; // We take a copy here because we're going to convert hdr->datalen to network byte order #if defined(USE_TCP_LOOPBACK) || defined(USE_NAMED_ERROR_RETURN_SOCKET) char *const data = (char *)hdr + sizeof(ipc_msg_hdr); #endif dnssd_sock_t listenfd = dnssd_InvalidSocket, errsd = dnssd_InvalidSocket; DNSServiceErrorType err = kDNSServiceErr_Unknown; // Default for the "goto cleanup" cases - int MakeSeparateReturnSocket = 0; // Note: need to check hdr->op, not sdr->op. // hdr->op contains the code for the specific operation we're currently doing, whereas sdr->op // contains the original parent DNSServiceOp (e.g. for an add_record_request, hdr->op will be // add_record_request but the parent sdr->op will be connection_request or reg_service_request) - if (sdr->primary || - hdr->op == reg_record_request || hdr->op == add_record_request || hdr->op == update_record_request || hdr->op == remove_record_request) - MakeSeparateReturnSocket = 1; + const int MakeSeparateReturnSocket = (sdr->primary || + hdr->op == reg_record_request || hdr->op == add_record_request || hdr->op == update_record_request || hdr->op == remove_record_request); if (!DNSServiceRefValid(sdr)) { @@ -622,12 +638,6 @@ static DNSServiceErrorType deliver_request(ipc_msg_hdr *hdr, DNSServiceOp *sdr) return kDNSServiceErr_BadReference; } - if (!hdr) - { - syslog(LOG_WARNING, "dnssd_clientstub deliver_request: !hdr"); - return kDNSServiceErr_Unknown; - } - if (MakeSeparateReturnSocket) { #if defined(USE_TCP_LOOPBACK) @@ -637,21 +647,21 @@ static DNSServiceErrorType deliver_request(ipc_msg_hdr *hdr, DNSServiceOp *sdr) dnssd_socklen_t len = (dnssd_socklen_t) sizeof(caddr); listenfd = socket(AF_DNSSD, SOCK_STREAM, 0); if (!dnssd_SocketValid(listenfd)) { - deliver_request_bailout("TCP socket"); - } + deliver_request_bailout("TCP socket"); + } caddr.sin_family = AF_INET; caddr.sin_port = 0; caddr.sin_addr.s_addr = inet_addr(MDNS_TCP_SERVERADDR); if (bind(listenfd, (struct sockaddr*) &caddr, sizeof(caddr)) < 0) { - deliver_request_bailout("TCP bind"); - } - if (getsockname(listenfd, (struct sockaddr*) &caddr, &len) < 0) { - deliver_request_bailout("TCP getsockname"); - } - if (listen(listenfd, 1) < 0) { - deliver_request_bailout("TCP listen"); - } + deliver_request_bailout("TCP bind"); + } + if (getsockname(listenfd, (struct sockaddr*) &caddr, &len) < 0) { + deliver_request_bailout("TCP getsockname"); + } + if (listen(listenfd, 1) < 0) { + deliver_request_bailout("TCP listen"); + } port.s = caddr.sin_port; data[0] = port.b[0]; // don't switch the byte order, as the data[1] = port.b[1]; // daemon expects it in network byte order @@ -663,8 +673,8 @@ static DNSServiceErrorType deliver_request(ipc_msg_hdr *hdr, DNSServiceOp *sdr) dnssd_sockaddr_t caddr; listenfd = socket(AF_DNSSD, SOCK_STREAM, 0); if (!dnssd_SocketValid(listenfd)) { - deliver_request_bailout("USE_NAMED_ERROR_RETURN_SOCKET socket"); - } + deliver_request_bailout("USE_NAMED_ERROR_RETURN_SOCKET socket"); + } caddr.sun_family = AF_LOCAL; // According to Stevens (section 3.2), there is no portable way to @@ -676,19 +686,19 @@ static DNSServiceErrorType deliver_request(ipc_msg_hdr *hdr, DNSServiceOp *sdr) mask = umask(0); bindresult = bind(listenfd, (struct sockaddr *)&caddr, sizeof(caddr)); umask(mask); - if (bindresult < 0) { - deliver_request_bailout("USE_NAMED_ERROR_RETURN_SOCKET bind"); - } + if (bindresult < 0) { + deliver_request_bailout("USE_NAMED_ERROR_RETURN_SOCKET bind"); + } if (listen(listenfd, 1) < 0) { - deliver_request_bailout("USE_NAMED_ERROR_RETURN_SOCKET listen"); - } + deliver_request_bailout("USE_NAMED_ERROR_RETURN_SOCKET listen"); + } } #else { dnssd_sock_t sp[2]; if (socketpair(AF_DNSSD, SOCK_STREAM, 0, sp) < 0) { - deliver_request_bailout("socketpair"); - } + deliver_request_bailout("socketpair"); + } else { errsd = sp[0]; // We'll read our four-byte error code from sp[0] @@ -756,7 +766,7 @@ static DNSServiceErrorType deliver_request(ipc_msg_hdr *hdr, DNSServiceOp *sdr) errsd = accept(listenfd, (struct sockaddr *)&daddr, &len); if (!dnssd_SocketValid(errsd)) { deliver_request_bailout("accept"); - } + } #else struct iovec vec = { ((char *)hdr) + sizeof(ipc_msg_hdr) + datalen, 1 }; // Send the last byte along with the SCM_RIGHTS @@ -1176,6 +1186,8 @@ DNSServiceErrorType DNSSD_API DNSServiceGetProperty(const char *property, void * put_string(property, &ptr); err = deliver_request(hdr, tmp); // Will free hdr for us + if (err) { DNSServiceRefDeallocate(tmp); return err; } + if (read_all(tmp->sockfd, (char*)&actualsize, (int)sizeof(actualsize)) < 0) { DNSServiceRefDeallocate(tmp); return kDNSServiceErr_ServiceNotRunning; } @@ -1200,24 +1212,17 @@ DNSServiceErrorType DNSSD_API DNSServiceGetPID(const uint16_t srcport, int32_t * size_t len = sizeof(int32_t); DNSServiceErrorType err = ConnectToServer(&tmp, 0, getpid_request, NULL, NULL, NULL); - if (err) - return err; + if (err) return err; hdr = create_hdr(getpid_request, &len, &ptr, 0, tmp); - if (!hdr) - { - DNSServiceRefDeallocate(tmp); - return kDNSServiceErr_NoMemory; - } + if (!hdr) { DNSServiceRefDeallocate(tmp); return kDNSServiceErr_NoMemory; } put_uint16(srcport, &ptr); err = deliver_request(hdr, tmp); // Will free hdr for us + if (err) { DNSServiceRefDeallocate(tmp); return err; } if (read_all(tmp->sockfd, (char*)pid, sizeof(int32_t)) < 0) - { - DNSServiceRefDeallocate(tmp); - return kDNSServiceErr_ServiceNotRunning; - } + { DNSServiceRefDeallocate(tmp); return kDNSServiceErr_ServiceNotRunning; } DNSServiceRefDeallocate(tmp); return kDNSServiceErr_NoError; @@ -1399,16 +1404,17 @@ DNSServiceErrorType DNSSD_API DNSServiceQueryRecord static void handle_addrinfo_response(DNSServiceOp *const sdr, const CallbackHeader *const cbh, const char *data, const char *const end) { char hostname[kDNSServiceMaxDomainName]; - uint16_t rrtype, rdlen; + uint16_t rrtype, rrclass, rdlen; const char *rdata; uint32_t ttl; get_string(&data, end, hostname, kDNSServiceMaxDomainName); rrtype = get_uint16(&data, end); - (void) get_uint16(&data, end); /* class is not used */ + rrclass = get_uint16(&data, end); rdlen = get_uint16(&data, end); rdata = get_rdata (&data, end, rdlen); ttl = get_uint32(&data, end); + (void)rrclass; // Unused // We only generate client callbacks for A and AAAA results (including NXDOMAIN results for // those types, if the client has requested those with the kDNSServiceFlagsReturnIntermediates). @@ -1631,13 +1637,7 @@ DNSServiceErrorType DNSSD_API DNSServiceRegister hdr = create_hdr(reg_service_request, &len, &ptr, (*sdRef)->primary ? 1 : 0, *sdRef); if (!hdr) { DNSServiceRefDeallocate(*sdRef); *sdRef = NULL; return kDNSServiceErr_NoMemory; } - - // If it is going over a shared connection, then don't set the IPC_FLAGS_NOREPLY - // as it affects all the operations over the shared connection. This is not - // a normal case and hence receiving the response back from the daemon and - // discarding it in ConnectionResponse is okay. - - if (!(flags & kDNSServiceFlagsShareConnection) && !callBack) hdr->ipc_flags |= IPC_FLAGS_NOREPLY; + if (!callBack) hdr->ipc_flags |= IPC_FLAGS_NOREPLY; put_flags(flags, &ptr); put_uint32(interfaceIndex, &ptr); diff --git a/usr/src/lib/libdns_sd/common/dnssd_ipc.c b/usr/src/lib/libdns_sd/common/dnssd_ipc.c index 6059eb392c..0fd75824f5 100644 --- a/usr/src/lib/libdns_sd/common/dnssd_ipc.c +++ b/usr/src/lib/libdns_sd/common/dnssd_ipc.c @@ -1,6 +1,6 @@ /* -*- Mode: C; tab-width: 4 -*- * - * Copyright (c) 2003-2004, Apple Computer, Inc. All rights reserved. + * Copyright (c) 2003-2011 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -10,7 +10,7 @@ * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of its + * 3. Neither the name of Apple Inc. ("Apple") nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * diff --git a/usr/src/lib/libdns_sd/common/dnssd_ipc.h b/usr/src/lib/libdns_sd/common/dnssd_ipc.h index ec098032b4..b9c0b144d3 100644 --- a/usr/src/lib/libdns_sd/common/dnssd_ipc.h +++ b/usr/src/lib/libdns_sd/common/dnssd_ipc.h @@ -1,6 +1,6 @@ /* -*- Mode: C; tab-width: 4 -*- * - * Copyright (c) 2003-2004, Apple Computer, Inc. All rights reserved. + * Copyright (c) 2003-2015 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -10,7 +10,7 @@ * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of its + * 3. Neither the name of Apple Inc. ("Apple") nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -88,7 +88,7 @@ extern char *win32_strerror(int inErrorCode); # define MDNS_UDS_SERVERPATH_ENVVAR "DNSSD_UDS_PATH" # define LISTENQ 100 // longest legal control path length -# define MAX_CTLPATH 256 +# define MAX_CTLPATH (sizeof(((struct sockaddr_un*)0)->sun_path)) # define dnssd_sockaddr_t struct sockaddr_un #endif |