]>
Commit | Line | Data |
---|---|---|
b7080c8e A |
1 | /* |
2 | * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. | |
3 | * | |
4 | * @APPLE_LICENSE_HEADER_START@ | |
5 | * | |
6 | * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights | |
7 | * Reserved. This file contains Original Code and/or Modifications of | |
8 | * Original Code as defined in and that are subject to the Apple Public | |
9 | * Source License Version 1.0 (the 'License'). You may not use this file | |
10 | * except in compliance with the License. Please obtain a copy of the | |
11 | * License at http://www.apple.com/publicsource and read it before using | |
12 | * this file. | |
13 | * | |
14 | * The Original Code and all software distributed under the License are | |
15 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER | |
16 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, | |
17 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
18 | * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the | |
19 | * License for the specific language governing rights and limitations | |
20 | * under the License." | |
21 | * | |
22 | * @APPLE_LICENSE_HEADER_END@ | |
23 | */ | |
24 | /* | |
25 | * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996 | |
26 | * The Regents of the University of California. All rights reserved. | |
27 | * | |
28 | * Redistribution and use in source and binary forms, with or without | |
29 | * modification, are permitted provided that: (1) source code distributions | |
30 | * retain the above copyright notice and this paragraph in its entirety, (2) | |
31 | * distributions including binary code include the above copyright notice and | |
32 | * this paragraph in its entirety in the documentation or other materials | |
33 | * provided with the distribution, and (3) all advertising materials mentioning | |
34 | * features or use of this software display the following acknowledgement: | |
35 | * ``This product includes software developed by the University of California, | |
36 | * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of | |
37 | * the University nor the names of its contributors may be used to endorse | |
38 | * or promote products derived from this software without specific prior | |
39 | * written permission. | |
40 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED | |
41 | * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF | |
42 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. | |
43 | */ | |
44 | ||
45 | #ifndef lint | |
46 | static const char rcsid[] = | |
47 | "@(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/print-domain.c,v 1.1.1.1 1999/05/02 03:58:33 wsanchez Exp $ (LBL)"; | |
48 | #endif | |
49 | ||
50 | #include <sys/param.h> | |
51 | #include <sys/time.h> | |
52 | #include <sys/socket.h> | |
53 | ||
54 | #if __STDC__ | |
55 | struct mbuf; | |
56 | struct rtentry; | |
57 | #endif | |
58 | #include <net/if.h> | |
59 | ||
60 | #include <netinet/in.h> | |
61 | #include <netinet/if_ether.h> | |
62 | #include <netinet/in_systm.h> | |
63 | #include <netinet/ip.h> | |
64 | #include <netinet/ip_var.h> | |
65 | #include <netinet/udp.h> | |
66 | #include <netinet/udp_var.h> | |
67 | #include <netinet/tcp.h> | |
68 | #include <netinet/tcpip.h> | |
69 | ||
70 | #undef NOERROR /* Solaris sucks */ | |
71 | #undef T_UNSPEC /* SINIX does too */ | |
72 | #include <arpa/nameser.h> | |
73 | ||
74 | #include <stdio.h> | |
75 | ||
76 | #include "interface.h" | |
77 | #include "addrtoname.h" | |
78 | #include "extract.h" /* must come after interface.h */ | |
79 | ||
80 | /* Compatibility */ | |
81 | #ifndef T_TXT | |
82 | #define T_TXT 16 /* text strings */ | |
83 | #endif | |
84 | #ifndef T_RP | |
85 | #define T_RP 17 /* responsible person */ | |
86 | #endif | |
87 | #ifndef T_AFSDB | |
88 | #define T_AFSDB 18 /* AFS cell database */ | |
89 | #endif | |
90 | #ifndef T_X25 | |
91 | #define T_X25 19 /* X_25 calling address */ | |
92 | #endif | |
93 | #ifndef T_ISDN | |
94 | #define T_ISDN 20 /* ISDN calling address */ | |
95 | #endif | |
96 | #ifndef T_RT | |
97 | #define T_RT 21 /* router */ | |
98 | #endif | |
99 | #ifndef T_NSAP | |
100 | #define T_NSAP 22 /* NSAP address */ | |
101 | #endif | |
102 | #ifndef T_NSAP_PTR | |
103 | #define T_NSAP_PTR 23 /* reverse NSAP lookup (deprecated) */ | |
104 | #endif | |
105 | #ifndef T_SIG | |
106 | #define T_SIG 24 /* security signature */ | |
107 | #endif | |
108 | #ifndef T_KEY | |
109 | #define T_KEY 25 /* security key */ | |
110 | #endif | |
111 | #ifndef T_PX | |
112 | #define T_PX 26 /* X.400 mail mapping */ | |
113 | #endif | |
114 | #ifndef T_GPOS | |
115 | #define T_GPOS 27 /* geographical position (withdrawn) */ | |
116 | #endif | |
117 | #ifndef T_AAAA | |
118 | #define T_AAAA 28 /* IP6 Address */ | |
119 | #endif | |
120 | #ifndef T_LOC | |
121 | #define T_LOC 29 /* Location Information */ | |
122 | #endif | |
123 | ||
124 | #ifndef T_UNSPEC | |
125 | #define T_UNSPEC 103 /* Unspecified format (binary data) */ | |
126 | #endif | |
127 | #ifndef T_UNSPECA | |
128 | #define T_UNSPECA 104 /* "unspecified ascii". Ugly MIT hack */ | |
129 | #endif | |
130 | ||
131 | #ifndef C_CHAOS | |
132 | #define C_CHAOS 3 /* for chaos net (MIT) */ | |
133 | #endif | |
134 | #ifndef C_HS | |
135 | #define C_HS 4 /* for Hesiod name server (MIT) (XXX) */ | |
136 | #endif | |
137 | ||
138 | static char *ns_ops[] = { | |
139 | "", " inv_q", " stat", " op3", " notify", " op5", " op6", " op7", | |
140 | " op8", " updataA", " updateD", " updateDA", | |
141 | " updateM", " updateMA", " zoneInit", " zoneRef", | |
142 | }; | |
143 | ||
144 | static char *ns_resp[] = { | |
145 | "", " FormErr", " ServFail", " NXDomain", | |
146 | " NotImp", " Refused", " Resp6", " Resp7", | |
147 | " Resp8", " Resp9", " Resp10", " Resp11", | |
148 | " Resp12", " Resp13", " Resp14", " NoChange", | |
149 | }; | |
150 | ||
151 | /* skip over a domain name */ | |
152 | static const u_char * | |
153 | ns_nskip(register const u_char *cp, register const u_char *bp) | |
154 | { | |
155 | register u_char i; | |
156 | ||
157 | if (((i = *cp++) & INDIR_MASK) == INDIR_MASK) | |
158 | return (cp + 1); | |
159 | while (i && cp < snapend) { | |
160 | cp += i; | |
161 | i = *cp++; | |
162 | } | |
163 | return (cp); | |
164 | } | |
165 | ||
166 | /* print a <domain-name> */ | |
167 | static const u_char * | |
168 | ns_nprint(register const u_char *cp, register const u_char *bp) | |
169 | { | |
170 | register u_int i; | |
171 | register const u_char *rp; | |
172 | register int compress; | |
173 | ||
174 | i = *cp++; | |
175 | rp = cp + i; | |
176 | if ((i & INDIR_MASK) == INDIR_MASK) { | |
177 | rp = cp + 1; | |
178 | compress = 1; | |
179 | } else | |
180 | compress = 0; | |
181 | if (i != 0) | |
182 | while (i && cp < snapend) { | |
183 | if ((i & INDIR_MASK) == INDIR_MASK) { | |
184 | cp = bp + (((i << 8) | *cp) & 0x3fff); | |
185 | i = *cp++; | |
186 | continue; | |
187 | } | |
188 | if (fn_printn(cp, i, snapend)) | |
189 | break; | |
190 | cp += i; | |
191 | putchar('.'); | |
192 | i = *cp++; | |
193 | if (!compress) | |
194 | rp += i + 1; | |
195 | } | |
196 | else | |
197 | putchar('.'); | |
198 | return (rp); | |
199 | } | |
200 | ||
201 | /* print a <character-string> */ | |
202 | static const u_char * | |
203 | ns_cprint(register const u_char *cp, register const u_char *bp) | |
204 | { | |
205 | register u_int i; | |
206 | ||
207 | i = *cp++; | |
208 | (void)fn_printn(cp, i, snapend); | |
209 | return (cp + i); | |
210 | } | |
211 | ||
212 | static struct tok type2str[] = { | |
213 | { T_A, "A" }, | |
214 | { T_NS, "NS" }, | |
215 | { T_MD, "MD" }, | |
216 | { T_MF, "MF" }, | |
217 | { T_CNAME, "CNAME" }, | |
218 | { T_SOA, "SOA" }, | |
219 | { T_MB, "MB" }, | |
220 | { T_MG, "MG" }, | |
221 | { T_MR, "MR" }, | |
222 | { T_NULL, "NULL" }, | |
223 | { T_WKS, "WKS" }, | |
224 | { T_PTR, "PTR" }, | |
225 | { T_HINFO, "HINFO" }, | |
226 | { T_MINFO, "MINFO" }, | |
227 | { T_MX, "MX" }, | |
228 | { T_TXT, "TXT" }, | |
229 | { T_RP, "RP" }, | |
230 | { T_AFSDB, "AFSDB" }, | |
231 | { T_X25, "X25" }, | |
232 | { T_ISDN, "ISDN" }, | |
233 | { T_RT, "RT" }, | |
234 | { T_NSAP, "NSAP" }, | |
235 | { T_NSAP_PTR, "NSAP_PTR" }, | |
236 | { T_SIG, "SIG" }, | |
237 | { T_KEY, "KEY" }, | |
238 | { T_PX, "PX" }, | |
239 | { T_GPOS, "GPOS" }, | |
240 | { T_AAAA, "AAAA" }, | |
241 | { T_LOC , "LOC " }, | |
242 | { T_UINFO, "UINFO" }, | |
243 | { T_UID, "UID" }, | |
244 | { T_GID, "GID" }, | |
245 | { T_UNSPEC, "UNSPEC" }, | |
246 | { T_UNSPECA, "UNSPECA" }, | |
247 | { T_AXFR, "AXFR" }, | |
248 | { T_MAILB, "MAILB" }, | |
249 | { T_MAILA, "MAILA" }, | |
250 | { T_ANY, "ANY" }, | |
251 | { 0, NULL } | |
252 | }; | |
253 | ||
254 | static struct tok class2str[] = { | |
255 | { C_IN, "IN" }, /* Not used */ | |
256 | { C_CHAOS, "CHAOS)" }, | |
257 | { C_HS, "HS" }, | |
258 | { C_ANY, "ANY" }, | |
259 | { 0, NULL } | |
260 | }; | |
261 | ||
262 | /* print a query */ | |
263 | static void | |
264 | ns_qprint(register const u_char *cp, register const u_char *bp) | |
265 | { | |
266 | register const u_char *np = cp; | |
267 | register u_int i; | |
268 | ||
269 | cp = ns_nskip(cp, bp); | |
270 | ||
271 | if (cp + 4 > snapend) | |
272 | return; | |
273 | ||
274 | /* print the qtype and qclass (if it's not IN) */ | |
275 | i = *cp++ << 8; | |
276 | i |= *cp++; | |
277 | printf(" %s", tok2str(type2str, "Type%d", i)); | |
278 | i = *cp++ << 8; | |
279 | i |= *cp++; | |
280 | if (i != C_IN) | |
281 | printf(" %s", tok2str(class2str, "(Class %d)", i)); | |
282 | ||
283 | fputs("? ", stdout); | |
284 | ns_nprint(np, bp); | |
285 | } | |
286 | ||
287 | /* print a reply */ | |
288 | static const u_char * | |
289 | ns_rprint(register const u_char *cp, register const u_char *bp) | |
290 | { | |
291 | register u_int i; | |
292 | register u_short typ, len; | |
293 | register const u_char *rp; | |
294 | ||
295 | if (vflag) { | |
296 | putchar(' '); | |
297 | cp = ns_nprint(cp, bp); | |
298 | } else | |
299 | cp = ns_nskip(cp, bp); | |
300 | ||
301 | if (cp + 10 > snapend) | |
302 | return (snapend); | |
303 | ||
304 | /* print the type/qtype and class (if it's not IN) */ | |
305 | typ = *cp++ << 8; | |
306 | typ |= *cp++; | |
307 | i = *cp++ << 8; | |
308 | i |= *cp++; | |
309 | if (i != C_IN) | |
310 | printf(" %s", tok2str(class2str, "(Class %d)", i)); | |
311 | ||
312 | /* ignore ttl */ | |
313 | cp += 4; | |
314 | ||
315 | len = *cp++ << 8; | |
316 | len |= *cp++; | |
317 | ||
318 | rp = cp + len; | |
319 | ||
320 | printf(" %s", tok2str(type2str, "Type%d", typ)); | |
321 | switch (typ) { | |
322 | ||
323 | case T_A: | |
324 | printf(" %s", ipaddr_string(cp)); | |
325 | break; | |
326 | ||
327 | case T_NS: | |
328 | case T_CNAME: | |
329 | case T_PTR: | |
330 | putchar(' '); | |
331 | (void)ns_nprint(cp, bp); | |
332 | break; | |
333 | ||
334 | case T_MX: | |
335 | putchar(' '); | |
336 | (void)ns_nprint(cp + 2, bp); | |
337 | printf(" %d", EXTRACT_16BITS(cp)); | |
338 | break; | |
339 | ||
340 | case T_TXT: | |
341 | putchar(' '); | |
342 | (void)ns_cprint(cp, bp); | |
343 | break; | |
344 | ||
345 | case T_UNSPECA: /* One long string */ | |
346 | printf(" %.*s", len, cp); | |
347 | break; | |
348 | } | |
349 | return (rp); /* XXX This isn't always right */ | |
350 | } | |
351 | ||
352 | void | |
353 | ns_print(register const u_char *bp, u_int length) | |
354 | { | |
355 | register const HEADER *np; | |
356 | register int qdcount, ancount, nscount, arcount; | |
357 | register const u_char *cp; | |
358 | ||
359 | np = (const HEADER *)bp; | |
360 | /* get the byte-order right */ | |
361 | qdcount = ntohs(np->qdcount); | |
362 | ancount = ntohs(np->ancount); | |
363 | nscount = ntohs(np->nscount); | |
364 | arcount = ntohs(np->arcount); | |
365 | ||
366 | if (np->qr) { | |
367 | /* this is a response */ | |
368 | printf(" %d%s%s%s%s%s", | |
369 | ntohs(np->id), | |
370 | ns_ops[np->opcode], | |
371 | ns_resp[np->rcode], | |
372 | np->aa? "*" : "", | |
373 | np->ra? "" : "-", | |
374 | np->tc? "|" : ""); | |
375 | if (qdcount != 1) | |
376 | printf(" [%dq]", qdcount); | |
377 | /* Print QUESTION section on -vv */ | |
378 | if (vflag > 1) { | |
379 | fputs(" q: ", stdout); | |
380 | cp = ns_nprint((const u_char *)(np + 1), bp); | |
381 | } else | |
382 | cp = ns_nskip((const u_char *)(np + 1), bp); | |
383 | printf(" %d/%d/%d", ancount, nscount, arcount); | |
384 | if (ancount--) { | |
385 | cp = ns_rprint(cp + 4, bp); | |
386 | while (ancount-- && cp < snapend) { | |
387 | putchar(','); | |
388 | cp = ns_rprint(cp, bp); | |
389 | } | |
390 | } | |
391 | } | |
392 | else { | |
393 | /* this is a request */ | |
394 | printf(" %d%s%s", | |
395 | ntohs(np->id), | |
396 | ns_ops[np->opcode], | |
397 | np->rd? "+" : ""); | |
398 | ||
399 | /* any weirdness? */ | |
400 | if (*(((u_short *)np)+1) & htons(0x6ff)) | |
401 | printf(" [b2&3=0x%x]", ntohs(*(((u_short *)np)+1))); | |
402 | ||
403 | if (np->opcode == IQUERY) { | |
404 | if (qdcount) | |
405 | printf(" [%dq]", qdcount); | |
406 | if (ancount != 1) | |
407 | printf(" [%da]", ancount); | |
408 | } | |
409 | else { | |
410 | if (ancount) | |
411 | printf(" [%da]", ancount); | |
412 | if (qdcount != 1) | |
413 | printf(" [%dq]", qdcount); | |
414 | } | |
415 | if (nscount) | |
416 | printf(" [%dn]", nscount); | |
417 | if (arcount) | |
418 | printf(" [%dau]", arcount); | |
419 | ||
420 | ns_qprint((const u_char *)(np + 1), (const u_char *)np); | |
421 | } | |
422 | printf(" (%d)", length); | |
423 | } |