File: | src/usr.sbin/tcpdump/print-domain.c |
Warning: | line 346, column 2 Value stored to 'cp' is never read |
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 > 4) { |
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 != 0) |
178 | while (i && cp < snapend) { |
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 == NULL((void *)0) || !TTEST2(*cp, 4)(snapend - (4) <= snapend && (const u_char *)& (*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; |
Value stored to 'cp' is never read | |
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 && (i & C_QU0x8000)) |
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 | } |