version 320.10
diff --git a/Makefile b/Makefile
index 501abbe..75a0f57 100644
--- a/Makefile
+++ b/Makefile
@@ -16,7 +16,7 @@
 
 include /Developer/Makefiles/pb_makefiles/platform.make
 
-MVERS = "mDNSResponder-320.5.1"
+MVERS = "mDNSResponder-320.10"
 
 DDNSWRITECONFIG = "$(DSTROOT)/Library/Application Support/Bonjour/ddnswriteconfig"
 
diff --git a/mDNSCore/DNSCommon.c b/mDNSCore/DNSCommon.c
index 2c23925..b75c128 100644
--- a/mDNSCore/DNSCommon.c
+++ b/mDNSCore/DNSCommon.c
@@ -1369,12 +1369,20 @@
 	return(rr->namehash == q->qnamehash && SameDomainName(rr->name, &q->qname));
 	}
 
-// This is called only when the caller knows that it is a Unicast Resource Record and it is a Unicast Question
-// and hence we don't need InterfaceID checks like above. Though this may not be a big optimization, the main
-// reason we need this is that we can't compare DNSServers between the question and the resource record because
-// the resource record may not be completely initialized e.g., mDNSCoreReceiveResponse
-mDNSexport mDNSBool UnicastResourceRecordAnswersQuestion(const ResourceRecord *const rr, const DNSQuestion *const q)
+// This is called with both unicast resource record and multicast resource record. The question that
+// received the unicast response could be the regular unicast response from a DNS server or a response
+// to a mDNS QU query. The main reason we need this function is that we can't compare DNSServers between the
+// question and the resource record because the resource record is not completely initialized in
+// mDNSCoreReceiveResponse when this function is called.
+mDNSexport mDNSBool ResourceRecordAnswersUnicastResponse(const ResourceRecord *const rr, const DNSQuestion *const q)
 	{
+	// For resource records created using multicast, the InterfaceIDs have to match
+	if (rr->InterfaceID &&
+		q->InterfaceID && rr->InterfaceID != q->InterfaceID) return(mDNSfalse);
+
+	// If ResourceRecord received via multicast, but question was unicast, then shouldn't use record to answer this question.
+	if (rr->InterfaceID && !mDNSOpaque16IsZero(q->TargetQID)) return(mDNSfalse);
+
 	// RR type CNAME matches any query type. QTYPE ANY matches any RR type. QCLASS ANY matches any RR class.
 	if (!RRTypeAnswersQuestionType(rr,q->qtype)) return(mDNSfalse);
 
diff --git a/mDNSCore/DNSCommon.h b/mDNSCore/DNSCommon.h
index 08c636d..5df4ce4 100644
--- a/mDNSCore/DNSCommon.h
+++ b/mDNSCore/DNSCommon.h
@@ -164,7 +164,7 @@
 extern mDNSBool SameNameRecordAnswersQuestion(const ResourceRecord *const rr, const DNSQuestion *const q);
 extern mDNSBool ResourceRecordAnswersQuestion(const ResourceRecord *const rr, const DNSQuestion *const q);
 extern mDNSBool AnyTypeRecordAnswersQuestion (const ResourceRecord *const rr, const DNSQuestion *const q);
-extern mDNSBool UnicastResourceRecordAnswersQuestion(const ResourceRecord *const rr, const DNSQuestion *const q);
+extern mDNSBool ResourceRecordAnswersUnicastResponse(const ResourceRecord *const rr, const DNSQuestion *const q);
 extern mDNSBool LocalOnlyRecordAnswersQuestion(AuthRecord *const rr, const DNSQuestion *const q);
 extern mDNSu16 GetRDLength(const ResourceRecord *const rr, mDNSBool estimate);
 extern mDNSBool ValidateRData(const mDNSu16 rrtype, const mDNSu16 rdlength, const RData *const rd);
diff --git a/mDNSCore/mDNS.c b/mDNSCore/mDNS.c
index 005983c..ede13e9 100755
--- a/mDNSCore/mDNS.c
+++ b/mDNSCore/mDNS.c
@@ -349,7 +349,7 @@
 
 	if (addr->type == mDNSAddrType_IPv6)
 		{
-		if (mDNSv6AddressIsLinkLocal(&addr->ip.v4)) return(mDNStrue);
+		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) &&
@@ -1663,6 +1663,7 @@
 	AuthRecord *rr;
 	AuthRecord  *ResponseRecords = mDNSNULL;
 	AuthRecord **nrp             = &ResponseRecords;
+	NetworkInterfaceInfo *intf = FirstInterfaceForID(m, InterfaceID);
 
 	// Make a list of all our records that need to be unicast to this destination
 	for (rr = m->ResourceRecords; rr; rr=rr->next)
@@ -1674,6 +1675,7 @@
 			rr->ImmedUnicast = mDNSfalse;
 
 		if (rr->ImmedUnicast && rr->ImmedAnswer == InterfaceID)
+			{
 			if ((dest->type == mDNSAddrType_IPv4 && mDNSSameIPv4Address(rr->v4Requester, dest->ip.v4)) ||
 				(dest->type == mDNSAddrType_IPv6 && mDNSSameIPv6Address(rr->v6Requester, dest->ip.v6)))
 				{
@@ -1681,9 +1683,18 @@
 				rr->ImmedUnicast = mDNSfalse;
 				rr->v4Requester  = zerov4Addr;
 				rr->v6Requester  = zerov6Addr;
+
+				// Only sent records registered for P2P over P2P interfaces
+				if (intf && !mDNSPlatformValidRecordForInterface(rr, intf))
+					{
+					LogInfo("SendDelayedUnicastResponse: Not sending %s, on %s", ARDisplayString(m, rr), InterfaceNameForID(m, InterfaceID));
+					continue;
+					}
+
 				if (rr->NextResponse == mDNSNULL && nrp != &rr->NextResponse)	// rr->NR_AnswerTo
 					{ rr->NR_AnswerTo = (mDNSu8*)~0; *nrp = rr; nrp = &rr->NextResponse; }
 				}
+			}
 		}
 
 	AddAdditionalsToResponseList(m, ResponseRecords, &nrp, InterfaceID);
