File: | src/usr.sbin/tcpdump/print-domain.c |
Warning: | line 121, column 29 The result of the left shift is undefined because the right operand is negative |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* $OpenBSD: print-domain.c,v 1.28 2023/03/01 08:15:58 claudio 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 NOERROR0 | |||
38 | #undef NOERROR0 /* Solaris sucks */ | |||
39 | #endif | |||
40 | #ifdef NOERROR0 | |||
41 | #undef T_UNSPEC103 /* 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)(snapend - (1) <= snapend && (const u_char *)& (*cp) <= snapend - (1))) | |||
72 | return (NULL((void *)0)); | |||
73 | i = *cp++; | |||
74 | while (i) { | |||
75 | if ((i & INDIR_MASK0xc0) == INDIR_MASK0xc0) | |||
76 | return (cp + 1); | |||
77 | if ((i & INDIR_MASK0xc0) == EDNS0_MASK0x40) { | |||
78 | int bitlen, bytelen; | |||
79 | ||||
80 | if ((i & ~INDIR_MASK0xc0) != EDNS0_ELT_BITLABEL0x01) | |||
81 | return(NULL((void *)0)); /* unknown ELT */ | |||
82 | if (!TTEST2(*cp, 1)(snapend - (1) <= snapend && (const u_char *)& (*cp) <= snapend - (1))) | |||
83 | return (NULL((void *)0)); | |||
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)(snapend - (1) <= snapend && (const u_char *)& (*cp) <= snapend - (1))) | |||
91 | return (NULL((void *)0)); | |||
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)(snapend - (1) <= snapend && (const u_char *)& (*cp) <= snapend - (1))) | |||
106 | return(NULL((void *)0)); | |||
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)if (!(snapend - (sizeof(*bitp)) <= snapend && (const u_char *)&(*bitp) <= snapend - (sizeof(*bitp)))) goto trunc; | |||
116 | printf("%02x", *bitp); | |||
117 | } | |||
118 | if (b
| |||
119 | TCHECK(*bitp)if (!(snapend - (sizeof(*bitp)) <= snapend && (const u_char *)&(*bitp) <= snapend - (sizeof(*bitp)))) goto trunc; | |||
120 | tc = *bitp++; | |||
121 | printf("%02x", tc & (0xff << (8 - b))); | |||
| ||||
122 | } else if (b > 0) { | |||
123 | TCHECK(*bitp)if (!(snapend - (sizeof(*bitp)) <= snapend && (const u_char *)&(*bitp) <= snapend - (sizeof(*bitp)))) goto trunc; | |||
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((void *)0); | |||
132 | } | |||
133 | ||||
134 | static int | |||
135 | labellen(const u_char *cp) | |||
136 | { | |||
137 | u_int i; | |||
138 | ||||
139 | if (!TTEST2(*cp, 1)(snapend - (1) <= snapend && (const u_char *)& (*cp) <= snapend - (1))) | |||
140 | return(-1); | |||
141 | i = *cp; | |||
142 | if ((i & INDIR_MASK0xc0) == EDNS0_MASK0x40) { | |||
143 | int bitlen, elt; | |||
144 | if ((elt = (i & ~INDIR_MASK0xc0)) != EDNS0_ELT_BITLABEL0x01) { | |||
145 | printf("<ELT %d>", elt); | |||
146 | return(-1); | |||
147 | } | |||
148 | if (!TTEST2(*(cp + 1), 1)(snapend - (1) <= snapend && (const u_char *)& (*(cp + 1)) <= snapend - (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((void *)0); | |||
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((void *)0)); | |||
169 | if (!TTEST2(*cp, 1)(snapend - (1) <= snapend && (const u_char *)& (*cp) <= snapend - (1))) | |||
170 | return(NULL((void *)0)); | |||
171 | chars_processed = 1; | |||
172 | if (((i = *cp++) & INDIR_MASK0xc0) != INDIR_MASK0xc0) { | |||
173 | compress = 0; | |||
174 | rp = cp + l; | |||
175 | } | |||
176 | ||||
177 | if (i
| |||
178 | while (i
| |||
179 | if ((i & INDIR_MASK0xc0) == INDIR_MASK0xc0) { | |||
180 | if (!compress) { | |||
181 | rp = cp + 1; | |||
182 | compress = 1; | |||
183 | } | |||
184 | if (!TTEST2(*cp, 1)(snapend - (1) <= snapend && (const u_char *)& (*cp) <= snapend - (1))) | |||
185 | return(NULL((void *)0)); | |||
186 | cp = bp + (((i << 8) | *cp) & 0x3fff); | |||
187 | if ((l = labellen(cp)) == (u_int)-1) | |||
188 | return(NULL((void *)0)); | |||
189 | if (!TTEST2(*cp, 1)(snapend - (1) <= snapend && (const u_char *)& (*cp) <= snapend - (1))) | |||
190 | return(NULL((void *)0)); | |||
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((void *)0)); | |||
203 | } | |||
204 | continue; | |||
205 | } | |||
206 | if ((i & INDIR_MASK0xc0) == EDNS0_MASK0x40) { | |||
207 | elt = (i & ~INDIR_MASK0xc0); | |||
208 | switch(elt) { | |||
209 | case EDNS0_ELT_BITLABEL0x01: | |||
210 | if (blabel_print(cp) == NULL((void *)0)) | |||
211 | return (NULL((void *)0)); | |||
212 | break; | |||
213 | default: | |||
214 | /* unknown ELT */ | |||
215 | printf("<ELT %d>", elt); | |||
216 | return(NULL((void *)0)); | |||
217 | } | |||
218 | } else { | |||
219 | if (fn_printn(cp, l, snapend)) | |||
220 | return(NULL((void *)0)); | |||
221 | } | |||
222 | ||||
223 | cp += l; | |||
224 | chars_processed += l; | |||
225 | putchar('.')(!__isthreaded ? __sputc('.', (&__sF[1])) : (putc)('.', ( &__sF[1]))); | |||
226 | if ((l = labellen(cp)) == (u_int)-1) | |||
227 | return(NULL((void *)0)); | |||
228 | if (!TTEST2(*cp, 1)(snapend - (1) <= snapend && (const u_char *)& (*cp) <= snapend - (1))) | |||
229 | return(NULL((void *)0)); | |||
230 | i = *cp++; | |||
231 | chars_processed++; | |||
232 | if (!compress
| |||
233 | rp += l + 1; | |||
234 | } | |||
235 | else | |||
236 | putchar('.')(!__isthreaded ? __sputc('.', (&__sF[1])) : (putc)('.', ( &__sF[1]))); | |||
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)(snapend - (1) <= snapend && (const u_char *)& (*cp) <= snapend - (1))) | |||
247 | return (NULL((void *)0)); | |||
248 | i = *cp++; | |||
249 | if (fn_printn(cp, i, snapend)) | |||
250 | return (NULL((void *)0)); | |||
251 | return (cp + i); | |||
252 | } | |||
253 | ||||
254 | /* https://www.iana.org/assignments/dns-parameters */ | |||
255 | struct tok ns_type2str[] = { | |||
256 | { T_A1, "A" }, /* RFC 1035 */ | |||
257 | { T_NS2, "NS" }, /* RFC 1035 */ | |||
258 | { T_MD3, "MD" }, /* RFC 1035 */ | |||
259 | { T_MF4, "MF" }, /* RFC 1035 */ | |||
260 | { T_CNAME5, "CNAME" }, /* RFC 1035 */ | |||
261 | { T_SOA6, "SOA" }, /* RFC 1035 */ | |||
262 | { T_MB7, "MB" }, /* RFC 1035 */ | |||
263 | { T_MG8, "MG" }, /* RFC 1035 */ | |||
264 | { T_MR9, "MR" }, /* RFC 1035 */ | |||
265 | { T_NULL10, "NULL" }, /* RFC 1035 */ | |||
266 | { T_WKS11, "WKS" }, /* RFC 1035 */ | |||
267 | { T_PTR12, "PTR" }, /* RFC 1035 */ | |||
268 | { T_HINFO13, "HINFO" }, /* RFC 1035 */ | |||
269 | { T_MINFO14, "MINFO" }, /* RFC 1035 */ | |||
270 | { T_MX15, "MX" }, /* RFC 1035 */ | |||
271 | { T_TXT16, "TXT" }, /* RFC 1035 */ | |||
272 | { T_RP17, "RP" }, /* RFC 1183 */ | |||
273 | { T_AFSDB18, "AFSDB" }, /* RFC 1183 */ | |||
274 | { T_X2519, "X25" }, /* RFC 1183 */ | |||
275 | { T_ISDN20, "ISDN" }, /* RFC 1183 */ | |||
276 | { T_RT21, "RT" }, /* RFC 1183 */ | |||
277 | { T_NSAP22, "NSAP" }, /* RFC 1706 */ | |||
278 | { T_NSAP_PTR23, "NSAP_PTR" }, | |||
279 | { T_SIG24, "SIG" }, /* RFC 2535 */ | |||
280 | { T_KEY25, "KEY" }, /* RFC 2535 */ | |||
281 | { T_PX26, "PX" }, /* RFC 2163 */ | |||
282 | { T_GPOS27, "GPOS" }, /* RFC 1712 */ | |||
283 | { T_AAAA28, "AAAA" }, /* RFC 1886 */ | |||
284 | { T_LOC29, "LOC" }, /* RFC 1876 */ | |||
285 | { T_NXT30, "NXT" }, /* RFC 2535 */ | |||
286 | { T_EID31, "EID" }, /* Nimrod */ | |||
287 | { T_NIMLOC32, "NIMLOC" }, /* Nimrod */ | |||
288 | { T_SRV33, "SRV" }, /* RFC 2782 */ | |||
289 | { T_ATMA34, "ATMA" }, /* ATM Forum */ | |||
290 | { T_NAPTR35, "NAPTR" }, /* RFC 2168, RFC 2915 */ | |||
291 | { T_KX36, "KX" }, /* RFC 2230 */ | |||
292 | { T_CERT37, "CERT" }, /* RFC 2538 */ | |||
293 | { T_A638, "A6" }, /* RFC 2874 */ | |||
294 | { T_DNAME39, "DNAME" }, /* RFC 2672 */ | |||
295 | { T_SINK40, "SINK" }, | |||
296 | { T_OPT41, "OPT" }, /* RFC 2671 */ | |||
297 | { T_APL42, "APL" }, /* RFC 3123 */ | |||
298 | { T_DS43, "DS" }, /* RFC 4034 */ | |||
299 | { T_SSHFP44, "SSHFP" }, /* RFC 4255 */ | |||
300 | { T_IPSECKEY45, "IPSECKEY" }, /* RFC 4025 */ | |||
301 | { T_RRSIG46, "RRSIG" }, /* RFC 4034 */ | |||
302 | { T_NSEC47, "NSEC" }, /* RFC 4034 */ | |||
303 | { T_DNSKEY48, "DNSKEY" }, /* RFC 4034 */ | |||
304 | { T_SPF99, "SPF" }, /* RFC-schlitt-spf-classic-02.txt */ | |||
305 | { T_UINFO100, "UINFO" }, | |||
306 | { T_UID101, "UID" }, | |||
307 | { T_GID102, "GID" }, | |||
308 | { T_UNSPEC103, "UNSPEC" }, | |||
309 | { T_UNSPECA104, "UNSPECA" }, | |||
310 | { T_TKEY249, "TKEY" }, /* RFC 2930 */ | |||
311 | { T_TSIG250, "TSIG" }, /* RFC 2845 */ | |||
312 | { T_IXFR251, "IXFR" }, /* RFC 1995 */ | |||
313 | { T_AXFR252, "AXFR" }, /* RFC 1035 */ | |||
314 | { T_MAILB253, "MAILB" }, /* RFC 1035 */ | |||
315 | { T_MAILA254, "MAILA" }, /* RFC 1035 */ | |||
316 | { T_ANY255, "ANY" }, | |||
317 | { 0, NULL((void *)0) } | |||
318 | }; | |||
319 | ||||
320 | struct tok ns_class2str[] = { | |||
321 | { C_IN1, "IN" }, /* Not used */ | |||
322 | { C_CHAOS3, "CHAOS" }, | |||
323 | { C_HS4, "HS" }, | |||
324 | { C_ANY255, "ANY" }, | |||
325 | { 0, NULL((void *)0) } | |||
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
(*cp) <= snapend - (4))) | |||
338 | return(NULL((void *)0)); | |||
339 | ||||
340 | /* print the qtype */ | |||
341 | i = EXTRACT_16BITS(cp)((u_int16_t)*((const u_int8_t *)(cp) + 0) << 8 | (u_int16_t )*((const u_int8_t *)(cp) + 1)); | |||
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)((u_int16_t)*((const u_int8_t *)(cp) + 0) << 8 | (u_int16_t )*((const u_int8_t *)(cp) + 1)); | |||
346 | cp += 2; | |||
347 | if (is_mdns) | |||
348 | class = (i & ~C_QU0x8000); | |||
349 | else | |||
350 | class = i; | |||
351 | if (class != C_IN1) | |||
352 | printf(" %s", tok2str(ns_class2str, "(Class %d)", class)); | |||
353 | if (is_mdns
| |||
354 | printf(" (QU)"); | |||
355 | ||||
356 | printf("? "); | |||
357 | cp = ns_nprint(np, bp); | |||
358 | return(cp ? cp + 4 : NULL((void *)0)); | |||
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(' ')(!__isthreaded ? __sputc(' ', (&__sF[1])) : (putc)(' ', ( &__sF[1]))); | |||
371 | if ((cp = ns_nprint(cp, bp)) == NULL((void *)0)) | |||
372 | return NULL((void *)0); | |||
373 | } else | |||
374 | cp = ns_nskip(cp); | |||
375 | ||||
376 | if (cp == NULL((void *)0) || !TTEST2(*cp, 10)(snapend - (10) <= snapend && (const u_char *)& (*cp) <= snapend - (10))) | |||
377 | return (snapend); | |||
378 | ||||
379 | /* print the type/qtype */ | |||
380 | typ = EXTRACT_16BITS(cp)((u_int16_t)*((const u_int8_t *)(cp) + 0) << 8 | (u_int16_t )*((const u_int8_t *)(cp) + 1)); | |||
381 | cp += 2; | |||
382 | /* print the class (if it's not IN and the type isn't OPT) */ | |||
383 | i = EXTRACT_16BITS(cp)((u_int16_t)*((const u_int8_t *)(cp) + 0) << 8 | (u_int16_t )*((const u_int8_t *)(cp) + 1)); | |||
384 | cp += 2; | |||
385 | if (is_mdns) | |||
386 | class = (i & ~C_CACHE_FLUSH0x8000); | |||
387 | else | |||
388 | class = i; | |||
389 | if (class != C_IN1 && typ != T_OPT41) | |||
390 | printf(" %s", tok2str(ns_class2str, "(Class %d)", class)); | |||
391 | if (is_mdns) { | |||
392 | if (i & C_CACHE_FLUSH0x8000) | |||
393 | printf(" (Cache flush)"); | |||
394 | } | |||
395 | ||||
396 | if (typ == T_OPT41) { | |||
397 | /* get opt flags */ | |||
398 | cp += 2; | |||
399 | opt_flags = EXTRACT_16BITS(cp)((u_int16_t)*((const u_int8_t *)(cp) + 0) << 8 | (u_int16_t )*((const u_int8_t *)(cp) + 1)); | |||
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)((u_int32_t)*((const u_int8_t *)(cp) + 0) << 24 | (u_int32_t )*((const u_int8_t *)(cp) + 1) << 16 | (u_int32_t)*((const u_int8_t *)(cp) + 2) << 8 | (u_int32_t)*((const u_int8_t *)(cp) + 3))); | |||
406 | printf("]"); | |||
407 | cp += 4; | |||
408 | } else { | |||
409 | /* ignore ttl */ | |||
410 | cp += 4; | |||
411 | } | |||
412 | ||||
413 | len = EXTRACT_16BITS(cp)((u_int16_t)*((const u_int8_t *)(cp) + 0) << 8 | (u_int16_t )*((const u_int8_t *)(cp) + 1)); | |||
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((void *)0)); | |||
421 | ||||
422 | switch (typ) { | |||
423 | case T_A1: | |||
424 | if (!TTEST2(*cp, sizeof(struct in_addr))(snapend - (sizeof(struct in_addr)) <= snapend && ( const u_char *)&(*cp) <= snapend - (sizeof(struct in_addr )))) | |||
425 | return(NULL((void *)0)); | |||
426 | printf(" %s", ipaddr_string(cp)getname((const u_char *)(cp))); | |||
427 | break; | |||
428 | ||||
429 | case T_NS2: | |||
430 | case T_CNAME5: | |||
431 | case T_PTR12: | |||
432 | #ifdef T_DNAME39 | |||
433 | case T_DNAME39: | |||
434 | #endif | |||
435 | putchar(' ')(!__isthreaded ? __sputc(' ', (&__sF[1])) : (putc)(' ', ( &__sF[1]))); | |||
436 | if (ns_nprint(cp, bp) == NULL((void *)0)) | |||
437 | return(NULL((void *)0)); | |||
438 | break; | |||
439 | ||||
440 | case T_SOA6: | |||
441 | if (!vflag) | |||
442 | break; | |||
443 | putchar(' ')(!__isthreaded ? __sputc(' ', (&__sF[1])) : (putc)(' ', ( &__sF[1]))); | |||
444 | if ((cp = ns_nprint(cp, bp)) == NULL((void *)0)) | |||
445 | return(NULL((void *)0)); | |||
446 | putchar(' ')(!__isthreaded ? __sputc(' ', (&__sF[1])) : (putc)(' ', ( &__sF[1]))); | |||
447 | if ((cp = ns_nprint(cp, bp)) == NULL((void *)0)) | |||
448 | return(NULL((void *)0)); | |||
449 | if (!TTEST2(*cp, 5 * 4)(snapend - (5 * 4) <= snapend && (const u_char *)& (*cp) <= snapend - (5 * 4))) | |||
450 | return(NULL((void *)0)); | |||
451 | printf(" %u", EXTRACT_32BITS(cp)((u_int32_t)*((const u_int8_t *)(cp) + 0) << 24 | (u_int32_t )*((const u_int8_t *)(cp) + 1) << 16 | (u_int32_t)*((const u_int8_t *)(cp) + 2) << 8 | (u_int32_t)*((const u_int8_t *)(cp) + 3))); | |||
452 | cp += 4; | |||
453 | printf(" %u", EXTRACT_32BITS(cp)((u_int32_t)*((const u_int8_t *)(cp) + 0) << 24 | (u_int32_t )*((const u_int8_t *)(cp) + 1) << 16 | (u_int32_t)*((const u_int8_t *)(cp) + 2) << 8 | (u_int32_t)*((const u_int8_t *)(cp) + 3))); | |||
454 | cp += 4; | |||
455 | printf(" %u", EXTRACT_32BITS(cp)((u_int32_t)*((const u_int8_t *)(cp) + 0) << 24 | (u_int32_t )*((const u_int8_t *)(cp) + 1) << 16 | (u_int32_t)*((const u_int8_t *)(cp) + 2) << 8 | (u_int32_t)*((const u_int8_t *)(cp) + 3))); | |||
456 | cp += 4; | |||
457 | printf(" %u", EXTRACT_32BITS(cp)((u_int32_t)*((const u_int8_t *)(cp) + 0) << 24 | (u_int32_t )*((const u_int8_t *)(cp) + 1) << 16 | (u_int32_t)*((const u_int8_t *)(cp) + 2) << 8 | (u_int32_t)*((const u_int8_t *)(cp) + 3))); | |||
458 | cp += 4; | |||
459 | printf(" %u", EXTRACT_32BITS(cp)((u_int32_t)*((const u_int8_t *)(cp) + 0) << 24 | (u_int32_t )*((const u_int8_t *)(cp) + 1) << 16 | (u_int32_t)*((const u_int8_t *)(cp) + 2) << 8 | (u_int32_t)*((const u_int8_t *)(cp) + 3))); | |||
460 | cp += 4; | |||
461 | break; | |||
462 | case T_MX15: | |||
463 | putchar(' ')(!__isthreaded ? __sputc(' ', (&__sF[1])) : (putc)(' ', ( &__sF[1]))); | |||
464 | if (!TTEST2(*cp, 2)(snapend - (2) <= snapend && (const u_char *)& (*cp) <= snapend - (2))) | |||
465 | return(NULL((void *)0)); | |||
466 | if (ns_nprint(cp + 2, bp) == NULL((void *)0)) | |||
467 | return(NULL((void *)0)); | |||
468 | printf(" %d", EXTRACT_16BITS(cp)((u_int16_t)*((const u_int8_t *)(cp) + 0) << 8 | (u_int16_t )*((const u_int8_t *)(cp) + 1))); | |||
469 | break; | |||
470 | ||||
471 | case T_TXT16: | |||
472 | while (cp < rp) { | |||
473 | printf(" \""); | |||
474 | cp = ns_cprint(cp); | |||
475 | if (cp == NULL((void *)0)) | |||
476 | return(NULL((void *)0)); | |||
477 | putchar('"')(!__isthreaded ? __sputc('"', (&__sF[1])) : (putc)('"', ( &__sF[1]))); | |||
478 | } | |||
479 | break; | |||
480 | ||||
481 | case T_SRV33: | |||
482 | putchar(' ')(!__isthreaded ? __sputc(' ', (&__sF[1])) : (putc)(' ', ( &__sF[1]))); | |||
483 | if (!TTEST2(*cp, 6)(snapend - (6) <= snapend && (const u_char *)& (*cp) <= snapend - (6))) | |||
484 | return(NULL((void *)0)); | |||
485 | if (ns_nprint(cp + 6, bp) == NULL((void *)0)) | |||
486 | return(NULL((void *)0)); | |||
487 | printf(":%d %d %d", EXTRACT_16BITS(cp + 4)((u_int16_t)*((const u_int8_t *)(cp + 4) + 0) << 8 | (u_int16_t )*((const u_int8_t *)(cp + 4) + 1)), | |||
488 | EXTRACT_16BITS(cp)((u_int16_t)*((const u_int8_t *)(cp) + 0) << 8 | (u_int16_t )*((const u_int8_t *)(cp) + 1)), EXTRACT_16BITS(cp + 2)((u_int16_t)*((const u_int8_t *)(cp + 2) + 0) << 8 | (u_int16_t )*((const u_int8_t *)(cp + 2) + 1))); | |||
489 | break; | |||
490 | ||||
491 | case T_AAAA28: | |||
492 | if (!TTEST2(*cp, sizeof(struct in6_addr))(snapend - (sizeof(struct in6_addr)) <= snapend && (const u_char *)&(*cp) <= snapend - (sizeof(struct in6_addr )))) | |||
493 | return(NULL((void *)0)); | |||
494 | printf(" %s", ip6addr_string(cp)getname6((const u_char *)(cp))); | |||
495 | break; | |||
496 | ||||
497 | case T_A638: | |||
498 | { | |||
499 | struct in6_addr a; | |||
500 | int pbit, pbyte; | |||
501 | ||||
502 | if (!TTEST2(*cp, 1)(snapend - (1) <= snapend && (const u_char *)& (*cp) <= snapend - (1))) | |||
503 | return(NULL((void *)0)); | |||
504 | pbit = *cp; | |||
505 | pbyte = (pbit & ~7) / 8; | |||
506 | if (pbit > 128) { | |||
507 | printf(" %u(bad plen)", pbit); | |||
508 | break; | |||
509 | } else if (pbit < 128) { | |||
510 | if (!TTEST2(*(cp + 1), sizeof(a) - pbyte)(snapend - (sizeof(a) - pbyte) <= snapend && (const u_char *)&(*(cp + 1)) <= snapend - (sizeof(a) - pbyte ))) | |||
511 | return(NULL((void *)0)); | |||
512 | memset(&a, 0, sizeof(a)); | |||
513 | memcpy(&a.s6_addr__u6_addr.__u6_addr8[pbyte], cp + 1, sizeof(a) - pbyte); | |||
514 | printf(" %u %s", pbit, ip6addr_string(&a)getname6((const u_char *)(&a))); | |||
515 | } | |||
516 | if (pbit > 0) { | |||
517 | putchar(' ')(!__isthreaded ? __sputc(' ', (&__sF[1])) : (putc)(' ', ( &__sF[1]))); | |||
518 | if (ns_nprint(cp + 1 + sizeof(a) - pbyte, bp) == NULL((void *)0)) | |||
519 | return(NULL((void *)0)); | |||
520 | } | |||
521 | break; | |||
522 | } | |||
523 | ||||
524 | case T_OPT41: | |||
525 | printf(" UDPsize=%u", class); | |||
526 | if (opt_flags & 0x8000) | |||
527 | printf(" DO"); | |||
528 | break; | |||
529 | ||||
530 | case T_UNSPECA104: /* One long string */ | |||
531 | if (!TTEST2(*cp, len)(snapend - (len) <= snapend && (const u_char *)& (*cp) <= snapend - (len))) | |||
532 | return(NULL((void *)0)); | |||
533 | if (fn_printn(cp, len, snapend)) | |||
534 | return(NULL((void *)0)); | |||
535 | break; | |||
536 | ||||
537 | case T_TSIG250: | |||
538 | { | |||
539 | if (cp + len > snapend) | |||
540 | return(NULL((void *)0)); | |||
541 | if (!vflag) | |||
542 | break; | |||
543 | putchar(' ')(!__isthreaded ? __sputc(' ', (&__sF[1])) : (putc)(' ', ( &__sF[1]))); | |||
544 | if ((cp = ns_nprint(cp, bp)) == NULL((void *)0)) | |||
545 | return(NULL((void *)0)); | |||
546 | cp += 6; | |||
547 | if (!TTEST2(*cp, 2)(snapend - (2) <= snapend && (const u_char *)& (*cp) <= snapend - (2))) | |||
548 | return(NULL((void *)0)); | |||
549 | printf(" fudge=%u", EXTRACT_16BITS(cp)((u_int16_t)*((const u_int8_t *)(cp) + 0) << 8 | (u_int16_t )*((const u_int8_t *)(cp) + 1))); | |||
550 | cp += 2; | |||
551 | if (!TTEST2(*cp, 2)(snapend - (2) <= snapend && (const u_char *)& (*cp) <= snapend - (2))) | |||
552 | return(NULL((void *)0)); | |||
553 | printf(" maclen=%u", EXTRACT_16BITS(cp)((u_int16_t)*((const u_int8_t *)(cp) + 0) << 8 | (u_int16_t )*((const u_int8_t *)(cp) + 1))); | |||
554 | cp += 2 + EXTRACT_16BITS(cp)((u_int16_t)*((const u_int8_t *)(cp) + 0) << 8 | (u_int16_t )*((const u_int8_t *)(cp) + 1)); | |||
555 | if (!TTEST2(*cp, 2)(snapend - (2) <= snapend && (const u_char *)& (*cp) <= snapend - (2))) | |||
556 | return(NULL((void *)0)); | |||
557 | printf(" origid=%u", EXTRACT_16BITS(cp)((u_int16_t)*((const u_int8_t *)(cp) + 0) << 8 | (u_int16_t )*((const u_int8_t *)(cp) + 1))); | |||
558 | cp += 2; | |||
559 | if (!TTEST2(*cp, 2)(snapend - (2) <= snapend && (const u_char *)& (*cp) <= snapend - (2))) | |||
560 | return(NULL((void *)0)); | |||
561 | printf(" error=%u", EXTRACT_16BITS(cp)((u_int16_t)*((const u_int8_t *)(cp) + 0) << 8 | (u_int16_t )*((const u_int8_t *)(cp) + 1))); | |||
562 | cp += 2; | |||
563 | if (!TTEST2(*cp, 2)(snapend - (2) <= snapend && (const u_char *)& (*cp) <= snapend - (2))) | |||
564 | return(NULL((void *)0)); | |||
565 | printf(" otherlen=%u", EXTRACT_16BITS(cp)((u_int16_t)*((const u_int8_t *)(cp) + 0) << 8 | (u_int16_t )*((const u_int8_t *)(cp) + 1))); | |||
566 | cp += 2; | |||
567 | } | |||
568 | } | |||
569 | return (rp); /* XXX This isn't always right */ | |||
570 | } | |||
571 | ||||
572 | void | |||
573 | ns_print(const u_char *bp, u_int length, int is_mdns) | |||
574 | { | |||
575 | const HEADER *np; | |||
576 | int qdcount, ancount, nscount, arcount; | |||
577 | const u_char *cp; | |||
578 | u_int16_t b2; | |||
579 | ||||
580 | np = (const HEADER *)bp; | |||
581 | TCHECK(*np)if (!(snapend - (sizeof(*np)) <= snapend && (const u_char *)&(*np) <= snapend - (sizeof(*np)))) goto trunc; | |||
| ||||
582 | /* get the byte-order right */ | |||
583 | qdcount = EXTRACT_16BITS(&np->qdcount)((u_int16_t)*((const u_int8_t *)(&np->qdcount) + 0) << 8 | (u_int16_t)*((const u_int8_t *)(&np->qdcount) + 1 )); | |||
584 | ancount = EXTRACT_16BITS(&np->ancount)((u_int16_t)*((const u_int8_t *)(&np->ancount) + 0) << 8 | (u_int16_t)*((const u_int8_t *)(&np->ancount) + 1 )); | |||
585 | nscount = EXTRACT_16BITS(&np->nscount)((u_int16_t)*((const u_int8_t *)(&np->nscount) + 0) << 8 | (u_int16_t)*((const u_int8_t *)(&np->nscount) + 1 )); | |||
586 | arcount = EXTRACT_16BITS(&np->arcount)((u_int16_t)*((const u_int8_t *)(&np->arcount) + 0) << 8 | (u_int16_t)*((const u_int8_t *)(&np->arcount) + 1 )); | |||
587 | ||||
588 | if (DNS_QR(np)((np)->flags1 & 0x80)) { | |||
589 | /* this is a response */ | |||
590 | printf("%d%s%s%s%s%s%s", | |||
591 | EXTRACT_16BITS(&np->id)((u_int16_t)*((const u_int8_t *)(&np->id) + 0) << 8 | (u_int16_t)*((const u_int8_t *)(&np->id) + 1)), | |||
592 | ns_ops[DNS_OPCODE(np)((((np)->flags1) >> 3) & 0xF)], | |||
593 | ns_resp[DNS_RCODE(np)((np)->flags2 & 0xF)], | |||
594 | DNS_AA(np)((np)->flags1 & 0x04)? "*" : "", | |||
595 | DNS_RA(np)((np)->flags2 & 0x80)? "" : "-", | |||
596 | DNS_TC(np)((np)->flags1 & 0x02)? "|" : "", | |||
597 | DNS_AD(np)((np)->flags2 & 0x20)? "$" : ""); | |||
598 | ||||
599 | if (qdcount != 1) | |||
600 | printf(" [%dq]", qdcount); | |||
601 | /* Print QUESTION section on -vv */ | |||
602 | cp = (const u_char *)(np + 1); | |||
603 | while (qdcount--) { | |||
604 | if (qdcount < EXTRACT_16BITS(&np->qdcount)((u_int16_t)*((const u_int8_t *)(&np->qdcount) + 0) << 8 | (u_int16_t)*((const u_int8_t *)(&np->qdcount) + 1 )) - 1) | |||
605 | putchar(',')(!__isthreaded ? __sputc(',', (&__sF[1])) : (putc)(',', ( &__sF[1]))); | |||
606 | if (vflag > 1) { | |||
607 | printf(" q:"); | |||
608 | if ((cp = ns_qprint(cp, bp, is_mdns)) == NULL((void *)0)) | |||
609 | goto trunc; | |||
610 | } else { | |||
611 | if ((cp = ns_nskip(cp)) == NULL((void *)0)) | |||
612 | goto trunc; | |||
613 | cp += 4; /* skip QTYPE and QCLASS */ | |||
614 | } | |||
615 | } | |||
616 | printf(" %d/%d/%d", ancount, nscount, arcount); | |||
617 | if (ancount--) { | |||
618 | if ((cp = ns_rprint(cp, bp, is_mdns)) == NULL((void *)0)) | |||
619 | goto trunc; | |||
620 | while (cp < snapend && ancount--) { | |||
621 | putchar(',')(!__isthreaded ? __sputc(',', (&__sF[1])) : (putc)(',', ( &__sF[1]))); | |||
622 | if ((cp = ns_rprint(cp, bp, is_mdns)) == NULL((void *)0)) | |||
623 | goto trunc; | |||
624 | } | |||
625 | } | |||
626 | if (ancount > 0) | |||
627 | goto trunc; | |||
628 | /* Print NS and AR sections on -vv */ | |||
629 | if (vflag > 1) { | |||
630 | if (cp < snapend && nscount--) { | |||
631 | printf(" ns:"); | |||
632 | if ((cp = ns_rprint(cp, bp, is_mdns)) == NULL((void *)0)) | |||
633 | goto trunc; | |||
634 | while (cp < snapend && nscount--) { | |||
635 | putchar(',')(!__isthreaded ? __sputc(',', (&__sF[1])) : (putc)(',', ( &__sF[1]))); | |||
636 | if ((cp = ns_rprint(cp, bp, is_mdns)) == NULL((void *)0)) | |||
637 | goto trunc; | |||
638 | } | |||
639 | } | |||
640 | if (nscount > 0) | |||
641 | goto trunc; | |||
642 | if (cp < snapend && arcount--) { | |||
643 | printf(" ar:"); | |||
644 | if ((cp = ns_rprint(cp, bp, is_mdns)) == NULL((void *)0)) | |||
645 | goto trunc; | |||
646 | while (cp < snapend && arcount--) { | |||
647 | putchar(',')(!__isthreaded ? __sputc(',', (&__sF[1])) : (putc)(',', ( &__sF[1]))); | |||
648 | if ((cp = ns_rprint(cp, bp, is_mdns)) == NULL((void *)0)) | |||
649 | goto trunc; | |||
650 | } | |||
651 | } | |||
652 | if (arcount > 0) | |||
653 | goto trunc; | |||
654 | } | |||
655 | } else { | |||
656 | /* this is a request */ | |||
657 | printf("%d%s%s%s", EXTRACT_16BITS(&np->id)((u_int16_t)*((const u_int8_t *)(&np->id) + 0) << 8 | (u_int16_t)*((const u_int8_t *)(&np->id) + 1)), ns_ops[DNS_OPCODE(np)((((np)->flags1) >> 3) & 0xF)], | |||
658 | DNS_RD(np)((np)->flags1 & 0x01) ? "+" : "", | |||
659 | DNS_CD(np)((np)->flags2 & 0x10) ? "%" : ""); | |||
660 | ||||
661 | /* any weirdness? AA is expected in NOTIFY. */ | |||
662 | b2 = EXTRACT_16BITS(((u_short *)np)+1)((u_int16_t)*((const u_int8_t *)(((u_short *)np)+1) + 0) << 8 | (u_int16_t)*((const u_int8_t *)(((u_short *)np)+1) + 1)); | |||
663 | if ((b2 & 0x6cf) != | |||
664 | (DNS_OPCODE(np)((((np)->flags1) >> 3) & 0xF) == NS_NOTIFY_OP0x4 ? htons(0x400)(__uint16_t)(__builtin_constant_p(0x400) ? (__uint16_t)(((__uint16_t )(0x400) & 0xffU) << 8 | ((__uint16_t)(0x400) & 0xff00U) >> 8) : __swap16md(0x400)) : 0)) | |||
665 | printf(" [b2&3=0x%x]", b2); | |||
666 | ||||
667 | if (DNS_OPCODE(np)((((np)->flags1) >> 3) & 0xF) == IQUERY0x1) { | |||
668 | if (qdcount) | |||
669 | printf(" [%dq]", qdcount); | |||
670 | if (ancount != 1) | |||
671 | printf(" [%da]", ancount); | |||
672 | } | |||
673 | else { | |||
674 | if (ancount) | |||
675 | printf(" [%da]", ancount); | |||
676 | if (qdcount != 1) | |||
677 | printf(" [%dq]", qdcount); | |||
678 | } | |||
679 | if (nscount) | |||
680 | printf(" [%dn]", nscount); | |||
681 | if (arcount) | |||
682 | printf(" [%dau]", arcount); | |||
683 | ||||
684 | cp = (const u_char *)(np + 1); | |||
685 | if (qdcount--) { | |||
686 | cp = ns_qprint(cp, (const u_char *)np, is_mdns); | |||
687 | if (!cp) | |||
688 | goto trunc; | |||
689 | while (cp < snapend && qdcount--) { | |||
690 | cp = ns_qprint((const u_char *)cp, | |||
691 | (const u_char *)np, | |||
692 | is_mdns); | |||
693 | if (!cp) | |||
694 | goto trunc; | |||
695 | } | |||
696 | } | |||
697 | if (qdcount > 0) | |||
698 | goto trunc; | |||
699 | ||||
700 | /* Print remaining sections on -vv */ | |||
701 | if (vflag > 1) { | |||
702 | if (ancount--) { | |||
703 | if ((cp = ns_rprint(cp, bp, is_mdns)) == NULL((void *)0)) | |||
704 | goto trunc; | |||
705 | while (cp < snapend && ancount--) { | |||
706 | putchar(',')(!__isthreaded ? __sputc(',', (&__sF[1])) : (putc)(',', ( &__sF[1]))); | |||
707 | if ((cp = ns_rprint(cp, bp, is_mdns)) == NULL((void *)0)) | |||
708 | goto trunc; | |||
709 | } | |||
710 | } | |||
711 | if (ancount > 0) | |||
712 | goto trunc; | |||
713 | if (cp < snapend && nscount--) { | |||
714 | printf(" ns:"); | |||
715 | if ((cp = ns_rprint(cp, bp, is_mdns)) == NULL((void *)0)) | |||
716 | goto trunc; | |||
717 | while (nscount-- && cp < snapend) { | |||
718 | putchar(',')(!__isthreaded ? __sputc(',', (&__sF[1])) : (putc)(',', ( &__sF[1]))); | |||
719 | if ((cp = ns_rprint(cp, bp, is_mdns)) == NULL((void *)0)) | |||
720 | goto trunc; | |||
721 | } | |||
722 | } | |||
723 | if (nscount > 0) | |||
724 | goto trunc; | |||
725 | if (cp < snapend && arcount--) { | |||
726 | printf(" ar:"); | |||
727 | if ((cp = ns_rprint(cp, bp, is_mdns)) == NULL((void *)0)) | |||
728 | goto trunc; | |||
729 | while (cp < snapend && arcount--) { | |||
730 | putchar(',')(!__isthreaded ? __sputc(',', (&__sF[1])) : (putc)(',', ( &__sF[1]))); | |||
731 | if ((cp = ns_rprint(cp, bp, is_mdns)) == NULL((void *)0)) | |||
732 | goto trunc; | |||
733 | } | |||
734 | } | |||
735 | if (arcount > 0) | |||
736 | goto trunc; | |||
737 | } | |||
738 | } | |||
739 | printf("(%d)", length); | |||
740 | return; | |||
741 | ||||
742 | trunc: | |||
743 | printf("[|domain]"); | |||
744 | return; | |||
745 | } |