X-Git-Url: https://git.saurik.com/apple/mdnsresponder.git/blobdiff_plain/c9d2d929f6ad52e6996754033ee77c725b90d1d4..c71e3068dca7ed8b0536b4ce3fe0552e9f39d389:/mDNSPosix/Identify.c diff --git a/mDNSPosix/Identify.c b/mDNSPosix/Identify.c index c1724f2..24c08bc 100644 --- a/mDNSPosix/Identify.c +++ b/mDNSPosix/Identify.c @@ -1,154 +1,19 @@ /* -*- Mode: C; tab-width: 4 -*- * - * Copyright (c) 2002-2004 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2002-2018 Apple Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and + * 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. - * - * @APPLE_LICENSE_HEADER_END@ * - * Formatting notes: - * This code follows the "Whitesmiths style" C indentation rules. Plenty of discussion - * on C indentation can be found on the web, such as , - * but for the sake of brevity here I will say just this: Curly braces are not syntactially - * part of an "if" statement; they are the beginning and ending markers of a compound statement; - * therefore common sense dictates that if they are part of a compound statement then they - * should be indented to the same level as everything else in that compound statement. - * Indenting curly braces at the same level as the "if" implies that curly braces are - * part of the "if", which is false. (This is as misleading as people who write "char* x,y;" - * thinking that variables x and y are both of type "char*" -- and anyone who doesn't - * understand why variable y is not of type "char*" just proves the point that poor code - * layout leads people to unfortunate misunderstandings about how the C language really works.) - - Change History (most recent first): - -$Log: Identify.c,v $ -Revision 1.34 2004/12/16 20:17:11 cheshire - Cache memory management improvements - -Revision 1.33 2004/11/30 22:37:00 cheshire -Update copyright dates and add "Mode: C; tab-width: 4" headers - -Revision 1.32 2004/10/19 21:33:21 cheshire - Cannot resolve non-local registrations using the mach API -Added flag 'kDNSServiceFlagsForceMulticast'. Passing through an interface id for a unicast name -doesn't force multicast unless you set this flag to indicate explicitly that this is what you want - -Revision 1.31 2004/10/16 00:17:00 cheshire - Replace IP TTL 255 check with local subnet source address check - -Revision 1.30 2004/09/21 23:29:51 cheshire - DNSServiceResolve should delay sending packets - -Revision 1.29 2004/09/17 01:08:53 cheshire -Renamed mDNSClientAPI.h to mDNSEmbeddedAPI.h - The name "mDNSClientAPI.h" is misleading to new developers looking at this code. The interfaces - declared in that file are ONLY appropriate to single-address-space embedded applications. - For clients on general-purpose computers, the interfaces defined in dns_sd.h should be used. - -Revision 1.28 2004/09/17 00:31:52 cheshire -For consistency with ipv6, renamed rdata field 'ip' to 'ipv4' - -Revision 1.27 2004/09/16 01:58:22 cheshire -Fix compiler warnings - -Revision 1.26 2004/08/24 21:55:07 cheshire -Don't try to build IPv6 code on systems that don't have IPv6 - -Revision 1.25 2004/07/20 23:42:37 cheshire -Update to use only "_services._dns-sd._udp.local." meta-query for service enumeration - -Revision 1.24 2004/06/15 02:39:47 cheshire -When displaying error message, only show command name, not entire path - -Revision 1.23 2004/05/18 23:51:26 cheshire -Tidy up all checkin comments to use consistent "" format for bug numbers - -Revision 1.22 2004/04/20 22:43:28 cheshire -Use _services._dns-sd._udp query, as documented in - - -Revision 1.21 2004/01/28 21:38:57 cheshire -Also ask target host for _services._mdns._udp.local. list - -Revision 1.20 2004/01/28 19:04:38 cheshire -Fix Ctrl-C handling when multiple targets are specified - -Revision 1.19 2004/01/28 03:49:30 cheshire -Enhanced mDNSIdentify to make use of new targeted-query capability - -Revision 1.18 2004/01/27 19:06:51 cheshire -Remove workaround for WWDC 2003 bug; no one has run that buggy build for a long time - -Revision 1.17 2004/01/22 03:57:00 cheshire -Use the new meta-interface mDNSInterface_ForceMCast. This restores mDNSIdentify's -ability to use multicast queries with non-link-local target addresses, like 17.x.x.x. - -Revision 1.16 2004/01/22 00:03:32 cheshire -Add while() loop so that a list of targets may be specified on the command line - -Revision 1.15 2004/01/21 21:55:06 cheshire -Don't need to wait for timeout once we've got the information we wanted - -Revision 1.14 2003/12/17 00:51:22 cheshire -Changed mDNSNetMonitor and mDNSIdentify to link the object files -instead of #including the "DNSCommon.c" "uDNS.c" and source files - -Revision 1.13 2003/12/13 03:05:28 ksekar -: DynDNS: Unicast query of service records - -Revision 1.12 2003/11/14 21:27:09 cheshire -: Security: Crashing bug in mDNSResponder -Fix code that should use buffer size MAX_ESCAPED_DOMAIN_NAME (1005) instead of 256-byte buffers. - -Revision 1.11 2003/10/30 19:26:38 cheshire -Fix warnings on certain compilers - -Revision 1.10 2003/09/02 20:38:57 cheshire -#include for Linux - -Revision 1.9 2003/08/14 23:57:46 cheshire -Report if there is no answer at all from the target host - -Revision 1.8 2003/08/14 02:19:55 cheshire - Split generic ResourceRecord type into two separate types: AuthRecord and CacheRecord - -Revision 1.7 2003/08/12 19:56:26 cheshire -Update to APSL 2.0 - -Revision 1.6 2003/08/06 01:46:18 cheshire -Distinguish no answer from partial answer - -Revision 1.5 2003/08/05 23:56:26 cheshire -Update code to compile with the new mDNSCoreReceive() function that requires a TTL -(Right now mDNSPosix.c just reports 255 -- we should fix this) - -Revision 1.4 2003/08/04 17:24:48 cheshire -Combine the three separate A/AAAA/HINFO queries into a single qtype "ANY" query - -Revision 1.3 2003/08/04 17:14:08 cheshire -Do both AAAA queries in parallel - -Revision 1.2 2003/08/02 02:25:13 cheshire -Multiple improvements: Now displays host's name, and all v4 and v6 addresses, as well as HINFO record - -Revision 1.1 2003/08/01 02:20:02 cheshire -Add mDNSIdentify tool, used to discover what version of mDNSResponder a particular host is running - */ //************************************************************************************************************* @@ -169,24 +34,25 @@ Add mDNSIdentify tool, used to discover what version of mDNSResponder a particul #include #include #include -#include // For n_long, required by below -#include // For IPTOS_LOWDELAY etc. +#include // For n_long, required by below +#include // For IPTOS_LOWDELAY etc. #include #include -#include "mDNSEmbeddedAPI.h"// Defines the interface to the mDNS core code +#include "mDNSEmbeddedAPI.h" // Defines the interface to the mDNS core code #include "mDNSPosix.h" // Defines the specific types needed to run mDNS on this platform #include "ExampleClientApp.h" //************************************************************************************************************* // Globals -static mDNS mDNSStorage; // mDNS core uses this to store its globals +mDNS mDNSStorage; // mDNS core uses this to store its globals static mDNS_PlatformSupport PlatformStorage; // Stores this platform's globals #define RR_CACHE_SIZE 500 static CacheEntity gRRCache[RR_CACHE_SIZE]; +mDNSexport const char ProgramName[] = "mDNSIdentify"; -static volatile int StopNow; // 0 means running, 1 means stop because we got an answer, 2 means stop because of Ctrl-C +static volatile int StopNow; // 0 means running, 1 means stop because we got an answer, 2 means stop because of Ctrl-C static volatile int NumAnswers, NumAddr, NumAAAA, NumHINFO; static char hostname[MAX_ESCAPED_DOMAIN_NAME], hardware[256], software[256]; static mDNSAddr lastsrc, hostaddr, target; @@ -198,287 +64,312 @@ static mDNSOpaque16 lastid, id; // Special version of printf that knows how to print IP addresses, DNS-format name strings, etc. mDNSlocal mDNSu32 mprintf(const char *format, ...) IS_A_PRINTF_STYLE_FUNCTION(1,2); mDNSlocal mDNSu32 mprintf(const char *format, ...) - { - mDNSu32 length; - unsigned char buffer[512]; - va_list ptr; - va_start(ptr,format); - length = mDNS_vsnprintf((char *)buffer, sizeof(buffer), format, ptr); - va_end(ptr); - printf("%s", buffer); - return(length); - } +{ + mDNSu32 length; + unsigned char buffer[512]; + va_list ptr; + va_start(ptr,format); + length = mDNS_vsnprintf((char *)buffer, sizeof(buffer), format, ptr); + va_end(ptr); + printf("%s", buffer); + return(length); +} //************************************************************************************************************* // Main code mDNSexport void mDNSCoreReceive(mDNS *const m, DNSMessage *const msg, const mDNSu8 *const end, - const mDNSAddr *const srcaddr, const mDNSIPPort srcport, const mDNSAddr *const dstaddr, const mDNSIPPort dstport, - const mDNSInterfaceID InterfaceID) - { - (void)dstaddr; // Unused - // Snag copy of header ID, then call through - lastid = msg->h.id; - lastsrc = *srcaddr; - - // We *want* to allow off-net unicast responses here. - // For now, the simplest way to allow that is to pretend it was received via multicast so that mDNSCore doesn't reject the packet - __MDNS__mDNSCoreReceive(m, msg, end, srcaddr, srcport, &AllDNSLinkGroup_v4, dstport, InterfaceID); - } - -static void NameCallback(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, mDNSBool AddRecord) - { - (void)m; // Unused - (void)question; // Unused - (void)AddRecord;// Unused - if (!id.NotAnInteger) id = lastid; - if (answer->rrtype == kDNSType_PTR || answer->rrtype == kDNSType_CNAME) - { - ConvertDomainNameToCString(&answer->rdata->u.name, hostname); - StopNow = 1; - mprintf("%##s %s %##s\n", answer->name->c, DNSTypeName(answer->rrtype), answer->rdata->u.name.c); - } - } - -static void InfoCallback(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, mDNSBool AddRecord) - { - (void)m; // Unused - (void)question; // Unused - (void)AddRecord;// Unused - if (answer->rrtype == kDNSType_A) - { - if (!id.NotAnInteger) id = lastid; - NumAnswers++; - NumAddr++; - mprintf("%##s %s %.4a\n", answer->name->c, DNSTypeName(answer->rrtype), &answer->rdata->u.ipv4); - hostaddr.type = mDNSAddrType_IPv4; // Prefer v4 target to v6 target, for now - hostaddr.ip.v4 = answer->rdata->u.ipv4; - } - else if (answer->rrtype == kDNSType_AAAA) - { - if (!id.NotAnInteger) id = lastid; - NumAnswers++; - NumAAAA++; - mprintf("%##s %s %.16a\n", answer->name->c, DNSTypeName(answer->rrtype), &answer->rdata->u.ipv6); - if (!hostaddr.type) // Prefer v4 target to v6 target, for now - { - hostaddr.type = mDNSAddrType_IPv6; - hostaddr.ip.v6 = answer->rdata->u.ipv6; - } - } - else if (answer->rrtype == kDNSType_HINFO) - { - mDNSu8 *p = answer->rdata->u.data; - strncpy(hardware, (char*)(p+1), p[0]); - hardware[p[0]] = 0; - p += 1 + p[0]; - strncpy(software, (char*)(p+1), p[0]); - software[p[0]] = 0; - NumAnswers++; - NumHINFO++; - } - - // If we've got everything we're looking for, don't need to wait any more - if (NumHINFO && (NumAddr || NumAAAA)) StopNow = 1; - } - -static void ServicesCallback(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, mDNSBool AddRecord) - { - (void)m; // Unused - (void)question; // Unused - (void)AddRecord;// Unused - // Right now the mDNSCore targeted-query code is incomplete -- - // it issues targeted queries, but accepts answers from anywhere - // For now, we'll just filter responses here so we don't get confused by responses from someone else - if (answer->rrtype == kDNSType_PTR && mDNSSameAddress(&lastsrc, &target)) - { - NumAnswers++; - NumAddr++; - mprintf("%##s %s %##s\n", answer->name->c, DNSTypeName(answer->rrtype), answer->rdata->u.name.c); - StopNow = 1; - } - } - -mDNSexport void WaitForAnswer(mDNS *const m, int seconds) - { - struct timeval end; - gettimeofday(&end, NULL); - end.tv_sec += seconds; - StopNow = 0; - NumAnswers = 0; - while (!StopNow) - { - int nfds = 0; - fd_set readfds; - struct timeval now, remain = end; - int result; - - FD_ZERO(&readfds); - gettimeofday(&now, NULL); - if (remain.tv_usec < now.tv_usec) { remain.tv_usec += 1000000; remain.tv_sec--; } - if (remain.tv_sec < now.tv_sec) return; - remain.tv_usec -= now.tv_usec; - remain.tv_sec -= now.tv_sec; - mDNSPosixGetFDSet(m, &nfds, &readfds, &remain); - result = select(nfds, &readfds, NULL, NULL, &remain); - if (result >= 0) mDNSPosixProcessFDSet(m, &readfds); - else if (errno != EINTR) StopNow = 2; - } - } + const mDNSAddr *const srcaddr, const mDNSIPPort srcport, const mDNSAddr *const dstaddr, const mDNSIPPort dstport, + const mDNSInterfaceID InterfaceID) +{ + (void)dstaddr; // Unused + // Snag copy of header ID, then call through + lastid = msg->h.id; + lastsrc = *srcaddr; + + // We *want* to allow off-net unicast responses here. + // For now, the simplest way to allow that is to pretend it was received via multicast so that mDNSCore doesn't reject the packet + __MDNS__mDNSCoreReceive(m, msg, end, srcaddr, srcport, &AllDNSLinkGroup_v4, dstport, InterfaceID); +} + +mDNSlocal void NameCallback(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord) +{ + (void)m; // Unused + (void)question; // Unused + (void)AddRecord; // Unused + if (!id.NotAnInteger) id = lastid; + if (answer->rrtype == kDNSType_PTR || answer->rrtype == kDNSType_CNAME) + { + ConvertDomainNameToCString(&answer->rdata->u.name, hostname); + StopNow = 1; + mprintf("%##s %s %##s\n", answer->name->c, DNSTypeName(answer->rrtype), answer->rdata->u.name.c); + } +} + +mDNSlocal void InfoCallback(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord) +{ + (void)m; // Unused + (void)question; // Unused + (void)AddRecord; // Unused + if (answer->rrtype == kDNSType_A) + { + if (!id.NotAnInteger) id = lastid; + NumAnswers++; + NumAddr++; + mprintf("%##s %s %.4a\n", answer->name->c, DNSTypeName(answer->rrtype), &answer->rdata->u.ipv4); + hostaddr.type = mDNSAddrType_IPv4; // Prefer v4 target to v6 target, for now + hostaddr.ip.v4 = answer->rdata->u.ipv4; + } + else if (answer->rrtype == kDNSType_AAAA) + { + if (!id.NotAnInteger) id = lastid; + NumAnswers++; + NumAAAA++; + mprintf("%##s %s %.16a\n", answer->name->c, DNSTypeName(answer->rrtype), &answer->rdata->u.ipv6); + if (!hostaddr.type) // Prefer v4 target to v6 target, for now + { + hostaddr.type = mDNSAddrType_IPv6; + hostaddr.ip.v6 = answer->rdata->u.ipv6; + } + } + else if (answer->rrtype == kDNSType_HINFO) + { + mDNSu8 *p = answer->rdata->u.data; + strncpy(hardware, (char*)(p+1), p[0]); + hardware[p[0]] = 0; + p += 1 + p[0]; + strncpy(software, (char*)(p+1), p[0]); + software[p[0]] = 0; + NumAnswers++; + NumHINFO++; + } + + // If we've got everything we're looking for, don't need to wait any more + if (/*NumHINFO && */ (NumAddr || NumAAAA)) StopNow = 1; +} + +mDNSlocal void ServicesCallback(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord) +{ + (void)m; // Unused + (void)question; // Unused + (void)AddRecord; // Unused + // Right now the mDNSCore targeted-query code is incomplete -- + // it issues targeted queries, but accepts answers from anywhere + // For now, we'll just filter responses here so we don't get confused by responses from someone else + if (answer->rrtype == kDNSType_PTR && mDNSSameAddress(&lastsrc, &target)) + { + NumAnswers++; + mprintf("%##s %s %##s\n", answer->name->c, DNSTypeName(answer->rrtype), answer->rdata->u.name.c); + } +} + +mDNSlocal void WaitForAnswer(mDNS *const m, int seconds) +{ + struct timeval end; + gettimeofday(&end, NULL); + end.tv_sec += seconds; + StopNow = 0; + NumAnswers = 0; + while (!StopNow) + { + int nfds = 0; + fd_set readfds, writefds; + struct timeval now, remain = end; + int result; + + FD_ZERO(&readfds); + FD_ZERO(&writefds); + gettimeofday(&now, NULL); + if (remain.tv_usec < now.tv_usec) { remain.tv_usec += 1000000; remain.tv_sec--; } + if (remain.tv_sec < now.tv_sec) + { + if (!NumAnswers) printf("No response after %d seconds\n", seconds); + return; + } + remain.tv_usec -= now.tv_usec; + remain.tv_sec -= now.tv_sec; + mDNSPosixGetFDSet(m, &nfds, &readfds, &writefds, &remain); + result = select(nfds, &readfds, &writefds, NULL, &remain); + if (result >= 0) mDNSPosixProcessFDSet(m, &readfds, &writefds); + else if (errno != EINTR) StopNow = 2; + } +} mDNSlocal mStatus StartQuery(DNSQuestion *q, char *qname, mDNSu16 qtype, const mDNSAddr *target, mDNSQuestionCallback callback) - { - if (qname) MakeDomainNameFromDNSNameString(&q->qname, qname); - q->Target = target ? *target : zeroAddr; - q->TargetPort = MulticastDNSPort; - q->TargetQID = zeroID; - q->InterfaceID = mDNSInterface_Any; - q->qtype = qtype; - q->qclass = kDNSClass_IN; - q->LongLived = mDNSfalse; - q->ExpectUnique = mDNStrue; - q->ForceMCast = mDNStrue; // Query via multicast, even for apparently uDNS names like 1.1.1.17.in-addr.arpa. - q->QuestionCallback = callback; - q->QuestionContext = NULL; - - //mprintf("%##s %s ?\n", q->qname.c, DNSTypeName(qtype)); - return(mDNS_StartQuery(&mDNSStorage, q)); - } +{ + lastsrc = zeroAddr; + if (qname) MakeDomainNameFromDNSNameString(&q->qname, qname); + q->InterfaceID = mDNSInterface_Any; + q->flags = 0; + q->Target = target ? *target : zeroAddr; + q->TargetPort = MulticastDNSPort; + q->TargetQID = zeroID; + q->qtype = qtype; + q->qclass = kDNSClass_IN; + q->LongLived = mDNSfalse; + q->ExpectUnique = mDNSfalse; // Don't want to stop after the first response packet + q->ForceMCast = mDNStrue; // Query via multicast, even for apparently uDNS names like 1.1.1.17.in-addr.arpa. + q->ReturnIntermed = mDNStrue; + q->SuppressUnusable = mDNSfalse; + q->AppendSearchDomains = 0; + q->TimeoutQuestion = 0; + q->ValidationRequired = 0; + q->ValidatingResponse = 0; + q->WakeOnResolve = 0; + q->UseBackgroundTraffic = mDNSfalse; + q->ProxyQuestion = 0; + q->pid = mDNSPlatformGetPID(); + q->QuestionCallback = callback; + q->QuestionContext = NULL; + + //mprintf("%##s %s ?\n", q->qname.c, DNSTypeName(qtype)); + return(mDNS_StartQuery(&mDNSStorage, q)); +} mDNSlocal void DoOneQuery(DNSQuestion *q, char *qname, mDNSu16 qtype, const mDNSAddr *target, mDNSQuestionCallback callback) - { - mStatus status = StartQuery(q, qname, qtype, target, callback); - if (status != mStatus_NoError) - StopNow = 2; - else - { - WaitForAnswer(&mDNSStorage, 4); - mDNS_StopQuery(&mDNSStorage, q); - } - } +{ + mStatus status = StartQuery(q, qname, qtype, target, callback); + if (status != mStatus_NoError) + StopNow = 2; + else + { + WaitForAnswer(&mDNSStorage, 4); + mDNS_StopQuery(&mDNSStorage, q); + } +} mDNSlocal int DoQuery(DNSQuestion *q, char *qname, mDNSu16 qtype, const mDNSAddr *target, mDNSQuestionCallback callback) - { - DoOneQuery(q, qname, qtype, target, callback); - if (StopNow == 0 && target && target->type) - { - mprintf("%##s %s Trying multicast\n", q->qname.c, DNSTypeName(q->qtype)); - DoOneQuery(q, qname, qtype, NULL, callback); - } - if (StopNow == 0 && NumAnswers == 0) - mprintf("%##s %s *** No Answer ***\n", q->qname.c, DNSTypeName(q->qtype)); - return(StopNow); - } +{ + DoOneQuery(q, qname, qtype, target, callback); + if (StopNow == 0 && NumAnswers == 0 && target && target->type) + { + mprintf("%##s %s Trying multicast\n", q->qname.c, DNSTypeName(q->qtype)); + DoOneQuery(q, qname, qtype, NULL, callback); + } + if (StopNow == 0 && NumAnswers == 0) + mprintf("%##s %s *** No Answer ***\n", q->qname.c, DNSTypeName(q->qtype)); + return(StopNow); +} mDNSlocal void HandleSIG(int signal) - { - (void)signal; // Unused - debugf("%s",""); - debugf("HandleSIG"); - StopNow = 2; - } +{ + (void)signal; // Unused + debugf("%s",""); + debugf("HandleSIG"); + StopNow = 2; +} mDNSexport int main(int argc, char **argv) - { - const char *progname = strrchr(argv[0], '/') ? strrchr(argv[0], '/') + 1 : argv[0]; - int this_arg = 1; - mStatus status; - struct in_addr s4; +{ + const char *progname = strrchr(argv[0], '/') ? strrchr(argv[0], '/') + 1 : argv[0]; + int this_arg = 1; + mStatus status; + struct in_addr s4; #if HAVE_IPV6 - struct in6_addr s6; + struct in6_addr s6; #endif - char buffer[256]; - DNSQuestion q; - - if (argc < 2) goto usage; - - // Since this is a special command-line tool, we want LogMsg() errors to go to stderr, not syslog - mDNS_DebugMode = mDNStrue; - + char buffer[256]; + DNSQuestion q; + + if (argc < 2) goto usage; + + // Since this is a special command-line tool, we want LogMsg() errors to go to stderr, not syslog + mDNS_DebugMode = mDNStrue; + // Initialise the mDNS core. - status = mDNS_Init(&mDNSStorage, &PlatformStorage, - gRRCache, RR_CACHE_SIZE, - mDNS_Init_DontAdvertiseLocalAddresses, - mDNS_Init_NoInitCallback, mDNS_Init_NoInitCallbackContext); - if (status) { fprintf(stderr, "Daemon start: mDNS_Init failed %ld\n", status); return(status); } - - signal(SIGINT, HandleSIG); // SIGINT is what you get for a Ctrl-C - signal(SIGTERM, HandleSIG); - - while (this_arg < argc) - { - char *arg = argv[this_arg++]; - if (this_arg > 2) printf("\n"); - - lastid = id = zeroID; - hostaddr = target = zeroAddr; - hostname[0] = hardware[0] = software[0] = 0; - NumAddr = NumAAAA = NumHINFO = 0; - - if (inet_pton(AF_INET, arg, &s4) == 1) - { - mDNSu8 *p = (mDNSu8 *)&s4; - mDNS_snprintf(buffer, sizeof(buffer), "%d.%d.%d.%d.in-addr.arpa.", p[3], p[2], p[1], p[0]); - printf("%s\n", buffer); - target.type = mDNSAddrType_IPv4; - target.ip.v4.NotAnInteger = s4.s_addr; - DoQuery(&q, buffer, kDNSType_PTR, &target, NameCallback); - if (StopNow == 2) break; - } + status = mDNS_Init(&mDNSStorage, &PlatformStorage, + gRRCache, RR_CACHE_SIZE, + mDNS_Init_DontAdvertiseLocalAddresses, + mDNS_Init_NoInitCallback, mDNS_Init_NoInitCallbackContext); + if (status) { fprintf(stderr, "Daemon start: mDNS_Init failed %d\n", (int)status); return(status); } + + signal(SIGINT, HandleSIG); // SIGINT is what you get for a Ctrl-C + signal(SIGTERM, HandleSIG); + + while (this_arg < argc) + { + char *arg = argv[this_arg++]; + if (this_arg > 2) printf("\n"); + + lastid = id = zeroID; + hostaddr = target = zeroAddr; + hostname[0] = hardware[0] = software[0] = 0; + NumAddr = NumAAAA = NumHINFO = 0; + + if (inet_pton(AF_INET, arg, &s4) == 1) + { + mDNSu8 *p = (mDNSu8 *)&s4; + // Note: This is reverse order compared to a normal dotted-decimal IP address, so we can't use our customary "%.4a" format code + mDNS_snprintf(buffer, sizeof(buffer), "%d.%d.%d.%d.in-addr.arpa.", p[3], p[2], p[1], p[0]); + printf("%s\n", buffer); + target.type = mDNSAddrType_IPv4; + target.ip.v4.NotAnInteger = s4.s_addr; + DoQuery(&q, buffer, kDNSType_PTR, &target, NameCallback); + if (StopNow == 2) break; + } #if HAVE_IPV6 - else if (inet_pton(AF_INET6, arg, &s6) == 1) - { - int i; - mDNSu8 *p = (mDNSu8 *)&s6; - for (i = 0; i < 16; i++) - { - static const char hexValues[] = "0123456789ABCDEF"; - buffer[i * 4 ] = hexValues[p[15-i] & 0x0F]; - buffer[i * 4 + 1] = '.'; - buffer[i * 4 + 2] = hexValues[p[15-i] >> 4]; - buffer[i * 4 + 3] = '.'; - } - mDNS_snprintf(&buffer[64], sizeof(buffer)-64, "ip6.arpa."); - target.type = mDNSAddrType_IPv6; - bcopy(&s6, &target.ip.v6, sizeof(target.ip.v6)); - DoQuery(&q, buffer, kDNSType_PTR, &target, NameCallback); - if (StopNow == 2) break; - } + else if (inet_pton(AF_INET6, arg, &s6) == 1) + { + int i; + mDNSu8 *p = (mDNSu8 *)&s6; + for (i = 0; i < 16; i++) + { + static const char hexValues[] = "0123456789ABCDEF"; + buffer[i * 4 ] = hexValues[p[15-i] & 0x0F]; + buffer[i * 4 + 1] = '.'; + buffer[i * 4 + 2] = hexValues[p[15-i] >> 4]; + buffer[i * 4 + 3] = '.'; + } + mDNS_snprintf(&buffer[64], sizeof(buffer)-64, "ip6.arpa."); + target.type = mDNSAddrType_IPv6; + mDNSPlatformMemCopy(&target.ip.v6, &s6, sizeof(target.ip.v6)); + DoQuery(&q, buffer, kDNSType_PTR, &target, NameCallback); + if (StopNow == 2) break; + } #endif - else - strcpy(hostname, arg); - - // Now we have the host name; get its A, AAAA, and HINFO - if (hostname[0]) DoQuery(&q, hostname, kDNSQType_ANY, &target, InfoCallback); - if (StopNow == 2) break; - - if (hardware[0] || software[0]) - { - DNSQuestion q1; - printf("HINFO Hardware: %s\n", hardware); - printf("HINFO Software: %s\n", software); - // We need to make sure the services query is targeted - if (target.type == 0) target = hostaddr; - StartQuery(&q1, "_services._dns-sd._udp.local.", kDNSQType_ANY, &target, ServicesCallback); - WaitForAnswer(&mDNSStorage, 4); - mDNS_StopQuery(&mDNSStorage, &q1); - if (StopNow == 2) break; - } - else if (NumAnswers) - { - printf("Host has no HINFO record; Best guess is "); - if (id.b[1]) printf("mDNSResponder-%d\n", id.b[1]); - else if (NumAAAA) printf("very early Panther build (mDNSResponder-33 or earlier)\n"); - else printf("Jaguar version of mDNSResponder with no IPv6 support\n"); - } - else - printf("Incorrect dot-local hostname, address, or no mDNSResponder running on that machine\n"); - } - - mDNS_Close(&mDNSStorage); - return(0); + else + { + if (strlen(arg) >= sizeof(hostname)) + { + fprintf(stderr, "hostname must be < %d characters\n", (int)sizeof(hostname)); + goto usage; + } + strcpy(hostname, arg); + } + + // Now we have the host name; get its A, AAAA, and HINFO + if (hostname[0]) DoQuery(&q, hostname, kDNSQType_ANY, &target, InfoCallback); + if (StopNow == 2) break; + + if (hardware[0] || software[0]) + { + printf("HINFO Hardware: %s\n", hardware); + printf("HINFO Software: %s\n", software); + } + else if (NumAnswers) printf("%s has no HINFO record\n", hostname); + else printf("Incorrect dot-local hostname, address, or no mDNSResponder running on that machine\n"); + + if (NumAnswers) + { + // Because of the way we use lastsrc in ServicesCallback, we need to clear the cache to make sure we're getting fresh answers + mDNS *const m = &mDNSStorage; + mDNSu32 slot; + CacheGroup *cg; + CacheRecord *rr; + FORALL_CACHERECORDS(slot, cg, rr) + { + mDNS_PurgeCacheResourceRecord(m, rr); + } + if (target.type == 0) target = hostaddr; // Make sure the services query is targeted + DoQuery(&q, "_services._dns-sd._udp.local.", kDNSType_PTR, &target, ServicesCallback); + if (StopNow == 2) break; + } + } + + mDNS_Close(&mDNSStorage); + return(0); usage: - fprintf(stderr, "%s or or ...\n", progname); - return(-1); - } + fprintf(stderr, "Usage: %s or or ...\n", progname); + return(-1); +}