From e36ca101817ed47e788f1f2801190718736e834e Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Wed, 19 Sep 2018 08:49:34 +0200 Subject: mDNSResponder: Update to v567 The sources can be obtained via: https://opensource.apple.com/tarballs/mDNSResponder/mDNSResponder-567.tar.gz Update #3522. --- mDNSResponder/mDNSPosix/Makefile | 23 ++++++------ mDNSResponder/mDNSPosix/NetMonitor.c | 69 +++++++++++++++++++++++++++++++----- mDNSResponder/mDNSPosix/mDNSPosix.c | 40 ++++++++++++++++++++- mDNSResponder/mDNSPosix/mDNSPosix.h | 3 +- 4 files changed, 113 insertions(+), 22 deletions(-) (limited to 'mDNSResponder/mDNSPosix') diff --git a/mDNSResponder/mDNSPosix/Makefile b/mDNSResponder/mDNSPosix/Makefile index d095a0f4..817a3775 100755 --- a/mDNSResponder/mDNSPosix/Makefile +++ b/mDNSResponder/mDNSPosix/Makefile @@ -1,6 +1,6 @@ # -*- tab-width: 4 -*- # -# Copyright (c) 2002-2004, Apple Computer, Inc. All rights reserved. +# Copyright (c) 2002-2004, 2015, Apple Computer, 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: @@ -30,8 +30,8 @@ # If "make os=xxx" gives lots of errors like "Missing dependency operator", # then try typing "gmake os=xxx" instead. # -# This Makefile builds an mDNSResponder daemon and a libdns_sd.so shared library -# for Linux. It also builds several example programs for embedded systems. +# This Makefile builds an mDNSResponder daemon and a libdns_sd.so shared library +# for Linux. It also builds several example programs for embedded systems. # # Make with no arguments to build all production targets. # 'make DEBUG=1' to build debugging targets. @@ -57,6 +57,7 @@ JDK = /usr/jdk CC = @cc BISON = @bison FLEX = @flex +ST = @strip LD = ld -shared CP = cp RM = rm @@ -71,18 +72,18 @@ JAVACFLAGS_OS = -fPIC -shared -ldns_sd # Set up diverging paths for debug vs. prod builds DEBUG=0 ifeq ($(DEBUG),1) -CFLAGS_DEBUG = -g -DMDNS_DEBUGMSGS=2 +CFLAGS_DEBUG = -g -DMDNS_DEBUGMSGS=2 OBJDIR = objects/debug BUILDDIR = build/debug -STRIP = echo +STRIP = echo else # We use -Os for two reasons: # 1. We want to make small binaries, suitable for putting into hardware devices # 2. Some of the code analysis warnings only work when some form of optimization is enabled -CFLAGS_DEBUG = -Os -DMDNS_DEBUGMSGS=0 +CFLAGS_DEBUG = -Os -DMDNS_DEBUGMSGS=0 OBJDIR ?= objects/prod BUILDDIR ?= build/prod -STRIP = strip -S +STRIP = $(ST) -S endif # Configure per-OS peculiarities @@ -95,14 +96,14 @@ LD = gcc -shared LINKOPTS = -lsocket -lnsl -lresolv JAVACFLAGS_OS += -I$(JDK)/include/solaris ifneq ($(DEBUG),1) -STRIP = strip +STRIP = $(ST) endif else # any target that contains the string "linux" ifeq ($(findstring linux,$(os)),linux) CFLAGS_OS = -D_GNU_SOURCE -DHAVE_IPV6 -DNOT_HAVE_SA_LEN -DUSES_NETLINK -DHAVE_LINUX -DTARGET_OS_LINUX -fno-strict-aliasing -LD = gcc -shared +LD = $(CC) -shared FLEXFLAGS_OS = -l JAVACFLAGS_OS += -I$(JDK)/include/linux @@ -151,11 +152,11 @@ LD = $(CC) -dynamiclib LINKOPTS = -lSystem LDSUFFIX = dylib JDK = /System/Library/Frameworks/JavaVM.framework/Home -JAVACFLAGS_OS = -dynamiclib -I/System/Library/Frameworks/JavaVM.framework/Headers -framework JavaVM +JAVACFLAGS_OS = -dynamiclib -I/System/Library/Frameworks/JavaVM.framework/Headers -framework JavaVM else $(error ERROR: Must specify target OS on command-line, e.g. "make os=x [target]".\ -Supported operating systems include: x, linux, linux-uclibc, netbsd, freebsd, openbsd, solaris) +Supported operating systems include: x, linux, linux-uclibc, netbsd, freebsd, openbsd, solaris) endif endif endif diff --git a/mDNSResponder/mDNSPosix/NetMonitor.c b/mDNSResponder/mDNSPosix/NetMonitor.c index 1354f1f8..a3823c54 100644 --- a/mDNSResponder/mDNSPosix/NetMonitor.c +++ b/mDNSResponder/mDNSPosix/NetMonitor.c @@ -120,6 +120,7 @@ struct timeval tv_start, tv_end, tv_interval; static int FilterInterface = 0; static FilterList *Filters; #define ExactlyOneFilter (Filters && !Filters->next) +static mDNSBool AddressType = mDNSAddrType_IPv4; static int NumPktQ, NumPktL, NumPktR, NumPktB; // Query/Legacy/Response/Bad static int NumProbes, NumGoodbyes, NumQuestions, NumLegacy, NumAnswers, NumAdditionals; @@ -464,9 +465,9 @@ mDNSlocal const mDNSu8 *FindUpdate(mDNS *const m, const DNSMessage *const query, mDNSlocal void DisplayPacketHeader(mDNS *const m, const DNSMessage *const msg, const mDNSu8 *const end, const mDNSAddr *srcaddr, mDNSIPPort srcport, const mDNSAddr *dstaddr, const mDNSInterfaceID InterfaceID) { - const char *const ptype = (msg->h.flags.b[0] & kDNSFlag0_QR_Response) ? "-R- " : + const char *const ptype = (msg->h.flags.b[0] & kDNSFlag0_QR_Response) ? "-R- " : (srcport.NotAnInteger == MulticastDNSPort.NotAnInteger) ? "-Q- " : "-LQ-"; - + const unsigned length = end - (mDNSu8 *)msg; struct timeval tv; struct tm tm; const mDNSu32 index = mDNSPlatformInterfaceIndexfromInterfaceID(m, InterfaceID, mDNSfalse); @@ -477,7 +478,7 @@ mDNSlocal void DisplayPacketHeader(mDNS *const m, const DNSMessage *const msg, c mprintf("\n%d:%02d:%02d.%06d Interface %d/%s\n", tm.tm_hour, tm.tm_min, tm.tm_sec, tv.tv_usec, index, if_name); mprintf("%#-16a %s Q:%3d Ans:%3d Auth:%3d Add:%3d Size:%5d bytes", - srcaddr, ptype, msg->h.numQuestions, msg->h.numAnswers, msg->h.numAuthorities, msg->h.numAdditionals, end - (mDNSu8 *)msg); + srcaddr, ptype, msg->h.numQuestions, msg->h.numAnswers, msg->h.numAuthorities, msg->h.numAdditionals, length); if (msg->h.id.NotAnInteger) mprintf(" ID:%u", mDNSVal16(msg->h.id)); @@ -488,7 +489,27 @@ mDNSlocal void DisplayPacketHeader(mDNS *const m, const DNSMessage *const msg, c if (msg->h.flags.b[0] & kDNSFlag0_QR_Response) mprintf(" Truncated"); else mprintf(" Truncated (KA list continues in next packet)"); } + mprintf("\n"); + + if (length < sizeof(DNSMessageHeader) + NormalMaxDNSMessageData - 192) + if (msg->h.flags.b[0] & kDNSFlag0_TC) + mprintf("%#-16a **** WARNING: Packet suspiciously small. Payload size (excluding IP and UDP headers)\n" + "%#-16a **** should usually be closer to %d bytes before truncation becomes necessary.\n", + srcaddr, srcaddr, sizeof(DNSMessageHeader) + NormalMaxDNSMessageData); +} + +mDNSlocal void DisplaySizeCheck(const DNSMessage *const msg, const mDNSu8 *const end, const mDNSAddr *srcaddr, int num_opts) +{ + const unsigned length = end - (mDNSu8 *)msg; + const int num_records = msg->h.numAnswers + msg->h.numAuthorities + msg->h.numAdditionals - num_opts; + + if (length > sizeof(DNSMessageHeader) + NormalMaxDNSMessageData) + if (num_records > 1) + mprintf("%#-16a **** ERROR: Oversized packet with %d records.\n" + "%#-16a **** Many network devices cannot receive packets larger than %d bytes.\n" + "%#-16a **** To minimize interoperability failures, oversized packets MUST be limited to a single resource record.\n", + srcaddr, num_records, srcaddr, 40 + 8 + sizeof(DNSMessageHeader) + NormalMaxDNSMessageData, srcaddr); } mDNSlocal void DisplayResourceRecord(const mDNSAddr *const srcaddr, const char *const op, const ResourceRecord *const pktrr) @@ -594,7 +615,7 @@ mDNSlocal void HexDump(const mDNSu8 *ptr, const mDNSu8 *const end) mDNSlocal void DisplayError(const mDNSAddr *srcaddr, const mDNSu8 *ptr, const mDNSu8 *const end, char *msg) { - mprintf("%#-16a **** ERROR: FAILED TO READ %s **** \n", srcaddr, msg); + mprintf("%#-16a **** ERROR: FAILED TO READ %s ****\n", srcaddr, msg); HexDump(ptr, end); } @@ -602,6 +623,7 @@ mDNSlocal void DisplayQuery(mDNS *const m, const DNSMessage *const msg, const mD const mDNSAddr *srcaddr, mDNSIPPort srcport, const mDNSAddr *dstaddr, const mDNSInterfaceID InterfaceID) { int i; + int num_opts = 0; const mDNSu8 *ptr = msg->data; const mDNSu8 *auth = LocateAuthorities(msg, end); mDNSBool MQ = (srcport.NotAnInteger == MulticastDNSPort.NotAnInteger); @@ -611,7 +633,7 @@ mDNSlocal void DisplayQuery(mDNS *const m, const DNSMessage *const msg, const mD DisplayPacketHeader(m, msg, end, srcaddr, srcport, dstaddr, InterfaceID); if (msg->h.id.NotAnInteger != 0xFFFF) { - if (MQ) NumPktQ++;else NumPktL++; + if (MQ) NumPktQ++; else NumPktL++; } for (i=0; ih.numQuestions; i++) @@ -648,6 +670,8 @@ mDNSlocal void DisplayQuery(mDNS *const m, const DNSMessage *const msg, const mD ptr = GetLargeResourceRecord(m, msg, ptr, end, InterfaceID, kDNSRecordTypePacketAns, &pkt); if (!ptr) { DisplayError(srcaddr, ep, end, "KNOWN ANSWER"); return; } DisplayResourceRecord(srcaddr, "(KA)", &pkt.r.resrec); + if (pkt.r.resrec.rrtype == kDNSType_OPT) + { num_opts++; mprintf("%#-16a **** ERROR: OPT RECORD IN ANSWER SECTION ****\n", srcaddr); } // In the case of queries with long multi-packet KA lists, we count each subsequent KA packet // the same as a single query, to more accurately reflect the burden on the network @@ -664,6 +688,8 @@ mDNSlocal void DisplayQuery(mDNS *const m, const DNSMessage *const msg, const mD // After we display an Update record with its matching question (above) we zero out its type and class // If any remain that haven't been zero'd out, display them here if (pkt.r.resrec.rrtype || pkt.r.resrec.rrclass) DisplayResourceRecord(srcaddr, "(AU)", &pkt.r.resrec); + if (pkt.r.resrec.rrtype == kDNSType_OPT) + { num_opts++; mprintf("%#-16a **** ERROR: OPT RECORD IN AUTHORITY SECTION ****\n", srcaddr); } } for (i=0; ih.numAdditionals; i++) @@ -672,8 +698,15 @@ mDNSlocal void DisplayQuery(mDNS *const m, const DNSMessage *const msg, const mD ptr = GetLargeResourceRecord(m, msg, ptr, end, InterfaceID, kDNSRecordTypePacketAdd, &pkt); if (!ptr) { DisplayError(srcaddr, ep, end, "ADDITIONAL"); return; } DisplayResourceRecord(srcaddr, pkt.r.resrec.rrtype == kDNSType_OPT ? "(OP)" : "(AD)", &pkt.r.resrec); + if (pkt.r.resrec.rrtype == kDNSType_OPT) num_opts++; } + DisplaySizeCheck(msg, end, srcaddr, num_opts); + + // We don't hexdump the DNSMessageHeader here because those six fields (id, flags, numQuestions, numAnswers, numAuthorities, numAdditionals) + // have already been swapped to host byte order and displayed, so including them in the hexdump is confusing + if (num_opts > 1) { mprintf("%#-16a **** ERROR: MULTIPLE OPT RECORDS ****\n", srcaddr); HexDump(msg->data, end); } + if (entry) AnalyseHost(m, entry, InterfaceID); } @@ -681,6 +714,7 @@ mDNSlocal void DisplayResponse(mDNS *const m, const DNSMessage *const msg, const const mDNSAddr *srcaddr, mDNSIPPort srcport, const mDNSAddr *dstaddr, const mDNSInterfaceID InterfaceID) { int i; + int num_opts = 0; const mDNSu8 *ptr = msg->data; HostEntry *entry = GotPacketFromHost(srcaddr, HostPkt_R, msg->h.id); LargeCacheRecord pkt; @@ -718,6 +752,8 @@ mDNSlocal void DisplayResponse(mDNS *const m, const DNSMessage *const msg, const DisplayResourceRecord(srcaddr, "(DE)", &pkt.r.resrec); recordstat(entry, pkt.r.resrec.name, OP_goodbye, pkt.r.resrec.rrtype); } + if (pkt.r.resrec.rrtype == kDNSType_OPT) + { num_opts++; mprintf("%#-16a **** ERROR: OPT RECORD IN ANSWER SECTION ****\n", srcaddr); } } for (i=0; ih.numAuthorities; i++) @@ -725,9 +761,12 @@ mDNSlocal void DisplayResponse(mDNS *const m, const DNSMessage *const msg, const const mDNSu8 *ep = ptr; ptr = GetLargeResourceRecord(m, msg, ptr, end, InterfaceID, kDNSRecordTypePacketAuth, &pkt); if (!ptr) { DisplayError(srcaddr, ep, end, "AUTHORITY"); return; } - if (pkt.r.resrec.rrtype != kDNSType_NSEC3) + DisplayResourceRecord(srcaddr, "(AU)", &pkt.r.resrec); + if (pkt.r.resrec.rrtype == kDNSType_OPT) + { num_opts++; mprintf("%#-16a **** ERROR: OPT RECORD IN AUTHORITY SECTION ****\n", srcaddr); } + else if (pkt.r.resrec.rrtype != kDNSType_NSEC3) mprintf("%#-16a (?) **** ERROR: SHOULD NOT HAVE AUTHORITY IN mDNS RESPONSE **** %-5s %##s\n", - srcaddr, DNSTypeName(pkt.r.resrec.rrtype), pkt.r.resrec.name->c); + srcaddr, DNSTypeName(pkt.r.resrec.rrtype), pkt.r.resrec.name->c); } for (i=0; ih.numAdditionals; i++) @@ -736,12 +775,19 @@ mDNSlocal void DisplayResponse(mDNS *const m, const DNSMessage *const msg, const ptr = GetLargeResourceRecord(m, msg, ptr, end, InterfaceID, kDNSRecordTypePacketAdd, &pkt); if (!ptr) { DisplayError(srcaddr, ep, end, "ADDITIONAL"); return; } NumAdditionals++; + if (pkt.r.resrec.rrtype == kDNSType_OPT) num_opts++; DisplayResourceRecord(srcaddr, pkt.r.resrec.rrtype == kDNSType_OPT ? "(OP)" : (pkt.r.resrec.RecordType & kDNSRecordTypePacketUniqueMask) ? "(AD)" : "(AD+)", &pkt.r.resrec); if (entry) RecordHostInfo(entry, &pkt.r.resrec); } + DisplaySizeCheck(msg, end, srcaddr, num_opts); + + // We don't hexdump the DNSMessageHeader here because those six fields (id, flags, numQuestions, numAnswers, numAuthorities, numAdditionals) + // have already been swapped to host byte order and displayed, so including them in the hexdump is confusing + if (num_opts > 1) { mprintf("%#-16a **** ERROR: MULTIPLE OPT RECORDS ****\n", srcaddr); HexDump(msg->data, end); } + if (entry) AnalyseHost(m, entry, InterfaceID); } @@ -763,7 +809,7 @@ mDNSlocal void ProcessUnicastResponse(mDNS *const m, const DNSMessage *const msg mDNSlocal mDNSBool AddressMatchesFilterList(const mDNSAddr *srcaddr) { FilterList *f; - if (!Filters) return(srcaddr->type == mDNSAddrType_IPv4); + if (!Filters) return(srcaddr->type == AddressType); for (f=Filters; f; f=f->next) if (mDNSSameAddress(srcaddr, &f->FilterAddr)) return(mDNStrue); return(mDNSfalse); } @@ -930,9 +976,14 @@ mDNSexport int main(int argc, char **argv) if (i+1 < argc && !strcmp(argv[i], "-i") && atoi(argv[i+1])) { FilterInterface = atoi(argv[i+1]); - i += 2; + i += 1; printf("Monitoring interface %d\n", FilterInterface); } + else if (!strcmp(argv[i], "-6")) + { + AddressType = mDNSAddrType_IPv6; + printf("Monitoring IPv6 traffic\n"); + } else { struct in_addr s4; diff --git a/mDNSResponder/mDNSPosix/mDNSPosix.c b/mDNSResponder/mDNSPosix/mDNSPosix.c index 6bc22af3..bdfb71f2 100755 --- a/mDNSResponder/mDNSPosix/mDNSPosix.c +++ b/mDNSResponder/mDNSPosix/mDNSPosix.c @@ -90,6 +90,8 @@ static GenLinkedList gEventSources; // linked list of PosixEventSour static sigset_t gEventSignalSet; // Signals which event loop listens for static sigset_t gEventSignals; // Signals which were received while inside loop +static PosixNetworkInterface *gRecentInterfaces; + // *************************************************************************** // Globals (for debugging) @@ -574,6 +576,13 @@ mDNSexport mDNSu32 mDNSPlatformInterfaceIndexfromInterfaceID(mDNS *const m, mDNS while ((intf != NULL) && (mDNSInterfaceID) intf != id) intf = (PosixNetworkInterface *)(intf->coreIntf.next); + if (intf) return intf->index; + + // If we didn't find the interface, check the RecentInterfaces list as well + intf = gRecentInterfaces; + while ((intf != NULL) && (mDNSInterfaceID) intf != id) + intf = (PosixNetworkInterface *)(intf->coreIntf.next); + return intf ? intf->index : 0; } @@ -587,7 +596,11 @@ mDNSlocal void FreePosixNetworkInterface(PosixNetworkInterface *intf) #if HAVE_IPV6 if (intf->multicastSocket6 != -1) assert(close(intf->multicastSocket6) == 0); #endif - free(intf); + + // Move interface to the RecentInterfaces list for a minute + intf->LastSeen = mDNSPlatformUTC(); + intf->coreIntf.next = &gRecentInterfaces->coreIntf; + gRecentInterfaces = intf; } // Grab the first interface, deregister it, free it, and repeat until done. @@ -643,6 +656,14 @@ mDNSlocal int SetupSocket(struct sockaddr *intfAddr, mDNSIPPort port, int interf #error This platform has no way to avoid address busy errors on multicast. #endif if (err < 0) { err = errno; perror("setsockopt - SO_REUSExxxx"); } + + // 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. + #ifndef SO_RECV_ANYIF + #define SO_RECV_ANYIF 0x1104 /* unrestricted inbound processing */ + #endif + if (setsockopt(*sktPtr, SOL_SOCKET, SO_RECV_ANYIF, &kOn, sizeof(kOn)) < 0) perror("setsockopt - SO_RECV_ANYIF"); } // We want to receive destination addresses and interface identifiers. @@ -978,6 +999,17 @@ mDNSlocal int SetupInterfaceList(mDNS *const m) // Clean up. if (intfList != NULL) free_ifi_info(intfList); + + // Clean up any interfaces that have been hanging around on the RecentInterfaces list for more than a minute + PosixNetworkInterface **ri = &gRecentInterfaces; + const mDNSs32 utc = mDNSPlatformUTC(); + while (*ri) + { + PosixNetworkInterface *pi = *ri; + if (utc - pi->LastSeen < 60) ri = (PosixNetworkInterface **)&pi->coreIntf.next; + else { *ri = (PosixNetworkInterface *)pi->coreIntf.next; free(pi); } + } + return err; } @@ -1318,9 +1350,15 @@ mDNSexport void mDNSPlatformClose(mDNS *const m) #endif } +// This is used internally by InterfaceChangeCallback. +// It's also exported so that the Standalone Responder (mDNSResponderPosix) +// can call it in response to a SIGHUP (mainly for debugging purposes). mDNSexport mStatus mDNSPlatformPosixRefreshInterfaceList(mDNS *const m) { int err; + // This is a pretty heavyweight way to process interface changes -- + // destroying the entire interface list and then making fresh one from scratch. + // We should make it like the OS X version, which leaves unchanged interfaces alone. ClearInterfaceList(m); err = SetupInterfaceList(m); return PosixErrorToStatus(err); diff --git a/mDNSResponder/mDNSPosix/mDNSPosix.h b/mDNSResponder/mDNSPosix/mDNSPosix.h index f6dab9e9..9e16bb89 100755 --- a/mDNSResponder/mDNSPosix/mDNSPosix.h +++ b/mDNSResponder/mDNSPosix/mDNSPosix.h @@ -38,7 +38,8 @@ typedef struct PosixNetworkInterface PosixNetworkInterface; struct PosixNetworkInterface { - NetworkInterfaceInfo coreIntf; + NetworkInterfaceInfo coreIntf; // MUST be the first element in this structure + mDNSs32 LastSeen; const char * intfName; PosixNetworkInterface * aliasIntf; int index; -- cgit v1.2.3