1*48a54d36SAndroid Build Coastguard Worker /* -*- Mode: C; tab-width: 4 -*-
2*48a54d36SAndroid Build Coastguard Worker *
3*48a54d36SAndroid Build Coastguard Worker * Copyright (c) 2002-2004 Apple Computer, Inc. All rights reserved.
4*48a54d36SAndroid Build Coastguard Worker *
5*48a54d36SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
6*48a54d36SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
7*48a54d36SAndroid Build Coastguard Worker * You may obtain a copy of the License at
8*48a54d36SAndroid Build Coastguard Worker *
9*48a54d36SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
10*48a54d36SAndroid Build Coastguard Worker *
11*48a54d36SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
12*48a54d36SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
13*48a54d36SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14*48a54d36SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
15*48a54d36SAndroid Build Coastguard Worker * limitations under the License.
16*48a54d36SAndroid Build Coastguard Worker *
17*48a54d36SAndroid Build Coastguard Worker * Formatting notes:
18*48a54d36SAndroid Build Coastguard Worker * This code follows the "Whitesmiths style" C indentation rules. Plenty of discussion
19*48a54d36SAndroid Build Coastguard Worker * on C indentation can be found on the web, such as <http://www.kafejo.com/komp/1tbs.htm>,
20*48a54d36SAndroid Build Coastguard Worker * but for the sake of brevity here I will say just this: Curly braces are not syntactially
21*48a54d36SAndroid Build Coastguard Worker * part of an "if" statement; they are the beginning and ending markers of a compound statement;
22*48a54d36SAndroid Build Coastguard Worker * therefore common sense dictates that if they are part of a compound statement then they
23*48a54d36SAndroid Build Coastguard Worker * should be indented to the same level as everything else in that compound statement.
24*48a54d36SAndroid Build Coastguard Worker * Indenting curly braces at the same level as the "if" implies that curly braces are
25*48a54d36SAndroid Build Coastguard Worker * part of the "if", which is false. (This is as misleading as people who write "char* x,y;"
26*48a54d36SAndroid Build Coastguard Worker * thinking that variables x and y are both of type "char*" -- and anyone who doesn't
27*48a54d36SAndroid Build Coastguard Worker * understand why variable y is not of type "char*" just proves the point that poor code
28*48a54d36SAndroid Build Coastguard Worker * layout leads people to unfortunate misunderstandings about how the C language really works.)
29*48a54d36SAndroid Build Coastguard Worker */
30*48a54d36SAndroid Build Coastguard Worker
31*48a54d36SAndroid Build Coastguard Worker //*************************************************************************************************************
32*48a54d36SAndroid Build Coastguard Worker // Incorporate mDNS.c functionality
33*48a54d36SAndroid Build Coastguard Worker
34*48a54d36SAndroid Build Coastguard Worker // We want to use the functionality provided by "mDNS.c",
35*48a54d36SAndroid Build Coastguard Worker // except we'll sneak a peek at the packets before forwarding them to the normal mDNSCoreReceive() routine
36*48a54d36SAndroid Build Coastguard Worker #define mDNSCoreReceive __MDNS__mDNSCoreReceive
37*48a54d36SAndroid Build Coastguard Worker #include "mDNS.c"
38*48a54d36SAndroid Build Coastguard Worker #undef mDNSCoreReceive
39*48a54d36SAndroid Build Coastguard Worker
40*48a54d36SAndroid Build Coastguard Worker //*************************************************************************************************************
41*48a54d36SAndroid Build Coastguard Worker // Headers
42*48a54d36SAndroid Build Coastguard Worker
43*48a54d36SAndroid Build Coastguard Worker #include <unistd.h>
44*48a54d36SAndroid Build Coastguard Worker #include <stdio.h>
45*48a54d36SAndroid Build Coastguard Worker #include <string.h>
46*48a54d36SAndroid Build Coastguard Worker #include <errno.h>
47*48a54d36SAndroid Build Coastguard Worker #include <sys/socket.h>
48*48a54d36SAndroid Build Coastguard Worker #include <netinet/in.h>
49*48a54d36SAndroid Build Coastguard Worker #include <netinet/in_systm.h> // For n_long, required by <netinet/ip.h> below
50*48a54d36SAndroid Build Coastguard Worker #include <netinet/ip.h> // For IPTOS_LOWDELAY etc.
51*48a54d36SAndroid Build Coastguard Worker #include <arpa/inet.h>
52*48a54d36SAndroid Build Coastguard Worker #include <signal.h>
53*48a54d36SAndroid Build Coastguard Worker
54*48a54d36SAndroid Build Coastguard Worker #include "mDNSEmbeddedAPI.h"// Defines the interface to the mDNS core code
55*48a54d36SAndroid Build Coastguard Worker #include "mDNSPosix.h" // Defines the specific types needed to run mDNS on this platform
56*48a54d36SAndroid Build Coastguard Worker #include "ExampleClientApp.h"
57*48a54d36SAndroid Build Coastguard Worker
58*48a54d36SAndroid Build Coastguard Worker //*************************************************************************************************************
59*48a54d36SAndroid Build Coastguard Worker // Globals
60*48a54d36SAndroid Build Coastguard Worker
61*48a54d36SAndroid Build Coastguard Worker static mDNS mDNSStorage; // mDNS core uses this to store its globals
62*48a54d36SAndroid Build Coastguard Worker static mDNS_PlatformSupport PlatformStorage; // Stores this platform's globals
63*48a54d36SAndroid Build Coastguard Worker #define RR_CACHE_SIZE 500
64*48a54d36SAndroid Build Coastguard Worker static CacheEntity gRRCache[RR_CACHE_SIZE];
65*48a54d36SAndroid Build Coastguard Worker mDNSexport const char ProgramName[] = "mDNSIdentify";
66*48a54d36SAndroid Build Coastguard Worker
67*48a54d36SAndroid Build Coastguard Worker static volatile int StopNow; // 0 means running, 1 means stop because we got an answer, 2 means stop because of Ctrl-C
68*48a54d36SAndroid Build Coastguard Worker static volatile int NumAnswers, NumAddr, NumAAAA, NumHINFO;
69*48a54d36SAndroid Build Coastguard Worker static char hostname[MAX_ESCAPED_DOMAIN_NAME], hardware[256], software[256];
70*48a54d36SAndroid Build Coastguard Worker static mDNSAddr lastsrc, hostaddr, target;
71*48a54d36SAndroid Build Coastguard Worker static mDNSOpaque16 lastid, id;
72*48a54d36SAndroid Build Coastguard Worker
73*48a54d36SAndroid Build Coastguard Worker //*************************************************************************************************************
74*48a54d36SAndroid Build Coastguard Worker // Utilities
75*48a54d36SAndroid Build Coastguard Worker
76*48a54d36SAndroid Build Coastguard Worker // Special version of printf that knows how to print IP addresses, DNS-format name strings, etc.
77*48a54d36SAndroid Build Coastguard Worker mDNSlocal mDNSu32 mprintf(const char *format, ...) IS_A_PRINTF_STYLE_FUNCTION(1,2);
mprintf(const char * format,...)78*48a54d36SAndroid Build Coastguard Worker mDNSlocal mDNSu32 mprintf(const char *format, ...)
79*48a54d36SAndroid Build Coastguard Worker {
80*48a54d36SAndroid Build Coastguard Worker mDNSu32 length;
81*48a54d36SAndroid Build Coastguard Worker unsigned char buffer[512];
82*48a54d36SAndroid Build Coastguard Worker va_list ptr;
83*48a54d36SAndroid Build Coastguard Worker va_start(ptr,format);
84*48a54d36SAndroid Build Coastguard Worker length = mDNS_vsnprintf((char *)buffer, sizeof(buffer), format, ptr);
85*48a54d36SAndroid Build Coastguard Worker va_end(ptr);
86*48a54d36SAndroid Build Coastguard Worker printf("%s", buffer);
87*48a54d36SAndroid Build Coastguard Worker return(length);
88*48a54d36SAndroid Build Coastguard Worker }
89*48a54d36SAndroid Build Coastguard Worker
90*48a54d36SAndroid Build Coastguard Worker //*************************************************************************************************************
91*48a54d36SAndroid Build Coastguard Worker // Main code
92*48a54d36SAndroid Build Coastguard Worker
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)93*48a54d36SAndroid Build Coastguard Worker mDNSexport void mDNSCoreReceive(mDNS *const m, DNSMessage *const msg, const mDNSu8 *const end,
94*48a54d36SAndroid Build Coastguard Worker const mDNSAddr *const srcaddr, const mDNSIPPort srcport, const mDNSAddr *const dstaddr, const mDNSIPPort dstport,
95*48a54d36SAndroid Build Coastguard Worker const mDNSInterfaceID InterfaceID)
96*48a54d36SAndroid Build Coastguard Worker {
97*48a54d36SAndroid Build Coastguard Worker (void)dstaddr; // Unused
98*48a54d36SAndroid Build Coastguard Worker // Snag copy of header ID, then call through
99*48a54d36SAndroid Build Coastguard Worker lastid = msg->h.id;
100*48a54d36SAndroid Build Coastguard Worker lastsrc = *srcaddr;
101*48a54d36SAndroid Build Coastguard Worker
102*48a54d36SAndroid Build Coastguard Worker // We *want* to allow off-net unicast responses here.
103*48a54d36SAndroid Build Coastguard Worker // For now, the simplest way to allow that is to pretend it was received via multicast so that mDNSCore doesn't reject the packet
104*48a54d36SAndroid Build Coastguard Worker __MDNS__mDNSCoreReceive(m, msg, end, srcaddr, srcport, &AllDNSLinkGroup_v4, dstport, InterfaceID);
105*48a54d36SAndroid Build Coastguard Worker }
106*48a54d36SAndroid Build Coastguard Worker
NameCallback(mDNS * const m,DNSQuestion * question,const ResourceRecord * const answer,QC_result AddRecord)107*48a54d36SAndroid Build Coastguard Worker mDNSlocal void NameCallback(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord)
108*48a54d36SAndroid Build Coastguard Worker {
109*48a54d36SAndroid Build Coastguard Worker (void)m; // Unused
110*48a54d36SAndroid Build Coastguard Worker (void)question; // Unused
111*48a54d36SAndroid Build Coastguard Worker (void)AddRecord;// Unused
112*48a54d36SAndroid Build Coastguard Worker if (!id.NotAnInteger) id = lastid;
113*48a54d36SAndroid Build Coastguard Worker if (answer->rrtype == kDNSType_PTR || answer->rrtype == kDNSType_CNAME)
114*48a54d36SAndroid Build Coastguard Worker {
115*48a54d36SAndroid Build Coastguard Worker ConvertDomainNameToCString(&answer->rdata->u.name, hostname);
116*48a54d36SAndroid Build Coastguard Worker StopNow = 1;
117*48a54d36SAndroid Build Coastguard Worker mprintf("%##s %s %##s\n", answer->name->c, DNSTypeName(answer->rrtype), answer->rdata->u.name.c);
118*48a54d36SAndroid Build Coastguard Worker }
119*48a54d36SAndroid Build Coastguard Worker }
120*48a54d36SAndroid Build Coastguard Worker
InfoCallback(mDNS * const m,DNSQuestion * question,const ResourceRecord * const answer,QC_result AddRecord)121*48a54d36SAndroid Build Coastguard Worker mDNSlocal void InfoCallback(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord)
122*48a54d36SAndroid Build Coastguard Worker {
123*48a54d36SAndroid Build Coastguard Worker (void)m; // Unused
124*48a54d36SAndroid Build Coastguard Worker (void)question; // Unused
125*48a54d36SAndroid Build Coastguard Worker (void)AddRecord;// Unused
126*48a54d36SAndroid Build Coastguard Worker if (answer->rrtype == kDNSType_A)
127*48a54d36SAndroid Build Coastguard Worker {
128*48a54d36SAndroid Build Coastguard Worker if (!id.NotAnInteger) id = lastid;
129*48a54d36SAndroid Build Coastguard Worker NumAnswers++;
130*48a54d36SAndroid Build Coastguard Worker NumAddr++;
131*48a54d36SAndroid Build Coastguard Worker mprintf("%##s %s %.4a\n", answer->name->c, DNSTypeName(answer->rrtype), &answer->rdata->u.ipv4);
132*48a54d36SAndroid Build Coastguard Worker hostaddr.type = mDNSAddrType_IPv4; // Prefer v4 target to v6 target, for now
133*48a54d36SAndroid Build Coastguard Worker hostaddr.ip.v4 = answer->rdata->u.ipv4;
134*48a54d36SAndroid Build Coastguard Worker }
135*48a54d36SAndroid Build Coastguard Worker else if (answer->rrtype == kDNSType_AAAA)
136*48a54d36SAndroid Build Coastguard Worker {
137*48a54d36SAndroid Build Coastguard Worker if (!id.NotAnInteger) id = lastid;
138*48a54d36SAndroid Build Coastguard Worker NumAnswers++;
139*48a54d36SAndroid Build Coastguard Worker NumAAAA++;
140*48a54d36SAndroid Build Coastguard Worker mprintf("%##s %s %.16a\n", answer->name->c, DNSTypeName(answer->rrtype), &answer->rdata->u.ipv6);
141*48a54d36SAndroid Build Coastguard Worker if (!hostaddr.type) // Prefer v4 target to v6 target, for now
142*48a54d36SAndroid Build Coastguard Worker {
143*48a54d36SAndroid Build Coastguard Worker hostaddr.type = mDNSAddrType_IPv6;
144*48a54d36SAndroid Build Coastguard Worker hostaddr.ip.v6 = answer->rdata->u.ipv6;
145*48a54d36SAndroid Build Coastguard Worker }
146*48a54d36SAndroid Build Coastguard Worker }
147*48a54d36SAndroid Build Coastguard Worker else if (answer->rrtype == kDNSType_HINFO)
148*48a54d36SAndroid Build Coastguard Worker {
149*48a54d36SAndroid Build Coastguard Worker mDNSu8 *p = answer->rdata->u.data;
150*48a54d36SAndroid Build Coastguard Worker strncpy(hardware, (char*)(p+1), p[0]);
151*48a54d36SAndroid Build Coastguard Worker hardware[p[0]] = 0;
152*48a54d36SAndroid Build Coastguard Worker p += 1 + p[0];
153*48a54d36SAndroid Build Coastguard Worker strncpy(software, (char*)(p+1), p[0]);
154*48a54d36SAndroid Build Coastguard Worker software[p[0]] = 0;
155*48a54d36SAndroid Build Coastguard Worker NumAnswers++;
156*48a54d36SAndroid Build Coastguard Worker NumHINFO++;
157*48a54d36SAndroid Build Coastguard Worker }
158*48a54d36SAndroid Build Coastguard Worker
159*48a54d36SAndroid Build Coastguard Worker // If we've got everything we're looking for, don't need to wait any more
160*48a54d36SAndroid Build Coastguard Worker if (/*NumHINFO && */ (NumAddr || NumAAAA)) StopNow = 1;
161*48a54d36SAndroid Build Coastguard Worker }
162*48a54d36SAndroid Build Coastguard Worker
ServicesCallback(mDNS * const m,DNSQuestion * question,const ResourceRecord * const answer,QC_result AddRecord)163*48a54d36SAndroid Build Coastguard Worker mDNSlocal void ServicesCallback(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord)
164*48a54d36SAndroid Build Coastguard Worker {
165*48a54d36SAndroid Build Coastguard Worker (void)m; // Unused
166*48a54d36SAndroid Build Coastguard Worker (void)question; // Unused
167*48a54d36SAndroid Build Coastguard Worker (void)AddRecord;// Unused
168*48a54d36SAndroid Build Coastguard Worker // Right now the mDNSCore targeted-query code is incomplete --
169*48a54d36SAndroid Build Coastguard Worker // it issues targeted queries, but accepts answers from anywhere
170*48a54d36SAndroid Build Coastguard Worker // For now, we'll just filter responses here so we don't get confused by responses from someone else
171*48a54d36SAndroid Build Coastguard Worker if (answer->rrtype == kDNSType_PTR && mDNSSameAddress(&lastsrc, &target))
172*48a54d36SAndroid Build Coastguard Worker {
173*48a54d36SAndroid Build Coastguard Worker NumAnswers++;
174*48a54d36SAndroid Build Coastguard Worker mprintf("%##s %s %##s\n", answer->name->c, DNSTypeName(answer->rrtype), answer->rdata->u.name.c);
175*48a54d36SAndroid Build Coastguard Worker }
176*48a54d36SAndroid Build Coastguard Worker }
177*48a54d36SAndroid Build Coastguard Worker
WaitForAnswer(mDNS * const m,int seconds)178*48a54d36SAndroid Build Coastguard Worker mDNSlocal void WaitForAnswer(mDNS *const m, int seconds)
179*48a54d36SAndroid Build Coastguard Worker {
180*48a54d36SAndroid Build Coastguard Worker struct timeval end;
181*48a54d36SAndroid Build Coastguard Worker gettimeofday(&end, NULL);
182*48a54d36SAndroid Build Coastguard Worker end.tv_sec += seconds;
183*48a54d36SAndroid Build Coastguard Worker StopNow = 0;
184*48a54d36SAndroid Build Coastguard Worker NumAnswers = 0;
185*48a54d36SAndroid Build Coastguard Worker while (!StopNow)
186*48a54d36SAndroid Build Coastguard Worker {
187*48a54d36SAndroid Build Coastguard Worker int nfds = 0;
188*48a54d36SAndroid Build Coastguard Worker fd_set readfds;
189*48a54d36SAndroid Build Coastguard Worker struct timeval now, remain = end;
190*48a54d36SAndroid Build Coastguard Worker int result;
191*48a54d36SAndroid Build Coastguard Worker
192*48a54d36SAndroid Build Coastguard Worker FD_ZERO(&readfds);
193*48a54d36SAndroid Build Coastguard Worker gettimeofday(&now, NULL);
194*48a54d36SAndroid Build Coastguard Worker if (remain.tv_usec < now.tv_usec) { remain.tv_usec += 1000000; remain.tv_sec--; }
195*48a54d36SAndroid Build Coastguard Worker if (remain.tv_sec < now.tv_sec)
196*48a54d36SAndroid Build Coastguard Worker {
197*48a54d36SAndroid Build Coastguard Worker if (!NumAnswers) printf("No response after %d seconds\n", seconds);
198*48a54d36SAndroid Build Coastguard Worker return;
199*48a54d36SAndroid Build Coastguard Worker }
200*48a54d36SAndroid Build Coastguard Worker remain.tv_usec -= now.tv_usec;
201*48a54d36SAndroid Build Coastguard Worker remain.tv_sec -= now.tv_sec;
202*48a54d36SAndroid Build Coastguard Worker mDNSPosixGetFDSet(m, &nfds, &readfds, &remain);
203*48a54d36SAndroid Build Coastguard Worker result = select(nfds, &readfds, NULL, NULL, &remain);
204*48a54d36SAndroid Build Coastguard Worker if (result >= 0) mDNSPosixProcessFDSet(m, &readfds);
205*48a54d36SAndroid Build Coastguard Worker else if (errno != EINTR) StopNow = 2;
206*48a54d36SAndroid Build Coastguard Worker }
207*48a54d36SAndroid Build Coastguard Worker }
208*48a54d36SAndroid Build Coastguard Worker
StartQuery(DNSQuestion * q,char * qname,mDNSu16 qtype,const mDNSAddr * target,mDNSQuestionCallback callback)209*48a54d36SAndroid Build Coastguard Worker mDNSlocal mStatus StartQuery(DNSQuestion *q, char *qname, mDNSu16 qtype, const mDNSAddr *target, mDNSQuestionCallback callback)
210*48a54d36SAndroid Build Coastguard Worker {
211*48a54d36SAndroid Build Coastguard Worker lastsrc = zeroAddr;
212*48a54d36SAndroid Build Coastguard Worker if (qname) MakeDomainNameFromDNSNameString(&q->qname, qname);
213*48a54d36SAndroid Build Coastguard Worker q->InterfaceID = mDNSInterface_Any;
214*48a54d36SAndroid Build Coastguard Worker q->Target = target ? *target : zeroAddr;
215*48a54d36SAndroid Build Coastguard Worker q->TargetPort = MulticastDNSPort;
216*48a54d36SAndroid Build Coastguard Worker q->TargetQID = zeroID;
217*48a54d36SAndroid Build Coastguard Worker q->qtype = qtype;
218*48a54d36SAndroid Build Coastguard Worker q->qclass = kDNSClass_IN;
219*48a54d36SAndroid Build Coastguard Worker q->LongLived = mDNSfalse;
220*48a54d36SAndroid Build Coastguard Worker q->ExpectUnique = mDNSfalse; // Don't want to stop after the first response packet
221*48a54d36SAndroid Build Coastguard Worker q->ForceMCast = mDNStrue; // Query via multicast, even for apparently uDNS names like 1.1.1.17.in-addr.arpa.
222*48a54d36SAndroid Build Coastguard Worker q->ReturnIntermed = mDNStrue;
223*48a54d36SAndroid Build Coastguard Worker q->SuppressUnusable = mDNSfalse;
224*48a54d36SAndroid Build Coastguard Worker q->SearchListIndex = 0;
225*48a54d36SAndroid Build Coastguard Worker q->AppendSearchDomains = 0;
226*48a54d36SAndroid Build Coastguard Worker q->RetryWithSearchDomains = mDNSfalse;
227*48a54d36SAndroid Build Coastguard Worker q->TimeoutQuestion = 0;
228*48a54d36SAndroid Build Coastguard Worker q->WakeOnResolve = 0;
229*48a54d36SAndroid Build Coastguard Worker q->qnameOrig = mDNSNULL;
230*48a54d36SAndroid Build Coastguard Worker q->QuestionCallback = callback;
231*48a54d36SAndroid Build Coastguard Worker q->QuestionContext = NULL;
232*48a54d36SAndroid Build Coastguard Worker
233*48a54d36SAndroid Build Coastguard Worker //mprintf("%##s %s ?\n", q->qname.c, DNSTypeName(qtype));
234*48a54d36SAndroid Build Coastguard Worker return(mDNS_StartQuery(&mDNSStorage, q));
235*48a54d36SAndroid Build Coastguard Worker }
236*48a54d36SAndroid Build Coastguard Worker
DoOneQuery(DNSQuestion * q,char * qname,mDNSu16 qtype,const mDNSAddr * target,mDNSQuestionCallback callback)237*48a54d36SAndroid Build Coastguard Worker mDNSlocal void DoOneQuery(DNSQuestion *q, char *qname, mDNSu16 qtype, const mDNSAddr *target, mDNSQuestionCallback callback)
238*48a54d36SAndroid Build Coastguard Worker {
239*48a54d36SAndroid Build Coastguard Worker mStatus status = StartQuery(q, qname, qtype, target, callback);
240*48a54d36SAndroid Build Coastguard Worker if (status != mStatus_NoError)
241*48a54d36SAndroid Build Coastguard Worker StopNow = 2;
242*48a54d36SAndroid Build Coastguard Worker else
243*48a54d36SAndroid Build Coastguard Worker {
244*48a54d36SAndroid Build Coastguard Worker WaitForAnswer(&mDNSStorage, 4);
245*48a54d36SAndroid Build Coastguard Worker mDNS_StopQuery(&mDNSStorage, q);
246*48a54d36SAndroid Build Coastguard Worker }
247*48a54d36SAndroid Build Coastguard Worker }
248*48a54d36SAndroid Build Coastguard Worker
DoQuery(DNSQuestion * q,char * qname,mDNSu16 qtype,const mDNSAddr * target,mDNSQuestionCallback callback)249*48a54d36SAndroid Build Coastguard Worker mDNSlocal int DoQuery(DNSQuestion *q, char *qname, mDNSu16 qtype, const mDNSAddr *target, mDNSQuestionCallback callback)
250*48a54d36SAndroid Build Coastguard Worker {
251*48a54d36SAndroid Build Coastguard Worker DoOneQuery(q, qname, qtype, target, callback);
252*48a54d36SAndroid Build Coastguard Worker if (StopNow == 0 && NumAnswers == 0 && target && target->type)
253*48a54d36SAndroid Build Coastguard Worker {
254*48a54d36SAndroid Build Coastguard Worker mprintf("%##s %s Trying multicast\n", q->qname.c, DNSTypeName(q->qtype));
255*48a54d36SAndroid Build Coastguard Worker DoOneQuery(q, qname, qtype, NULL, callback);
256*48a54d36SAndroid Build Coastguard Worker }
257*48a54d36SAndroid Build Coastguard Worker if (StopNow == 0 && NumAnswers == 0)
258*48a54d36SAndroid Build Coastguard Worker mprintf("%##s %s *** No Answer ***\n", q->qname.c, DNSTypeName(q->qtype));
259*48a54d36SAndroid Build Coastguard Worker return(StopNow);
260*48a54d36SAndroid Build Coastguard Worker }
261*48a54d36SAndroid Build Coastguard Worker
HandleSIG(int signal)262*48a54d36SAndroid Build Coastguard Worker mDNSlocal void HandleSIG(int signal)
263*48a54d36SAndroid Build Coastguard Worker {
264*48a54d36SAndroid Build Coastguard Worker (void)signal; // Unused
265*48a54d36SAndroid Build Coastguard Worker debugf("%s","");
266*48a54d36SAndroid Build Coastguard Worker debugf("HandleSIG");
267*48a54d36SAndroid Build Coastguard Worker StopNow = 2;
268*48a54d36SAndroid Build Coastguard Worker }
269*48a54d36SAndroid Build Coastguard Worker
main(int argc,char ** argv)270*48a54d36SAndroid Build Coastguard Worker mDNSexport int main(int argc, char **argv)
271*48a54d36SAndroid Build Coastguard Worker {
272*48a54d36SAndroid Build Coastguard Worker const char *progname = strrchr(argv[0], '/') ? strrchr(argv[0], '/') + 1 : argv[0];
273*48a54d36SAndroid Build Coastguard Worker int this_arg = 1;
274*48a54d36SAndroid Build Coastguard Worker mStatus status;
275*48a54d36SAndroid Build Coastguard Worker struct in_addr s4;
276*48a54d36SAndroid Build Coastguard Worker #if HAVE_IPV6
277*48a54d36SAndroid Build Coastguard Worker struct in6_addr s6;
278*48a54d36SAndroid Build Coastguard Worker #endif
279*48a54d36SAndroid Build Coastguard Worker char buffer[256];
280*48a54d36SAndroid Build Coastguard Worker DNSQuestion q;
281*48a54d36SAndroid Build Coastguard Worker
282*48a54d36SAndroid Build Coastguard Worker if (argc < 2) goto usage;
283*48a54d36SAndroid Build Coastguard Worker
284*48a54d36SAndroid Build Coastguard Worker // Since this is a special command-line tool, we want LogMsg() errors to go to stderr, not syslog
285*48a54d36SAndroid Build Coastguard Worker mDNS_DebugMode = mDNStrue;
286*48a54d36SAndroid Build Coastguard Worker
287*48a54d36SAndroid Build Coastguard Worker // Initialise the mDNS core.
288*48a54d36SAndroid Build Coastguard Worker status = mDNS_Init(&mDNSStorage, &PlatformStorage,
289*48a54d36SAndroid Build Coastguard Worker gRRCache, RR_CACHE_SIZE,
290*48a54d36SAndroid Build Coastguard Worker mDNS_Init_DontAdvertiseLocalAddresses,
291*48a54d36SAndroid Build Coastguard Worker mDNS_Init_NoInitCallback, mDNS_Init_NoInitCallbackContext);
292*48a54d36SAndroid Build Coastguard Worker if (status) { fprintf(stderr, "Daemon start: mDNS_Init failed %d\n", (int)status); return(status); }
293*48a54d36SAndroid Build Coastguard Worker
294*48a54d36SAndroid Build Coastguard Worker signal(SIGINT, HandleSIG); // SIGINT is what you get for a Ctrl-C
295*48a54d36SAndroid Build Coastguard Worker signal(SIGTERM, HandleSIG);
296*48a54d36SAndroid Build Coastguard Worker
297*48a54d36SAndroid Build Coastguard Worker while (this_arg < argc)
298*48a54d36SAndroid Build Coastguard Worker {
299*48a54d36SAndroid Build Coastguard Worker char *arg = argv[this_arg++];
300*48a54d36SAndroid Build Coastguard Worker if (this_arg > 2) printf("\n");
301*48a54d36SAndroid Build Coastguard Worker
302*48a54d36SAndroid Build Coastguard Worker lastid = id = zeroID;
303*48a54d36SAndroid Build Coastguard Worker hostaddr = target = zeroAddr;
304*48a54d36SAndroid Build Coastguard Worker hostname[0] = hardware[0] = software[0] = 0;
305*48a54d36SAndroid Build Coastguard Worker NumAddr = NumAAAA = NumHINFO = 0;
306*48a54d36SAndroid Build Coastguard Worker
307*48a54d36SAndroid Build Coastguard Worker if (inet_pton(AF_INET, arg, &s4) == 1)
308*48a54d36SAndroid Build Coastguard Worker {
309*48a54d36SAndroid Build Coastguard Worker mDNSu8 *p = (mDNSu8 *)&s4;
310*48a54d36SAndroid Build Coastguard Worker // Note: This is reverse order compared to a normal dotted-decimal IP address, so we can't use our customary "%.4a" format code
311*48a54d36SAndroid Build Coastguard Worker mDNS_snprintf(buffer, sizeof(buffer), "%d.%d.%d.%d.in-addr.arpa.", p[3], p[2], p[1], p[0]);
312*48a54d36SAndroid Build Coastguard Worker printf("%s\n", buffer);
313*48a54d36SAndroid Build Coastguard Worker target.type = mDNSAddrType_IPv4;
314*48a54d36SAndroid Build Coastguard Worker target.ip.v4.NotAnInteger = s4.s_addr;
315*48a54d36SAndroid Build Coastguard Worker DoQuery(&q, buffer, kDNSType_PTR, &target, NameCallback);
316*48a54d36SAndroid Build Coastguard Worker if (StopNow == 2) break;
317*48a54d36SAndroid Build Coastguard Worker }
318*48a54d36SAndroid Build Coastguard Worker #if HAVE_IPV6
319*48a54d36SAndroid Build Coastguard Worker else if (inet_pton(AF_INET6, arg, &s6) == 1)
320*48a54d36SAndroid Build Coastguard Worker {
321*48a54d36SAndroid Build Coastguard Worker int i;
322*48a54d36SAndroid Build Coastguard Worker mDNSu8 *p = (mDNSu8 *)&s6;
323*48a54d36SAndroid Build Coastguard Worker for (i = 0; i < 16; i++)
324*48a54d36SAndroid Build Coastguard Worker {
325*48a54d36SAndroid Build Coastguard Worker static const char hexValues[] = "0123456789ABCDEF";
326*48a54d36SAndroid Build Coastguard Worker buffer[i * 4 ] = hexValues[p[15-i] & 0x0F];
327*48a54d36SAndroid Build Coastguard Worker buffer[i * 4 + 1] = '.';
328*48a54d36SAndroid Build Coastguard Worker buffer[i * 4 + 2] = hexValues[p[15-i] >> 4];
329*48a54d36SAndroid Build Coastguard Worker buffer[i * 4 + 3] = '.';
330*48a54d36SAndroid Build Coastguard Worker }
331*48a54d36SAndroid Build Coastguard Worker mDNS_snprintf(&buffer[64], sizeof(buffer)-64, "ip6.arpa.");
332*48a54d36SAndroid Build Coastguard Worker target.type = mDNSAddrType_IPv6;
333*48a54d36SAndroid Build Coastguard Worker mDNSPlatformMemCopy(&target.ip.v6, &s6, sizeof(target.ip.v6));
334*48a54d36SAndroid Build Coastguard Worker DoQuery(&q, buffer, kDNSType_PTR, &target, NameCallback);
335*48a54d36SAndroid Build Coastguard Worker if (StopNow == 2) break;
336*48a54d36SAndroid Build Coastguard Worker }
337*48a54d36SAndroid Build Coastguard Worker #endif
338*48a54d36SAndroid Build Coastguard Worker else {
339*48a54d36SAndroid Build Coastguard Worker if (strlen(arg) >= sizeof(hostname)) {
340*48a54d36SAndroid Build Coastguard Worker fprintf(stderr, "hostname must be < %d characters\n", (int)sizeof(hostname));
341*48a54d36SAndroid Build Coastguard Worker goto usage;
342*48a54d36SAndroid Build Coastguard Worker }
343*48a54d36SAndroid Build Coastguard Worker strcpy(hostname, arg);
344*48a54d36SAndroid Build Coastguard Worker }
345*48a54d36SAndroid Build Coastguard Worker
346*48a54d36SAndroid Build Coastguard Worker // Now we have the host name; get its A, AAAA, and HINFO
347*48a54d36SAndroid Build Coastguard Worker if (hostname[0]) DoQuery(&q, hostname, kDNSQType_ANY, &target, InfoCallback);
348*48a54d36SAndroid Build Coastguard Worker if (StopNow == 2) break;
349*48a54d36SAndroid Build Coastguard Worker
350*48a54d36SAndroid Build Coastguard Worker if (hardware[0] || software[0])
351*48a54d36SAndroid Build Coastguard Worker {
352*48a54d36SAndroid Build Coastguard Worker printf("HINFO Hardware: %s\n", hardware);
353*48a54d36SAndroid Build Coastguard Worker printf("HINFO Software: %s\n", software);
354*48a54d36SAndroid Build Coastguard Worker }
355*48a54d36SAndroid Build Coastguard Worker else if (NumAnswers) printf("%s has no HINFO record\n", hostname);
356*48a54d36SAndroid Build Coastguard Worker else printf("Incorrect dot-local hostname, address, or no mDNSResponder running on that machine\n");
357*48a54d36SAndroid Build Coastguard Worker
358*48a54d36SAndroid Build Coastguard Worker if (NumAnswers)
359*48a54d36SAndroid Build Coastguard Worker {
360*48a54d36SAndroid Build Coastguard Worker // Because of the way we use lastsrc in ServicesCallback, we need to clear the cache to make sure we're getting fresh answers
361*48a54d36SAndroid Build Coastguard Worker mDNS *const m = &mDNSStorage;
362*48a54d36SAndroid Build Coastguard Worker mDNSu32 slot;
363*48a54d36SAndroid Build Coastguard Worker CacheGroup *cg;
364*48a54d36SAndroid Build Coastguard Worker CacheRecord *rr;
365*48a54d36SAndroid Build Coastguard Worker FORALL_CACHERECORDS(slot, cg, rr) mDNS_PurgeCacheResourceRecord(m, rr);
366*48a54d36SAndroid Build Coastguard Worker if (target.type == 0) target = hostaddr; // Make sure the services query is targeted
367*48a54d36SAndroid Build Coastguard Worker DoQuery(&q, "_services._dns-sd._udp.local.", kDNSType_PTR, &target, ServicesCallback);
368*48a54d36SAndroid Build Coastguard Worker if (StopNow == 2) break;
369*48a54d36SAndroid Build Coastguard Worker }
370*48a54d36SAndroid Build Coastguard Worker }
371*48a54d36SAndroid Build Coastguard Worker
372*48a54d36SAndroid Build Coastguard Worker mDNS_Close(&mDNSStorage);
373*48a54d36SAndroid Build Coastguard Worker return(0);
374*48a54d36SAndroid Build Coastguard Worker
375*48a54d36SAndroid Build Coastguard Worker usage:
376*48a54d36SAndroid Build Coastguard Worker fprintf(stderr, "Usage: %s <dot-local hostname> or <IPv4 address> or <IPv6 address> ...\n", progname);
377*48a54d36SAndroid Build Coastguard Worker return(-1);
378*48a54d36SAndroid Build Coastguard Worker }
379