1 |
|
|
/* $OpenBSD: print-domain.c,v 1.24 2017/02/27 11:44:23 jca Exp $ */ |
2 |
|
|
|
3 |
|
|
/* |
4 |
|
|
* Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997 |
5 |
|
|
* The Regents of the University of California. All rights reserved. |
6 |
|
|
* |
7 |
|
|
* Redistribution and use in source and binary forms, with or without |
8 |
|
|
* modification, are permitted provided that: (1) source code distributions |
9 |
|
|
* retain the above copyright notice and this paragraph in its entirety, (2) |
10 |
|
|
* distributions including binary code include the above copyright notice and |
11 |
|
|
* this paragraph in its entirety in the documentation or other materials |
12 |
|
|
* provided with the distribution, and (3) all advertising materials mentioning |
13 |
|
|
* features or use of this software display the following acknowledgement: |
14 |
|
|
* ``This product includes software developed by the University of California, |
15 |
|
|
* Lawrence Berkeley Laboratory and its contributors.'' Neither the name of |
16 |
|
|
* the University nor the names of its contributors may be used to endorse |
17 |
|
|
* or promote products derived from this software without specific prior |
18 |
|
|
* written permission. |
19 |
|
|
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED |
20 |
|
|
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF |
21 |
|
|
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. |
22 |
|
|
*/ |
23 |
|
|
|
24 |
|
|
#include <sys/time.h> |
25 |
|
|
#include <sys/socket.h> |
26 |
|
|
|
27 |
|
|
#include <net/if.h> |
28 |
|
|
|
29 |
|
|
#include <netinet/in.h> |
30 |
|
|
#include <netinet/if_ether.h> |
31 |
|
|
#include <netinet/ip.h> |
32 |
|
|
#include <netinet/ip_var.h> |
33 |
|
|
#include <netinet/udp.h> |
34 |
|
|
#include <netinet/udp_var.h> |
35 |
|
|
#include <netinet/tcp.h> |
36 |
|
|
|
37 |
|
|
#ifdef NOERROR |
38 |
|
|
#undef NOERROR /* Solaris sucks */ |
39 |
|
|
#endif |
40 |
|
|
#ifdef NOERROR |
41 |
|
|
#undef T_UNSPEC /* SINIX does too */ |
42 |
|
|
#endif |
43 |
|
|
#include "nameser.h" |
44 |
|
|
|
45 |
|
|
#include <stdio.h> |
46 |
|
|
#include <string.h> |
47 |
|
|
|
48 |
|
|
#include "interface.h" |
49 |
|
|
#include "addrtoname.h" |
50 |
|
|
#include "extract.h" /* must come after interface.h */ |
51 |
|
|
|
52 |
|
|
static const char *ns_ops[] = { |
53 |
|
|
"", " inv_q", " stat", " op3", " notify", " update", " op6", " op7", |
54 |
|
|
" op8", " updataA", " updateD", " updateDA", |
55 |
|
|
" updateM", " updateMA", " zoneInit", " zoneRef", |
56 |
|
|
}; |
57 |
|
|
|
58 |
|
|
static const char *ns_resp[] = { |
59 |
|
|
"", " FormErr", " ServFail", " NXDomain", |
60 |
|
|
" NotImp", " Refused", " YXDomain", " YXRRSet", |
61 |
|
|
" NXRRSet", " NotAuth", " NotZone", " Resp11", |
62 |
|
|
" Resp12", " Resp13", " Resp14", " NoChange", |
63 |
|
|
}; |
64 |
|
|
|
65 |
|
|
/* skip over a domain name */ |
66 |
|
|
static const u_char * |
67 |
|
|
ns_nskip(const u_char *cp) |
68 |
|
|
{ |
69 |
|
|
u_char i; |
70 |
|
|
|
71 |
|
|
if (!TTEST2(*cp, 1)) |
72 |
|
|
return (NULL); |
73 |
|
|
i = *cp++; |
74 |
|
|
while (i) { |
75 |
|
|
if ((i & INDIR_MASK) == INDIR_MASK) |
76 |
|
|
return (cp + 1); |
77 |
|
|
if ((i & INDIR_MASK) == EDNS0_MASK) { |
78 |
|
|
int bitlen, bytelen; |
79 |
|
|
|
80 |
|
|
if ((i & ~INDIR_MASK) != EDNS0_ELT_BITLABEL) |
81 |
|
|
return(NULL); /* unknown ELT */ |
82 |
|
|
if (!TTEST2(*cp, 1)) |
83 |
|
|
return (NULL); |
84 |
|
|
if ((bitlen = *cp++) == 0) |
85 |
|
|
bitlen = 256; |
86 |
|
|
bytelen = (bitlen + 7) / 8; |
87 |
|
|
cp += bytelen; |
88 |
|
|
} else |
89 |
|
|
cp += i; |
90 |
|
|
if (!TTEST2(*cp, 1)) |
91 |
|
|
return (NULL); |
92 |
|
|
i = *cp++; |
93 |
|
|
} |
94 |
|
|
return (cp); |
95 |
|
|
} |
96 |
|
|
|
97 |
|
|
/* print a <domain-name> */ |
98 |
|
|
static const u_char * |
99 |
|
|
blabel_print(const u_char *cp) |
100 |
|
|
{ |
101 |
|
|
int bitlen, slen, b; |
102 |
|
|
const u_char *bitp, *lim; |
103 |
|
|
char tc; |
104 |
|
|
|
105 |
|
|
if (!TTEST2(*cp, 1)) |
106 |
|
|
return(NULL); |
107 |
|
|
if ((bitlen = *cp) == 0) |
108 |
|
|
bitlen = 256; |
109 |
|
|
slen = (bitlen + 3) / 4; |
110 |
|
|
lim = cp + 1 + slen; |
111 |
|
|
|
112 |
|
|
/* print the bit string as a hex string */ |
113 |
|
|
printf("\\[x"); |
114 |
|
|
for (bitp = cp + 1, b = bitlen; bitp < lim && b > 7; b -= 8, bitp++) { |
115 |
|
|
TCHECK(*bitp); |
116 |
|
|
printf("%02x", *bitp); |
117 |
|
|
} |
118 |
|
|
if (b > 4) { |
119 |
|
|
TCHECK(*bitp); |
120 |
|
|
tc = *bitp++; |
121 |
|
|
printf("%02x", tc & (0xff << (8 - b))); |
122 |
|
|
} else if (b > 0) { |
123 |
|
|
TCHECK(*bitp); |
124 |
|
|
tc = *bitp++; |
125 |
|
|
printf("%1x", ((tc >> 4) & 0x0f) & (0x0f << (4 - b))); |
126 |
|
|
} |
127 |
|
|
printf("/%d]", bitlen); |
128 |
|
|
return lim; |
129 |
|
|
trunc: |
130 |
|
|
printf(".../%d]", bitlen); |
131 |
|
|
return NULL; |
132 |
|
|
} |
133 |
|
|
|
134 |
|
|
static int |
135 |
|
|
labellen(const u_char *cp) |
136 |
|
|
{ |
137 |
|
|
u_int i; |
138 |
|
|
|
139 |
|
|
if (!TTEST2(*cp, 1)) |
140 |
|
|
return(-1); |
141 |
|
|
i = *cp; |
142 |
|
|
if ((i & INDIR_MASK) == EDNS0_MASK) { |
143 |
|
|
int bitlen, elt; |
144 |
|
|
if ((elt = (i & ~INDIR_MASK)) != EDNS0_ELT_BITLABEL) { |
145 |
|
|
printf("<ELT %d>", elt); |
146 |
|
|
return(-1); |
147 |
|
|
} |
148 |
|
|
if (!TTEST2(*(cp + 1), 1)) |
149 |
|
|
return(-1); |
150 |
|
|
if ((bitlen = *(cp + 1)) == 0) |
151 |
|
|
bitlen = 256; |
152 |
|
|
return(((bitlen + 7) / 8) + 1); |
153 |
|
|
} else |
154 |
|
|
return(i); |
155 |
|
|
} |
156 |
|
|
|
157 |
|
|
static const u_char * |
158 |
|
|
ns_nprint(const u_char *cp, const u_char *bp) |
159 |
|
|
{ |
160 |
|
|
u_int i, l; |
161 |
|
|
const u_char *rp = NULL; |
162 |
|
|
int compress = 0; |
163 |
|
|
int chars_processed; |
164 |
|
|
int elt; |
165 |
|
|
int data_size = snapend - bp; |
166 |
|
|
|
167 |
|
|
if ((l = labellen(cp)) == (u_int)-1) |
168 |
|
|
return(NULL); |
169 |
|
|
if (!TTEST2(*cp, 1)) |
170 |
|
|
return(NULL); |
171 |
|
|
chars_processed = 1; |
172 |
|
|
if (((i = *cp++) & INDIR_MASK) != INDIR_MASK) { |
173 |
|
|
compress = 0; |
174 |
|
|
rp = cp + l; |
175 |
|
|
} |
176 |
|
|
|
177 |
|
|
if (i != 0) |
178 |
|
|
while (i && cp < snapend) { |
179 |
|
|
if ((i & INDIR_MASK) == INDIR_MASK) { |
180 |
|
|
if (!compress) { |
181 |
|
|
rp = cp + 1; |
182 |
|
|
compress = 1; |
183 |
|
|
} |
184 |
|
|
if (!TTEST2(*cp, 1)) |
185 |
|
|
return(NULL); |
186 |
|
|
cp = bp + (((i << 8) | *cp) & 0x3fff); |
187 |
|
|
if ((l = labellen(cp)) == (u_int)-1) |
188 |
|
|
return(NULL); |
189 |
|
|
if (!TTEST2(*cp, 1)) |
190 |
|
|
return(NULL); |
191 |
|
|
i = *cp++; |
192 |
|
|
chars_processed++; |
193 |
|
|
|
194 |
|
|
/* |
195 |
|
|
* If we've looked at every character in |
196 |
|
|
* the message, this pointer will make |
197 |
|
|
* us look at some character again, |
198 |
|
|
* which means we're looping. |
199 |
|
|
*/ |
200 |
|
|
if (chars_processed >= data_size) { |
201 |
|
|
printf("<LOOP>"); |
202 |
|
|
return (NULL); |
203 |
|
|
} |
204 |
|
|
continue; |
205 |
|
|
} |
206 |
|
|
if ((i & INDIR_MASK) == EDNS0_MASK) { |
207 |
|
|
elt = (i & ~INDIR_MASK); |
208 |
|
|
switch(elt) { |
209 |
|
|
case EDNS0_ELT_BITLABEL: |
210 |
|
|
if (blabel_print(cp) == NULL) |
211 |
|
|
return (NULL); |
212 |
|
|
break; |
213 |
|
|
default: |
214 |
|
|
/* unknown ELT */ |
215 |
|
|
printf("<ELT %d>", elt); |
216 |
|
|
return(NULL); |
217 |
|
|
} |
218 |
|
|
} else { |
219 |
|
|
if (fn_printn(cp, l, snapend)) |
220 |
|
|
return(NULL); |
221 |
|
|
} |
222 |
|
|
|
223 |
|
|
cp += l; |
224 |
|
|
chars_processed += l; |
225 |
|
|
putchar('.'); |
226 |
|
|
if ((l = labellen(cp)) == (u_int)-1) |
227 |
|
|
return(NULL); |
228 |
|
|
if (!TTEST2(*cp, 1)) |
229 |
|
|
return(NULL); |
230 |
|
|
i = *cp++; |
231 |
|
|
chars_processed++; |
232 |
|
|
if (!compress) |
233 |
|
|
rp += l + 1; |
234 |
|
|
} |
235 |
|
|
else |
236 |
|
|
putchar('.'); |
237 |
|
|
return (rp); |
238 |
|
|
} |
239 |
|
|
|
240 |
|
|
/* print a <character-string> */ |
241 |
|
|
static const u_char * |
242 |
|
|
ns_cprint(const u_char *cp) |
243 |
|
|
{ |
244 |
|
|
u_int i; |
245 |
|
|
|
246 |
|
|
if (!TTEST2(*cp, 1)) |
247 |
|
|
return (NULL); |
248 |
|
|
i = *cp++; |
249 |
|
|
if (fn_printn(cp, i, snapend)) |
250 |
|
|
return (NULL); |
251 |
|
|
return (cp + i); |
252 |
|
|
} |
253 |
|
|
|
254 |
|
|
/* https://www.iana.org/assignments/dns-parameters */ |
255 |
|
|
struct tok ns_type2str[] = { |
256 |
|
|
{ T_A, "A" }, /* RFC 1035 */ |
257 |
|
|
{ T_NS, "NS" }, /* RFC 1035 */ |
258 |
|
|
{ T_MD, "MD" }, /* RFC 1035 */ |
259 |
|
|
{ T_MF, "MF" }, /* RFC 1035 */ |
260 |
|
|
{ T_CNAME, "CNAME" }, /* RFC 1035 */ |
261 |
|
|
{ T_SOA, "SOA" }, /* RFC 1035 */ |
262 |
|
|
{ T_MB, "MB" }, /* RFC 1035 */ |
263 |
|
|
{ T_MG, "MG" }, /* RFC 1035 */ |
264 |
|
|
{ T_MR, "MR" }, /* RFC 1035 */ |
265 |
|
|
{ T_NULL, "NULL" }, /* RFC 1035 */ |
266 |
|
|
{ T_WKS, "WKS" }, /* RFC 1035 */ |
267 |
|
|
{ T_PTR, "PTR" }, /* RFC 1035 */ |
268 |
|
|
{ T_HINFO, "HINFO" }, /* RFC 1035 */ |
269 |
|
|
{ T_MINFO, "MINFO" }, /* RFC 1035 */ |
270 |
|
|
{ T_MX, "MX" }, /* RFC 1035 */ |
271 |
|
|
{ T_TXT, "TXT" }, /* RFC 1035 */ |
272 |
|
|
{ T_RP, "RP" }, /* RFC 1183 */ |
273 |
|
|
{ T_AFSDB, "AFSDB" }, /* RFC 1183 */ |
274 |
|
|
{ T_X25, "X25" }, /* RFC 1183 */ |
275 |
|
|
{ T_ISDN, "ISDN" }, /* RFC 1183 */ |
276 |
|
|
{ T_RT, "RT" }, /* RFC 1183 */ |
277 |
|
|
{ T_NSAP, "NSAP" }, /* RFC 1706 */ |
278 |
|
|
{ T_NSAP_PTR, "NSAP_PTR" }, |
279 |
|
|
{ T_SIG, "SIG" }, /* RFC 2535 */ |
280 |
|
|
{ T_KEY, "KEY" }, /* RFC 2535 */ |
281 |
|
|
{ T_PX, "PX" }, /* RFC 2163 */ |
282 |
|
|
{ T_GPOS, "GPOS" }, /* RFC 1712 */ |
283 |
|
|
{ T_AAAA, "AAAA" }, /* RFC 1886 */ |
284 |
|
|
{ T_LOC, "LOC" }, /* RFC 1876 */ |
285 |
|
|
{ T_NXT, "NXT" }, /* RFC 2535 */ |
286 |
|
|
{ T_EID, "EID" }, /* Nimrod */ |
287 |
|
|
{ T_NIMLOC, "NIMLOC" }, /* Nimrod */ |
288 |
|
|
{ T_SRV, "SRV" }, /* RFC 2782 */ |
289 |
|
|
{ T_ATMA, "ATMA" }, /* ATM Forum */ |
290 |
|
|
{ T_NAPTR, "NAPTR" }, /* RFC 2168, RFC 2915 */ |
291 |
|
|
{ T_KX, "KX" }, /* RFC 2230 */ |
292 |
|
|
{ T_CERT, "CERT" }, /* RFC 2538 */ |
293 |
|
|
{ T_A6, "A6" }, /* RFC 2874 */ |
294 |
|
|
{ T_DNAME, "DNAME" }, /* RFC 2672 */ |
295 |
|
|
{ T_SINK, "SINK" }, |
296 |
|
|
{ T_OPT, "OPT" }, /* RFC 2671 */ |
297 |
|
|
{ T_APL, "APL" }, /* RFC 3123 */ |
298 |
|
|
{ T_DS, "DS" }, /* RFC 4034 */ |
299 |
|
|
{ T_SSHFP, "SSHFP" }, /* RFC 4255 */ |
300 |
|
|
{ T_IPSECKEY, "IPSECKEY" }, /* RFC 4025 */ |
301 |
|
|
{ T_RRSIG, "RRSIG" }, /* RFC 4034 */ |
302 |
|
|
{ T_NSEC, "NSEC" }, /* RFC 4034 */ |
303 |
|
|
{ T_DNSKEY, "DNSKEY" }, /* RFC 4034 */ |
304 |
|
|
{ T_SPF, "SPF" }, /* RFC-schlitt-spf-classic-02.txt */ |
305 |
|
|
{ T_UINFO, "UINFO" }, |
306 |
|
|
{ T_UID, "UID" }, |
307 |
|
|
{ T_GID, "GID" }, |
308 |
|
|
{ T_UNSPEC, "UNSPEC" }, |
309 |
|
|
{ T_UNSPECA, "UNSPECA" }, |
310 |
|
|
{ T_TKEY, "TKEY" }, /* RFC 2930 */ |
311 |
|
|
{ T_TSIG, "TSIG" }, /* RFC 2845 */ |
312 |
|
|
{ T_IXFR, "IXFR" }, /* RFC 1995 */ |
313 |
|
|
{ T_AXFR, "AXFR" }, /* RFC 1035 */ |
314 |
|
|
{ T_MAILB, "MAILB" }, /* RFC 1035 */ |
315 |
|
|
{ T_MAILA, "MAILA" }, /* RFC 1035 */ |
316 |
|
|
{ T_ANY, "ANY" }, |
317 |
|
|
{ 0, NULL } |
318 |
|
|
}; |
319 |
|
|
|
320 |
|
|
struct tok ns_class2str[] = { |
321 |
|
|
{ C_IN, "IN" }, /* Not used */ |
322 |
|
|
{ C_CHAOS, "CHAOS" }, |
323 |
|
|
{ C_HS, "HS" }, |
324 |
|
|
{ C_ANY, "ANY" }, |
325 |
|
|
{ 0, NULL } |
326 |
|
|
}; |
327 |
|
|
|
328 |
|
|
/* print a query */ |
329 |
|
|
static const u_char * |
330 |
|
|
ns_qprint(const u_char *cp, const u_char *bp, int is_mdns) |
331 |
|
|
{ |
332 |
|
|
const u_char *np = cp; |
333 |
|
|
u_int i, class; |
334 |
|
|
|
335 |
|
|
cp = ns_nskip(cp); |
336 |
|
|
|
337 |
|
|
if (cp == NULL || !TTEST2(*cp, 4)) |
338 |
|
|
return(NULL); |
339 |
|
|
|
340 |
|
|
/* print the qtype */ |
341 |
|
|
i = EXTRACT_16BITS(cp); |
342 |
|
|
cp += 2; |
343 |
|
|
printf(" %s", tok2str(ns_type2str, "Type%d", i)); |
344 |
|
|
/* print the qclass (if it's not IN) */ |
345 |
|
|
i = EXTRACT_16BITS(cp); |
346 |
|
|
cp += 2; |
347 |
|
|
if (is_mdns) |
348 |
|
|
class = (i & ~C_QU); |
349 |
|
|
else |
350 |
|
|
class = i; |
351 |
|
|
if (class != C_IN) |
352 |
|
|
printf(" %s", tok2str(ns_class2str, "(Class %d)", class)); |
353 |
|
|
if (is_mdns && (i & C_QU)) |
354 |
|
|
printf(" (QU)"); |
355 |
|
|
|
356 |
|
|
fputs("? ", stdout); |
357 |
|
|
cp = ns_nprint(np, bp); |
358 |
|
|
return(cp ? cp + 4 : NULL); |
359 |
|
|
} |
360 |
|
|
|
361 |
|
|
/* print a reply */ |
362 |
|
|
static const u_char * |
363 |
|
|
ns_rprint(const u_char *cp, const u_char *bp, int is_mdns) |
364 |
|
|
{ |
365 |
|
|
u_int i, class, opt_flags = 0; |
366 |
|
|
u_short typ, len; |
367 |
|
|
const u_char *rp; |
368 |
|
|
|
369 |
|
|
if (vflag) { |
370 |
|
|
putchar(' '); |
371 |
|
|
if ((cp = ns_nprint(cp, bp)) == NULL) |
372 |
|
|
return NULL; |
373 |
|
|
} else |
374 |
|
|
cp = ns_nskip(cp); |
375 |
|
|
|
376 |
|
|
if (cp == NULL || !TTEST2(*cp, 10)) |
377 |
|
|
return (snapend); |
378 |
|
|
|
379 |
|
|
/* print the type/qtype */ |
380 |
|
|
typ = EXTRACT_16BITS(cp); |
381 |
|
|
cp += 2; |
382 |
|
|
/* print the class (if it's not IN and the type isn't OPT) */ |
383 |
|
|
i = EXTRACT_16BITS(cp); |
384 |
|
|
cp += 2; |
385 |
|
|
if (is_mdns) |
386 |
|
|
class = (i & ~C_CACHE_FLUSH); |
387 |
|
|
else |
388 |
|
|
class = i; |
389 |
|
|
if (class != C_IN && typ != T_OPT) |
390 |
|
|
printf(" %s", tok2str(ns_class2str, "(Class %d)", class)); |
391 |
|
|
if (is_mdns) { |
392 |
|
|
if (i & C_CACHE_FLUSH) |
393 |
|
|
printf(" (Cache flush)"); |
394 |
|
|
} |
395 |
|
|
|
396 |
|
|
if (typ == T_OPT) { |
397 |
|
|
/* get opt flags */ |
398 |
|
|
cp += 2; |
399 |
|
|
opt_flags = EXTRACT_16BITS(cp); |
400 |
|
|
/* ignore rest of ttl field */ |
401 |
|
|
cp += 2; |
402 |
|
|
} else if (vflag > 2) { |
403 |
|
|
/* print ttl */ |
404 |
|
|
printf(" ["); |
405 |
|
|
relts_print(EXTRACT_32BITS(cp)); |
406 |
|
|
printf("]"); |
407 |
|
|
cp += 4; |
408 |
|
|
} else { |
409 |
|
|
/* ignore ttl */ |
410 |
|
|
cp += 4; |
411 |
|
|
} |
412 |
|
|
|
413 |
|
|
len = EXTRACT_16BITS(cp); |
414 |
|
|
cp += 2; |
415 |
|
|
|
416 |
|
|
rp = cp + len; |
417 |
|
|
|
418 |
|
|
printf(" %s", tok2str(ns_type2str, "Type%d", typ)); |
419 |
|
|
if (rp > snapend) |
420 |
|
|
return(NULL); |
421 |
|
|
|
422 |
|
|
switch (typ) { |
423 |
|
|
case T_A: |
424 |
|
|
if (!TTEST2(*cp, sizeof(struct in_addr))) |
425 |
|
|
return(NULL); |
426 |
|
|
printf(" %s", ipaddr_string(cp)); |
427 |
|
|
break; |
428 |
|
|
|
429 |
|
|
case T_NS: |
430 |
|
|
case T_CNAME: |
431 |
|
|
case T_PTR: |
432 |
|
|
#ifdef T_DNAME |
433 |
|
|
case T_DNAME: |
434 |
|
|
#endif |
435 |
|
|
putchar(' '); |
436 |
|
|
if (ns_nprint(cp, bp) == NULL) |
437 |
|
|
return(NULL); |
438 |
|
|
break; |
439 |
|
|
|
440 |
|
|
case T_SOA: |
441 |
|
|
if (!vflag) |
442 |
|
|
break; |
443 |
|
|
putchar(' '); |
444 |
|
|
if ((cp = ns_nprint(cp, bp)) == NULL) |
445 |
|
|
return(NULL); |
446 |
|
|
putchar(' '); |
447 |
|
|
if ((cp = ns_nprint(cp, bp)) == NULL) |
448 |
|
|
return(NULL); |
449 |
|
|
if (!TTEST2(*cp, 5 * 4)) |
450 |
|
|
return(NULL); |
451 |
|
|
printf(" %u", EXTRACT_32BITS(cp)); |
452 |
|
|
cp += 4; |
453 |
|
|
printf(" %u", EXTRACT_32BITS(cp)); |
454 |
|
|
cp += 4; |
455 |
|
|
printf(" %u", EXTRACT_32BITS(cp)); |
456 |
|
|
cp += 4; |
457 |
|
|
printf(" %u", EXTRACT_32BITS(cp)); |
458 |
|
|
cp += 4; |
459 |
|
|
printf(" %u", EXTRACT_32BITS(cp)); |
460 |
|
|
cp += 4; |
461 |
|
|
break; |
462 |
|
|
case T_MX: |
463 |
|
|
putchar(' '); |
464 |
|
|
if (!TTEST2(*cp, 2)) |
465 |
|
|
return(NULL); |
466 |
|
|
if (ns_nprint(cp + 2, bp) == NULL) |
467 |
|
|
return(NULL); |
468 |
|
|
printf(" %d", EXTRACT_16BITS(cp)); |
469 |
|
|
break; |
470 |
|
|
|
471 |
|
|
case T_TXT: |
472 |
|
|
while (cp < rp) { |
473 |
|
|
printf(" \""); |
474 |
|
|
cp = ns_cprint(cp); |
475 |
|
|
if (cp == NULL) |
476 |
|
|
return(NULL); |
477 |
|
|
putchar('"'); |
478 |
|
|
} |
479 |
|
|
break; |
480 |
|
|
|
481 |
|
|
case T_SRV: |
482 |
|
|
putchar(' '); |
483 |
|
|
if (!TTEST2(*cp, 6)) |
484 |
|
|
return(NULL); |
485 |
|
|
if (ns_nprint(cp + 6, bp) == NULL) |
486 |
|
|
return(NULL); |
487 |
|
|
printf(":%d %d %d", EXTRACT_16BITS(cp + 4), |
488 |
|
|
EXTRACT_16BITS(cp), EXTRACT_16BITS(cp + 2)); |
489 |
|
|
break; |
490 |
|
|
|
491 |
|
|
#ifdef INET6 |
492 |
|
|
case T_AAAA: |
493 |
|
|
if (!TTEST2(*cp, sizeof(struct in6_addr))) |
494 |
|
|
return(NULL); |
495 |
|
|
printf(" %s", ip6addr_string(cp)); |
496 |
|
|
break; |
497 |
|
|
|
498 |
|
|
case T_A6: |
499 |
|
|
{ |
500 |
|
|
struct in6_addr a; |
501 |
|
|
int pbit, pbyte; |
502 |
|
|
|
503 |
|
|
if (!TTEST2(*cp, 1)) |
504 |
|
|
return(NULL); |
505 |
|
|
pbit = *cp; |
506 |
|
|
pbyte = (pbit & ~7) / 8; |
507 |
|
|
if (pbit > 128) { |
508 |
|
|
printf(" %u(bad plen)", pbit); |
509 |
|
|
break; |
510 |
|
|
} else if (pbit < 128) { |
511 |
|
|
if (!TTEST2(*(cp + 1), sizeof(a) - pbyte)) |
512 |
|
|
return(NULL); |
513 |
|
|
memset(&a, 0, sizeof(a)); |
514 |
|
|
memcpy(&a.s6_addr[pbyte], cp + 1, sizeof(a) - pbyte); |
515 |
|
|
printf(" %u %s", pbit, ip6addr_string(&a)); |
516 |
|
|
} |
517 |
|
|
if (pbit > 0) { |
518 |
|
|
putchar(' '); |
519 |
|
|
if (ns_nprint(cp + 1 + sizeof(a) - pbyte, bp) == NULL) |
520 |
|
|
return(NULL); |
521 |
|
|
} |
522 |
|
|
break; |
523 |
|
|
} |
524 |
|
|
#endif /*INET6*/ |
525 |
|
|
|
526 |
|
|
case T_OPT: |
527 |
|
|
printf(" UDPsize=%u", class); |
528 |
|
|
if (opt_flags & 0x8000) |
529 |
|
|
printf(" DO"); |
530 |
|
|
break; |
531 |
|
|
|
532 |
|
|
case T_UNSPECA: /* One long string */ |
533 |
|
|
if (!TTEST2(*cp, len)) |
534 |
|
|
return(NULL); |
535 |
|
|
if (fn_printn(cp, len, snapend)) |
536 |
|
|
return(NULL); |
537 |
|
|
break; |
538 |
|
|
|
539 |
|
|
case T_TSIG: |
540 |
|
|
{ |
541 |
|
|
if (cp + len > snapend) |
542 |
|
|
return(NULL); |
543 |
|
|
if (!vflag) |
544 |
|
|
break; |
545 |
|
|
putchar(' '); |
546 |
|
|
if ((cp = ns_nprint(cp, bp)) == NULL) |
547 |
|
|
return(NULL); |
548 |
|
|
cp += 6; |
549 |
|
|
if (!TTEST2(*cp, 2)) |
550 |
|
|
return(NULL); |
551 |
|
|
printf(" fudge=%u", EXTRACT_16BITS(cp)); |
552 |
|
|
cp += 2; |
553 |
|
|
if (!TTEST2(*cp, 2)) |
554 |
|
|
return(NULL); |
555 |
|
|
printf(" maclen=%u", EXTRACT_16BITS(cp)); |
556 |
|
|
cp += 2 + EXTRACT_16BITS(cp); |
557 |
|
|
if (!TTEST2(*cp, 2)) |
558 |
|
|
return(NULL); |
559 |
|
|
printf(" origid=%u", EXTRACT_16BITS(cp)); |
560 |
|
|
cp += 2; |
561 |
|
|
if (!TTEST2(*cp, 2)) |
562 |
|
|
return(NULL); |
563 |
|
|
printf(" error=%u", EXTRACT_16BITS(cp)); |
564 |
|
|
cp += 2; |
565 |
|
|
if (!TTEST2(*cp, 2)) |
566 |
|
|
return(NULL); |
567 |
|
|
printf(" otherlen=%u", EXTRACT_16BITS(cp)); |
568 |
|
|
cp += 2; |
569 |
|
|
} |
570 |
|
|
} |
571 |
|
|
return (rp); /* XXX This isn't always right */ |
572 |
|
|
} |
573 |
|
|
|
574 |
|
|
void |
575 |
|
|
ns_print(const u_char *bp, u_int length, int is_mdns) |
576 |
|
|
{ |
577 |
|
|
const HEADER *np; |
578 |
|
|
int qdcount, ancount, nscount, arcount; |
579 |
|
|
const u_char *cp; |
580 |
|
|
u_int16_t b2; |
581 |
|
|
|
582 |
|
|
np = (const HEADER *)bp; |
583 |
|
|
TCHECK(*np); |
584 |
|
|
/* get the byte-order right */ |
585 |
|
|
qdcount = EXTRACT_16BITS(&np->qdcount); |
586 |
|
|
ancount = EXTRACT_16BITS(&np->ancount); |
587 |
|
|
nscount = EXTRACT_16BITS(&np->nscount); |
588 |
|
|
arcount = EXTRACT_16BITS(&np->arcount); |
589 |
|
|
|
590 |
|
|
if (DNS_QR(np)) { |
591 |
|
|
/* this is a response */ |
592 |
|
|
printf(" %d%s%s%s%s%s%s", |
593 |
|
|
EXTRACT_16BITS(&np->id), |
594 |
|
|
ns_ops[DNS_OPCODE(np)], |
595 |
|
|
ns_resp[DNS_RCODE(np)], |
596 |
|
|
DNS_AA(np)? "*" : "", |
597 |
|
|
DNS_RA(np)? "" : "-", |
598 |
|
|
DNS_TC(np)? "|" : "", |
599 |
|
|
DNS_AD(np)? "$" : ""); |
600 |
|
|
|
601 |
|
|
if (qdcount != 1) |
602 |
|
|
printf(" [%dq]", qdcount); |
603 |
|
|
/* Print QUESTION section on -vv */ |
604 |
|
|
cp = (const u_char *)(np + 1); |
605 |
|
|
while (qdcount--) { |
606 |
|
|
if (qdcount < EXTRACT_16BITS(&np->qdcount) - 1) |
607 |
|
|
putchar(','); |
608 |
|
|
if (vflag > 1) { |
609 |
|
|
fputs(" q:", stdout); |
610 |
|
|
if ((cp = ns_qprint(cp, bp, is_mdns)) == NULL) |
611 |
|
|
goto trunc; |
612 |
|
|
} else { |
613 |
|
|
if ((cp = ns_nskip(cp)) == NULL) |
614 |
|
|
goto trunc; |
615 |
|
|
cp += 4; /* skip QTYPE and QCLASS */ |
616 |
|
|
} |
617 |
|
|
} |
618 |
|
|
printf(" %d/%d/%d", ancount, nscount, arcount); |
619 |
|
|
if (ancount--) { |
620 |
|
|
if ((cp = ns_rprint(cp, bp, is_mdns)) == NULL) |
621 |
|
|
goto trunc; |
622 |
|
|
while (cp < snapend && ancount--) { |
623 |
|
|
putchar(','); |
624 |
|
|
if ((cp = ns_rprint(cp, bp, is_mdns)) == NULL) |
625 |
|
|
goto trunc; |
626 |
|
|
} |
627 |
|
|
} |
628 |
|
|
if (ancount > 0) |
629 |
|
|
goto trunc; |
630 |
|
|
/* Print NS and AR sections on -vv */ |
631 |
|
|
if (vflag > 1) { |
632 |
|
|
if (cp < snapend && nscount--) { |
633 |
|
|
fputs(" ns:", stdout); |
634 |
|
|
if ((cp = ns_rprint(cp, bp, is_mdns)) == NULL) |
635 |
|
|
goto trunc; |
636 |
|
|
while (cp < snapend && nscount--) { |
637 |
|
|
putchar(','); |
638 |
|
|
if ((cp = ns_rprint(cp, bp, is_mdns)) == NULL) |
639 |
|
|
goto trunc; |
640 |
|
|
} |
641 |
|
|
} |
642 |
|
|
if (nscount > 0) |
643 |
|
|
goto trunc; |
644 |
|
|
if (cp < snapend && arcount--) { |
645 |
|
|
fputs(" ar:", stdout); |
646 |
|
|
if ((cp = ns_rprint(cp, bp, is_mdns)) == NULL) |
647 |
|
|
goto trunc; |
648 |
|
|
while (cp < snapend && arcount--) { |
649 |
|
|
putchar(','); |
650 |
|
|
if ((cp = ns_rprint(cp, bp, is_mdns)) == NULL) |
651 |
|
|
goto trunc; |
652 |
|
|
} |
653 |
|
|
} |
654 |
|
|
if (arcount > 0) |
655 |
|
|
goto trunc; |
656 |
|
|
} |
657 |
|
|
} |
658 |
|
|
else { |
659 |
|
|
/* this is a request */ |
660 |
|
|
printf(" %d%s%s%s", EXTRACT_16BITS(&np->id), ns_ops[DNS_OPCODE(np)], |
661 |
|
|
DNS_RD(np) ? "+" : "", |
662 |
|
|
DNS_CD(np) ? "%" : ""); |
663 |
|
|
|
664 |
|
|
/* any weirdness? AA is expected in NOTIFY. */ |
665 |
|
|
b2 = EXTRACT_16BITS(((u_short *)np)+1); |
666 |
|
|
if ((b2 & 0x6cf) != |
667 |
|
|
(DNS_OPCODE(np) == NS_NOTIFY_OP ? htons(0x400) : 0)) |
668 |
|
|
printf(" [b2&3=0x%x]", b2); |
669 |
|
|
|
670 |
|
|
if (DNS_OPCODE(np) == IQUERY) { |
671 |
|
|
if (qdcount) |
672 |
|
|
printf(" [%dq]", qdcount); |
673 |
|
|
if (ancount != 1) |
674 |
|
|
printf(" [%da]", ancount); |
675 |
|
|
} |
676 |
|
|
else { |
677 |
|
|
if (ancount) |
678 |
|
|
printf(" [%da]", ancount); |
679 |
|
|
if (qdcount != 1) |
680 |
|
|
printf(" [%dq]", qdcount); |
681 |
|
|
} |
682 |
|
|
if (nscount) |
683 |
|
|
printf(" [%dn]", nscount); |
684 |
|
|
if (arcount) |
685 |
|
|
printf(" [%dau]", arcount); |
686 |
|
|
|
687 |
|
|
cp = (const u_char *)(np + 1); |
688 |
|
|
if (qdcount--) { |
689 |
|
|
cp = ns_qprint(cp, (const u_char *)np, is_mdns); |
690 |
|
|
if (!cp) |
691 |
|
|
goto trunc; |
692 |
|
|
while (cp < snapend && qdcount--) { |
693 |
|
|
cp = ns_qprint((const u_char *)cp, |
694 |
|
|
(const u_char *)np, |
695 |
|
|
is_mdns); |
696 |
|
|
if (!cp) |
697 |
|
|
goto trunc; |
698 |
|
|
} |
699 |
|
|
} |
700 |
|
|
if (qdcount > 0) |
701 |
|
|
goto trunc; |
702 |
|
|
|
703 |
|
|
/* Print remaining sections on -vv */ |
704 |
|
|
if (vflag > 1) { |
705 |
|
|
if (ancount--) { |
706 |
|
|
if ((cp = ns_rprint(cp, bp, is_mdns)) == NULL) |
707 |
|
|
goto trunc; |
708 |
|
|
while (cp < snapend && ancount--) { |
709 |
|
|
putchar(','); |
710 |
|
|
if ((cp = ns_rprint(cp, bp, is_mdns)) == NULL) |
711 |
|
|
goto trunc; |
712 |
|
|
} |
713 |
|
|
} |
714 |
|
|
if (ancount > 0) |
715 |
|
|
goto trunc; |
716 |
|
|
if (cp < snapend && nscount--) { |
717 |
|
|
fputs(" ns:", stdout); |
718 |
|
|
if ((cp = ns_rprint(cp, bp, is_mdns)) == NULL) |
719 |
|
|
goto trunc; |
720 |
|
|
while (nscount-- && cp < snapend) { |
721 |
|
|
putchar(','); |
722 |
|
|
if ((cp = ns_rprint(cp, bp, is_mdns)) == NULL) |
723 |
|
|
goto trunc; |
724 |
|
|
} |
725 |
|
|
} |
726 |
|
|
if (nscount > 0) |
727 |
|
|
goto trunc; |
728 |
|
|
if (cp < snapend && arcount--) { |
729 |
|
|
fputs(" ar:", stdout); |
730 |
|
|
if ((cp = ns_rprint(cp, bp, is_mdns)) == NULL) |
731 |
|
|
goto trunc; |
732 |
|
|
while (cp < snapend && arcount--) { |
733 |
|
|
putchar(','); |
734 |
|
|
if ((cp = ns_rprint(cp, bp, is_mdns)) == NULL) |
735 |
|
|
goto trunc; |
736 |
|
|
} |
737 |
|
|
} |
738 |
|
|
if (arcount > 0) |
739 |
|
|
goto trunc; |
740 |
|
|
} |
741 |
|
|
} |
742 |
|
|
printf(" (%d)", length); |
743 |
|
|
return; |
744 |
|
|
|
745 |
|
|
trunc: |
746 |
|
|
printf("[|domain]"); |
747 |
|
|
return; |
748 |
|
|
} |