1*05b00f60SXin Li /*
2*05b00f60SXin Li * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
3*05b00f60SXin Li * The Regents of the University of California. All rights reserved.
4*05b00f60SXin Li *
5*05b00f60SXin Li * Redistribution and use in source and binary forms, with or without
6*05b00f60SXin Li * modification, are permitted provided that: (1) source code distributions
7*05b00f60SXin Li * retain the above copyright notice and this paragraph in its entirety, (2)
8*05b00f60SXin Li * distributions including binary code include the above copyright notice and
9*05b00f60SXin Li * this paragraph in its entirety in the documentation or other materials
10*05b00f60SXin Li * provided with the distribution, and (3) all advertising materials mentioning
11*05b00f60SXin Li * features or use of this software display the following acknowledgement:
12*05b00f60SXin Li * ``This product includes software developed by the University of California,
13*05b00f60SXin Li * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
14*05b00f60SXin Li * the University nor the names of its contributors may be used to endorse
15*05b00f60SXin Li * or promote products derived from this software without specific prior
16*05b00f60SXin Li * written permission.
17*05b00f60SXin Li * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
18*05b00f60SXin Li * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
19*05b00f60SXin Li * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20*05b00f60SXin Li */
21*05b00f60SXin Li
22*05b00f60SXin Li /* \summary: Domain Name System (DNS) printer */
23*05b00f60SXin Li
24*05b00f60SXin Li #ifdef HAVE_CONFIG_H
25*05b00f60SXin Li #include <config.h>
26*05b00f60SXin Li #endif
27*05b00f60SXin Li
28*05b00f60SXin Li #include "netdissect-stdinc.h"
29*05b00f60SXin Li
30*05b00f60SXin Li #include <string.h>
31*05b00f60SXin Li
32*05b00f60SXin Li #include "netdissect.h"
33*05b00f60SXin Li #include "addrtoname.h"
34*05b00f60SXin Li #include "addrtostr.h"
35*05b00f60SXin Li #include "extract.h"
36*05b00f60SXin Li
37*05b00f60SXin Li #include "nameser.h"
38*05b00f60SXin Li
39*05b00f60SXin Li static const char *ns_ops[] = {
40*05b00f60SXin Li "", " inv_q", " stat", " op3", " notify", " update", " op6", " op7",
41*05b00f60SXin Li " op8", " updateA", " updateD", " updateDA",
42*05b00f60SXin Li " updateM", " updateMA", " zoneInit", " zoneRef",
43*05b00f60SXin Li };
44*05b00f60SXin Li
45*05b00f60SXin Li static const char *ns_resp[] = {
46*05b00f60SXin Li "", " FormErr", " ServFail", " NXDomain",
47*05b00f60SXin Li " NotImp", " Refused", " YXDomain", " YXRRSet",
48*05b00f60SXin Li " NXRRSet", " NotAuth", " NotZone", " Resp11",
49*05b00f60SXin Li " Resp12", " Resp13", " Resp14", " NoChange",
50*05b00f60SXin Li " BadVers", "Resp17", " Resp18", " Resp19",
51*05b00f60SXin Li " Resp20", "Resp21", " Resp22", " BadCookie",
52*05b00f60SXin Li };
53*05b00f60SXin Li
54*05b00f60SXin Li static const char *
ns_rcode(u_int rcode)55*05b00f60SXin Li ns_rcode(u_int rcode) {
56*05b00f60SXin Li static char buf[sizeof(" Resp4095")];
57*05b00f60SXin Li
58*05b00f60SXin Li if (rcode < sizeof(ns_resp)/sizeof(ns_resp[0])) {
59*05b00f60SXin Li return (ns_resp[rcode]);
60*05b00f60SXin Li }
61*05b00f60SXin Li snprintf(buf, sizeof(buf), " Resp%u", rcode & 0xfff);
62*05b00f60SXin Li return (buf);
63*05b00f60SXin Li }
64*05b00f60SXin Li
65*05b00f60SXin Li /* skip over a domain name */
66*05b00f60SXin Li static const u_char *
ns_nskip(netdissect_options * ndo,const u_char * cp)67*05b00f60SXin Li ns_nskip(netdissect_options *ndo,
68*05b00f60SXin Li const u_char *cp)
69*05b00f60SXin Li {
70*05b00f60SXin Li u_char i;
71*05b00f60SXin Li
72*05b00f60SXin Li if (!ND_TTEST_1(cp))
73*05b00f60SXin Li return (NULL);
74*05b00f60SXin Li i = GET_U_1(cp);
75*05b00f60SXin Li cp++;
76*05b00f60SXin Li while (i) {
77*05b00f60SXin Li switch (i & TYPE_MASK) {
78*05b00f60SXin Li
79*05b00f60SXin Li case TYPE_INDIR:
80*05b00f60SXin Li return (cp + 1);
81*05b00f60SXin Li
82*05b00f60SXin Li case TYPE_EDNS0: {
83*05b00f60SXin Li int bitlen, bytelen;
84*05b00f60SXin Li
85*05b00f60SXin Li if ((i & ~TYPE_MASK) != EDNS0_ELT_BITLABEL)
86*05b00f60SXin Li return(NULL); /* unknown ELT */
87*05b00f60SXin Li if (!ND_TTEST_1(cp))
88*05b00f60SXin Li return (NULL);
89*05b00f60SXin Li if ((bitlen = GET_U_1(cp)) == 0)
90*05b00f60SXin Li bitlen = 256;
91*05b00f60SXin Li cp++;
92*05b00f60SXin Li bytelen = (bitlen + 7) / 8;
93*05b00f60SXin Li cp += bytelen;
94*05b00f60SXin Li }
95*05b00f60SXin Li break;
96*05b00f60SXin Li
97*05b00f60SXin Li case TYPE_RESERVED:
98*05b00f60SXin Li return (NULL);
99*05b00f60SXin Li
100*05b00f60SXin Li case TYPE_LABEL:
101*05b00f60SXin Li cp += i;
102*05b00f60SXin Li break;
103*05b00f60SXin Li }
104*05b00f60SXin Li if (!ND_TTEST_1(cp))
105*05b00f60SXin Li return (NULL);
106*05b00f60SXin Li i = GET_U_1(cp);
107*05b00f60SXin Li cp++;
108*05b00f60SXin Li }
109*05b00f60SXin Li return (cp);
110*05b00f60SXin Li }
111*05b00f60SXin Li
112*05b00f60SXin Li static const u_char *
blabel_print(netdissect_options * ndo,const u_char * cp)113*05b00f60SXin Li blabel_print(netdissect_options *ndo,
114*05b00f60SXin Li const u_char *cp)
115*05b00f60SXin Li {
116*05b00f60SXin Li u_int bitlen, slen, b;
117*05b00f60SXin Li const u_char *bitp, *lim;
118*05b00f60SXin Li uint8_t tc;
119*05b00f60SXin Li
120*05b00f60SXin Li if (!ND_TTEST_1(cp))
121*05b00f60SXin Li return(NULL);
122*05b00f60SXin Li if ((bitlen = GET_U_1(cp)) == 0)
123*05b00f60SXin Li bitlen = 256;
124*05b00f60SXin Li slen = (bitlen + 3) / 4;
125*05b00f60SXin Li lim = cp + 1 + slen;
126*05b00f60SXin Li
127*05b00f60SXin Li /* print the bit string as a hex string */
128*05b00f60SXin Li ND_PRINT("\\[x");
129*05b00f60SXin Li for (bitp = cp + 1, b = bitlen; bitp < lim && b > 7; b -= 8, bitp++) {
130*05b00f60SXin Li ND_PRINT("%02x", GET_U_1(bitp));
131*05b00f60SXin Li }
132*05b00f60SXin Li if (b > 4) {
133*05b00f60SXin Li tc = GET_U_1(bitp);
134*05b00f60SXin Li bitp++;
135*05b00f60SXin Li ND_PRINT("%02x", tc & (0xff << (8 - b)));
136*05b00f60SXin Li } else if (b > 0) {
137*05b00f60SXin Li tc = GET_U_1(bitp);
138*05b00f60SXin Li bitp++;
139*05b00f60SXin Li ND_PRINT("%1x", ((tc >> 4) & 0x0f) & (0x0f << (4 - b)));
140*05b00f60SXin Li }
141*05b00f60SXin Li ND_PRINT("/%u]", bitlen);
142*05b00f60SXin Li return lim;
143*05b00f60SXin Li }
144*05b00f60SXin Li
145*05b00f60SXin Li static int
labellen(netdissect_options * ndo,const u_char * cp)146*05b00f60SXin Li labellen(netdissect_options *ndo,
147*05b00f60SXin Li const u_char *cp)
148*05b00f60SXin Li {
149*05b00f60SXin Li u_int i;
150*05b00f60SXin Li
151*05b00f60SXin Li if (!ND_TTEST_1(cp))
152*05b00f60SXin Li return(-1);
153*05b00f60SXin Li i = GET_U_1(cp);
154*05b00f60SXin Li switch (i & TYPE_MASK) {
155*05b00f60SXin Li
156*05b00f60SXin Li case TYPE_EDNS0: {
157*05b00f60SXin Li u_int bitlen, elt;
158*05b00f60SXin Li if ((elt = (i & ~TYPE_MASK)) != EDNS0_ELT_BITLABEL) {
159*05b00f60SXin Li ND_PRINT("<ELT %d>", elt);
160*05b00f60SXin Li return(-1);
161*05b00f60SXin Li }
162*05b00f60SXin Li if (!ND_TTEST_1(cp + 1))
163*05b00f60SXin Li return(-1);
164*05b00f60SXin Li if ((bitlen = GET_U_1(cp + 1)) == 0)
165*05b00f60SXin Li bitlen = 256;
166*05b00f60SXin Li return(((bitlen + 7) / 8) + 1);
167*05b00f60SXin Li }
168*05b00f60SXin Li
169*05b00f60SXin Li case TYPE_INDIR:
170*05b00f60SXin Li case TYPE_LABEL:
171*05b00f60SXin Li return(i);
172*05b00f60SXin Li
173*05b00f60SXin Li default:
174*05b00f60SXin Li /*
175*05b00f60SXin Li * TYPE_RESERVED, but we use default to suppress compiler
176*05b00f60SXin Li * warnings about falling out of the switch statement.
177*05b00f60SXin Li */
178*05b00f60SXin Li ND_PRINT("<BAD LABEL TYPE>");
179*05b00f60SXin Li return(-1);
180*05b00f60SXin Li }
181*05b00f60SXin Li }
182*05b00f60SXin Li
183*05b00f60SXin Li /* print a <domain-name> */
184*05b00f60SXin Li const u_char *
fqdn_print(netdissect_options * ndo,const u_char * cp,const u_char * bp)185*05b00f60SXin Li fqdn_print(netdissect_options *ndo,
186*05b00f60SXin Li const u_char *cp, const u_char *bp)
187*05b00f60SXin Li {
188*05b00f60SXin Li u_int i, l;
189*05b00f60SXin Li const u_char *rp = NULL;
190*05b00f60SXin Li int compress = 0;
191*05b00f60SXin Li u_int elt;
192*05b00f60SXin Li u_int offset, max_offset;
193*05b00f60SXin Li u_int name_chars = 0;
194*05b00f60SXin Li
195*05b00f60SXin Li if ((l = labellen(ndo, cp)) == (u_int)-1)
196*05b00f60SXin Li return(NULL);
197*05b00f60SXin Li if (!ND_TTEST_1(cp))
198*05b00f60SXin Li return(NULL);
199*05b00f60SXin Li max_offset = (u_int)(cp - bp);
200*05b00f60SXin Li i = GET_U_1(cp);
201*05b00f60SXin Li cp++;
202*05b00f60SXin Li if ((i & TYPE_MASK) != TYPE_INDIR) {
203*05b00f60SXin Li compress = 0;
204*05b00f60SXin Li rp = cp + l;
205*05b00f60SXin Li }
206*05b00f60SXin Li
207*05b00f60SXin Li if (i != 0) {
208*05b00f60SXin Li while (i && cp < ndo->ndo_snapend) {
209*05b00f60SXin Li switch (i & TYPE_MASK) {
210*05b00f60SXin Li
211*05b00f60SXin Li case TYPE_INDIR:
212*05b00f60SXin Li if (!compress) {
213*05b00f60SXin Li rp = cp + 1;
214*05b00f60SXin Li compress = 1;
215*05b00f60SXin Li }
216*05b00f60SXin Li if (!ND_TTEST_1(cp))
217*05b00f60SXin Li return(NULL);
218*05b00f60SXin Li offset = (((i << 8) | GET_U_1(cp)) & 0x3fff);
219*05b00f60SXin Li /*
220*05b00f60SXin Li * This must move backwards in the packet.
221*05b00f60SXin Li * No RFC explicitly says that, but BIND's
222*05b00f60SXin Li * name decompression code requires it,
223*05b00f60SXin Li * as a way of preventing infinite loops
224*05b00f60SXin Li * and other bad behavior, and it's probably
225*05b00f60SXin Li * what was intended (compress by pointing
226*05b00f60SXin Li * to domain name suffixes already seen in
227*05b00f60SXin Li * the packet).
228*05b00f60SXin Li */
229*05b00f60SXin Li if (offset >= max_offset) {
230*05b00f60SXin Li ND_PRINT("<BAD PTR>");
231*05b00f60SXin Li return(NULL);
232*05b00f60SXin Li }
233*05b00f60SXin Li max_offset = offset;
234*05b00f60SXin Li cp = bp + offset;
235*05b00f60SXin Li if (!ND_TTEST_1(cp))
236*05b00f60SXin Li return(NULL);
237*05b00f60SXin Li i = GET_U_1(cp);
238*05b00f60SXin Li if ((l = labellen(ndo, cp)) == (u_int)-1)
239*05b00f60SXin Li return(NULL);
240*05b00f60SXin Li cp++;
241*05b00f60SXin Li continue;
242*05b00f60SXin Li
243*05b00f60SXin Li case TYPE_EDNS0:
244*05b00f60SXin Li elt = (i & ~TYPE_MASK);
245*05b00f60SXin Li switch(elt) {
246*05b00f60SXin Li case EDNS0_ELT_BITLABEL:
247*05b00f60SXin Li if (blabel_print(ndo, cp) == NULL)
248*05b00f60SXin Li return (NULL);
249*05b00f60SXin Li break;
250*05b00f60SXin Li default:
251*05b00f60SXin Li /* unknown ELT */
252*05b00f60SXin Li ND_PRINT("<ELT %u>", elt);
253*05b00f60SXin Li return(NULL);
254*05b00f60SXin Li }
255*05b00f60SXin Li break;
256*05b00f60SXin Li
257*05b00f60SXin Li case TYPE_RESERVED:
258*05b00f60SXin Li ND_PRINT("<BAD LABEL TYPE>");
259*05b00f60SXin Li return(NULL);
260*05b00f60SXin Li
261*05b00f60SXin Li case TYPE_LABEL:
262*05b00f60SXin Li if (name_chars + l <= MAXCDNAME) {
263*05b00f60SXin Li if (nd_printn(ndo, cp, l, ndo->ndo_snapend))
264*05b00f60SXin Li return(NULL);
265*05b00f60SXin Li } else if (name_chars < MAXCDNAME) {
266*05b00f60SXin Li if (nd_printn(ndo, cp,
267*05b00f60SXin Li MAXCDNAME - name_chars, ndo->ndo_snapend))
268*05b00f60SXin Li return(NULL);
269*05b00f60SXin Li }
270*05b00f60SXin Li name_chars += l;
271*05b00f60SXin Li break;
272*05b00f60SXin Li }
273*05b00f60SXin Li
274*05b00f60SXin Li cp += l;
275*05b00f60SXin Li if (name_chars <= MAXCDNAME)
276*05b00f60SXin Li ND_PRINT(".");
277*05b00f60SXin Li name_chars++;
278*05b00f60SXin Li if (!ND_TTEST_1(cp))
279*05b00f60SXin Li return(NULL);
280*05b00f60SXin Li i = GET_U_1(cp);
281*05b00f60SXin Li if ((l = labellen(ndo, cp)) == (u_int)-1)
282*05b00f60SXin Li return(NULL);
283*05b00f60SXin Li cp++;
284*05b00f60SXin Li if (!compress)
285*05b00f60SXin Li rp += l + 1;
286*05b00f60SXin Li }
287*05b00f60SXin Li if (name_chars > MAXCDNAME)
288*05b00f60SXin Li ND_PRINT("<DOMAIN NAME TOO LONG>");
289*05b00f60SXin Li } else
290*05b00f60SXin Li ND_PRINT(".");
291*05b00f60SXin Li return (rp);
292*05b00f60SXin Li }
293*05b00f60SXin Li
294*05b00f60SXin Li /* print a <character-string> */
295*05b00f60SXin Li static const u_char *
ns_cprint(netdissect_options * ndo,const u_char * cp)296*05b00f60SXin Li ns_cprint(netdissect_options *ndo,
297*05b00f60SXin Li const u_char *cp)
298*05b00f60SXin Li {
299*05b00f60SXin Li u_int i;
300*05b00f60SXin Li
301*05b00f60SXin Li if (!ND_TTEST_1(cp))
302*05b00f60SXin Li return (NULL);
303*05b00f60SXin Li i = GET_U_1(cp);
304*05b00f60SXin Li cp++;
305*05b00f60SXin Li if (nd_printn(ndo, cp, i, ndo->ndo_snapend))
306*05b00f60SXin Li return (NULL);
307*05b00f60SXin Li return (cp + i);
308*05b00f60SXin Li }
309*05b00f60SXin Li
310*05b00f60SXin Li static void
print_eopt_ecs(netdissect_options * ndo,const u_char * cp,u_int data_len)311*05b00f60SXin Li print_eopt_ecs(netdissect_options *ndo, const u_char *cp,
312*05b00f60SXin Li u_int data_len)
313*05b00f60SXin Li {
314*05b00f60SXin Li u_int family, addr_bits, src_len, scope_len;
315*05b00f60SXin Li
316*05b00f60SXin Li u_char padded[32];
317*05b00f60SXin Li char addr[INET6_ADDRSTRLEN];
318*05b00f60SXin Li
319*05b00f60SXin Li /* ecs option must at least contain family, src len, and scope len */
320*05b00f60SXin Li if (data_len < 4) {
321*05b00f60SXin Li nd_print_invalid(ndo);
322*05b00f60SXin Li return;
323*05b00f60SXin Li }
324*05b00f60SXin Li
325*05b00f60SXin Li family = GET_BE_U_2(cp);
326*05b00f60SXin Li cp += 2;
327*05b00f60SXin Li src_len = GET_U_1(cp);
328*05b00f60SXin Li cp += 1;
329*05b00f60SXin Li scope_len = GET_U_1(cp);
330*05b00f60SXin Li cp += 1;
331*05b00f60SXin Li
332*05b00f60SXin Li if (family == 1)
333*05b00f60SXin Li addr_bits = 32;
334*05b00f60SXin Li else if (family == 2)
335*05b00f60SXin Li addr_bits = 128;
336*05b00f60SXin Li else {
337*05b00f60SXin Li nd_print_invalid(ndo);
338*05b00f60SXin Li return;
339*05b00f60SXin Li }
340*05b00f60SXin Li
341*05b00f60SXin Li if (data_len - 4 > (addr_bits / 8)) {
342*05b00f60SXin Li nd_print_invalid(ndo);
343*05b00f60SXin Li return;
344*05b00f60SXin Li }
345*05b00f60SXin Li /* checks for invalid ecs scope or source length */
346*05b00f60SXin Li if (src_len > addr_bits || scope_len > addr_bits || ((src_len + 7) / 8) != (data_len - 4)) {
347*05b00f60SXin Li nd_print_invalid(ndo);
348*05b00f60SXin Li return;
349*05b00f60SXin Li }
350*05b00f60SXin Li
351*05b00f60SXin Li /* pad the truncated address from ecs with zeros */
352*05b00f60SXin Li memset(padded, 0, sizeof(padded));
353*05b00f60SXin Li memcpy(padded, cp, data_len - 4);
354*05b00f60SXin Li
355*05b00f60SXin Li
356*05b00f60SXin Li if (family == 1)
357*05b00f60SXin Li ND_PRINT("%s/%d/%d", addrtostr(padded, addr, INET_ADDRSTRLEN),
358*05b00f60SXin Li src_len, scope_len);
359*05b00f60SXin Li else
360*05b00f60SXin Li ND_PRINT("%s/%d/%d", addrtostr6(padded, addr, INET6_ADDRSTRLEN),
361*05b00f60SXin Li src_len, scope_len);
362*05b00f60SXin Li
363*05b00f60SXin Li }
364*05b00f60SXin Li
365*05b00f60SXin Li extern const struct tok edns_opt2str[];
366*05b00f60SXin Li extern const struct tok dau_alg2str[];
367*05b00f60SXin Li extern const struct tok dhu_alg2str[];
368*05b00f60SXin Li extern const struct tok n3u_alg2str[];
369*05b00f60SXin Li
370*05b00f60SXin Li
371*05b00f60SXin Li /* print an <EDNS-option> */
372*05b00f60SXin Li static const u_char *
eopt_print(netdissect_options * ndo,const u_char * cp)373*05b00f60SXin Li eopt_print(netdissect_options *ndo,
374*05b00f60SXin Li const u_char *cp)
375*05b00f60SXin Li {
376*05b00f60SXin Li u_int opt, data_len, i;
377*05b00f60SXin Li
378*05b00f60SXin Li if (!ND_TTEST_2(cp))
379*05b00f60SXin Li return (NULL);
380*05b00f60SXin Li opt = GET_BE_U_2(cp);
381*05b00f60SXin Li cp += 2;
382*05b00f60SXin Li ND_PRINT("%s", tok2str(edns_opt2str, "Opt%u", opt));
383*05b00f60SXin Li if (!ND_TTEST_2(cp))
384*05b00f60SXin Li return (NULL);
385*05b00f60SXin Li data_len = GET_BE_U_2(cp);
386*05b00f60SXin Li cp += 2;
387*05b00f60SXin Li
388*05b00f60SXin Li ND_TCHECK_LEN(cp, data_len);
389*05b00f60SXin Li
390*05b00f60SXin Li if (data_len > 0) {
391*05b00f60SXin Li ND_PRINT(" ");
392*05b00f60SXin Li switch (opt) {
393*05b00f60SXin Li
394*05b00f60SXin Li case E_ECS:
395*05b00f60SXin Li print_eopt_ecs(ndo, cp, data_len);
396*05b00f60SXin Li break;
397*05b00f60SXin Li case E_COOKIE:
398*05b00f60SXin Li if (data_len < 8 || (data_len > 8 && data_len < 16) || data_len > 40)
399*05b00f60SXin Li nd_print_invalid(ndo);
400*05b00f60SXin Li else {
401*05b00f60SXin Li for (i = 0; i < data_len; ++i) {
402*05b00f60SXin Li /* split client and server cookie */
403*05b00f60SXin Li if (i == 8)
404*05b00f60SXin Li ND_PRINT(" ");
405*05b00f60SXin Li ND_PRINT("%02x", GET_U_1(cp + i));
406*05b00f60SXin Li }
407*05b00f60SXin Li }
408*05b00f60SXin Li break;
409*05b00f60SXin Li case E_KEEPALIVE:
410*05b00f60SXin Li if (data_len != 2)
411*05b00f60SXin Li nd_print_invalid(ndo);
412*05b00f60SXin Li else
413*05b00f60SXin Li /* keepalive is in increments of 100ms. Convert to seconds */
414*05b00f60SXin Li ND_PRINT("%0.1f sec", (GET_BE_U_2(cp) / 10.0));
415*05b00f60SXin Li break;
416*05b00f60SXin Li case E_EXPIRE:
417*05b00f60SXin Li if (data_len != 4)
418*05b00f60SXin Li nd_print_invalid(ndo);
419*05b00f60SXin Li else
420*05b00f60SXin Li ND_PRINT("%u sec", GET_BE_U_4(cp));
421*05b00f60SXin Li break;
422*05b00f60SXin Li case E_PADDING:
423*05b00f60SXin Li /* ignore contents and just print length */
424*05b00f60SXin Li ND_PRINT("(%u)", data_len);
425*05b00f60SXin Li break;
426*05b00f60SXin Li case E_KEYTAG:
427*05b00f60SXin Li if (data_len % 2 != 0)
428*05b00f60SXin Li nd_print_invalid(ndo);
429*05b00f60SXin Li else
430*05b00f60SXin Li for (i = 0; i < data_len; i += 2) {
431*05b00f60SXin Li if (i > 0)
432*05b00f60SXin Li ND_PRINT(" ");
433*05b00f60SXin Li ND_PRINT("%u", GET_BE_U_2(cp + i));
434*05b00f60SXin Li }
435*05b00f60SXin Li break;
436*05b00f60SXin Li case E_DAU:
437*05b00f60SXin Li for (i = 0; i < data_len; ++i) {
438*05b00f60SXin Li if (i > 0)
439*05b00f60SXin Li ND_PRINT(" ");
440*05b00f60SXin Li ND_PRINT("%s", tok2str(dau_alg2str, "Alg_%u", GET_U_1(cp + i)));
441*05b00f60SXin Li }
442*05b00f60SXin Li break;
443*05b00f60SXin Li case E_DHU:
444*05b00f60SXin Li for (i = 0; i < data_len; ++i) {
445*05b00f60SXin Li if (i > 0)
446*05b00f60SXin Li ND_PRINT(" ");
447*05b00f60SXin Li ND_PRINT("%s", tok2str(dhu_alg2str, "Alg_%u", GET_U_1(cp + i)));
448*05b00f60SXin Li }
449*05b00f60SXin Li break;
450*05b00f60SXin Li case E_N3U:
451*05b00f60SXin Li for (i = 0; i < data_len; ++i) {
452*05b00f60SXin Li if (i > 0)
453*05b00f60SXin Li ND_PRINT(" ");
454*05b00f60SXin Li ND_PRINT("%s", tok2str(n3u_alg2str, "Alg_%u", GET_U_1(cp + i)));
455*05b00f60SXin Li }
456*05b00f60SXin Li break;
457*05b00f60SXin Li case E_CHAIN:
458*05b00f60SXin Li fqdn_print(ndo, cp, cp + data_len);
459*05b00f60SXin Li break;
460*05b00f60SXin Li case E_NSID:
461*05b00f60SXin Li /* intentional fall-through. NSID is an undefined byte string */
462*05b00f60SXin Li default:
463*05b00f60SXin Li for (i = 0; i < data_len; ++i)
464*05b00f60SXin Li ND_PRINT("%02x", GET_U_1(cp + i));
465*05b00f60SXin Li break;
466*05b00f60SXin Li }
467*05b00f60SXin Li }
468*05b00f60SXin Li return (cp + data_len);
469*05b00f60SXin Li
470*05b00f60SXin Li trunc:
471*05b00f60SXin Li return (NULL);
472*05b00f60SXin Li
473*05b00f60SXin Li }
474*05b00f60SXin Li
475*05b00f60SXin Li
476*05b00f60SXin Li
477*05b00f60SXin Li extern const struct tok ns_type2str[];
478*05b00f60SXin Li
479*05b00f60SXin Li /* https://www.iana.org/assignments/dns-parameters */
480*05b00f60SXin Li const struct tok ns_type2str[] = {
481*05b00f60SXin Li { T_A, "A" }, /* RFC 1035 */
482*05b00f60SXin Li { T_NS, "NS" }, /* RFC 1035 */
483*05b00f60SXin Li { T_MD, "MD" }, /* RFC 1035 */
484*05b00f60SXin Li { T_MF, "MF" }, /* RFC 1035 */
485*05b00f60SXin Li { T_CNAME, "CNAME" }, /* RFC 1035 */
486*05b00f60SXin Li { T_SOA, "SOA" }, /* RFC 1035 */
487*05b00f60SXin Li { T_MB, "MB" }, /* RFC 1035 */
488*05b00f60SXin Li { T_MG, "MG" }, /* RFC 1035 */
489*05b00f60SXin Li { T_MR, "MR" }, /* RFC 1035 */
490*05b00f60SXin Li { T_NULL, "NULL" }, /* RFC 1035 */
491*05b00f60SXin Li { T_WKS, "WKS" }, /* RFC 1035 */
492*05b00f60SXin Li { T_PTR, "PTR" }, /* RFC 1035 */
493*05b00f60SXin Li { T_HINFO, "HINFO" }, /* RFC 1035 */
494*05b00f60SXin Li { T_MINFO, "MINFO" }, /* RFC 1035 */
495*05b00f60SXin Li { T_MX, "MX" }, /* RFC 1035 */
496*05b00f60SXin Li { T_TXT, "TXT" }, /* RFC 1035 */
497*05b00f60SXin Li { T_RP, "RP" }, /* RFC 1183 */
498*05b00f60SXin Li { T_AFSDB, "AFSDB" }, /* RFC 5864 */
499*05b00f60SXin Li { T_X25, "X25" }, /* RFC 1183 */
500*05b00f60SXin Li { T_ISDN, "ISDN" }, /* RFC 1183 */
501*05b00f60SXin Li { T_RT, "RT" }, /* RFC 1183 */
502*05b00f60SXin Li { T_NSAP, "NSAP" }, /* RFC 1706 */
503*05b00f60SXin Li { T_NSAP_PTR, "NSAP_PTR" }, /* RFC 1706 */
504*05b00f60SXin Li { T_SIG, "SIG" }, /* RFC 3008 */
505*05b00f60SXin Li { T_KEY, "KEY" }, /* RFC 3110 */
506*05b00f60SXin Li { T_PX, "PX" }, /* RFC 2163 */
507*05b00f60SXin Li { T_GPOS, "GPOS" }, /* RFC 1712 */
508*05b00f60SXin Li { T_AAAA, "AAAA" }, /* RFC 3596 */
509*05b00f60SXin Li { T_LOC, "LOC" }, /* RFC 1876 */
510*05b00f60SXin Li { T_NXT, "NXT" }, /* RFC 3755 */
511*05b00f60SXin Li { T_EID, "EID" }, /* Nimrod */
512*05b00f60SXin Li { T_NIMLOC, "NIMLOC" }, /* Nimrod */
513*05b00f60SXin Li { T_SRV, "SRV" }, /* RFC 2782 */
514*05b00f60SXin Li { T_ATMA, "ATMA" }, /* ATM Forum */
515*05b00f60SXin Li { T_NAPTR, "NAPTR" }, /* RFC 3403 */
516*05b00f60SXin Li { T_KX, "KX" }, /* RFC 2230 */
517*05b00f60SXin Li { T_CERT, "CERT" }, /* RFC 4398 */
518*05b00f60SXin Li { T_A6, "A6" }, /* RFC 6563 */
519*05b00f60SXin Li { T_DNAME, "DNAME" }, /* RFC 6672 */
520*05b00f60SXin Li { T_SINK, "SINK" },
521*05b00f60SXin Li { T_OPT, "OPT" }, /* RFC 6891 */
522*05b00f60SXin Li { T_APL, "APL" }, /* RFC 3123 */
523*05b00f60SXin Li { T_DS, "DS" }, /* RFC 4034 */
524*05b00f60SXin Li { T_SSHFP, "SSHFP" }, /* RFC 4255 */
525*05b00f60SXin Li { T_IPSECKEY, "IPSECKEY" }, /* RFC 4025 */
526*05b00f60SXin Li { T_RRSIG, "RRSIG" }, /* RFC 4034 */
527*05b00f60SXin Li { T_NSEC, "NSEC" }, /* RFC 4034 */
528*05b00f60SXin Li { T_DNSKEY, "DNSKEY" }, /* RFC 4034 */
529*05b00f60SXin Li { T_DHCID, "DHCID" }, /* RFC 4071 */
530*05b00f60SXin Li { T_NSEC3, "NSEC3" }, /* RFC 5155 */
531*05b00f60SXin Li { T_NSEC3PARAM, "NSEC3PARAM" }, /* RFC 5155 */
532*05b00f60SXin Li { T_TLSA, "TLSA" }, /* RFC 6698 */
533*05b00f60SXin Li { T_SMIMEA, "SMIMEA" }, /* RFC 8162 */
534*05b00f60SXin Li { T_HIP, "HIP" }, /* RFC 8005 */
535*05b00f60SXin Li { T_NINFO, "NINFO" },
536*05b00f60SXin Li { T_RKEY, "RKEY" },
537*05b00f60SXin Li { T_TALINK, "TALINK" },
538*05b00f60SXin Li { T_CDS, "CDS" }, /* RFC 7344 */
539*05b00f60SXin Li { T_CDNSKEY, "CDNSKEY" }, /* RFC 7344 */
540*05b00f60SXin Li { T_OPENPGPKEY, "OPENPGPKEY" }, /* RFC 7929 */
541*05b00f60SXin Li { T_CSYNC, "CSYNC" }, /* RFC 7477 */
542*05b00f60SXin Li { T_ZONEMD, "ZONEMD" }, /* RFC 8976 */
543*05b00f60SXin Li { T_SVCB, "SVCB" },
544*05b00f60SXin Li { T_HTTPS, "HTTPS" },
545*05b00f60SXin Li { T_SPF, "SPF" }, /* RFC 7208 */
546*05b00f60SXin Li { T_UINFO, "UINFO" },
547*05b00f60SXin Li { T_UID, "UID" },
548*05b00f60SXin Li { T_GID, "GID" },
549*05b00f60SXin Li { T_UNSPEC, "UNSPEC" },
550*05b00f60SXin Li { T_NID, "NID" }, /* RFC 6742 */
551*05b00f60SXin Li { T_L32, "L32" }, /* RFC 6742 */
552*05b00f60SXin Li { T_L64, "L64" }, /* RFC 6742 */
553*05b00f60SXin Li { T_LP, "LP" }, /* RFC 6742 */
554*05b00f60SXin Li { T_EUI48, "EUI48" }, /* RFC 7043 */
555*05b00f60SXin Li { T_EUI64, "EUI64" }, /* RFC 7043 */
556*05b00f60SXin Li { T_TKEY, "TKEY" }, /* RFC 2930 */
557*05b00f60SXin Li { T_TSIG, "TSIG" }, /* RFC 8945 */
558*05b00f60SXin Li { T_IXFR, "IXFR" }, /* RFC 1995 */
559*05b00f60SXin Li { T_AXFR, "AXFR" }, /* RFC 5936 */
560*05b00f60SXin Li { T_MAILB, "MAILB" }, /* RFC 1035 */
561*05b00f60SXin Li { T_MAILA, "MAILA" }, /* RFC 1035 */
562*05b00f60SXin Li { T_ANY, "ANY" }, /* RFC 8482 */
563*05b00f60SXin Li { T_URI, "URI" }, /* RFC 7553 */
564*05b00f60SXin Li { T_CAA, "CAA" }, /* RFC 8659 */
565*05b00f60SXin Li { T_AVC, "AVC" },
566*05b00f60SXin Li { T_DOA, "DOA" },
567*05b00f60SXin Li { T_AMTRELAY, "AMTRELAY" }, /* RFC 8777 */
568*05b00f60SXin Li { T_TA, "TA" },
569*05b00f60SXin Li { T_DLV, "DLV" }, /* RFC 8749 */
570*05b00f60SXin Li { 0, NULL }
571*05b00f60SXin Li };
572*05b00f60SXin Li
573*05b00f60SXin Li extern const struct tok ns_class2str[];
574*05b00f60SXin Li
575*05b00f60SXin Li const struct tok ns_class2str[] = {
576*05b00f60SXin Li { C_IN, "IN" }, /* Not used */
577*05b00f60SXin Li { C_CHAOS, "CHAOS" },
578*05b00f60SXin Li { C_HS, "HS" },
579*05b00f60SXin Li { C_ANY, "ANY" },
580*05b00f60SXin Li { 0, NULL }
581*05b00f60SXin Li };
582*05b00f60SXin Li
583*05b00f60SXin Li const struct tok edns_opt2str[] = {
584*05b00f60SXin Li { E_LLQ, "LLQ" },
585*05b00f60SXin Li { E_UL, "UL" },
586*05b00f60SXin Li { E_NSID, "NSID" },
587*05b00f60SXin Li { E_DAU, "DAU" },
588*05b00f60SXin Li { E_DHU, "DHU" },
589*05b00f60SXin Li { E_N3U, "N3U" },
590*05b00f60SXin Li { E_ECS, "ECS" },
591*05b00f60SXin Li { E_EXPIRE, "EXPIRE" },
592*05b00f60SXin Li { E_COOKIE, "COOKIE" },
593*05b00f60SXin Li { E_KEEPALIVE, "KEEPALIVE" },
594*05b00f60SXin Li { E_PADDING, "PADDING" },
595*05b00f60SXin Li { E_CHAIN, "CHAIN" },
596*05b00f60SXin Li { E_KEYTAG, "KEY-TAG" },
597*05b00f60SXin Li { E_CLIENTTAG, "CLIENT-TAG" },
598*05b00f60SXin Li { E_SERVERTAG, "SERVER-TAG" },
599*05b00f60SXin Li { 0, NULL }
600*05b00f60SXin Li };
601*05b00f60SXin Li
602*05b00f60SXin Li const struct tok dau_alg2str[] = {
603*05b00f60SXin Li { A_DELETE, "DELETE" },
604*05b00f60SXin Li { A_RSAMD5, "RSAMD5" },
605*05b00f60SXin Li { A_DH, "DH" },
606*05b00f60SXin Li { A_DSA, "DS" },
607*05b00f60SXin Li { A_RSASHA1, "RSASHA1" },
608*05b00f60SXin Li { A_DSA_NSEC3_SHA1, "DSA-NSEC3-SHA1" },
609*05b00f60SXin Li { A_RSASHA1_NSEC3_SHA1, "RSASHA1-NSEC3-SHA1" },
610*05b00f60SXin Li { A_RSASHA256, "RSASHA256" },
611*05b00f60SXin Li { A_RSASHA512, "RSASHA512" },
612*05b00f60SXin Li { A_ECC_GOST, "ECC-GOST" },
613*05b00f60SXin Li { A_ECDSAP256SHA256, "ECDSAP256SHA256" },
614*05b00f60SXin Li { A_ECDSAP384SHA384, "ECDSAP384SHA384" },
615*05b00f60SXin Li { A_ED25519, "ED25519" },
616*05b00f60SXin Li { A_ED448, "ED448" },
617*05b00f60SXin Li { A_INDIRECT, "INDIRECT" },
618*05b00f60SXin Li { A_PRIVATEDNS, "PRIVATEDNS" },
619*05b00f60SXin Li { A_PRIVATEOID, "PRIVATEOID" },
620*05b00f60SXin Li { 0, NULL }
621*05b00f60SXin Li };
622*05b00f60SXin Li
623*05b00f60SXin Li const struct tok dhu_alg2str[] = {
624*05b00f60SXin Li { DS_SHA1, "SHA-1" },
625*05b00f60SXin Li { DS_SHA256,"SHA-256" },
626*05b00f60SXin Li { DS_GOST, "GOST_R_34.11-94" },
627*05b00f60SXin Li { DS_SHA384,"SHA-384" },
628*05b00f60SXin Li { 0, NULL }
629*05b00f60SXin Li };
630*05b00f60SXin Li
631*05b00f60SXin Li const struct tok n3u_alg2str[] = {
632*05b00f60SXin Li { NSEC_SHA1,"SHA-1" },
633*05b00f60SXin Li { 0, NULL }
634*05b00f60SXin Li };
635*05b00f60SXin Li
636*05b00f60SXin Li /* print a query */
637*05b00f60SXin Li static const u_char *
ns_qprint(netdissect_options * ndo,const u_char * cp,const u_char * bp,int is_mdns)638*05b00f60SXin Li ns_qprint(netdissect_options *ndo,
639*05b00f60SXin Li const u_char *cp, const u_char *bp, int is_mdns)
640*05b00f60SXin Li {
641*05b00f60SXin Li const u_char *np = cp;
642*05b00f60SXin Li u_int i, class;
643*05b00f60SXin Li
644*05b00f60SXin Li cp = ns_nskip(ndo, cp);
645*05b00f60SXin Li
646*05b00f60SXin Li if (cp == NULL || !ND_TTEST_4(cp))
647*05b00f60SXin Li return(NULL);
648*05b00f60SXin Li
649*05b00f60SXin Li /* print the qtype */
650*05b00f60SXin Li i = GET_BE_U_2(cp);
651*05b00f60SXin Li cp += 2;
652*05b00f60SXin Li ND_PRINT(" %s", tok2str(ns_type2str, "Type%u", i));
653*05b00f60SXin Li /* print the qclass (if it's not IN) */
654*05b00f60SXin Li i = GET_BE_U_2(cp);
655*05b00f60SXin Li cp += 2;
656*05b00f60SXin Li if (is_mdns)
657*05b00f60SXin Li class = (i & ~C_QU);
658*05b00f60SXin Li else
659*05b00f60SXin Li class = i;
660*05b00f60SXin Li if (class != C_IN)
661*05b00f60SXin Li ND_PRINT(" %s", tok2str(ns_class2str, "(Class %u)", class));
662*05b00f60SXin Li if (is_mdns) {
663*05b00f60SXin Li ND_PRINT(i & C_QU ? " (QU)" : " (QM)");
664*05b00f60SXin Li }
665*05b00f60SXin Li
666*05b00f60SXin Li ND_PRINT("? ");
667*05b00f60SXin Li cp = fqdn_print(ndo, np, bp);
668*05b00f60SXin Li return(cp ? cp + 4 : NULL);
669*05b00f60SXin Li }
670*05b00f60SXin Li
671*05b00f60SXin Li /* print a reply */
672*05b00f60SXin Li static const u_char *
ns_rprint(netdissect_options * ndo,const u_char * cp,const u_char * bp,int is_mdns)673*05b00f60SXin Li ns_rprint(netdissect_options *ndo,
674*05b00f60SXin Li const u_char *cp, const u_char *bp, int is_mdns)
675*05b00f60SXin Li {
676*05b00f60SXin Li u_int i, class, opt_flags = 0;
677*05b00f60SXin Li u_short typ, len;
678*05b00f60SXin Li const u_char *rp;
679*05b00f60SXin Li
680*05b00f60SXin Li if (ndo->ndo_vflag) {
681*05b00f60SXin Li ND_PRINT(" ");
682*05b00f60SXin Li if ((cp = fqdn_print(ndo, cp, bp)) == NULL)
683*05b00f60SXin Li return NULL;
684*05b00f60SXin Li } else
685*05b00f60SXin Li cp = ns_nskip(ndo, cp);
686*05b00f60SXin Li
687*05b00f60SXin Li if (cp == NULL || !ND_TTEST_LEN(cp, 10))
688*05b00f60SXin Li return (ndo->ndo_snapend);
689*05b00f60SXin Li
690*05b00f60SXin Li /* print the type/qtype */
691*05b00f60SXin Li typ = GET_BE_U_2(cp);
692*05b00f60SXin Li cp += 2;
693*05b00f60SXin Li /* print the class (if it's not IN and the type isn't OPT) */
694*05b00f60SXin Li i = GET_BE_U_2(cp);
695*05b00f60SXin Li cp += 2;
696*05b00f60SXin Li if (is_mdns)
697*05b00f60SXin Li class = (i & ~C_CACHE_FLUSH);
698*05b00f60SXin Li else
699*05b00f60SXin Li class = i;
700*05b00f60SXin Li if (class != C_IN && typ != T_OPT)
701*05b00f60SXin Li ND_PRINT(" %s", tok2str(ns_class2str, "(Class %u)", class));
702*05b00f60SXin Li if (is_mdns) {
703*05b00f60SXin Li if (i & C_CACHE_FLUSH)
704*05b00f60SXin Li ND_PRINT(" (Cache flush)");
705*05b00f60SXin Li }
706*05b00f60SXin Li
707*05b00f60SXin Li if (typ == T_OPT) {
708*05b00f60SXin Li /* get opt flags */
709*05b00f60SXin Li cp += 2;
710*05b00f60SXin Li opt_flags = GET_BE_U_2(cp);
711*05b00f60SXin Li /* ignore rest of ttl field */
712*05b00f60SXin Li cp += 2;
713*05b00f60SXin Li } else if (ndo->ndo_vflag > 2) {
714*05b00f60SXin Li /* print ttl */
715*05b00f60SXin Li ND_PRINT(" [");
716*05b00f60SXin Li unsigned_relts_print(ndo, GET_BE_U_4(cp));
717*05b00f60SXin Li ND_PRINT("]");
718*05b00f60SXin Li cp += 4;
719*05b00f60SXin Li } else {
720*05b00f60SXin Li /* ignore ttl */
721*05b00f60SXin Li cp += 4;
722*05b00f60SXin Li }
723*05b00f60SXin Li
724*05b00f60SXin Li len = GET_BE_U_2(cp);
725*05b00f60SXin Li cp += 2;
726*05b00f60SXin Li
727*05b00f60SXin Li rp = cp + len;
728*05b00f60SXin Li
729*05b00f60SXin Li ND_PRINT(" %s", tok2str(ns_type2str, "Type%u", typ));
730*05b00f60SXin Li if (rp > ndo->ndo_snapend)
731*05b00f60SXin Li return(NULL);
732*05b00f60SXin Li
733*05b00f60SXin Li switch (typ) {
734*05b00f60SXin Li case T_A:
735*05b00f60SXin Li if (!ND_TTEST_LEN(cp, sizeof(nd_ipv4)))
736*05b00f60SXin Li return(NULL);
737*05b00f60SXin Li ND_PRINT(" %s", intoa(GET_IPV4_TO_NETWORK_ORDER(cp)));
738*05b00f60SXin Li break;
739*05b00f60SXin Li
740*05b00f60SXin Li case T_NS:
741*05b00f60SXin Li case T_CNAME:
742*05b00f60SXin Li case T_PTR:
743*05b00f60SXin Li case T_DNAME:
744*05b00f60SXin Li ND_PRINT(" ");
745*05b00f60SXin Li if (fqdn_print(ndo, cp, bp) == NULL)
746*05b00f60SXin Li return(NULL);
747*05b00f60SXin Li break;
748*05b00f60SXin Li
749*05b00f60SXin Li case T_SOA:
750*05b00f60SXin Li if (!ndo->ndo_vflag)
751*05b00f60SXin Li break;
752*05b00f60SXin Li ND_PRINT(" ");
753*05b00f60SXin Li if ((cp = fqdn_print(ndo, cp, bp)) == NULL)
754*05b00f60SXin Li return(NULL);
755*05b00f60SXin Li ND_PRINT(" ");
756*05b00f60SXin Li if ((cp = fqdn_print(ndo, cp, bp)) == NULL)
757*05b00f60SXin Li return(NULL);
758*05b00f60SXin Li if (!ND_TTEST_LEN(cp, 5 * 4))
759*05b00f60SXin Li return(NULL);
760*05b00f60SXin Li ND_PRINT(" %u", GET_BE_U_4(cp));
761*05b00f60SXin Li cp += 4;
762*05b00f60SXin Li ND_PRINT(" %u", GET_BE_U_4(cp));
763*05b00f60SXin Li cp += 4;
764*05b00f60SXin Li ND_PRINT(" %u", GET_BE_U_4(cp));
765*05b00f60SXin Li cp += 4;
766*05b00f60SXin Li ND_PRINT(" %u", GET_BE_U_4(cp));
767*05b00f60SXin Li cp += 4;
768*05b00f60SXin Li ND_PRINT(" %u", GET_BE_U_4(cp));
769*05b00f60SXin Li cp += 4;
770*05b00f60SXin Li break;
771*05b00f60SXin Li case T_MX:
772*05b00f60SXin Li ND_PRINT(" ");
773*05b00f60SXin Li if (!ND_TTEST_2(cp))
774*05b00f60SXin Li return(NULL);
775*05b00f60SXin Li if (fqdn_print(ndo, cp + 2, bp) == NULL)
776*05b00f60SXin Li return(NULL);
777*05b00f60SXin Li ND_PRINT(" %u", GET_BE_U_2(cp));
778*05b00f60SXin Li break;
779*05b00f60SXin Li
780*05b00f60SXin Li case T_TXT:
781*05b00f60SXin Li while (cp < rp) {
782*05b00f60SXin Li ND_PRINT(" \"");
783*05b00f60SXin Li cp = ns_cprint(ndo, cp);
784*05b00f60SXin Li if (cp == NULL)
785*05b00f60SXin Li return(NULL);
786*05b00f60SXin Li ND_PRINT("\"");
787*05b00f60SXin Li }
788*05b00f60SXin Li break;
789*05b00f60SXin Li
790*05b00f60SXin Li case T_SRV:
791*05b00f60SXin Li ND_PRINT(" ");
792*05b00f60SXin Li if (!ND_TTEST_6(cp))
793*05b00f60SXin Li return(NULL);
794*05b00f60SXin Li if (fqdn_print(ndo, cp + 6, bp) == NULL)
795*05b00f60SXin Li return(NULL);
796*05b00f60SXin Li ND_PRINT(":%u %u %u", GET_BE_U_2(cp + 4),
797*05b00f60SXin Li GET_BE_U_2(cp), GET_BE_U_2(cp + 2));
798*05b00f60SXin Li break;
799*05b00f60SXin Li
800*05b00f60SXin Li case T_AAAA:
801*05b00f60SXin Li {
802*05b00f60SXin Li char ntop_buf[INET6_ADDRSTRLEN];
803*05b00f60SXin Li
804*05b00f60SXin Li if (!ND_TTEST_LEN(cp, sizeof(nd_ipv6)))
805*05b00f60SXin Li return(NULL);
806*05b00f60SXin Li ND_PRINT(" %s",
807*05b00f60SXin Li addrtostr6(cp, ntop_buf, sizeof(ntop_buf)));
808*05b00f60SXin Li
809*05b00f60SXin Li break;
810*05b00f60SXin Li }
811*05b00f60SXin Li
812*05b00f60SXin Li case T_A6:
813*05b00f60SXin Li {
814*05b00f60SXin Li nd_ipv6 a;
815*05b00f60SXin Li int pbit, pbyte;
816*05b00f60SXin Li char ntop_buf[INET6_ADDRSTRLEN];
817*05b00f60SXin Li
818*05b00f60SXin Li if (!ND_TTEST_1(cp))
819*05b00f60SXin Li return(NULL);
820*05b00f60SXin Li pbit = GET_U_1(cp);
821*05b00f60SXin Li pbyte = (pbit & ~7) / 8;
822*05b00f60SXin Li if (pbit > 128) {
823*05b00f60SXin Li ND_PRINT(" %u(bad plen)", pbit);
824*05b00f60SXin Li break;
825*05b00f60SXin Li } else if (pbit < 128) {
826*05b00f60SXin Li memset(a, 0, sizeof(a));
827*05b00f60SXin Li GET_CPY_BYTES(a + pbyte, cp + 1, sizeof(a) - pbyte);
828*05b00f60SXin Li ND_PRINT(" %u %s", pbit,
829*05b00f60SXin Li addrtostr6(&a, ntop_buf, sizeof(ntop_buf)));
830*05b00f60SXin Li }
831*05b00f60SXin Li if (pbit > 0) {
832*05b00f60SXin Li ND_PRINT(" ");
833*05b00f60SXin Li if (fqdn_print(ndo, cp + 1 + sizeof(a) - pbyte, bp) == NULL)
834*05b00f60SXin Li return(NULL);
835*05b00f60SXin Li }
836*05b00f60SXin Li break;
837*05b00f60SXin Li }
838*05b00f60SXin Li
839*05b00f60SXin Li case T_URI:
840*05b00f60SXin Li if (!ND_TTEST_LEN(cp, len))
841*05b00f60SXin Li return(NULL);
842*05b00f60SXin Li ND_PRINT(" %u %u ", GET_BE_U_2(cp), GET_BE_U_2(cp + 2));
843*05b00f60SXin Li if (nd_printn(ndo, cp + 4, len - 4, ndo->ndo_snapend))
844*05b00f60SXin Li return(NULL);
845*05b00f60SXin Li break;
846*05b00f60SXin Li
847*05b00f60SXin Li case T_OPT:
848*05b00f60SXin Li ND_PRINT(" UDPsize=%u", class);
849*05b00f60SXin Li if (opt_flags & 0x8000)
850*05b00f60SXin Li ND_PRINT(" DO");
851*05b00f60SXin Li if (cp < rp) {
852*05b00f60SXin Li ND_PRINT(" [");
853*05b00f60SXin Li while (cp < rp) {
854*05b00f60SXin Li cp = eopt_print(ndo, cp);
855*05b00f60SXin Li if (cp == NULL)
856*05b00f60SXin Li return(NULL);
857*05b00f60SXin Li if (cp < rp)
858*05b00f60SXin Li ND_PRINT(",");
859*05b00f60SXin Li }
860*05b00f60SXin Li ND_PRINT("]");
861*05b00f60SXin Li }
862*05b00f60SXin Li break;
863*05b00f60SXin Li
864*05b00f60SXin Li case T_TSIG:
865*05b00f60SXin Li {
866*05b00f60SXin Li if (cp + len > ndo->ndo_snapend)
867*05b00f60SXin Li return(NULL);
868*05b00f60SXin Li if (!ndo->ndo_vflag)
869*05b00f60SXin Li break;
870*05b00f60SXin Li ND_PRINT(" ");
871*05b00f60SXin Li if ((cp = fqdn_print(ndo, cp, bp)) == NULL)
872*05b00f60SXin Li return(NULL);
873*05b00f60SXin Li cp += 6;
874*05b00f60SXin Li if (!ND_TTEST_2(cp))
875*05b00f60SXin Li return(NULL);
876*05b00f60SXin Li ND_PRINT(" fudge=%u", GET_BE_U_2(cp));
877*05b00f60SXin Li cp += 2;
878*05b00f60SXin Li if (!ND_TTEST_2(cp))
879*05b00f60SXin Li return(NULL);
880*05b00f60SXin Li ND_PRINT(" maclen=%u", GET_BE_U_2(cp));
881*05b00f60SXin Li cp += 2 + GET_BE_U_2(cp);
882*05b00f60SXin Li if (!ND_TTEST_2(cp))
883*05b00f60SXin Li return(NULL);
884*05b00f60SXin Li ND_PRINT(" origid=%u", GET_BE_U_2(cp));
885*05b00f60SXin Li cp += 2;
886*05b00f60SXin Li if (!ND_TTEST_2(cp))
887*05b00f60SXin Li return(NULL);
888*05b00f60SXin Li ND_PRINT(" error=%u", GET_BE_U_2(cp));
889*05b00f60SXin Li cp += 2;
890*05b00f60SXin Li if (!ND_TTEST_2(cp))
891*05b00f60SXin Li return(NULL);
892*05b00f60SXin Li ND_PRINT(" otherlen=%u", GET_BE_U_2(cp));
893*05b00f60SXin Li cp += 2;
894*05b00f60SXin Li }
895*05b00f60SXin Li }
896*05b00f60SXin Li return (rp); /* XXX This isn't always right */
897*05b00f60SXin Li }
898*05b00f60SXin Li
899*05b00f60SXin Li void
domain_print(netdissect_options * ndo,const u_char * bp,u_int length,int over_tcp,int is_mdns)900*05b00f60SXin Li domain_print(netdissect_options *ndo,
901*05b00f60SXin Li const u_char *bp, u_int length, int over_tcp, int is_mdns)
902*05b00f60SXin Li {
903*05b00f60SXin Li const dns_header_t *np;
904*05b00f60SXin Li uint16_t flags, rcode, rdlen, type;
905*05b00f60SXin Li u_int qdcount, ancount, nscount, arcount;
906*05b00f60SXin Li u_int i;
907*05b00f60SXin Li const u_char *cp;
908*05b00f60SXin Li uint16_t b2;
909*05b00f60SXin Li
910*05b00f60SXin Li ndo->ndo_protocol = "domain";
911*05b00f60SXin Li
912*05b00f60SXin Li if (over_tcp) {
913*05b00f60SXin Li /*
914*05b00f60SXin Li * The message is prefixed with a two byte length field
915*05b00f60SXin Li * which gives the message length, excluding the two byte
916*05b00f60SXin Li * length field. (RFC 1035 - 4.2.2. TCP usage)
917*05b00f60SXin Li */
918*05b00f60SXin Li if (length < 2) {
919*05b00f60SXin Li ND_PRINT(" [DNS over TCP: length %u < 2]", length);
920*05b00f60SXin Li nd_print_invalid(ndo);
921*05b00f60SXin Li return;
922*05b00f60SXin Li } else {
923*05b00f60SXin Li length -= 2; /* excluding the two byte length field */
924*05b00f60SXin Li if (GET_BE_U_2(bp) != length) {
925*05b00f60SXin Li ND_PRINT(" [prefix length(%u) != length(%u)]",
926*05b00f60SXin Li GET_BE_U_2(bp), length);
927*05b00f60SXin Li nd_print_invalid(ndo);
928*05b00f60SXin Li return;
929*05b00f60SXin Li } else {
930*05b00f60SXin Li bp += 2;
931*05b00f60SXin Li /* in over TCP case, we need to prepend a space
932*05b00f60SXin Li * (not needed in over UDP case)
933*05b00f60SXin Li */
934*05b00f60SXin Li ND_PRINT(" ");
935*05b00f60SXin Li }
936*05b00f60SXin Li }
937*05b00f60SXin Li }
938*05b00f60SXin Li
939*05b00f60SXin Li np = (const dns_header_t *)bp;
940*05b00f60SXin Li
941*05b00f60SXin Li if(length < sizeof(*np)) {
942*05b00f60SXin Li nd_print_protocol(ndo);
943*05b00f60SXin Li ND_PRINT(" [length %u < %zu]", length, sizeof(*np));
944*05b00f60SXin Li nd_print_invalid(ndo);
945*05b00f60SXin Li return;
946*05b00f60SXin Li }
947*05b00f60SXin Li
948*05b00f60SXin Li ND_TCHECK_SIZE(np);
949*05b00f60SXin Li flags = GET_BE_U_2(np->flags);
950*05b00f60SXin Li /* get the byte-order right */
951*05b00f60SXin Li qdcount = GET_BE_U_2(np->qdcount);
952*05b00f60SXin Li ancount = GET_BE_U_2(np->ancount);
953*05b00f60SXin Li nscount = GET_BE_U_2(np->nscount);
954*05b00f60SXin Li arcount = GET_BE_U_2(np->arcount);
955*05b00f60SXin Li
956*05b00f60SXin Li /* find the opt record to extract extended rcode */
957*05b00f60SXin Li cp = (const u_char *)(np + 1);
958*05b00f60SXin Li rcode = DNS_RCODE(flags);
959*05b00f60SXin Li for (i = 0; i < qdcount; i++) {
960*05b00f60SXin Li if ((cp = ns_nskip(ndo, cp)) == NULL)
961*05b00f60SXin Li goto print;
962*05b00f60SXin Li cp += 4; /* skip QTYPE and QCLASS */
963*05b00f60SXin Li if (cp >= ndo->ndo_snapend)
964*05b00f60SXin Li goto print;
965*05b00f60SXin Li }
966*05b00f60SXin Li for (i = 0; i < ancount + nscount; i++) {
967*05b00f60SXin Li if ((cp = ns_nskip(ndo, cp)) == NULL)
968*05b00f60SXin Li goto print;
969*05b00f60SXin Li cp += 8; /* skip TYPE, CLASS and TTL */
970*05b00f60SXin Li if (cp + 2 > ndo->ndo_snapend)
971*05b00f60SXin Li goto print;
972*05b00f60SXin Li rdlen = GET_BE_U_2(cp);
973*05b00f60SXin Li cp += 2 + rdlen;
974*05b00f60SXin Li if (cp >= ndo->ndo_snapend)
975*05b00f60SXin Li goto print;
976*05b00f60SXin Li }
977*05b00f60SXin Li for (i = 0; i < arcount; i++) {
978*05b00f60SXin Li if ((cp = ns_nskip(ndo, cp)) == NULL)
979*05b00f60SXin Li goto print;
980*05b00f60SXin Li if (cp + 2 > ndo->ndo_snapend)
981*05b00f60SXin Li goto print;
982*05b00f60SXin Li type = GET_BE_U_2(cp);
983*05b00f60SXin Li cp += 4; /* skip TYPE and CLASS */
984*05b00f60SXin Li if (cp + 1 > ndo->ndo_snapend)
985*05b00f60SXin Li goto print;
986*05b00f60SXin Li if (type == T_OPT) {
987*05b00f60SXin Li rcode |= (GET_U_1(cp) << 4);
988*05b00f60SXin Li goto print;
989*05b00f60SXin Li }
990*05b00f60SXin Li cp += 4;
991*05b00f60SXin Li if (cp + 2 > ndo->ndo_snapend)
992*05b00f60SXin Li goto print;
993*05b00f60SXin Li rdlen = GET_BE_U_2(cp);
994*05b00f60SXin Li cp += 2 + rdlen;
995*05b00f60SXin Li if (cp >= ndo->ndo_snapend)
996*05b00f60SXin Li goto print;
997*05b00f60SXin Li }
998*05b00f60SXin Li
999*05b00f60SXin Li print:
1000*05b00f60SXin Li if (DNS_QR(flags)) {
1001*05b00f60SXin Li /* this is a response */
1002*05b00f60SXin Li ND_PRINT("%u%s%s%s%s%s%s",
1003*05b00f60SXin Li GET_BE_U_2(np->id),
1004*05b00f60SXin Li ns_ops[DNS_OPCODE(flags)],
1005*05b00f60SXin Li ns_rcode(rcode),
1006*05b00f60SXin Li DNS_AA(flags)? "*" : "",
1007*05b00f60SXin Li DNS_RA(flags)? "" : "-",
1008*05b00f60SXin Li DNS_TC(flags)? "|" : "",
1009*05b00f60SXin Li DNS_AD(flags)? "$" : "");
1010*05b00f60SXin Li
1011*05b00f60SXin Li if (qdcount != 1)
1012*05b00f60SXin Li ND_PRINT(" [%uq]", qdcount);
1013*05b00f60SXin Li /* Print QUESTION section on -vv */
1014*05b00f60SXin Li cp = (const u_char *)(np + 1);
1015*05b00f60SXin Li for (i = 0; i < qdcount; i++) {
1016*05b00f60SXin Li if (i != 0)
1017*05b00f60SXin Li ND_PRINT(",");
1018*05b00f60SXin Li if (ndo->ndo_vflag > 1) {
1019*05b00f60SXin Li ND_PRINT(" q:");
1020*05b00f60SXin Li if ((cp = ns_qprint(ndo, cp, bp, is_mdns)) == NULL)
1021*05b00f60SXin Li goto trunc;
1022*05b00f60SXin Li } else {
1023*05b00f60SXin Li if ((cp = ns_nskip(ndo, cp)) == NULL)
1024*05b00f60SXin Li goto trunc;
1025*05b00f60SXin Li cp += 4; /* skip QTYPE and QCLASS */
1026*05b00f60SXin Li }
1027*05b00f60SXin Li }
1028*05b00f60SXin Li ND_PRINT(" %u/%u/%u", ancount, nscount, arcount);
1029*05b00f60SXin Li if (ancount) {
1030*05b00f60SXin Li if ((cp = ns_rprint(ndo, cp, bp, is_mdns)) == NULL)
1031*05b00f60SXin Li goto trunc;
1032*05b00f60SXin Li ancount--;
1033*05b00f60SXin Li while (cp < ndo->ndo_snapend && ancount) {
1034*05b00f60SXin Li ND_PRINT(",");
1035*05b00f60SXin Li if ((cp = ns_rprint(ndo, cp, bp, is_mdns)) == NULL)
1036*05b00f60SXin Li goto trunc;
1037*05b00f60SXin Li ancount--;
1038*05b00f60SXin Li }
1039*05b00f60SXin Li }
1040*05b00f60SXin Li if (ancount)
1041*05b00f60SXin Li goto trunc;
1042*05b00f60SXin Li /* Print NS and AR sections on -vv */
1043*05b00f60SXin Li if (ndo->ndo_vflag > 1) {
1044*05b00f60SXin Li if (cp < ndo->ndo_snapend && nscount) {
1045*05b00f60SXin Li ND_PRINT(" ns:");
1046*05b00f60SXin Li if ((cp = ns_rprint(ndo, cp, bp, is_mdns)) == NULL)
1047*05b00f60SXin Li goto trunc;
1048*05b00f60SXin Li nscount--;
1049*05b00f60SXin Li while (cp < ndo->ndo_snapend && nscount) {
1050*05b00f60SXin Li ND_PRINT(",");
1051*05b00f60SXin Li if ((cp = ns_rprint(ndo, cp, bp, is_mdns)) == NULL)
1052*05b00f60SXin Li goto trunc;
1053*05b00f60SXin Li nscount--;
1054*05b00f60SXin Li }
1055*05b00f60SXin Li }
1056*05b00f60SXin Li if (nscount)
1057*05b00f60SXin Li goto trunc;
1058*05b00f60SXin Li if (cp < ndo->ndo_snapend && arcount) {
1059*05b00f60SXin Li ND_PRINT(" ar:");
1060*05b00f60SXin Li if ((cp = ns_rprint(ndo, cp, bp, is_mdns)) == NULL)
1061*05b00f60SXin Li goto trunc;
1062*05b00f60SXin Li arcount--;
1063*05b00f60SXin Li while (cp < ndo->ndo_snapend && arcount) {
1064*05b00f60SXin Li ND_PRINT(",");
1065*05b00f60SXin Li if ((cp = ns_rprint(ndo, cp, bp, is_mdns)) == NULL)
1066*05b00f60SXin Li goto trunc;
1067*05b00f60SXin Li arcount--;
1068*05b00f60SXin Li }
1069*05b00f60SXin Li }
1070*05b00f60SXin Li if (arcount)
1071*05b00f60SXin Li goto trunc;
1072*05b00f60SXin Li }
1073*05b00f60SXin Li }
1074*05b00f60SXin Li else {
1075*05b00f60SXin Li /* this is a request */
1076*05b00f60SXin Li ND_PRINT("%u%s%s%s", GET_BE_U_2(np->id),
1077*05b00f60SXin Li ns_ops[DNS_OPCODE(flags)],
1078*05b00f60SXin Li DNS_RD(flags) ? "+" : "",
1079*05b00f60SXin Li DNS_CD(flags) ? "%" : "");
1080*05b00f60SXin Li
1081*05b00f60SXin Li /* any weirdness? */
1082*05b00f60SXin Li b2 = GET_BE_U_2(((const u_short *)np) + 1);
1083*05b00f60SXin Li if (b2 & 0x6cf)
1084*05b00f60SXin Li ND_PRINT(" [b2&3=0x%x]", b2);
1085*05b00f60SXin Li
1086*05b00f60SXin Li if (DNS_OPCODE(flags) == IQUERY) {
1087*05b00f60SXin Li if (qdcount)
1088*05b00f60SXin Li ND_PRINT(" [%uq]", qdcount);
1089*05b00f60SXin Li if (ancount != 1)
1090*05b00f60SXin Li ND_PRINT(" [%ua]", ancount);
1091*05b00f60SXin Li }
1092*05b00f60SXin Li else {
1093*05b00f60SXin Li if (ancount)
1094*05b00f60SXin Li ND_PRINT(" [%ua]", ancount);
1095*05b00f60SXin Li if (qdcount != 1)
1096*05b00f60SXin Li ND_PRINT(" [%uq]", qdcount);
1097*05b00f60SXin Li }
1098*05b00f60SXin Li if (nscount)
1099*05b00f60SXin Li ND_PRINT(" [%un]", nscount);
1100*05b00f60SXin Li if (arcount)
1101*05b00f60SXin Li ND_PRINT(" [%uau]", arcount);
1102*05b00f60SXin Li
1103*05b00f60SXin Li cp = (const u_char *)(np + 1);
1104*05b00f60SXin Li if (qdcount) {
1105*05b00f60SXin Li cp = ns_qprint(ndo, cp, (const u_char *)np, is_mdns);
1106*05b00f60SXin Li if (!cp)
1107*05b00f60SXin Li goto trunc;
1108*05b00f60SXin Li qdcount--;
1109*05b00f60SXin Li while (cp < ndo->ndo_snapend && qdcount) {
1110*05b00f60SXin Li cp = ns_qprint(ndo, (const u_char *)cp,
1111*05b00f60SXin Li (const u_char *)np,
1112*05b00f60SXin Li is_mdns);
1113*05b00f60SXin Li if (!cp)
1114*05b00f60SXin Li goto trunc;
1115*05b00f60SXin Li qdcount--;
1116*05b00f60SXin Li }
1117*05b00f60SXin Li }
1118*05b00f60SXin Li if (qdcount)
1119*05b00f60SXin Li goto trunc;
1120*05b00f60SXin Li
1121*05b00f60SXin Li /* Print remaining sections on -vv */
1122*05b00f60SXin Li if (ndo->ndo_vflag > 1) {
1123*05b00f60SXin Li if (ancount) {
1124*05b00f60SXin Li if ((cp = ns_rprint(ndo, cp, bp, is_mdns)) == NULL)
1125*05b00f60SXin Li goto trunc;
1126*05b00f60SXin Li ancount--;
1127*05b00f60SXin Li while (cp < ndo->ndo_snapend && ancount) {
1128*05b00f60SXin Li ND_PRINT(",");
1129*05b00f60SXin Li if ((cp = ns_rprint(ndo, cp, bp, is_mdns)) == NULL)
1130*05b00f60SXin Li goto trunc;
1131*05b00f60SXin Li ancount--;
1132*05b00f60SXin Li }
1133*05b00f60SXin Li }
1134*05b00f60SXin Li if (ancount)
1135*05b00f60SXin Li goto trunc;
1136*05b00f60SXin Li if (cp < ndo->ndo_snapend && nscount) {
1137*05b00f60SXin Li ND_PRINT(" ns:");
1138*05b00f60SXin Li if ((cp = ns_rprint(ndo, cp, bp, is_mdns)) == NULL)
1139*05b00f60SXin Li goto trunc;
1140*05b00f60SXin Li nscount--;
1141*05b00f60SXin Li while (cp < ndo->ndo_snapend && nscount) {
1142*05b00f60SXin Li ND_PRINT(",");
1143*05b00f60SXin Li if ((cp = ns_rprint(ndo, cp, bp, is_mdns)) == NULL)
1144*05b00f60SXin Li goto trunc;
1145*05b00f60SXin Li nscount--;
1146*05b00f60SXin Li }
1147*05b00f60SXin Li }
1148*05b00f60SXin Li if (nscount > 0)
1149*05b00f60SXin Li goto trunc;
1150*05b00f60SXin Li if (cp < ndo->ndo_snapend && arcount) {
1151*05b00f60SXin Li ND_PRINT(" ar:");
1152*05b00f60SXin Li if ((cp = ns_rprint(ndo, cp, bp, is_mdns)) == NULL)
1153*05b00f60SXin Li goto trunc;
1154*05b00f60SXin Li arcount--;
1155*05b00f60SXin Li while (cp < ndo->ndo_snapend && arcount) {
1156*05b00f60SXin Li ND_PRINT(",");
1157*05b00f60SXin Li if ((cp = ns_rprint(ndo, cp, bp, is_mdns)) == NULL)
1158*05b00f60SXin Li goto trunc;
1159*05b00f60SXin Li arcount--;
1160*05b00f60SXin Li }
1161*05b00f60SXin Li }
1162*05b00f60SXin Li if (arcount)
1163*05b00f60SXin Li goto trunc;
1164*05b00f60SXin Li }
1165*05b00f60SXin Li }
1166*05b00f60SXin Li ND_PRINT(" (%u)", length);
1167*05b00f60SXin Li return;
1168*05b00f60SXin Li
1169*05b00f60SXin Li trunc:
1170*05b00f60SXin Li nd_print_trunc(ndo);
1171*05b00f60SXin Li }
1172