]>
Commit | Line | Data |
---|---|---|
7f0064bd A |
1 | /* -*- Mode: C; tab-width: 4 -*- |
2 | * | |
3 | * Copyright (c) 2002-2004 Apple Computer, Inc. All rights reserved. | |
c9b9ae52 | 4 | * |
619ee211 A |
5 | * Licensed under the Apache License, Version 2.0 (the "License"); |
6 | * you may not use this file except in compliance with the License. | |
7 | * You may obtain a copy of the License at | |
c9b9ae52 | 8 | * |
619ee211 | 9 | * http://www.apache.org/licenses/LICENSE-2.0 |
c9b9ae52 | 10 | * |
619ee211 A |
11 | * Unless required by applicable law or agreed to in writing, software |
12 | * distributed under the License is distributed on an "AS IS" BASIS, | |
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
14 | * See the License for the specific language governing permissions and | |
c9b9ae52 | 15 | * limitations under the License. |
c9b9ae52 A |
16 | * |
17 | * Formatting notes: | |
18 | * This code follows the "Whitesmiths style" C indentation rules. Plenty of discussion | |
19 | * on C indentation can be found on the web, such as <http://www.kafejo.com/komp/1tbs.htm>, | |
20 | * but for the sake of brevity here I will say just this: Curly braces are not syntactially | |
21 | * part of an "if" statement; they are the beginning and ending markers of a compound statement; | |
22 | * therefore common sense dictates that if they are part of a compound statement then they | |
23 | * should be indented to the same level as everything else in that compound statement. | |
24 | * Indenting curly braces at the same level as the "if" implies that curly braces are | |
25 | * part of the "if", which is false. (This is as misleading as people who write "char* x,y;" | |
26 | * thinking that variables x and y are both of type "char*" -- and anyone who doesn't | |
27 | * understand why variable y is not of type "char*" just proves the point that poor code | |
28 | * layout leads people to unfortunate misunderstandings about how the C language really works.) | |
29 | ||
30 | Change History (most recent first): | |
31 | ||
32 | $Log: Identify.c,v $ | |
619ee211 A |
33 | Revision 1.36 2006/08/14 23:24:46 cheshire |
34 | Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0 | |
35 | ||
36 | Revision 1.35 2006/06/12 18:22:42 cheshire | |
37 | <rdar://problem/4580067> mDNSResponder building warnings under Red Hat 64-bit (LP64) Linux | |
38 | ||
283ee3ff A |
39 | Revision 1.34 2004/12/16 20:17:11 cheshire |
40 | <rdar://problem/3324626> Cache memory management improvements | |
41 | ||
7f0064bd A |
42 | Revision 1.33 2004/11/30 22:37:00 cheshire |
43 | Update copyright dates and add "Mode: C; tab-width: 4" headers | |
44 | ||
45 | Revision 1.32 2004/10/19 21:33:21 cheshire | |
46 | <rdar://problem/3844991> Cannot resolve non-local registrations using the mach API | |
47 | Added flag 'kDNSServiceFlagsForceMulticast'. Passing through an interface id for a unicast name | |
48 | doesn't force multicast unless you set this flag to indicate explicitly that this is what you want | |
49 | ||
50 | Revision 1.31 2004/10/16 00:17:00 cheshire | |
51 | <rdar://problem/3770558> Replace IP TTL 255 check with local subnet source address check | |
52 | ||
53 | Revision 1.30 2004/09/21 23:29:51 cheshire | |
54 | <rdar://problem/3680045> DNSServiceResolve should delay sending packets | |
55 | ||
56 | Revision 1.29 2004/09/17 01:08:53 cheshire | |
57 | Renamed mDNSClientAPI.h to mDNSEmbeddedAPI.h | |
58 | The name "mDNSClientAPI.h" is misleading to new developers looking at this code. The interfaces | |
59 | declared in that file are ONLY appropriate to single-address-space embedded applications. | |
60 | For clients on general-purpose computers, the interfaces defined in dns_sd.h should be used. | |
61 | ||
62 | Revision 1.28 2004/09/17 00:31:52 cheshire | |
63 | For consistency with ipv6, renamed rdata field 'ip' to 'ipv4' | |
64 | ||
65 | Revision 1.27 2004/09/16 01:58:22 cheshire | |
66 | Fix compiler warnings | |
67 | ||
68 | Revision 1.26 2004/08/24 21:55:07 cheshire | |
69 | Don't try to build IPv6 code on systems that don't have IPv6 | |
70 | ||
71 | Revision 1.25 2004/07/20 23:42:37 cheshire | |
72 | Update to use only "_services._dns-sd._udp.local." meta-query for service enumeration | |
73 | ||
74 | Revision 1.24 2004/06/15 02:39:47 cheshire | |
75 | When displaying error message, only show command name, not entire path | |
76 | ||
8e92c31c A |
77 | Revision 1.23 2004/05/18 23:51:26 cheshire |
78 | Tidy up all checkin comments to use consistent "<rdar://problem/xxxxxxx>" format for bug numbers | |
79 | ||
80 | Revision 1.22 2004/04/20 22:43:28 cheshire | |
81 | Use _services._dns-sd._udp query, as documented in | |
82 | <http://files.dns-sd.org/draft-cheshire-dnsext-dns-sd-02.txt> | |
83 | ||
84 | Revision 1.21 2004/01/28 21:38:57 cheshire | |
85 | Also ask target host for _services._mdns._udp.local. list | |
86 | ||
87 | Revision 1.20 2004/01/28 19:04:38 cheshire | |
88 | Fix Ctrl-C handling when multiple targets are specified | |
89 | ||
90 | Revision 1.19 2004/01/28 03:49:30 cheshire | |
91 | Enhanced mDNSIdentify to make use of new targeted-query capability | |
92 | ||
93 | Revision 1.18 2004/01/27 19:06:51 cheshire | |
94 | Remove workaround for WWDC 2003 bug; no one has run that buggy build for a long time | |
95 | ||
96 | Revision 1.17 2004/01/22 03:57:00 cheshire | |
97 | Use the new meta-interface mDNSInterface_ForceMCast. This restores mDNSIdentify's | |
98 | ability to use multicast queries with non-link-local target addresses, like 17.x.x.x. | |
99 | ||
100 | Revision 1.16 2004/01/22 00:03:32 cheshire | |
101 | Add while() loop so that a list of targets may be specified on the command line | |
102 | ||
103 | Revision 1.15 2004/01/21 21:55:06 cheshire | |
104 | Don't need to wait for timeout once we've got the information we wanted | |
105 | ||
106 | Revision 1.14 2003/12/17 00:51:22 cheshire | |
107 | Changed mDNSNetMonitor and mDNSIdentify to link the object files | |
108 | instead of #including the "DNSCommon.c" "uDNS.c" and source files | |
109 | ||
110 | Revision 1.13 2003/12/13 03:05:28 ksekar | |
111 | <rdar://problem/3192548>: DynDNS: Unicast query of service records | |
112 | ||
716635cc A |
113 | Revision 1.12 2003/11/14 21:27:09 cheshire |
114 | <rdar://problem/3484766>: Security: Crashing bug in mDNSResponder | |
115 | Fix code that should use buffer size MAX_ESCAPED_DOMAIN_NAME (1005) instead of 256-byte buffers. | |
116 | ||
117 | Revision 1.11 2003/10/30 19:26:38 cheshire | |
118 | Fix warnings on certain compilers | |
119 | ||
c9b9ae52 A |
120 | Revision 1.10 2003/09/02 20:38:57 cheshire |
121 | #include <signal.h> for Linux | |
122 | ||
123 | Revision 1.9 2003/08/14 23:57:46 cheshire | |
124 | Report if there is no answer at all from the target host | |
125 | ||
126 | Revision 1.8 2003/08/14 02:19:55 cheshire | |
127 | <rdar://problem/3375491> Split generic ResourceRecord type into two separate types: AuthRecord and CacheRecord | |
128 | ||
129 | Revision 1.7 2003/08/12 19:56:26 cheshire | |
130 | Update to APSL 2.0 | |
131 | ||
132 | Revision 1.6 2003/08/06 01:46:18 cheshire | |
133 | Distinguish no answer from partial answer | |
134 | ||
135 | Revision 1.5 2003/08/05 23:56:26 cheshire | |
136 | Update code to compile with the new mDNSCoreReceive() function that requires a TTL | |
137 | (Right now mDNSPosix.c just reports 255 -- we should fix this) | |
138 | ||
139 | Revision 1.4 2003/08/04 17:24:48 cheshire | |
140 | Combine the three separate A/AAAA/HINFO queries into a single qtype "ANY" query | |
141 | ||
142 | Revision 1.3 2003/08/04 17:14:08 cheshire | |
143 | Do both AAAA queries in parallel | |
144 | ||
145 | Revision 1.2 2003/08/02 02:25:13 cheshire | |
146 | Multiple improvements: Now displays host's name, and all v4 and v6 addresses, as well as HINFO record | |
147 | ||
148 | Revision 1.1 2003/08/01 02:20:02 cheshire | |
149 | Add mDNSIdentify tool, used to discover what version of mDNSResponder a particular host is running | |
150 | ||
151 | */ | |
152 | ||
153 | //************************************************************************************************************* | |
154 | // Incorporate mDNS.c functionality | |
155 | ||
156 | // We want to use the functionality provided by "mDNS.c", | |
157 | // except we'll sneak a peek at the packets before forwarding them to the normal mDNSCoreReceive() routine | |
158 | #define mDNSCoreReceive __MDNS__mDNSCoreReceive | |
159 | #include "mDNS.c" | |
160 | #undef mDNSCoreReceive | |
161 | ||
162 | //************************************************************************************************************* | |
163 | // Headers | |
164 | ||
165 | #include <unistd.h> | |
166 | #include <stdio.h> | |
167 | #include <string.h> | |
168 | #include <errno.h> | |
169 | #include <sys/socket.h> | |
170 | #include <netinet/in.h> | |
171 | #include <netinet/in_systm.h> // For n_long, required by <netinet/ip.h> below | |
172 | #include <netinet/ip.h> // For IPTOS_LOWDELAY etc. | |
173 | #include <arpa/inet.h> | |
174 | #include <signal.h> | |
175 | ||
7f0064bd | 176 | #include "mDNSEmbeddedAPI.h"// Defines the interface to the mDNS core code |
c9b9ae52 A |
177 | #include "mDNSPosix.h" // Defines the specific types needed to run mDNS on this platform |
178 | #include "ExampleClientApp.h" | |
179 | ||
180 | //************************************************************************************************************* | |
181 | // Globals | |
182 | ||
183 | static mDNS mDNSStorage; // mDNS core uses this to store its globals | |
184 | static mDNS_PlatformSupport PlatformStorage; // Stores this platform's globals | |
185 | #define RR_CACHE_SIZE 500 | |
283ee3ff | 186 | static CacheEntity gRRCache[RR_CACHE_SIZE]; |
c9b9ae52 A |
187 | |
188 | static volatile int StopNow; // 0 means running, 1 means stop because we got an answer, 2 means stop because of Ctrl-C | |
189 | static volatile int NumAnswers, NumAddr, NumAAAA, NumHINFO; | |
716635cc | 190 | static char hostname[MAX_ESCAPED_DOMAIN_NAME], hardware[256], software[256]; |
8e92c31c | 191 | static mDNSAddr lastsrc, hostaddr, target; |
c9b9ae52 A |
192 | static mDNSOpaque16 lastid, id; |
193 | ||
194 | //************************************************************************************************************* | |
195 | // Utilities | |
196 | ||
197 | // Special version of printf that knows how to print IP addresses, DNS-format name strings, etc. | |
198 | mDNSlocal mDNSu32 mprintf(const char *format, ...) IS_A_PRINTF_STYLE_FUNCTION(1,2); | |
199 | mDNSlocal mDNSu32 mprintf(const char *format, ...) | |
200 | { | |
201 | mDNSu32 length; | |
202 | unsigned char buffer[512]; | |
203 | va_list ptr; | |
204 | va_start(ptr,format); | |
205 | length = mDNS_vsnprintf((char *)buffer, sizeof(buffer), format, ptr); | |
206 | va_end(ptr); | |
207 | printf("%s", buffer); | |
208 | return(length); | |
209 | } | |
210 | ||
211 | //************************************************************************************************************* | |
212 | // Main code | |
213 | ||
214 | mDNSexport void mDNSCoreReceive(mDNS *const m, DNSMessage *const msg, const mDNSu8 *const end, | |
215 | const mDNSAddr *const srcaddr, const mDNSIPPort srcport, const mDNSAddr *const dstaddr, const mDNSIPPort dstport, | |
7f0064bd | 216 | const mDNSInterfaceID InterfaceID) |
c9b9ae52 | 217 | { |
7f0064bd | 218 | (void)dstaddr; // Unused |
c9b9ae52 A |
219 | // Snag copy of header ID, then call through |
220 | lastid = msg->h.id; | |
8e92c31c A |
221 | lastsrc = *srcaddr; |
222 | ||
223 | // We *want* to allow off-net unicast responses here. | |
7f0064bd A |
224 | // For now, the simplest way to allow that is to pretend it was received via multicast so that mDNSCore doesn't reject the packet |
225 | __MDNS__mDNSCoreReceive(m, msg, end, srcaddr, srcport, &AllDNSLinkGroup_v4, dstport, InterfaceID); | |
c9b9ae52 A |
226 | } |
227 | ||
228 | static void NameCallback(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, mDNSBool AddRecord) | |
229 | { | |
230 | (void)m; // Unused | |
231 | (void)question; // Unused | |
232 | (void)AddRecord;// Unused | |
233 | if (!id.NotAnInteger) id = lastid; | |
8e92c31c A |
234 | if (answer->rrtype == kDNSType_PTR || answer->rrtype == kDNSType_CNAME) |
235 | { | |
236 | ConvertDomainNameToCString(&answer->rdata->u.name, hostname); | |
237 | StopNow = 1; | |
283ee3ff | 238 | mprintf("%##s %s %##s\n", answer->name->c, DNSTypeName(answer->rrtype), answer->rdata->u.name.c); |
8e92c31c | 239 | } |
c9b9ae52 A |
240 | } |
241 | ||
242 | static void InfoCallback(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, mDNSBool AddRecord) | |
243 | { | |
244 | (void)m; // Unused | |
245 | (void)question; // Unused | |
246 | (void)AddRecord;// Unused | |
247 | if (answer->rrtype == kDNSType_A) | |
248 | { | |
249 | if (!id.NotAnInteger) id = lastid; | |
250 | NumAnswers++; | |
251 | NumAddr++; | |
283ee3ff | 252 | mprintf("%##s %s %.4a\n", answer->name->c, DNSTypeName(answer->rrtype), &answer->rdata->u.ipv4); |
8e92c31c | 253 | hostaddr.type = mDNSAddrType_IPv4; // Prefer v4 target to v6 target, for now |
7f0064bd | 254 | hostaddr.ip.v4 = answer->rdata->u.ipv4; |
c9b9ae52 A |
255 | } |
256 | else if (answer->rrtype == kDNSType_AAAA) | |
257 | { | |
258 | if (!id.NotAnInteger) id = lastid; | |
259 | NumAnswers++; | |
260 | NumAAAA++; | |
283ee3ff | 261 | mprintf("%##s %s %.16a\n", answer->name->c, DNSTypeName(answer->rrtype), &answer->rdata->u.ipv6); |
8e92c31c A |
262 | if (!hostaddr.type) // Prefer v4 target to v6 target, for now |
263 | { | |
264 | hostaddr.type = mDNSAddrType_IPv6; | |
265 | hostaddr.ip.v6 = answer->rdata->u.ipv6; | |
266 | } | |
c9b9ae52 A |
267 | } |
268 | else if (answer->rrtype == kDNSType_HINFO) | |
269 | { | |
270 | mDNSu8 *p = answer->rdata->u.data; | |
716635cc | 271 | strncpy(hardware, (char*)(p+1), p[0]); |
c9b9ae52 A |
272 | hardware[p[0]] = 0; |
273 | p += 1 + p[0]; | |
716635cc | 274 | strncpy(software, (char*)(p+1), p[0]); |
c9b9ae52 A |
275 | software[p[0]] = 0; |
276 | NumAnswers++; | |
277 | NumHINFO++; | |
278 | } | |
8e92c31c A |
279 | |
280 | // If we've got everything we're looking for, don't need to wait any more | |
281 | if (NumHINFO && (NumAddr || NumAAAA)) StopNow = 1; | |
282 | } | |
283 | ||
284 | static void ServicesCallback(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, mDNSBool AddRecord) | |
285 | { | |
286 | (void)m; // Unused | |
287 | (void)question; // Unused | |
288 | (void)AddRecord;// Unused | |
289 | // Right now the mDNSCore targeted-query code is incomplete -- | |
290 | // it issues targeted queries, but accepts answers from anywhere | |
291 | // For now, we'll just filter responses here so we don't get confused by responses from someone else | |
292 | if (answer->rrtype == kDNSType_PTR && mDNSSameAddress(&lastsrc, &target)) | |
293 | { | |
294 | NumAnswers++; | |
295 | NumAddr++; | |
283ee3ff | 296 | mprintf("%##s %s %##s\n", answer->name->c, DNSTypeName(answer->rrtype), answer->rdata->u.name.c); |
8e92c31c A |
297 | StopNow = 1; |
298 | } | |
c9b9ae52 A |
299 | } |
300 | ||
301 | mDNSexport void WaitForAnswer(mDNS *const m, int seconds) | |
302 | { | |
303 | struct timeval end; | |
304 | gettimeofday(&end, NULL); | |
305 | end.tv_sec += seconds; | |
306 | StopNow = 0; | |
307 | NumAnswers = 0; | |
308 | while (!StopNow) | |
309 | { | |
310 | int nfds = 0; | |
311 | fd_set readfds; | |
312 | struct timeval now, remain = end; | |
313 | int result; | |
314 | ||
315 | FD_ZERO(&readfds); | |
316 | gettimeofday(&now, NULL); | |
317 | if (remain.tv_usec < now.tv_usec) { remain.tv_usec += 1000000; remain.tv_sec--; } | |
318 | if (remain.tv_sec < now.tv_sec) return; | |
319 | remain.tv_usec -= now.tv_usec; | |
320 | remain.tv_sec -= now.tv_sec; | |
321 | mDNSPosixGetFDSet(m, &nfds, &readfds, &remain); | |
322 | result = select(nfds, &readfds, NULL, NULL, &remain); | |
323 | if (result >= 0) mDNSPosixProcessFDSet(m, &readfds); | |
324 | else if (errno != EINTR) StopNow = 2; | |
325 | } | |
326 | } | |
327 | ||
8e92c31c | 328 | mDNSlocal mStatus StartQuery(DNSQuestion *q, char *qname, mDNSu16 qtype, const mDNSAddr *target, mDNSQuestionCallback callback) |
c9b9ae52 A |
329 | { |
330 | if (qname) MakeDomainNameFromDNSNameString(&q->qname, qname); | |
8e92c31c A |
331 | q->Target = target ? *target : zeroAddr; |
332 | q->TargetPort = MulticastDNSPort; | |
333 | q->TargetQID = zeroID; | |
7f0064bd | 334 | q->InterfaceID = mDNSInterface_Any; |
c9b9ae52 A |
335 | q->qtype = qtype; |
336 | q->qclass = kDNSClass_IN; | |
7f0064bd A |
337 | q->LongLived = mDNSfalse; |
338 | q->ExpectUnique = mDNStrue; | |
339 | q->ForceMCast = mDNStrue; // Query via multicast, even for apparently uDNS names like 1.1.1.17.in-addr.arpa. | |
c9b9ae52 A |
340 | q->QuestionCallback = callback; |
341 | q->QuestionContext = NULL; | |
342 | ||
343 | //mprintf("%##s %s ?\n", q->qname.c, DNSTypeName(qtype)); | |
344 | return(mDNS_StartQuery(&mDNSStorage, q)); | |
345 | } | |
346 | ||
8e92c31c | 347 | mDNSlocal void DoOneQuery(DNSQuestion *q, char *qname, mDNSu16 qtype, const mDNSAddr *target, mDNSQuestionCallback callback) |
c9b9ae52 | 348 | { |
8e92c31c | 349 | mStatus status = StartQuery(q, qname, qtype, target, callback); |
c9b9ae52 A |
350 | if (status != mStatus_NoError) |
351 | StopNow = 2; | |
352 | else | |
353 | { | |
354 | WaitForAnswer(&mDNSStorage, 4); | |
355 | mDNS_StopQuery(&mDNSStorage, q); | |
c9b9ae52 | 356 | } |
8e92c31c A |
357 | } |
358 | ||
359 | mDNSlocal int DoQuery(DNSQuestion *q, char *qname, mDNSu16 qtype, const mDNSAddr *target, mDNSQuestionCallback callback) | |
360 | { | |
361 | DoOneQuery(q, qname, qtype, target, callback); | |
362 | if (StopNow == 0 && target && target->type) | |
363 | { | |
364 | mprintf("%##s %s Trying multicast\n", q->qname.c, DNSTypeName(q->qtype)); | |
365 | DoOneQuery(q, qname, qtype, NULL, callback); | |
366 | } | |
367 | if (StopNow == 0 && NumAnswers == 0) | |
368 | mprintf("%##s %s *** No Answer ***\n", q->qname.c, DNSTypeName(q->qtype)); | |
c9b9ae52 A |
369 | return(StopNow); |
370 | } | |
371 | ||
372 | mDNSlocal void HandleSIG(int signal) | |
373 | { | |
374 | (void)signal; // Unused | |
7f0064bd | 375 | debugf("%s",""); |
c9b9ae52 A |
376 | debugf("HandleSIG"); |
377 | StopNow = 2; | |
378 | } | |
379 | ||
380 | mDNSexport int main(int argc, char **argv) | |
381 | { | |
7f0064bd | 382 | const char *progname = strrchr(argv[0], '/') ? strrchr(argv[0], '/') + 1 : argv[0]; |
8e92c31c | 383 | int this_arg = 1; |
c9b9ae52 | 384 | mStatus status; |
716635cc | 385 | struct in_addr s4; |
7f0064bd | 386 | #if HAVE_IPV6 |
716635cc | 387 | struct in6_addr s6; |
7f0064bd | 388 | #endif |
716635cc A |
389 | char buffer[256]; |
390 | DNSQuestion q; | |
391 | ||
c9b9ae52 A |
392 | if (argc < 2) goto usage; |
393 | ||
8e92c31c A |
394 | // Since this is a special command-line tool, we want LogMsg() errors to go to stderr, not syslog |
395 | mDNS_DebugMode = mDNStrue; | |
396 | ||
c9b9ae52 A |
397 | // Initialise the mDNS core. |
398 | status = mDNS_Init(&mDNSStorage, &PlatformStorage, | |
399 | gRRCache, RR_CACHE_SIZE, | |
400 | mDNS_Init_DontAdvertiseLocalAddresses, | |
401 | mDNS_Init_NoInitCallback, mDNS_Init_NoInitCallbackContext); | |
619ee211 | 402 | if (status) { fprintf(stderr, "Daemon start: mDNS_Init failed %d\n", (int)status); return(status); } |
c9b9ae52 A |
403 | |
404 | signal(SIGINT, HandleSIG); // SIGINT is what you get for a Ctrl-C | |
405 | signal(SIGTERM, HandleSIG); | |
406 | ||
8e92c31c | 407 | while (this_arg < argc) |
c9b9ae52 | 408 | { |
8e92c31c A |
409 | char *arg = argv[this_arg++]; |
410 | if (this_arg > 2) printf("\n"); | |
c9b9ae52 | 411 | |
8e92c31c A |
412 | lastid = id = zeroID; |
413 | hostaddr = target = zeroAddr; | |
414 | hostname[0] = hardware[0] = software[0] = 0; | |
415 | NumAddr = NumAAAA = NumHINFO = 0; | |
c9b9ae52 | 416 | |
8e92c31c A |
417 | if (inet_pton(AF_INET, arg, &s4) == 1) |
418 | { | |
419 | mDNSu8 *p = (mDNSu8 *)&s4; | |
420 | mDNS_snprintf(buffer, sizeof(buffer), "%d.%d.%d.%d.in-addr.arpa.", p[3], p[2], p[1], p[0]); | |
421 | printf("%s\n", buffer); | |
422 | target.type = mDNSAddrType_IPv4; | |
423 | target.ip.v4.NotAnInteger = s4.s_addr; | |
424 | DoQuery(&q, buffer, kDNSType_PTR, &target, NameCallback); | |
425 | if (StopNow == 2) break; | |
426 | } | |
7f0064bd | 427 | #if HAVE_IPV6 |
8e92c31c A |
428 | else if (inet_pton(AF_INET6, arg, &s6) == 1) |
429 | { | |
430 | int i; | |
431 | mDNSu8 *p = (mDNSu8 *)&s6; | |
432 | for (i = 0; i < 16; i++) | |
433 | { | |
434 | static const char hexValues[] = "0123456789ABCDEF"; | |
435 | buffer[i * 4 ] = hexValues[p[15-i] & 0x0F]; | |
436 | buffer[i * 4 + 1] = '.'; | |
437 | buffer[i * 4 + 2] = hexValues[p[15-i] >> 4]; | |
438 | buffer[i * 4 + 3] = '.'; | |
439 | } | |
440 | mDNS_snprintf(&buffer[64], sizeof(buffer)-64, "ip6.arpa."); | |
441 | target.type = mDNSAddrType_IPv6; | |
442 | bcopy(&s6, &target.ip.v6, sizeof(target.ip.v6)); | |
443 | DoQuery(&q, buffer, kDNSType_PTR, &target, NameCallback); | |
444 | if (StopNow == 2) break; | |
445 | } | |
7f0064bd | 446 | #endif |
8e92c31c A |
447 | else |
448 | strcpy(hostname, arg); | |
449 | ||
450 | // Now we have the host name; get its A, AAAA, and HINFO | |
451 | if (hostname[0]) DoQuery(&q, hostname, kDNSQType_ANY, &target, InfoCallback); | |
452 | if (StopNow == 2) break; | |
453 | ||
454 | if (hardware[0] || software[0]) | |
455 | { | |
7f0064bd | 456 | DNSQuestion q1; |
8e92c31c A |
457 | printf("HINFO Hardware: %s\n", hardware); |
458 | printf("HINFO Software: %s\n", software); | |
459 | // We need to make sure the services query is targeted | |
460 | if (target.type == 0) target = hostaddr; | |
7f0064bd | 461 | StartQuery(&q1, "_services._dns-sd._udp.local.", kDNSQType_ANY, &target, ServicesCallback); |
8e92c31c A |
462 | WaitForAnswer(&mDNSStorage, 4); |
463 | mDNS_StopQuery(&mDNSStorage, &q1); | |
8e92c31c A |
464 | if (StopNow == 2) break; |
465 | } | |
466 | else if (NumAnswers) | |
467 | { | |
468 | printf("Host has no HINFO record; Best guess is "); | |
469 | if (id.b[1]) printf("mDNSResponder-%d\n", id.b[1]); | |
470 | else if (NumAAAA) printf("very early Panther build (mDNSResponder-33 or earlier)\n"); | |
471 | else printf("Jaguar version of mDNSResponder with no IPv6 support\n"); | |
472 | } | |
473 | else | |
474 | printf("Incorrect dot-local hostname, address, or no mDNSResponder running on that machine\n"); | |
c9b9ae52 | 475 | } |
c9b9ae52 | 476 | |
c9b9ae52 A |
477 | mDNS_Close(&mDNSStorage); |
478 | return(0); | |
479 | ||
480 | usage: | |
7f0064bd | 481 | fprintf(stderr, "%s <dot-local hostname> or <IPv4 address> or <IPv6 address> ...\n", progname); |
c9b9ae52 A |
482 | return(-1); |
483 | } |