print-domain.c revision 21262
118334Speter/*
218334Speter * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996
318334Speter *	The Regents of the University of California.  All rights reserved.
418334Speter *
518334Speter * Redistribution and use in source and binary forms, with or without
618334Speter * modification, are permitted provided that: (1) source code distributions
718334Speter * retain the above copyright notice and this paragraph in its entirety, (2)
818334Speter * distributions including binary code include the above copyright notice and
918334Speter * this paragraph in its entirety in the documentation or other materials
1018334Speter * provided with the distribution, and (3) all advertising materials mentioning
1118334Speter * features or use of this software display the following acknowledgement:
1218334Speter * ``This product includes software developed by the University of California,
1318334Speter * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
1418334Speter * the University nor the names of its contributors may be used to endorse
1518334Speter * or promote products derived from this software without specific prior
1618334Speter * written permission.
1718334Speter * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
1818334Speter * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
1918334Speter * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
2018334Speter */
2118334Speter
2218334Speter#ifndef lint
2318334Speterstatic char rcsid[] =
2418334Speter    "@(#) $Header: print-domain.c,v 1.35 96/07/23 14:17:22 leres Exp $ (LBL)";
2518334Speter#endif
2618334Speter
2718334Speter#include <sys/param.h>
2818334Speter#include <sys/time.h>
2918334Speter#include <sys/socket.h>
3018334Speter
3118334Speter#if __STDC__
3218334Speterstruct mbuf;
3318334Speterstruct rtentry;
3418334Speter#endif
3518334Speter#include <net/if.h>
3618334Speter
3718334Speter#include <netinet/in.h>
3818334Speter#include <net/ethernet.h>
3918334Speter#include <netinet/in_systm.h>
4018334Speter#include <netinet/ip.h>
4118334Speter#include <netinet/ip_var.h>
4218334Speter#include <netinet/udp.h>
4318334Speter#include <netinet/udp_var.h>
4418334Speter#include <netinet/tcp.h>
4518334Speter#include <netinet/tcpip.h>
4618334Speter
4718334Speter#undef NOERROR					/* Solaris sucks */
4818334Speter#undef T_UNSPEC					/* SINIX does too */
4918334Speter#include <arpa/nameser.h>
5018334Speter
5118334Speter#include <stdio.h>
5218334Speter
5318334Speter#include "interface.h"
5418334Speter#include "addrtoname.h"
5518334Speter#include "extract.h"                    /* must come after interface.h */
5618334Speter
5718334Speter/* Compatibility */
5818334Speter#ifndef T_TXT
5918334Speter#define T_TXT		16		/* text strings */
6018334Speter#endif
6118334Speter#ifndef T_RP
6218334Speter#define T_RP		17		/* responsible person */
6318334Speter#endif
6418334Speter#ifndef T_AFSDB
6518334Speter#define T_AFSDB		18		/* AFS cell database */
6618334Speter#endif
6718334Speter#ifndef T_X25
6818334Speter#define T_X25		19		/* X_25 calling address */
6918334Speter#endif
7018334Speter#ifndef T_ISDN
7118334Speter#define T_ISDN		20		/* ISDN calling address */
7218334Speter#endif
7318334Speter#ifndef T_RT
7418334Speter#define T_RT		21		/* router */
7518334Speter#endif
7618334Speter#ifndef T_NSAP
7718334Speter#define T_NSAP		22		/* NSAP address */
7818334Speter#endif
7918334Speter#ifndef T_NSAP_PTR
8018334Speter#define T_NSAP_PTR	23		/* reverse NSAP lookup (deprecated) */
8118334Speter#endif
8218334Speter#ifndef T_SIG
8318334Speter#define T_SIG		24		/* security signature */
8418334Speter#endif
8518334Speter#ifndef T_KEY
8618334Speter#define T_KEY		25		/* security key */
8718334Speter#endif
8818334Speter#ifndef T_PX
8918334Speter#define T_PX		26		/* X.400 mail mapping */
9018334Speter#endif
9118334Speter#ifndef T_GPOS
9218334Speter#define T_GPOS		27		/* geographical position (withdrawn) */
9318334Speter#endif
9418334Speter#ifndef T_AAAA
9518334Speter#define T_AAAA		28		/* IP6 Address */
9618334Speter#endif
9718334Speter#ifndef T_LOC
9818334Speter#define T_LOC		29		/* Location Information */
9918334Speter#endif
10018334Speter
10118334Speter#ifndef T_UNSPEC
10218334Speter#define T_UNSPEC	103		/* Unspecified format (binary data) */
10318334Speter#endif
10418334Speter#ifndef T_UNSPECA
10518334Speter#define T_UNSPECA	104		/* "unspecified ascii". Ugly MIT hack */
10618334Speter#endif
10718334Speter
10818334Speter#ifndef C_CHAOS
10918334Speter#define C_CHAOS		3		/* for chaos net (MIT) */
11018334Speter#endif
11118334Speter#ifndef C_HS
11218334Speter#define C_HS		4		/* for Hesiod name server (MIT) (XXX) */
11318334Speter#endif
11418334Speter
11518334Speterstatic char *ns_ops[] = {
11618334Speter	"", " inv_q", " stat", " op3", " notify", " op5", " op6", " op7",
11718334Speter	" op8", " updataA", " updateD", " updateDA",
11818334Speter	" updateM", " updateMA", " zoneInit", " zoneRef",
11918334Speter};
12018334Speter
12118334Speterstatic char *ns_resp[] = {
12218334Speter	"", " FormErr", " ServFail", " NXDomain",
12318334Speter	" NotImp", " Refused", " Resp6", " Resp7",
12418334Speter	" Resp8", " Resp9", " Resp10", " Resp11",
12518334Speter	" Resp12", " Resp13", " Resp14", " NoChange",
12618334Speter};
12718334Speter
12818334Speter/* skip over a domain name */
12918334Speterstatic const u_char *
13018334Speterns_nskip(register const u_char *cp, register const u_char *bp)
13118334Speter{
13218334Speter	register u_char i;
13318334Speter
13418334Speter	if (((i = *cp++) & INDIR_MASK) == INDIR_MASK)
13518334Speter		return (cp + 1);
13618334Speter	while (i && cp < snapend) {
13718334Speter		cp += i;
13818334Speter		i = *cp++;
13918334Speter	}
14018334Speter	return (cp);
14118334Speter}
14218334Speter
14318334Speter/* print a <domain-name> */
14418334Speterstatic const u_char *
14518334Speterns_nprint(register const u_char *cp, register const u_char *bp)
14618334Speter{
14718334Speter	register u_int i;
14818334Speter	register const u_char *rp;
14918334Speter	register int compress;
15018334Speter
15118334Speter	i = *cp++;
15218334Speter	rp = cp + i;
15318334Speter	if ((i & INDIR_MASK) == INDIR_MASK) {
15418334Speter		rp = cp + 1;
15518334Speter		compress = 1;
15618334Speter	} else
15718334Speter		compress = 0;
15818334Speter	if (i != 0)
15918334Speter		while (i && cp < snapend) {
16018334Speter			if ((i & INDIR_MASK) == INDIR_MASK) {
16118334Speter				cp = bp + (((i << 8) | *cp) & 0x3fff);
16218334Speter				i = *cp++;
16318334Speter				continue;
16418334Speter			}
16518334Speter			if (fn_printn(cp, i, snapend))
16618334Speter				break;
16718334Speter			cp += i;
16818334Speter			putchar('.');
16918334Speter			i = *cp++;
17018334Speter			if (!compress)
17118334Speter				rp += i + 1;
17218334Speter		}
17318334Speter	else
17418334Speter		putchar('.');
17518334Speter	return (rp);
17618334Speter}
17718334Speter
17818334Speter/* print a <character-string> */
17918334Speterstatic const u_char *
18018334Speterns_cprint(register const u_char *cp, register const u_char *bp)
18118334Speter{
18218334Speter	register u_int i;
18318334Speter
18418334Speter	i = *cp++;
18518334Speter	(void)fn_printn(cp, i, snapend);
18618334Speter	return (cp + i);
18718334Speter}
18818334Speter
18918334Speterstatic struct tok type2str[] = {
19018334Speter	{ T_A,		"A" },
19118334Speter	{ T_NS,		"NS" },
19218334Speter	{ T_MD,		"MD" },
19318334Speter	{ T_MF,		"MF" },
19418334Speter	{ T_CNAME,	"CNAME" },
19518334Speter	{ T_SOA,	"SOA" },
19618334Speter	{ T_MB,		"MB" },
19718334Speter	{ T_MG,		"MG" },
19818334Speter	{ T_MR,		"MR" },
19918334Speter	{ T_NULL,	"NULL" },
20018334Speter	{ T_WKS,	"WKS" },
20118334Speter	{ T_PTR,	"PTR" },
20218334Speter	{ T_HINFO,	"HINFO" },
20318334Speter	{ T_MINFO,	"MINFO" },
20418334Speter	{ T_MX,		"MX" },
20518334Speter	{ T_TXT,	"TXT" },
20618334Speter	{ T_RP,		"RP" },
20718334Speter	{ T_AFSDB,	"AFSDB" },
20818334Speter	{ T_X25,	"X25" },
20918334Speter	{ T_ISDN,	"ISDN" },
21018334Speter	{ T_RT,		"RT" },
21118334Speter	{ T_NSAP,	"NSAP" },
21218334Speter	{ T_NSAP_PTR,	"NSAP_PTR" },
21318334Speter	{ T_SIG,	"SIG" },
21418334Speter	{ T_KEY,	"KEY" },
21518334Speter	{ T_PX,		"PX" },
21618334Speter	{ T_GPOS,	"GPOS" },
21718334Speter	{ T_AAAA,	"AAAA" },
21818334Speter	{ T_LOC ,	"LOC " },
21918334Speter	{ T_UINFO,	"UINFO" },
22018334Speter	{ T_UID,	"UID" },
22118334Speter	{ T_GID,	"GID" },
22218334Speter	{ T_UNSPEC,	"UNSPEC" },
22318334Speter	{ T_UNSPECA,	"UNSPECA" },
22418334Speter	{ T_AXFR,	"AXFR" },
22518334Speter	{ T_MAILB,	"MAILB" },
22618334Speter	{ T_MAILA,	"MAILA" },
22718334Speter	{ T_ANY,	"ANY" },
22818334Speter	{ 0,		NULL }
22918334Speter};
23018334Speter
23118334Speterstatic struct tok class2str[] = {
23218334Speter	{ C_IN,		"IN" },		/* Not used */
23318334Speter	{ C_CHAOS,	"CHAOS)" },
23418334Speter	{ C_HS,		"HS" },
23518334Speter	{ C_ANY,	"ANY" },
23618334Speter	{ 0,		NULL }
23718334Speter};
23818334Speter
23918334Speter/* print a query */
24018334Speterstatic void
24118334Speterns_qprint(register const u_char *cp, register const u_char *bp)
24218334Speter{
24318334Speter	register const u_char *np = cp;
24418334Speter	register u_int i;
24518334Speter
24618334Speter	cp = ns_nskip(cp, bp);
24718334Speter
24818334Speter	if (cp + 4 > snapend)
24918334Speter		return;
25018334Speter
25118334Speter	/* print the qtype and qclass (if it's not IN) */
25218334Speter	i = *cp++ << 8;
25318334Speter	i |= *cp++;
25418334Speter	printf(" %s", tok2str(type2str, "Type%d", i));
25518334Speter	i = *cp++ << 8;
25618334Speter	i |= *cp++;
25718334Speter	if (i != C_IN)
25818334Speter		printf(" %s", tok2str(class2str, "(Class %d)", i));
25918334Speter
26018334Speter	fputs("? ", stdout);
26118334Speter	ns_nprint(np, bp);
26218334Speter}
26318334Speter
26418334Speter/* print a reply */
26518334Speterstatic const u_char *
26618334Speterns_rprint(register const u_char *cp, register const u_char *bp)
26718334Speter{
26818334Speter	register u_int i;
26918334Speter	register u_short typ, len;
27018334Speter	register const u_char *rp;
27118334Speter
27218334Speter	if (vflag) {
27318334Speter		putchar(' ');
27418334Speter		cp = ns_nprint(cp, bp);
27518334Speter	} else
27618334Speter		cp = ns_nskip(cp, bp);
27718334Speter
27818334Speter	if (cp + 10 > snapend)
27918334Speter		return (snapend);
28018334Speter
28118334Speter	/* print the type/qtype and class (if it's not IN) */
28218334Speter	typ = *cp++ << 8;
28318334Speter	typ |= *cp++;
28418334Speter	i = *cp++ << 8;
28518334Speter	i |= *cp++;
28618334Speter	if (i != C_IN)
28718334Speter		printf(" %s", tok2str(class2str, "(Class %d)", i));
28818334Speter
28918334Speter	/* ignore ttl */
29018334Speter	cp += 4;
29118334Speter
29218334Speter	len = *cp++ << 8;
29318334Speter	len |= *cp++;
29418334Speter
295	rp = cp + len;
296
297	printf(" %s", tok2str(type2str, "Type%d", typ));
298	switch (typ) {
299
300	case T_A:
301		printf(" %s", ipaddr_string(cp));
302		break;
303
304	case T_NS:
305	case T_CNAME:
306	case T_PTR:
307		putchar(' ');
308		(void)ns_nprint(cp, bp);
309		break;
310
311	case T_MX:
312		putchar(' ');
313		(void)ns_nprint(cp + 2, bp);
314		printf(" %d", EXTRACT_16BITS(cp));
315		break;
316
317	case T_TXT:
318		putchar(' ');
319		(void)ns_cprint(cp, bp);
320		break;
321
322	case T_UNSPECA:		/* One long string */
323	        printf(" %.*s", len, cp);
324		break;
325	}
326	return (rp);		/* XXX This isn't always right*/
327}
328
329void
330ns_print(register const u_char *bp, u_int length)
331{
332	register const HEADER *np;
333	register int qdcount, ancount, nscount, arcount;
334	register const u_char *cp;
335
336	np = (const HEADER *)bp;
337	/* get the byte-order right */
338	qdcount = ntohs(np->qdcount);
339	ancount = ntohs(np->ancount);
340	nscount = ntohs(np->nscount);
341	arcount = ntohs(np->arcount);
342
343	if (np->qr) {
344		/* this is a response */
345		printf(" %d%s%s%s%s%s",
346			ntohs(np->id),
347			ns_ops[np->opcode],
348			ns_resp[np->rcode],
349			np->aa? "*" : "",
350			np->ra? "" : "-",
351			np->tc? "|" : "");
352		if (qdcount != 1)
353			printf(" [%dq]", qdcount);
354		/* Print QUESTION section on -vv */
355		if (vflag > 1) {
356		            fputs(" q: ", stdout);
357			    cp = ns_nprint((const u_char *)(np + 1), bp);
358		} else
359			    cp = ns_nskip((const u_char *)(np + 1), bp);
360		printf(" %d/%d/%d", ancount, nscount, arcount);
361		if (ancount--) {
362			cp = ns_rprint(cp + 4, bp);
363			while (ancount-- && cp < snapend) {
364				putchar(',');
365				cp = ns_rprint(cp, bp);
366			}
367		}
368	}
369	else {
370		/* this is a request */
371		printf(" %d%s%s",
372		        ntohs(np->id),
373			ns_ops[np->opcode],
374			np->rd? "+" : "");
375
376		/* any weirdness? */
377		if (*(((u_short *)np)+1) & htons(0x6ff))
378			printf(" [b2&3=0x%x]", ntohs(*(((u_short *)np)+1)));
379
380		if (np->opcode == IQUERY) {
381			if (qdcount)
382				printf(" [%dq]", qdcount);
383			if (ancount != 1)
384				printf(" [%da]", ancount);
385		}
386		else {
387			if (ancount)
388				printf(" [%da]", ancount);
389			if (qdcount != 1)
390				printf(" [%dq]", qdcount);
391		}
392		if (nscount)
393			printf(" [%dn]", nscount);
394		if (arcount)
395			printf(" [%dau]", arcount);
396
397		ns_qprint((const u_char *)(np + 1), (const u_char *)np);
398	}
399	printf(" (%d)", length);
400}
401