tcpdump.c revision 75118
117680Spst/*
239297Sfenner * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
317680Spst *	The Regents of the University of California.  All rights reserved.
417680Spst *
517680Spst * Redistribution and use in source and binary forms, with or without
617680Spst * modification, are permitted provided that: (1) source code distributions
717680Spst * retain the above copyright notice and this paragraph in its entirety, (2)
817680Spst * distributions including binary code include the above copyright notice and
917680Spst * this paragraph in its entirety in the documentation or other materials
1017680Spst * provided with the distribution, and (3) all advertising materials mentioning
1117680Spst * features or use of this software display the following acknowledgement:
1217680Spst * ``This product includes software developed by the University of California,
1317680Spst * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
1417680Spst * the University nor the names of its contributors may be used to endorse
1517680Spst * or promote products derived from this software without specific prior
1617680Spst * written permission.
1717680Spst * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
1817680Spst * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
1917680Spst * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
2017680Spst */
2117680Spst
2217680Spst#ifndef lint
2326180Sfennerstatic const char copyright[] =
2439297Sfenner    "@(#) Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997\n\
2517680SpstThe Regents of the University of California.  All rights reserved.\n";
2626180Sfennerstatic const char rcsid[] =
2775118Sfenner    "@(#) $Header: /tcpdump/master/tcpdump/tcpdump.c,v 1.158 2000/12/21 10:43:24 guy Exp $ (LBL)";
2817680Spst#endif
2917680Spst
3056648Sarchie/* $FreeBSD: head/contrib/tcpdump/tcpdump.c 75118 2001-04-03 07:50:46Z fenner $ */
3156648Sarchie
3217680Spst/*
3317680Spst * tcpdump - monitor tcp/ip traffic on an ethernet.
3417680Spst *
3517680Spst * First written in 1987 by Van Jacobson, Lawrence Berkeley Laboratory.
3617680Spst * Mercilessly hacked and occasionally improved since then via the
3717680Spst * combined efforts of Van, Steve McCanne and Craig Leres of LBL.
3817680Spst */
3917680Spst
4056896Sfenner#ifdef HAVE_CONFIG_H
4156896Sfenner#include "config.h"
4256896Sfenner#endif
4356896Sfenner
4417680Spst#include <sys/types.h>
4517680Spst#include <sys/time.h>
4617680Spst
4717680Spst#include <netinet/in.h>
4817680Spst
4917680Spst#include <pcap.h>
5017680Spst#include <signal.h>
5117680Spst#include <stdio.h>
5217680Spst#include <stdlib.h>
5317680Spst#include <string.h>
5417680Spst#include <unistd.h>
5556896Sfenner#include <ctype.h>
5617680Spst
5756896Sfenner
5817680Spst#include "interface.h"
5917680Spst#include "addrtoname.h"
6017680Spst#include "machdep.h"
6139297Sfenner#include "setsignal.h"
6239297Sfenner#include "gmt2local.h"
6317680Spst
6439297Sfennerint aflag;			/* translate network and broadcast addresses */
6539297Sfennerint dflag;			/* print filter code */
6639297Sfennerint eflag;			/* print ethernet header */
6717680Spstint fflag;			/* don't translate "foreign" IP address */
6817680Spstint nflag;			/* leave addresses as numbers */
6917680Spstint Nflag;			/* remove domains from printed host names */
7039297Sfennerint Oflag = 1;			/* run filter code optimizer */
7117680Spstint pflag;			/* don't go promiscuous */
7217680Spstint qflag;			/* quick (shorter) output */
7356896Sfennerint Rflag = 1;			/* print sequence # field in AH/ESP*/
7456896Sfennerint sflag = 0;			/* use the libsmi to translate OIDs */
7539297Sfennerint Sflag;			/* print raw TCP sequence numbers */
7617680Spstint tflag = 1;			/* print packet arrival time */
7775118Sfennerint uflag = 0;			/* Print undecoded NFS handles */
7817680Spstint vflag;			/* verbose */
7917680Spstint xflag;			/* print packet in hex */
8056896Sfennerint Xflag;			/* print packet in ascii as well as hex */
8139297Sfenner
8256896Sfennerchar *espsecret = NULL;		/* ESP secret key */
8356896Sfenner
8417680Spstint packettype;
8517680Spst
8617680Spst
8717680Spstchar *program_name;
8817680Spst
8917680Spstint32_t thiszone;		/* seconds offset from gmt to local time */
9017680Spst
9117680Spst/* Forwards */
9275118Sfennerstatic RETSIGTYPE cleanup(int);
9375118Sfennerstatic void usage(void) __attribute__((noreturn));
9417680Spst
9517680Spst/* Length of saved portion of packet. */
9617680Spstint snaplen = DEFAULT_SNAPLEN;
9717680Spst
9817680Spststruct printer {
9917680Spst	pcap_handler f;
10017680Spst	int type;
10117680Spst};
10217680Spst
10317680Spststatic struct printer printers[] = {
10417680Spst	{ ether_if_print,	DLT_EN10MB },
10544165Sjulian	{ token_if_print,	DLT_IEEE802 },
10656896Sfenner#ifdef DLT_LANE8023
10756896Sfenner	{ lane_if_print,        DLT_LANE8023 },
10856896Sfenner#endif
10956896Sfenner#ifdef DLT_CIP
11056896Sfenner	{ cip_if_print,         DLT_CIP },
11156896Sfenner#endif
11275118Sfenner#ifdef DLT_ATM_CLIP
11375118Sfenner	{ cip_if_print,         DLT_ATM_CLIP },
11475118Sfenner#endif
11517680Spst	{ sl_if_print,		DLT_SLIP },
11639297Sfenner	{ sl_bsdos_if_print,	DLT_SLIP_BSDOS },
11717680Spst	{ ppp_if_print,		DLT_PPP },
11839297Sfenner	{ ppp_bsdos_if_print,	DLT_PPP_BSDOS },
11917680Spst	{ fddi_if_print,	DLT_FDDI },
12017680Spst	{ null_if_print,	DLT_NULL },
12175118Sfenner#ifdef DLT_LOOP
12275118Sfenner	{ null_if_print,	DLT_LOOP },
12375118Sfenner#endif
12439297Sfenner	{ raw_if_print,		DLT_RAW },
12517680Spst	{ atm_if_print,		DLT_ATM_RFC1483 },
12675118Sfenner#ifdef DLT_C_HDLC
12775118Sfenner	{ chdlc_if_print,	DLT_C_HDLC },
12856896Sfenner#endif
12975118Sfenner#ifdef DLT_PPP_SERIAL
13075118Sfenner	{ ppp_hdlc_if_print,    DLT_PPP_SERIAL },
13175118Sfenner#endif
13275118Sfenner#ifdef DLT_LINUX_SLL
13375118Sfenner	{ sll_if_print,		DLT_LINUX_SLL },
13475118Sfenner#endif
13517680Spst	{ NULL,			0 },
13617680Spst};
13717680Spst
13817680Spststatic pcap_handler
13917680Spstlookup_printer(int type)
14017680Spst{
14117680Spst	struct printer *p;
14217680Spst
14317680Spst	for (p = printers; p->f; ++p)
14417680Spst		if (type == p->type)
14517680Spst			return p->f;
14617680Spst
14775118Sfenner	error("unknown data link type %d", type);
14817680Spst	/* NOTREACHED */
14917680Spst}
15017680Spst
15117680Spststatic pcap_t *pd;
15217680Spst
15317680Spstextern int optind;
15417680Spstextern int opterr;
15517680Spstextern char *optarg;
15617680Spst
15717680Spstint
15817680Spstmain(int argc, char **argv)
15917680Spst{
16017680Spst	register int cnt, op, i;
16117680Spst	bpf_u_int32 localnet, netmask;
16217680Spst	register char *cp, *infile, *cmdbuf, *device, *RFileName, *WFileName;
16317680Spst	pcap_handler printer;
16417680Spst	struct bpf_program fcode;
16539297Sfenner	RETSIGTYPE (*oldhandler)(int);
16617680Spst	u_char *pcap_userdata;
16717680Spst	char ebuf[PCAP_ERRBUF_SIZE];
16817680Spst
16917680Spst	cnt = -1;
17017680Spst	device = NULL;
17117680Spst	infile = NULL;
17217680Spst	RFileName = NULL;
17317680Spst	WFileName = NULL;
17417680Spst	if ((cp = strrchr(argv[0], '/')) != NULL)
17517680Spst		program_name = cp + 1;
17617680Spst	else
17717680Spst		program_name = argv[0];
17817680Spst
17975118Sfenner	if (abort_on_misalignment(ebuf, sizeof(ebuf)) < 0)
18026180Sfenner		error("%s", ebuf);
18117680Spst
18256896Sfenner#ifdef LIBSMI
18356896Sfenner	smiInit("tcpdump");
18456896Sfenner#endif
18556896Sfenner
18617680Spst	opterr = 0;
18739297Sfenner	while (
18875118Sfenner	    (op = getopt(argc, argv, "ac:deE:fF:i:lm:nNOpqr:Rs:StT:uvw:xXY")) != -1)
18917680Spst		switch (op) {
19039297Sfenner
19139297Sfenner		case 'a':
19239297Sfenner			++aflag;
19339297Sfenner			break;
19439297Sfenner
19517680Spst		case 'c':
19617680Spst			cnt = atoi(optarg);
19717680Spst			if (cnt <= 0)
19817680Spst				error("invalid packet count %s", optarg);
19917680Spst			break;
20017680Spst
20117680Spst		case 'd':
20217680Spst			++dflag;
20317680Spst			break;
20417680Spst
20517680Spst		case 'e':
20617680Spst			++eflag;
20717680Spst			break;
20817680Spst
20956896Sfenner		case 'E':
21075118Sfenner#ifndef HAVE_LIBCRYPTO
21156896Sfenner			warning("crypto code not compiled in");
21256896Sfenner#endif
21356896Sfenner			espsecret = optarg;
21456896Sfenner			break;
21556896Sfenner
21617680Spst		case 'f':
21717680Spst			++fflag;
21817680Spst			break;
21917680Spst
22017680Spst		case 'F':
22117680Spst			infile = optarg;
22217680Spst			break;
22317680Spst
22417680Spst		case 'i':
22517680Spst			device = optarg;
22617680Spst			break;
22717680Spst
22817680Spst		case 'l':
22917680Spst#ifdef HAVE_SETLINEBUF
23017680Spst			setlinebuf(stdout);
23117680Spst#else
23217680Spst			setvbuf(stdout, NULL, _IOLBF, 0);
23317680Spst#endif
23417680Spst			break;
23517680Spst
23617680Spst		case 'n':
23717680Spst			++nflag;
23817680Spst			break;
23917680Spst
24017680Spst		case 'N':
24117680Spst			++Nflag;
24217680Spst			break;
24317680Spst
24456896Sfenner		case 'm':
24556896Sfenner#ifdef LIBSMI
24656896Sfenner		        if (smiLoadModule(optarg) == 0) {
24756896Sfenner				error("could not load MIB module %s", optarg);
24856896Sfenner		        }
24956896Sfenner			sflag = 1;
25056896Sfenner#else
25156896Sfenner			(void)fprintf(stderr, "%s: ignoring option `-m %s' ",
25256896Sfenner				      program_name, optarg);
25356896Sfenner			(void)fprintf(stderr, "(no libsmi support)\n");
25456896Sfenner#endif
25556896Sfenner
25617680Spst		case 'O':
25717680Spst			Oflag = 0;
25817680Spst			break;
25917680Spst
26017680Spst		case 'p':
26117680Spst			++pflag;
26217680Spst			break;
26317680Spst
26417680Spst		case 'q':
26517680Spst			++qflag;
26617680Spst			break;
26717680Spst
26817680Spst		case 'r':
26917680Spst			RFileName = optarg;
27017680Spst			break;
27117680Spst
27256896Sfenner		case 'R':
27356896Sfenner			Rflag = 0;
27456896Sfenner			break;
27556896Sfenner
27675118Sfenner		case 's': {
27775118Sfenner			char *end;
27875118Sfenner
27975118Sfenner			snaplen = strtol(optarg, &end, 0);
28075118Sfenner			if (optarg == end || *end != '\0'
28175118Sfenner			    || snaplen < 0 || snaplen > 65535)
28217680Spst				error("invalid snaplen %s", optarg);
28375118Sfenner			else if (snaplen == 0)
28475118Sfenner				snaplen = 65535;
28517680Spst			break;
28675118Sfenner		}
28717680Spst
28817680Spst		case 'S':
28917680Spst			++Sflag;
29017680Spst			break;
29117680Spst
29217680Spst		case 't':
29317680Spst			--tflag;
29417680Spst			break;
29517680Spst
29617680Spst		case 'T':
29717680Spst			if (strcasecmp(optarg, "vat") == 0)
29817680Spst				packettype = PT_VAT;
29917680Spst			else if (strcasecmp(optarg, "wb") == 0)
30017680Spst				packettype = PT_WB;
30117680Spst			else if (strcasecmp(optarg, "rpc") == 0)
30217680Spst				packettype = PT_RPC;
30317680Spst			else if (strcasecmp(optarg, "rtp") == 0)
30417680Spst				packettype = PT_RTP;
30517680Spst			else if (strcasecmp(optarg, "rtcp") == 0)
30617680Spst				packettype = PT_RTCP;
30756896Sfenner			else if (strcasecmp(optarg, "snmp") == 0)
30856896Sfenner				packettype = PT_SNMP;
30975118Sfenner			else if (strcasecmp(optarg, "cnfp") == 0)
31075118Sfenner				packettype = PT_CNFP;
31117680Spst			else
31217680Spst				error("unknown packet type `%s'", optarg);
31317680Spst			break;
31417680Spst
31575118Sfenner		case 'u':
31675118Sfenner			++uflag;
31775118Sfenner			break;
31875118Sfenner
31917680Spst		case 'v':
32017680Spst			++vflag;
32117680Spst			break;
32217680Spst
32317680Spst		case 'w':
32417680Spst			WFileName = optarg;
32517680Spst			break;
32656896Sfenner
32756896Sfenner		case 'x':
32856896Sfenner			++xflag;
32956896Sfenner			break;
33056896Sfenner
33156896Sfenner		case 'X':
33275118Sfenner    		        ++xflag;
33356896Sfenner			++Xflag;
33456896Sfenner			break;
33556896Sfenner
33617680Spst#ifdef YYDEBUG
33717680Spst		case 'Y':
33817680Spst			{
33917680Spst			/* Undocumented flag */
34017680Spst			extern int yydebug;
34117680Spst			yydebug = 1;
34217680Spst			}
34317680Spst			break;
34417680Spst#endif
34517680Spst		default:
34617680Spst			usage();
34717680Spst			/* NOTREACHED */
34817680Spst		}
34917680Spst
35039297Sfenner	if (aflag && nflag)
35139297Sfenner		error("-a and -n options are incompatible");
35239297Sfenner
35317680Spst	if (tflag > 0)
35439297Sfenner		thiszone = gmt2local(0);
35517680Spst
35617680Spst	if (RFileName != NULL) {
35717680Spst		/*
35817680Spst		 * We don't need network access, so set it back to the user id.
35917680Spst		 * Also, this prevents the user from reading anyone's
36017680Spst		 * trace file.
36117680Spst		 */
36217680Spst		setuid(getuid());
36317680Spst
36417680Spst		pd = pcap_open_offline(RFileName, ebuf);
36517680Spst		if (pd == NULL)
36626180Sfenner			error("%s", ebuf);
36717680Spst		localnet = 0;
36817680Spst		netmask = 0;
36917680Spst		if (fflag != 0)
37017680Spst			error("-f and -r options are incompatible");
37117680Spst	} else {
37217680Spst		if (device == NULL) {
37317680Spst			device = pcap_lookupdev(ebuf);
37417680Spst			if (device == NULL)
37526180Sfenner				error("%s", ebuf);
37617680Spst		}
37717680Spst		pd = pcap_open_live(device, snaplen, !pflag, 1000, ebuf);
37817680Spst		if (pd == NULL)
37926180Sfenner			error("%s", ebuf);
38017680Spst		i = pcap_snapshot(pd);
38117680Spst		if (snaplen < i) {
38217680Spst			warning("snaplen raised from %d to %d", snaplen, i);
38317680Spst			snaplen = i;
38417680Spst		}
38539297Sfenner		if (pcap_lookupnet(device, &localnet, &netmask, ebuf) < 0) {
38639297Sfenner			localnet = 0;
38739297Sfenner			netmask = 0;
38839297Sfenner			warning("%s", ebuf);
38939297Sfenner		}
39017680Spst		/*
39117680Spst		 * Let user own process after socket has been opened.
39217680Spst		 */
39317680Spst		setuid(getuid());
39417680Spst	}
39517680Spst	if (infile)
39617680Spst		cmdbuf = read_infile(infile);
39717680Spst	else
39817680Spst		cmdbuf = copy_argv(&argv[optind]);
39917680Spst
40017680Spst	if (pcap_compile(pd, &fcode, cmdbuf, Oflag, netmask) < 0)
40126180Sfenner		error("%s", pcap_geterr(pd));
40217680Spst	if (dflag) {
40317680Spst		bpf_dump(&fcode, dflag);
40417680Spst		exit(0);
40517680Spst	}
40639297Sfenner	init_addrtoname(localnet, netmask);
40717680Spst
40839297Sfenner	(void)setsignal(SIGTERM, cleanup);
40939297Sfenner	(void)setsignal(SIGINT, cleanup);
41039297Sfenner	/* Cooperate with nohup(1) */
41139297Sfenner	if ((oldhandler = setsignal(SIGHUP, cleanup)) != SIG_DFL)
41239297Sfenner		(void)setsignal(SIGHUP, oldhandler);
41317680Spst
41417680Spst	if (pcap_setfilter(pd, &fcode) < 0)
41526180Sfenner		error("%s", pcap_geterr(pd));
41617680Spst	if (WFileName) {
41717680Spst		pcap_dumper_t *p = pcap_dump_open(pd, WFileName);
41817680Spst		if (p == NULL)
41926180Sfenner			error("%s", pcap_geterr(pd));
42017680Spst		printer = pcap_dump;
42117680Spst		pcap_userdata = (u_char *)p;
42217680Spst	} else {
42317680Spst		printer = lookup_printer(pcap_datalink(pd));
42417680Spst		pcap_userdata = 0;
42517680Spst	}
42617680Spst	if (RFileName == NULL) {
42717680Spst		(void)fprintf(stderr, "%s: listening on %s\n",
42817680Spst		    program_name, device);
42917680Spst		(void)fflush(stderr);
43017680Spst	}
43117680Spst	if (pcap_loop(pd, cnt, printer, pcap_userdata) < 0) {
43217680Spst		(void)fprintf(stderr, "%s: pcap_loop: %s\n",
43317680Spst		    program_name, pcap_geterr(pd));
43417680Spst		exit(1);
43517680Spst	}
43617680Spst	pcap_close(pd);
43717680Spst	exit(0);
43817680Spst}
43917680Spst
44017680Spst/* make a clean exit on interrupts */
44175118Sfennerstatic RETSIGTYPE
44217680Spstcleanup(int signo)
44317680Spst{
44417680Spst	struct pcap_stat stat;
44517680Spst
44617680Spst	/* Can't print the summary if reading from a savefile */
44717680Spst	if (pd != NULL && pcap_file(pd) == NULL) {
44817680Spst		(void)fflush(stdout);
44917680Spst		putc('\n', stderr);
45017680Spst		if (pcap_stats(pd, &stat) < 0)
45117680Spst			(void)fprintf(stderr, "pcap_stats: %s\n",
45217680Spst			    pcap_geterr(pd));
45317680Spst		else {
45417680Spst			(void)fprintf(stderr, "%d packets received by filter\n",
45517680Spst			    stat.ps_recv);
45617680Spst			(void)fprintf(stderr, "%d packets dropped by kernel\n",
45717680Spst			    stat.ps_drop);
45817680Spst		}
45917680Spst	}
46017680Spst	exit(0);
46117680Spst}
46217680Spst
46317680Spst/* Like default_print() but data need not be aligned */
46417680Spstvoid
46517680Spstdefault_print_unaligned(register const u_char *cp, register u_int length)
46617680Spst{
46717680Spst	register u_int i, s;
46817680Spst	register int nshorts;
46917680Spst
47056648Sarchie	if (Xflag) {
47156896Sfenner		ascii_print(cp, length);
47256896Sfenner		return;
47317680Spst	}
47456896Sfenner	nshorts = (u_int) length / sizeof(u_short);
47556896Sfenner	i = 0;
47656896Sfenner	while (--nshorts >= 0) {
47756896Sfenner		if ((i++ % 8) == 0)
47856896Sfenner			(void)printf("\n\t\t\t");
47956896Sfenner		s = *cp++;
48056896Sfenner		(void)printf(" %02x%02x", s, *cp++);
48156896Sfenner	}
48256896Sfenner	if (length & 1) {
48356896Sfenner		if ((i % 8) == 0)
48456896Sfenner			(void)printf("\n\t\t\t");
48556896Sfenner		(void)printf(" %02x", *cp);
48656896Sfenner	}
48717680Spst}
48817680Spst
48939297Sfenner/*
49039297Sfenner * By default, print the packet out in hex.
49139297Sfenner */
49217680Spstvoid
49317680Spstdefault_print(register const u_char *bp, register u_int length)
49417680Spst{
49556896Sfenner	default_print_unaligned(bp, length);
49617680Spst}
49717680Spst
49875118Sfennerstatic void
49926180Sfennerusage(void)
50017680Spst{
50117680Spst	extern char version[];
50239297Sfenner	extern char pcap_version[];
50317680Spst
50439297Sfenner	(void)fprintf(stderr, "%s version %s\n", program_name, version);
50539297Sfenner	(void)fprintf(stderr, "libpcap version %s\n", pcap_version);
50617680Spst	(void)fprintf(stderr,
50775118Sfenner"Usage: %s [-adeflnNOpqStuvxX] [-c count] [ -F file ]\n", program_name);
50817680Spst	(void)fprintf(stderr,
50917680Spst"\t\t[ -i interface ] [ -r file ] [ -s snaplen ]\n");
51017680Spst	(void)fprintf(stderr,
51117680Spst"\t\t[ -T type ] [ -w file ] [ expression ]\n");
51217680Spst	exit(-1);
51317680Spst}
514