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