xref: /openbsd-src/usr.sbin/tcpdump/tcpdump.c (revision daf88648c0e349d5c02e1504293082072c981640)
1 /*	$OpenBSD: tcpdump.c,v 1.55 2006/06/16 16:55:46 deraadt Exp $	*/
2 
3 /*
4  * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
5  *	The Regents of the University of California.  All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that: (1) source code distributions
9  * retain the above copyright notice and this paragraph in its entirety, (2)
10  * distributions including binary code include the above copyright notice and
11  * this paragraph in its entirety in the documentation or other materials
12  * provided with the distribution, and (3) all advertising materials mentioning
13  * features or use of this software display the following acknowledgement:
14  * ``This product includes software developed by the University of California,
15  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
16  * the University nor the names of its contributors may be used to endorse
17  * or promote products derived from this software without specific prior
18  * written permission.
19  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
20  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
21  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
22  */
23 
24 #ifndef lint
25 static const char copyright[] =
26     "@(#) Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997\n\
27 The Regents of the University of California.  All rights reserved.\n";
28 static const char rcsid[] =
29     "@(#) $Header: /home/cvs/src/usr.sbin/tcpdump/tcpdump.c,v 1.55 2006/06/16 16:55:46 deraadt Exp $ (LBL)";
30 #endif
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 #include <sys/types.h>
41 #include <sys/time.h>
42 #include <sys/ioctl.h>
43 #include <sys/wait.h>
44 
45 #include <netinet/in.h>
46 
47 #include <pcap.h>
48 #include <signal.h>
49 #include <stdio.h>
50 #include <stdlib.h>
51 #include <string.h>
52 #include <unistd.h>
53 #include <ctype.h>
54 #include <err.h>
55 #include <errno.h>
56 
57 #include "interface.h"
58 #include "addrtoname.h"
59 #include "machdep.h"
60 #include "setsignal.h"
61 #include "gmt2local.h"
62 
63 #include <sys/socket.h>
64 #include <net/if.h>
65 #include <netinet/in.h>
66 #include <net/pfvar.h>
67 #include "pfctl.h"
68 #include "pfctl_parser.h"
69 #include "privsep.h"
70 
71 int aflag;			/* translate network and broadcast addresses */
72 int dflag;			/* print filter code */
73 int eflag;			/* print ethernet header */
74 int fflag;			/* don't translate "foreign" IP address */
75 int Lflag;			/* List available link types */
76 int nflag;			/* leave addresses as numbers */
77 int Nflag;			/* remove domains from printed host names */
78 int Oflag = 1;			/* run filter code optimizer */
79 int oflag;			/* print passive OS fingerprints */
80 int pflag;			/* don't go promiscuous */
81 int qflag;			/* quick (shorter) output */
82 int Sflag;			/* print raw TCP sequence numbers */
83 int tflag = 1;			/* print packet arrival time */
84 int vflag;			/* verbose */
85 int xflag;			/* print packet in hex */
86 int Xflag;			/* print packet in emacs-hexl style */
87 
88 int packettype;
89 
90 char *program_name;
91 
92 int32_t thiszone;		/* seconds offset from gmt to local time */
93 
94 extern volatile pid_t child_pid;
95 
96 /* Externs */
97 extern void bpf_dump(struct bpf_program *, int);
98 extern int esp_init(char *);
99 
100 /* Forwards */
101 RETSIGTYPE cleanup(int);
102 RETSIGTYPE gotchld(int);
103 extern __dead void usage(void);
104 
105 /* Length of saved portion of packet. */
106 int snaplen = 0;
107 
108 struct printer {
109 	pcap_handler f;
110 	int type;
111 };
112 
113 /* XXX needed if using old bpf.h */
114 #ifndef DLT_ATM_RFC1483
115 #define DLT_ATM_RFC1483 11
116 #endif
117 
118 static struct printer printers[] = {
119 	{ ether_if_print,		DLT_EN10MB },
120 	{ ether_if_print,		DLT_IEEE802 },
121 	{ sl_if_print,			DLT_SLIP },
122 	{ sl_bsdos_if_print,		DLT_SLIP_BSDOS },
123 	{ ppp_if_print,			DLT_PPP },
124 	{ fddi_if_print,		DLT_FDDI },
125 	{ null_if_print,		DLT_NULL },
126 	{ raw_if_print,			DLT_RAW },
127 	{ atm_if_print,			DLT_ATM_RFC1483 },
128 	{ loop_if_print,		DLT_LOOP },
129 	{ enc_if_print,			DLT_ENC },
130 	{ pflog_if_print,		DLT_PFLOG },
131 	{ pflog_old_if_print,		DLT_OLD_PFLOG },
132 	{ pfsync_if_print,		DLT_PFSYNC },
133 	{ ppp_ether_if_print,		DLT_PPP_ETHER },
134 	{ ieee802_11_if_print,		DLT_IEEE802_11 },
135 	{ ieee802_11_radio_if_print,	DLT_IEEE802_11_RADIO },
136 	{ NULL,				0 },
137 };
138 
139 static pcap_handler
140 lookup_printer(int type)
141 {
142 	struct printer *p;
143 
144 	for (p = printers; p->f; ++p) {
145 		if (type == p->type)
146 			return p->f;
147 	}
148 
149 	error("unknown data link type 0x%x", type);
150 	/* NOTREACHED */
151 }
152 
153 static int
154 init_pfosfp(void)
155 {
156 	pf_osfp_initialize();
157 	if (pfctl_file_fingerprints(-1,
158 	    PF_OPT_QUIET|PF_OPT_NOACTION, PF_OSFP_FILE) == 0)
159 		return 1;
160 	return 0;
161 }
162 
163 static pcap_t *pd;
164 
165 /* Multiple DLT support */
166 void		 pcap_list_linktypes(pcap_t *);
167 void		 pcap_print_linktype(u_int);
168 
169 void
170 pcap_print_linktype(u_int dlt)
171 {
172 	const char *name;
173 
174 	if ((name = pcap_datalink_val_to_name(dlt)) != NULL)
175 		fprintf(stderr, "%s\n", name);
176 	else
177 		fprintf(stderr, "<unknown: %u>\n", dlt);
178 }
179 
180 void
181 pcap_list_linktypes(pcap_t *p)
182 {
183 	int fd = p->fd;
184 	u_int n;
185 
186 #define MAXDLT	100
187 
188 	u_int dltlist[MAXDLT];
189 	struct bpf_dltlist dl = {MAXDLT, dltlist};
190 
191 	if (fd < 0)
192 		error("Invalid bpf descriptor");
193 
194 	if (ioctl(fd, BIOCGDLTLIST, &dl) < 0)
195 		err(1, "BIOCGDLTLIST");
196 
197 	if (dl.bfl_len > MAXDLT)
198 		error("Invalid number of linktypes: %u", dl.bfl_len);
199 
200 	fprintf(stderr, "%d link type%s supported:\n", dl.bfl_len,
201 	    dl.bfl_len == 1 ? "" : "s");
202 
203 	for (n = 0; n < dl.bfl_len; n++) {
204 		fprintf(stderr, "\t");
205 		pcap_print_linktype(dltlist[n]);
206 	}
207 }
208 
209 extern int optind;
210 extern int opterr;
211 extern char *optarg;
212 
213 int
214 main(int argc, char **argv)
215 {
216 	int cnt = -1, op, i;
217 	bpf_u_int32 localnet, netmask;
218 	char *cp, *infile = NULL, *device = NULL, *RFileName = NULL;
219 	char ebuf[PCAP_ERRBUF_SIZE], *WFileName = NULL;
220 	pcap_handler printer;
221 	struct bpf_program *fcode;
222 	u_char *pcap_userdata;
223 	u_int dlt = (u_int) -1;
224 
225 	if ((cp = strrchr(argv[0], '/')) != NULL)
226 		program_name = cp + 1;
227 	else
228 		program_name = argv[0];
229 
230 	if (priv_init(argc, argv))
231 		error("Failed to setup privsep");
232 
233 	/* state: STATE_INIT */
234 	if (abort_on_misalignment(ebuf, sizeof(ebuf)) < 0)
235 		error("%s", ebuf);
236 
237 	opterr = 0;
238 	while ((op = getopt(argc, argv,
239 	    "ac:deE:fF:i:lLnNOopqr:s:StT:vw:xXy:Y")) != -1)
240 		switch (op) {
241 
242 		case 'a':
243 			++aflag;
244 			break;
245 
246 		case 'c':
247 			cnt = atoi(optarg);
248 			if (cnt <= 0)
249 				error("invalid packet count %s", optarg);
250 			break;
251 
252 		case 'd':
253 			++dflag;
254 			break;
255 		case 'e':
256 			++eflag;
257 			break;
258 
259 		case 'f':
260 			++fflag;
261 			break;
262 
263 		case 'F':
264 			infile = optarg;
265 			break;
266 
267 		case 'i':
268 			device = optarg;
269 			break;
270 
271 		case 'l':
272 #ifdef HAVE_SETLINEBUF
273 			setlinebuf(stdout);
274 #else
275 			setvbuf(stdout, NULL, _IOLBF, 0);
276 #endif
277 			break;
278 		case 'L':
279 			++Lflag;
280 			break;
281 		case 'n':
282 			++nflag;
283 			break;
284 
285 		case 'N':
286 			++Nflag;
287 			break;
288 
289 		case 'O':
290 			Oflag = 0;
291 			break;
292 
293 		case 'o':
294 			oflag = 1;
295 			break;
296 
297 		case 'p':
298 			++pflag;
299 			break;
300 
301 		case 'q':
302 			++qflag;
303 			break;
304 
305 		case 'r':
306 			RFileName = optarg;
307 			break;
308 
309 		case 's':
310 			snaplen = atoi(optarg);
311 			if (snaplen <= 0)
312 				error("invalid snaplen %s", optarg);
313 			break;
314 
315 		case 'S':
316 			++Sflag;
317 			break;
318 
319 		case 't':
320 			--tflag;
321 			break;
322 
323 		case 'T':
324 			if (strcasecmp(optarg, "vat") == 0)
325 				packettype = PT_VAT;
326 			else if (strcasecmp(optarg, "wb") == 0)
327 				packettype = PT_WB;
328 			else if (strcasecmp(optarg, "rpc") == 0)
329 				packettype = PT_RPC;
330 			else if (strcasecmp(optarg, "rtp") == 0)
331 				packettype = PT_RTP;
332 			else if (strcasecmp(optarg, "rtcp") == 0)
333 				packettype = PT_RTCP;
334 			else if (strcasecmp(optarg, "cnfp") == 0)
335 				packettype = PT_CNFP;
336 			else if (strcasecmp(optarg, "vrrp") == 0)
337 				packettype = PT_VRRP;
338 			else if (strcasecmp(optarg, "tcp") == 0)
339 				packettype = PT_TCP;
340 			else if (strcasecmp(optarg, "sack") == 0)
341 				snaplen = SACK_SNAPLEN;
342 			else
343 				error("unknown packet type `%s'", optarg);
344 			break;
345 
346 		case 'v':
347 			++vflag;
348 			break;
349 
350 		case 'w':
351 			WFileName = optarg;
352 			break;
353 #ifdef YYDEBUG
354 		case 'Y':
355 			{
356 			/* Undocumented flag */
357 			extern int yydebug;
358 			yydebug = 1;
359 			}
360 			break;
361 #endif
362 		case 'y':
363 			i = pcap_datalink_name_to_val(optarg);
364 			if (i < 0)
365 				error("invalid data link type: %s", optarg);
366 			dlt = (u_int)i;
367 			break;
368 
369 		case 'x':
370 			++xflag;
371 			break;
372 
373 		case 'X':
374 			++Xflag;
375 			if (xflag == 0) ++xflag;
376 			break;
377 
378 		case 'E':
379 			if (esp_init(optarg) < 0)
380 				error("bad esp specification `%s'", optarg);
381 			break;
382 
383 		default:
384 			usage();
385 			/* NOTREACHED */
386 		}
387 
388 	if (snaplen == 0) {
389 		switch (dlt) {
390 		case DLT_IEEE802_11:
391 			snaplen = IEEE802_11_SNAPLEN;
392 			break;
393 		case DLT_IEEE802_11_RADIO:
394 			snaplen = IEEE802_11_RADIO_SNAPLEN;
395 			break;
396 		default:
397 			snaplen = DEFAULT_SNAPLEN;
398 			break;
399 		}
400 	}
401 
402 	if (aflag && nflag)
403 		error("-a and -n options are incompatible");
404 
405 	if (RFileName != NULL) {
406 		pd = priv_pcap_offline(RFileName, ebuf);
407 		if (pd == NULL)
408 			error("%s", ebuf);
409 		/* state: STATE_BPF */
410 		localnet = 0;
411 		netmask = 0;
412 		if (fflag != 0)
413 			error("-f and -r options are incompatible");
414 	} else {
415 		if (device == NULL) {
416 			device = pcap_lookupdev(ebuf);
417 			if (device == NULL)
418 				error("%s", ebuf);
419 		}
420 		pd = priv_pcap_live(device, snaplen, !pflag, 1000, ebuf, dlt);
421 		if (pd == NULL)
422 			error("%s", ebuf);
423 
424 		/* state: STATE_BPF */
425 		if (pcap_lookupnet(device, &localnet, &netmask, ebuf)) {
426 			warning("%s", ebuf);
427 			localnet = 0;
428 			netmask = 0;
429 		}
430 	}
431 	i = pcap_snapshot(pd);
432 	if (snaplen < i) {
433 		warning("snaplen raised from %d to %d", snaplen, i);
434 		snaplen = i;
435 	}
436 
437 	if (Lflag) {
438 		pcap_list_linktypes(pd);
439 		exit(0);
440 	}
441 
442 	fcode = priv_pcap_setfilter(pd, Oflag, netmask);
443 	/* state: STATE_FILTER */
444 	if (fcode == NULL)
445 		error("%s", pcap_geterr(pd));
446 	if (dflag) {
447 		bpf_dump(fcode, dflag);
448 		exit(0);
449 	}
450 	init_addrtoname(localnet, netmask);
451 
452 	if (WFileName) {
453 		pcap_dumper_t *p;
454 
455 		p = priv_pcap_dump_open(pd, WFileName);
456 		/* state: STATE_RUN */
457 		if (p == NULL)
458 			error("%s", pcap_geterr(pd));
459 		{
460 			FILE *fp = (FILE *)p;	/* XXX touching pcap guts! */
461 			fflush(fp);
462 			setvbuf(fp, NULL, _IONBF, 0);
463 		}
464 		printer = pcap_dump;
465 		pcap_userdata = (u_char *)p;
466 	} else {
467 		printer = lookup_printer(pcap_datalink(pd));
468 		pcap_userdata = 0;
469 		priv_init_done();
470 		/* state: STATE_RUN */
471 	}
472 	if (RFileName == NULL) {
473 		(void)fprintf(stderr, "%s: listening on %s, link-type ",
474 		    program_name, device);
475 		pcap_print_linktype(pd->linktype);
476 		(void)fflush(stderr);
477 	}
478 
479 	if (oflag)
480 		oflag = init_pfosfp();
481 	if (tflag > 0)
482 		thiszone = gmt2local(0);
483 
484 
485 	if (pcap_loop(pd, cnt, printer, pcap_userdata) < 0) {
486 		(void)fprintf(stderr, "%s: pcap_loop: %s\n",
487 		    program_name, pcap_geterr(pd));
488 		exit(1);
489 	}
490 	pcap_close(pd);
491 	exit(0);
492 }
493 
494 /* make a clean exit on interrupts */
495 /* ARGSUSED */
496 RETSIGTYPE
497 cleanup(int signo)
498 {
499 	struct pcap_stat stat;
500 	sigset_t allsigs;
501 	char buf[1024];
502 
503 	sigfillset(&allsigs);
504 	sigprocmask(SIG_BLOCK, &allsigs, NULL);
505 
506 	/* Can't print the summary if reading from a savefile */
507 	(void)write(STDERR_FILENO, "\n", 1);
508 	if (pd != NULL && pcap_file(pd) == NULL) {
509 		if (pcap_stats(pd, &stat) < 0) {
510 			(void)snprintf(buf, sizeof buf,
511 			    "pcap_stats: %s\n", pcap_geterr(pd));
512 			write(STDERR_FILENO, buf, strlen(buf));
513 		} else {
514 			(void)snprintf(buf, sizeof buf,
515 			    "%d packets received by filter\n", stat.ps_recv);
516 			write(STDERR_FILENO, buf, strlen(buf));
517 			(void)snprintf(buf, sizeof buf,
518 			    "%d packets dropped by kernel\n", stat.ps_drop);
519 			write(STDERR_FILENO, buf, strlen(buf));
520 		}
521 	}
522 	_exit(0);
523 }
524 
525 /* ARGSUSED */
526 RETSIGTYPE
527 gotchld(int signo)
528 {
529 	pid_t pid;
530 	int status;
531 	int save_err = errno;
532 
533 	do {
534 		pid = waitpid(child_pid, &status, WNOHANG);
535 		if (pid > 0 && (WIFEXITED(status) || WIFSIGNALED(status)))
536 			cleanup(0);
537 	} while (pid == -1 && errno == EINTR);
538 
539 	if (pid == -1)
540 		_exit(1);
541 
542 	errno = save_err;
543 }
544 
545 /* dump the buffer in `emacs-hexl' style */
546 void
547 default_print_hexl(const u_char *cp, unsigned int length, unsigned int offset)
548 {
549 	unsigned int i, j, jm;
550 	int c;
551 	char ln[128], buf[128];
552 
553 	printf("\n");
554 	for (i = 0; i < length; i += 0x10) {
555 		snprintf(ln, sizeof(ln), "  %04x: ",
556 		    (unsigned int)(i + offset));
557 		jm = length - i;
558 		jm = jm > 16 ? 16 : jm;
559 
560 		for (j = 0; j < jm; j++) {
561 			if ((j % 2) == 1)
562 				snprintf(buf, sizeof(buf), "%02x ",
563 				    (unsigned int)cp[i+j]);
564 			else
565 				snprintf(buf, sizeof(buf), "%02x",
566 				    (unsigned int)cp[i+j]);
567 			strlcat(ln, buf, sizeof ln);
568 		}
569 		for (; j < 16; j++) {
570 			if ((j % 2) == 1)
571 				snprintf(buf, sizeof buf, "   ");
572 			else
573 				snprintf(buf, sizeof buf, "  ");
574 			strlcat(ln, buf, sizeof ln);
575 		}
576 
577 		strlcat(ln, " ", sizeof ln);
578 		for (j = 0; j < jm; j++) {
579 			c = cp[i+j];
580 			c = isprint(c) ? c : '.';
581 			buf[0] = c;
582 			buf[1] = '\0';
583 			strlcat(ln, buf, sizeof ln);
584 		}
585 		printf("%s\n", ln);
586 	}
587 }
588 
589 /* Like default_print() but data need not be aligned */
590 void
591 default_print_unaligned(register const u_char *cp, register u_int length)
592 {
593 	register u_int i, s;
594 	register int nshorts;
595 
596 	if (Xflag) {
597 		/* dump the buffer in `emacs-hexl' style */
598 		default_print_hexl(cp, length, 0);
599 	} else {
600 		/* dump the buffer in old tcpdump style */
601 		nshorts = (u_int) length / sizeof(u_short);
602 		i = 0;
603 		while (--nshorts >= 0) {
604 			if ((i++ % 8) == 0)
605 				(void)printf("\n\t\t\t");
606 			s = *cp++;
607 			(void)printf(" %02x%02x", s, *cp++);
608 		}
609 		if (length & 1) {
610 			if ((i % 8) == 0)
611 				(void)printf("\n\t\t\t");
612 			(void)printf(" %02x", *cp);
613 		}
614 	}
615 }
616 
617 void
618 default_print(register const u_char *bp, register u_int length)
619 {
620 	register const u_short *sp;
621 	register u_int i;
622 	register int nshorts;
623 
624 	if (Xflag) {
625 		/* dump the buffer in `emacs-hexl' style */
626 		default_print_hexl(bp, length, 0);
627 	} else {
628 		/* dump the buffer in old tcpdump style */
629 		if ((long)bp & 1) {
630 			default_print_unaligned(bp, length);
631 			return;
632 		}
633 		sp = (u_short *)bp;
634 		nshorts = (u_int) length / sizeof(u_short);
635 		i = 0;
636 		while (--nshorts >= 0) {
637 			if ((i++ % 8) == 0)
638 				(void)printf("\n\t\t\t");
639 			(void)printf(" %04x", ntohs(*sp++));
640 		}
641 		if (length & 1) {
642 			if ((i % 8) == 0)
643 				(void)printf("\n\t\t\t");
644 			(void)printf(" %02x", *(u_char *)sp);
645 		}
646 	}
647 }
648 
649 void
650 set_slave_signals(void)
651 {
652 	RETSIGTYPE (*oldhandler)(int);
653 
654 	setsignal(SIGTERM, cleanup);
655 	setsignal(SIGINT, cleanup);
656 	setsignal(SIGCHLD, gotchld);
657 	/* Cooperate with nohup(1) XXX is this still necessary/working? */
658 	if ((oldhandler = setsignal(SIGHUP, cleanup)) != SIG_DFL)
659 		(void)setsignal(SIGHUP, oldhandler);
660 }
661 
662 __dead void
663 usage(void)
664 {
665 	(void)fprintf(stderr,
666 "Usage: %s [-adefLlNnOopqStvXx] [-c count] [-E [espalg:]espkey] [-F file]\n",
667 	    program_name);
668 	(void)fprintf(stderr,
669 "\t       [-i interface] [-r file] [-s snaplen] [-T type] [-w file]\n");
670 	(void)fprintf(stderr,
671 "\t       [-y datalinktype] [expression]\n");
672 	exit(1);
673 }
674