tcpdump.c revision 75118
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 copyright[] =
24    "@(#) Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997\n\
25The Regents of the University of California.  All rights reserved.\n";
26static const char rcsid[] =
27    "@(#) $Header: /tcpdump/master/tcpdump/tcpdump.c,v 1.158 2000/12/21 10:43:24 guy Exp $ (LBL)";
28#endif
29
30/* $FreeBSD: head/contrib/tcpdump/tcpdump.c 75118 2001-04-03 07:50:46Z fenner $ */
31
32/*
33 * tcpdump - monitor tcp/ip traffic on an ethernet.
34 *
35 * First written in 1987 by Van Jacobson, Lawrence Berkeley Laboratory.
36 * Mercilessly hacked and occasionally improved since then via the
37 * combined efforts of Van, Steve McCanne and Craig Leres of LBL.
38 */
39
40#ifdef HAVE_CONFIG_H
41#include "config.h"
42#endif
43
44#include <sys/types.h>
45#include <sys/time.h>
46
47#include <netinet/in.h>
48
49#include <pcap.h>
50#include <signal.h>
51#include <stdio.h>
52#include <stdlib.h>
53#include <string.h>
54#include <unistd.h>
55#include <ctype.h>
56
57
58#include "interface.h"
59#include "addrtoname.h"
60#include "machdep.h"
61#include "setsignal.h"
62#include "gmt2local.h"
63
64int aflag;			/* translate network and broadcast addresses */
65int dflag;			/* print filter code */
66int eflag;			/* print ethernet header */
67int fflag;			/* don't translate "foreign" IP address */
68int nflag;			/* leave addresses as numbers */
69int Nflag;			/* remove domains from printed host names */
70int Oflag = 1;			/* run filter code optimizer */
71int pflag;			/* don't go promiscuous */
72int qflag;			/* quick (shorter) output */
73int Rflag = 1;			/* print sequence # field in AH/ESP*/
74int sflag = 0;			/* use the libsmi to translate OIDs */
75int Sflag;			/* print raw TCP sequence numbers */
76int tflag = 1;			/* print packet arrival time */
77int uflag = 0;			/* Print undecoded NFS handles */
78int vflag;			/* verbose */
79int xflag;			/* print packet in hex */
80int Xflag;			/* print packet in ascii as well as hex */
81
82char *espsecret = NULL;		/* ESP secret key */
83
84int packettype;
85
86
87char *program_name;
88
89int32_t thiszone;		/* seconds offset from gmt to local time */
90
91/* Forwards */
92static RETSIGTYPE cleanup(int);
93static void usage(void) __attribute__((noreturn));
94
95/* Length of saved portion of packet. */
96int snaplen = DEFAULT_SNAPLEN;
97
98struct printer {
99	pcap_handler f;
100	int type;
101};
102
103static struct printer printers[] = {
104	{ ether_if_print,	DLT_EN10MB },
105	{ token_if_print,	DLT_IEEE802 },
106#ifdef DLT_LANE8023
107	{ lane_if_print,        DLT_LANE8023 },
108#endif
109#ifdef DLT_CIP
110	{ cip_if_print,         DLT_CIP },
111#endif
112#ifdef DLT_ATM_CLIP
113	{ cip_if_print,         DLT_ATM_CLIP },
114#endif
115	{ sl_if_print,		DLT_SLIP },
116	{ sl_bsdos_if_print,	DLT_SLIP_BSDOS },
117	{ ppp_if_print,		DLT_PPP },
118	{ ppp_bsdos_if_print,	DLT_PPP_BSDOS },
119	{ fddi_if_print,	DLT_FDDI },
120	{ null_if_print,	DLT_NULL },
121#ifdef DLT_LOOP
122	{ null_if_print,	DLT_LOOP },
123#endif
124	{ raw_if_print,		DLT_RAW },
125	{ atm_if_print,		DLT_ATM_RFC1483 },
126#ifdef DLT_C_HDLC
127	{ chdlc_if_print,	DLT_C_HDLC },
128#endif
129#ifdef DLT_PPP_SERIAL
130	{ ppp_hdlc_if_print,    DLT_PPP_SERIAL },
131#endif
132#ifdef DLT_LINUX_SLL
133	{ sll_if_print,		DLT_LINUX_SLL },
134#endif
135	{ NULL,			0 },
136};
137
138static pcap_handler
139lookup_printer(int type)
140{
141	struct printer *p;
142
143	for (p = printers; p->f; ++p)
144		if (type == p->type)
145			return p->f;
146
147	error("unknown data link type %d", type);
148	/* NOTREACHED */
149}
150
151static pcap_t *pd;
152
153extern int optind;
154extern int opterr;
155extern char *optarg;
156
157int
158main(int argc, char **argv)
159{
160	register int cnt, op, i;
161	bpf_u_int32 localnet, netmask;
162	register char *cp, *infile, *cmdbuf, *device, *RFileName, *WFileName;
163	pcap_handler printer;
164	struct bpf_program fcode;
165	RETSIGTYPE (*oldhandler)(int);
166	u_char *pcap_userdata;
167	char ebuf[PCAP_ERRBUF_SIZE];
168
169	cnt = -1;
170	device = NULL;
171	infile = NULL;
172	RFileName = NULL;
173	WFileName = NULL;
174	if ((cp = strrchr(argv[0], '/')) != NULL)
175		program_name = cp + 1;
176	else
177		program_name = argv[0];
178
179	if (abort_on_misalignment(ebuf, sizeof(ebuf)) < 0)
180		error("%s", ebuf);
181
182#ifdef LIBSMI
183	smiInit("tcpdump");
184#endif
185
186	opterr = 0;
187	while (
188	    (op = getopt(argc, argv, "ac:deE:fF:i:lm:nNOpqr:Rs:StT:uvw:xXY")) != -1)
189		switch (op) {
190
191		case 'a':
192			++aflag;
193			break;
194
195		case 'c':
196			cnt = atoi(optarg);
197			if (cnt <= 0)
198				error("invalid packet count %s", optarg);
199			break;
200
201		case 'd':
202			++dflag;
203			break;
204
205		case 'e':
206			++eflag;
207			break;
208
209		case 'E':
210#ifndef HAVE_LIBCRYPTO
211			warning("crypto code not compiled in");
212#endif
213			espsecret = optarg;
214			break;
215
216		case 'f':
217			++fflag;
218			break;
219
220		case 'F':
221			infile = optarg;
222			break;
223
224		case 'i':
225			device = optarg;
226			break;
227
228		case 'l':
229#ifdef HAVE_SETLINEBUF
230			setlinebuf(stdout);
231#else
232			setvbuf(stdout, NULL, _IOLBF, 0);
233#endif
234			break;
235
236		case 'n':
237			++nflag;
238			break;
239
240		case 'N':
241			++Nflag;
242			break;
243
244		case 'm':
245#ifdef LIBSMI
246		        if (smiLoadModule(optarg) == 0) {
247				error("could not load MIB module %s", optarg);
248		        }
249			sflag = 1;
250#else
251			(void)fprintf(stderr, "%s: ignoring option `-m %s' ",
252				      program_name, optarg);
253			(void)fprintf(stderr, "(no libsmi support)\n");
254#endif
255
256		case 'O':
257			Oflag = 0;
258			break;
259
260		case 'p':
261			++pflag;
262			break;
263
264		case 'q':
265			++qflag;
266			break;
267
268		case 'r':
269			RFileName = optarg;
270			break;
271
272		case 'R':
273			Rflag = 0;
274			break;
275
276		case 's': {
277			char *end;
278
279			snaplen = strtol(optarg, &end, 0);
280			if (optarg == end || *end != '\0'
281			    || snaplen < 0 || snaplen > 65535)
282				error("invalid snaplen %s", optarg);
283			else if (snaplen == 0)
284				snaplen = 65535;
285			break;
286		}
287
288		case 'S':
289			++Sflag;
290			break;
291
292		case 't':
293			--tflag;
294			break;
295
296		case 'T':
297			if (strcasecmp(optarg, "vat") == 0)
298				packettype = PT_VAT;
299			else if (strcasecmp(optarg, "wb") == 0)
300				packettype = PT_WB;
301			else if (strcasecmp(optarg, "rpc") == 0)
302				packettype = PT_RPC;
303			else if (strcasecmp(optarg, "rtp") == 0)
304				packettype = PT_RTP;
305			else if (strcasecmp(optarg, "rtcp") == 0)
306				packettype = PT_RTCP;
307			else if (strcasecmp(optarg, "snmp") == 0)
308				packettype = PT_SNMP;
309			else if (strcasecmp(optarg, "cnfp") == 0)
310				packettype = PT_CNFP;
311			else
312				error("unknown packet type `%s'", optarg);
313			break;
314
315		case 'u':
316			++uflag;
317			break;
318
319		case 'v':
320			++vflag;
321			break;
322
323		case 'w':
324			WFileName = optarg;
325			break;
326
327		case 'x':
328			++xflag;
329			break;
330
331		case 'X':
332    		        ++xflag;
333			++Xflag;
334			break;
335
336#ifdef YYDEBUG
337		case 'Y':
338			{
339			/* Undocumented flag */
340			extern int yydebug;
341			yydebug = 1;
342			}
343			break;
344#endif
345		default:
346			usage();
347			/* NOTREACHED */
348		}
349
350	if (aflag && nflag)
351		error("-a and -n options are incompatible");
352
353	if (tflag > 0)
354		thiszone = gmt2local(0);
355
356	if (RFileName != NULL) {
357		/*
358		 * We don't need network access, so set it back to the user id.
359		 * Also, this prevents the user from reading anyone's
360		 * trace file.
361		 */
362		setuid(getuid());
363
364		pd = pcap_open_offline(RFileName, ebuf);
365		if (pd == NULL)
366			error("%s", ebuf);
367		localnet = 0;
368		netmask = 0;
369		if (fflag != 0)
370			error("-f and -r options are incompatible");
371	} else {
372		if (device == NULL) {
373			device = pcap_lookupdev(ebuf);
374			if (device == NULL)
375				error("%s", ebuf);
376		}
377		pd = pcap_open_live(device, snaplen, !pflag, 1000, ebuf);
378		if (pd == NULL)
379			error("%s", ebuf);
380		i = pcap_snapshot(pd);
381		if (snaplen < i) {
382			warning("snaplen raised from %d to %d", snaplen, i);
383			snaplen = i;
384		}
385		if (pcap_lookupnet(device, &localnet, &netmask, ebuf) < 0) {
386			localnet = 0;
387			netmask = 0;
388			warning("%s", ebuf);
389		}
390		/*
391		 * Let user own process after socket has been opened.
392		 */
393		setuid(getuid());
394	}
395	if (infile)
396		cmdbuf = read_infile(infile);
397	else
398		cmdbuf = copy_argv(&argv[optind]);
399
400	if (pcap_compile(pd, &fcode, cmdbuf, Oflag, netmask) < 0)
401		error("%s", pcap_geterr(pd));
402	if (dflag) {
403		bpf_dump(&fcode, dflag);
404		exit(0);
405	}
406	init_addrtoname(localnet, netmask);
407
408	(void)setsignal(SIGTERM, cleanup);
409	(void)setsignal(SIGINT, cleanup);
410	/* Cooperate with nohup(1) */
411	if ((oldhandler = setsignal(SIGHUP, cleanup)) != SIG_DFL)
412		(void)setsignal(SIGHUP, oldhandler);
413
414	if (pcap_setfilter(pd, &fcode) < 0)
415		error("%s", pcap_geterr(pd));
416	if (WFileName) {
417		pcap_dumper_t *p = pcap_dump_open(pd, WFileName);
418		if (p == NULL)
419			error("%s", pcap_geterr(pd));
420		printer = pcap_dump;
421		pcap_userdata = (u_char *)p;
422	} else {
423		printer = lookup_printer(pcap_datalink(pd));
424		pcap_userdata = 0;
425	}
426	if (RFileName == NULL) {
427		(void)fprintf(stderr, "%s: listening on %s\n",
428		    program_name, device);
429		(void)fflush(stderr);
430	}
431	if (pcap_loop(pd, cnt, printer, pcap_userdata) < 0) {
432		(void)fprintf(stderr, "%s: pcap_loop: %s\n",
433		    program_name, pcap_geterr(pd));
434		exit(1);
435	}
436	pcap_close(pd);
437	exit(0);
438}
439
440/* make a clean exit on interrupts */
441static RETSIGTYPE
442cleanup(int signo)
443{
444	struct pcap_stat stat;
445
446	/* Can't print the summary if reading from a savefile */
447	if (pd != NULL && pcap_file(pd) == NULL) {
448		(void)fflush(stdout);
449		putc('\n', stderr);
450		if (pcap_stats(pd, &stat) < 0)
451			(void)fprintf(stderr, "pcap_stats: %s\n",
452			    pcap_geterr(pd));
453		else {
454			(void)fprintf(stderr, "%d packets received by filter\n",
455			    stat.ps_recv);
456			(void)fprintf(stderr, "%d packets dropped by kernel\n",
457			    stat.ps_drop);
458		}
459	}
460	exit(0);
461}
462
463/* Like default_print() but data need not be aligned */
464void
465default_print_unaligned(register const u_char *cp, register u_int length)
466{
467	register u_int i, s;
468	register int nshorts;
469
470	if (Xflag) {
471		ascii_print(cp, length);
472		return;
473	}
474	nshorts = (u_int) length / sizeof(u_short);
475	i = 0;
476	while (--nshorts >= 0) {
477		if ((i++ % 8) == 0)
478			(void)printf("\n\t\t\t");
479		s = *cp++;
480		(void)printf(" %02x%02x", s, *cp++);
481	}
482	if (length & 1) {
483		if ((i % 8) == 0)
484			(void)printf("\n\t\t\t");
485		(void)printf(" %02x", *cp);
486	}
487}
488
489/*
490 * By default, print the packet out in hex.
491 */
492void
493default_print(register const u_char *bp, register u_int length)
494{
495	default_print_unaligned(bp, length);
496}
497
498static void
499usage(void)
500{
501	extern char version[];
502	extern char pcap_version[];
503
504	(void)fprintf(stderr, "%s version %s\n", program_name, version);
505	(void)fprintf(stderr, "libpcap version %s\n", pcap_version);
506	(void)fprintf(stderr,
507"Usage: %s [-adeflnNOpqStuvxX] [-c count] [ -F file ]\n", program_name);
508	(void)fprintf(stderr,
509"\t\t[ -i interface ] [ -r file ] [ -s snaplen ]\n");
510	(void)fprintf(stderr,
511"\t\t[ -T type ] [ -w file ] [ expression ]\n");
512	exit(-1);
513}
514