print-domain.c revision 56896
16059Samurai/*
26059Samurai * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
36059Samurai *	The Regents of the University of California.  All rights reserved.
46059Samurai *
56059Samurai * Redistribution and use in source and binary forms, with or without
66059Samurai * modification, are permitted provided that: (1) source code distributions
76059Samurai * retain the above copyright notice and this paragraph in its entirety, (2)
86059Samurai * distributions including binary code include the above copyright notice and
96059Samurai * this paragraph in its entirety in the documentation or other materials
106059Samurai * provided with the distribution, and (3) all advertising materials mentioning
116059Samurai * features or use of this software display the following acknowledgement:
126059Samurai * ``This product includes software developed by the University of California,
136059Samurai * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
146059Samurai * the University nor the names of its contributors may be used to endorse
156059Samurai * or promote products derived from this software without specific prior
166059Samurai * written permission.
176059Samurai * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
186059Samurai * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
198857Srgrimes * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
2028679Sbrian *
218857Srgrimes * $FreeBSD: head/contrib/tcpdump/print-domain.c 56896 2000-01-30 01:05:24Z fenner $
226059Samurai */
236059Samurai
246059Samurai#ifndef lint
256059Samuraistatic const char rcsid[] =
266059Samurai    "@(#) $Header: /tcpdump/master/tcpdump/print-domain.c,v 1.42 1999/11/21 09:36:50 fenner Exp $ (LBL)";
276059Samurai#endif
286059Samurai
296059Samurai#ifdef HAVE_CONFIG_H
3026142Sbrian#include "config.h"
316059Samurai#endif
3213389Sphk
338857Srgrimes#include <sys/param.h>
346059Samurai#include <sys/time.h>
356059Samurai#include <sys/socket.h>
3626516Sbrian
3728679Sbrian#if __STDC__
3828679Sbrianstruct mbuf;
3928679Sbrianstruct rtentry;
4026516Sbrian#endif
4126516Sbrian#include <net/if.h>
4226516Sbrian
4326516Sbrian#include <netinet/in.h>
4426516Sbrian#include <net/ethernet.h>
456059Samurai#include <netinet/in_systm.h>
466059Samurai#include <netinet/ip.h>
476059Samurai#include <netinet/ip_var.h>
486059Samurai#include <netinet/udp.h>
496059Samurai#include <netinet/udp_var.h>
506059Samurai#include <netinet/tcp.h>
516059Samurai
526059Samurai#ifdef NOERROR
536059Samurai#undef NOERROR					/* Solaris sucks */
546059Samurai#endif
556059Samurai#ifdef NOERROR
5628679Sbrian#undef T_UNSPEC					/* SINIX does too */
5728679Sbrian#endif
5828461Sbrian#include <arpa/nameser.h>
596059Samurai
606059Samurai#include <stdio.h>
616059Samurai#include <string.h>
626059Samurai
636059Samurai#include "interface.h"
646059Samurai#include "addrtoname.h"
656059Samurai#include "extract.h"                    /* must come after interface.h */
666059Samurai
676059Samurai/* Compatibility */
686059Samurai#ifndef T_TXT
696059Samurai#define T_TXT		16		/* text strings */
706059Samurai#endif
7113760Sphk#ifndef T_RP
7228679Sbrian#define T_RP		17		/* responsible person */
7328679Sbrian#endif
7428679Sbrian#ifndef T_AFSDB
7528679Sbrian#define T_AFSDB		18		/* AFS cell database */
7628679Sbrian#endif
7728679Sbrian#ifndef T_X25
786059Samurai#define T_X25		19		/* X_25 calling address */
796059Samurai#endif
8025630Sbrian#ifndef T_ISDN
816059Samurai#define T_ISDN		20		/* ISDN calling address */
826059Samurai#endif
836059Samurai#ifndef T_RT
846059Samurai#define T_RT		21		/* router */
856059Samurai#endif
8626516Sbrian#ifndef T_NSAP
8726516Sbrian#define T_NSAP		22		/* NSAP address */
8826516Sbrian#endif
8926516Sbrian#ifndef T_NSAP_PTR
9026516Sbrian#define T_NSAP_PTR	23		/* reverse NSAP lookup (deprecated) */
9126516Sbrian#endif
9226516Sbrian#ifndef T_SIG
9325630Sbrian#define T_SIG		24		/* security signature */
946059Samurai#endif
956059Samurai#ifndef T_KEY
966059Samurai#define T_KEY		25		/* security key */
976059Samurai#endif
986059Samurai#ifndef T_PX
996059Samurai#define T_PX		26		/* X.400 mail mapping */
1006059Samurai#endif
1016059Samurai#ifndef T_GPOS
1026059Samurai#define T_GPOS		27		/* geographical position (withdrawn) */
1036059Samurai#endif
1046059Samurai#ifndef T_AAAA
1056059Samurai#define T_AAAA		28		/* IP6 Address */
1066059Samurai#endif
1076059Samurai#ifndef T_LOC
1086059Samurai#define T_LOC		29		/* Location Information */
10928679Sbrian#endif
1106059Samurai#ifndef T_NXT
1116735Samurai#define T_NXT		30		/* Next Valid Name in Zone */
1126059Samurai#endif
1136059Samurai#ifndef T_EID
1146059Samurai#define T_EID		31		/* Endpoint identifier */
1156059Samurai#endif
11628679Sbrian#ifndef T_NIMLOC
1176059Samurai#define T_NIMLOC	32		/* Nimrod locator */
1186059Samurai#endif
1196059Samurai#ifndef T_SRV
1206059Samurai#define T_SRV		33		/* Server selection */
1216059Samurai#endif
12228461Sbrian#ifndef T_ATMA
1236059Samurai#define T_ATMA		34		/* ATM Address */
12428679Sbrian#endif
12528679Sbrian#ifndef T_NAPTR
1266059Samurai#define T_NAPTR		35		/* Naming Authority PoinTeR */
1276059Samurai#endif
1286059Samurai#ifndef T_A6
1296059Samurai#define T_A6		38		/* IP6 address (ipngwg-dns-lookups) */
1306059Samurai#endif
13128679Sbrian
1326059Samurai#ifndef T_UNSPEC
13328679Sbrian#define T_UNSPEC	103		/* Unspecified format (binary data) */
13428461Sbrian#endif
1356059Samurai#ifndef T_UNSPECA
1366059Samurai#define T_UNSPECA	104		/* "unspecified ascii". Ugly MIT hack */
1376059Samurai#endif
1386059Samurai
13928679Sbrian#ifndef C_CHAOS
1406059Samurai#define C_CHAOS		3		/* for chaos net (MIT) */
1416059Samurai#endif
1426059Samurai#ifndef C_HS
1436059Samurai#define C_HS		4		/* for Hesiod name server (MIT) (XXX) */
1446059Samurai#endif
14528679Sbrian
1466059Samuraistatic char *ns_ops[] = {
14728461Sbrian	"", " inv_q", " stat", " op3", " notify", " op5", " op6", " op7",
1486059Samurai	" op8", " updataA", " updateD", " updateDA",
1496059Samurai	" updateM", " updateMA", " zoneInit", " zoneRef",
1506059Samurai};
1516059Samurai
15228679Sbrianstatic char *ns_resp[] = {
1536059Samurai	"", " FormErr", " ServFail", " NXDomain",
15428679Sbrian	" NotImp", " Refused", " Resp6", " Resp7",
1556059Samurai	" Resp8", " Resp9", " Resp10", " Resp11",
1566059Samurai	" Resp12", " Resp13", " Resp14", " NoChange",
1576059Samurai};
15828679Sbrian
1596059Samurai/* skip over a domain name */
16028461Sbrianstatic const u_char *
1616059Samurains_nskip(register const u_char *cp, register const u_char *bp)
1626059Samurai{
1636059Samurai	register u_char i;
16428679Sbrian
1656059Samurai	if (((i = *cp++) & INDIR_MASK) == INDIR_MASK)
16628461Sbrian		return (cp + 1);
1676059Samurai	while (i && cp < snapend) {
1686059Samurai		cp += i;
1696059Samurai		i = *cp++;
17028679Sbrian	}
1716059Samurai	return (cp);
17228461Sbrian}
1736059Samurai
1746059Samurai/* print a <domain-name> */
1756059Samuraistatic const u_char *
1766059Samurains_nprint(register const u_char *cp, register const u_char *bp)
1776059Samurai{
1786059Samurai	register u_int i;
17928679Sbrian	register const u_char *rp;
1806059Samurai	register int compress;
18128461Sbrian
18228461Sbrian	i = *cp++;
18328679Sbrian	rp = cp + i;
18428679Sbrian	if ((i & INDIR_MASK) == INDIR_MASK) {
1856059Samurai		rp = cp + 1;
1866059Samurai		compress = 1;
1876059Samurai	} else
1886059Samurai		compress = 0;
1896059Samurai	if (i != 0)
1906059Samurai		while (i && cp < snapend) {
19128461Sbrian			if ((i & INDIR_MASK) == INDIR_MASK) {
1926059Samurai				cp = bp + (((i << 8) | *cp) & 0x3fff);
1936059Samurai				i = *cp++;
1946059Samurai				continue;
1956059Samurai			}
1966059Samurai			if (fn_printn(cp, i, snapend))
1976059Samurai				break;
1986059Samurai			cp += i;
1996059Samurai			putchar('.');
2006059Samurai			i = *cp++;
2016059Samurai			if (!compress)
20228679Sbrian				rp += i + 1;
2036059Samurai		}
2046735Samurai	else
2056059Samurai		putchar('.');
2066059Samurai	return (rp);
2076059Samurai}
2086059Samurai
2096059Samurai/* print a <character-string> */
2106059Samuraistatic const u_char *
2116059Samurains_cprint(register const u_char *cp, register const u_char *bp)
2126059Samurai{
2136059Samurai	register u_int i;
2146059Samurai
2156059Samurai	i = *cp++;
2166059Samurai	(void)fn_printn(cp, i, snapend);
21721488Simp	return (cp + i);
2186059Samurai}
21921488Simp
2206059Samuraistatic struct tok type2str[] = {
22128461Sbrian	{ T_A,		"A" },
2226059Samurai	{ T_NS,		"NS" },
2236059Samurai	{ T_MD,		"MD" },
2246059Samurai	{ T_MF,		"MF" },
2256059Samurai	{ T_CNAME,	"CNAME" },
2266059Samurai	{ T_SOA,	"SOA" },
2276059Samurai	{ T_MB,		"MB" },
2286059Samurai	{ T_MG,		"MG" },
2296059Samurai	{ T_MR,		"MR" },
2306059Samurai	{ T_NULL,	"NULL" },
2316059Samurai	{ T_WKS,	"WKS" },
2326059Samurai	{ T_PTR,	"PTR" },
2336059Samurai	{ T_HINFO,	"HINFO" },
2346059Samurai	{ T_MINFO,	"MINFO" },
2356059Samurai	{ T_MX,		"MX" },
2366059Samurai	{ T_TXT,	"TXT" },
2376059Samurai	{ T_RP,		"RP" },
2386059Samurai	{ T_AFSDB,	"AFSDB" },
2396059Samurai	{ T_X25,	"X25" },
2406059Samurai	{ T_ISDN,	"ISDN" },
2416059Samurai	{ T_RT,		"RT" },
2426059Samurai	{ T_NSAP,	"NSAP" },
2436059Samurai	{ T_NSAP_PTR,	"NSAP_PTR" },
2446059Samurai	{ T_SIG,	"SIG" },
2456059Samurai	{ T_KEY,	"KEY" },
2466059Samurai	{ T_PX,		"PX" },
2476059Samurai	{ T_GPOS,	"GPOS" },
2486059Samurai	{ T_AAAA,	"AAAA" },
2496059Samurai	{ T_LOC,	"LOC " },
2506059Samurai	{ T_NXT,	"NXT " },
2516059Samurai	{ T_EID,	"EID " },
2526059Samurai	{ T_NIMLOC,	"NIMLOC " },
2536059Samurai	{ T_SRV,	"SRV " },
2546059Samurai	{ T_ATMA,	"ATMA " },
2556059Samurai	{ T_NAPTR,	"NAPTR " },
25628679Sbrian	{ T_A6,		"A6 " },
2576059Samurai#ifndef T_UINFO
2586059Samurai#define T_UINFO 100
2596059Samurai#endif
2606059Samurai	{ T_UINFO,	"UINFO" },
26126516Sbrian#ifndef T_UID
2626059Samurai#define T_UID 101
2636059Samurai#endif
2646059Samurai	{ T_UID,	"UID" },
265#ifndef T_GID
266#define T_GID 102
267#endif
268	{ T_GID,	"GID" },
269	{ T_UNSPEC,	"UNSPEC" },
270	{ T_UNSPECA,	"UNSPECA" },
271	{ T_AXFR,	"AXFR" },
272	{ T_MAILB,	"MAILB" },
273	{ T_MAILA,	"MAILA" },
274	{ T_ANY,	"ANY" },
275	{ 0,		NULL }
276};
277
278static struct tok class2str[] = {
279	{ C_IN,		"IN" },		/* Not used */
280	{ C_CHAOS,	"CHAOS)" },
281	{ C_HS,		"HS" },
282	{ C_ANY,	"ANY" },
283	{ 0,		NULL }
284};
285
286/* print a query */
287static void
288ns_qprint(register const u_char *cp, register const u_char *bp)
289{
290	register const u_char *np = cp;
291	register u_int i;
292
293	cp = ns_nskip(cp, bp);
294
295	if (cp + 4 > snapend)
296		return;
297
298	/* print the qtype and qclass (if it's not IN) */
299	i = *cp++ << 8;
300	i |= *cp++;
301	printf(" %s", tok2str(type2str, "Type%d", i));
302	i = *cp++ << 8;
303	i |= *cp++;
304	if (i != C_IN)
305		printf(" %s", tok2str(class2str, "(Class %d)", i));
306
307	fputs("? ", stdout);
308	ns_nprint(np, bp);
309}
310
311/* print a reply */
312static const u_char *
313ns_rprint(register const u_char *cp, register const u_char *bp)
314{
315	register u_int i;
316	register u_short typ, len;
317	register const u_char *rp;
318
319	if (vflag) {
320		putchar(' ');
321		cp = ns_nprint(cp, bp);
322	} else
323		cp = ns_nskip(cp, bp);
324
325	if (cp + 10 > snapend)
326		return (snapend);
327
328	/* print the type/qtype and class (if it's not IN) */
329	typ = *cp++ << 8;
330	typ |= *cp++;
331	i = *cp++ << 8;
332	i |= *cp++;
333	if (i != C_IN)
334		printf(" %s", tok2str(class2str, "(Class %d)", i));
335
336	/* ignore ttl */
337	cp += 4;
338
339	len = *cp++ << 8;
340	len |= *cp++;
341
342	rp = cp + len;
343
344	printf(" %s", tok2str(type2str, "Type%d", typ));
345	switch (typ) {
346
347	case T_A:
348		printf(" %s", ipaddr_string(cp));
349		break;
350
351	case T_NS:
352	case T_CNAME:
353	case T_PTR:
354#ifdef T_DNAME
355	case T_DNAME:	/*XXX not checked as there's no server support yet*/
356#endif
357		putchar(' ');
358		(void)ns_nprint(cp, bp);
359		break;
360
361	case T_MX:
362		putchar(' ');
363		(void)ns_nprint(cp + 2, bp);
364		printf(" %d", EXTRACT_16BITS(cp));
365		break;
366
367	case T_TXT:
368		putchar(' ');
369		(void)ns_cprint(cp, bp);
370		break;
371
372#ifdef INET6
373	case T_AAAA:
374		printf(" %s", ip6addr_string(cp));
375		break;
376
377	case T_A6:	/*XXX not checked as there's no server support yet*/
378	    {
379		struct in6_addr a;
380		int pbyte;
381
382		pbyte = (*cp + 7) / 8;
383		memset(&a, 0, sizeof(a));
384		memcpy(&a, cp + 1, pbyte);
385		printf(" %u %s ", *cp, ip6addr_string(&a));
386		(void)ns_nprint(cp + 1 + pbyte, bp);
387		break;
388	    }
389#endif /*INET6*/
390
391	case T_UNSPECA:		/* One long string */
392	        printf(" %.*s", len, cp);
393		break;
394	}
395	return (rp);		/* XXX This isn't always right */
396}
397
398void
399ns_print(register const u_char *bp, u_int length)
400{
401	register const HEADER *np;
402	register int qdcount, ancount, nscount, arcount;
403	register const u_char *cp;
404
405	np = (const HEADER *)bp;
406	/* get the byte-order right */
407	qdcount = ntohs(np->qdcount);
408	ancount = ntohs(np->ancount);
409	nscount = ntohs(np->nscount);
410	arcount = ntohs(np->arcount);
411
412	if (np->qr) {
413		/* this is a response */
414		printf(" %d%s%s%s%s%s",
415			ntohs(np->id),
416			ns_ops[np->opcode],
417			ns_resp[np->rcode],
418			np->aa? "*" : "",
419			np->ra? "" : "-",
420			np->tc? "|" : "");
421		if (qdcount != 1)
422			printf(" [%dq]", qdcount);
423		/* Print QUESTION section on -vv */
424		if (vflag > 1) {
425		            fputs(" q: ", stdout);
426			    cp = ns_nprint((const u_char *)(np + 1), bp);
427		} else
428			    cp = ns_nskip((const u_char *)(np + 1), bp);
429		printf(" %d/%d/%d", ancount, nscount, arcount);
430		if (ancount--) {
431			cp = ns_rprint(cp + 4, bp);
432			while (ancount-- && cp < snapend) {
433				putchar(',');
434				cp = ns_rprint(cp, bp);
435			}
436		}
437	}
438	else {
439		/* this is a request */
440		printf(" %d%s%s",
441		        ntohs(np->id),
442			ns_ops[np->opcode],
443			np->rd? "+" : "");
444
445		/* any weirdness? */
446		if (*(((u_short *)np)+1) & htons(0x6ff))
447			printf(" [b2&3=0x%x]", ntohs(*(((u_short *)np)+1)));
448
449		if (np->opcode == IQUERY) {
450			if (qdcount)
451				printf(" [%dq]", qdcount);
452			if (ancount != 1)
453				printf(" [%da]", ancount);
454		}
455		else {
456			if (ancount)
457				printf(" [%da]", ancount);
458			if (qdcount != 1)
459				printf(" [%dq]", qdcount);
460		}
461		if (nscount)
462			printf(" [%dn]", nscount);
463		if (arcount)
464			printf(" [%dau]", arcount);
465
466		ns_qprint((const u_char *)(np + 1), (const u_char *)np);
467	}
468	printf(" (%d)", length);
469}
470