147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt/* -*- Mode: C; tab-width: 4 -*- 247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt * 347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt * Copyright (c) 2002-2004 Apple Computer, Inc. All rights reserved. 447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt * 547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt * Licensed under the Apache License, Version 2.0 (the "License"); 647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt * you may not use this file except in compliance with the License. 747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt * You may obtain a copy of the License at 847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt * 947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt * http://www.apache.org/licenses/LICENSE-2.0 1047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt * 1147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt * Unless required by applicable law or agreed to in writing, software 1247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt * distributed under the License is distributed on an "AS IS" BASIS, 1347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt * See the License for the specific language governing permissions and 1547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt * limitations under the License. 1647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt * 1747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt * Formatting notes: 1847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt * This code follows the "Whitesmiths style" C indentation rules. Plenty of discussion 1947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt * on C indentation can be found on the web, such as <http://www.kafejo.com/komp/1tbs.htm>, 2047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt * but for the sake of brevity here I will say just this: Curly braces are not syntactially 2147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt * part of an "if" statement; they are the beginning and ending markers of a compound statement; 2247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt * therefore common sense dictates that if they are part of a compound statement then they 2347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt * should be indented to the same level as everything else in that compound statement. 2447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt * Indenting curly braces at the same level as the "if" implies that curly braces are 2547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt * part of the "if", which is false. (This is as misleading as people who write "char* x,y;" 2647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt * thinking that variables x and y are both of type "char*" -- and anyone who doesn't 2747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt * understand why variable y is not of type "char*" just proves the point that poor code 2847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt * layout leads people to unfortunate misunderstandings about how the C language really works.) 2947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt */ 3047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 3147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt//************************************************************************************************************* 3247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// Incorporate mDNS.c functionality 3347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 3447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// We want to use the functionality provided by "mDNS.c", 3547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// except we'll sneak a peek at the packets before forwarding them to the normal mDNSCoreReceive() routine 3647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#define mDNSCoreReceive __MDNS__mDNSCoreReceive 3747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include "mDNS.c" 3847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#undef mDNSCoreReceive 3947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 4047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt//************************************************************************************************************* 4147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// Headers 4247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 4347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include <unistd.h> 4447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include <stdio.h> 4547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include <string.h> 4647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include <errno.h> 4747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include <sys/socket.h> 4847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include <netinet/in.h> 4947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include <netinet/in_systm.h> // For n_long, required by <netinet/ip.h> below 5047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include <netinet/ip.h> // For IPTOS_LOWDELAY etc. 5147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include <arpa/inet.h> 5247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include <signal.h> 5347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 5447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include "mDNSEmbeddedAPI.h"// Defines the interface to the mDNS core code 5547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include "mDNSPosix.h" // Defines the specific types needed to run mDNS on this platform 5647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#include "ExampleClientApp.h" 5747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 5847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt//************************************************************************************************************* 5947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// Globals 6047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 6147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic mDNS mDNSStorage; // mDNS core uses this to store its globals 6247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic mDNS_PlatformSupport PlatformStorage; // Stores this platform's globals 6347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#define RR_CACHE_SIZE 500 6447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic CacheEntity gRRCache[RR_CACHE_SIZE]; 6547e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSexport const char ProgramName[] = "mDNSIdentify"; 6647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 6747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic volatile int StopNow; // 0 means running, 1 means stop because we got an answer, 2 means stop because of Ctrl-C 6847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic volatile int NumAnswers, NumAddr, NumAAAA, NumHINFO; 6947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic char hostname[MAX_ESCAPED_DOMAIN_NAME], hardware[256], software[256]; 7047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic mDNSAddr lastsrc, hostaddr, target; 7147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltstatic mDNSOpaque16 lastid, id; 7247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 7347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt//************************************************************************************************************* 7447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// Utilities 7547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 7647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// Special version of printf that knows how to print IP addresses, DNS-format name strings, etc. 7747e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSlocal mDNSu32 mprintf(const char *format, ...) IS_A_PRINTF_STYLE_FUNCTION(1,2); 7847e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSlocal mDNSu32 mprintf(const char *format, ...) 7947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 8047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNSu32 length; 8147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt unsigned char buffer[512]; 8247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt va_list ptr; 8347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt va_start(ptr,format); 8447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt length = mDNS_vsnprintf((char *)buffer, sizeof(buffer), format, ptr); 8547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt va_end(ptr); 8647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt printf("%s", buffer); 8747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt return(length); 8847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 8947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 9047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt//************************************************************************************************************* 9147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt// Main code 9247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 9347e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSexport void mDNSCoreReceive(mDNS *const m, DNSMessage *const msg, const mDNSu8 *const end, 9447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt const mDNSAddr *const srcaddr, const mDNSIPPort srcport, const mDNSAddr *const dstaddr, const mDNSIPPort dstport, 9547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt const mDNSInterfaceID InterfaceID) 9647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 9747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt (void)dstaddr; // Unused 9847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // Snag copy of header ID, then call through 9947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt lastid = msg->h.id; 10047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt lastsrc = *srcaddr; 10147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 10247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // We *want* to allow off-net unicast responses here. 10347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // For now, the simplest way to allow that is to pretend it was received via multicast so that mDNSCore doesn't reject the packet 10447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt __MDNS__mDNSCoreReceive(m, msg, end, srcaddr, srcport, &AllDNSLinkGroup_v4, dstport, InterfaceID); 10547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 10647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 10747e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSlocal void NameCallback(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord) 10847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 10947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt (void)m; // Unused 11047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt (void)question; // Unused 11147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt (void)AddRecord;// Unused 11247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (!id.NotAnInteger) id = lastid; 11347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (answer->rrtype == kDNSType_PTR || answer->rrtype == kDNSType_CNAME) 11447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 11547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt ConvertDomainNameToCString(&answer->rdata->u.name, hostname); 11647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt StopNow = 1; 11747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mprintf("%##s %s %##s\n", answer->name->c, DNSTypeName(answer->rrtype), answer->rdata->u.name.c); 11847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 11947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 12047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 12147e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSlocal void InfoCallback(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord) 12247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 12347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt (void)m; // Unused 12447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt (void)question; // Unused 12547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt (void)AddRecord;// Unused 12647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (answer->rrtype == kDNSType_A) 12747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 12847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (!id.NotAnInteger) id = lastid; 12947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt NumAnswers++; 13047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt NumAddr++; 13147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mprintf("%##s %s %.4a\n", answer->name->c, DNSTypeName(answer->rrtype), &answer->rdata->u.ipv4); 13247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt hostaddr.type = mDNSAddrType_IPv4; // Prefer v4 target to v6 target, for now 13347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt hostaddr.ip.v4 = answer->rdata->u.ipv4; 13447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 13547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt else if (answer->rrtype == kDNSType_AAAA) 13647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 13747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (!id.NotAnInteger) id = lastid; 13847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt NumAnswers++; 13947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt NumAAAA++; 14047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mprintf("%##s %s %.16a\n", answer->name->c, DNSTypeName(answer->rrtype), &answer->rdata->u.ipv6); 14147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (!hostaddr.type) // Prefer v4 target to v6 target, for now 14247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 14347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt hostaddr.type = mDNSAddrType_IPv6; 14447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt hostaddr.ip.v6 = answer->rdata->u.ipv6; 14547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 14647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 14747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt else if (answer->rrtype == kDNSType_HINFO) 14847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 14947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNSu8 *p = answer->rdata->u.data; 15047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt strncpy(hardware, (char*)(p+1), p[0]); 15147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt hardware[p[0]] = 0; 15247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt p += 1 + p[0]; 15347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt strncpy(software, (char*)(p+1), p[0]); 15447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt software[p[0]] = 0; 15547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt NumAnswers++; 15647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt NumHINFO++; 15747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 15847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 15947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // If we've got everything we're looking for, don't need to wait any more 16047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (/*NumHINFO && */ (NumAddr || NumAAAA)) StopNow = 1; 16147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 16247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 16347e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSlocal void ServicesCallback(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord) 16447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 16547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt (void)m; // Unused 16647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt (void)question; // Unused 16747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt (void)AddRecord;// Unused 16847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // Right now the mDNSCore targeted-query code is incomplete -- 16947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // it issues targeted queries, but accepts answers from anywhere 17047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // For now, we'll just filter responses here so we don't get confused by responses from someone else 17147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (answer->rrtype == kDNSType_PTR && mDNSSameAddress(&lastsrc, &target)) 17247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 17347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt NumAnswers++; 17447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mprintf("%##s %s %##s\n", answer->name->c, DNSTypeName(answer->rrtype), answer->rdata->u.name.c); 17547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 17647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 17747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 17847e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSlocal void WaitForAnswer(mDNS *const m, int seconds) 17947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 18047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt struct timeval end; 18147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt gettimeofday(&end, NULL); 18247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt end.tv_sec += seconds; 18347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt StopNow = 0; 18447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt NumAnswers = 0; 18547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt while (!StopNow) 18647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 18747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt int nfds = 0; 18847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt fd_set readfds; 18947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt struct timeval now, remain = end; 19047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt int result; 19147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 19247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt FD_ZERO(&readfds); 19347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt gettimeofday(&now, NULL); 19447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (remain.tv_usec < now.tv_usec) { remain.tv_usec += 1000000; remain.tv_sec--; } 19547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (remain.tv_sec < now.tv_sec) 19647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 19747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (!NumAnswers) printf("No response after %d seconds\n", seconds); 19847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt return; 19947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 20047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt remain.tv_usec -= now.tv_usec; 20147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt remain.tv_sec -= now.tv_sec; 20247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNSPosixGetFDSet(m, &nfds, &readfds, &remain); 20347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt result = select(nfds, &readfds, NULL, NULL, &remain); 20447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (result >= 0) mDNSPosixProcessFDSet(m, &readfds); 20547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt else if (errno != EINTR) StopNow = 2; 20647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 20747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 20847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 20947e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSlocal mStatus StartQuery(DNSQuestion *q, char *qname, mDNSu16 qtype, const mDNSAddr *target, mDNSQuestionCallback callback) 21047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 21147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt lastsrc = zeroAddr; 21247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (qname) MakeDomainNameFromDNSNameString(&q->qname, qname); 21347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt q->InterfaceID = mDNSInterface_Any; 21447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt q->Target = target ? *target : zeroAddr; 21547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt q->TargetPort = MulticastDNSPort; 21647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt q->TargetQID = zeroID; 21747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt q->qtype = qtype; 21847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt q->qclass = kDNSClass_IN; 21947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt q->LongLived = mDNSfalse; 22047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt q->ExpectUnique = mDNSfalse; // Don't want to stop after the first response packet 22147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt q->ForceMCast = mDNStrue; // Query via multicast, even for apparently uDNS names like 1.1.1.17.in-addr.arpa. 22247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt q->ReturnIntermed = mDNStrue; 22347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt q->SuppressUnusable = mDNSfalse; 22447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt q->SearchListIndex = 0; 22547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt q->AppendSearchDomains = 0; 22647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt q->RetryWithSearchDomains = mDNSfalse; 22747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt q->TimeoutQuestion = 0; 22847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt q->WakeOnResolve = 0; 22947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt q->qnameOrig = mDNSNULL; 23047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt q->QuestionCallback = callback; 23147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt q->QuestionContext = NULL; 23247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 23347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt //mprintf("%##s %s ?\n", q->qname.c, DNSTypeName(qtype)); 23447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt return(mDNS_StartQuery(&mDNSStorage, q)); 23547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 23647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 23747e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSlocal void DoOneQuery(DNSQuestion *q, char *qname, mDNSu16 qtype, const mDNSAddr *target, mDNSQuestionCallback callback) 23847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 23947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mStatus status = StartQuery(q, qname, qtype, target, callback); 24047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (status != mStatus_NoError) 24147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt StopNow = 2; 24247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt else 24347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 24447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt WaitForAnswer(&mDNSStorage, 4); 24547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNS_StopQuery(&mDNSStorage, q); 24647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 24747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 24847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 24947e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSlocal int DoQuery(DNSQuestion *q, char *qname, mDNSu16 qtype, const mDNSAddr *target, mDNSQuestionCallback callback) 25047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 25147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt DoOneQuery(q, qname, qtype, target, callback); 25247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (StopNow == 0 && NumAnswers == 0 && target && target->type) 25347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 25447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mprintf("%##s %s Trying multicast\n", q->qname.c, DNSTypeName(q->qtype)); 25547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt DoOneQuery(q, qname, qtype, NULL, callback); 25647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 25747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (StopNow == 0 && NumAnswers == 0) 25847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mprintf("%##s %s *** No Answer ***\n", q->qname.c, DNSTypeName(q->qtype)); 25947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt return(StopNow); 26047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 26147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 26247e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSlocal void HandleSIG(int signal) 26347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 26447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt (void)signal; // Unused 26547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt debugf("%s",""); 26647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt debugf("HandleSIG"); 26747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt StopNow = 2; 26847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 26947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 27047e4cebad7397422144bb03a21f3f7682c062c4aRobert GreenwaltmDNSexport int main(int argc, char **argv) 27147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 27247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt const char *progname = strrchr(argv[0], '/') ? strrchr(argv[0], '/') + 1 : argv[0]; 27347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt int this_arg = 1; 27447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mStatus status; 27547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt struct in_addr s4; 27647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#if HAVE_IPV6 27747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt struct in6_addr s6; 27847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#endif 27947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt char buffer[256]; 28047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt DNSQuestion q; 28147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 28247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (argc < 2) goto usage; 28347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 28447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // Since this is a special command-line tool, we want LogMsg() errors to go to stderr, not syslog 28547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNS_DebugMode = mDNStrue; 28647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 28747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // Initialise the mDNS core. 28847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt status = mDNS_Init(&mDNSStorage, &PlatformStorage, 28947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt gRRCache, RR_CACHE_SIZE, 29047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNS_Init_DontAdvertiseLocalAddresses, 29147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNS_Init_NoInitCallback, mDNS_Init_NoInitCallbackContext); 29247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (status) { fprintf(stderr, "Daemon start: mDNS_Init failed %d\n", (int)status); return(status); } 29347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 29447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt signal(SIGINT, HandleSIG); // SIGINT is what you get for a Ctrl-C 29547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt signal(SIGTERM, HandleSIG); 29647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 29747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt while (this_arg < argc) 29847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 29947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt char *arg = argv[this_arg++]; 30047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (this_arg > 2) printf("\n"); 30147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 30247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt lastid = id = zeroID; 30347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt hostaddr = target = zeroAddr; 30447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt hostname[0] = hardware[0] = software[0] = 0; 30547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt NumAddr = NumAAAA = NumHINFO = 0; 30647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 30747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (inet_pton(AF_INET, arg, &s4) == 1) 30847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 30947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNSu8 *p = (mDNSu8 *)&s4; 31047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // Note: This is reverse order compared to a normal dotted-decimal IP address, so we can't use our customary "%.4a" format code 31147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNS_snprintf(buffer, sizeof(buffer), "%d.%d.%d.%d.in-addr.arpa.", p[3], p[2], p[1], p[0]); 31247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt printf("%s\n", buffer); 31347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt target.type = mDNSAddrType_IPv4; 31447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt target.ip.v4.NotAnInteger = s4.s_addr; 31547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt DoQuery(&q, buffer, kDNSType_PTR, &target, NameCallback); 31647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (StopNow == 2) break; 31747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 31847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#if HAVE_IPV6 31947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt else if (inet_pton(AF_INET6, arg, &s6) == 1) 32047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 32147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt int i; 32247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNSu8 *p = (mDNSu8 *)&s6; 32347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt for (i = 0; i < 16; i++) 32447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 32547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt static const char hexValues[] = "0123456789ABCDEF"; 32647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt buffer[i * 4 ] = hexValues[p[15-i] & 0x0F]; 32747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt buffer[i * 4 + 1] = '.'; 32847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt buffer[i * 4 + 2] = hexValues[p[15-i] >> 4]; 32947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt buffer[i * 4 + 3] = '.'; 33047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 33147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNS_snprintf(&buffer[64], sizeof(buffer)-64, "ip6.arpa."); 33247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt target.type = mDNSAddrType_IPv6; 33347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNSPlatformMemCopy(&target.ip.v6, &s6, sizeof(target.ip.v6)); 33447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt DoQuery(&q, buffer, kDNSType_PTR, &target, NameCallback); 33547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (StopNow == 2) break; 33647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 33747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt#endif 33847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt else { 33947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (strlen(arg) >= sizeof(hostname)) { 34047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt fprintf(stderr, "hostname must be < %d characters\n", (int)sizeof(hostname)); 34147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt goto usage; 34247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 34347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt strcpy(hostname, arg); 34447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 34547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 34647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // Now we have the host name; get its A, AAAA, and HINFO 34747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (hostname[0]) DoQuery(&q, hostname, kDNSQType_ANY, &target, InfoCallback); 34847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (StopNow == 2) break; 34947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 35047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (hardware[0] || software[0]) 35147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 35247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt printf("HINFO Hardware: %s\n", hardware); 35347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt printf("HINFO Software: %s\n", software); 35447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 35547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt else if (NumAnswers) printf("%s has no HINFO record\n", hostname); 35647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt else printf("Incorrect dot-local hostname, address, or no mDNSResponder running on that machine\n"); 35747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 35847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (NumAnswers) 35947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt { 36047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt // Because of the way we use lastsrc in ServicesCallback, we need to clear the cache to make sure we're getting fresh answers 36147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNS *const m = &mDNSStorage; 36247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNSu32 slot; 36347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt CacheGroup *cg; 36447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt CacheRecord *rr; 36547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt FORALL_CACHERECORDS(slot, cg, rr) mDNS_PurgeCacheResourceRecord(m, rr); 36647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (target.type == 0) target = hostaddr; // Make sure the services query is targeted 36747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt DoQuery(&q, "_services._dns-sd._udp.local.", kDNSType_PTR, &target, ServicesCallback); 36847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt if (StopNow == 2) break; 36947e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 37047e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 37147e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 37247e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt mDNS_Close(&mDNSStorage); 37347e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt return(0); 37447e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt 37547e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwaltusage: 37647e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt fprintf(stderr, "Usage: %s <dot-local hostname> or <IPv4 address> or <IPv6 address> ...\n", progname); 37747e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt return(-1); 37847e4cebad7397422144bb03a21f3f7682c062c4aRobert Greenwalt } 379