@@ -1730,7 +1741,7 @@
 			}
 
 		if (m->omsg.h.numAnswers)
-			mDNSSendDNSMessage(m, &m->omsg, responseptr, mDNSInterface_Any, mDNSNULL, dest, MulticastDNSPort, mDNSNULL, mDNSNULL);
+			mDNSSendDNSMessage(m, &m->omsg, responseptr, InterfaceID, mDNSNULL, dest, MulticastDNSPort, mDNSNULL, mDNSNULL);
 		}
 	}
 
@@ -2240,7 +2251,7 @@
 			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)
@@ -6278,6 +6289,8 @@
 	return(mDNSNULL);
 	}
 
+// This function is called when we receive a unicast response. This could be the case of a unicast response from the
+// DNS server or a response to the QU query. Hence, the cache record's InterfaceId can be both NULL or non-NULL (QU case)
 mDNSlocal DNSQuestion *ExpectingUnicastResponseForRecord(mDNS *const m,
 	const mDNSAddr *const srcaddr, const mDNSBool SrcLocal, const mDNSIPPort port, const mDNSOpaque16 id, const CacheRecord *const rr, mDNSBool tcp)
 	{
@@ -6285,12 +6298,9 @@
 	(void)id;
 	(void)srcaddr;
 
-	// Unicast records have zero as InterfaceID
-	if (rr->resrec.InterfaceID) return mDNSNULL;
-
 	for (q = m->Questions; q; q=q->next)
 		{
-		if (!q->DuplicateOf && UnicastResourceRecordAnswersQuestion(&rr->resrec, q))
+		if (!q->DuplicateOf && ResourceRecordAnswersUnicastResponse(&rr->resrec, q))
 			{
 			if (!mDNSOpaque16IsZero(q->TargetQID))
 				{
diff --git a/mDNSCore/uDNS.c b/mDNSCore/uDNS.c
index 513150b..47559a4 100755
--- a/mDNSCore/uDNS.c
+++ b/mDNSCore/uDNS.c
@@ -3156,7 +3156,7 @@
 
 	rr->updateError = err;
 #if APPLE_OSX_mDNSResponder
-	if (err == mStatus_BadSig) UpdateAutoTunnelDomainStatuses(m);
+	if (err == mStatus_BadSig || err == mStatus_BadKey) UpdateAutoTunnelDomainStatuses(m);
 #endif
 
 	SetRecordRetry(m, rr, random);
diff --git a/mDNSMacOSX/mDNSMacOSX.c b/mDNSMacOSX/mDNSMacOSX.c
index f782826..1ee1c1f 100644
--- a/mDNSMacOSX/mDNSMacOSX.c
+++ b/mDNSMacOSX/mDNSMacOSX.c
@@ -3170,7 +3170,7 @@
 			for (ptr = m->AuthInfoList; ptr; ptr = ptr->next)
 				if (SameDomainName(&ptr->domain, n))
 					{
-					if (ptr == info && r->updateError == mStatus_BadSig)
+					if (ptr == info && (r->updateError == mStatus_BadSig || r->updateError == mStatus_BadKey))
 						{
 						mDNS_snprintf(buffer, bufsz, "Resource record update failed for %##s", r->resrec.name);
 						return r->updateError;
@@ -7616,6 +7616,8 @@
 // "hash" function to solve this, the others are hard to solve. Hence, we share the hash (AuthHash) implementation
 // of the core layer which does all of the above very efficiently
 
+#define ETCHOSTS_BUFSIZE	1024	// Buffer size to parse a single line in /etc/hosts
+
 mDNSexport void FreeEtcHosts(mDNS *const m, AuthRecord *const rr, mStatus result)
     {
     (void)m;  // unused
@@ -7757,6 +7759,8 @@
 	*name = NULL;
 	for (i = start; i < length; i++)
 		{
+		if (buffer[i] == '#')
+			return -1;
 		if (buffer[i] != ' ' && buffer[i] != ',' && buffer[i] != '\t')
 			{
 			*name = &buffer[i];
@@ -7935,58 +7939,38 @@
 
 mDNSlocal void mDNSMacOSXParseEtcHosts(mDNS *const m, int fd, AuthHash *auth)
 	{
-	if (fd == -1) { LogInfo("mDNSMacOSXParseEtcHosts: fd is -1"); return; }
-	
-	LogInfo("mDNSMacOSXParseEtcHosts: Parsing etc hosts");
+	mDNSBool good;
+	char	buf[ETCHOSTS_BUFSIZE];
+	int len;
+	FILE *fp;
 
-	// Read through the file
-	char	readBuf[1024]; // support a maximum line of 1024 bytes including newline
-	off_t	offset = 0;
-	int	comment = 0;
-	ssize_t	i = 0;
-	ssize_t	length;
-	ssize_t	linestart;
-	while ((length = pread(fd, &readBuf[i], sizeof(readBuf) - i, offset) + i) >= i)
+	if (fd == -1) { LogInfo("mDNSMacOSXParseEtcHosts: fd is -1"); return; }
+
+	fp = fopen("/etc/hosts", "r");
+	if (!fp) { LogInfo("mDNSMacOSXParseEtcHosts: fp is NULL"); return; }
+
+	while (1)
 		{
-		if (length == i)
-			{
-			// end of file
-			if (length != 0) mDNSMacOSXParseEtcHostsLine(m, readBuf, length, auth);
-			break;
-			}
-		
-		// increment our offset by the number of bytes we read
-		offset += length - i;
-		
-		// loop through the buffer looking for end of lines
-		for (linestart = 0; i < length; i++)
-			{
-			if (readBuf[i] == '#' || readBuf[i] == '\r' || readBuf[i] == '\n')
-				{
-				int parseline = i - linestart > 0 && comment == 0;
-				comment = readBuf[i] == '#';
-				if (parseline)
-					{
-					readBuf[i] = 0;
-					mDNSMacOSXParseEtcHostsLine(m, &readBuf[linestart], i - linestart, auth);
-					}
-				linestart = i + 1;
-				}
-			}
-		
-		// prepare to read the next chunk of the file
-		if (linestart == 0)
-			{
-			// single line was larger than our buffer, we're going to ignore it
-			comment = 1; // treat remainder of line as comment
-			i = 0;
-			}
-		else
-			{
-			i = length - linestart;
-			if (i) memmove(readBuf, &readBuf[linestart], i);
-			}
+		good = (fgets(buf, ETCHOSTS_BUFSIZE, fp) != NULL);
+		if (!good) break;
+
+		// skip comment and empty lines
+		if (buf[0] == '#' || buf[0] == '\r' || buf[0] == '\n')
+			continue;
+
+		len = strlen(buf);
+		if (!len) break;	// sanity check
+
+		if (buf[len - 1] == '\r' || buf[len - 1] == '\n')
+			buf[len - 1] = '\0';
+
+		// fgets always null terminates and hence even if we have no
+		// newline at the end, it is null terminated. The callee expects
+		// the length to be such that buf[length] to be zero and hence
+		// we pass len - 1.
+		mDNSMacOSXParseEtcHostsLine(m, buf, len - 1, auth);
 		}
+	fclose(fp);
 	}
 
 mDNSlocal void mDNSMacOSXUpdateEtcHosts(mDNS *const m);
diff --git a/mDNSMacOSX/mDNSResponder.xcodeproj/project.pbxproj b/mDNSMacOSX/mDNSResponder.xcodeproj/project.pbxproj
index d03b50d..3362c8a 100644
--- a/mDNSMacOSX/mDNSResponder.xcodeproj/project.pbxproj
+++ b/mDNSMacOSX/mDNSResponder.xcodeproj/project.pbxproj
@@ -274,10 +274,10 @@
 			fileType = sourcecode.yacc;
 			isEditable = 1;
 			outputFiles = (
-				"$(DERIVED_FILE_DIR)/dnsextd_parser.h",
-				"$(DERIVED_FILE_DIR)/dnsextd_parser.c",
+				"$(DERIVED_FILE_DIR)/$(INPUT_FILE_BASE).h",
+				"$(DERIVED_FILE_DIR)/$(INPUT_FILE_BASE).c",
 			);
-			script = "/usr/bin/bison -o ${DERIVED_FILE_DIR}/${INPUT_FILE_BASE}.c -d ${INPUT_FILE_PATH}";
+			script = "echo NOOP yacc ${INPUT_FILE_PATH}";
 		};
 		D284BFB80ADD8E510027CCDF /* PBXBuildRule */ = {
 			isa = PBXBuildRule;
@@ -285,7 +285,7 @@
 			fileType = sourcecode.lex;
 			isEditable = 1;
 			outputFiles = (
-				"$(DERIVED_FILE_DIR)/dnsextd_lexer.c",
+				"$(DERIVED_FILE_DIR)/$(INPUT_FILE_BASE).c",
 			);
 			script = "/usr/bin/flex -i -o${DERIVED_FILE_DIR}/${INPUT_FILE_BASE}.c ${INPUT_FILE_PATH}";
 		};
@@ -1337,9 +1337,9 @@
 			buildConfigurationList = D284BED60ADD80A20027CCDF /* Build configuration list for PBXNativeTarget "dnsextd" */;
 			buildPhases = (
 				D284BEC20ADD80A20027CCDF /* Headers */,
+				4A4EE3A413CB8E82005C624B /* Build yacc file into derived source files */,
 				D284BEC40ADD80A20027CCDF /* Sources */,
 				D284BECE0ADD80A20027CCDF /* Frameworks */,
-				D284BED30ADD80A20027CCDF /* Rez */,
 				D284BED40ADD80A20027CCDF /* CopyFiles */,
 				FFFF8F770C32F0FD00722979 /* CopyFiles */,
 				FF37FAAD0BC581780044A5CF /* ShellScript */,
@@ -1561,13 +1561,6 @@
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
-		D284BED30ADD80A20027CCDF /* Rez */ = {
-			isa = PBXRezBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
 		D284BEE40ADD80A70027CCDF /* Rez */ = {
 			isa = PBXRezBuildPhase;
 			buildActionMask = 2147483647;
@@ -1637,6 +1630,23 @@
 			shellPath = /bin/sh;
 			shellScript = "#if we are building for simulator, change the installation path\nif [ \"${RC_ProjectName%_Sim}\" != \"${RC_ProjectName}\" ] ; then\n\tDSTROOT=${DSTROOT}${SDKROOT}\nfi\nmkdir -p \"$DSTROOT/usr/include/DNSServiceDiscovery\"\ncp $SRCROOT/DNSServiceDiscovery.h $DSTROOT/usr/include/DNSServiceDiscovery\nsed 's/\\(^#define _DNS_SD_LIBDISPATCH \\)0$/\\1 1/' \"$SRCROOT/../mDNSShared/dns_sd.h\" > \"$DSTROOT/usr/include/dns_sd.h\"";
 		};
+		4A4EE3A413CB8E82005C624B /* Build yacc file into derived source files */ = {
+			isa = PBXShellScriptBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			inputPaths = (
+				"$(SRCROOT)/../mDNSShared/dnsextd_parser.y",
+			);
+			name = "Build yacc file into derived source files";
+			outputPaths = (
+				"$(DERIVED_FILE_DIR)/dnsextd_parser.c",
+				"$(DERIVED_FILE_DIR)/dnsextd_parser.h",
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+			shellPath = /bin/sh;
+			shellScript = "/usr/bin/bison -o ${SCRIPT_OUTPUT_FILE_0} -d ${SCRIPT_INPUT_FILE_0}";
+		};
 		D284BE510ADD80740027CCDF /* ShellScript */ = {
 			isa = PBXShellScriptBuildPhase;
 			buildActionMask = 2147483647;
@@ -2421,9 +2431,6 @@
 					"${CONFIGURATION_TEMP_DIR}",
 				);
 				INSTALL_PATH = /usr/sbin;
-				LEX = /usr/bin/flex;
-				LEXFLAGS = "";
-				LEX_CASE_INSENSITIVE_SCANNER = YES;
 				LIBRARY_SEARCH_PATHS = "\"${CONFIGURATION_TEMP_DIR}\"";
 				MACOSX_DEPLOYMENT_TARGET = 10.5;
 				OTHER_CFLAGS = (
@@ -2432,11 +2439,8 @@
 				);
 				OTHER_LDFLAGS = "";
 				"OTHER_LDFLAGS[sdk=macosx10.7][arch=*]" = "-Wl,-pie";
-				OTHER_REZFLAGS = "";
 				PRODUCT_NAME = dnsextd;
-				REZ_EXECUTABLE = YES;
 				SECTORDER_FLAGS = "";
-				YACC = "/usr/bin/bison -y";
 			};
 			name = Development;
 		};
diff --git a/mDNSShared/dns_sd.h b/mDNSShared/dns_sd.h
index 3588d59..56c1d30 100644
--- a/mDNSShared/dns_sd.h
+++ b/mDNSShared/dns_sd.h
@@ -77,7 +77,7 @@
  */
 
 #ifndef _DNS_SD_H
-#define _DNS_SD_H 3200501
+#define _DNS_SD_H 3201000
 
 #ifdef  __cplusplus
     extern "C" {