diff options
author | Toomas Soome <tsoome@me.com> | 2017-11-24 14:37:01 +0200 |
---|---|---|
committer | Robert Mustacchi <rm@joyent.com> | 2019-01-10 22:31:41 +0000 |
commit | c65ebfc7045424bd04a6c7719a27b0ad3399ad54 (patch) | |
tree | 9ad2229fe7f2fd02d54cb8030330aa8d9b00e9a9 | |
parent | bc586359b7d9a851391f04b06254a9ead6109d47 (diff) | |
download | illumos-joyent-c65ebfc7045424bd04a6c7719a27b0ad3399ad54.tar.gz |
8886 mdns: update to mDNSResponder-878.1.1
Reviewed by: Gergő Mihály Doma <domag02@gmail.com>
Reviewed by: Andy Fiddaman <af@citrus-it.net>
Approved by: Robert Mustacchi <rm@joyent.com>
88 files changed, 4556 insertions, 7939 deletions
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 24028e7f42..9640cc9a2d 100644 --- a/usr/src/cmd/cmd-inet/usr.bin/dns-sd/Makefile +++ b/usr/src/cmd/cmd-inet/usr.bin/dns-sd/Makefile @@ -10,7 +10,7 @@ # # -# Copyright 2016 Toomas Soome <tsoome@me.com> +# Copyright 2017 Toomas Soome <tsoome@me.com> # # cmd/cmd-inet/usr.bin/dns-sd/Makefile @@ -23,7 +23,9 @@ include ../../Makefile.cmd-inet OBJS= ClientCommon.o dns-sd.o SRCS= ClientCommon.c dns-sd.c +SRCDIR= $(SRC)/contrib/mDNSResponder CFLAGS += $(CSTD_GNU99) +CPPFLAGS += -I$(SRCDIR)/mDNSShared CPPFLAGS += -DMDNS_VERSIONSTR_NODTS LDLIBS += -lsocket -ldns_sd @@ -42,6 +44,8 @@ install: all $(ROOTPROG) clean: $(RM) $(OBJS) -lint: lint_SRCS +%.o: $(SRCDIR)/Clients/%.c + $(COMPILE.c) -o $@ $< + $(POST_PROCESS_O) include ../../../Makefile.targ diff --git a/usr/src/cmd/cmd-inet/usr.lib/mdnsd/Makefile b/usr/src/cmd/cmd-inet/usr.lib/mdnsd/Makefile index e110c4ef48..0aa9db8da9 100644 --- a/usr/src/cmd/cmd-inet/usr.lib/mdnsd/Makefile +++ b/usr/src/cmd/cmd-inet/usr.lib/mdnsd/Makefile @@ -26,19 +26,13 @@ PROG= mdnsd MANIFEST= multicast.xml -CMN_DIR= $(SRC)/lib/libdns_sd/common -CMN_OBJS= dnssd_ipc.o -CMN_SRCS= $(CMN_OBJS:%.o=$(CMN_DIR)/%.c) +SRCDIR= $(SRC)/contrib/mDNSResponder -LOCAL_OBJS= DNSCommon.o DNSDigest.o GenLinkedList.o \ +OBJS= DNSCommon.o DNSDigest.o GenLinkedList.o \ PlatformCommon.o PosixDaemon.o \ mDNS.o mDNSDebug.o mDNSPosix.o mDNSUNP.o \ - uDNS.o uds_daemon.o CryptoAlg.o anonymous.o -LOCAL_SRCS= $(LOCAL_OBJS:%.o=%.c) - -SRCS= $(LOCAL_SRCS) $(CMN_SRCS) -OBJS= $(LOCAL_OBJS) $(CMN_OBJS) - + uDNS.o uds_daemon.o CryptoAlg.o anonymous.o dnssd_ipc.o +SRCS= $(OBJS:%.o=%.c) MDNSFLAGS= -DNOT_HAVE_SA_LEN \ -DLOG_PERROR=0 -DHAVE_SOLARIS -DTARGET_OS_SOLARIS \ @@ -49,14 +43,10 @@ MDNSFLAGS= -DNOT_HAVE_SA_LEN \ include ../../../Makefile.cmd -CERRWARN += -_gcc=-Wno-unused-variable -CERRWARN += -_gcc=-Wno-implicit-function-declaration -CERRWARN += -_gcc=-Wno-uninitialized - ROOTMANIFESTDIR= $(ROOTSVCNETWORKDNS) $(ROOTMANIFEST) := FILEMODE= 444 -.PARALLEL: $(LOCAL_OBJS) +.PARALLEL: $(OBJS) .WAIT: $(PROG) .KEEP_STATE: @@ -69,12 +59,22 @@ $(PROG): $(OBJS) include ../Makefile.lib CSTD = $(CSTD_GNU99) -CPPFLAGS += -D_REENTRANT $(MDNSFLAGS) -I$(CMN_DIR) +CPPFLAGS += -D_REENTRANT $(MDNSFLAGS) +CPPFLAGS += -I$(SRCDIR)/mDNSShared -I$(SRCDIR)/mDNSPosix +CPPFLAGS += -I$(SRCDIR)/mDNSCore LDLIBS += -lsocket -lnsl install: all $(ROOTLIBINETPROG) $(ROOTMANIFEST) -%.o: $(CMN_DIR)/%.c +%.o: $(SRCDIR)/mDNSCore/%.c + $(COMPILE.c) $(OUTPUT_OPTION) $< + $(POST_PROCESS_O) + +%.o: $(SRCDIR)/mDNSShared/%.c + $(COMPILE.c) $(OUTPUT_OPTION) $< + $(POST_PROCESS_O) + +%.o: $(SRCDIR)/mDNSPosix/%.c $(COMPILE.c) $(OUTPUT_OPTION) $< $(POST_PROCESS_O) @@ -83,6 +83,4 @@ check: $(CHKMANIFEST) clean: $(RM) $(OBJS) -lint: lint_SRCS - include ../../../Makefile.targ diff --git a/usr/src/cmd/cmd-inet/usr.lib/mdnsd/THIRDPARTYLICENSE.descrip b/usr/src/cmd/cmd-inet/usr.lib/mdnsd/THIRDPARTYLICENSE.descrip deleted file mode 100644 index beda9598bf..0000000000 --- a/usr/src/cmd/cmd-inet/usr.lib/mdnsd/THIRDPARTYLICENSE.descrip +++ /dev/null @@ -1 +0,0 @@ -MDNS DAEMON 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 deleted file mode 100644 index 6cc9197d63..0000000000 --- a/usr/src/cmd/cmd-inet/usr.lib/mdnsd/uds_daemon.h +++ /dev/null @@ -1,85 +0,0 @@ -/* -*- Mode: C; tab-width: 4 -*- - * - * 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "mDNSEmbeddedAPI.h" -#include "dnssd_ipc.h" - -/* Client interface: */ - -#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 -extern void udsserver_handle_configchange(mDNS *const m); -extern int udsserver_exit(void); // should be called prior to app exit -extern void LogMcastStateInfo(mDNS *const m, mDNSBool mflag, mDNSBool start, mDNSBool mstatelog); -#define LogMcastQ (mDNS_McastLoggingEnabled == 0) ? ((void)0) : LogMcastQuestion -#define LogMcastS (mDNS_McastLoggingEnabled == 0) ? ((void)0) : LogMcastService -#define LogMcast (mDNS_McastLoggingEnabled == 0) ? ((void)0) : LogMsg -#define LogMcastNoIdent (mDNS_McastLoggingEnabled == 0) ? ((void)0) : LogMsgNoIdent - -/* Routines that uds_daemon expects to link against: */ - -typedef void (*udsEventCallback)(int fd, short filter, void *context); -extern mStatus udsSupportAddFDToEventLoop(dnssd_sock_t fd, udsEventCallback callback, void *context, void **platform_data); -extern int udsSupportReadFD(dnssd_sock_t fd, char* buf, int len, int flags, void *platform_data); -extern mStatus udsSupportRemoveFDFromEventLoop(dnssd_sock_t fd, void *platform_data); // Note: This also CLOSES the file descriptor as well - -extern void RecordUpdatedNiceLabel(mDNS *const m, mDNSs32 delay); - -// Globals and functions defined in uds_daemon.c and also shared with the old "daemon.c" on OS X - -extern mDNS mDNSStorage; -extern DNameListElem *AutoRegistrationDomains; -extern DNameListElem *AutoBrowseDomains; - -extern mDNSs32 ChopSubTypes(char *regtype, char **AnonData); -extern AuthRecord *AllocateSubTypes(mDNSs32 NumSubTypes, char *p, char **AnonData); -extern int CountExistingRegistrations(domainname *srv, mDNSIPPort port); -extern void FreeExtraRR(mDNS *const m, AuthRecord *const rr, mStatus result); -extern int CountPeerRegistrations(mDNS *const m, ServiceRecordSet *const srs); - -#if APPLE_OSX_mDNSResponder - -extern void machserver_automatic_browse_domain_changed(const domainname *d, mDNSBool add); -extern void machserver_automatic_registration_domain_changed(const domainname *d, mDNSBool add); -// D2D interface support -extern void external_start_browsing_for_service(mDNSInterfaceID InterfaceID, const domainname *const type, DNS_TypeValues qtype, DNSServiceFlags flags); -extern void external_stop_browsing_for_service(mDNSInterfaceID InterfaceID, const domainname *const type, DNS_TypeValues qtype, DNSServiceFlags flags); -extern void external_start_advertising_service(const ResourceRecord *const resourceRecord, DNSServiceFlags flags); -extern void external_stop_advertising_service(const ResourceRecord *const resourceRecord, DNSServiceFlags flags); -extern void external_start_resolving_service(mDNSInterfaceID InterfaceID, const domainname *const fqdn, DNSServiceFlags flags); -extern void external_stop_resolving_service(mDNSInterfaceID InterfaceID, const domainname *const fqdn, DNSServiceFlags flags); -extern void external_connection_release(const domainname *instance); - -#else // APPLE_OSX_mDNSResponder - -#define external_start_browsing_for_service(A,B,C,D) (void)(A) -#define external_stop_browsing_for_service(A,B,C,D) (void)(A) -#define external_start_advertising_service(A,B) (void)(A) -#define external_stop_advertising_service(A,B) (void)(A) -#define external_start_resolving_service(A,B,C) (void)(A) -#define external_stop_resolving_service(A,B,C) (void)(A) -#define external_connection_release(A) (void)(A) - -#endif // APPLE_OSX_mDNSResponder - -extern const char mDNSResponderVersionString_SCCS[]; -#define mDNSResponderVersionString (mDNSResponderVersionString_SCCS+5) diff --git a/usr/src/cmd/cmd-inet/usr.bin/dns-sd/ClientCommon.c b/usr/src/contrib/mDNSResponder/Clients/ClientCommon.c index cb59e7b9b8..f96319cea7 100644 --- a/usr/src/cmd/cmd-inet/usr.bin/dns-sd/ClientCommon.c +++ b/usr/src/contrib/mDNSResponder/Clients/ClientCommon.c @@ -49,8 +49,9 @@ const char *GetNextLabel(const char *cstr, char label[64]) while (*cstr && *cstr != '.') // While we have characters in the label... { char c = *cstr++; - if (c == '\\' && *cstr) // If we have a backslash, and it's not the last character of the string + if (c == '\\') // If escape character, check next character { + if (*cstr == '\0') break; // If this is the end of the string, then break c = *cstr++; if (isdigit(cstr[-1]) && isdigit(cstr[0]) && isdigit(cstr[1])) { diff --git a/usr/src/cmd/cmd-inet/usr.bin/dns-sd/ClientCommon.h b/usr/src/contrib/mDNSResponder/Clients/ClientCommon.h index afe5b7a501..afe5b7a501 100644 --- a/usr/src/cmd/cmd-inet/usr.bin/dns-sd/ClientCommon.h +++ b/usr/src/contrib/mDNSResponder/Clients/ClientCommon.h diff --git a/usr/src/cmd/cmd-inet/usr.bin/dns-sd/dns-sd.c b/usr/src/contrib/mDNSResponder/Clients/dns-sd.c index 53619446f7..5ae5c48380 100644 --- a/usr/src/cmd/cmd-inet/usr.bin/dns-sd/dns-sd.c +++ b/usr/src/contrib/mDNSResponder/Clients/dns-sd.c @@ -165,6 +165,7 @@ static const char kFilePathSep = '/'; #undef _DNS_SD_LIBDISPATCH #endif #include "dns_sd.h" +#include "dns_sd_internal.h" #include "ClientCommon.h" #if TEST_NEW_CLIENTSTUB @@ -320,18 +321,70 @@ static char *DNSTypeName(unsigned short rr_type) { switch (rr_type) { - case kDNSServiceType_A: return("Addr"); - case kDNSServiceType_NS: return("NS"); - case kDNSServiceType_MX: return("MX"); - case kDNSServiceType_CNAME: return("CNAME"); - case kDNSServiceType_SOA: return("SOA"); - case kDNSServiceType_PTR: return("PTR"); - case kDNSServiceType_AAAA: return("AAAA"); - case kDNSServiceType_NSEC: return("NSEC"); - case kDNSServiceType_TSIG: return("TSIG"); - case kDNSServiceType_RRSIG: return("RRSIG"); - case kDNSServiceType_DNSKEY: return("DNSKEY"); - case kDNSServiceType_DS: return("DS"); + case kDNSServiceType_A: return("Addr"); + case kDNSServiceType_NS: return("NS"); + case kDNSServiceType_MD: return("MD"); + case kDNSServiceType_MF: return("MF"); + case kDNSServiceType_CNAME: return("CNAME"); + case kDNSServiceType_SOA: return("SOA"); + case kDNSServiceType_MB: return("MB"); + case kDNSServiceType_MG: return("MG"); + case kDNSServiceType_MR: return("MR"); + case kDNSServiceType_NULL: return("NULL"); + case kDNSServiceType_WKS: return("WKS"); + case kDNSServiceType_PTR: return("PTR"); + case kDNSServiceType_HINFO: return("HINFO"); + case kDNSServiceType_MINFO: return("MINFO"); + case kDNSServiceType_MX: return("MX"); + case kDNSServiceType_TXT: return("TXT"); + case kDNSServiceType_RP: return("RP"); + case kDNSServiceType_AFSDB: return("AFSDB"); + case kDNSServiceType_X25: return("X25"); + case kDNSServiceType_ISDN: return("ISDN"); + case kDNSServiceType_RT: return("RT"); + case kDNSServiceType_NSAP: return("NSAP"); + case kDNSServiceType_NSAP_PTR: return("NSAP_PTR"); + case kDNSServiceType_SIG: return("SIG"); + case kDNSServiceType_KEY: return("KEY"); + case kDNSServiceType_PX: return("PX"); + case kDNSServiceType_GPOS: return("GPOS"); + case kDNSServiceType_AAAA: return("AAAA"); + case kDNSServiceType_LOC: return("LOC"); + case kDNSServiceType_NXT: return("NXT"); + case kDNSServiceType_EID: return("EID"); + case kDNSServiceType_NIMLOC: return("NIMLOC"); + case kDNSServiceType_SRV: return("SRV"); + case kDNSServiceType_ATMA: return("ATMA"); + case kDNSServiceType_NAPTR: return("NAPTR"); + case kDNSServiceType_KX: return("KX"); + case kDNSServiceType_CERT: return("CERT"); + case kDNSServiceType_A6: return("A6"); + case kDNSServiceType_DNAME: return("DNAME"); + case kDNSServiceType_SINK: return("SINK"); + case kDNSServiceType_OPT: return("OPT"); + case kDNSServiceType_APL: return("APL"); + case kDNSServiceType_DS: return("DS"); + case kDNSServiceType_SSHFP: return("SSHFP"); + case kDNSServiceType_IPSECKEY: return("IPSECKEY"); + case kDNSServiceType_RRSIG: return("RRSIG"); + case kDNSServiceType_NSEC: return("NSEC"); + case kDNSServiceType_DNSKEY: return("DNSKEY"); + case kDNSServiceType_DHCID: return("DHCID"); + case kDNSServiceType_NSEC3: return("NSEC3"); + case kDNSServiceType_NSEC3PARAM: return("NSEC3PARAM"); + case kDNSServiceType_HIP: return("HIP"); + case kDNSServiceType_SPF: return("SPF"); + case kDNSServiceType_UINFO: return("UINFO"); + case kDNSServiceType_UID: return("UID"); + case kDNSServiceType_GID: return("GID"); + case kDNSServiceType_UNSPEC: return("UNSPEC"); + case kDNSServiceType_TKEY: return("TKEY"); + case kDNSServiceType_TSIG: return("TSIG"); + case kDNSServiceType_IXFR: return("IXFR"); + case kDNSServiceType_AXFR: return("AXFR"); + case kDNSServiceType_MAILB: return("MAILB"); + case kDNSServiceType_MAILA: return("MAILA"); + case kDNSServiceType_ANY: return("ANY"); default: { static char buffer[RR_TYPE_SIZE]; @@ -422,7 +475,9 @@ static DNSServiceProtocol GetProtocol(const char *s) //************************************************************************************************************* // Sample callback functions for each of the operation types -static void printtimestamp(void) +#define printtimestamp() printtimestamp_F(stdout) + +static void printtimestamp_F(FILE *outstream) { struct tm tm; int ms; @@ -443,10 +498,10 @@ static void printtimestamp(void) strftime(new_date, sizeof(new_date), "%a %d %b %Y", &tm); if (strncmp(date, new_date, sizeof(new_date))) { - printf("DATE: ---%s---\n", new_date); //display date only if it has changed + fprintf(outstream, "DATE: ---%s---\n", new_date); //display date only if it has changed strncpy(date, new_date, sizeof(date)); } - printf("%2d:%02d:%02d.%03d ", tm.tm_hour, tm.tm_min, tm.tm_sec, ms); + fprintf(outstream, "%2d:%02d:%02d.%03d ", tm.tm_hour, tm.tm_min, tm.tm_sec, ms); } // formating time to RFC 4034 format @@ -467,41 +522,50 @@ static void FormatTime(unsigned long te, unsigned char *buf, int bufsize) static void print_usage(const char *arg0, int print_all) { + // Print the commonly used command line options. These are listed in "the order they have been in historically". fprintf(stderr, "%s -E (Enumerate recommended registration domains)\n", arg0); fprintf(stderr, "%s -F (Enumerate recommended browsing domains)\n", arg0); fprintf(stderr, "%s -R <Name> <Type> <Domain> <Port> [<TXT>...] (Register a service)\n", arg0); - fprintf(stderr, "%s -B <Type> <Domain> (Browse for services instances)\n", arg0); - fprintf(stderr, "%s -L <Name> <Type> <Domain> (Look up a service instance)\n", arg0); - fprintf(stderr, "%s -P <Name> <Type> <Domain> <Port> <Host> <IP> [<TXT>...] (Proxy)\n", arg0); - 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 -B <Type> <Domain> (Browse for service instances)\n", arg0); + fprintf(stderr, "%s -L <Name> <Type> <Domain> (Resolve a service instance)\n", arg0); + fprintf(stderr, "%s -Q <name> <rrtype> <rrclass> (Generic query for any record type)\n", arg0); fprintf(stderr, "%s -Z <Type> <Domain> (Output results in Zone File format)\n", arg0); 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); + fprintf(stderr, "%s -H (Print usage for complete command list)\n", arg0); 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 + if (print_all) // Print all available options for dns-sd tool. Keep these in alphabetical order for easier maintenance. { - fprintf(stderr, "%s -C <FQDN> <rrtype> <rrclass> (Query; reconfirming each result)\n", arg0); - fprintf(stderr, "%s -X udp/tcp/udptcp <IntPort> <ExtPort> <TTL> (NAT Port Mapping)\n", arg0); + fprintf(stderr, "\n"); 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 -C <FQDN> <rrtype> <rrclass> (Query; reconfirming each result)\n", arg0); + fprintf(stderr, "%s -D <name> <rrtype> <rrclass>(Validate query for any record type with DNSSEC)\n", arg0); + fprintf(stderr, "%s -I (Test registering and then immediately updating TXT record)\n", arg0); fprintf(stderr, "%s -N (Test adding a large NULL record)\n", arg0); - fprintf(stderr, "%s -T (Test creating a large TXT record)\n", arg0); fprintf(stderr, "%s -M (Test creating a registration with multiple TXT records)\n", arg0); - fprintf(stderr, "%s -I (Test registering and then immediately updating TXT record)\n", arg0); + fprintf(stderr, "%s -P <Name> <Type> <Domain> <Port> <Host> <IP> [<TXT>...] (Proxy)\n", arg0); fprintf(stderr, "%s -S (Test multiple operations on a shared socket)\n", arg0); + fprintf(stderr, "%s -T (Test creating a large TXT record)\n", arg0); + fprintf(stderr, "%s -U (Test updating a TXT record)\n", arg0); + fprintf(stderr, "%s -X udp/tcp/udptcp <IntPort> <ExtPort> <TTL> (NAT Port Mapping)\n", arg0); + fprintf(stderr, "%s -ble (Use kDNSServiceInterfaceIndexBLE)\n", arg0); + fprintf(stderr, "%s -g v4/v6/v4v6 <name> (Validate address info for hostname with DNSSEC)\n", arg0); fprintf(stderr, "%s -i <Interface> (Run dns-sd cmd on a specific interface (en0/en1)\n", arg0); - fprintf(stderr, "%s -lo (Run dns-sd cmd using local only interface)\n", arg0); - fprintf(stderr, "%s -p2p (Use kDNSServiceInterfaceIndexP2P)\n", arg0); fprintf(stderr, "%s -includep2p (Set kDNSServiceFlagsIncludeP2P flag)\n", arg0); fprintf(stderr, "%s -includeAWDL (Set kDNSServiceFlagsIncludeAWDL flag)\n", arg0); + fprintf(stderr, "%s -intermediates (Set kDNSServiceFlagsReturnIntermediates flag)\n", arg0); + fprintf(stderr, "%s -ku (Set kDNSServiceFlagsKnownUnique flag)\n", arg0); + fprintf(stderr, "%s -lo (Run dns-sd cmd using local only interface)\n", arg0); fprintf(stderr, "%s -optional (Set kDNSServiceFlagsValidateOptional flag)\n", arg0); + fprintf(stderr, "%s -p2p (Use kDNSServiceInterfaceIndexP2P)\n", arg0); + fprintf(stderr, "%s -q <name> <rrtype> <rrclass> (Equivalent to -Q with kDNSServiceFlagsSuppressUnusable set)\n", arg0); fprintf(stderr, "%s -tc (Set kDNSServiceFlagsBackgroundTrafficClass flag)\n", arg0); - fprintf(stderr, "%s -unicastResponse (Set kDNSServiceFlagsUnicastResponse flag)\n", arg0); + fprintf(stderr, "%s -test (Run basic API input range tests)\n", arg0); fprintf(stderr, "%s -t1 (Set kDNSServiceFlagsThresholdOne flag)\n", arg0); fprintf(stderr, "%s -tFinder (Set kDNSServiceFlagsThresholdFinder flag)\n", arg0); fprintf(stderr, "%s -timeout (Set kDNSServiceFlagsTimeout flag)\n", arg0); + fprintf(stderr, "%s -unicastResponse (Set kDNSServiceFlagsUnicastResponse flag)\n", arg0); + fprintf(stderr, "%s -autoTrigger (Set kDNSServiceFlagsAutoTrigger flag)\n", arg0); } } @@ -731,17 +795,20 @@ static void DNSSD_API resolve_reply(DNSServiceRef sdref, const DNSServiceFlags f (void)context; // Unused EXIT_IF_LIBDISPATCH_FATAL_ERROR(errorCode); - if (errorCode) - printf("Error code %d\n", errorCode); - else - { - printtimestamp(); - printf("%s can be reached at %s:%u (interface %d)", fullname, hosttarget, PortAsNumber, ifIndex); - if (flags) printf(" Flags: %X", flags); - // Don't show degenerate TXT records containing nothing but a single empty string - if (txtLen > 1) { printf("\n"); ShowTXTRecord(txtLen, txtRecord); } - printf("\n"); - } + printtimestamp(); + + printf("%s ", fullname); + + if (errorCode == kDNSServiceErr_NoSuchRecord) printf("No Such Record"); + else if (errorCode) printf("error code %d\n", errorCode); + else printf("can be reached at %s:%u (interface %d)", hosttarget, PortAsNumber, ifIndex); + + if (flags) printf(" Flags: %X", flags); + + // Don't show degenerate TXT records containing nothing but a single empty string + if (!errorCode && txtLen > 1) { printf("\n"); ShowTXTRecord(txtLen, txtRecord); } + + printf("\n"); if (!(flags & kDNSServiceFlagsMoreComing)) fflush(stdout); } @@ -776,6 +843,7 @@ static void myTimerCallBack(void) { if (updatetest[1] != 'Z') updatetest[1]++; else updatetest[1] = 'A'; + // The following line toggles the string length between 1 and 2 characters. updatetest[0] = 3 - updatetest[0]; updatetest[2] = updatetest[1]; printtimestamp(); @@ -1249,7 +1317,7 @@ static void HandleEvents(void) DNSServiceErrorType err = kDNSServiceErr_NoError; if (client && FD_ISSET(dns_sd_fd, &readfds)) err = DNSServiceProcessResult(client ); else if (client_pa && FD_ISSET(dns_sd_fd2, &readfds)) err = DNSServiceProcessResult(client_pa); - if (err) { fprintf(stderr, "DNSServiceProcessResult returned %d\n", err); stopNow = 1; } + if (err) { printtimestamp_F(stderr); fprintf(stderr, "DNSServiceProcessResult returned %d\n", err); stopNow = 1; } } else if (result == 0) myTimerCallBack(); @@ -1306,18 +1374,6 @@ static void DNSSD_API MyRegisterRecordCallback(DNSServiceRef service, DNSRecordR default: printf("Error %d\n", errorCode); break; } if (!(flags & kDNSServiceFlagsMoreComing)) fflush(stdout); - // DNSServiceRemoveRecord(service, rec, 0); to test record removal - -#if 0 // To test updating of individual records registered via DNSServiceRegisterRecord - if (!errorCode) - { - int x = 0x11111111; - printf("Updating\n"); - DNSServiceUpdateRecord(service, rec, 0, sizeof(x), &x, 0); - } -#endif - - if (!(flags & kDNSServiceFlagsMoreComing)) fflush(stdout); } static void getip(const char *const name, struct sockaddr_storage *result) @@ -1403,131 +1459,583 @@ static char *gettype(char *buffer, char *typ) return(typ); } -int main(int argc, char **argv) +// Do some basic tests to verify API handles > 63 byte strings gracefully with +// a returned error code. + +#define STRING_64_BYTES "_123456789012345678901234567890123456789012345678901234567890123" + +static int API_string_limit_test() { - DNSServiceErrorType err; - char buffer[TypeBufferSize], *typ, *dom; - int opi; - DNSServiceFlags flags = 0; - int optional = 0; + const char * regtype; + DNSServiceRef sdRef = NULL; + const char * longHost = STRING_64_BYTES ".local"; + const char * longDomain = "hostname." STRING_64_BYTES; - // Extract the program name from argv[0], which by convention contains the path to this executable. - // Note that this is just a voluntary convention, not enforced by the kernel -- - // the process calling exec() can pass bogus data in argv[0] if it chooses to. - const char *a0 = strrchr(argv[0], kFilePathSep) + 1; - if (a0 == (const char *)1) a0 = argv[0]; + printf("Testing for error returns when various strings are > 63 bytes.\n"); -#if defined(_WIN32) - HeapSetInformation(NULL, HeapEnableTerminationOnCorruption, NULL, 0); -#endif + printf("DNSServiceGetAddrInfo(), hostname = %s\n", longHost); + if (DNSServiceGetAddrInfo(&sdRef, 0, 0, 0, longHost, addrinfo_reply, 0) == 0) + { + printf("DNSServiceGetAddrInfo(): expected error return\n"); + return 1; + }; -#if TEST_NEW_CLIENTSTUB - printf("Using embedded copy of dnssd_clientstub instead of system library\n"); - if (sizeof(argv) == 8) printf("Running in 64-bit mode\n"); + printf("DNSServiceGetAddrInfo(), hostname = %s\n", longDomain); + if (DNSServiceGetAddrInfo(&sdRef, 0, 0, 0, longDomain, addrinfo_reply, 0) == 0) + { + printf("DNSServiceGetAddrInfo(): expected error return\n"); + return 1; + }; + + printf("DNSServiceResolve(), name = %s\n", STRING_64_BYTES); + if (DNSServiceResolve(&sdRef, 0, 0, STRING_64_BYTES, "_test._tcp", "local", resolve_reply, NULL) == 0) + { + printf("DNSServiceResolve(): expected error return\n"); + return 1; + }; + + regtype = STRING_64_BYTES "._tcp"; + printf("DNSServiceResolve(), regtype = %s\n", regtype); + if (DNSServiceResolve(&sdRef, 0, 0, "instanceName", regtype, "local", resolve_reply, NULL) == 0) + { + printf("DNSServiceResolve(): expected error return\n"); + return 1; + }; + + printf("DNSServiceResolve(), domain = %s\n", STRING_64_BYTES); + if (DNSServiceResolve(&sdRef, 0, 0, "instanceName", "_test._tcp", STRING_64_BYTES, resolve_reply, NULL) == 0) + { + printf("DNSServiceResolve(): expected error return\n"); + return 1; + }; + + printf("Testing for error returns when various strings are > 63 bytes: PASSED\n"); + return 0; +} + +// local prototypes for routines that don't have prototypes in dns_sd.h +#if APPLE_OSX_mDNSResponder +DNSServiceErrorType DNSSD_API DNSServiceSetDefaultDomainForUser(DNSServiceFlags flags, const char *domain); +DNSServiceErrorType DNSSD_API DNSServiceCreateDelegateConnection(DNSServiceRef *sdRef, int32_t pid, uuid_t uuid); #endif - // Test code for TXTRecord functions - //TXTRecordRef txtRecord; - //TXTRecordCreate(&txtRecord, 0, NULL); - //TXTRecordSetValue(&txtRecord, "aaa", 1, "b"); - //printf("%d\n", TXTRecordContainsKey(TXTRecordGetLength(&txtRecord), TXTRecordGetBytesPtr(&txtRecord), "Aaa")); +static int API_NULL_input_test() +{ + printf("Running basic API input range tests with various pointer parameters set to NULL:\n"); + + // Test that API's handle NULL pointers by returning an error when appropriate. + + // DNSServiceRefSockFD() + if (DNSServiceRefSockFD(0) != -1) + { + printf("DNSServiceRefSockFD(): expected dnssd_InvalidSocket return\n"); + return 1; + } - if (argc > 1 && !strcmp(argv[1], "-lo")) + // DNSServiceProcessResult() + if (DNSServiceProcessResult(0) == 0) { - argc--; - argv++; - opinterface = kDNSServiceInterfaceIndexLocalOnly; - printf("Using LocalOnly\n"); + printf("DNSServiceProcessResult(): expected error return\n"); + return 1; } - if (argc > 1 && (!strcmp(argv[1], "-p2p") || !strcmp(argv[1], "-P2P"))) + // DNSServiceRefDeallocate(): no return value, just verify it doesn't crash + DNSServiceRefDeallocate(0); + + // DNSServiceGetProperty() { - argc--; - argv++; - opinterface = kDNSServiceInterfaceIndexP2P; + uint32_t result; + uint32_t size; + + if ( (DNSServiceGetProperty( 0, &result, &size) == 0) + || (DNSServiceGetProperty(kDNSServiceProperty_DaemonVersion, 0, &size) == 0) + || (DNSServiceGetProperty(kDNSServiceProperty_DaemonVersion, &result, 0) == 0) + ) + { + printf("DNSServiceGetProperty(): expected error return\n"); + return 1; + } } - if (argc > 1 && !strcasecmp(argv[1], "-includep2p")) + // DNSServiceResolve() { - argc--; - argv++; - flags |= kDNSServiceFlagsIncludeP2P; - printf("Setting kDNSServiceFlagsIncludeP2P\n"); + DNSServiceRef sdRef; + DNSServiceFlags flags = 0; + uint32_t interfaceIndex = 0; + const char *name = "name"; + const char *regtype = "_test._tcp"; + const char *domain = "local"; + DNSServiceResolveReply callBack = 0; + void *context = 0; // can be a NULL pointer + + if ( (DNSServiceResolve( 0, flags, interfaceIndex, name, regtype, domain, callBack, context) == 0) + || (DNSServiceResolve(&sdRef, flags, interfaceIndex, 0, regtype, domain, callBack, context) == 0) + || (DNSServiceResolve(&sdRef, flags, interfaceIndex, name, 0, domain, callBack, context) == 0) + || (DNSServiceResolve(&sdRef, flags, interfaceIndex, name, regtype, 0, callBack, context) == 0) + || (DNSServiceResolve(&sdRef, flags, interfaceIndex, name, regtype, domain, callBack, context) == 0) + ) + { + printf("DNSServiceResolve(): expected error return\n"); + return 1; + } } - if (argc > 1 && !strcasecmp(argv[1], "-includeAWDL")) + // DNSServiceQueryRecord() { - argc--; - argv++; - flags |= kDNSServiceFlagsIncludeAWDL; - printf("Setting kDNSServiceFlagsIncludeAWDL\n"); + DNSServiceRef sdRef; + DNSServiceFlags flags = 0; + uint32_t interfaceIndex = 0; + const char *fullname = "fullname"; + uint16_t rrtype = 0; + uint16_t rrclass = 0; + DNSServiceQueryRecordReply callBack = 0; + void *context = 0; /* may be NULL */ + + if ( (DNSServiceQueryRecord( 0, flags, interfaceIndex, fullname, rrtype, rrclass, callBack, context) == 0) + || (DNSServiceQueryRecord(&sdRef, flags, interfaceIndex, 0, rrtype, rrclass, callBack, context) == 0) + || (DNSServiceQueryRecord(&sdRef, flags, interfaceIndex, fullname, rrtype, rrclass, 0, context) == 0) + ) + { + printf("DNSServiceQueryRecord(): expected error return\n"); + return 1; + } } - if (argc > 1 && !strcasecmp(argv[1], "-tc")) + // DNSServiceGetAddrInfo() { - argc--; - argv++; - flags |= kDNSServiceFlagsBackgroundTrafficClass; - printf("Setting kDNSServiceFlagsBackgroundTrafficClass\n"); + DNSServiceRef sdRef; + DNSServiceFlags flags = 0; + uint32_t interfaceIndex = 0; + DNSServiceProtocol protocol = kDNSServiceProtocol_IPv4|kDNSServiceProtocol_IPv6; + const char *hostname = "host.local"; + DNSServiceGetAddrInfoReply callBack = 0; + void *context = 0; // may be NULL + + if ( (DNSServiceGetAddrInfo( 0, flags, interfaceIndex, protocol, hostname, callBack, context) == 0) + || (DNSServiceGetAddrInfo(&sdRef, flags, interfaceIndex, protocol, 0, callBack, context) == 0) + || (DNSServiceGetAddrInfo(&sdRef, flags, interfaceIndex, protocol, hostname, 0, context) == 0) + ) + { + printf("DNSServiceGetAddrInfo(): expected error return\n"); + return 1; + } } - if (argc > 1 && !strcasecmp(argv[1], "-t1")) + // DNSServiceBrowse() { - argc--; - argv++; - flags |= kDNSServiceFlagsThresholdOne; - printf("Setting kDNSServiceFlagsThresholdOne\n"); + DNSServiceRef sdRef; + DNSServiceFlags flags = 0; + uint32_t interfaceIndex = 0; + const char *regtype = "_test._tcp"; + const char *domain = 0; /* may be NULL */ + DNSServiceBrowseReply callBack = 0; + void *context = 0; /* may be NULL */ + + if ( (DNSServiceBrowse( 0, flags, interfaceIndex, regtype, domain, callBack, context) == 0) + || (DNSServiceBrowse(&sdRef, flags, interfaceIndex, 0, domain, callBack, context) == 0) + || (DNSServiceBrowse(&sdRef, flags, interfaceIndex, regtype, domain, 0, context) == 0) + ) + { + printf("DNSServiceBrowse(): expected error return\n"); + return 1; + } } - if (argc > 1 && !strcasecmp(argv[1], "-tFinder")) +#if APPLE_OSX_mDNSResponder + // DNSServiceSetDefaultDomainForUser() + if (DNSServiceSetDefaultDomainForUser(0, 0) == 0) + { + printf("DNSServiceSetDefaultDomainForUser(): expected error return\n"); + return 1; + } +#endif + + // DNSServiceRegister() { - argc--; - argv++; - flags |= kDNSServiceFlagsThresholdFinder; - printf("Setting kDNSServiceFlagsThresholdFinder\n"); + DNSServiceRef sdRef; + DNSServiceFlags flags = 0; + uint32_t interfaceIndex = 0; + const char *name = 0; /* may be NULL */ + const char *regtype = "_test._tcp"; + const char *domain = 0; /* may be NULL */ + const char *host = 0; /* may be NULL */ + uint16_t port = 0x2211; /* In network byte order */ + uint16_t txtLen = 1; + const void *txtRecord = "\0"; /* may be NULL */ + DNSServiceRegisterReply callBack = 0; /* may be NULL */ + void *context = 0; /* may be NULL */ + + if ( (DNSServiceRegister( 0, flags, interfaceIndex, name, regtype, domain, host, port, txtLen, txtRecord, callBack, context) == 0) + || (DNSServiceRegister(&sdRef, flags, interfaceIndex, name, 0, domain, host, port, txtLen, txtRecord, callBack, context) == 0) + ) + { + printf("DNSServiceRegister(): expected error return\n"); + return 1; + } } - if (argc > 1 && !strcasecmp(argv[1], "-wo")) + // DNSServiceEnumerateDomains() { - argc--; - argv++; - flags |= kDNSServiceFlagsWakeOnlyService; - printf("Setting kDNSServiceFlagsWakeOnlyService\n"); + DNSServiceRef sdRef; + DNSServiceFlags flags = 0; + uint32_t interfaceIndex = 0; + DNSServiceDomainEnumReply callBack = 0; + void *context = 0; /* may be NULL */ + + if ( (DNSServiceEnumerateDomains( 0, flags, interfaceIndex, callBack, context) == 0) + || (DNSServiceEnumerateDomains(&sdRef, flags, interfaceIndex, 0, context) == 0) + ) + { + printf("DNSServiceEnumerateDomains(): expected error return\n"); + return 1; + } } - if (argc > 1 && !strcasecmp(argv[1], "-unicastResponse")) + // DNSServiceCreateConnection() + if (DNSServiceCreateConnection(0) == 0) { - argc--; - argv++; - flags |= kDNSServiceFlagsUnicastResponse; - printf("Setting kDNSServiceFlagsUnicastResponse\n"); + printf("DNSServiceCreateConnection(): expected error return\n"); + return 1; } - if (argc > 1 && !strcasecmp(argv[1], "-timeout")) + +#if APPLE_OSX_mDNSResponder + // DNSServiceCreateDelegateConnection() + if (DNSServiceCreateDelegateConnection(0, 0, 0) == 0) { - argc--; - argv++; - flags |= kDNSServiceFlagsTimeout; - printf("Setting kDNSServiceFlagsTimeout\n"); + printf("DNSServiceCreateDelegateConnection(): expected error return\n"); + return 1; } - if (argc > 1 && !strcasecmp(argv[1], "-optional")) +#endif + + // DNSServiceRegisterRecord() { - argc--; - argv++; - optional = 1; - printf("Setting DNSSEC optional flag\n"); + DNSServiceRef sdRef; + DNSRecordRef RecordRef; + DNSServiceFlags flags = 0; + uint32_t interfaceIndex = 0; + const char *fullname = "test1._test._tcp.local"; + uint16_t rrtype = kDNSServiceType_TXT; + uint16_t rrclass = kDNSServiceClass_IN; + uint16_t rdlen = 1; + const void *rdata = "\0"; + uint32_t ttl = 0; + DNSServiceRegisterRecordReply callBack = 0; + void *context = 0; /* may be NULL */ + + // Need an initialize sdRef + if (DNSServiceCreateConnection(&sdRef)) + { + printf("DNSServiceCreateConnection(): failed\n"); + return 1; + } + + if ( (DNSServiceRegisterRecord( 0, &RecordRef, flags, interfaceIndex, fullname, rrtype, rrclass, rdlen, rdata, ttl, callBack, context) == 0) + || (DNSServiceRegisterRecord(sdRef, &RecordRef, flags, interfaceIndex, 0, rrtype, rrclass, rdlen, rdata, ttl, callBack, context) == 0) + || (DNSServiceRegisterRecord(sdRef, &RecordRef, flags, interfaceIndex, fullname, rrtype, rrclass, rdlen, 0, ttl, callBack, context) == 0) + || (DNSServiceRegisterRecord(sdRef, &RecordRef, flags, interfaceIndex, fullname, rrtype, rrclass, rdlen, rdata, ttl, 0, context) == 0) + ) + { + printf("DNSServiceRegisterRecord(): expected error return\n"); + return 1; + } } - if (argc > 2 && !strcmp(argv[1], "-i")) + // DNSServiceAddRecord(), DNSServiceUpdateRecord(), and DNSServiceRemoveRecord() verify that they + // get a valid DNSServiceRef returned from DNSServiceRegister() + { + DNSServiceErrorType err; + Opaque16 registerPort = { { 0x12, 0x34 } }; + static const char TXT[] = "\xC" "First String"; + DNSServiceRef sdRef; + + DNSRecordRef RecordRef; + DNSServiceFlags flags = 0; + uint16_t rrtype = kDNSServiceType_TXT; + uint16_t rdlen = 1; + const void *rdata = "\0"; + uint32_t ttl = 100; + + err = DNSServiceRegister(&sdRef, 0, 0, "Test", "_test._tcp.", "", NULL, registerPort.NotAnInteger, sizeof(TXT)-1, TXT, reg_reply, NULL); + if (err) + { + printf("DNSServiceRegister() failed with: %d\n", err); + return 1; + } + + // DNSServiceAddRecord() + if ( (DNSServiceAddRecord( 0, &RecordRef, flags, rrtype, rdlen, rdata, ttl) == 0) + || (DNSServiceAddRecord(sdRef, 0, flags, rrtype, rdlen, rdata, ttl) == 0) + || (DNSServiceAddRecord(sdRef, &RecordRef, flags, rrtype, rdlen, 0, ttl) == 0) + ) + + { + printf("DNSServiceAddRecord(): expected error return\n"); + return 1; + } + + // (rdlen == 0 && rdata == 0) should indicate a TXT with rdata containing only a 0 length byte. + if (DNSServiceAddRecord(sdRef, &RecordRef, flags, rrtype, 0, 0, ttl) == kDNSServiceErr_BadParam) + { + printf("DNSServiceAddRecord(): with (rdlen == 0 && rdata == 0) returned kDNSServiceErr_BadParam\n"); + return 1; + } + + // DNSServiceUpdateRecord() + // Note, RecordRef can be NULL per explanation with declaration in dns_sd.h + if ( (DNSServiceUpdateRecord( 0, RecordRef, flags, rdlen, rdata, ttl) == 0) + || (DNSServiceUpdateRecord(sdRef, RecordRef, flags, rdlen, 0, ttl) == 0) + ) + { + printf("DNSServiceUpdateRecord(): expected error return\n"); + return 1; + } + + // (rdlen == 0 && rdata == 0) should indicate a TXT with rdata containing only a 0 length byte. + if (DNSServiceUpdateRecord(sdRef, RecordRef, flags, 0, 0, ttl) == kDNSServiceErr_BadParam) + { + printf("DNSServiceUpdateRecord(): with (rdlen == 0 && rdata == 0) returned kDNSServiceErr_BadParam\n"); + return 1; + } + + // DNSServiceRemoveRecord() + if ( (DNSServiceRemoveRecord( 0, RecordRef, flags) == 0) + || (DNSServiceRemoveRecord(sdRef, 0, flags) == 0) + ) + { + printf("DNSServiceRemoveRecord(): expected error return\n"); + return 1; + } + + DNSServiceRefDeallocate(sdRef); + } + + // DNSServiceReconfirmRecord() + { + DNSServiceFlags flags = 0; + uint32_t interfaceIndex = 0; + const char *fullname = "aaa._test._tcp.local"; + uint16_t rrtype = kDNSServiceType_TXT; + uint16_t rrclass = kDNSServiceClass_IN; + uint16_t rdlen = 1; + const void *rdata = "\0"; + + if ( (DNSServiceReconfirmRecord(flags, interfaceIndex, 0, rrtype, rrclass, rdlen, rdata) == 0) + || (DNSServiceReconfirmRecord(flags, interfaceIndex, fullname, rrtype, rrclass, rdlen, 0) == 0) + ) + { + printf("DNSServiceReconfirmRecord(): expected error return\n"); + return 1; + } + // (rdlen == 0 && rdata == 0) should indicate a TXT with rdata containing only a 0 length byte. + if (DNSServiceReconfirmRecord(flags, interfaceIndex, fullname, rrtype, rrclass, 0, 0) == kDNSServiceErr_BadParam) + { + printf("DNSServiceReconfirmRecord(): with (rdlen == 0 && rdata == 0) returned kDNSServiceErr_BadParam\n"); + return 1; + } + } + + + printf("Basic API input range tests: PASSED\n"); + return 0; +} + +static int API_input_range_test() +{ + + if (API_string_limit_test()) + return 1; + + if (API_NULL_input_test()) + return 1; + + return 0; +} + +int main(int argc, char **argv) +{ + DNSServiceErrorType err; + char buffer[TypeBufferSize], *typ, *dom; + int opi; + DNSServiceFlags flags = 0; + int optional = 0; + + // Extract the program name from argv[0], which by convention contains the path to this executable. + // Note that this is just a voluntary convention, not enforced by the kernel -- + // the process calling exec() can pass bogus data in argv[0] if it chooses to. + const char *a0 = strrchr(argv[0], kFilePathSep) + 1; + if (a0 == (const char *)1) a0 = argv[0]; + +#if defined(_WIN32) + HeapSetInformation(NULL, HeapEnableTerminationOnCorruption, NULL, 0); +#endif + +#if TEST_NEW_CLIENTSTUB + printf("Using embedded copy of dnssd_clientstub instead of system library\n"); + if (sizeof(argv) == 8) printf("Running in 64-bit mode\n"); +#endif + + // Test code for TXTRecord functions + //TXTRecordRef txtRecord; + //TXTRecordCreate(&txtRecord, 0, NULL); + //TXTRecordSetValue(&txtRecord, "aaa", 1, "b"); + //printf("%d\n", TXTRecordContainsKey(TXTRecordGetLength(&txtRecord), TXTRecordGetBytesPtr(&txtRecord), "Aaa")); + + while (argc > 1) { - opinterface = if_nametoindex(argv[2]); - if (!opinterface) opinterface = atoi(argv[2]); - if (!opinterface) { fprintf(stderr, "Unknown interface %s\n", argv[2]); goto Fail; } - argc -= 2; - argv += 2; + int entryCount; + + // record current argc to see if we process an argument in this pass + entryCount = argc; + + if (argc > 1 && !strcmp(argv[1], "-test")) + { + argc--; + argv++; + return API_input_range_test(); + } + + if (argc > 1 && !strcmp(argv[1], "-lo")) + { + argc--; + argv++; + opinterface = kDNSServiceInterfaceIndexLocalOnly; + printf("Using LocalOnly\n"); + } + + if (argc > 1 && (!strcasecmp(argv[1], "-p2p"))) + { + argc--; + argv++; + opinterface = kDNSServiceInterfaceIndexP2P; + } + + if (argc > 1 && (!strcasecmp(argv[1], "-ble"))) + { + argc--; + argv++; + opinterface = kDNSServiceInterfaceIndexBLE; + } + + if (argc > 1 && !strcasecmp(argv[1], "-includep2p")) + { + argc--; + argv++; + flags |= kDNSServiceFlagsIncludeP2P; + printf("Setting kDNSServiceFlagsIncludeP2P\n"); + } + + if (argc > 1 && !strcasecmp(argv[1], "-fmc")) + { + argc--; + argv++; + flags |= kDNSServiceFlagsForceMulticast; + printf("Setting kDNSServiceFlagsForceMulticast flag for this request\n"); + } + + if (argc > 1 && !strcasecmp(argv[1], "-includeAWDL")) + { + argc--; + argv++; + flags |= kDNSServiceFlagsIncludeAWDL; + printf("Setting kDNSServiceFlagsIncludeAWDL\n"); + } + + if (argc > 1 && !strcasecmp(argv[1], "-intermediates")) + { + argc--; + argv++; + flags |= kDNSServiceFlagsReturnIntermediates; + printf("Setting kDNSServiceFlagsReturnIntermediates\n"); + } + + if (argc > 1 && !strcasecmp(argv[1], "-tc")) + { + argc--; + argv++; + flags |= kDNSServiceFlagsBackgroundTrafficClass; + printf("Setting kDNSServiceFlagsBackgroundTrafficClass\n"); + } + + if (argc > 1 && !strcasecmp(argv[1], "-t1")) + { + argc--; + argv++; + flags |= kDNSServiceFlagsThresholdOne; + printf("Setting kDNSServiceFlagsThresholdOne\n"); + } + + if (argc > 1 && !strcasecmp(argv[1], "-tFinder")) + { + argc--; + argv++; + flags |= kDNSServiceFlagsThresholdFinder; + printf("Setting kDNSServiceFlagsThresholdFinder\n"); + } + + if (argc > 1 && !strcasecmp(argv[1], "-wo")) + { + argc--; + argv++; + flags |= kDNSServiceFlagsWakeOnlyService; + printf("Setting kDNSServiceFlagsWakeOnlyService\n"); + } + + if (argc > 1 && !strcasecmp(argv[1], "-ku")) + { + argc--; + argv++; + flags |= kDNSServiceFlagsKnownUnique; + printf("Setting kDNSServiceFlagsKnownUnique\n"); + } + + if (argc > 1 && !strcasecmp(argv[1], "-unicastResponse")) + { + argc--; + argv++; + flags |= kDNSServiceFlagsUnicastResponse; + printf("Setting kDNSServiceFlagsUnicastResponse\n"); + } + + if (argc > 1 && !strcasecmp(argv[1], "-timeout")) + { + argc--; + argv++; + flags |= kDNSServiceFlagsTimeout; + printf("Setting kDNSServiceFlagsTimeout\n"); + } + + if (argc > 1 && !strcasecmp(argv[1], "-autoTrigger")) + { + argc--; + argv++; + flags |= kDNSServiceFlagsAutoTrigger; + printf("Setting kDNSServiceFlagsAutoTrigger\n"); + } + + if (argc > 1 && !strcasecmp(argv[1], "-optional")) + { + argc--; + argv++; + optional = 1; + printf("Setting DNSSEC optional flag\n"); + } + + if (argc > 2 && !strcmp(argv[1], "-i")) + { + opinterface = if_nametoindex(argv[2]); + if (!opinterface) opinterface = atoi(argv[2]); + if (!opinterface) { fprintf(stderr, "Unknown interface %s\n", argv[2]); goto Fail; } + argc -= 2; + argv += 2; + } + + // Exit loop if if we didn't match one of the multi character options. + if (argc == entryCount) + break; } if (argc < 2) goto Fail; // Minimum command line is the command name and one argument - operation = getfirstoption(argc, argv, "EFBZLlRPQqCAUNTMISVHhD" + operation = getfirstoption(argc, argv, "ABCDEFHILMNPQRSTUVZhlq" "X" "Gg" , &opi); @@ -1686,6 +2194,7 @@ int main(int argc, char **argv) case 'g': case 'G': { flags |= kDNSServiceFlagsReturnIntermediates; + if (operation == 'g') { flags |= kDNSServiceFlagsSuppressUnusable; @@ -1779,11 +2288,7 @@ Fail: // NOT static -- otherwise the compiler may optimize it out // The "@(#) " pattern is a special prefix the "what" command looks for -#ifndef MDNS_VERSIONSTR_NODTS const char VersionString_SCCS[] = "@(#) dns-sd " STRINGIFY(mDNSResponderVersion) " (" __DATE__ " " __TIME__ ")"; -#else -const char VersionString_SCCS[] = "@(#) dns-sd " STRINGIFY(mDNSResponderVersion); -#endif #if _BUILDING_XCODE_PROJECT_ // If the process crashes, then this string will be magically included in the automatically-generated crash log diff --git a/usr/src/cmd/cmd-inet/usr.lib/mdnsd/THIRDPARTYLICENSE b/usr/src/contrib/mDNSResponder/LICENSE index f4589044ee..f4589044ee 100644 --- a/usr/src/cmd/cmd-inet/usr.lib/mdnsd/THIRDPARTYLICENSE +++ b/usr/src/contrib/mDNSResponder/LICENSE diff --git a/usr/src/contrib/mDNSResponder/LICENSE.descrip b/usr/src/contrib/mDNSResponder/LICENSE.descrip new file mode 100644 index 0000000000..73f70154ad --- /dev/null +++ b/usr/src/contrib/mDNSResponder/LICENSE.descrip @@ -0,0 +1 @@ +mDNSResponder diff --git a/usr/src/lib/libdns_sd/README b/usr/src/contrib/mDNSResponder/README index 9bae6c7404..ea5d4d4740 100644 --- a/usr/src/lib/libdns_sd/README +++ b/usr/src/contrib/mDNSResponder/README @@ -21,22 +21,24 @@ # # CDDL HEADER END # + +The mdns vendor source repository is at https://github.com/illumos/mdns/. + +Updated from upstream version mDNSResponder-878.1.1 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 -Apple Bonjour source code (v107.6). Apple Bonjour source can be -downloaded from: - http://developer.apple.com/networking/bonjour/download/ +Apple Bonjour source code (v107.6). Apple Bonjour source can be +downloaded from: + http://developer.apple.com/networking/bonjour/download/ The following components are integrated from the Apple Bonjour source in Solaris: - libdns_sd: usr/src/lib/libdns_sd <dns_sd.h> - libjdns_sd: usr/src/lib/libdns_sd/java/common - dnssd.jar: usr/src/lib/libdns_sd/java/com (incl. examples) + libdns_sd: usr/src/lib/libdns_sd <dns_sd.h> mdnsd: usr/src/cmd/cmd-inet/usr.lib/mdnsd - dns-sd: usr/src/cmd/cmd-inet/usr.bin/dns-sd.c + dns-sd: usr/src/cmd/cmd-inet/usr.bin/dns-sd -Following fixes have been made to the Apple Bonjour source +Following fixes have been made to the Apple Bonjour source integrated in Solaris: * 64-bit support by adding pad bytes in ipc_msg_hdr_struct * 64-bit support in libjdns_sd, dnssd.jar (JNISupport.c, DNSSD.java) @@ -44,13 +46,13 @@ integrated in Solaris: * Fixes to support IPv6 (mDNSPosix.c, mDNSUNP.c) * Fix error raised when uDNS.c is compiled with Sun Studio compiler * Fix in dnssd_clientstub.c to not check errno when recvmsg returns 0 -* mDNSDebug.c modified to not send msgs directly to console when +* mDNSDebug.c modified to not send msgs directly to console when syslog call returns an error. Logs the messages at LOG_INFO level and not LOG_ERR In addition the project introduces the following changes: -* A new nss_mdns module is introduced to use Multicast DNS (mdns) - for resolving link-local hostnames and is located at: +* A new nss_mdns module is introduced to use Multicast DNS (mdns) + for resolving link-local hostnames and is located at: usr/src/lib/nsswitch/mdns * snoop updated to decode mDNS packets * updated /etc/services to include mdns @@ -61,5 +63,5 @@ In addition the project introduces the following changes: Both authorizations added in network management execution profile. * Default nsswitch.dns includes mdns as source for hosts & ipnodes * nscd daemon updated to support mdns -* SUNWdsdu and SUNWdsdr packages deliver all the new mDNS +* SUNWdsdu and SUNWdsdr packages deliver all the new mDNS service discovery components. diff --git a/usr/src/contrib/mDNSResponder/copy_files.sh b/usr/src/contrib/mDNSResponder/copy_files.sh new file mode 100755 index 0000000000..a7f3662a8f --- /dev/null +++ b/usr/src/contrib/mDNSResponder/copy_files.sh @@ -0,0 +1,11 @@ +#!/bin/ksh + +if [ ! -d "$1" ]; then + echo "\"$1\" should be source repository root directory" + exit 1 +fi + +for f in LICENSE */* +do + cp $1/$f $f +done diff --git a/usr/src/cmd/cmd-inet/usr.lib/mdnsd/CryptoAlg.c b/usr/src/contrib/mDNSResponder/mDNSCore/CryptoAlg.c index 0008405ddd..0008405ddd 100644 --- a/usr/src/cmd/cmd-inet/usr.lib/mdnsd/CryptoAlg.c +++ b/usr/src/contrib/mDNSResponder/mDNSCore/CryptoAlg.c diff --git a/usr/src/cmd/cmd-inet/usr.lib/mdnsd/CryptoAlg.h b/usr/src/contrib/mDNSResponder/mDNSCore/CryptoAlg.h index c21507e4b1..c21507e4b1 100644 --- a/usr/src/cmd/cmd-inet/usr.lib/mdnsd/CryptoAlg.h +++ b/usr/src/contrib/mDNSResponder/mDNSCore/CryptoAlg.h diff --git a/usr/src/cmd/cmd-inet/usr.lib/mdnsd/DNSCommon.c b/usr/src/contrib/mDNSResponder/mDNSCore/DNSCommon.c index e75f734e22..323974cb45 100644 --- a/usr/src/cmd/cmd-inet/usr.lib/mdnsd/DNSCommon.c +++ b/usr/src/contrib/mDNSResponder/mDNSCore/DNSCommon.c @@ -21,6 +21,10 @@ #include "CryptoAlg.h" #include "anonymous.h" +#ifdef UNIT_TEST +#include "unittest.h" +#endif + // Disable certain benign warnings with Microsoft compilers #if (defined(_MSC_VER)) // Disable "conditional expression is constant" warning for debug macros. @@ -43,6 +47,7 @@ mDNSexport const mDNSInterfaceID mDNSInterface_LocalOnly = (mDNSInterfaceID)-2; mDNSexport const mDNSInterfaceID mDNSInterface_Unicast = (mDNSInterfaceID)-3; mDNSexport const mDNSInterfaceID mDNSInterface_P2P = (mDNSInterfaceID)-4; mDNSexport const mDNSInterfaceID uDNSInterfaceMark = (mDNSInterfaceID)-5; +mDNSexport const mDNSInterfaceID mDNSInterface_BLE = (mDNSInterfaceID)-6; // Note: Microsoft's proposed "Link Local Multicast Name Resolution Protocol" (LLMNR) is essentially a limited version of // Multicast DNS, using the same packet formats, naming syntax, and record types as Multicast DNS, but on a different UDP @@ -107,8 +112,11 @@ mDNSexport const mDNSOpaque16 DNSSecQFlags = { { kDNSFlag0_QR_Query | kDNS mDNSexport const mDNSOpaque16 ResponseFlags = { { kDNSFlag0_QR_Response | kDNSFlag0_OP_StdQuery | kDNSFlag0_AA, 0 } }; mDNSexport const mDNSOpaque16 UpdateReqFlags = { { kDNSFlag0_QR_Query | kDNSFlag0_OP_Update, 0 } }; mDNSexport const mDNSOpaque16 UpdateRespFlags = { { kDNSFlag0_QR_Response | kDNSFlag0_OP_Update, 0 } }; +mDNSexport const mDNSOpaque16 SubscribeFlags = { { kDNSFlag0_QR_Query | kDNSFlag0_OP_Subscribe, 0 } }; +mDNSexport const mDNSOpaque16 UnSubscribeFlags= { { kDNSFlag0_QR_Query | kDNSFlag0_OP_UnSubscribe, 0 } }; -mDNSexport const mDNSOpaque64 zeroOpaque64 = { { 0 } }; +mDNSexport const mDNSOpaque64 zeroOpaque64 = { { 0 } }; +mDNSexport const mDNSOpaque128 zeroOpaque128 = { { 0 } }; // *************************************************************************** #if COMPILER_LIKES_PRAGMA_MARK @@ -462,9 +470,9 @@ mDNSexport char *GetRRDisplayString_rdb(const ResourceRecord *const rr, const RD const mDNSu8 *p = (mDNSu8 *)&nsec3->salt; int hashLength, bitmaplen, i; - length += mDNS_snprintf(buffer+length, RemSpc, "\t%s %d %d ", + length += mDNS_snprintf(buffer+length, RemSpc, "\t%s %d %d ", DNSSECDigestName(nsec3->alg), nsec3->flags, swap16(nsec3->iterations)); - + if (!nsec3->saltLength) { length += mDNS_snprintf(buffer+length, RemSpc, "-"); @@ -483,7 +491,7 @@ mDNSexport char *GetRRDisplayString_rdb(const ResourceRecord *const rr, const RD p += nsec3->saltLength; // p is pointing at hashLength hashLength = (int)*p++; - + length += baseEncode(buffer + length, RemSpc, p, hashLength, ENC_BASE32); // put a space at the end @@ -510,7 +518,7 @@ mDNSexport char *GetRRDisplayString_rdb(const ResourceRecord *const rr, const RD length += mDNS_snprintf(buffer+length, RemSpc, "\t%s %s %d %d %s %s %d %##s ", DNSTypeName(swap16(rrsig->typeCovered)), DNSSECAlgName(rrsig->alg), rrsig->labels, swap32(rrsig->origTTL), - expTimeBuf, inceptTimeBuf, swap16(rrsig->keyTag), ((domainname *)(&rrsig->signerName))->c); + expTimeBuf, inceptTimeBuf, swap16(rrsig->keyTag), rrsig->signerName); len = DomainNameLength((domainname *)&rrsig->signerName); baseEncode(buffer + length, RemSpc, (const mDNSu8 *)(rd->data + len + RRSIG_FIXED_SIZE), @@ -541,7 +549,7 @@ mDNSexport char *GetRRDisplayString_rdb(const ResourceRecord *const rr, const RD } break; - default: mDNS_snprintf(buffer+length, RemSpc, "RDLen %d: %s", rr->rdlength, rd->data); + default: mDNS_snprintf(buffer+length, RemSpc, "RDLen %d: %.*s", rr->rdlength, rr->rdlength, rd->data); // Really should scan buffer to check if text is valid UTF-8 and only replace with dots if not for (ptr = buffer; *ptr; ptr++) if (*ptr < ' ') *ptr = '.'; break; @@ -619,6 +627,8 @@ mDNSexport mDNSBool mDNSAddrIsDNSMulticast(const mDNSAddr *ip) #pragma mark - Domain Name Utility Functions #endif +#if !APPLE_OSX_mDNSResponder + mDNSexport mDNSBool SameDomainLabel(const mDNSu8 *a, const mDNSu8 *b) { int i; @@ -639,6 +649,8 @@ mDNSexport mDNSBool SameDomainLabel(const mDNSu8 *a, const mDNSu8 *b) return(mDNStrue); } +#endif // !APPLE_OSX_mDNSResponder + mDNSexport mDNSBool SameDomainName(const domainname *const d1, const domainname *const d2) { const mDNSu8 * a = d1->c; @@ -803,6 +815,7 @@ mDNSexport mDNSu8 *AppendDNSNameString(domainname *const name, const char *cstri mDNSu8 c = (mDNSu8)*cstr++; // Read the character if (c == '\\') // If escape character, check next character { + if (*cstr == '\0') break; // If this is the end of the string, then break c = (mDNSu8)*cstr++; // Assume we'll just take the next character if (mDNSIsDigit(cstr[-1]) && mDNSIsDigit(cstr[0]) && mDNSIsDigit(cstr[1])) { // If three decimal digits, @@ -815,7 +828,7 @@ mDNSexport mDNSu8 *AppendDNSNameString(domainname *const name, const char *cstri } *ptr++ = c; // Write the character } - if (*cstr) cstr++; // Skip over the trailing dot (if present) + if (*cstr == '.') cstr++; // Skip over the trailing dot (if present) if (ptr - lengthbyte - 1 > MAX_DOMAIN_LABEL) // If illegal label, abort return(mDNSNULL); *lengthbyte = (mDNSu8)(ptr - lengthbyte - 1); // Fill in the length byte @@ -967,10 +980,6 @@ mDNSexport void ConvertUTF8PstringToRFC1034HostLabel(const mDNSu8 UTF8Name[], do hostlabel->c[0] = (mDNSu8)(ptr - &hostlabel->c[1]); } -#define ValidTransportProtocol(X) ( (X)[0] == 4 && (X)[1] == '_' && \ - ((((X)[2] | 0x20) == 'u' && ((X)[3] | 0x20) == 'd') || (((X)[2] | 0x20) == 't' && ((X)[3] | 0x20) == 'c')) && \ - ((X)[4] | 0x20) == 'p') - mDNSexport mDNSu8 *ConstructServiceName(domainname *const fqdn, const domainlabel *name, const domainname *type, const domainname *const domain) { @@ -1029,10 +1038,6 @@ mDNSexport mDNSu8 *ConstructServiceName(domainname *const fqdn, { LogMsg("Bad service type in %#s.%##s%##s Application protocol name must be underscore plus 1-15 characters. " "See <http://www.dns-sd.org/ServiceTypes.html>", name->c, type->c, domain->c); -#if APPLE_OSX_mDNSResponder - ConvertDomainNameToCString(type, typeBuf); - mDNSASLLog(mDNSNULL, "serviceType.nameTooLong", "noop", typeBuf, ""); -#endif } if (len < 2 || len >= 0x40 || (len > 16 && !SameDomainName(domain, &localdomain))) return(mDNSNULL); if (src[1] != '_') { errormsg = "Application protocol name must begin with underscore"; goto fail; } @@ -1049,19 +1054,13 @@ mDNSexport mDNSu8 *ConstructServiceName(domainname *const fqdn, if (src[i] == '_' && loggedUnderscore == mDNSfalse) { ConvertDomainNameToCString(type, typeBuf); - mDNSASLLog(mDNSNULL, "serviceType.nameWithUnderscore", "noop", typeBuf, ""); + LogInfo("ConstructServiceName: Service type with non-leading underscore %s", typeBuf); loggedUnderscore = mDNStrue; } #endif continue; } errormsg = "Application protocol name must contain only letters, digits, and hyphens"; -#if APPLE_OSX_mDNSResponder - { - ConvertDomainNameToCString(type, typeBuf); - mDNSASLLog(mDNSNULL, "serviceType.nameWithIllegalCharacters", "noop", typeBuf, ""); - } -#endif goto fail; } for (i=0; i<=len; i++) *dst++ = *src++; @@ -1165,7 +1164,8 @@ mDNSexport const mDNSu8 *NSEC3HashName(const domainname *name, rdataNSEC3 *nsec3 const mDNSu8 hash[NSEC3_MAX_HASH_LEN], int *dlen) { AlgContext *ctx; - int i; + unsigned int i; + unsigned int iterations; domainname lname; mDNSu8 *p = (mDNSu8 *)&nsec3->salt; const mDNSu8 *digest; @@ -1183,7 +1183,8 @@ mDNSexport const mDNSu8 *NSEC3HashName(const domainname *name, rdataNSEC3 *nsec3 // Note that it is "i <=". The first iteration is for digesting the name and salt. // The iteration count does not include that. - for (i = 0; i <= swap16(nsec3->iterations); i++) + iterations = swap16(nsec3->iterations); + for (i = 0; i <= iterations; i++) { ctx = AlgCreate(DIGEST_ALG, nsec3->alg); if (!ctx) @@ -1367,17 +1368,14 @@ mDNSexport void mDNS_SetupResourceRecord(AuthRecord *rr, RData *RDataStorage, mD if (InterfaceID == mDNSInterface_LocalOnly && artype != AuthRecordLocalOnly) { LogMsg("mDNS_SetupResourceRecord: ERROR!! Mismatch LocalOnly record InterfaceID %p called with artype %d", InterfaceID, artype); - return; } else if (InterfaceID == mDNSInterface_P2P && artype != AuthRecordP2P) { LogMsg("mDNS_SetupResourceRecord: ERROR!! Mismatch P2P record InterfaceID %p called with artype %d", InterfaceID, artype); - return; } else if (!InterfaceID && (artype == AuthRecordP2P || artype == AuthRecordLocalOnly)) { LogMsg("mDNS_SetupResourceRecord: ERROR!! Mismatch InterfaceAny record InterfaceID %p called with artype %d", InterfaceID, artype); - return; } // Don't try to store a TTL bigger than we can represent in platform time units @@ -1467,8 +1465,6 @@ mDNSexport void mDNS_SetupQuestion(DNSQuestion *const q, const mDNSInterfaceID I q->ForceMCast = mDNSfalse; q->ReturnIntermed = mDNSfalse; q->SuppressUnusable = mDNSfalse; - q->DenyOnCellInterface = mDNSfalse; - q->DenyOnExpInterface = mDNSfalse; q->SearchListIndex = 0; q->AppendSearchDomains = 0; q->RetryWithSearchDomains = mDNSfalse; @@ -1779,7 +1775,7 @@ mDNSexport mDNSBool SameNameRecordAnswersQuestion(const ResourceRecord *const rr // LocalOnly/P2P questions can be answered with AuthRecordAny in this function. LocalOnly/P2P records // are handled in LocalOnlyRecordAnswersQuestion - if ((rr->InterfaceID == mDNSInterface_LocalOnly) || (rr->InterfaceID == mDNSInterface_P2P)) + if (LocalOnlyOrP2PInterface(rr->InterfaceID)) { LogMsg("SameNameRecordAnswersQuestion: ERROR!! called with LocalOnly ResourceRecord %p, Question %p", rr->InterfaceID, q->InterfaceID); return mDNSfalse; @@ -1914,7 +1910,7 @@ mDNSexport mDNSBool AnyTypeRecordAnswersQuestion(const ResourceRecord *const rr, { // LocalOnly/P2P questions can be answered with AuthRecordAny in this function. LocalOnly/P2P records // are handled in LocalOnlyRecordAnswersQuestion - if ((rr->InterfaceID == mDNSInterface_LocalOnly) || (rr->InterfaceID == mDNSInterface_P2P)) + if (LocalOnlyOrP2PInterface(rr->InterfaceID)) { LogMsg("AnyTypeRecordAnswersQuestion: ERROR!! called with LocalOnly ResourceRecord %p, Question %p", rr->InterfaceID, q->InterfaceID); return mDNSfalse; @@ -2142,7 +2138,6 @@ mDNSexport const mDNSu8 *FindCompressionPointer(const mDNSu8 *const base, const return(mDNSNULL); } -// Put a string of dot-separated labels as length-prefixed labels // domainname is a fully-qualified name (i.e. assumed to be ending in a dot, even if it doesn't) // msg points to the message we're building (pass mDNSNULL if we don't want to use compression pointers) // end points to the end of the message so far @@ -2305,12 +2300,12 @@ mDNSexport mDNSu8 *putRData(const DNSMessage *const msg, mDNSu8 *ptr, const mDNS int len = 0; const rdataOPT *opt; const rdataOPT *const end = (const rdataOPT *)&rr->rdata->u.data[rr->rdlength]; - for (opt = &rr->rdata->u.opt[0]; opt < end; opt++) + for (opt = &rr->rdata->u.opt[0]; opt < end; opt++) len += DNSOpt_Data_Space(opt); - if (ptr + len > limit) - { - LogMsg("ERROR: putOptRData - out of space"); - return mDNSNULL; + if (ptr + len > limit) + { + LogMsg("ERROR: putOptRData - out of space"); + return mDNSNULL; } for (opt = &rr->rdata->u.opt[0]; opt < end; opt++) { @@ -2754,12 +2749,12 @@ mDNSexport const mDNSu8 *getDomainName(const DNSMessage *const msg, const mDNSu8 while (1) // Read sequence of labels { + int i; + mDNSu16 offset; const mDNSu8 len = *ptr++; // Read length of this label if (len == 0) break; // If length is zero, that means this name is complete switch (len & 0xC0) { - int i; - mDNSu16 offset; case 0x00: if (ptr + len >= end) // Remember: expect at least one more byte for the root label { debugf("getDomainName: Malformed domain name (overruns packet end)"); return(mDNSNULL); } @@ -2843,7 +2838,7 @@ mDNSlocal mDNSu8 *SanityCheckBitMap(const mDNSu8 *bmap, const mDNSu8 *end, int l // (domainnames are expanded to 255 bytes) when stored in memory. // // This function can also be called with "NULL" msg to parse a single resource record pointed to by ptr. -// The caller can do this only if the names in the resource records are compressed and validity of the +// The caller can do this only if the names in the resource records are not compressed and validity of the // resource record has already been done before. DNSSEC currently uses it this way. mDNSexport mDNSBool SetRData(const DNSMessage *const msg, const mDNSu8 *ptr, const mDNSu8 *end, LargeCacheRecord *const largecr, mDNSu16 rdlength) @@ -3293,7 +3288,7 @@ mDNSexport mDNSBool SetRData(const DNSMessage *const msg, const mDNSu8 *ptr, con { LogInfo("SetRData: nsec3 iteration count %d too big", swap16(nsec3->iterations)); goto fail; - } + } p += nsec3->saltLength; // There should at least be one byte beyond saltLength if (p >= end) @@ -3348,6 +3343,12 @@ mDNSexport mDNSBool SetRData(const DNSMessage *const msg, const mDNSu8 *ptr, con dlen = DomainNameLength(&name); rlen = end - ptr; rr->resrec.rdlength = dlen + rlen; + if (rr->resrec.rdlength > MaximumRDSize) + { + LogInfo("SetRData: Malformed TSIG/TKEY rdlength %d, rr->resrec.rdlength %d, " + "bmaplen %d, name %##s", rdlength, rr->resrec.rdlength, name.c); + goto fail; + } AssignDomainName((domainname *)rdb->data, &name); mDNSPlatformMemCopy(rdb->data + dlen, ptr, rlen); break; @@ -3451,12 +3452,6 @@ mDNSexport const mDNSu8 *GetLargeResourceRecord(mDNS *const m, const DNSMessage rr->CRActiveQuestion = mDNSNULL; rr->UnansweredQueries = 0; rr->LastUnansweredTime= 0; -#if ENABLE_MULTI_PACKET_QUERY_SNOOPING - rr->MPUnansweredQ = 0; - rr->MPLastUnansweredQT= 0; - rr->MPUnansweredKA = 0; - rr->MPExpectingKA = mDNSfalse; -#endif rr->NextInCFList = mDNSNULL; rr->resrec.InterfaceID = InterfaceID; @@ -3611,22 +3606,33 @@ mDNSexport const rdataOPT *GetLLQOptData(mDNS *const m, const DNSMessage *const } // Get the lease life of records in a dynamic update -// returns 0 on error or if no lease present -mDNSexport mDNSu32 GetPktLease(mDNS *m, DNSMessage *msg, const mDNSu8 *end) +mDNSexport mDNSBool GetPktLease(mDNS *const m, const DNSMessage *const msg, const mDNSu8 *const end, mDNSu32 *const lease) { - mDNSu32 result = 0; const mDNSu8 *ptr = LocateOptRR(msg, end, DNSOpt_LeaseData_Space); - if (ptr) ptr = GetLargeResourceRecord(m, msg, ptr, end, 0, kDNSRecordTypePacketAdd, &m->rec); - if (ptr && m->rec.r.resrec.rdlength >= DNSOpt_LeaseData_Space && m->rec.r.resrec.rdata->u.opt[0].opt == kDNSOpt_Lease) - result = m->rec.r.resrec.rdata->u.opt[0].u.updatelease; - m->rec.r.resrec.RecordType = 0; // Clear RecordType to show we're not still using it - return(result); + if (ptr) + { + ptr = GetLargeResourceRecord(m, msg, ptr, end, 0, kDNSRecordTypePacketAdd, &m->rec); + if (ptr && m->rec.r.resrec.RecordType != kDNSRecordTypePacketNegative && m->rec.r.resrec.rrtype == kDNSType_OPT) + { + const rdataOPT *o; + const rdataOPT *const e = (const rdataOPT *)&m->rec.r.resrec.rdata->u.data[m->rec.r.resrec.rdlength]; + for (o = &m->rec.r.resrec.rdata->u.opt[0]; o < e; o++) + if (o->opt == kDNSOpt_Lease) + { + *lease = o->u.updatelease; + m->rec.r.resrec.RecordType = 0; // Clear RecordType to show we're not still using it + return mDNStrue; + } + } + m->rec.r.resrec.RecordType = 0; // Clear RecordType to show we're not still using it + } + return mDNSfalse; } mDNSlocal const mDNSu8 *DumpRecords(mDNS *const m, const DNSMessage *const msg, const mDNSu8 *ptr, const mDNSu8 *const end, int count, char *label) { int i; - LogMsg("%2d %s", count, label); + LogInfo("%2d %s", count, label); for (i = 0; i < count && ptr; i++) { // This puts a LargeCacheRecord on the stack instead of using the shared m->rec storage, @@ -3634,9 +3640,11 @@ mDNSlocal const mDNSu8 *DumpRecords(mDNS *const m, const DNSMessage *const msg, // embedded systems) putting a 9kB object on the stack isn't a big problem. LargeCacheRecord largecr; ptr = GetLargeResourceRecord(m, msg, ptr, end, mDNSInterface_Any, kDNSRecordTypePacketAns, &largecr); - if (ptr) LogMsg("%2d TTL%8d %s", i, largecr.r.resrec.rroriginalttl, CRDisplayString(m, &largecr.r)); + if (ptr) + LogInfo("%2d TTL%8d %s", i, largecr.r.resrec.rroriginalttl, CRDisplayString(m, &largecr.r)); } - if (!ptr) LogMsg("DumpRecords: ERROR: Premature end of packet data"); + if (!ptr) + LogInfo("DumpRecords: ERROR: Premature end of packet data"); return(ptr); } @@ -3646,7 +3654,9 @@ mDNSlocal const mDNSu8 *DumpRecords(mDNS *const m, const DNSMessage *const msg, (X) == kDNSFlag0_OP_Status ? "Status " : \ (X) == kDNSFlag0_OP_Unused3 ? "Unused3 " : \ (X) == kDNSFlag0_OP_Notify ? "Notify " : \ - (X) == kDNSFlag0_OP_Update ? "Update " : "?? " ) + (X) == kDNSFlag0_OP_Update ? "Update " : \ + (X) == kDNSFlag0_OP_Subscribe? "Subscribe": \ + (X) == kDNSFlag0_OP_UnSubscribe? "UnSubscribe" : "?? " ) #define DNS_RC_Name(X) ( \ (X) == kDNSFlag1_RC_NoErr ? "NoErr" : \ @@ -3678,7 +3688,7 @@ mDNSexport void DumpPacket(mDNS *const m, mStatus status, mDNSBool sent, char *t if (dstaddr || !mDNSIPPortIsZero(dstport)) dbuffer[mDNS_snprintf(dbuffer, sizeof(dbuffer), " to %#a:%d", dstaddr, mDNSVal16(dstport))] = 0; - LogMsg("-- %s %s DNS %s%s (flags %02X%02X) RCODE: %s (%d) %s%s%s%s%s%sID: %d %d bytes from %s%d%s%s --", + LogInfo("-- %s %s DNS %s%s (flags %02X%02X) RCODE: %s (%d) %s%s%s%s%s%sID: %d %d bytes from %s%d%s%s --", tbuffer, transport, DNS_OP_Name(msg->h.flags.b[0] & kDNSFlag0_OP_Mask), msg->h.flags.b[0] & kDNSFlag0_QR_Response ? "Response" : "Query", @@ -3697,16 +3707,16 @@ mDNSexport void DumpPacket(mDNS *const m, mStatus status, mDNSBool sent, char *t (msg->h.flags.b[0] & kDNSFlag0_TC) ? " (truncated)" : "" ); - LogMsg("%2d %s", msg->h.numQuestions, IsUpdate ? "Zone" : "Questions"); + LogInfo("%2d %s", msg->h.numQuestions, IsUpdate ? "Zone" : "Questions"); for (i = 0; i < msg->h.numQuestions && ptr; i++) { ptr = getQuestion(msg, ptr, end, mDNSInterface_Any, &q); - if (ptr) LogMsg("%2d %##s %s", i, q.qname.c, DNSTypeName(q.qtype)); + if (ptr) LogInfo("%2d %##s %s", i, q.qname.c, DNSTypeName(q.qtype)); } ptr = DumpRecords(m, msg, ptr, end, msg->h.numAnswers, IsUpdate ? "Prerequisites" : "Answers"); ptr = DumpRecords(m, msg, ptr, end, msg->h.numAuthorities, IsUpdate ? "Updates" : "Authorities"); DumpRecords(m, msg, ptr, end, msg->h.numAdditionals, "Additionals"); - LogMsg("--------------"); + LogInfo("--------------"); } // *************************************************************************** @@ -3715,6 +3725,10 @@ mDNSexport void DumpPacket(mDNS *const m, mStatus status, mDNSBool sent, char *t #pragma mark - Packet Sending Functions #endif +#ifdef UNIT_TEST +// Run the unit test of mDNSSendDNSMessage +UNITTEST_SENDDNSMESSAGE +#else // Stub definition of TCPSocket_struct so we can access flags field. (Rest of TCPSocket_struct is platform-dependent.) struct TCPSocket_struct { TCPSocketFlags flags; /* ... */ }; // Stub definition of UDPSocket_struct so we can access port field. (Rest of UDPSocket_struct is platform-dependent.) @@ -3723,7 +3737,7 @@ 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. mDNSexport mStatus mDNSSendDNSMessage(mDNS *const m, DNSMessage *const msg, mDNSu8 *end, - mDNSInterfaceID InterfaceID, UDPSocket *src, const mDNSAddr *dst, + mDNSInterfaceID InterfaceID, UDPSocket *src, const mDNSAddr *dst, mDNSIPPort dstport, TCPSocket *sock, DomainAuthInfo *authInfo, mDNSBool useBackgroundTrafficClass) { @@ -3808,19 +3822,15 @@ mDNSexport mStatus mDNSSendDNSMessage(mDNS *const m, DNSMessage *const msg, mDNS SwapDNSHeaderBytes(msg); // 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); - } + if (mDNS_PacketLoggingEnabled && !mDNSOpaque16IsZero(msg->h.id)) + DumpPacket(m, status, mDNStrue, sock && (sock->flags & kTCPSocketFlags_UseTLS) ? "TLS" : sock ? "TCP" : "UDP", mDNSNULL, src ? src->port : MulticastDNSPort, dst, dstport, msg, end); // put the number of additionals back the way it was msg->h.numAdditionals = numAdditionals; return(status); } +#endif // UNIT_TEST // *************************************************************************** #if COMPILER_LIKES_PRAGMA_MARK @@ -3878,7 +3888,7 @@ mDNSlocal AuthRecord *AnyLocalRecordReady(const mDNS *const m) mDNSlocal mDNSs32 GetNextScheduledEvent(const mDNS *const m) { - mDNSs32 e = m->timenow + 0x78000000; + mDNSs32 e = m->timenow + FutureTime; if (m->mDNSPlatformStatus != mStatus_NoError) return(e); if (m->NewQuestions) { @@ -3901,6 +3911,10 @@ mDNSlocal mDNSs32 GetNextScheduledEvent(const mDNS *const m) if (e - m->NextScheduledSPS > 0) e = m->NextScheduledSPS; if (e - m->NextScheduledKA > 0) e = m->NextScheduledKA; +#if BONJOUR_ON_DEMAND + if (m->NextBonjourDisableTime && (e - m->NextBonjourDisableTime > 0)) e = m->NextBonjourDisableTime; +#endif // BONJOUR_ON_DEMAND + // NextScheduledSPRetry only valid when DelaySleep not set if (!m->DelaySleep && m->SleepLimit && e - m->NextScheduledSPRetry > 0) e = m->NextScheduledSPRetry; if (m->DelaySleep && e - m->DelaySleep > 0) e = m->DelaySleep; @@ -3916,6 +3930,9 @@ mDNSlocal mDNSs32 GetNextScheduledEvent(const mDNS *const m) if (e - m->NextScheduledResponse > 0) e = m->NextScheduledResponse; } if (e - m->NextScheduledStopTime > 0) e = m->NextScheduledStopTime; + + if (m->NextBLEServiceTime && (e - m->NextBLEServiceTime > 0)) e = m->NextBLEServiceTime; + return(e); } @@ -4045,7 +4062,8 @@ mDNSexport mDNSu32 mDNS_vsnprintf(char *sbuffer, mDNSu32 buflen, const char *fmt for (c = *fmt; c != 0; c = *++fmt) { - if (c != '%') + unsigned long n; + if (c != '%') { *sbuffer++ = (char)c; if (++nwritten >= buflen) goto exit; @@ -4101,7 +4119,6 @@ mDNSexport mDNSu32 mDNS_vsnprintf(char *sbuffer, mDNSu32 buflen, const char *fmt conv: switch (c) // perform appropriate conversion { - unsigned long n; case 'h': F.hSize = 1; c = *++fmt; goto conv; case 'l': // fall through case 'L': F.lSize = 1; c = *++fmt; goto conv; diff --git a/usr/src/cmd/cmd-inet/usr.lib/mdnsd/DNSCommon.h b/usr/src/contrib/mDNSResponder/mDNSCore/DNSCommon.h index e51b06dd7a..1e0e09abe1 100644 --- a/usr/src/cmd/cmd-inet/usr.lib/mdnsd/DNSCommon.h +++ b/usr/src/contrib/mDNSResponder/mDNSCore/DNSCommon.h @@ -40,17 +40,19 @@ extern "C" { typedef enum { - kDNSFlag0_QR_Mask = 0x80, // Query or response? - kDNSFlag0_QR_Query = 0x00, - kDNSFlag0_QR_Response = 0x80, - - kDNSFlag0_OP_Mask = 0x78, // Operation type - kDNSFlag0_OP_StdQuery = 0x00, - kDNSFlag0_OP_Iquery = 0x08, - kDNSFlag0_OP_Status = 0x10, - kDNSFlag0_OP_Unused3 = 0x18, - kDNSFlag0_OP_Notify = 0x20, - kDNSFlag0_OP_Update = 0x28, + kDNSFlag0_QR_Mask = 0x80, // Query or response? + kDNSFlag0_QR_Query = 0x00, + kDNSFlag0_QR_Response = 0x80, + + kDNSFlag0_OP_Mask = 0x78, // Operation type + kDNSFlag0_OP_StdQuery = 0x00, + kDNSFlag0_OP_Subscribe = 0x06, + kDNSFlag0_OP_UnSubscribe = 0x07, + kDNSFlag0_OP_Iquery = 0x08, + kDNSFlag0_OP_Status = 0x10, + kDNSFlag0_OP_Unused3 = 0x18, + kDNSFlag0_OP_Notify = 0x20, + kDNSFlag0_OP_Update = 0x28, kDNSFlag0_QROP_Mask = kDNSFlag0_QR_Mask | kDNSFlag0_OP_Mask, @@ -84,6 +86,7 @@ typedef enum TSIG_ErrBadTime = 18 } TSIG_ErrorCode; + // *************************************************************************** #if COMPILER_LIKES_PRAGMA_MARK #pragma mark - @@ -237,8 +240,7 @@ extern const mDNSu8 *NSEC3HashName(const domainname *name, rdataNSEC3 *nsec3, co #pragma mark - DNS Message Parsing Functions #endif -#define AuthHashSlot(X) (DomainNameHashValue(X) % AUTH_HASH_SLOTS) -#define HashSlot(X) (DomainNameHashValue(X) % CACHE_HASH_SLOTS) +#define HashSlotFromNameHash(X) ((X) % CACHE_HASH_SLOTS) extern mDNSu32 DomainNameHashValue(const domainname *const name); extern void SetNewRData(ResourceRecord *const rr, RData *NewRData, mDNSu16 rdlength); extern const mDNSu8 *skipDomainName(const DNSMessage *const msg, const mDNSu8 *ptr, const mDNSu8 *const end); @@ -257,7 +259,7 @@ extern const mDNSu8 *LocateAuthorities(const DNSMessage *const msg, const mDNSu8 extern const mDNSu8 *LocateAdditionals(const DNSMessage *const msg, const mDNSu8 *const end); extern const mDNSu8 *LocateOptRR(const DNSMessage *const msg, const mDNSu8 *const end, int minsize); extern const rdataOPT *GetLLQOptData(mDNS *const m, const DNSMessage *const msg, const mDNSu8 *const end); -extern mDNSu32 GetPktLease(mDNS *m, DNSMessage *msg, const mDNSu8 *end); +extern mDNSBool GetPktLease(mDNS *const m, const DNSMessage *const msg, const mDNSu8 *const end, mDNSu32 *const lease); extern void DumpPacket(mDNS *const m, mStatus status, mDNSBool sent, char *transport, const mDNSAddr *srcaddr, mDNSIPPort srcport, const mDNSAddr *dstaddr, mDNSIPPort dstport, const DNSMessage *const msg, const mDNSu8 *const end); @@ -275,7 +277,7 @@ extern mDNSu32 swap32(mDNSu32 x); #endif extern mStatus mDNSSendDNSMessage(mDNS *const m, DNSMessage *const msg, mDNSu8 *end, - mDNSInterfaceID InterfaceID, UDPSocket *src, const mDNSAddr *dst, + mDNSInterfaceID InterfaceID, UDPSocket *src, const mDNSAddr *dst, mDNSIPPort dstport, TCPSocket *sock, DomainAuthInfo *authInfo, mDNSBool useBackgroundTrafficClass); diff --git a/usr/src/cmd/cmd-inet/usr.lib/mdnsd/DNSDigest.c b/usr/src/contrib/mDNSResponder/mDNSCore/DNSDigest.c index 6520ac6f6e..0f8b32b082 100644 --- a/usr/src/cmd/cmd-inet/usr.lib/mdnsd/DNSDigest.c +++ b/usr/src/contrib/mDNSResponder/mDNSCore/DNSDigest.c @@ -1,7 +1,6 @@ /* -*- Mode: C; tab-width: 4 -*- * * Copyright (c) 2002-2011 Apple Inc. All rights reserved. - * Copyright (c) 2016 by Delphix. 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/anonymous.c b/usr/src/contrib/mDNSResponder/mDNSCore/anonymous.c index 184de13788..107dc177ac 100644 --- a/usr/src/cmd/cmd-inet/usr.lib/mdnsd/anonymous.c +++ b/usr/src/contrib/mDNSResponder/mDNSCore/anonymous.c @@ -25,7 +25,7 @@ #ifndef ANONYMOUS_DISABLED -#define ANON_NSEC3_ITERATIONS 1 +#define ANON_NSEC3_ITERATIONS 1 struct AnonInfoResourceRecord_struct { @@ -71,7 +71,7 @@ mDNSlocal mDNSBool InitializeNSEC3Record(ResourceRecord *rr, const mDNSu8 *AnonD // Hash the base service name + salt + AnonData if (!NSEC3HashName(rr->name, nsec3, AnonData, len, hashName, &hlen)) { - LogMsg("InitializeNSEC3Record: NSEC3HashName failed for ##s", rr->name->c); + LogMsg("InitializeNSEC3Record: NSEC3HashName failed for %##s", rr->name->c); return mDNSfalse; } if (hlen != SHA1_HASH_LENGTH) @@ -98,8 +98,8 @@ mDNSlocal ResourceRecord *ConstructNSEC3Record(const domainname *service, const } dlen = DomainNameLength(service); - - // Allocate space for the name and RData. + + // Allocate space for the name and RData. rr = mDNSPlatformMemAllocate(sizeof(ResourceRecord) + dlen + sizeof(RData)); if (!rr) return mDNSNULL; @@ -236,10 +236,16 @@ mDNSexport void SetAnonData(DNSQuestion *q, ResourceRecord *rr, mDNSBool ForQues LogMsg("SetAnonData: question %##s(%p), rr %##s(%p), NULL", q->qname.c, q->AnonInfo, rr->name->c, rr->AnonInfo); return; } - + debugf("SetAnonData: question %##s(%p), rr %##s(%p)", q->qname.c, q->AnonInfo, rr->name->c, rr->AnonInfo); if (ForQuestion) { + if (q->AnonInfo->AnonDataLen < rr->AnonInfo->AnonDataLen) + { + mDNSPlatformMemFree(q->AnonInfo->AnonData); + q->AnonInfo->AnonData = mDNSNULL; + } + if (!q->AnonInfo->AnonData) { q->AnonInfo->AnonData = mDNSPlatformMemAllocate(rr->AnonInfo->AnonDataLen); @@ -251,6 +257,12 @@ mDNSexport void SetAnonData(DNSQuestion *q, ResourceRecord *rr, mDNSBool ForQues } else { + if (rr->AnonInfo->AnonDataLen < q->AnonInfo->AnonDataLen) + { + mDNSPlatformMemFree(rr->AnonInfo->AnonData); + rr->AnonInfo->AnonData = mDNSNULL; + } + if (!rr->AnonInfo->AnonData) { rr->AnonInfo->AnonData = mDNSPlatformMemAllocate(q->AnonInfo->AnonDataLen); @@ -275,9 +287,10 @@ mDNSexport int AnonInfoAnswersQuestion(const ResourceRecord *const rr, const DNS int AnonDataLen; rdataNSEC3 *nsec3; int hlen; - const mDNSu8 hashName[NSEC3_MAX_HASH_LEN]; int nxtLength; mDNSu8 *nxtName; + mDNSu8 hashName[NSEC3_MAX_HASH_LEN]; + mDNSPlatformMemZero(hashName, sizeof(hashName)); debugf("AnonInfoAnswersQuestion: question qname %##s", q->qname.c); @@ -289,7 +302,7 @@ mDNSexport int AnonInfoAnswersQuestion(const ResourceRecord *const rr, const DNS // We allow anonymous questions to be answered by both normal services (without the // anonymous information) and anonymous services that are part of the same set. And - // normal questions discover normal services and all anonymous services. + // normal questions discover normal services and all anonymous services. // // The three cases have been enumerated clearly even though they all behave the // same way. @@ -341,7 +354,7 @@ mDNSexport int AnonInfoAnswersQuestion(const ResourceRecord *const rr, const DNS // // It is also possible that a local question is matched against the local AuthRecord // as that is also the case for which the AnonData would be non-NULL for both. - // We match questions against AuthRecords (rather than the cache) for LocalOnly case and + // We match questions against AuthRecords (rather than the cache) for LocalOnly case and // to see whether a .local query should be suppressed or not. The latter never happens // because PTR queries are never suppressed. @@ -368,7 +381,7 @@ mDNSexport int AnonInfoAnswersQuestion(const ResourceRecord *const rr, const DNS // If there is AnonData, then this is a local question. The // NSEC3 RR comes from the resource record which could be part // of the cache or local auth record. The cache entry could - // be from a remote host or created when we heard our own + // be from a remote host or created when we heard our own // announcements. In any case, we use that to see if it matches // the question. AnonData = qai->AnonData; @@ -398,7 +411,7 @@ mDNSexport int AnonInfoAnswersQuestion(const ResourceRecord *const rr, const DNS if (!NSEC3HashName(nsec3RR->name, nsec3, AnonData, AnonDataLen, hashName, &hlen)) { - LogMsg("AnonInfoAnswersQuestion: NSEC3HashName failed for ##s", nsec3RR->name->c); + LogMsg("AnonInfoAnswersQuestion: NSEC3HashName failed for %##s", nsec3RR->name->c); return mDNSfalse; } if (hlen != SHA1_HASH_LENGTH) @@ -434,7 +447,7 @@ mDNSlocal CacheRecord *FindMatchingNSEC3ForName(mDNS *const m, CacheRecord **nse { CacheRecord *cr; CacheRecord **prev = nsec3; - + (void) m; for (cr = *nsec3; cr; cr = cr->next) diff --git a/usr/src/cmd/cmd-inet/usr.lib/mdnsd/anonymous.h b/usr/src/contrib/mDNSResponder/mDNSCore/anonymous.h index b60812ea0d..b60812ea0d 100644 --- a/usr/src/cmd/cmd-inet/usr.lib/mdnsd/anonymous.h +++ b/usr/src/contrib/mDNSResponder/mDNSCore/anonymous.h diff --git a/usr/src/contrib/mDNSResponder/mDNSCore/dnsproxy.h b/usr/src/contrib/mDNSResponder/mDNSCore/dnsproxy.h new file mode 100644 index 0000000000..7008c058da --- /dev/null +++ b/usr/src/contrib/mDNSResponder/mDNSCore/dnsproxy.h @@ -0,0 +1,31 @@ +/* -*- Mode: C; tab-width: 4 -*- + * + * 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __DNS_PROXY_H +#define __DNS_PROXY_H + +#include "mDNSEmbeddedAPI.h" +#include "DNSCommon.h" + +extern void ProxyUDPCallback(void *socket, DNSMessage *const msg, const mDNSu8 *const end, const mDNSAddr *const srcaddr, + const mDNSIPPort srcport, const mDNSAddr *dstaddr, const mDNSIPPort dstport, const mDNSInterfaceID InterfaceID, void *context); +extern void ProxyTCPCallback(void *socket, DNSMessage *const msg, const mDNSu8 *const end, const mDNSAddr *const srcaddr, + const mDNSIPPort srcport, const mDNSAddr *dstaddr, const mDNSIPPort dstport, const mDNSInterfaceID InterfaceID, void *context); +extern void DNSProxyInit(mDNSu32 IpIfArr[MaxIp], mDNSu32 OpIf); +extern void DNSProxyTerminate(void); + +#endif // __DNS_PROXY_H diff --git a/usr/src/cmd/cmd-inet/usr.lib/mdnsd/dnssec.h b/usr/src/contrib/mDNSResponder/mDNSCore/dnssec.h index b770af8de0..b770af8de0 100644 --- a/usr/src/cmd/cmd-inet/usr.lib/mdnsd/dnssec.h +++ b/usr/src/contrib/mDNSResponder/mDNSCore/dnssec.h diff --git a/usr/src/cmd/cmd-inet/usr.lib/mdnsd/mDNS.c b/usr/src/contrib/mDNSResponder/mDNSCore/mDNS.c index 69236e0b88..f51c22b287 100644..100755 --- a/usr/src/cmd/cmd-inet/usr.lib/mdnsd/mDNS.c +++ b/usr/src/contrib/mDNSResponder/mDNSCore/mDNS.c @@ -45,10 +45,14 @@ #endif #include "dns_sd.h" // for kDNSServiceFlags* definitions +#include "dns_sd_internal.h" #if APPLE_OSX_mDNSResponder #include <WebFilterDNS/WebFilterDNS.h> +// Delay in seconds before disabling multicast after there are no active queries or registrations. +#define BONJOUR_DISABLE_DELAY 60 + #if !NO_WCF WCFConnection *WCFConnectionNew(void) __attribute__((weak_import)); void WCFConnectionDealloc(WCFConnection* c) __attribute__((weak_import)); @@ -62,15 +66,22 @@ void WCFConnectionDealloc(WCFConnection* c) __attribute__((weak_import)); #define NO_WCF 1 #endif // APPLE_OSX_mDNSResponder -#if TARGET_OS_EMBEDDED +#if AWD_METRICS #include "Metrics.h" #endif +#if USE_DNS64 +#include "DNS64.h" +#endif + +#ifdef UNIT_TEST +#include "unittest.h" +#endif + // Forward declarations mDNSlocal void BeginSleepProcessing(mDNS *const m); mDNSlocal void RetrySPSRegistrations(mDNS *const m); -mDNSlocal void SendWakeup(mDNS *const m, mDNSInterfaceID InterfaceID, mDNSEthAddr *EthAddr, mDNSOpaque48 *password); -mDNSlocal mDNSBool CacheRecordRmvEventsForQuestion(mDNS *const m, DNSQuestion *q); +mDNSlocal void SendWakeup(mDNS *const m, mDNSInterfaceID InterfaceID, mDNSEthAddr *EthAddr, mDNSOpaque48 *password, mDNSBool unicastOnly); mDNSlocal mDNSBool LocalRecordRmvEventsForQuestion(mDNS *const m, DNSQuestion *q); mDNSlocal void mDNS_PurgeForQuestion(mDNS *const m, DNSQuestion *q); mDNSlocal void CheckForDNSSECRecords(mDNS *const m, DNSQuestion *q); @@ -106,16 +117,43 @@ mDNSlocal mDNSu8 *GetValueForMACAddr(mDNSu8 *ptr, mDNSu8 *limit, mDNSEthAddr *et #define NR_AnswerMulticast (mDNSu8*)~0 #define NR_AnswerUnicast (mDNSu8*)~1 -// Defined to set the kDNSQClass_UnicastResponse bit in the first four query packets. -// else, it's just set it the first query. -#define mDNS_REQUEST_UNICAST_RESPONSE 0 +// Question default timeout values +#define DEFAULT_MCAST_TIMEOUT 5 +#define DEFAULT_LO_OR_P2P_TIMEOUT 5 // The code (see SendQueries() and BuildQuestion()) needs to have the // RequestUnicast value set to a value one greater than the number of times you want the query // sent with the "request unicast response" (QU) bit set. #define SET_QU_IN_FIRST_QUERY 2 -#define SET_QU_IN_FIRST_FOUR_QUERIES 5 +#define kDefaultRequestUnicastCount SET_QU_IN_FIRST_QUERY + +// The time needed to offload records to a sleep proxy after powerd sends the kIOMessageSystemWillSleep notification +#define DARK_WAKE_DELAY_SLEEP 5 +#define kDarkWakeDelaySleep (mDNSPlatformOneSecond * DARK_WAKE_DELAY_SLEEP) + +// The maximum number of times we delay probing to prevent spurious conflicts due to stale packets +#define MAX_CONFLICT_PROCESSING_DELAYS 3 + +// RFC 6762 defines Passive Observation Of Failures (POOF) +// +// A host observes the multicast queries issued by the other hosts on +// the network. One of the major benefits of also sending responses +// using multicast is that it allows all hosts to see the responses +// (or lack thereof) to those queries. +// +// If a host sees queries, for which a record in its cache would be +// expected to be given as an answer in a multicast response, but no +// such answer is seen, then the host may take this as an indication +// that the record may no longer be valid. +// +// After seeing two or more of these queries, and seeing no multicast +// response containing the expected answer within ten seconds, then even +// though its TTL may indicate that it is not yet due to expire, that +// record SHOULD be flushed from the cache. +// +// <https://tools.ietf.org/html/rfc6762#section-10.5> +#define POOF_ENABLED 1 mDNSexport const char *const mDNS_DomainTypeNames[] = { @@ -136,8 +174,8 @@ mDNSexport const char *const mDNS_DomainTypeNames[] = #pragma mark - General Utility Functions #endif -// Returns true if this is a unique, authoritative LocalOnly record that answers questions of type -// A, AAAA , CNAME, or PTR. The caller should answer the question with this record and not send out +// Returns true if this is a unique, authoritative LocalOnly record that answers questions of type +// A, AAAA , CNAME, or PTR. The caller should answer the question with this record and not send out // the question on the wire if LocalOnlyRecordAnswersQuestion() also returns true. // Main use is to handle /etc/hosts records and the LocalOnly PTR records created for localhost. #define UniqueLocalOnlyRecord(rr) ((rr)->ARType == AuthRecordLocalOnly && \ @@ -248,24 +286,27 @@ mDNSlocal AuthEntity *GetAuthEntity(AuthHash *r, const AuthGroup *const Preserve return(e); } -mDNSexport AuthGroup *AuthGroupForName(AuthHash *r, const mDNSu32 slot, const mDNSu32 namehash, const domainname *const name) +mDNSexport AuthGroup *AuthGroupForName(AuthHash *r, const mDNSu32 namehash, const domainname *const name) { AuthGroup *ag; + const mDNSu32 slot = namehash % AUTH_HASH_SLOTS; + for (ag = r->rrauth_hash[slot]; ag; ag=ag->next) if (ag->namehash == namehash && SameDomainName(ag->name, name)) break; return(ag); } -mDNSexport AuthGroup *AuthGroupForRecord(AuthHash *r, const mDNSu32 slot, const ResourceRecord *const rr) +mDNSexport AuthGroup *AuthGroupForRecord(AuthHash *r, const ResourceRecord *const rr) { - return(AuthGroupForName(r, slot, rr->namehash, rr->name)); + return(AuthGroupForName(r, rr->namehash, rr->name)); } -mDNSlocal AuthGroup *GetAuthGroup(AuthHash *r, const mDNSu32 slot, const ResourceRecord *const rr) +mDNSlocal AuthGroup *GetAuthGroup(AuthHash *r, const ResourceRecord *const rr) { mDNSu16 namelen = DomainNameLength(rr->name); AuthGroup *ag = (AuthGroup*)GetAuthEntity(r, mDNSNULL); + const mDNSu32 slot = rr->namehash % AUTH_HASH_SLOTS; if (!ag) { LogMsg("GetAuthGroup: Failed to allocate memory for %##s", rr->name->c); return(mDNSNULL); } ag->next = r->rrauth_hash[slot]; ag->namehash = rr->namehash; @@ -284,9 +325,9 @@ mDNSlocal AuthGroup *GetAuthGroup(AuthHash *r, const mDNSu32 slot, const Resourc } AssignDomainName(ag->name, rr->name); - if (AuthGroupForRecord(r, slot, rr)) LogMsg("GetAuthGroup: Already have AuthGroup for %##s", rr->name->c); + if (AuthGroupForRecord(r, rr)) LogMsg("GetAuthGroup: Already have AuthGroup for %##s", rr->name->c); r->rrauth_hash[slot] = ag; - if (AuthGroupForRecord(r, slot, rr) != ag) LogMsg("GetAuthGroup: Not finding AuthGroup for %##s", rr->name->c); + if (AuthGroupForRecord(r, rr) != ag) LogMsg("GetAuthGroup: Not finding AuthGroup for %##s", rr->name->c); return(ag); } @@ -295,12 +336,12 @@ mDNSlocal AuthGroup *GetAuthGroup(AuthHash *r, const mDNSu32 slot, const Resourc mDNSexport AuthGroup *InsertAuthRecord(mDNS *const m, AuthHash *r, AuthRecord *rr) { AuthGroup *ag; - const mDNSu32 slot = AuthHashSlot(rr->resrec.name); - ag = AuthGroupForRecord(r, slot, &rr->resrec); - if (!ag) ag = GetAuthGroup(r, slot, &rr->resrec); // If we don't have a AuthGroup for this name, make one now + + (void)m; + ag = AuthGroupForRecord(r, &rr->resrec); + if (!ag) ag = GetAuthGroup(r, &rr->resrec); // If we don't have a AuthGroup for this name, make one now if (ag) { - LogInfo("InsertAuthRecord: inserting auth record %s from table", ARDisplayString(m, rr)); *(ag->rrauth_tail) = rr; // Append this record to tail of cache slot list ag->rrauth_tail = &(rr->next); // Advance tail pointer } @@ -310,13 +351,11 @@ mDNSexport AuthGroup *InsertAuthRecord(mDNS *const m, AuthHash *r, AuthRecord *r mDNSexport AuthGroup *RemoveAuthRecord(mDNS *const m, AuthHash *r, AuthRecord *rr) { AuthGroup *a; - AuthGroup **ag = &a; AuthRecord **rp; - const mDNSu32 slot = AuthHashSlot(rr->resrec.name); - a = AuthGroupForRecord(r, slot, &rr->resrec); + a = AuthGroupForRecord(r, &rr->resrec); if (!a) { LogMsg("RemoveAuthRecord: ERROR!! AuthGroup not found for %s", ARDisplayString(m, rr)); return mDNSNULL; } - rp = &(*ag)->members; + rp = &a->members; while (*rp) { if (*rp != rr) @@ -330,22 +369,23 @@ mDNSexport AuthGroup *RemoveAuthRecord(mDNS *const m, AuthHash *r, AuthRecord *r } } // TBD: If there are no more members, release authgroup ? - (*ag)->rrauth_tail = rp; + a->rrauth_tail = rp; return a; } -mDNSexport CacheGroup *CacheGroupForName(const mDNS *const m, const mDNSu32 slot, const mDNSu32 namehash, const domainname *const name) +mDNSexport CacheGroup *CacheGroupForName(const mDNS *const m, const mDNSu32 namehash, const domainname *const name) { CacheGroup *cg; + mDNSu32 slot = HashSlotFromNameHash(namehash); for (cg = m->rrcache_hash[slot]; cg; cg=cg->next) if (cg->namehash == namehash && SameDomainName(cg->name, name)) break; return(cg); } -mDNSlocal CacheGroup *CacheGroupForRecord(const mDNS *const m, const mDNSu32 slot, const ResourceRecord *const rr) +mDNSlocal CacheGroup *CacheGroupForRecord(const mDNS *const m, const ResourceRecord *const rr) { - return(CacheGroupForName(m, slot, rr->namehash, rr->name)); + return(CacheGroupForName(m, rr->namehash, rr->name)); } mDNSexport mDNSBool mDNS_AddressIsLocalSubnet(mDNS *const m, const mDNSInterfaceID InterfaceID, const mDNSAddr *addr) @@ -391,7 +431,7 @@ mDNSlocal NetworkInterfaceInfo *FirstIPv4LLInterfaceForID(mDNS *const m, const m if (!InterfaceID) return mDNSNULL; - // Note: We don't check for InterfaceActive, as the active interface could be IPv6 and + // Note: We don't check for InterfaceActive, as the active interface could be IPv6 and // we still want to find the first IPv4 Link-Local interface for (intf = m->HostInterfaces; intf; intf = intf->next) { @@ -412,14 +452,15 @@ mDNSexport char *InterfaceNameForID(mDNS *const m, const mDNSInterfaceID Interfa } // Caller should hold the lock -mDNSlocal void GenerateNegativeResponse(mDNS *const m, QC_result qc) +mDNSlocal void GenerateNegativeResponse(mDNS *const m, mDNSInterfaceID InterfaceID, QC_result qc) { DNSQuestion *q; if (!m->CurrentQuestion) { LogMsg("GenerateNegativeResponse: ERROR!! CurrentQuestion not set"); return; } q = m->CurrentQuestion; LogInfo("GenerateNegativeResponse: Generating negative response for question %##s (%s)", q->qname.c, DNSTypeName(q->qtype)); - MakeNegativeCacheRecord(m, &m->rec.r, &q->qname, q->qnamehash, q->qtype, q->qclass, 60, mDNSInterface_Any, mDNSNULL); + MakeNegativeCacheRecord(m, &m->rec.r, &q->qname, q->qnamehash, q->qtype, q->qclass, 60, InterfaceID, mDNSNULL); + // We need to force the response through in the following cases // // a) SuppressUnusable questions that are suppressed @@ -446,29 +487,11 @@ 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; +#if AWD_METRICS + uDNSMetrics metrics; #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)); - q->LocalSocket = mDNSNULL; - } - else - { - sock = mDNSNULL; - } + q->LocalSocket = mDNSNULL; // The SameDomainName check above is to ignore bogus CNAME records that point right back at // themselves. Without that check we can get into a case where we have two duplicate questions, @@ -488,30 +511,25 @@ 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) +#if AWD_METRICS + if ((q->CNAMEReferrals == 0) && !q->metrics.originalQName) { - originalQName = q->metrics.originalQName; - q->metrics.originalQName = mDNSNULL; - } - else - { - mDNSu16 qNameLen; + domainname * qName; + mDNSu16 qNameLen; qNameLen = DomainNameLength(&q->qname); if ((qNameLen > 0) && (qNameLen <= MAX_DOMAIN_NAME)) { - originalQName = mDNSPlatformMemAllocate(qNameLen); - if (originalQName) + qName = mDNSPlatformMemAllocate(qNameLen); + if (qName) { - mDNSPlatformMemCopy(originalQName->c, q->qname.c, qNameLen); + mDNSPlatformMemCopy(qName->c, q->qname.c, qNameLen); + q->metrics.originalQName = qName; } } - else - { - originalQName = mDNSNULL; - } } + metrics = q->metrics; + mDNSPlatformMemZero(&q->metrics, sizeof(q->metrics)); #endif mDNS_StopQuery_internal(m, q); // Stop old query AssignDomainName(&q->qname, &rr->rdata->u.name); // Update qname @@ -529,20 +547,97 @@ 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; +#if AWD_METRICS + q->metrics = metrics; #endif if (sock) { - // We have a message waiting and that should answer this question. - if (q->LocalSocket) - mDNSPlatformUDPClose(q->LocalSocket); - q->LocalSocket = sock; - q->TargetQID = id; + // If our new query is a duplicate, then it can't have a socket of its own, so we have to close the one we saved. + if (q->DuplicateOf) mDNSPlatformUDPClose(sock); + else + { + // Transplant the old socket into the new question, and copy the query ID across too. + // No need to close the old q->LocalSocket value because it won't have been created yet (they're made lazily on-demand). + q->LocalSocket = sock; + q->TargetQID = id; + } } } } +#ifdef USE_LIBIDN + +#include <unicode/uidna.h> + +// #define DEBUG_PUNYCODE 1 + +mDNSlocal mDNSu8 *PunycodeConvert(const mDNSu8 *const src, mDNSu8 *const dst, const mDNSu8 *const end) +{ + UErrorCode errorCode = U_ZERO_ERROR; + UIDNAInfo info = UIDNA_INFO_INITIALIZER; + UIDNA *uts46 = uidna_openUTS46(UIDNA_USE_STD3_RULES|UIDNA_NONTRANSITIONAL_TO_UNICODE, &errorCode); + int32_t len = uidna_nameToASCII_UTF8(uts46, (const char *)src+1, src[0], (char *)dst+1, end-(dst+1), &info, &errorCode); + uidna_close(uts46); + #if DEBUG_PUNYCODE + if (errorCode) LogMsg("uidna_nameToASCII_UTF8(%##s) failed errorCode %d", src, errorCode); + if (info.errors) LogMsg("uidna_nameToASCII_UTF8(%##s) failed info.errors 0x%08X", src, info.errors); + if (len > MAX_DOMAIN_LABEL) LogMsg("uidna_nameToASCII_UTF8(%##s) result too long %d", src, len); + #endif + if (errorCode || info.errors || len > MAX_DOMAIN_LABEL) return mDNSNULL; + *dst = len; + return(dst + 1 + len); +} + +mDNSlocal mDNSBool IsHighASCIILabel(const mDNSu8 *d) +{ + int i; + for (i=1; i<=d[0]; i++) if (d[i] & 0x80) return mDNStrue; + return mDNSfalse; +} + +mDNSlocal const mDNSu8 *FindLastHighASCIILabel(const domainname *const d) +{ + const mDNSu8 *ptr = d->c; + const mDNSu8 *ans = mDNSNULL; + while (ptr[0]) + { + const mDNSu8 *const next = ptr + 1 + ptr[0]; + if (ptr[0] > MAX_DOMAIN_LABEL || next >= d->c + MAX_DOMAIN_NAME) return mDNSNULL; + if (IsHighASCIILabel(ptr)) ans = ptr; + ptr = next; + } + return ans; +} + +mDNSlocal mDNSBool PerformNextPunycodeConversion(const DNSQuestion *const q, domainname *const newname) +{ + const mDNSu8 *h = FindLastHighASCIILabel(&q->qname); + #if DEBUG_PUNYCODE + LogMsg("PerformNextPunycodeConversion: %##s (%s) Last High-ASCII Label %##s", q->qname.c, DNSTypeName(q->qtype), h); + #endif + if (!h) return mDNSfalse; // There are no high-ascii labels to convert + + mDNSu8 *const dst = PunycodeConvert(h, newname->c + (h - q->qname.c), newname->c + MAX_DOMAIN_NAME); + if (!dst) + return mDNSfalse; // The label was not convertible to Punycode + else + { + // If Punycode conversion of final eligible label was successful, copy the rest of the domainname + const mDNSu8 *const src = h + 1 + h[0]; + const mDNSu8 remainder = DomainNameLength((domainname*)src); + if (dst + remainder > newname->c + MAX_DOMAIN_NAME) return mDNSfalse; // Name too long -- cannot be converted to Punycode + + mDNSPlatformMemCopy(newname->c, q->qname.c, h - q->qname.c); // Fill in the leading part + mDNSPlatformMemCopy(dst, src, remainder); // Fill in the trailing part + #if DEBUG_PUNYCODE + LogMsg("PerformNextPunycodeConversion: %##s converted to %##s", q->qname.c, newname->c); + #endif + return mDNStrue; + } +} + +#endif // USE_LIBIDN + // For a single given DNSQuestion pointed to by CurrentQuestion, deliver an add/remove result for the single given AuthRecord // Note: All the callers should use the m->CurrentQuestion to see if the question is still valid or not mDNSlocal void AnswerLocalQuestionWithLocalAuthRecord(mDNS *const m, AuthRecord *rr, QC_result AddRecord) @@ -707,7 +802,6 @@ mDNSlocal void AnswerAllLocalQuestionsWithLocalAuthRecord(mDNS *const m, AuthRec (X) &kDNSRecordTypeActiveUniqueMask ? DefaultAnnounceIntervalForTypeUnique : 0) #define TimeToAnnounceThisRecord(RR,time) ((RR)->AnnounceCount && (time) - ((RR)->LastAPTime + (RR)->ThisAPInterval) >= 0) -#define TimeToSendThisRecord(RR,time) ((TimeToAnnounceThisRecord(RR,time) || (RR)->ImmedAnswer) && ResourceRecordIsValidAnswer(RR)) #define TicksTTL(RR) ((mDNSs32)(RR)->resrec.rroriginalttl * mDNSPlatformOneSecond) #define RRExpireTime(RR) ((RR)->TimeRcvd + TicksTTL(RR)) @@ -766,6 +860,8 @@ mDNSlocal mDNSBool PacketRRMatchesSignature(const CacheRecord *const pktrr, cons pktrr->resrec.InterfaceID != authrr->resrec.InterfaceID) return(mDNSfalse); if (!(authrr->resrec.RecordType & kDNSRecordTypeUniqueMask) || authrr->WakeUp.HMAC.l[0]) if (pktrr->resrec.rrtype != authrr->resrec.rrtype) return(mDNSfalse); + if ((authrr->resrec.InterfaceID == mDNSInterface_Any) && + !mDNSPlatformValidRecordForInterface(authrr, pktrr->resrec.InterfaceID)) return(mDNSfalse); return (mDNSBool)( pktrr->resrec.rrclass == authrr->resrec.rrclass && pktrr->resrec.namehash == authrr->resrec.namehash && @@ -843,11 +939,12 @@ mDNSlocal void InitializeLastAPTime(mDNS *const m, AuthRecord *const rr) if (m->SuppressProbes == 0 || m->SuppressProbes - m->timenow < 0) { // To allow us to aggregate probes when a group of services are registered together, - // the first probe is delayed 1/4 second. This means the common-case behaviour is: - // 1/4 second wait; probe + // the first probe is delayed by a random delay in the range 1/8 to 1/4 second. + // This means the common-case behaviour is: + // randomized wait; probe // 1/4 second wait; probe // 1/4 second wait; probe - // 1/4 second wait; announce (i.e. service is normally announced exactly one second after being registered) + // 1/4 second wait; announce (i.e. service is normally announced 7/8 to 1 second after being registered) m->SuppressProbes = NonZeroTime(m->timenow + DefaultProbeIntervalForTypeUnique/2 + mDNSRandom(DefaultProbeIntervalForTypeUnique/2)); // If we already have a *probe* scheduled to go out sooner, then use that time to get better aggregation @@ -879,7 +976,9 @@ mDNSlocal void InitializeLastAPTime(mDNS *const m, AuthRecord *const rr) } rr->LastAPTime = m->SuppressProbes - rr->ThisAPInterval; } - else if (m->SuppressProbes && m->SuppressProbes - m->timenow >= 0) + // Skip kDNSRecordTypeKnownUnique and kDNSRecordTypeShared records here and set their LastAPTime in the "else" block below so + // that they get announced immediately, otherwise, their announcement would be delayed until the based on the SuppressProbes value. + else if ((rr->resrec.RecordType != kDNSRecordTypeKnownUnique) && (rr->resrec.RecordType != kDNSRecordTypeShared) && m->SuppressProbes && (m->SuppressProbes - m->timenow >= 0)) rr->LastAPTime = m->SuppressProbes - rr->ThisAPInterval + DefaultProbeIntervalForTypeUnique * DefaultProbeCountForTypeUnique + rr->ThisAPInterval / 2; else rr->LastAPTime = m->timenow - rr->ThisAPInterval; @@ -890,7 +989,7 @@ mDNSlocal void InitializeLastAPTime(mDNS *const m, AuthRecord *const rr) // and we can begin broadcasting our announcements to take over ownership of that IP address. // If we don't wait for the client to go to sleep, then when the client sees our ARP Announcements there's a risk // (depending on the OS and networking stack it's using) that it might interpret it as a conflict and change its IP address. - if (rr->AddressProxy.type) + if (rr->AddressProxy.type) rr->LastAPTime = m->timenow; // Set LastMCTime to now, to inhibit multicast responses @@ -1068,26 +1167,24 @@ mDNSexport void ActivateUnicastRegistration(mDNS *const m, AuthRecord *const rr) mDNSlocal AuthRecord *CheckAuthIdenticalRecord(AuthHash *r, AuthRecord *rr) { - AuthGroup *a; - AuthGroup **ag = &a; - AuthRecord **rp; - const mDNSu32 slot = AuthHashSlot(rr->resrec.name); + const AuthGroup *a; + AuthRecord *rp; - a = AuthGroupForRecord(r, slot, &rr->resrec); + a = AuthGroupForRecord(r, &rr->resrec); if (!a) return mDNSNULL; - rp = &(*ag)->members; - while (*rp) + rp = a->members; + while (rp) { - if (!RecordIsLocalDuplicate(*rp, rr)) - rp=&(*rp)->next; + if (!RecordIsLocalDuplicate(rp, rr)) + rp = rp->next; else { - if ((*rp)->resrec.RecordType == kDNSRecordTypeDeregistering) + if (rp->resrec.RecordType == kDNSRecordTypeDeregistering) { - (*rp)->AnnounceCount = 0; - rp=&(*rp)->next; + rp->AnnounceCount = 0; + rp = rp->next; } - else return *rp; + else return rp; } } return (mDNSNULL); @@ -1095,22 +1192,20 @@ mDNSlocal AuthRecord *CheckAuthIdenticalRecord(AuthHash *r, AuthRecord *rr) mDNSlocal mDNSBool CheckAuthRecordConflict(AuthHash *r, AuthRecord *rr) { - AuthGroup *a; - AuthGroup **ag = &a; - AuthRecord **rp; - const mDNSu32 slot = AuthHashSlot(rr->resrec.name); + const AuthGroup *a; + const AuthRecord *rp; - a = AuthGroupForRecord(r, slot, &rr->resrec); + a = AuthGroupForRecord(r, &rr->resrec); if (!a) return mDNSfalse; - rp = &(*ag)->members; - while (*rp) + rp = a->members; + while (rp) { const AuthRecord *s1 = rr->RRSet ? rr->RRSet : rr; - const AuthRecord *s2 = (*rp)->RRSet ? (*rp)->RRSet : *rp; - if (s1 != s2 && SameResourceRecordSignature((*rp), rr) && !IdenticalSameNameRecord(&(*rp)->resrec, &rr->resrec)) + const AuthRecord *s2 = rp->RRSet ? rp->RRSet : rp; + if (s1 != s2 && SameResourceRecordSignature(rp, rr) && !IdenticalSameNameRecord(&rp->resrec, &rr->resrec)) return mDNStrue; else - rp=&(*rp)->next; + rp = rp->next; } return (mDNSfalse); } @@ -1118,21 +1213,19 @@ mDNSlocal mDNSBool CheckAuthRecordConflict(AuthHash *r, AuthRecord *rr) // checks to see if "rr" is already present mDNSlocal AuthRecord *CheckAuthSameRecord(AuthHash *r, AuthRecord *rr) { - AuthGroup *a; - AuthGroup **ag = &a; - AuthRecord **rp; - const mDNSu32 slot = AuthHashSlot(rr->resrec.name); + const AuthGroup *a; + AuthRecord *rp; - a = AuthGroupForRecord(r, slot, &rr->resrec); + a = AuthGroupForRecord(r, &rr->resrec); if (!a) return mDNSNULL; - rp = &(*ag)->members; - while (*rp) + rp = a->members; + while (rp) { - if (*rp != rr) - rp=&(*rp)->next; + if (rp != rr) + rp = rp->next; else { - return *rp; + return rp; } } return (mDNSNULL); @@ -1158,20 +1251,22 @@ mDNSlocal void DecrementAutoTargetServices(mDNS *const m, AuthRecord *const rr) LogInfo("DecrementAutoTargetServices: AutoTargetServices %d Record %s", m->AutoTargetServices, ARDisplayString(m, rr)); } -#if TARGET_OS_WATCH +#if BONJOUR_ON_DEMAND if (!AuthRecord_uDNS(rr)) { if (m->NumAllInterfaceRecords + m->NumAllInterfaceQuestions == 1) - m->NetworkChanged = m->timenow; + m->NextBonjourDisableTime = NonZeroTime(m->timenow + (BONJOUR_DISABLE_DELAY * mDNSPlatformOneSecond)); m->NumAllInterfaceRecords--; LogInfo("DecrementAutoTargetServices: NumAllInterfaceRecords %d NumAllInterfaceQuestions %d %s", m->NumAllInterfaceRecords, m->NumAllInterfaceQuestions, ARDisplayString(m, rr)); } -#endif +#endif // BONJOUR_ON_DEMAND } mDNSlocal void IncrementAutoTargetServices(mDNS *const m, AuthRecord *const rr) { + mDNSBool enablingBonjour = 0; + if (RRLocalOnly(rr)) { // A sanity check, this should be prevented in calling code. @@ -1179,34 +1274,51 @@ mDNSlocal void IncrementAutoTargetServices(mDNS *const m, AuthRecord *const rr) return; } -#if TARGET_OS_WATCH +#if BONJOUR_ON_DEMAND if (!AuthRecord_uDNS(rr)) { 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; + { + m->NextBonjourDisableTime = 0; + if (m->BonjourEnabled == 0) + { + // Enable Bonjour immediately by scheduling network changed processing where + // we will join the multicast group on each active interface. + m->BonjourEnabled = 1; + enablingBonjour = 1; + m->NetworkChanged = m->timenow; + } + } } -#endif +#endif // BONJOUR_ON_DEMAND if (!AuthRecord_uDNS(rr) && rr->resrec.rrtype == kDNSType_SRV && rr->AutoTarget == Target_AutoHost) { m->AutoTargetServices++; LogInfo("IncrementAutoTargetServices: AutoTargetServices %d Record %s", m->AutoTargetServices, ARDisplayString(m, rr)); - // If this is the first advertised service - if (m->AutoTargetServices == 1) + + // If this is the first advertised service and we did not just enable Bonjour above, then + // advertise all the interface records. If we did enable Bonjour above, the interface records will + // be advertised during the network changed processing scheduled above, so no need + // to do it here. + if ((m->AutoTargetServices == 1) && (enablingBonjour == 0)) AdvertiseAllInterfaceRecords(m); } } mDNSlocal void getKeepaliveRaddr(mDNS *const m, AuthRecord *rr, mDNSAddr *raddr) { - mDNSAddr laddr; - mDNSEthAddr eth; - mDNSIPPort lport, rport; - mDNSu32 timeout, seq, ack; - mDNSu16 win; + mDNSAddr laddr = zeroAddr; + mDNSEthAddr eth = zeroEthAddr; + mDNSIPPort lport = zeroIPPort; + mDNSIPPort rport = zeroIPPort; + mDNSu32 timeout = 0; + mDNSu32 seq = 0; + mDNSu32 ack = 0; + mDNSu16 win = 0; if (mDNS_KeepaliveRecord(&rr->resrec)) { @@ -1285,9 +1397,9 @@ mDNSexport mStatus mDNS_Register_internal(mDNS *const m, AuthRecord *const rr) { if (rr->resrec.RecordType == kDNSRecordTypeUnique) rr->resrec.RecordType = kDNSRecordTypeVerified; - else + else if (rr->resrec.RecordType != kDNSRecordTypeKnownUnique) { - LogMsg("mDNS_Register_internal: ERROR! %##s (%s): rr->DependentOn && RecordType != kDNSRecordTypeUnique", + LogMsg("mDNS_Register_internal: ERROR! %##s (%s): rr->DependentOn && RecordType != kDNSRecordTypeUnique or kDNSRecordTypeKnownUnique", rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype)); return(mStatus_Invalid); } @@ -1305,15 +1417,15 @@ mDNSexport mStatus mDNS_Register_internal(mDNS *const m, AuthRecord *const rr) // Set up by client prior to call // Field Group 2: Persistent metadata for Authoritative Records -// rr->Additional1 = set to mDNSNULL in mDNS_SetupResourceRecord; may be overridden by client -// rr->Additional2 = set to mDNSNULL in mDNS_SetupResourceRecord; may be overridden by client -// rr->DependentOn = set to mDNSNULL in mDNS_SetupResourceRecord; may be overridden by client -// rr->RRSet = set to mDNSNULL in mDNS_SetupResourceRecord; may be overridden by client -// rr->Callback = already set in mDNS_SetupResourceRecord -// rr->Context = already set in mDNS_SetupResourceRecord -// rr->RecordType = already set in mDNS_SetupResourceRecord -// rr->HostTarget = set to mDNSfalse in mDNS_SetupResourceRecord; may be overridden by client -// rr->AllowRemoteQuery = set to mDNSfalse in mDNS_SetupResourceRecord; may be overridden by client +// rr->Additional1 = set to mDNSNULL in mDNS_SetupResourceRecord; may be overridden by client +// rr->Additional2 = set to mDNSNULL in mDNS_SetupResourceRecord; may be overridden by client +// rr->DependentOn = set to mDNSNULL in mDNS_SetupResourceRecord; may be overridden by client +// rr->RRSet = set to mDNSNULL in mDNS_SetupResourceRecord; may be overridden by client +// rr->Callback = already set in mDNS_SetupResourceRecord +// rr->Context = already set in mDNS_SetupResourceRecord +// rr->RecordType = already set in mDNS_SetupResourceRecord +// rr->HostTarget = set to mDNSfalse in mDNS_SetupResourceRecord; may be overridden by client +// rr->AllowRemoteQuery = set to mDNSfalse in mDNS_SetupResourceRecord; may be overridden by client // Make sure target is not uninitialized data, or we may crash writing debugging log messages if (rr->AutoTarget && target) target->c[0] = 0; @@ -1336,9 +1448,9 @@ mDNSexport mStatus mDNS_Register_internal(mDNS *const m, AuthRecord *const rr) rr->NR_AnswerTo = mDNSNULL; rr->NR_AdditionalTo = mDNSNULL; if (!rr->AutoTarget) InitializeLastAPTime(m, rr); -// rr->LastAPTime = Set for us in InitializeLastAPTime() -// rr->LastMCTime = Set for us in InitializeLastAPTime() -// rr->LastMCInterface = Set for us in InitializeLastAPTime() +// rr->LastAPTime = Set for us in InitializeLastAPTime() +// rr->LastMCTime = Set for us in InitializeLastAPTime() +// rr->LastMCInterface = Set for us in InitializeLastAPTime() rr->NewRData = mDNSNULL; rr->newrdlength = 0; rr->UpdateCallback = mDNSNULL; @@ -1371,12 +1483,12 @@ mDNSexport mStatus mDNS_Register_internal(mDNS *const m, AuthRecord *const rr) // times with different values if the external NAT port changes during the lifetime of the service registration. //if (rr->resrec.rrtype == kDNSType_SRV) rr->NATinfo.IntPort = rr->resrec.rdata->u.srv.port; -// rr->resrec.interface = already set in mDNS_SetupResourceRecord -// rr->resrec.name->c = MUST be set by client -// rr->resrec.rrtype = already set in mDNS_SetupResourceRecord -// rr->resrec.rrclass = already set in mDNS_SetupResourceRecord -// rr->resrec.rroriginalttl = already set in mDNS_SetupResourceRecord -// rr->resrec.rdata = MUST be set by client, unless record type is CNAME or PTR and rr->HostTarget is set +// rr->resrec.interface = already set in mDNS_SetupResourceRecord +// rr->resrec.name->c = MUST be set by client +// rr->resrec.rrtype = already set in mDNS_SetupResourceRecord +// rr->resrec.rrclass = already set in mDNS_SetupResourceRecord +// rr->resrec.rroriginalttl = already set in mDNS_SetupResourceRecord +// rr->resrec.rdata = MUST be set by client, unless record type is CNAME or PTR and rr->HostTarget is set // BIND named (name daemon) doesn't allow TXT records with zero-length rdata. This is strictly speaking correct, // since RFC 1035 specifies a TXT record as "One or more <character-string>s", not "Zero or more <character-string>s". @@ -1471,7 +1583,7 @@ mDNSexport mStatus mDNS_Register_internal(mDNS *const m, AuthRecord *const rr) if (r) { - debugf("mDNS_Register_internal:Adding to duplicate list %s", ARDisplayString(m,rr)); + LogInfo("mDNS_Register_internal: Adding to duplicate list %s", ARDisplayString(m,rr)); *d = rr; // If the previous copy of this record is already verified unique, // then indicate that we should move this record promptly to kDNSRecordTypeUnique state. @@ -1482,7 +1594,7 @@ mDNSexport mStatus mDNS_Register_internal(mDNS *const m, AuthRecord *const rr) } else { - debugf("mDNS_Register_internal: Adding to active record list %s", ARDisplayString(m,rr)); + LogInfo("mDNS_Register_internal: Adding to active record list %s", ARDisplayString(m,rr)); if (RRLocalOnly(rr)) { AuthGroup *ag; @@ -1504,6 +1616,19 @@ 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. + 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); + + // Adding a record may affect whether or not we should sleep + mDNS_UpdateAllowSleep(m); + } + // 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 (!rr->WakeUp.HMAC.l[0] && mDNS_KeepaliveRecord(&rr->resrec)) @@ -1516,20 +1641,7 @@ mDNSexport mStatus mDNS_Register_internal(mDNS *const m, AuthRecord *const rr) 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 - mDNSPlatformGetRemoteMacAddr(m, &raddr); - } - - 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. - 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); - - // Adding a record may affect whether or not we should sleep - mDNS_UpdateAllowSleep(m); + mDNSPlatformGetRemoteMacAddr(&raddr); } return(mStatus_NoError); @@ -1577,13 +1689,11 @@ mDNSexport mStatus mDNS_Deregister_internal(mDNS *const m, AuthRecord *const rr, if (RRLocalOnly(rr)) { AuthGroup *a; - AuthGroup **ag = &a; AuthRecord **rp; - const mDNSu32 slot = AuthHashSlot(rr->resrec.name); - a = AuthGroupForRecord(&m->rrauth, slot, &rr->resrec); + a = AuthGroupForRecord(&m->rrauth, &rr->resrec); if (!a) return mDNSfalse; - rp = &(*ag)->members; + rp = &a->members; while (*rp && *rp != rr) rp=&(*rp)->next; p = rp; } @@ -1793,7 +1903,7 @@ mDNSexport mStatus mDNS_Deregister_internal(mDNS *const m, AuthRecord *const rr, if (drt != mDNS_Dereg_conflict) { mDNS_DropLockBeforeCallback(); // Allow client to legally make mDNS API calls from the callback - LogInfo("mDNS_Deregister_internal: mStatus_MemFree for %s", ARDisplayString(m, rr)); + LogInfo("mDNS_Deregister_internal: callback with mStatus_MemFree for %s", ARDisplayString(m, rr)); if (rr->RecordCallback) rr->RecordCallback(m, rr, mStatus_MemFree); // MUST NOT touch rr after this mDNS_ReclaimLockAfterCallback(); // Decrement mDNS_reentrancy to block mDNS API calls again @@ -1817,6 +1927,10 @@ mDNSexport mStatus mDNS_Deregister_internal(mDNS *const m, AuthRecord *const rr, } else { +#if APPLE_OSX_mDNSResponder + // See if this record was also registered with any D2D plugins. + D2D_stop_advertising_record(r2); +#endif mDNS_Deregister_internal(m, r2, mDNS_Dereg_conflict); // As this is a duplicate record, it will be unlinked from the list // immediately @@ -1850,6 +1964,27 @@ mDNSlocal void AddRecordToResponseList(AuthRecord ***nrpp, AuthRecord *rr, AuthR debugf("AddRecordToResponseList: %##s (%s) already in list", rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype)); } +mDNSlocal void AddRRSetAdditionalsToResponseList(mDNS *const m, AuthRecord ***nrpp, AuthRecord *rr, AuthRecord *additional, const mDNSInterfaceID InterfaceID) +{ + AuthRecord *rr2; + if (additional->resrec.RecordType & kDNSRecordTypeUniqueMask) + { + for (rr2 = m->ResourceRecords; rr2; rr2 = rr2->next) + { + if ((rr2->resrec.namehash == additional->resrec.namehash) && + (rr2->resrec.rrtype == additional->resrec.rrtype) && + (rr2 != additional) && + (rr2->resrec.RecordType & kDNSRecordTypeUniqueMask) && + (rr2->resrec.rrclass == additional->resrec.rrclass) && + ResourceRecordIsValidInterfaceAnswer(rr2, InterfaceID) && + SameDomainName(rr2->resrec.name, additional->resrec.name)) + { + AddRecordToResponseList(nrpp, rr2, rr); + } + } + } +} + mDNSlocal void AddAdditionalsToResponseList(mDNS *const m, AuthRecord *ResponseRecords, AuthRecord ***nrpp, const mDNSInterfaceID InterfaceID) { AuthRecord *rr, *rr2; @@ -1858,10 +1993,16 @@ mDNSlocal void AddAdditionalsToResponseList(mDNS *const m, AuthRecord *ResponseR // (Note: This is an "if", not a "while". If we add a record, we'll find it again // later in the "for" loop, and we will follow further "additional" links then.) if (rr->Additional1 && ResourceRecordIsValidInterfaceAnswer(rr->Additional1, InterfaceID)) + { AddRecordToResponseList(nrpp, rr->Additional1, rr); + AddRRSetAdditionalsToResponseList(m, nrpp, rr, rr->Additional1, InterfaceID); + } if (rr->Additional2 && ResourceRecordIsValidInterfaceAnswer(rr->Additional2, InterfaceID)) + { AddRecordToResponseList(nrpp, rr->Additional2, rr); + AddRRSetAdditionalsToResponseList(m, nrpp, rr, rr->Additional2, InterfaceID); + } // For SRV records, automatically add the Address record(s) for the target host if (rr->resrec.rrtype == kDNSType_SRV) @@ -1927,9 +2068,8 @@ mDNSlocal void SendDelayedUnicastResponse(mDNS *const m, const mDNSAddr *const d rr->v6Requester = zerov6Addr; // Only sent records registered for P2P over P2P interfaces - if (intf && !mDNSPlatformValidRecordForInterface(rr, intf)) + if (intf && !mDNSPlatformValidRecordForInterface(rr, intf->InterfaceID)) { - LogInfo("SendDelayedUnicastResponse: Not sending %s, on %s", ARDisplayString(m, rr), InterfaceNameForID(m, InterfaceID)); continue; } @@ -2036,7 +2176,7 @@ mDNSexport void CompleteDeregistration(mDNS *const m, AuthRecord *rr) rr->resrec.RecordType = kDNSRecordTypeShared; rr->RequireGoodbye = mDNSfalse; rr->WakeUp.HMAC = zeroEthAddr; - if (rr->AnsweredLocalQ) { AnswerAllLocalQuestionsWithLocalAuthRecord(m, rr, QC_rmv); rr->AnsweredLocalQ = mDNSfalse; } + if (rr->AnsweredLocalQ) { AnswerAllLocalQuestionsWithLocalAuthRecord(m, rr, mDNSfalse); rr->AnsweredLocalQ = mDNSfalse; } mDNS_Deregister_internal(m, rr, mDNS_Dereg_normal); // Don't touch rr after this } @@ -2224,11 +2364,7 @@ mDNSlocal void SendNDP(mDNS *const m, const mDNSu8 op, const mDNSu8 flags, const // *ptr++ = tpa->b[0xF]; // 0x06 Source address (Note: Since we don't currently set the BIOCSHDRCMPLT option, BPF will fill in the real interface address for us) - for (i=0; i<6; i++) - if (tha) - *ptr++ = tha->b[i]; - else - *ptr++ = intf->MAC.b[i]; + for (i=0; i<6; i++) *ptr++ = (tha ? *tha : intf->MAC).b[i]; // 0x0C IPv6 Ethertype (0x86DD) *ptr++ = 0x86; *ptr++ = 0xDD; @@ -2265,11 +2401,7 @@ mDNSlocal void SendNDP(mDNS *const m, const mDNSu8 op, const mDNSu8 flags, const { *ptr++ = NDP_SrcLL; // Option Type 1 == Source Link-layer Address *ptr++ = 0x01; // Option length 1 (in units of 8 octets) - for (i=0; i<6; i++) - if (tha) - *ptr++ = tha->b[i]; - else - *ptr++ = intf->MAC.b[i]; + for (i=0; i<6; i++) *ptr++ = (tha ? *tha : intf->MAC).b[i]; } } else // Neighbor Advertisement. The NDP "target" is the address we're giving information about. @@ -2279,11 +2411,7 @@ mDNSlocal void SendNDP(mDNS *const m, const mDNSu8 op, const mDNSu8 flags, const // 0x4E Target Link-layer Address *ptr++ = NDP_TgtLL; // Option Type 2 == Target Link-layer Address *ptr++ = 0x01; // Option length 1 (in units of 8 octets) - for (i=0; i<6; i++) - if (tha) - *ptr++ = tha->b[i]; - else - *ptr++ = intf->MAC.b[i]; + for (i=0; i<6; i++) *ptr++ = (tha ? *tha : intf->MAC).b[i]; } // 0x4E or 0x56 Total NDP Packet length 78 or 86 bytes @@ -2355,6 +2483,22 @@ mDNSlocal mDNSBool ShouldSendGoodbyesBeforeSleep(mDNS *const m, const NetworkInt } } +mDNSlocal mDNSBool IsInterfaceValidForAuthRecord(const AuthRecord *ar, mDNSInterfaceID InterfaceID) +{ + mDNSBool result; + + if (ar->resrec.InterfaceID == mDNSInterface_Any) + { + result = mDNSPlatformValidRecordForInterface(ar, InterfaceID); + } + else + { + result = (ar->resrec.InterfaceID == InterfaceID); + } + + return(result); +} + // Note about acceleration of announcements to facilitate automatic coalescing of // multiple independent threads of announcements into a single synchronized thread: // The announcements in the packet may be at different stages of maturity; @@ -2378,7 +2522,7 @@ mDNSlocal void SendResponses(mDNS *const m) mDNSs32 maxExistingAnnounceInterval = 0; const NetworkInterfaceInfo *intf = GetFirstActiveInterface(m->HostInterfaces); - m->NextScheduledResponse = m->timenow + 0x78000000; + m->NextScheduledResponse = m->timenow + FutureTime; if (m->SleepState == SleepState_Transferring) RetrySPSRegistrations(m); @@ -2416,8 +2560,10 @@ mDNSlocal void SendResponses(mDNS *const m) } else { + mDNSBool unicastOnly; 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); + unicastOnly = ((rr->AnnounceCount == WakeupCount) || (rr->AnnounceCount == WakeupCount - 1)) ? mDNStrue : mDNSfalse; + SendWakeup(m, rr->resrec.InterfaceID, &rr->WakeUp.IMAC, &rr->WakeUp.password, unicastOnly); for (r2 = rr; r2; r2=r2->next) 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)) @@ -2518,17 +2664,28 @@ mDNSlocal void SendResponses(mDNS *const m) if (rr->ImmedAnswer) // If we're sending this as answer, see that its whole RRSet is similarly marked { for (r2 = m->ResourceRecords; r2; r2=r2->next) - if (ResourceRecordIsValidAnswer(r2)) - if (r2->ImmedAnswer != mDNSInterfaceMark && - r2->ImmedAnswer != rr->ImmedAnswer && SameResourceRecordSignature(r2, rr)) - r2->ImmedAnswer = !r2->ImmedAnswer ? rr->ImmedAnswer : mDNSInterfaceMark; + { + if ((r2->resrec.RecordType & kDNSRecordTypeUniqueMask) && ResourceRecordIsValidAnswer(r2) && + (r2->ImmedAnswer != mDNSInterfaceMark) && (r2->ImmedAnswer != rr->ImmedAnswer) && + SameResourceRecordSignature(r2, rr) && + ((rr->ImmedAnswer == mDNSInterfaceMark) || IsInterfaceValidForAuthRecord(r2, rr->ImmedAnswer))) + { + r2->ImmedAnswer = !r2->ImmedAnswer ? rr->ImmedAnswer : mDNSInterfaceMark; + } + } } else if (rr->ImmedAdditional) // If we're sending this as additional, see that its whole RRSet is similarly marked { for (r2 = m->ResourceRecords; r2; r2=r2->next) - if (ResourceRecordIsValidAnswer(r2)) - if (r2->ImmedAdditional != rr->ImmedAdditional && SameResourceRecordSignature(r2, rr)) - r2->ImmedAdditional = rr->ImmedAdditional; + { + if ((r2->resrec.RecordType & kDNSRecordTypeUniqueMask) && ResourceRecordIsValidAnswer(r2) && + (r2->ImmedAdditional != rr->ImmedAdditional) && + SameResourceRecordSignature(r2, rr) && + IsInterfaceValidForAuthRecord(r2, rr->ImmedAdditional)) + { + r2->ImmedAdditional = rr->ImmedAdditional; + } + } } } @@ -2541,6 +2698,7 @@ mDNSlocal void SendResponses(mDNS *const m) rr->ImmedAdditional = mDNSNULL; // No need to send as additional if sending as answer rr->LastMCTime = m->timenow; rr->LastMCInterface = rr->ImmedAnswer; + rr->ProbeRestartCount = 0; // Reset the probe restart count // If we're announcing this record, and it's at least half-way to its ordained time, then consider this announcement done if (TimeToAnnounceThisRecord(rr, m->timenow + rr->ThisAPInterval/2)) { @@ -2588,9 +2746,8 @@ mDNSlocal void SendResponses(mDNS *const m) // Skip this interface if the record InterfaceID is *Any and the record is not // appropriate for the interface type. if ((rr->SendRNow == intf->InterfaceID) && - ((rr->resrec.InterfaceID == mDNSInterface_Any) && !mDNSPlatformValidRecordForInterface(rr, intf))) + ((rr->resrec.InterfaceID == mDNSInterface_Any) && !mDNSPlatformValidRecordForInterface(rr, intf->InterfaceID))) { - // LogInfo("SendResponses: Not sending %s, on %s", ARDisplayString(m, rr), InterfaceNameForID(m, rr->SendRNow)); rr->SendRNow = GetNextActiveInterfaceID(intf); } else if (rr->SendRNow == intf->InterfaceID) @@ -2663,7 +2820,7 @@ mDNSlocal void SendResponses(mDNS *const m) // Get the reserved space back OwnerRecordSpace -= AnoninfoSpace; - TraceRecordSpace -= AnoninfoSpace; + TraceRecordSpace -= AnoninfoSpace; newptr = responseptr; for (rr = m->ResourceRecords; rr; rr=rr->next) { @@ -2812,10 +2969,9 @@ mDNSlocal void SendResponses(mDNS *const m) SetupTracerOpt(m, &opt.resrec.rdata->u.opt[0]); } newptr = PutResourceRecord(&m->omsg, responseptr, &m->omsg.h.numAdditionals, &opt.resrec); - if (newptr) - { - responseptr = newptr; - LogInfo("SendResponses put %s %s: %s %s", OwnerRecordSpace ? "OWNER" : "", TraceRecordSpace ? "TRACER" : "", intf->ifname, ARDisplayString(m, &opt)); + if (newptr) + { + responseptr = newptr; } else if (m->omsg.h.numAnswers + m->omsg.h.numAuthorities + m->omsg.h.numAdditionals == 1) { @@ -2828,7 +2984,7 @@ mDNSlocal void SendResponses(mDNS *const m) m->omsg.h.numQuestions, m->omsg.h.numAnswers, m->omsg.h.numAuthorities, m->omsg.h.numAdditionals, ARDisplayString(m, &opt)); } } - + debugf("SendResponses: Sending %d Deregistration%s, %d Announcement%s, %d Answer%s, %d Additional%s on %p", numDereg, numDereg == 1 ? "" : "s", numAnnounce, numAnnounce == 1 ? "" : "s", @@ -2940,13 +3096,18 @@ mDNSexport void SetNextCacheCheckTimeForRecord(mDNS *const m, CacheRecord *const verbosedebugf("SetNextCacheCheckTimeForRecord: NextRequiredQuery in %ld sec CacheCheckGracePeriod %d ticks for %s", (rr->NextRequiredQuery - m->timenow) / mDNSPlatformOneSecond, CacheCheckGracePeriod(rr), CRDisplayString(m,rr)); } - ScheduleNextCacheCheckTime(m, HashSlot(rr->resrec.name), NextCacheCheckEvent(rr)); + ScheduleNextCacheCheckTime(m, HashSlotFromNameHash(rr->resrec.namehash), NextCacheCheckEvent(rr)); } #define kMinimumReconfirmTime ((mDNSu32)mDNSPlatformOneSecond * 5) #define kDefaultReconfirmTimeForWake ((mDNSu32)mDNSPlatformOneSecond * 5) #define kDefaultReconfirmTimeForNoAnswer ((mDNSu32)mDNSPlatformOneSecond * 5) -#define kDefaultReconfirmTimeForFlappingInterface ((mDNSu32)mDNSPlatformOneSecond * 5) + +// Delay before restarting questions on a flapping interface. +#define kDefaultQueryDelayTimeForFlappingInterface ((mDNSu32)mDNSPlatformOneSecond * 3) +// After kDefaultQueryDelayTimeForFlappingInterface seconds, allow enough time for up to three queries (0, 1, and 4 seconds) +// plus three seconds for "response delay" before removing the reconfirmed records from the cache. +#define kDefaultReconfirmTimeForFlappingInterface (kDefaultQueryDelayTimeForFlappingInterface + ((mDNSu32)mDNSPlatformOneSecond * 7)) mDNSexport mStatus mDNS_Reconfirm_internal(mDNS *const m, CacheRecord *const rr, mDNSu32 interval) { @@ -2961,7 +3122,7 @@ mDNSexport mStatus mDNS_Reconfirm_internal(mDNS *const m, CacheRecord *const rr, // Add a 33% random amount to the interval, to avoid synchronization between multiple hosts // For all the reconfirmations in a given batch, we want to use the same random value // so that the reconfirmation questions can be grouped into a single query packet - if (!m->RandomReconfirmDelay) m->RandomReconfirmDelay = 1 + mDNSRandom(0x3FFFFFFF); + if (!m->RandomReconfirmDelay) m->RandomReconfirmDelay = 1 + mDNSRandom(FutureTime); interval += m->RandomReconfirmDelay % ((interval/3) + 1); rr->TimeRcvd = m->timenow - (mDNSs32)interval * 3; rr->resrec.rroriginalttl = (interval * 4 + mDNSPlatformOneSecond - 1) / mDNSPlatformOneSecond; @@ -2991,8 +3152,7 @@ mDNSlocal mDNSBool BuildQuestion(mDNS *const m, const NetworkInterfaceInfo *intf else { mDNSu32 forecast = *answerforecast + anoninfo_space; - const mDNSu32 slot = HashSlot(&q->qname); - const CacheGroup *const cg = CacheGroupForName(m, slot, q->qnamehash, &q->qname); + const CacheGroup *const cg = CacheGroupForName(m, q->qnamehash, &q->qname); CacheRecord *rr; CacheRecord **ka = *kalistptrptr; // Make a working copy of the pointer we're going to update @@ -3085,7 +3245,7 @@ mDNSlocal void ReconfirmAntecedents(mDNS *const m, const domainname *const name, // to get a AAAA response is not grounds to doubt the PTR/SRV chain that lead us to that name. mDNSlocal const CacheRecord *CacheHasAddressTypeForName(mDNS *const m, const domainname *const name, const mDNSu32 namehash) { - CacheGroup *const cg = CacheGroupForName(m, HashSlot(name), namehash, name); + CacheGroup *const cg = CacheGroupForName(m, namehash, name); const CacheRecord *cr = cg ? cg->members : mDNSNULL; while (cr && !RRTypeIsAddressType(cr->resrec.rrtype)) cr=cr->next; return(cr); @@ -3095,7 +3255,7 @@ mDNSlocal const CacheRecord *CacheHasAddressTypeForName(mDNS *const m, const dom mDNSlocal const CacheRecord *FindSPSInCache1(mDNS *const m, const DNSQuestion *const q, const CacheRecord *const c0, const CacheRecord *const c1) { #ifndef SPC_DISABLED - CacheGroup *const cg = CacheGroupForName(m, HashSlot(&q->qname), q->qnamehash, &q->qname); + CacheGroup *const cg = CacheGroupForName(m, q->qnamehash, &q->qname); const CacheRecord *cr, *bestcr = mDNSNULL; mDNSu32 bestmetric = 1000000; for (cr = cg ? cg->members : mDNSNULL; cr; cr=cr->next) @@ -3109,11 +3269,11 @@ mDNSlocal const CacheRecord *FindSPSInCache1(mDNS *const m, const DNSQuestion *c } return(bestcr); #else // SPC_DISABLED - (void) m; - (void) q; - (void) c0; - (void) c1; - (void) c1; + (void) m; + (void) q; + (void) c0; + (void) c1; + (void) c1; return mDNSNULL; #endif // SPC_DISABLED } @@ -3211,7 +3371,7 @@ mDNSlocal void mDNSSendWakeOnResolve(mDNS *const m, DNSQuestion *q) domainname *d = &q->qname; // We can't send magic packets without knowing which interface to send it on. - if (InterfaceID == mDNSInterface_Any || InterfaceID == mDNSInterface_LocalOnly || InterfaceID == mDNSInterface_P2P) + if (InterfaceID == mDNSInterface_Any || LocalOnlyOrP2PInterface(InterfaceID)) { LogMsg("mDNSSendWakeOnResolve: ERROR!! Invalid InterfaceID %p for question %##s", InterfaceID, q->qname.c); return; @@ -3246,7 +3406,7 @@ mDNSlocal void mDNSSendWakeOnResolve(mDNS *const m, DNSQuestion *q) mDNSPlatformMemCopy(IPAddr, &d->c[i + 1], len - i); IPAddr[len - i] = 0; m->mDNSStats.WakeOnResolves++; - mDNSPlatformSendWakeupPacket(m, InterfaceID, EthAddr, IPAddr, InitialWakeOnResolveCount - q->WakeOnResolveCount); + mDNSPlatformSendWakeupPacket(InterfaceID, EthAddr, IPAddr, InitialWakeOnResolveCount - q->WakeOnResolveCount); return; } else if (d->c[i] == ':') @@ -3267,8 +3427,7 @@ mDNSlocal mDNSBool AccelerateThisQuery(mDNS *const m, DNSQuestion *q) { // We forecast: qname (n) type (2) class (2) mDNSu32 forecast = (mDNSu32)DomainNameLength(&q->qname) + 4; - const mDNSu32 slot = HashSlot(&q->qname); - const CacheGroup *const cg = CacheGroupForName(m, slot, q->qnamehash, &q->qname); + const CacheGroup *const cg = CacheGroupForName(m, q->qnamehash, &q->qname); const CacheRecord *rr; for (rr = cg ? cg->members : mDNSNULL; rr; rr=rr->next) // If we have a resource record in our cache, if (rr->resrec.rdlength <= SmallRecordLimit && // which is small enough to sensibly fit in the packet @@ -3371,7 +3530,7 @@ mDNSlocal void SendQueries(mDNS *const m) const mDNSu8 *const limit = m->omsg.data + sizeof(m->omsg.data); // If we fail to get a new on-demand socket (should only happen cases of the most extreme resource exhaustion), we'll try again next time - if (!q->LocalSocket) q->LocalSocket = mDNSPlatformUDPSocket(m, zeroIPPort); + if (!q->LocalSocket) q->LocalSocket = mDNSPlatformUDPSocket(zeroIPPort); if (q->LocalSocket) { InitializeDNSMessage(&m->omsg.h, q->TargetQID, QueryFlags); @@ -3412,7 +3571,7 @@ mDNSlocal void SendQueries(mDNS *const m) // Note: Don't set NextScheduledQuery until here, because uDNS_CheckCurrentQuestion in the loop above can add new questions to the list, // which causes NextScheduledQuery to get (incorrectly) set to m->timenow. Setting it here is the right place, because the very // next thing we do is scan the list and call SetNextQueryTime() for every question we find, so we know we end up with the right value. - m->NextScheduledQuery = m->timenow + 0x78000000; + m->NextScheduledQuery = m->timenow + FutureTime; for (q = m->Questions; q && q != m->NewQuestions; q=q->next) { if (mDNSOpaque16IsZero(q->TargetQID) @@ -3423,11 +3582,11 @@ mDNSlocal void SendQueries(mDNS *const m) // treat this as logically a repeat of the last transmission, without advancing the interval if (m->timenow - (q->LastQTime + (q->ThisQInterval/2)) >= 0) { - // If we have reached the answer threshold for this question, + // If we have reached the answer threshold for this question, // don't send it again until MaxQuestionInterval unless: // one of its cached answers needs to be refreshed, // or it's the initial query for a kDNSServiceFlagsThresholdFinder mode browse. - if (q->BrowseThreshold + if (q->BrowseThreshold && (q->CurrentAnswers >= q->BrowseThreshold) && (q->CachedAnswerNeedsUpdate == mDNSfalse) && !((q->flags & kDNSServiceFlagsThresholdFinder) && (q->ThisQInterval == InitialQuestionInterval))) @@ -3449,7 +3608,7 @@ mDNSlocal void SendQueries(mDNS *const m) debugf("SendQueries: %##s (%s) next interval %d seconds RequestUnicast = %d", q->qname.c, DNSTypeName(q->qtype), q->ThisQInterval / InitialQuestionInterval, q->RequestUnicast); - if (q->ThisQInterval >= QuestionIntervalThreshold) + if (q->ThisQInterval > MaxQuestionInterval) { q->ThisQInterval = MaxQuestionInterval; } @@ -3491,7 +3650,7 @@ mDNSlocal void SendQueries(mDNS *const m) // 2. Scan our authoritative RR list to see what probes we might need to send - m->NextScheduledProbe = m->timenow + 0x78000000; + m->NextScheduledProbe = m->timenow + FutureTime; if (m->CurrentRecord) LogMsg("SendQueries ERROR m->CurrentRecord already set %s", ARDisplayString(m, m->CurrentRecord)); @@ -3512,11 +3671,11 @@ mDNSlocal void SendQueries(mDNS *const m) { if (ar->AddressProxy.type == mDNSAddrType_IPv4) { - // There's a problem here. If a host is waking up, and we probe to see if it responds, then - // it will see those ARP probes as signalling intent to use the address, so it picks a different one. - // A more benign way to find out if a host is responding to ARPs might be send a standard ARP *request* - // (using our sender IP address) instead of an ARP *probe* (using all-zero sender IP address). - // A similar concern may apply to the NDP Probe too. -- SC + // There's a problem here. If a host is waking up, and we probe to see if it responds, then + // it will see those ARP probes as signalling intent to use the address, so it picks a different one. + // A more benign way to find out if a host is responding to ARPs might be send a standard ARP *request* + // (using our sender IP address) instead of an ARP *probe* (using all-zero sender IP address). + // A similar concern may apply to the NDP Probe too. -- SC LogSPS("SendQueries ARP Probe %d %s %s", ar->ProbeCount, InterfaceNameForID(m, ar->resrec.InterfaceID), ARDisplayString(m,ar)); SendARP(m, 1, ar, &zerov4Addr, &zeroEthAddr, &ar->AddressProxy.ip.v4, &ar->WakeUp.IMAC); } @@ -3608,7 +3767,6 @@ mDNSlocal void SendQueries(mDNS *const m) // If interface is P2P type, verify that query should be sent over it. if (!mDNSPlatformValidQuestionForInterface(q, intf)) { - LogInfo("SendQueries: Not sending (%s) %##s on %s", DNSTypeName(q->qtype), q->qname.c, InterfaceNameForID(m, intf->InterfaceID)); q->SendQNow = (q->InterfaceID || !q->SendOnAll) ? mDNSNULL : GetNextActiveInterfaceID(intf); } // If we're suppressing this question, or we successfully put it, update its SendQNow state @@ -3648,24 +3806,62 @@ mDNSlocal void SendQueries(mDNS *const m) // Put probe questions in this packet for (ar = m->ResourceRecords; ar; ar=ar->next) - if (ar->SendRNow == intf->InterfaceID) + { + if (ar->SendRNow != intf->InterfaceID) + continue; + + // If interface is a P2P variant, verify that the probe should be sent over it. + if (!mDNSPlatformValidRecordForInterface(ar, intf->InterfaceID)) + { + ar->SendRNow = (ar->resrec.InterfaceID) ? mDNSNULL : GetNextActiveInterfaceID(intf); + ar->IncludeInProbe = mDNSfalse; + } + else { 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) mDNSu32 forecast = answerforecast + 12 + ar->resrec.rdestimate; - mDNSu8 *newptr = putQuestion(&m->omsg, queryptr, limit - forecast, ar->resrec.name, kDNSQType_ANY, (mDNSu16)(ar->resrec.rrclass | ucbit)); - if (newptr) + mDNSBool putProbe = mDNStrue; + mDNSu16 qclass = ar->resrec.rrclass | ucbit; + + {// Determine if this probe question is already in packet's dns message + const mDNSu8 *questionptr = m->omsg.data; + DNSQuestion question; + mDNSu16 n; + for (n = 0; n < m->omsg.h.numQuestions && questionptr; n++) + { + questionptr = getQuestion(&m->omsg, questionptr, limit, mDNSInterface_Any, &question); + if (questionptr && (question.qtype == kDNSQType_ANY) && (question.qclass == qclass) && + (question.qnamehash == ar->resrec.namehash) && SameDomainName(&question.qname, ar->resrec.name)) + { + putProbe = mDNSfalse; // set to false if already in message + break; + } + } + } + + if (putProbe) + { + mDNSu8 *newptr = putQuestion(&m->omsg, queryptr, limit - forecast, ar->resrec.name, kDNSQType_ANY, qclass); + if (newptr) + { + queryptr = newptr; + answerforecast = forecast; + ar->SendRNow = (ar->resrec.InterfaceID) ? mDNSNULL : GetNextActiveInterfaceID(intf); + ar->IncludeInProbe = mDNStrue; + verbosedebugf("SendQueries: Put Question %##s (%s) probecount %d InterfaceID= %d %d %d", + ar->resrec.name->c, DNSTypeName(ar->resrec.rrtype), ar->ProbeCount, ar->resrec.InterfaceID, ar->resrec.rdestimate, answerforecast); + } + } + else { - queryptr = newptr; - answerforecast = forecast; ar->SendRNow = (ar->resrec.InterfaceID) ? mDNSNULL : GetNextActiveInterfaceID(intf); ar->IncludeInProbe = mDNStrue; - verbosedebugf("SendQueries: Put Question %##s (%s) probecount %d", - ar->resrec.name->c, DNSTypeName(ar->resrec.rrtype), ar->ProbeCount); } } + } } // Put our known answer list (either new one from this question or questions, or remainder of old one from last time) @@ -3731,7 +3927,7 @@ mDNSlocal void SendQueries(mDNS *const m) AuthRecord opt; mDNS_SetupResourceRecord(&opt, mDNSNULL, mDNSInterface_Any, kDNSType_OPT, kStandardTTL, kDNSRecordTypeKnownUnique, AuthRecordAny, mDNSNULL, mDNSNULL); opt.resrec.rrclass = NormalMaxDNSMessageData; - opt.resrec.rdlength = sizeof(rdataOPT); + opt.resrec.rdlength = sizeof(rdataOPT); opt.resrec.rdestimate = sizeof(rdataOPT); if (OwnerRecordSpace && TraceRecordSpace) { @@ -3748,19 +3944,18 @@ mDNSlocal void SendQueries(mDNS *const m) { SetupTracerOpt(m, &opt.resrec.rdata->u.opt[0]); } - LogInfo("SendQueries putting %s %s: %s %s", OwnerRecordSpace ? "OWNER" : "", TraceRecordSpace ? "TRACER" : "", intf->ifname, ARDisplayString(m, &opt)); queryptr = PutResourceRecordTTLWithLimit(&m->omsg, queryptr, &m->omsg.h.numAdditionals, &opt.resrec, opt.resrec.rroriginalttl, m->omsg.data + AbsoluteMaxDNSMessageData); if (!queryptr) - { + { LogMsg("SendQueries: How did we fail to have space for %s %s OPT record (%d/%d/%d/%d) %s", OwnerRecordSpace ? "OWNER" : "", TraceRecordSpace ? "TRACER" : "", m->omsg.h.numQuestions, m->omsg.h.numAnswers, m->omsg.h.numAuthorities, m->omsg.h.numAdditionals, ARDisplayString(m, &opt)); } if (queryptr > m->omsg.data + NormalMaxDNSMessageData) { if (m->omsg.h.numQuestions != 1 || m->omsg.h.numAnswers != 0 || m->omsg.h.numAuthorities != 1 || m->omsg.h.numAdditionals != 1) - LogMsg("SendQueries: Why did we generate oversized packet with %s %s OPT record %p %p %p (%d/%d/%d/%d) %s", OwnerRecordSpace ? "OWNER" : "", - TraceRecordSpace ? "TRACER" : "", m->omsg.data, m->omsg.data + NormalMaxDNSMessageData, queryptr, m->omsg.h.numQuestions, m->omsg.h.numAnswers, + LogMsg("SendQueries: Why did we generate oversized packet with %s %s OPT record %p %p %p (%d/%d/%d/%d) %s", OwnerRecordSpace ? "OWNER" : "", + TraceRecordSpace ? "TRACER" : "", m->omsg.data, m->omsg.data + NormalMaxDNSMessageData, queryptr, m->omsg.h.numQuestions, m->omsg.h.numAnswers, m->omsg.h.numAuthorities, m->omsg.h.numAdditionals, ARDisplayString(m, &opt)); } } @@ -3829,17 +4024,21 @@ mDNSlocal void SendQueries(mDNS *const m) { DNSQuestion *x; for (x = m->NewQuestions; x; x=x->next) if (x == q) break; // Check if this question is a NewQuestion - LogInfo("SendQueries: No active interface %d to send %s question: %d %##s (%s)", - (uint32_t)q->SendQNow, x ? "new" : "old", (uint32_t)q->InterfaceID, q->qname.c, DNSTypeName(q->qtype)); + // There will not be an active interface for questions applied to mDNSInterface_BLE + // so don't log the warning in that case. + if (q->InterfaceID != mDNSInterface_BLE) + LogInfo("SendQueries: No active interface %d to send %s question: %d %##s (%s)", + (uint32_t)q->SendQNow, x ? "new" : "old", (uint32_t)q->InterfaceID, q->qname.c, DNSTypeName(q->qtype)); q->SendQNow = mDNSNULL; } q->CachedAnswerNeedsUpdate = mDNSfalse; } } -mDNSlocal void SendWakeup(mDNS *const m, mDNSInterfaceID InterfaceID, mDNSEthAddr *EthAddr, mDNSOpaque48 *password) +mDNSlocal void SendWakeup(mDNS *const m, mDNSInterfaceID InterfaceID, mDNSEthAddr *EthAddr, mDNSOpaque48 *password, mDNSBool unicastOnly) { int i, j; + mDNSu8 *ptr = m->omsg.data; NetworkInterfaceInfo *intf = FirstInterfaceForID(m, InterfaceID); if (!intf) { LogMsg("SendARP: No interface with InterfaceID %p found", InterfaceID); return; } @@ -3865,13 +4064,16 @@ mDNSlocal void SendWakeup(mDNS *const m, mDNSInterfaceID InterfaceID, mDNSEthAdd mDNSPlatformSendRawPacket(m->omsg.data, ptr, InterfaceID); - // For Ethernet switches that don't flood-foward packets with unknown unicast destination MAC addresses, - // broadcast is the only reliable way to get a wakeup packet to the intended target machine. - // For 802.11 WPA networks, where a sleeping target machine may have missed a broadcast/multicast - // key rotation, unicast is the only way to get a wakeup packet to the intended target machine. - // So, we send one of each, unicast first, then broadcast second. - for (i=0; i<6; i++) m->omsg.data[i] = 0xFF; - mDNSPlatformSendRawPacket(m->omsg.data, ptr, InterfaceID); + if (!unicastOnly) + { + // For Ethernet switches that don't flood-foward packets with unknown unicast destination MAC addresses, + // broadcast is the only reliable way to get a wakeup packet to the intended target machine. + // For 802.11 WPA networks, where a sleeping target machine may have missed a broadcast/multicast + // key rotation, unicast is the only way to get a wakeup packet to the intended target machine. + // So, we send one of each, unicast first, then broadcast second. + for (i=0; i<6; i++) m->omsg.data[i] = 0xFF; + mDNSPlatformSendRawPacket(m->omsg.data, ptr, InterfaceID); + } } // *************************************************************************** @@ -3903,7 +4105,7 @@ mDNSlocal void ResetQuestionState(mDNS *const m, DNSQuestion *q) mDNSexport void AnswerCurrentQuestionWithResourceRecord(mDNS *const m, CacheRecord *const rr, const QC_result AddRecord) { DNSQuestion *const q = m->CurrentQuestion; - mDNSBool followcname = FollowCNAME(q, &rr->resrec, AddRecord); + const mDNSBool followcname = FollowCNAME(q, &rr->resrec, AddRecord); verbosedebugf("AnswerCurrentQuestionWithResourceRecord:%4lu %s TTL %d %s", q->CurrentAnswers, AddRecord ? "Add" : "Rmv", rr->resrec.rroriginalttl, CRDisplayString(m, rr)); @@ -3919,7 +4121,7 @@ mDNSexport void AnswerCurrentQuestionWithResourceRecord(mDNS *const m, CacheReco // to do it on the next ADD of a negative cache record. This ADD could be the result of a timeout, no DNS servers // etc. in which case we need to reset the state to make sure we don't deliver them as secure. If this is // a real negative response, we would reset the state here and validate the results at the end of this function. - // or the real response again if we purge the cache. + // or the real response again if we purge the cache. if (q->ValidationRequired && ((AddRecord == QC_rmv) || (rr->resrec.RecordType == kDNSRecordTypePacketNegative && (AddRecord == QC_add)))) { @@ -3948,29 +4150,33 @@ 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))) +#if AWD_METRICS + if ((AddRecord == QC_add) && Question_uDNS(q) && !followcname) { - uDNSMetrics * metrics; const domainname * queryName; mDNSu32 responseLatencyMs; mDNSBool isForCellular; - metrics = &q->metrics; - queryName = metrics->originalQName ? metrics->originalQName : &q->qname; - if (metrics->querySendCount > 0) + queryName = q->metrics.originalQName ? q->metrics.originalQName : &q->qname; + isForCellular = (q->qDNSServer && q->qDNSServer->cellIntf); + if (!q->metrics.answered) { - responseLatencyMs = ((m->timenow - metrics->firstQueryTime) * 1000) / mDNSPlatformOneSecond; + if (q->metrics.querySendCount > 0) + { + responseLatencyMs = ((m->timenow - q->metrics.firstQueryTime) * 1000) / mDNSPlatformOneSecond; + } + else + { + responseLatencyMs = 0; + } + + MetricsUpdateUDNSQueryStats(queryName, q->qtype, &rr->resrec, q->metrics.querySendCount, responseLatencyMs, isForCellular); + q->metrics.answered = mDNStrue; } - else + if (q->metrics.querySendCount > 0) { - responseLatencyMs = 0; + MetricsUpdateUDNSResolveStats(queryName, &rr->resrec, isForCellular); } - 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) @@ -4003,6 +4209,35 @@ mDNSexport void AnswerCurrentQuestionWithResourceRecord(mDNS *const m, CacheReco if (rr->DelayDelivery) return; // We'll come back later when CacheRecordDeferredAdd() calls us +#if USE_DNS64 + // If DNS64StateMachine() returns true, then the question was restarted as a different question, so return. + if (!mDNSOpaque16IsZero(q->TargetQID) && DNS64StateMachine(m, q, &rr->resrec, AddRecord)) return; +#endif + +#ifdef USE_LIBIDN + if (rr->resrec.RecordType == kDNSRecordTypePacketNegative) // If negative answer, check if we need to try Punycode conversion + { + domainname newname; + if (PerformNextPunycodeConversion(q, &newname)) // Itertative Punycode conversion succeeded, so reissue question with new name + { + UDPSocket *const sock = q->LocalSocket; // Save old socket and transaction ID + const mDNSOpaque16 id = q->TargetQID; + q->LocalSocket = mDNSNULL; + mDNS_StopQuery_internal(m, q); // Stop old query + AssignDomainName(&q->qname, &newname); // Update qname + q->qnamehash = DomainNameHashValue(&q->qname); // and namehash + mDNS_StartQuery_internal(m, q); // Start new query + + if (sock) // Transplant saved socket, if appropriate + { + if (q->DuplicateOf) mDNSPlatformUDPClose(sock); + else { q->LocalSocket = sock; q->TargetQID = id; } + } + return; // All done for now; wait until we get the next answer + } + } +#endif // USE_LIBIDN + // Only deliver negative answers if client has explicitly requested them except when we are forcing a negative response // for the purpose of retrying search domains/timeout OR the question is suppressed if (rr->resrec.RecordType == kDNSRecordTypePacketNegative || (q->qtype != kDNSType_NSEC && RRAssertsNonexistence(&rr->resrec, q->qtype))) @@ -4019,7 +4254,18 @@ mDNSexport void AnswerCurrentQuestionWithResourceRecord(mDNS *const m, CacheReco q->QuestionCallback(m, q, &neg.resrec, AddRecord); } else - q->QuestionCallback(m, q, &rr->resrec, AddRecord); + { +#if USE_DNS64 + if (DNS64ShouldAnswerQuestion(q, &rr->resrec)) + { + DNS64AnswerQuestion(m, q, &rr->resrec, AddRecord); + } + else +#endif + { + q->QuestionCallback(m, q, &rr->resrec, AddRecord); + } + } mDNS_ReclaimLockAfterCallback(); // Decrement mDNS_reentrancy to block mDNS API calls again } // If this is an "Add" operation and this question needs validation, validate the response. @@ -4053,7 +4299,7 @@ mDNSexport void AnswerCurrentQuestionWithResourceRecord(mDNS *const m, CacheReco // If we get a CNAME back while we are validating the response (i.e., CNAME for DS, DNSKEY, RRSIG), // don't follow them. If it is a ValidationRequired question, wait for the CNAME to be validated // first before following it - if (!ValidatingQuestion(q) && followcname && m->CurrentQuestion == q) + if ((m->CurrentQuestion == q) && followcname && !ValidatingQuestion(q)) AnswerQuestionByFollowingCNAME(m, q, &rr->resrec); } @@ -4075,12 +4321,12 @@ mDNSlocal void CacheRecordDeferredAdd(mDNS *const m, CacheRecord *rr) m->CurrentQuestion = mDNSNULL; } -mDNSlocal mDNSs32 CheckForSoonToExpireRecords(mDNS *const m, const domainname *const name, const mDNSu32 namehash, const mDNSu32 slot, mDNSBool *purge) +mDNSlocal mDNSs32 CheckForSoonToExpireRecords(mDNS *const m, const domainname *const name, const mDNSu32 namehash, mDNSBool *purge) { const mDNSs32 threshhold = m->timenow + mDNSPlatformOneSecond; // See if there are any records expiring within one second const mDNSs32 start = m->timenow - 0x10000000; mDNSs32 delay = start; - CacheGroup *cg = CacheGroupForName(m, slot, namehash, name); + CacheGroup *cg = CacheGroupForName(m, namehash, name); const CacheRecord *rr; if (purge) @@ -4094,7 +4340,7 @@ mDNSlocal mDNSs32 CheckForSoonToExpireRecords(mDNS *const m, const domainname *c // deliver a RMV (for the current old entry) followed by ADD (for the new entry). // It needs to schedule the timer for the next cache expiry (ScheduleNextCacheCheckTime), // so that the cache entry can be purged (purging causes the RMV followed by ADD) - // + // // 2) A new question is about to be answered and the caller needs to know whether it's // scheduling should be delayed so that the question is not answered with this record. // Instead of delivering an ADD (old entry) followed by RMV (old entry) and another ADD @@ -4154,7 +4400,6 @@ 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 @@ -4177,7 +4422,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 : zp), q); + rr->resrec.rDNSServer->port : zeroIPPort), q); q->CurrentAnswers++; q->unansweredQueries = 0; @@ -4274,12 +4519,10 @@ mDNSlocal void CacheRecordRmv(mDNS *const m, CacheRecord *rr) q->FlappingInterface1 = mDNSNULL; q->FlappingInterface2 = mDNSNULL; - if (q->CurrentAnswers == 0) { - mDNSIPPort zp = zeroIPPort; + if (q->CurrentAnswers == 0) LogMsg("CacheRecordRmv ERROR!!: How can CurrentAnswers already be zero for %p %##s (%s) DNSServer %#a:%d", q, q->qname.c, DNSTypeName(q->qtype), q->qDNSServer ? &q->qDNSServer->addr : mDNSNULL, - mDNSVal16(q->qDNSServer ? q->qDNSServer->port : zp)); - } + mDNSVal16(q->qDNSServer ? q->qDNSServer->port : zeroIPPort)); else { q->CurrentAnswers--; @@ -4332,7 +4575,7 @@ mDNSlocal void ReleaseCacheGroup(mDNS *const m, CacheGroup **cp) if ((*cp)->rrcache_tail != &(*cp)->members) LogMsg("ERROR: (*cp)->members == mDNSNULL but (*cp)->rrcache_tail != &(*cp)->members)"); //if ((*cp)->name != (domainname*)((*cp)->namestorage)) - // LogMsg("ReleaseCacheGroup: %##s, %p %p", (*cp)->name->c, (*cp)->name, (domainname*)((*cp)->namestorage)); + // LogMsg("ReleaseCacheGroup: %##s, %p %p", (*cp)->name->c, (*cp)->name, (domainname*)((*cp)->namestorage)); if ((*cp)->name != (domainname*)((*cp)->namestorage)) mDNSPlatformMemFree((*cp)->name); (*cp)->name = mDNSNULL; *cp = (*cp)->next; // Cut record from list @@ -4372,14 +4615,13 @@ mDNSlocal void ReleaseAdditionalCacheRecords(mDNS *const m, CacheRecord **rp) mDNSexport void ReleaseCacheRecord(mDNS *const m, CacheRecord *r) { CacheGroup *cg; - const mDNSu32 slot = HashSlot(r->resrec.name); //LogMsg("ReleaseCacheRecord: Releasing %s", CRDisplayString(m, r)); if (r->resrec.rdata && r->resrec.rdata != (RData*)&r->smallrdatastorage) mDNSPlatformMemFree(r->resrec.rdata); r->resrec.rdata = mDNSNULL; - cg = CacheGroupForRecord(m, slot, &r->resrec); - + cg = CacheGroupForRecord(m, &r->resrec); + if (!cg) { // It is okay to have this printed for NSEC/NSEC3s @@ -4432,7 +4674,7 @@ mDNSlocal void CheckCacheExpiration(mDNS *const m, const mDNSu32 slot, CacheGrou if (m->timenow - event >= 0) // If expired, delete it { *rp = rr->next; // Cut it from the list - + verbosedebugf("CheckCacheExpiration: Deleting%7d %7d %p %s", m->timenow - rr->TimeRcvd, rr->resrec.rroriginalttl, rr->CRActiveQuestion, CRDisplayString(m, rr)); if (rr->CRActiveQuestion) // If this record has one or more active questions, tell them it's going away @@ -4475,7 +4717,7 @@ mDNSlocal void CheckCacheExpiration(mDNS *const m, const mDNSu32 slot, CacheGrou m->NextScheduledQuery = m->timenow; // After sending the query we'll increment UnansweredQueries and call SetNextCacheCheckTimeForRecord(), // which will correctly update m->NextCacheCheck for us. - event = m->timenow + 0x3FFFFFFF; + event = m->timenow + FutureTime; } } } @@ -4496,19 +4738,17 @@ mDNSlocal void CheckCacheExpiration(mDNS *const m, const mDNSu32 slot, CacheGrou // If "CheckOnly" is set to "true", the question won't be answered but just check to see if there is an answer and // returns true if there is an answer. // -// If "CheckOnly" is set to "false", the question will be answered if there is a LocalOnly/P2P record and +// If "CheckOnly" is set to "false", the question will be answered if there is a LocalOnly/P2P record and // returns true to indicate the same. mDNSlocal mDNSBool AnswerQuestionWithLORecord(mDNS *const m, DNSQuestion *q, mDNSBool checkOnly) { - mDNSu32 slot; AuthRecord *lr; AuthGroup *ag; if (m->CurrentRecord) LogMsg("AnswerQuestionWithLORecord ERROR m->CurrentRecord already set %s", ARDisplayString(m, m->CurrentRecord)); - slot = AuthHashSlot(&q->qname); - ag = AuthGroupForName(&m->rrauth, slot, q->qnamehash, &q->qname); + ag = AuthGroupForName(&m->rrauth, q->qnamehash, &q->qname); if (ag) { m->CurrentRecord = ag->members; @@ -4524,7 +4764,7 @@ mDNSlocal mDNSBool AnswerQuestionWithLORecord(mDNS *const m, DNSQuestion *q, mDN // details on how we handle this case. For P2P we just handle "Interface_Any" questions. For LocalOnly // we handle both mDNSInterface_Any and scoped questions. - if (rr->ARType == AuthRecordLocalOnly || (rr->ARType == AuthRecordP2P && q->InterfaceID == mDNSInterface_Any)) + if (rr->ARType == AuthRecordLocalOnly || (rr->ARType == AuthRecordP2P && (q->InterfaceID == mDNSInterface_Any || q->InterfaceID == mDNSInterface_BLE))) if (LocalOnlyRecordAnswersQuestion(rr, q)) { if (checkOnly) @@ -4534,7 +4774,7 @@ mDNSlocal mDNSBool AnswerQuestionWithLORecord(mDNS *const m, DNSQuestion *q, mDN m->CurrentRecord = mDNSNULL; return mDNStrue; } - AnswerLocalQuestionWithLocalAuthRecord(m, rr, QC_add); + AnswerLocalQuestionWithLocalAuthRecord(m, rr, mDNStrue); if (m->CurrentQuestion != q) break; // If callback deleted q, then we're finished here } @@ -4585,14 +4825,25 @@ mDNSlocal mDNSBool AnswerQuestionWithLORecord(mDNS *const m, DNSQuestion *q, mDN // reasons for suppressing the query, this function should be updated. mDNSlocal void AnswerSuppressedQuestion(mDNS *const m, DNSQuestion *q) { - mDNSBool SuppressQuery = q->SuppressQuery; - mDNSBool DisallowPID = q->DisallowPID; + mDNSBool SuppressQuery; + mDNSBool DisallowPID; + + // If the client did not set the kDNSServiceFlagsReturnIntermediates flag, then don't generate a negative response, just + // deactivate the DNSQuestion. + if (!q->ReturnIntermed) + { + q->ThisQInterval = 0; + return; + } + + SuppressQuery = q->SuppressQuery; + DisallowPID = q->DisallowPID; // make sure that QuerySuppressed() returns false q->SuppressQuery = mDNSfalse; q->DisallowPID = mDNSfalse; - GenerateNegativeResponse(m, QC_suppressed); + GenerateNegativeResponse(m, mDNSInterface_Any, QC_suppressed); q->SuppressQuery = SuppressQuery; q->DisallowPID = DisallowPID; @@ -4602,13 +4853,15 @@ mDNSlocal void AnswerNewQuestion(mDNS *const m) { mDNSBool ShouldQueryImmediately = mDNStrue; DNSQuestion *const q = m->NewQuestions; // Grab the question we're going to answer - mDNSu32 slot = HashSlot(&q->qname); - CacheGroup *const cg = CacheGroupForName(m, slot, q->qnamehash, &q->qname); +#if USE_DNS64 + if (!mDNSOpaque16IsZero(q->TargetQID)) DNS64HandleNewQuestion(m, q); +#endif + CacheGroup *const cg = CacheGroupForName(m, q->qnamehash, &q->qname); mDNSBool AnsweredFromCache = mDNSfalse; verbosedebugf("AnswerNewQuestion: Answering %##s (%s)", q->qname.c, DNSTypeName(q->qtype)); - if (cg) CheckCacheExpiration(m, slot, cg); + if (cg) CheckCacheExpiration(m, HashSlotFromNameHash(q->qnamehash), cg); if (m->NewQuestions != q) { LogInfo("AnswerNewQuestion: Question deleted while doing CheckCacheExpiration"); goto exit; } m->NewQuestions = q->next; // Advance NewQuestions to the next *after* calling CheckCacheExpiration, because if we advance it first @@ -4697,7 +4950,7 @@ mDNSlocal void AnswerNewQuestion(mDNS *const m) AnswerCurrentQuestionWithResourceRecord(m, rr, QC_add); if (m->CurrentQuestion != q) break; // If callback deleted q, then we're finished here } - else if (RRTypeIsAddressType(rr->resrec.rrtype) && RRTypeIsAddressType(q->qtype)) + else if (mDNSOpaque16IsZero(q->TargetQID) && RRTypeIsAddressType(rr->resrec.rrtype) && RRTypeIsAddressType(q->qtype)) ShouldQueryImmediately = mDNSfalse; } // We don't use LogInfo for this "Question deleted" message because it happens so routinely that @@ -4711,7 +4964,7 @@ mDNSlocal void AnswerNewQuestion(mDNS *const m) if (!QuerySuppressed(q) && !AnsweredFromCache && q->RetryWithSearchDomains) { LogInfo("AnswerNewQuestion: Generating response for retrying with search domains %##s (%s)", q->qname.c, DNSTypeName(q->qtype)); - GenerateNegativeResponse(m, QC_forceresponse); + GenerateNegativeResponse(m, mDNSInterface_Any, QC_forceresponse); } if (m->CurrentQuestion != q) { debugf("AnswerNewQuestion: Question deleted while giving negative answer"); goto exit; } @@ -4748,9 +5001,9 @@ exit: // appropriate answers, stopping if it reaches a NewLocalOnlyRecord -- these will be handled by AnswerAllLocalQuestionsWithLocalAuthRecord mDNSlocal void AnswerNewLocalOnlyQuestion(mDNS *const m) { - mDNSu32 slot; AuthGroup *ag; DNSQuestion *q = m->NewLocalOnlyQuestions; // Grab the question we're going to answer + mDNSBool retEv = mDNSfalse; m->NewLocalOnlyQuestions = q->next; // Advance NewLocalOnlyQuestions to the next (if any) debugf("AnswerNewLocalOnlyQuestion: Answering %##s (%s)", q->qname.c, DNSTypeName(q->qtype)); @@ -4766,8 +5019,7 @@ mDNSlocal void AnswerNewLocalOnlyQuestion(mDNS *const m) // 1. First walk the LocalOnly records answering the LocalOnly question // 2. As LocalOnly questions should also be answered by any other Auth records local to the machine, // walk the ResourceRecords list delivering the answers - slot = AuthHashSlot(&q->qname); - ag = AuthGroupForName(&m->rrauth, slot, q->qnamehash, &q->qname); + ag = AuthGroupForName(&m->rrauth, q->qnamehash, &q->qname); if (ag) { m->CurrentRecord = ag->members; @@ -4777,7 +5029,8 @@ mDNSlocal void AnswerNewLocalOnlyQuestion(mDNS *const m) m->CurrentRecord = rr->next; if (LocalOnlyRecordAnswersQuestion(rr, q)) { - AnswerLocalQuestionWithLocalAuthRecord(m, rr, QC_add); + retEv = mDNStrue; + AnswerLocalQuestionWithLocalAuthRecord(m, rr, mDNStrue); if (m->CurrentQuestion != q) break; // If callback deleted q, then we're finished here } } @@ -4793,12 +5046,18 @@ mDNSlocal void AnswerNewLocalOnlyQuestion(mDNS *const m) m->CurrentRecord = rr->next; if (ResourceRecordAnswersQuestion(&rr->resrec, q)) { - AnswerLocalQuestionWithLocalAuthRecord(m, rr, QC_add); + retEv = mDNStrue; + AnswerLocalQuestionWithLocalAuthRecord(m, rr, mDNStrue); if (m->CurrentQuestion != q) break; // If callback deleted q, then we're finished here } } } + // The local host is the authoritative source for LocalOnly questions + // so if no records exist and client requested intermediates, then generate a negative response + if (!retEv && (m->CurrentQuestion == q) && q->ReturnIntermed) + GenerateNegativeResponse(m, mDNSInterface_LocalOnly, QC_forceresponse); + m->CurrentQuestion = mDNSNULL; m->CurrentRecord = mDNSNULL; } @@ -4913,7 +5172,7 @@ mDNSlocal CacheGroup *GetCacheGroup(mDNS *const m, const mDNSu32 slot, const Res cg->namehash = rr->namehash; cg->members = mDNSNULL; cg->rrcache_tail = &cg->members; - if (namelen > sizeof(cg->namestorage)) + if (namelen > sizeof(cg->namestorage)) cg->name = mDNSPlatformMemAllocate(namelen); else cg->name = (domainname*)cg->namestorage; @@ -4925,9 +5184,9 @@ mDNSlocal CacheGroup *GetCacheGroup(mDNS *const m, const mDNSu32 slot, const Res } AssignDomainName(cg->name, rr->name); - if (CacheGroupForRecord(m, slot, rr)) LogMsg("GetCacheGroup: Already have CacheGroup for %##s", rr->name->c); + if (CacheGroupForRecord(m, rr)) LogMsg("GetCacheGroup: Already have CacheGroup for %##s", rr->name->c); m->rrcache_hash[slot] = cg; - if (CacheGroupForRecord(m, slot, rr) != cg) LogMsg("GetCacheGroup: Not finding CacheGroup for %##s", rr->name->c); + if (CacheGroupForRecord(m, rr) != cg) LogMsg("GetCacheGroup: Not finding CacheGroup for %##s", rr->name->c); return(cg); } @@ -4967,7 +5226,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->SPSProxyListChanged); \ m->SPSProxyListChanged = (X); } while(0) // Called from mDNS_Execute() to expire stale proxy records @@ -5011,7 +5270,7 @@ mDNSlocal void CheckRmvEventsForLocalRecords(mDNS *const m) { debugf("CheckRmvEventsForLocalRecords: Generating local RMV events for %s", ARDisplayString(m, rr)); rr->resrec.RecordType = kDNSRecordTypeShared; - AnswerAllLocalQuestionsWithLocalAuthRecord(m, rr, QC_rmv); + AnswerAllLocalQuestionsWithLocalAuthRecord(m, rr, mDNSfalse); if (m->CurrentRecord == rr) // If rr still exists in list, restore its state now { rr->resrec.RecordType = kDNSRecordTypeDeregistering; @@ -5026,13 +5285,12 @@ mDNSlocal void CheckRmvEventsForLocalRecords(mDNS *const m) } } -mDNSlocal void TimeoutQuestions(mDNS *const m) +mDNSlocal void TimeoutQuestions_internal(mDNS *const m, DNSQuestion* questions, mDNSInterfaceID InterfaceID) { - m->NextScheduledStopTime = m->timenow + 0x3FFFFFFF; if (m->CurrentQuestion) LogMsg("TimeoutQuestions ERROR m->CurrentQuestion already set: %##s (%s)", m->CurrentQuestion->qname.c, DNSTypeName(m->CurrentQuestion->qtype)); - m->CurrentQuestion = m->Questions; + m->CurrentQuestion = questions; while (m->CurrentQuestion) { DNSQuestion *const q = m->CurrentQuestion; @@ -5044,7 +5302,8 @@ mDNSlocal void TimeoutQuestions(mDNS *const m) if (m->timenow - q->StopTime >= 0) { LogInfo("TimeoutQuestions: question %p %##s timed out, time %d", q, q->qname.c, m->timenow - q->StopTime); - GenerateNegativeResponse(m, QC_forceresponse); + q->LOAddressAnswers = 0; // unset since timing out the question + GenerateNegativeResponse(m, InterfaceID, QC_forceresponse); if (m->CurrentQuestion == q) q->StopTime = 0; } else @@ -5062,6 +5321,13 @@ mDNSlocal void TimeoutQuestions(mDNS *const m) m->CurrentQuestion = mDNSNULL; } +mDNSlocal void TimeoutQuestions(mDNS *const m) +{ + m->NextScheduledStopTime = m->timenow + FutureTime; // push reschedule of TimeoutQuestions to way off into the future + TimeoutQuestions_internal(m, m->Questions, mDNSInterface_Any); + TimeoutQuestions_internal(m, m->LocalOnlyQuestions, mDNSInterface_LocalOnly); +} + mDNSlocal void mDNSCoreFreeProxyRR(mDNS *const m) { AuthRecord *rrPtr = m->SPSRRSet, *rrNext = mDNSNULL; @@ -5079,10 +5345,6 @@ mDNSexport mDNSs32 mDNS_Execute(mDNS *const m) { mDNS_Lock(m); // Must grab lock before trying to read m->timenow -#if APPLE_OSX_mDNSResponder - mDNSLogStatistics(m); -#endif // APPLE_OSX_mDNSResponder - if (m->timenow - m->NextScheduledEvent >= 0) { int i; @@ -5109,13 +5371,13 @@ mDNSexport mDNSs32 mDNS_Execute(mDNS *const m) if (m->rrcache_size && m->timenow - m->NextCacheCheck >= 0) { mDNSu32 numchecked = 0; - m->NextCacheCheck = m->timenow + 0x3FFFFFFF; + m->NextCacheCheck = m->timenow + FutureTime; for (slot = 0; slot < CACHE_HASH_SLOTS; slot++) { if (m->timenow - m->rrcache_nextcheck[slot] >= 0) { CacheGroup **cp = &m->rrcache_hash[slot]; - m->rrcache_nextcheck[slot] = m->timenow + 0x3FFFFFFF; + m->rrcache_nextcheck[slot] = m->timenow + FutureTime; while (*cp) { debugf("m->NextCacheCheck %4d Slot %3d %##s", numchecked, slot, *cp ? (*cp)->name : (domainname*)"\x04NULL"); @@ -5135,7 +5397,7 @@ mDNSexport mDNSs32 mDNS_Execute(mDNS *const m) if (m->timenow - m->NextScheduledSPS >= 0) { - m->NextScheduledSPS = m->timenow + 0x3FFFFFFF; + m->NextScheduledSPS = m->timenow + FutureTime; CheckProxyRecords(m, m->DuplicateRecords); // Clear m->DuplicateRecords first, then m->ResourceRecords CheckProxyRecords(m, m->ResourceRecords); } @@ -5146,14 +5408,30 @@ mDNSexport mDNSs32 mDNS_Execute(mDNS *const m) // as records could have expired during that check if (m->timenow - m->NextScheduledKA >= 0) { - m->NextScheduledKA = m->timenow + 0x3FFFFFFF; + m->NextScheduledKA = m->timenow + FutureTime; mDNS_SendKeepalives(m); } +#if BONJOUR_ON_DEMAND + if (m->NextBonjourDisableTime && (m->timenow - m->NextBonjourDisableTime >= 0)) + { + // Schedule immediate network change processing to leave the multicast group + // since the delay time has expired since the previous active registration or query. + m->NetworkChanged = m->timenow; + m->NextBonjourDisableTime = 0; + m->BonjourEnabled = 0; + + LogInfo("mDNS_Execute: Scheduled network changed processing to leave multicast group."); + } +#endif // BONJOUR_ON_DEMAND + // Clear AnnounceOwner if necessary. (Do this *before* SendQueries() and SendResponses().) if (m->AnnounceOwner && m->timenow - m->AnnounceOwner >= 0) { m->AnnounceOwner = 0; + + // This is a good time to reset the delay counter used to prevent spurious conflicts + m->DelayConflictProcessing = 0; } if (m->DelaySleep && m->timenow - m->DelaySleep >= 0) @@ -5203,7 +5481,7 @@ mDNSexport mDNSs32 mDNS_Execute(mDNS *const m) if (LocalRecordReady(rr)) { debugf("mDNS_Execute: Delivering Add event with LocalAuthRecord %s", ARDisplayString(m, rr)); - AnswerAllLocalQuestionsWithLocalAuthRecord(m, rr, QC_add); + AnswerAllLocalQuestionsWithLocalAuthRecord(m, rr, mDNStrue); } else if (!rr->next) { @@ -5260,7 +5538,7 @@ mDNSexport mDNSs32 mDNS_Execute(mDNS *const m) if (LocalRecordReady(rr)) { debugf("mDNS_Execute: Delivering Add event with LocalAuthRecord %s", ARDisplayString(m, rr)); - AnswerAllLocalQuestionsWithLocalAuthRecord(m, rr, QC_add); + AnswerAllLocalQuestionsWithLocalAuthRecord(m, rr, mDNStrue); } else LogMsg("mDNS_Execute: LocalOnlyRecord %s not ready", ARDisplayString(m, rr)); } @@ -5314,12 +5592,17 @@ mDNSexport mDNSs32 mDNS_Execute(mDNS *const m) m->RandomQueryDelay = 0; m->RandomReconfirmDelay = 0; + // See if any questions (or local-only questions) have timed out if (m->NextScheduledStopTime && m->timenow - m->NextScheduledStopTime >= 0) TimeoutQuestions(m); #ifndef UNICAST_DISABLED if (m->NextSRVUpdate && m->timenow - m->NextSRVUpdate >= 0) UpdateAllSRVRecords(m); if (m->timenow - m->NextScheduledNATOp >= 0) CheckNATMappings(m); if (m->timenow - m->NextuDNSEvent >= 0) uDNS_Tasks(m); #endif +#if APPLE_OSX_mDNSResponder && ENABLE_BLE_TRIGGERED_BONJOUR + extern void serviceBLE(); + if (m->NextBLEServiceTime && (m->timenow - m->NextBLEServiceTime >= 0)) serviceBLE(); +#endif // APPLE_OSX_mDNSResponder && ENABLE_BLE_TRIGGERED_BONJOUR } // Note about multi-threaded systems: @@ -5359,11 +5642,9 @@ mDNSlocal void SuspendLLQs(mDNS *m) mDNSlocal mDNSBool QuestionHasLocalAnswers(mDNS *const m, DNSQuestion *q) { AuthRecord *rr; - mDNSu32 slot; AuthGroup *ag; - slot = AuthHashSlot(&q->qname); - ag = AuthGroupForName(&m->rrauth, slot, q->qnamehash, &q->qname); + ag = AuthGroupForName(&m->rrauth, q->qnamehash, &q->qname); if (ag) { for (rr = ag->members; rr; rr=rr->next) @@ -5399,7 +5680,7 @@ mDNSlocal void ActivateUnicastQuery(mDNS *const m, DNSQuestion *const question, !SameDomainLabel(question->qname.c, (const mDNSu8 *)"\x0c_autotunnel6")&& question->QuestionCallback != AutoTunnelCallback) { question->NoAnswer = NoAnswer_Suspended; - AddNewClientTunnel(m, question); + AddNewClientTunnel(question); return; } #endif // APPLE_OSX_mDNSResponder @@ -5565,11 +5846,7 @@ mDNSexport void mDNSCoreRestartQuestion(mDNS *const m, DNSQuestion *q) if (mDNSOpaque16IsZero(q->TargetQID) && ActiveQuestion(q)) { q->ThisQInterval = InitialQuestionInterval; // MUST be > zero for an active question -#if mDNS_REQUEST_UNICAST_RESPONSE - q->RequestUnicast = SET_QU_IN_FIRST_FOUR_QUERIES; -#else // mDNS_REQUEST_UNICAST_RESPONSE - q->RequestUnicast = SET_QU_IN_FIRST_QUERY; -#endif // mDNS_REQUEST_UNICAST_RESPONSE + q->RequestUnicast = kDefaultRequestUnicastCount; q->LastQTime = m->timenow - q->ThisQInterval; q->RecentAnswerPkts = 0; ExpireDupSuppressInfo(q->DupSuppress, m->timenow); @@ -5578,23 +5855,26 @@ mDNSexport void mDNSCoreRestartQuestion(mDNS *const m, DNSQuestion *q) } // restart the probe/announce cycle for multicast record -mDNSexport void mDNSCoreRestartRegistration(mDNS *const m, AuthRecord *rr, int announceCount) +mDNSexport void mDNSCoreRestartRegistration(mDNS *const m, AuthRecord *rr, int announceCount) { if (!AuthRecord_uDNS(rr)) { if (rr->resrec.RecordType == kDNSRecordTypeVerified && !rr->DependentOn) rr->resrec.RecordType = kDNSRecordTypeUnique; rr->ProbeCount = DefaultProbeCountForRecordType(rr->resrec.RecordType); - // announceCount < 0 indicates default announce count should be used - if (announceCount < 0) - announceCount = InitialAnnounceCount; - if (rr->AnnounceCount < announceCount) - rr->AnnounceCount = announceCount; - if (mDNS_KeepaliveRecord(&rr->resrec)) - rr->AnnounceCount = 0; // Do not announce keepalive records + { + rr->AnnounceCount = 0; // Do not announce keepalive records + } else - rr->AnnounceCount = InitialAnnounceCount; + { + // announceCount < 0 indicates default announce count should be used + if (announceCount < 0) + announceCount = InitialAnnounceCount; + if (rr->AnnounceCount < (mDNSu8)announceCount) + rr->AnnounceCount = (mDNSu8)announceCount; + } + rr->SendNSECNow = mDNSNULL; InitializeLastAPTime(m, rr); } @@ -5676,7 +5956,7 @@ mDNSexport void mDNS_UpdateAllowSleep(mDNS *const m) } // Call the platform code to enable/disable sleep - mDNSPlatformSetAllowSleep(m, allowSleep, reason); + mDNSPlatformSetAllowSleep(allowSleep, reason); #else (void) m; #endif /* !defined(IDLESLEEPCONTROL_DISABLED) */ @@ -5687,7 +5967,7 @@ mDNSlocal mDNSBool mDNSUpdateOkToSend(mDNS *const m, AuthRecord *rr, NetworkInte // If it is not a uDNS record, check to see if the updateid is zero. "updateid" is cleared when we have // sent the resource record on all the interfaces. If the update id is not zero, check to see if it is time // to send. - if (AuthRecord_uDNS(rr) || (rr->AuthFlags & AuthFlagsWakeOnly) || mDNSOpaque16IsZero(rr->updateid) || + if (AuthRecord_uDNS(rr) || (rr->AuthFlags & AuthFlagsWakeOnly) || mDNSOpaque16IsZero(rr->updateid) || m->timenow - (rr->LastAPTime + rr->ThisAPInterval) < 0) { return mDNSfalse; @@ -5708,53 +5988,56 @@ mDNSlocal mDNSBool mDNSUpdateOkToSend(mDNS *const m, AuthRecord *rr, NetworkInte return mDNSfalse; } -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 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 void UpdateRMAC(mDNS *const m, void *context) +{ + IPAddressMACMapping *addrmap = (IPAddressMACMapping *)context ; + m->CurrentRecord = m->ResourceRecords; + + if (!addrmap) + { + LogMsg("UpdateRMAC: 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) { mDNSu16 newrdlength; - mDNSAddr laddr, raddr; - mDNSEthAddr eth; - mDNSIPPort lport, rport; - mDNSu32 timeout, seq, ack; - mDNSu16 win; + mDNSAddr laddr = zeroAddr; + mDNSAddr raddr = zeroAddr; + mDNSEthAddr eth = zeroEthAddr; + mDNSIPPort lport = zeroIPPort; + mDNSIPPort rport = zeroIPPort; + mDNSu32 timeout = 0; + mDNSu32 seq = 0; + mDNSu32 ack = 0; + mDNSu16 win = 0; UTF8str255 txt; int rdsize; RData *newrd; @@ -5764,8 +6047,7 @@ mDNSexport mStatus UpdateKeepaliveRData(mDNS *const m, AuthRecord *rr, NetworkIn // Note: If we fail to update the DNS NULL record with additional information in this function, it will be registered // with the SPS like any other record. SPS will not send keepalives if it does not have additional information. mDNS_ExtractKeepaliveInfo(rr, &timeout, &laddr, &raddr, ð, &seq, &ack, &lport, &rport, &win); - if (!timeout || mDNSAddressIsZero(&laddr) || mDNSAddressIsZero(&raddr) || mDNSIPPortIsZero(lport) || - mDNSIPPortIsZero(rport)) + if (!timeout || mDNSAddressIsZero(&laddr) || mDNSAddressIsZero(&raddr) || mDNSIPPortIsZero(lport) || mDNSIPPortIsZero(rport)) { LogMsg("UpdateKeepaliveRData: not a valid record %s for keepalive %#a:%d %#a:%d", ARDisplayString(m, rr), &laddr, lport.NotAnInteger, &raddr, rport.NotAnInteger); return mStatus_UnknownErr; @@ -5785,7 +6067,7 @@ mDNSexport mStatus UpdateKeepaliveRData(mDNS *const m, AuthRecord *rr, NetworkIn // now, then we don't update the DNS NULL record. But we do not prevent it from registering with the SPS. When SPS sees // this DNS NULL record, it does not send any keepalives as it does not have all the information mDNSPlatformMemZero(&mti, sizeof (mDNSTCPInfo)); - ret = mDNSPlatformRetrieveTCPInfo(m, &laddr, &lport, &raddr, &rport, &mti); + ret = mDNSPlatformRetrieveTCPInfo(&laddr, &lport, &raddr, &rport, &mti); if (ret != mStatus_NoError) { LogMsg("mDNSPlatformRetrieveTCPInfo: mDNSPlatformRetrieveTCPInfo failed %d", ret); @@ -5828,8 +6110,8 @@ mDNSexport mStatus UpdateKeepaliveRData(mDNS *const m, AuthRecord *rr, NetworkIn // free that memory here before copying in the new data. if ( rr->resrec.rdata != &rr->rdatastorage) { - mDNSPlatformMemFree(rr->resrec.rdata); LogSPS("UpdateKeepaliveRData: Freed allocated memory for keep alive packet: %s ", ARDisplayString(m, rr)); + mDNSPlatformMemFree(rr->resrec.rdata); } SetNewRData(&rr->resrec, newrd, newrdlength); // Update our rdata @@ -5969,7 +6251,7 @@ mDNSlocal void SendSPSRegistrationForOwner(mDNS *const m, NetworkInterfaceInfo * LogSPS("SendSPSRegistration: Sending Update %s %d (%d) id %5d with %d records %d bytes to %#a:%d", intf->ifname, intf->NextSPSAttempt, sps, mDNSVal16(m->omsg.h.id), m->omsg.h.mDNS_numUpdates, p - m->omsg.data, &intf->SPSAddr[sps], mDNSVal16(intf->SPSPort[sps])); - // if (intf->NextSPSAttempt < 5) m->omsg.h.flags = zeroID; // For simulating packet loss + // if (intf->NextSPSAttempt < 5) m->omsg.h.flags = zeroID; // For simulating packet loss err = mDNSSendDNSMessage(m, &m->omsg, p, intf->InterfaceID, mDNSNULL, &intf->SPSAddr[sps], intf->SPSPort[sps], mDNSNULL, mDNSNULL, mDNSfalse); if (err) LogSPS("SendSPSRegistration: mDNSSendDNSMessage err %d", err); if (err && intf->SPSAddr[sps].type == mDNSAddrType_IPv4 && intf->NetWakeResolve[sps].ThisQInterval == -1) @@ -6042,7 +6324,7 @@ mDNSlocal void SPSInitRecordsBeforeUpdate(mDNS *const m, mDNSOpaque64 updateIntI { AuthRecord *ar; LogSPS("SPSInitRecordsBeforeUpdate: UpdateIntID 0x%x 0x%x", updateIntID.l[1], updateIntID.l[0]); - + *WakeOnlyService = mDNSfalse; // Before we store the A and AAAA records that we are going to register with the sleep proxy, @@ -6159,7 +6441,7 @@ mDNSlocal void NetWakeResolve(mDNS *const m, DNSQuestion *question, const Resour if (!AddRecord) return; // Don't care about REMOVE events if (answer->rrtype != question->qtype) return; // Don't care about CNAMEs - // if (answer->rrtype == kDNSType_AAAA && sps == 0) return; // To test failing to resolve sleep proxy's address + // if (answer->rrtype == kDNSType_AAAA && sps == 0) return; // To test failing to resolve sleep proxy's address if (answer->rrtype == kDNSType_SRV) { @@ -6245,14 +6527,8 @@ mDNSlocal void SendGoodbyesForWakeOnlyService(mDNS *const m, mDNSBool *WakeOnlyS { return SendGoodbyesForSelectServices(m, WakeOnlyService, WAKE_ONLY_SERVICE); } -#endif // APPLE_OSx_mDNSResponder +#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) { @@ -6349,25 +6625,23 @@ 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; - mDNSInterfaceID registeredIntfIDS[128]; + mDNSInterfaceID registeredIntfIDS[128] = { 0 }; mDNSu32 registeredCount = 0; int skippedRegistrations = 0; m->NextScheduledSPRetry = m->timenow; + // Clear out the SCDynamic entry that stores the external SPS information + mDNSPlatformClearSPSData(); + if (!m->SystemWakeOnLANEnabled) LogSPS("BeginSleepProcessing: m->SystemWakeOnLANEnabled is false"); else if (!mDNSCoreHaveAdvertisedMulticastServices(m)) LogSPS("BeginSleepProcessing: No advertised services"); else // If we have at least one advertised service { NetworkInterfaceInfo *intf; - - // Clear out the SCDynamic entry that stores the external SPS information - mDNSPlatformClearSPSMACAddr(); - for (intf = GetFirstActiveInterface(m->HostInterfaces); intf; intf = GetFirstActiveInterface(intf->next)) { // Intialize it to false. These values make sense only when SleepState is set to Sleeping. @@ -6407,18 +6681,21 @@ mDNSlocal void BeginSleepProcessing(mDNS *const m) else if (SupportsInNICProxy(intf)) { mDNSBool keepaliveOnly = mDNSfalse; - if (ActivateLocalProxy(m, intf, &keepaliveOnly) == mStatus_NoError) + if (ActivateLocalProxy(intf, &keepaliveOnly) == mStatus_NoError) { SendGoodbyesForWakeOnlyService(m, &WakeOnlyService); - if (keepaliveOnly) - SendGoodbyesForACOnlyServices(m, &ACOnlyService); - SendGoodbyes = mDNSfalse; - invokeKACallback = mDNSfalse; + + // Send goodbyes for all advertised services if the only record offloaded was the keepalive record. + SendGoodbyes = (keepaliveOnly) ? mDNStrue: mDNSfalse; + invokeKACallback = mDNSfalse; LogSPS("BeginSleepProcessing: %-6s using local proxy", intf->ifname); // This will leave m->SleepState set to SleepState_Transferring, // which is okay because with no outstanding resolves, or updates in flight, // mDNSCoreReadyForSleep() will conclude correctly that all the updates have already completed + // Setting this flag activates the SleepLimit which delays sleep by 5 seconds and + // will allow the system to deregister any BTMM records. + m->NextScheduledSPRetry = m->timenow + (5 * mDNSPlatformOneSecond); registeredIntfIDS[registeredCount] = intf->InterfaceID; registeredCount++; } @@ -6497,7 +6774,7 @@ mDNSlocal void BeginSleepProcessing(mDNS *const m) // // - If there are no sleep proxy servers, then send goodbyes on all interfaces // for both multicast and unicast. - // + // // - If we skipped registrations on some interfaces, then we have already marked // them appropriately above. We don't need to send goodbyes for unicast as // we have registered with at least one sleep proxy. @@ -6517,10 +6794,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 || ACOnlyService) + else if (WakeOnlyService) { // If we saw WakeOnly service above, send the goodbyes now. - LogSPS("BeginSleepProcessing: Sending goodbyes for %s", WakeOnlyService? "WakeOnlyService" : "AC Only Service"); + LogSPS("BeginSleepProcessing: Sending goodbyes for WakeOnlyService"); SendResponses(m); } } @@ -6546,7 +6823,7 @@ mDNSexport void mDNSCoreMachineSleep(mDNS *const m, mDNSBool sleep) #ifndef SPC_DISABLED if (oldstate == 1) mDNS_DeregisterService(m, &m->SPSRecords); #else - (void)oldstate; + (void)oldstate; #endif mDNS_ReclaimLockAfterCallback(); } @@ -6594,7 +6871,11 @@ mDNSexport void mDNSCoreMachineSleep(mDNS *const m, mDNSBool sleep) { m->SleepState = SleepState_Awake; m->SleepSeqNum++; - m->DelaySleep = 0; + // If the machine wakes and then immediately tries to sleep again (e.g. a maintenance wake) + // then we enforce a minimum delay of five 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 + kDarkWakeDelaySleep); } if (m->SPSState == 3) @@ -6603,7 +6884,7 @@ mDNSexport void mDNSCoreMachineSleep(mDNS *const m, mDNSBool sleep) mDNSCoreBeSleepProxyServer_internal(m, m->SPSType, m->SPSPortability, m->SPSMarginalPower, m->SPSTotalPower, m->SPSFeatureFlags); } m->mDNSStats.Wakes++; - + m->DelayConflictProcessing = MAX_CONFLICT_PROCESSING_DELAYS; // ... and the same for NextSPSAttempt for (intf = GetFirstActiveInterface(m->HostInterfaces); intf; intf = GetFirstActiveInterface(intf->next)) intf->NextSPSAttempt = -1; @@ -6617,11 +6898,6 @@ mDNSexport void mDNSCoreMachineSleep(mDNS *const m, mDNSBool sleep) // 2. Re-validate our cache records currtime = mDNSPlatformUTC(); -#if APPLE_OSX_mDNSResponder - // start time of this statistics gathering interval - m->StatStartTime = currtime; -#endif // APPLE_OSX_mDNSResponder - diff = currtime - m->TimeSlept; FORALL_CACHERECORDS(slot, cg, cr) { @@ -6644,7 +6920,7 @@ mDNSexport void mDNSCoreMachineSleep(mDNS *const m, mDNSBool sleep) mDNSu32 uTTL = RRUnadjustedTTL(cr->resrec.rroriginalttl); const mDNSs32 remain = uTTL - (m->timenow - cr->TimeRcvd) / mDNSPlatformOneSecond; - // -if we have slept longer than the remaining TTL, purge and start fresh. + // -if we have slept longer than the remaining TTL, purge and start fresh. // -if we have been sleeping for a long time, we could reduce TimeRcvd below by // a sufficiently big value which could cause the value to go into the future // because of the signed comparison of time. For this to happen, we should have been @@ -6768,7 +7044,7 @@ mDNSexport mDNSBool mDNSCoreReadyForSleep(mDNS *m, mDNSs32 now) if (rr->state == regState_Refresh && rr->tcp) { LogSPS("mDNSCoreReadyForSleep: waiting for Record updateIntID 0x%x 0x%x (updateid %d) %s", rr->updateIntID.l[1], rr->updateIntID.l[0], mDNSVal16(rr->updateid), ARDisplayString(m,rr)); goto notready; } #if APPLE_OSX_mDNSResponder - if (!RecordReadyForSleep(m, rr)) { LogSPS("mDNSCoreReadyForSleep: waiting for %s", ARDisplayString(m, rr)); goto notready; } + if (!RecordReadyForSleep(rr)) { LogSPS("mDNSCoreReadyForSleep: waiting for %s", ARDisplayString(m, rr)); goto notready; } #endif } @@ -7099,8 +7375,7 @@ exit: mDNSlocal CacheRecord *FindIdenticalRecordInCache(const mDNS *const m, const ResourceRecord *const pktrr) { - mDNSu32 slot = HashSlot(pktrr->name); - CacheGroup *cg = CacheGroupForRecord(m, slot, pktrr); + CacheGroup *cg = CacheGroupForRecord(m, pktrr); CacheRecord *rr; mDNSBool match; for (rr = cg ? cg->members : mDNSNULL; rr; rr=rr->next) @@ -7128,7 +7403,7 @@ mDNSlocal void DeregisterProxyRecord(mDNS *const m, AuthRecord *const rr) mDNSlocal void ClearKeepaliveProxyRecords(mDNS *const m, const OwnerOptData *const owner, AuthRecord *const thelist, const mDNSInterfaceID InterfaceID) { if (m->CurrentRecord) - LogMsg("ClearIdenticalProxyRecords ERROR m->CurrentRecord already set %s", ARDisplayString(m, m->CurrentRecord)); + LogMsg("ClearKeepaliveProxyRecords ERROR m->CurrentRecord already set %s", ARDisplayString(m, m->CurrentRecord)); m->CurrentRecord = thelist; // Normally, the RDATA of the keepalive record will be different each time and hence we always @@ -7262,9 +7537,9 @@ mDNSlocal mDNSu8 *ProcessQuery(mDNS *const m, const DNSMessage *const query, con m->rec.r.resrec.RecordType = 0; // Clear RecordType to show we're not still using it } - // + // // Look in Authority Section for NSEC3 record - // + // mDNSParseNSEC3Records(m, query, end, InterfaceID, &McastNSEC3Records); @@ -7328,7 +7603,7 @@ mDNSlocal mDNSu8 *ProcessQuery(mDNS *const m, const DNSMessage *const query, con // As we have verified this question to be part of the same subset, // set the anonymous data which is needed below when walk the cache // records to see what answers we should be expecting. The cache records - // may cache only the nsec3RR and not the anonymous data itself. + // may cache only the nsec3RR and not the anonymous data itself. if (pktq.AnonInfo && rr->resrec.AnonInfo) SetAnonData(&pktq, &rr->resrec, mDNStrue); @@ -7347,7 +7622,7 @@ mDNSlocal mDNSu8 *ProcessQuery(mDNS *const m, const DNSMessage *const query, con // We only mark this question for sending if it is at least one second since the last time we multicast it // on this interface. If it is more than a second, or LastMCInterface is different, then we may multicast it. // This is to guard against the case where someone blasts us with queries as fast as they can. - if (m->timenow - (rr->LastMCTime + mDNSPlatformOneSecond) >= 0 || + if ((mDNSu32)(m->timenow - rr->LastMCTime) >= (mDNSu32)mDNSPlatformOneSecond || (rr->LastMCInterface != mDNSInterfaceMark && rr->LastMCInterface != InterfaceID)) rr->NR_AnswerTo = NR_AnswerMulticast; } @@ -7376,44 +7651,25 @@ mDNSlocal mDNSu8 *ProcessQuery(mDNS *const m, const DNSMessage *const query, con if (query->h.flags.b[0] & kDNSFlag0_TC) m->mDNSStats.KnownAnswerMultiplePkts++; -#if ENABLE_MULTI_PACKET_QUERY_SNOOPING - if (QuestionNeedsMulticastResponse) -#else // We only do the following accelerated cache expiration and duplicate question suppression processing // for non-truncated multicast queries with multicast responses. // For any query generating a unicast response we don't do this because we can't assume we will see the response. // For truncated queries we don't do this because a response we're expecting might be suppressed by a subsequent // known-answer packet, and when there's packet loss we can't safely assume we'll receive *all* known-answer packets. if (QuestionNeedsMulticastResponse && !(query->h.flags.b[0] & kDNSFlag0_TC)) -#endif { #if POOF_ENABLED - const mDNSu32 slot = HashSlot(&pktq.qname); - CacheGroup *cg = CacheGroupForName(m, slot, pktq.qnamehash, &pktq.qname); + CacheGroup *cg = CacheGroupForName(m, pktq.qnamehash, &pktq.qname); CacheRecord *cr; // Make a list indicating which of our own cache records we expect to see updated as a result of this query // Note: Records larger than 1K are not habitually multicast, so don't expect those to be updated -#if ENABLE_MULTI_PACKET_QUERY_SNOOPING - if (!(query->h.flags.b[0] & kDNSFlag0_TC)) -#endif // ENABLE_MULTI_PACKET_QUERY_SNOOPING for (cr = cg ? cg->members : mDNSNULL; cr; cr=cr->next) if (SameNameRecordAnswersQuestion(&cr->resrec, &pktq) && cr->resrec.rdlength <= SmallRecordLimit) if (!cr->NextInKAList && eap != &cr->NextInKAList) { *eap = cr; eap = &cr->NextInKAList; -#if ENABLE_MULTI_PACKET_QUERY_SNOOPING - if (cr->MPUnansweredQ == 0 || m->timenow - cr->MPLastUnansweredQT >= mDNSPlatformOneSecond) - { - // Although MPUnansweredQ is only really used for multi-packet query processing, - // we increment it for both single-packet and multi-packet queries, so that it stays in sync - // with the MPUnansweredKA value, which by necessity is incremented for both query types. - cr->MPUnansweredQ++; - cr->MPLastUnansweredQT = m->timenow; - cr->MPExpectingKA = mDNStrue; - } -#endif // ENABLE_MULTI_PACKET_QUERY_SNOOPING } #endif // POOF_ENABLED @@ -7421,9 +7677,6 @@ mDNSlocal mDNSu8 *ProcessQuery(mDNS *const m, const DNSMessage *const query, con // We only do this for non-truncated queries. Right now it would be too complicated to try // to keep track of duplicate suppression state between multiple packets, especially when we // can't guarantee to receive all of the Known Answer packets that go with a particular query. -#if ENABLE_MULTI_PACKET_QUERY_SNOOPING - if (!(query->h.flags.b[0] & kDNSFlag0_TC)) -#endif // For anonymous question, the duplicate suppressesion should happen if the // question belongs in the same group. As the group is expected to be // small, we don't do the optimization for now. @@ -7507,16 +7760,6 @@ mDNSlocal mDNSu8 *ProcessQuery(mDNS *const m, const DNSMessage *const query, con ourcacherr = FindIdenticalRecordInCache(m, &m->rec.r.resrec); - #if ENABLE_MULTI_PACKET_QUERY_SNOOPING - // See if this Known-Answer suppresses any answers we were expecting for our cache records. We do this always, - // even if the TC bit is not set (the TC bit will *not* be set in the *last* packet of a multi-packet KA list). - if (ourcacherr && ourcacherr->MPExpectingKA && m->timenow - ourcacherr->MPLastUnansweredQT < mDNSPlatformOneSecond) - { - ourcacherr->MPUnansweredKA++; - ourcacherr->MPExpectingKA = mDNSfalse; - } - #endif - #if POOF_ENABLED // Having built our ExpectedAnswers list from the questions in this packet, we then remove // any records that are suppressed by the Known Answer list in this packet. @@ -7563,13 +7806,9 @@ mDNSlocal mDNSu8 *ProcessQuery(mDNS *const m, const DNSMessage *const query, con mDNSBool SendMulticastResponse = mDNSfalse; // Send modern multicast response mDNSBool SendUnicastResponse = mDNSfalse; // Send modern unicast response (not legacy unicast response) -#if !TARGET_OS_EMBEDDED - // always honor kDNSQClass_UnicastResponse in embedded environment to increase reliability - // in high multicast packet loss environments. - - // If it's been one TTL/4 since we multicast this, then send a multicast response + // If it's been one TTL/4 since we multicast this, then send a multicast response // for conflict detection, etc. - if (m->timenow - (rr->LastMCTime + TicksTTL(rr)/4) >= 0) + if ((mDNSu32)(m->timenow - rr->LastMCTime) >= (mDNSu32)TicksTTL(rr)/4) { SendMulticastResponse = mDNStrue; // If this record was marked for modern (delayed) unicast response, then mark it as promoted to @@ -7581,7 +7820,6 @@ mDNSlocal mDNSu8 *ProcessQuery(mDNS *const m, const DNSMessage *const query, con rr->NR_AnswerTo = NR_AnswerMulticast; } } -#endif // !TARGET_OS_EMBEDDED // If the client insists on a multicast response, then we'd better send one if (rr->NR_AnswerTo == NR_AnswerMulticast) @@ -7598,7 +7836,6 @@ mDNSlocal mDNSu8 *ProcessQuery(mDNS *const m, const DNSMessage *const query, con { SendLegacyResponse = mDNStrue; } - if (SendMulticastResponse || SendUnicastResponse) { @@ -7705,15 +7942,12 @@ exit: // For non-truncated queries, we can definitively say that we should expect // to be seeing a response for any records still left in the ExpectedAnswers list if (!(query->h.flags.b[0] & kDNSFlag0_TC)) - if (cr->UnansweredQueries == 0 || m->timenow - cr->LastUnansweredTime >= mDNSPlatformOneSecond) + if (cr->UnansweredQueries == 0 || m->timenow - cr->LastUnansweredTime >= mDNSPlatformOneSecond * 3/4) { cr->UnansweredQueries++; cr->LastUnansweredTime = m->timenow; -#if ENABLE_MULTI_PACKET_QUERY_SNOOPING if (cr->UnansweredQueries > 1) - debugf("ProcessQuery: (!TC) UAQ %lu MPQ %lu MPKA %lu %s", - cr->UnansweredQueries, cr->MPUnansweredQ, cr->MPUnansweredKA, CRDisplayString(m, cr)); -#endif // ENABLE_MULTI_PACKET_QUERY_SNOOPING + debugf("ProcessQuery: UnansweredQueries %lu %s", cr->UnansweredQueries, CRDisplayString(m, cr)); SetNextCacheCheckTimeForRecord(m, cr); } @@ -7721,47 +7955,14 @@ exit: // then mark it to expire in five seconds if we don't get a response by then. if (cr->UnansweredQueries >= MaxUnansweredQueries) { -#if ENABLE_MULTI_PACKET_QUERY_SNOOPING // Only show debugging message if this record was not about to expire anyway - if (RRExpireTime(cr) - m->timenow > 4 * mDNSPlatformOneSecond) - debugf("ProcessQuery: (Max) UAQ %lu MPQ %lu MPKA %lu mDNS_Reconfirm() for %s", - cr->UnansweredQueries, cr->MPUnansweredQ, cr->MPUnansweredKA, CRDisplayString(m, cr)); -#endif // ENABLE_MULTI_PACKET_QUERY_SNOOPING + if (RRExpireTime(cr) - m->timenow > (mDNSs32) kDefaultReconfirmTimeForNoAnswer * 4 / 3 + mDNSPlatformOneSecond) + LogInfo("ProcessQuery: UnansweredQueries %lu interface %lu TTL %lu mDNS_Reconfirm() for %s", + cr->UnansweredQueries, InterfaceID, (RRExpireTime(cr) - m->timenow + mDNSPlatformOneSecond-1) / mDNSPlatformOneSecond, CRDisplayString(m, cr)); + m->mDNSStats.PoofCacheDeletions++; mDNS_Reconfirm_internal(m, cr, kDefaultReconfirmTimeForNoAnswer); } -#if ENABLE_MULTI_PACKET_QUERY_SNOOPING - // Make a guess, based on the multi-packet query / known answer counts, whether we think we - // should have seen an answer for this. (We multiply MPQ by 4 and MPKA by 5, to allow for - // possible packet loss of up to 20% of the additional KA packets.) - else if (cr->MPUnansweredQ * 4 > cr->MPUnansweredKA * 5 + 8) - { - // We want to do this conservatively. - // If there are so many machines on the network that they have to use multi-packet known-answer lists, - // then we don't want them to all hit the network simultaneously with their final expiration queries. - // By setting the record to expire in four minutes, we achieve two things: - // (a) the 90-95% final expiration queries will be less bunched together - // (b) we allow some time for us to witness enough other failed queries that we don't have to do our own - mDNSu32 remain = (mDNSu32)(RRExpireTime(cr) - m->timenow) / 4; - if (remain > 240 * (mDNSu32)mDNSPlatformOneSecond) - remain = 240 * (mDNSu32)mDNSPlatformOneSecond; - - // Only show debugging message if this record was not about to expire anyway - if (RRExpireTime(cr) - m->timenow > 4 * mDNSPlatformOneSecond) - debugf("ProcessQuery: (MPQ) UAQ %lu MPQ %lu MPKA %lu mDNS_Reconfirm() for %s", - cr->UnansweredQueries, cr->MPUnansweredQ, cr->MPUnansweredKA, CRDisplayString(m, cr)); - - if (remain <= 60 * (mDNSu32)mDNSPlatformOneSecond) - cr->UnansweredQueries++; // Treat this as equivalent to one definite unanswered query - cr->MPUnansweredQ = 0; // Clear MPQ/MPKA statistics - cr->MPUnansweredKA = 0; - cr->MPExpectingKA = mDNSfalse; - - if (remain < kDefaultReconfirmTimeForNoAnswer) - remain = kDefaultReconfirmTimeForNoAnswer; - mDNS_Reconfirm_internal(m, cr, remain); - } -#endif // ENABLE_MULTI_PACKET_QUERY_SNOOPING } #endif // POOF_ENABLED @@ -7792,15 +7993,16 @@ mDNSlocal void mDNSCoreReceiveQuery(mDNS *const m, const DNSMessage *const msg, mDNSBool QueryWasLocalUnicast = srcaddr && dstaddr && !mDNSAddrIsDNSMulticast(dstaddr) && mDNS_AddressIsLocalSubnet(m, InterfaceID, srcaddr); - if (!InterfaceID && dstaddr && mDNSAddrIsDNSMulticast(dstaddr)) + if (!dstaddr || (!InterfaceID && mDNSAddrIsDNSMulticast(dstaddr))) { + const char *const reason = !dstaddr ? "Received over TCP connection" : "Multicast, but no InterfaceID"; LogMsg("Ignoring Query from %#-15a:%-5d to %#-15a:%-5d on 0x%p with " - "%2d Question%s %2d Answer%s %2d Authorit%s %2d Additional%s %d bytes (Multicast, but no InterfaceID)", + "%2d Question%s %2d Answer%s %2d Authorit%s %2d Additional%s %d bytes (%s)", srcaddr, mDNSVal16(srcport), dstaddr, mDNSVal16(dstport), InterfaceID, msg->h.numQuestions, msg->h.numQuestions == 1 ? ", " : "s,", 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); + msg->h.numAdditionals, msg->h.numAdditionals == 1 ? " " : "s", end - msg->data, reason); return; } @@ -7882,10 +8084,7 @@ mDNSlocal DNSQuestion *ExpectingUnicastResponseForRecord(mDNS *const m, mDNSIPPort srcp; if (!tcp) { - if (q->LocalSocket) - srcp = q->LocalSocket->port; - else - srcp = zeroIPPort; + srcp = q->LocalSocket ? q->LocalSocket->port : zeroIPPort; } else { @@ -7893,9 +8092,9 @@ mDNSlocal DNSQuestion *ExpectingUnicastResponseForRecord(mDNS *const m, } if (mDNSSameIPPort(srcp, port)) return(q); - // if (mDNSSameAddress(srcaddr, &q->Target)) return(mDNStrue); - // if (q->LongLived && mDNSSameAddress(srcaddr, &q->servAddr)) return(mDNStrue); Shouldn't need this now that we have LLQType checking - // if (TrustedSource(m, srcaddr)) return(mDNStrue); + // if (mDNSSameAddress(srcaddr, &q->Target)) return(mDNStrue); + // if (q->LongLived && mDNSSameAddress(srcaddr, &q->servAddr)) return(mDNStrue); Shouldn't need this now that we have LLQType checking + // if (TrustedSource(m, srcaddr)) return(mDNStrue); LogInfo("WARNING: Ignoring suspect uDNS response for %##s (%s) [q->Target %#a:%d] from %#a:%d %s", q->qname.c, DNSTypeName(q->qtype), &q->Target, mDNSVal16(srcp), srcaddr, mDNSVal16(port), CRDisplayString(m, rr)); return(mDNSNULL); @@ -7933,7 +8132,7 @@ mDNSexport CacheRecord *CreateNewCacheEntry(mDNS *const m, const mDNSu32 slot, C if (!m->rec.r.resrec.InterfaceID) debugf("CreateNewCacheEntry %s", CRDisplayString(m, &m->rec.r)); //if (RDLength > InlineCacheRDSize) - // LogInfo("Rdata len %4d > InlineCacheRDSize %d %s", RDLength, InlineCacheRDSize, CRDisplayString(m, &m->rec.r)); + // LogInfo("Rdata len %4d > InlineCacheRDSize %d %s", RDLength, InlineCacheRDSize, CRDisplayString(m, &m->rec.r)); if (!cg) cg = GetCacheGroup(m, slot, &m->rec.r.resrec); // If we don't have a CacheGroup for this name, make one now if (cg) rr = GetCacheRecord(m, cg, RDLength); // Make a cache record, being careful not to recycle cg @@ -8010,19 +8209,13 @@ mDNSlocal void RefreshCacheRecord(mDNS *const m, CacheRecord *rr, mDNSu32 ttl) rr->TimeRcvd = m->timenow; rr->resrec.rroriginalttl = ttl; rr->UnansweredQueries = 0; -#if ENABLE_MULTI_PACKET_QUERY_SNOOPING - rr->MPUnansweredQ = 0; - rr->MPUnansweredKA = 0; - rr->MPExpectingKA = mDNSfalse; -#endif SetNextCacheCheckTimeForRecord(m, rr); } mDNSexport void GrantCacheExtensions(mDNS *const m, DNSQuestion *q, mDNSu32 lease) { CacheRecord *rr; - const mDNSu32 slot = HashSlot(&q->qname); - CacheGroup *cg = CacheGroupForName(m, slot, q->qnamehash, &q->qname); + CacheGroup *cg = CacheGroupForName(m, q->qnamehash, &q->qname); for (rr = cg ? cg->members : mDNSNULL; rr; rr=rr->next) if (rr->CRActiveQuestion == q) { @@ -8197,7 +8390,7 @@ mDNSlocal void mDNSCoreReceiveNoDNSSECAnswers(mDNS *const m, const DNSMessage *c LogMsg("mDNSCoreReceiveNoDNSSECAnswers: ERROR!! qptr %##s (%s) Duplicate question matching response", qptr->qname.c, DNSTypeName(qptr->qtype)); // Be careful to call the callback for duplicate questions first and then the original - // question. If we called the callback on the original question, it could stop and + // question. If we called the callback on the original question, it could stop and // a duplicate question would become the original question. mDNS_DropLockBeforeCallback(); // Allow client (and us) to legally make mDNS API calls for (q = qptr->next ; q && q != m->NewQuestions; q = next) @@ -8235,8 +8428,7 @@ mDNSlocal void mDNSCoreReceiveNoUnicastAnswers(mDNS *const m, const DNSMessage * if (ptr && (qptr = ExpectingUnicastResponseForQuestion(m, dstport, response->h.id, &q, !dstaddr))) { CacheRecord *rr, *neg = mDNSNULL; - mDNSu32 slot = HashSlot(&q.qname); - CacheGroup *cg = CacheGroupForName(m, slot, q.qnamehash, &q.qname); + CacheGroup *cg = CacheGroupForName(m, q.qnamehash, &q.qname); for (rr = cg ? cg->members : mDNSNULL; rr; rr=rr->next) if (SameNameRecordAnswersQuestion(&rr->resrec, qptr)) { @@ -8272,7 +8464,7 @@ mDNSlocal void mDNSCoreReceiveNoUnicastAnswers(mDNS *const m, const DNSMessage * // the application if (qptr->ProxyQuestion) qptr->responseFlags = response->h.flags; - GenerateNegativeResponse(m, QC_forceresponse); + GenerateNegativeResponse(m, mDNSInterface_Any, QC_forceresponse); m->CurrentQuestion = mDNSNULL; } else @@ -8305,8 +8497,7 @@ mDNSlocal void mDNSCoreReceiveNoUnicastAnswers(mDNS *const m, const DNSMessage * ptr = GetLargeResourceRecord(m, response, ptr, end, InterfaceID, kDNSRecordTypePacketAuth, &m->rec); if (ptr && m->rec.r.resrec.RecordType != kDNSRecordTypePacketNegative && m->rec.r.resrec.rrtype == kDNSType_SOA) { - const mDNSu32 s = HashSlot(m->rec.r.resrec.name); - CacheGroup *cgSOA = CacheGroupForRecord(m, s, &m->rec.r.resrec); + CacheGroup *cgSOA = CacheGroupForRecord(m, &m->rec.r.resrec); const rdataSOA *const soa = (const rdataSOA *)m->rec.r.resrec.rdata->u.data; mDNSu32 ttl_s = soa->min; // We use the lesser of the SOA.MIN field and the SOA record's TTL, *except* @@ -8318,7 +8509,7 @@ mDNSlocal void mDNSCoreReceiveNoUnicastAnswers(mDNS *const m, const DNSMessage * // Create the SOA record as we may have to return this to the questions // that we are acting as a proxy for currently or in the future. - SOARecord = CreateNewCacheEntry(m, s, cgSOA, 1, mDNSfalse, mDNSNULL); + SOARecord = CreateNewCacheEntry(m, HashSlotFromNameHash(m->rec.r.resrec.namehash), cgSOA, 1, mDNSfalse, mDNSNULL); // Special check for SOA queries: If we queried for a.b.c.d.com, and got no answer, // with an Authority Section SOA record for d.com, then this is a hint that the authority @@ -8401,12 +8592,12 @@ mDNSlocal void mDNSCoreReceiveNoUnicastAnswers(mDNS *const m, const DNSMessage * // been NULL. If we pass NULL cg to new cache entries that we create below, // it will create additional cache groups for the same name. To avoid that, // look up the cache group again to re-initialize cg again. - cg = CacheGroupForName(m, slot, hash, name); + cg = CacheGroupForName(m, hash, name); if (NSECRecords && DNSSECQuestion(qptr)) { // Create the cache entry with delay and then add the NSEC records // to it and add it immediately. - negcr = CreateNewCacheEntry(m, slot, cg, 1, mDNStrue, mDNSNULL); + negcr = CreateNewCacheEntry(m, HashSlotFromNameHash(hash), cg, 1, mDNStrue, mDNSNULL); if (negcr) { negcr->CRDNSSECQuestion = 0; @@ -8431,7 +8622,7 @@ mDNSlocal void mDNSCoreReceiveNoUnicastAnswers(mDNS *const m, const DNSMessage * else { // Need to add with a delay so that we can tag the SOA record - negcr = CreateNewCacheEntry(m, slot, cg, 1, mDNStrue, mDNSNULL); + negcr = CreateNewCacheEntry(m, HashSlotFromNameHash(hash), cg, 1, mDNStrue, mDNSNULL); if (negcr) { negcr->CRDNSSECQuestion = 0; @@ -8455,9 +8646,6 @@ mDNSlocal void mDNSCoreReceiveNoUnicastAnswers(mDNS *const m, const DNSMessage * repeat--; name = (const domainname *)(name->c + 1 + name->c[0]); hash = DomainNameHashValue(name); - slot = HashSlot(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); } } } @@ -8632,7 +8820,6 @@ mDNSlocal CacheRecord* mDNSCoreReceiveCacheCheck(mDNS *const m, const DNSMessage } else { - // If the packet TTL is zero, that means we're deleting this record. // To give other hosts on the network a chance to protest, we push the deletion // out one second into the future. Also, we set UnansweredQueries to MaxUnansweredQueries. @@ -8673,7 +8860,6 @@ mDNSlocal void mDNSParseNSEC3Records(mDNS *const m, const DNSMessage *const resp } for (i = 0; i < response->h.numAuthorities && ptr && ptr < end; i++) { - mDNSu32 slot; CacheGroup *cg; ptr = GetLargeResourceRecord(m, response, ptr, end, InterfaceID, kDNSRecordTypePacketAuth, &m->rec); @@ -8683,11 +8869,10 @@ mDNSlocal void mDNSParseNSEC3Records(mDNS *const m, const DNSMessage *const resp m->rec.r.resrec.RecordType = 0; continue; } - slot = HashSlot(m->rec.r.resrec.name); - cg = CacheGroupForRecord(m, slot, &m->rec.r.resrec); + cg = CacheGroupForRecord(m, &m->rec.r.resrec); // Create the cache entry but don't add it to the cache it. We need // to cache this along with the main cache record. - rr = CreateNewCacheEntry(m, slot, cg, 0, mDNSfalse, mDNSNULL); + rr = CreateNewCacheEntry(m, HashSlotFromNameHash(m->rec.r.resrec.namehash), cg, 0, mDNSfalse, mDNSNULL); if (rr) { debugf("mDNSParseNSEC3Records: %s", CRDisplayString(m, rr)); @@ -8703,7 +8888,7 @@ mDNSlocal void mDNSCoreResetRecord(mDNS *const m) m->rec.r.resrec.RecordType = 0; // Clear RecordType to show we're not still using it if (m->rec.r.resrec.AnonInfo) { - FreeAnonInfo(m->rec.r.resrec.AnonInfo); + FreeAnonInfo(m->rec.r.resrec.AnonInfo); m->rec.r.resrec.AnonInfo = mDNSNULL; } } @@ -8740,6 +8925,7 @@ mDNSlocal void mDNSCoreReceiveResponse(mDNS *const m, mDNSBool rrsigsCreated = mDNSfalse; mDNSBool DNSSECQuestion = mDNSfalse; NetworkInterfaceInfo *llintf = FirstIPv4LLInterfaceForID(m, InterfaceID); + mDNSBool recordAcceptedInResponse = mDNSfalse; // Set if a record is accepted from a unicast mDNS response that answers an existing question. // 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 @@ -8808,8 +8994,7 @@ mDNSlocal void mDNSCoreReceiveResponse(mDNS *const m, CacheRecord *rr; // Remember the unicast question that we found, which we use to make caching // decisions later on in this function - const mDNSu32 slot = HashSlot(&q.qname); - CacheGroup *cg = CacheGroupForName(m, slot, q.qnamehash, &q.qname); + CacheGroup *cg = CacheGroupForName(m, q.qnamehash, &q.qname); if (!mDNSOpaque16IsZero(response->h.id)) { unicastQuestion = qptr; @@ -8850,14 +9035,14 @@ mDNSlocal void mDNSCoreReceiveResponse(mDNS *const m, // and hence retransmit without the EDNS0/DOK option. if (DNSSECOptionalQuestion(qptr) && qptr->qDNSServer && !qptr->qDNSServer->DNSSECAware) { - LogInfo("mDNSCoreReceiveResponse: Server %p responded with code %d to DNSSEC Query %##s (%s), clear DO flag", + LogInfo("mDNSCoreReceiveResponse: Server %p responded with code %d to DNSSEC Query %##s (%s), clear DO flag", qptr->qDNSServer, rcode, q.qname.c, DNSTypeName(q.qtype)); - qptr->qDNSServer->req_DO = mDNSfalse; + qptr->qDNSServer->req_DO = mDNSfalse; } // For Unicast DNS Queries, penalize the DNSServer else { - LogInfo("mDNSCoreReceiveResponse: Server %p responded with code %d to query %##s (%s)", + LogInfo("mDNSCoreReceiveResponse: Server %p responded with code %d to query %##s (%s)", qptr->qDNSServer, rcode, q.qname.c, DNSTypeName(q.qtype)); PenalizeDNSServer(m, qptr, response->h.flags); } @@ -8892,7 +9077,9 @@ mDNSlocal void mDNSCoreReceiveResponse(mDNS *const m, { // All responses sent via LL multicast are acceptable for caching // All responses received over our outbound TCP connections are acceptable for caching - mDNSBool AcceptableResponse = ResponseMCast || !dstaddr || LLQType; + // We accept all records in a unicast response to a multicast query once we find one that + // answers an active question. + mDNSBool AcceptableResponse = ResponseMCast || !dstaddr || LLQType || recordAcceptedInResponse; // (Note that just because we are willing to cache something, that doesn't necessarily make it a trustworthy answer // to any specific question -- any code reading records from the cache needs to make that determination for itself.) @@ -8979,38 +9166,42 @@ mDNSlocal void mDNSCoreReceiveResponse(mDNS *const m, // Even though it is AcceptableResponse, we still need a DNSServer pointer for the resource records that // we create. - 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; - } - } + 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 + { + // Accept all remaining records in this unicast response to an mDNS query. + recordAcceptedInResponse = mDNStrue; + LogInfo("mDNSCoreReceiveResponse: Accepting response for query: %##s (%s)", 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) @@ -9121,13 +9312,36 @@ mDNSlocal void mDNSCoreReceiveResponse(mDNS *const m, // If we're probing for this record, we just failed else if (rr->resrec.RecordType == kDNSRecordTypeUnique) { + // At this point in the code, we're probing for uniqueness. + // We've sent at least one probe (rr->ProbeCount < DefaultProbeCountForTypeUnique) + // but we haven't completed probing yet (rr->resrec.RecordType == kDNSRecordTypeUnique). // Before we call deregister, check if this is a packet we registered with the sleep proxy. if (!mDNSCoreRegisteredProxyRecord(m, rr)) { - LogMsg("mDNSCoreReceiveResponse: ProbeCount %d; will deregister %s", rr->ProbeCount, ARDisplayString(m, rr)); - - m->mDNSStats.NameConflicts++; - mDNS_Deregister_internal(m, rr, mDNS_Dereg_conflict); + // This may be a conflict due to stale packets on the network. Delay probing by a second. + // If there are conflicts after 3 such attempts, then it is a true conflict. + if (m->DelayConflictProcessing) + { + m->DelayConflictProcessing--; + LogMsg("Possible spurious conflict for %s. Attempt %d at suppressing probes for one second", + ARDisplayString(m, rr), (MAX_CONFLICT_PROCESSING_DELAYS - m->DelayConflictProcessing)); + rr->ProbeCount = DefaultProbeCountForTypeUnique + 1; + rr->AnnounceCount = InitialAnnounceCount; + m->SuppressProbes = NonZeroTime(m->timenow + mDNSPlatformOneSecond); + InitializeLastAPTime(m, rr); + RecordProbeFailure(m, rr); // Repeated late conflicts also cause us to back off to the slower probing rate + } + else + { + LogMsg("mDNSCoreReceiveResponse: ProbeCount %d; will deregister %s", rr->ProbeCount, ARDisplayString(m, rr)); + m->mDNSStats.NameConflicts++; +#if APPLE_OSX_mDNSResponder + // See if this record was also registered with any D2D plugins. + D2D_stop_advertising_record(rr); +#endif + mDNS_Deregister_internal(m, rr, mDNS_Dereg_conflict); + } + } } // We assumed this record must be unique, but we were wrong. (e.g. There are two mDNSResponders on the @@ -9139,6 +9353,9 @@ mDNSlocal void mDNSCoreReceiveResponse(mDNS *const m, { LogMsg("mDNSCoreReceiveResponse: Unexpected conflict discarding %s", ARDisplayString(m, rr)); m->mDNSStats.KnownUniqueNameConflicts++; +#if APPLE_OSX_mDNSResponder + D2D_stop_advertising_record(rr); +#endif mDNS_Deregister_internal(m, rr, mDNS_Dereg_conflict); } else @@ -9150,7 +9367,7 @@ mDNSlocal void mDNSCoreReceiveResponse(mDNS *const m, // have any record(s) of the same type that we should re-assert to rescue them // (see note about "multi-homing and bridged networks" at the end of this function). else if (m->rec.r.resrec.rrtype == rr->resrec.rrtype) - if ((m->rec.r.resrec.RecordType & kDNSRecordTypePacketUniqueMask) && m->timenow - rr->LastMCTime > mDNSPlatformOneSecond/2) + if ((m->rec.r.resrec.RecordType & kDNSRecordTypePacketUniqueMask) && (mDNSu32)(m->timenow - rr->LastMCTime) > (mDNSu32)mDNSPlatformOneSecond/2) { rr->ImmedAnswer = mDNSInterfaceMark; m->NextScheduledResponse = m->timenow; } } } @@ -9169,8 +9386,8 @@ mDNSlocal void mDNSCoreReceiveResponse(mDNS *const m, if (!AcceptableResponse) LogInfo("mDNSCoreReceiveResponse ignoring %s", CRDisplayString(m, &m->rec.r)); if (m->rrcache_size && AcceptableResponse) { - const mDNSu32 slot = HashSlot(m->rec.r.resrec.name); - CacheGroup *cg = CacheGroupForRecord(m, slot, &m->rec.r.resrec); + const mDNSu32 slot = HashSlotFromNameHash(m->rec.r.resrec.namehash); + CacheGroup *cg = CacheGroupForRecord(m, &m->rec.r.resrec); CacheRecord *rr = mDNSNULL; if (McastNSEC3Records) @@ -9180,7 +9397,7 @@ mDNSlocal void mDNSCoreReceiveResponse(mDNS *const m, // // If this record should go in the nseclist, don't look in the cache for updating it. // They are supposed to be cached under the "nsec" field of the cache record for - // validation. Just create the cache record. + // validation. Just create the cache record. if (!nseclist) { rr = mDNSCoreReceiveCacheCheck(m, response, LLQType, slot, cg, unicastQuestion, &cfp, &NSECCachePtr, InterfaceID); @@ -9196,7 +9413,7 @@ mDNSlocal void mDNSCoreReceiveResponse(mDNS *const m, if (AddToCFList) delay = NonZeroTime(m->timenow + mDNSPlatformOneSecond); else - delay = CheckForSoonToExpireRecords(m, m->rec.r.resrec.name, m->rec.r.resrec.namehash, slot, mDNSNULL); + delay = CheckForSoonToExpireRecords(m, m->rec.r.resrec.name, m->rec.r.resrec.namehash, mDNSNULL); // If unique, assume we may have to delay delivery of this 'add' event. // Below, where we walk the CacheFlushRecords list, we either call CacheRecordDeferredAdd() @@ -9262,8 +9479,8 @@ exit: while (CacheFlushRecords != (CacheRecord*)1) { CacheRecord *r1 = CacheFlushRecords, *r2; - const mDNSu32 slot = HashSlot(r1->resrec.name); - const CacheGroup *cg = CacheGroupForRecord(m, slot, &r1->resrec); + const mDNSu32 slot = HashSlotFromNameHash(r1->resrec.namehash); + const CacheGroup *cg = CacheGroupForRecord(m, &r1->resrec); CacheFlushRecords = CacheFlushRecords->NextInCFList; r1->NextInCFList = mDNSNULL; @@ -9307,7 +9524,7 @@ exit: continue; } } - + // For Unicast (null InterfaceID) the resolver IDs should also match if ((r1->resrec.InterfaceID == r2->resrec.InterfaceID) && (r1->resrec.InterfaceID || (id1 == id2)) && @@ -9331,7 +9548,7 @@ exit: // 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 + // We also suppress log message in the case of SRV records that are received // 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. @@ -9406,14 +9623,14 @@ exit: // Note: We need to do this before we call CacheRecordDeferredAdd as this // might start the verification process which needs these NSEC records if (!AddNSECSForCacheRecord(m, NSECRecords, NSECCachePtr, rcode)) - { + { LogInfo("mDNSCoreReceiveResponse: AddNSECSForCacheRecord failed to add NSEC for %s", CRDisplayString(m, NSECCachePtr)); FreeNSECRecords(m, NSECRecords); } NSECRecords = mDNSNULL; NSECCachePtr = mDNSNULL; } - r1->DelayDelivery = CheckForSoonToExpireRecords(m, r1->resrec.name, r1->resrec.namehash, slot, mDNSNULL); + r1->DelayDelivery = CheckForSoonToExpireRecords(m, r1->resrec.name, r1->resrec.namehash, mDNSNULL); // If no longer delaying, deliver answer now, else schedule delivery for the appropriate time if (!r1->DelayDelivery) CacheRecordDeferredAdd(m, r1); else ScheduleNextCacheCheckTime(m, slot, r1->DelayDelivery); @@ -9426,7 +9643,7 @@ exit: { LogInfo("mDNSCoreReceieveResponse: Updating NSEC records in %s", CRDisplayString(m, NSECCachePtr)); if (!AddNSECSForCacheRecord(m, NSECRecords, NSECCachePtr, rcode)) - { + { LogInfo("mDNSCoreReceiveResponse: AddNSECSForCacheRecord failed to add NSEC for %s", CRDisplayString(m, NSECCachePtr)); FreeNSECRecords(m, NSECRecords); } @@ -9506,8 +9723,8 @@ mDNSlocal void SPSRecordCallback(mDNS *const m, AuthRecord *const ar, mStatus re LogMsg("%-7s Conflicting mDNS -- waking %.6a %s", InterfaceNameForID(m, ar->resrec.InterfaceID), &ar->WakeUp.HMAC, ARDisplayString(m, ar)); if (ar->WakeUp.HMAC.l[0]) { - SendWakeup(m, ar->resrec.InterfaceID, &ar->WakeUp.IMAC, &ar->WakeUp.password); // Send one wakeup magic packet - ScheduleWakeup(m, ar->resrec.InterfaceID, &ar->WakeUp.HMAC); // Schedule all other records with the same owner to be woken + SendWakeup(m, ar->resrec.InterfaceID, &ar->WakeUp.IMAC, &ar->WakeUp.password, mDNSfalse); // Send one wakeup magic packet + ScheduleWakeup(m, ar->resrec.InterfaceID, &ar->WakeUp.HMAC); // Schedule all other records with the same owner to be woken } mDNS_Unlock(m); } @@ -9525,7 +9742,7 @@ mDNSlocal mDNSu8 *GetValueForMACAddr(mDNSu8 *ptr, mDNSu8 *limit, mDNSEthAddr *et int i; mDNSs8 hval = 0; int colons = 0; - mDNSu16 val = 0; /* need to use 16 bit int to detect overflow */ + mDNSu8 val = 0; for (i = 0; ptr < limit && *ptr != ' ' && i < 17; i++, ptr++) { @@ -9537,12 +9754,12 @@ mDNSlocal mDNSu8 *GetValueForMACAddr(mDNSu8 *ptr, mDNSu8 *limit, mDNSEthAddr *et } else if (*ptr == ':') { - if (colons >=5 || val > 255) + if (colons >=5) { LogMsg("GetValueForMACAddr: Address malformed colons %d val %d", colons, val); return mDNSNULL; } - eth->b[colons] = (mDNSs8)val; + eth->b[colons] = val; colons++; val = 0; } @@ -9552,7 +9769,7 @@ mDNSlocal mDNSu8 *GetValueForMACAddr(mDNSu8 *ptr, mDNSu8 *limit, mDNSEthAddr *et LogMsg("GetValueForMACAddr: Address malformed colons %d", colons); return mDNSNULL; } - eth->b[colons] = (mDNSs8)val; + eth->b[colons] = val; return ptr; } @@ -9722,32 +9939,33 @@ mDNSlocal mDNSu8 *GetValueForKeepalive(mDNSu8 *ptr, mDNSu8 *limit, mDNSu32 *valu mDNSexport mDNSBool mDNSValidKeepAliveRecord(AuthRecord *rr) { - mDNSAddr laddr, raddr; - mDNSEthAddr eth; - mDNSIPPort lport, rport; - mDNSu32 timeout, seq, ack; - mDNSu16 win; + mDNSAddr laddr, raddr; + mDNSEthAddr eth; + mDNSIPPort lport, rport; + mDNSu32 timeout, seq, ack; + mDNSu16 win; - if (!mDNS_KeepaliveRecord(&rr->resrec)) - { - return mDNSfalse; - } + if (!mDNS_KeepaliveRecord(&rr->resrec)) + { + return mDNSfalse; + } - timeout = seq = ack = 0; - win = 0; - laddr = raddr = zeroAddr; - lport = rport = zeroIPPort; + timeout = seq = ack = 0; + win = 0; + laddr = raddr = zeroAddr; + lport = rport = zeroIPPort; + eth = zeroEthAddr; - mDNS_ExtractKeepaliveInfo(rr, &timeout, &laddr, &raddr, ð, &seq, &ack, &lport, &rport, &win); + mDNS_ExtractKeepaliveInfo(rr, &timeout, &laddr, &raddr, ð, &seq, &ack, &lport, &rport, &win); - if (mDNSAddressIsZero(&laddr) || mDNSIPPortIsZero(lport) || - mDNSAddressIsZero(&raddr) || mDNSIPPortIsZero(rport) || - mDNSEthAddressIsZero(eth)) - { - return mDNSfalse; - } + if (mDNSAddressIsZero(&laddr) || mDNSIPPortIsZero(lport) || + mDNSAddressIsZero(&raddr) || mDNSIPPortIsZero(rport) || + mDNSEthAddressIsZero(eth)) + { + return mDNSfalse; + } - return mDNStrue; + return mDNStrue; } @@ -9778,7 +9996,7 @@ mDNSlocal void mDNS_ExtractKeepaliveInfo(AuthRecord *ar, mDNSu32 *timeout, mDNSA raddr->type = mDNSAddrType_IPv4; ptr = GetValueForIPv4Addr(ptr, limit, &raddr->ip.v4); } - if (param == 'H') + else if (param == 'H') { laddr->type = mDNSAddrType_IPv6; ptr = GetValueForIPv6Addr(ptr, limit, &laddr->ip.v6); @@ -10124,30 +10342,48 @@ mDNSlocal void mDNSCoreReceiveUpdate(mDNS *const m, mDNS_SendKeepalives(m); } +mDNSlocal mDNSu32 mDNSGenerateOwnerOptForInterface(mDNS *const m, const mDNSInterfaceID InterfaceID, DNSMessage *msg) +{ + mDNSu8 *ptr = msg->data; + mDNSu8 *end = mDNSNULL; + mDNSu32 length = 0; + AuthRecord opt; + NetworkInterfaceInfo *intf; + + mDNS_SetupResourceRecord(&opt, mDNSNULL, mDNSInterface_Any, kDNSType_OPT, kStandardTTL, kDNSRecordTypeKnownUnique, AuthRecordAny, mDNSNULL, mDNSNULL); + opt.resrec.rrclass = NormalMaxDNSMessageData; + opt.resrec.rdlength = sizeof(rdataOPT); + opt.resrec.rdestimate = sizeof(rdataOPT); + + intf = FirstInterfaceForID(m, InterfaceID); + SetupOwnerOpt(m, intf, &opt.resrec.rdata->u.opt[0]); + + LogSPS("Generated OPT record : %s", ARDisplayString(m, &opt)); + end = PutResourceRecord(msg, ptr, &msg->h.numAdditionals, &opt.resrec); + if (end != mDNSNULL) + { + // Put all the integer values in IETF byte-order (MSB first, LSB second) + SwapDNSHeaderBytes(msg); + length = (end - msg->data); + } + else + LogSPS("mDNSGenerateOwnerOptForInterface: Failed to generate owner OPT record"); + + return length; +} + +// Note that this routine is called both for Sleep Proxy Registrations, and for Standard Dynamic +// DNS registrations, but (currently) only has to handle the Sleep Proxy Registration reply case, +// and should ignore Standard Dynamic DNS registration replies, because those are handled elsewhere. +// Really, both should be unified and handled in one place. mDNSlocal void mDNSCoreReceiveUpdateR(mDNS *const m, const DNSMessage *const msg, const mDNSu8 *end, const mDNSAddr *srcaddr, const mDNSInterfaceID InterfaceID) { if (InterfaceID) { - 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); - if (ptr && m->rec.r.resrec.RecordType != kDNSRecordTypePacketNegative && m->rec.r.resrec.rrtype == kDNSType_OPT) - { - const rdataOPT *o; - const rdataOPT *const e = (const rdataOPT *)&m->rec.r.resrec.rdata->u.data[m->rec.r.resrec.rdlength]; - for (o = &m->rec.r.resrec.rdata->u.opt[0]; o < e; o++) - if (o->opt == kDNSOpt_Lease) - { - updatelease = o->u.updatelease; - LogSPS("Sleep Proxy granted lease time %4d seconds, updateid %d, InterfaceID %p", updatelease, mDNSVal16(msg->h.id), InterfaceID); - } - } - m->rec.r.resrec.RecordType = 0; // Clear RecordType to show we're not still using it - } + mDNSu32 pktlease = 0, spsupdates = 0; + const mDNSBool gotlease = GetPktLease(m, msg, end, &pktlease); + const mDNSu32 updatelease = gotlease ? pktlease : 60 * 60; // If SPS fails to indicate lease time, assume one hour + if (gotlease) LogSPS("DNS Update response contains lease option granting %4d seconds, updateid %d, InterfaceID %p", updatelease, mDNSVal16(msg->h.id), InterfaceID); if (m->CurrentRecord) LogMsg("mDNSCoreReceiveUpdateR ERROR m->CurrentRecord already set %s", ARDisplayString(m, m->CurrentRecord)); @@ -10166,7 +10402,8 @@ mDNSlocal void mDNSCoreReceiveUpdateR(mDNS *const m, const DNSMessage *const msg if (mDNSOpaque64IsZero(&rr->updateIntID)) rr->updateid = zeroID; rr->expire = NonZeroTime(m->timenow + updatelease * mDNSPlatformOneSecond); - LogSPS("Sleep Proxy %s record %5d 0x%x 0x%x (%d) %s", rr->WakeUp.HMAC.l[0] ? "transferred" : "registered", updatelease, rr->updateIntID.l[1], rr->updateIntID.l[0], mDNSVal16(rr->updateid), ARDisplayString(m,rr)); + spsupdates++; + LogSPS("Sleep Proxy %s record %2d %5d 0x%x 0x%x (%d) %s", rr->WakeUp.HMAC.l[0] ? "transferred" : "registered", spsupdates, updatelease, rr->updateIntID.l[1], rr->updateIntID.l[0], mDNSVal16(rr->updateid), ARDisplayString(m,rr)); if (rr->WakeUp.HMAC.l[0]) { rr->WakeUp.HMAC = zeroEthAddr; // Clear HMAC so that mDNS_Deregister_internal doesn't waste packets trying to wake this host @@ -10179,11 +10416,27 @@ mDNSlocal void mDNSCoreReceiveUpdateR(mDNS *const m, const DNSMessage *const msg if (m->CurrentRecord == rr) // If m->CurrentRecord was not advanced for us, do it now m->CurrentRecord = rr->next; } + if (spsupdates) // Only do this dynamic store stuff if this was, in fact, a Sleep Proxy Update response + { + char *ifname; + mDNSAddr spsaddr; + DNSMessage optMsg; + int length; + // Update the dynamic store with the IP Address and MAC address of the sleep proxy + ifname = InterfaceNameForID(m, InterfaceID); + mDNSPlatformMemCopy(&spsaddr, srcaddr, sizeof (mDNSAddr)); + mDNSPlatformStoreSPSMACAddr(&spsaddr, ifname); - // Update the dynamic store with the IP Address and MAC address of the sleep proxy - ifname = InterfaceNameForID(m, InterfaceID); - mDNSPlatformMemCopy(&spsaddr, srcaddr, sizeof (mDNSAddr)); - mDNSPlatformStoreSPSMACAddr(&spsaddr, ifname); + // Store the Owner OPT record for this interface. + // Configd may use the OPT record if it detects a conflict with the BSP when the system wakes up + InitializeDNSMessage(&optMsg.h, zeroID, ResponseFlags); + length = mDNSGenerateOwnerOptForInterface(m, InterfaceID, &optMsg); + if (length != 0) + { + length += sizeof(DNSMessageHeader); + mDNSPlatformStoreOwnerOptRecord(ifname, &optMsg, length); + } + } } // If we were waiting to go to sleep, then this SPS registration or wide-area record deletion // may have been the thing we were waiting for, so schedule another check to see if we can sleep now. @@ -10219,12 +10472,6 @@ mDNSexport void MakeNegativeCacheRecord(mDNS *const m, CacheRecord *const cr, cr->CRActiveQuestion = mDNSNULL; cr->UnansweredQueries = 0; cr->LastUnansweredTime = 0; -#if ENABLE_MULTI_PACKET_QUERY_SNOOPING - cr->MPUnansweredQ = 0; - cr->MPLastUnansweredQT = 0; - cr->MPUnansweredKA = 0; - cr->MPExpectingKA = mDNSfalse; -#endif cr->NextInCFList = mDNSNULL; cr->nsec = mDNSNULL; cr->soa = mDNSNULL; @@ -10234,12 +10481,12 @@ mDNSexport void MakeNegativeCacheRecord(mDNS *const m, CacheRecord *const cr, cr->responseFlags = ResponseFlags; } -mDNSexport void mDNSCoreReceive(mDNS *const m, void *const pkt, const mDNSu8 *const end, +mDNSexport void mDNSCoreReceive(mDNS *const m, DNSMessage *const msg, const mDNSu8 *const end, const mDNSAddr *const srcaddr, const mDNSIPPort srcport, const mDNSAddr *dstaddr, const mDNSIPPort dstport, const mDNSInterfaceID InterfaceID) { mDNSInterfaceID ifid = InterfaceID; - DNSMessage *msg = (DNSMessage *)pkt; + const mDNSu8 *const pkt = (mDNSu8 *)msg; const mDNSu8 StdQ = kDNSFlag0_QR_Query | kDNSFlag0_OP_StdQuery; const mDNSu8 StdR = kDNSFlag0_QR_Response | kDNSFlag0_OP_StdQuery; const mDNSu8 UpdQ = kDNSFlag0_QR_Query | kDNSFlag0_OP_Update; @@ -10256,7 +10503,7 @@ mDNSexport void mDNSCoreReceive(mDNS *const m, void *const pkt, const mDNSu8 *co if (mDNSSameIPPort(srcport, SSDPPort) || (m->SSDPSocket && mDNSSameIPPort(dstport, m->SSDPSocket->port))) { mDNS_Lock(m); - LNT_ConfigureRouterInfo(m, InterfaceID, pkt, (mDNSu16)(end - (mDNSu8 *)pkt)); + LNT_ConfigureRouterInfo(m, InterfaceID, (mDNSu8 *)msg, (mDNSu16)(end - pkt)); mDNS_Unlock(m); return; } @@ -10264,7 +10511,7 @@ mDNSexport void mDNSCoreReceive(mDNS *const m, void *const pkt, const mDNSu8 *co if (mDNSSameIPPort(srcport, NATPMPPort)) { mDNS_Lock(m); - uDNS_ReceiveNATPacket(m, InterfaceID, pkt, (mDNSu16)(end - (mDNSu8 *)pkt)); + uDNS_ReceiveNATPacket(m, InterfaceID, (mDNSu8 *)msg, (mDNSu16)(end - pkt)); mDNS_Unlock(m); return; } @@ -10274,9 +10521,9 @@ mDNSexport void mDNSCoreReceive(mDNS *const m, void *const pkt, const mDNSu8 *co #endif #endif - if ((unsigned)(end - (mDNSu8 *)pkt) < sizeof(DNSMessageHeader)) + if ((unsigned)(end - pkt) < sizeof(DNSMessageHeader)) { - LogMsg("DNS Message from %#a:%d to %#a:%d length %d too short", srcaddr, mDNSVal16(srcport), dstaddr, mDNSVal16(dstport), end - (mDNSu8 *)pkt); + LogMsg("DNS Message from %#a:%d to %#a:%d length %d too short", srcaddr, mDNSVal16(srcport), dstaddr, mDNSVal16(dstport), (int)(end - pkt)); return; } QR_OP = (mDNSu8)(msg->h.flags.b[0] & kDNSFlag0_QROP_Mask); @@ -10302,7 +10549,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) && + if (!mDNS_AddressIsLocalSubnet(m, InterfaceID, srcaddr) && dstaddr && mDNSAddressIsAllDNSLinkGroup(dstaddr)) { m->RemoteSubnet++; @@ -10327,17 +10574,21 @@ mDNSexport void mDNSCoreReceive(mDNS *const m, void *const pkt, const mDNSu8 *co else if (QR_OP == UpdR) mDNSCoreReceiveUpdateR (m, msg, end, srcaddr, InterfaceID); else { - LogMsg("Unknown DNS packet type %02X%02X from %#-15a:%-5d to %#-15a:%-5d length %d on %p (ignored)", - msg->h.flags.b[0], msg->h.flags.b[1], srcaddr, mDNSVal16(srcport), dstaddr, mDNSVal16(dstport), end - (mDNSu8 *)pkt, InterfaceID); if (mDNS_LoggingEnabled) { - int i = 0; - while (i<end - (mDNSu8 *)pkt) - { - char buffer[128]; - char *p = buffer + mDNS_snprintf(buffer, sizeof(buffer), "%04X", i); - do if (i<end - (mDNSu8 *)pkt) p += mDNS_snprintf(p, sizeof(buffer), " %02X", ((mDNSu8 *)pkt)[i]);while (++i & 15); - LogInfo("%s", buffer); + static int msgCount = 0; + if (msgCount < 1000) { + int i = 0; + msgCount++; + LogInfo("Unknown DNS packet type %02X%02X from %#-15a:%-5d to %#-15a:%-5d length %d on %p (ignored)", + msg->h.flags.b[0], msg->h.flags.b[1], srcaddr, mDNSVal16(srcport), dstaddr, mDNSVal16(dstport), (int)(end - pkt), InterfaceID); + while (i < (int)(end - pkt)) + { + char buffer[128]; + char *p = buffer + mDNS_snprintf(buffer, sizeof(buffer), "%04X", i); + do if (i < (int)(end - pkt)) p += mDNS_snprintf(p, sizeof(buffer), " %02X", pkt[i]);while (++i & 15); + LogInfo("%s", buffer); + } } } } @@ -10361,6 +10612,11 @@ mDNSexport void mDNSCoreReceive(mDNS *const m, void *const pkt, const mDNSu8 *co #define SameQTarget(A,B) (((A)->Target.type == mDNSAddrType_None && (B)->Target.type == mDNSAddrType_None) || \ (mDNSSameAddress(& (A)->Target, & (B)->Target) && mDNSSameIPPort((A)->TargetPort, (B)->TargetPort))) +// SameQuestionKind is true if *both* questions are either multicast or unicast +// TargetQID is used for this determination. +#define SameQuestionKind(A,B) ((mDNSOpaque16IsZero(A) && mDNSOpaque16IsZero(B)) || \ + ((!mDNSOpaque16IsZero(A)) && (!mDNSOpaque16IsZero(B)))) + // Note: We explicitly disallow making a public query be a duplicate of a private one. This is to avoid the // circular deadlock where a client does a query for something like "dns-sd -Q _dns-query-tls._tcp.company.com SRV" // and we have a key for company.com, so we try to locate the private query server for company.com, which necessarily entails @@ -10404,8 +10660,9 @@ mDNSlocal DNSQuestion *FindDuplicateQuestion(const mDNS *const m, const DNSQuest (q->DisallowPID == question->DisallowPID) && // Disallowing a PID should not affect a PID that is allowed (q->BrowseThreshold == question->BrowseThreshold) && // browse thresholds must match q->qnamehash == question->qnamehash && - (IsAWDLIncluded(q) == IsAWDLIncluded(question)) && // Inclusion of AWDL interface must match - SameDomainName(&q->qname, &question->qname)) // and name + (IsAWDLIncluded(q) == IsAWDLIncluded(question)) && // Inclusion of AWDL interface must match + SameQuestionKind(q->TargetQID, question->TargetQID) && // mDNS or uDNS must match + SameDomainName(&q->qname, &question->qname)) // and name return(q); return(mDNSNULL); } @@ -10453,15 +10710,11 @@ mDNSlocal void UpdateQuestionDuplicates(mDNS *const m, DNSQuestion *const questi q->triedAllServersOnce = question->triedAllServersOnce; q->TargetQID = question->TargetQID; - if (q->LocalSocket) - { - mDNSPlatformUDPClose(q->LocalSocket); - } - q->LocalSocket = question->LocalSocket; + // No need to close old q->LocalSocket first -- duplicate questions can't have their own sockets q->state = question->state; - // q->tcp = question->tcp; + // q->tcp = question->tcp; q->ReqLease = question->ReqLease; q->expire = question->expire; q->ntries = question->ntries; @@ -10469,7 +10722,7 @@ mDNSlocal void UpdateQuestionDuplicates(mDNS *const m, DNSQuestion *const questi question->LocalSocket = mDNSNULL; question->nta = mDNSNULL; // If we've got a GetZoneData in progress, transfer it to the newly active question - // question->tcp = mDNSNULL; + // question->tcp = mDNSNULL; if (q->LocalSocket) debugf("UpdateQuestionDuplicates transferred LocalSocket pointer for %##s (%s)", q->qname.c, DNSTypeName(q->qtype)); @@ -10675,7 +10928,7 @@ mDNSlocal mDNSBool DNSServerMatch(DNSServer *d, mDNSInterfaceID InterfaceID, mDN // // 3) Scoped questions (non-zero ServiceID) should consider *only* scoped DNSServers (DNSServer // with "scoped" set to kScopeServiceID) and their ServiceIDs should match. - // + // // The first condition in the "if" statement checks to see if both the question and the DNSServer are // unscoped. The question is unscoped only if InterfaceID is zero and ServiceID is -1. // @@ -10714,7 +10967,7 @@ mDNSexport mDNSu32 SetValidDNSServers(mDNS *m, DNSQuestion *question) mDNSu32 timeout = 0; mDNSBool DEQuery; - question->validDNSServers = zeroOpaque64; + question->validDNSServers = zeroOpaque128; DEQuery = DomainEnumQuery(&question->qname); for (curr = m->DNSServers; curr; curr = curr->next) { @@ -10742,7 +10995,9 @@ mDNSexport mDNSu32 SetValidDNSServers(mDNS *m, DNSQuestion *question) } currcount = CountLabels(&curr->domain); - if ((!DEQuery || !curr->cellIntf) && DNSServerMatch(curr, question->InterfaceID, question->ServiceID)) + if ((!curr->cellIntf || (!DEQuery && !(question->flags & kDNSServiceFlagsDenyCellular))) && + (!curr->isExpensive || !(question->flags & kDNSServiceFlagsDenyExpensive)) && + DNSServerMatch(curr, question->InterfaceID, question->ServiceID)) { bettermatch = BetterMatchForName(&question->qname, namecount, &curr->domain, currcount, bestmatchlen); @@ -10756,7 +11011,7 @@ mDNSexport mDNSu32 SetValidDNSServers(mDNS *m, DNSQuestion *question) if (bettermatch) { debugf("SetValidDNSServers: Resetting all the bits"); - question->validDNSServers = zeroOpaque64; + question->validDNSServers = zeroOpaque128; timeout = 0; } debugf("SetValidDNSServers: question %##s Setting the bit for DNS server Address %#a (Domain %##s), Scoped:%d index %d," @@ -10765,15 +11020,15 @@ mDNSexport mDNSu32 SetValidDNSServers(mDNS *m, DNSQuestion *question) timeout += curr->timeout; if (DEQuery) debugf("DomainEnumQuery: Question %##s, DNSServer %#a, cell %d", question->qname.c, &curr->addr, curr->cellIntf); - bit_set_opaque64(question->validDNSServers, index); + bit_set_opaque128(question->validDNSServers, index); } } index++; } question->noServerResponse = 0; - debugf("SetValidDNSServers: ValidDNSServer bits 0x%x%x for question %p %##s (%s)", - question->validDNSServers.l[1], question->validDNSServers.l[0], question, question->qname.c, DNSTypeName(question->qtype)); + debugf("SetValidDNSServers: ValidDNSServer bits 0x%x%x%x%x for question %p %##s (%s)", + question->validDNSServers.l[3], question->validDNSServers.l[2], question->validDNSServers.l[1], question->validDNSServers.l[0], question, question->qname.c, DNSTypeName(question->qtype)); // If there are no matching resolvers, then use the default timeout value. // For ProxyQuestion, shorten the timeout so that dig does not timeout on us in case of no response. return ((question->ProxyQuestion || question->ValidatingResponse) ? DEFAULT_UDNSSEC_TIMEOUT : timeout ? timeout : DEFAULT_UDNS_TIMEOUT); @@ -10781,7 +11036,7 @@ mDNSexport mDNSu32 SetValidDNSServers(mDNS *m, DNSQuestion *question) // Get the Best server that matches a name. If you find penalized servers, look for the one // that will come out of the penalty box soon -mDNSlocal DNSServer *GetBestServer(mDNS *m, const domainname *name, mDNSInterfaceID InterfaceID, mDNSs32 ServiceID, mDNSOpaque64 validBits, +mDNSlocal DNSServer *GetBestServer(mDNS *m, const domainname *name, mDNSInterfaceID InterfaceID, mDNSs32 ServiceID, mDNSOpaque128 validBits, int *selected, mDNSBool nameMatch) { DNSServer *curmatch = mDNSNULL; @@ -10860,7 +11115,7 @@ mDNSlocal DNSServer *GetServerForName(mDNS *m, const domainname *name, mDNSInter { DNSServer *curmatch = mDNSNULL; char *ifname = mDNSNULL; // for logging purposes only - mDNSOpaque64 allValid; + mDNSOpaque128 allValid; if ((InterfaceID == mDNSInterface_Unicast) || (InterfaceID == mDNSInterface_LocalOnly)) InterfaceID = mDNSNULL; @@ -10868,7 +11123,7 @@ mDNSlocal DNSServer *GetServerForName(mDNS *m, const domainname *name, mDNSInter if (InterfaceID) ifname = InterfaceNameForID(m, InterfaceID); // By passing in all ones, we make sure that every DNS server is considered - allValid.l[0] = allValid.l[1] = 0xFFFFFFFF; + allValid.l[0] = allValid.l[1] = allValid.l[2] = allValid.l[3] = 0xFFFFFFFF; curmatch = GetBestServer(m, name, InterfaceID, ServiceID, allValid, mDNSNULL, mDNStrue); @@ -10897,11 +11152,11 @@ mDNSexport DNSServer *GetServerForQuestion(mDNS *m, DNSQuestion *question) if (InterfaceID) ifname = InterfaceNameForID(m, InterfaceID); - if (!mDNSOpaque64IsZero(&question->validDNSServers)) + if (!mDNSOpaque128IsZero(&question->validDNSServers)) { curmatch = GetBestServer(m, name, InterfaceID, question->ServiceID, question->validDNSServers, &currindex, mDNSfalse); if (currindex != -1) - bit_clr_opaque64(question->validDNSServers, currindex); + bit_clr_opaque128(question->validDNSServers, currindex); } if (curmatch != mDNSNULL) @@ -10981,7 +11236,7 @@ mDNSlocal mDNSBool ShouldSuppressUnicastQuery(mDNS *const m, DNSQuestion *q, DNS LogInfo("ShouldSuppressUnicastQuery: Query suppressed for %##s, qtype %s, as the DNS server is NULL", q->qname.c, DNSTypeName(q->qtype)); return mDNStrue; } - + // Check if the DNS Configuration allows A/AAAA queries to be sent if ((q->qtype == kDNSType_A) && (d->req_A)) { @@ -10995,6 +11250,13 @@ mDNSlocal mDNSBool ShouldSuppressUnicastQuery(mDNS *const m, DNSQuestion *q, DNS DNSTypeName(q->qtype), d->domain.c, &d->addr, mDNSVal16(d->port)); return mDNSfalse; } +#if USE_DNS64 + if (DNS64IsQueryingARecord(q->dns64.state)) + { + LogInfo("ShouldSuppressUnicastQuery: DNS64 query not suppressed for %##s, qtype %s", q->qname.c, DNSTypeName(q->qtype)); + return mDNSfalse; + } +#endif LogInfo("ShouldSuppressUnicastQuery: Query suppressed for %##s, qtype %s, since DNS Configuration does not allow (req_A is %s and req_AAAA is %s)", q->qname.c, DNSTypeName(q->qtype), d->req_A ? "true" : "false", d->req_AAAA ? "true" : "false"); @@ -11011,12 +11273,12 @@ mDNSlocal mDNSBool ShouldSuppressDotLocalQuery(mDNS *const m, DNSQuestion *q) // Check to see if there is at least one interface other than loopback and don't suppress // .local questions if you find one. If we have at least one interface, it means that // we can send unicast queries for the .local name and we don't want to suppress - // multicast in that case as upper layers don't know how to handle if we return a + // multicast in that case as upper layers don't know how to handle if we return a // negative response for multicast followed by a positive response for unicast. // // Note: we used to check for multicast capable interfaces instead of just any interface // present. That did not work in the case where we have a valid interface for unicast - // but not multicast capable e.g., cellular, as we ended up delivering a negative response + // but not multicast capable e.g., cellular, as we ended up delivering a negative response // first and the upper layer did not wait for the positive response that came later. for (intf = m->HostInterfaces; intf; intf = intf->next) { @@ -11040,7 +11302,7 @@ mDNSlocal mDNSBool ShouldSuppressDotLocalQuery(mDNS *const m, DNSQuestion *q) return mDNSfalse; } - // 2. If we find a local AuthRecord answering this question, then don't suppress it. + // 2. If we find a local AuthRecord answering this question, then don't suppress it. for (rr = m->ResourceRecords; rr; rr = rr->next) { if (ResourceRecordAnswersQuestion(&rr->resrec, q)) @@ -11055,6 +11317,12 @@ mDNSlocal mDNSBool ShouldSuppressDotLocalQuery(mDNS *const m, DNSQuestion *q) mDNSlocal mDNSBool ShouldSuppressQuery(mDNS *const m, DNSQuestion *q) { + if (q->InterfaceID == mDNSInterface_LocalOnly) + { + LogInfo("ShouldSuppressQuery: LocalOnly query not suppressed for %##s, qtype %s", q->qname.c, DNSTypeName(q->qtype)); + return mDNSfalse; + } + if (q->qtype != kDNSType_A && q->qtype != kDNSType_AAAA) { LogInfo("ShouldSuppressQuery: Query not suppressed for %##s, qtype %s, not A/AAAA type", q->qname.c, DNSTypeName(q->qtype)); @@ -11084,11 +11352,9 @@ mDNSlocal mDNSBool ShouldSuppressQuery(mDNS *const m, DNSQuestion *q) mDNSlocal void CacheRecordRmvEventsForCurrentQuestion(mDNS *const m, DNSQuestion *q) { CacheRecord *rr; - mDNSu32 slot; CacheGroup *cg; - slot = HashSlot(&q->qname); - cg = CacheGroupForName(m, slot, q->qnamehash, &q->qname); + cg = CacheGroupForName(m, q->qnamehash, &q->qname); for (rr = cg ? cg->members : mDNSNULL; rr; rr=rr->next) { // Don't deliver RMV events for negative records @@ -11145,7 +11411,6 @@ mDNSlocal mDNSBool IsQuestionNew(mDNS *const m, DNSQuestion *question) mDNSlocal mDNSBool LocalRecordRmvEventsForQuestion(mDNS *const m, DNSQuestion *q) { AuthRecord *rr; - mDNSu32 slot; AuthGroup *ag; if (m->CurrentQuestion) @@ -11158,8 +11423,7 @@ mDNSlocal mDNSBool LocalRecordRmvEventsForQuestion(mDNS *const m, DNSQuestion *q return mDNStrue; } m->CurrentQuestion = q; - slot = AuthHashSlot(&q->qname); - ag = AuthGroupForName(&m->rrauth, slot, q->qnamehash, &q->qname); + ag = AuthGroupForName(&m->rrauth, q->qnamehash, &q->qname); if (ag) { for (rr = ag->members; rr; rr=rr->next) @@ -11185,7 +11449,7 @@ mDNSlocal mDNSBool LocalRecordRmvEventsForQuestion(mDNS *const m, DNSQuestion *q // Returns false if the question got deleted while delivering the RMV events // The caller should handle the case -mDNSlocal mDNSBool CacheRecordRmvEventsForQuestion(mDNS *const m, DNSQuestion *q) +mDNSexport mDNSBool CacheRecordRmvEventsForQuestion(mDNS *const m, DNSQuestion *q) { if (m->CurrentQuestion) LogMsg("CacheRecordRmvEventsForQuestion: ERROR m->CurrentQuestion already set: %##s (%s)", @@ -11328,7 +11592,7 @@ mDNSlocal void RestartUnicastQuestions(mDNS *const m) { if (mDNSOpaque16IsZero(q->TargetQID)) LogMsg("RestartUnicastQuestions: ERROR!! Restart set for multicast question %##s (%s)", q->qname.c, DNSTypeName(q->qtype)); - + q->Restart = 0; SuppressStatusChanged(m, q, &restart); } @@ -11344,8 +11608,8 @@ mDNSlocal void RestartUnicastQuestions(mDNS *const m) } -// ValidateParameters() is called by mDNS_StartQuery_internal() to check the client parameters of -// DNS Question that are already set by the client before calling mDNS_StartQuery() +// ValidateParameters() is called by mDNS_StartQuery_internal() to check the client parameters of +// DNS Question that are already set by the client before calling mDNS_StartQuery() mDNSlocal mStatus ValidateParameters(mDNS *const m, DNSQuestion *const question) { @@ -11357,7 +11621,7 @@ mDNSlocal mStatus ValidateParameters(mDNS *const m, DNSQuestion *const question) } // If no question->Target specified, clear TargetPort - if (!question->Target.type) + if (!question->Target.type) question->TargetPort = zeroIPPort; if (!ValidateDomainName(&question->qname)) @@ -11366,71 +11630,71 @@ mDNSlocal mStatus ValidateParameters(mDNS *const m, DNSQuestion *const question) return(mStatus_Invalid); } - // If this question is referencing a specific interface, verify it exists - if (question->InterfaceID && question->InterfaceID != mDNSInterface_LocalOnly && question->InterfaceID != mDNSInterface_Unicast && question->InterfaceID != mDNSInterface_P2P) + // If this question is referencing a specific interface, verify it exists + if (question->InterfaceID && !LocalOnlyOrP2PInterface(question->InterfaceID) && question->InterfaceID != mDNSInterface_Unicast) { NetworkInterfaceInfo *intf = FirstInterfaceForID(m, question->InterfaceID); if (!intf) LogInfo("ValidateParameters: Note: InterfaceID %d for question %##s (%s) not currently found in active interface list", (uint32_t)question->InterfaceID, question->qname.c, DNSTypeName(question->qtype)); } - + return(mStatus_NoError); } -// InitDNSConfig() is called by InitCommonState() to initialize the DNS configuration of the Question. +// InitDNSConfig() is called by InitCommonState() to initialize the DNS configuration of the Question. // These are a subset of the internal uDNS fields. Must be done before ShouldSuppressQuery() & mDNS_PurgeForQuestion() mDNSlocal void InitDNSConfig(mDNS *const m, DNSQuestion *const question) { // First reset all DNS Configuration question->qDNSServer = mDNSNULL; - question->validDNSServers = zeroOpaque64; - question->triedAllServersOnce = 0; - question->noServerResponse = 0; - question->StopTime = 0; -#if TARGET_OS_EMBEDDED + question->validDNSServers = zeroOpaque128; + question->triedAllServersOnce = 0; + question->noServerResponse = 0; + question->StopTime = (question->TimeoutQuestion) ? question->StopTime : 0; +#if AWD_METRICS 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) + // Need not initialize the DNS Configuration for Local Only OR P2P Questions when timeout not specified + if (LocalOnlyOrP2PInterface(question->InterfaceID) && !question->TimeoutQuestion) return; // Proceed to initialize DNS Configuration (some are set in SetValidDNSServers()) if (!mDNSOpaque16IsZero(question->TargetQID)) - { + { mDNSu32 timeout = SetValidDNSServers(m, question); - mDNSIPPort zp = zeroIPPort; - // We set the timeout whenever mDNS_StartQuery_internal is called. This means if we have - // a networking change/search domain change that calls this function again we keep - // reinitializing the timeout value which means it may never timeout. If this becomes - // a common case in the future, we can easily fix this by adding extra state that - // indicates that we have already set the StopTime. - // - // Note that we set the timeout for all questions. If this turns out to be a duplicate, + // We set the timeout value the first time mDNS_StartQuery_internal is called for a question. + // So if a question is restarted when a network change occurs, the StopTime is not reset. + // Note that we set the timeout for all questions. If this turns out to be a duplicate, // it gets a full timeout value even if the original question times out earlier. - if (question->TimeoutQuestion) + if (question->TimeoutQuestion && !question->StopTime) { question->StopTime = NonZeroTime(m->timenow + timeout * mDNSPlatformOneSecond); - LogInfo("InitDNSConfig: Setting StopTime on question %p %##s (%s)", question, question->qname.c, DNSTypeName(question->qtype)); + LogInfo("InitDNSConfig: Setting StopTime on the uDNS question %p %##s (%s)", question, question->qname.c, DNSTypeName(question->qtype)); } question->qDNSServer = GetServerForQuestion(m, question); LogInfo("InitDNSConfig: question %p %##s (%s) Timeout %d, DNS Server %#a:%d", question, question->qname.c, DNSTypeName(question->qtype), timeout, question->qDNSServer ? &question->qDNSServer->addr : mDNSNULL, - mDNSVal16(question->qDNSServer ? question->qDNSServer->port : zp)); + mDNSVal16(question->qDNSServer ? question->qDNSServer->port : zeroIPPort)); } - else - { - if (question->TimeoutQuestion) - question->StopTime = NonZeroTime(m->timenow + GetTimeoutForMcastQuestion(m, question) * mDNSPlatformOneSecond); + else if (question->TimeoutQuestion && !question->StopTime) + { + // If the question is to be timed out and its a multicast, local-only or P2P case, + // then set it's stop time. + mDNSu32 timeout = LocalOnlyOrP2PInterface(question->InterfaceID) ? + DEFAULT_LO_OR_P2P_TIMEOUT : GetTimeoutForMcastQuestion(m, question); + question->StopTime = NonZeroTime(m->timenow + timeout * mDNSPlatformOneSecond); + LogInfo("InitDNSConfig: Setting StopTime on question %p %##s (%s)", question, question->qname.c, DNSTypeName(question->qtype)); } - // Set StopTime here since it is a part of DNS Configuration + // Set StopTime here since it is a part of DNS Configuration if (question->StopTime) SetNextQueryStopTime(m, question); - // SetNextQueryTime() need not be initialized for LocalOnly OR P2P Questions since those questions - // will never be transmitted on the wire. Hence we call SetNextQueryTime() here. - SetNextQueryTime(m,question); + // Don't call SetNextQueryTime() if a LocalOnly OR P2P Question since those questions + // will never be transmitted on the wire. + if (!(LocalOnlyOrP2PInterface(question->InterfaceID))) + SetNextQueryTime(m,question); } // InitCommonState() is called by mDNS_StartQuery_internal() to initialize the common(uDNS/mDNS) internal @@ -11439,7 +11703,7 @@ mDNSlocal mDNSBool InitCommonState(mDNS *const m, DNSQuestion *const question) { mDNSBool purge; int i; - mDNSBool isCellBlocked = mDNSfalse; + mDNSBool isBlocked = 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 @@ -11456,7 +11720,7 @@ mDNSlocal mDNSBool InitCommonState(mDNS *const m, DNSQuestion *const question) // turned ON which can allocate memory e.g., base64 encoding, in the case of DNSSEC. question->ThisQInterval = InitialQuestionInterval; // MUST be > zero for an active question question->qnamehash = DomainNameHashValue(&question->qname); - question->DelayAnswering = CheckForSoonToExpireRecords(m, &question->qname, question->qnamehash, HashSlot(&question->qname), &purge); + question->DelayAnswering = CheckForSoonToExpireRecords(m, &question->qname, question->qnamehash, &purge); question->LastQTime = m->timenow; question->ExpectUnicastResp = 0; question->LastAnswerPktNum = m->PktNum; @@ -11487,13 +11751,19 @@ mDNSlocal mDNSBool InitCommonState(mDNS *const m, DNSQuestion *const question) question->LOAddressAnswers = 0; question->FlappingInterface1 = mDNSNULL; question->FlappingInterface2 = mDNSNULL; - - // 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)) - mDNSPlatformGetDNSRoutePolicy(m, question, &isCellBlocked); - else - LogInfo("InitCommonState: Query for %##s (%s), PID[%d], EUID[%d], ServiceID[%d] is already set by client", question->qname.c, + + // 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)) + { +#if APPLE_OSX_mDNSResponder + mDNSPlatformGetDNSRoutePolicy(question, &isBlocked); +#else + question->ServiceID = -1; +#endif + } + else + 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); @@ -11505,7 +11775,7 @@ 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 || (isCellBlocked && question->qDNSServer && question->qDNSServer->cellIntf)); + question->DisallowPID = (question->ServiceID == 0 || isBlocked); 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); @@ -11513,47 +11783,27 @@ mDNSlocal mDNSBool InitCommonState(mDNS *const m, DNSQuestion *const question) question->NextInDQList = mDNSNULL; question->SendQNow = mDNSNULL; question->SendOnAll = mDNSfalse; - -#if mDNS_REQUEST_UNICAST_RESPONSE - question->RequestUnicast = SET_QU_IN_FIRST_FOUR_QUERIES; -#else // mDNS_REQUEST_UNICAST_RESPONSE - question->RequestUnicast = SET_QU_IN_FIRST_QUERY; -#endif // mDNS_REQUEST_UNICAST_RESPONSE + question->RequestUnicast = kDefaultRequestUnicastCount; #if APPLE_OSX_mDNSResponder - // Request unicast response for first 4 queries to increase - // reliability in an environment with high multicast packet loss. - // Must set to one more than the number of unicast queries you want, since SendQueries() - // decrements it before calling BuildQuestion() which acts on it. - if (question->flags & kDNSServiceFlagsUnicastResponse) + // Set the QU bit in the first query for the following options. + if ((question->flags & kDNSServiceFlagsUnicastResponse) || (question->flags & kDNSServiceFlagsThresholdFinder)) { - question->RequestUnicast = SET_QU_IN_FIRST_FOUR_QUERIES; + question->RequestUnicast = SET_QU_IN_FIRST_QUERY; LogInfo("InitCommonState: setting RequestUnicast = %d for %##s (%s)", question->RequestUnicast, question->qname.c, DNSTypeName(question->qtype)); - } - else if (question->flags & kDNSServiceFlagsThresholdFinder) - { - // always send one request with QU bit set when kDNSServiceFlagsThresholdFinder is set -#if mDNS_REQUEST_UNICAST_RESPONSE - question->RequestUnicast = SET_QU_IN_FIRST_FOUR_QUERIES; -#else // mDNS_REQUEST_UNICAST_RESPONSE - question->RequestUnicast = SET_QU_IN_FIRST_QUERY; -#endif // mDNS_REQUEST_UNICAST_RESPONSE - - LogInfo("InitCommonState: kDNSServiceFlagsThresholdFinder set, setting RequestUnicast = %d for %##s (%s)", - question->RequestUnicast, question->qname.c, DNSTypeName(question->qtype)); } #endif // APPLE_OSX_mDNSResponder question->LastQTxTime = m->timenow; - question->CNAMEReferrals = 0; + question->CNAMEReferrals = 0; question->WakeOnResolveCount = 0; if (question->WakeOnResolve) - { + { question->WakeOnResolveCount = InitialWakeOnResolveCount; purge = mDNStrue; - } + } for (i=0; i<DupSuppressInfoSize; i++) question->DupSuppress[i].InterfaceID = mDNSNULL; @@ -11580,7 +11830,7 @@ mDNSlocal void InitWABState(DNSQuestion *const question) // We won't need one for duplicate questions, or from questions answered immediately out of the cache. // We also don't need one for LLQs because (when we're using NAT) we want them all to share a single // NAT mapping for receiving inbound add/remove events. - question->LocalSocket = mDNSNULL; + question->LocalSocket = mDNSNULL; question->unansweredQueries = 0; question->nta = mDNSNULL; question->servAddr = zeroAddr; @@ -11612,8 +11862,15 @@ mDNSlocal void InitLLQState(DNSQuestion *const question) question->id = zeroOpaque64; } +#ifdef DNS_PUSH_ENABLED +mDNSlocal void InitDNSPNState(DNSQuestion *const question) +{ + question->dnsPushState = DNSPUSH_INIT; +} +#endif // DNS_PUSH_ENABLED + // InitDNSSECProxyState() is called by mDNS_StartQuery_internal() to initialize -// DNSSEC & DNS Proxy fields of the DNS Question. +// DNSSEC & DNS Proxy fields of the DNS Question. mDNSlocal void InitDNSSECProxyState(mDNS *const m, DNSQuestion *const question) { (void) m; @@ -11650,13 +11907,22 @@ mDNSlocal void FinalizeUnicastQuestion(mDNS *const m, DNSQuestion *question, mDN // Ensure DNS related info of duplicate question is same as the orig question if (question->DuplicateOf) { - mDNSIPPort zp = zeroIPPort; question->validDNSServers = question->DuplicateOf->validDNSServers; + // If current(dup) question has DNS Server assigned but the original question has no DNS Server assigned to it, + // then we log a line as it could indicate an issue + if (question->DuplicateOf->qDNSServer == mDNSNULL) + { + if (question->qDNSServer) + LogInfo("FinalizeUnicastQuestion: Current(dup) question %p has DNSServer(%#a:%d) but original question(%p) has no DNS Server! %##s (%s)", + question, question->qDNSServer ? &question->qDNSServer->addr : mDNSNULL, + mDNSVal16(question->qDNSServer ? question->qDNSServer->port : zeroIPPort), + question->DuplicateOf, question->qname.c, DNSTypeName(question->qtype)); + } question->qDNSServer = question->DuplicateOf->qDNSServer; LogInfo("FinalizeUnicastQuestion: Duplicate question %p (%p) %##s (%s), DNS Server %#a:%d", question, question->DuplicateOf, question->qname.c, DNSTypeName(question->qtype), question->qDNSServer ? &question->qDNSServer->addr : mDNSNULL, - mDNSVal16(question->qDNSServer ? question->qDNSServer->port : zp)); + mDNSVal16(question->qDNSServer ? question->qDNSServer->port : zeroIPPort)); } ActivateUnicastQuery(m, question, mDNSfalse); @@ -11692,7 +11958,6 @@ mDNSexport mStatus mDNS_StartQuery_internal(mDNS *const m, DNSQuestion *const qu DNSQuestion **q; mStatus vStatus; mDNSBool purge; - mDNSOpaque16 zqid = zeroID; // First check for cache space (can't do queries if there is no cache space allocated) if (m->rrcache_size == 0) @@ -11701,19 +11966,30 @@ mDNSexport mStatus mDNS_StartQuery_internal(mDNS *const m, DNSQuestion *const qu vStatus = ValidateParameters(m, question); if (vStatus) return(vStatus); - + +#ifdef USE_LIBIDN + // If the TLD includes high-ascii bytes, assume it will need to be converted to Punycode. + // (In the future the root name servers may answer UTF-8 queries directly, but for now they do not.) + if (IsHighASCIILabel(LastLabel(&question->qname))) + { + domainname newname; + if (PerformNextPunycodeConversion(question, &newname)) + AssignDomainName(&question->qname, &newname); + } +#endif // USE_LIBIDN + question->TargetQID = #ifndef UNICAST_DISABLED (question->Target.type || Question_uDNS(question)) ? mDNS_NewMessageID(m) : #endif // UNICAST_DISABLED - zqid; - debugf("mDNS_StartQuery_internal: %##s (%s)", question->qname.c, DNSTypeName(question->qtype)); - + zeroID; + debugf("mDNS_StartQuery_internal: %##s (%s)", question->qname.c, DNSTypeName(question->qtype)); + // Note: It important that new questions are appended at the *end* of the list, not prepended at the start q = &m->Questions; - if (question->InterfaceID == mDNSInterface_LocalOnly || question->InterfaceID == mDNSInterface_P2P) + if (LocalOnlyOrP2PInterface(question->InterfaceID)) q = &m->LocalOnlyQuestions; - while (*q && *q != question) + while (*q && *q != question) q=&(*q)->next; if (*q) @@ -11723,7 +11999,6 @@ mDNSexport mStatus mDNS_StartQuery_internal(mDNS *const m, DNSQuestion *const qu return(mStatus_AlreadyRegistered); } *q = question; - // Intialize the question. The only ordering constraint we have today is that // InitDNSSECProxyState should be called after the DNS server is selected (in @@ -11733,23 +12008,26 @@ mDNSexport mStatus mDNS_StartQuery_internal(mDNS *const m, DNSQuestion *const qu purge = InitCommonState(m, question); InitWABState(question); InitLLQState(question); +#ifdef DNS_PUSH_ENABLED + InitDNSPNState(question); +#endif // DNS_PUSH_ENABLED InitDNSSECProxyState(m, question); // FindDuplicateQuestion should be called last after all the intialization // as the duplicate logic could be potentially based on any field in the // question. question->DuplicateOf = FindDuplicateQuestion(m, question); - if (question->DuplicateOf) - question->AuthInfo = question->DuplicateOf->AuthInfo; + if (question->DuplicateOf) + question->AuthInfo = question->DuplicateOf->AuthInfo; - if (question->InterfaceID == mDNSInterface_LocalOnly || question->InterfaceID == mDNSInterface_P2P) + if (LocalOnlyOrP2PInterface(question->InterfaceID)) { - if (!m->NewLocalOnlyQuestions) + if (!m->NewLocalOnlyQuestions) m->NewLocalOnlyQuestions = question; } else { - if (!m->NewQuestions) + if (!m->NewQuestions) m->NewQuestions = question; // If the question's id is non-zero, then it's Wide Area @@ -11764,13 +12042,22 @@ 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 BONJOUR_ON_DEMAND + 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->NextBonjourDisableTime = 0; + if (m->BonjourEnabled == 0) + { + // Enable Bonjour immediately by scheduling network changed processing where + // we will join the multicast group on each active interface. + m->BonjourEnabled = 1; + m->NetworkChanged = m->timenow; + } + } +#endif // BONJOUR_ON_DEMAND if (purge) { LogInfo("mDNS_StartQuery_internal: Purging for %##s", question->qname.c); @@ -11800,14 +12087,14 @@ mDNSexport void CancelGetZoneData(mDNS *const m, ZoneData *nta) mDNSexport mStatus mDNS_StopQuery_internal(mDNS *const m, DNSQuestion *const question) { - const mDNSu32 slot = HashSlot(&question->qname); - CacheGroup *cg = CacheGroupForName(m, slot, question->qnamehash, &question->qname); + CacheGroup *cg = CacheGroupForName(m, question->qnamehash, &question->qname); CacheRecord *rr; DNSQuestion **qp = &m->Questions; //LogInfo("mDNS_StopQuery_internal %##s (%s)", question->qname.c, DNSTypeName(question->qtype)); - if (question->InterfaceID == mDNSInterface_LocalOnly || question->InterfaceID == mDNSInterface_P2P) qp = &m->LocalOnlyQuestions; + if (LocalOnlyOrP2PInterface(question->InterfaceID)) + qp = &m->LocalOnlyQuestions; while (*qp && *qp != question) qp=&(*qp)->next; if (*qp) *qp = (*qp)->next; else @@ -11819,29 +12106,28 @@ mDNSexport mStatus mDNS_StopQuery_internal(mDNS *const m, DNSQuestion *const que return(mStatus_BadReferenceErr); } -#if TARGET_OS_WATCH - if (question->InterfaceID != mDNSInterface_LocalOnly && question->InterfaceID != mDNSInterface_P2P && mDNSOpaque16IsZero(question->TargetQID)) +#if BONJOUR_ON_DEMAND + if (!LocalOnlyOrP2PInterface(question->InterfaceID) && 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)); + if (m->NumAllInterfaceRecords + m->NumAllInterfaceQuestions == 1) + m->NextBonjourDisableTime = NonZeroTime(m->timenow + (BONJOUR_DISABLE_DELAY * mDNSPlatformOneSecond)); + m->NumAllInterfaceQuestions--; + LogInfo("mDNS_StopQuery_internal: NumAllInterfaceRecords %d NumAllInterfaceQuestions %d %##s (%s)", + m->NumAllInterfaceRecords, m->NumAllInterfaceQuestions, question->qname.c, DNSTypeName(question->qtype)); } -#endif +#endif // BONJOUR_ON_DEMAND -#if TARGET_OS_EMBEDDED - if (Question_uDNS(question) && !question->metrics.answered) +#if AWD_METRICS + if (Question_uDNS(question) && !question->metrics.answered && (question->metrics.querySendCount > 0)) { - uDNSMetrics * metrics; const domainname * queryName; - mDNSBool isForCellular; - - metrics = &question->metrics; - queryName = metrics->originalQName ? metrics->originalQName : &question->qname; - isForCellular = (question->qDNSServer && question->qDNSServer->cellIntf); + mDNSBool isForCell; + mDNSu32 durationMs; - MetricsUpdateUDNSStats(queryName, mDNSfalse, metrics->querySendCount, 0, isForCellular); + queryName = question->metrics.originalQName ? question->metrics.originalQName : &question->qname; + isForCell = (question->qDNSServer && question->qDNSServer->cellIntf); + durationMs = ((m->timenow - question->metrics.firstQueryTime) * 1000) / mDNSPlatformOneSecond; + MetricsUpdateUDNSQueryStats(queryName, question->qtype, mDNSNULL, question->metrics.querySendCount, durationMs, isForCell); } #endif // Take care to cut question from list *before* calling UpdateQuestionDuplicates @@ -11856,16 +12142,31 @@ mDNSexport mStatus mDNS_StopQuery_internal(mDNS *const m, DNSQuestion *const que if (rr->CRActiveQuestion == question) { DNSQuestion *q; - // Checking for ActiveQuestion filters questions that are suppressed also - // as suppressed questions are not active - for (q = m->Questions; q; q=q->next) // Scan our list of questions - if (ActiveQuestion(q) && ResourceRecordAnswersQuestion(&rr->resrec, q)) - break; - if (q) + DNSQuestion *replacement = mDNSNULL; + // If we find an active question that is answered by this cached record, use it as the cache record's + // CRActiveQuestion replacement. If there are no such questions, but there's at least one unsuppressed inactive + // question that is answered by this cache record, then use an inactive one to not forgo generating RMV events + // via CacheRecordRmv() when the cache record expires. + for (q = m->Questions; q && (q != m->NewQuestions); q = q->next) + { + if (!q->DuplicateOf && !QuerySuppressed(q) && ResourceRecordAnswersQuestion(&rr->resrec, q)) + { + if (q->ThisQInterval > 0) + { + replacement = q; + break; + } + else if (!replacement) + { + replacement = q; + } + } + } + if (replacement) debugf("mDNS_StopQuery_internal: Updating CRActiveQuestion to %p for cache record %s, Original question CurrentAnswers %d, new question " - "CurrentAnswers %d, SuppressQuery %d", q, CRDisplayString(m,rr), question->CurrentAnswers, q->CurrentAnswers, q->SuppressQuery); - rr->CRActiveQuestion = q; // Question used to be active; new value may or may not be null - if (!q) m->rrcache_active--; // If no longer active, decrement rrcache_active count + "CurrentAnswers %d, SuppressQuery %d", replacement, CRDisplayString(m,rr), question->CurrentAnswers, replacement->CurrentAnswers, replacement->SuppressQuery); + rr->CRActiveQuestion = replacement; // Question used to be active; new value may or may not be null + if (!replacement) m->rrcache_active--; // If no longer active, decrement rrcache_active count } } @@ -11948,6 +12249,17 @@ mDNSexport mStatus mDNS_StopQuery_internal(mDNS *const m, DNSQuestion *const que question->tcp = mDNSNULL; } } +#ifdef DNS_PUSH_ENABLED + else if (question->dnsPushState == DNSPUSH_ESTABLISHED) + { + if (question->tcp) + { + UnSubscribeToDNSPushNotificationServer(m, q); + question->tcp->question = mDNSNULL; + question->tcp = mDNSNULL; + } + } +#endif // DNS_PUSH_ENABLED #if APPLE_OSX_mDNSResponder UpdateAutoTunnelDomainStatuses(m); #endif @@ -11966,7 +12278,7 @@ mDNSexport mStatus mDNS_StopQuery_internal(mDNS *const m, DNSQuestion *const que FreeAnonInfo(question->AnonInfo); question->AnonInfo = mDNSNULL; } -#if TARGET_OS_EMBEDDED +#if AWD_METRICS if (question->metrics.originalQName) { mDNSPlatformMemFree(question->metrics.originalQName); @@ -11974,6 +12286,10 @@ mDNSexport mStatus mDNS_StopQuery_internal(mDNS *const m, DNSQuestion *const que } #endif +#if USE_DNS64 + DNS64ResetState(question); +#endif + return(mStatus_NoError); } @@ -12012,15 +12328,14 @@ mDNSexport mStatus mDNS_StopQueryWithRemoves(mDNS *const m, DNSQuestion *const q if (status == mStatus_NoError && !qq) { const CacheRecord *rr; - const mDNSu32 slot = HashSlot(&question->qname); - CacheGroup *const cg = CacheGroupForName(m, slot, question->qnamehash, &question->qname); + CacheGroup *const cg = CacheGroupForName(m, question->qnamehash, &question->qname); LogInfo("Generating terminal removes for %##s (%s)", question->qname.c, DNSTypeName(question->qtype)); for (rr = cg ? cg->members : mDNSNULL; rr; rr=rr->next) if (rr->resrec.RecordType != kDNSRecordTypePacketNegative && SameNameRecordAnswersQuestion(&rr->resrec, question)) { // Don't use mDNS_DropLockBeforeCallback() here, since we don't allow API calls if (question->QuestionCallback) - question->QuestionCallback(m, question, &rr->resrec, QC_rmv); + question->QuestionCallback(m, question, &rr->resrec, mDNSfalse); } } mDNS_Unlock(m); @@ -12064,10 +12379,8 @@ mDNSlocal mStatus mDNS_StartBrowse_internal(mDNS *const m, DNSQuestion *const qu question->LongLived = mDNStrue; question->ExpectUnique = mDNSfalse; question->ForceMCast = ForceMCast; - question->ReturnIntermed = mDNSfalse; + question->ReturnIntermed = (flags & kDNSServiceFlagsReturnIntermediates) != 0; question->SuppressUnusable = mDNSfalse; - question->DenyOnCellInterface = mDNSfalse; - question->DenyOnExpInterface = mDNSfalse; question->SearchListIndex = 0; question->AppendSearchDomains = 0; question->RetryWithSearchDomains = mDNSfalse; @@ -12108,295 +12421,6 @@ mDNSexport mStatus mDNS_StartBrowse(mDNS *const m, DNSQuestion *const question, return(status); } -mDNSlocal mDNSBool MachineHasActiveIPv6(mDNS *const m) -{ - NetworkInterfaceInfo *intf; - for (intf = m->HostInterfaces; intf; intf = intf->next) - if (intf->ip.type == mDNSAddrType_IPv6) return(mDNStrue); - return(mDNSfalse); -} - -mDNSlocal void FoundServiceInfoSRV(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord) -{ - ServiceInfoQuery *query = (ServiceInfoQuery *)question->QuestionContext; - mDNSBool PortChanged = !mDNSSameIPPort(query->info->port, answer->rdata->u.srv.port); - if (!AddRecord) return; - if (answer->rrtype != kDNSType_SRV) return; - - query->info->port = answer->rdata->u.srv.port; - - // If this is our first answer, then set the GotSRV flag and start the address query - if (!query->GotSRV) - { - query->GotSRV = mDNStrue; - query->qAv4.InterfaceID = answer->InterfaceID; - AssignDomainName(&query->qAv4.qname, &answer->rdata->u.srv.target); - query->qAv6.InterfaceID = answer->InterfaceID; - AssignDomainName(&query->qAv6.qname, &answer->rdata->u.srv.target); - mDNS_StartQuery(m, &query->qAv4); - // Only do the AAAA query if this machine actually has IPv6 active - if (MachineHasActiveIPv6(m)) mDNS_StartQuery(m, &query->qAv6); - } - // If this is not our first answer, only re-issue the address query if the target host name has changed - else if ((query->qAv4.InterfaceID != query->qSRV.InterfaceID && query->qAv4.InterfaceID != answer->InterfaceID) || - !SameDomainName(&query->qAv4.qname, &answer->rdata->u.srv.target)) - { - mDNS_StopQuery(m, &query->qAv4); - if (query->qAv6.ThisQInterval >= 0) mDNS_StopQuery(m, &query->qAv6); - if (SameDomainName(&query->qAv4.qname, &answer->rdata->u.srv.target) && !PortChanged) - { - // If we get here, it means: - // 1. This is not our first SRV answer - // 2. The interface ID is different, but the target host and port are the same - // This implies that we're seeing the exact same SRV record on more than one interface, so we should - // make our address queries at least as broad as the original SRV query so that we catch all the answers. - query->qAv4.InterfaceID = query->qSRV.InterfaceID; // Will be mDNSInterface_Any, or a specific interface - query->qAv6.InterfaceID = query->qSRV.InterfaceID; - } - else - { - query->qAv4.InterfaceID = answer->InterfaceID; - AssignDomainName(&query->qAv4.qname, &answer->rdata->u.srv.target); - query->qAv6.InterfaceID = answer->InterfaceID; - AssignDomainName(&query->qAv6.qname, &answer->rdata->u.srv.target); - } - debugf("FoundServiceInfoSRV: Restarting address queries for %##s (%s)", query->qAv4.qname.c, DNSTypeName(query->qAv4.qtype)); - mDNS_StartQuery(m, &query->qAv4); - // Only do the AAAA query if this machine actually has IPv6 active - if (MachineHasActiveIPv6(m)) mDNS_StartQuery(m, &query->qAv6); - } - else if (query->ServiceInfoQueryCallback && query->GotADD && query->GotTXT && PortChanged) - { - if (++query->Answers >= 100) - debugf("**** WARNING **** Have given %lu answers for %##s (SRV) %##s %u", - query->Answers, query->qSRV.qname.c, answer->rdata->u.srv.target.c, - mDNSVal16(answer->rdata->u.srv.port)); - query->ServiceInfoQueryCallback(m, query); - } - // CAUTION: MUST NOT do anything more with query after calling query->Callback(), because the client's - // callback function is allowed to do anything, including deleting this query and freeing its memory. -} - -mDNSlocal void FoundServiceInfoTXT(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord) -{ - ServiceInfoQuery *query = (ServiceInfoQuery *)question->QuestionContext; - if (!AddRecord) return; - if (answer->rrtype != kDNSType_TXT) return; - if (answer->rdlength > sizeof(query->info->TXTinfo)) return; - - query->GotTXT = mDNStrue; - query->info->TXTlen = answer->rdlength; - query->info->TXTinfo[0] = 0; // In case answer->rdlength is zero - mDNSPlatformMemCopy(query->info->TXTinfo, answer->rdata->u.txt.c, answer->rdlength); - - verbosedebugf("FoundServiceInfoTXT: %##s GotADD=%d", query->info->name.c, query->GotADD); - - // CAUTION: MUST NOT do anything more with query after calling query->Callback(), because the client's - // callback function is allowed to do anything, including deleting this query and freeing its memory. - if (query->ServiceInfoQueryCallback && query->GotADD) - { - if (++query->Answers >= 100) - debugf("**** WARNING **** have given %lu answers for %##s (TXT) %#s...", - query->Answers, query->qSRV.qname.c, answer->rdata->u.txt.c); - query->ServiceInfoQueryCallback(m, query); - } -} - -mDNSlocal void FoundServiceInfo(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord) -{ - ServiceInfoQuery *query = (ServiceInfoQuery *)question->QuestionContext; - //LogInfo("FoundServiceInfo %d %s", AddRecord, RRDisplayString(m, answer)); - if (!AddRecord) return; - - if (answer->rrtype == kDNSType_A) - { - query->info->ip.type = mDNSAddrType_IPv4; - query->info->ip.ip.v4 = answer->rdata->u.ipv4; - } - else if (answer->rrtype == kDNSType_AAAA) - { - query->info->ip.type = mDNSAddrType_IPv6; - query->info->ip.ip.v6 = answer->rdata->u.ipv6; - } - else - { - debugf("FoundServiceInfo: answer %##s type %d (%s) unexpected", answer->name->c, answer->rrtype, DNSTypeName(answer->rrtype)); - return; - } - - query->GotADD = mDNStrue; - query->info->InterfaceID = answer->InterfaceID; - - verbosedebugf("FoundServiceInfo v%ld: %##s GotTXT=%d", query->info->ip.type, query->info->name.c, query->GotTXT); - - // CAUTION: MUST NOT do anything more with query after calling query->Callback(), because the client's - // callback function is allowed to do anything, including deleting this query and freeing its memory. - if (query->ServiceInfoQueryCallback && query->GotTXT) - { - if (++query->Answers >= 100) - debugf(answer->rrtype == kDNSType_A ? - "**** WARNING **** have given %lu answers for %##s (A) %.4a" : - "**** WARNING **** have given %lu answers for %##s (AAAA) %.16a", - query->Answers, query->qSRV.qname.c, &answer->rdata->u.data); - query->ServiceInfoQueryCallback(m, query); - } -} - -// On entry, the client must have set the name and InterfaceID fields of the ServiceInfo structure -// If the query is not interface-specific, then InterfaceID may be zero -// Each time the Callback is invoked, the remainder of the fields will have been filled in -// In addition, InterfaceID will be updated to give the interface identifier corresponding to that response -mDNSexport mStatus mDNS_StartResolveService(mDNS *const m, - ServiceInfoQuery *query, ServiceInfo *info, mDNSServiceInfoQueryCallback *Callback, void *Context) -{ - mStatus status; - mDNS_Lock(m); - - query->qSRV.ThisQInterval = -1; // So that mDNS_StopResolveService() knows whether to cancel this question - query->qSRV.InterfaceID = info->InterfaceID; - query->qSRV.flags = 0; - query->qSRV.Target = zeroAddr; - AssignDomainName(&query->qSRV.qname, &info->name); - query->qSRV.qtype = kDNSType_SRV; - query->qSRV.qclass = kDNSClass_IN; - query->qSRV.LongLived = mDNSfalse; - query->qSRV.ExpectUnique = mDNStrue; - query->qSRV.ForceMCast = mDNSfalse; - query->qSRV.ReturnIntermed = mDNSfalse; - query->qSRV.SuppressUnusable = mDNSfalse; - query->qSRV.DenyOnCellInterface = mDNSfalse; - query->qSRV.DenyOnExpInterface = mDNSfalse; - query->qSRV.SearchListIndex = 0; - query->qSRV.AppendSearchDomains = 0; - query->qSRV.RetryWithSearchDomains = mDNSfalse; - query->qSRV.TimeoutQuestion = 0; - query->qSRV.WakeOnResolve = 0; - query->qSRV.UseBackgroundTrafficClass = mDNSfalse; - query->qSRV.ValidationRequired = 0; - query->qSRV.ValidatingResponse = 0; - query->qSRV.ProxyQuestion = 0; - query->qSRV.qnameOrig = mDNSNULL; - query->qSRV.AnonInfo = mDNSNULL; - query->qSRV.QuestionCallback = FoundServiceInfoSRV; - query->qSRV.QuestionContext = query; - - query->qTXT.ThisQInterval = -1; // So that mDNS_StopResolveService() knows whether to cancel this question - query->qTXT.InterfaceID = info->InterfaceID; - query->qTXT.flags = 0; - query->qTXT.Target = zeroAddr; - AssignDomainName(&query->qTXT.qname, &info->name); - query->qTXT.qtype = kDNSType_TXT; - query->qTXT.qclass = kDNSClass_IN; - query->qTXT.LongLived = mDNSfalse; - query->qTXT.ExpectUnique = mDNStrue; - query->qTXT.ForceMCast = mDNSfalse; - query->qTXT.ReturnIntermed = mDNSfalse; - query->qTXT.SuppressUnusable = mDNSfalse; - query->qTXT.DenyOnCellInterface = mDNSfalse; - query->qTXT.DenyOnExpInterface = mDNSfalse; - query->qTXT.SearchListIndex = 0; - query->qTXT.AppendSearchDomains = 0; - query->qTXT.RetryWithSearchDomains = mDNSfalse; - query->qTXT.TimeoutQuestion = 0; - query->qTXT.WakeOnResolve = 0; - query->qTXT.UseBackgroundTrafficClass = mDNSfalse; - query->qTXT.ValidationRequired = 0; - query->qTXT.ValidatingResponse = 0; - query->qTXT.ProxyQuestion = 0; - query->qTXT.qnameOrig = mDNSNULL; - query->qTXT.AnonInfo = mDNSNULL; - query->qTXT.QuestionCallback = FoundServiceInfoTXT; - query->qTXT.QuestionContext = query; - - query->qAv4.ThisQInterval = -1; // So that mDNS_StopResolveService() knows whether to cancel this question - query->qAv4.InterfaceID = info->InterfaceID; - query->qAv4.flags = 0; - query->qAv4.Target = zeroAddr; - query->qAv4.qname.c[0] = 0; - query->qAv4.qtype = kDNSType_A; - query->qAv4.qclass = kDNSClass_IN; - query->qAv4.LongLived = mDNSfalse; - query->qAv4.ExpectUnique = mDNStrue; - query->qAv4.ForceMCast = mDNSfalse; - query->qAv4.ReturnIntermed = mDNSfalse; - query->qAv4.SuppressUnusable = mDNSfalse; - query->qAv4.DenyOnCellInterface = mDNSfalse; - query->qAv4.DenyOnExpInterface = mDNSfalse; - query->qAv4.SearchListIndex = 0; - query->qAv4.AppendSearchDomains = 0; - query->qAv4.RetryWithSearchDomains = mDNSfalse; - query->qAv4.TimeoutQuestion = 0; - query->qAv4.WakeOnResolve = 0; - query->qAv4.UseBackgroundTrafficClass = mDNSfalse; - query->qAv4.ValidationRequired = 0; - query->qAv4.ValidatingResponse = 0; - query->qAv4.ProxyQuestion = 0; - query->qAv4.qnameOrig = mDNSNULL; - query->qAv4.AnonInfo = mDNSNULL; - query->qAv4.QuestionCallback = FoundServiceInfo; - query->qAv4.QuestionContext = query; - - query->qAv6.ThisQInterval = -1; // So that mDNS_StopResolveService() knows whether to cancel this question - query->qAv6.InterfaceID = info->InterfaceID; - query->qAv6.flags = 0; - query->qAv6.Target = zeroAddr; - query->qAv6.qname.c[0] = 0; - query->qAv6.qtype = kDNSType_AAAA; - query->qAv6.qclass = kDNSClass_IN; - query->qAv6.LongLived = mDNSfalse; - query->qAv6.ExpectUnique = mDNStrue; - query->qAv6.ForceMCast = mDNSfalse; - query->qAv6.ReturnIntermed = mDNSfalse; - query->qAv6.SuppressUnusable = mDNSfalse; - query->qAv6.DenyOnCellInterface = mDNSfalse; - query->qAv6.DenyOnExpInterface = mDNSfalse; - query->qAv6.SearchListIndex = 0; - query->qAv6.AppendSearchDomains = 0; - query->qAv6.RetryWithSearchDomains = mDNSfalse; - query->qAv6.TimeoutQuestion = 0; - query->qAv6.UseBackgroundTrafficClass = mDNSfalse; - query->qAv6.ValidationRequired = 0; - query->qAv6.ValidatingResponse = 0; - query->qAv6.ProxyQuestion = 0; - query->qAv6.qnameOrig = mDNSNULL; - query->qAv6.AnonInfo = mDNSNULL; - query->qAv6.QuestionCallback = FoundServiceInfo; - query->qAv6.QuestionContext = query; - - query->GotSRV = mDNSfalse; - query->GotTXT = mDNSfalse; - query->GotADD = mDNSfalse; - query->Answers = 0; - - query->info = info; - query->ServiceInfoQueryCallback = Callback; - query->ServiceInfoQueryContext = Context; - -// info->name = Must already be set up by client -// info->interface = Must already be set up by client - info->ip = zeroAddr; - info->port = zeroIPPort; - info->TXTlen = 0; - - // We use mDNS_StartQuery_internal here because we're already holding the lock - status = mDNS_StartQuery_internal(m, &query->qSRV); - if (status == mStatus_NoError) status = mDNS_StartQuery_internal(m, &query->qTXT); - if (status != mStatus_NoError) mDNS_StopResolveService(m, query); - - mDNS_Unlock(m); - return(status); -} - -mDNSexport void mDNS_StopResolveService (mDNS *const m, ServiceInfoQuery *q) -{ - mDNS_Lock(m); - // We use mDNS_StopQuery_internal here because we're already holding the lock - if (q->qSRV.ThisQInterval >= 0) mDNS_StopQuery_internal(m, &q->qSRV); - if (q->qTXT.ThisQInterval >= 0) mDNS_StopQuery_internal(m, &q->qTXT); - if (q->qAv4.ThisQInterval >= 0) mDNS_StopQuery_internal(m, &q->qAv4); - if (q->qAv6.ThisQInterval >= 0) mDNS_StopQuery_internal(m, &q->qAv6); - mDNS_Unlock(m); -} mDNSexport mStatus mDNS_GetDomains(mDNS *const m, DNSQuestion *const question, mDNS_DomainType DomainType, const domainname *dom, const mDNSInterfaceID InterfaceID, mDNSQuestionCallback *Callback, void *Context) @@ -12411,8 +12435,6 @@ mDNSexport mStatus mDNS_GetDomains(mDNS *const m, DNSQuestion *const question, m question->ForceMCast = mDNSfalse; question->ReturnIntermed = mDNSfalse; question->SuppressUnusable = mDNSfalse; - question->DenyOnCellInterface = mDNSfalse; - question->DenyOnExpInterface = mDNSfalse; question->SearchListIndex = 0; question->AppendSearchDomains = 0; question->RetryWithSearchDomains = mDNSfalse; @@ -12425,7 +12447,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->euid = 0; question->QuestionCallback = Callback; question->QuestionContext = Context; if (DomainType > mDNS_DomainTypeMax) return(mStatus_BadParamErr); @@ -12538,6 +12560,8 @@ mDNSlocal NetworkInterfaceInfo *FindFirstAdvertisedInterface(mDNS *const m) return(intf); } +// The parameter "set" here refers to the set of AuthRecords used to advertise this interface. +// (It's a set of records, not a set of interfaces.) mDNSlocal void AdvertiseInterface(mDNS *const m, NetworkInterfaceInfo *set) { char buffer[MAX_REVERSE_MAPPING_NAME]; @@ -12552,6 +12576,8 @@ mDNSlocal void AdvertiseInterface(mDNS *const m, NetworkInterfaceInfo *set) primary = FindFirstAdvertisedInterface(m); if (!primary) primary = set; // If no existing advertised interface, this new NetworkInterfaceInfo becomes our new primary + // We should never have primary be NULL, because even if there is + // no other interface yet, we should always find ourself in the list. // 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. @@ -12561,9 +12587,9 @@ mDNSlocal void AdvertiseInterface(mDNS *const m, NetworkInterfaceInfo *set) LogInfo("AdvertiseInterface: Marking address record as kDNSRecordTypeKnownUnique for %s", set->ifname); // Send dynamic update for non-linklocal IPv4 Addresses - mDNS_SetupResourceRecord(&set->RR_A, mDNSNULL, set->InterfaceID, kDNSType_A, kHostNameTTL, recordType, AuthRecordAny, mDNS_HostNameCallback, set); - mDNS_SetupResourceRecord(&set->RR_PTR, mDNSNULL, set->InterfaceID, kDNSType_PTR, kHostNameTTL, kDNSRecordTypeKnownUnique, AuthRecordAny, mDNSNULL, mDNSNULL); - mDNS_SetupResourceRecord(&set->RR_HINFO, mDNSNULL, set->InterfaceID, kDNSType_HINFO, kHostNameTTL, kDNSRecordTypeUnique, AuthRecordAny, mDNSNULL, mDNSNULL); + mDNS_SetupResourceRecord(&set->RR_A, mDNSNULL, set->InterfaceID, kDNSType_A, kHostNameTTL, recordType, AuthRecordAny, mDNS_HostNameCallback, set); + mDNS_SetupResourceRecord(&set->RR_PTR, mDNSNULL, set->InterfaceID, kDNSType_PTR, kHostNameTTL, kDNSRecordTypeKnownUnique, AuthRecordAny, mDNSNULL, mDNSNULL); + mDNS_SetupResourceRecord(&set->RR_HINFO, mDNSNULL, set->InterfaceID, kDNSType_HINFO, kHostNameTTL, kDNSRecordTypeUnique, AuthRecordAny, mDNSNULL, mDNSNULL); #if ANSWER_REMOTE_HOSTNAME_QUERIES set->RR_A.AllowRemoteQuery = mDNStrue; @@ -12636,6 +12662,10 @@ mDNSlocal void DeadvertiseInterface(mDNS *const m, NetworkInterfaceInfo *set) return; } +#if APPLE_OSX_mDNSResponder + D2D_stop_advertising_interface(set); +#endif // APPLE_OSX_mDNSResponder + // 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. @@ -12644,11 +12674,6 @@ mDNSlocal void DeadvertiseInterface(mDNS *const m, NetworkInterfaceInfo *set) 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 - D2D_stop_advertising_interface(set); -#endif // APPLE_OSX_mDNSResponder - } mDNSlocal void AdvertiseAllInterfaceRecords(mDNS *const m) @@ -12677,6 +12702,23 @@ mDNSlocal void DeadvertiseAllInterfaceRecords(mDNS *const m) } } +// Change target host name for record. +mDNSlocal void UpdateTargetHostName(mDNS *const m, AuthRecord *const rr) +{ +#if APPLE_OSX_mDNSResponder + // If this record was also registered with any D2D plugins, stop advertising + // the version with the old host name. + D2D_stop_advertising_record(rr); +#endif + + SetTargetToHostName(m, rr); + +#if APPLE_OSX_mDNSResponder + // Advertise the record with the updated host name with the D2D plugins if appropriate. + D2D_start_advertising_record(rr); +#endif +} + mDNSexport void mDNS_SetFQDN(mDNS *const m) { domainname newmname; @@ -12697,8 +12739,8 @@ mDNSexport void mDNS_SetFQDN(mDNS *const m) } // 3. Make sure that any AutoTarget SRV records (and the like) get updated - for (rr = m->ResourceRecords; rr; rr=rr->next) if (rr->AutoTarget) SetTargetToHostName(m, rr); - for (rr = m->DuplicateRecords; rr; rr=rr->next) if (rr->AutoTarget) SetTargetToHostName(m, rr); + for (rr = m->ResourceRecords; rr; rr=rr->next) if (rr->AutoTarget) UpdateTargetHostName(m, rr); + for (rr = m->DuplicateRecords; rr; rr=rr->next) if (rr->AutoTarget) UpdateTargetHostName(m, rr); mDNS_Unlock(m); } @@ -12787,7 +12829,7 @@ mDNSlocal void InitializeNetWakeState(mDNS *const m, NetworkInterfaceInfo *set) // be stopped during interface deregistration. We can't sanity check to see if the // question has been stopped or not before initializing it to -1 because we need to // initialize it to -1 the very first time. - + set->NetWakeBrowse.ThisQInterval = -1; for (i=0; i<3; i++) { @@ -12834,7 +12876,7 @@ mDNSexport void mDNS_DeactivateNetWake_internal(mDNS *const m, NetworkInterfaceI if (m->SPSBrowseCallback) { mDNS_DropLockBeforeCallback(); // Allow client to legally make mDNS API calls from the callback - m->SPSBrowseCallback(m, &set->NetWakeBrowse, mDNSNULL, QC_rmv); + m->SPSBrowseCallback(m, &set->NetWakeBrowse, mDNSNULL, mDNSfalse); mDNS_ReclaimLockAfterCallback(); // Decrement mDNS_reentrancy to block mDNS API calls again } @@ -12844,7 +12886,7 @@ mDNSexport void mDNS_DeactivateNetWake_internal(mDNS *const m, NetworkInterfaceI } } -mDNSexport mStatus mDNS_RegisterInterface(mDNS *const m, NetworkInterfaceInfo *set, mDNSBool flapping) +mDNSexport mStatus mDNS_RegisterInterface(mDNS *const m, NetworkInterfaceInfo *set, InterfaceActivationSpeed activationSpeed) { AuthRecord *rr; mDNSBool FirstOfType = mDNStrue; @@ -12915,31 +12957,56 @@ mDNSexport mStatus mDNS_RegisterInterface(mDNS *const m, NetworkInterfaceInfo *s // We don't want to do a probe, and then see a stale echo of an announcement we ourselves sent, // and think it's a conflicting answer to our probe. // In the case of a flapping interface, we pause for five seconds, and reduce the announcement count to one packet. - const mDNSs32 probedelay = flapping ? mDNSPlatformOneSecond * 5 : mDNSPlatformOneSecond / 2; - const mDNSu8 numannounce = flapping ? (mDNSu8)1 : InitialAnnounceCount; + mDNSs32 probedelay; + mDNSu8 numannounce; + switch (activationSpeed) + { + case FastActivation: + probedelay = (mDNSs32)0; + numannounce = InitialAnnounceCount; + LogMsg("mDNS_RegisterInterface: Using fast activation for DirectLink interface %s (%#a)", set->ifname, &set->ip); + break; - // Use a small amount of randomness: - // In the case of a network administrator turning on an Ethernet hub so that all the - // connected machines establish link at exactly the same time, we don't want them all - // to go and hit the network with identical queries at exactly the same moment. - // We set a random delay of up to InitialQuestionInterval (1/3 second). - // We must *never* set m->SuppressSending to more than that (or set it repeatedly in a way - // that causes mDNSResponder to remain in a prolonged state of SuppressSending, because - // suppressing packet sending for more than about 1/3 second can cause protocol correctness - // to start to break down (e.g. we don't answer probes fast enough, and get name conflicts). - // See <rdar://problem/4073853> mDNS: m->SuppressSending set too enthusiastically - if (!m->SuppressSending) m->SuppressSending = m->timenow + (mDNSs32)mDNSRandom((mDNSu32)InitialQuestionInterval); + case SlowActivation: + probedelay = mDNSPlatformOneSecond * 5; + numannounce = (mDNSu8)1; + LogMsg("mDNS_RegisterInterface: Frequent transitions for interface %s (%#a), doing slow activation", set->ifname, &set->ip); + m->mDNSStats.InterfaceUpFlap++; + break; - if (flapping) - { - LogMsg("mDNS_RegisterInterface: Frequent transitions for interface %s (%#a)", set->ifname, &set->ip); - m->mDNSStats.InterfaceUpFlap++; + case NormalActivation: + default: + probedelay = mDNSPlatformOneSecond / 2; + numannounce = InitialAnnounceCount; + break; } LogInfo("mDNS_RegisterInterface: %s (%#a) probedelay %d", set->ifname, &set->ip, probedelay); - if (m->SuppressProbes == 0 || - m->SuppressProbes - NonZeroTime(m->timenow + probedelay) < 0) - m->SuppressProbes = NonZeroTime(m->timenow + probedelay); + + // No probe or sending suppression on DirectLink type interfaces. + if (activationSpeed == FastActivation) + { + m->SuppressSending = 0; + m->SuppressProbes = 0; + } + else + { + // Use a small amount of randomness: + // In the case of a network administrator turning on an Ethernet hub so that all the + // connected machines establish link at exactly the same time, we don't want them all + // to go and hit the network with identical queries at exactly the same moment. + // We set a random delay of up to InitialQuestionInterval (1/3 second). + // We must *never* set m->SuppressSending to more than that (or set it repeatedly in a way + // that causes mDNSResponder to remain in a prolonged state of SuppressSending, because + // suppressing packet sending for more than about 1/3 second can cause protocol correctness + // to start to break down (e.g. we don't answer probes fast enough, and get name conflicts). + // See <rdar://problem/4073853> mDNS: m->SuppressSending set too enthusiastically + if (!m->SuppressSending) m->SuppressSending = m->timenow + (mDNSs32)mDNSRandom((mDNSu32)InitialQuestionInterval); + + if (m->SuppressProbes == 0 || + m->SuppressProbes - NonZeroTime(m->timenow + probedelay) < 0) + m->SuppressProbes = NonZeroTime(m->timenow + probedelay); + } // Include OWNER option in packets for 60 seconds after connecting to the network. Setting // it here also handles the wake up case as the network link comes UP after waking causing @@ -12956,21 +13023,15 @@ mDNSexport mStatus mDNS_RegisterInterface(mDNS *const m, NetworkInterfaceInfo *s if (!q->InterfaceID || q->InterfaceID == set->InterfaceID) // If non-specific Q, or Q on this specific interface, { // then reactivate this question // If flapping, delay between first and second queries is nine seconds instead of one second - mDNSBool dodelay = flapping && (q->FlappingInterface1 == set->InterfaceID || q->FlappingInterface2 == set->InterfaceID); + mDNSBool dodelay = (activationSpeed == SlowActivation) && (q->FlappingInterface1 == set->InterfaceID || q->FlappingInterface2 == set->InterfaceID); mDNSs32 initial = dodelay ? InitialQuestionInterval * QuestionIntervalStep2 : InitialQuestionInterval; - mDNSs32 qdelay = dodelay ? mDNSPlatformOneSecond * 5 : 0; - if (dodelay) LogInfo("No cache records expired for %##s (%s); okay to delay questions a little", q->qname.c, DNSTypeName(q->qtype)); + mDNSs32 qdelay = dodelay ? kDefaultQueryDelayTimeForFlappingInterface : 0; + if (dodelay) LogInfo("No cache records expired for %##s (%s); delaying questions by %d seconds", q->qname.c, DNSTypeName(q->qtype), qdelay); if (!q->ThisQInterval || q->ThisQInterval > initial) { - q->ThisQInterval = initial; - -#if mDNS_REQUEST_UNICAST_RESPONSE - q->RequestUnicast = SET_QU_IN_FIRST_FOUR_QUERIES; -#else // mDNS_REQUEST_UNICAST_RESPONSE - q->RequestUnicast = SET_QU_IN_FIRST_QUERY; -#endif // mDNS_REQUEST_UNICAST_RESPONSE - + q->ThisQInterval = initial; + q->RequestUnicast = kDefaultRequestUnicastCount; } q->LastQTime = m->timenow - q->ThisQInterval + qdelay; q->RecentAnswerPkts = 0; @@ -13008,7 +13069,7 @@ mDNSexport mStatus mDNS_RegisterInterface(mDNS *const m, NetworkInterfaceInfo *s // Note: mDNS_DeregisterInterface 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. -mDNSexport void mDNS_DeregisterInterface(mDNS *const m, NetworkInterfaceInfo *set, mDNSBool flapping) +mDNSexport void mDNS_DeregisterInterface(mDNS *const m, NetworkInterfaceInfo *set, InterfaceActivationSpeed activationSpeed) { NetworkInterfaceInfo **p = &m->HostInterfaces; mDNSBool revalidate = mDNSfalse; @@ -13068,7 +13129,7 @@ mDNSexport void mDNS_DeregisterInterface(mDNS *const m, NetworkInterfaceInfo *se m->mDNSStats.InterfaceDown++; - if (set->McastTxRx && flapping) + if (set->McastTxRx && (activationSpeed == SlowActivation)) { LogMsg("mDNS_DeregisterInterface: Frequent transitions for interface %s (%#a)", set->ifname, &set->ip); m->mDNSStats.InterfaceDownFlap++; @@ -13094,9 +13155,10 @@ mDNSexport void mDNS_DeregisterInterface(mDNS *const m, NetworkInterfaceInfo *se { // If this interface is deemed flapping, // postpone deleting the cache records in case the interface comes back again - if (set->McastTxRx && flapping) + if (set->McastTxRx && (activationSpeed == SlowActivation)) { - // For a flapping interface we want these record to go away after 30 seconds + // For a flapping interface we want these records to go away after + // kDefaultReconfirmTimeForFlappingInterface seconds if they are not reconfirmed. mDNS_Reconfirm_internal(m, rr, kDefaultReconfirmTimeForFlappingInterface); // We set UnansweredQueries = MaxUnansweredQueries so we don't waste time doing any queries for them -- // if the interface does come back, any relevant questions will be reactivated anyway @@ -13256,20 +13318,21 @@ mDNSlocal void NSSCallback(mDNS *const m, AuthRecord *const rr, mStatus result) } +// Derive AuthRecType from the kDNSServiceFlags* values. mDNSlocal AuthRecType setAuthRecType(mDNSInterfaceID InterfaceID, mDNSu32 flags) { AuthRecType artype; if (InterfaceID == mDNSInterface_LocalOnly) artype = AuthRecordLocalOnly; - else if (InterfaceID == mDNSInterface_P2P) + else if (InterfaceID == mDNSInterface_P2P || InterfaceID == mDNSInterface_BLE) artype = AuthRecordP2P; - else if ((InterfaceID == mDNSInterface_Any) && (flags & coreFlagIncludeP2P) - && (flags & coreFlagIncludeAWDL)) + else if ((InterfaceID == mDNSInterface_Any) && (flags & kDNSServiceFlagsIncludeP2P) + && (flags & kDNSServiceFlagsIncludeAWDL)) artype = AuthRecordAnyIncludeAWDLandP2P; - else if ((InterfaceID == mDNSInterface_Any) && (flags & coreFlagIncludeP2P)) + else if ((InterfaceID == mDNSInterface_Any) && (flags & kDNSServiceFlagsIncludeP2P)) artype = AuthRecordAnyIncludeP2P; - else if ((InterfaceID == mDNSInterface_Any) && (flags & coreFlagIncludeAWDL)) + else if ((InterfaceID == mDNSInterface_Any) && (flags & kDNSServiceFlagsIncludeAWDL)) artype = AuthRecordAnyIncludeAWDL; else artype = AuthRecordAny; @@ -13277,6 +13340,18 @@ mDNSlocal AuthRecType setAuthRecType(mDNSInterfaceID InterfaceID, mDNSu32 flags) return artype; } +// Used to derive the original D2D specific flags specified by the client in the registration +// when we don't have access to the original flag (kDNSServiceFlags*) values. +mDNSexport mDNSu32 deriveD2DFlagsFromAuthRecType(AuthRecType authRecType) +{ + mDNSu32 flags = 0; + if ((authRecType == AuthRecordAnyIncludeP2P) || (authRecType == AuthRecordAnyIncludeAWDLandP2P)) + flags |= kDNSServiceFlagsIncludeP2P; + else if ((authRecType == AuthRecordAnyIncludeAWDL) || (authRecType == AuthRecordAnyIncludeAWDLandP2P)) + flags |= kDNSServiceFlagsIncludeAWDL; + return flags; +} + // Note: // Name is first label of domain name (any dots in the name are actual dots, not label separators) // Type is service type (e.g. "_ipp._tcp.") @@ -13296,7 +13371,7 @@ mDNSexport mStatus mDNS_RegisterService(mDNS *const m, ServiceRecordSet *sr, mDNSu32 i; mDNSu32 hostTTL; AuthRecType artype; - mDNSu8 recordType = (flags & coreFlagKnownUnique) ? kDNSRecordTypeKnownUnique : kDNSRecordTypeUnique; + mDNSu8 recordType = (flags & kDNSServiceFlagsKnownUnique) ? kDNSRecordTypeKnownUnique : kDNSRecordTypeUnique; sr->ServiceCallback = Callback; sr->ServiceContext = Context; @@ -13314,7 +13389,7 @@ mDNSexport mStatus mDNS_RegisterService(mDNS *const m, ServiceRecordSet *sr, mDNS_SetupResourceRecord(&sr->RR_ADV, mDNSNULL, InterfaceID, kDNSType_PTR, kStandardTTL, kDNSRecordTypeAdvisory, artype, ServiceCallback, sr); mDNS_SetupResourceRecord(&sr->RR_PTR, mDNSNULL, InterfaceID, kDNSType_PTR, kStandardTTL, kDNSRecordTypeShared, artype, ServiceCallback, sr); - if (flags & coreFlagWakeOnly) + if (flags & kDNSServiceFlagsWakeOnlyService) { sr->RR_PTR.AuthFlags = AuthFlagsWakeOnly; } @@ -13325,14 +13400,14 @@ mDNSexport mStatus mDNS_RegisterService(mDNS *const m, ServiceRecordSet *sr, hostTTL = kHostNameTTL; mDNS_SetupResourceRecord(&sr->RR_SRV, mDNSNULL, InterfaceID, kDNSType_SRV, hostTTL, recordType, artype, ServiceCallback, sr); - mDNS_SetupResourceRecord(&sr->RR_TXT, mDNSNULL, InterfaceID, kDNSType_TXT, kStandardTTL, kDNSRecordTypeUnique, artype, ServiceCallback, sr); + mDNS_SetupResourceRecord(&sr->RR_TXT, mDNSNULL, InterfaceID, kDNSType_TXT, kStandardTTL, recordType, artype, ServiceCallback, sr); // If port number is zero, that means the client is really trying to do a RegisterNoSuchService if (mDNSIPPortIsZero(port)) return(mDNS_RegisterNoSuchService(m, &sr->RR_SRV, name, type, domain, mDNSNULL, InterfaceID, NSSCallback, sr, flags)); - // If the client is registering an oversized TXT record, - // it is the client's responsibility to alloate a ServiceRecordSet structure that is large enough for it + // If the caller is registering an oversized TXT record, + // it is the caller's responsibility to allocate a ServiceRecordSet structure that is large enough for it if (sr->RR_TXT.resrec.rdata->MaxRDLength < txtlen) sr->RR_TXT.resrec.rdata->MaxRDLength = txtlen; @@ -13370,7 +13445,7 @@ mDNSexport mStatus mDNS_RegisterService(mDNS *const m, ServiceRecordSet *sr, sr->SubTypes[i].Additional1 = &sr->RR_SRV; sr->SubTypes[i].Additional2 = &sr->RR_TXT; } - + SetAnonInfoSRS(sr, NumSubTypes); // 3. Set up the SRV record rdata. @@ -13430,6 +13505,7 @@ mDNSexport mStatus mDNS_AddRecordToService(mDNS *const m, ServiceRecordSet *sr, mStatus status; AuthRecType artype; mDNSInterfaceID InterfaceID = sr->RR_PTR.resrec.InterfaceID; + ResourceRecord *rr; artype = setAuthRecType(InterfaceID, flags); @@ -13439,6 +13515,37 @@ mDNSexport mStatus mDNS_AddRecordToService(mDNS *const m, ServiceRecordSet *sr, AssignDomainName(&extra->r.namestorage, sr->RR_SRV.resrec.name); mDNS_Lock(m); + rr = mDNSNULL; + if (extra->r.resrec.rrtype == kDNSType_TXT) + { + if (sr->RR_TXT.resrec.RecordType & kDNSRecordTypeUniqueMask) rr = &sr->RR_TXT.resrec; + } + else if (extra->r.resrec.rrtype == kDNSType_SRV) + { + if (sr->RR_SRV.resrec.RecordType & kDNSRecordTypeUniqueMask) rr = &sr->RR_SRV.resrec; + } + + if (!rr) + { + ExtraResourceRecord *srExtra; + + for (srExtra = sr->Extras; srExtra; srExtra = srExtra->next) + { + if ((srExtra->r.resrec.rrtype == extra->r.resrec.rrtype) && (srExtra->r.resrec.RecordType & kDNSRecordTypeUniqueMask)) + { + rr = &srExtra->r.resrec; + break; + } + } + } + + if (rr && (extra->r.resrec.rroriginalttl != rr->rroriginalttl)) + { + LogMsg("mDNS_AddRecordToService: Correcting TTL from %4d to %4d for %s", + extra->r.resrec.rroriginalttl, rr->rroriginalttl, RRDisplayString(m, &extra->r.resrec)); + extra->r.resrec.rroriginalttl = rr->rroriginalttl; + } + e = &sr->Extras; while (*e) e = &(*e)->next; @@ -13614,7 +13721,7 @@ mDNSexport mStatus mDNS_AdvertiseDomains(mDNS *const m, AuthRecord *rr, if (InterfaceID == mDNSInterface_LocalOnly) artype = AuthRecordLocalOnly; - else if (InterfaceID == mDNSInterface_P2P) + else if (InterfaceID == mDNSInterface_P2P || InterfaceID == mDNSInterface_BLE) artype = AuthRecordP2P; else artype = AuthRecordAny; @@ -13723,8 +13830,9 @@ mDNSlocal void mDNSCoreReceiveRawARP(mDNS *const m, const ARP_EthIP *const arp, const char *const msg = mDNSSameEthAddress(&arp->sha, &rr->WakeUp.IMAC) ? msg1 : (rr->AnnounceCount == InitialAnnounceCount) ? msg2 : mDNSSameEthAddress(&arp->sha, &intf->MAC) ? msg3 : msg4; - LogSPS("%-7s %s %.6a %.4a for %.4a -- H-MAC %.6a I-MAC %.6a %s", - intf->ifname, msg, &arp->sha, &arp->spa, &arp->tpa, &rr->WakeUp.HMAC, &rr->WakeUp.IMAC, ARDisplayString(m, rr)); + LogMsg("Arp %-7s %s %.6a %.4a for %.4a -- H-MAC %.6a I-MAC %.6a %s", + intf->ifname, msg, arp->sha.b, arp->spa.b, arp->tpa.b, + &rr->WakeUp.HMAC, &rr->WakeUp.IMAC, ARDisplayString(m, rr)); if (msg == msg1) { if ( rr->ProbeRestartCount < MAX_PROBE_RESTARTS) @@ -13734,11 +13842,11 @@ mDNSlocal void mDNSCoreReceiveRawARP(mDNS *const m, const ARP_EthIP *const arp, } else if (msg == msg3) { - mDNSPlatformSetLocalAddressCacheEntry(m, &rr->AddressProxy, &rr->WakeUp.IMAC, InterfaceID); + mDNSPlatformSetLocalAddressCacheEntry(&rr->AddressProxy, &rr->WakeUp.IMAC, InterfaceID); } else if (msg == msg4) { - SendARP(m, 2, rr, &arp->tpa, &arp->sha, &arp->spa, &arp->sha); + SendARP(m, 2, rr, (mDNSv4Addr *)arp->tpa.b, &arp->sha, (mDNSv4Addr *)arp->spa.b, &arp->sha); } } } @@ -13752,7 +13860,7 @@ mDNSlocal void mDNSCoreReceiveRawARP(mDNS *const m, const ARP_EthIP *const arp, // If the sender hardware address is the original owner this is benign, so we just suppress our own proxy answering for a while longer. // If the sender hardware address is *not* the original owner, then this is a conflict, and we need to wake the sleeping machine to handle it. if (mDNSSameEthAddress(&arp->sha, &intf->MAC)) - debugf("ARP from self for %.4a", &arp->tpa); + debugf("ARP from self for %.4a", arp->tpa.b); else { if (!mDNSSameIPv4Address(arp->spa, zerov4Addr)) @@ -13762,22 +13870,22 @@ mDNSlocal void mDNSCoreReceiveRawARP(mDNS *const m, const ARP_EthIP *const arp, { if (mDNSSameEthAddress(&zeroEthAddr, &rr->WakeUp.HMAC)) { - LogSPS("%-7s ARP from %.6a %.4a for %.4a -- Invalid H-MAC %.6a I-MAC %.6a %s", intf->ifname, - &arp->sha, &arp->spa, &arp->tpa, &rr->WakeUp.HMAC, &rr->WakeUp.IMAC, ARDisplayString(m, rr)); + LogMsg("%-7s ARP from %.6a %.4a for %.4a -- Invalid H-MAC %.6a I-MAC %.6a %s", intf->ifname, + arp->sha.b, arp->spa.b, arp->tpa.b, &rr->WakeUp.HMAC, &rr->WakeUp.IMAC, ARDisplayString(m, rr)); } else { RestartARPProbing(m, rr); if (mDNSSameEthAddress(&arp->sha, &rr->WakeUp.IMAC)) { - LogSPS("%-7s ARP %s from owner %.6a %.4a for %-15.4a -- re-starting probing for %s", intf->ifname, + LogMsg("%-7s ARP %s from owner %.6a %.4a for %-15.4a -- re-starting probing for %s", intf->ifname, mDNSSameIPv4Address(arp->spa, arp->tpa) ? "Announcement " : mDNSSameOpaque16(arp->op, ARP_op_request) ? "Request " : "Response ", - &arp->sha, &arp->spa, &arp->tpa, ARDisplayString(m, rr)); + arp->sha.b, arp->spa.b, arp->tpa.b, ARDisplayString(m, rr)); } else { LogMsg("%-7s Conflicting ARP from %.6a %.4a for %.4a -- waking H-MAC %.6a I-MAC %.6a %s", intf->ifname, - &arp->sha, &arp->spa, &arp->tpa, &rr->WakeUp.HMAC, &rr->WakeUp.IMAC, ARDisplayString(m, rr)); + arp->sha.b, arp->spa.b, arp->tpa.b, &rr->WakeUp.HMAC, &rr->WakeUp.IMAC, ARDisplayString(m, rr)); ScheduleWakeup(m, rr->resrec.InterfaceID, &rr->WakeUp.HMAC); } } @@ -13840,10 +13948,10 @@ mDNSlocal void mDNSCoreReceiveRawND(mDNS *const m, const mDNSEthAddr *const sha, LogSPS("Reached maximum number of restarts for probing - %s", ARDisplayString(m,rr)); } else if (msg == msg3) - mDNSPlatformSetLocalAddressCacheEntry(m, &rr->AddressProxy, &rr->WakeUp.IMAC, InterfaceID); - else if (msg == msg4) + mDNSPlatformSetLocalAddressCacheEntry(&rr->AddressProxy, &rr->WakeUp.IMAC, InterfaceID); + else if (msg == msg4) SendNDP(m, NDP_Adv, NDP_Solicited, rr, &ndp->target, mDNSNULL, spa, sha); - else if (msg == msg5) + else if (msg == msg5) SendNDP(m, NDP_Adv, 0, rr, &ndp->target, mDNSNULL, &AllHosts_v6, &AllHosts_v6_Eth); } } @@ -14179,7 +14287,7 @@ mDNSexport void mDNSCoreBeSleepProxyServer_internal(mDNS *const m, mDNSu8 sps, m { if (!m->SPSSocket) { - m->SPSSocket = mDNSPlatformUDPSocket(m, zeroIPPort); + m->SPSSocket = mDNSPlatformUDPSocket(zeroIPPort); if (!m->SPSSocket) { LogMsg("mDNSCoreBeSleepProxyServer: Failed to allocate SPSSocket"); goto fail; } } #ifndef SPC_DISABLED @@ -14221,9 +14329,9 @@ mDNSexport void mDNS_GrowCache(mDNS *const m, CacheEntity *storage, mDNSu32 numr mDNS_Unlock(m); } -mDNSexport mStatus mDNS_Init(mDNS *const m, mDNS_PlatformSupport *const p, - CacheEntity *rrcachestorage, mDNSu32 rrcachesize, - mDNSBool AdvertiseLocalAddresses, mDNSCallback *Callback, void *Context) +mDNSlocal mStatus mDNS_InitStorage(mDNS *const m, mDNS_PlatformSupport *const p, + CacheEntity *rrcachestorage, mDNSu32 rrcachesize, + mDNSBool AdvertiseLocalAddresses, mDNSCallback *Callback, void *Context) { mDNSu32 slot; mDNSs32 timenow; @@ -14263,14 +14371,22 @@ mDNSexport mStatus mDNS_Init(mDNS *const m, mDNS_PlatformSupport *const p, m->timenow_last = timenow; m->NextScheduledEvent = timenow; m->SuppressSending = timenow; - m->NextCacheCheck = timenow + 0x78000000; - m->NextScheduledQuery = timenow + 0x78000000; - m->NextScheduledProbe = timenow + 0x78000000; - m->NextScheduledResponse = timenow + 0x78000000; - m->NextScheduledNATOp = timenow + 0x78000000; - m->NextScheduledSPS = timenow + 0x78000000; - m->NextScheduledKA = timenow + 0x78000000; - m->NextScheduledStopTime = timenow + 0x78000000; + m->NextCacheCheck = timenow + FutureTime; + m->NextScheduledQuery = timenow + FutureTime; + m->NextScheduledProbe = timenow + FutureTime; + m->NextScheduledResponse = timenow + FutureTime; + m->NextScheduledNATOp = timenow + FutureTime; + m->NextScheduledSPS = timenow + FutureTime; + m->NextScheduledKA = timenow + FutureTime; + m->NextScheduledStopTime = timenow + FutureTime; + m->NextBLEServiceTime = 0; // zero indicates inactive + +#if BONJOUR_ON_DEMAND + m->NextBonjourDisableTime = 0; // Timer active when non zero. + m->BonjourEnabled = 0; // Set when Bonjour on Demand is enabled and Bonjour is currently enabled. +#endif // BONJOUR_ON_DEMAND + + m->DelayConflictProcessing = MAX_CONFLICT_PROCESSING_DELAYS; m->RandomQueryDelay = 0; m->RandomReconfirmDelay = 0; m->PktNum = 0; @@ -14284,9 +14400,6 @@ mDNSexport mStatus mDNS_Init(mDNS *const m, mDNS_PlatformSupport *const p, m->SleepLimit = 0; #if APPLE_OSX_mDNSResponder - m->StatStartTime = mDNSPlatformUTC(); - m->NextStatLogTime = m->StatStartTime + kDefaultNextStatsticsLogTime; - m->ActiveStatTime = 0; m->UnicastPacketsSent = 0; m->MulticastPacketsSent = 0; m->RemoteSubnet = 0; @@ -14309,7 +14422,7 @@ mDNSexport mStatus mDNS_Init(mDNS *const m, mDNS_PlatformSupport *const p, for (slot = 0; slot < CACHE_HASH_SLOTS; slot++) { m->rrcache_hash[slot] = mDNSNULL; - m->rrcache_nextcheck[slot] = timenow + 0x78000000;; + m->rrcache_nextcheck[slot] = timenow + FutureTime;; } mDNS_GrowCache_internal(m, rrcachestorage, rrcachesize); @@ -14335,8 +14448,8 @@ mDNSexport mStatus mDNS_Init(mDNS *const m, mDNS_PlatformSupport *const p, m->SuppressProbes = 0; #ifndef UNICAST_DISABLED - m->NextuDNSEvent = timenow + 0x78000000; - m->NextSRVUpdate = timenow + 0x78000000; + m->NextuDNSEvent = timenow + FutureTime; + m->NextSRVUpdate = timenow + FutureTime; m->DNSServers = mDNSNULL; @@ -14355,19 +14468,11 @@ mDNSexport mStatus mDNS_Init(mDNS *const m, mDNS_PlatformSupport *const p, m->WABBrowseQueriesCount = 0; m->WABLBrowseQueriesCount = 0; m->WABRegQueriesCount = 0; -#if TARGET_OS_EMBEDDED || TARGET_OS_WATCH - m->AutoTargetServices = 0; -#else m->AutoTargetServices = 1; -#endif -#if TARGET_OS_WATCH + +#if BONJOUR_ON_DEMAND 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 // NAT traversal fields m->LLQNAT.clientCallback = mDNSNULL; @@ -14375,7 +14480,7 @@ mDNSexport mStatus mDNS_Init(mDNS *const m, mDNS_PlatformSupport *const p, m->NATTraversals = mDNSNULL; m->CurrentNATTraversal = mDNSNULL; m->retryIntervalGetAddr = 0; // delta between time sent and retry - m->retryGetAddr = timenow + 0x78000000; // absolute time when we retry + m->retryGetAddr = timenow + FutureTime; // absolute time when we retry m->ExtAddress = zerov4Addr; m->PCPNonce[0] = mDNSRandom(-1); m->PCPNonce[1] = mDNSRandom(-1); @@ -14407,6 +14512,8 @@ mDNSexport mStatus mDNS_Init(mDNS *const m, mDNS_PlatformSupport *const p, m->SPSBrowseCallback = mDNSNULL; m->ProxyRecords = 0; + m->DNSPushServers = mDNSNULL; + m->DNSPushZones = mDNSNULL; #endif #if APPLE_OSX_mDNSResponder @@ -14422,6 +14529,17 @@ mDNSexport mStatus mDNS_Init(mDNS *const m, mDNS_PlatformSupport *const p, #endif + return(result); +} + +mDNSexport mStatus mDNS_Init(mDNS *const m, mDNS_PlatformSupport *const p, + CacheEntity *rrcachestorage, mDNSu32 rrcachesize, + mDNSBool AdvertiseLocalAddresses, mDNSCallback *Callback, void *Context) +{ + mStatus result = mDNS_InitStorage(m, p, rrcachestorage, rrcachesize, AdvertiseLocalAddresses, Callback, Context); + if (result != mStatus_NoError) + return(result); + result = mDNSPlatformInit(m); #ifndef UNICAST_DISABLED @@ -14471,7 +14589,8 @@ mDNSlocal void PurgeOrReconfirmCacheRecord(mDNS *const m, CacheRecord *cr, const mDNSBool purge = cr->resrec.RecordType == kDNSRecordTypePacketNegative || cr->resrec.rrtype == kDNSType_A || cr->resrec.rrtype == kDNSType_AAAA || - cr->resrec.rrtype == kDNSType_SRV; + cr->resrec.rrtype == kDNSType_SRV || + cr->resrec.rrtype == kDNSType_CNAME; (void) lameduck; (void) ptr; @@ -14494,8 +14613,7 @@ mDNSlocal void PurgeOrReconfirmCacheRecord(mDNS *const m, CacheRecord *cr, const mDNSlocal void mDNS_PurgeForQuestion(mDNS *const m, DNSQuestion *q) { - const mDNSu32 slot = HashSlot(&q->qname); - CacheGroup *const cg = CacheGroupForName(m, slot, q->qnamehash, &q->qname); + CacheGroup *const cg = CacheGroupForName(m, q->qnamehash, &q->qname); CacheRecord *rp; mDNSu8 validatingResponse = 0; @@ -14530,8 +14648,7 @@ mDNSlocal void mDNS_PurgeForQuestion(mDNS *const m, DNSQuestion *q) // them. mDNSlocal void CheckForDNSSECRecords(mDNS *const m, DNSQuestion *q) { - const mDNSu32 slot = HashSlot(&q->qname); - CacheGroup *const cg = CacheGroupForName(m, slot, q->qnamehash, &q->qname); + CacheGroup *const cg = CacheGroupForName(m, q->qnamehash, &q->qname); CacheRecord *rp; for (rp = cg ? cg->members : mDNSNULL; rp; rp = rp->next) @@ -14554,8 +14671,7 @@ mDNSlocal void CheckForDNSSECRecords(mDNS *const m, DNSQuestion *q) mDNSexport mDNSBool mDNS_CheckForCacheRecord(mDNS *const m, DNSQuestion *q, mDNSu16 qtype) { DNSQuestion question; - const mDNSu32 slot = HashSlot(&q->qname); - CacheGroup *const cg = CacheGroupForName(m, slot, q->qnamehash, &q->qname); + CacheGroup *const cg = CacheGroupForName(m, q->qnamehash, &q->qname); CacheRecord *rp; // Create an identical question but with qtype @@ -14633,6 +14749,23 @@ mDNSlocal void SetConfigState(mDNS *const m, mDNSBool delete) } } +mDNSlocal void SetDynDNSHostNameIfChanged(mDNS *const m, domainname *const fqdn) +{ + // Did our FQDN change? + if (!SameDomainName(fqdn, &m->FQDN)) + { + if (m->FQDN.c[0]) mDNS_RemoveDynDNSHostName(m, &m->FQDN); + + AssignDomainName(&m->FQDN, fqdn); + + if (m->FQDN.c[0]) + { + mDNSPlatformDynDNSHostNameStatusChanged(&m->FQDN, 1); + mDNS_AddDynDNSHostName(m, &m->FQDN, DynDNSHostNameCallback, mDNSNULL); + } + } +} + mDNSexport mStatus uDNS_SetupDNSConfig(mDNS *const m) { mDNSu32 slot; @@ -14661,8 +14794,9 @@ mDNSexport mStatus uDNS_SetupDNSConfig(mDNS *const m) // hence we are ready to ack the configuration as this is the last call to mDNSPlatformSetConfig // for the dns configuration change notification. SetConfigState(m, mDNStrue); - if (!mDNSPlatformSetDNSConfig(m, mDNStrue, mDNSfalse, &fqdn, mDNSNULL, mDNSNULL, mDNStrue)) + if (!mDNSPlatformSetDNSConfig(mDNStrue, mDNSfalse, &fqdn, mDNSNULL, mDNSNULL, mDNStrue)) { + SetDynDNSHostNameIfChanged(m, &fqdn); SetConfigState(m, mDNSfalse); mDNS_Unlock(m); LogInfo("uDNS_SetupDNSConfig: No configuration change"); @@ -14716,6 +14850,9 @@ mDNSexport mStatus uDNS_SetupDNSConfig(mDNS *const m) // cache records and as the resGroupID is different, you can't use the cache record from the scoped DNSServer to answer the // non-scoped question and vice versa. // +#if USE_DNS64 + DNS64RestartQuestions(m); +#endif for (q = m->Questions; q; q=q->next) { if (!mDNSOpaque16IsZero(q->TargetQID)) @@ -14730,21 +14867,10 @@ mDNSexport mStatus uDNS_SetupDNSConfig(mDNS *const m) if (t != s) { mDNSBool old, new; - mDNSIPPort tport, sport; - - if (t) - tport = t->port; - else - tport = zeroIPPort; - - if (s) - sport = s->port; - else - sport = zeroIPPort; // If DNS Server for this question has changed, reactivate it LogInfo("uDNS_SetupDNSConfig: Updating DNS Server from %#a:%d (%##s) to %#a:%d (%##s) for question %##s (%s) (scope:%p)", - t ? &t->addr : mDNSNULL, mDNSVal16(tport), t ? t->domain.c : (mDNSu8*)"", - s ? &s->addr : mDNSNULL, mDNSVal16(sport), s ? s->domain.c : (mDNSu8*)"", + t ? &t->addr : mDNSNULL, mDNSVal16(t ? t->port : zeroIPPort), t ? t->domain.c : (mDNSu8*)"", + s ? &s->addr : mDNSNULL, mDNSVal16(s ? s->port : zeroIPPort), s ? s->domain.c : (mDNSu8*)"", q->qname.c, DNSTypeName(q->qtype), q->InterfaceID); old = q->SuppressQuery; @@ -14793,9 +14919,8 @@ 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 : zp), q->DuplicateOf, q->SuppressUnusable); + q, q->qname.c, DNSTypeName(q->qtype), t ? &t->addr : mDNSNULL, mDNSVal16(t ? t->port : zeroIPPort), q->DuplicateOf, q->SuppressUnusable); for (qptr = q->next ; qptr; qptr = qptr->next) if (qptr->DuplicateOf == q) { qptr->validDNSServers = q->validDNSServers; qptr->qDNSServer = q->qDNSServer; } } @@ -14851,6 +14976,14 @@ mDNSexport mStatus uDNS_SetupDNSConfig(mDNS *const m) PurgeOrReconfirmCacheRecord(m, cr, ptr, mDNSfalse); } } + + // If a cache record's DNSServer pointer is NULL, but its active question got a DNSServer in this DNS configuration + // update, then use its DNSServer. This way, the active question and its duplicates don't miss out on RMV events. + if (!cr->resrec.rDNSServer && cr->CRActiveQuestion && cr->CRActiveQuestion->qDNSServer) + { + cr->resrec.rDNSServer = cr->CRActiveQuestion->qDNSServer; + LogInfo("uDNS_SetupDNSConfig: Using active question's DNS server %#a for cache record %s", &cr->resrec.rDNSServer->addr, CRDisplayString(m, cr)); + } } while (*p) @@ -14881,9 +15014,9 @@ mDNSexport mStatus uDNS_SetupDNSConfig(mDNS *const m) if (qptr->qDNSServer == ptr) { - LogMsg("uDNS_SetupDNSConfig: ERROR!! Cache Record %s Active question %##s (%s) (scope:%p) poining to DNSServer Address %#a" + LogMsg("uDNS_SetupDNSConfig: ERROR!! Cache Record %s Active question %##s (%s) (scope:%p) pointing to DNSServer Address %#a" " to be freed", CRDisplayString(m, cr), qptr->qname.c, DNSTypeName(qptr->qtype), qptr->InterfaceID, &ptr->addr); - qptr->validDNSServers = zeroOpaque64; + qptr->validDNSServers = zeroOpaque128; qptr->qDNSServer = mDNSNULL; cr->resrec.rDNSServer = mDNSNULL; } @@ -14891,7 +15024,7 @@ mDNSexport mStatus uDNS_SetupDNSConfig(mDNS *const m) { LogInfo("uDNS_SetupDNSConfig: Cache Record %s, Active question %##s (%s) (scope:%p), pointing to DNSServer %#a (to be deleted)," " resetting to question's DNSServer Address %#a", CRDisplayString(m, cr), qptr->qname.c, DNSTypeName(qptr->qtype), - qptr->InterfaceID, &ptr->addr, (qptr->qDNSServer ? &qptr->qDNSServer->addr : mDNSNULL)); + qptr->InterfaceID, &ptr->addr, (qptr->qDNSServer) ? &qptr->qDNSServer->addr : mDNSNULL); cr->resrec.rDNSServer = qptr->qDNSServer; } } @@ -14938,19 +15071,7 @@ mDNSexport mStatus uDNS_SetupDNSConfig(mDNS *const m) RestartRecordGetZoneData(m); } - // Did our FQDN change? - if (!SameDomainName(&fqdn, &m->FQDN)) - { - if (m->FQDN.c[0]) mDNS_RemoveDynDNSHostName(m, &m->FQDN); - - AssignDomainName(&m->FQDN, &fqdn); - - if (m->FQDN.c[0]) - { - mDNSPlatformDynDNSHostNameStatusChanged(&m->FQDN, 1); - mDNS_AddDynDNSHostName(m, &m->FQDN, DynDNSHostNameCallback, mDNSNULL); - } - } + SetDynDNSHostNameIfChanged(m, &fqdn); mDNS_Unlock(m); @@ -14958,7 +15079,7 @@ mDNSexport mStatus uDNS_SetupDNSConfig(mDNS *const m) v4 = v6 = r = zeroAddr; v4.type = r.type = mDNSAddrType_IPv4; - if (mDNSPlatformGetPrimaryInterface(m, &v4, &v6, &r) == mStatus_NoError && !mDNSv4AddressIsLinkLocal(&v4.ip.v4)) + if (mDNSPlatformGetPrimaryInterface(&v4, &v6, &r) == mStatus_NoError && !mDNSv4AddressIsLinkLocal(&v4.ip.v4)) { mDNS_SetPrimaryInterfaceInfo(m, !mDNSIPv4AddressIsZero(v4.ip.v4) ? &v4 : mDNSNULL, @@ -15144,3 +15265,7 @@ mDNSexport void mDNS_FinalExit(mDNS *const m) LogInfo("mDNS_FinalExit: done"); } + +#ifdef UNIT_TEST +#include "../unittests/mdns_ut.c" +#endif diff --git a/usr/src/cmd/cmd-inet/usr.lib/mdnsd/mDNSDebug.h b/usr/src/contrib/mDNSResponder/mDNSCore/mDNSDebug.h index 7bd783c568..68a696ef8a 100644..100755 --- a/usr/src/cmd/cmd-inet/usr.lib/mdnsd/mDNSDebug.h +++ b/usr/src/contrib/mDNSResponder/mDNSCore/mDNSDebug.h @@ -87,9 +87,9 @@ extern "C" { #define MDNS_GNU_VA_ARGS 0 #define MDNS_HAS_VA_ARG_MACROS 1 #else - #define MDNS_C99_VA_ARGS 1 + #define MDNS_C99_VA_ARGS 0 #define MDNS_GNU_VA_ARGS 0 - #define MDNS_HAS_VA_ARG_MACROS 1 + #define MDNS_HAS_VA_ARG_MACROS 0 #endif #if (MDNS_HAS_VA_ARG_MACROS) diff --git a/usr/src/cmd/cmd-inet/usr.lib/mdnsd/mDNSEmbeddedAPI.h b/usr/src/contrib/mDNSResponder/mDNSCore/mDNSEmbeddedAPI.h index 0b3e646423..cd52c20e53 100644..100755 --- a/usr/src/cmd/cmd-inet/usr.lib/mdnsd/mDNSEmbeddedAPI.h +++ b/usr/src/contrib/mDNSResponder/mDNSCore/mDNSEmbeddedAPI.h @@ -96,9 +96,9 @@ extern "C" { #ifdef LIMITED_RESOURCES_TARGET // Don't support jumbo frames // 40 (IPv6 header) + 8 (UDP header) + 12 (DNS message header) + 1440 (DNS message body) = 1500 total -#define AbsoluteMaxDNSMessageData 1440 +#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 +#define MaximumRDSize 264 #endif // *************************************************************************** @@ -276,8 +276,6 @@ typedef struct mDNSInterfaceID_dummystruct { void *dummy; } *mDNSInterfaceID; // find you get code that doesn't work consistently on big-endian and little-endian machines. #if defined(_WIN32) #pragma pack(push,2) -#elif !defined(__GNUC__) - #pragma pack(1) #endif typedef union { mDNSu8 b[ 2]; mDNSu16 NotAnInteger; } mDNSOpaque16; typedef union { mDNSu8 b[ 4]; mDNSu32 NotAnInteger; } mDNSOpaque32; @@ -286,8 +284,6 @@ typedef union { mDNSu8 b[ 8]; mDNSu16 w[4]; mDNSu32 l[2]; } mDNSOpaque64; typedef union { mDNSu8 b[16]; mDNSu16 w[8]; mDNSu32 l[4]; } mDNSOpaque128; #if defined(_WIN32) #pragma pack(pop) -#elif !defined(__GNUC__) - #pragma pack() #endif typedef mDNSOpaque16 mDNSIPPort; // An IP port is a two-byte opaque identifier (not an integer) @@ -301,20 +297,25 @@ typedef mDNSOpaque48 mDNSEthAddr; // An Ethernet address is a six-byte opa #define bit_clr_opaque64(op64, index) (op64.l[((index))/(sizeof(mDNSu32) * mDNSNBBY)] &= ~(1 << ((index) % (sizeof(mDNSu32) * mDNSNBBY)))) #define bit_get_opaque64(op64, index) (op64.l[((index))/(sizeof(mDNSu32) * mDNSNBBY)] & (1 << ((index) % (sizeof(mDNSu32) * mDNSNBBY)))) -enum +// Bit operations for opaque 128 bit quantity. Uses the 32 bit quantity(l[4]) to set and clear bits +#define bit_set_opaque128(op128, index) (op128.l[((index))/(sizeof(mDNSu32) * mDNSNBBY)] |= (1 << ((index) % (sizeof(mDNSu32) * mDNSNBBY)))) +#define bit_clr_opaque128(op128, index) (op128.l[((index))/(sizeof(mDNSu32) * mDNSNBBY)] &= ~(1 << ((index) % (sizeof(mDNSu32) * mDNSNBBY)))) +#define bit_get_opaque128(op128, index) (op128.l[((index))/(sizeof(mDNSu32) * mDNSNBBY)] & (1 << ((index) % (sizeof(mDNSu32) * mDNSNBBY)))) + +typedef enum { mDNSAddrType_None = 0, mDNSAddrType_IPv4 = 4, mDNSAddrType_IPv6 = 6, mDNSAddrType_Unknown = ~0 // Special marker value used in known answer list recording -}; +} mDNSAddr_Type; -enum +typedef enum { mDNSTransport_None = 0, mDNSTransport_UDP = 1, mDNSTransport_TCP = 2 -}; +} mDNSTransport_Type; typedef struct { @@ -368,7 +369,8 @@ enum mStatus_NoRouter = -65566, mStatus_PollingMode = -65567, mStatus_Timeout = -65568, - // -65568 to -65786 currently unused; available for allocation + mStatus_HostUnreachErr = -65569, + // -65570 to -65786 currently unused; available for allocation // tcp connection status mStatus_ConnPending = -65787, @@ -485,7 +487,7 @@ typedef struct UDPSocket_struct UDPSocket; #define mDNS_numPrereqs numAnswers #define mDNS_numUpdates numAuthorities -typedef packedstruct +typedef struct { mDNSOpaque16 id; mDNSOpaque16 flags; @@ -502,7 +504,7 @@ typedef packedstruct #define AbsoluteMaxDNSMessageData 8940 #endif #define NormalMaxDNSMessageData 1440 -typedef packedstruct +typedef struct { DNSMessageHeader h; // Note: Size 12 bytes mDNSu8 data[AbsoluteMaxDNSMessageData]; // 40 (IPv6) + 8 (UDP) + 12 (DNS header) + 8940 (data) = 9000 @@ -620,7 +622,7 @@ typedef packedstruct mDNSu16 checksum; } UDPHeader; // 8 bytes; IP protocol type 0x11 -typedef packedstruct +typedef struct { mDNSu8 type; // 0x87 == Neighbor Solicitation, 0x88 == Neighbor Advertisement mDNSu8 code; @@ -725,7 +727,7 @@ typedef packedstruct // Bit 6 (value 0x40) is set for answer records; clear for authority/additional records // Bit 5 (value 0x20) is set for records received with the kDNSClass_UniqueRRSet -enum +typedef enum { kDNSRecordTypeUnregistered = 0x00, // Not currently in any list kDNSRecordTypeDeregistering = 0x01, // Shared record about to announce its departure and leave the list @@ -753,7 +755,7 @@ enum kDNSRecordTypePacketNegative = 0xF0, // Pseudo-RR generated to cache non-existence results like NXDomain kDNSRecordTypePacketUniqueMask = 0x10 // True for PacketAddUnique, PacketAnsUnique, PacketAuthUnique, kDNSRecordTypePacketNegative -}; +} kDNSRecordTypes; typedef packedstruct { mDNSu16 priority; mDNSu16 weight; mDNSIPPort port; domainname target; } rdataSRV; typedef packedstruct { mDNSu16 preference; domainname exchange; } rdataMX; @@ -812,14 +814,14 @@ typedef struct TrustAnchor struct TrustAnchor *next; int digestLen; mDNSu32 validFrom; - mDNSu32 validUntil; + mDNSu32 validUntil; domainname zone; rdataDS rds; } TrustAnchor; //size of rdataRRSIG excluding signerName and signature (which are variable fields) #define RRSIG_FIXED_SIZE 18 -typedef packedstruct +typedef struct { mDNSu16 typeCovered; mDNSu8 alg; @@ -828,7 +830,7 @@ typedef packedstruct mDNSu32 sigExpireTime; mDNSu32 sigInceptTime; mDNSu16 keyTag; - mDNSu8 *signerName; + mDNSu8 signerName[1]; // signerName is a dynamically-sized array // mDNSu8 *signature } rdataRRSig; @@ -879,10 +881,10 @@ typedef packedstruct // For example, SHA-1 hash of 20 bytes will be encoded as 20/5 * 8 = 32 base32 // bytes. For a max domain name size of 255 bytes of base32 encoding : (255/8)*5 // is the max hash length possible. -#define NSEC3_MAX_HASH_LEN 155 +#define NSEC3_MAX_HASH_LEN 155 // In NSEC3, the names are hashed and stored in the first label and hence cannot exceed label // size. -#define NSEC3_MAX_B32_LEN MAX_DOMAIN_LABEL +#define NSEC3_MAX_B32_LEN MAX_DOMAIN_LABEL // We define it here instead of dnssec.h so that these values can be used // in files without bringing in all of dnssec.h unnecessarily. @@ -900,9 +902,9 @@ typedef enum typedef enum { - platform_OSX = 1, // OSX Platform - platform_iOS, // iOS Platform - platform_Atv, // Atv Platform + platform_OSX = 1, // OSX Platform + platform_iOS, // iOS Platform + platform_Atv, // Atv Platform platform_NonApple // Non-Apple (Windows, POSIX) Platform } Platform_t; @@ -913,7 +915,7 @@ typedef enum #define kDNSOpt_Lease 2 #define kDNSOpt_NSID 3 #define kDNSOpt_Owner 4 -#define kDNSOpt_Trace 65001 // 65001-65534 Reserved for Local/Experimental Use +#define kDNSOpt_Trace 65001 // 65001-65534 Reserved for Local/Experimental Use typedef struct { @@ -941,7 +943,7 @@ typedef struct } TracerOptData; // Note: rdataOPT format may be repeated an arbitrary number of times in a single resource record -typedef packedstruct +typedef struct { mDNSu16 opt; mDNSu16 optlen; @@ -1185,7 +1187,7 @@ typedef enum PCPResult_ExcesRemotePeer = 13 } PCPResult_t; -typedef packedstruct +typedef struct { mDNSu8 version; mDNSu8 opCode; @@ -1200,7 +1202,7 @@ typedef packedstruct mDNSv6Addr extAddress; } PCPMapRequest; -typedef packedstruct +typedef struct { mDNSu8 version; mDNSu8 opCode; @@ -1311,14 +1313,6 @@ struct NATTraversalInfo_struct enum { - DNSServer_Untested = 0, - DNSServer_Passed = 1, - DNSServer_Failed = 2, - DNSServer_Disabled = 3 -}; - -enum -{ DNSServer_FlagDelete = 0x1, DNSServer_FlagNew = 0x2, #if APPLE_OSX_mDNSResponder @@ -1346,8 +1340,9 @@ enum { kScopeNone = 0, // DNS server used by unscoped questions kScopeInterfaceID = 1, // Scoped DNS server used only by scoped questions - kScopeServiceID = 2 // Service specific DNS server used only by questions + kScopeServiceID = 2, // Service specific DNS server used only by questions // have a matching serviceID + kScopesMaxCount = 3 // Max count for scopes enum }; // Note: DNSSECAware is set if we are able to get a valid response to @@ -1364,22 +1359,19 @@ typedef struct DNSServer mDNSs32 serviceID; mDNSAddr addr; mDNSIPPort port; - mDNSOpaque16 testid; mDNSu32 flags; // Set when we're planning to delete this from the list - mDNSu32 teststate; // Have we sent bug-detection query to this server? - mDNSs32 lasttest; // Time we sent last bug-detection query to this server domainname domain; // name->server matching for "split dns" mDNSs32 penaltyTime; // amount of time this server is penalized mDNSu32 scoped; // See the scoped enum above mDNSu32 timeout; // timeout value for questions - mDNSBool cellIntf; // Resolver from Cellular Interface ? mDNSu16 resGroupID; // ID of the resolver group that contains this DNSServer + mDNSu8 retransDO; // Total Retransmissions for queries sent with DO option + mDNSBool cellIntf; // Resolver from Cellular Interface? mDNSBool req_A; // If set, send v4 query (DNSConfig allows A queries) mDNSBool req_AAAA; // If set, send v6 query (DNSConfig allows AAAA queries) mDNSBool req_DO; // If set, okay to send DNSSEC queries (EDNS DO bit is supported) - mDNSBool retransDO; // Total Retransmissions for queries sent with DO option - mDNSBool DNSSECAware; // set if we are able to receive a response to a request - // sent with DO option. + mDNSBool DNSSECAware; // Set if we are able to receive a response to a request sent with DO option. + mDNSBool isExpensive; // True if the interface to this server is expensive. } DNSServer; typedef struct @@ -1393,9 +1385,9 @@ typedef struct struct ResourceRecord_struct { - mDNSu8 RecordType; // See enum above - mDNSu16 rrtype; - mDNSu16 rrclass; + mDNSu8 RecordType; // See kDNSRecordTypes enum. + mDNSu16 rrtype; // See DNS_TypeValues enum. + mDNSu16 rrclass; // See DNS_ClassValues enum. mDNSu32 rroriginalttl; // In seconds mDNSu16 rdlength; // Size of the raw rdata, in bytes, in the on-the-wire format // (In-memory storage may be larger, for structures containing 'holes', like SOA) @@ -1608,10 +1600,13 @@ struct AuthRecord_struct // Everywhere else in the code, the determination of whether a question is unicast is made by checking to see if TargetQID is nonzero. #define AuthRecord_uDNS(R) ((R)->resrec.InterfaceID == mDNSInterface_Any && !(R)->ForceMCast && !IsLocalDomain((R)->resrec.name)) #define Question_uDNS(Q) ((Q)->InterfaceID == mDNSInterface_Unicast || (Q)->ProxyQuestion || \ - ((Q)->InterfaceID != mDNSInterface_LocalOnly && (Q)->InterfaceID != mDNSInterface_P2P && !(Q)->ForceMCast && !IsLocalDomain(&(Q)->qname))) + ((Q)->InterfaceID != mDNSInterface_LocalOnly && (Q)->InterfaceID != mDNSInterface_P2P && (Q)->InterfaceID != mDNSInterface_BLE && !(Q)->ForceMCast && !IsLocalDomain(&(Q)->qname))) +// AuthRecordLocalOnly records are registered using mDNSInterface_LocalOnly and +// AuthRecordP2P records are created by D2DServiceFound events. Both record types are kept on the same list. #define RRLocalOnly(rr) ((rr)->ARType == AuthRecordLocalOnly || (rr)->ARType == AuthRecordP2P) +// All other auth records, not including those defined as RRLocalOnly(). #define RRAny(rr) ((rr)->ARType == AuthRecordAny || (rr)->ARType == AuthRecordAnyIncludeP2P || (rr)->ARType == AuthRecordAnyIncludeAWDL || (rr)->ARType == AuthRecordAnyIncludeAWDLandP2P) // Question (A or AAAA) that is suppressed currently because IPv4 or IPv6 address @@ -1649,12 +1644,6 @@ struct CacheRecord_struct mDNSu8 UnansweredQueries; // Number of times we've issued a query for this record without getting an answer mDNSu8 CRDNSSECQuestion; // Set to 1 if this was created in response to a DNSSEC question mDNSOpaque16 responseFlags; // Second 16 bit in the DNS response -#if ENABLE_MULTI_PACKET_QUERY_SNOOPING - mDNSu32 MPUnansweredQ; // Multi-packet query handling: Number of times we've seen a query for this record - mDNSs32 MPLastUnansweredQT; // Multi-packet query handling: Last time we incremented MPUnansweredQ - mDNSu32 MPUnansweredKA; // Multi-packet query handling: Number of times we've seen this record in a KA list - mDNSBool MPExpectingKA; // Multi-packet query handling: Set when we increment MPUnansweredQ; allows one KA -#endif CacheRecord *NextInCFList; // Set if this is in the list of records we just received with the cache flush bit set CacheRecord *nsec; // NSEC records needed for non-existence proofs CacheRecord *soa; // SOA record to return for proxy questions @@ -1745,7 +1734,7 @@ struct ServiceRecordSet_struct mDNSu32 NumSubTypes; AuthRecord *SubTypes; const mDNSu8 *AnonData; - mDNSu32 flags; // saved for subsequent calls to mDNS_RegisterService() if records + mDNSu32 flags; // saved for subsequent calls to mDNS_RegisterService() if records // need to be re-registered. AuthRecord RR_ADV; // e.g. _services._dns-sd._udp.local. PTR _printer._tcp.local. AuthRecord RR_PTR; // e.g. _printer._tcp.local. PTR Name._printer._tcp.local. @@ -1806,6 +1795,25 @@ enum enum { NoAnswer_Normal = 0, NoAnswer_Suspended = 1, NoAnswer_Fail = 2 }; +// DNS Push Notification +typedef enum +{ + DNSPUSH_NOERROR = 0, + DNSPUSH_FORMERR = 1, + DNSPUSH_SERVFAIL = 2, + DNSPUSH_NOTIMP = 4, + DNSPUSH_REFUSED = 5 +} DNSPUSH_ErrorCode; + +typedef enum { + DNSPUSH_INIT = 1, + DNSPUSH_NOSERVER = 2, + DNSPUSH_SERVERFOUND = 3, + DNSPUSH_ESTABLISHED = 4 +} DNSPush_State; + + + #define HMAC_LEN 64 #define HMAC_IPAD 0x36 #define HMAC_OPAD 0x5c @@ -1862,7 +1870,7 @@ typedef enum { DNSSECValNotRequired = 0, DNSSECValRequired, DNSSECValInProgress, // ValidationRequired can be set to the following values: // -// SECURE validation is set to determine whether something is secure or bogus +// SECURE validation is set to determine whether something is secure or bogus // INSECURE validation is set internally by dnssec code to indicate that it is currently proving something // is insecure #define DNSSEC_VALIDATION_NONE 0x00 @@ -1885,10 +1893,12 @@ typedef enum { DNSSECValNotRequired = 0, DNSSECValRequired, DNSSECValInProgress, (rr)->RecordType != kDNSRecordTypePacketNegative && \ (rr)->rrtype == kDNSType_CNAME) -// RFC 4122 defines it to be 16 bytes +// RFC 4122 defines it to be 16 bytes #define UUID_SIZE 16 -#if TARGET_OS_EMBEDDED +#define AWD_METRICS (USE_AWD && TARGET_OS_EMBEDDED) + +#if AWD_METRICS typedef struct { domainname * originalQName; // Name of original A/AAAA record if this question is for a CNAME record. @@ -1899,6 +1909,18 @@ typedef struct } uDNSMetrics; #endif +// DNS64 code is only for iOS, which is currently the only Apple OS that supports DNS proxy network extensions. +#define USE_DNS64 (HAVE_DNS64 && TARGET_OS_IOS) + +#if USE_DNS64 +#include "DNS64State.h" +#endif + +#if TARGET_OS_EMBEDDED +extern mDNSu32 curr_num_regservices; // tracks the current number of services registered +extern mDNSu32 max_num_regservices; // tracks the max number of simultaneous services registered by the device +#endif + struct DNSQuestion_struct { // Internal state fields. These are used internally by mDNSCore; the client layer needn't be concerned with them. @@ -1927,7 +1949,7 @@ struct DNSQuestion_struct DupSuppressInfo DupSuppress[DupSuppressInfoSize]; mDNSInterfaceID SendQNow; // The interface this query is being sent on right now mDNSBool SendOnAll; // Set if we're sending this question on all active interfaces - mDNSBool CachedAnswerNeedsUpdate; // See SendQueries(). Set if we're sending this question + mDNSBool CachedAnswerNeedsUpdate; // See SendQueries(). Set if we're sending this question // because a cached answer needs to be refreshed. mDNSu32 RequestUnicast; // Non-zero if we want to send query with kDNSQClass_UnicastResponse bit set mDNSs32 LastQTxTime; // Last time this Q was sent on one (but not necessarily all) interfaces @@ -1951,7 +1973,7 @@ struct DNSQuestion_struct // |-> DNS Configuration related fields used in uDNS (Subset of Wide Area/Unicast fields) DNSServer *qDNSServer; // Caching server for this query (in the absence of an SRV saying otherwise) - mDNSOpaque64 validDNSServers; // Valid DNSServers for this question + mDNSOpaque128 validDNSServers; // Valid DNSServers for this question mDNSu16 noServerResponse; // At least one server did not respond. mDNSu16 triedAllServersOnce; // Tried all DNS servers once mDNSu8 unansweredQueries; // The number of unanswered queries to this server @@ -1973,6 +1995,12 @@ struct DNSQuestion_struct // for TCP: there is some ambiguity in the use of this variable, but in general, it is // the number of TCP/TLS connection attempts for this LLQ state, or // the number of packets sent for this TCP/TLS connection + + // DNS Push Notification fields. These fields are only meaningful when LongLived flag is set + DNSPush_State dnsPushState; // The state of the DNS push notification negotiation + mDNSAddr dnsPushServerAddr; // Address of the system acting as the DNS Push Server + mDNSIPPort dnsPushServerPort; // Port on which the DNS Push Server is being advertised. + mDNSOpaque64 id; // DNS Proxy fields @@ -1980,7 +2008,7 @@ struct DNSQuestion_struct // till we populate in the cache mDNSBool DisallowPID; // Is the query allowed for the "PID" that we are sending on behalf of ? mDNSs32 ServiceID; // Service identifier to match against the DNS server - + // Client API fields: The client must set up these fields *before* calling mDNS_StartQuery() mDNSInterfaceID InterfaceID; // Non-zero if you want to issue queries only on a single specific IP interface mDNSu32 flags; // flags from original DNSService*() API request. @@ -1995,8 +2023,6 @@ struct DNSQuestion_struct mDNSBool ForceMCast; // Set by client to force mDNS query, even for apparently uDNS names mDNSBool ReturnIntermed; // Set by client to request callbacks for intermediate CNAME/NXDOMAIN results mDNSBool SuppressUnusable; // Set by client to suppress unusable queries to be sent on the wire - mDNSBool DenyOnCellInterface; // Set by client to suppress uDNS queries on cellular interface - mDNSBool DenyOnExpInterface; // Set by client to suppress uDNS queries on expensive interface mDNSu8 RetryWithSearchDomains; // Retry with search domains if there is no entry in the cache or AuthRecords mDNSu8 TimeoutQuestion; // Timeout this question if there is no reply in configured time mDNSu8 WakeOnResolve; // Send wakeup on resolve @@ -2016,45 +2042,12 @@ struct DNSQuestion_struct #if TARGET_OS_EMBEDDED uDNSMetrics metrics; // Data used for collecting unicast DNS query metrics. #endif +#if USE_DNS64 + DNS64 dns64; // DNS64 state for performing IPv6 address synthesis on networks with NAT64. +#endif }; -typedef struct -{ - // Client API fields: The client must set up name and InterfaceID *before* calling mDNS_StartResolveService() - // When the callback is invoked, ip, port, TXTlen and TXTinfo will have been filled in with the results learned from the network. - domainname name; - mDNSInterfaceID InterfaceID; // ID of the interface the response was received on - mDNSAddr ip; // Remote (destination) IP address where this service can be accessed - mDNSIPPort port; // Port where this service can be accessed - mDNSu16 TXTlen; - mDNSu8 TXTinfo[2048]; // Additional demultiplexing information (e.g. LPR queue name) -} ServiceInfo; - -// Note: Within an mDNSServiceInfoQueryCallback mDNS all API calls are legal except mDNS_Init(), mDNS_Exit(), mDNS_Execute() -typedef struct ServiceInfoQuery_struct ServiceInfoQuery; -typedef void mDNSServiceInfoQueryCallback (mDNS *const m, ServiceInfoQuery *query); -struct ServiceInfoQuery_struct -{ - // Internal state fields. These are used internally by mDNSCore; the client layer needn't be concerned with them. - // No fields need to be set up by the client prior to calling mDNS_StartResolveService(); - // all required data is passed as parameters to that function. - // The ServiceInfoQuery structure memory is working storage for mDNSCore to discover the requested information - // and place it in the ServiceInfo structure. After the client has called mDNS_StopResolveService(), it may - // dispose of the ServiceInfoQuery structure while retaining the results in the ServiceInfo structure. - DNSQuestion qSRV; - DNSQuestion qTXT; - DNSQuestion qAv4; - DNSQuestion qAv6; - mDNSu8 GotSRV; - mDNSu8 GotTXT; - mDNSu8 GotADD; - mDNSu32 Answers; - ServiceInfo *info; - mDNSServiceInfoQueryCallback *ServiceInfoQueryCallback; - void *ServiceInfoQueryContext; -}; - -typedef enum { ZoneServiceUpdate, ZoneServiceQuery, ZoneServiceLLQ } ZoneService; +typedef enum { ZoneServiceUpdate, ZoneServiceQuery, ZoneServiceLLQ, ZoneServiceDNSPush } ZoneService; typedef void ZoneDataCallback (mDNS *const m, mStatus err, const ZoneData *result); @@ -2162,7 +2155,7 @@ struct NetworkInterfaceInfo_struct 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. + // to Bonjour queries. Generally true for an interface }; #define SLE_DELETE 0x00000001 @@ -2280,6 +2273,30 @@ typedef struct extern void LogMDNSStatistics(mDNS *const m); +typedef struct mDNS_DNSPushNotificationServer DNSPushNotificationServer; +typedef struct mDNS_DNSPushNotificationZone DNSPushNotificationZone; + +struct mDNS_DNSPushNotificationServer +{ + mDNSAddr serverAddr; // Server Address + tcpInfo_t *connection; // TCP Connection pointer + mDNSu32 numberOfQuestions; // Number of questions for this server + DNSPushNotificationServer *next; +} ; + +struct mDNS_DNSPushNotificationZone +{ + domainname zoneName; + DNSPushNotificationServer *servers; // DNS Push Notification Servers for this zone + mDNSu32 numberOfQuestions; // Number of questions for this zone + DNSPushNotificationZone *next; +} ; + + +// Time constant (~= 260 hours ~= 10 days and 21 hours) used to set +// various time values to a point well into the future. +#define FutureTime 0x38000000 + struct mDNS_struct { // Internal state fields. These hold the main internal state of mDNSCore; @@ -2324,6 +2341,11 @@ struct mDNS_struct mDNSs32 NextScheduledNATOp; // Next time to send NAT-traversal packets mDNSs32 NextScheduledSPS; // Next time to purge expiring Sleep Proxy records mDNSs32 NextScheduledKA; // Next time to send Keepalive packets (SPS) +#if BONJOUR_ON_DEMAND + mDNSs32 NextBonjourDisableTime; // Next time to leave multicast group if Bonjour on Demand is enabled + mDNSu8 BonjourEnabled; // Non zero if Bonjour is currently enabled by the Bonjour on Demand logic +#endif // BONJOUR_ON_DEMAND + mDNSs32 DelayConflictProcessing; // To prevent spurious confilcts due to stale packets on the wire/air. mDNSs32 RandomQueryDelay; // For de-synchronization of query packets on the wire mDNSu32 RandomReconfirmDelay; // For de-synchronization of reconfirmation queries on the wire mDNSs32 PktNum; // Unique sequence number assigned to each received packet @@ -2340,9 +2362,6 @@ struct mDNS_struct // during which underying platform layer should inhibit system sleep mDNSs32 TimeSlept; // Time we went to sleep. - mDNSs32 StatStartTime; // Time we started gathering statistics during this interval. - mDNSs32 NextStatLogTime; // Next time to log statistics. - mDNSs32 ActiveStatTime; // Total time awake/gathering statistics for this log period. mDNSs32 UnicastPacketsSent; // Number of unicast packets sent. mDNSs32 MulticastPacketsSent; // Number of multicast packets sent. mDNSs32 RemoteSubnet; // Multicast packets received from outside our subnet. @@ -2352,6 +2371,7 @@ struct mDNS_struct mDNSs32 NextScheduledStopTime; // Next time to stop a question + mDNSs32 NextBLEServiceTime; // Next time to call the BLE discovery management layer. Non zero when active. // These fields only required for mDNS Searcher... DNSQuestion *Questions; // List of all registered questions, active and inactive @@ -2388,7 +2408,7 @@ struct mDNS_struct mDNSs32 ProbeFailTime; mDNSu32 NumFailedProbes; mDNSs32 SuppressProbes; - Platform_t mDNS_plat; // Why is this here in the “only required for mDNS Responder” section? -- SC + 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 @@ -2438,11 +2458,15 @@ struct mDNS_struct mDNSBool SSDPWANPPPConnection; // whether we should send the SSDP query for WANIPConnection or WANPPPConnection mDNSIPPort UPnPRouterPort; // port we send discovery messages to mDNSIPPort UPnPSOAPPort; // port we send SOAP messages to - mDNSu8 *UPnPRouterURL; // router's URL string + char *UPnPRouterURL; // router's URL string mDNSBool UPnPWANPPPConnection; // whether we're using WANIPConnection or WANPPPConnection - mDNSu8 *UPnPSOAPURL; // router's SOAP control URL string - mDNSu8 *UPnPRouterAddressString; // holds both the router's address and port - mDNSu8 *UPnPSOAPAddressString; // holds both address and port for SOAP messages + char *UPnPSOAPURL; // router's SOAP control URL string + char *UPnPRouterAddressString; // holds both the router's address and port + char *UPnPSOAPAddressString; // holds both address and port for SOAP messages + + // DNS Push Notification fields + DNSPushNotificationServer *DNSPushServers; // DNS Push Notification Servers + DNSPushNotificationZone *DNSPushZones; // Sleep Proxy client fields AuthRecord *SPSRRSet; // To help the client keep track of the records registered with the sleep proxy @@ -2465,7 +2489,6 @@ struct mDNS_struct #if APPLE_OSX_mDNSResponder ClientTunnel *TunnelClients; - uuid_t asl_uuid; // uuid for ASL logging void *WCF; #endif // DNS Proxy fields @@ -2476,8 +2499,13 @@ struct mDNS_struct int notifyToken; 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. + +#if BONJOUR_ON_DEMAND + // Counters used in Bonjour on Demand logic. + 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. +#endif // BONJOUR_ON_DEMAND + DNSSECStatistics DNSSECStats; mDNSStatistics mDNSStats; @@ -2505,6 +2533,9 @@ extern const mDNSInterfaceID mDNSInterface_Unicast; // Special value extern const mDNSInterfaceID mDNSInterfaceMark; // Special value extern const mDNSInterfaceID mDNSInterface_P2P; // Special value extern const mDNSInterfaceID uDNSInterfaceMark; // Special value +extern const mDNSInterfaceID mDNSInterface_BLE; // Special value + +#define LocalOnlyOrP2PInterface(INTERFACE) ((INTERFACE == mDNSInterface_LocalOnly) || (INTERFACE == mDNSInterface_P2P) || (INTERFACE == mDNSInterface_BLE)) extern const mDNSIPPort DiscardPort; extern const mDNSIPPort SSHPort; @@ -2546,8 +2577,11 @@ extern const mDNSOpaque16 DNSSecQFlags; extern const mDNSOpaque16 ResponseFlags; extern const mDNSOpaque16 UpdateReqFlags; extern const mDNSOpaque16 UpdateRespFlags; +extern const mDNSOpaque16 SubscribeFlags; +extern const mDNSOpaque16 UnSubscribeFlags; extern const mDNSOpaque64 zeroOpaque64; +extern const mDNSOpaque128 zeroOpaque128; extern mDNSBool StrictUnicastOrdering; extern mDNSu8 NumUnicastDNSServers; @@ -2570,8 +2604,6 @@ extern mDNSu8 NumUnreachableDNSServers; #define mDNSinline static __inline #elif ((__GNUC__ > 2) || ((__GNUC__ == 2) && (__GNUC_MINOR__ >= 9))) #define mDNSinline static inline -#else - #define mDNSinline static inline #endif // If we're not doing inline functions, then this header needs to have the extern declarations @@ -2612,7 +2644,7 @@ mDNSinline mDNSOpaque16 mDNSOpaque16fromIntVal(mDNSu16 v) // Every client should call mDNS_Init, passing in storage for the mDNS object and the mDNS_PlatformSupport object. // // Clients that are only advertising services should use mDNS_Init_NoCache and mDNS_Init_ZeroCacheSize. -// Clients that plan to perform queries (mDNS_StartQuery, mDNS_StartBrowse, mDNS_StartResolveService, etc.) +// Clients that plan to perform queries (mDNS_StartQuery, mDNS_StartBrowse, etc.) // need to provide storage for the resource record cache, or the query calls will return 'mStatus_NoCache'. // The rrcachestorage parameter is the address of memory for the resource record cache, and // the rrcachesize parameter is the number of entries in the CacheRecord array passed in. @@ -2725,11 +2757,6 @@ typedef enum { mDNS_Dereg_normal, mDNS_Dereg_rapid, mDNS_Dereg_conflict, mDNS_De // mDNS_RegisterService is a single call to register the set of resource records associated with a given named service. // -// mDNS_StartResolveService is single call which is equivalent to multiple calls to mDNS_StartQuery, -// to find the IP address, port number, and demultiplexing information for a given named service. -// As with mDNS_StartQuery, it executes asynchronously, and calls the ServiceInfoQueryCallback when the answer is -// found. After the service is resolved, the client should call mDNS_StopResolveService to complete the transaction. -// The client can also call mDNS_StopResolveService at any time to abort the transaction. // // mDNS_AddRecordToService adds an additional record to a Service Record Set. This record may be deregistered // via mDNS_RemoveRecordFromService, or by deregistering the service. mDNS_RemoveRecordFromService is passed a @@ -2748,17 +2775,7 @@ typedef enum { mDNS_Dereg_normal, mDNS_Dereg_rapid, mDNS_Dereg_conflict, mDNS_De extern void mDNS_SetupResourceRecord(AuthRecord *rr, RData *RDataStorage, mDNSInterfaceID InterfaceID, mDNSu16 rrtype, mDNSu32 ttl, mDNSu8 RecordType, AuthRecType artype, mDNSRecordCallback Callback, void *Context); -// mDNS_RegisterService() flags parameter bit definitions. -// Note these are only defined to transfer the corresponding DNSServiceFlags settings into mDNSCore routines, -// since code in mDNSCore does not include the DNSServiceFlags definitions in dns_sd.h. -enum -{ - coreFlagIncludeP2P = 0x1, // include P2P interfaces when using mDNSInterface_Any - coreFlagIncludeAWDL = 0x2, // include AWDL interface when using mDNSInterface_Any - coreFlagKnownUnique = 0x4, // client guarantees that SRV and TXT record names are unique - coreFlagWakeOnly = 0x8 // Service won't be registered with sleep proxy -}; - +extern mDNSu32 deriveD2DFlagsFromAuthRecType(AuthRecType authRecType); extern mStatus mDNS_RegisterService (mDNS *const m, ServiceRecordSet *sr, const domainlabel *const name, const domainname *const type, const domainname *const domain, const domainname *const host, mDNSIPPort port, const mDNSu8 txtinfo[], mDNSu16 txtlen, @@ -2786,8 +2803,6 @@ extern mStatus mDNS_StartBrowse(mDNS *const m, DNSQuestion *const question, mDNSQuestionCallback *Callback, void *Context); #define mDNS_StopBrowse mDNS_StopQuery -extern mStatus mDNS_StartResolveService(mDNS *const m, ServiceInfoQuery *query, ServiceInfo *info, mDNSServiceInfoQueryCallback *Callback, void *Context); -extern void mDNS_StopResolveService (mDNS *const m, ServiceInfoQuery *query); typedef enum { @@ -2830,7 +2845,7 @@ extern mDNSu32 SetValidDNSServers(mDNS *m, DNSQuestion *question); // because that object is defined to be 256 bytes long, but not all domainname objects are truly the full size. // This macro uses mDNSPlatformMemCopy() to make sure it only touches the actual bytes that are valid. #define AssignDomainName(DST, SRC) do { mDNSu16 len__ = DomainNameLength((SRC)); \ - if (len__ <= MAX_DOMAIN_NAME) mDNSPlatformMemCopy((DST)->c, (SRC)->c, len__);else (DST)->c[0] = 0;} while(0) + if (len__ <= MAX_DOMAIN_NAME) mDNSPlatformMemCopy((DST)->c, (SRC)->c, len__); else (DST)->c[0] = 0; } while(0) // Comparison functions #define SameDomainLabelCS(A,B) ((A)[0] == (B)[0] && mDNSPlatformMemSame((A)+1, (B)+1, (A)[0])) @@ -2887,6 +2902,10 @@ extern char *ConvertDomainNameToCString_withescape(const domainname *const na extern void ConvertUTF8PstringToRFC1034HostLabel(const mDNSu8 UTF8Name[], domainlabel *const hostlabel); +#define ValidTransportProtocol(X) ( (X)[0] == 4 && (X)[1] == '_' && \ + ((((X)[2] | 0x20) == 'u' && ((X)[3] | 0x20) == 'd') || (((X)[2] | 0x20) == 't' && ((X)[3] | 0x20) == 'c')) && \ + ((X)[4] | 0x20) == 'p') + extern mDNSu8 *ConstructServiceName(domainname *const fqdn, const domainlabel *name, const domainname *type, const domainname *const domain); extern mDNSBool DeconstructServiceName(const domainname *const fqdn, domainlabel *const name, domainname *const type, domainname *const domain); @@ -2912,7 +2931,7 @@ extern mDNSBool DeconstructServiceName(const domainname *const fqdn, domainlabel // then the output will be truncated by one character to allow space for the terminating null. // Unlike standard C vsnprintf/snprintf, they return the number of characters *actually* written, // not the number of characters that *would* have been printed were buflen unlimited. -extern mDNSu32 mDNS_vsnprintf(char *sbuffer, mDNSu32 buflen, const char *fmt, va_list arg); +extern mDNSu32 mDNS_vsnprintf(char *sbuffer, mDNSu32 buflen, const char *fmt, va_list arg) IS_A_PRINTF_STYLE_FUNCTION(3,0); extern mDNSu32 mDNS_snprintf(char *sbuffer, mDNSu32 buflen, const char *fmt, ...) IS_A_PRINTF_STYLE_FUNCTION(3,4); extern mDNSu32 NumCacheRecordsForInterfaceID(const mDNS *const m, mDNSInterfaceID id); extern char *DNSTypeName(mDNSu16 rrtype); @@ -2942,6 +2961,7 @@ extern mDNSBool mDNSAddrIPv4FromMappedIPv6(mDNSv6Addr *in, mDNSv4Addr *out); #define mDNSIPPortIsZero(A) ((A).NotAnInteger == 0) #define mDNSOpaque16IsZero(A) ((A).NotAnInteger == 0) #define mDNSOpaque64IsZero(A) (((A)->l[0] | (A)->l[1] ) == 0) +#define mDNSOpaque128IsZero(A) (((A)->l[0] | (A)->l[1] | (A)->l[2] | (A)->l[3]) == 0) #define mDNSIPv4AddressIsZero(A) ((A).NotAnInteger == 0) #define mDNSIPv6AddressIsZero(A) (((A).l[0] | (A).l[1] | (A).l[2] | (A).l[3]) == 0) #define mDNSEthAddressIsZero(A) (((A).w[0] | (A).w[1] | (A).w[2] ) == 0) @@ -2976,12 +2996,6 @@ extern mDNSBool mDNSAddrIPv4FromMappedIPv6(mDNSv6Addr *in, mDNSv4Addr *out); ((X)->type == mDNSAddrType_IPv4) ? mDNSv4AddressIsLinkLocal(&(X)->ip.v4) : \ ((X)->type == mDNSAddrType_IPv6) ? mDNSv6AddressIsLinkLocal(&(X)->ip.v6) : mDNSfalse) -#define mDNSv4AddressIsLoopback(X) ((X)->b[0] == 127 && (X)->b[1] == 0 && (X)->b[2] == 0 && (X)->b[3] == 1) -#define mDNSv6AddressIsLoopback(X) ((((X)->l[0] | (X)->l[1] | (X)->l[2]) == 0) && ((X)->b[12] == 0 && (X)->b[13] == 0 && (X)->b[14] == 0 && (X)->b[15] == 1)) - -#define mDNSAddressIsLoopback(X) ( \ - ((X)->type == mDNSAddrType_IPv4) ? mDNSv4AddressIsLoopback(&(X)->ip.v4) : \ - ((X)->type == mDNSAddrType_IPv6) ? mDNSv6AddressIsLoopback(&(X)->ip.v6) : mDNSfalse) // *************************************************************************** #if 0 @@ -3025,8 +3039,8 @@ extern void mDNS_AddDynDNSHostName(mDNS *m, const domainname *fqdn, mDNSRecordCa extern void mDNS_RemoveDynDNSHostName(mDNS *m, const domainname *fqdn); extern void mDNS_SetPrimaryInterfaceInfo(mDNS *m, const mDNSAddr *v4addr, const mDNSAddr *v6addr, const mDNSAddr *router); extern DNSServer *mDNS_AddDNSServer(mDNS *const m, const domainname *d, const mDNSInterfaceID interface, mDNSs32 serviceID, const mDNSAddr *addr, - const mDNSIPPort port, mDNSu32 scoped, mDNSu32 timeout, mDNSBool cellIntf, mDNSu16 resGroupID, mDNSBool reqA, - mDNSBool reqAAAA, mDNSBool reqDO); + const mDNSIPPort port, mDNSu32 scoped, mDNSu32 timeout, mDNSBool cellIntf, mDNSBool isExpensive, mDNSu16 resGroupID, + mDNSBool reqA, mDNSBool reqAAAA, mDNSBool reqDO); extern void PenalizeDNSServer(mDNS *const m, DNSQuestion *q, mDNSOpaque16 responseFlags); extern void mDNS_AddSearchDomain(const domainname *const domain, mDNSInterfaceID InterfaceID); @@ -3101,14 +3115,14 @@ extern mDNSBool DNSDigest_VerifyMessage(DNSMessage *msg, mDNSu8 *end, LargeCache extern mStatus mDNSPlatformInit (mDNS *const m); extern void mDNSPlatformClose (mDNS *const m); extern mStatus mDNSPlatformSendUDP(const mDNS *const m, const void *const msg, const mDNSu8 *const end, - mDNSInterfaceID InterfaceID, UDPSocket *src, const mDNSAddr *dst, + mDNSInterfaceID InterfaceID, UDPSocket *src, const mDNSAddr *dst, mDNSIPPort dstport, mDNSBool useBackgroundTrafficClass); -extern mDNSBool mDNSPlatformPeekUDP (mDNS *const m, UDPSocket *src); extern void mDNSPlatformLock (const mDNS *const m); extern void mDNSPlatformUnlock (const mDNS *const m); extern void mDNSPlatformStrCopy ( void *dst, const void *src); +extern mDNSu32 mDNSPlatformStrLCopy ( void *dst, const void *src, mDNSu32 len); extern mDNSu32 mDNSPlatformStrLen ( const void *src); extern void mDNSPlatformMemCopy ( void *dst, const void *src, mDNSu32 len); extern mDNSBool mDNSPlatformMemSame (const void *dst, const void *src, mDNSu32 len); @@ -3144,17 +3158,6 @@ extern void mDNSPlatformWriteDebugMsg(const char *msg); #endif extern void mDNSPlatformWriteLogMsg(const char *ident, const char *msg, mDNSLogLevel_t loglevel); -#if APPLE_OSX_mDNSResponder -// Utility function for ASL logging -mDNSexport void mDNSASLLog(uuid_t *uuid, const char *subdomain, const char *result, const char *signature, const char *fmt, ...); - -// Log unicast and multicast traffic statistics once a day. Also used for DNSSEC statistics. -#define kDefaultNextStatsticsLogTime (24 * 60 * 60) - -extern void mDNSLogStatistics(mDNS *const m); - -#endif // APPLE_OSX_mDNSResponder - // Platform support modules should provide the following functions to map between opaque interface IDs // and interface indexes in order to support the DNS-SD API. If your target platform does not support // multiple interfaces and/or does not support the DNS-SD API, these functions can be empty. @@ -3185,7 +3188,7 @@ typedef enum } TCPSocketFlags; typedef void (*TCPConnectionCallback)(TCPSocket *sock, void *context, mDNSBool ConnectionEstablished, mStatus err); -extern TCPSocket *mDNSPlatformTCPSocket(mDNS *const m, TCPSocketFlags flags, mDNSIPPort *port, mDNSBool useBackgroundTrafficClass); // creates a TCP socket +extern TCPSocket *mDNSPlatformTCPSocket(TCPSocketFlags flags, mDNSIPPort *port, mDNSBool useBackgroundTrafficClass); // creates a TCP socket extern TCPSocket *mDNSPlatformTCPAccept(TCPSocketFlags flags, int sd); extern int mDNSPlatformTCPGetFD(TCPSocket *sock); extern mStatus mDNSPlatformTCPConnect(TCPSocket *sock, const mDNSAddr *dst, mDNSOpaque16 dstport, domainname *hostname, @@ -3193,19 +3196,21 @@ extern mStatus mDNSPlatformTCPConnect(TCPSocket *sock, const mDNSAddr *dst, m extern void mDNSPlatformTCPCloseConnection(TCPSocket *sock); extern long mDNSPlatformReadTCP(TCPSocket *sock, void *buf, unsigned long buflen, mDNSBool *closed); extern long mDNSPlatformWriteTCP(TCPSocket *sock, const char *msg, unsigned long len); -extern UDPSocket *mDNSPlatformUDPSocket(mDNS *const m, const mDNSIPPort requestedport); +extern UDPSocket *mDNSPlatformUDPSocket(const mDNSIPPort requestedport); extern mDNSu16 mDNSPlatformGetUDPPort(UDPSocket *sock); extern void mDNSPlatformUDPClose(UDPSocket *sock); -extern void mDNSPlatformReceiveBPF_fd(mDNS *const m, int fd); -extern void mDNSPlatformUpdateProxyList(mDNS *const m, const mDNSInterfaceID InterfaceID); +extern mDNSBool mDNSPlatformUDPSocketEncounteredEOF(const UDPSocket *sock); +extern void mDNSPlatformReceiveBPF_fd(int fd); +extern void mDNSPlatformUpdateProxyList(const mDNSInterfaceID InterfaceID); extern void mDNSPlatformSendRawPacket(const void *const msg, const mDNSu8 *const end, mDNSInterfaceID InterfaceID); -extern void mDNSPlatformSetLocalAddressCacheEntry(mDNS *const m, const mDNSAddr *const tpa, const mDNSEthAddr *const tha, mDNSInterfaceID InterfaceID); +extern void mDNSPlatformSetLocalAddressCacheEntry(const mDNSAddr *const tpa, const mDNSEthAddr *const tha, mDNSInterfaceID InterfaceID); extern void mDNSPlatformSourceAddrForDest(mDNSAddr *const src, const mDNSAddr *const dst); extern void mDNSPlatformSendKeepalive(mDNSAddr *sadd, mDNSAddr *dadd, mDNSIPPort *lport, mDNSIPPort *rport, mDNSu32 seq, mDNSu32 ack, mDNSu16 win); -extern mStatus mDNSPlatformRetrieveTCPInfo(mDNS *const m, mDNSAddr *laddr, mDNSIPPort *lport, mDNSAddr *raddr, mDNSIPPort *rport, mDNSTCPInfo *mti); -extern mStatus mDNSPlatformGetRemoteMacAddr(mDNS *const m, mDNSAddr *raddr); +extern mStatus mDNSPlatformRetrieveTCPInfo(mDNSAddr *laddr, mDNSIPPort *lport, mDNSAddr *raddr, mDNSIPPort *rport, mDNSTCPInfo *mti); +extern mStatus mDNSPlatformGetRemoteMacAddr(mDNSAddr *raddr); extern mStatus mDNSPlatformStoreSPSMACAddr(mDNSAddr *spsaddr, char *ifname); -extern mStatus mDNSPlatformClearSPSMACAddr(void); +extern mStatus mDNSPlatformClearSPSData(void); +extern mStatus mDNSPlatformStoreOwnerOptRecord(char *ifname, DNSMessage *msg, int length); // mDNSPlatformTLSSetupCerts/mDNSPlatformTLSTearDownCerts used by dnsextd extern mStatus mDNSPlatformTLSSetupCerts(void); @@ -3214,19 +3219,19 @@ extern void mDNSPlatformTLSTearDownCerts(void); // Platforms that support unicast browsing and dynamic update registration for clients who do not specify a domain // in browse/registration calls must implement these routines to get the "default" browse/registration list. -extern mDNSBool mDNSPlatformSetDNSConfig(mDNS *const m, mDNSBool setservers, mDNSBool setsearch, domainname *const fqdn, DNameListElem **RegDomains, +extern mDNSBool mDNSPlatformSetDNSConfig(mDNSBool setservers, mDNSBool setsearch, domainname *const fqdn, DNameListElem **RegDomains, DNameListElem **BrowseDomains, mDNSBool ackConfig); -extern mStatus mDNSPlatformGetPrimaryInterface(mDNS *const m, mDNSAddr *v4, mDNSAddr *v6, mDNSAddr *router); +extern mStatus mDNSPlatformGetPrimaryInterface(mDNSAddr *v4, mDNSAddr *v6, mDNSAddr *router); 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 void mDNSPlatformSetAllowSleep(mDNSBool allowSleep, const char *reason); +extern void mDNSPlatformPreventSleep(mDNSu32 timeout, const char *reason); +extern void mDNSPlatformSendWakeupPacket(mDNSInterfaceID InterfaceID, char *EthAddr, char *IPAddr, int iteration); extern mDNSBool mDNSPlatformInterfaceIsD2D(mDNSInterfaceID InterfaceID); extern mDNSBool mDNSPlatformInterfaceIsAWDL(const NetworkInterfaceInfo *intf); extern mDNSBool mDNSPlatformValidRecordForQuestion(const ResourceRecord *const rr, const DNSQuestion *const q); -extern mDNSBool mDNSPlatformValidRecordForInterface(AuthRecord *rr, const NetworkInterfaceInfo *intf); +extern mDNSBool mDNSPlatformValidRecordForInterface(const AuthRecord *rr, mDNSInterfaceID InterfaceID); extern mDNSBool mDNSPlatformValidQuestionForInterface(DNSQuestion *q, const NetworkInterfaceInfo *intf); extern void mDNSPlatformFormatTime(unsigned long t, mDNSu8 *buf, int bufsize); @@ -3279,10 +3284,19 @@ extern void LNT_ClearState(mDNS *const m); extern void mDNS_SetFQDN(mDNS *const m); extern void mDNS_ActivateNetWake_internal (mDNS *const m, NetworkInterfaceInfo *set); extern void mDNS_DeactivateNetWake_internal(mDNS *const m, NetworkInterfaceInfo *set); -extern mStatus mDNS_RegisterInterface (mDNS *const m, NetworkInterfaceInfo *set, mDNSBool flapping); -extern void mDNS_DeregisterInterface(mDNS *const m, NetworkInterfaceInfo *set, mDNSBool flapping); + +// Attributes that controls the Bonjour operation initiation and response speed for an interface. +typedef enum +{ + FastActivation, // For p2p* and DirectLink type interfaces + NormalActivation, // For standard interface timing + SlowActivation // For flapping interfaces +} InterfaceActivationSpeed; + +extern mStatus mDNS_RegisterInterface (mDNS *const m, NetworkInterfaceInfo *set, InterfaceActivationSpeed probeDelay); +extern void mDNS_DeregisterInterface(mDNS *const m, NetworkInterfaceInfo *set, InterfaceActivationSpeed probeDelay); extern void mDNSCoreInitComplete(mDNS *const m, mStatus result); -extern void mDNSCoreReceive(mDNS *const m, void *const msg, const mDNSu8 *const end, +extern void mDNSCoreReceive(mDNS *const m, DNSMessage *const msg, const mDNSu8 *const end, const mDNSAddr *const srcaddr, const mDNSIPPort srcport, const mDNSAddr *dstaddr, const mDNSIPPort dstport, const mDNSInterfaceID InterfaceID); extern void mDNSCoreRestartQueries(mDNS *const m); @@ -3302,7 +3316,7 @@ extern void mDNSCoreReceiveRawPacket (mDNS *const m, const mDNSu8 *const p, extern mDNSBool mDNSAddrIsDNSMulticast(const mDNSAddr *ip); extern CacheRecord *CreateNewCacheEntry(mDNS *const m, const mDNSu32 slot, CacheGroup *cg, mDNSs32 delay, mDNSBool Add, const mDNSAddr *sourceAddress); -extern CacheGroup *CacheGroupForName(const mDNS *const m, const mDNSu32 slot, const mDNSu32 namehash, const domainname *const name); +extern CacheGroup *CacheGroupForName(const mDNS *const m, const mDNSu32 namehash, const domainname *const name); extern void ReleaseCacheRecord(mDNS *const m, CacheRecord *r); extern void ScheduleNextCacheCheckTime(mDNS *const m, const mDNSu32 slot, const mDNSs32 event); extern void SetNextCacheCheckTimeForRecord(mDNS *const m, CacheRecord *const rr); @@ -3321,13 +3335,13 @@ extern void RetrySearchDomainQuestions(mDNS *const m); extern mDNSBool DomainEnumQuery(const domainname *qname); extern mStatus UpdateKeepaliveRData(mDNS *const m, AuthRecord *rr, NetworkInterfaceInfo *const intf, mDNSBool updateMac, char *ethAddr); extern void UpdateKeepaliveRMACAsync(mDNS *const m, void *context); -extern void UpdateRMACCallback(mDNS *const m, void *context); +extern void UpdateRMAC(mDNS *const m, void *context); // Used only in logging to restrict the number of /etc/hosts entries printed extern void FreeEtcHosts(mDNS *const m, AuthRecord *const rr, mStatus result); // exported for using the hash for /etc/hosts AuthRecords -extern AuthGroup *AuthGroupForName(AuthHash *r, const mDNSu32 slot, const mDNSu32 namehash, const domainname *const name); -extern AuthGroup *AuthGroupForRecord(AuthHash *r, const mDNSu32 slot, const ResourceRecord *const rr); +extern AuthGroup *AuthGroupForName(AuthHash *r, const mDNSu32 namehash, const domainname *const name); +extern AuthGroup *AuthGroupForRecord(AuthHash *r, const ResourceRecord *const rr); extern AuthGroup *InsertAuthRecord(mDNS *const m, AuthHash *r, AuthRecord *rr); extern AuthGroup *RemoveAuthRecord(mDNS *const m, AuthHash *r, AuthRecord *rr); extern mDNSBool mDNS_CheckForCacheRecord(mDNS *const m, DNSQuestion *q, mDNSu16 qtype); @@ -3336,38 +3350,36 @@ extern mDNSBool mDNS_CheckForCacheRecord(mDNS *const m, DNSQuestion *q, mDNSu16 // In the future, if there's demand, we may see if we can abstract it out cleanly into the platform layer #if APPLE_OSX_mDNSResponder extern void AutoTunnelCallback(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord); -extern void AddNewClientTunnel(mDNS *const m, DNSQuestion *const q); -extern void StartServerTunnel(mDNS *const m, DomainAuthInfo *const info); +extern void AddNewClientTunnel(DNSQuestion *const q); +extern void StartServerTunnel(DomainAuthInfo *const info); extern void UpdateAutoTunnelDomainStatuses(const mDNS *const m); extern void RemoveAutoTunnel6Record(mDNS *const m); -extern mDNSBool RecordReadyForSleep(mDNS *const m, AuthRecord *rr); +extern mDNSBool RecordReadyForSleep(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, mDNSBool *keepaliveOnly); -extern void mDNSPlatformUpdateDNSStatus(mDNS *const m, DNSQuestion *q); -extern void mDNSPlatformTriggerDNSRetry(mDNS *const m, DNSQuestion *v4q, DNSQuestion *v6q); +extern mStatus ActivateLocalProxy(NetworkInterfaceInfo *const intf, mDNSBool *keepaliveOnly); +extern void mDNSPlatformUpdateDNSStatus(DNSQuestion *q); +extern void mDNSPlatformTriggerDNSRetry(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, +typedef void ProxyCallback (void *socket, DNSMessage *const msg, const mDNSu8 *const end, const mDNSAddr *const srcaddr, const mDNSIPPort srcport, const mDNSAddr *dstaddr, const mDNSIPPort dstport, const mDNSInterfaceID InterfaceID, void *context); -extern void mDNSPlatformInitDNSProxySkts(mDNS *const m, ProxyCallback *UDPCallback, ProxyCallback *TCPCallback); +extern void mDNSPlatformInitDNSProxySkts(ProxyCallback *UDPCallback, ProxyCallback *TCPCallback); extern void mDNSPlatformCloseDNSProxySkts(mDNS *const m); extern void mDNSPlatformDisposeProxyContext(void *context); extern mDNSu8 *DNSProxySetAttributes(DNSQuestion *q, DNSMessageHeader *h, DNSMessage *msg, mDNSu8 *start, mDNSu8 *limit); -// Sleep Assertions are specific to Mac OS X #if APPLE_OSX_mDNSResponder -extern void mDNSPlatformSleepAssertion(mDNS *const m, double timeout); +extern void mDNSPlatformGetDNSRoutePolicy(DNSQuestion *q, mDNSBool *isBlocked); #endif - -extern void mDNSPlatformGetDNSRoutePolicy(mDNS *const m, DNSQuestion *q, mDNSBool *isBlocked); -extern void mDNSPlatformSetuDNSSocktOpt(UDPSocket *src, const mDNSAddr *dst, DNSQuestion *q); +extern void mDNSPlatformSetSocktOpt(void *sock, mDNSTransport_Type transType, mDNSAddr_Type addrType, const DNSQuestion *q); extern mDNSs32 mDNSPlatformGetPID(void); extern mDNSBool mDNSValidKeepAliveRecord(AuthRecord *rr); +extern mDNSBool CacheRecordRmvEventsForQuestion(mDNS *const m, DNSQuestion *q); // *************************************************************************** #if 0 @@ -3575,6 +3587,11 @@ struct CompileTimeAssertionChecks_mDNS char assertK[(sizeof(UDPHeader ) == 8 ) ? 1 : -1]; char assertL[(sizeof(IKEHeader ) == 28 ) ? 1 : -1]; char assertM[(sizeof(TCPHeader ) == 20 ) ? 1 : -1]; + char assertN[(sizeof(rdataOPT) == 24 ) ? 1 : -1]; + char assertO[(sizeof(rdataRRSig) == 20 ) ? 1 : -1]; + char assertP[(sizeof(PCPMapRequest) == 60 ) ? 1 : -1]; + char assertQ[(sizeof(PCPMapReply) == 60 ) ? 1 : -1]; + // Check our structures are reasonable sizes. Including overly-large buffers, or embedding // other overly-large structures instead of having a pointer to them, can inadvertently @@ -3584,18 +3601,17 @@ 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) <= 864) ? 1 : -1]; + char sizecheck_DNSQuestion [(sizeof(DNSQuestion) <= 912) ? 1 : -1]; - char sizecheck_ZoneData [(sizeof(ZoneData) <= 1700) ? 1 : -1]; + char sizecheck_ZoneData [(sizeof(ZoneData) <= 1744) ? 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) <= 7184) ? 1 : -1]; + char sizecheck_DNSServer [(sizeof(DNSServer) <= 330) ? 1 : -1]; + char sizecheck_NetworkInterfaceInfo[(sizeof(NetworkInterfaceInfo) <= 7376) ? 1 : -1]; char sizecheck_ServiceRecordSet [(sizeof(ServiceRecordSet) <= 5540) ? 1 : -1]; char sizecheck_DomainAuthInfo [(sizeof(DomainAuthInfo) <= 7888) ? 1 : -1]; - char sizecheck_ServiceInfoQuery [(sizeof(ServiceInfoQuery) <= 3488) ? 1 : -1]; #if APPLE_OSX_mDNSResponder - char sizecheck_ClientTunnel [(sizeof(ClientTunnel) <= 1208) ? 1 : -1]; + char sizecheck_ClientTunnel [(sizeof(ClientTunnel) <= 1256) ? 1 : -1]; #endif }; @@ -3605,6 +3621,13 @@ mDNSu32 initializeDeviceInfoTXT(mDNS *m, mDNSu8 *ptr); #if APPLE_OSX_mDNSResponder extern void D2D_start_advertising_interface(NetworkInterfaceInfo *interface); extern void D2D_stop_advertising_interface(NetworkInterfaceInfo *interface); +extern void D2D_start_advertising_record(AuthRecord *ar); +extern void D2D_stop_advertising_record(AuthRecord *ar); +#else +#define D2D_start_advertising_interface(X) +#define D2D_stop_advertising_interface(X) +#define D2D_start_advertising_record(X) +#define D2D_stop_advertising_record(X) #endif // *************************************************************************** diff --git a/usr/src/cmd/cmd-inet/usr.lib/mdnsd/nsec.h b/usr/src/contrib/mDNSResponder/mDNSCore/nsec.h index 198f57db92..198f57db92 100644 --- a/usr/src/cmd/cmd-inet/usr.lib/mdnsd/nsec.h +++ b/usr/src/contrib/mDNSResponder/mDNSCore/nsec.h diff --git a/usr/src/cmd/cmd-inet/usr.lib/mdnsd/uDNS.c b/usr/src/contrib/mDNSResponder/mDNSCore/uDNS.c index 56aced0180..0b1fe638ec 100644..100755 --- a/usr/src/cmd/cmd-inet/usr.lib/mdnsd/uDNS.c +++ b/usr/src/contrib/mDNSResponder/mDNSCore/uDNS.c @@ -45,12 +45,12 @@ mDNSexport SearchListElem *SearchList = mDNSNULL; mDNSBool StrictUnicastOrdering = mDNSfalse; // We keep track of the number of unicast DNS servers and log a message when we exceed 64. -// Currently the unicast queries maintain a 64 bit map to track the valid DNS servers for that +// Currently the unicast queries maintain a 128 bit map to track the valid DNS servers for that // question. Bit position is the index into the DNS server list. This is done so to try all // the servers exactly once before giving up. If we could allocate memory in the core, then -// arbitrary limitation of 64 DNSServers can be removed. +// arbitrary limitation of 128 DNSServers can be removed. mDNSu8 NumUnicastDNSServers = 0; -#define MAX_UNICAST_DNS_SERVERS 64 +#define MAX_UNICAST_DNS_SERVERS 128 #if APPLE_OSX_mDNSResponder mDNSu8 NumUnreachableDNSServers = 0; #endif @@ -112,8 +112,8 @@ mDNSlocal void SetRecordRetry(mDNS *const m, AuthRecord *rr, mDNSu32 random) #endif mDNSexport DNSServer *mDNS_AddDNSServer(mDNS *const m, const domainname *d, const mDNSInterfaceID interface, const mDNSs32 serviceID, const mDNSAddr *addr, - const mDNSIPPort port, mDNSu32 scoped, mDNSu32 timeout, mDNSBool cellIntf, mDNSu16 resGroupID, mDNSBool reqA, - mDNSBool reqAAAA, mDNSBool reqDO) + const mDNSIPPort port, mDNSu32 scoped, mDNSu32 timeout, mDNSBool cellIntf, mDNSBool isExpensive, mDNSu16 resGroupID, + mDNSBool reqA, mDNSBool reqAAAA, mDNSBool reqDO) { DNSServer **p = &m->DNSServers; DNSServer *tmp = mDNSNULL; @@ -124,20 +124,20 @@ mDNSexport DNSServer *mDNS_AddDNSServer(mDNS *const m, const domainname *d, cons return mDNSNULL; } - if (!d) + if (!d) d = (const domainname *)""; - LogInfo("mDNS_AddDNSServer(%d): Adding %#a for %##s, InterfaceID %p, serviceID %u, scoped %d, resGroupID %d req_A is %s req_AAAA is %s cell %s req_DO is %s", + LogInfo("mDNS_AddDNSServer(%d): Adding %#a for %##s, InterfaceID %p, serviceID %u, scoped %d, resGroupID %d req_A is %s req_AAAA is %s cell %s isExpensive %s req_DO is %s", NumUnicastDNSServers, addr, d->c, interface, serviceID, scoped, resGroupID, reqA ? "True" : "False", reqAAAA ? "True" : "False", - cellIntf ? "True" : "False", reqDO ? "True" : "False"); + cellIntf ? "True" : "False", isExpensive ? "True" : "False", reqDO ? "True" : "False"); while (*p) // Check if we already have this {interface,address,port,domain} tuple registered + reqA/reqAAAA bits { - if ((*p)->scoped == scoped && (*p)->interface == interface && (*p)->serviceID == serviceID && (*p)->teststate != DNSServer_Disabled && - mDNSSameAddress(&(*p)->addr, addr) && mDNSSameIPPort((*p)->port, port) && SameDomainName(&(*p)->domain, d) && + if ((*p)->scoped == scoped && (*p)->interface == interface && (*p)->serviceID == serviceID && + mDNSSameAddress(&(*p)->addr, addr) && mDNSSameIPPort((*p)->port, port) && SameDomainName(&(*p)->domain, d) && (*p)->req_A == reqA && (*p)->req_AAAA == reqAAAA) { - if (!((*p)->flags & DNSServer_FlagDelete)) + if (!((*p)->flags & DNSServer_FlagDelete)) debugf("Note: DNS Server %#a:%d for domain %##s (%p) registered more than once", addr, mDNSVal16(port), d->c, interface); tmp = *p; *p = tmp->next; @@ -184,19 +184,18 @@ mDNSexport DNSServer *mDNS_AddDNSServer(mDNS *const m, const domainname *d, cons } else { - (*p)->scoped = scoped; - (*p)->interface = interface; - (*p)->serviceID = serviceID; - (*p)->addr = *addr; - (*p)->port = port; - (*p)->flags = DNSServer_FlagNew; - (*p)->teststate = /* DNSServer_Untested */ DNSServer_Passed; - (*p)->lasttest = m->timenow - INIT_UCAST_POLL_INTERVAL; - (*p)->timeout = timeout; - (*p)->cellIntf = cellIntf; - (*p)->req_A = reqA; - (*p)->req_AAAA = reqAAAA; - (*p)->req_DO = reqDO; + (*p)->scoped = scoped; + (*p)->interface = interface; + (*p)->serviceID = serviceID; + (*p)->addr = *addr; + (*p)->port = port; + (*p)->flags = DNSServer_FlagNew; + (*p)->timeout = timeout; + (*p)->cellIntf = cellIntf; + (*p)->isExpensive = isExpensive; + (*p)->req_A = reqA; + (*p)->req_AAAA = reqAAAA; + (*p)->req_DO = reqDO; // We start off assuming that the DNS server is not DNSSEC aware and // when we receive the first response to a DNSSEC question, we set // it to true. @@ -206,11 +205,13 @@ mDNSexport DNSServer *mDNS_AddDNSServer(mDNS *const m, const domainname *d, cons (*p)->next = mDNSNULL; } } - (*p)->penaltyTime = 0; - // We always update the ID (not just when we allocate a new instance) because we could - // be adding a new non-scoped resolver with a new ID and we want all the non-scoped - // resolvers belong to the same group. - (*p)->resGroupID = resGroupID; + if (*p) { + (*p)->penaltyTime = 0; + // We always update the ID (not just when we allocate a new instance) because we could + // be adding a new non-scoped resolver with a new ID and we want all the non-scoped + // resolvers belong to the same group. + (*p)->resGroupID = resGroupID; + } return(*p); } @@ -229,14 +230,14 @@ mDNSexport void PenalizeDNSServer(mDNS *const m, DNSQuestion *q, mDNSOpaque16 re (q->qDNSServer ? &q->qDNSServer->addr : mDNSNULL), q, q->qname.c, DNSTypeName(q->qtype), q->SuppressUnusable); // If we get error from any DNS server, remember the error. If all of the servers, - // return the error, then return the first error. + // return the error, then return the first error. 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. + // penalizing again. if (!q->qDNSServer) goto end; @@ -480,10 +481,10 @@ mDNSexport mStatus mDNS_SetSecretForDomain(mDNS *m, DomainAuthInfo *info, mDNSlocal mStatus uDNS_RequestAddress(mDNS *m) { mStatus err = mStatus_NoError; - + if (!m->NATTraversals) { - m->retryGetAddr = NonZeroTime(m->timenow + 0x78000000); + m->retryGetAddr = NonZeroTime(m->timenow + FutureTime); LogInfo("uDNS_RequestAddress: Setting retryGetAddr to future"); } else if (m->timenow - m->retryGetAddr >= 0) @@ -495,7 +496,7 @@ mDNSlocal mStatus uDNS_RequestAddress(mDNS *m) mDNSu8* end = start + sizeof(NATAddrRequest); err = mDNSPlatformSendUDP(m, start, end, 0, mDNSNULL, &m->Router, NATPMPPort, mDNSfalse); debugf("uDNS_RequestAddress: Sent NAT-PMP external address request %d", err); - + #ifdef _LEGACY_NAT_TRAVERSAL_ if (mDNSIPPortIsZero(m->UPnPRouterPort) || mDNSIPPortIsZero(m->UPnPSOAPPort)) { @@ -507,7 +508,7 @@ mDNSlocal mStatus uDNS_RequestAddress(mDNS *m) mStatus lnterr = LNT_GetExternalAddress(m); if (lnterr) LogMsg("uDNS_RequestAddress: LNT_GetExternalAddress returned error %d", lnterr); - + err = err ? err : lnterr; // NAT-PMP error takes precedence } #endif // _LEGACY_NAT_TRAVERSAL_ @@ -552,7 +553,7 @@ mDNSlocal mStatus uDNS_SendNATMsg(mDNS *m, NATTraversalInfo *info, mDNSBool useP LogMsg("uDNS_SendNATMsg called unexpectedly with NULL info"); return mStatus_BadParamErr; } - + // send msg if the router's address is private (which means it's non-zero) if (mDNSv4AddrIsRFC1918(&m->Router.ip.v4)) { @@ -565,7 +566,7 @@ mDNSlocal mStatus uDNS_SendNATMsg(mDNS *m, NATTraversalInfo *info, mDNSBool useP static NATPortMapRequest NATPortReq; static const mDNSu8* end = (mDNSu8 *)&NATPortReq + sizeof(NATPortMapRequest); mDNSu8 *p = (mDNSu8 *)&NATPortReq.NATReq_lease; - + NATPortReq.vers = NATMAP_VERS; NATPortReq.opcode = info->Protocol; NATPortReq.unused = zeroID; @@ -575,7 +576,7 @@ mDNSlocal mStatus uDNS_SendNATMsg(mDNS *m, NATTraversalInfo *info, mDNSBool useP p[1] = (mDNSu8)((info->NATLease >> 16) & 0xFF); p[2] = (mDNSu8)((info->NATLease >> 8) & 0xFF); p[3] = (mDNSu8)( info->NATLease & 0xFF); - + err = mDNSPlatformSendUDP(m, (mDNSu8 *)&NATPortReq, end, 0, mDNSNULL, &m->Router, NATPMPPort, mDNSfalse); debugf("uDNS_SendNATMsg: Sent NAT-PMP mapping request %d", err); } @@ -602,34 +603,31 @@ mDNSlocal mStatus uDNS_SendNATMsg(mDNS *m, NATTraversalInfo *info, mDNSBool useP mDNSu8* start = (mDNSu8*)&req; mDNSu8* end = start + sizeof(req); mDNSu8* p = (mDNSu8*)&req.lifetime; - + req.version = PCP_VERS; req.opCode = PCPOp_Map; req.reserved = zeroID; - + p[0] = (mDNSu8)((info->NATLease >> 24) & 0xFF); p[1] = (mDNSu8)((info->NATLease >> 16) & 0xFF); p[2] = (mDNSu8)((info->NATLease >> 8) & 0xFF); p[3] = (mDNSu8)( info->NATLease & 0xFF); - + mDNSAddrMapIPv4toIPv6(&m->AdvertisedV4.ip.v4, &req.clientAddr); - + req.nonce[0] = m->PCPNonce[0]; req.nonce[1] = m->PCPNonce[1]; req.nonce[2] = m->PCPNonce[2]; - + req.protocol = (info->Protocol == NATOp_MapUDP ? PCPProto_UDP : PCPProto_TCP); - + req.reservedMapOp[0] = 0; req.reservedMapOp[1] = 0; req.reservedMapOp[2] = 0; - - if (info->Protocol) - req.intPort = info->IntPort; - else - req.intPort = DiscardPort; + + req.intPort = info->Protocol ? info->IntPort : DiscardPort; req.extPort = info->RequestedPort; - + // Since we only support IPv4, even if using the all-zeros address, map it, so // the PCP gateway will give us an IPv4 address & not an IPv6 address. mDNSAddrMapIPv4toIPv6(&info->NewAddress, &req.extAddress); @@ -655,7 +653,7 @@ mDNSlocal mStatus uDNS_SendNATMsg(mDNS *m, NATTraversalInfo *info, mDNSBool useP mStatus lnterr = LNT_MapPort(m, info); if (lnterr) LogMsg("uDNS_SendNATMsg: LNT_MapPort returned error %d", lnterr); - + err = err ? err : lnterr; // PCP error takes precedence } #endif // _LEGACY_NAT_TRAVERSAL_ @@ -728,7 +726,7 @@ mDNSexport void natTraversalHandleAddressReply(mDNS *const m, mDNSu16 err, mDNSv m->NextScheduledNATOp = m->retryGetAddr; last_err = err; - + for (n = m->NATTraversals; n; n=n->next) { // We should change n->NewAddress only when n is one of: @@ -925,7 +923,7 @@ mDNSexport mStatus mDNS_StopNATOperation_internal(mDNS *m, NATTraversalInfo *tra { traversal->NATLease = 0; traversal->retryInterval = 0; - + // In case we most recently sent NAT-PMP, we need to set sentNATPMP to false so // that we'll send a NAT-PMP request to destroy the mapping. We do this because // the NATTraversal struct has already been cut from the list, and the client @@ -941,7 +939,7 @@ mDNSexport mStatus mDNS_StopNATOperation_internal(mDNS *m, NATTraversalInfo *tra // would have requested an IPv4 address. traversal->RequestedPort = zeroIPPort; traversal->NewAddress = zerov4Addr; - + uDNS_SendNATMsg(m, traversal, traversal->lastSuccessfulProtocol != NATTProtocolNATPMP); } @@ -1555,7 +1553,7 @@ mDNSlocal tcpInfo_t *MakeTCPConn(mDNS *const m, const DNSMessage *const msg, con mDNSPlatformMemZero(info, sizeof(tcpInfo_t)); info->m = m; - info->sock = mDNSPlatformTCPSocket(m, flags, &srcport, useBackgroundTrafficClass); + info->sock = mDNSPlatformTCPSocket(flags, &srcport, useBackgroundTrafficClass); info->requestLen = 0; info->question = question; info->rr = rr; @@ -1574,6 +1572,7 @@ mDNSlocal tcpInfo_t *MakeTCPConn(mDNS *const m, const DNSMessage *const msg, con } if (!info->sock) { LogMsg("MakeTCPConn: unable to create TCP socket"); mDNSPlatformMemFree(info); return(mDNSNULL); } + mDNSPlatformSetSocktOpt(info->sock, mDNSTransport_TCP, Addr->type, question); err = mDNSPlatformTCPConnect(info->sock, Addr, Port, hostname, (question ? question->InterfaceID : mDNSNULL), tcpCallback, info); // Probably suboptimal here. @@ -1704,6 +1703,7 @@ mDNSexport void startLLQHandshake(mDNS *m, DNSQuestion *q) } } + // forward declaration so GetServiceTarget can do reverse lookup if needed mDNSlocal void GetStaticHostname(mDNS *m); @@ -1719,7 +1719,7 @@ mDNSexport const domainname *GetServiceTarget(mDNS *m, AuthRecord *const rr) DomainAuthInfo *AuthInfo = GetAuthInfoForName_internal(m, rr->resrec.name); if (AuthInfo && AuthInfo->AutoTunnel) { - StartServerTunnel(m, AuthInfo); + StartServerTunnel(AuthInfo); if (AuthInfo->AutoTunnelHostRecord.namestorage.c[0] == 0) return(mDNSNULL); debugf("GetServiceTarget: Returning %##s", AuthInfo->AutoTunnelHostRecord.namestorage.c); return(&AuthInfo->AutoTunnelHostRecord.namestorage); @@ -1755,11 +1755,13 @@ mDNSlocal const domainname *PUBLIC_LLQ_SERVICE_TYPE = (const domainname*)"\x mDNSlocal const domainname *PRIVATE_UPDATE_SERVICE_TYPE = (const domainname*)"\x0F_dns-update-tls" "\x04_tcp"; mDNSlocal const domainname *PRIVATE_QUERY_SERVICE_TYPE = (const domainname*)"\x0E_dns-query-tls" "\x04_tcp"; mDNSlocal const domainname *PRIVATE_LLQ_SERVICE_TYPE = (const domainname*)"\x0C_dns-llq-tls" "\x04_tcp"; +mDNSlocal const domainname *DNS_PUSH_NOTIFICATION_SERVICE_TYPE = (const domainname*)"\x0C_dns-push-tls" "\x04_tcp"; #define ZoneDataSRV(X) ( \ - (X)->ZoneService == ZoneServiceUpdate ? ((X)->ZonePrivate ? PRIVATE_UPDATE_SERVICE_TYPE : PUBLIC_UPDATE_SERVICE_TYPE) : \ - (X)->ZoneService == ZoneServiceQuery ? ((X)->ZonePrivate ? PRIVATE_QUERY_SERVICE_TYPE : (const domainname*)"" ) : \ - (X)->ZoneService == ZoneServiceLLQ ? ((X)->ZonePrivate ? PRIVATE_LLQ_SERVICE_TYPE : PUBLIC_LLQ_SERVICE_TYPE ) : (const domainname*)"") + (X)->ZoneService == ZoneServiceUpdate ? ((X)->ZonePrivate ? PRIVATE_UPDATE_SERVICE_TYPE : PUBLIC_UPDATE_SERVICE_TYPE) : \ + (X)->ZoneService == ZoneServiceQuery ? ((X)->ZonePrivate ? PRIVATE_QUERY_SERVICE_TYPE : (const domainname*)"" ) : \ + (X)->ZoneService == ZoneServiceLLQ ? ((X)->ZonePrivate ? PRIVATE_LLQ_SERVICE_TYPE : PUBLIC_LLQ_SERVICE_TYPE ) : \ + (X)->ZoneService == ZoneServiceDNSPush ? DNS_PUSH_NOTIFICATION_SERVICE_TYPE : (const domainname*)"") // Forward reference: GetZoneData_StartQuery references GetZoneData_QuestionCallback, and // GetZoneData_QuestionCallback calls GetZoneData_StartQuery @@ -1854,10 +1856,7 @@ mDNSlocal void GetZoneData_QuestionCallback(mDNS *const m, DNSQuestion *question if (question->ThisQInterval != -1) 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; - else - zd->Addr.ip.v4 = zerov4Addr; + zd->Addr.ip.v4 = (answer->rdlength == 4) ? answer->rdata->u.ipv4 : 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 @@ -1890,7 +1889,7 @@ mDNSlocal mStatus GetZoneData_StartQuery(mDNS *const m, ZoneData *zd, mDNSu16 qt zd->question.InterfaceID = mDNSInterface_Any; zd->question.flags = 0; zd->question.Target = zeroAddr; - //zd->question.qname.c[0] = 0; // Already set + //zd->question.qname.c[0] = 0; // Already set zd->question.qtype = qtype; zd->question.qclass = kDNSClass_IN; zd->question.LongLived = mDNSfalse; @@ -1898,8 +1897,6 @@ mDNSlocal mStatus GetZoneData_StartQuery(mDNS *const m, ZoneData *zd, mDNSu16 qt zd->question.ForceMCast = mDNSfalse; zd->question.ReturnIntermed = mDNStrue; zd->question.SuppressUnusable = mDNSfalse; - zd->question.DenyOnCellInterface = mDNSfalse; - zd->question.DenyOnExpInterface = mDNSfalse; zd->question.SearchListIndex = 0; zd->question.AppendSearchDomains = 0; zd->question.RetryWithSearchDomains = mDNSfalse; @@ -2175,7 +2172,7 @@ mDNSlocal void StartRecordNatMap(mDNS *m, AuthRecord *rr) else { LogMsg("StartRecordNatMap: could not determine transport protocol of service %##s", rr->resrec.name->c); return; } //LogMsg("StartRecordNatMap: clientContext %p IntPort %d srv.port %d %s", - // rr->NATinfo.clientContext, mDNSVal16(rr->NATinfo.IntPort), mDNSVal16(rr->resrec.rdata->u.srv.port), ARDisplayString(m, rr)); + // rr->NATinfo.clientContext, mDNSVal16(rr->NATinfo.IntPort), mDNSVal16(rr->resrec.rdata->u.srv.port), ARDisplayString(m, rr)); if (rr->NATinfo.clientContext) mDNS_StopNATOperation_internal(m, &rr->NATinfo); rr->NATinfo.Protocol = protocol; @@ -2589,8 +2586,6 @@ mDNSlocal void GetStaticHostname(mDNS *m) q->ForceMCast = mDNSfalse; q->ReturnIntermed = mDNStrue; q->SuppressUnusable = mDNSfalse; - q->DenyOnCellInterface = mDNSfalse; - q->DenyOnExpInterface = mDNSfalse; q->SearchListIndex = 0; q->AppendSearchDomains = 0; q->RetryWithSearchDomains = mDNSfalse; @@ -2650,12 +2645,30 @@ mDNSexport void mDNS_RemoveDynDNSHostName(mDNS *m, const domainname *fqdn) // below could free the memory, and we have to make sure we don't touch hi fields after that. mDNSBool f4 = hi->arv4.resrec.RecordType != kDNSRecordTypeUnregistered && hi->arv4.state != regState_Unregistered; mDNSBool f6 = hi->arv6.resrec.RecordType != kDNSRecordTypeUnregistered && hi->arv6.state != regState_Unregistered; - if (f4) LogInfo("mDNS_RemoveDynDNSHostName removing v4 %##s", fqdn); - if (f6) LogInfo("mDNS_RemoveDynDNSHostName removing v6 %##s", fqdn); *ptr = (*ptr)->next; // unlink - if (f4) mDNS_Deregister_internal(m, &hi->arv4, mDNS_Dereg_normal); - if (f6) mDNS_Deregister_internal(m, &hi->arv6, mDNS_Dereg_normal); - // When both deregistrations complete we'll free the memory in the mStatus_MemFree callback + if (f4 || f6) + { + if (f4) + { + LogInfo("mDNS_RemoveDynDNSHostName removing v4 %##s", fqdn); + mDNS_Deregister_internal(m, &hi->arv4, mDNS_Dereg_normal); + } + if (f6) + { + LogInfo("mDNS_RemoveDynDNSHostName removing v6 %##s", fqdn); + mDNS_Deregister_internal(m, &hi->arv6, mDNS_Dereg_normal); + } + // When both deregistrations complete we'll free the memory in the mStatus_MemFree callback + } + else + { + if (hi->natinfo.clientContext) + { + mDNS_StopNATOperation_internal(m, &hi->natinfo); + hi->natinfo.clientContext = mDNSNULL; + } + mDNSPlatformMemFree(hi); + } } mDNS_CheckLock(m); m->NextSRVUpdate = NonZeroTime(m->timenow); @@ -2666,7 +2679,6 @@ mDNSexport void mDNS_RemoveDynDNSHostName(mDNS *m, const domainname *fqdn) mDNSexport void mDNS_SetPrimaryInterfaceInfo(mDNS *m, const mDNSAddr *v4addr, const mDNSAddr *v6addr, const mDNSAddr *router) { mDNSBool v4Changed, v6Changed, RouterChanged; - mDNSv6Addr v6; if (m->mDNS_busy != m->mDNS_reentrancy) LogMsg("mDNS_SetPrimaryInterfaceInfo: mDNS_busy (%ld) != mDNS_reentrancy (%ld)", m->mDNS_busy, m->mDNS_reentrancy); @@ -2678,11 +2690,7 @@ mDNSexport void mDNS_SetPrimaryInterfaceInfo(mDNS *m, const mDNSAddr *v4addr, co mDNS_Lock(m); v4Changed = !mDNSSameIPv4Address(m->AdvertisedV4.ip.v4, v4addr ? v4addr->ip.v4 : zerov4Addr); - if (v6addr) - v6 = v6addr->ip.v6; - else - v6 = zerov6Addr; - v6Changed = !mDNSSameIPv6Address(m->AdvertisedV6.ip.v6, v6); + v6Changed = !mDNSSameIPv6Address(m->AdvertisedV6.ip.v6, v6addr ? v6addr->ip.v6 : zerov6Addr); RouterChanged = !mDNSSameIPv4Address(m->Router.ip.v4, router ? router->ip.v4 : zerov4Addr); if (v4addr && (v4Changed || RouterChanged)) @@ -2751,7 +2759,6 @@ mDNSexport void mDNS_SetPrimaryInterfaceInfo(mDNS *m, const mDNSAddr *v4addr, co m->NextSRVUpdate = NonZeroTime(m->timenow); #if APPLE_OSX_mDNSResponder - if (RouterChanged) uuid_generate(m->asl_uuid); UpdateAutoTunnelDomainStatuses(m); #endif } @@ -3026,7 +3033,6 @@ exit: mDNSlocal mDNSBool IsRecordMergeable(mDNS *const m, AuthRecord *rr, mDNSs32 time) { DomainAuthInfo *info; - (void) m; //unused // A record is eligible for merge, if the following properties are met. // // 1. uDNS Resource Record @@ -3631,13 +3637,13 @@ mDNSlocal void uDNS_ReceiveNATPMPPacket(mDNS *m, const mDNSInterfaceID Interface // Minimum NAT-PMP packet is vers (1) opcode (1) + err (2) = 4 bytes if (len < 4) { LogMsg("NAT-PMP message too short (%d bytes)", len); return; } - + // Read multi-byte error value (field is identical in a NATPortMapReply) AddrReply->err = (mDNSu16) ((mDNSu16)pkt[2] << 8 | pkt[3]); - + if (AddrReply->err == NATErr_Vers) { - NATTraversalInfo *n; + NATTraversalInfo *n; LogInfo("NAT-PMP version unsupported message received"); for (n = m->NATTraversals; n; n=n->next) { @@ -3645,7 +3651,7 @@ mDNSlocal void uDNS_ReceiveNATPMPPacket(mDNS *m, const mDNSInterfaceID Interface // and update the state variables uDNS_SendNATMsg(m, n, mDNSfalse); } - + m->NextScheduledNATOp = m->timenow; return; @@ -3659,7 +3665,7 @@ mDNSlocal void uDNS_ReceiveNATPMPPacket(mDNS *m, const mDNSInterfaceID Interface LogMsg("NAT-PMP message too short (%d bytes) 0x%X 0x%X", len, AddrReply->opcode, AddrReply->err); return; } - + // Read multi-byte upseconds value (field is identical in a NATPortMapReply) AddrReply->upseconds = (mDNSs32) ((mDNSs32)pkt[4] << 24 | (mDNSs32)pkt[5] << 16 | (mDNSs32)pkt[6] << 8 | pkt[7]); @@ -3689,9 +3695,7 @@ mDNSlocal void uDNS_ReceiveNATPMPPacket(mDNS *m, const mDNSInterfaceID Interface if (AddrReply->opcode == NATOp_AddrResponse) { #if APPLE_OSX_mDNSResponder - static char msgbuf[16]; - mDNS_snprintf(msgbuf, sizeof(msgbuf), "%d", AddrReply->err); - mDNSASLLog((uuid_t *)&m->asl_uuid, "natt.natpmp.AddressRequest", AddrReply->err ? "failure" : "success", msgbuf, ""); + LogInfo("uDNS_ReceiveNATPMPPacket: AddressRequest %s error %d", AddrReply->err ? "failure" : "success", AddrReply->err); #endif if (!AddrReply->err && len < sizeof(NATAddrReply)) { LogMsg("NAT-PMP AddrResponse message too short (%d bytes)", len); return; } natTraversalHandleAddressReply(m, AddrReply->err, AddrReply->ExtAddr); @@ -3700,9 +3704,8 @@ mDNSlocal void uDNS_ReceiveNATPMPPacket(mDNS *m, const mDNSInterfaceID Interface { mDNSu8 Protocol = AddrReply->opcode & 0x7F; #if APPLE_OSX_mDNSResponder - static char msgbuf[16]; - mDNS_snprintf(msgbuf, sizeof(msgbuf), "%s - %d", AddrReply->opcode == NATOp_MapUDPResponse ? "UDP" : "TCP", PortMapReply->err); - mDNSASLLog((uuid_t *)&m->asl_uuid, "natt.natpmp.PortMapRequest", PortMapReply->err ? "failure" : "success", msgbuf, ""); + LogInfo("uDNS_ReceiveNATPMPPacket: PortMapRequest %s %s - error %d", + PortMapReply->err ? "failure" : "success", (AddrReply->opcode == NATOp_MapUDPResponse) ? "UDP" : "TCP", PortMapReply->err); #endif if (!PortMapReply->err) { @@ -3736,16 +3739,16 @@ mDNSlocal void uDNS_ReceivePCPPacket(mDNS *m, const mDNSInterfaceID InterfaceID, mDNSu8 protocol = 0; mDNSIPPort intport = zeroIPPort; mDNSIPPort extport = zeroIPPort; - + // Minimum PCP packet is 24 bytes if (len < 24) { LogMsg("uDNS_ReceivePCPPacket: message too short (%d bytes)", len); return; } - + strippedOpCode = reply->opCode & 0x7f; - + if ((reply->opCode & 0x80) == 0x00 || (strippedOpCode != PCPOp_Announce && strippedOpCode != PCPOp_Map)) { LogMsg("uDNS_ReceivePCPPacket: unhandled opCode %u", reply->opCode); @@ -3784,11 +3787,11 @@ mDNSlocal void uDNS_ReceivePCPPacket(mDNS *m, const mDNSInterfaceID InterfaceID, if (strippedOpCode == PCPOp_Announce) return; - + // We globally keep track of the most recent error code for mappings. // This seems bad to do with PCP, but best not change it now. m->LastNATMapResultCode = reply->result; - + if (!reply->result) { if (len < sizeof(PCPMapReply)) @@ -3796,7 +3799,7 @@ mDNSlocal void uDNS_ReceivePCPPacket(mDNS *m, const mDNSInterfaceID InterfaceID, LogMsg("uDNS_ReceivePCPPacket: mapping response too short (%d bytes)", len); return; } - + // Check the nonce if (reply->nonce[0] != m->PCPNonce[0] || reply->nonce[1] != m->PCPNonce[1] || reply->nonce[2] != m->PCPNonce[2]) { @@ -3835,7 +3838,7 @@ mDNSlocal void uDNS_ReceivePCPPacket(mDNS *m, const mDNSInterfaceID InterfaceID, { LogInfo("uDNS_ReceivePCPPacket: error received from server. opcode %X result %X lifetime %X epoch %X", reply->opCode, reply->result, reply->lifetime, reply->epoch); - + // If the packet is long enough, get the protocol & intport for matching to report // the error if (len >= sizeof(PCPMapReply)) @@ -3868,135 +3871,6 @@ mDNSexport void uDNS_ReceiveNATPacket(mDNS *m, const mDNSInterfaceID InterfaceID LogMsg("uDNS_ReceiveNATPacket: packet with version %u (expected %u or %u)", pkt[0], PCP_VERS, NATMAP_VERS); } -// <rdar://problem/3925163> Shorten DNS-SD queries to avoid NAT bugs -// <rdar://problem/4288449> Add check to avoid crashing NAT gateways that have buggy DNS relay code -// -// We know of bugs in home NAT gateways that cause them to crash if they receive certain DNS queries. -// The DNS queries that make them crash are perfectly legal DNS queries, but even if they weren't, -// the gateway shouldn't crash -- in today's world of viruses and network attacks, software has to -// be written assuming that a malicious attacker could send them any packet, properly-formed or not. -// Still, we don't want to be crashing people's home gateways, so we go out of our way to avoid -// the queries that crash them. -// -// Some examples: -// -// 1. Any query where the name ends in ".in-addr.arpa." and the text before this is 32 or more bytes. -// The query type does not need to be PTR -- the gateway will crash for any query type. -// e.g. "ping long-name-crashes-the-buggy-router.in-addr.arpa" will crash one of these. -// -// 2. Any query that results in a large response with the TC bit set. -// -// 3. Any PTR query that doesn't begin with four decimal numbers. -// These gateways appear to assume that the only possible PTR query is a reverse-mapping query -// (e.g. "1.0.168.192.in-addr.arpa") and if they ever get a PTR query where the first four -// labels are not all decimal numbers in the range 0-255, they handle that by crashing. -// These gateways also ignore the remainder of the name following the four decimal numbers -// -- whether or not it actually says in-addr.arpa, they just make up an answer anyway. -// -// The challenge therefore is to craft a query that will discern whether the DNS server -// is one of these buggy ones, without crashing it. Furthermore we don't want our test -// queries making it all the way to the root name servers, putting extra load on those -// name servers and giving Apple a bad reputation. To this end we send this query: -// dig -t ptr 1.0.0.127.dnsbugtest.1.0.0.127.in-addr.arpa. -// -// The text preceding the ".in-addr.arpa." is under 32 bytes, so it won't cause crash (1). -// It will not yield a large response with the TC bit set, so it won't cause crash (2). -// It starts with four decimal numbers, so it won't cause crash (3). -// The name falls within the "1.0.0.127.in-addr.arpa." domain, the reverse-mapping name for the local -// loopback address, and therefore the query will black-hole at the first properly-configured DNS server -// it reaches, making it highly unlikely that this query will make it all the way to the root. -// -// Finally, the correct response to this query is NXDOMAIN or a similar error, but the -// gateways that ignore the remainder of the name following the four decimal numbers -// give themselves away by actually returning a result for this nonsense query. - -mDNSlocal const domainname *DNSRelayTestQuestion = (const domainname*) - "\x1" "1" "\x1" "0" "\x1" "0" "\x3" "127" "\xa" "dnsbugtest" - "\x1" "1" "\x1" "0" "\x1" "0" "\x3" "127" "\x7" "in-addr" "\x4" "arpa"; - -// See comments above for DNSRelayTestQuestion -// If this is the kind of query that has the risk of crashing buggy DNS servers, we do a test question first -mDNSlocal mDNSBool NoTestQuery(DNSQuestion *q) -{ - int i; - mDNSu8 *p = q->qname.c; - if (q->AuthInfo) return(mDNStrue); // Don't need a test query for private queries sent directly to authoritative server over TLS/TCP - if (q->qtype != kDNSType_PTR) return(mDNStrue); // Don't need a test query for any non-PTR queries - for (i=0; i<4; i++) // If qname does not begin with num.num.num.num, can't skip the test query - { - if (p[0] < 1 || p[0] > 3) return(mDNSfalse); - if ( p[1] < '0' || p[1] > '9' ) return(mDNSfalse); - if (p[0] >= 2 && (p[2] < '0' || p[2] > '9')) return(mDNSfalse); - if (p[0] >= 3 && (p[3] < '0' || p[3] > '9')) return(mDNSfalse); - p += 1 + p[0]; - } - // If remainder of qname is ".in-addr.arpa.", this is a vanilla reverse-mapping query and - // we can safely do it without needing a test query first, otherwise we need the test query. - return(SameDomainName((domainname*)p, (const domainname*)"\x7" "in-addr" "\x4" "arpa")); -} - -// Returns mDNStrue if response was handled -mDNSlocal mDNSBool uDNS_ReceiveTestQuestionResponse(mDNS *const m, DNSMessage *const msg, const mDNSu8 *const end, - const mDNSAddr *const srcaddr, const mDNSIPPort srcport) -{ - const mDNSu8 *ptr = msg->data; - DNSQuestion pktq; - DNSServer *s; - mDNSu32 result = 0; - - // 1. Find out if this is an answer to one of our test questions - if (msg->h.numQuestions != 1) return(mDNSfalse); - ptr = getQuestion(msg, ptr, end, mDNSInterface_Any, &pktq); - if (!ptr) return(mDNSfalse); - if (pktq.qtype != kDNSType_PTR || pktq.qclass != kDNSClass_IN) return(mDNSfalse); - if (!SameDomainName(&pktq.qname, DNSRelayTestQuestion)) return(mDNSfalse); - - // 2. If the DNS relay gave us a positive response, then it's got buggy firmware - // else, if the DNS relay gave us an error or no-answer response, it passed our test - if ((msg->h.flags.b[1] & kDNSFlag1_RC_Mask) == kDNSFlag1_RC_NoErr && msg->h.numAnswers > 0) - result = DNSServer_Failed; - else - result = DNSServer_Passed; - - // 3. Find occurrences of this server in our list, and mark them appropriately - for (s = m->DNSServers; s; s = s->next) - { - mDNSBool matchaddr = (s->teststate != result && mDNSSameAddress(srcaddr, &s->addr) && mDNSSameIPPort(srcport, s->port)); - mDNSBool matchid = (s->teststate == DNSServer_Untested && mDNSSameOpaque16(msg->h.id, s->testid)); - if (matchaddr || matchid) - { - DNSQuestion *q; - s->teststate = result; - if (result == DNSServer_Passed) - { - LogInfo("DNS Server %#a:%d (%#a:%d) %d passed%s", - &s->addr, mDNSVal16(s->port), srcaddr, mDNSVal16(srcport), mDNSVal16(s->testid), - matchaddr ? "" : " NOTE: Reply did not come from address to which query was sent"); - } - else - { - LogMsg("NOTE: Wide-Area Service Discovery disabled to avoid crashing defective DNS relay %#a:%d (%#a:%d) %d%s", - &s->addr, mDNSVal16(s->port), srcaddr, mDNSVal16(srcport), mDNSVal16(s->testid), - matchaddr ? "" : " NOTE: Reply did not come from address to which query was sent"); - } - - // If this server has just changed state from DNSServer_Untested to DNSServer_Passed, then retrigger any waiting questions. - // We use the NoTestQuery() test so that we only retrigger questions that were actually blocked waiting for this test to complete. - if (result == DNSServer_Passed) // Unblock any questions that were waiting for this result - for (q = m->Questions; q; q=q->next) - if (q->qDNSServer == s && !NoTestQuery(q)) - { - q->ThisQInterval = INIT_UCAST_POLL_INTERVAL / QuestionIntervalStep; - q->unansweredQueries = 0; - q->LastQTime = m->timenow - q->ThisQInterval; - m->NextScheduledQuery = m->timenow; - } - } - } - - return(mDNStrue); // Return mDNStrue to tell uDNS_ReceiveMsg it doesn't need to process this packet further -} - // Called from mDNSCoreReceive with the lock held mDNSexport void uDNS_ReceiveMsg(mDNS *const m, DNSMessage *const msg, const mDNSu8 *const end, const mDNSAddr *const srcaddr, const mDNSIPPort srcport) { @@ -4025,7 +3899,6 @@ mDNSexport void uDNS_ReceiveMsg(mDNS *const m, DNSMessage *const msg, const mDNS if (QR_OP == StdR) { //if (srcaddr && recvLLQResponse(m, msg, end, srcaddr, srcport)) return; - if (uDNS_ReceiveTestQuestionResponse(m, msg, end, srcaddr, srcport)) return; for (qptr = m->Questions; qptr; qptr = qptr->next) if (msg->h.flags.b[0] & kDNSFlag0_TC && mDNSSameOpaque16(qptr->TargetQID, msg->h.id) && m->timenow - qptr->LastQTime < RESPONSE_WINDOW) { @@ -4043,11 +3916,13 @@ mDNSexport void uDNS_ReceiveMsg(mDNS *const m, DNSMessage *const msg, const mDNS if (QR_OP == UpdateR) { - mDNSu32 lease = GetPktLease(m, msg, end); + mDNSu32 pktlease = 0; + mDNSBool gotlease = GetPktLease(m, msg, end, &pktlease); + mDNSu32 lease = gotlease ? pktlease : 60 * 60; // If lease option missing, assume one hour mDNSs32 expire = m->timenow + (mDNSs32)lease * mDNSPlatformOneSecond; mDNSu32 random = mDNSRandom((mDNSs32)lease * mDNSPlatformOneSecond/10); - //rcode = kDNSFlag1_RC_ServFail; // Simulate server failure (rcode 2) + //rcode = kDNSFlag1_RC_ServFail; // Simulate server failure (rcode 2) // Walk through all the records that matches the messageID. There could be multiple // records if we had sent them in a group @@ -4130,7 +4005,7 @@ mDNSexport void sendLLQRefresh(mDNS *m, DNSQuestion *q) return; // ThisQInterval is not adjusted when we return from here which means that we will get called back // again immediately. As q->servAddr and q->servPort are still valid and the nta->Host is initialized - // without any additional discovery for PrivateQuery, things work. + // without any additional discovery for PrivateQuery, things work. } q->tcp = MakeTCPConn(m, &m->omsg, end, kTCPSocketFlags_UseTLS, &q->servAddr, q->servPort, &q->nta->Host, q, mDNSNULL); } @@ -4210,6 +4085,41 @@ mDNSexport void LLQGotZoneData(mDNS *const m, mStatus err, const ZoneData *zoneI mDNS_Unlock(m); } +#ifdef DNS_PUSH_ENABLED +mDNSexport void DNSPushNotificationGotZoneData(mDNS *const m, mStatus err, const ZoneData *zoneInfo) +{ + DNSQuestion *q = (DNSQuestion *)zoneInfo->ZoneDataContext; + mDNS_Lock(m); + + // If we get here it means that the GetZoneData operation has completed. + // We hold on to the zone data if it is AutoTunnel as we use the hostname + // in zoneInfo during the TLS connection setup. + q->servAddr = zeroAddr; + q->servPort = zeroIPPort; + if (!err && zoneInfo && !mDNSIPPortIsZero(zoneInfo->Port) && !mDNSAddressIsZero(&zoneInfo->Addr) && zoneInfo->Host.c[0]) + { + q->dnsPushState = DNSPUSH_SERVERFOUND; + q->dnsPushServerAddr = zoneInfo->Addr; + q->dnsPushServerPort = zoneInfo->Port; + q->ntries = 0; + LogInfo("DNSPushNotificationGotZoneData %#a:%d", &q->dnsPushServerAddr, mDNSVal16(q->dnsPushServerPort)); + SubscribeToDNSPushNotificationServer(m,q); + } + else + { + q->dnsPushState = DNSPUSH_NOSERVER; + StartLLQPolling(m,q); + if (err == mStatus_NoSuchNameErr) + { + // this actually failed, so mark it by setting address to all ones + q->servAddr.type = mDNSAddrType_IPv4; + q->servAddr.ip.v4 = onesIPv4Addr; + } + } + mDNS_Unlock(m); +} +#endif // DNS_PUSH_ENABLED + // Called in normal callback context (i.e. mDNS_busy and mDNS_reentrancy are both 1) mDNSlocal void PrivateQueryGotZoneData(mDNS *const m, mStatus err, const ZoneData *zoneInfo) { @@ -4477,7 +4387,7 @@ mDNSlocal void SendRecordDeregistration(mDNS *m, AuthRecord *rr) if (!rr->nta) { LogMsg("SendRecordDeregistration:ERROR!! nta is NULL for %s", ARDisplayString(m, rr)); return; } err = mDNSSendDNSMessage(m, &m->omsg, ptr, mDNSInterface_Any, mDNSNULL, &rr->nta->Addr, rr->nta->Port, mDNSNULL, GetAuthInfoForName_internal(m, rr->resrec.name), mDNSfalse); if (err) debugf("ERROR: SendRecordDeregistration - mDNSSendDNSMessage - %d", err); - //if (rr->state == regState_DeregPending) CompleteDeregistration(m, rr); // Don't touch rr after this + //if (rr->state == regState_DeregPending) CompleteDeregistration(m, rr); // Don't touch rr after this } SetRecordRetry(m, rr, 0); return; @@ -4684,7 +4594,7 @@ mDNSlocal void handle_unanswered_query(mDNS *const m) // the middlebox is DNSSEC aware. If we receive at least one response to a DNSSEC // question, we don't turn off validation. Also, we wait for MAX_DNSSEC_RETRANSMISSIONS // before turning off validation to accomodate packet loss. - // + // // Note: req_DO affects only DNSSEC_VALIDATION_SECURE_OPTIONAL questions; // DNSSEC_VALIDATION_SECURE questions ignores req_DO. @@ -4700,17 +4610,37 @@ mDNSlocal void handle_unanswered_query(mDNS *const m) if (!q->qDNSServer->req_DO) { - q->ValidationState = DNSSECValNotRequired; + q->ValidationState = DNSSECValNotRequired; q->ValidationRequired = DNSSEC_VALIDATION_NONE; - + if (q->ProxyQuestion) q->ProxyDNSSECOK = mDNSfalse; - LogInfo("handle_unanswered_query: unanswered query for %##s (%s), so turned off validation for %#a", + LogInfo("handle_unanswered_query: unanswered query for %##s (%s), so turned off validation for %#a", q->qname.c, DNSTypeName(q->qtype), &q->qDNSServer->addr); } } } +mDNSlocal void uDNS_HandleLLQState(mDNS *const m, DNSQuestion *q) +{ +#ifdef DNS_PUSH_ENABLED + // First attempt to use DNS Push Notification. + if (q->dnsPushState == DNSPUSH_INIT) + DiscoverDNSPushNotificationServer(m, q); +#endif // DNS_PUSH_ENABLED + switch (q->state) + { + case LLQ_InitialRequest: startLLQHandshake(m, q); break; + case LLQ_SecondaryRequest: + // For PrivateQueries, we need to start the handshake again as we don't do the Challenge/Response step + if (PrivateQuery(q)) startLLQHandshake(m, q); + else sendChallengeResponse(m, q, mDNSNULL); + break; + case LLQ_Established: sendLLQRefresh(m, q); break; + case LLQ_Poll: break; // Do nothing (handled below) + } +} + // The question to be checked is not passed in as an explicit parameter; // instead it is implicit that the question to be checked is m->CurrentQuestion. mDNSexport void uDNS_CheckCurrentQuestion(mDNS *const m) @@ -4720,22 +4650,10 @@ mDNSexport void uDNS_CheckCurrentQuestion(mDNS *const m) if (q->LongLived) { - switch (q->state) - { - case LLQ_InitialRequest: startLLQHandshake(m, q); break; - case LLQ_SecondaryRequest: - // For PrivateQueries, we need to start the handshake again as we don't do the Challenge/Response step - if (PrivateQuery(q)) - startLLQHandshake(m, q); - else - sendChallengeResponse(m, q, mDNSNULL); - break; - case LLQ_Established: sendLLQRefresh(m, q); break; - case LLQ_Poll: break; // Do nothing (handled below) - } + uDNS_HandleLLQState(m,q); } - handle_unanswered_query(m); + handle_unanswered_query(m); // We repeat the check above (rather than just making this the "else" case) because startLLQHandshake can change q->state to LLQ_Poll if (!(q->LongLived && q->state != LLQ_Poll)) { @@ -4776,44 +4694,32 @@ mDNSexport void uDNS_CheckCurrentQuestion(mDNS *const m) new = GetServerForQuestion(m, q); if (new) { - 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 : zeroIPPort), q->ThisQInterval); DNSServerChangeForQuestion(m, q, new); } for (qptr = q->next ; qptr; qptr = qptr->next) if (qptr->DuplicateOf == q) { qptr->validDNSServers = q->validDNSServers; qptr->qDNSServer = q->qDNSServer; } } - if (q->qDNSServer && q->qDNSServer->teststate != DNSServer_Disabled) + if (q->qDNSServer) { - mDNSu8 *end = m->omsg.data; + mDNSu8 *end; mStatus err = mStatus_NoError; mDNSBool private = mDNSfalse; InitializeDNSMessage(&m->omsg.h, q->TargetQID, (DNSSECQuestion(q) ? DNSSecQFlags : uQueryFlags)); - if (q->qDNSServer->teststate != DNSServer_Untested || NoTestQuery(q)) - { - end = putQuestion(&m->omsg, m->omsg.data, m->omsg.data + AbsoluteMaxDNSMessageData, &q->qname, q->qtype, q->qclass); - if (DNSSECQuestion(q) && !q->qDNSServer->cellIntf) - { - if (q->ProxyQuestion) - end = DNSProxySetAttributes(q, &m->omsg.h, &m->omsg, end, m->omsg.data + AbsoluteMaxDNSMessageData); - else - end = putDNSSECOption(&m->omsg, end, m->omsg.data + AbsoluteMaxDNSMessageData); - } - private = PrivateQuery(q); - } - else if (m->timenow - q->qDNSServer->lasttest >= INIT_UCAST_POLL_INTERVAL) // Make sure at least three seconds has elapsed since last test query + end = putQuestion(&m->omsg, m->omsg.data, m->omsg.data + AbsoluteMaxDNSMessageData, &q->qname, q->qtype, q->qclass); + if (DNSSECQuestion(q) && !q->qDNSServer->cellIntf) { - LogInfo("Sending DNS test query to %#a:%d", &q->qDNSServer->addr, mDNSVal16(q->qDNSServer->port)); - q->ThisQInterval = INIT_UCAST_POLL_INTERVAL / QuestionIntervalStep; - q->qDNSServer->lasttest = m->timenow; - end = putQuestion(&m->omsg, m->omsg.data, m->omsg.data + AbsoluteMaxDNSMessageData, DNSRelayTestQuestion, kDNSType_PTR, kDNSClass_IN); - q->qDNSServer->testid = m->omsg.h.id; + if (q->ProxyQuestion) + end = DNSProxySetAttributes(q, &m->omsg.h, &m->omsg, end, m->omsg.data + AbsoluteMaxDNSMessageData); + else + end = putDNSSECOption(&m->omsg, end, m->omsg.data + AbsoluteMaxDNSMessageData); } + private = PrivateQuery(q); - if (end > m->omsg.data && (q->qDNSServer->teststate != DNSServer_Failed || NoTestQuery(q))) + if (end > m->omsg.data) { //LogMsg("uDNS_CheckCurrentQuestion %p %d %p %##s (%s)", q, NextQSendTime(q) - m->timenow, private, q->qname.c, DNSTypeName(q->qtype)); if (private) @@ -4824,15 +4730,28 @@ 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 : zp), q->unansweredQueries); + q->qDNSServer ? &q->qDNSServer->addr : mDNSNULL, mDNSVal16(q->qDNSServer ? q->qDNSServer->port : zeroIPPort), q->unansweredQueries); +#if APPLE_OSX_mDNSResponder + // When a DNS proxy network extension initiates the close of a UDP flow (this usually happens when a DNS + // proxy gets disabled or crashes), mDNSResponder's corresponding UDP socket will be marked with the + // SS_CANTRCVMORE state flag. Reading from such a socket is no longer possible, so close the current + // socket pair so that we can create a new pair. + if (q->LocalSocket && mDNSPlatformUDPSocketEncounteredEOF(q->LocalSocket)) + { + mDNSPlatformUDPClose(q->LocalSocket); + q->LocalSocket = mDNSNULL; + } +#endif if (!q->LocalSocket) { - q->LocalSocket = mDNSPlatformUDPSocket(m, zeroIPPort); + q->LocalSocket = mDNSPlatformUDPSocket(zeroIPPort); if (q->LocalSocket) - mDNSPlatformSetuDNSSocktOpt(q->LocalSocket, &q->qDNSServer->addr, q); + { + mDNSPlatformSetSocktOpt(q->LocalSocket, mDNSTransport_UDP, mDNSAddrType_IPv4, q); + mDNSPlatformSetSocktOpt(q->LocalSocket, mDNSTransport_UDP, mDNSAddrType_IPv6, q); + } } if (!q->LocalSocket) err = mStatus_NoMemoryErr; // If failed to make socket (should be very rare), we'll try again next time else @@ -4841,6 +4760,11 @@ mDNSexport void uDNS_CheckCurrentQuestion(mDNS *const m) #if TARGET_OS_EMBEDDED if (!err) { + if (q->metrics.answered) + { + q->metrics.querySendCount = 0; + q->metrics.answered = mDNSfalse; + } if (q->metrics.querySendCount++ == 0) { q->metrics.firstQueryTime = m->timenow; @@ -4851,32 +4775,77 @@ mDNSexport void uDNS_CheckCurrentQuestion(mDNS *const m) } } - if (err != mStatus_TransientErr) // if it is not a transient error backoff and DO NOT flood queries unnecessarily + if (err == mStatus_HostUnreachErr) { - q->ThisQInterval = q->ThisQInterval * QuestionIntervalStep; // Only increase interval if send succeeded - q->unansweredQueries++; - if (q->ThisQInterval > MAX_UCAST_POLL_INTERVAL) - q->ThisQInterval = MAX_UCAST_POLL_INTERVAL; - if (private && q->state != LLQ_Poll) + DNSServer *newServer; + + LogInfo("uDNS_CheckCurrentQuestion: host unreachable error for DNS server %#a for question [%p] %##s (%s)", + &q->qDNSServer->addr, q, q->qname.c, DNSTypeName(q->qtype)); + + if (!StrictUnicastOrdering) { - // We don't want to retransmit too soon. Hence, we always schedule our first - // retransmisson at 3 seconds rather than one second - if (q->ThisQInterval < (3 * mDNSPlatformOneSecond)) - q->ThisQInterval = q->ThisQInterval * QuestionIntervalStep; - if (q->ThisQInterval > LLQ_POLL_INTERVAL) - q->ThisQInterval = LLQ_POLL_INTERVAL; - LogInfo("uDNS_CheckCurrentQuestion: private non polling question for %##s (%s) will be retried in %d ms", q->qname.c, DNSTypeName(q->qtype), q->ThisQInterval); + q->qDNSServer->penaltyTime = NonZeroTime(m->timenow + DNSSERVER_PENALTY_TIME); + } + + newServer = GetServerForQuestion(m, q); + if (!newServer) + { + q->triedAllServersOnce = 1; + SetValidDNSServers(m, q); + newServer = GetServerForQuestion(m, q); + } + if (newServer) + { + LogInfo("uDNS_checkCurrentQuestion: Retrying question %p %##s (%s) DNS Server %#a:%u ThisQInterval %d", + q, q->qname.c, DNSTypeName(q->qtype), newServer ? &newServer->addr : mDNSNULL, mDNSVal16(newServer ? newServer->port : zeroIPPort), q->ThisQInterval); + DNSServerChangeForQuestion(m, q, newServer); } - if (q->qDNSServer->cellIntf) + if (q->triedAllServersOnce) + { + q->LastQTime = m->timenow; + } + else { - // We don't want to retransmit too soon. Schedule our first retransmisson at - // MIN_UCAST_RETRANS_TIMEOUT seconds. - if (q->ThisQInterval < MIN_UCAST_RETRANS_TIMEOUT) - q->ThisQInterval = MIN_UCAST_RETRANS_TIMEOUT; + q->ThisQInterval = InitialQuestionInterval; + q->LastQTime = m->timenow - q->ThisQInterval; } - debugf("uDNS_CheckCurrentQuestion: Increased ThisQInterval to %d for %##s (%s), cell %d", q->ThisQInterval, q->qname.c, DNSTypeName(q->qtype), q->qDNSServer->cellIntf); + q->unansweredQueries = 0; + } + else + { + if (err != mStatus_TransientErr) // if it is not a transient error backoff and DO NOT flood queries unnecessarily + { + // If all DNS Servers are not responding, then we back-off using the multiplier UDNSBackOffMultiplier(*2). + // Only increase interval if send succeeded + + q->ThisQInterval = q->ThisQInterval * UDNSBackOffMultiplier; + if ((q->ThisQInterval > 0) && (q->ThisQInterval < MinQuestionInterval)) // We do not want to retx within 1 sec + q->ThisQInterval = MinQuestionInterval; + + q->unansweredQueries++; + if (q->ThisQInterval > MAX_UCAST_POLL_INTERVAL) + q->ThisQInterval = MAX_UCAST_POLL_INTERVAL; + if (private && q->state != LLQ_Poll) + { + // We don't want to retransmit too soon. Hence, we always schedule our first + // retransmisson at 3 seconds rather than one second + if (q->ThisQInterval < (3 * mDNSPlatformOneSecond)) + q->ThisQInterval = q->ThisQInterval * QuestionIntervalStep; + if (q->ThisQInterval > LLQ_POLL_INTERVAL) + q->ThisQInterval = LLQ_POLL_INTERVAL; + LogInfo("uDNS_CheckCurrentQuestion: private non polling question for %##s (%s) will be retried in %d ms", q->qname.c, DNSTypeName(q->qtype), q->ThisQInterval); + } + if (q->qDNSServer->cellIntf) + { + // We don't want to retransmit too soon. Schedule our first retransmisson at + // MIN_UCAST_RETRANS_TIMEOUT seconds. + if (q->ThisQInterval < MIN_UCAST_RETRANS_TIMEOUT) + q->ThisQInterval = MIN_UCAST_RETRANS_TIMEOUT; + } + debugf("uDNS_CheckCurrentQuestion: Increased ThisQInterval to %d for %##s (%s), cell %d", q->ThisQInterval, q->qname.c, DNSTypeName(q->qtype), q->qDNSServer->cellIntf); + } + q->LastQTime = m->timenow; } - q->LastQTime = m->timenow; SetNextQueryTime(m, q); } else @@ -4890,20 +4859,20 @@ mDNSexport void uDNS_CheckCurrentQuestion(mDNS *const m) // passed to uDNS_CheckCurrentQuestion -- we only want one set of query packets hitting the wire -- // but we want *all* of the questions to get answer callbacks.) CacheRecord *rr; - const mDNSu32 slot = HashSlot(&q->qname); - CacheGroup *const cg = CacheGroupForName(m, slot, q->qnamehash, &q->qname); + const mDNSu32 slot = HashSlotFromNameHash(q->qnamehash); + CacheGroup *const cg = CacheGroupForName(m, q->qnamehash, &q->qname); if (!q->qDNSServer) { - if (!mDNSOpaque64IsZero(&q->validDNSServers)) - LogMsg("uDNS_CheckCurrentQuestion: ERROR!!: valid DNSServer bits not zero 0x%x, 0x%x for question %##s (%s)", - q->validDNSServers.l[1], q->validDNSServers.l[0], q->qname.c, DNSTypeName(q->qtype)); + if (!mDNSOpaque128IsZero(&q->validDNSServers)) + LogMsg("uDNS_CheckCurrentQuestion: ERROR!!: valid DNSServer bits not zero 0x%x, 0x%x 0x%x 0x%x for question %##s (%s)", + q->validDNSServers.l[3], q->validDNSServers.l[2], q->validDNSServers.l[1], q->validDNSServers.l[0], q->qname.c, DNSTypeName(q->qtype)); // If we reached the end of list while picking DNS servers, then we don't want to deactivate the // question. Try after 60 seconds. We find this by looking for valid DNSServers for this question, // if we find any, then we must have tried them before we came here. This avoids maintaining // another state variable to see if we had valid DNS servers for this question. SetValidDNSServers(m, q); - if (mDNSOpaque64IsZero(&q->validDNSServers)) + if (mDNSOpaque128IsZero(&q->validDNSServers)) { LogInfo("uDNS_CheckCurrentQuestion: no DNS server for %##s (%s)", q->qname.c, DNSTypeName(q->qtype)); q->ThisQInterval = 0; @@ -4922,12 +4891,9 @@ mDNSexport void uDNS_CheckCurrentQuestion(mDNS *const m) q->qDNSServer = GetServerForQuestion(m, q); for (qptr = q->next ; qptr; qptr = qptr->next) 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); - } + q->qDNSServer ? &q->qDNSServer->addr : mDNSNULL, mDNSVal16(q->qDNSServer ? q->qDNSServer->port : zeroIPPort), q->ThisQInterval); } } else @@ -4942,7 +4908,7 @@ mDNSexport void uDNS_CheckCurrentQuestion(mDNS *const m) { if (SameNameRecordAnswersQuestion(&rr->resrec, q)) { - LogInfo("uDNS_CheckCurrentQuestion: Purged resourcerecord %s", CRDisplayString(m, rr)); + LogInfo("uDNS_CheckCurrentQuestion: Purged resourcerecord %s", CRDisplayString(m, rr)); mDNS_PurgeCacheResourceRecord(m, rr); } } @@ -4970,7 +4936,7 @@ mDNSexport void CheckNATMappings(mDNS *m) { mDNSBool rfc1918 = mDNSv4AddrIsRFC1918(&m->AdvertisedV4.ip.v4); mDNSBool HaveRoutable = !rfc1918 && !mDNSIPv4AddressIsZero(m->AdvertisedV4.ip.v4); - m->NextScheduledNATOp = m->timenow + 0x3FFFFFFF; + m->NextScheduledNATOp = m->timenow + FutureTime; if (HaveRoutable) m->ExtAddress = m->AdvertisedV4.ip.v4; @@ -4980,7 +4946,7 @@ mDNSexport void CheckNATMappings(mDNS *m) { // we need to log a message if we can't get our socket, but only the first time (after success) static mDNSBool needLog = mDNStrue; - m->NATMcastRecvskt = mDNSPlatformUDPSocket(m, NATPMPAnnouncementPort); + m->NATMcastRecvskt = mDNSPlatformUDPSocket(NATPMPAnnouncementPort); if (!m->NATMcastRecvskt) { if (needLog) @@ -5025,7 +4991,7 @@ mDNSexport void CheckNATMappings(mDNS *m) cur->retryInterval = NATMAP_INIT_RETRY; } - (void)uDNS_SendNATMsg(m, cur, mDNStrue); // Will also do UPnP discovery for us, if necessary + uDNS_SendNATMsg(m, cur, mDNStrue); // Will also do UPnP discovery for us, if necessary if (cur->ExpiryTime) // If have active mapping then set next renewal time halfway to expiry NATSetNextRenewalTime(m, cur); @@ -5062,14 +5028,8 @@ 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; - - if (HaveRoutable) - ExternalPort = cur->IntPort; - else if (!mDNSIPv4AddressIsZero(EffectiveAddress) && cur->ExpiryTime) - ExternalPort = cur->RequestedPort; - else - ExternalPort = zeroIPPort; + const mDNSIPPort ExternalPort = HaveRoutable ? cur->IntPort : + !mDNSIPv4AddressIsZero(EffectiveAddress) && cur->ExpiryTime ? cur->RequestedPort : zeroIPPort; if (!cur->Protocol || HaveRoutable || cur->ExpiryTime || cur->retryInterval > NATMAP_INIT_RETRY * 8) { @@ -5107,7 +5067,7 @@ mDNSexport void CheckNATMappings(mDNS *m) mDNSlocal mDNSs32 CheckRecordUpdates(mDNS *m) { AuthRecord *rr; - mDNSs32 nextevent = m->timenow + 0x3FFFFFFF; + mDNSs32 nextevent = m->timenow + FutureTime; CheckGroupRecordUpdates(m); @@ -5165,7 +5125,7 @@ mDNSexport void uDNS_Tasks(mDNS *const m) mDNSs32 nexte; DNSServer *d; - m->NextuDNSEvent = m->timenow + 0x3FFFFFFF; + m->NextuDNSEvent = m->timenow + FutureTime; nexte = CheckRecordUpdates(m); if (m->NextuDNSEvent - nexte > 0) @@ -5358,8 +5318,8 @@ mDNSexport void udns_validatelists(void *const v) DNSServer *d; for (d = m->DNSServers; d; d=d->next) - if (d->next == (DNSServer *)~0 || d->teststate > DNSServer_Disabled) - LogMemCorruption("m->DNSServers: %p is garbage (%d)", d, d->teststate); + if (d->next == (DNSServer *)~0) + LogMemCorruption("m->DNSServers: %p is garbage", d); DomainAuthInfo *info; for (info = m->AuthInfoList; info; info = info->next) @@ -5460,7 +5420,7 @@ mDNSexport void uDNS_SetupWABQueries(mDNS *const m) // Make sure we have the search domains from the platform layer so that if we start the WAB // queries below, we have the latest information. mDNS_Lock(m); - if (!mDNSPlatformSetDNSConfig(m, mDNSfalse, mDNStrue, mDNSNULL, mDNSNULL, mDNSNULL, mDNSfalse)) + if (!mDNSPlatformSetDNSConfig(mDNSfalse, mDNStrue, mDNSNULL, mDNSNULL, mDNSNULL, mDNSfalse)) { // If the configuration did not change, clear the flag so that we don't free the searchlist. // We still have to start the domain enumeration queries as we may not have started them @@ -5708,11 +5668,10 @@ mDNSexport void uDNS_StopWABQueries(mDNS *const m, int queryType) uDNS_SetupWABQueries(m); } -mDNSexport domainname *uDNS_GetNextSearchDomain(mDNS *const m, mDNSInterfaceID InterfaceID, mDNSs8 *searchIndex, mDNSBool ignoreDotLocal) +mDNSexport domainname *uDNS_GetNextSearchDomain(mDNSInterfaceID InterfaceID, mDNSs8 *searchIndex, mDNSBool ignoreDotLocal) { SearchListElem *p = SearchList; int count = *searchIndex; - (void) m; // unused if (count < 0) { LogMsg("uDNS_GetNextSearchDomain: count %d less than zero", count); return mDNSNULL; } @@ -5831,101 +5790,335 @@ struct CompileTimeAssertionChecks_uDNS char sizecheck_SearchListElem[(sizeof(SearchListElem) <= 5000) ? 1 : -1]; }; +#if COMPILER_LIKES_PRAGMA_MARK +#pragma mark - DNS Push Notification functions +#endif + +#ifdef DNS_PUSH_ENABLED +mDNSlocal tcpInfo_t * GetTCPConnectionToPushServer(mDNS *m, DNSQuestion *q) +{ + DNSPushNotificationZone *zone; + DNSPushNotificationServer *server; + DNSPushNotificationZone *newZone; + DNSPushNotificationServer *newServer; + + // If we already have a question for this zone and if the server is the same, reuse it + for (zone = m->DNSPushZones; zone != mDNSNULL; zone = zone->next) + { + if (SameDomainName(&q->nta->ChildName, &zone->zoneName)) + { + DNSPushNotificationServer *zoneServer = mDNSNULL; + for (zoneServer = zone->servers; zoneServer != mDNSNULL; zoneServer = zoneServer->next) + { + if (mDNSSameAddress(&q->dnsPushServerAddr, &zoneServer->serverAddr)) + { + zone->numberOfQuestions++; + zoneServer->numberOfQuestions++; + return zoneServer->connection; + } + } + } + } + + // If we have a connection to this server but it is for a differnt zone, create a new zone entry and reuse the connection + for (server = m->DNSPushServers; server != mDNSNULL; server = server->next) + { + if (mDNSSameAddress(&q->dnsPushServerAddr, &server->serverAddr)) + { + newZone = mDNSPlatformMemAllocate(sizeof(DNSPushNotificationZone)); + newZone->numberOfQuestions = 1; + newZone->zoneName = q->nta->ChildName; + newZone->servers = server; + + // Add the new zone to the begining of the list + newZone->next = m->DNSPushZones; + m->DNSPushZones = newZone; + + server->numberOfQuestions++; + return server->connection; + } + } + + // If we do not have any existing connections, create a new connection + newServer = mDNSPlatformMemAllocate(sizeof(DNSPushNotificationServer)); + newZone = mDNSPlatformMemAllocate(sizeof(DNSPushNotificationZone)); + + newServer->numberOfQuestions = 1; + newServer->serverAddr = q->dnsPushServerAddr; + newServer->connection = MakeTCPConn(m, mDNSNULL, mDNSNULL, kTCPSocketFlags_UseTLS, &q->dnsPushServerAddr, q->dnsPushServerPort, &q->nta->Host, q, mDNSNULL); + + newZone->numberOfQuestions = 1; + newZone->zoneName = q->nta->ChildName; + newZone->servers = newServer; + + // Add the new zone to the begining of the list + newZone->next = m->DNSPushZones; + m->DNSPushZones = newZone; + + newServer->next = m->DNSPushServers; + m->DNSPushServers = newServer; + return newServer->connection; +} + +mDNSexport void DiscoverDNSPushNotificationServer(mDNS *m, DNSQuestion *q) +{ + /* Use the same NAT setup as in the LLQ case */ + if (m->LLQNAT.clientContext != mDNSNULL) // LLQNAT just started, give it some time + { + LogInfo("startLLQHandshake: waiting for NAT status for %##s (%s)", q->qname.c, DNSTypeName(q->qtype)); + q->ThisQInterval = LLQ_POLL_INTERVAL + mDNSRandom(LLQ_POLL_INTERVAL/10); // Retry in approx 15 minutes + q->LastQTime = m->timenow; + SetNextQueryTime(m, q); + return; + } + + // Either we don't have {PCP, NAT-PMP, UPnP/IGD} support (ExternalPort is zero) or behind a Double NAT that may or + // may not have {PCP, NAT-PMP, UPnP/IGD} support (NATResult is non-zero) + if (mDNSIPPortIsZero(m->LLQNAT.ExternalPort) || m->LLQNAT.Result) + { + LogInfo("startLLQHandshake: Cannot receive inbound packets; will poll for %##s (%s) External Port %d, NAT Result %d", + q->qname.c, DNSTypeName(q->qtype), mDNSVal16(m->LLQNAT.ExternalPort), m->LLQNAT.Result); + StartLLQPolling(m, q); // Actually sets up the NAT Auto Tunnel + return; + } + + if (mDNSIPPortIsZero(q->dnsPushServerPort) && q->dnsPushState == DNSPUSH_INIT) + { + LogInfo("SubscribeToDNSPushNotificationServer: StartGetZoneData for %##s (%s)", q->qname.c, DNSTypeName(q->qtype)); + q->ThisQInterval = LLQ_POLL_INTERVAL + mDNSRandom(LLQ_POLL_INTERVAL/10); // Retry in approx 15 minutes + q->LastQTime = m->timenow; + SetNextQueryTime(m, q); + q->dnsPushServerAddr = zeroAddr; + // We know q->dnsPushServerPort is zero because of check above + if (q->nta) CancelGetZoneData(m, q->nta); + q->nta = StartGetZoneData(m, &q->qname, ZoneServiceDNSPush, DNSPushNotificationGotZoneData, q); + return; + } + + if (q->tcp) + { + LogInfo("SubscribeToDNSPushNotificationServer: Disposing existing TCP connection for %##s (%s)", q->qname.c, DNSTypeName(q->qtype)); + DisposeTCPConn(q->tcp); + q->tcp = mDNSNULL; + } + + if (!q->nta) + { + // Normally we lookup the zone data and then call this function. And we never free the zone data + // for "PrivateQuery". But sometimes this can happen due to some race conditions. When we + // switch networks, we might end up "Polling" the network e.g., we are behind a Double NAT. + // When we poll, we free the zone information as we send the query to the server (See + // PrivateQueryGotZoneData). The NAT callback (LLQNATCallback) may happen soon after that. If we + // are still behind Double NAT, we would have returned early in this function. But we could + // have switched to a network with no NATs and we should get the zone data again. + LogInfo("SubscribeToDNSPushNotificationServer: nta is NULL for %##s (%s)", q->qname.c, DNSTypeName(q->qtype)); + q->nta = StartGetZoneData(m, &q->qname, ZoneServiceDNSPush, DNSPushNotificationGotZoneData, q); + return; + } + else if (!q->nta->Host.c[0]) + { + // This should not happen. If it happens, we print a log and MakeTCPConn will fail if it can't find a hostname + LogMsg("SubscribeToDNSPushNotificationServer: ERROR!!: nta non NULL for %##s (%s) but HostName %d NULL, LongLived %d", q->qname.c, DNSTypeName(q->qtype), q->nta->Host.c[0], q->LongLived); + } + q->tcp = GetTCPConnectionToPushServer(m,q); + // If TCP failed (transient networking glitch) try again in five seconds + q->ThisQInterval = (q->tcp != mDNSNULL) ? q->ThisQInterval = 0 : (mDNSPlatformOneSecond * 5); + q->LastQTime = m->timenow; + SetNextQueryTime(m, q); +} + + +mDNSexport void SubscribeToDNSPushNotificationServer(mDNS *m, DNSQuestion *q) +{ + mDNSu8 *end = mDNSNULL; + InitializeDNSMessage(&m->omsg.h, zeroID, SubscribeFlags); + end = putQuestion(&m->omsg, end, m->omsg.data + AbsoluteMaxDNSMessageData, &q->qname, q->qtype, q->qclass); + if (!end) + { + LogMsg("ERROR: SubscribeToDNSPushNotificationServer putQuestion failed"); + return; + } + + mDNSSendDNSMessage(m, &m->omsg, end, mDNSInterface_Any, q->LocalSocket, &q->dnsPushServerAddr, q->dnsPushServerPort, q->tcp->sock, mDNSNULL, mDNSfalse); + + // update question state + q->dnsPushState = DNSPUSH_ESTABLISHED; + q->ThisQInterval = (kLLQ_INIT_RESEND * mDNSPlatformOneSecond); + q->LastQTime = m->timenow; + SetNextQueryTime(m, q); + +} + +mDNSlocal void reconcileDNSPushConnection(mDNS *m, DNSQuestion *q) +{ + DNSPushNotificationZone *zone; + DNSPushNotificationServer *server; + DNSPushNotificationServer *nextServer; + DNSPushNotificationZone *nextZone; + + // Update the counts + for (zone = m->DNSPushZones; zone != mDNSNULL; zone = zone->next) + { + if (SameDomainName(&zone->zoneName, &q->nta->ChildName)) + { + zone->numberOfQuestions--; + for (server = zone->servers; server != mDNSNULL; server = server->next) + { + if (mDNSSameAddress(&server->serverAddr, &q->dnsPushServerAddr)) + server->numberOfQuestions--; + } + } + } + + // Now prune the lists + server = m->DNSPushServers; + nextServer = mDNSNULL; + while(server != mDNSNULL) + { + nextServer = server->next; + if (server->numberOfQuestions <= 0) + { + DisposeTCPConn(server->connection); + if (server == m->DNSPushServers) + m->DNSPushServers = nextServer; + mDNSPlatformMemFree(server); + server = nextServer; + } + else server = server->next; + } + + zone = m->DNSPushZones; + nextZone = mDNSNULL; + while(zone != mDNSNULL) + { + nextZone = zone->next; + if (zone->numberOfQuestions <= 0) + { + if (zone == m->DNSPushZones) + m->DNSPushZones = nextZone; + mDNSPlatformMemFree(zone); + zone = nextZone; + } + else zone = zone->next; + } + +} + +mDNSexport void UnSubscribeToDNSPushNotificationServer(mDNS *m, DNSQuestion *q) +{ + mDNSu8 *end = mDNSNULL; + InitializeDNSMessage(&m->omsg.h, q->TargetQID, UnSubscribeFlags); + end = putQuestion(&m->omsg, end, m->omsg.data + AbsoluteMaxDNSMessageData, &q->qname, q->qtype, q->qclass); + if (!end) + { + LogMsg("ERROR: UnSubscribeToDNSPushNotificationServer - putQuestion failed"); + return; + } + + mDNSSendDNSMessage(m, &m->omsg, end, mDNSInterface_Any, q->LocalSocket, &q->dnsPushServerAddr, q->dnsPushServerPort, q->tcp->sock, mDNSNULL, mDNSfalse); + + reconcileDNSPushConnection(m, q); +} + +#endif // DNS_PUSH_ENABLED +#if COMPILER_LIKES_PRAGMA_MARK +#pragma mark - +#endif #else // !UNICAST_DISABLED mDNSexport const domainname *GetServiceTarget(mDNS *m, AuthRecord *const rr) { - (void) m; - (void) rr; + (void) m; + (void) rr; - return mDNSNULL; + return mDNSNULL; } mDNSexport DomainAuthInfo *GetAuthInfoForName_internal(mDNS *m, const domainname *const name) { - (void) m; - (void) name; + (void) m; + (void) name; - return mDNSNULL; + return mDNSNULL; } mDNSexport DomainAuthInfo *GetAuthInfoForQuestion(mDNS *m, const DNSQuestion *const q) { - (void) m; - (void) q; + (void) m; + (void) q; - return mDNSNULL; + return mDNSNULL; } mDNSexport void startLLQHandshake(mDNS *m, DNSQuestion *q) { - (void) m; - (void) q; + (void) m; + (void) q; } mDNSexport void DisposeTCPConn(struct tcpInfo_t *tcp) { - (void) tcp; + (void) tcp; } mDNSexport mStatus mDNS_StartNATOperation_internal(mDNS *m, NATTraversalInfo *traversal) { - (void) m; - (void) traversal; + (void) m; + (void) traversal; - return mStatus_UnsupportedErr; + return mStatus_UnsupportedErr; } mDNSexport mStatus mDNS_StopNATOperation_internal(mDNS *m, NATTraversalInfo *traversal) { - (void) m; - (void) traversal; + (void) m; + (void) traversal; - return mStatus_UnsupportedErr; + return mStatus_UnsupportedErr; } mDNSexport void sendLLQRefresh(mDNS *m, DNSQuestion *q) { - (void) m; - (void) q; + (void) m; + (void) q; } mDNSexport ZoneData *StartGetZoneData(mDNS *const m, const domainname *const name, const ZoneService target, ZoneDataCallback callback, void *ZoneDataContext) { - (void) m; - (void) name; - (void) target; - (void) callback; - (void) ZoneDataContext; + (void) m; + (void) name; + (void) target; + (void) callback; + (void) ZoneDataContext; - return mDNSNULL; + return mDNSNULL; } mDNSexport void RecordRegistrationGotZoneData(mDNS *const m, mStatus err, const ZoneData *zoneData) { - (void) m; - (void) err; - (void) zoneData; + (void) m; + (void) err; + (void) zoneData; } mDNSexport uDNS_LLQType uDNS_recvLLQResponse(mDNS *const m, const DNSMessage *const msg, const mDNSu8 *const end, const mDNSAddr *const srcaddr, const mDNSIPPort srcport, DNSQuestion **matchQuestion) { - (void) m; - (void) msg; - (void) end; - (void) srcaddr; - (void) srcport; - (void) matchQuestion; + (void) m; + (void) msg; + (void) end; + (void) srcaddr; + (void) srcport; + (void) matchQuestion; - return uDNS_LLQ_Not; + return uDNS_LLQ_Not; } mDNSexport void PenalizeDNSServer(mDNS *const m, DNSQuestion *q, mDNSOpaque16 responseFlags) { - (void) m; - (void) q; - (void) responseFlags; + (void) m; + (void) q; + (void) responseFlags; } mDNSexport void mDNS_AddSearchDomain(const domainname *const domain, mDNSInterfaceID InterfaceID) @@ -5949,17 +6142,16 @@ mDNSexport mStatus mDNS_SetSecretForDomain(mDNS *m, DomainAuthInfo *info, const (void) hostname; (void) port; (void) autoTunnel; - + return mStatus_UnsupportedErr; } -mDNSexport domainname *uDNS_GetNextSearchDomain(mDNS *const m, mDNSInterfaceID InterfaceID, mDNSs8 *searchIndex, mDNSBool ignoreDotLocal) +mDNSexport domainname *uDNS_GetNextSearchDomain(mDNSInterfaceID InterfaceID, mDNSs8 *searchIndex, mDNSBool ignoreDotLocal) { - (void) m; (void) InterfaceID; (void) searchIndex; (void) ignoreDotLocal; - + return mDNSNULL; } @@ -5967,7 +6159,7 @@ mDNSexport DomainAuthInfo *GetAuthInfoForName(mDNS *m, const domainname *const n { (void) m; (void) name; - + return mDNSNULL; } @@ -5975,7 +6167,7 @@ mDNSexport mStatus mDNS_StartNATOperation(mDNS *const m, NATTraversalInfo *trave { (void) m; (void) traversal; - + return mStatus_UnsupportedErr; } @@ -5983,13 +6175,13 @@ mDNSexport mStatus mDNS_StopNATOperation(mDNS *const m, NATTraversalInfo *traver { (void) m; (void) traversal; - + return mStatus_UnsupportedErr; } mDNSexport DNSServer *mDNS_AddDNSServer(mDNS *const m, const domainname *d, const mDNSInterfaceID interface, const mDNSs32 serviceID, const mDNSAddr *addr, - const mDNSIPPort port, mDNSu32 scoped, mDNSu32 timeout, mDNSBool cellIntf, mDNSu16 resGroupID, mDNSBool reqA, - mDNSBool reqAAAA, mDNSBool reqDO) + const mDNSIPPort port, mDNSu32 scoped, mDNSu32 timeout, mDNSBool cellIntf, mDNSBool isExpensive, mDNSu16 resGroupID, + mDNSBool reqA, mDNSBool reqAAAA, mDNSBool reqDO) { (void) m; (void) d; @@ -6000,11 +6192,12 @@ mDNSexport DNSServer *mDNS_AddDNSServer(mDNS *const m, const domainname *d, cons (void) scoped; (void) timeout; (void) cellIntf; + (void) isExpensive; (void) resGroupID; (void) reqA; (void) reqAAAA; (void) reqDO; - + return mDNSNULL; } @@ -6055,8 +6248,26 @@ mDNSexport void RecreateNATMappings(mDNS *const m, const mDNSu32 waitTicks) mDNSexport mDNSBool IsGetZoneDataQuestion(DNSQuestion *q) { (void)q; - + return mDNSfalse; } +mDNSexport void SubscribeToDNSPushNotificationServer(mDNS *m, DNSQuestion *q) +{ + (void)m; + (void)q; +} + +mDNSexport void UnSubscribeToDNSPushNotificationServer(mDNS *m, DNSQuestion *q) +{ + (void)m; + (void)q; +} + +mDNSexport void DiscoverDNSPushNotificationServer(mDNS *m, DNSQuestion *q) +{ + (void)m; + (void)q; +} + #endif // !UNICAST_DISABLED diff --git a/usr/src/cmd/cmd-inet/usr.lib/mdnsd/uDNS.h b/usr/src/contrib/mDNSResponder/mDNSCore/uDNS.h index eca8b70152..90f50a6fc1 100644..100755 --- a/usr/src/cmd/cmd-inet/usr.lib/mdnsd/uDNS.h +++ b/usr/src/contrib/mDNSResponder/mDNSCore/uDNS.h @@ -47,9 +47,8 @@ extern "C" { #define QuestionIntervalStep3 (QuestionIntervalStep*QuestionIntervalStep*QuestionIntervalStep) #define InitialQuestionInterval ((mDNSPlatformOneSecond + QuestionIntervalStep-1) / QuestionIntervalStep) #define MaxQuestionInterval (3600 * mDNSPlatformOneSecond) - -// just move to MaxQuestionInterval once over this threshold -#define QuestionIntervalThreshold (QuestionIntervalStep3 * mDNSPlatformOneSecond) +#define UDNSBackOffMultiplier 2 +#define MinQuestionInterval (1 * mDNSPlatformOneSecond) // For Unicast record registrations, we initialize the interval to 1 second. When we send any query for // the record registration e.g., GetZoneData, we always back off by QuestionIntervalStep @@ -82,6 +81,11 @@ extern void LLQGotZoneData(mDNS *const m, mStatus err, const ZoneData *zoneInfo) extern void startLLQHandshake(mDNS *m, DNSQuestion *q); extern void sendLLQRefresh(mDNS *m, DNSQuestion *q); +extern void DNSPushNotificationGotZoneData(mDNS *const m, mStatus err, const ZoneData *zoneInfo); +extern void DiscoverDNSPushNotificationServer(mDNS *m, DNSQuestion *q); +extern void SubscribeToDNSPushNotificationServer(mDNS *m, DNSQuestion *q); +extern void UnSubscribeToDNSPushNotificationServer(mDNS *m, DNSQuestion *q); + extern void SleepRecordRegistrations(mDNS *m); // uDNS_UpdateRecord @@ -124,7 +128,7 @@ extern mStatus uDNS_SetupDNSConfig(mDNS *const m); extern void uDNS_SetupWABQueries(mDNS *const m); extern void uDNS_StartWABQueries(mDNS *const m, int queryType); extern void uDNS_StopWABQueries(mDNS *const m, int queryType); -extern domainname *uDNS_GetNextSearchDomain(mDNS *const m, mDNSInterfaceID InterfaceID, mDNSs8 *searchIndex, mDNSBool ignoreDotLocal); +extern domainname *uDNS_GetNextSearchDomain(mDNSInterfaceID InterfaceID, mDNSs8 *searchIndex, mDNSBool ignoreDotLocal); typedef enum { @@ -144,8 +148,12 @@ extern void uDNS_ReceiveNATPacket(mDNS *m, const mDNSInterfaceID InterfaceID, mD extern void natTraversalHandleAddressReply(mDNS *const m, mDNSu16 err, mDNSv4Addr ExtAddr); extern void natTraversalHandlePortMapReply(mDNS *const m, NATTraversalInfo *n, const mDNSInterfaceID InterfaceID, mDNSu16 err, mDNSIPPort extport, mDNSu32 lease, NATTProtocol protocol); +// DNS Push Notification +extern void SubscribeToDNSPushNotification(mDNS *m, DNSQuestion *q); + + #ifdef __cplusplus } #endif -#endif // __UDNS_H_ +#endif // __UDNS_H diff --git a/usr/src/cmd/cmd-inet/usr.lib/mdnsd/PosixDaemon.c b/usr/src/contrib/mDNSResponder/mDNSPosix/PosixDaemon.c index 55edb0475d..26477da593 100644 --- a/usr/src/cmd/cmd-inet/usr.lib/mdnsd/PosixDaemon.c +++ b/usr/src/contrib/mDNSResponder/mDNSPosix/PosixDaemon.c @@ -132,11 +132,11 @@ mDNSlocal void ToggleLogPacket(void) mDNS_PacketLoggingEnabled = !mDNS_PacketLoggingEnabled; } -mDNSlocal void DumpStateLog(mDNS *const m) +mDNSlocal void DumpStateLog() // Dump a little log of what we've been up to. { - LogMsg("---- BEGIN STATE LOG ----"); - udsserver_info(m); + LogMsg("---- BEGIN STATE LOG ----"); + udsserver_info(); LogMsg("---- END STATE LOG ----"); } @@ -176,7 +176,7 @@ mDNSlocal mStatus MainLoop(mDNS *m) // Loop until we quit. (void) mDNSPosixRunEventLoopOnce(m, &timeout, &signals, &gotData); if (sigismember(&signals, SIGHUP )) Reconfigure(m); - if (sigismember(&signals, SIGINFO)) DumpStateLog(m); + if (sigismember(&signals, SIGINFO)) DumpStateLog(); if (sigismember(&signals, SIGUSR1)) ToggleLog(); if (sigismember(&signals, SIGUSR2)) ToggleLogPacket(); // SIGPIPE happens when we try to write to a dead client; death should be detected soon in request_callback() and cleaned up. @@ -260,9 +260,8 @@ mStatus udsSupportRemoveFDFromEventLoop(int fd, void *platform_data) // N return err; } -mDNSexport void RecordUpdatedNiceLabel(mDNS *const m, mDNSs32 delay) +mDNSexport void RecordUpdatedNiceLabel(mDNSs32 delay) { - (void)m; (void)delay; // No-op, for now } diff --git a/usr/src/cmd/cmd-inet/usr.lib/mdnsd/mDNSPosix.c b/usr/src/contrib/mDNSResponder/mDNSPosix/mDNSPosix.c index f16e82044a..b9c3cd58eb 100644..100755 --- a/usr/src/cmd/cmd-inet/usr.lib/mdnsd/mDNSPosix.c +++ b/usr/src/contrib/mDNSResponder/mDNSPosix/mDNSPosix.c @@ -52,6 +52,7 @@ #include "mDNSUNP.h" #include "GenLinkedList.h" +#include "dnsproxy.h" // *************************************************************************** // Structures @@ -138,7 +139,7 @@ mDNSlocal void SockAddrTomDNSAddr(const struct sockaddr *const sa, mDNSAddr *ipA // mDNS core calls this routine when it needs to send a packet. mDNSexport mStatus mDNSPlatformSendUDP(const mDNS *const m, const void *const msg, const mDNSu8 *const end, - mDNSInterfaceID InterfaceID, UDPSocket *src, const mDNSAddr *dst, + mDNSInterfaceID InterfaceID, UDPSocket *src, const mDNSAddr *dst, mDNSIPPort dstPort, mDNSBool useBackgroundTrafficClass) { int err = 0; @@ -314,16 +315,8 @@ mDNSlocal void SocketDataReady(mDNS *const m, PosixNetworkInterface *intf, int s &senderAddr, senderPort, &destAddr, MulticastDNSPort, InterfaceID); } -mDNSexport mDNSBool mDNSPlatformPeekUDP(mDNS *const m, UDPSocket *src) +mDNSexport TCPSocket *mDNSPlatformTCPSocket(TCPSocketFlags flags, mDNSIPPort * port, mDNSBool useBackgroundTrafficClass) { - (void)m; // unused - (void)src; // unused - return mDNSfalse; -} - -mDNSexport TCPSocket *mDNSPlatformTCPSocket(mDNS * const m, TCPSocketFlags flags, mDNSIPPort * port, mDNSBool useBackgroundTrafficClass) -{ - (void)m; // Unused (void)flags; // Unused (void)port; // Unused (void)useBackgroundTrafficClass; // Unused @@ -378,9 +371,8 @@ mDNSexport long mDNSPlatformWriteTCP(TCPSocket *sock, const char *msg, unsigned return 0; } -mDNSexport UDPSocket *mDNSPlatformUDPSocket(mDNS * const m, mDNSIPPort port) +mDNSexport UDPSocket *mDNSPlatformUDPSocket(mDNSIPPort port) { - (void)m; // Unused (void)port; // Unused return NULL; } @@ -390,9 +382,8 @@ mDNSexport void mDNSPlatformUDPClose(UDPSocket *sock) (void)sock; // Unused } -mDNSexport void mDNSPlatformUpdateProxyList(mDNS *const m, const mDNSInterfaceID InterfaceID) +mDNSexport void mDNSPlatformUpdateProxyList(const mDNSInterfaceID InterfaceID) { - (void)m; // Unused (void)InterfaceID; // Unused } @@ -403,9 +394,8 @@ mDNSexport void mDNSPlatformSendRawPacket(const void *const msg, const mDNSu8 *c (void)InterfaceID; // Unused } -mDNSexport void mDNSPlatformSetLocalAddressCacheEntry(mDNS *const m, const mDNSAddr *const tpa, const mDNSEthAddr *const tha, mDNSInterfaceID InterfaceID) +mDNSexport void mDNSPlatformSetLocalAddressCacheEntry(const mDNSAddr *const tpa, const mDNSEthAddr *const tha, mDNSInterfaceID InterfaceID) { - (void)m; // Unused (void)tpa; // Unused (void)tha; // Unused (void)InterfaceID; // Unused @@ -420,9 +410,8 @@ mDNSexport void mDNSPlatformTLSTearDownCerts(void) { } -mDNSexport void mDNSPlatformSetAllowSleep(mDNS *const m, mDNSBool allowSleep, const char *reason) +mDNSexport void mDNSPlatformSetAllowSleep(mDNSBool allowSleep, const char *reason) { - (void) m; (void) allowSleep; (void) reason; } @@ -445,13 +434,12 @@ mDNSexport void FreeEtcHosts(mDNS *const m, AuthRecord *const rr, mStatus result #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. + * 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, +mDNSexport mDNSBool mDNSPlatformSetDNSConfig(mDNSBool setservers, mDNSBool setsearch, domainname *const fqdn, DNameListElem **RegDomains, DNameListElem **BrowseDomains, mDNSBool ackConfig) { - (void) m; (void) setservers; if (fqdn) fqdn->c[0] = 0; (void) setsearch; @@ -462,9 +450,8 @@ mDNSexport mDNSBool mDNSPlatformSetDNSConfig(mDNS *const m, mDNSBool setservers, return mDNStrue; } -mDNSexport mStatus mDNSPlatformGetPrimaryInterface(mDNS * const m, mDNSAddr * v4, mDNSAddr * v6, mDNSAddr * router) +mDNSexport mStatus mDNSPlatformGetPrimaryInterface(mDNSAddr * v4, mDNSAddr * v6, mDNSAddr * router) { - (void) m; (void) v4; (void) v6; (void) router; @@ -519,7 +506,7 @@ mDNSexport int ParseDNSServers(mDNS *m, const char *filePath) mDNSAddr DNSAddr; DNSAddr.type = mDNSAddrType_IPv4; DNSAddr.ip.v4.NotAnInteger = ina.s_addr; - mDNS_AddDNSServer(m, NULL, mDNSInterface_Any, 0, &DNSAddr, UnicastDNSPort, kScopeNone, 0, mDNSfalse, 0, mDNStrue, mDNStrue, mDNSfalse); + mDNS_AddDNSServer(m, NULL, mDNSInterface_Any, 0, &DNSAddr, UnicastDNSPort, kScopeNone, 0, mDNSfalse, mDNSfalse, 0, mDNStrue, mDNStrue, mDNSfalse); numOfServers++; } } @@ -589,11 +576,20 @@ mDNSexport mDNSu32 mDNSPlatformInterfaceIndexfromInterfaceID(mDNS *const m, mDNS // interface must have already been deregistered with the mDNS core. mDNSlocal void FreePosixNetworkInterface(PosixNetworkInterface *intf) { + int rv; assert(intf != NULL); if (intf->intfName != NULL) free((void *)intf->intfName); - if (intf->multicastSocket4 != -1) assert(close(intf->multicastSocket4) == 0); + if (intf->multicastSocket4 != -1) + { + rv = close(intf->multicastSocket4); + assert(rv == 0); + } #if HAVE_IPV6 - if (intf->multicastSocket6 != -1) assert(close(intf->multicastSocket6) == 0); + if (intf->multicastSocket6 != -1) + { + rv = close(intf->multicastSocket6); + assert(rv == 0); + } #endif // Move interface to the RecentInterfaces list for a minute @@ -610,7 +606,7 @@ mDNSlocal void ClearInterfaceList(mDNS *const m) while (m->HostInterfaces) { PosixNetworkInterface *intf = (PosixNetworkInterface*)(m->HostInterfaces); - mDNS_DeregisterInterface(m, &intf->coreIntf, mDNSfalse); + mDNS_DeregisterInterface(m, &intf->coreIntf, NormalActivation); if (gMDNSPlatformPosixVerboseLevel > 0) fprintf(stderr, "Deregistered interface %s\n", intf->intfName); FreePosixNetworkInterface(intf); } @@ -671,9 +667,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. @@ -775,11 +771,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) { @@ -867,7 +863,13 @@ mDNSlocal int SetupSocket(struct sockaddr *intfAddr, mDNSIPPort port, int interf } // Clean up - if (err != 0 && *sktPtr != -1) { assert(close(*sktPtr) == 0); *sktPtr = -1; } + if (err != 0 && *sktPtr != -1) + { + int rv; + rv = close(*sktPtr); + assert(rv == 0); + *sktPtr = -1; + } assert((err == 0) == (*sktPtr != -1)); return err; } @@ -938,14 +940,14 @@ mDNSlocal int SetupOneInterface(mDNS *const m, struct sockaddr *intfAddr, struct // and skip the probe phase of the probe/announce packet sequence. intf->coreIntf.DirectLink = mDNSfalse; #ifdef DIRECTLINK_INTERFACE_NAME - if (strcmp(intfName, STRINGIFY(DIRECTLINK_INTERFACE_NAME)) == 0) - intf->coreIntf.DirectLink = mDNStrue; + 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) - err = mDNS_RegisterInterface(m, &intf->coreIntf, mDNSfalse); + err = mDNS_RegisterInterface(m, &intf->coreIntf, NormalActivation); // Clean up. if (err == 0) @@ -1218,10 +1220,10 @@ mDNSlocal mDNSu32 ProcessRoutingNotification(int sd) */ case RTM_ADD: case RTM_DELETE: - if (pRSMsg->ifam_type == RTM_IFINFO) - result |= 1 << ((struct if_msghdr*) pRSMsg)->ifm_index; - else - result |= 1 << pRSMsg->ifam_index; + if (pRSMsg->ifam_type == RTM_IFINFO) + result |= 1 << ((struct if_msghdr*) pRSMsg)->ifm_index; + else + result |= 1 << pRSMsg->ifam_index; break; } @@ -1339,8 +1341,7 @@ 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", getpid(), err); err = mStatus_NoError; } } @@ -1358,11 +1359,20 @@ mDNSexport mStatus mDNSPlatformInit(mDNS *const m) // In our case all we need to do is to tear down every network interface. mDNSexport void mDNSPlatformClose(mDNS *const m) { + int rv; assert(m != NULL); ClearInterfaceList(m); - if (m->p->unicastSocket4 != -1) assert(close(m->p->unicastSocket4) == 0); + if (m->p->unicastSocket4 != -1) + { + rv = close(m->p->unicastSocket4); + assert(rv == 0); + } #if HAVE_IPV6 - if (m->p->unicastSocket6 != -1) assert(close(m->p->unicastSocket6) == 0); + if (m->p->unicastSocket6 != -1) + { + rv = close(m->p->unicastSocket6); + assert(rv == 0); + } #endif } @@ -1409,14 +1419,36 @@ mDNSexport void mDNSPlatformUnlock (const mDNS *const m) // On the Posix platform this maps directly to the ANSI C strcpy. mDNSexport void mDNSPlatformStrCopy(void *dst, const void *src) { - strcpy((char *)dst, (char *)src); + strcpy((char *)dst, (const char *)src); +} + +mDNSexport mDNSu32 mDNSPlatformStrLCopy(void *dst, const void *src, mDNSu32 len) +{ +#if HAVE_STRLCPY + return ((mDNSu32)strlcpy((char *)dst, (const char *)src, len)); +#else + size_t srcLen; + + srcLen = strlen((const char *)src); + if (srcLen < len) + { + memcpy(dst, src, srcLen + 1); + } + else if (len > 0) + { + memcpy(dst, src, len - 1); + ((char *)dst)[len - 1] = '\0'; + } + + return ((mDNSu32)srcLen); +#endif } // mDNS core calls this routine to get the length of a C string. // On the Posix platform this maps directly to the ANSI C strlen. mDNSexport mDNSu32 mDNSPlatformStrLen (const void *src) { - return strlen((char*)src); + return strlen((const char*)src); } // mDNS core calls this routine to copy memory. @@ -1482,16 +1514,14 @@ mDNSexport mDNSu8 *DNSProxySetAttributes(DNSQuestion *q, DNSMessageHeader *h, DN return ptr; } -mDNSexport void DNSProxyInit(mDNS *const m, mDNSu32 IpIfArr[], mDNSu32 OpIf) +mDNSexport void DNSProxyInit(mDNSu32 IpIfArr[], mDNSu32 OpIf) { - (void) m; (void) IpIfArr; (void) OpIf; } -mDNSexport void DNSProxyTerminate(mDNS *const m) +mDNSexport void DNSProxyTerminate(void) { - (void) m; } // mDNS core calls this routine to clear blocks of memory. @@ -1504,12 +1534,19 @@ mDNSexport void mDNSPlatformMemZero(void *dst, mDNSu32 len) mDNSexport void * mDNSPlatformMemAllocate(mDNSu32 len) { return(malloc(len)); } mDNSexport void mDNSPlatformMemFree (void *mem) { free(mem); } +#if _PLATFORM_HAS_STRONG_PRNG_ +mDNSexport mDNSu32 mDNSPlatformRandomNumber(void) +{ + return(arc4random()); +} +#else mDNSexport mDNSu32 mDNSPlatformRandomSeed(void) { struct timeval tv; gettimeofday(&tv, NULL); return(tv.tv_usec); } +#endif mDNSexport mDNSs32 mDNSPlatformOneSecond = 1024; @@ -1539,19 +1576,18 @@ mDNSexport mDNSs32 mDNSPlatformUTC(void) return time(NULL); } -mDNSexport void mDNSPlatformSendWakeupPacket(mDNS *const m, mDNSInterfaceID InterfaceID, char *EthAddr, char *IPAddr, int iteration) +mDNSexport void mDNSPlatformSendWakeupPacket(mDNSInterfaceID InterfaceID, char *EthAddr, char *IPAddr, int iteration) { - (void) m; (void) InterfaceID; (void) EthAddr; (void) IPAddr; (void) iteration; } -mDNSexport mDNSBool mDNSPlatformValidRecordForInterface(AuthRecord *rr, const NetworkInterfaceInfo *intf) +mDNSexport mDNSBool mDNSPlatformValidRecordForInterface(const AuthRecord *rr, mDNSInterfaceID InterfaceID) { (void) rr; - (void) intf; + (void) InterfaceID; return 1; } @@ -1582,9 +1618,8 @@ mDNSexport void mDNSPlatformSendKeepalive(mDNSAddr *sadd, mDNSAddr *dadd, mDNSIP (void) win; // Unused } -mDNSexport mStatus mDNSPlatformRetrieveTCPInfo(mDNS *const m, mDNSAddr *laddr, mDNSIPPort *lport, mDNSAddr *raddr, mDNSIPPort *rport, mDNSTCPInfo *mti) +mDNSexport mStatus mDNSPlatformRetrieveTCPInfo(mDNSAddr *laddr, mDNSIPPort *lport, mDNSAddr *raddr, mDNSIPPort *rport, mDNSTCPInfo *mti) { - (void) m; // Unused (void) laddr; // Unused (void) raddr; // Unused (void) lport; // Unused @@ -1594,10 +1629,9 @@ mDNSexport mStatus mDNSPlatformRetrieveTCPInfo(mDNS *const m, mDNSAddr *laddr, m return mStatus_NoError; } -mDNSexport mStatus mDNSPlatformGetRemoteMacAddr(mDNS *const m, mDNSAddr *raddr) +mDNSexport mStatus mDNSPlatformGetRemoteMacAddr(mDNSAddr *raddr) { (void) raddr; // Unused - (void) m; // Unused return mStatus_NoError; } @@ -1610,37 +1644,38 @@ mDNSexport mStatus mDNSPlatformStoreSPSMACAddr(mDNSAddr *spsaddr, char *ifnam return mStatus_NoError; } -mDNSexport mStatus mDNSPlatformClearSPSMACAddr(void) +mDNSexport mStatus mDNSPlatformClearSPSData(void) { return mStatus_NoError; } +mDNSexport mStatus mDNSPlatformStoreOwnerOptRecord(char *ifname, DNSMessage *msg, int length) +{ + (void) ifname; // Unused + (void) msg; // Unused + (void) length; // Unused + return mStatus_UnsupportedErr; +} + mDNSexport mDNSu16 mDNSPlatformGetUDPPort(UDPSocket *sock) { (void) sock; // unused - + return (mDNSu16)-1; } mDNSexport mDNSBool mDNSPlatformInterfaceIsD2D(mDNSInterfaceID InterfaceID) { (void) InterfaceID; // unused - - return mDNSfalse; -} -mDNSexport void mDNSPlatformGetDNSRoutePolicy(mDNS *const m, DNSQuestion *q, mDNSBool *isCellBlocked) -{ - (void) m; - - q->ServiceID = -1; - *isCellBlocked = mDNSfalse; + return mDNSfalse; } -mDNSexport void mDNSPlatformSetuDNSSocktOpt(UDPSocket *src, const mDNSAddr *dst, DNSQuestion *q) +mDNSexport void mDNSPlatformSetSocktOpt(void *sock, mDNSTransport_Type transType, mDNSAddr_Type addrType, const DNSQuestion *q) { - (void) src; - (void) dst; + (void) sock; + (void) transType; + (void) addrType; (void) q; } diff --git a/usr/src/cmd/cmd-inet/usr.lib/mdnsd/mDNSPosix.h b/usr/src/contrib/mDNSResponder/mDNSPosix/mDNSPosix.h index d3d413eb3c..ca60d806ab 100644..100755 --- a/usr/src/cmd/cmd-inet/usr.lib/mdnsd/mDNSPosix.h +++ b/usr/src/contrib/mDNSResponder/mDNSPosix/mDNSPosix.h @@ -65,7 +65,7 @@ extern mStatus mDNSPlatformPosixRefreshInterfaceList(mDNS *const m); // Call mDNSPosixGetFDSet before calling select(), to update the parameters // as may be necessary to meet the needs of the mDNSCore code. // The timeout pointer MUST NOT be NULL. -// Set timeout->tv_sec to 0x3FFFFFFF if you want to have effectively no timeout +// Set timeout->tv_sec to FutureTime if you want to have effectively no timeout // After calling mDNSPosixGetFDSet(), call select(nfds, &readfds, NULL, NULL, &timeout); as usual // After select() returns, call mDNSPosixProcessFDSet() to let mDNSCore do its work extern void mDNSPosixGetFDSet(mDNS *m, int *nfds, fd_set *readfds, struct timeval *timeout); diff --git a/usr/src/cmd/cmd-inet/usr.lib/mdnsd/mDNSUNP.c b/usr/src/contrib/mDNSResponder/mDNSPosix/mDNSUNP.c index 0b174e8301..ed6da80953 100644..100755 --- a/usr/src/cmd/cmd-inet/usr.lib/mdnsd/mDNSUNP.c +++ b/usr/src/contrib/mDNSResponder/mDNSPosix/mDNSUNP.c @@ -203,7 +203,9 @@ gotError: } done: if (sockfd != -1) { - assert(close(sockfd) == 0); + int rv; + rv = close(sockfd); + assert(rv == 0); } if (fp != NULL) { fclose(fp); @@ -220,7 +222,8 @@ done: * Unlike plen_to_mask returns netmask in binary form and not * in text form. */ -static void plen_to_netmask(int prefix, unsigned char *addr) { +static void plen_to_netmask(int prefix, unsigned char *addr) +{ for (; prefix > 8; prefix -= 8) *addr++ = 0xff; for (; prefix > 0; prefix--) @@ -836,7 +839,7 @@ recvfrom_flags(int fd, void *ptr, size_t nbytes, int *flagsp, *ttl = 255; // If kernel fails to provide TTL data then assume the TTL was 255 as it should be - msg.msg_control = (void *) control_un.control; + msg.msg_control = control_un.control; msg.msg_controllen = sizeof(control_un.control); msg.msg_flags = 0; #else diff --git a/usr/src/cmd/cmd-inet/usr.lib/mdnsd/mDNSUNP.h b/usr/src/contrib/mDNSResponder/mDNSPosix/mDNSUNP.h index cc81b7d393..cc81b7d393 100644..100755 --- a/usr/src/cmd/cmd-inet/usr.lib/mdnsd/mDNSUNP.h +++ b/usr/src/contrib/mDNSResponder/mDNSPosix/mDNSUNP.h diff --git a/usr/src/cmd/cmd-inet/usr.lib/mdnsd/GenLinkedList.c b/usr/src/contrib/mDNSResponder/mDNSShared/GenLinkedList.c index 1c6cb5be7c..1c6cb5be7c 100644 --- a/usr/src/cmd/cmd-inet/usr.lib/mdnsd/GenLinkedList.c +++ b/usr/src/contrib/mDNSResponder/mDNSShared/GenLinkedList.c diff --git a/usr/src/cmd/cmd-inet/usr.lib/mdnsd/GenLinkedList.h b/usr/src/contrib/mDNSResponder/mDNSShared/GenLinkedList.h index 2d0ada6dcd..2d0ada6dcd 100644 --- a/usr/src/cmd/cmd-inet/usr.lib/mdnsd/GenLinkedList.h +++ b/usr/src/contrib/mDNSResponder/mDNSShared/GenLinkedList.h diff --git a/usr/src/cmd/cmd-inet/usr.lib/mdnsd/PlatformCommon.c b/usr/src/contrib/mDNSResponder/mDNSShared/PlatformCommon.c index afba1c66bf..909efed5c5 100644 --- a/usr/src/cmd/cmd-inet/usr.lib/mdnsd/PlatformCommon.c +++ b/usr/src/contrib/mDNSResponder/mDNSShared/PlatformCommon.c @@ -23,6 +23,10 @@ #include <netinet/in.h> // Needed for sockaddr_in #include <syslog.h> +#if APPLE_OSX_mDNSResponder +#include <os/log.h> +#endif + #include "mDNSEmbeddedAPI.h" // Defines the interface provided to the client layer above #include "DNSCommon.h" #include "PlatformCommon.h" @@ -65,9 +69,10 @@ 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)); + if (errno != ENETUNREACH) { + LogMsg("mDNSPlatformSourceAddrForDest: connect %#a failed errno %d " + "(%s)", dst, errno, strerror(errno)); + } goto exit; } @@ -178,6 +183,14 @@ mDNSexport void mDNSPlatformWriteLogMsg(const char *ident, const char *buffer, m int syslog_level = LOG_ERR; switch (loglevel) { +#if APPLE_OSX_mDNSResponder + case MDNS_LOG_MSG: syslog_level = OS_LOG_TYPE_DEFAULT; break; + case MDNS_LOG_OPERATION: syslog_level = OS_LOG_TYPE_INFO; break; + case MDNS_LOG_SPS: syslog_level = OS_LOG_TYPE_INFO; break; + case MDNS_LOG_INFO: syslog_level = OS_LOG_TYPE_INFO; break; + case MDNS_LOG_DEBUG: syslog_level = OS_LOG_TYPE_DEBUG; break; + default: syslog_level = OS_LOG_TYPE_DEFAULT; break; +#else case MDNS_LOG_MSG: syslog_level = LOG_ERR; break; case MDNS_LOG_OPERATION: syslog_level = LOG_WARNING; break; case MDNS_LOG_SPS: syslog_level = LOG_NOTICE; break; @@ -186,6 +199,7 @@ mDNSexport void mDNSPlatformWriteLogMsg(const char *ident, const char *buffer, m default: fprintf(stderr, "Unknown loglevel %d, assuming LOG_ERR\n", loglevel); fflush(stderr); +#endif } if (!log_inited) { openlog(ident, LOG_CONS, LOG_DAEMON); log_inited++; } diff --git a/usr/src/cmd/cmd-inet/usr.lib/mdnsd/PlatformCommon.h b/usr/src/contrib/mDNSResponder/mDNSShared/PlatformCommon.h index 2a068711e0..2a068711e0 100644 --- a/usr/src/cmd/cmd-inet/usr.lib/mdnsd/PlatformCommon.h +++ b/usr/src/contrib/mDNSResponder/mDNSShared/PlatformCommon.h diff --git a/usr/src/lib/libdns_sd/common/dns_sd.h b/usr/src/contrib/mDNSResponder/mDNSShared/dns_sd.h index cf32ea1eda..701c4ff3a6 100644 --- a/usr/src/lib/libdns_sd/common/dns_sd.h +++ b/usr/src/contrib/mDNSResponder/mDNSShared/dns_sd.h @@ -66,7 +66,7 @@ */ #ifndef _DNS_SD_H -#define _DNS_SD_H 6254102 +#define _DNS_SD_H 8780101 #ifdef __cplusplus extern "C" { @@ -88,6 +88,13 @@ extern "C" { #define DNSSD_API #endif +#if defined(_WIN32) +#include <winsock2.h> +typedef SOCKET dnssd_sock_t; +#else +typedef int dnssd_sock_t; +#endif + /* stdint.h does not exist on FreeBSD 4.x; its types are defined in sys/types.h instead */ #if defined(__FreeBSD__) && (__FreeBSD__ < 5) #include <sys/types.h> @@ -156,11 +163,11 @@ struct sockaddr; * The reliable way to test whether a particular bit is set is not with an equality test, * but with a bitwise mask: * if (flags & kDNSServiceFlagsAdd) ... - * With the exception of kDNSServiceFlagsValidate, each flag can be valid(be set) + * With the exception of kDNSServiceFlagsValidate, each flag can be valid(be set) * EITHER only as an input to one of the DNSService*() APIs OR only as an output * (provide status) through any of the callbacks used. For example, kDNSServiceFlagsAdd * can be set only as an output in the callback, whereas the kDNSServiceFlagsIncludeP2P - * can be set only as an input to the DNSService*() APIs. See comments on kDNSServiceFlagsValidate + * can be set only as an input to the DNSService*() APIs. See comments on kDNSServiceFlagsValidate * defined in enum below. */ enum @@ -180,6 +187,15 @@ enum * in the future they will be delivered as usual. */ + kDNSServiceFlagsAutoTrigger = 0x1, + /* Valid for browses using kDNSServiceInterfaceIndexAny. + * Will auto trigger the browse over AWDL as well once the service is discoveryed + * over BLE. + * This flag is an input value to DNSServiceBrowse(), which is why we can + * use the same value as kDNSServiceFlagsMoreComing, which is an output flag + * for various client callbacks. + */ + kDNSServiceFlagsAdd = 0x2, kDNSServiceFlagsDefault = 0x4, /* Flags for domain enumeration and browse/query reply callbacks. @@ -229,7 +245,7 @@ enum kDNSServiceFlagsForce = 0x800, // This flag is deprecated. kDNSServiceFlagsKnownUnique = 0x800, - /* + /* * Client guarantees that record names are unique, so we can skip sending out initial * probe messages. Standard name conflict resolution is still done if a conflict is discovered. * Currently only valid for a DNSServiceRegister call. @@ -330,10 +346,21 @@ enum * * 5. Thread Safety * The dns_sd.h API does not presuppose any particular threading model, and consequently - * does no locking of its own (which would require linking some specific threading library). - * If client code calls API routines on the same DNSServiceRef concurrently - * from multiple threads, it is the client's responsibility to use a mutext - * lock or take similar appropriate precautions to serialize those calls. + * does no locking internally (which would require linking with a specific threading library). + * If the client concurrently, from multiple threads (or contexts), calls API routines using + * the same DNSServiceRef, it is the client's responsibility to provide mutual exclusion for + * that DNSServiceRef. + + * For example, use of DNSServiceRefDeallocate requires caution. A common mistake is as follows: + * Thread B calls DNSServiceRefDeallocate to deallocate sdRef while Thread A is processing events + * using sdRef. Doing this will lead to intermittent crashes on thread A if the sdRef is used after + * it was deallocated. + + * A telltale sign of this crash type is to see DNSServiceProcessResult on the stack preceding the + * actual crash location. + + * To state this more explicitly, mDNSResponder does not queue DNSServiceRefDeallocate so + * that it occurs discretely before or after an event is handled. */ kDNSServiceFlagsSuppressUnusable = 0x8000, @@ -370,7 +397,7 @@ enum kDNSServiceFlagsBackgroundTrafficClass = 0x80000, /* - * This flag is meaningful for Unicast DNS queries. When set, it uses the background traffic + * This flag is meaningful for Unicast DNS queries. When set, it uses the background traffic * class for packets that service the request. */ @@ -381,32 +408,32 @@ enum kDNSServiceFlagsValidate = 0x200000, /* - * This flag is meaningful in DNSServiceGetAddrInfo and DNSServiceQueryRecord. This is the ONLY flag to be valid + * This flag is meaningful in DNSServiceGetAddrInfo and DNSServiceQueryRecord. This is the ONLY flag to be valid * as an input to the APIs and also an output through the callbacks in the APIs. * - * When this flag is passed to DNSServiceQueryRecord and DNSServiceGetAddrInfo to resolve unicast names, - * the response will be validated using DNSSEC. The validation results are delivered using the flags field in + * When this flag is passed to DNSServiceQueryRecord and DNSServiceGetAddrInfo to resolve unicast names, + * the response will be validated using DNSSEC. The validation results are delivered using the flags field in * the callback and kDNSServiceFlagsValidate is marked in the flags to indicate that DNSSEC status is also available. - * When the callback is called to deliver the query results, the validation results may or may not be available. + * When the callback is called to deliver the query results, the validation results may or may not be available. * If it is not delivered along with the results, the validation status is delivered when the validation completes. - * + * * When the validation results are delivered in the callback, it is indicated by marking the flags with * kDNSServiceFlagsValidate and kDNSServiceFlagsAdd along with the DNSSEC status flags (described below) and a NULL * sockaddr will be returned for DNSServiceGetAddrInfo and zero length rdata will be returned for DNSServiceQueryRecord. * DNSSEC validation results are for the whole RRSet and not just individual records delivered in the callback. When - * kDNSServiceFlagsAdd is not set in the flags, applications should implicitly assume that the DNSSEC status of the + * kDNSServiceFlagsAdd is not set in the flags, applications should implicitly assume that the DNSSEC status of the * RRSet that has been delivered up until that point is not valid anymore, till another callback is called with * kDNSServiceFlagsAdd and kDNSServiceFlagsValidate. * * The following four flags indicate the status of the DNSSEC validation and marked in the flags field of the callback. - * When any of the four flags is set, kDNSServiceFlagsValidate will also be set. To check the validation status, the + * When any of the four flags is set, kDNSServiceFlagsValidate will also be set. To check the validation status, the * other applicable output flags should be masked. See kDNSServiceOutputFlags below. */ kDNSServiceFlagsSecure = 0x200010, /* - * The response has been validated by verifying all the signaures in the response and was able to - * build a successful authentication chain starting from a known trust anchor. + * The response has been validated by verifying all the signatures in the response and was able to + * build a successful authentication chain starting from a known trust anchor. */ kDNSServiceFlagsInsecure = 0x200020, @@ -472,11 +499,11 @@ enum * should not rely on this behavior being supported in any given software release. * * When kDNSServiceFlagsThresholdReached is set in the client callback add or remove event, - * it indicates that the browse answer threshold has been reached and no + * it indicates that the browse answer threshold has been reached and no * browse requests will be generated on the network until the number of answers falls * below the threshold value. Add and remove events can still occur based * on incoming Bonjour traffic observed by the system. - * The set of services return to the client is not guaranteed to represent the + * The set of services return to the client is not guaranteed to represent the * entire set of services present on the network once the threshold has been reached. * * Note, while kDNSServiceFlagsThresholdReached and kDNSServiceFlagsThresholdOne @@ -484,29 +511,24 @@ enum * is only set in the callbacks and kDNSServiceFlagsThresholdOne is only set on * input to a DNSServiceBrowse call. */ - kDNSServiceFlagsDenyCellular = 0x8000000, + kDNSServiceFlagsPrivateOne = 0x8000000, /* - * This flag is meaningful only for Unicast DNS queries. When set, the kernel will restrict - * DNS resolutions on the cellular interface for that request. + * This flag is private and should not be used. */ - kDNSServiceFlagsServiceIndex = 0x10000000, + kDNSServiceFlagsPrivateTwo = 0x10000000, /* - * This flag is meaningful only for DNSServiceGetAddrInfo() for Unicast DNS queries. - * When set, DNSServiceGetAddrInfo() will interpret the "interfaceIndex" argument of the call - * as the "serviceIndex". + * This flag is private and should not be used. */ - kDNSServiceFlagsDenyExpensive = 0x20000000, + kDNSServiceFlagsPrivateThree = 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. + * This flag is private and should not be used. */ - kDNSServiceFlagsPathEvaluationDone = 0x40000000 + kDNSServiceFlagsPrivateFour = 0x40000000 /* - * This flag is meaningful for only Unicast DNS queries. - * When set, it indicates that Network PathEvaluation has already been performed. + * This flag is private and should not be used. */ }; @@ -673,24 +695,49 @@ enum * -- or -- * "Why is kDNSServiceMaxDomainName 1009, when the maximum legal domain name is 256 bytes?" * - * All strings used in the DNS-SD APIs are UTF-8 strings. Apart from the exceptions noted below, - * the APIs expect the strings to be properly escaped, using the conventional DNS escaping rules: + * All strings used in the DNS-SD APIs are UTF-8 strings. + * Apart from the exceptions noted below, the APIs expect the strings to be properly escaped, using the + * conventional DNS escaping rules, as used by the traditional DNS res_query() API, as described below: + * + * Generally all UTF-8 characters (which includes all US ASCII characters) represent themselves, + * with two exceptions, the dot ('.') character, which is the label separator, + * and the backslash ('\') character, which is the escape character. + * The escape character ('\') is interpreted as described below: * - * '\\' represents a single literal '\' in the name - * '\.' represents a single literal '.' in the name * '\ddd', where ddd is a three-digit decimal value from 000 to 255, - * represents a single literal byte with that value. - * A bare unescaped '.' is a label separator, marking a boundary between domain and subdomain. + * represents a single literal byte with that value. Any byte value may be + * represented in '\ddd' format, even characters that don't strictly need to be escaped. + * For example, the ASCII code for 'w' is 119, and therefore '\119' is equivalent to 'w'. + * Thus the command "ping '\119\119\119.apple.com'" is the equivalent to the command "ping 'www.apple.com'". + * Nonprinting ASCII characters in the range 0-31 are often represented this way. + * In particular, the ASCII NUL character (0) cannot appear in a C string because C uses it as the + * string terminator character, so ASCII NUL in a domain name has to be represented in a C string as '\000'. + * Other characters like space (ASCII code 32) are sometimes represented as '\032' + * in contexts where having an actual space character in a C string would be inconvenient. + * + * Otherwise, for all cases where a '\' is followed by anything other than a three-digit decimal value + * from 000 to 255, the character sequence '\x' represents a single literal occurrence of character 'x'. + * This is legal for any character, so, for example, '\w' is equivalent to 'w'. + * Thus the command "ping '\w\w\w.apple.com'" is the equivalent to the command "ping 'www.apple.com'". + * However, this encoding is most useful when representing the characters '.' and '\', + * which otherwise would have special meaning in DNS name strings. + * This means that the following encodings are particularly common: + * '\\' represents a single literal '\' in the name + * '\.' represents a single literal '.' in the name + * + * A lone escape character ('\') appearing at the end of a string is not allowed, since it is + * followed by neither a three-digit decimal value from 000 to 255 nor a single character. + * If a lone escape character ('\') does appear as the last character of a string, it is silently ignored. * * The exceptions, that do not use escaping, are the routines where the full * DNS name of a resource is broken, for convenience, into servicename/regtype/domain. * In these routines, the "servicename" is NOT escaped. It does not need to be, since * it is, by definition, just a single literal string. Any characters in that string * represent exactly what they are. The "regtype" portion is, technically speaking, - * escaped, but since legal regtypes are only allowed to contain letters, digits, - * and hyphens, there is nothing to escape, so the issue is moot. The "domain" - * portion is also escaped, though most domains in use on the public Internet - * today, like regtypes, don't contain any characters that need to be escaped. + * escaped, but since legal regtypes are only allowed to contain US ASCII letters, + * digits, and hyphens, there is nothing to escape, so the issue is moot. + * The "domain" portion is also escaped, though most domains in use on the public + * Internet today, like regtypes, don't contain any characters that need to be escaped. * As DNS-SD becomes more popular, rich-text domains for service discovery will * become common, so software should be written to cope with domains with escaping. * @@ -710,7 +757,7 @@ enum * full DNS name, the helper function DNSServiceConstructFullName() is provided. * * The following (highly contrived) example illustrates the escaping process. - * Suppose you have an service called "Dr. Smith\Dr. Johnson", of type "_ftp._tcp" + * Suppose you have a service called "Dr. Smith\Dr. Johnson", of type "_ftp._tcp" * in subdomain "4th. Floor" of subdomain "Building 2" of domain "apple.com." * The full (escaped) DNS name of this service's SRV record would be: * Dr\.\032Smith\\Dr\.\032Johnson._ftp._tcp.4th\.\032Floor.Building\0322.apple.com. @@ -742,12 +789,29 @@ enum * in a way such that it does not inadvertently appear in service lists on * all the other machines on the network. * - * If the client passes kDNSServiceInterfaceIndexLocalOnly when browsing - * then it will find *all* records registered on that same local machine. - * Clients explicitly wishing to discover *only* LocalOnly services can - * accomplish this by inspecting the interfaceIndex of each service reported - * to their DNSServiceBrowseReply() callback function, and discarding those - * where the interface index is not kDNSServiceInterfaceIndexLocalOnly. + * If the client passes kDNSServiceInterfaceIndexLocalOnly when querying or + * browsing, then the LocalOnly authoritative records and /etc/hosts caches + * are searched and will find *all* records registered or configured on that + * same local machine. + * + * If interested in getting negative answers to local questions while querying + * or browsing, then set both the kDNSServiceInterfaceIndexLocalOnly and the + * kDNSServiceFlagsReturnIntermediates flags. If no local answers exist at this + * moment in time, then the reply will return an immediate negative answer. If + * local records are subsequently created that answer the question, then those + * answers will be delivered, for as long as the question is still active. + * + * If the kDNSServiceFlagsTimeout and kDNSServiceInterfaceIndexLocalOnly flags + * are set simultaneously when either DNSServiceQueryRecord or DNSServiceGetAddrInfo + * is called then both flags take effect. However, if DNSServiceQueryRecord is called + * with both the kDNSServiceFlagsSuppressUnusable and kDNSServiceInterfaceIndexLocalOnly + * flags set, then the kDNSServiceFlagsSuppressUnusable flag is ignored. + * + * Clients explicitly wishing to discover *only* LocalOnly services during a + * browse may do this, without flags, by inspecting the interfaceIndex of each + * service reported to a DNSServiceBrowseReply() callback function, and + * discarding those answers where the interface index is not set to + * kDNSServiceInterfaceIndexLocalOnly. * * kDNSServiceInterfaceIndexP2P is meaningful only in Browse, QueryRecord, Register, * and Resolve operations. It should not be used in other DNSService APIs. @@ -761,7 +825,7 @@ enum * * - If kDNSServiceInterfaceIndexP2P is passed to DNSServiceResolve, it is * mapped internally to kDNSServiceInterfaceIndexAny with the kDNSServiceFlagsIncludeP2P - * set, because resolving a P2P service may create and/or enable an interface whose + * set, because resolving a P2P service may create and/or enable an interface whose * index is not known a priori. The resolve callback will indicate the index of the * interface via which the service can be accessed. * @@ -776,6 +840,7 @@ enum #define kDNSServiceInterfaceIndexLocalOnly ((uint32_t)-1) #define kDNSServiceInterfaceIndexUnicast ((uint32_t)-2) #define kDNSServiceInterfaceIndexP2P ((uint32_t)-3) +#define kDNSServiceInterfaceIndexBLE ((uint32_t)-4) typedef uint32_t DNSServiceFlags; typedef uint32_t DNSServiceProtocol; @@ -833,29 +898,6 @@ DNSServiceErrorType DNSSD_API DNSServiceGetProperty #define kDNSServiceProperty_DaemonVersion "DaemonVersion" - -// Map the source port of the local UDP socket that was opened for sending the DNS query -// to the process ID of the application that triggered the DNS resolution. -// -/* DNSServiceGetPID() Parameters: - * - * srcport: Source port (in network byte order) of the UDP socket that was created by - * the daemon to send the DNS query on the wire. - * - * pid: Process ID of the application that started the name resolution which triggered - * the daemon to send the query on the wire. The value can be -1 if the srcport - * cannot be mapped. - * - * return value: Returns kDNSServiceErr_NoError on success, or kDNSServiceErr_ServiceNotRunning - * if the daemon is not running. The value of the pid is undefined if the return - * value has error. - */ -DNSServiceErrorType DNSSD_API DNSServiceGetPID -( - uint16_t srcport, - int32_t *pid -); - /********************************************************************************************* * * Unix Domain Socket access, DNSServiceRef deallocation, and data processing functions @@ -876,8 +918,8 @@ DNSServiceErrorType DNSSD_API DNSServiceGetPID * a client can choose to fork a thread and have it loop calling "DNSServiceProcessResult(ref);" * If DNSServiceProcessResult() is called when no data is available for reading on the socket, it * will block until data does become available, and then process the data and return to the caller. - * The application is reponsible for checking the return value of DNSServiceProcessResult() to determine - * if the socket is valid and if it should continue to process data on the socket. + * The application is responsible for checking the return value of DNSServiceProcessResult() + * to determine if the socket is valid and if it should continue to process data on the socket. * When data arrives on the socket, the client is responsible for calling DNSServiceProcessResult(ref) * in a timely fashion -- if the client allows a large backlog of data to build up the daemon * may terminate the connection. @@ -888,7 +930,7 @@ DNSServiceErrorType DNSSD_API DNSServiceGetPID * error. */ -int DNSSD_API DNSServiceRefSockFD(DNSServiceRef sdRef); +dnssd_sock_t DNSSD_API DNSServiceRefSockFD(DNSServiceRef sdRef); /* DNSServiceProcessResult() @@ -1090,14 +1132,14 @@ typedef void (DNSSD_API *DNSServiceRegisterReply) * and the registration will remain active indefinitely until the client * terminates it by passing this DNSServiceRef to DNSServiceRefDeallocate(). * + * flags: Indicates the renaming behavior on name conflict (most applications + * will pass 0). See flag definitions above for details. + * * interfaceIndex: If non-zero, specifies the interface on which to register the service * (the index for a given interface is determined via the if_nametoindex() * family of calls.) Most applications will pass 0 to register on all * available interfaces. See "Constants for specifying an interface index" for more details. * - * flags: Indicates the renaming behavior on name conflict (most applications - * will pass 0). See flag definitions above for details. - * * name: If non-NULL, specifies the service name to be registered. * Most applications will not specify a name, in which case the computer * name is used (this name is communicated to the client via the callback). @@ -1149,15 +1191,15 @@ typedef void (DNSSD_API *DNSServiceRegisterReply) * service type using a colon (":") as a delimeter. If subtypes are also present, * it should be given before the subtype as shown below. * - * % dns-sd -R _test1 _http._tcp:mygroup1 local 1001 - * % dns-sd -R _test2 _http._tcp:mygroup2 local 1001 - * % dns-sd -R _test3 _http._tcp:mygroup3,HasFeatureA local 1001 + * % dns-sd -R _test1 _http._tcp:mygroup1 local 1001 + * % dns-sd -R _test2 _http._tcp:mygroup2 local 1001 + * % dns-sd -R _test3 _http._tcp:mygroup3,HasFeatureA local 1001 * * Now: * % dns-sd -B _http._tcp:"mygroup1" # will discover only test1 * % dns-sd -B _http._tcp:"mygroup2" # will discover only test2 * % dns-sd -B _http._tcp:"mygroup3",HasFeatureA # will discover only test3 - * + * * By specifying the group information, only the members of that group are * discovered. * @@ -1237,7 +1279,7 @@ DNSServiceErrorType DNSSD_API DNSServiceRegister * Note that the DNSServiceAddRecord/UpdateRecord/RemoveRecord are *NOT* thread-safe * with respect to a single DNSServiceRef. If you plan to have multiple threads * in your program simultaneously add, update, or remove records from the same - * DNSServiceRef, then it's the caller's responsibility to use a mutext lock + * DNSServiceRef, then it's the caller's responsibility to use a mutex lock * or take similar appropriate precautions to serialize those calls. * * Parameters; @@ -1320,7 +1362,7 @@ DNSServiceErrorType DNSSD_API DNSServiceUpdateRecord /* DNSServiceRemoveRecord * * Remove a record previously added to a service record set via DNSServiceAddRecord(), or deregister - * an record registered individually via DNSServiceRegisterRecord(). + * a record registered individually via DNSServiceRegisterRecord(). * * Parameters: * @@ -1628,7 +1670,9 @@ DNSServiceErrorType DNSSD_API DNSServiceResolve * only applies to clients that cancel the asynchronous operation when * they get a result. Clients that leave the asynchronous operation * running can safely assume that the data remains valid until they - * get another callback telling them otherwise. + * get another callback telling them otherwise. The ttl value is not + * updated when the daemon answers from the cache, hence relying on + * the accuracy of the ttl value is not recommended. * * context: The context pointer that was passed to the callout. * @@ -1734,7 +1778,9 @@ DNSServiceErrorType DNSSD_API DNSServiceQueryRecord * only applies to clients that cancel the asynchronous operation when * they get a result. Clients that leave the asynchronous operation * running can safely assume that the data remains valid until they - * get another callback telling them otherwise. + * get another callback telling them otherwise. The ttl value is not + * updated when the daemon answers from the cache, hence relying on + * the accuracy of the ttl value is not recommended. * * context: The context pointer that was passed to the callout. * @@ -2247,8 +2293,8 @@ typedef union _TXTRecordRef_t { char PrivateData[16]; char *ForceNaturalAlignmen * For most applications, DNS-SD TXT records are generally * less than 100 bytes, so in most cases a simple fixed-sized * 256-byte buffer will be more than sufficient. - * Recommended size limits for DNS-SD TXT Records are discussed in - * <http://files.dns-sd.org/draft-cheshire-dnsext-dns-sd.txt> + * Recommended size limits for DNS-SD TXT Records are discussed in RFC 6763 + * <https://tools.ietf.org/html/rfc6763#section-6.2> * * Note: When passing parameters to and from these TXT record APIs, * the key name does not include the '=' character. The '=' character @@ -2298,8 +2344,8 @@ void DNSSD_API TXTRecordDeallocate * - Present with no value ("key" appears alone) * - Present with empty value ("key=" appears in TXT record) * - Present with non-empty value ("key=value" appears in TXT record) - * For more details refer to "Data Syntax for DNS-SD TXT Records" in - * <http://files.dns-sd.org/draft-cheshire-dnsext-dns-sd.txt> + * For more details refer to "Data Syntax for DNS-SD TXT Records" in RFC 6763 + * <https://tools.ietf.org/html/rfc6763#section-6> * * txtRecord: A TXTRecordRef initialized by calling TXTRecordCreate(). * @@ -2611,13 +2657,6 @@ DNSServiceErrorType DNSSD_API DNSServiceSleepKeepalive ); #endif -#ifdef __APPLE_API_PRIVATE - -#define kDNSServiceCompPrivateDNS "PrivateDNS" -#define kDNSServiceCompMulticastDNS "MulticastDNS" - -#endif //__APPLE_API_PRIVATE - /* Some C compiler cleverness. We can make the compiler check certain things for us, * and report errors at compile-time if anything is wrong. The usual way to do this would * be to use a run-time "if" statement or the conventional run-time "assert" mechanism, but diff --git a/usr/src/contrib/mDNSResponder/mDNSShared/dns_sd_internal.h b/usr/src/contrib/mDNSResponder/mDNSShared/dns_sd_internal.h new file mode 100644 index 0000000000..4be93e943b --- /dev/null +++ b/usr/src/contrib/mDNSResponder/mDNSShared/dns_sd_internal.h @@ -0,0 +1,15 @@ +/* -*- Mode: C; tab-width: 4 -*- + * + * Copyright (c) 2016 Apple Inc. All rights reserved. + */ + +#ifndef _DNS_SD_INTERNAL_H +#define _DNS_SD_INTERNAL_H + +#if !APPLE_OSX_mDNSResponder +#define DNSSD_NO_CREATE_DELEGATE_CONNECTION 1 +#endif + +#include "dns_sd_private.h" + +#endif diff --git a/usr/src/contrib/mDNSResponder/mDNSShared/dns_sd_private.h b/usr/src/contrib/mDNSResponder/mDNSShared/dns_sd_private.h new file mode 100644 index 0000000000..ccec1403d0 --- /dev/null +++ b/usr/src/contrib/mDNSResponder/mDNSShared/dns_sd_private.h @@ -0,0 +1,89 @@ +/* -*- Mode: C; tab-width: 4 -*- + * + * Copyright (c) 2015 Apple Inc. All rights reserved. + */ + +#ifndef _DNS_SD_PRIVATE_H +#define _DNS_SD_PRIVATE_H + + +// Private flags (kDNSServiceFlagsPrivateOne, kDNSServiceFlagsPrivateTwo, kDNSServiceFlagsPrivateThree, kDNSServiceFlagsPrivateFour) from dns_sd.h +enum +{ + kDNSServiceFlagsDenyCellular = 0x8000000, + /* + * This flag is meaningful only for Unicast DNS queries. When set, the daemon will restrict + * DNS resolutions on the cellular interface for that request. + */ + kDNSServiceFlagsServiceIndex = 0x10000000, + /* + * This flag is meaningful only for DNSServiceGetAddrInfo() for Unicast DNS queries. + * When set, DNSServiceGetAddrInfo() will interpret the "interfaceIndex" argument of the call + * as the "serviceIndex". + */ + + kDNSServiceFlagsDenyExpensive = 0x20000000, + /* + * This flag is meaningful only for Unicast DNS queries. When set, the daemon 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. + */ +}; + + +#if !DNSSD_NO_CREATE_DELEGATE_CONNECTION +/* DNSServiceCreateDelegateConnection() + * + * 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 + +// Map the source port of the local UDP socket that was opened for sending the DNS query +// to the process ID of the application that triggered the DNS resolution. +// +/* DNSServiceGetPID() Parameters: + * + * srcport: Source port (in network byte order) of the UDP socket that was created by + * the daemon to send the DNS query on the wire. + * + * pid: Process ID of the application that started the name resolution which triggered + * the daemon to send the query on the wire. The value can be -1 if the srcport + * cannot be mapped. + * + * return value: Returns kDNSServiceErr_NoError on success, or kDNSServiceErr_ServiceNotRunning + * if the daemon is not running. The value of the pid is undefined if the return + * value has error. + */ +DNSServiceErrorType DNSSD_API DNSServiceGetPID +( + uint16_t srcport, + int32_t *pid +); + +#define kDNSServiceCompPrivateDNS "PrivateDNS" +#define kDNSServiceCompMulticastDNS "MulticastDNS" + +#endif diff --git a/usr/src/lib/libdns_sd/common/dnssd_clientlib.c b/usr/src/contrib/mDNSResponder/mDNSShared/dnssd_clientlib.c index 649d403f02..649d403f02 100644 --- a/usr/src/lib/libdns_sd/common/dnssd_clientlib.c +++ b/usr/src/contrib/mDNSResponder/mDNSShared/dnssd_clientlib.c diff --git a/usr/src/lib/libdns_sd/common/dnssd_clientstub.c b/usr/src/contrib/mDNSResponder/mDNSShared/dnssd_clientstub.c index b0fd9f9983..e943c47f80 100644 --- a/usr/src/lib/libdns_sd/common/dnssd_clientstub.c +++ b/usr/src/contrib/mDNSResponder/mDNSShared/dnssd_clientstub.c @@ -28,7 +28,6 @@ #include <errno.h> #include <stdlib.h> -#include <fcntl.h> #include "dnssd_ipc.h" @@ -36,7 +35,7 @@ #include <mach-o/dyld.h> #include <uuid/uuid.h> #include <TargetConditionals.h> -#include "dns_sd_private.h" +#include "dns_sd_internal.h" #endif #if defined(_WIN32) @@ -81,7 +80,7 @@ static void syslog( int priority, const char * message, ...) } #else - #include <sys/fcntl.h> // For O_RDWR etc. + #include <fcntl.h> // For O_RDWR etc. #include <sys/time.h> #include <sys/socket.h> #include <syslog.h> @@ -173,6 +172,19 @@ struct _DNSRecordRef_t DNSServiceOp *sdr; }; +#if !defined(USE_TCP_LOOPBACK) +static void SetUDSPath(struct sockaddr_un *saddr, const char *path) +{ + size_t pathLen; + + pathLen = strlen(path); + if (pathLen < sizeof(saddr->sun_path)) + memcpy(saddr->sun_path, path, pathLen + 1); + else + saddr->sun_path[0] = '\0'; +} +#endif + // Write len bytes. Return 0 on success, -1 on error static int write_all(dnssd_sock_t sd, char *buf, size_t len) { @@ -183,10 +195,11 @@ static int write_all(dnssd_sock_t sd, char *buf, size_t len) ssize_t num_written = send(sd, buf, (long)len, 0); if (num_written < 0 || (size_t)num_written > len) { - // Should never happen. If it does, it indicates some OS bug, + // Check whether socket has gone defunct, + // otherwise, an error here indicates some OS bug // or that the mDNSResponder daemon crashed (which should never happen). - #if !defined(__ppc__) && defined(SO_ISDEFUNCT) - int defunct; +#if !defined(__ppc__) && defined(SO_ISDEFUNCT) + int defunct = 0; socklen_t dlen = sizeof (defunct); if (getsockopt(sd, SOL_SOCKET, SO_ISDEFUNCT, &defunct, &dlen) < 0) syslog(LOG_WARNING, "dnssd_clientstub write_all: SO_ISDEFUNCT failed %d %s", dnssd_errno, dnssd_strerror(dnssd_errno)); @@ -197,12 +210,12 @@ static int write_all(dnssd_sock_t sd, char *buf, size_t len) (num_written < 0) ? dnssd_strerror(dnssd_errno) : ""); else syslog(LOG_INFO, "dnssd_clientstub write_all(%d) DEFUNCT", sd); - #else +#else syslog(LOG_WARNING, "dnssd_clientstub write_all(%d) failed %ld/%ld %d %s", sd, (long)num_written, (long)len, (num_written < 0) ? dnssd_errno : 0, (num_written < 0) ? dnssd_strerror(dnssd_errno) : ""); - #endif +#endif return -1; } buf += num_written; @@ -224,16 +237,18 @@ static int read_all(dnssd_sock_t sd, char *buf, int len) ssize_t num_read = recv(sd, buf, len, 0); // It is valid to get an interrupted system call error e.g., somebody attaching // in a debugger, retry without failing - if ((num_read < 0) && (errno == EINTR)) - { - syslog(LOG_INFO, "dnssd_clientstub read_all: EINTR continue"); - continue; + if ((num_read < 0) && (errno == EINTR)) + { + syslog(LOG_INFO, "dnssd_clientstub read_all: EINTR continue"); + continue; } if ((num_read == 0) || (num_read < 0) || (num_read > len)) { int printWarn = 0; int defunct = 0; - // Should never happen. If it does, it indicates some OS bug, + + // Check whether socket has gone defunct, + // otherwise, an error here indicates some OS bug // or that the mDNSResponder daemon crashed (which should never happen). #if defined(WIN32) // <rdar://problem/7481776> Suppress logs for "A non-blocking socket operation @@ -273,6 +288,12 @@ static int more_bytes(dnssd_sock_t sd) fd_set *fs; int ret; +#if defined(_WIN32) + fs = &readfds; + FD_ZERO(fs); + FD_SET(sd, fs); + ret = select((int)sd+1, fs, (fd_set*)NULL, (fd_set*)NULL, &tv); +#else if (sd < FD_SETSIZE) { fs = &readfds; @@ -287,24 +308,25 @@ static int more_bytes(dnssd_sock_t sd) int nfdbits = sizeof (int) * 8; int nints = (sd/nfdbits) + 1; fs = (fd_set *)calloc(nints, (size_t)sizeof(int)); - if (fs == NULL) - { - syslog(LOG_WARNING, "dnssd_clientstub more_bytes: malloc failed"); - return 0; + if (fs == NULL) + { + syslog(LOG_WARNING, "dnssd_clientstub more_bytes: malloc failed"); + return 0; } } FD_SET(sd, fs); ret = select((int)sd+1, fs, (fd_set*)NULL, (fd_set*)NULL, &tv); - if (fs != &readfds) + if (fs != &readfds) free(fs); +#endif return (ret > 0); } // set_waitlimit() implements a timeout using select. It is called from deliver_request() before recv() OR accept() // to ensure the UDS clients are not blocked in these system calls indefinitely. // Note: Ideally one should never be blocked here, because it indicates either mDNSResponder daemon is not yet up/hung/ -// superbusy/crashed or some other OS bug. For eg: On Windows which suffers from 3rd party software -// (primarily 3rd party firewall software) interfering with proper functioning of the TCP protocol stack it is possible +// superbusy/crashed or some other OS bug. For eg: On Windows which suffers from 3rd party software +// (primarily 3rd party firewall software) interfering with proper functioning of the TCP protocol stack it is possible // the next operation on this socket(recv/accept) is blocked since we depend on TCP to communicate with the system service. static int set_waitlimit(dnssd_sock_t sock, int timeout) { @@ -431,8 +453,8 @@ static void FreeDNSServiceOp(DNSServiceOp *x) x->disp_queue = NULL; #endif // DNSRecords may have been added to subordinate sdRef e.g., DNSServiceRegister/DNSServiceAddRecord - // or on the main sdRef e.g., DNSServiceCreateConnection/DNSServiveRegisterRecord. DNSRecords may have - // been freed if the application called DNSRemoveRecord + // or on the main sdRef e.g., DNSServiceCreateConnection/DNSServiceRegisterRecord. + // DNSRecords may have been freed if the application called DNSRemoveRecord. FreeDNSRecords(x); if (x->kacontext) { @@ -451,10 +473,10 @@ static DNSServiceErrorType ConnectToServer(DNSServiceRef *ref, DNSServiceFlags f dnssd_sockaddr_t saddr; DNSServiceOp *sdr; - if (!ref) - { - syslog(LOG_WARNING, "dnssd_clientstub DNSService operation with NULL DNSServiceRef"); - return kDNSServiceErr_BadParam; + if (!ref) + { + syslog(LOG_WARNING, "dnssd_clientstub DNSService operation with NULL DNSServiceRef"); + return kDNSServiceErr_BadParam; } if (flags & kDNSServiceFlagsShareConnection) @@ -481,16 +503,16 @@ static DNSServiceErrorType ConnectToServer(DNSServiceRef *ref, DNSServiceFlags f if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0) { *ref = NULL; return kDNSServiceErr_ServiceNotRunning; } } // <rdar://problem/4096913> If the system service is disabled, we only want to try to connect once - if (IsSystemServiceDisabled()) + if (IsSystemServiceDisabled()) NumTries = DNSSD_CLIENT_MAXTRIES; #endif sdr = malloc(sizeof(DNSServiceOp)); - if (!sdr) - { - syslog(LOG_WARNING, "dnssd_clientstub ConnectToServer: malloc failed"); - *ref = NULL; - return kDNSServiceErr_NoMemory; + if (!sdr) + { + syslog(LOG_WARNING, "dnssd_clientstub ConnectToServer: malloc failed"); + *ref = NULL; + return kDNSServiceErr_NoMemory; } sdr->next = NULL; sdr->primary = NULL; @@ -515,11 +537,11 @@ static DNSServiceErrorType ConnectToServer(DNSServiceRef *ref, DNSServiceFlags f if (flags & kDNSServiceFlagsShareConnection) { DNSServiceOp **p = &(*ref)->next; // Append ourselves to end of primary's list - while (*p) + while (*p) p = &(*p)->next; *p = sdr; // Preincrement counter before we use it -- it helps with debugging if we know the all-zeroes ID should never appear - if (++(*ref)->uid.u32[0] == 0) + if (++(*ref)->uid.u32[0] == 0) ++(*ref)->uid.u32[1]; // In parent DNSServiceOp increment UID counter sdr->primary = *ref; // Set our primary pointer sdr->sockfd = (*ref)->sockfd; // Inherit primary's socket @@ -562,7 +584,7 @@ static DNSServiceErrorType ConnectToServer(DNSServiceRef *ref, DNSServiceFlags f saddr.sin_port = htons(MDNS_TCP_SERVERPORT); #else saddr.sun_family = AF_LOCAL; - strcpy(saddr.sun_path, uds_serverpath); + SetUDSPath(&saddr, uds_serverpath); #if !defined(__ppc__) && defined(SO_DEFUNCTOK) { int defunct = 1; @@ -571,7 +593,7 @@ static DNSServiceErrorType ConnectToServer(DNSServiceRef *ref, DNSServiceFlags f } #endif #endif - + while (1) { int err = connect(sdr->sockfd, (struct sockaddr *) &saddr, sizeof(saddr)); @@ -584,18 +606,18 @@ static DNSServiceErrorType ConnectToServer(DNSServiceRef *ref, DNSServiceFlags f // then we give up and return a failure code. if (++NumTries < DNSSD_CLIENT_MAXTRIES) { - syslog(LOG_WARNING, "dnssd_clientstub ConnectToServer: connect()-> No of tries: %d", NumTries); + syslog(LOG_WARNING, "dnssd_clientstub ConnectToServer: connect()-> No of tries: %d", NumTries); sleep(1); // Sleep a bit, then try again } - else + else { #if !defined(USE_TCP_LOOPBACK) - syslog(LOG_WARNING, "dnssd_clientstub ConnectToServer: connect() failed path:%s Socket:%d Err:%d Errno:%d %s", + 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; + dnssd_close(sdr->sockfd); + FreeDNSServiceOp(sdr); + return kDNSServiceErr_ServiceNotRunning; } } //printf("ConnectToServer opened socket %d\n", sdr->sockfd); @@ -606,28 +628,34 @@ static DNSServiceErrorType ConnectToServer(DNSServiceRef *ref, DNSServiceFlags f } #define deliver_request_bailout(MSG) \ - syslog(LOG_WARNING, "dnssd_clientstub deliver_request: %s failed %d (%s)", (MSG), dnssd_errno, dnssd_strerror(dnssd_errno)); goto cleanup + do { syslog(LOG_WARNING, "dnssd_clientstub deliver_request: %s failed %d (%s)", (MSG), dnssd_errno, dnssd_strerror(dnssd_errno)); goto cleanup; } while(0) static DNSServiceErrorType deliver_request(ipc_msg_hdr *hdr, DNSServiceOp *sdr) { + uint32_t datalen; + dnssd_sock_t listenfd = dnssd_InvalidSocket, errsd = dnssd_InvalidSocket; + DNSServiceErrorType err = kDNSServiceErr_Unknown; // Default for the "goto cleanup" cases + int MakeSeparateReturnSocket; + #if defined(USE_TCP_LOOPBACK) || defined(USE_NAMED_ERROR_RETURN_SOCKET) + char *data; + #endif + 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 + 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); + 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 // 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) - const int MakeSeparateReturnSocket = (sdr->primary || + 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)) @@ -646,22 +674,14 @@ static DNSServiceErrorType deliver_request(ipc_msg_hdr *hdr, DNSServiceOp *sdr) dnssd_sockaddr_t caddr; 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"); - } + if (!dnssd_SocketValid(listenfd)) 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"); - } + 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"); 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 @@ -672,9 +692,7 @@ static DNSServiceErrorType deliver_request(ipc_msg_hdr *hdr, DNSServiceOp *sdr) int bindresult; dnssd_sockaddr_t caddr; listenfd = socket(AF_DNSSD, SOCK_STREAM, 0); - if (!dnssd_SocketValid(listenfd)) { - deliver_request_bailout("USE_NAMED_ERROR_RETURN_SOCKET socket"); - } + if (!dnssd_SocketValid(listenfd)) 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 @@ -682,23 +700,17 @@ static DNSServiceErrorType deliver_request(ipc_msg_hdr *hdr, DNSServiceOp *sdr) #ifndef NOT_HAVE_SA_LEN caddr.sun_len = sizeof(struct sockaddr_un); #endif - strcpy(caddr.sun_path, data); + SetUDSPath(&caddr, data); 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 (listen(listenfd, 1) < 0) { - deliver_request_bailout("USE_NAMED_ERROR_RETURN_SOCKET listen"); - } + 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"); } #else { dnssd_sock_t sp[2]; - if (socketpair(AF_DNSSD, SOCK_STREAM, 0, sp) < 0) { - deliver_request_bailout("socketpair"); - } + if (socketpair(AF_DNSSD, SOCK_STREAM, 0, sp) < 0) deliver_request_bailout("socketpair"); else { errsd = sp[0]; // We'll read our four-byte error code from sp[0] @@ -722,7 +734,7 @@ static DNSServiceErrorType deliver_request(ipc_msg_hdr *hdr, DNSServiceOp *sdr) // any associated data does not work reliably -- e.g. one particular issue we ran // into is that if the receiving program is in a kqueue loop waiting to be notified // of the received message, it doesn't get woken up when the control message arrives. - if (MakeSeparateReturnSocket || sdr->op == send_bpf) + if (MakeSeparateReturnSocket || sdr->op == send_bpf) datalen--; // Okay to use sdr->op when checking for op == send_bpf #endif @@ -751,7 +763,7 @@ static DNSServiceErrorType deliver_request(ipc_msg_hdr *hdr, DNSServiceOp *sdr) } #endif - if (!MakeSeparateReturnSocket) + if (!MakeSeparateReturnSocket) errsd = sdr->sockfd; if (MakeSeparateReturnSocket || sdr->op == send_bpf) // Okay to use sdr->op when checking for op == send_bpf { @@ -761,12 +773,11 @@ static DNSServiceErrorType deliver_request(ipc_msg_hdr *hdr, DNSServiceOp *sdr) // set_waitlimit() ensures we do not block indefinitely just in case something is wrong dnssd_sockaddr_t daddr; dnssd_socklen_t len = sizeof(daddr); - if ((err = set_waitlimit(listenfd, DNSSD_CLIENT_TIMEOUT)) != kDNSServiceErr_NoError) + if ((err = set_waitlimit(listenfd, DNSSD_CLIENT_TIMEOUT)) != kDNSServiceErr_NoError) goto cleanup; errsd = accept(listenfd, (struct sockaddr *)&daddr, &len); - if (!dnssd_SocketValid(errsd)) { + 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 @@ -870,7 +881,7 @@ cleanup: return err; } -int DNSSD_API DNSServiceRefSockFD(DNSServiceRef sdRef) +dnssd_sock_t DNSSD_API DNSServiceRefSockFD(DNSServiceRef sdRef) { if (!sdRef) { syslog(LOG_WARNING, "dnssd_clientstub DNSServiceRefSockFD called with NULL DNSServiceRef"); return dnssd_InvalidSocket; } @@ -887,7 +898,7 @@ int DNSSD_API DNSServiceRefSockFD(DNSServiceRef sdRef) return dnssd_InvalidSocket; } - return (int) sdRef->sockfd; + return sdRef->sockfd; } #if _DNS_SD_LIBDISPATCH @@ -1172,13 +1183,18 @@ void DNSSD_API DNSServiceRefDeallocate(DNSServiceRef sdRef) DNSServiceErrorType DNSSD_API DNSServiceGetProperty(const char *property, void *result, uint32_t *size) { + DNSServiceErrorType err; char *ptr; - size_t len = strlen(property) + 1; + size_t len; ipc_msg_hdr *hdr; DNSServiceOp *tmp; uint32_t actualsize; - DNSServiceErrorType err = ConnectToServer(&tmp, 0, getproperty_request, NULL, NULL, NULL); + if (!property || !result || !size) + return kDNSServiceErr_BadParam; + + len = strlen(property) + 1; + err = ConnectToServer(&tmp, 0, getproperty_request, NULL, NULL, NULL); if (err) return err; hdr = create_hdr(getproperty_request, &len, &ptr, 0, tmp); @@ -1208,7 +1224,7 @@ DNSServiceErrorType DNSSD_API DNSServiceGetPID(const uint16_t srcport, int32_t * { char *ptr; ipc_msg_hdr *hdr; - DNSServiceOp *tmp; + DNSServiceOp *tmp = NULL; size_t len = sizeof(int32_t); DNSServiceErrorType err = ConnectToServer(&tmp, 0, getpid_request, NULL, NULL, NULL); @@ -1298,14 +1314,15 @@ DNSServiceErrorType DNSSD_API DNSServiceResolve ipc_msg_hdr *hdr; DNSServiceErrorType err; - if (!name || !regtype || !domain || !callBack) return kDNSServiceErr_BadParam; + if (!sdRef || !name || !regtype || !domain || !callBack) return kDNSServiceErr_BadParam; // Need a real InterfaceID for WakeOnResolve if ((flags & kDNSServiceFlagsWakeOnResolve) != 0 && ((interfaceIndex == kDNSServiceInterfaceIndexAny) || (interfaceIndex == kDNSServiceInterfaceIndexLocalOnly) || (interfaceIndex == kDNSServiceInterfaceIndexUnicast) || - (interfaceIndex == kDNSServiceInterfaceIndexP2P))) + (interfaceIndex == kDNSServiceInterfaceIndexP2P) || + (interfaceIndex == kDNSServiceInterfaceIndexBLE))) { return kDNSServiceErr_BadParam; } @@ -1313,7 +1330,7 @@ DNSServiceErrorType DNSSD_API DNSServiceResolve if ((interfaceIndex == kDNSServiceInterfaceIndexAny) && includeP2PWithIndexAny()) flags |= kDNSServiceFlagsIncludeP2P; - err = ConnectToServer(sdRef, flags, resolve_request, handle_resolve_response, (void *)callBack, context); + err = ConnectToServer(sdRef, flags, resolve_request, handle_resolve_response, callBack, context); if (err) return err; // On error ConnectToServer leaves *sdRef set to NULL // Calculate total message length @@ -1373,10 +1390,13 @@ DNSServiceErrorType DNSSD_API DNSServiceQueryRecord ipc_msg_hdr *hdr; DNSServiceErrorType err; + // NULL name handled below. + if (!sdRef || !callBack) return kDNSServiceErr_BadParam; + if ((interfaceIndex == kDNSServiceInterfaceIndexAny) && includeP2PWithIndexAny()) flags |= kDNSServiceFlagsIncludeP2P; - err = ConnectToServer(sdRef, flags, query_request, handle_query_response, (void *)callBack, context); + err = ConnectToServer(sdRef, flags, query_request, handle_query_response, callBack, context); if (err) return err; // On error ConnectToServer leaves *sdRef set to NULL if (!name) name = "\0"; @@ -1482,9 +1502,9 @@ DNSServiceErrorType DNSSD_API DNSServiceGetAddrInfo ipc_msg_hdr *hdr; DNSServiceErrorType err; - if (!hostname) return kDNSServiceErr_BadParam; + if (!sdRef || !hostname || !callBack) return kDNSServiceErr_BadParam; - err = ConnectToServer(sdRef, flags, addrinfo_request, handle_addrinfo_response, (void *)callBack, context); + err = ConnectToServer(sdRef, flags, addrinfo_request, handle_addrinfo_response, callBack, context); if (err) { return err; // On error ConnectToServer leaves *sdRef set to NULL @@ -1536,10 +1556,13 @@ DNSServiceErrorType DNSSD_API DNSServiceBrowse ipc_msg_hdr *hdr; DNSServiceErrorType err; + // NULL domain handled below + if (!sdRef || !regtype || !callBack) return kDNSServiceErr_BadParam; + if ((interfaceIndex == kDNSServiceInterfaceIndexAny) && includeP2PWithIndexAny()) flags |= kDNSServiceFlagsIncludeP2P; - err = ConnectToServer(sdRef, flags, browse_request, handle_browse_response, (void *)callBack, context); + err = ConnectToServer(sdRef, flags, browse_request, handle_browse_response, callBack, context); if (err) return err; // On error ConnectToServer leaves *sdRef set to NULL if (!domain) domain = ""; @@ -1564,11 +1587,16 @@ DNSServiceErrorType DNSSD_API DNSServiceBrowse DNSServiceErrorType DNSSD_API DNSServiceSetDefaultDomainForUser(DNSServiceFlags flags, const char *domain); DNSServiceErrorType DNSSD_API DNSServiceSetDefaultDomainForUser(DNSServiceFlags flags, const char *domain) { + DNSServiceErrorType err; DNSServiceOp *tmp; char *ptr; - size_t len = sizeof(flags) + strlen(domain) + 1; + size_t len; ipc_msg_hdr *hdr; - DNSServiceErrorType err = ConnectToServer(&tmp, 0, setdomain_request, NULL, NULL, NULL); + + if (!domain) return kDNSServiceErr_BadParam; + len = sizeof(flags) + strlen(domain) + 1; + + err = ConnectToServer(&tmp, 0, setdomain_request, NULL, NULL, NULL); if (err) return err; hdr = create_hdr(setdomain_request, &len, &ptr, 0, tmp); @@ -1614,8 +1642,8 @@ DNSServiceErrorType DNSSD_API DNSServiceRegister DNSServiceErrorType err; union { uint16_t s; u_char b[2]; } port = { PortInNetworkByteOrder }; + if (!sdRef || !regtype) return kDNSServiceErr_BadParam; if (!name) name = ""; - if (!regtype) return kDNSServiceErr_BadParam; if (!domain) domain = ""; if (!host) host = ""; if (!txtRecord) txtRecord = (void*)""; @@ -1626,7 +1654,7 @@ DNSServiceErrorType DNSSD_API DNSServiceRegister if ((interfaceIndex == kDNSServiceInterfaceIndexAny) && includeP2PWithIndexAny()) flags |= kDNSServiceFlagsIncludeP2P; - err = ConnectToServer(sdRef, flags, reg_service_request, callBack ? handle_regservice_response : NULL, (void *)callBack, context); + err = ConnectToServer(sdRef, flags, reg_service_request, callBack ? handle_regservice_response : NULL, callBack, context); if (err) return err; // On error ConnectToServer leaves *sdRef set to NULL len = sizeof(DNSServiceFlags); @@ -1677,12 +1705,16 @@ DNSServiceErrorType DNSSD_API DNSServiceEnumerateDomains size_t len; ipc_msg_hdr *hdr; DNSServiceErrorType err; + int f1; + int f2; - int f1 = (flags & kDNSServiceFlagsBrowseDomains) != 0; - int f2 = (flags & kDNSServiceFlagsRegistrationDomains) != 0; + if (!sdRef || !callBack) return kDNSServiceErr_BadParam; + + f1 = (flags & kDNSServiceFlagsBrowseDomains) != 0; + f2 = (flags & kDNSServiceFlagsRegistrationDomains) != 0; if (f1 + f2 != 1) return kDNSServiceErr_BadParam; - err = ConnectToServer(sdRef, flags, enumeration_request, handle_enumeration_response, (void *)callBack, context); + err = ConnectToServer(sdRef, flags, enumeration_request, handle_enumeration_response, callBack, context); if (err) return err; // On error ConnectToServer leaves *sdRef set to NULL len = sizeof(DNSServiceFlags); @@ -1754,10 +1786,13 @@ static void ConnectionResponse(DNSServiceOp *const sdr, const CallbackHeader *co DNSServiceErrorType DNSSD_API DNSServiceCreateConnection(DNSServiceRef *sdRef) { + DNSServiceErrorType err; char *ptr; size_t len = 0; ipc_msg_hdr *hdr; - DNSServiceErrorType err = ConnectToServer(sdRef, 0, connection_request, ConnectionResponse, NULL, NULL); + + if (!sdRef) return kDNSServiceErr_BadParam; + err = ConnectToServer(sdRef, 0, connection_request, ConnectionResponse, NULL, NULL); if (err) return err; // On error ConnectToServer leaves *sdRef set to NULL hdr = create_hdr(connection_request, &len, &ptr, 0, *sdRef); @@ -1775,13 +1810,14 @@ DNSServiceErrorType DNSSD_API DNSServiceCreateDelegateConnection(DNSServiceRef * size_t len = 0; ipc_msg_hdr *hdr; + if (!sdRef) return kDNSServiceErr_BadParam; DNSServiceErrorType err = ConnectToServer(sdRef, 0, connection_delegate_request, ConnectionResponse, NULL, NULL); if (err) { return err; // On error ConnectToServer leaves *sdRef set to NULL } - // Only one of the two options can be set. If pid is zero, uuid is used. + // Only one of the two options can be set. If pid is zero, uuid is used. // If both are specified only pid will be used. We send across the pid // so that the daemon knows what to read from the socket. @@ -1796,9 +1832,9 @@ DNSServiceErrorType DNSSD_API DNSServiceCreateDelegateConnection(DNSServiceRef * } if (pid && setsockopt((*sdRef)->sockfd, SOL_SOCKET, SO_DELEGATED, &pid, sizeof(pid)) == -1) - { - syslog(LOG_WARNING, "dnssdclientstub: Could not setsockopt() for PID[%d], no entitlements or process(pid) invalid errno:%d (%s)", pid, errno, strerror(errno)); - // Free the hdr in case we return before calling deliver_request() + { + syslog(LOG_WARNING, "dnssdclientstub: Could not setsockopt() for PID[%d], no entitlements or process(pid) invalid errno:%d (%s)", pid, errno, strerror(errno)); + // Free the hdr in case we return before calling deliver_request() if (hdr) free(hdr); DNSServiceRefDeallocate(*sdRef); @@ -1864,7 +1900,11 @@ DNSServiceErrorType DNSSD_API DNSServiceRegisterRecord if ((interfaceIndex == kDNSServiceInterfaceIndexAny) && includeP2PWithIndexAny()) flags |= kDNSServiceFlagsIncludeP2P; - if (!sdRef) { syslog(LOG_WARNING, "dnssd_clientstub DNSServiceRegisterRecord called with NULL DNSServiceRef"); return kDNSServiceErr_BadParam; } + if (!sdRef || !RecordRef || !fullname || (!rdata && rdlen) || !callBack) + { + syslog(LOG_WARNING, "dnssd_clientstub DNSServiceRegisterRecord called with NULL parameter"); + return kDNSServiceErr_BadParam; + } if (!DNSServiceRefValid(sdRef)) { @@ -1945,8 +1985,11 @@ DNSServiceErrorType DNSSD_API DNSServiceAddRecord DNSRecordRef rref; DNSRecord **p; - if (!sdRef) { syslog(LOG_WARNING, "dnssd_clientstub DNSServiceAddRecord called with NULL DNSServiceRef"); return kDNSServiceErr_BadParam; } - if (!RecordRef) { syslog(LOG_WARNING, "dnssd_clientstub DNSServiceAddRecord called with NULL DNSRecordRef pointer"); return kDNSServiceErr_BadParam; } + if (!sdRef || !RecordRef || (!rdata && rdlen)) + { + syslog(LOG_WARNING, "dnssd_clientstub DNSServiceAddRecord called with NULL parameter"); + return kDNSServiceErr_BadParam; + } if (sdRef->op != reg_service_request) { syslog(LOG_WARNING, "dnssd_clientstub DNSServiceAddRecord called with non-DNSServiceRegister DNSServiceRef %p %d", sdRef, sdRef->op); @@ -2006,7 +2049,11 @@ DNSServiceErrorType DNSSD_API DNSServiceUpdateRecord size_t len = 0; char *ptr; - if (!sdRef) { syslog(LOG_WARNING, "dnssd_clientstub DNSServiceUpdateRecord called with NULL DNSServiceRef"); return kDNSServiceErr_BadParam; } + if (!sdRef || (!rdata && rdlen)) + { + syslog(LOG_WARNING, "dnssd_clientstub DNSServiceUpdateRecord called with NULL parameter"); + return kDNSServiceErr_BadParam; + } if (!DNSServiceRefValid(sdRef)) { @@ -2082,12 +2129,15 @@ DNSServiceErrorType DNSSD_API DNSServiceReconfirmRecord const void *rdata ) { + DNSServiceErrorType err; char *ptr; size_t len; ipc_msg_hdr *hdr; - DNSServiceOp *tmp; + DNSServiceOp *tmp = NULL; + + if (!fullname || (!rdata && rdlen)) return kDNSServiceErr_BadParam; - DNSServiceErrorType err = ConnectToServer(&tmp, flags, reconfirm_record_request, NULL, NULL, NULL); + err = ConnectToServer(&tmp, flags, reconfirm_record_request, NULL, NULL, NULL); if (err) return err; len = sizeof(DNSServiceFlags); @@ -2161,7 +2211,7 @@ DNSServiceErrorType DNSSD_API DNSServiceNATPortMappingCreate union { uint16_t s; u_char b[2]; } internalPort = { internalPortInNetworkByteOrder }; union { uint16_t s; u_char b[2]; } externalPort = { externalPortInNetworkByteOrder }; - DNSServiceErrorType err = ConnectToServer(sdRef, flags, port_mapping_request, handle_port_mapping_response, (void *)callBack, context); + DNSServiceErrorType err = ConnectToServer(sdRef, flags, port_mapping_request, handle_port_mapping_response, callBack, context); if (err) return err; // On error ConnectToServer leaves *sdRef set to NULL len = sizeof(flags); @@ -2363,7 +2413,7 @@ DNSServiceErrorType DNSSD_API DNSServiceSleepKeepalive ka = malloc(sizeof(SleepKAContext)); if (!ka) return kDNSServiceErr_NoMemory; - ka->AppCallback = (void *)callBack; + ka->AppCallback = callBack; ka->AppContext = context; err = DNSServiceCreateConnection(sdRef); diff --git a/usr/src/lib/libdns_sd/common/dnssd_ipc.c b/usr/src/contrib/mDNSResponder/mDNSShared/dnssd_ipc.c index 0fd75824f5..0fd75824f5 100644 --- a/usr/src/lib/libdns_sd/common/dnssd_ipc.c +++ b/usr/src/contrib/mDNSResponder/mDNSShared/dnssd_ipc.c diff --git a/usr/src/lib/libdns_sd/common/dnssd_ipc.h b/usr/src/contrib/mDNSResponder/mDNSShared/dnssd_ipc.h index b9c0b144d3..c054188453 100644 --- a/usr/src/lib/libdns_sd/common/dnssd_ipc.h +++ b/usr/src/contrib/mDNSResponder/mDNSShared/dnssd_ipc.h @@ -41,7 +41,6 @@ # define dnssd_EWOULDBLOCK WSAEWOULDBLOCK # define dnssd_EINTR WSAEINTR # define dnssd_ECONNRESET WSAECONNRESET -# define dnssd_sock_t SOCKET # define dnssd_socklen_t int # define dnssd_close(sock) closesocket(sock) # define dnssd_errno WSAGetLastError() @@ -67,7 +66,6 @@ extern char *win32_strerror(int inErrorCode); # define dnssd_EINTR EINTR # define dnssd_ECONNRESET ECONNRESET # define dnssd_EPIPE EPIPE -# define dnssd_sock_t int # define dnssd_socklen_t unsigned int # define dnssd_close(sock) close(sock) # define dnssd_errno errno diff --git a/usr/src/cmd/cmd-inet/usr.lib/mdnsd/mDNSDebug.c b/usr/src/contrib/mDNSResponder/mDNSShared/mDNSDebug.c index 1243ae77a7..3f78384c81 100644 --- a/usr/src/cmd/cmd-inet/usr.lib/mdnsd/mDNSDebug.c +++ b/usr/src/contrib/mDNSResponder/mDNSShared/mDNSDebug.c @@ -33,7 +33,7 @@ mDNSexport int mDNS_LoggingEnabled = 0; mDNSexport int mDNS_PacketLoggingEnabled = 0; mDNSexport int mDNS_McastLoggingEnabled = 0; -mDNSexport int mDNS_McastTracingEnabled = 0; +mDNSexport int mDNS_McastTracingEnabled = 0; #if MDNS_DEBUGMSGS mDNSexport int mDNS_DebugMode = mDNStrue; diff --git a/usr/src/cmd/cmd-inet/usr.lib/mdnsd/uds_daemon.c b/usr/src/contrib/mDNSResponder/mDNSShared/uds_daemon.c index 9af68dc95d..de30ef13a1 100644 --- a/usr/src/cmd/cmd-inet/usr.lib/mdnsd/uds_daemon.c +++ b/usr/src/contrib/mDNSResponder/mDNSShared/uds_daemon.c @@ -34,6 +34,7 @@ #include "DNSCommon.h" #include "uDNS.h" #include "uds_daemon.h" +#include "dns_sd_internal.h" // Normally we append search domains only for queries with a single label that are not // fully qualified. This can be overridden to apply search domains for queries (that are @@ -48,17 +49,20 @@ mDNSBool AlwaysAppendSearchDomains = mDNSfalse; #endif #endif -#ifdef LOCAL_PEERPID -#include <sys/un.h> // for LOCAL_PEERPID +#ifdef LOCAL_PEEREPID +#include <sys/un.h> // for LOCAL_PEEREPID #include <sys/socket.h> // for getsockopt #include <sys/proc_info.h> // for struct proc_bsdshortinfo #include <libproc.h> // for proc_pidinfo() -#endif //LOCAL_PEERPID -//upto 16 characters of process name (defined in <sys/proc.h> but we do not want to include that file) -#define MAXCOMLEN 16 +#endif //LOCAL_PEEREPID + +#ifdef UNIT_TEST +#include "unittest.h" +#endif #if APPLE_OSX_mDNSResponder #include <WebFilterDNS/WebFilterDNS.h> +#include "BLE.h" #if !NO_WCF @@ -83,187 +87,6 @@ int WCFNameResolvesToName(WCFConnection *conn, char* fromName, char* toName, uid // *************************************************************************** #if COMPILER_LIKES_PRAGMA_MARK #pragma mark - -#pragma mark - Types and Data Structures -#endif - -typedef enum -{ - t_uninitialized, - t_morecoming, - t_complete, - t_error, - t_terminated -} transfer_state; - -typedef struct request_state request_state; - -typedef void (*req_termination_fn)(request_state *request); - -typedef struct registered_record_entry -{ - struct registered_record_entry *next; - mDNSu32 key; - client_context_t regrec_client_context; - request_state *request; - mDNSBool external_advertise; - mDNSInterfaceID origInterfaceID; - AuthRecord *rr; // Pointer to variable-sized AuthRecord (Why a pointer? Why not just embed it here?) -} registered_record_entry; - -// A single registered service: ServiceRecordSet + bookkeeping -// Note that we duplicate some fields from parent service_info object -// to facilitate cleanup, when instances and parent may be deallocated at different times. -typedef struct service_instance -{ - struct service_instance *next; - request_state *request; - AuthRecord *subtypes; - mDNSBool renameonmemfree; // Set on config change when we deregister original name - mDNSBool clientnotified; // Has client been notified of successful registration yet? - mDNSBool default_local; // is this the "local." from an empty-string registration? - mDNSBool external_advertise; // is this is being advertised externally? - domainname domain; - ServiceRecordSet srs; // note -- variable-sized object -- must be last field in struct -} service_instance; - -// for multi-domain default browsing -typedef struct browser_t -{ - struct browser_t *next; - domainname domain; - DNSQuestion q; -} browser_t; - -#ifdef _WIN32 - typedef unsigned int pid_t; - typedef unsigned int socklen_t; -#endif - -struct request_state -{ - request_state *next; - request_state *primary; // If this operation is on a shared socket, pointer to primary - // request_state for the original DNSServiceCreateConnection() operation - dnssd_sock_t sd; - pid_t process_id; // Client's PID value - char pid_name[MAXCOMLEN]; // Client's process name - char uuid[UUID_SIZE]; - mDNSBool validUUID; - dnssd_sock_t errsd; - mDNSu32 uid; - void * platform_data; - - // Note: On a shared connection these fields in the primary structure, including hdr, are re-used - // for each new request. This is because, until we've read the ipc_msg_hdr to find out what the - // operation is, we don't know if we're going to need to allocate a new request_state or not. - transfer_state ts; - mDNSu32 hdr_bytes; // bytes of header already read - ipc_msg_hdr hdr; - mDNSu32 data_bytes; // bytes of message data already read - char *msgbuf; // pointer to data storage to pass to free() - const char *msgptr; // pointer to data to be read from (may be modified) - char *msgend; // pointer to byte after last byte of message - - // reply, termination, error, and client context info - int no_reply; // don't send asynchronous replies to client - mDNSs32 time_blocked; // record time of a blocked client - int unresponsiveness_reports; - struct reply_state *replies; // corresponding (active) reply list - req_termination_fn terminate; - DNSServiceFlags flags; - mDNSu32 interfaceIndex; - - union - { - registered_record_entry *reg_recs; // list of registrations for a connection-oriented request - struct - { - mDNSInterfaceID interface_id; - mDNSBool default_domain; - mDNSBool ForceMCast; - domainname regtype; - browser_t *browsers; - const mDNSu8 *AnonData; - } browser; - struct - { - mDNSInterfaceID InterfaceID; - mDNSu16 txtlen; - void *txtdata; - mDNSIPPort port; - domainlabel name; - char type_as_string[MAX_ESCAPED_DOMAIN_NAME]; - domainname type; - mDNSBool default_domain; - domainname host; - mDNSBool autoname; // Set if this name is tied to the Computer Name - mDNSBool autorename; // Set if this client wants us to automatically rename on conflict - mDNSBool allowremotequery; // Respond to unicast queries from outside the local link? - int num_subtypes; - mDNSBool AnonData; - service_instance *instances; - } servicereg; - struct - { - mDNSInterfaceID interface_id; - mDNSu32 flags; - mDNSu32 protocol; - DNSQuestion q4; - DNSQuestion *q42; - DNSQuestion q6; - DNSQuestion *q62; - mDNSu8 v4ans; - mDNSu8 v6ans; - } addrinfo; - struct - { - mDNSIPPort ReqExt; // External port we originally requested, for logging purposes - NATTraversalInfo NATinfo; - } pm; - struct - { - DNSServiceFlags flags; - DNSQuestion q_all; - DNSQuestion q_default; - } enumeration; - struct - { - DNSQuestion q; - DNSQuestion *q2; - mDNSu8 ans; - } queryrecord; - struct - { - DNSQuestion qtxt; - DNSQuestion qsrv; - const ResourceRecord *txt; - const ResourceRecord *srv; - mDNSs32 ReportTime; - mDNSBool external_advertise; - } resolve; - } u; -}; - -// struct physically sits between ipc message header and call-specific fields in the message buffer -typedef struct -{ - DNSServiceFlags flags; // Note: This field is in NETWORK byte order - mDNSu32 ifi; // Note: This field is in NETWORK byte order - DNSServiceErrorType error; // Note: This field is in NETWORK byte order -} reply_hdr; - -typedef struct reply_state -{ - struct reply_state *next; // If there are multiple unsent replies - mDNSu32 totallen; - mDNSu32 nwriten; - ipc_msg_hdr mhdr[1]; - reply_hdr rhdr[1]; -} reply_state; - -// *************************************************************************** -#if COMPILER_LIKES_PRAGMA_MARK -#pragma mark - #pragma mark - Globals #endif @@ -271,11 +94,19 @@ typedef struct reply_state mDNSexport mDNS mDNSStorage; mDNSexport const char ProgramName[] = "mDNSResponder"; +#if defined(USE_TCP_LOOPBACK) +static char* boundPath = NULL; +#else +static char* boundPath = MDNS_UDS_SERVERPATH; +#endif +#if DEBUG +#define MDNS_UDS_SERVERPATH_DEBUG "/var/tmp/mDNSResponder" +#endif static dnssd_sock_t listenfd = dnssd_InvalidSocket; static request_state *all_requests = NULL; -#ifdef LOCAL_PEERPID +#ifdef LOCAL_PEEREPID struct proc_bsdshortinfo proc; -#endif //LOCAL_PEERPID +#endif //LOCAL_PEEREPID mDNSlocal void set_peer_pid(request_state *request); mDNSlocal void LogMcastClientInfo(request_state *req); mDNSlocal void GetMcastClients(request_state *req); @@ -284,6 +115,13 @@ static mDNSu32 i_mcount; // sets mcount when McastLogging is enabled(PROF sign static mDNSu32 n_mrecords; // tracks the current active mcast records for McastLogging static mDNSu32 n_mquests; // tracks the current active mcast questions for McastLogging + +#if TARGET_OS_EMBEDDED +mDNSu32 curr_num_regservices = 0; +mDNSu32 max_num_regservices = 0; +#endif + + // Note asymmetry here between registration and browsing. // For service registrations we only automatically register in domains that explicitly appear in local configuration data // (so AutoRegistrationDomains could equally well be called SCPrefRegDomains) @@ -340,13 +178,13 @@ mDNSlocal void my_perror(char *errmsg) mDNSlocal void my_throttled_perror(char *err_msg) { static int uds_throttle_count = 0; - if ((uds_throttle_count++ % 250) == 0) + if ((uds_throttle_count++ % 250) == 0) my_perror(err_msg); -} +} // LogMcastQuestion/LogMcastQ should be called after the DNSQuestion struct is initialized(especially for q->TargetQID) // Hence all calls are made after mDNS_StartQuery()/mDNS_StopQuery()/mDNS_StopBrowse() is called. -mDNSlocal void LogMcastQuestion(mDNS *const m, const DNSQuestion *const q, request_state *req, q_state status) +mDNSlocal void LogMcastQuestion(const DNSQuestion *const q, request_state *req, q_state status) { if (mDNSOpaque16IsZero(q->TargetQID)) // Check for Mcast Query { @@ -360,18 +198,20 @@ mDNSlocal void LogMcastQuestion(mDNS *const m, const DNSQuestion *const q, reque { mcount--; } - LogMcast("%s: %##s (%s) (%s) Client(%d)[%s]", status ? "+Question" : "-Question", q->qname.c, DNSTypeName(q->qtype), - q->InterfaceID == mDNSInterface_LocalOnly ? "lo" : q->InterfaceID == mDNSInterface_P2P ? "p2p" : - q->InterfaceID == mDNSInterface_Any ? "any" : InterfaceNameForID(m, q->InterfaceID), + LogMcast("%s: %##s (%s) (%s) Client(%d)[%s]", status ? "+Question" : "-Question", q->qname.c, DNSTypeName(q->qtype), + q->InterfaceID == mDNSInterface_LocalOnly ? "lo" : + q->InterfaceID == mDNSInterface_P2P ? "p2p" : + q->InterfaceID == mDNSInterface_BLE ? "BLE" : + q->InterfaceID == mDNSInterface_Any ? "any" : InterfaceNameForID(&mDNSStorage, q->InterfaceID), req->process_id, req->pid_name); - LogMcastStateInfo(m, mflag, mDNSfalse, mDNSfalse); + LogMcastStateInfo(mflag, mDNSfalse, mDNSfalse); } return; } // LogMcastService/LogMcastS should be called after the AuthRecord struct is initialized // Hence all calls are made after mDNS_Register()/ just before mDNS_Deregister() -mDNSlocal void LogMcastService(mDNS *const m, const AuthRecord *const ar, request_state *req, reg_state status) +mDNSlocal void LogMcastService(const AuthRecord *const ar, request_state *req, reg_state status) { if (!AuthRecord_uDNS(ar)) // Check for Mcast Service { @@ -386,17 +226,20 @@ mDNSlocal void LogMcastService(mDNS *const m, const AuthRecord *const ar, reques mcount--; } LogMcast("%s: %##s (%s) (%s) Client(%d)[%s]", status ? "+Service" : "-Service", ar->resrec.name->c, DNSTypeName(ar->resrec.rrtype), - ar->resrec.InterfaceID == mDNSInterface_LocalOnly ? "lo" : ar->resrec.InterfaceID == mDNSInterface_P2P ? "p2p" : - ar->resrec.InterfaceID == mDNSInterface_Any ? "all" : InterfaceNameForID(m, ar->resrec.InterfaceID), + ar->resrec.InterfaceID == mDNSInterface_LocalOnly ? "lo" : + ar->resrec.InterfaceID == mDNSInterface_P2P ? "p2p" : + ar->resrec.InterfaceID == mDNSInterface_BLE ? "BLE" : + ar->resrec.InterfaceID == mDNSInterface_Any ? "all" : InterfaceNameForID(&mDNSStorage, ar->resrec.InterfaceID), req->process_id, req->pid_name); - LogMcastStateInfo(m, mflag, mDNSfalse, mDNSfalse); + LogMcastStateInfo(mflag, mDNSfalse, mDNSfalse); } return; } // For complete Mcast State Log, pass mDNStrue to mstatelog in LogMcastStateInfo() -mDNSexport void LogMcastStateInfo(mDNS *const m, mDNSBool mflag, mDNSBool start, mDNSBool mstatelog) +mDNSexport void LogMcastStateInfo(mDNSBool mflag, mDNSBool start, mDNSBool mstatelog) { + mDNS *const m = &mDNSStorage; if (!mstatelog) { if (!all_requests) @@ -407,13 +250,13 @@ mDNSexport void LogMcastStateInfo(mDNS *const m, mDNSBool mflag, mDNSBool start, { request_state *req, *r; for (req = all_requests; req; req=req->next) - { + { if (req->primary) // If this is a subbordinate operation, check that the parent is in the list - { - for (r = all_requests; r && r != req; r=r->next) - if (r == req->primary) + { + for (r = all_requests; r && r != req; r=r->next) + if (r == req->primary) goto foundpar; - } + } // For non-subbordinate operations, and subbordinate operations that have lost their parent, write out their info GetMcastClients(req); foundpar:; @@ -432,28 +275,28 @@ mDNSexport void LogMcastStateInfo(mDNS *const m, mDNSBool mflag, mDNSBool start, // wrong value if MulticastLogging is disabled and then re-enabled LogMcastNoIdent("--- START MCAST STATE LOG ---"); if (!all_requests) - { + { mcount = 0; LogMcastNoIdent("<None>"); - } - else - { + } + else + { request_state *req, *r; for (req = all_requests; req; req=req->next) - { + { if (req->primary) // If this is a subbordinate operation, check that the parent is in the list - { - for (r = all_requests; r && r != req; r=r->next) - if (r == req->primary) + { + for (r = all_requests; r && r != req; r=r->next) + if (r == req->primary) goto foundparent; LogMcastNoIdent("%3d: Orphan operation; parent not found in request list", req->sd); - } + } // For non-subbordinate operations, and subbordinate operations that have lost their parent, write out their info LogMcastClientInfo(req); foundparent:; } if(!mcount) // To initially set mcount - mcount = i_mcount; + mcount = i_mcount; } if (mcount == 0) { @@ -461,7 +304,7 @@ mDNSexport void LogMcastStateInfo(mDNS *const m, mDNSBool mflag, mDNSBool start, LogMcastNoIdent("--- MCOUNT[%d]: IMPKTNUM[%d] ---", mcount, i_mpktnum); } if (mflag) - LogMcastNoIdent("--- MCOUNT[%d]: CMPKTNUM[%d] - IMPKTNUM[%d] = [%d]PKTS ---", mcount, m->MPktNum, i_mpktnum, (m->MPktNum - i_mpktnum)); + LogMcastNoIdent("--- MCOUNT[%d]: CMPKTNUM[%d] - IMPKTNUM[%d] = [%d]PKTS ---", mcount, m->MPktNum, i_mpktnum, (m->MPktNum - i_mpktnum)); LogMcastNoIdent("--- END MCAST STATE LOG ---"); } } @@ -507,6 +350,24 @@ mDNSlocal void abort_request(request_state *req) req->terminate = (req_termination_fn) ~0; } +#if DEBUG +mDNSexport void SetDebugBoundPath(void) +{ +#if !defined(USE_TCP_LOOPBACK) + boundPath = MDNS_UDS_SERVERPATH_DEBUG; +#endif +} + +mDNSexport int IsDebugSocketInUse(void) +{ +#if !defined(USE_TCP_LOOPBACK) + return !strcmp(boundPath, MDNS_UDS_SERVERPATH_DEBUG); +#else + return mDNSfalse; +#endif +} +#endif + mDNSlocal void AbortUnlinkAndFree(request_state *req) { request_state **p = &all_requests; @@ -611,9 +472,7 @@ mDNSlocal mStatus GenerateNTDResponse(const domainname *const servicename, const } } -// Special support to enable the DNSServiceBrowse call made by Bonjour Browser -// Remove after Bonjour Browser is updated to use DNSServiceQueryRecord instead of DNSServiceBrowse -mDNSlocal void GenerateBonjourBrowserResponse(const domainname *const servicename, const mDNSInterfaceID id, +mDNSlocal void GenerateBrowseReply(const domainname *const servicename, const mDNSInterfaceID id, request_state *const request, reply_state **const rep, reply_op_t op, DNSServiceFlags flags, mStatus err) { char namestr[MAX_DOMAIN_LABEL+1]; @@ -665,7 +524,7 @@ mDNSlocal AuthRecord *read_rr_from_ipc_msg(request_state *request, int GetTTL, i mDNSu16 rdlen = get_uint16(&request->msgptr, request->msgend); const char *rdata = get_rdata (&request->msgptr, request->msgend, rdlen); mDNSu32 ttl = GetTTL ? get_uint32(&request->msgptr, request->msgend) : 0; - int storage_size = rdlen > sizeof(RDataBody) ? rdlen : sizeof(RDataBody); + size_t storage_size = rdlen > sizeof(RDataBody) ? rdlen : sizeof(RDataBody); AuthRecord *rr; mDNSInterfaceID InterfaceID; AuthRecType artype; @@ -691,7 +550,7 @@ mDNSlocal AuthRecord *read_rr_from_ipc_msg(request_state *request, int GetTTL, i InterfaceID = mDNSPlatformInterfaceIDfromInterfaceIndex(&mDNSStorage, interfaceIndex); if (InterfaceID == mDNSInterface_LocalOnly) artype = AuthRecordLocalOnly; - else if (InterfaceID == mDNSInterface_P2P) + else if (InterfaceID == mDNSInterface_P2P || InterfaceID == mDNSInterface_BLE) artype = AuthRecordP2P; else if ((InterfaceID == mDNSInterface_Any) && (flags & kDNSServiceFlagsIncludeP2P) && (flags & kDNSServiceFlagsIncludeAWDL)) @@ -782,12 +641,14 @@ mDNSlocal mDNSBool AuthorizedDomain(const request_state * const request, const d #pragma mark - external helpers #endif -mDNSlocal mDNSBool callExternalHelpers(mDNSInterfaceID InterfaceID, const domainname *const domain, DNSServiceFlags flags) +mDNSexport mDNSBool callExternalHelpers(mDNSInterfaceID InterfaceID, const domainname *const domain, DNSServiceFlags flags) { #if APPLE_OSX_mDNSResponder - if ( ((InterfaceID == mDNSInterface_Any) && (flags & (kDNSServiceFlagsIncludeP2P | kDNSServiceFlagsIncludeAWDL)) && IsLocalDomain(domain)) - || mDNSPlatformInterfaceIsD2D(InterfaceID)) + // Only call D2D layer routines if request applies to a D2D interface and the domain is "local". + if ( (((InterfaceID == mDNSInterface_Any) && (flags & (kDNSServiceFlagsIncludeP2P | kDNSServiceFlagsIncludeAWDL | kDNSServiceFlagsAutoTrigger))) + || mDNSPlatformInterfaceIsD2D(InterfaceID) || (InterfaceID == mDNSInterface_BLE)) + && IsLocalDomain(domain)) { return mDNStrue; } @@ -822,6 +683,7 @@ mDNSlocal void external_start_advertising_helper(service_instance *const instanc external_start_advertising_service(&instance->srs.RR_PTR.resrec, instance->request->flags); external_start_advertising_service(&instance->srs.RR_SRV.resrec, instance->request->flags); + external_start_advertising_service(&instance->srs.RR_TXT.resrec, instance->request->flags); for (e = instance->srs.Extras; e; e = e->next) @@ -917,13 +779,13 @@ mDNSlocal void unlink_and_free_service_instance(service_instance *srv) // Count how many other service records we have locally with the same name, but different rdata. // For auto-named services, we can have at most one per machine -- if we allowed two auto-named services of // the same type on the same machine, we'd get into an infinite autoimmune-response loop of continuous renaming. -mDNSexport int CountPeerRegistrations(mDNS *const m, ServiceRecordSet *const srs) +mDNSexport int CountPeerRegistrations(ServiceRecordSet *const srs) { int count = 0; ResourceRecord *r = &srs->RR_SRV.resrec; AuthRecord *rr; - for (rr = m->ResourceRecords; rr; rr=rr->next) + for (rr = mDNSStorage.ResourceRecords; rr; rr=rr->next) if (rr->resrec.rrtype == kDNSType_SRV && SameDomainName(rr->resrec.name, r->name) && !IdenticalSameNameRecord(&rr->resrec, r)) count++; @@ -1009,11 +871,14 @@ mDNSlocal void regservice_callback(mDNS *const m, ServiceRecordSet *const srs, m LogInfo("regservice_callback: calling external_start_advertising_helper()"); external_start_advertising_helper(instance); } - if (instance->request->u.servicereg.autoname && CountPeerRegistrations(m, srs) == 0) - RecordUpdatedNiceLabel(m, 0); // Successfully got new name, tell user immediately + if (instance->request->u.servicereg.autoname && CountPeerRegistrations(srs) == 0) + RecordUpdatedNiceLabel(0); // Successfully got new name, tell user immediately } else if (result == mStatus_MemFree) { +#if TARGET_OS_EMBEDDED + curr_num_regservices--; +#endif if (instance->request && instance->renameonmemfree) { external_stop_advertising_helper(instance); @@ -1030,7 +895,7 @@ mDNSlocal void regservice_callback(mDNS *const m, ServiceRecordSet *const srs, m if (instance->request->u.servicereg.autorename) { external_stop_advertising_helper(instance); - if (instance->request->u.servicereg.autoname && CountPeerRegistrations(m, srs) == 0) + if (instance->request->u.servicereg.autoname && CountPeerRegistrations(srs) == 0) { // On conflict for an autoname service, rename and reregister *all* autoname services IncrementLabelSuffix(&m->nicelabel, mDNStrue); @@ -1144,32 +1009,30 @@ mDNSlocal void regrecord_callback(mDNS *const m, AuthRecord *rr, mStatus result) // This accounts for 2 places (connect_callback, request_callback) mDNSlocal void set_peer_pid(request_state *request) { -#ifdef LOCAL_PEERPID +#ifdef LOCAL_PEEREPID pid_t p = (pid_t) -1; socklen_t len = sizeof(p); +#endif request->pid_name[0] = '\0'; request->process_id = -1; - - if (request->sd < 0) +#ifdef LOCAL_PEEREPID + if (request->sd < 0) return; - // to extract the pid value - if (getsockopt(request->sd, SOL_LOCAL, LOCAL_PEERPID, &p, &len) != 0) + // to extract the effective pid value + if (getsockopt(request->sd, SOL_LOCAL, LOCAL_PEEREPID, &p, &len) != 0) return; // to extract the process name from the pid value if (proc_pidinfo(p, PROC_PIDT_SHORTBSDINFO, 1, &proc, PROC_PIDT_SHORTBSDINFO_SIZE) == 0) return; - mDNSPlatformStrCopy(request->pid_name, proc.pbsi_comm); + mDNSPlatformStrLCopy(request->pid_name, proc.pbsi_comm, sizeof(request->pid_name)); 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; - + debugf("set_peer_pid: Client PEEREPID is %d %s", p, request->pid_name); +#else // !LOCAL_PEEREPID LogInfo("set_peer_pid: Not Supported on this version of OS"); if (request->sd < 0) return; -#endif // LOCAL_PEERPID +#endif // LOCAL_PEEREPID } mDNSlocal void connection_termination(request_state *request) @@ -1200,14 +1063,14 @@ mDNSlocal void connection_termination(request_state *request) { registered_record_entry *ptr = request->u.reg_recs; LogOperation("%3d: DNSServiceRegisterRecord(%u %s) STOP PID[%d](%s)", request->sd, ptr->key, RRDisplayString(&mDNSStorage, &ptr->rr->resrec), request->process_id, request->pid_name); - request->u.reg_recs = request->u.reg_recs->next; + request->u.reg_recs = request->u.reg_recs->next; ptr->rr->RecordContext = NULL; if (ptr->external_advertise) { ptr->external_advertise = mDNSfalse; external_stop_advertising_service(&ptr->rr->resrec, request->flags); } - LogMcastS(&mDNSStorage, ptr->rr, request, reg_stop); + LogMcastS(ptr->rr, request, reg_stop); mDNS_Deregister(&mDNSStorage, ptr->rr); // Will free ptr->rr for us freeL("registered_record_entry/connection_termination", ptr); } @@ -1237,7 +1100,12 @@ mDNSlocal void handle_cancel_request(request_state *request) mDNSlocal mStatus handle_regrecord_request(request_state *request) { mStatus err = mStatus_BadParamErr; - AuthRecord *rr = read_rr_from_ipc_msg(request, 1, 1); + AuthRecord *rr; + + if (request->terminate != connection_termination) + { LogMsg("%3d: DNSServiceRegisterRecord(not a shared connection ref)", request->sd); return(err); } + + rr = read_rr_from_ipc_msg(request, 1, 1); if (rr) { registered_record_entry *re; @@ -1252,7 +1120,7 @@ mDNSlocal mStatus handle_regrecord_request(request_state *request) } // allocate registration entry, link into list re = mallocL("registered_record_entry", sizeof(registered_record_entry)); - if (!re) + if (!re) FatalError("ERROR: malloc"); re->key = request->hdr.reg_index; re->rr = rr; @@ -1263,7 +1131,7 @@ mDNSlocal mStatus handle_regrecord_request(request_state *request) rr->RecordCallback = regrecord_callback; re->origInterfaceID = rr->resrec.InterfaceID; - if (rr->resrec.InterfaceID == mDNSInterface_P2P) + if (rr->resrec.InterfaceID == mDNSInterface_P2P) rr->resrec.InterfaceID = mDNSInterface_Any; #if 0 if (!AuthorizedDomain(request, rr->resrec.name, AutoRegistrationDomains)) return (mStatus_NoError); @@ -1271,7 +1139,7 @@ mDNSlocal mStatus handle_regrecord_request(request_state *request) if (rr->resrec.rroriginalttl == 0) rr->resrec.rroriginalttl = DefaultTTLforRRType(rr->resrec.rrtype); - LogOperation("%3d: DNSServiceRegisterRecord(%u %s) START PID[%d](%s)", request->sd, re->key, RRDisplayString(&mDNSStorage, &rr->resrec), + LogOperation("%3d: DNSServiceRegisterRecord(%u %s) START PID[%d](%s)", request->sd, re->key, RRDisplayString(&mDNSStorage, &rr->resrec), request->process_id, request->pid_name); err = mDNS_Register(&mDNSStorage, rr); @@ -1283,7 +1151,7 @@ mDNSlocal mStatus handle_regrecord_request(request_state *request) } else { - LogMcastS(&mDNSStorage, rr, request, reg_start); + LogMcastS(rr, request, reg_start); re->next = request->u.reg_recs; request->u.reg_recs = re; } @@ -1295,17 +1163,17 @@ mDNSlocal void UpdateDeviceInfoRecord(mDNS *const m); mDNSlocal void regservice_termination_callback(request_state *request) { - if (!request) - { - LogMsg("regservice_termination_callback context is NULL"); - return; + if (!request) + { + LogMsg("regservice_termination_callback context is NULL"); + return; } while (request->u.servicereg.instances) { service_instance *p = request->u.servicereg.instances; request->u.servicereg.instances = request->u.servicereg.instances->next; // only safe to free memory if registration is not valid, i.e. deregister fails (which invalidates p) - LogOperation("%3d: DNSServiceRegister(%##s, %u) STOP PID[%d](%s)", request->sd, p->srs.RR_SRV.resrec.name->c, + LogOperation("%3d: DNSServiceRegister(%##s, %u) STOP PID[%d](%s)", request->sd, p->srs.RR_SRV.resrec.name->c, mDNSVal16(p->srs.RR_SRV.resrec.rdata->u.srv.port), request->process_id, request->pid_name); external_stop_advertising_helper(p); @@ -1316,7 +1184,7 @@ mDNSlocal void regservice_termination_callback(request_state *request) // We can't clear p->request *after* the calling mDNS_DeregisterService/unlink_and_free_service_instance // because by then we might have already freed p p->request = NULL; - LogMcastS(&mDNSStorage, &p->srs.RR_SRV, request, reg_stop); + LogMcastS(&p->srs.RR_SRV, request, reg_stop); if (mDNS_DeregisterService(&mDNSStorage, &p->srs)) { unlink_and_free_service_instance(p); @@ -1324,9 +1192,9 @@ mDNSlocal void regservice_termination_callback(request_state *request) } } if (request->u.servicereg.txtdata) - { - freeL("service_info txtdata", request->u.servicereg.txtdata); - request->u.servicereg.txtdata = NULL; + { + freeL("service_info txtdata", request->u.servicereg.txtdata); + request->u.servicereg.txtdata = NULL; } if (request->u.servicereg.autoname) { @@ -1350,8 +1218,7 @@ mDNSlocal mStatus add_record_to_service(request_state *request, service_instance { ServiceRecordSet *srs = &instance->srs; mStatus result; - mDNSu32 coreFlags = 0; // translate to corresponding mDNSCore flag definitions - int size = rdlen > sizeof(RDataBody) ? rdlen : sizeof(RDataBody); + size_t size = rdlen > sizeof(RDataBody) ? rdlen : sizeof(RDataBody); ExtraResourceRecord *extra = mallocL("ExtraResourceRecord", sizeof(*extra) - sizeof(RDataBody) + size); if (!extra) { my_perror("ERROR: malloc"); return mStatus_NoMemoryErr; } @@ -1363,19 +1230,14 @@ mDNSlocal mStatus add_record_to_service(request_state *request, service_instance // use InterfaceID value from DNSServiceRegister() call that created the original service extra->r.resrec.InterfaceID = request->u.servicereg.InterfaceID; - if (request->flags & kDNSServiceFlagsIncludeP2P) - coreFlags |= coreFlagIncludeP2P; - if (request->flags & kDNSServiceFlagsIncludeAWDL) - coreFlags |= coreFlagIncludeAWDL; - - result = mDNS_AddRecordToService(&mDNSStorage, srs, extra, &extra->r.rdatastorage, ttl, coreFlags); - if (result) - { - freeL("ExtraResourceRecord/add_record_to_service", extra); - return result; - } - LogMcastS(&mDNSStorage, &srs->RR_PTR, request, reg_start); - + result = mDNS_AddRecordToService(&mDNSStorage, srs, extra, &extra->r.rdatastorage, ttl, request->flags); + if (result) + { + freeL("ExtraResourceRecord/add_record_to_service", extra); + return result; + } + LogMcastS(&srs->RR_PTR, request, reg_start); + extra->ClientID = request->hdr.reg_index; if ( instance->external_advertise && callExternalHelpers(request->u.servicereg.InterfaceID, &instance->domain, request->flags)) @@ -1411,8 +1273,9 @@ mDNSlocal mStatus handle_add_request(request_state *request) if (mDNSIPPortIsZero(request->u.servicereg.port)) { LogMsg("%3d: DNSServiceAddRecord: adding record to a service registered with zero port", request->sd); return(mStatus_BadParamErr); } - LogOperation("%3d: DNSServiceAddRecord(%X, %##s, %s, %d)", request->sd, flags, - (request->u.servicereg.instances) ? request->u.servicereg.instances->srs.RR_SRV.resrec.name->c : NULL, DNSTypeName(rrtype), rdlen); + LogOperation("%3d: DNSServiceAddRecord(%X, %##s, %s, %d) PID[%d](%s)", request->sd, flags, + (request->u.servicereg.instances) ? request->u.servicereg.instances->srs.RR_SRV.resrec.name->c : NULL, DNSTypeName(rrtype), rdlen, + request->process_id, request->pid_name); for (i = request->u.servicereg.instances; i; i = i->next) { @@ -1441,14 +1304,7 @@ mDNSlocal void update_callback(mDNS *const m, AuthRecord *const rr, RData *oldrd if (external_advertise) { ResourceRecord ext = rr->resrec; - DNSServiceFlags flags = 0; - - // Since we don't have a copy of the flags value used when the record was registered, - // we'll have to derive it from the ARType field. - if (rr->ARType == AuthRecordAnyIncludeP2P) - flags |= kDNSServiceFlagsIncludeP2P; - else if (rr->ARType == AuthRecordAnyIncludeAWDL) - flags |= kDNSServiceFlagsIncludeAWDL; + DNSServiceFlags flags = deriveD2DFlagsFromAuthRecType(rr->ARType); if (ext.rdlength == oldrdlen && mDNSPlatformMemSame(&ext.rdata->u, &oldrd->u, oldrdlen)) goto exit; SetNewRData(&ext, oldrd, oldrdlen); @@ -1463,7 +1319,7 @@ exit: mDNSlocal mStatus update_record(AuthRecord *rr, mDNSu16 rdlen, const char *rdata, mDNSu32 ttl, const mDNSBool *const external_advertise) { mStatus result; - const int rdsize = rdlen > sizeof(RDataBody) ? rdlen : sizeof(RDataBody); + const size_t rdsize = rdlen > sizeof(RDataBody) ? rdlen : sizeof(RDataBody); RData *newrd = mallocL("RData/update_record", sizeof(RData) - sizeof(RDataBody) + rdsize); if (!newrd) FatalError("ERROR: malloc"); newrd->MaxRDLength = (mDNSu16) rdsize; @@ -1509,8 +1365,9 @@ mDNSlocal mStatus handle_update_request(request_state *request) if (reptr->key == hdr->reg_index) { result = update_record(reptr->rr, rdlen, rdata, ttl, &reptr->external_advertise); - LogOperation("%3d: DNSServiceUpdateRecord(%##s, %s)", - request->sd, reptr->rr->resrec.name->c, reptr->rr ? DNSTypeName(reptr->rr->resrec.rrtype) : "<NONE>"); + LogOperation("%3d: DNSServiceUpdateRecord(%##s, %s) PID[%d](%s)", + request->sd, reptr->rr->resrec.name->c, reptr->rr ? DNSTypeName(reptr->rr->resrec.rrtype) : "<NONE>", + request->process_id, request->pid_name); goto end; } } @@ -1558,9 +1415,10 @@ mDNSlocal mStatus handle_update_request(request_state *request) end: if (request->terminate == regservice_termination_callback) - LogOperation("%3d: DNSServiceUpdateRecord(%##s, %s)", request->sd, + LogOperation("%3d: DNSServiceUpdateRecord(%##s, %s) PID[%d](%s)", request->sd, (request->u.servicereg.instances) ? request->u.servicereg.instances->srs.RR_SRV.resrec.name->c : NULL, - rr ? DNSTypeName(rr->resrec.rrtype) : "<NONE>"); + rr ? DNSTypeName(rr->resrec.rrtype) : "<NONE>", + request->process_id, request->pid_name); return(result); } @@ -1576,14 +1434,15 @@ mDNSlocal mStatus remove_record(request_state *request) e = *ptr; *ptr = e->next; // unlink - LogOperation("%3d: DNSServiceRemoveRecord(%u %s)", request->sd, e->key, RRDisplayString(&mDNSStorage, &e->rr->resrec)); + LogOperation("%3d: DNSServiceRemoveRecord(%u %s) PID[%d](%s)", + request->sd, e->key, RRDisplayString(&mDNSStorage, &e->rr->resrec), request->process_id, request->pid_name); e->rr->RecordContext = NULL; if (e->external_advertise) { external_stop_advertising_service(&e->rr->resrec, request->flags); e->external_advertise = mDNSfalse; } - LogMcastS(&mDNSStorage, e->rr, request, reg_stop); + LogMcastS(e->rr, request, reg_stop); err = mDNS_Deregister(&mDNSStorage, e->rr); // Will free e->rr for us; we're responsible for freeing e if (err) { @@ -1630,9 +1489,9 @@ mDNSlocal mStatus handle_removerecord_request(request_state *request) { service_instance *i; mDNSu16 rrtype = 0; - LogOperation("%3d: DNSServiceRemoveRecord(%##s, %s)", request->sd, + LogOperation("%3d: DNSServiceRemoveRecord(%##s, %s) PID[%d](%s)", request->sd, (request->u.servicereg.instances) ? request->u.servicereg.instances->srs.RR_SRV.resrec.name->c : NULL, - rrtype ? DNSTypeName(rrtype) : "<NONE>"); + rrtype ? DNSTypeName(rrtype) : "<NONE>", request->process_id, request->pid_name); for (i = request->u.servicereg.instances; i; i = i->next) { err = remove_extra(request, i, &rrtype); @@ -1713,7 +1572,7 @@ mDNSexport mDNSs32 ChopSubTypes(char *regtype, char **AnonData) mDNSexport AuthRecord *AllocateSubTypes(mDNSs32 NumSubTypes, char *p, char **AnonData) { AuthRecord *st = mDNSNULL; - // + // // "p" is pointing at the regtype e.g., _http._tcp followed by ":<AnonData>" indicated // by AnonData being non-NULL which is in turn follwed by ",<SubTypes>" indicated by // NumSubTypes being non-zero. We need to skip the initial regtype to get to the actual @@ -1761,7 +1620,7 @@ mDNSexport AuthRecord *AllocateSubTypes(mDNSs32 NumSubTypes, char *p, char **Ano if (!MakeDomainNameFromDNSNameString(&st[i].namestorage, p)) { freeL("ServiceSubTypes", st); - if (*AnonData) + if (AnonData && *AnonData) freeL("AnonymousData", *AnonData); return(mDNSNULL); } @@ -1775,24 +1634,10 @@ mDNSexport AuthRecord *AllocateSubTypes(mDNSs32 NumSubTypes, char *p, char **Ano mDNSlocal mStatus register_service_instance(request_state *request, const domainname *domain) { service_instance **ptr, *instance; - const int extra_size = (request->u.servicereg.txtlen > sizeof(RDataBody)) ? (request->u.servicereg.txtlen - sizeof(RDataBody)) : 0; + size_t extra_size = (request->u.servicereg.txtlen > sizeof(RDataBody)) ? (request->u.servicereg.txtlen - sizeof(RDataBody)) : 0; const mDNSBool DomainIsLocal = SameDomainName(domain, &localdomain); mStatus result; mDNSInterfaceID interfaceID = request->u.servicereg.InterfaceID; - mDNSu32 coreFlags = 0; - - if (request->flags & kDNSServiceFlagsIncludeP2P) - coreFlags |= coreFlagIncludeP2P; - if (request->flags & kDNSServiceFlagsIncludeAWDL) - coreFlags |= coreFlagIncludeAWDL; - - // Client guarantees that record names are unique, so we can skip sending out initial - // probe messages. Standard name conflict resolution is still done if a conflict is discovered. - if (request->flags & kDNSServiceFlagsKnownUnique) - coreFlags |= coreFlagKnownUnique; - - if (request->flags & kDNSServiceFlagsWakeOnlyService) - coreFlags |= coreFlagWakeOnly; // If the client specified an interface, but no domain, then we honor the specified interface for the "local" (mDNS) // registration but for the wide-area registrations we don't (currently) have any concept of a wide-area unicast @@ -1832,14 +1677,14 @@ mDNSlocal mStatus register_service_instance(request_state *request, const domain char *AnonData = mDNSNULL; instance->subtypes = AllocateSubTypes(request->u.servicereg.num_subtypes, request->u.servicereg.type_as_string, &AnonData); if (AnonData) - instance->srs.AnonData = (const mDNSu8 *)AnonData; + instance->srs.AnonData = (const mDNSu8 *)AnonData; } if (request->u.servicereg.num_subtypes && !instance->subtypes) - { - unlink_and_free_service_instance(instance); - instance = NULL; - FatalError("ERROR: malloc"); + { + unlink_and_free_service_instance(instance); + instance = NULL; + FatalError("ERROR: malloc"); } result = mDNS_RegisterService(&mDNSStorage, &instance->srs, @@ -1848,14 +1693,14 @@ mDNSlocal mStatus register_service_instance(request_state *request, const domain request->u.servicereg.port, request->u.servicereg.txtdata, request->u.servicereg.txtlen, instance->subtypes, request->u.servicereg.num_subtypes, - interfaceID, regservice_callback, instance, coreFlags); + interfaceID, regservice_callback, instance, request->flags); if (!result) { *ptr = instance; // Append this to the end of our request->u.servicereg.instances list - LogOperation("%3d: DNSServiceRegister(%##s, %u) ADDED", instance->request->sd, + LogOperation("%3d: DNSServiceRegister(%##s, %u) ADDED", instance->request->sd, instance->srs.RR_SRV.resrec.name->c, mDNSVal16(request->u.servicereg.port)); - LogMcastS(&mDNSStorage, &instance->srs.RR_SRV, request, reg_start); + LogMcastS(&instance->srs.RR_SRV, request, reg_start); } else { @@ -1871,10 +1716,6 @@ mDNSlocal void udsserver_default_reg_domain_changed(const DNameListElem *const d { request_state *request; -#if APPLE_OSX_mDNSResponder - machserver_automatic_registration_domain_changed(&d->name, add); -#endif // APPLE_OSX_mDNSResponder - LogMsg("%s registration domain %##s", add ? "Adding" : "Removing", d->name.c); for (request = all_requests; request; request = request->next) { @@ -1989,6 +1830,7 @@ mDNSlocal mDNSBool PreDefinedInterfaceIndex(mDNSu32 interfaceIndex) case kDNSServiceInterfaceIndexLocalOnly: case kDNSServiceInterfaceIndexUnicast: case kDNSServiceInterfaceIndexP2P: + case kDNSServiceInterfaceIndexBLE: return mDNStrue; default: return mDNSfalse; @@ -2009,7 +1851,7 @@ mDNSlocal mStatus handle_regservice_request(request_state *request) mDNSu32 interfaceIndex = get_uint32(&request->msgptr, request->msgend); mDNSInterfaceID InterfaceID; - // Map kDNSServiceInterfaceIndexP2P to kDNSServiceInterfaceIndexAny with the + // Map kDNSServiceInterfaceIndexP2P to kDNSServiceInterfaceIndexAny with the // kDNSServiceFlagsIncludeP2P flag set. if (interfaceIndex == kDNSServiceInterfaceIndexP2P) { @@ -2020,7 +1862,7 @@ mDNSlocal mStatus handle_regservice_request(request_state *request) InterfaceID = mDNSPlatformInterfaceIDfromInterfaceIndex(&mDNSStorage, interfaceIndex); - // The registration is scoped to a specific interface index, but the + // The registration is scoped to a specific interface index, but the // interface is not currently in our list. if (interfaceIndex && !InterfaceID) { @@ -2049,7 +1891,7 @@ mDNSlocal mStatus handle_regservice_request(request_state *request) request->u.servicereg.instances = NULL; request->u.servicereg.txtlen = 0; request->u.servicereg.txtdata = NULL; - mDNSPlatformStrCopy(request->u.servicereg.type_as_string, type_as_string); + mDNSPlatformStrLCopy(request->u.servicereg.type_as_string, type_as_string, sizeof(request->u.servicereg.type_as_string)); if (request->msgptr + 2 > request->msgend) request->msgptr = NULL; else @@ -2151,8 +1993,17 @@ mDNSlocal mStatus handle_regservice_request(request_state *request) request->pid_name, count+1, srv.c, mDNSVal16(request->u.servicereg.port)); } +#if APPLE_OSX_mDNSResponder && ENABLE_BLE_TRIGGERED_BONJOUR + // Determine if this request should be promoted to use BLE triggered feature. + if (shouldUseBLE(InterfaceID, 0, &request->u.servicereg.type, &d)) + { + request->flags |= (kDNSServiceFlagsAutoTrigger | kDNSServiceFlagsIncludeAWDL); + LogInfo("handle_regservice_request: registration promoted to use kDNSServiceFlagsAutoTrigger"); + } +#endif // APPLE_OSX_mDNSResponder && ENABLE_BLE_TRIGGERED_BONJOUR + LogOperation("%3d: DNSServiceRegister(%X, %d, \"%s\", \"%s\", \"%s\", \"%s\", %u) START PID[%d](%s)", - request->sd, flags, interfaceIndex, name, request->u.servicereg.type_as_string, domain, host, + request->sd, request->flags, interfaceIndex, name, request->u.servicereg.type_as_string, domain, host, mDNSVal16(request->u.servicereg.port), request->process_id, request->pid_name); // We need to unconditionally set request->terminate, because even if we didn't successfully @@ -2165,6 +2016,12 @@ mDNSlocal mStatus handle_regservice_request(request_state *request) err = register_service_instance(request, &d); +#if TARGET_OS_EMBEDDED + ++curr_num_regservices; + if (curr_num_regservices > max_num_regservices) + max_num_regservices = curr_num_regservices; +#endif + #if 0 err = AuthorizedDomain(request, &d, AutoRegistrationDomains) ? register_service_instance(request, &d) : mStatus_NoError; #endif @@ -2211,14 +2068,21 @@ mDNSlocal void FoundInstance(mDNS *const m, DNSQuestion *question, const Resourc flags |= kDNSServiceFlagsThresholdReached; } + // if returning a negative answer, then use question's name in reply + if (answer->RecordType == kDNSRecordTypePacketNegative) + { + GenerateBrowseReply(&question->qname, answer->InterfaceID, req, &rep, browse_reply_op, flags, kDNSServiceErr_NoSuchRecord); + goto validReply; + } + if (GenerateNTDResponse(&answer->rdata->u.name, answer->InterfaceID, req, &rep, browse_reply_op, flags, mStatus_NoError) != mStatus_NoError) { if (SameDomainName(&req->u.browser.regtype, (const domainname*)"\x09_services\x07_dns-sd\x04_udp")) { // Special support to enable the DNSServiceBrowse call made by Bonjour Browser // Remove after Bonjour Browser is updated to use DNSServiceQueryRecord instead of DNSServiceBrowse - GenerateBonjourBrowserResponse(&answer->rdata->u.name, answer->InterfaceID, req, &rep, browse_reply_op, flags, mStatus_NoError); - goto bonjourbrowserhack; + GenerateBrowseReply(&answer->rdata->u.name, answer->InterfaceID, req, &rep, browse_reply_op, flags, mStatus_NoError); + goto validReply; } LogMsg("%3d: FoundInstance: %##s PTR %##s received from network is not valid DNS-SD service pointer", @@ -2226,15 +2090,41 @@ mDNSlocal void FoundInstance(mDNS *const m, DNSQuestion *question, const Resourc return; } -bonjourbrowserhack: +validReply: - LogOperation("%3d: DNSServiceBrowse(%##s, %s) RESULT %s %d: %s", - req->sd, question->qname.c, DNSTypeName(question->qtype), AddRecord ? "Add" : "Rmv", + LogOperation("%3d: DNSServiceBrowse(%##s, %s) RESULT %s interface %d: %s", + req->sd, question->qname.c, DNSTypeName(question->qtype), AddRecord ? "ADD" : "RMV", mDNSPlatformInterfaceIndexfromInterfaceID(m, answer->InterfaceID, mDNSfalse), RRDisplayString(m, answer)); append_reply(req, rep); } +mDNSlocal void SetQuestionPolicy(DNSQuestion *q, request_state *req) +{ + 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 + // by examining all the 16 bytes at the time of the policy + // check and also when setting the delegate socket option. Also, it + // requires that we zero out the uuid wherever the question is + // initialized to make sure that it is not interpreted as valid. + // To prevent these intrusive changes, just pass a zero pid to indicate + // that pid is not valid when uuid is valid. In future if we need the + // pid in the question, we will reevaluate this strategy. + if (req->validUUID) + { + mDNSPlatformMemCopy(q->uuid, req->uuid, UUID_SIZE); + q->pid = 0; + } + else + { + 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 add_domain_to_browser(request_state *info, const domainname *d) { browser_t *b, *p; @@ -2248,8 +2138,10 @@ mDNSlocal mStatus add_domain_to_browser(request_state *info, const domainname *d b = mallocL("browser_t", sizeof(*b)); if (!b) return mStatus_NoMemoryErr; + mDNSPlatformMemZero(b, sizeof(*b)); AssignDomainName(&b->domain, d); - err = mDNS_StartBrowse(&mDNSStorage, &b->q, &info->u.browser.regtype, d, info->u.browser.AnonData, info->u.browser.interface_id, info->flags, + SetQuestionPolicy(&b->q, info); + err = mDNS_StartBrowse(&mDNSStorage, &b->q, &info->u.browser.regtype, d, info->u.browser.AnonData, info->u.browser.interface_id, info->flags, info->u.browser.ForceMCast, (info->flags & kDNSServiceFlagsBackgroundTrafficClass) != 0, FoundInstance, info); if (err) { @@ -2260,9 +2152,18 @@ mDNSlocal mStatus add_domain_to_browser(request_state *info, const domainname *d { b->next = info->u.browser.browsers; info->u.browser.browsers = b; - LogOperation("%3d: DNSServiceBrowse(%##s) START PID[%d](%s)", info->sd, b->q.qname.c, info->process_id, - info->pid_name); - LogMcastQ(&mDNSStorage, &b->q, info, q_start); + +#if APPLE_OSX_mDNSResponder && ENABLE_BLE_TRIGGERED_BONJOUR + // Determine if this request should be promoted to use BLE triggered discovery. + if (shouldUseBLE(info->u.browser.interface_id, 0, &info->u.browser.regtype, (domainname *) d)) + { + info->flags |= (kDNSServiceFlagsAutoTrigger | kDNSServiceFlagsIncludeAWDL); + b->q.flags |= (kDNSServiceFlagsAutoTrigger | kDNSServiceFlagsIncludeAWDL); + LogInfo("add_domain_to_browser: request promoted to use kDNSServiceFlagsAutoTrigger"); + } +#endif // APPLE_OSX_mDNSResponder && ENABLE_BLE_TRIGGERED_BONJOUR + + LogMcastQ(&b->q, info, q_start); if (callExternalHelpers(info->u.browser.interface_id, &b->domain, info->flags)) { domainname tmp; @@ -2288,18 +2189,20 @@ mDNSlocal void browse_termination_callback(request_state *info) { browser_t *ptr = info->u.browser.browsers; - if (callExternalHelpers(info->u.browser.interface_id, &ptr->domain, info->flags)) + if (callExternalHelpers(ptr->q.InterfaceID, &ptr->domain, ptr->q.flags)) { domainname tmp; ConstructServiceName(&tmp, NULL, &info->u.browser.regtype, &ptr->domain); LogInfo("browse_termination_callback: calling external_stop_browsing_for_service()"); - external_stop_browsing_for_service(info->u.browser.interface_id, &tmp, kDNSType_PTR, info->flags); + external_stop_browsing_for_service(ptr->q.InterfaceID, &tmp, kDNSType_PTR, ptr->q.flags); } + LogOperation("%3d: DNSServiceBrowse(%X, %d, \"%##s\") STOP PID[%d](%s)", + info->sd, info->flags, info->interfaceIndex, ptr->q.qname.c, info->process_id, info->pid_name); + info->u.browser.browsers = ptr->next; - LogOperation("%3d: DNSServiceBrowse(%##s) STOP PID[%d](%s)", info->sd, ptr->q.qname.c, info->process_id, info->pid_name); mDNS_StopBrowse(&mDNSStorage, &ptr->q); // no need to error-check result - LogMcastQ(&mDNSStorage, &ptr->q, info, q_stop); + LogMcastQ(&ptr->q, info, q_stop); freeL("browser_t/browse_termination_callback", ptr); } } @@ -2309,10 +2212,6 @@ mDNSlocal void udsserver_automatic_browse_domain_changed(const DNameListElem *co request_state *request; debugf("udsserver_automatic_browse_domain_changed: %s default browse domain %##s", add ? "Adding" : "Removing", d->name.c); -#if APPLE_OSX_mDNSResponder - machserver_automatic_browse_domain_changed(&d->name, add); -#endif // APPLE_OSX_mDNSResponder - for (request = all_requests; request; request = request->next) { if (request->terminate != browse_termination_callback) continue; // Not a browse operation @@ -2537,7 +2436,7 @@ mDNSexport void udsserver_handle_configchange(mDNS *const m) // Let the platform layer get the current DNS information mDNS_Lock(m); - mDNSPlatformSetDNSConfig(m, mDNSfalse, mDNSfalse, mDNSNULL, &RegDomains, &BrowseDomains, mDNSfalse); + mDNSPlatformSetDNSConfig(mDNSfalse, mDNSfalse, mDNSNULL, &RegDomains, &BrowseDomains, mDNSfalse); mDNS_Unlock(m); // Any automatic registration domains are also implicitly automatic browsing domains @@ -2619,7 +2518,7 @@ mDNSlocal mStatus handle_browse_request(request_state *request) mDNSu32 interfaceIndex = get_uint32(&request->msgptr, request->msgend); mDNSInterfaceID InterfaceID = mDNSPlatformInterfaceIDfromInterfaceIndex(&mDNSStorage, interfaceIndex); - // The browse is scoped to a specific interface index, but the + // The browse is scoped to a specific interface index, but the // interface is not currently in our list. if (interfaceIndex && !InterfaceID) { @@ -2669,7 +2568,7 @@ mDNSlocal mStatus handle_browse_request(request_state *request) if (!MakeDomainNameFromDNSNameString(&temp, regtype)) return(mStatus_BadParamErr); // For over-long service types, we only allow domain "local" - if (temp.c[0] > 15 && domain[0] == 0) mDNSPlatformStrCopy(domain, "local."); + if (temp.c[0] > 15 && domain[0] == 0) mDNSPlatformStrLCopy(domain, "local.", sizeof(domain)); // Set up browser info request->u.browser.ForceMCast = (flags & kDNSServiceFlagsForceMulticast) != 0; @@ -2678,8 +2577,8 @@ mDNSlocal mStatus handle_browse_request(request_state *request) request->u.browser.default_domain = !domain[0]; request->u.browser.browsers = NULL; - LogOperation("%3d: DNSServiceBrowse(%X, %d, \"%##s\", \"%s\") START PID[%d](%s)", - request->sd, request->flags, interfaceIndex, request->u.browser.regtype.c, domain, request->process_id, request->pid_name); + LogOperation("%3d: DNSServiceBrowse(%X, %d, \"%##s\", \"%s\") START PID[%d](%s)", + request->sd, request->flags, interfaceIndex, request->u.browser.regtype.c, domain, request->process_id, request->pid_name); if (request->u.browser.default_domain) { @@ -2734,13 +2633,17 @@ mDNSlocal mStatus handle_browse_request(request_state *request) mDNSlocal void resolve_result_callback(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord) { size_t len = 0; - char fullname[MAX_ESCAPED_DOMAIN_NAME], target[MAX_ESCAPED_DOMAIN_NAME]; + char fullname[MAX_ESCAPED_DOMAIN_NAME], target[MAX_ESCAPED_DOMAIN_NAME] = "0"; char *data; reply_state *rep; request_state *req = question->QuestionContext; + const DNSServiceErrorType error = + (answer->RecordType == kDNSRecordTypePacketNegative) ? kDNSServiceErr_NoSuchRecord : kDNSServiceErr_NoError; (void)m; // Unused - LogOperation("%3d: DNSServiceResolve(%##s) %s %s", req->sd, question->qname.c, AddRecord ? "ADD" : "RMV", RRDisplayString(m, answer)); + LogOperation("%3d: DNSServiceResolve(%##s) %s interface %d: %s", + req->sd, question->qname.c, AddRecord ? "ADD" : "RMV", + mDNSPlatformInterfaceIndexfromInterfaceID(m, answer->InterfaceID, mDNSfalse), RRDisplayString(m, answer)); if (!AddRecord) { @@ -2755,7 +2658,9 @@ mDNSlocal void resolve_result_callback(mDNS *const m, DNSQuestion *question, con if (!req->u.resolve.txt || !req->u.resolve.srv) return; // only deliver result to client if we have both answers ConvertDomainNameToCString(answer->name, fullname); - ConvertDomainNameToCString(&req->u.resolve.srv->rdata->u.srv.target, target); + + if (answer->RecordType != kDNSRecordTypePacketNegative) + ConvertDomainNameToCString(&req->u.resolve.srv->rdata->u.srv.target, target); // calculate reply length len += sizeof(DNSServiceFlags); @@ -2770,7 +2675,7 @@ mDNSlocal void resolve_result_callback(mDNS *const m, DNSQuestion *question, con rep = create_reply(resolve_reply_op, len, req); rep->rhdr->flags = dnssd_htonl(0); rep->rhdr->ifi = dnssd_htonl(mDNSPlatformInterfaceIndexfromInterfaceID(m, answer->InterfaceID, mDNSfalse)); - rep->rhdr->error = dnssd_htonl(kDNSServiceErr_NoError); + rep->rhdr->error = dnssd_htonl(error); data = (char *)&rep->rhdr[1]; @@ -2788,11 +2693,12 @@ mDNSlocal void resolve_result_callback(mDNS *const m, DNSQuestion *question, con mDNSlocal void resolve_termination_callback(request_state *request) { - LogOperation("%3d: DNSServiceResolve(%##s) STOP PID[%d](%s)", request->sd, request->u.resolve.qtxt.qname.c, request->process_id, request->pid_name); + LogOperation("%3d: DNSServiceResolve(%X, %d, \"%##s\") STOP PID[%d](%s)", + request->sd, request->flags, request->interfaceIndex, request->u.resolve.qtxt.qname.c, request->process_id, request->pid_name); mDNS_StopQuery(&mDNSStorage, &request->u.resolve.qtxt); mDNS_StopQuery(&mDNSStorage, &request->u.resolve.qsrv); - LogMcastQ(&mDNSStorage, &request->u.resolve.qsrv, request, q_stop); - if (request->u.resolve.external_advertise) + LogMcastQ(&request->u.resolve.qsrv, request, q_stop); + if (request->u.resolve.external_advertise) external_stop_resolving_service(request->u.resolve.qsrv.InterfaceID, &request->u.resolve.qsrv.qname, request->flags); } @@ -2818,7 +2724,7 @@ mDNSlocal mStatus handle_resolve_request(request_state *request) InterfaceID = mDNSPlatformInterfaceIDfromInterfaceIndex(&mDNSStorage, interfaceIndex); - // The operation is scoped to a specific interface index, but the + // The operation is scoped to a specific interface index, but the // interface is not currently in our list. if (interfaceIndex && !InterfaceID) { @@ -2847,6 +2753,15 @@ mDNSlocal mStatus handle_resolve_request(request_state *request) mDNSPlatformMemZero(&request->u.resolve, sizeof(request->u.resolve)); +#if APPLE_OSX_mDNSResponder && ENABLE_BLE_TRIGGERED_BONJOUR + // Determine if this request should be promoted to use BLE triggered discovery. + if (shouldUseBLE(InterfaceID, 0, (domainname *)SkipLeadingLabels(&fqdn, 1), &fqdn)) + { + flags |= (kDNSServiceFlagsAutoTrigger | kDNSServiceFlagsIncludeAWDL); + LogInfo("handle_resolve_request: request promoted to use kDNSServiceFlagsAutoTrigger"); + } +#endif // APPLE_OSX_mDNSResponder && ENABLE_BLE_TRIGGERED_BONJOUR + request->flags = flags; request->interfaceIndex = interfaceIndex; @@ -2862,8 +2777,6 @@ mDNSlocal mStatus handle_resolve_request(request_state *request) request->u.resolve.qsrv.ForceMCast = (flags & kDNSServiceFlagsForceMulticast ) != 0; request->u.resolve.qsrv.ReturnIntermed = (flags & kDNSServiceFlagsReturnIntermediates) != 0; request->u.resolve.qsrv.SuppressUnusable = mDNSfalse; - request->u.resolve.qsrv.DenyOnCellInterface = mDNSfalse; - request->u.resolve.qsrv.DenyOnExpInterface = mDNSfalse; request->u.resolve.qsrv.SearchListIndex = 0; request->u.resolve.qsrv.AppendSearchDomains = 0; request->u.resolve.qsrv.RetryWithSearchDomains = mDNSfalse; @@ -2891,8 +2804,6 @@ mDNSlocal mStatus handle_resolve_request(request_state *request) request->u.resolve.qtxt.ForceMCast = (flags & kDNSServiceFlagsForceMulticast ) != 0; request->u.resolve.qtxt.ReturnIntermed = (flags & kDNSServiceFlagsReturnIntermediates) != 0; request->u.resolve.qtxt.SuppressUnusable = mDNSfalse; - request->u.resolve.qtxt.DenyOnCellInterface = mDNSfalse; - request->u.resolve.qtxt.DenyOnExpInterface = mDNSfalse; request->u.resolve.qtxt.SearchListIndex = 0; request->u.resolve.qtxt.AppendSearchDomains = 0; request->u.resolve.qtxt.RetryWithSearchDomains = mDNSfalse; @@ -2918,21 +2829,22 @@ mDNSlocal mStatus handle_resolve_request(request_state *request) #endif // ask the questions - LogOperation("%3d: DNSServiceResolve(%X %d %##s) START PID[%d](%s)", request->sd, flags, interfaceIndex, - request->u.resolve.qsrv.qname.c, request->process_id, request->pid_name); + LogOperation("%3d: DNSServiceResolve(%X, %d, \"%##s\") START PID[%d](%s)", request->sd, flags, interfaceIndex, + request->u.resolve.qsrv.qname.c, request->process_id, request->pid_name); + err = mDNS_StartQuery(&mDNSStorage, &request->u.resolve.qsrv); - + if (!err) { err = mDNS_StartQuery(&mDNSStorage, &request->u.resolve.qtxt); if (err) - { + { mDNS_StopQuery(&mDNSStorage, &request->u.resolve.qsrv); } else { request->terminate = resolve_termination_callback; - LogMcastQ(&mDNSStorage, &request->u.resolve.qsrv, request, q_start); + LogMcastQ(&request->u.resolve.qsrv, request, q_start); if (callExternalHelpers(InterfaceID, &fqdn, flags)) { request->u.resolve.external_advertise = mDNStrue; @@ -2959,7 +2871,7 @@ mDNSlocal mStatus handle_resolve_request(request_state *request) // Returns -1 to tell the caller that it should not try to reissue the query anymore // Returns 1 on successfully appending a search domain and the caller should reissue the new query // Returns 0 when there are no more search domains and the caller should reissue the query -mDNSlocal int AppendNewSearchDomain(mDNS *const m, DNSQuestion *question) +mDNSlocal int AppendNewSearchDomain(DNSQuestion *question) { domainname *sd; mStatus err; @@ -2988,7 +2900,7 @@ mDNSlocal int AppendNewSearchDomain(mDNS *const m, DNSQuestion *question) LogInfo("AppendSearchDomain: qnameOrig %##s", question->qnameOrig->c); } - sd = uDNS_GetNextSearchDomain(m, question->InterfaceID, &question->SearchListIndex, !question->AppendLocalSearchDomains); + sd = uDNS_GetNextSearchDomain(question->InterfaceID, &question->SearchListIndex, !question->AppendLocalSearchDomains); // We use -1 to indicate that we have searched all the domains and should try the single label // query directly on the wire. uDNS_GetNextSearchDomain should never return a negative value if (question->SearchListIndex == -1) @@ -3008,7 +2920,7 @@ mDNSlocal int AppendNewSearchDomain(mDNS *const m, DNSQuestion *question) // without appending search domains, then we are done. if (!sd && !ApplySearchDomainsFirst(question)) { - LogInfo("AppnedNewSearchDomain: No more search domains for question with name %##s (%s), not trying anymore", question->qname.c, DNSTypeName(question->qtype)); + LogInfo("AppendNewSearchDomain: No more search domains for question with name %##s (%s), not trying anymore", question->qname.c, DNSTypeName(question->qtype)); return -1; } @@ -3059,7 +2971,7 @@ mDNSlocal mDNSBool DomainInSearchList(const domainname *domain, mDNSBool exclude } // The caller already checks that this is a dotlocal question. -mDNSlocal mDNSBool ShouldDeliverNegativeResponse(mDNS *const m, DNSQuestion *question) +mDNSlocal mDNSBool ShouldDeliverNegativeResponse(DNSQuestion *question) { mDNSu16 qtype; @@ -3085,7 +2997,7 @@ mDNSlocal mDNSBool ShouldDeliverNegativeResponse(mDNS *const m, DNSQuestion *que return mDNSfalse; } qtype = (question->qtype == kDNSType_A ? kDNSType_AAAA : kDNSType_A); - if (!mDNS_CheckForCacheRecord(m, question, qtype)) + if (!mDNS_CheckForCacheRecord(&mDNSStorage, question, qtype)) { LogOperation("ShouldDeliverNegativeResponse:Question %##s (%s) not answering local question with negative unicast response" " (can't find positive record)", question->qname.c, DNSTypeName(question->qtype)); @@ -3202,14 +3114,14 @@ mDNSlocal mStatus SendAdditionalQuery(DNSQuestion *q, request_state *request, mS (void) q; (void) request; (void) err; - + return mStatus_NoError; #endif // !UNICAST_DISABLED } #endif // APPLE_OSX_mDNSResponder // This function tries to append a search domain if valid and possible. If so, returns true. -mDNSlocal mDNSBool RetryQuestionWithSearchDomains(mDNS *const m, DNSQuestion *question, request_state *req, QC_result AddRecord) +mDNSlocal mDNSBool RetryQuestionWithSearchDomains(DNSQuestion *question, request_state *req, QC_result AddRecord) { int result; // RetryWithSearchDomains tells the core to call us back so that we can retry with search domains if there is no @@ -3223,7 +3135,7 @@ mDNSlocal mDNSBool RetryQuestionWithSearchDomains(mDNS *const m, DNSQuestion *qu if ((AddRecord != QC_suppressed) && question->SearchListIndex != -1 && question->AppendSearchDomains) { question->RetryWithSearchDomains = 0; - result = AppendNewSearchDomain(m, question); + result = AppendNewSearchDomain(question); // As long as the result is either zero or 1, we retry the question. If we exahaust the search // domains (result is zero) we try the original query (as it was before appending the search // domains) as such on the wire as a last resort if we have not tried them before. For queries @@ -3232,7 +3144,7 @@ mDNSlocal mDNSBool RetryQuestionWithSearchDomains(mDNS *const m, DNSQuestion *qu if (result != -1) { mStatus err; - err = mDNS_StartQuery(m, question); + err = mDNS_StartQuery(&mDNSStorage, question); if (!err) { LogOperation("%3d: RetryQuestionWithSearchDomains(%##s, %s), retrying after appending search domain", req->sd, question->qname.c, DNSTypeName(question->qtype)); @@ -3268,9 +3180,10 @@ mDNSlocal void queryrecord_result_reply(mDNS *const m, request_state *req, DNSQu ConvertDomainNameToCString(answer->name, name); - LogOperation("%3d: %s(%##s, %s) %s %s", req->sd, + LogOperation("%3d: %s(%##s, %s) RESULT %s interface %d: %s", req->sd, req->hdr.op == query_request ? "DNSServiceQueryRecord" : "DNSServiceGetAddrInfo", - question->qname.c, DNSTypeName(question->qtype), AddRecord ? "ADD" : "RMV", RRDisplayString(m, answer)); + question->qname.c, DNSTypeName(question->qtype), AddRecord ? "ADD" : "RMV", + mDNSPlatformInterfaceIndexfromInterfaceID(m, answer->InterfaceID, mDNSfalse), RRDisplayString(m, answer)); len = sizeof(DNSServiceFlags); // calculate reply data length len += sizeof(mDNSu32); // interface index @@ -3283,7 +3196,7 @@ mDNSlocal void queryrecord_result_reply(mDNS *const m, request_state *req, DNSQu rep = create_reply(req->hdr.op == query_request ? query_reply_op : addrinfo_reply_op, len, req); if (AddRecord) - flags |= kDNSServiceFlagsAdd; + flags |= kDNSServiceFlagsAdd; if (question->ValidationStatus != 0) { error = kDNSServiceErr_NoError; @@ -3308,7 +3221,7 @@ mDNSlocal void queryrecord_result_reply(mDNS *const m, request_state *req, DNSQu } } } - + rep->rhdr->flags = dnssd_htonl(flags); // Call mDNSPlatformInterfaceIndexfromInterfaceID, but suppressNetworkChange (last argument). Otherwise, if the // InterfaceID is not valid, then it simulates a "NetworkChanged" which in turn makes questions @@ -3517,7 +3430,7 @@ mDNSlocal void queryrecord_result_callback(mDNS *const m, DNSQuestion *question, // As we ignore negative unicast answers below, we would never reach the code where the search domains are appended. // To keep things simple, we handle unicast ".local" separately here. LogInfo("queryrecord_result_callback: Retrying .local question %##s (%s) as unicast after appending search domains", question->qname.c, DNSTypeName(question->qtype)); - if (RetryQuestionWithSearchDomains(m, question, req, AddRecord)) + if (RetryQuestionWithSearchDomains(question, req, AddRecord)) return; if (question->AppendSearchDomains && !question->AppendLocalSearchDomains && IsLocalDomain(&question->qname)) { @@ -3581,7 +3494,7 @@ mDNSlocal void queryrecord_result_callback(mDNS *const m, DNSQuestion *question, return; } #if APPLE_OSX_mDNSResponder - if (!ShouldDeliverNegativeResponse(m, question)) + if (!ShouldDeliverNegativeResponse(question)) { return; } @@ -3607,7 +3520,7 @@ mDNSlocal void queryrecord_result_callback(mDNS *const m, DNSQuestion *question, // normally happen just once because after we append .local, we ignore all negative // responses for .local above. LogInfo("queryrecord_result_callback: Retrying question %##s (%s) after appending search domains", question->qname.c, DNSTypeName(question->qtype)); - if (RetryQuestionWithSearchDomains(m, question, req, AddRecord)) + if (RetryQuestionWithSearchDomains(question, req, AddRecord)) { // Note: We need to call SendAdditionalQuery every time after appending a search domain as .local could // be anywhere in the search domain list. @@ -3625,12 +3538,12 @@ mDNSlocal void queryrecord_result_callback(mDNS *const m, DNSQuestion *question, mDNSlocal void queryrecord_termination_callback(request_state *request) { - LogOperation("%3d: DNSServiceQueryRecord(%##s, %s) STOP PID[%d](%s)", - request->sd, request->u.queryrecord.q.qname.c, DNSTypeName(request->u.queryrecord.q.qtype), request->process_id, request->pid_name); + LogOperation("%3d: DNSServiceQueryRecord(%X, %d, %##s, %s) STOP PID[%d](%s)", + request->sd, request->flags, request->interfaceIndex, request->u.queryrecord.q.qname.c, DNSTypeName(request->u.queryrecord.q.qtype), request->process_id, request->pid_name); if (request->u.queryrecord.q.QuestionContext) { mDNS_StopQuery(&mDNSStorage, &request->u.queryrecord.q); // no need to error check - LogMcastQ(&mDNSStorage, &request->u.queryrecord.q, request, q_stop); + LogMcastQ(&request->u.queryrecord.q, request, q_stop); request->u.queryrecord.q.QuestionContext = mDNSNULL; } else @@ -3645,10 +3558,10 @@ mDNSlocal void queryrecord_termination_callback(request_state *request) request->u.queryrecord.q.qnameOrig = mDNSNULL; } - if (callExternalHelpers(request->u.queryrecord.q.InterfaceID, &request->u.queryrecord.q.qname, request->flags)) + if (callExternalHelpers(request->u.queryrecord.q.InterfaceID, &request->u.queryrecord.q.qname, request->u.queryrecord.q.flags)) { LogInfo("queryrecord_termination_callback: calling external_stop_browsing_for_service()"); - external_stop_browsing_for_service(request->u.queryrecord.q.InterfaceID, &request->u.queryrecord.q.qname, request->u.queryrecord.q.qtype, request->flags); + external_stop_browsing_for_service(request->u.queryrecord.q.InterfaceID, &request->u.queryrecord.q.qname, request->u.queryrecord.q.qtype, request->u.queryrecord.q.flags); } if (request->u.queryrecord.q2) { @@ -3656,7 +3569,7 @@ mDNSlocal void queryrecord_termination_callback(request_state *request) { LogInfo("queryrecord_termination_callback: Stopping q2 %##s", request->u.queryrecord.q2->qname.c); mDNS_StopQuery(&mDNSStorage, request->u.queryrecord.q2); - LogMcastQ(&mDNSStorage, request->u.queryrecord.q2, request, q_stop); + LogMcastQ(request->u.queryrecord.q2, request, q_stop); } else { @@ -3684,46 +3597,17 @@ mDNSlocal void queryrecord_termination_callback(request_state *request) v4q = &request->u.queryrecord.q; else if (request->u.queryrecord.q.qtype == kDNSType_AAAA) v6q = &request->u.queryrecord.q; - mDNSPlatformTriggerDNSRetry(&mDNSStorage, v4q, v6q); + mDNSPlatformTriggerDNSRetry(v4q, v6q); } } #endif // APPLE_OSX_mDNSResponder } -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 - // by examining all the 16 bytes at the time of the policy - // check and also when setting the delegate socket option. Also, it - // requires that we zero out the uuid wherever the question is - // initialized to make sure that it is not interpreted as valid. - // To prevent these intrusive changes, just pass a zero pid to indicate - // that pid is not valid when uuid is valid. In future if we need the - // pid in the question, we will reevaluate this strategy. - if (req->validUUID) - { - for (i = 0; i < UUID_SIZE; i++) - { - q->uuid[i] = req->uuid[i]; - } - q->pid = 0; - } - else - { - 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) { DNSQuestion *const q = &request->u.queryrecord.q; char name[256]; + size_t nameLen; mDNSu16 rrtype, rrclass; mStatus err; @@ -3731,10 +3615,13 @@ mDNSlocal mStatus handle_queryrecord_request(request_state *request) mDNSu32 interfaceIndex = get_uint32(&request->msgptr, request->msgend); mDNSInterfaceID InterfaceID = mDNSPlatformInterfaceIDfromInterfaceIndex(&mDNSStorage, interfaceIndex); - // The request is scoped to a specific interface index, but the + // The request is scoped to a specific interface index, but the // interface is not currently in our list. if (interfaceIndex && !InterfaceID) { + if (interfaceIndex > 1) + LogMsg("handle_queryrecord_request: interfaceIndex %d is currently inactive requested by client[%d][%s]", + interfaceIndex, request->process_id, request->pid_name); // If it's one of the specially defined inteface index values, just return an error. // Also, caller should return an error immediately if lo0 (index 1) is not configured // into the current active interfaces. See background in Radar 21967160. @@ -3778,8 +3665,6 @@ mDNSlocal mStatus handle_queryrecord_request(request_state *request) q->TimeoutQuestion = (flags & kDNSServiceFlagsTimeout ) != 0; q->WakeOnResolve = 0; q->UseBackgroundTrafficClass = (flags & kDNSServiceFlagsBackgroundTrafficClass) != 0; - q->DenyOnCellInterface = (flags & kDNSServiceFlagsDenyCellular) != 0; - q->DenyOnExpInterface = (flags & kDNSServiceFlagsDenyExpensive) != 0; if ((flags & kDNSServiceFlagsValidate) != 0) q->ValidationRequired = DNSSEC_VALIDATION_SECURE; else if ((flags & kDNSServiceFlagsValidateOptional) != 0) @@ -3790,6 +3675,7 @@ mDNSlocal mStatus handle_queryrecord_request(request_state *request) q->QuestionCallback = queryrecord_result_callback; q->QuestionContext = request; q->SearchListIndex = 0; + q->StopTime = 0; q->DNSSECAuthInfo = mDNSNULL; q->DAIFreeCallback = mDNSNULL; @@ -3797,19 +3683,20 @@ mDNSlocal mStatus handle_queryrecord_request(request_state *request) //Turn off dnssec validation for local domains and Question Types: RRSIG/ANY(ANY Type is not supported yet) if ((IsLocalDomain(&q->qname)) || (q->qtype == kDNSServiceType_RRSIG) || (q->qtype == kDNSServiceType_ANY)) q->ValidationRequired = 0; - + // Don't append search domains for fully qualified domain names including queries // such as e.g., "abc." that has only one label. We convert all names to FQDNs as internally // we only deal with FQDNs. Hence, we cannot look at qname to figure out whether we should // append search domains or not. So, we record that information in AppendSearchDomains. // - // We append search domains only for queries that are a single label. If overriden using command line + // We append search domains only for queries that are a single label. If overriden using command line // argument "AlwaysAppendSearchDomains", then we do it for any query which is not fully qualified. // For DNSSEC questions, append search domains only if kDNSServiceFlagsValidateOptional is set. - if ((!(q->ValidationRequired == DNSSEC_VALIDATION_SECURE)) && (!(q->ValidationRequired == DNSSEC_VALIDATION_INSECURE)) - && (rrtype == kDNSType_A || rrtype == kDNSType_AAAA) && name[strlen(name) - 1] != '.' && - (AlwaysAppendSearchDomains || CountLabels(&q->qname) == 1)) + nameLen = strlen(name); + if ((!(q->ValidationRequired == DNSSEC_VALIDATION_SECURE)) && (!(q->ValidationRequired == DNSSEC_VALIDATION_INSECURE)) + && (rrtype == kDNSType_A || rrtype == kDNSType_AAAA) && ((nameLen == 0) || (name[nameLen - 1] != '.')) && + (AlwaysAppendSearchDomains || CountLabels(&q->qname) == 1)) { q->AppendSearchDomains = 1; q->AppendLocalSearchDomains = 1; @@ -3828,10 +3715,20 @@ mDNSlocal mStatus handle_queryrecord_request(request_state *request) q->qnameOrig = mDNSNULL; SetQuestionPolicy(q, request); +#if APPLE_OSX_mDNSResponder && ENABLE_BLE_TRIGGERED_BONJOUR + // Determine if this request should be promoted to use BLE triggered discovery. + if (shouldUseBLE(InterfaceID, rrtype, (domainname *)SkipLeadingLabels(&q->qname, 1), &q->qname)) + { + q->flags |= (kDNSServiceFlagsAutoTrigger | kDNSServiceFlagsIncludeAWDL); + request->flags |= (kDNSServiceFlagsAutoTrigger | kDNSServiceFlagsIncludeAWDL); + LogInfo("handle_queryrecord_request: request promoted to use kDNSServiceFlagsAutoTrigger"); + } +#endif // APPLE_OSX_mDNSResponder && ENABLE_BLE_TRIGGERED_BONJOUR + 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); + request->sd, request->flags, interfaceIndex, q->qname.c, DNSTypeName(q->qtype), request->process_id, request->pid_name); err = mDNS_StartQuery(&mDNSStorage, q); - + if (err) { LogMsg("%3d: ERROR: DNSServiceQueryRecord %##s %s mDNS_StartQuery: %d", request->sd, q->qname.c, DNSTypeName(q->qtype), (int)err); @@ -3839,11 +3736,11 @@ mDNSlocal mStatus handle_queryrecord_request(request_state *request) else { request->terminate = queryrecord_termination_callback; - LogMcastQ(&mDNSStorage, q, request, q_start); - if (callExternalHelpers(q->InterfaceID, &q->qname, flags)) + LogMcastQ(q, request, q_start); + if (callExternalHelpers(q->InterfaceID, &q->qname, q->flags)) { LogInfo("handle_queryrecord_request: calling external_start_browsing_for_service()"); - external_start_browsing_for_service(q->InterfaceID, &q->qname, q->qtype, flags); + external_start_browsing_for_service(q->InterfaceID, &q->qname, q->qtype, q->flags); } } @@ -3892,7 +3789,8 @@ mDNSlocal void enum_termination_callback(request_state *request) else { LogInfo("%3d: DNSServiceEnumeration Cancel WAB Browse PID[%d](%s)", request->sd, request->process_id, request->pid_name); - uDNS_StopWABQueries(&mDNSStorage, UDNS_WAB_BROWSE_QUERY); + uDNS_StopWABQueries(&mDNSStorage, UDNS_WAB_BROWSE_QUERY | UDNS_WAB_LBROWSE_QUERY); + mDNS_StopGetDomains(&mDNSStorage, &request->u.enumeration.q_autoall); } mDNS_StopGetDomains(&mDNSStorage, &request->u.enumeration.q_all); mDNS_StopGetDomains(&mDNSStorage, &request->u.enumeration.q_default); @@ -3930,7 +3828,7 @@ mDNSlocal void enum_result_callback(mDNS *const m, reply = format_enumeration_reply(request, domain, flags, kDNSServiceInterfaceIndexAny, kDNSServiceErr_NoError); if (!reply) { LogMsg("ERROR: enum_result_callback, format_enumeration_reply"); return; } - LogOperation("%3d: DNSServiceEnumerateDomains(%#2s) RESULT %s: %s", request->sd, question->qname.c, AddRecord ? "Add" : "Rmv", domain); + LogOperation("%3d: DNSServiceEnumerateDomains(%#2s) RESULT %s: %s", request->sd, question->qname.c, AddRecord ? "ADD" : "RMV", domain); append_reply(request, reply); } @@ -3959,6 +3857,7 @@ mDNSlocal mStatus handle_enum_request(request_state *request) // necessary context can be reached from the callbacks request->u.enumeration.q_all.QuestionContext = request; request->u.enumeration.q_default.QuestionContext = request; + if (!reg) request->u.enumeration.q_autoall.QuestionContext = request; // if the caller hasn't specified an explicit interface, we use local-only to get the system-wide list. if (!InterfaceID) InterfaceID = mDNSInterface_LocalOnly; @@ -3972,7 +3871,16 @@ mDNSlocal mStatus handle_enum_request(request_state *request) { err = mDNS_GetDomains(&mDNSStorage, &request->u.enumeration.q_default, t_default, NULL, InterfaceID, enum_result_callback, request); if (err) mDNS_StopGetDomains(&mDNSStorage, &request->u.enumeration.q_all); - else request->terminate = enum_termination_callback; + else if (!reg) + { + err = mDNS_GetDomains(&mDNSStorage, &request->u.enumeration.q_autoall, mDNS_DomainTypeBrowseAutomatic, NULL, InterfaceID, enum_result_callback, request); + if (err) + { + mDNS_StopGetDomains(&mDNSStorage, &request->u.enumeration.q_all); + mDNS_StopGetDomains(&mDNSStorage, &request->u.enumeration.q_default); + } + } + if (!err) request->terminate = enum_termination_callback; } if (!err) { @@ -3982,10 +3890,10 @@ mDNSlocal mStatus handle_enum_request(request_state *request) LogInfo("%3d: DNSServiceEnumerateDomains Start WAB Registration PID[%d](%s)", request->sd, request->process_id, request->pid_name); uDNS_StartWABQueries(&mDNSStorage, UDNS_WAB_REG_QUERY); } - else + else { LogInfo("%3d: DNSServiceEnumerateDomains Start WAB Browse PID[%d](%s)", request->sd, request->process_id, request->pid_name); - uDNS_StartWABQueries(&mDNSStorage, UDNS_WAB_BROWSE_QUERY); + uDNS_StartWABQueries(&mDNSStorage, UDNS_WAB_BROWSE_QUERY | UDNS_WAB_LBROWSE_QUERY); } } @@ -4007,10 +3915,11 @@ mDNSlocal mStatus handle_reconfirm_request(request_state *request) status = mDNS_ReconfirmByValue(&mDNSStorage, &rr->resrec); LogOperation( (status == mStatus_NoError) ? - "%3d: DNSServiceReconfirmRecord(%s) interface %d initiated" : - "%3d: DNSServiceReconfirmRecord(%s) interface %d failed: %d", + "%3d: DNSServiceReconfirmRecord(%s) interface %d initiated PID[%d](%s)" : + "%3d: DNSServiceReconfirmRecord(%s) interface %d failed PID[%d](%s) status %d", request->sd, RRDisplayString(&mDNSStorage, &rr->resrec), - mDNSPlatformInterfaceIndexfromInterfaceID(&mDNSStorage, rr->resrec.InterfaceID, mDNSfalse), status); + mDNSPlatformInterfaceIndexfromInterfaceID(&mDNSStorage, rr->resrec.InterfaceID, mDNSfalse), + request->process_id, request->pid_name, status); freeL("AuthRecord/handle_reconfirm_request", rr); } return(status); @@ -4049,7 +3958,7 @@ mDNSlocal mStatus handle_release_request(request_state *request) LogOperation("%3d: PeerConnectionRelease(%X %##s) START PID[%d](%s)", request->sd, flags, instance.c, request->process_id, request->pid_name); - + external_connection_release(&instance); return(err); } @@ -4058,7 +3967,7 @@ mDNSlocal mStatus handle_release_request(request_state *request) mDNSlocal mStatus handle_release_request(request_state *request) { - (void) request; + (void) request; return mStatus_UnsupportedErr; } @@ -4113,6 +4022,10 @@ mDNSlocal void handle_connection_delegate_request(request_state *request) mDNSs32 pid; socklen_t len; + LogOperation("%3d: DNSServiceCreateDelegateConnection START PID[%d](%s)", + request->sd, request->process_id, request->pid_name); + request->terminate = connection_termination; + len = 0; pid = get_uint32(&request->msgptr, request->msgend); #ifdef LOCAL_PEEREPID @@ -4120,11 +4033,14 @@ mDNSlocal void handle_connection_delegate_request(request_state *request) { len = sizeof(pid); if (getsockopt(request->sd, SOL_LOCAL, LOCAL_PEEREPID, &request->process_id, &len) != 0) + { + LogMsg("handle_connection_delegate_request: getsockopt for LOCAL_PEEREPID failed errno:%d / %s", errno, strerror(errno)); return; + } // to extract the process name from the pid value if (proc_pidinfo(request->process_id, PROC_PIDT_SHORTBSDINFO, 1, &proc, PROC_PIDT_SHORTBSDINFO_SIZE) == 0) return; - mDNSPlatformStrCopy(request->pid_name, proc.pbsi_comm); + mDNSPlatformStrLCopy(request->pid_name, proc.pbsi_comm, sizeof(request->pid_name)); debugf("handle_connection_delegate_request: process id %d, name %s", request->process_id, request->pid_name); } #endif @@ -4133,7 +4049,10 @@ mDNSlocal void handle_connection_delegate_request(request_state *request) { len = UUID_SIZE; if (getsockopt(request->sd, SOL_LOCAL, LOCAL_PEEREUUID, request->uuid, &len) != 0) + { + LogMsg("handle_connection_delegate_request: getsockopt for LOCAL_PEEREUUID failed errno:%d / %s", errno, strerror(errno)); return; + } request->validUUID = mDNStrue; } #endif @@ -4201,7 +4120,7 @@ mDNSlocal void handle_getpid_request(request_state *request) } } } - + pi.err = 0; pi.pid = pid; send_all(request->sd, (const char *)&pi, sizeof(PIDInfo)); @@ -4220,8 +4139,8 @@ mDNSlocal void port_mapping_termination_callback(request_state *request) { LogOperation("%3d: DNSServiceNATPortMappingCreate(%X, %u, %u, %d) STOP PID[%d](%s)", request->sd, DNSServiceProtocol(request->u.pm.NATinfo.Protocol), - mDNSVal16(request->u.pm.NATinfo.IntPort), mDNSVal16(request->u.pm.ReqExt), request->u.pm.NATinfo.NATLease, - request->process_id, request->pid_name); + mDNSVal16(request->u.pm.NATinfo.IntPort), mDNSVal16(request->u.pm.ReqExt), request->u.pm.NATinfo.NATLease, + request->process_id, request->pid_name); mDNS_StopNATOperation(&mDNSStorage, &request->u.pm.NATinfo); } @@ -4313,8 +4232,8 @@ mDNSlocal mStatus handle_port_mapping_request(request_state *request) request->u.pm.NATinfo.clientContext = request; LogOperation("%3d: DNSServiceNATPortMappingCreate(%X, %u, %u, %d) START PID[%d](%s)", request->sd, - protocol, mDNSVal16(request->u.pm.NATinfo.IntPort), mDNSVal16(request->u.pm.ReqExt), request->u.pm.NATinfo.NATLease, - request->process_id, request->pid_name); + protocol, mDNSVal16(request->u.pm.NATinfo.IntPort), mDNSVal16(request->u.pm.ReqExt), request->u.pm.NATinfo.NATLease, + request->process_id, request->pid_name); err = mDNS_StartNATOperation(&mDNSStorage, &request->u.pm.NATinfo); if (err) LogMsg("ERROR: mDNS_StartNATOperation: %d", (int)err); else request->terminate = port_mapping_termination_callback; @@ -4331,13 +4250,19 @@ mDNSlocal mStatus handle_port_mapping_request(request_state *request) mDNSlocal void addrinfo_termination_callback(request_state *request) { LogOperation("%3d: DNSServiceGetAddrInfo(%##s) STOP PID[%d](%s)", request->sd, request->u.addrinfo.q4.qname.c, - request->process_id, request->pid_name); + request->process_id, request->pid_name); if (request->u.addrinfo.q4.QuestionContext) { mDNS_StopQuery(&mDNSStorage, &request->u.addrinfo.q4); - LogMcastQ(&mDNSStorage, &request->u.addrinfo.q4, request, q_stop); + LogMcastQ(&request->u.addrinfo.q4, request, q_stop); request->u.addrinfo.q4.QuestionContext = mDNSNULL; + + if (callExternalHelpers(request->u.addrinfo.interface_id, &request->u.addrinfo.q4.qname, request->flags)) + { + LogInfo("addrinfo_termination_callback: calling external_stop_browsing_for_service() for kDNSServiceType_A record"); + external_stop_browsing_for_service(request->u.addrinfo.interface_id, &request->u.addrinfo.q4.qname, kDNSServiceType_A, request->flags); + } } if (request->u.addrinfo.q4.qnameOrig) { @@ -4350,7 +4275,7 @@ mDNSlocal void addrinfo_termination_callback(request_state *request) { LogInfo("addrinfo_termination_callback: Stopping q42 %##s", request->u.addrinfo.q42->qname.c); mDNS_StopQuery(&mDNSStorage, request->u.addrinfo.q42); - LogMcastQ(&mDNSStorage, request->u.addrinfo.q42, request, q_stop); + LogMcastQ(request->u.addrinfo.q42, request, q_stop); } if (request->u.addrinfo.q42->qnameOrig) { @@ -4365,8 +4290,14 @@ mDNSlocal void addrinfo_termination_callback(request_state *request) if (request->u.addrinfo.q6.QuestionContext) { mDNS_StopQuery(&mDNSStorage, &request->u.addrinfo.q6); - LogMcastQ(&mDNSStorage, &request->u.addrinfo.q6, request, q_stop); + LogMcastQ(&request->u.addrinfo.q6, request, q_stop); request->u.addrinfo.q6.QuestionContext = mDNSNULL; + + if (callExternalHelpers(request->u.addrinfo.interface_id, &request->u.addrinfo.q6.qname, request->flags)) + { + LogInfo("addrinfo_termination_callback: calling external_stop_browsing_for_service() for kDNSServiceType_AAAA record"); + external_stop_browsing_for_service(request->u.addrinfo.interface_id, &request->u.addrinfo.q6.qname, kDNSServiceType_AAAA, request->flags); + } } if (request->u.addrinfo.q6.qnameOrig) { @@ -4379,7 +4310,7 @@ mDNSlocal void addrinfo_termination_callback(request_state *request) { LogInfo("addrinfo_termination_callback: Stopping q62 %##s", request->u.addrinfo.q62->qname.c); mDNS_StopQuery(&mDNSStorage, request->u.addrinfo.q62); - LogMcastQ(&mDNSStorage, request->u.addrinfo.q62, request, q_stop); + LogMcastQ(request->u.addrinfo.q62, request, q_stop); } if (request->u.addrinfo.q62->qnameOrig) { @@ -4401,7 +4332,7 @@ mDNSlocal void addrinfo_termination_callback(request_state *request) // valid response again. if (request->u.addrinfo.q4.TimeoutQuestion && !request->u.addrinfo.v4ans) { - mDNSPlatformUpdateDNSStatus(&mDNSStorage, &request->u.addrinfo.q4); + mDNSPlatformUpdateDNSStatus(&request->u.addrinfo.q4); } // If we have a v4 answer and if we timed out prematurely before, provide // a trigger to the upper layer so that it can retry questions if needed. @@ -4412,12 +4343,12 @@ mDNSlocal void addrinfo_termination_callback(request_state *request) { if (request->u.addrinfo.q6.TimeoutQuestion && !request->u.addrinfo.v6ans) { - mDNSPlatformUpdateDNSStatus(&mDNSStorage, &request->u.addrinfo.q6); + mDNSPlatformUpdateDNSStatus(&request->u.addrinfo.q6); } if (request->u.addrinfo.v6ans) v6q = &request->u.addrinfo.q6; } - mDNSPlatformTriggerDNSRetry(&mDNSStorage, v4q, v6q); + mDNSPlatformTriggerDNSRetry(v4q, v6q); } #endif // APPLE_OSX_mDNSResponder } @@ -4425,13 +4356,14 @@ mDNSlocal void addrinfo_termination_callback(request_state *request) mDNSlocal mStatus handle_addrinfo_request(request_state *request) { char hostname[256]; + size_t hostnameLen; 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); - + mDNSu32 interfaceIndex = get_uint32(&request->msgptr, request->msgend); if (flags & kDNSServiceFlagsServiceIndex) @@ -4443,15 +4375,18 @@ mDNSlocal mStatus handle_addrinfo_request(request_state *request) serviceIndex = interfaceIndex; interfaceIndex = 0; } - + mDNSPlatformMemZero(&request->u.addrinfo, sizeof(request->u.addrinfo)); InterfaceID = mDNSPlatformInterfaceIDfromInterfaceIndex(&mDNSStorage, interfaceIndex); - // The request is scoped to a specific interface index, but the + // The request is scoped to a specific interface index, but the // interface is not currently in our list. if (interfaceIndex && !InterfaceID) { + if (interfaceIndex > 1) + LogMsg("handle_addrinfo_request: interfaceIndex %d is currently inactive requested by client[%d][%s]", + interfaceIndex, request->process_id, request->pid_name); // If it's one of the specially defined inteface index values, just return an error. if (PreDefinedInterfaceIndex(interfaceIndex)) { @@ -4459,7 +4394,7 @@ mDNSlocal mStatus handle_addrinfo_request(request_state *request) return(mStatus_BadParamErr); } - // Otherwise, use the specified interface index value and the registration will + // Otherwise, use the specified interface index value and the request will // be applied to that interface when it comes up. InterfaceID = (mDNSInterfaceID)(uintptr_t)interfaceIndex; LogInfo("handle_addrinfo_request: query pending for interface index %d", interfaceIndex); @@ -4504,8 +4439,6 @@ mDNSlocal mStatus handle_addrinfo_request(request_state *request) request->u.addrinfo.q4.TimeoutQuestion = request->u.addrinfo.q6.TimeoutQuestion = (flags & kDNSServiceFlagsTimeout ) != 0; request->u.addrinfo.q4.WakeOnResolve = request->u.addrinfo.q6.WakeOnResolve = 0; request->u.addrinfo.q4.UseBackgroundTrafficClass = request->u.addrinfo.q6.UseBackgroundTrafficClass = (flags & kDNSServiceFlagsBackgroundTrafficClass) != 0; - request->u.addrinfo.q4.DenyOnCellInterface = request->u.addrinfo.q6.DenyOnCellInterface = (flags & kDNSServiceFlagsDenyCellular) != 0; - request->u.addrinfo.q4.DenyOnExpInterface = request->u.addrinfo.q6.DenyOnExpInterface = (flags & kDNSServiceFlagsDenyExpensive) != 0; if ((flags & kDNSServiceFlagsValidate) != 0) request->u.addrinfo.q4.ValidationRequired = request->u.addrinfo.q6.ValidationRequired = DNSSEC_VALIDATION_SECURE; else if ((flags & kDNSServiceFlagsValidateOptional) != 0) @@ -4518,6 +4451,8 @@ mDNSlocal mStatus handle_addrinfo_request(request_state *request) SetQuestionPolicy(&request->u.addrinfo.q4, request); SetQuestionPolicy(&request->u.addrinfo.q6, request); + request->u.addrinfo.q4.StopTime = request->u.addrinfo.q6.StopTime = 0; + request->u.addrinfo.q4.DNSSECAuthInfo = request->u.addrinfo.q6.DNSSECAuthInfo = mDNSNULL; request->u.addrinfo.q4.DAIFreeCallback = request->u.addrinfo.q6.DAIFreeCallback = mDNSNULL; @@ -4525,13 +4460,18 @@ mDNSlocal mStatus handle_addrinfo_request(request_state *request) if (IsLocalDomain(&d)) request->u.addrinfo.q4.ValidationRequired = request->u.addrinfo.q6.ValidationRequired = 0; + hostnameLen = strlen(hostname); + + 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); + if (request->u.addrinfo.protocol & kDNSServiceProtocol_IPv6) { request->u.addrinfo.q6.qtype = kDNSServiceType_AAAA; request->u.addrinfo.q6.SearchListIndex = 0; // For DNSSEC questions, append search domains only if kDNSServiceFlagsValidateOptional is set - if ((!(request->u.addrinfo.q6.ValidationRequired == DNSSEC_VALIDATION_SECURE)) && (!(request->u.addrinfo.q6.ValidationRequired == DNSSEC_VALIDATION_INSECURE)) - && hostname[strlen(hostname) - 1] != '.' && (AlwaysAppendSearchDomains || CountLabels(&d) == 1)) + if ((!(request->u.addrinfo.q6.ValidationRequired == DNSSEC_VALIDATION_SECURE)) && (!(request->u.addrinfo.q6.ValidationRequired == DNSSEC_VALIDATION_INSECURE)) + && ((hostnameLen == 0) || (hostname[hostnameLen - 1] != '.')) && (AlwaysAppendSearchDomains || CountLabels(&d) == 1)) { request->u.addrinfo.q6.AppendSearchDomains = 1; request->u.addrinfo.q6.AppendLocalSearchDomains = 1; @@ -4554,9 +4494,14 @@ mDNSlocal mStatus handle_addrinfo_request(request_state *request) err = SendAdditionalQuery(&request->u.addrinfo.q6, request, err); #endif // APPLE_OSX_mDNSResponder if (!err) - { + { request->terminate = addrinfo_termination_callback; - LogMcastQ(&mDNSStorage, &request->u.addrinfo.q6, request, q_start); + LogMcastQ(&request->u.addrinfo.q6, request, q_start); + if (callExternalHelpers(InterfaceID, &d, flags)) + { + LogInfo("handle_addrinfo_request: calling external_start_browsing_for_service() for kDNSServiceType_AAAA record"); + external_start_browsing_for_service(InterfaceID, &d, kDNSServiceType_AAAA, flags); + } } } @@ -4569,8 +4514,8 @@ mDNSlocal mStatus handle_addrinfo_request(request_state *request) // "AlwaysAppendSearchDomains", then we do it for any query which is not fully qualified. // For DNSSEC questions, append search domains only if kDNSServiceFlagsValidateOptional is set. - if ((!(request->u.addrinfo.q4.ValidationRequired == DNSSEC_VALIDATION_SECURE)) && (!(request->u.addrinfo.q4.ValidationRequired == DNSSEC_VALIDATION_INSECURE)) - && hostname[strlen(hostname) - 1] != '.' && (AlwaysAppendSearchDomains || CountLabels(&d) == 1)) + if ((!(request->u.addrinfo.q4.ValidationRequired == DNSSEC_VALIDATION_SECURE)) && (!(request->u.addrinfo.q4.ValidationRequired == DNSSEC_VALIDATION_INSECURE)) + && ((hostnameLen == 0) || (hostname[hostnameLen - 1] != '.')) && (AlwaysAppendSearchDomains || CountLabels(&d) == 1)) { request->u.addrinfo.q4.AppendSearchDomains = 1; request->u.addrinfo.q4.AppendLocalSearchDomains = 1; @@ -4589,11 +4534,17 @@ mDNSlocal mStatus handle_addrinfo_request(request_state *request) LogMsg("ERROR: mDNS_StartQuery: %d", (int)err); request->u.addrinfo.q4.QuestionContext = mDNSNULL; if (request->u.addrinfo.protocol & kDNSServiceProtocol_IPv6) - { - // If we started a query for IPv6, we need to cancel it + { + // If we started a query for IPv6, we need to cancel it mDNS_StopQuery(&mDNSStorage, &request->u.addrinfo.q6); request->u.addrinfo.q6.QuestionContext = mDNSNULL; - } + + if (callExternalHelpers(InterfaceID, &d, flags)) + { + LogInfo("addrinfo_termination_callback: calling external_stop_browsing_for_service() for kDNSServiceType_AAAA record"); + external_stop_browsing_for_service(InterfaceID, &d, kDNSServiceType_AAAA, flags); + } + } } #if APPLE_OSX_mDNSResponder err = SendAdditionalQuery(&request->u.addrinfo.q4, request, err); @@ -4601,11 +4552,15 @@ mDNSlocal mStatus handle_addrinfo_request(request_state *request) if (!err) { request->terminate = addrinfo_termination_callback; - LogMcastQ(&mDNSStorage, &request->u.addrinfo.q4, request, q_start); - } + LogMcastQ(&request->u.addrinfo.q4, request, q_start); + if (callExternalHelpers(InterfaceID, &d, flags)) + { + LogInfo("handle_addrinfo_request: calling external_start_browsing_for_service() for kDNSServiceType_A record"); + external_start_browsing_for_service(InterfaceID, &d, kDNSServiceType_A, flags); + } + } } - 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); } @@ -4618,10 +4573,10 @@ mDNSlocal mStatus handle_addrinfo_request(request_state *request) mDNSlocal request_state *NewRequest(void) { request_state **p = &all_requests; - while (*p) + while (*p) p=&(*p)->next; *p = mallocL("request_state", sizeof(request_state)); - if (!*p) + if (!*p) FatalError("ERROR: malloc"); mDNSPlatformMemZero(*p, sizeof(request_state)); return(*p); @@ -4723,7 +4678,7 @@ mDNSlocal void read_msg(request_state *req) { dnssd_sock_t x = *(dnssd_sock_t *)CMSG_DATA(cmsg); LogOperation("%3d: Got len %d, BPF %d", req->sd, cmsg->cmsg_len, x); - mDNSPlatformReceiveBPF_fd(&mDNSStorage, x); + mDNSPlatformReceiveBPF_fd(x); } else #endif // APPLE_OSX_mDNSResponder @@ -4762,7 +4717,7 @@ mDNSlocal void read_msg(request_state *req) get_string(&req->msgptr, req->msgend, ctrl_path, MAX_CTLPATH); // path is first element in message buffer mDNSPlatformMemZero(&cliaddr, sizeof(cliaddr)); cliaddr.sun_family = AF_LOCAL; - mDNSPlatformStrCopy(cliaddr.sun_path, ctrl_path); + mDNSPlatformStrLCopy(cliaddr.sun_path, ctrl_path, sizeof(cliaddr.sun_path)); // If the error return path UDS name is empty string, that tells us // that this is a new version of the library that's going to pass us // the error return path socket via sendmsg/recvmsg @@ -4775,8 +4730,8 @@ mDNSlocal void read_msg(request_state *req) #endif req->errsd = socket(AF_DNSSD, SOCK_STREAM, 0); - if (!dnssd_SocketValid(req->errsd)) - { + if (!dnssd_SocketValid(req->errsd)) + { my_throttled_perror("ERROR: socket"); req->ts = t_error; return; @@ -4825,6 +4780,52 @@ rerror: req->ts = t_error; } +mDNSlocal mStatus handle_client_request(request_state *req) +{ + mStatus err = mStatus_NoError; + switch(req->hdr.op) + { + // These are all operations that have their own first-class request_state object + case connection_request: + LogOperation("%3d: DNSServiceCreateConnection START PID[%d](%s)", + req->sd, req->process_id, req->pid_name); + req->terminate = connection_termination; + break; + case connection_delegate_request: + LogOperation("%3d: DNSServiceCreateDelegateConnection START PID[%d](%s)", + req->sd, req->process_id, req->pid_name); + req->terminate = connection_termination; + handle_connection_delegate_request(req); + break; + case resolve_request: err = handle_resolve_request (req); break; + case query_request: err = handle_queryrecord_request (req); break; + case browse_request: err = handle_browse_request (req); break; + case reg_service_request: err = handle_regservice_request (req); break; + case enumeration_request: err = handle_enum_request (req); break; + case reconfirm_record_request: err = handle_reconfirm_request (req); break; + case setdomain_request: err = handle_setdomain_request (req); break; + case getproperty_request: handle_getproperty_request (req); break; + case getpid_request: handle_getpid_request (req); break; + case port_mapping_request: err = handle_port_mapping_request(req); break; + case addrinfo_request: err = handle_addrinfo_request (req); break; + case send_bpf: /* Do nothing for send_bpf */ break; + + // These are all operations that work with an existing request_state object + case reg_record_request: err = handle_regrecord_request (req); break; + case add_record_request: err = handle_add_request (req); break; + case update_record_request: err = handle_update_request (req); break; + case remove_record_request: err = handle_removerecord_request(req); break; + case cancel_request: handle_cancel_request (req); break; + case release_request: err = handle_release_request (req); break; + default: LogMsg("request_callback: %3d:ERROR: Unsupported UDS req:%d PID[%d][%s]", + req->sd, req->hdr.op, req->process_id, req->pid_name); + err = mStatus_BadParamErr; + break; + } + + return err; +} + #define RecordOrientedOp(X) \ ((X) == reg_record_request || (X) == add_record_request || (X) == update_record_request || (X) == remove_record_request) @@ -4842,23 +4843,16 @@ mDNSlocal void request_callback(int fd, short filter, void *info) for (;;) { read_msg(req); - if (req->ts == t_morecoming) + if (req->ts == t_morecoming) + return; + if (req->ts == t_terminated || req->ts == t_error) + { + AbortUnlinkAndFree(req); return; - if (req->ts == t_terminated || req->ts == t_error) - { - AbortUnlinkAndFree(req); - return; - } - if (req->ts != t_complete) - { - LogMsg("request_callback: req->ts %d != t_complete PID[%d][%s]", req->ts, req->process_id, req->pid_name); - AbortUnlinkAndFree(req); - return; } - if (req->hdr.version != VERSION) + if (req->ts != t_complete) { - LogMsg("request_callback: ERROR: client IPC version %d incompatible with daemon IPC version %d PID[%d][%s]", - req->hdr.version, VERSION, req->process_id, req->pid_name); + LogMsg("request_callback: req->ts %d != t_complete PID[%d][%s]", req->ts, req->process_id, req->pid_name); AbortUnlinkAndFree(req); return; } @@ -4885,24 +4879,24 @@ mDNSlocal void request_callback(int fd, short filter, void *info) case send_bpf: // Same as cancel_request below case cancel_request: min_size = 0; break; case release_request: min_size += sizeof(mDNSu32) + 3 /* type, type, domain */; break; - default: LogMsg("request_callback: ERROR: validate_message - unsupported req type: %d PID[%d][%s]", - req->hdr.op, req->process_id, req->pid_name); + default: LogMsg("request_callback: ERROR: validate_message - unsupported req type: %d PID[%d][%s]", + req->hdr.op, req->process_id, req->pid_name); min_size = -1; break; } if ((mDNSs32)req->data_bytes < min_size) - { - LogMsg("request_callback: Invalid message %d bytes; min for %d is %d PID[%d][%s]", - req->data_bytes, req->hdr.op, min_size, req->process_id, req->pid_name); - AbortUnlinkAndFree(req); - return; + { + LogMsg("request_callback: Invalid message %d bytes; min for %d is %d PID[%d][%s]", + req->data_bytes, req->hdr.op, min_size, req->process_id, req->pid_name); + AbortUnlinkAndFree(req); + return; } if (LightweightOp(req->hdr.op) && !req->terminate) - { - LogMsg("request_callback: Reg/Add/Update/Remove %d require existing connection PID[%d][%s]", - req->hdr.op, req->process_id, req->pid_name); - AbortUnlinkAndFree(req); - return; + { + LogMsg("request_callback: Reg/Add/Update/Remove %d require existing connection PID[%d][%s]", + req->hdr.op, req->process_id, req->pid_name); + AbortUnlinkAndFree(req); + return; } // If req->terminate is already set, this means this operation is sharing an existing connection @@ -4921,18 +4915,15 @@ mDNSlocal void request_callback(int fd, short filter, void *info) // relevant bits if (req->validUUID) { - int i; newreq->validUUID = mDNStrue; - for (i = 0; i < UUID_SIZE; i++) - { - newreq->uuid[i] = req->uuid[i]; - } + mDNSPlatformMemCopy(newreq->uuid, req->uuid, UUID_SIZE); } else { if (req->process_id) { newreq->process_id = req->process_id; + mDNSPlatformStrLCopy(newreq->pid_name, req->pid_name, (mDNSu32)sizeof(newreq->pid_name)); } else { @@ -4948,49 +4939,10 @@ mDNSlocal void request_callback(int fd, short filter, void *info) // 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) - { err = mStatus_ServiceNotRunning; - } else - { - switch(req->hdr.op) - { - // These are all operations that have their own first-class request_state object - case connection_request: - LogOperation("%3d: DNSServiceCreateConnection START PID[%d](%s)", - req->sd, req->process_id, req->pid_name); - req->terminate = connection_termination; - break; - case connection_delegate_request: - LogOperation("%3d: DNSServiceCreateDelegateConnection START PID[%d](%s)", - req->sd, req->process_id, req->pid_name); - req->terminate = connection_termination; - handle_connection_delegate_request(req); - break; - case resolve_request: err = handle_resolve_request (req); break; - case query_request: err = handle_queryrecord_request (req); break; - case browse_request: err = handle_browse_request (req); break; - case reg_service_request: err = handle_regservice_request (req); break; - case enumeration_request: err = handle_enum_request (req); break; - case reconfirm_record_request: err = handle_reconfirm_request (req); break; - case setdomain_request: err = handle_setdomain_request (req); break; - case getproperty_request: handle_getproperty_request (req); break; - case getpid_request: handle_getpid_request (req); break; - case port_mapping_request: err = handle_port_mapping_request(req); break; - case addrinfo_request: err = handle_addrinfo_request (req); break; - case send_bpf: /* Do nothing for send_bpf */ break; - - // These are all operations that work with an existing request_state object - case reg_record_request: err = handle_regrecord_request (req); break; - case add_record_request: err = handle_add_request (req); break; - case update_record_request: err = handle_update_request (req); break; - case remove_record_request: err = handle_removerecord_request(req); break; - case cancel_request: handle_cancel_request (req); break; - case release_request: err = handle_release_request (req); break; - default: LogMsg("request_callback: %3d:ERROR: Unsupported UDS req:%d PID[%d][%s]", - req->sd, req->hdr.op, req->process_id, req->pid_name); break; - } - } + err = handle_client_request(req); + // req->msgbuf may be NULL, e.g. for connection_request or remove_record_request if (req->msgbuf) freeL("request_state msgbuf", req->msgbuf); @@ -5036,7 +4988,7 @@ mDNSlocal void connect_callback(int fd, short filter, void *info) if (!dnssd_SocketValid(sd)) { - if (dnssd_errno != dnssd_EWOULDBLOCK) + if (dnssd_errno != dnssd_EWOULDBLOCK) my_throttled_perror("ERROR: accept"); return; } @@ -5114,7 +5066,7 @@ mDNSlocal mDNSBool uds_socket_setup(dnssd_sock_t skt) return mDNSfalse; } else - { + { LogOperation("%3d: Listening for incoming Unix Domain Socket client requests", skt); mDNSStorage.uds_listener_skt = skt; } @@ -5135,7 +5087,7 @@ mDNSexport int udsserver_init(dnssd_sock_t skts[], mDNSu32 count) FILE *fp = fopen(PID_FILE, "w"); if (fp != NULL) { - fprintf(fp, "%d\n", (int)getpid()); + fprintf(fp, "%d\n", getpid()); fclose(fp); } } @@ -5172,19 +5124,19 @@ mDNSexport int udsserver_init(dnssd_sock_t skts[], mDNSu32 count) #else { mode_t mask = umask(0); - unlink(MDNS_UDS_SERVERPATH); // OK if this fails + unlink(boundPath); // OK if this fails laddr.sun_family = AF_LOCAL; #ifndef NOT_HAVE_SA_LEN // According to Stevens (section 3.2), there is no portable way to // determine whether sa_len is defined on a particular platform. laddr.sun_len = sizeof(struct sockaddr_un); #endif - if (strlen(MDNS_UDS_SERVERPATH) >= sizeof(laddr.sun_path)) + if (strlen(boundPath) >= sizeof(laddr.sun_path)) { LogMsg("ERROR: MDNS_UDS_SERVERPATH must be < %d characters", (int)sizeof(laddr.sun_path)); goto error; } - mDNSPlatformStrCopy(laddr.sun_path, MDNS_UDS_SERVERPATH); + mDNSPlatformStrLCopy(laddr.sun_path, boundPath, sizeof(laddr.sun_path)); ret = bind(listenfd, (struct sockaddr *) &laddr, sizeof(laddr)); umask(mask); if (ret < 0) @@ -5264,7 +5216,7 @@ mDNSexport int udsserver_exit(void) // Currently, we're unable to remove /var/run/mdnsd because we've changed to userid "nobody" // to give up unnecessary privilege, but we need to be root to remove this Unix Domain Socket. // It would be nice if we could find a solution to this problem - if (unlink(MDNS_UDS_SERVERPATH)) + if (unlink(boundPath)) debugf("Unable to remove %s", MDNS_UDS_SERVERPATH); #endif } @@ -5274,12 +5226,12 @@ mDNSexport int udsserver_exit(void) return 0; } -mDNSlocal void LogClientInfo(mDNS *const m, request_state *req) +mDNSlocal void LogClientInfo(request_state *req) { char prefix[16]; - if (req->primary) + if (req->primary) mDNS_snprintf(prefix, sizeof(prefix), " -> "); - else + else mDNS_snprintf(prefix, sizeof(prefix), "%3d:", req->sd); if (!req->terminate) @@ -5291,13 +5243,13 @@ mDNSlocal void LogClientInfo(mDNS *const m, request_state *req) request_state *r; for (p = req->u.reg_recs; p; p=p->next) num_records++; for (r = req->next; r; r=r->next) if (r->primary == req) num_ops++; - LogMsgNoIdent("%s DNSServiceCreateConnection: %d registered record%s, %d kDNSServiceFlagsShareConnection operation%s PID[%d](%s)", - prefix, num_records, num_records != 1 ? "s" : "", num_ops, num_ops != 1 ? "s" : "", + LogMsgNoIdent("%s DNSServiceCreateConnection: %d registered record%s, %d kDNSServiceFlagsShareConnection operation%s PID[%d](%s)", + 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 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); + req->flags, req->interfaceIndex, p->key, ARDisplayString(&mDNSStorage, p->rr), req->process_id, req->pid_name); + for (r = req->next; r; r=r->next) if (r->primary == req) LogClientInfo(r); } else if (req->terminate == regservice_termination_callback) { @@ -5340,7 +5292,7 @@ mDNSlocal void LogClientInfo(mDNS *const m, request_state *req) mDNSVal16(req->u.pm.NATinfo.ExternalPort), req->u.pm.NATinfo.NATLease, req->u.pm.NATinfo.Lifetime, - req->process_id, req->pid_name); + req->process_id, req->pid_name); else if (req->terminate == addrinfo_termination_callback) LogMsgNoIdent("%s DNSServiceGetAddrInfo 0x%08X %2d %s%s %##s PID[%d](%s)", prefix, req->flags, req->interfaceIndex, @@ -5358,18 +5310,18 @@ mDNSlocal void GetMcastClients(request_state *req) int num_records = 0, num_ops = 0; const registered_record_entry *p; request_state *r; - for (p = req->u.reg_recs; p; p=p->next) + for (p = req->u.reg_recs; p; p=p->next) num_records++; - for (r = req->next; r; r=r->next) - if (r->primary == req) + for (r = req->next; r; r=r->next) + if (r->primary == req) num_ops++; for (p = req->u.reg_recs; p; p=p->next) { if (!AuthRecord_uDNS(p->rr)) n_mrecords++; } - for (r = req->next; r; r=r->next) - if (r->primary == req) + for (r = req->next; r; r=r->next) + if (r->primary == req) GetMcastClients(r); } else if (req->terminate == regservice_termination_callback) @@ -5378,7 +5330,7 @@ mDNSlocal void GetMcastClients(request_state *req) for (ptr = req->u.servicereg.instances; ptr; ptr = ptr->next) { if (!AuthRecord_uDNS(&ptr->srs.RR_SRV)) - n_mrecords++; + n_mrecords++; } } else if (req->terminate == browse_termination_callback) @@ -5421,19 +5373,19 @@ mDNSlocal void LogMcastClientInfo(request_state *req) int num_records = 0, num_ops = 0; const registered_record_entry *p; request_state *r; - for (p = req->u.reg_recs; p; p=p->next) + for (p = req->u.reg_recs; p; p=p->next) num_records++; - for (r = req->next; r; r=r->next) - if (r->primary == req) + for (r = req->next; r; r=r->next) + if (r->primary == req) num_ops++; for (p = req->u.reg_recs; p; p=p->next) { if (!AuthRecord_uDNS(p->rr)) - LogMcastNoIdent("R: -> DNSServiceRegisterRecord: %##s %s PID[%d](%s)", p->rr->resrec.name->c, + LogMcastNoIdent("R: -> DNSServiceRegisterRecord: %##s %s PID[%d](%s)", p->rr->resrec.name->c, DNSTypeName(p->rr->resrec.rrtype), req->process_id, req->pid_name, i_mcount++); } - for (r = req->next; r; r=r->next) - if (r->primary == req) + for (r = req->next; r; r=r->next) + if (r->primary == req) LogMcastClientInfo(r); } else if (req->terminate == regservice_termination_callback) @@ -5441,8 +5393,8 @@ mDNSlocal void LogMcastClientInfo(request_state *req) service_instance *ptr; for (ptr = req->u.servicereg.instances; ptr; ptr = ptr->next) { - if (!AuthRecord_uDNS(&ptr->srs.RR_SRV)) - LogMcastNoIdent("R: DNSServiceRegister: %##s %u/%u PID[%d](%s)", ptr->srs.RR_SRV.resrec.name->c, mDNSVal16(req->u.servicereg.port), + if (!AuthRecord_uDNS(&ptr->srs.RR_SRV)) + LogMcastNoIdent("R: DNSServiceRegister: %##s %u/%u PID[%d](%s)", ptr->srs.RR_SRV.resrec.name->c, mDNSVal16(req->u.servicereg.port), SRS_PORT(&ptr->srs), req->process_id, req->pid_name, i_mcount++); } } @@ -5465,7 +5417,7 @@ mDNSlocal void LogMcastClientInfo(request_state *req) else if (req->terminate == queryrecord_termination_callback) { if ((mDNSOpaque16IsZero(req->u.queryrecord.q.TargetQID)) && (req->u.queryrecord.q.ThisQInterval > 0)) - LogMcastNoIdent("Q: DNSServiceQueryRecord %##s %s PID[%d](%s)", req->u.queryrecord.q.qname.c, DNSTypeName(req->u.queryrecord.q.qtype), + LogMcastNoIdent("Q: DNSServiceQueryRecord %##s %s PID[%d](%s)", req->u.queryrecord.q.qname.c, DNSTypeName(req->u.queryrecord.q.qtype), req->process_id, req->pid_name, i_mcount++); } else if (req->terminate == addrinfo_termination_callback) @@ -5480,7 +5432,7 @@ mDNSlocal void LogMcastClientInfo(request_state *req) { return; } - + } mDNSlocal char *RecordTypeName(mDNSu8 rtype) @@ -5498,7 +5450,7 @@ mDNSlocal char *RecordTypeName(mDNSu8 rtype) } } -mDNSlocal void LogEtcHosts(mDNS *const m) +mDNSlocal int LogEtcHosts(mDNS *const m) { mDNSBool showheader = mDNStrue; const AuthRecord *ar; @@ -5534,6 +5486,7 @@ mDNSlocal void LogEtcHosts(mDNS *const m) if (showheader) LogMsgNoIdent("<None>"); else if (truncated) LogMsgNoIdent("<Truncated: to 50 records, Total records %d, Total Auth Groups %d, Auth Slots %d>", count, m->rrauth.rrauth_totalused, authslot); + return count; } mDNSlocal void LogLocalOnlyAuthRecords(mDNS *const m) @@ -5553,9 +5506,14 @@ mDNSlocal void LogLocalOnlyAuthRecords(mDNS *const m) // Print a maximum of 400 records if (ar->ARType == AuthRecordLocalOnly) - LogMsgNoIdent(" %s LO %s", RecordTypeName(ar->resrec.RecordType), ARDisplayString(m, ar)); + LogMsgNoIdent(" %s LO %s", RecordTypeName(ar->resrec.RecordType), ARDisplayString(m, ar)); else if (ar->ARType == AuthRecordP2P) - LogMsgNoIdent(" %s PP %s", RecordTypeName(ar->resrec.RecordType), ARDisplayString(m, ar)); + { + if (ar->resrec.InterfaceID == mDNSInterface_BLE) + LogMsgNoIdent(" %s BLE %s", RecordTypeName(ar->resrec.RecordType), ARDisplayString(m, ar)); + else + LogMsgNoIdent(" %s PP %s", RecordTypeName(ar->resrec.RecordType), ARDisplayString(m, ar)); + } } } @@ -5572,42 +5530,44 @@ mDNSlocal char *AnonInfoToString(AnonymousInfo *ai, char *anonstr, int anstrlen) return anonstr; } -mDNSlocal void LogOneAuthRecord(mDNS *const m, const AuthRecord *ar, mDNSs32 now, const char *const ifname) +mDNSlocal void LogOneAuthRecord(const AuthRecord *ar, mDNSs32 now, const char *const ifname) { char anstr[256]; if (AuthRecord_uDNS(ar)) { - LogMsgNoIdent("%7d %7d %7d %7d %s %s", + LogMsgNoIdent("%7d %7d %7d %-7s %4d %s %s", ar->ThisAPInterval / mDNSPlatformOneSecond, (ar->LastAPTime + ar->ThisAPInterval - now) / mDNSPlatformOneSecond, ar->expire ? (ar->expire - now) / mDNSPlatformOneSecond : 0, + "-U-", ar->state, ar->AllowRemoteQuery ? "☠" : " ", - ARDisplayString(m, ar)); + ARDisplayString(&mDNSStorage, ar)); } else { - LogMsgNoIdent("%7d %7d %7d %7s %s %s%s", + LogMsgNoIdent("%7d %7d %7d %-7s 0x%02X %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->resrec.RecordType, ar->AllowRemoteQuery ? "☠" : " ", - ARDisplayString(m, ar), AnonInfoToString(ar->resrec.AnonInfo, anstr, sizeof(anstr))); + ARDisplayString(&mDNSStorage, ar), AnonInfoToString(ar->resrec.AnonInfo, anstr, sizeof(anstr))); } } -mDNSlocal void LogAuthRecords(mDNS *const m, const mDNSs32 now, AuthRecord *ResourceRecords, int *proxy) +mDNSlocal void LogAuthRecords(const mDNSs32 now, AuthRecord *ResourceRecords, int *proxy) { mDNSBool showheader = mDNStrue; const AuthRecord *ar; OwnerOptData owner = zeroOwner; for (ar = ResourceRecords; ar; ar=ar->next) { - const char *const ifname = InterfaceNameForID(m, ar->resrec.InterfaceID); + const char *const ifname = InterfaceNameForID(&mDNSStorage, ar->resrec.InterfaceID); if ((ar->WakeUp.HMAC.l[0] != 0) == (proxy != mDNSNULL)) { - if (showheader) { showheader = mDNSfalse; LogMsgNoIdent(" Int Next Expire State"); } + if (showheader) { showheader = mDNSfalse; LogMsgNoIdent(" Int Next Expire if State"); } if (proxy) (*proxy)++; if (!mDNSPlatformMemSame(&owner, &ar->WakeUp, sizeof(owner))) { @@ -5621,19 +5581,22 @@ mDNSlocal void LogAuthRecords(mDNS *const m, const mDNSs32 now, AuthRecord *Reso } if (AuthRecord_uDNS(ar)) { - LogOneAuthRecord(m, ar, now, ifname); + LogOneAuthRecord(ar, now, ifname); } else if (ar->ARType == AuthRecordLocalOnly) { - LogMsgNoIdent(" LO %s", ARDisplayString(m, ar)); + LogMsgNoIdent(" LO %s", ARDisplayString(&mDNSStorage, ar)); } else if (ar->ARType == AuthRecordP2P) { - LogMsgNoIdent(" PP %s", ARDisplayString(m, ar)); + if (ar->resrec.InterfaceID == mDNSInterface_BLE) + LogMsgNoIdent(" BLE %s", ARDisplayString(&mDNSStorage, ar)); + else + LogMsgNoIdent(" PP %s", ARDisplayString(&mDNSStorage, ar)); } else { - LogOneAuthRecord(m, ar, now, ifname); + LogOneAuthRecord(ar, now, ifname); if (ar->resrec.AnonInfo) { ResourceRecord *nsec3 = ar->resrec.AnonInfo->nsec3RR; @@ -5644,7 +5607,7 @@ mDNSlocal void LogAuthRecords(mDNS *const m, const mDNSs32 now, AuthRecord *Reso ar->AnnounceCount ? (ar->LastAPTime + ar->ThisAPInterval - now) / mDNSPlatformOneSecond : 0, ar->TimeExpire ? (ar->TimeExpire - now) / mDNSPlatformOneSecond : 0, ifname ? ifname : "ALL", - RRDisplayString(m, nsec3)); + RRDisplayString(&mDNSStorage, nsec3)); } } } @@ -5652,7 +5615,7 @@ mDNSlocal void LogAuthRecords(mDNS *const m, const mDNSs32 now, AuthRecord *Reso if (showheader) LogMsgNoIdent("<None>"); } -mDNSlocal void PrintOneCacheRecord(mDNS *const m, const CacheRecord *cr, mDNSu32 slot, const mDNSu32 remain, const char *ifname, mDNSu32 *CacheUsed) +mDNSlocal void PrintOneCacheRecord(const CacheRecord *cr, mDNSu32 slot, const mDNSu32 remain, const char *ifname, mDNSu32 *CacheUsed) { LogMsgNoIdent("%3d %s%8d %-7s%s %-6s%s", slot, @@ -5662,11 +5625,11 @@ mDNSlocal void PrintOneCacheRecord(mDNS *const m, const CacheRecord *cr, mDNSu32 (cr->resrec.RecordType == kDNSRecordTypePacketNegative) ? "-" : (cr->resrec.RecordType & kDNSRecordTypePacketUniqueMask) ? " " : "+", DNSTypeName(cr->resrec.rrtype), - CRDisplayString(m, cr)); + CRDisplayString(&mDNSStorage, cr)); (*CacheUsed)++; } -mDNSlocal void PrintCachedRecords(mDNS *const m, const CacheRecord *cr, mDNSu32 slot, const mDNSu32 remain, const char *ifname, mDNSu32 *CacheUsed) +mDNSlocal void PrintCachedRecords(const CacheRecord *cr, mDNSu32 slot, const mDNSu32 remain, const char *ifname, mDNSu32 *CacheUsed) { CacheRecord *nsec; CacheRecord *soa; @@ -5676,13 +5639,13 @@ mDNSlocal void PrintCachedRecords(mDNS *const m, const CacheRecord *cr, mDNSu32 // their own lifetime. If the main cache record expires, they also expire. while (nsec) { - PrintOneCacheRecord(m, nsec, slot, remain, ifname, CacheUsed); + PrintOneCacheRecord(nsec, slot, remain, ifname, CacheUsed); nsec = nsec->next; } soa = cr->soa; if (soa) { - PrintOneCacheRecord(m, soa, slot, remain, ifname, CacheUsed); + PrintOneCacheRecord(soa, slot, remain, ifname, CacheUsed); } if (cr->resrec.AnonInfo) { @@ -5699,7 +5662,7 @@ mDNSlocal void PrintCachedRecords(mDNS *const m, const CacheRecord *cr, mDNSu32 (nsec3->RecordType == kDNSRecordTypePacketNegative) ? "-" : (nsec3->RecordType & kDNSRecordTypePacketUniqueMask) ? " " : "+", DNSTypeName(nsec3->rrtype), - RRDisplayString(m, nsec3)); + RRDisplayString(&mDNSStorage, nsec3)); } } } @@ -5735,7 +5698,7 @@ mDNSlocal char *AnonDataToString(const mDNSu8 *ad, int adlen, char *adstr, int a mDNSexport void LogMDNSStatistics(mDNS *const m) { LogMsgNoIdent("--- MDNS Statistics ---"); - + LogMsgNoIdent("Name Conflicts %u", m->mDNSStats.NameConflicts); LogMsgNoIdent("KnownUnique Name Conflicts %u", m->mDNSStats.KnownUniqueNameConflicts); LogMsgNoIdent("Duplicate Query Suppressions %u", m->mDNSStats.DupQuerySuppressions); @@ -5766,11 +5729,15 @@ mDNSexport void LogMDNSStatistics(mDNS *const m) LogMsgNoIdent("Wakeup on Resolves %u", m->mDNSStats.WakeOnResolves); } -mDNSexport void udsserver_info(mDNS *const m) +mDNSexport void udsserver_info() { + mDNS *const m = &mDNSStorage; const mDNSs32 now = mDNS_TimeNow(m); mDNSu32 CacheUsed = 0, CacheActive = 0, slot; int ProxyA = 0, ProxyD = 0; + mDNSu32 groupCount = 0; + mDNSu32 mcastRecordCount = 0; + mDNSu32 ucastRecordCount = 0; const CacheGroup *cg; const CacheRecord *cr; const DNSQuestion *q; @@ -5785,30 +5752,33 @@ mDNSexport void udsserver_info(mDNS *const m) { for (cg = m->rrcache_hash[slot]; cg; cg=cg->next) { - CacheUsed++; // Count one cache entity for the CacheGroup object + groupCount++; // Count one cache entity for the CacheGroup object for (cr = cg->members; cr; cr=cr->next) { const mDNSs32 remain = cr->resrec.rroriginalttl - (now - cr->TimeRcvd) / mDNSPlatformOneSecond; const char *ifname; mDNSInterfaceID InterfaceID = cr->resrec.InterfaceID; + mDNSu32 *const countPtr = InterfaceID ? &mcastRecordCount : &ucastRecordCount; if (!InterfaceID && cr->resrec.rDNSServer && cr->resrec.rDNSServer->scoped) InterfaceID = cr->resrec.rDNSServer->interface; ifname = InterfaceNameForID(m, InterfaceID); if (cr->CRActiveQuestion) CacheActive++; - PrintOneCacheRecord(m, cr, slot, remain, ifname, &CacheUsed); - PrintCachedRecords(m, cr, slot, remain, ifname, &CacheUsed); + PrintOneCacheRecord(cr, slot, remain, ifname, countPtr); + PrintCachedRecords(cr, slot, remain, ifname, countPtr); } } } + CacheUsed = groupCount + mcastRecordCount + ucastRecordCount; if (m->rrcache_totalused != CacheUsed) LogMsgNoIdent("Cache use mismatch: rrcache_totalused is %lu, true count %lu", m->rrcache_totalused, CacheUsed); if (m->rrcache_active != CacheActive) LogMsgNoIdent("Cache use mismatch: rrcache_active is %lu, true count %lu", m->rrcache_active, CacheActive); - LogMsgNoIdent("Cache currently contains %lu entities; %lu referenced by active questions", CacheUsed, CacheActive); + LogMsgNoIdent("Cache size %u entities; %u in use (%u group, %u multicast, %u unicast); %u referenced by active questions", + m->rrcache_size, CacheUsed, groupCount, mcastRecordCount, ucastRecordCount, CacheActive); LogMsgNoIdent("--------- Auth Records ---------"); - LogAuthRecords(m, now, m->ResourceRecords, mDNSNULL); + LogAuthRecords(now, m->ResourceRecords, mDNSNULL); LogMsgNoIdent("--------- LocalOnly, P2P Auth Records ---------"); LogLocalOnlyAuthRecords(m); @@ -5817,13 +5787,13 @@ mDNSexport void udsserver_info(mDNS *const m) LogEtcHosts(m); LogMsgNoIdent("------ Duplicate Records -------"); - LogAuthRecords(m, now, m->DuplicateRecords, mDNSNULL); + LogAuthRecords(now, m->DuplicateRecords, mDNSNULL); LogMsgNoIdent("----- Auth Records Proxied -----"); - LogAuthRecords(m, now, m->ResourceRecords, &ProxyA); + LogAuthRecords(now, m->ResourceRecords, &ProxyA); LogMsgNoIdent("-- Duplicate Records Proxied ---"); - LogAuthRecords(m, now, m->DuplicateRecords, &ProxyD); + LogAuthRecords(now, m->DuplicateRecords, &ProxyD); LogMsgNoIdent("---------- Questions -----------"); if (!m->Questions) LogMsgNoIdent("<None>"); @@ -5840,12 +5810,13 @@ mDNSexport void udsserver_info(mDNS *const m) char *ifname = InterfaceNameForID(m, q->InterfaceID); CacheUsed++; if (q->ThisQInterval) CacheActive++; - LogMsgNoIdent("%6d%6d %-7s%s%s %5d 0x%x%x 0x%p 0x%p %1d %2d %-5s%##s%s%s", + LogMsgNoIdent("%6d%6d %-7s%s%s %5d 0x%x%x%x%x 0x%p 0x%p %1d %2d %-5s%##s%s%s", i, n, ifname ? ifname : mDNSOpaque16IsZero(q->TargetQID) ? "" : "-U-", mDNSOpaque16IsZero(q->TargetQID) ? (q->LongLived ? "l" : " ") : (q->LongLived ? "L" : "O"), PrivateQuery(q) ? "P" : q->ValidationRequired ? "V" : q->ValidatingResponse ? "R" : " ", - q->CurrentAnswers, q->validDNSServers.l[1], q->validDNSServers.l[0], q, q->DuplicateOf, + q->CurrentAnswers, q->validDNSServers.l[3], q->validDNSServers.l[2], q->validDNSServers.l[1], + q->validDNSServers.l[0], q, q->DuplicateOf, q->SuppressUnusable, q->SuppressQuery, DNSTypeName(q->qtype), q->qname.c, AnonInfoToString(q->AnonInfo, anonstr, sizeof(anonstr)), q->DuplicateOf ? " (dup)" : ""); @@ -5853,10 +5824,11 @@ mDNSexport void udsserver_info(mDNS *const m) LogMsgNoIdent("%lu question%s; %lu active", CacheUsed, CacheUsed > 1 ? "s" : "", CacheActive); } - LogMsgNoIdent("----- Local-Only Questions -----"); + LogMsgNoIdent("----- LocalOnly, P2P Questions -----"); if (!m->LocalOnlyQuestions) LogMsgNoIdent("<None>"); else for (q = m->LocalOnlyQuestions; q; q=q->next) - LogMsgNoIdent(" %5d %-6s%##s%s", + LogMsgNoIdent(" %3s %5d %-6s%##s%s", + q->InterfaceID == mDNSInterface_LocalOnly ? "LO ": q->InterfaceID == mDNSInterface_BLE ? "BLE": "P2P", q->CurrentAnswers, DNSTypeName(q->qtype), q->qname.c, q->DuplicateOf ? " (dup)" : ""); LogMsgNoIdent("---- Active UDS Client Requests ----"); @@ -5872,7 +5844,7 @@ mDNSexport void udsserver_info(mDNS *const m) LogMsgNoIdent("%3d: Orhpan operation %p; parent %p not found in request list", req->sd); } // For non-subbordinate operations, and subbordinate operations that have lost their parent, write out their info - LogClientInfo(m, req); + LogClientInfo(req); foundparent:; } } @@ -5969,7 +5941,7 @@ foundparent:; } } LogInfo("--- Trust Anchors ---"); - if (!m->TrustAnchors) + if (!m->TrustAnchors) { LogInfo("<None>"); } @@ -5990,7 +5962,6 @@ foundparent:; LogInfo("--- DNSSEC Statistics ---"); - LogInfo("Next Stats Time %u", m->NextStatLogTime - mDNSPlatformUTC()); LogMsgNoIdent("Unicast Cache size %u", m->rrcache_totalused_unicast); LogInfo("DNSSEC Cache size %u", m->DNSSECStats.TotalMemUsed); if (m->rrcache_totalused_unicast) @@ -6021,6 +5992,15 @@ foundparent:; LogMsgNoIdent("---- Task Scheduling Timers ----"); +#if BONJOUR_ON_DEMAND + LogMsgNoIdent("BonjourEnabled %d", m->BonjourEnabled); +#endif // BONJOUR_ON_DEMAND + +#if APPLE_OSX_mDNSResponder && ENABLE_BLE_TRIGGERED_BONJOUR + LogMsgNoIdent("EnableBLEBasedDiscovery %d", EnableBLEBasedDiscovery); + LogMsgNoIdent("DefaultToBLETriggered %d", DefaultToBLETriggered); +#endif // APPLE_OSX_mDNSResponder && ENABLE_BLE_TRIGGERED_BONJOUR + if (!m->NewQuestions) LogMsgNoIdent("NewQuestion <NONE>"); else @@ -6062,6 +6042,11 @@ foundparent:; LogTimer("m->NextCacheCheck ", m->NextCacheCheck); LogTimer("m->NextScheduledSPS ", m->NextScheduledSPS); LogTimer("m->NextScheduledKA ", m->NextScheduledKA); + +#if BONJOUR_ON_DEMAND + LogTimer("m->NextBonjourDisableTime ", m->NextBonjourDisableTime); +#endif // BONJOUR_ON_DEMAND + LogTimer("m->NextScheduledSPRetry ", m->NextScheduledSPRetry); LogTimer("m->DelaySleep ", m->DelaySleep); @@ -6190,15 +6175,16 @@ mDNSexport mDNSs32 udsserver_idle(mDNSs32 nextevent) if (r->u.resolve.ReportTime && now - r->u.resolve.ReportTime >= 0) { r->u.resolve.ReportTime = 0; - LogMsgNoIdent("Client application bug PID[%d](%s) : DNSServiceResolve(%##s) active for over two minutes. " - "This places considerable burden on the network.", r->process_id, r->pid_name, r->u.resolve.qsrv.qname.c); + // if client received results and resolve still active + if (r->u.resolve.txt && r->u.resolve.srv) + LogMsgNoIdent("Client application PID[%d](%s) has received results for DNSServiceResolve(%##s) yet remains active over two minutes.", r->process_id, r->pid_name, r->u.resolve.qsrv.qname.c); } // Note: Only primary req's have reply lists, not subordinate req's. while (r->replies) // Send queued replies { transfer_state result; - if (r->replies->next) + if (r->replies->next) r->replies->rhdr->flags |= dnssd_htonl(kDNSServiceFlagsMoreComing); result = send_msg(r); // Returns t_morecoming if buffer full because client is not reading if (result == t_complete) @@ -6210,10 +6196,15 @@ mDNSexport mDNSs32 udsserver_idle(mDNSs32 nextevent) r->unresponsiveness_reports = 0; continue; } - else if (result == t_terminated || result == t_error) + else if (result == t_terminated) + { + LogInfo("%3d: Could not write data to client PID[%d](%s) because connection is terminated by the client", r->sd, r->process_id, r->pid_name); + abort_request(r); + } + else if (result == t_error) { 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); + LogClientInfo(r); abort_request(r); } break; @@ -6221,28 +6212,28 @@ mDNSexport mDNSs32 udsserver_idle(mDNSs32 nextevent) if (r->replies) // If we failed to send everything, check our time_blocked timer { - if (nextevent - now > mDNSPlatformOneSecond) + if (nextevent - now > mDNSPlatformOneSecond) nextevent = now + mDNSPlatformOneSecond; - if (mDNSStorage.SleepState != SleepState_Awake) + if (mDNSStorage.SleepState != SleepState_Awake) r->time_blocked = 0; - else if (!r->time_blocked) + else if (!r->time_blocked) r->time_blocked = NonZeroTime(now); else if (now - r->time_blocked >= 10 * mDNSPlatformOneSecond * (r->unresponsiveness_reports+1)) { int num = 0; struct reply_state *x = r->replies; - while (x) - { - num++; - x=x->next; + while (x) + { + num++; + x=x->next; } LogMsg("%3d: Could not write data to client PID[%d](%s) after %ld seconds, %d repl%s waiting", r->sd, r->process_id, r->pid_name, (now - r->time_blocked) / mDNSPlatformOneSecond, num, num == 1 ? "y" : "ies"); if (++r->unresponsiveness_reports >= 60) { LogMsg("%3d: Client PID[%d](%s) unresponsive; aborting connection", r->sd, r->process_id, r->pid_name); - LogClientInfo(&mDNSStorage, r); + LogClientInfo(r); abort_request(r); } } @@ -6265,10 +6256,14 @@ struct CompileTimeAssertionChecks_uds_daemon // Check our structures are reasonable sizes. Including overly-large buffers, or embedding // other overly-large structures instead of having a pointer to them, can inadvertently // cause structure sizes (and therefore memory usage) to balloon unreasonably. - char sizecheck_request_state [(sizeof(request_state) <= 2000) ? 1 : -1]; + char sizecheck_request_state [(sizeof(request_state) <= 2954) ? 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) <= 1128) ? 1 : -1]; + char sizecheck_browser_t [(sizeof(browser_t) <= 1202) ? 1 : -1]; char sizecheck_reply_hdr [(sizeof(reply_hdr) <= 12) ? 1 : -1]; char sizecheck_reply_state [(sizeof(reply_state) <= 64) ? 1 : -1]; }; + +#ifdef UNIT_TEST +#include "../unittests/uds_daemon_ut.c" +#endif // UNIT_TEST diff --git a/usr/src/contrib/mDNSResponder/mDNSShared/uds_daemon.h b/usr/src/contrib/mDNSResponder/mDNSShared/uds_daemon.h new file mode 100644 index 0000000000..dc7d9ac26b --- /dev/null +++ b/usr/src/contrib/mDNSResponder/mDNSShared/uds_daemon.h @@ -0,0 +1,282 @@ +/* -*- Mode: C; tab-width: 4 -*- + * + * 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef UDS_DAEMON_H +#define UDS_DAEMON_H + +#include "mDNSEmbeddedAPI.h" +#include "dnssd_ipc.h" + +/* Client request: */ + +// *************************************************************************** +#if COMPILER_LIKES_PRAGMA_MARK +#pragma mark - +#pragma mark - Types and Data Structures +#endif + +typedef enum +{ + t_uninitialized, + t_morecoming, + t_complete, + t_error, + t_terminated +} transfer_state; + +typedef struct request_state request_state; + +typedef void (*req_termination_fn)(request_state *request); + +typedef struct registered_record_entry +{ + struct registered_record_entry *next; + mDNSu32 key; + client_context_t regrec_client_context; + request_state *request; + mDNSBool external_advertise; + mDNSInterfaceID origInterfaceID; + AuthRecord *rr; // Pointer to variable-sized AuthRecord (Why a pointer? Why not just embed it here?) +} registered_record_entry; + +// A single registered service: ServiceRecordSet + bookkeeping +// Note that we duplicate some fields from parent service_info object +// to facilitate cleanup, when instances and parent may be deallocated at different times. +typedef struct service_instance +{ + struct service_instance *next; + request_state *request; + AuthRecord *subtypes; + mDNSBool renameonmemfree; // Set on config change when we deregister original name + mDNSBool clientnotified; // Has client been notified of successful registration yet? + mDNSBool default_local; // is this the "local." from an empty-string registration? + mDNSBool external_advertise; // is this is being advertised externally? + domainname domain; + ServiceRecordSet srs; // note -- variable-sized object -- must be last field in struct +} service_instance; + +// for multi-domain default browsing +typedef struct browser_t +{ + struct browser_t *next; + domainname domain; + DNSQuestion q; +} browser_t; + +#ifdef _WIN32 +typedef unsigned int pid_t; +typedef unsigned int socklen_t; +#endif + +#if (!defined(MAXCOMLEN)) +#define MAXCOMLEN 16 +#endif + +struct request_state +{ + request_state *next; + request_state *primary; // If this operation is on a shared socket, pointer to primary + // request_state for the original DNSServiceCreateConnection() operation + dnssd_sock_t sd; + pid_t process_id; // Client's PID value + char pid_name[MAXCOMLEN]; // Client's process name + mDNSu8 uuid[UUID_SIZE]; + mDNSBool validUUID; + dnssd_sock_t errsd; + mDNSu32 uid; + void * platform_data; + + // Note: On a shared connection these fields in the primary structure, including hdr, are re-used + // for each new request. This is because, until we've read the ipc_msg_hdr to find out what the + // operation is, we don't know if we're going to need to allocate a new request_state or not. + transfer_state ts; + mDNSu32 hdr_bytes; // bytes of header already read + ipc_msg_hdr hdr; + mDNSu32 data_bytes; // bytes of message data already read + char *msgbuf; // pointer to data storage to pass to free() + const char *msgptr; // pointer to data to be read from (may be modified) + char *msgend; // pointer to byte after last byte of message + + // reply, termination, error, and client context info + int no_reply; // don't send asynchronous replies to client + mDNSs32 time_blocked; // record time of a blocked client + int unresponsiveness_reports; + struct reply_state *replies; // corresponding (active) reply list + req_termination_fn terminate; + DNSServiceFlags flags; + mDNSu32 interfaceIndex; + + union + { + registered_record_entry *reg_recs; // list of registrations for a connection-oriented request + struct + { + mDNSInterfaceID interface_id; + mDNSBool default_domain; + mDNSBool ForceMCast; + domainname regtype; + browser_t *browsers; + const mDNSu8 *AnonData; + } browser; + struct + { + mDNSInterfaceID InterfaceID; + mDNSu16 txtlen; + void *txtdata; + mDNSIPPort port; + domainlabel name; + char type_as_string[MAX_ESCAPED_DOMAIN_NAME]; + domainname type; + mDNSBool default_domain; + domainname host; + mDNSBool autoname; // Set if this name is tied to the Computer Name + mDNSBool autorename; // Set if this client wants us to automatically rename on conflict + mDNSBool allowremotequery; // Respond to unicast queries from outside the local link? + int num_subtypes; + mDNSBool AnonData; + service_instance *instances; + } servicereg; + struct + { + mDNSInterfaceID interface_id; + mDNSu32 flags; + mDNSu32 protocol; + DNSQuestion q4; + DNSQuestion *q42; + DNSQuestion q6; + DNSQuestion *q62; + mDNSu8 v4ans; + mDNSu8 v6ans; + } addrinfo; + struct + { + mDNSIPPort ReqExt; // External port we originally requested, for logging purposes + NATTraversalInfo NATinfo; + } pm; + struct + { + DNSServiceFlags flags; + DNSQuestion q_all; + DNSQuestion q_default; + DNSQuestion q_autoall; + } enumeration; + struct + { + DNSQuestion q; + DNSQuestion *q2; + mDNSu8 ans; + } queryrecord; + struct + { + DNSQuestion qtxt; + DNSQuestion qsrv; + const ResourceRecord *txt; + const ResourceRecord *srv; + mDNSs32 ReportTime; + mDNSBool external_advertise; + } resolve; + } u; +}; + +// struct physically sits between ipc message header and call-specific fields in the message buffer +typedef struct +{ + DNSServiceFlags flags; // Note: This field is in NETWORK byte order + mDNSu32 ifi; // Note: This field is in NETWORK byte order + DNSServiceErrorType error; // Note: This field is in NETWORK byte order +} reply_hdr; + +typedef struct reply_state +{ + struct reply_state *next; // If there are multiple unsent replies + mDNSu32 totallen; + mDNSu32 nwriten; + ipc_msg_hdr mhdr[1]; + reply_hdr rhdr[1]; +} reply_state; + +/* Client interface: */ + +#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(void); // print out info about current state +extern void udsserver_handle_configchange(mDNS *const m); +extern int udsserver_exit(void); // should be called prior to app exit +extern void LogMcastStateInfo(mDNSBool mflag, mDNSBool start, mDNSBool mstatelog); +#define LogMcastQ (mDNS_McastLoggingEnabled == 0) ? ((void)0) : LogMcastQuestion +#define LogMcastS (mDNS_McastLoggingEnabled == 0) ? ((void)0) : LogMcastService +#define LogMcast (mDNS_McastLoggingEnabled == 0) ? ((void)0) : LogMsg +#define LogMcastNoIdent (mDNS_McastLoggingEnabled == 0) ? ((void)0) : LogMsgNoIdent + +/* Routines that uds_daemon expects to link against: */ + +typedef void (*udsEventCallback)(int fd, short filter, void *context); +extern mStatus udsSupportAddFDToEventLoop(dnssd_sock_t fd, udsEventCallback callback, void *context, void **platform_data); +extern int udsSupportReadFD(dnssd_sock_t fd, char* buf, int len, int flags, void *platform_data); +extern mStatus udsSupportRemoveFDFromEventLoop(dnssd_sock_t fd, void *platform_data); // Note: This also CLOSES the file descriptor as well + +extern void RecordUpdatedNiceLabel(mDNSs32 delay); + +// Globals and functions defined in uds_daemon.c and also shared with the old "daemon.c" on OS X + +extern mDNS mDNSStorage; +extern DNameListElem *AutoRegistrationDomains; +extern DNameListElem *AutoBrowseDomains; + +extern mDNSs32 ChopSubTypes(char *regtype, char **AnonData); +extern AuthRecord *AllocateSubTypes(mDNSs32 NumSubTypes, char *p, char **AnonData); +extern int CountExistingRegistrations(domainname *srv, mDNSIPPort port); +extern mDNSBool callExternalHelpers(mDNSInterfaceID InterfaceID, const domainname *const domain, DNSServiceFlags flags); +extern void FreeExtraRR(mDNS *const m, AuthRecord *const rr, mStatus result); +extern int CountPeerRegistrations(ServiceRecordSet *const srs); + +#if APPLE_OSX_mDNSResponder + +// D2D interface support +extern void external_start_browsing_for_service(mDNSInterfaceID InterfaceID, const domainname *const type, DNS_TypeValues qtype, DNSServiceFlags flags); +extern void external_stop_browsing_for_service(mDNSInterfaceID InterfaceID, const domainname *const type, DNS_TypeValues qtype, DNSServiceFlags flags); +extern void external_start_advertising_service(const ResourceRecord *const resourceRecord, DNSServiceFlags flags); +extern void external_stop_advertising_service(const ResourceRecord *const resourceRecord, DNSServiceFlags flags); +extern void external_start_resolving_service(mDNSInterfaceID InterfaceID, const domainname *const fqdn, DNSServiceFlags flags); +extern void external_stop_resolving_service(mDNSInterfaceID InterfaceID, const domainname *const fqdn, DNSServiceFlags flags); +extern void external_connection_release(const domainname *instance); + +#else // APPLE_OSX_mDNSResponder + +#define external_start_browsing_for_service(A,B,C,D) (void)(A) +#define external_stop_browsing_for_service(A,B,C,D) (void)(A) +#define external_start_advertising_service(A,B) (void)(A) +#define external_stop_advertising_service(A,B) do { (void)(A); (void)(B); } while (0) +#define external_start_resolving_service(A,B,C) (void)(A) +#define external_stop_resolving_service(A,B,C) (void)(A) +#define external_connection_release(A) (void)(A) + +#endif // APPLE_OSX_mDNSResponder + +extern const char mDNSResponderVersionString_SCCS[]; +#define mDNSResponderVersionString (mDNSResponderVersionString_SCCS+5) + +#if DEBUG +extern void SetDebugBoundPath(void); +extern int IsDebugSocketInUse(void); +#endif + +#endif /* UDS_DAEMON_H */ diff --git a/usr/src/lib/libdns_sd/Makefile b/usr/src/lib/libdns_sd/Makefile index 5e33bde9f9..b08abfb1be 100644 --- a/usr/src/lib/libdns_sd/Makefile +++ b/usr/src/lib/libdns_sd/Makefile @@ -25,21 +25,20 @@ include ../Makefile.lib HDR = dns_sd.h -HDRDIR = common +HDRDIR = $(SRC)/contrib/mDNSResponder/mDNSShared SUBDIRS = $(MACH) $(BUILD64)SUBDIRS += $(MACH64) -all := TARGET = all +all := TARGET = all clean := TARGET = clean clobber := TARGET = clobber install := TARGET = install -lint := TARGET = lint .KEEP_STATE: -all install: install_h $(SUBDIRS) .WAIT java +all install: install_h $(SUBDIRS) -clean clobber: $(SUBDIRS) java +clean clobber: $(SUBDIRS) ROOTHDRDIR= $(ROOT)/usr/include ROOTHDRS= $(HDR:%=$(ROOTHDRDIR)/%) @@ -48,9 +47,7 @@ install_h: $(ROOTHDRS) check: -lint: $(SUBDIRS) - -$(SUBDIRS) java: FRC +$(SUBDIRS): FRC @cd $@; pwd; $(MAKE) $(TARGET) FRC: diff --git a/usr/src/lib/libdns_sd/Makefile.com b/usr/src/lib/libdns_sd/Makefile.com index 5363d2dead..217ef72c05 100644 --- a/usr/src/lib/libdns_sd/Makefile.com +++ b/usr/src/lib/libdns_sd/Makefile.com @@ -29,10 +29,9 @@ OBJECTS = dnssd_clientlib.o dnssd_clientstub.o dnssd_ipc.o include ../../Makefile.lib -LIBS = $(DYNLIB) $(LINTLIB) -$(LINTLIB):= SRCS = $(SRCDIR)/$(LINTSRC) - -SRCDIR = ../common +MAPFILEDIR= ../common +SRCDIR= $(SRC)/contrib/mDNSResponder/mDNSShared +LIBS = $(DYNLIB) LDLIBS += -lsocket -lnsl -lc @@ -45,8 +44,10 @@ pics/dnssd_clientstub.o := CERRWARN += -_gcc=-Wno-unused-but-set-variable .PARALLEL = $(OBJECTS) .KEEP_STATE: -lint: lintcheck - all: $(LIBS) +pics/%.o: $(SRCDIR)/%.c + $(COMPILE.c) -o $@ $< + $(POST_PROCESS_O) + include ../../Makefile.targ diff --git a/usr/src/lib/libdns_sd/THIRDPARTYLICENSE b/usr/src/lib/libdns_sd/THIRDPARTYLICENSE deleted file mode 100644 index f4589044ee..0000000000 --- a/usr/src/lib/libdns_sd/THIRDPARTYLICENSE +++ /dev/null @@ -1,13 +0,0 @@ -The majority of the source code in the mDNSResponder project is licensed -under the terms of the Apache License, Version 2.0, available from: - <http://www.apache.org/licenses/LICENSE-2.0> - -To accommodate license compatibility with the widest possible range -of client code licenses, the shared library code, which is linked -at runtime into the same address space as the client using it, is -licensed under the terms of the "Three-Clause BSD License". - -The Linux Name Service Switch code, contributed by National ICT -Australia Ltd (NICTA) is licensed under the terms of the NICTA Public -Software Licence (which is substantially similar to the "Three-Clause -BSD License", with some additional language pertaining to Australian law). diff --git a/usr/src/lib/libdns_sd/THIRDPARTYLICENSE.descrip b/usr/src/lib/libdns_sd/THIRDPARTYLICENSE.descrip deleted file mode 100644 index 3a395f72de..0000000000 --- a/usr/src/lib/libdns_sd/THIRDPARTYLICENSE.descrip +++ /dev/null @@ -1 +0,0 @@ -MDNS LIBRARY diff --git a/usr/src/lib/libdns_sd/amd64/Makefile b/usr/src/lib/libdns_sd/amd64/Makefile index 2fa1329472..f4938d1ce4 100644 --- a/usr/src/lib/libdns_sd/amd64/Makefile +++ b/usr/src/lib/libdns_sd/amd64/Makefile @@ -21,10 +21,8 @@ # Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # -#ident "%Z%%M% %I% %E% SMI" include ../Makefile.com include ../../Makefile.lib.64 -CFLAGS64 += -erroff=E_ASSIGNMENT_TYPE_MISMATCH -install: all $(ROOTLIBS64) $(ROOTLINKS64) $(ROOTLINT64) +install: all $(ROOTLIBS64) $(ROOTLINKS64) diff --git a/usr/src/lib/libdns_sd/common/llib-ldns_sd b/usr/src/lib/libdns_sd/common/llib-ldns_sd deleted file mode 100644 index 464e3b9a6d..0000000000 --- a/usr/src/lib/libdns_sd/common/llib-ldns_sd +++ /dev/null @@ -1,32 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -/* LINTLIBRARY */ -/* PROTOLIB1 */ - -#include <dns_sd.h> diff --git a/usr/src/lib/libdns_sd/i386/Makefile b/usr/src/lib/libdns_sd/i386/Makefile index 9c1be5bf3a..32145a695a 100644 --- a/usr/src/lib/libdns_sd/i386/Makefile +++ b/usr/src/lib/libdns_sd/i386/Makefile @@ -21,8 +21,7 @@ # Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # -#ident "%Z%%M% %I% %E% SMI" include ../Makefile.com -install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT) +install: all $(ROOTLIBS) $(ROOTLINKS) diff --git a/usr/src/lib/libdns_sd/java/Makefile b/usr/src/lib/libdns_sd/java/Makefile deleted file mode 100644 index 5b015fc86e..0000000000 --- a/usr/src/lib/libdns_sd/java/Makefile +++ /dev/null @@ -1,47 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License (the "License"). -# You may not use this file except in compliance with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# Copyright 2007 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -#ident "%Z%%M% %I% %E% SMI" - -include $(SRC)/lib/Makefile.lib - -POFILE = libjdns_sd.po - -SUBDIRS = $(MACH) -$(BUILD64)SUBDIRS += $(MACH64) - -all := TARGET= all -clean := TARGET= clean -clobber := TARGET= clobber -install := TARGET= install -lint := TARGET= lint - -.KEEP_STATE: - -all install clean clobber lint: com/apple .WAIT $(SUBDIRS) - -com/apple $(SUBDIRS): FRC - @cd $@; pwd; $(MAKE) $(TARGET) - -FRC: diff --git a/usr/src/lib/libdns_sd/java/Makefile.com b/usr/src/lib/libdns_sd/java/Makefile.com deleted file mode 100644 index acfcc13dbd..0000000000 --- a/usr/src/lib/libdns_sd/java/Makefile.com +++ /dev/null @@ -1,57 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License (the "License"). -# You may not use this file except in compliance with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# Copyright 2007 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# - -LIBRARY= libjdns_sd.a -VERS= .1 - -OBJECTS= JNISupport.o - -include $(SRC)/lib/Makefile.lib - -LIBS = $(DYNLIB) - -SRCDIR = ../common - -CSTD = $(CSTD_GNU99) -CPPFLAGS += -I$(JAVA_ROOT)/include -I$(JAVA_ROOT)/include/solaris -CPPFLAGS += -I../com/apple/dnssd -CPPFLAGS += -D_REENTRANT -CPPFLAGS += -DMDNS_VERSIONSTR_NODTS - -LDLIBS += -lc -lsocket -ldns_sd - -CLEANFILES= $(LINTOUT) $(LINTLIB) - -LINTLIB = - -.KEEP_STATE: - -lint: lintcheck - -include $(SRC)/lib/Makefile.targ - -pics/%.o: ../common/%.c - $(COMPILE.c) -o $@ $< - $(POST_PROCESS_O) diff --git a/usr/src/lib/libdns_sd/java/amd64/Makefile b/usr/src/lib/libdns_sd/java/amd64/Makefile deleted file mode 100644 index b645e1caed..0000000000 --- a/usr/src/lib/libdns_sd/java/amd64/Makefile +++ /dev/null @@ -1,32 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License (the "License"). -# You may not use this file except in compliance with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# Copyright 2007 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -#ident "%Z%%M% %I% %E% SMI" - -include ../Makefile.com -include ../../../Makefile.lib.64 - -all: $(LIBS) - -install: all $(ROOTLIBS64) $(ROOTLINKS64) diff --git a/usr/src/lib/libdns_sd/java/com/apple/Makefile b/usr/src/lib/libdns_sd/java/com/apple/Makefile deleted file mode 100644 index 8cfdc2e941..0000000000 --- a/usr/src/lib/libdns_sd/java/com/apple/Makefile +++ /dev/null @@ -1,47 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License (the "License"). -# You may not use this file except in compliance with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# Copyright 2007 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -#ident "%Z%%M% %I% %E% SMI" - -include Makefile.com - -SUBDIRS = dnssd - -all:= TARGET = all -clean:= TARGET = clean -clobber:= TARGET = clobber -install:= TARGET = install - -.KEEP_STATE: - -all clean install clobber: ${SUBDIRS} - -${SUBDIRS}: FRC - cd $@; pwd; $(MAKE) $(TARGET) - -lint: - -.WAIT: - -FRC: diff --git a/usr/src/lib/libdns_sd/java/com/apple/Makefile.com b/usr/src/lib/libdns_sd/java/com/apple/Makefile.com deleted file mode 100644 index e699ff14a4..0000000000 --- a/usr/src/lib/libdns_sd/java/com/apple/Makefile.com +++ /dev/null @@ -1,31 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License (the "License"). -# You may not use this file except in compliance with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# Copyright 2007 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -#ident "%Z%%M% %I% %E% SMI" - -include $(SRC)/lib/Makefile.lib - -ROOTDNSSDJAVAHOME = $(ROOT)/usr/share/lib/java - -.KEEP_STATE: diff --git a/usr/src/lib/libdns_sd/java/com/apple/dnssd/BaseListener.java b/usr/src/lib/libdns_sd/java/com/apple/dnssd/BaseListener.java deleted file mode 100644 index b99d341c2f..0000000000 --- a/usr/src/lib/libdns_sd/java/com/apple/dnssd/BaseListener.java +++ /dev/null @@ -1,36 +0,0 @@ -/* -*- Mode: Java; tab-width: 4 -*- - * - * Copyright (c) 2004 Apple Computer, 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - -package com.apple.dnssd; - - -/** A base class for DNSSD listeners. */ - -public interface BaseListener -{ - /** Called to report DNSSD operation failures.<P> - - @param service - The service that encountered the failure. - <P> - @param errorCode - Indicates the failure that occurred. See {@link DNSSDException} for error codes. - */ - void operationFailed( DNSSDService service, int errorCode); -} - diff --git a/usr/src/lib/libdns_sd/java/com/apple/dnssd/BrowseListener.java b/usr/src/lib/libdns_sd/java/com/apple/dnssd/BrowseListener.java deleted file mode 100644 index b92b9dc59f..0000000000 --- a/usr/src/lib/libdns_sd/java/com/apple/dnssd/BrowseListener.java +++ /dev/null @@ -1,73 +0,0 @@ -/* -*- Mode: Java; tab-width: 4 -*- - * - * Copyright (c) 2004 Apple Computer, 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - -package com.apple.dnssd; - - -/** A listener that receives results from {@link DNSSD#browse}. */ - -public interface BrowseListener extends BaseListener -{ - /** Called to report discovered services.<P> - - @param browser - The active browse service. - <P> - @param flags - Possible values are DNSSD.MORE_COMING. - <P> - @param ifIndex - The interface on which the service is advertised. This index should be passed - to {@link DNSSD#resolve} when resolving the service. - <P> - @param serviceName - The service name discovered. - <P> - @param regType - The registration type, as passed in to DNSSD.browse(). - <P> - @param domain - The domain in which the service was discovered. - */ - void serviceFound( DNSSDService browser, int flags, int ifIndex, - String serviceName, String regType, String domain); - - /** Called to report services which have been deregistered.<P> - - @param browser - The active browse service. - <P> - @param flags - Possible values are DNSSD.MORE_COMING. - <P> - @param ifIndex - The interface on which the service is advertised. - <P> - @param serviceName - The service name which has deregistered. - <P> - @param regType - The registration type, as passed in to DNSSD.browse(). - <P> - @param domain - The domain in which the service was discovered. - */ - void serviceLost( DNSSDService browser, int flags, int ifIndex, - String serviceName, String regType, String domain); -} - diff --git a/usr/src/lib/libdns_sd/java/com/apple/dnssd/DNSRecord.java b/usr/src/lib/libdns_sd/java/com/apple/dnssd/DNSRecord.java deleted file mode 100644 index a853d091fa..0000000000 --- a/usr/src/lib/libdns_sd/java/com/apple/dnssd/DNSRecord.java +++ /dev/null @@ -1,52 +0,0 @@ -/* -*- Mode: Java; tab-width: 4 -*- - * - * Copyright (c) 2004 Apple Computer, 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - -package com.apple.dnssd; - - -/** - Reference to a record returned by {@link DNSSDRegistration#addRecord}.<P> - - Note: client is responsible for serializing access to these objects if - they are shared between concurrent threads. -*/ - -public interface DNSRecord -{ - /** Update a registered resource record.<P> - The record must either be the primary txt record of a service registered via DNSSD.register(), - or a record added to a registered service via addRecord().<P> - - @param flags - Currently unused, reserved for future use. - <P> - @param rData - The new rdata to be contained in the updated resource record. - <P> - @param ttl - The time to live of the updated resource record, in seconds. - */ - void update( int flags, byte[] rData, int ttl) - throws DNSSDException; - - /** Remove a registered resource record.<P> - */ - void remove() - throws DNSSDException; -} - diff --git a/usr/src/lib/libdns_sd/java/com/apple/dnssd/DNSSD.java b/usr/src/lib/libdns_sd/java/com/apple/dnssd/DNSSD.java deleted file mode 100644 index f749a88ead..0000000000 --- a/usr/src/lib/libdns_sd/java/com/apple/dnssd/DNSSD.java +++ /dev/null @@ -1,860 +0,0 @@ -/* -*- Mode: Java; tab-width: 4 -*- - * - * Copyright (c) 2004 Apple Computer, 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - - This file declares and implements DNSSD, the central Java factory class - for doing DNS Service Discovery. It includes the mostly-abstract public - interface, as well as the Apple* implementation subclasses. - */ - - -package com.apple.dnssd; - - -/** - DNSSD provides access to DNS Service Discovery features of ZeroConf networking.<P> - - It is a factory class that is used to invoke registration and discovery-related - operations. Most operations are non-blocking; clients are called back through an interface - with the result of an operation. Callbacks are made from a separate worker thread.<P> - - For example, in this program<P> - <PRE><CODE> - class MyClient implements BrowseListener { - void lookForWebServers() { - myBrowser = DNSSD.browse("_http._tcp", this); - } - - public void serviceFound(DNSSDService browser, int flags, int ifIndex, - String serviceName, String regType, String domain) {} - ... - }</CODE></PRE> - <CODE>MyClient.serviceFound()</CODE> would be called for every HTTP server discovered in the - default browse domain(s). -*/ - -abstract public class DNSSD -{ - /** Flag indicates to a {@link BrowseListener} that another result is - queued. Applications should not update their UI to display browse - results if the MORE_COMING flag is set; they will be called at least once - more with the flag clear. - */ - public static final int MORE_COMING = ( 1 << 0 ); - - /** If flag is set in a {@link DomainListener} callback, indicates that the result is the default domain. */ - public static final int DEFAULT = ( 1 << 2 ); - - /** If flag is set, a name conflict will trigger an exception when registering non-shared records.<P> - A name must be explicitly specified when registering a service if this bit is set - (i.e. the default name may not not be used). - */ - public static final int NO_AUTO_RENAME = ( 1 << 3 ); - - /** If flag is set, allow multiple records with this name on the network (e.g. PTR records) - when registering individual records on a {@link DNSSDRegistration}. - */ - public static final int SHARED = ( 1 << 4 ); - - /** If flag is set, records with this name must be unique on the network (e.g. SRV records). */ - public static final int UNIQUE = ( 1 << 5 ); - - /** Set flag when calling enumerateDomains() to restrict results to domains recommended for browsing. */ - public static final int BROWSE_DOMAINS = ( 1 << 6 ); - /** Set flag when calling enumerateDomains() to restrict results to domains recommended for registration. */ - public static final int REGISTRATION_DOMAINS = ( 1 << 7 ); - - /** Maximum length, in bytes, of a domain name represented as an escaped C-String. */ - public static final int MAX_DOMAIN_NAME = 1009; - - /** Pass for ifIndex to specify all available interfaces. */ - public static final int ALL_INTERFACES = 0; - - /** Pass for ifIndex to specify the localhost interface. */ - public static final int LOCALHOST_ONLY = -1; - - /** Browse for instances of a service.<P> - - Note: browsing consumes network bandwidth. Call {@link DNSSDService#stop} when you have finished browsing.<P> - - @param flags - Currently ignored, reserved for future use. - <P> - @param ifIndex - If non-zero, specifies the interface on which to browse for services - (the index for a given interface is determined via the if_nametoindex() - family of calls.) Most applications will pass 0 to browse on all available - interfaces. Pass -1 to only browse for services provided on the local host. - <P> - @param regType - The registration type being browsed for followed by the protocol, separated by a - dot (e.g. "_ftp._tcp"). The transport protocol must be "_tcp" or "_udp". - <P> - @param domain - If non-null, specifies the domain on which to browse for services. - Most applications will not specify a domain, instead browsing on the - default domain(s). - <P> - @param listener - This object will get called when instances of the service are discovered (or disappear). - <P> - @return A {@link DNSSDService} that represents the active browse operation. - - @throws SecurityException If a security manager is present and denies <tt>RuntimePermission("getDNSSDInstance")</tt>. - @see RuntimePermission - */ - public static DNSSDService browse( int flags, int ifIndex, String regType, String domain, BrowseListener listener) - throws DNSSDException - { return getInstance()._makeBrowser( flags, ifIndex, regType, domain, listener); } - - /** Browse for instances of a service. Use default flags, ifIndex and domain.<P> - - @param regType - The registration type being browsed for followed by the protocol, separated by a - dot (e.g. "_ftp._tcp"). The transport protocol must be "_tcp" or "_udp". - <P> - @param listener - This object will get called when instances of the service are discovered (or disappear). - <P> - @return A {@link DNSSDService} that represents the active browse operation. - - @throws SecurityException If a security manager is present and denies <tt>RuntimePermission("getDNSSDInstance")</tt>. - @see RuntimePermission - */ - public static DNSSDService browse( String regType, BrowseListener listener) - throws DNSSDException - { return browse( 0, 0, regType, "", listener); } - - /** Resolve a service name discovered via browse() to a target host name, port number, and txt record.<P> - - Note: Applications should NOT use resolve() solely for txt record monitoring - use - queryRecord() instead, as it is more efficient for this task.<P> - - Note: When the desired results have been returned, the client MUST terminate the resolve by - calling {@link DNSSDService#stop}.<P> - - Note: resolve() behaves correctly for typical services that have a single SRV record and - a single TXT record (the TXT record may be empty.) To resolve non-standard services with - multiple SRV or TXT records, use queryRecord().<P> - - @param flags - Currently ignored, reserved for future use. - <P> - @param ifIndex - The interface on which to resolve the service. The client should - pass the interface on which the serviceName was discovered (i.e. - the ifIndex passed to the serviceFound() callback) - or 0 to resolve the named service on all available interfaces. - <P> - @param serviceName - The servicename to be resolved. - <P> - @param regType - The registration type being resolved followed by the protocol, separated by a - dot (e.g. "_ftp._tcp"). The transport protocol must be "_tcp" or "_udp". - <P> - @param domain - The domain on which the service is registered, i.e. the domain passed - to the serviceFound() callback. - <P> - @param listener - This object will get called when the service is resolved. - <P> - @return A {@link DNSSDService} that represents the active resolve operation. - - @throws SecurityException If a security manager is present and denies <tt>RuntimePermission("getDNSSDInstance")</tt>. - @see RuntimePermission - */ - public static DNSSDService resolve( int flags, int ifIndex, String serviceName, String regType, - String domain, ResolveListener listener) - throws DNSSDException - { return getInstance()._resolve( flags, ifIndex, serviceName, regType, domain, listener); } - - /** Register a service, to be discovered via browse() and resolve() calls.<P> - @param flags - Possible values are: NO_AUTO_RENAME. - <P> - @param ifIndex - If non-zero, specifies the interface on which to register the service - (the index for a given interface is determined via the if_nametoindex() - family of calls.) Most applications will pass 0 to register on all - available interfaces. Pass -1 to register a service only on the local - machine (service will not be visible to remote hosts). - <P> - @param serviceName - If non-null, specifies the service name to be registered. - Applications need not specify a name, in which case the - computer name is used (this name is communicated to the client via - the serviceRegistered() callback). - <P> - @param regType - The registration type being registered followed by the protocol, separated by a - dot (e.g. "_ftp._tcp"). The transport protocol must be "_tcp" or "_udp". - <P> - @param domain - If non-null, specifies the domain on which to advertise the service. - Most applications will not specify a domain, instead automatically - registering in the default domain(s). - <P> - @param host - If non-null, specifies the SRV target host name. Most applications - will not specify a host, instead automatically using the machine's - default host name(s). Note that specifying a non-null host does NOT - create an address record for that host - the application is responsible - for ensuring that the appropriate address record exists, or creating it - via {@link DNSSDRegistration#addRecord}. - <P> - @param port - The port on which the service accepts connections. Pass 0 for a - "placeholder" service (i.e. a service that will not be discovered by - browsing, but will cause a name conflict if another client tries to - register that same name.) Most clients will not use placeholder services. - <P> - @param txtRecord - The txt record rdata. May be null. Note that a non-null txtRecord - MUST be a properly formatted DNS TXT record, i.e. <length byte> <data> - <length byte> <data> ... - <P> - @param listener - This object will get called when the service is registered. - <P> - @return A {@link DNSSDRegistration} that controls the active registration. - - @throws SecurityException If a security manager is present and denies <tt>RuntimePermission("getDNSSDInstance")</tt>. - @see RuntimePermission - */ - public static DNSSDRegistration register( int flags, int ifIndex, String serviceName, String regType, - String domain, String host, int port, TXTRecord txtRecord, RegisterListener listener) - throws DNSSDException - { return getInstance()._register( flags, ifIndex, serviceName, regType, domain, host, port, txtRecord, listener); } - - /** Register a service, to be discovered via browse() and resolve() calls. Use default flags, ifIndex, domain, host and txtRecord.<P> - @param serviceName - If non-null, specifies the service name to be registered. - Applications need not specify a name, in which case the - computer name is used (this name is communicated to the client via - the serviceRegistered() callback). - <P> - @param regType - The registration type being registered followed by the protocol, separated by a - dot (e.g. "_ftp._tcp"). The transport protocol must be "_tcp" or "_udp". - <P> - @param port - The port on which the service accepts connections. Pass 0 for a - "placeholder" service (i.e. a service that will not be discovered by - browsing, but will cause a name conflict if another client tries to - register that same name.) Most clients will not use placeholder services. - <P> - @param listener - This object will get called when the service is registered. - <P> - @return A {@link DNSSDRegistration} that controls the active registration. - - @throws SecurityException If a security manager is present and denies <tt>RuntimePermission("getDNSSDInstance")</tt>. - @see RuntimePermission - */ - public static DNSSDRegistration register( String serviceName, String regType, int port, RegisterListener listener) - throws DNSSDException - { return register( 0, 0, serviceName, regType, null, null, port, null, listener); } - - /** Create a {@link DNSSDRecordRegistrar} allowing efficient registration of - multiple individual records.<P> - <P> - @return A {@link DNSSDRecordRegistrar} that can be used to register records. - - @throws SecurityException If a security manager is present and denies <tt>RuntimePermission("getDNSSDInstance")</tt>. - @see RuntimePermission - */ - public static DNSSDRecordRegistrar createRecordRegistrar( RegisterRecordListener listener) - throws DNSSDException - { return getInstance()._createRecordRegistrar( listener); } - - /** Query for an arbitrary DNS record.<P> - @param flags - Possible values are: MORE_COMING. - <P> - @param ifIndex - If non-zero, specifies the interface on which to issue the query - (the index for a given interface is determined via the if_nametoindex() - family of calls.) Passing 0 causes the name to be queried for on all - interfaces. Passing -1 causes the name to be queried for only on the - local host. - <P> - @param serviceName - The full domain name of the resource record to be queried for. - <P> - @param rrtype - The numerical type of the resource record to be queried for (e.g. PTR, SRV, etc) - as defined in nameser.h. - <P> - @param rrclass - The class of the resource record, as defined in nameser.h - (usually 1 for the Internet class). - <P> - @param listener - This object will get called when the query completes. - <P> - @return A {@link DNSSDService} that controls the active query. - - @throws SecurityException If a security manager is present and denies <tt>RuntimePermission("getDNSSDInstance")</tt>. - @see RuntimePermission - */ - public static DNSSDService queryRecord( int flags, int ifIndex, String serviceName, int rrtype, - int rrclass, QueryListener listener) - throws DNSSDException - { return getInstance()._queryRecord( flags, ifIndex, serviceName, rrtype, rrclass, listener); } - - /** Asynchronously enumerate domains available for browsing and registration.<P> - - Currently, the only domain returned is "local.", but other domains will be returned in future.<P> - - The enumeration MUST be cancelled by calling {@link DNSSDService#stop} when no more domains - are to be found.<P> - @param flags - Possible values are: BROWSE_DOMAINS, REGISTRATION_DOMAINS. - <P> - @param ifIndex - If non-zero, specifies the interface on which to look for domains. - (the index for a given interface is determined via the if_nametoindex() - family of calls.) Most applications will pass 0 to enumerate domains on - all interfaces. - <P> - @param listener - This object will get called when domains are found. - <P> - @return A {@link DNSSDService} that controls the active enumeration. - - @throws SecurityException If a security manager is present and denies <tt>RuntimePermission("getDNSSDInstance")</tt>. - @see RuntimePermission - */ - public static DNSSDService enumerateDomains( int flags, int ifIndex, DomainListener listener) - throws DNSSDException - { return getInstance()._enumerateDomains( flags, ifIndex, listener); } - - /** Concatenate a three-part domain name (as provided to the listeners) into a - properly-escaped full domain name. Note that strings passed to listeners are - ALREADY ESCAPED where necessary.<P> - @param serviceName - The service name - any dots or slashes must NOT be escaped. - May be null (to construct a PTR record name, e.g. "_ftp._tcp.apple.com"). - <P> - @param regType - The registration type followed by the protocol, separated by a dot (e.g. "_ftp._tcp"). - <P> - @param domain - The domain name, e.g. "apple.com". Any literal dots or backslashes must be escaped. - <P> - @return The full domain name. - - @throws SecurityException If a security manager is present and denies <tt>RuntimePermission("getDNSSDInstance")</tt>. - @see RuntimePermission - */ - public static String constructFullName( String serviceName, String regType, String domain) - throws DNSSDException - { return getInstance()._constructFullName( serviceName, regType, domain); } - - /** Instruct the daemon to verify the validity of a resource record that appears to - be out of date. (e.g. because tcp connection to a service's target failed.) <P> - - Causes the record to be flushed from the daemon's cache (as well as all other - daemons' caches on the network) if the record is determined to be invalid.<P> - @param flags - Currently unused, reserved for future use. - <P> - @param ifIndex - If non-zero, specifies the interface on which to reconfirm the record - (the index for a given interface is determined via the if_nametoindex() - family of calls.) Passing 0 causes the name to be reconfirmed on all - interfaces. Passing -1 causes the name to be reconfirmed only on the - local host. - <P> - @param fullName - The resource record's full domain name. - <P> - @param rrtype - The resource record's type (e.g. PTR, SRV, etc) as defined in nameser.h. - <P> - @param rrclass - The class of the resource record, as defined in nameser.h (usually 1). - <P> - @param rdata - The raw rdata of the resource record. - - @throws SecurityException If a security manager is present and denies <tt>RuntimePermission("getDNSSDInstance")</tt>. - @see RuntimePermission - */ - public static void reconfirmRecord( int flags, int ifIndex, String fullName, int rrtype, - int rrclass, byte[] rdata) - { getInstance()._reconfirmRecord( flags, ifIndex, fullName, rrtype, rrclass, rdata); } - - /** Return the canonical name of a particular interface index.<P> - @param ifIndex - A valid interface index. Must not be ALL_INTERFACES. - <P> - @return The name of the interface, which should match java.net.NetworkInterface.getName(). - - @throws SecurityException If a security manager is present and denies <tt>RuntimePermission("getDNSSDInstance")</tt>. - @see RuntimePermission - */ - public static String getNameForIfIndex( int ifIndex) - { return getInstance()._getNameForIfIndex( ifIndex); } - - /** Return the index of a named interface.<P> - @param ifName - A valid interface name. An example is java.net.NetworkInterface.getName(). - <P> - @return The interface index. - - @throws SecurityException If a security manager is present and denies <tt>RuntimePermission("getDNSSDInstance")</tt>. - @see RuntimePermission - */ - public static int getIfIndexForName( String ifName) - { return getInstance()._getIfIndexForName( ifName); } - - protected DNSSD() {} // prevent direct instantiation - - /** Return the single instance of DNSSD. */ - static protected final DNSSD getInstance() - { - SecurityManager sm = System.getSecurityManager(); - if (sm != null) - sm.checkPermission( new RuntimePermission( "getDNSSDInstance")); - return fInstance; - } - - abstract protected DNSSDService _makeBrowser( int flags, int ifIndex, String regType, String domain, BrowseListener listener) - throws DNSSDException; - - abstract protected DNSSDService _resolve( int flags, int ifIndex, String serviceName, String regType, - String domain, ResolveListener listener) - throws DNSSDException; - - abstract protected DNSSDRegistration _register( int flags, int ifIndex, String serviceName, String regType, - String domain, String host, int port, TXTRecord txtRecord, RegisterListener listener) - throws DNSSDException; - - abstract protected DNSSDRecordRegistrar _createRecordRegistrar( RegisterRecordListener listener) - throws DNSSDException; - - abstract protected DNSSDService _queryRecord( int flags, int ifIndex, String serviceName, int rrtype, - int rrclass, QueryListener listener) - throws DNSSDException; - - abstract protected DNSSDService _enumerateDomains( int flags, int ifIndex, DomainListener listener) - throws DNSSDException; - - abstract protected String _constructFullName( String serviceName, String regType, String domain) - throws DNSSDException; - - abstract protected void _reconfirmRecord( int flags, int ifIndex, String fullName, int rrtype, - int rrclass, byte[] rdata); - - abstract protected String _getNameForIfIndex( int ifIndex); - - abstract protected int _getIfIndexForName( String ifName); - - protected static DNSSD fInstance; - - static - { - try - { - String name = System.getProperty( "com.apple.dnssd.DNSSD" ); - if (name == null) - name = "com.apple.dnssd.AppleDNSSD"; // Fall back to Apple-provided class. - fInstance = (DNSSD) Class.forName(name).newInstance(); - } - catch( Exception e ) - { - throw new InternalError( "cannot instantiate DNSSD" + e ); - } - } -} - - -// Concrete implementation of DNSSDException -class AppleDNSSDException extends DNSSDException -{ - public AppleDNSSDException( int errorCode) { fErrorCode = errorCode; } - - public int getErrorCode() { return fErrorCode; } - - public String getMessage() - { - final String kMessages[] = { // should probably be put into a resource or something - "UNKNOWN", - "NO_SUCH_NAME", - "NO_MEMORY", - "BAD_PARAM", - "BAD_REFERENCE", - "BAD_STATE", - "BAD_FLAGS", - "UNSUPPORTED", - "NOT_INITIALIZED", - "NO_CACHE", - "ALREADY_REGISTERED", - "NAME_CONFLICT", - "INVALID", - "FIREWALL", - "INCOMPATIBLE", - "BAD_INTERFACE_INDEX", - "REFUSED", - "NOSUCHRECORD", - "NOAUTH", - "NOSUCHKEY", - "NATTRAVERSAL", - "DOUBLENAT", - "BADTIME", - "BADSIG", - "BADKEY", - "TRANSIENT", - "SERVICENOTRUNNING", - "NATPORTMAPPINGUNSUPPORTED", - "NATPORTMAPPINGDISABLED" - }; - - if (fErrorCode <= UNKNOWN && fErrorCode > ( UNKNOWN - kMessages.length)) - { - return "DNS-SD Error " + String.valueOf( fErrorCode) + ": " + kMessages[ UNKNOWN - fErrorCode]; - } - else - return super.getMessage() + "(" + String.valueOf( fErrorCode) + ")"; - } - - protected int fErrorCode; -} - -// The concrete, default implementation. -class AppleDNSSD extends DNSSD -{ - static - { - System.loadLibrary( "jdns_sd"); - - int libInitResult = InitLibrary( 2); // Current version number (must be sync'd with jnilib version) - - if (libInitResult != DNSSDException.NO_ERROR) - throw new InternalError( "cannot instantiate DNSSD: " + new AppleDNSSDException( libInitResult).getMessage()); - } - - static public boolean hasAutoCallbacks; // Set by InitLibrary() to value of AUTO_CALLBACKS - - protected DNSSDService _makeBrowser( int flags, int ifIndex, String regType, String domain, BrowseListener client) - throws DNSSDException - { - return new AppleBrowser( flags, ifIndex, regType, domain, client); - } - - protected DNSSDService _resolve( int flags, int ifIndex, String serviceName, String regType, - String domain, ResolveListener client) - throws DNSSDException - { - return new AppleResolver( flags, ifIndex, serviceName, regType, domain, client); - } - - protected DNSSDRegistration _register( int flags, int ifIndex, String serviceName, String regType, - String domain, String host, int port, TXTRecord txtRecord, RegisterListener client) - throws DNSSDException - { - return new AppleRegistration( flags, ifIndex, serviceName, regType, domain, host, port, - ( txtRecord != null) ? txtRecord.getRawBytes() : null, client); - } - - protected DNSSDRecordRegistrar _createRecordRegistrar( RegisterRecordListener listener) - throws DNSSDException - { - return new AppleRecordRegistrar( listener); - } - - protected DNSSDService _queryRecord( int flags, int ifIndex, String serviceName, int rrtype, - int rrclass, QueryListener client) - throws DNSSDException - { - return new AppleQuery( flags, ifIndex, serviceName, rrtype, rrclass, client); - } - - protected DNSSDService _enumerateDomains( int flags, int ifIndex, DomainListener listener) - throws DNSSDException - { - return new AppleDomainEnum( flags, ifIndex, listener); - } - - protected String _constructFullName( String serviceName, String regType, String domain) - throws DNSSDException - { - String[] responseHolder = new String[1]; // lame maneuver to get around Java's lack of reference parameters - - int rc = ConstructName( serviceName, regType, domain, responseHolder); - if (rc != 0) - throw new AppleDNSSDException( rc); - - return responseHolder[0]; - } - - protected void _reconfirmRecord( int flags, int ifIndex, String fullName, int rrtype, - int rrclass, byte[] rdata) - { - ReconfirmRecord( flags, ifIndex, fullName, rrtype, rrclass, rdata); - } - - protected String _getNameForIfIndex( int ifIndex) - { - return GetNameForIfIndex( ifIndex); - } - - protected int _getIfIndexForName( String ifName) - { - return GetIfIndexForName( ifName); - } - - - protected native int ConstructName( String serviceName, String regType, String domain, String[] pOut); - - protected native void ReconfirmRecord( int flags, int ifIndex, String fullName, int rrtype, - int rrclass, byte[] rdata); - - protected native String GetNameForIfIndex( int ifIndex); - - protected native int GetIfIndexForName( String ifName); - - protected static native int InitLibrary( int callerVersion); -} - -class AppleService implements DNSSDService, Runnable -{ - public AppleService(BaseListener listener) { fNativeContext = 0; fListener = listener; } - - public void stop() { this.HaltOperation(); } - - /* Block until data arrives, or one second passes. Returns 1 if data present, 0 otherwise. */ - protected native int BlockForData(); - - /* Call ProcessResults when data appears on socket descriptor. */ - protected native int ProcessResults(); - - protected synchronized native void HaltOperation(); - - protected void ThrowOnErr( int rc) throws DNSSDException - { - if (rc != 0) - throw new AppleDNSSDException( rc); - } - - protected long /* warning */ fNativeContext; // Private storage for native side - - public void run() - { - while ( true ) - { - // Note: We want to allow our DNS-SD operation to be stopped from other threads, so we have to - // block waiting for data *outside* the synchronized section. Because we're doing this unsynchronized - // we have to write some careful code. Suppose our DNS-SD operation is stopped from some other thread, - // and then immediately afterwards that thread (or some third, unrelated thread) starts a new DNS-SD - // operation. The Unix kernel always allocates the lowest available file descriptor to a new socket, - // so the same file descriptor is highly likely to be reused for the new operation, and if our old - // stale ServiceThread accidentally consumes bytes off that new socket we'll get really messed up. - // To guard against that, before calling ProcessResults we check to ensure that our - // fNativeContext has not been deleted, which is a telltale sign that our operation was stopped. - // After calling ProcessResults we check again, because it's extremely common for callback - // functions to stop their own operation and start others. For example, a resolveListener callback - // may well stop the resolve and then start a QueryRecord call to monitor the TXT record. - // - // The remaining risk is that between our checking fNativeContext and calling ProcessResults(), - // some other thread could stop the operation and start a new one using same file descriptor, and - // we wouldn't know. To prevent this, the AppleService object's HaltOperation() routine is declared - // synchronized and we perform our checks synchronized on the AppleService object, which ensures - // that HaltOperation() can't execute while we're doing it. Because Java locks are re-entrant this - // locking DOESN'T prevent the callback routine from stopping its own operation, but DOES prevent - // any other thread from stopping it until after the callback has completed and returned to us here. - - int result = BlockForData(); - synchronized (this) - { - if (fNativeContext == 0) break; // Some other thread stopped our DNSSD operation; time to terminate this thread - if (result == 0) continue; // If BlockForData() said there was no data, go back and block again - result = ProcessResults(); - if (fNativeContext == 0) break; // Event listener stopped its own DNSSD operation; terminate this thread - if (result != 0) { fListener.operationFailed(this, result); break; } // If error, notify listener - } - } - } - - protected BaseListener fListener; -} - - -class AppleBrowser extends AppleService -{ - public AppleBrowser( int flags, int ifIndex, String regType, String domain, BrowseListener client) - throws DNSSDException - { - super(client); - this.ThrowOnErr( this.CreateBrowser( flags, ifIndex, regType, domain)); - if (!AppleDNSSD.hasAutoCallbacks) - new Thread(this).start(); - } - - // Sets fNativeContext. Returns non-zero on error. - protected native int CreateBrowser( int flags, int ifIndex, String regType, String domain); -} - -class AppleResolver extends AppleService -{ - public AppleResolver( int flags, int ifIndex, String serviceName, String regType, - String domain, ResolveListener client) - throws DNSSDException - { - super(client); - this.ThrowOnErr( this.CreateResolver( flags, ifIndex, serviceName, regType, domain)); - if (!AppleDNSSD.hasAutoCallbacks) - new Thread(this).start(); - } - - // Sets fNativeContext. Returns non-zero on error. - protected native int CreateResolver( int flags, int ifIndex, String serviceName, String regType, - String domain); -} - -// An AppleDNSRecord is a simple wrapper around a dns_sd DNSRecord. -class AppleDNSRecord implements DNSRecord -{ - public AppleDNSRecord( AppleService owner) - { - fOwner = owner; - fRecord = 0; // record always starts out empty - } - - public void update( int flags, byte[] rData, int ttl) - throws DNSSDException - { - this.ThrowOnErr( this.Update( flags, rData, ttl)); - } - - public void remove() - throws DNSSDException - { - this.ThrowOnErr( this.Remove()); - } - - protected long fRecord; // Really a DNSRecord; sizeof(long) == sizeof(void*) ? - protected AppleService fOwner; - - protected void ThrowOnErr( int rc) throws DNSSDException - { - if (rc != 0) - throw new AppleDNSSDException( rc); - } - - protected native int Update( int flags, byte[] rData, int ttl); - - protected native int Remove(); -} - -class AppleRegistration extends AppleService implements DNSSDRegistration -{ - public AppleRegistration( int flags, int ifIndex, String serviceName, String regType, String domain, - String host, int port, byte[] txtRecord, RegisterListener client) - throws DNSSDException - { - super(client); - this.ThrowOnErr( this.BeginRegister( ifIndex, flags, serviceName, regType, domain, host, port, txtRecord)); - if (!AppleDNSSD.hasAutoCallbacks) - new Thread(this).start(); - } - - public DNSRecord addRecord( int flags, int rrType, byte[] rData, int ttl) - throws DNSSDException - { - AppleDNSRecord newRecord = new AppleDNSRecord( this); - - this.ThrowOnErr( this.AddRecord( flags, rrType, rData, ttl, newRecord)); - return newRecord; - } - - public DNSRecord getTXTRecord() - throws DNSSDException - { - return new AppleDNSRecord( this); // A record with ref 0 is understood to be primary TXT record - } - - // Sets fNativeContext. Returns non-zero on error. - protected native int BeginRegister( int ifIndex, int flags, String serviceName, String regType, - String domain, String host, int port, byte[] txtRecord); - - // Sets fNativeContext. Returns non-zero on error. - protected native int AddRecord( int flags, int rrType, byte[] rData, int ttl, AppleDNSRecord destObj); -} - -class AppleRecordRegistrar extends AppleService implements DNSSDRecordRegistrar -{ - public AppleRecordRegistrar( RegisterRecordListener listener) - throws DNSSDException - { - super(listener); - this.ThrowOnErr( this.CreateConnection()); - if (!AppleDNSSD.hasAutoCallbacks) - new Thread(this).start(); - } - - public DNSRecord registerRecord( int flags, int ifIndex, String fullname, int rrtype, - int rrclass, byte[] rdata, int ttl) - throws DNSSDException - { - AppleDNSRecord newRecord = new AppleDNSRecord( this); - - this.ThrowOnErr( this.RegisterRecord( flags, ifIndex, fullname, rrtype, rrclass, rdata, ttl, newRecord)); - return newRecord; - } - - // Sets fNativeContext. Returns non-zero on error. - protected native int CreateConnection(); - - // Sets fNativeContext. Returns non-zero on error. - protected native int RegisterRecord( int flags, int ifIndex, String fullname, int rrtype, - int rrclass, byte[] rdata, int ttl, AppleDNSRecord destObj); -} - -class AppleQuery extends AppleService -{ - public AppleQuery( int flags, int ifIndex, String serviceName, int rrtype, - int rrclass, QueryListener client) - throws DNSSDException - { - super(client); - this.ThrowOnErr( this.CreateQuery( flags, ifIndex, serviceName, rrtype, rrclass)); - if (!AppleDNSSD.hasAutoCallbacks) - new Thread(this).start(); - } - - // Sets fNativeContext. Returns non-zero on error. - protected native int CreateQuery( int flags, int ifIndex, String serviceName, int rrtype, int rrclass); -} - -class AppleDomainEnum extends AppleService -{ - public AppleDomainEnum( int flags, int ifIndex, DomainListener client) - throws DNSSDException - { - super(client); - this.ThrowOnErr( this.BeginEnum( flags, ifIndex)); - if (!AppleDNSSD.hasAutoCallbacks) - new Thread(this).start(); - } - - // Sets fNativeContext. Returns non-zero on error. - protected native int BeginEnum( int flags, int ifIndex); -} - - diff --git a/usr/src/lib/libdns_sd/java/com/apple/dnssd/DNSSDException.java b/usr/src/lib/libdns_sd/java/com/apple/dnssd/DNSSDException.java deleted file mode 100644 index 99549b5d68..0000000000 --- a/usr/src/lib/libdns_sd/java/com/apple/dnssd/DNSSDException.java +++ /dev/null @@ -1,64 +0,0 @@ -/* -*- Mode: Java; tab-width: 4 -*- - * - * Copyright (c) 2004 Apple Computer, 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.apple.dnssd; - - -/** - Used to report various DNS-SD-related error conditions. -*/ - -abstract public class DNSSDException extends Exception -{ - public static final int NO_ERROR = 0; - public static final int UNKNOWN = -65537; - public static final int NO_SUCH_NAME = -65538; - public static final int NO_MEMORY = -65539; - public static final int BAD_PARAM = -65540; - public static final int BAD_REFERENCE = -65541; - public static final int BAD_STATE = -65542; - public static final int BAD_FLAGS = -65543; - public static final int UNSUPPORTED = -65544; - public static final int NOT_INITIALIZED = -65545; - public static final int NO_CACHE = -65546; - public static final int ALREADY_REGISTERED = -65547; - public static final int NAME_CONFLICT = -65548; - public static final int INVALID = -65549; - public static final int FIREWALL = -65550; - public static final int INCOMPATIBLE = -65551; - public static final int BAD_INTERFACE_INDEX = -65552; - public static final int REFUSED = -65553; - public static final int NOSUCHRECORD = -65554; - public static final int NOAUTH = -65555; - public static final int NOSUCHKEY = -65556; - public static final int NATTRAVERSAL = -65557; - public static final int DOUBLENAT = -65558; - public static final int BADTIME = -65559; - public static final int BADSIG = -65560; - public static final int BADKEY = -65561; - public static final int TRANSIENT = -65562; - public static final int SERVICENOTRUNNING = -65563; - public static final int NATPORTMAPPINGUNSUPPORTED = -65564; - public static final int NATPORTMAPPINGDISABLED = -65565; - - // Note: When adding new error values here, remember also - // to update the corresponding kMessages array in AppleDNSSDException (DNSSD.java) - - /** Returns the sub-code that identifies the particular error. */ - abstract public int getErrorCode(); -} - diff --git a/usr/src/lib/libdns_sd/java/com/apple/dnssd/DNSSDRecordRegistrar.java b/usr/src/lib/libdns_sd/java/com/apple/dnssd/DNSSDRecordRegistrar.java deleted file mode 100644 index 62c5330840..0000000000 --- a/usr/src/lib/libdns_sd/java/com/apple/dnssd/DNSSDRecordRegistrar.java +++ /dev/null @@ -1,61 +0,0 @@ -/* -*- Mode: Java; tab-width: 4 -*- - * - * Copyright (c) 2006 Apple Computer, 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - -package com.apple.dnssd; - - -/** An object for registering records, created by {@link DNSSD#createRecordRegistrar}. */ - -public interface DNSSDRecordRegistrar extends DNSSDService -{ - /** Register an independent {@link DNSRecord}.<P> - @param flags - Possible values are SHARED or UNIQUE (see flag type definitions for details). - <P> - @param ifIndex - If non-zero, specifies the interface on which to register the record - (the index for a given interface is determined via the if_nametoindex() - family of calls.) Passing 0 causes the record to be registered on all interfaces. - <P> - @param fullname - The full domain name of the resource record. - <P> - @param rrtype - The numerical type of the resource record to be queried for (e.g. PTR, SRV, etc) - as defined in nameser.h. - <P> - @param rrclass - The class of the resource record, as defined in nameser.h - (usually 1 for the Internet class). - <P> - @param rdata - The new rdata as it is to appear in the DNS record. - <P> - @param ttl - The time to live of the resource record, in seconds. Pass 0 to use a default value. - <P> - @return A {@link DNSSDService} that can be used to abort the record registration. - - @throws SecurityException If a security manager is present and denies <tt>RuntimePermission("getDNSSDInstance")</tt>. - @see RuntimePermission - */ - public DNSRecord registerRecord( int flags, int ifIndex, String fullname, int rrtype, - int rrclass, byte[] rdata, int ttl) - throws DNSSDException; -} - diff --git a/usr/src/lib/libdns_sd/java/com/apple/dnssd/DNSSDRegistration.java b/usr/src/lib/libdns_sd/java/com/apple/dnssd/DNSSDRegistration.java deleted file mode 100644 index 720df0b847..0000000000 --- a/usr/src/lib/libdns_sd/java/com/apple/dnssd/DNSSDRegistration.java +++ /dev/null @@ -1,60 +0,0 @@ -/* -*- Mode: Java; tab-width: 4 -*- - * - * Copyright (c) 2004 Apple Computer, 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - -package com.apple.dnssd; - - -/** A tracking object for a registration created by {@link DNSSD#register}. */ - -public interface DNSSDRegistration extends DNSSDService -{ - /** Get a reference to the primary TXT record of a registered service.<P> - The record can be updated by sending it an update() message.<P> - - <P> - @return A {@link DNSRecord}. - If {@link DNSSDRegistration#stop} is called, the DNSRecord is also - invalidated and may not be used further. - */ - DNSRecord getTXTRecord() - throws DNSSDException; - - /** Add a record to a registered service.<P> - The name of the record will be the same as the registered service's name.<P> - The record can be updated or deregistered by sending it an update() or remove() message.<P> - - @param flags - Currently unused, reserved for future use. - <P> - @param rrType - The type of the record (e.g. TXT, SRV, etc), as defined in nameser.h. - <P> - @param rData - The raw rdata to be contained in the added resource record. - <P> - @param ttl - The time to live of the resource record, in seconds. - <P> - @return A {@link DNSRecord} that may be passed to updateRecord() or removeRecord(). - If {@link DNSSDRegistration#stop} is called, the DNSRecord is also - invalidated and may not be used further. - */ - DNSRecord addRecord( int flags, int rrType, byte[] rData, int ttl) - throws DNSSDException; -} - diff --git a/usr/src/lib/libdns_sd/java/com/apple/dnssd/DNSSDService.java b/usr/src/lib/libdns_sd/java/com/apple/dnssd/DNSSDService.java deleted file mode 100644 index 10f74021e6..0000000000 --- a/usr/src/lib/libdns_sd/java/com/apple/dnssd/DNSSDService.java +++ /dev/null @@ -1,37 +0,0 @@ -/* -*- Mode: Java; tab-width: 4 -*- - * - * Copyright (c) 2004 Apple Computer, 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - -package com.apple.dnssd; - -/** A tracking object for a service created by {@link DNSSD}. */ - -public interface DNSSDService -{ - /** - Halt the active operation and free resources associated with the DNSSDService.<P> - - Any services or records registered with this DNSSDService will be deregistered. Any - Browse, Resolve, or Query operations associated with this reference will be terminated.<P> - - Note: if the service was initialized with DNSSD.register(), and an extra resource record was - added to the service via {@link DNSSDRegistration#addRecord}, the DNSRecord so created - is invalidated when this method is called - the DNSRecord may not be used afterward. - */ - void stop(); -} - diff --git a/usr/src/lib/libdns_sd/java/com/apple/dnssd/DomainListener.java b/usr/src/lib/libdns_sd/java/com/apple/dnssd/DomainListener.java deleted file mode 100644 index 852f6430e5..0000000000 --- a/usr/src/lib/libdns_sd/java/com/apple/dnssd/DomainListener.java +++ /dev/null @@ -1,60 +0,0 @@ -/* -*- Mode: Java; tab-width: 4 -*- - * - * Copyright (c) 2004 Apple Computer, 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - -package com.apple.dnssd; - - -/** - A listener that receives results from {@link DNSSD#enumerateDomains}. -*/ - -public interface DomainListener extends BaseListener -{ - /** Called to report discovered domains.<P> - - @param domainEnum - The active domain enumerator. - @param flags - Possible values are: DNSSD.MORE_COMING, DNSSD.DEFAULT - <P> - @param ifIndex - Specifies the interface on which the domain exists. (The index for a given - interface is determined via the if_nametoindex() family of calls.) - <P> - @param domain - The name of the domain. - */ - void domainFound( DNSSDService domainEnum, int flags, int ifIndex, String domain); - - /** Called to report that a domain has disappeared.<P> - - @param domainEnum - The active domain enumerator. - @param flags - Possible values are: DNSSD.MORE_COMING, DNSSD.DEFAULT - <P> - @param ifIndex - Specifies the interface on which the domain exists. (The index for a given - interface is determined via the if_nametoindex() family of calls.) - <P> - @param domain - The name of the domain. - */ - void domainLost( DNSSDService domainEnum, int flags, int ifIndex, String domain); -} - diff --git a/usr/src/lib/libdns_sd/java/com/apple/dnssd/Makefile b/usr/src/lib/libdns_sd/java/com/apple/dnssd/Makefile deleted file mode 100644 index 334b97f158..0000000000 --- a/usr/src/lib/libdns_sd/java/com/apple/dnssd/Makefile +++ /dev/null @@ -1,150 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License (the "License"). -# You may not use this file except in compliance with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# Copyright 2007 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# - -include ../Makefile.com - -DNSSD_PKG = com.apple.dnssd - -TOP = $(SRC)/lib/libdns_sd/java -JAVASRCDIR = $(TOP)/com/apple/dnssd -CLASSPATH = $(TOP):com/apple/dnssd - -JAVAFLAGS += -source 1.4 -target 1.4 -SOURCE:sh = ls *.java -CLASSES = $(SOURCE:java=class) -JNIH = DNSSD.java.h -JAR_FILE = dnssd.jar - -DOCDIR = $(JAVASRCDIR)/docs -DOCAPIDIR = $(JAVASRCDIR)/docs/api -DOCDESTDIR = $(ROOTDNSSDJAVAHOME)/javadoc/dnssd -DOCAPIDESTDIR = $(DOCDESTDIR)/api -DOCEXAMPLESDESTDIR = $(DOCDESTDIR)/examples -$(BLD_JAVA_8)XDOCLINT_OPTION = -Xdoclint:none - -EXAMPLESDIR = $(JAVASRCDIR)/docs/examples -EXAMPLESSRC = $(JAVASRCDIR)/docs/examples/src -SIMPLECHATOBJ = $(EXAMPLESDIR)/SwingBrowseListener.class \ - $(EXAMPLESDIR)/SwingQueryListener.class \ - $(EXAMPLESDIR)/SimpleChat.class -BROWSERAPPOBJ = $(EXAMPLESDIR)/SwingResolveListener.class \ - $(EXAMPLESDIR)/SwingDomainListener.class \ - $(EXAMPLESDIR)/BrowserApp.class -EXAMPLEOBJS = $(SIMPLECHATOBJ) $(BROWSERAPPOBJ) -EXAMPLEJARS = SimpleChat.jar BrowserApp.jar - -INSTALL_JAR = $(ROOTDNSSDJAVAHOME)/$(JAR_FILE) -INSTALL_EXAMPLEJARS = $(DOCEXAMPLESDESTDIR)/SimpleChat.jar \ - $(DOCEXAMPLESDESTDIR)/BrowserApp.jar - -CLEAN_FILES = *.class $(JNIH) *.jar $(EXAMPLESDIR)/*.class $(EXAMPLESDIR)/*.jar - -DEFINES= - -INCLUDES= -I${JAVA_HOME}/include \ - -I${JAVA_HOME}/include/solaris - -.KEEP_STATE: - -all: $(JNIH) $(CLASSES) $(EXAMPLEOBJS) doc - -install: $(CLASSES) $(ROOTDNSSDJAVAHOME) \ - $(DOCEXAMPLESDESTDIR) $(DOCEXAMPLESSRCDESTDIR) \ - $(JAR_FILE) $(INSTALL_JAR) $(JNIH) \ - $(EXAMPLEJARS) $(INSTALL_EXAMPLEJARS) \ - install_doc - -$(JNIH): $(CLASSES) - class="com.apple.dnssd.AppleDNSSD \ - com.apple.dnssd.AppleBrowser \ - com.apple.dnssd.AppleResolver \ - com.apple.dnssd.AppleRegistration \ - com.apple.dnssd.AppleQuery \ - com.apple.dnssd.AppleDomainEnum \ - com.apple.dnssd.AppleService"; \ - $(JAVAH) -classpath $(CLASSPATH) -jni -o $(JNIH) $$class - -clean clobber: - $(RM) $(CLEAN_FILES) - -$(JAR_FILE): $(CLASSES) - cd $(TOP); \ - $(JAR) -cvf $(TOP)/com/apple/dnssd/$(JAR_FILE) com/apple/dnssd/*.class - -$(EXAMPLESDIR)/%.class: $(EXAMPLESSRC)/%.java - $(JAVAC) $(JAVAFLAGS) $< -classpath $(CLASSPATH):$(EXAMPLESDIR) -d $(EXAMPLESDIR) - -SIMPLECHATMAN = $(EXAMPLESSRC)/SimpleChat.manifest - -SimpleChat.jar: $(SIMPLECHATOBJ) $(SIMPLECHATMAN) - cd $(EXAMPLESDIR); $(JAR) -cvfm $@ $(SIMPLECHATMAN) \ - SwingBrowseListener.class SwingQueryListener.class \ - SimpleChat.class SimpleChat\$$1.class \ - ListenerThread.class TargetListElem.class \ - TargetListModel.class src/SimpleChat.java \ - src/SimpleChat.manifest src/SwingBrowseListener.java \ - src/SwingQueryListener.java - -BROWSERAPPMAN = $(EXAMPLESSRC)/BrowserApp.manifest - -BrowserApp.jar: $(BROWSERAPPOBJ) $(BROWSERAPPMAN) - cd $(EXAMPLESDIR); $(JAR) -cvfm $@ $(BROWSERAPPMAN) \ - BrowserApp\$$1.class BrowserApp.class \ - BrowserListModel\$$BrowserListElem.class \ - BrowserListModel.class DomainListModel.class \ - ServicesBrowserListModel.class \ - SwingResolveListener.class SwingDomainListener.class \ - src/BrowserApp.java src/SwingResolveListener.java \ - src/SwingDomainListener.java src/BrowserApp.manifest - -$(ROOTDNSSDJAVAHOME): - $(INS.dir) - -$(ROOTDNSSDJAVAHOME)/%: % - $(INS.file) - -$(DOCDESTDIR): - $(INS.dir) - -$(DOCAPIDESTDIR): $(DOCDESTDIR) - $(INS.dir) - -$(DOCEXAMPLESDESTDIR): $(DOCDESTDIR) - $(INS.dir) - -$(DOCEXAMPLESDESTDIR)/%: % - $(RM) $@; $(INS) -s -m $(FILEMODE) -f $(@D) $(EXAMPLESDIR)/$< - -install_doc: $(CLASSES) $(DOCAPIDESTDIR) - -$(RM) -r $(DOCAPIDESTDIR)/* - cd $(TOP); umask 022; \ - $(JAVADOC) $(JAVASRCDIR)/*.java $(XDOCLINT_OPTION) -notimestamp -classpath \ - $(CLASSPATH) -d $(DOCAPIDESTDIR) -public $(DNSSD_PKG) - -doc: - -@mkdir -p $(DOCAPIDIR) - cd $(TOP); umask 022; \ - $(JAVADOC) $(JAVASRCDIR)/*.java $(XDOCLINT_OPTION) -notimestamp -classpath \ - $(CLASSPATH) -d $(DOCAPIDIR) -public $(DNSSD_PKG) diff --git a/usr/src/lib/libdns_sd/java/com/apple/dnssd/QueryListener.java b/usr/src/lib/libdns_sd/java/com/apple/dnssd/QueryListener.java deleted file mode 100644 index 0decb7fc4a..0000000000 --- a/usr/src/lib/libdns_sd/java/com/apple/dnssd/QueryListener.java +++ /dev/null @@ -1,59 +0,0 @@ -/* -*- Mode: Java; tab-width: 4 -*- - * - * Copyright (c) 2004 Apple Computer, 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - -package com.apple.dnssd; - - -/** A listener that receives results from {@link DNSSD#queryRecord}. */ - -public interface QueryListener extends BaseListener -{ - /** Called when a record query has been completed. Inspect flags - parameter to determine nature of query event.<P> - - @param query - The active query object. - <P> - @param flags - If kDNSServiceFlagsAdd bit is set, this is a newly discovered answer; - otherwise this is a previously discovered answer which has expired. - Other possible values are DNSSD.MORE_COMING. - <P> - @param ifIndex - The interface on which the query was resolved. (The index for a given - interface is determined via the if_nametoindex() family of calls.) - <P> - @param fullName - The resource record's full domain name. - <P> - @param rrtype - The resource record's type (e.g. PTR, SRV, etc) as defined by RFC 1035 and its updates. - <P> - @param rrclass - The class of the resource record, as defined by RFC 1035 and its updates. - <P> - @param rdata - The raw rdata of the resource record. - <P> - @param ttl - The resource record's time to live, in seconds. - */ - void queryAnswered( DNSSDService query, int flags, int ifIndex, String fullName, - int rrtype, int rrclass, byte[] rdata, int ttl); -} - diff --git a/usr/src/lib/libdns_sd/java/com/apple/dnssd/RegisterListener.java b/usr/src/lib/libdns_sd/java/com/apple/dnssd/RegisterListener.java deleted file mode 100644 index 00fa1a6344..0000000000 --- a/usr/src/lib/libdns_sd/java/com/apple/dnssd/RegisterListener.java +++ /dev/null @@ -1,49 +0,0 @@ -/* -*- Mode: Java; tab-width: 4 -*- - * - * Copyright (c) 2004 Apple Computer, 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - -package com.apple.dnssd; - - -/** A listener that receives results from {@link DNSSD#register}. */ - -public interface RegisterListener extends BaseListener -{ - /** Called when a registration has been completed.<P> - - @param registration - The active registration. - <P> - @param flags - Currently unused, reserved for future use. - <P> - @param serviceName - The service name registered (if the application did not specify a name in - DNSSD.register(), this indicates what name was automatically chosen). - <P> - @param regType - The type of service registered, as it was passed to DNSSD.register(). - <P> - @param domain - The domain on which the service was registered. If the application did not - specify a domain in DNSSD.register(), this is the default domain - on which the service was registered. - */ - void serviceRegistered( DNSSDRegistration registration, int flags, String serviceName, - String regType, String domain); -} - diff --git a/usr/src/lib/libdns_sd/java/com/apple/dnssd/RegisterRecordListener.java b/usr/src/lib/libdns_sd/java/com/apple/dnssd/RegisterRecordListener.java deleted file mode 100644 index 6fecf8d81e..0000000000 --- a/usr/src/lib/libdns_sd/java/com/apple/dnssd/RegisterRecordListener.java +++ /dev/null @@ -1,37 +0,0 @@ -/* -*- Mode: Java; tab-width: 4 -*- - * - * Copyright (c) 2004 Apple Computer, 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - -package com.apple.dnssd; - - -/** A listener that receives results from {@link DNSSDRecordRegistrar#registerRecord}. */ - -public interface RegisterRecordListener extends BaseListener -{ - /** Called when a record registration succeeds.<P> - - @param record - A {@link DNSRecord}. - <P> - @param flags - Currently ignored, reserved for future use. - <P> - */ - void recordRegistered( DNSRecord record, int flags); -} - diff --git a/usr/src/lib/libdns_sd/java/com/apple/dnssd/ResolveListener.java b/usr/src/lib/libdns_sd/java/com/apple/dnssd/ResolveListener.java deleted file mode 100644 index 33dafa38df..0000000000 --- a/usr/src/lib/libdns_sd/java/com/apple/dnssd/ResolveListener.java +++ /dev/null @@ -1,56 +0,0 @@ -/* -*- Mode: Java; tab-width: 4 -*- - * - * Copyright (c) 2004 Apple Computer, 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - -package com.apple.dnssd; - - -/** A listener that receives results from {@link DNSSD#resolve}. */ - -public interface ResolveListener extends BaseListener -{ - /** Called when a service has been resolved.<P> - - @param resolver - The active resolver object. - <P> - @param flags - Currently unused, reserved for future use. - <P> - @param fullName - The full service domain name, in the form <servicename>.<protocol>.<domain>. - (Any literal dots (".") are escaped with a backslash ("\."), and literal - backslashes are escaped with a second backslash ("\\"), e.g. a web server - named "Dr. Pepper" would have the fullname "Dr\.\032Pepper._http._tcp.local."). - This is the appropriate format to pass to standard system DNS APIs such as - res_query(), or to the special-purpose functions included in this API that - take fullname parameters. - <P> - @param hostName - The target hostname of the machine providing the service. This name can - be passed to functions like queryRecord() to look up the host's IP address. - <P> - @param port - The port number on which connections are accepted for this service. - <P> - @param txtRecord - The service's primary txt record. - */ - void serviceResolved( DNSSDService resolver, int flags, int ifIndex, String fullName, - String hostName, int port, TXTRecord txtRecord); -} - diff --git a/usr/src/lib/libdns_sd/java/com/apple/dnssd/TXTRecord.java b/usr/src/lib/libdns_sd/java/com/apple/dnssd/TXTRecord.java deleted file mode 100644 index 8d9df7a149..0000000000 --- a/usr/src/lib/libdns_sd/java/com/apple/dnssd/TXTRecord.java +++ /dev/null @@ -1,290 +0,0 @@ -/* -*- Mode: Java; tab-width: 4 -*- - * - * Copyright (c) 2004 Apple Computer, 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - - To do: - - implement remove() - - fix set() to replace existing values - */ - - -package com.apple.dnssd; - - -/** - Object used to construct and parse DNS-SD format TXT records. - For more info see <a href="http://files.dns-sd.org/draft-cheshire-dnsext-dns-sd.txt">DNS-Based Service Discovery</a>, section 6. -*/ - -public class TXTRecord -{ - /* - DNS-SD specifies that a TXT record corresponding to an SRV record consist of - a packed array of bytes, each preceded by a length byte. Each string - is an attribute-value pair. - - The TXTRecord object stores the entire TXT data as a single byte array, traversing it - as need be to implement its various methods. - */ - - static final protected byte kAttrSep = '='; - - protected byte[] fBytes; - - /** Constructs a new, empty TXT record. */ - public TXTRecord() - { fBytes = new byte[0]; } - - /** Constructs a new TXT record from a byte array in the standard format. */ - public TXTRecord( byte[] initBytes) - { fBytes = (byte[]) initBytes.clone(); } - - /** Set a key/value pair in the TXT record. Setting an existing key will replace its value.<P> - @param key - The key name. Must be ASCII, with no '=' characters. - <P> - @param value - Value to be encoded into bytes using the default platform character set. - */ - public void set( String key, String value) - { - byte[] valBytes = (value != null) ? value.getBytes() : null; - this.set( key, valBytes); - } - - /** Set a key/value pair in the TXT record. Setting an existing key will replace its value.<P> - @param key - The key name. Must be ASCII, with no '=' characters. - <P> - @param value - Binary representation of the value. - */ - public void set( String key, byte[] value) - { - byte[] keyBytes; - int valLen = (value != null) ? value.length : 0; - - try { - keyBytes = key.getBytes( "US-ASCII"); - } - catch ( java.io.UnsupportedEncodingException uee) { - throw new IllegalArgumentException(); - } - - for ( int i=0; i < keyBytes.length; i++) - if ( keyBytes[i] == '=') - throw new IllegalArgumentException(); - - if ( keyBytes.length + valLen >= 255) - throw new ArrayIndexOutOfBoundsException(); - - int prevLoc = this.remove( key); - if ( prevLoc == -1) - prevLoc = this.size(); - - this.insert( keyBytes, value, prevLoc); - } - - protected void insert( byte[] keyBytes, byte[] value, int index) - // Insert a key-value pair at index - { - byte[] oldBytes = fBytes; - int valLen = (value != null) ? value.length : 0; - int insertion = 0; - int newLen, avLen; - - // locate the insertion point - for ( int i=0; i < index && insertion < fBytes.length; i++) - insertion += (0xFF & (fBytes[ insertion] + 1)); - - avLen = keyBytes.length + valLen + (value != null ? 1 : 0); - newLen = avLen + oldBytes.length + 1; - - fBytes = new byte[ newLen]; - System.arraycopy( oldBytes, 0, fBytes, 0, insertion); - int secondHalfLen = oldBytes.length - insertion; - System.arraycopy( oldBytes, insertion, fBytes, newLen - secondHalfLen, secondHalfLen); - fBytes[ insertion] = ( byte) avLen; - System.arraycopy( keyBytes, 0, fBytes, insertion + 1, keyBytes.length); - if ( value != null) - { - fBytes[ insertion + 1 + keyBytes.length] = kAttrSep; - System.arraycopy( value, 0, fBytes, insertion + keyBytes.length + 2, valLen); - } - } - - /** Remove a key/value pair from the TXT record. Returns index it was at, or -1 if not found. */ - public int remove( String key) - { - int avStart = 0; - - for ( int i=0; avStart < fBytes.length; i++) - { - int avLen = fBytes[ avStart]; - if ( key.length() <= avLen && - ( key.length() == avLen || fBytes[ avStart + key.length() + 1] == kAttrSep)) - { - String s = new String( fBytes, avStart + 1, key.length()); - if ( 0 == key.compareToIgnoreCase( s)) - { - byte[] oldBytes = fBytes; - fBytes = new byte[ oldBytes.length - avLen - 1]; - System.arraycopy( oldBytes, 0, fBytes, 0, avStart); - System.arraycopy( oldBytes, avStart + avLen + 1, fBytes, avStart, oldBytes.length - avStart - avLen - 1); - return i; - } - } - avStart += (0xFF & (avLen + 1)); - } - return -1; - } - - /** Return the number of keys in the TXT record. */ - public int size() - { - int i, avStart; - - for ( i=0, avStart=0; avStart < fBytes.length; i++) - avStart += (0xFF & (fBytes[ avStart] + 1)); - return i; - } - - /** Return true if key is present in the TXT record, false if not. */ - public boolean contains( String key) - { - String s = null; - - for ( int i=0; null != ( s = this.getKey( i)); i++) - if ( 0 == key.compareToIgnoreCase( s)) - return true; - return false; - } - - /** Return a key in the TXT record by zero-based index. Returns null if index exceeds the total number of keys. */ - public String getKey( int index) - { - int avStart = 0; - - for ( int i=0; i < index && avStart < fBytes.length; i++) - avStart += fBytes[ avStart] + 1; - - if ( avStart < fBytes.length) - { - int avLen = fBytes[ avStart]; - int aLen = 0; - - for ( aLen=0; aLen < avLen; aLen++) - if ( fBytes[ avStart + aLen + 1] == kAttrSep) - break; - return new String( fBytes, avStart + 1, aLen); - } - return null; - } - - /** - Look up a key in the TXT record by zero-based index and return its value. <P> - Returns null if index exceeds the total number of keys. - Returns null if the key is present with no value. - */ - public byte[] getValue( int index) - { - int avStart = 0; - byte[] value = null; - - for ( int i=0; i < index && avStart < fBytes.length; i++) - avStart += fBytes[ avStart] + 1; - - if ( avStart < fBytes.length) - { - int avLen = fBytes[ avStart]; - int aLen = 0; - - for ( aLen=0; aLen < avLen; aLen++) - { - if ( fBytes[ avStart + aLen + 1] == kAttrSep) - { - value = new byte[ avLen - aLen - 1]; - System.arraycopy( fBytes, avStart + aLen + 2, value, 0, avLen - aLen - 1); - break; - } - } - } - return value; - } - - /** Converts the result of getValue() to a string in the platform default character set. */ - public String getValueAsString( int index) - { - byte[] value = this.getValue( index); - return value != null ? new String( value) : null; - } - - /** Get the value associated with a key. Will be null if the key is not defined. - Array will have length 0 if the key is defined with an = but no value.<P> - - @param forKey - The left-hand side of the key-value pair. - <P> - @return The binary representation of the value. - */ - public byte[] getValue( String forKey) - { - String s = null; - int i; - - for ( i=0; null != ( s = this.getKey( i)); i++) - if ( 0 == forKey.compareToIgnoreCase( s)) - return this.getValue( i); - return null; - } - - /** Converts the result of getValue() to a string in the platform default character set.<P> - - @param forKey - The left-hand side of the key-value pair. - <P> - @return The value represented in the default platform character set. - */ - public String getValueAsString( String forKey) - { - byte[] val = this.getValue( forKey); - return val != null ? new String( val) : null; - } - - /** Return the contents of the TXT record as raw bytes. */ - public byte[] getRawBytes() { return (byte[]) fBytes.clone(); } - - /** Return a string representation of the object. */ - public String toString() - { - String a, result = null; - - for ( int i=0; null != ( a = this.getKey( i)); i++) - { - String av = String.valueOf( i) + "={" + a; - String val = this.getValueAsString( i); - if ( val != null) - av += "=" + val + "}"; - else - av += "}"; - if ( result == null) - result = av; - else - result = result + ", " + av; - } - return result != null ? result : ""; - } -} - diff --git a/usr/src/lib/libdns_sd/java/com/apple/dnssd/docs/examples/src/BrowserApp.java b/usr/src/lib/libdns_sd/java/com/apple/dnssd/docs/examples/src/BrowserApp.java deleted file mode 100644 index 8f51215165..0000000000 --- a/usr/src/lib/libdns_sd/java/com/apple/dnssd/docs/examples/src/BrowserApp.java +++ /dev/null @@ -1,420 +0,0 @@ -/* -*- Mode: Java; tab-width: 4 -*- - * - * Copyright (c) 2004 Apple Computer, Inc. All rights reserved. - * - * Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, 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, - * please do not use, install, modify or redistribute this Apple software. - * - * In consideration of your agreement to abide by the following terms, and subject - * to these terms, Apple grants you a personal, non-exclusive license, under Apple's - * copyrights in this original Apple software (the "Apple Software"), to use, - * reproduce, modify and redistribute the Apple Software, with or without - * modifications, in source and/or binary forms; provided that if you redistribute - * 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 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 - * may be infringed by your derivative works or by other works in which the Apple - * Software may be incorporated. - * - * The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO - * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED - * WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN - * COMBINATION WITH YOUR PRODUCTS. - * - * IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION - * OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT - * (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - BrowserApp demonstrates how to use DNS-SD to browse for and resolve services. - - To do: - - display resolved TXTRecord - */ - - -import java.awt.*; -import java.awt.event.*; -import java.util.*; -import java.text.*; -import javax.swing.*; -import javax.swing.event.*; - -import com.apple.dnssd.*; - - -class BrowserApp implements ListSelectionListener, ResolveListener, Runnable -{ - static BrowserApp app; - JFrame frame; - DomainListModel domainList; - BrowserListModel servicesList, serviceList; - JList domainPane, servicesPane, servicePane; - DNSSDService servicesBrowser, serviceBrowser, domainBrowser; - JLabel hostLabel, portLabel; - String hostNameForUpdate; - int portForUpdate; - - public BrowserApp() - { - frame = new JFrame("DNS-SD Service Browser"); - frame.addWindowListener(new WindowAdapter() { - public void windowClosing(WindowEvent e) {System.exit(0);} - }); - - domainList = new DomainListModel(); - servicesList = new ServicesBrowserListModel(); - serviceList = new BrowserListModel(); - - try { - domainBrowser = DNSSD.enumerateDomains( DNSSD.BROWSE_DOMAINS, 0, domainList); - - servicesBrowser = DNSSD.browse( 0, 0, "_services._dns-sd._udp.", "", servicesList); - serviceBrowser = null; - } - catch ( Exception ex) { terminateWithException( ex); } - - this.setupSubPanes( frame.getContentPane()); - frame.pack(); - frame.setVisible(true); - } - - protected void setupSubPanes( Container parent) - { - parent.setLayout( new BoxLayout( parent, BoxLayout.Y_AXIS)); - - JPanel browserRow = new JPanel(); - browserRow.setLayout( new BoxLayout( browserRow, BoxLayout.X_AXIS)); - domainPane = new JList( domainList); - domainPane.addListSelectionListener( this); - JScrollPane domainScroller = new JScrollPane( domainPane, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS); - browserRow.add( domainScroller); - servicesPane = new JList( servicesList); - servicesPane.addListSelectionListener( this); - JScrollPane servicesScroller = new JScrollPane( servicesPane, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS); - browserRow.add( servicesScroller); - servicePane = new JList( serviceList); - servicePane.addListSelectionListener( this); - JScrollPane serviceScroller = new JScrollPane( servicePane, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS); - browserRow.add( serviceScroller); - -/* - JPanel buttonRow = new JPanel(); - buttonRow.setLayout( new BoxLayout( buttonRow, BoxLayout.X_AXIS)); - buttonRow.add( Box.createHorizontalGlue()); - JButton connectButton = new JButton( "Don't Connect"); - buttonRow.add( connectButton); - buttonRow.add( Box.createRigidArea( new Dimension( 16, 0))); -*/ - - JPanel labelRow = new JPanel(); - labelRow.setLayout( new BoxLayout( labelRow, BoxLayout.X_AXIS)); - labelRow.add( new JLabel( " Host: ")); - hostLabel = new JLabel(); - labelRow.add( hostLabel); - labelRow.add( Box.createRigidArea( new Dimension( 32, 0))); - labelRow.add( new JLabel( "Port: ")); - portLabel = new JLabel(); - labelRow.add( portLabel); - labelRow.add( Box.createHorizontalGlue()); - - parent.add( browserRow); - parent.add( Box.createRigidArea( new Dimension( 0, 8))); - parent.add( labelRow); -// parent.add( buttonRow); - parent.add( Box.createRigidArea( new Dimension( 0, 16))); - } - - public void valueChanged( ListSelectionEvent e) - { - try { - if ( e.getSource() == domainPane && !e.getValueIsAdjusting()) - { - int newSel = domainPane.getSelectedIndex(); - if ( -1 != newSel) - { - if ( serviceBrowser != null) - serviceBrowser.stop(); - serviceList.removeAllElements(); - servicesBrowser = DNSSD.browse( 0, 0, "_services._dns-sd._udp.", "", servicesList); - } - } - else if ( e.getSource() == servicesPane && !e.getValueIsAdjusting()) - { - int newSel = servicesPane.getSelectedIndex(); - if ( serviceBrowser != null) - serviceBrowser.stop(); - serviceList.removeAllElements(); - if ( -1 != newSel) - serviceBrowser = DNSSD.browse( 0, 0, servicesList.getNthRegType( newSel), "", serviceList); - } - else if ( e.getSource() == servicePane && !e.getValueIsAdjusting()) - { - int newSel = servicePane.getSelectedIndex(); - - hostLabel.setText( ""); - portLabel.setText( ""); - - if ( -1 != newSel) - { - DNSSD.resolve( 0, serviceList.getNthInterface( newSel), - serviceList.getNthServiceName( newSel), - serviceList.getNthRegType( newSel), - serviceList.getNthDomain( newSel), - this); - } - } - } - catch ( Exception ex) { terminateWithException( ex); } - } - - public void run() - { - hostLabel.setText( hostNameForUpdate); - portLabel.setText( String.valueOf( portForUpdate)); - } - - public void serviceResolved( DNSSDService resolver, int flags, int ifIndex, String fullName, - String hostName, int port, TXTRecord txtRecord) - { - // We want to update GUI on the AWT event dispatching thread, but we can't stop - // the resolve from that thread, since stop() is synchronized with this callback. - // So, we stop the resolve on this thread, then invokeAndWait on the AWT event thread. - - resolver.stop(); - - hostNameForUpdate = hostName; - portForUpdate = port; - - try { - SwingUtilities.invokeAndWait(this); - } - catch ( Exception e) - { - e.printStackTrace(); - } - } - - public void operationFailed( DNSSDService service, int errorCode) - { - service.stop(); - // handle failure here - } - - protected static void terminateWithException( Exception e) - { - e.printStackTrace(); - System.exit( -1); - } - - public static void main(String s[]) - { - app = new BrowserApp(); - } -} - - -class BrowserListModel extends DefaultListModel implements BrowseListener, Runnable -{ - public BrowserListModel() - { - addCache = new Vector(); - removeCache = new Vector(); - } - - /* The Browser invokes this callback when a service is discovered. */ - public void serviceFound( DNSSDService browser, int flags, int ifIndex, - String serviceName, String regType, String domain) - { - addCache.add( new BrowserListElem( serviceName, domain, regType, ifIndex)); - if ( ( flags & DNSSD.MORE_COMING) == 0) - this.scheduleOnEventThread(); - } - - public void serviceLost( DNSSDService browser, int flags, int ifIndex, - String serviceName, String regType, String domain) - { - removeCache.add( serviceName); - if ( ( flags & DNSSD.MORE_COMING) == 0) - this.scheduleOnEventThread(); - } - - public void run() - { - while ( removeCache.size() > 0) - { - String serviceName = (String) removeCache.remove( removeCache.size() - 1); - int matchInd = this.findMatching( serviceName); // probably doesn't handle near-duplicates well. - if ( matchInd != -1) - this.removeElementAt( matchInd); - } - while ( addCache.size() > 0) - { - BrowserListElem elem = (BrowserListElem) addCache.remove( addCache.size() - 1); - if ( -1 == this.findMatching( elem.fServiceName)) // probably doesn't handle near-duplicates well. - this.addInSortOrder( elem); - } - } - - public void operationFailed( DNSSDService service, int errorCode) - { - // handle failure here - } - - /* The list contains BrowserListElem's */ - class BrowserListElem - { - public BrowserListElem( String serviceName, String domain, String type, int ifIndex) - { fServiceName = serviceName; fDomain = domain; fType = type; fInt = ifIndex; } - - public String toString() { return fServiceName; } - - public String fServiceName, fDomain, fType; - public int fInt; - } - - public String getNthServiceName( int n) - { - BrowserListElem sel = (BrowserListElem) this.get( n); - return sel.fServiceName; - } - - public String getNthRegType( int n) - { - BrowserListElem sel = (BrowserListElem) this.get( n); - return sel.fType; - } - - public String getNthDomain( int n) - { - BrowserListElem sel = (BrowserListElem) this.get( n); - return sel.fDomain; - } - - public int getNthInterface( int n) - { - BrowserListElem sel = (BrowserListElem) this.get( n); - return sel.fInt; - } - - protected void addInSortOrder( Object obj) - { - int i; - for ( i = 0; i < this.size(); i++) - if ( sCollator.compare( obj.toString(), this.getElementAt( i).toString()) < 0) - break; - this.add( i, obj); - } - - protected int findMatching( String match) - { - for ( int i = 0; i < this.size(); i++) - if ( match.equals( this.getElementAt( i).toString())) - return i; - return -1; - } - - protected void scheduleOnEventThread() - { - try { - SwingUtilities.invokeAndWait( this); - } - catch ( Exception e) - { - e.printStackTrace(); - } - } - - protected Vector removeCache; // list of serviceNames to remove - protected Vector addCache; // list of BrowserListElem's to add - - protected static Collator sCollator; - - static // Initialize our static variables - { - sCollator = Collator.getInstance(); - sCollator.setStrength( Collator.PRIMARY); - } -} - - -class ServicesBrowserListModel extends BrowserListModel -{ - /* The Browser invokes this callback when a service is discovered. */ - public void serviceFound( DNSSDService browser, int flags, int ifIndex, - String serviceName, String regType, String domain) - // Overridden to stuff serviceName into regType and make serviceName human-readable. - { - regType = serviceName + ( regType.startsWith( "_udp.") ? "._udp." : "._tcp."); - super.serviceFound( browser, flags, ifIndex, this.mapTypeToName( serviceName), regType, domain); - } - - public void serviceLost( DNSSDService browser, int flags, int ifIndex, - String serviceName, String regType, String domain) - // Overridden to make serviceName human-readable. - { - super.serviceLost( browser, flags, ifIndex, this.mapTypeToName( serviceName), regType, domain); - } - - protected String mapTypeToName( String type) - // Convert a registration type into a human-readable string. Returns original string on no-match. - { - final String[] namedServices = { - "_afpovertcp", "Apple File Sharing", - "_http", "World Wide Web servers", - "_daap", "Digital Audio Access", - "_apple-sasl", "Apple Password Servers", - "_distcc", "Distributed Compiler nodes", - "_finger", "Finger servers", - "_ichat", "iChat clients", - "_presence", "iChat AV clients", - "_ssh", "SSH servers", - "_telnet", "Telnet servers", - "_workstation", "Macintosh Manager clients", - "_bootps", "BootP servers", - "_xserveraid", "XServe RAID devices", - "_eppc", "Remote AppleEvents", - "_ftp", "FTP services", - "_tftp", "TFTP services" - }; - - for ( int i = 0; i < namedServices.length; i+=2) - if ( namedServices[i].equals( type)) - return namedServices[i + 1]; - return type; - } -} - - -class DomainListModel extends DefaultListModel implements DomainListener -{ - /* Called when a domain is discovered. */ - public void domainFound( DNSSDService domainEnum, int flags, int ifIndex, String domain) - { - if ( !this.contains( domain)) - this.addElement( domain); - } - - public void domainLost( DNSSDService domainEnum, int flags, int ifIndex, String domain) - { - if ( this.contains( domain)) - this.removeElement( domain); - } - - public void operationFailed( DNSSDService service, int errorCode) - { - // handle failure here - } -} - diff --git a/usr/src/lib/libdns_sd/java/com/apple/dnssd/docs/examples/src/BrowserApp.manifest b/usr/src/lib/libdns_sd/java/com/apple/dnssd/docs/examples/src/BrowserApp.manifest deleted file mode 100644 index 7c392a1908..0000000000 --- a/usr/src/lib/libdns_sd/java/com/apple/dnssd/docs/examples/src/BrowserApp.manifest +++ /dev/null @@ -1,2 +0,0 @@ -Manifest-Version: 1.0 -Main-Class: BrowserApp diff --git a/usr/src/lib/libdns_sd/java/com/apple/dnssd/docs/examples/src/SimpleChat.java b/usr/src/lib/libdns_sd/java/com/apple/dnssd/docs/examples/src/SimpleChat.java deleted file mode 100644 index a1fee5c018..0000000000 --- a/usr/src/lib/libdns_sd/java/com/apple/dnssd/docs/examples/src/SimpleChat.java +++ /dev/null @@ -1,333 +0,0 @@ -/* -*- Mode: Java; tab-width: 4 -*- - * - * Copyright (c) 2004 Apple Computer, Inc. All rights reserved. - * - * Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, 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, - * please do not use, install, modify or redistribute this Apple software. - * - * In consideration of your agreement to abide by the following terms, and subject - * to these terms, Apple grants you a personal, non-exclusive license, under Apple's - * copyrights in this original Apple software (the "Apple Software"), to use, - * reproduce, modify and redistribute the Apple Software, with or without - * modifications, in source and/or binary forms; provided that if you redistribute - * 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 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 - * may be infringed by your derivative works or by other works in which the Apple - * Software may be incorporated. - * - * The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO - * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED - * WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN - * COMBINATION WITH YOUR PRODUCTS. - * - * IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION - * OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT - * (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - SimpleChat is a simple peer-to-peer chat program that demonstrates - DNS-SD registration, browsing, resolving and record-querying. - - To do: - - implement better coloring algorithm - */ - - -import java.awt.*; -import java.awt.event.*; -import java.text.*; -import java.net.*; -import javax.swing.*; -import javax.swing.event.*; -import javax.swing.text.*; - -import com.apple.dnssd.*; - - -class SimpleChat implements ResolveListener, RegisterListener, QueryListener, - ActionListener, ItemListener, Runnable -{ - Document textDoc; // Holds all the chat text - JTextField inputField; // Holds a pending chat response - String ourName; // name used to identify this user in chat - DNSSDService browser; // object that actively browses for other chat clients - DNSSDService resolver; // object that resolves other chat clients - DNSSDRegistration registration; // object that maintains our connection advertisement - JComboBox targetPicker; // Indicates who we're talking to - TargetListModel targetList; // and its list model - JButton sendButton; // Will send text in inputField to target - InetAddress buddyAddr; // and address - int buddyPort; // and port - DatagramPacket dataPacket; // Inbound data packet - DatagramSocket outSocket; // Outbound data socket - SimpleAttributeSet textAttribs; - - static final String kChatExampleRegType = "_p2pchat._udp"; - static final String kWireCharSet = "ISO-8859-1"; - - public SimpleChat() throws Exception - { - JFrame frame = new JFrame("SimpleChat"); - frame.addWindowListener(new WindowAdapter() { - public void windowClosing(WindowEvent e) {System.exit(0);} - }); - - ourName = System.getProperty( "user.name"); - targetList = new TargetListModel(); - textAttribs = new SimpleAttributeSet(); - DatagramSocket inSocket = new DatagramSocket(); - dataPacket = new DatagramPacket( new byte[ 4096], 4096); - outSocket = new DatagramSocket(); - - this.setupSubPanes( frame.getContentPane(), frame.getRootPane()); - frame.pack(); - frame.setVisible(true); - inputField.requestFocusInWindow(); - - browser = DNSSD.browse( 0, 0, kChatExampleRegType, "", new SwingBrowseListener( targetList)); - - registration = DNSSD.register( 0, 0, ourName, kChatExampleRegType, "", "", inSocket.getLocalPort(), null, this); - - new ListenerThread( this, inSocket, dataPacket).start(); - } - - protected void setupSubPanes( Container parent, JRootPane rootPane) - { - parent.setLayout( new BoxLayout( parent, BoxLayout.Y_AXIS)); - - JPanel textRow = new JPanel(); - textRow.setLayout( new BoxLayout( textRow, BoxLayout.X_AXIS)); - textRow.add( Box.createRigidArea( new Dimension( 16, 0))); - JEditorPane textPane = new JEditorPane( "text/html", "<BR>"); - textPane.setPreferredSize( new Dimension( 400, 300)); - textPane.setEditable( false); - JScrollPane textScroller = new JScrollPane( textPane); - textRow.add( textScroller); - textRow.add( Box.createRigidArea( new Dimension( 16, 0))); - textDoc = textPane.getDocument(); - - JPanel addressRow = new JPanel(); - addressRow.setLayout( new BoxLayout( addressRow, BoxLayout.X_AXIS)); - targetPicker = new JComboBox( targetList); - targetPicker.addItemListener( this); - addressRow.add( Box.createRigidArea( new Dimension( 16, 0))); - addressRow.add( new JLabel( "Talk to: ")); - addressRow.add( targetPicker); - addressRow.add( Box.createHorizontalGlue()); - - JPanel buttonRow = new JPanel(); - buttonRow.setLayout( new BoxLayout( buttonRow, BoxLayout.X_AXIS)); - buttonRow.add( Box.createRigidArea( new Dimension( 16, 0))); - inputField = new JTextField(); - // prevent inputField from hijacking <Enter> key - inputField.getKeymap().removeKeyStrokeBinding( KeyStroke.getKeyStroke( KeyEvent.VK_ENTER, 0)); - buttonRow.add( inputField); - sendButton = new JButton( "Send"); - buttonRow.add( Box.createRigidArea( new Dimension( 8, 0))); - buttonRow.add( sendButton); - buttonRow.add( Box.createRigidArea( new Dimension( 16, 0))); - rootPane.setDefaultButton( sendButton); - sendButton.addActionListener( this); - sendButton.setEnabled( false); - - parent.add( Box.createRigidArea( new Dimension( 0, 16))); - parent.add( textRow); - parent.add( Box.createRigidArea( new Dimension( 0, 8))); - parent.add( addressRow); - parent.add( Box.createRigidArea( new Dimension( 0, 8))); - parent.add( buttonRow); - parent.add( Box.createRigidArea( new Dimension( 0, 16))); - } - - public void serviceRegistered( DNSSDRegistration registration, int flags, - String serviceName, String regType, String domain) - { - ourName = serviceName; // might have been renamed on collision - } - - public void operationFailed( DNSSDService service, int errorCode) - { - System.out.println( "Service reported error " + String.valueOf( errorCode)); - } - - public void serviceResolved( DNSSDService resolver, int flags, int ifIndex, String fullName, - String hostName, int port, TXTRecord txtRecord) - { - buddyPort = port; - try { - // Start a record query to obtain IP address from hostname - DNSSD.queryRecord( 0, ifIndex, hostName, 1 /* ns_t_a */, 1 /* ns_c_in */, - new SwingQueryListener( this)); - } - catch ( Exception e) { terminateWithException( e); } - resolver.stop(); - } - - public void queryAnswered( DNSSDService query, int flags, int ifIndex, String fullName, - int rrtype, int rrclass, byte[] rdata, int ttl) - { - try { - buddyAddr = InetAddress.getByAddress( rdata); - } - catch ( Exception e) { terminateWithException( e); } - sendButton.setEnabled( true); - } - - public void actionPerformed( ActionEvent e) // invoked when Send button is hit - { - try - { - String sendString = ourName + ": " + inputField.getText(); - byte[] sendData = sendString.getBytes( kWireCharSet); - outSocket.send( new DatagramPacket( sendData, sendData.length, buddyAddr, buddyPort)); - StyleConstants.setForeground( textAttribs, Color.black); - textDoc.insertString( textDoc.getLength(), inputField.getText() + "\n", textAttribs); - inputField.setText( ""); - } - catch ( Exception exception) { terminateWithException( exception); } - } - - public void itemStateChanged( ItemEvent e) // invoked when Target selection changes - { - sendButton.setEnabled( false); - if ( e.getStateChange() == ItemEvent.SELECTED) - { - try { - TargetListElem sel = (TargetListElem) targetList.getSelectedItem(); - resolver = DNSSD.resolve( 0, sel.fInt, sel.fServiceName, sel.fType, sel.fDomain, this); - } - catch ( Exception exception) { terminateWithException( exception); } - } - } - - public void run() // invoked on event thread when inbound packet arrives - { - try - { - String inMessage = new String( dataPacket.getData(), 0, dataPacket.getLength(), kWireCharSet); - StyleConstants.setForeground( textAttribs, this.getColorFor( dataPacket.getData(), dataPacket.getLength())); - textDoc.insertString( textDoc.getLength(), inMessage + "\n", textAttribs); - } - catch ( Exception e) { terminateWithException( e); } - } - - protected Color getColorFor( byte[] chars, int length) - // Produce a mapping from a string to a color, suitable for text display - { - int rgb = 0; - for ( int i=0; i < length && chars[i] != ':'; i++) - rgb = rgb ^ ( (int) chars[i] << (i%3+2) * 8); - return new Color( rgb & 0x007F7FFF); // mask off high bits so it is a dark color - -// for ( int i=0; i < length && chars[i] != ':'; i++) - - } - - protected static void terminateWithException( Exception e) - { - e.printStackTrace(); - System.exit( -1); - } - - public static void main(String s[]) - { - try { - new SimpleChat(); - } - catch ( Exception e) { terminateWithException( e); } - } -} - - - -class TargetListElem -{ - public TargetListElem( String serviceName, String domain, String type, int ifIndex) - { fServiceName = serviceName; fDomain = domain; fType = type; fInt = ifIndex; } - - public String toString() { return fServiceName; } - - public String fServiceName, fDomain, fType; - public int fInt; -} - -class TargetListModel extends DefaultComboBoxModel implements BrowseListener -{ - /* The Browser invokes this callback when a service is discovered. */ - public void serviceFound( DNSSDService browser, int flags, int ifIndex, - String serviceName, String regType, String domain) - { - TargetListElem match = this.findMatching( serviceName); // probably doesn't handle near-duplicates well. - - if ( match == null) - this.addElement( new TargetListElem( serviceName, domain, regType, ifIndex)); - } - - /* The Browser invokes this callback when a service disappears. */ - public void serviceLost( DNSSDService browser, int flags, int ifIndex, - String serviceName, String regType, String domain) - { - TargetListElem match = this.findMatching( serviceName); // probably doesn't handle near-duplicates well. - - if ( match != null) - this.removeElement( match); - } - - /* The Browser invokes this callback when a service disappears. */ - public void operationFailed( DNSSDService service, int errorCode) - { - System.out.println( "Service reported error " + String.valueOf( errorCode)); - } - - protected TargetListElem findMatching( String match) - { - for ( int i = 0; i < this.getSize(); i++) - if ( match.equals( this.getElementAt( i).toString())) - return (TargetListElem) this.getElementAt( i); - return null; - } - -} - - -// A ListenerThread runs its owner when datagram packet p appears on socket s. -class ListenerThread extends Thread -{ - public ListenerThread( Runnable owner, DatagramSocket s, DatagramPacket p) - { fOwner = owner; fSocket = s; fPacket = p; } - - public void run() - { - while ( true ) - { - try - { - fSocket.receive( fPacket); - SwingUtilities.invokeAndWait( fOwner); // process data on main thread - } - catch( Exception e) - { - break; // terminate thread - } - } - } - - protected Runnable fOwner; - protected DatagramSocket fSocket; - protected DatagramPacket fPacket; -} - - - diff --git a/usr/src/lib/libdns_sd/java/com/apple/dnssd/docs/examples/src/SimpleChat.manifest b/usr/src/lib/libdns_sd/java/com/apple/dnssd/docs/examples/src/SimpleChat.manifest deleted file mode 100644 index 45c02025c2..0000000000 --- a/usr/src/lib/libdns_sd/java/com/apple/dnssd/docs/examples/src/SimpleChat.manifest +++ /dev/null @@ -1,2 +0,0 @@ -Manifest-Version: 1.0 -Main-Class: SimpleChat diff --git a/usr/src/lib/libdns_sd/java/com/apple/dnssd/docs/examples/src/SwingBrowseListener.java b/usr/src/lib/libdns_sd/java/com/apple/dnssd/docs/examples/src/SwingBrowseListener.java deleted file mode 100644 index db971b2b43..0000000000 --- a/usr/src/lib/libdns_sd/java/com/apple/dnssd/docs/examples/src/SwingBrowseListener.java +++ /dev/null @@ -1,124 +0,0 @@ -/* -*- Mode: Java; tab-width: 4 -*- - * - * Copyright (c) 2004 Apple Computer, Inc. All rights reserved. - * - * Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, 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, - * please do not use, install, modify or redistribute this Apple software. - * - * In consideration of your agreement to abide by the following terms, and subject - * to these terms, Apple grants you a personal, non-exclusive license, under Apple's - * copyrights in this original Apple software (the "Apple Software"), to use, - * reproduce, modify and redistribute the Apple Software, with or without - * modifications, in source and/or binary forms; provided that if you redistribute - * 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 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 - * may be infringed by your derivative works or by other works in which the Apple - * Software may be incorporated. - * - * The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO - * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED - * WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN - * COMBINATION WITH YOUR PRODUCTS. - * - * IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION - * OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT - * (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - - -import javax.swing.*; -import com.apple.dnssd.*; - - -/** Use this to schedule BrowseListener callbacks via SwingUtilities.invokeAndWait(). */ - -public class SwingBrowseListener implements Runnable, BrowseListener -{ - /** Create a listener for DNSSD that will call your listener on the Swing/AWT event thread. */ - public SwingBrowseListener( BrowseListener listener) - { fListener = listener; fErrorCode = 0; } - - /** (Clients should not call this method directly.) */ - public void operationFailed( DNSSDService service, int errorCode) - { - fBrowser = service; - fErrorCode = errorCode; - this.schedule(); - } - - /** (Clients should not call this method directly.) */ - public void serviceFound( DNSSDService browser, int flags, int ifIndex, - String serviceName, String regType, String domain) - - { - fBrowser = browser; - fIsAdd = true; - fFlags = flags; - fIndex = ifIndex; - fService = serviceName; - fRegType = regType; - fDomain = domain; - this.schedule(); - } - - /** (Clients should not call this method directly.) */ - public void serviceLost( DNSSDService browser, int flags, int ifIndex, - String serviceName, String regType, String domain) - { - fBrowser = browser; - fIsAdd = false; - fFlags = flags; - fIndex = ifIndex; - fService = serviceName; - fRegType = regType; - fDomain = domain; - this.schedule(); - } - - /** (Clients should not call this method directly.) */ - public void run() - { - if ( fErrorCode != 0) - fListener.operationFailed( fBrowser, fErrorCode); - else if ( fIsAdd) - fListener.serviceFound( fBrowser, fFlags, fIndex, fService, fRegType, fDomain); - else - fListener.serviceLost( fBrowser, fFlags, fIndex, fService, fRegType, fDomain); - } - - protected void schedule() - { - try { - SwingUtilities.invokeAndWait( this); - } - catch ( Exception e) - { - e.printStackTrace(); - } - } - - protected BrowseListener fListener; - - protected boolean fIsAdd; - protected DNSSDService fBrowser; - protected int fFlags; - protected int fIndex; - protected int fErrorCode; - protected String fService; - protected String fRegType; - protected String fDomain; -} - diff --git a/usr/src/lib/libdns_sd/java/com/apple/dnssd/docs/examples/src/SwingDomainListener.java b/usr/src/lib/libdns_sd/java/com/apple/dnssd/docs/examples/src/SwingDomainListener.java deleted file mode 100644 index b67313b7bc..0000000000 --- a/usr/src/lib/libdns_sd/java/com/apple/dnssd/docs/examples/src/SwingDomainListener.java +++ /dev/null @@ -1,116 +0,0 @@ -/* -*- Mode: Java; tab-width: 4 -*- - * - * Copyright (c) 2004 Apple Computer, Inc. All rights reserved. - * - * Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, 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, - * please do not use, install, modify or redistribute this Apple software. - * - * In consideration of your agreement to abide by the following terms, and subject - * to these terms, Apple grants you a personal, non-exclusive license, under Apple's - * copyrights in this original Apple software (the "Apple Software"), to use, - * reproduce, modify and redistribute the Apple Software, with or without - * modifications, in source and/or binary forms; provided that if you redistribute - * 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 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 - * may be infringed by your derivative works or by other works in which the Apple - * Software may be incorporated. - * - * The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO - * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED - * WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN - * COMBINATION WITH YOUR PRODUCTS. - * - * IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION - * OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT - * (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - - -import javax.swing.*; -import com.apple.dnssd.*; - - -/** Use this to schedule DomainListener callbacks via SwingUtilities.invokeAndWait(). */ - -public class SwingDomainListener implements Runnable, DomainListener -{ - /** Create a listener for DNSSD that will call your listener on the Swing/AWT event thread. */ - public SwingDomainListener( DomainListener listener) - { fListener = listener; fErrorCode = 0; } - - /** (Clients should not call this method directly.) */ - public void operationFailed( DNSSDService service, int errorCode) - { - fEnumerator = service; - fErrorCode = errorCode; - this.schedule(); - } - - /** (Clients should not call this method directly.) */ - public void domainFound( DNSSDService domainEnum, int flags, int ifIndex, String domain) - - { - fEnumerator = domainEnum; - fIsAdd = true; - fFlags = flags; - fIndex = ifIndex; - fDomain = domain; - this.schedule(); - } - - /** (Clients should not call this method directly.) */ - public void domainLost( DNSSDService domainEnum, int flags, int ifIndex, String domain) - { - fEnumerator = domainEnum; - fIsAdd = false; - fFlags = flags; - fIndex = ifIndex; - fDomain = domain; - this.schedule(); - } - - /** (Clients should not call this method directly.) */ - public void run() - { - if ( fErrorCode != 0) - fListener.operationFailed( fEnumerator, fErrorCode); - else if ( fIsAdd) - fListener.domainFound( fEnumerator, fFlags, fIndex, fDomain); - else - fListener.domainLost( fEnumerator, fFlags, fIndex, fDomain); - } - - protected void schedule() - { - try { - SwingUtilities.invokeAndWait( this); - } - catch ( Exception e) - { - e.printStackTrace(); - } - } - - protected DomainListener fListener; - - protected boolean fIsAdd; - protected DNSSDService fEnumerator; - protected int fFlags; - protected int fIndex; - protected int fErrorCode; - protected String fDomain; -} - diff --git a/usr/src/lib/libdns_sd/java/com/apple/dnssd/docs/examples/src/SwingQueryListener.java b/usr/src/lib/libdns_sd/java/com/apple/dnssd/docs/examples/src/SwingQueryListener.java deleted file mode 100644 index fcac75b832..0000000000 --- a/usr/src/lib/libdns_sd/java/com/apple/dnssd/docs/examples/src/SwingQueryListener.java +++ /dev/null @@ -1,108 +0,0 @@ -/* -*- Mode: Java; tab-width: 4 -*- - * - * Copyright (c) 2004 Apple Computer, Inc. All rights reserved. - * - * Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, 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, - * please do not use, install, modify or redistribute this Apple software. - * - * In consideration of your agreement to abide by the following terms, and subject - * to these terms, Apple grants you a personal, non-exclusive license, under Apple's - * copyrights in this original Apple software (the "Apple Software"), to use, - * reproduce, modify and redistribute the Apple Software, with or without - * modifications, in source and/or binary forms; provided that if you redistribute - * 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 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 - * may be infringed by your derivative works or by other works in which the Apple - * Software may be incorporated. - * - * The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO - * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED - * WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN - * COMBINATION WITH YOUR PRODUCTS. - * - * IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION - * OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT - * (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - - -import javax.swing.*; -import com.apple.dnssd.*; - - -/** Use this to schedule QueryListener callbacks via SwingUtilities.invokeAndWait(). */ - -public class SwingQueryListener implements Runnable, QueryListener -{ - /** Create a listener for DNSSD that will call your listener on the Swing/AWT event thread. */ - public SwingQueryListener( QueryListener listener) - { fListener = listener; } - - public void operationFailed( DNSSDService service, int errorCode) - { - fQuery = service; - fErrorCode = errorCode; - this.schedule(); - } - - /** (Clients should not call this method directly.) */ - public void queryAnswered( DNSSDService query, int flags, int ifIndex, String fullName, - int rrtype, int rrclass, byte[] rdata, int ttl) - { - fQuery = query; - fFlags = flags; - fIndex = ifIndex; - fFullName = fullName; - fType = rrtype; - fClass = rrclass; - fData = rdata; - fTTL = ttl; - this.schedule(); - } - - /** (Clients should not call this method directly.) */ - public void run() - { - if ( fErrorCode != 0) - fListener.operationFailed( fQuery, fErrorCode); - else - fListener.queryAnswered( fQuery, fFlags, fIndex, fFullName, fType, fClass, fData, fTTL); - } - - protected void schedule() - { - try { - SwingUtilities.invokeAndWait( this); - } - catch ( Exception e) - { - e.printStackTrace(); - } - } - - protected QueryListener fListener; - - protected DNSSDService fQuery; - protected int fFlags; - protected int fIndex; - protected int fErrorCode; - protected String fFullName; - protected int fType; - protected int fClass; - protected byte[] fData; - protected int fTTL; -} - diff --git a/usr/src/lib/libdns_sd/java/com/apple/dnssd/docs/examples/src/SwingResolveListener.java b/usr/src/lib/libdns_sd/java/com/apple/dnssd/docs/examples/src/SwingResolveListener.java deleted file mode 100644 index 499da0707d..0000000000 --- a/usr/src/lib/libdns_sd/java/com/apple/dnssd/docs/examples/src/SwingResolveListener.java +++ /dev/null @@ -1,109 +0,0 @@ -/* -*- Mode: Java; tab-width: 4 -*- - * - * Copyright (c) 2004 Apple Computer, Inc. All rights reserved. - * - * Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, 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, - * please do not use, install, modify or redistribute this Apple software. - * - * In consideration of your agreement to abide by the following terms, and subject - * to these terms, Apple grants you a personal, non-exclusive license, under Apple's - * copyrights in this original Apple software (the "Apple Software"), to use, - * reproduce, modify and redistribute the Apple Software, with or without - * modifications, in source and/or binary forms; provided that if you redistribute - * 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 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 - * may be infringed by your derivative works or by other works in which the Apple - * Software may be incorporated. - * - * The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO - * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED - * WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN - * COMBINATION WITH YOUR PRODUCTS. - * - * IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION - * OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT - * (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -ident "%Z%%M% %I% %E% SMI" - - */ - - -import javax.swing.*; -import com.apple.dnssd.*; - - -/** Use this to schedule ResolveListener callbacks via SwingUtilities.invokeAndWait(). */ - -public class SwingResolveListener implements Runnable, ResolveListener -{ - /** Create a listener for DNSSD that will call your listener on the Swing/AWT event thread. */ - public SwingResolveListener( ResolveListener listener) - { fListener = listener; } - - public void operationFailed( DNSSDService service, int errorCode) - { - fResolver = service; - fErrorCode = errorCode; - this.schedule(); - } - - /** (Clients should not call this method directly.) */ - public void serviceResolved( DNSSDService resolver, int flags, int ifIndex, String fullName, - String hostName, int port, TXTRecord txtRecord) - { - fResolver = resolver; - fFlags = flags; - fIndex = ifIndex; - fFullName = fullName; - fHostName = hostName; - fPort = port; - fTXTRecord = txtRecord; - this.schedule(); - } - - /** (Clients should not call this method directly.) */ - public void run() - { - if ( fErrorCode != 0) - fListener.operationFailed( fResolver, fErrorCode); - else - fListener.serviceResolved( fResolver, fFlags, fIndex, fFullName, fHostName, fPort, fTXTRecord); - } - - protected void schedule() - { - try { - SwingUtilities.invokeAndWait( this); - } - catch ( Exception e) - { - e.printStackTrace(); - } - } - - protected ResolveListener fListener; - - protected DNSSDService fResolver; - protected int fFlags; - protected int fIndex; - protected int fErrorCode; - protected String fFullName; - protected String fHostName; - protected int fPort; - protected TXTRecord fTXTRecord; -} - diff --git a/usr/src/lib/libdns_sd/java/common/JNISupport.c b/usr/src/lib/libdns_sd/java/common/JNISupport.c deleted file mode 100644 index af4de19912..0000000000 --- a/usr/src/lib/libdns_sd/java/common/JNISupport.c +++ /dev/null @@ -1,1076 +0,0 @@ -/* -*- Mode: C; tab-width: 4 -*- - * - * Copyright (c) 2004 Apple Computer, 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - - This file contains the platform support for DNSSD and related Java classes. - It is used to shim through to the underlying <dns_sd.h> API. - */ - -// AUTO_CALLBACKS should be set to 1 if the underlying mDNS implementation fires response -// callbacks automatically (as in the early Windows prototypes). -// AUTO_CALLBACKS should be set to 0 if the client must call DNSServiceProcessResult() to -// invoke response callbacks (as is true on Mac OS X, Posix, Windows, etc.). -// (Invoking callbacks automatically on a different thread sounds attractive, but while -// the client gains by not needing to add an event source to its main event loop, it loses -// by being forced to deal with concurrency and locking, which can be a bigger burden.) -#ifndef AUTO_CALLBACKS -#define AUTO_CALLBACKS 0 -#endif - -#if !AUTO_CALLBACKS -#ifdef _WIN32 -#include <winsock2.h> -#else //_WIN32 -#include <sys/types.h> -#include <sys/select.h> -#endif // _WIN32 -#endif // AUTO_CALLBACKS - -#include <dns_sd.h> - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#ifdef _WIN32 -#include <winsock2.h> -#include <iphlpapi.h> -static char * win32_if_indextoname( DWORD ifIndex, char * nameBuff); -static DWORD win32_if_nametoindex( const char * nameStr ); -#define if_indextoname win32_if_indextoname -#define if_nametoindex win32_if_nametoindex -#define IF_NAMESIZE MAX_ADAPTER_NAME_LENGTH -#else // _WIN32 -#include <sys/socket.h> -#include <net/if.h> -#endif // _WIN32 - -// When compiling with "-Wshadow" set, including jni.h produces the following error: -// /System/Library/Frameworks/JavaVM.framework/Versions/A/Headers/jni.h:609: warning: declaration of 'index' shadows a global declaration -// To work around this, we use the preprocessor to map the identifier 'index', which appears harmlessly in function prototype declarations, -// to something 'jni_index', which doesn't conflict -#define index jni_index -#include "DNSSD.java.h" -#undef index - -//#include <syslog.h> - -// convenience definition -#ifdef __GNUC__ -#define _UNUSED __attribute__ ((unused)) -#else -#define _UNUSED -#endif - -enum { - kInterfaceVersionOne = 1, - kInterfaceVersionCurrent // Must match version in .jar file -}; - -typedef struct OpContext OpContext; - -struct OpContext -{ - DNSServiceRef ServiceRef; - JNIEnv *Env; - jobject JavaObj; - jobject ClientObj; - jmethodID Callback; - jmethodID Callback2; -}; - -// For AUTO_CALLBACKS, we must attach the callback thread to the Java VM prior to upcall. -#if AUTO_CALLBACKS -JavaVM *gJavaVM = NULL; -#endif - - -JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleDNSSD_InitLibrary( JNIEnv *pEnv, jclass cls, - jint callerVersion) -{ - /* Ensure that caller & interface versions match. */ - if ( callerVersion != kInterfaceVersionCurrent) - return kDNSServiceErr_Incompatible; - -#if AUTO_CALLBACKS - { - jsize numVMs; - - if ( 0 != JNI_GetCreatedJavaVMs( &gJavaVM, 1, &numVMs)) - return kDNSServiceErr_BadState; - } -#endif - - // Set AppleDNSSD.hasAutoCallbacks - { -#if AUTO_CALLBACKS - jboolean hasAutoC = JNI_TRUE; -#else - jboolean hasAutoC = JNI_FALSE; -#endif - jfieldID hasAutoCField = (*pEnv)->GetStaticFieldID( pEnv, cls, "hasAutoCallbacks", "Z"); - (*pEnv)->SetStaticBooleanField( pEnv, cls, hasAutoCField, hasAutoC); - } - - return kDNSServiceErr_NoError; -} - - -static const char* SafeGetUTFChars( JNIEnv *pEnv, jstring str) -// Wrapper for JNI GetStringUTFChars() that returns NULL for null str. -{ - return str != NULL ? (*pEnv)->GetStringUTFChars( pEnv, str, 0) : NULL; -} - -static void SafeReleaseUTFChars( JNIEnv *pEnv, jstring str, const char *buff) -// Wrapper for JNI GetStringUTFChars() that handles null str. -{ - if ( str != NULL) - (*pEnv)->ReleaseStringUTFChars( pEnv, str, buff); -} - - -#if AUTO_CALLBACKS -static void SetupCallbackState( JNIEnv **ppEnv) -{ - (*gJavaVM)->AttachCurrentThread( gJavaVM, (void**) ppEnv, NULL); -} - -static void TeardownCallbackState( void ) -{ - (*gJavaVM)->DetachCurrentThread( gJavaVM); -} - -#else // AUTO_CALLBACKS - -static void SetupCallbackState( JNIEnv **ppEnv _UNUSED) -{ - // No setup necessary if ProcessResults() has been called -} - -static void TeardownCallbackState( void ) -{ - // No teardown necessary if ProcessResults() has been called -} -#endif // AUTO_CALLBACKS - - -static OpContext *NewContext( JNIEnv *pEnv, jobject owner, - const char *callbackName, const char *callbackSig) -// Create and initialize a new OpContext. -{ - OpContext *pContext = (OpContext*) malloc( sizeof *pContext); - - if ( pContext != NULL) - { - jfieldID clientField = (*pEnv)->GetFieldID( pEnv, (*pEnv)->GetObjectClass( pEnv, owner), - "fListener", "Lcom/apple/dnssd/BaseListener;"); - - pContext->JavaObj = (*pEnv)->NewWeakGlobalRef( pEnv, owner); // must convert local ref to global to cache; - pContext->ClientObj = (*pEnv)->GetObjectField( pEnv, owner, clientField); - pContext->ClientObj = (*pEnv)->NewWeakGlobalRef( pEnv, pContext->ClientObj); // must convert local ref to global to cache - pContext->Callback = (*pEnv)->GetMethodID( pEnv, - (*pEnv)->GetObjectClass( pEnv, pContext->ClientObj), - callbackName, callbackSig); - pContext->Callback2 = NULL; // not always used - } - - return pContext; -} - - -static void ReportError( JNIEnv *pEnv, jobject target, jobject service, DNSServiceErrorType err) -// Invoke operationFailed() method on target with err. -{ - jclass cls = (*pEnv)->GetObjectClass( pEnv, target); - jmethodID opFailed = (*pEnv)->GetMethodID( pEnv, cls, "operationFailed", - "(Lcom/apple/dnssd/DNSSDService;I)V"); - - (*pEnv)->CallVoidMethod( pEnv, target, opFailed, service, err); -} - -JNIEXPORT void JNICALL Java_com_apple_dnssd_AppleService_HaltOperation( JNIEnv *pEnv, jobject pThis) -/* Deallocate the dns_sd service browser and set the Java object's fNativeContext field to 0. */ -{ - jclass cls = (*pEnv)->GetObjectClass( pEnv, pThis); - jfieldID contextField = (*pEnv)->GetFieldID( pEnv, cls, "fNativeContext", "J"); - - if ( contextField != 0) - { - OpContext *pContext = (OpContext*) (long) (*pEnv)->GetLongField(pEnv, pThis, contextField); - if ( pContext != NULL) - { - // MUST clear fNativeContext first, BEFORE calling DNSServiceRefDeallocate() - (*pEnv)->SetLongField(pEnv, pThis, contextField, 0); - if ( pContext->ServiceRef != NULL) - DNSServiceRefDeallocate( pContext->ServiceRef); - - (*pEnv)->DeleteWeakGlobalRef( pEnv, pContext->JavaObj); - (*pEnv)->DeleteWeakGlobalRef( pEnv, pContext->ClientObj); - free( pContext); - } - } -} - - -JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleService_BlockForData( JNIEnv *pEnv, jobject pThis) -/* Block until data arrives, or one second passes. Returns 1 if data present, 0 otherwise. */ -{ -// BlockForData() not supported with AUTO_CALLBACKS -#if !AUTO_CALLBACKS - jclass cls = (*pEnv)->GetObjectClass( pEnv, pThis); - jfieldID contextField = (*pEnv)->GetFieldID( pEnv, cls, "fNativeContext", "J"); - - if ( contextField != 0) - { - OpContext *pContext = (OpContext*) (long) (*pEnv)->GetLongField(pEnv, pThis, contextField); - if ( pContext != NULL) - { - fd_set readFDs; - int sd = DNSServiceRefSockFD( pContext->ServiceRef); - struct timeval timeout = { 1, 0 }; - FD_ZERO( &readFDs); - FD_SET( sd, &readFDs); - - // Q: Why do we poll here? - // A: Because there's no other thread-safe way to do it. - // Mac OS X terminates a select() call if you close one of the sockets it's listening on, but Linux does not, - // and arguably Linux is correct (See <http://www.ussg.iu.edu/hypermail/linux/kernel/0405.1/0418.html>) - // The problem is that the Mac OS X behaviour assumes that it's okay for one thread to close a socket while - // some other thread is monitoring that socket in select(), but the difficulty is that there's no general way - // to make that thread-safe, because there's no atomic way to enter select() and release a lock simultaneously. - // If we try to do this without holding any lock, then right as we jump to the select() routine, - // some other thread could stop our operation (thereby closing the socket), - // and then that thread (or even some third, unrelated thread) - // could do some other DNS-SD operation (or some other operation that opens a new file descriptor) - // and then we'd blindly resume our fall into the select() call, now blocking on a file descriptor - // that may coincidentally have the same numerical value, but is semantically unrelated - // to the true file descriptor we thought we were blocking on. - // We can't stop this race condition from happening, but at least if we wake up once a second we can detect - // when fNativeContext has gone to zero, and thereby discover that we were blocking on the wrong fd. - - if (select( sd + 1, &readFDs, (fd_set*) NULL, (fd_set*) NULL, &timeout) == 1) return(1); - } - } -#endif // !AUTO_CALLBACKS - return(0); -} - - -JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleService_ProcessResults( JNIEnv *pEnv, jobject pThis) -/* Call through to DNSServiceProcessResult() while data remains on socket. */ -{ -#if !AUTO_CALLBACKS // ProcessResults() not supported with AUTO_CALLBACKS - - jclass cls = (*pEnv)->GetObjectClass( pEnv, pThis); - jfieldID contextField = (*pEnv)->GetFieldID( pEnv, cls, "fNativeContext", "J"); - OpContext *pContext = (OpContext*) (long) (*pEnv)->GetLongField(pEnv, pThis, contextField); - DNSServiceErrorType err = kDNSServiceErr_BadState; - - if ( pContext != NULL) - { - int sd = DNSServiceRefSockFD( pContext->ServiceRef); - fd_set readFDs; - struct timeval zeroTimeout = { 0, 0 }; - - pContext->Env = pEnv; - - FD_ZERO( &readFDs); - FD_SET( sd, &readFDs); - - err = kDNSServiceErr_NoError; - if (0 < select(sd + 1, &readFDs, (fd_set*) NULL, (fd_set*) NULL, &zeroTimeout)) - { - err = DNSServiceProcessResult(pContext->ServiceRef); - // Use caution here! - // We cannot touch any data structures associated with this operation! - // The DNSServiceProcessResult() routine should have invoked our callback, - // and our callback could have terminated the operation with op.stop(); - // and that means HaltOperation() will have been called, which frees pContext. - // Basically, from here we just have to get out without touching any stale - // data structures that could blow up on us! Particularly, any attempt - // to loop here reading more results from the file descriptor is unsafe. - } - } - return err; -#endif // AUTO_CALLBACKS -} - - -static void DNSSD_API ServiceBrowseReply( DNSServiceRef sdRef _UNUSED, DNSServiceFlags flags, uint32_t interfaceIndex, - DNSServiceErrorType errorCode, const char *serviceName, const char *regtype, - const char *replyDomain, void *context) -{ - OpContext *pContext = (OpContext*) context; - - SetupCallbackState( &pContext->Env); - - if ( pContext->ClientObj != NULL && pContext->Callback != NULL) - { - if ( errorCode == kDNSServiceErr_NoError) - { - (*pContext->Env)->CallVoidMethod( pContext->Env, pContext->ClientObj, - ( flags & kDNSServiceFlagsAdd) != 0 ? pContext->Callback : pContext->Callback2, - pContext->JavaObj, flags, interfaceIndex, - (*pContext->Env)->NewStringUTF( pContext->Env, serviceName), - (*pContext->Env)->NewStringUTF( pContext->Env, regtype), - (*pContext->Env)->NewStringUTF( pContext->Env, replyDomain)); - } - else - ReportError( pContext->Env, pContext->ClientObj, pContext->JavaObj, errorCode); - } - - TeardownCallbackState(); -} - -JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleBrowser_CreateBrowser( JNIEnv *pEnv, jobject pThis, - jint flags, jint ifIndex, jstring regType, jstring domain) -{ - jclass cls = (*pEnv)->GetObjectClass( pEnv, pThis); - jfieldID contextField = (*pEnv)->GetFieldID( pEnv, cls, "fNativeContext", "J"); - OpContext *pContext = NULL; - DNSServiceErrorType err = kDNSServiceErr_NoError; - - if ( contextField != 0) - pContext = NewContext( pEnv, pThis, "serviceFound", - "(Lcom/apple/dnssd/DNSSDService;IILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)V"); - else - err = kDNSServiceErr_BadParam; - - if ( pContext != NULL) - { - const char *regStr = SafeGetUTFChars( pEnv, regType); - const char *domainStr = SafeGetUTFChars( pEnv, domain); - - pContext->Callback2 = (*pEnv)->GetMethodID( pEnv, - (*pEnv)->GetObjectClass( pEnv, pContext->ClientObj), - "serviceLost", "(Lcom/apple/dnssd/DNSSDService;IILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)V"); - - err = DNSServiceBrowse( &pContext->ServiceRef, flags, ifIndex, regStr, domainStr, ServiceBrowseReply, pContext); - if ( err == kDNSServiceErr_NoError) - { - (*pEnv)->SetLongField(pEnv, pThis, contextField, (long) pContext); - } - - SafeReleaseUTFChars( pEnv, regType, regStr); - SafeReleaseUTFChars( pEnv, domain, domainStr); - } - else - err = kDNSServiceErr_NoMemory; - - return err; -} - - -static void DNSSD_API ServiceResolveReply( DNSServiceRef sdRef _UNUSED, DNSServiceFlags flags, uint32_t interfaceIndex, - DNSServiceErrorType errorCode, const char *fullname, const char *hosttarget, - uint16_t port, uint16_t txtLen, const unsigned char *txtRecord, void *context) -{ - OpContext *pContext = (OpContext*) context; - jclass txtCls; - jmethodID txtCtor; - jbyteArray txtBytes; - jobject txtObj; - jbyte *pBytes; - - SetupCallbackState( &pContext->Env); - - txtCls = (*pContext->Env)->FindClass( pContext->Env, "com/apple/dnssd/TXTRecord"); - txtCtor = (*pContext->Env)->GetMethodID( pContext->Env, txtCls, "<init>", "([B)V"); - - if ( pContext->ClientObj != NULL && pContext->Callback != NULL && txtCtor != NULL && - NULL != ( txtBytes = (*pContext->Env)->NewByteArray( pContext->Env, txtLen))) - { - if ( errorCode == kDNSServiceErr_NoError) - { - // Since Java ints are defined to be big-endian, we canonicalize 'port' from a 16-bit - // pattern into a number here. - port = ( ((unsigned char*) &port)[0] << 8) | ((unsigned char*) &port)[1]; - - // Initialize txtBytes with contents of txtRecord - pBytes = (*pContext->Env)->GetByteArrayElements( pContext->Env, txtBytes, NULL); - memcpy( pBytes, txtRecord, txtLen); - (*pContext->Env)->ReleaseByteArrayElements( pContext->Env, txtBytes, pBytes, JNI_COMMIT); - - // Construct txtObj with txtBytes - txtObj = (*pContext->Env)->NewObject( pContext->Env, txtCls, txtCtor, txtBytes); - (*pContext->Env)->DeleteLocalRef( pContext->Env, txtBytes); - - (*pContext->Env)->CallVoidMethod( pContext->Env, pContext->ClientObj, pContext->Callback, - pContext->JavaObj, flags, interfaceIndex, - (*pContext->Env)->NewStringUTF( pContext->Env, fullname), - (*pContext->Env)->NewStringUTF( pContext->Env, hosttarget), - port, txtObj); - } - else - ReportError( pContext->Env, pContext->ClientObj, pContext->JavaObj, errorCode); - } - - TeardownCallbackState(); -} - -JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleResolver_CreateResolver( JNIEnv *pEnv, jobject pThis, - jint flags, jint ifIndex, jstring serviceName, jstring regType, jstring domain) -{ - jclass cls = (*pEnv)->GetObjectClass( pEnv, pThis); - jfieldID contextField = (*pEnv)->GetFieldID( pEnv, cls, "fNativeContext", "J"); - OpContext *pContext = NULL; - DNSServiceErrorType err = kDNSServiceErr_NoError; - - if ( contextField != 0) - pContext = NewContext( pEnv, pThis, "serviceResolved", - "(Lcom/apple/dnssd/DNSSDService;IILjava/lang/String;Ljava/lang/String;ILcom/apple/dnssd/TXTRecord;)V"); - else - err = kDNSServiceErr_BadParam; - - if ( pContext != NULL) - { - const char *servStr = SafeGetUTFChars( pEnv, serviceName); - const char *regStr = SafeGetUTFChars( pEnv, regType); - const char *domainStr = SafeGetUTFChars( pEnv, domain); - - err = DNSServiceResolve( &pContext->ServiceRef, flags, ifIndex, - servStr, regStr, domainStr, ServiceResolveReply, pContext); - if ( err == kDNSServiceErr_NoError) - { - (*pEnv)->SetLongField(pEnv, pThis, contextField, (long) pContext); - } - - SafeReleaseUTFChars( pEnv, serviceName, servStr); - SafeReleaseUTFChars( pEnv, regType, regStr); - SafeReleaseUTFChars( pEnv, domain, domainStr); - } - else - err = kDNSServiceErr_NoMemory; - - return err; -} - - -static void DNSSD_API ServiceRegisterReply( DNSServiceRef sdRef _UNUSED, DNSServiceFlags flags, - DNSServiceErrorType errorCode, const char *serviceName, - const char *regType, const char *domain, void *context) -{ - OpContext *pContext = (OpContext*) context; - - SetupCallbackState( &pContext->Env); - - if ( pContext->ClientObj != NULL && pContext->Callback != NULL) - { - if ( errorCode == kDNSServiceErr_NoError) - { - (*pContext->Env)->CallVoidMethod( pContext->Env, pContext->ClientObj, pContext->Callback, - pContext->JavaObj, flags, - (*pContext->Env)->NewStringUTF( pContext->Env, serviceName), - (*pContext->Env)->NewStringUTF( pContext->Env, regType), - (*pContext->Env)->NewStringUTF( pContext->Env, domain)); - } - else - ReportError( pContext->Env, pContext->ClientObj, pContext->JavaObj, errorCode); - } - TeardownCallbackState(); -} - -JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleRegistration_BeginRegister( JNIEnv *pEnv, jobject pThis, - jint ifIndex, jint flags, jstring serviceName, jstring regType, - jstring domain, jstring host, jint port, jbyteArray txtRecord) -{ - //syslog(LOG_ERR, "BR"); - jclass cls = (*pEnv)->GetObjectClass( pEnv, pThis); - jfieldID contextField = (*pEnv)->GetFieldID( pEnv, cls, "fNativeContext", "J"); - OpContext *pContext = NULL; - DNSServiceErrorType err = kDNSServiceErr_NoError; - jbyte *pBytes; - jsize numBytes; - - //syslog(LOG_ERR, "BR: contextField %d", contextField); - - if ( contextField != 0) - pContext = NewContext( pEnv, pThis, "serviceRegistered", - "(Lcom/apple/dnssd/DNSSDRegistration;ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)V"); - else - err = kDNSServiceErr_BadParam; - - if ( pContext != NULL) - { - const char *servStr = SafeGetUTFChars( pEnv, serviceName); - const char *regStr = SafeGetUTFChars( pEnv, regType); - const char *domainStr = SafeGetUTFChars( pEnv, domain); - const char *hostStr = SafeGetUTFChars( pEnv, host); - - //syslog(LOG_ERR, "BR: regStr %s", regStr); - - // Since Java ints are defined to be big-endian, we de-canonicalize 'port' from a - // big-endian number into a 16-bit pattern here. - uint16_t portBits = port; - portBits = ( ((unsigned char*) &portBits)[0] << 8) | ((unsigned char*) &portBits)[1]; - - pBytes = txtRecord ? (*pEnv)->GetByteArrayElements( pEnv, txtRecord, NULL) : NULL; - numBytes = txtRecord ? (*pEnv)->GetArrayLength( pEnv, txtRecord) : 0; - - err = DNSServiceRegister( &pContext->ServiceRef, flags, ifIndex, servStr, regStr, - domainStr, hostStr, portBits, - numBytes, pBytes, ServiceRegisterReply, pContext); - if ( err == kDNSServiceErr_NoError) - { - (*pEnv)->SetLongField(pEnv, pThis, contextField, (long) pContext); - } - - if ( pBytes != NULL) - (*pEnv)->ReleaseByteArrayElements( pEnv, txtRecord, pBytes, 0); - - SafeReleaseUTFChars( pEnv, serviceName, servStr); - SafeReleaseUTFChars( pEnv, regType, regStr); - SafeReleaseUTFChars( pEnv, domain, domainStr); - SafeReleaseUTFChars( pEnv, host, hostStr); - } - else - err = kDNSServiceErr_NoMemory; - - return err; -} - -JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleRegistration_AddRecord( JNIEnv *pEnv, jobject pThis, - jint flags, jint rrType, jbyteArray rData, jint ttl, jobject destObj) -{ - jclass cls = (*pEnv)->GetObjectClass( pEnv, pThis); - jfieldID contextField = (*pEnv)->GetFieldID( pEnv, cls, "fNativeContext", "J"); - jclass destCls = (*pEnv)->GetObjectClass( pEnv, destObj); - jfieldID recField = (*pEnv)->GetFieldID( pEnv, destCls, "fRecord", "J"); - OpContext *pContext = NULL; - DNSServiceErrorType err = kDNSServiceErr_NoError; - jbyte *pBytes; - jsize numBytes; - DNSRecordRef recRef; - - if ( contextField != 0) - pContext = (OpContext*) (long) (*pEnv)->GetLongField(pEnv, pThis, contextField); - if ( pContext == NULL || pContext->ServiceRef == NULL) - return kDNSServiceErr_BadParam; - - pBytes = (*pEnv)->GetByteArrayElements( pEnv, rData, NULL); - numBytes = (*pEnv)->GetArrayLength( pEnv, rData); - - err = DNSServiceAddRecord( pContext->ServiceRef, &recRef, flags, rrType, numBytes, pBytes, ttl); - if ( err == kDNSServiceErr_NoError) - { - (*pEnv)->SetLongField(pEnv, destObj, recField, (long) recRef); - } - - if ( pBytes != NULL) - (*pEnv)->ReleaseByteArrayElements( pEnv, rData, pBytes, 0); - - return err; -} - -JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleDNSRecord_Update( JNIEnv *pEnv, jobject pThis, - jint flags, jbyteArray rData, jint ttl) -{ - jclass cls = (*pEnv)->GetObjectClass( pEnv, pThis); - jfieldID ownerField = (*pEnv)->GetFieldID( pEnv, cls, "fOwner", "Lcom/apple/dnssd/AppleService;"); - jfieldID recField = (*pEnv)->GetFieldID( pEnv, cls, "fRecord", "J"); - OpContext *pContext = NULL; - DNSServiceErrorType err = kDNSServiceErr_NoError; - jbyte *pBytes; - jsize numBytes; - DNSRecordRef recRef = NULL; - - if ( ownerField != 0) - { - jobject ownerObj = (*pEnv)->GetObjectField( pEnv, pThis, ownerField); - jclass ownerClass = (*pEnv)->GetObjectClass( pEnv, ownerObj); - jfieldID contextField = (*pEnv)->GetFieldID( pEnv, ownerClass, "fNativeContext", "J"); - if ( contextField != 0) - pContext = (OpContext*) (long) (*pEnv)->GetLongField(pEnv, ownerObj, contextField); - } - if ( recField != 0) - recRef = (DNSRecordRef) (long) (*pEnv)->GetLongField(pEnv, pThis, recField); - if ( pContext == NULL || pContext->ServiceRef == NULL) - return kDNSServiceErr_BadParam; - - pBytes = (*pEnv)->GetByteArrayElements( pEnv, rData, NULL); - numBytes = (*pEnv)->GetArrayLength( pEnv, rData); - - err = DNSServiceUpdateRecord( pContext->ServiceRef, recRef, flags, numBytes, pBytes, ttl); - - if ( pBytes != NULL) - (*pEnv)->ReleaseByteArrayElements( pEnv, rData, pBytes, 0); - - return err; -} - -JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleDNSRecord_Remove( JNIEnv *pEnv, jobject pThis) -{ - jclass cls = (*pEnv)->GetObjectClass( pEnv, pThis); - jfieldID ownerField = (*pEnv)->GetFieldID( pEnv, cls, "fOwner", "Lcom/apple/dnssd/AppleService;"); - jfieldID recField = (*pEnv)->GetFieldID( pEnv, cls, "fRecord", "J"); - OpContext *pContext = NULL; - DNSServiceErrorType err = kDNSServiceErr_NoError; - DNSRecordRef recRef = NULL; - - if ( ownerField != 0) - { - jobject ownerObj = (*pEnv)->GetObjectField( pEnv, pThis, ownerField); - jclass ownerClass = (*pEnv)->GetObjectClass( pEnv, ownerObj); - jfieldID contextField = (*pEnv)->GetFieldID( pEnv, ownerClass, "fNativeContext", "J"); - if ( contextField != 0) - pContext = (OpContext*) (long) (*pEnv)->GetLongField(pEnv, ownerObj, contextField); - } - if ( recField != 0) - recRef = (DNSRecordRef) (long) (*pEnv)->GetLongField(pEnv, pThis, recField); - if ( pContext == NULL || pContext->ServiceRef == NULL) - return kDNSServiceErr_BadParam; - - err = DNSServiceRemoveRecord( pContext->ServiceRef, recRef, 0); - - return err; -} - - -JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleRecordRegistrar_CreateConnection( JNIEnv *pEnv, jobject pThis) -{ - jclass cls = (*pEnv)->GetObjectClass( pEnv, pThis); - jfieldID contextField = (*pEnv)->GetFieldID( pEnv, cls, "fNativeContext", "J"); - OpContext *pContext = NULL; - DNSServiceErrorType err = kDNSServiceErr_NoError; - - if ( contextField != 0) - pContext = NewContext( pEnv, pThis, "recordRegistered", "(Lcom/apple/dnssd/DNSRecord;I)V"); - else - err = kDNSServiceErr_BadParam; - - if ( pContext != NULL) - { - err = DNSServiceCreateConnection( &pContext->ServiceRef); - if ( err == kDNSServiceErr_NoError) - { - (*pEnv)->SetLongField(pEnv, pThis, contextField, (long) pContext); - } - } - else - err = kDNSServiceErr_NoMemory; - - return err; -} - -struct RecordRegistrationRef -{ - OpContext *Context; - jobject RecordObj; -}; -typedef struct RecordRegistrationRef RecordRegistrationRef; - -static void DNSSD_API RegisterRecordReply( DNSServiceRef sdRef _UNUSED, - DNSRecordRef recordRef _UNUSED, DNSServiceFlags flags, - DNSServiceErrorType errorCode, void *context) -{ - RecordRegistrationRef *regEnvelope = (RecordRegistrationRef*) context; - OpContext *pContext = regEnvelope->Context; - - SetupCallbackState( &pContext->Env); - - if ( pContext->ClientObj != NULL && pContext->Callback != NULL) - { - if ( errorCode == kDNSServiceErr_NoError) - { - (*pContext->Env)->CallVoidMethod( pContext->Env, pContext->ClientObj, pContext->Callback, - regEnvelope->RecordObj, flags); - } - else - ReportError( pContext->Env, pContext->ClientObj, pContext->JavaObj, errorCode); - } - - (*pContext->Env)->DeleteWeakGlobalRef( pContext->Env, regEnvelope->RecordObj); - free( regEnvelope); - - TeardownCallbackState(); -} - -JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleRecordRegistrar_RegisterRecord( JNIEnv *pEnv, jobject pThis, - jint flags, jint ifIndex, jstring fullname, jint rrType, jint rrClass, - jbyteArray rData, jint ttl, jobject destObj) -{ - jclass cls = (*pEnv)->GetObjectClass( pEnv, pThis); - jfieldID contextField = (*pEnv)->GetFieldID( pEnv, cls, "fNativeContext", "J"); - jclass destCls = (*pEnv)->GetObjectClass( pEnv, destObj); - jfieldID recField = (*pEnv)->GetFieldID( pEnv, destCls, "fRecord", "J"); - const char *nameStr = SafeGetUTFChars( pEnv, fullname); - OpContext *pContext = NULL; - DNSServiceErrorType err = kDNSServiceErr_NoError; - jbyte *pBytes; - jsize numBytes; - DNSRecordRef recRef; - RecordRegistrationRef *regEnvelope; - - if ( contextField != 0) - pContext = (OpContext*) (long) (*pEnv)->GetLongField(pEnv, pThis, contextField); - if ( pContext == NULL || pContext->ServiceRef == NULL || nameStr == NULL) - return kDNSServiceErr_BadParam; - - regEnvelope = calloc( 1, sizeof *regEnvelope); - if ( regEnvelope == NULL) - return kDNSServiceErr_NoMemory; - regEnvelope->Context = pContext; - regEnvelope->RecordObj = (*pEnv)->NewWeakGlobalRef( pEnv, destObj); // must convert local ref to global to cache - - pBytes = (*pEnv)->GetByteArrayElements( pEnv, rData, NULL); - numBytes = (*pEnv)->GetArrayLength( pEnv, rData); - - err = DNSServiceRegisterRecord( pContext->ServiceRef, &recRef, flags, ifIndex, - nameStr, rrType, rrClass, numBytes, pBytes, ttl, - RegisterRecordReply, regEnvelope); - - if ( err == kDNSServiceErr_NoError) - { - (*pEnv)->SetLongField(pEnv, destObj, recField, (long) recRef); - } - else - { - if ( regEnvelope->RecordObj != NULL) - (*pEnv)->DeleteWeakGlobalRef( pEnv, regEnvelope->RecordObj); - free( regEnvelope); - } - - if ( pBytes != NULL) - (*pEnv)->ReleaseByteArrayElements( pEnv, rData, pBytes, 0); - - SafeReleaseUTFChars( pEnv, fullname, nameStr); - - return err; -} - - -static void DNSSD_API ServiceQueryReply( DNSServiceRef sdRef _UNUSED, DNSServiceFlags flags, uint32_t interfaceIndex, - DNSServiceErrorType errorCode, const char *serviceName, - uint16_t rrtype, uint16_t rrclass, uint16_t rdlen, - const void *rdata, uint32_t ttl, void *context) -{ - OpContext *pContext = (OpContext*) context; - jbyteArray rDataObj; - jbyte *pBytes; - - SetupCallbackState( &pContext->Env); - - if ( pContext->ClientObj != NULL && pContext->Callback != NULL && - NULL != ( rDataObj = (*pContext->Env)->NewByteArray( pContext->Env, rdlen))) - { - if ( errorCode == kDNSServiceErr_NoError) - { - // Initialize rDataObj with contents of rdata - pBytes = (*pContext->Env)->GetByteArrayElements( pContext->Env, rDataObj, NULL); - memcpy( pBytes, rdata, rdlen); - (*pContext->Env)->ReleaseByteArrayElements( pContext->Env, rDataObj, pBytes, JNI_COMMIT); - - (*pContext->Env)->CallVoidMethod( pContext->Env, pContext->ClientObj, pContext->Callback, - pContext->JavaObj, flags, interfaceIndex, - (*pContext->Env)->NewStringUTF( pContext->Env, serviceName), - rrtype, rrclass, rDataObj, ttl); - } - else - ReportError( pContext->Env, pContext->ClientObj, pContext->JavaObj, errorCode); - } - TeardownCallbackState(); -} - -JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleQuery_CreateQuery( JNIEnv *pEnv, jobject pThis, - jint flags, jint ifIndex, jstring serviceName, jint rrtype, jint rrclass) -{ - jclass cls = (*pEnv)->GetObjectClass( pEnv, pThis); - jfieldID contextField = (*pEnv)->GetFieldID( pEnv, cls, "fNativeContext", "J"); - OpContext *pContext = NULL; - DNSServiceErrorType err = kDNSServiceErr_NoError; - - if ( contextField != 0) - pContext = NewContext( pEnv, pThis, "queryAnswered", - "(Lcom/apple/dnssd/DNSSDService;IILjava/lang/String;II[BI)V"); - else - err = kDNSServiceErr_BadParam; - - if ( pContext != NULL) - { - const char *servStr = SafeGetUTFChars( pEnv, serviceName); - - err = DNSServiceQueryRecord( &pContext->ServiceRef, flags, ifIndex, servStr, - rrtype, rrclass, ServiceQueryReply, pContext); - if ( err == kDNSServiceErr_NoError) - { - (*pEnv)->SetLongField(pEnv, pThis, contextField, (long) pContext); - } - - SafeReleaseUTFChars( pEnv, serviceName, servStr); - } - else - err = kDNSServiceErr_NoMemory; - - return err; -} - - -static void DNSSD_API DomainEnumReply( DNSServiceRef sdRef _UNUSED, DNSServiceFlags flags, uint32_t interfaceIndex, - DNSServiceErrorType errorCode, const char *replyDomain, void *context) -{ - OpContext *pContext = (OpContext*) context; - - SetupCallbackState( &pContext->Env); - - if ( pContext->ClientObj != NULL && pContext->Callback != NULL) - { - if ( errorCode == kDNSServiceErr_NoError) - { - (*pContext->Env)->CallVoidMethod( pContext->Env, pContext->ClientObj, - ( flags & kDNSServiceFlagsAdd) != 0 ? pContext->Callback : pContext->Callback2, - pContext->JavaObj, flags, interfaceIndex, - (*pContext->Env)->NewStringUTF( pContext->Env, replyDomain)); - } - else - ReportError( pContext->Env, pContext->ClientObj, pContext->JavaObj, errorCode); - } - TeardownCallbackState(); -} - -JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleDomainEnum_BeginEnum( JNIEnv *pEnv, jobject pThis, - jint flags, jint ifIndex) -{ - jclass cls = (*pEnv)->GetObjectClass( pEnv, pThis); - jfieldID contextField = (*pEnv)->GetFieldID( pEnv, cls, "fNativeContext", "J"); - OpContext *pContext = NULL; - DNSServiceErrorType err = kDNSServiceErr_NoError; - - if ( contextField != 0) - pContext = NewContext( pEnv, pThis, "domainFound", - "(Lcom/apple/dnssd/DNSSDService;IILjava/lang/String;)V"); - else - err = kDNSServiceErr_BadParam; - - if ( pContext != NULL) - { - pContext->Callback2 = (*pEnv)->GetMethodID( pEnv, - (*pEnv)->GetObjectClass( pEnv, pContext->ClientObj), - "domainLost", "(Lcom/apple/dnssd/DNSSDService;IILjava/lang/String;)V"); - - err = DNSServiceEnumerateDomains( &pContext->ServiceRef, flags, ifIndex, - DomainEnumReply, pContext); - if ( err == kDNSServiceErr_NoError) - { - (*pEnv)->SetLongField(pEnv, pThis, contextField, (long) pContext); - } - } - else - err = kDNSServiceErr_NoMemory; - - return err; -} - - -JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleDNSSD_ConstructName( JNIEnv *pEnv, jobject pThis _UNUSED, - jstring serviceName, jstring regtype, jstring domain, jobjectArray pOut) -{ - DNSServiceErrorType err = kDNSServiceErr_NoError; - const char *nameStr = SafeGetUTFChars( pEnv, serviceName); - const char *regStr = SafeGetUTFChars( pEnv, regtype); - const char *domStr = SafeGetUTFChars( pEnv, domain); - char buff[ kDNSServiceMaxDomainName + 1]; - - err = DNSServiceConstructFullName( buff, nameStr, regStr, domStr); - - if ( err == kDNSServiceErr_NoError) - { - // pOut is expected to be a String[1] array. - (*pEnv)->SetObjectArrayElement( pEnv, pOut, 0, (*pEnv)->NewStringUTF( pEnv, buff)); - } - - SafeReleaseUTFChars( pEnv, serviceName, nameStr); - SafeReleaseUTFChars( pEnv, regtype, regStr); - SafeReleaseUTFChars( pEnv, domain, domStr); - - return err; -} - -JNIEXPORT void JNICALL Java_com_apple_dnssd_AppleDNSSD_ReconfirmRecord( JNIEnv *pEnv, jobject pThis _UNUSED, - jint flags, jint ifIndex, jstring fullName, - jint rrtype, jint rrclass, jbyteArray rdata) -{ - jbyte *pBytes; - jsize numBytes; - const char *nameStr = SafeGetUTFChars( pEnv, fullName); - - pBytes = (*pEnv)->GetByteArrayElements( pEnv, rdata, NULL); - numBytes = (*pEnv)->GetArrayLength( pEnv, rdata); - - DNSServiceReconfirmRecord( flags, ifIndex, nameStr, rrtype, rrclass, numBytes, pBytes); - - if ( pBytes != NULL) - (*pEnv)->ReleaseByteArrayElements( pEnv, rdata, pBytes, 0); - - SafeReleaseUTFChars( pEnv, fullName, nameStr); -} - -#define LOCAL_ONLY_NAME "loo" -#define P2P_NAME "p2p" - -JNIEXPORT jstring JNICALL Java_com_apple_dnssd_AppleDNSSD_GetNameForIfIndex( JNIEnv *pEnv, jobject pThis _UNUSED, - jint ifIndex) -{ - char *p = LOCAL_ONLY_NAME, nameBuff[IF_NAMESIZE]; - - if (ifIndex == (jint) kDNSServiceInterfaceIndexP2P) - p = P2P_NAME; - else if (ifIndex != (jint) kDNSServiceInterfaceIndexLocalOnly) - p = if_indextoname( ifIndex, nameBuff ); - - return (*pEnv)->NewStringUTF( pEnv, p); -} - - -JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleDNSSD_GetIfIndexForName( JNIEnv *pEnv, jobject pThis _UNUSED, - jstring ifName) -{ - uint32_t ifIndex = kDNSServiceInterfaceIndexLocalOnly; - const char *nameStr = SafeGetUTFChars( pEnv, ifName); - - if (strcmp(nameStr, P2P_NAME) == 0) - ifIndex = kDNSServiceInterfaceIndexP2P; - else if (strcmp(nameStr, LOCAL_ONLY_NAME)) - ifIndex = if_nametoindex( nameStr); - - SafeReleaseUTFChars( pEnv, ifName, nameStr); - - return ifIndex; -} - - -#if defined(_WIN32) -static char* -win32_if_indextoname( DWORD ifIndex, char * nameBuff) -{ - PIP_ADAPTER_INFO pAdapterInfo = NULL; - PIP_ADAPTER_INFO pAdapter = NULL; - DWORD dwRetVal = 0; - char * ifName = NULL; - ULONG ulOutBufLen = 0; - - if (GetAdaptersInfo( NULL, &ulOutBufLen) != ERROR_BUFFER_OVERFLOW) - { - goto exit; - } - - pAdapterInfo = (IP_ADAPTER_INFO *) malloc(ulOutBufLen); - - if (pAdapterInfo == NULL) - { - goto exit; - } - - dwRetVal = GetAdaptersInfo( pAdapterInfo, &ulOutBufLen ); - - if (dwRetVal != NO_ERROR) - { - goto exit; - } - - pAdapter = pAdapterInfo; - while (pAdapter) - { - if (pAdapter->Index == ifIndex) - { - // It would be better if we passed in the length of nameBuff to this - // function, so we would have absolute certainty that no buffer - // overflows would occur. Buffer overflows *shouldn't* occur because - // nameBuff is of size MAX_ADAPTER_NAME_LENGTH. - strcpy( nameBuff, pAdapter->AdapterName ); - ifName = nameBuff; - break; - } - - pAdapter = pAdapter->Next; - } - -exit: - - if (pAdapterInfo != NULL) - { - free( pAdapterInfo ); - pAdapterInfo = NULL; - } - - return ifName; -} - - -static DWORD -win32_if_nametoindex( const char * nameStr ) -{ - PIP_ADAPTER_INFO pAdapterInfo = NULL; - PIP_ADAPTER_INFO pAdapter = NULL; - DWORD dwRetVal = 0; - DWORD ifIndex = 0; - ULONG ulOutBufLen = 0; - - if (GetAdaptersInfo( NULL, &ulOutBufLen) != ERROR_BUFFER_OVERFLOW) - { - goto exit; - } - - pAdapterInfo = (IP_ADAPTER_INFO *) malloc(ulOutBufLen); - - if (pAdapterInfo == NULL) - { - goto exit; - } - - dwRetVal = GetAdaptersInfo( pAdapterInfo, &ulOutBufLen ); - - if (dwRetVal != NO_ERROR) - { - goto exit; - } - - pAdapter = pAdapterInfo; - while (pAdapter) - { - if (strcmp(pAdapter->AdapterName, nameStr) == 0) - { - ifIndex = pAdapter->Index; - break; - } - - pAdapter = pAdapter->Next; - } - -exit: - - if (pAdapterInfo != NULL) - { - free( pAdapterInfo ); - pAdapterInfo = NULL; - } - - return ifIndex; -} -#endif - - -// Note: The C preprocessor stringify operator ('#') makes a string from its argument, without macro expansion -// e.g. If "version" is #define'd to be "4", then STRINGIFY_AWE(version) will return the string "version", not "4" -// To expand "version" to its value before making the string, use STRINGIFY(version) instead -#define STRINGIFY_ARGUMENT_WITHOUT_EXPANSION(s) # s -#define STRINGIFY(s) STRINGIFY_ARGUMENT_WITHOUT_EXPANSION(s) - -// NOT static -- otherwise the compiler may optimize it out -// The "@(#) " pattern is a special prefix the "what" command looks for -#ifndef MDNS_VERSIONSTR_NODTS -const char VersionString_SCCS[] = "@(#) libjdns_sd " STRINGIFY(mDNSResponderVersion) " (" __DATE__ " " __TIME__ ")"; -#else -const char VersionString_SCCS[] = "@(#) libjdns_sd " STRINGIFY(mDNSResponderVersion); -#endif diff --git a/usr/src/lib/libdns_sd/java/common/mapfile-vers b/usr/src/lib/libdns_sd/java/common/mapfile-vers deleted file mode 100644 index 01c3c548fd..0000000000 --- a/usr/src/lib/libdns_sd/java/common/mapfile-vers +++ /dev/null @@ -1,62 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License (the "License"). -# You may not use this file except in compliance with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. -# - -# -# MAPFILE HEADER START -# -# WARNING: STOP NOW. DO NOT MODIFY THIS FILE. -# Object versioning must comply with the rules detailed in -# -# usr/src/lib/README.mapfiles -# -# You should not be making modifications here until you've read the most current -# copy of that file. If you need help, contact a gatekeeper for guidance. -# -# MAPFILE HEADER END -# - -$mapfile_version 2 - -SYMBOL_VERSION SUNW_1.1 { - global: - Java_com_apple_dnssd_AppleBrowser_CreateBrowser; - Java_com_apple_dnssd_AppleDNSRecord_Remove; - Java_com_apple_dnssd_AppleDNSRecord_Update; - Java_com_apple_dnssd_AppleDNSSD_ConstructName; - Java_com_apple_dnssd_AppleDNSSD_GetIfIndexForName; - Java_com_apple_dnssd_AppleDNSSD_GetNameForIfIndex; - Java_com_apple_dnssd_AppleDNSSD_InitLibrary; - Java_com_apple_dnssd_AppleDNSSD_ReconfirmRecord; - Java_com_apple_dnssd_AppleDomainEnum_BeginEnum; - Java_com_apple_dnssd_AppleQuery_CreateQuery; - Java_com_apple_dnssd_AppleRecordRegistrar_CreateConnection; - Java_com_apple_dnssd_AppleRecordRegistrar_RegisterRecord; - Java_com_apple_dnssd_AppleRegistration_AddRecord; - Java_com_apple_dnssd_AppleRegistration_BeginRegister; - Java_com_apple_dnssd_AppleResolver_CreateResolver; - Java_com_apple_dnssd_AppleService_BlockForData; - Java_com_apple_dnssd_AppleService_HaltOperation; - Java_com_apple_dnssd_AppleService_ProcessResults; - local: - *; -}; diff --git a/usr/src/lib/libdns_sd/java/i386/Makefile b/usr/src/lib/libdns_sd/java/i386/Makefile deleted file mode 100644 index 3b6c2a1943..0000000000 --- a/usr/src/lib/libdns_sd/java/i386/Makefile +++ /dev/null @@ -1,35 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License (the "License"). -# You may not use this file except in compliance with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# Copyright 2007 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -#ident "%Z%%M% %I% %E% SMI" - -include ../Makefile.com - -.KEEP_STATE: - -CPPFLAGS += -_gcc=-Wno-pointer-to-int-cast -_gcc=-Wno-int-to-pointer-cast - -all: $(LIBS) - -install: all $(ROOTLIBS) $(ROOTLINKS) diff --git a/usr/src/lib/libdns_sd/java/sparc/Makefile b/usr/src/lib/libdns_sd/java/sparc/Makefile deleted file mode 100644 index 3b6c2a1943..0000000000 --- a/usr/src/lib/libdns_sd/java/sparc/Makefile +++ /dev/null @@ -1,35 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License (the "License"). -# You may not use this file except in compliance with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# Copyright 2007 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -#ident "%Z%%M% %I% %E% SMI" - -include ../Makefile.com - -.KEEP_STATE: - -CPPFLAGS += -_gcc=-Wno-pointer-to-int-cast -_gcc=-Wno-int-to-pointer-cast - -all: $(LIBS) - -install: all $(ROOTLIBS) $(ROOTLINKS) diff --git a/usr/src/lib/libdns_sd/java/sparcv9/Makefile b/usr/src/lib/libdns_sd/java/sparcv9/Makefile deleted file mode 100644 index b645e1caed..0000000000 --- a/usr/src/lib/libdns_sd/java/sparcv9/Makefile +++ /dev/null @@ -1,32 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License (the "License"). -# You may not use this file except in compliance with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# Copyright 2007 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -#ident "%Z%%M% %I% %E% SMI" - -include ../Makefile.com -include ../../../Makefile.lib.64 - -all: $(LIBS) - -install: all $(ROOTLIBS64) $(ROOTLINKS64) diff --git a/usr/src/lib/libdns_sd/sparc/Makefile b/usr/src/lib/libdns_sd/sparc/Makefile index 9c1be5bf3a..32145a695a 100644 --- a/usr/src/lib/libdns_sd/sparc/Makefile +++ b/usr/src/lib/libdns_sd/sparc/Makefile @@ -21,8 +21,7 @@ # Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # -#ident "%Z%%M% %I% %E% SMI" include ../Makefile.com -install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT) +install: all $(ROOTLIBS) $(ROOTLINKS) diff --git a/usr/src/lib/libdns_sd/sparcv9/Makefile b/usr/src/lib/libdns_sd/sparcv9/Makefile index abae92c693..fa485a4013 100644 --- a/usr/src/lib/libdns_sd/sparcv9/Makefile +++ b/usr/src/lib/libdns_sd/sparcv9/Makefile @@ -21,13 +21,10 @@ # Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # -#ident "%Z%%M% %I% %E% SMI" include ../Makefile.com include ../../Makefile.lib.64 -CFLAGS64 += -erroff=E_ASSIGNMENT_TYPE_MISMATCH - .KEEP_STATE: all: $(LIBS) diff --git a/usr/src/pkg/manifests/service-network-dns-mdns.mf b/usr/src/pkg/manifests/service-network-dns-mdns.mf index 4c809b4ae7..b060539159 100644 --- a/usr/src/pkg/manifests/service-network-dns-mdns.mf +++ b/usr/src/pkg/manifests/service-network-dns-mdns.mf @@ -44,17 +44,6 @@ dir path=usr/lib dir path=usr/lib/$(ARCH64) dir path=usr/lib/inet dir path=usr/share -dir path=usr/share/lib -dir path=usr/share/lib/java group=sys -dir path=usr/share/lib/java/javadoc group=other -dir path=usr/share/lib/java/javadoc/dnssd group=other -dir path=usr/share/lib/java/javadoc/dnssd/api group=other -dir path=usr/share/lib/java/javadoc/dnssd/api/com group=other -dir path=usr/share/lib/java/javadoc/dnssd/api/com/apple group=other -dir path=usr/share/lib/java/javadoc/dnssd/api/com/apple/dnssd group=other -$(JAVA_7_ONLY)dir path=usr/share/lib/java/javadoc/dnssd/api/resources \ - group=other -dir path=usr/share/lib/java/javadoc/dnssd/examples group=other dir path=usr/share/man dir path=usr/share/man/man1m dir path=usr/share/man/man3dns_sd @@ -63,95 +52,10 @@ file path=lib/svc/manifest/network/dns/multicast.xml group=sys mode=0444 file path=usr/bin/dns-sd mode=0555 file path=usr/include/dns_sd.h file path=usr/lib/$(ARCH64)/libdns_sd.so.1 -file path=usr/lib/$(ARCH64)/libjdns_sd.so.1 -file path=usr/lib/$(ARCH64)/llib-ldns_sd.ln file path=usr/lib/$(ARCH64)/nss_mdns.so.1 file path=usr/lib/inet/mdnsd mode=0555 file path=usr/lib/libdns_sd.so.1 -file path=usr/lib/libjdns_sd.so.1 -file path=usr/lib/llib-ldns_sd -file path=usr/lib/llib-ldns_sd.ln file path=usr/lib/nss_mdns.so.1 -file path=usr/share/lib/java/dnssd.jar group=sys -file path=usr/share/lib/java/javadoc/dnssd/api/allclasses-frame.html \ - group=other -file path=usr/share/lib/java/javadoc/dnssd/api/allclasses-noframe.html \ - group=other -file \ - path=usr/share/lib/java/javadoc/dnssd/api/com/apple/dnssd/BaseListener.html \ - group=other -file \ - path=usr/share/lib/java/javadoc/dnssd/api/com/apple/dnssd/BrowseListener.html \ - group=other -file path=usr/share/lib/java/javadoc/dnssd/api/com/apple/dnssd/DNSRecord.html \ - group=other -file path=usr/share/lib/java/javadoc/dnssd/api/com/apple/dnssd/DNSSD.html \ - group=other -file \ - path=usr/share/lib/java/javadoc/dnssd/api/com/apple/dnssd/DNSSDException.html \ - group=other -file \ - path=usr/share/lib/java/javadoc/dnssd/api/com/apple/dnssd/DNSSDRecordRegistrar.html \ - group=other -file \ - path=usr/share/lib/java/javadoc/dnssd/api/com/apple/dnssd/DNSSDRegistration.html \ - group=other -file \ - path=usr/share/lib/java/javadoc/dnssd/api/com/apple/dnssd/DNSSDService.html \ - group=other -file \ - path=usr/share/lib/java/javadoc/dnssd/api/com/apple/dnssd/DomainListener.html \ - group=other -file \ - path=usr/share/lib/java/javadoc/dnssd/api/com/apple/dnssd/QueryListener.html \ - group=other -file \ - path=usr/share/lib/java/javadoc/dnssd/api/com/apple/dnssd/RegisterListener.html \ - group=other -file \ - path=usr/share/lib/java/javadoc/dnssd/api/com/apple/dnssd/RegisterRecordListener.html \ - group=other -file \ - path=usr/share/lib/java/javadoc/dnssd/api/com/apple/dnssd/ResolveListener.html \ - group=other -file path=usr/share/lib/java/javadoc/dnssd/api/com/apple/dnssd/TXTRecord.html \ - group=other -file \ - path=usr/share/lib/java/javadoc/dnssd/api/com/apple/dnssd/package-frame.html \ - group=other -file \ - path=usr/share/lib/java/javadoc/dnssd/api/com/apple/dnssd/package-summary.html \ - group=other -file \ - path=usr/share/lib/java/javadoc/dnssd/api/com/apple/dnssd/package-tree.html \ - group=other -file path=usr/share/lib/java/javadoc/dnssd/api/constant-values.html \ - group=other -file path=usr/share/lib/java/javadoc/dnssd/api/deprecated-list.html \ - group=other -file path=usr/share/lib/java/javadoc/dnssd/api/help-doc.html group=other -file path=usr/share/lib/java/javadoc/dnssd/api/index-all.html group=other -file path=usr/share/lib/java/javadoc/dnssd/api/index.html group=other -file path=usr/share/lib/java/javadoc/dnssd/api/overview-tree.html group=other -file path=usr/share/lib/java/javadoc/dnssd/api/package-list group=other -$(JAVA_7_ONLY)file \ - path=usr/share/lib/java/javadoc/dnssd/api/resources/background.gif \ - group=other -$(JAVA_7_ONLY)file path=usr/share/lib/java/javadoc/dnssd/api/resources/tab.gif \ - group=other -$(JAVA_7_ONLY)file \ - path=usr/share/lib/java/javadoc/dnssd/api/resources/titlebar.gif \ - group=other -$(JAVA_7_ONLY)file \ - path=usr/share/lib/java/javadoc/dnssd/api/resources/titlebar_end.gif \ - group=other -$(JAVA_8_ONLY)file path=usr/share/lib/java/javadoc/dnssd/api/script.js \ - group=other -file path=usr/share/lib/java/javadoc/dnssd/api/serialized-form.html \ - group=other -file path=usr/share/lib/java/javadoc/dnssd/api/stylesheet.css group=other -file path=usr/share/lib/java/javadoc/dnssd/examples/BrowserApp.jar group=sys -file path=usr/share/lib/java/javadoc/dnssd/examples/SimpleChat.jar group=sys file path=usr/share/man/man1m/dns-sd.1m file path=usr/share/man/man1m/mdnsd.1m file path=usr/share/man/man3dns_sd/DNSServiceBrowse.3dns_sd @@ -174,14 +78,10 @@ legacy pkg=SUNWdsdu desc="Multicast DNS daemon and service discovery modules" \ name="Multicast DNS and Service Discovery (Usr)" license cr_Sun license=cr_Sun license lic_CDDL license=lic_CDDL -license usr/src/cmd/cmd-inet/usr.lib/mdnsd/THIRDPARTYLICENSE \ - license=usr/src/cmd/cmd-inet/usr.lib/mdnsd/THIRDPARTYLICENSE -license usr/src/lib/libdns_sd/THIRDPARTYLICENSE \ - license=usr/src/lib/libdns_sd/THIRDPARTYLICENSE +license usr/src/contrib/mDNSResponder/LICENSE \ + license=usr/src/contrib/mDNSResponder/LICENSE link path=usr/lib/$(ARCH64)/libdns_sd.so target=libdns_sd.so.1 -link path=usr/lib/$(ARCH64)/libjdns_sd.so target=libjdns_sd.so.1 link path=usr/lib/libdns_sd.so target=libdns_sd.so.1 -link path=usr/lib/libjdns_sd.so target=libjdns_sd.so.1 link path=usr/share/man/man3dns_sd/DNSServiceAddRecord.3dns_sd \ target=DNSServiceCreateConnection.3dns_sd link path=usr/share/man/man3dns_sd/DNSServiceRegisterRecord.3dns_sd \ |