1 /* $OpenBSD: tcpdump.c,v 1.99 2023/03/03 13:03:29 claudio 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 /*
25 * tcpdump - monitor tcp/ip traffic on an ethernet.
26 *
27 * First written in 1987 by Van Jacobson, Lawrence Berkeley Laboratory.
28 * Mercilessly hacked and occasionally improved since then via the
29 * combined efforts of Van, Steve McCanne and Craig Leres of LBL.
30 */
31
32 #include <sys/types.h>
33 #include <sys/time.h>
34 #include <sys/ioctl.h>
35 #include <sys/wait.h>
36
37 #include <netinet/in.h>
38
39 #include <pcap.h>
40 #include <signal.h>
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <string.h>
44 #include <unistd.h>
45 #include <limits.h>
46 #include <ctype.h>
47 #include <err.h>
48 #include <errno.h>
49
50 #include "interface.h"
51 #include "addrtoname.h"
52 #include "setsignal.h"
53 #include "gmt2local.h"
54
55 #include <sys/socket.h>
56 #include <net/if.h>
57 #include <net/pfvar.h>
58 #include "extract.h"
59 #include "pfctl.h"
60 #include "pfctl_parser.h"
61 #include "privsep.h"
62
63 int Aflag; /* dump ascii */
64 int aflag; /* translate network and broadcast addresses */
65 int Bflag = BPF_FILDROP_PASS; /* BPF fildrop setting */
66 int dflag; /* print filter code */
67 int eflag; /* print ethernet header */
68 int fflag; /* don't translate "foreign" IP address */
69 int Iflag; /* include interface in output */
70 int Lflag; /* List available link types */
71 int nflag; /* leave addresses as numbers */
72 int Nflag; /* remove domains from printed host names */
73 int Oflag = 1; /* run filter code optimizer */
74 int oflag; /* print passive OS fingerprints */
75 int pflag; /* don't go promiscuous */
76 int qflag; /* quick (shorter) output */
77 int Sflag; /* print raw TCP sequence numbers */
78 int tflag = 1; /* print packet arrival time */
79 int vflag; /* verbose */
80 int xflag; /* print packet in hex */
81 int Xflag; /* print packet in emacs-hexl style */
82
83 int packettype;
84
85 char *program_name;
86 char *device = NULL;
87
88 int32_t thiszone; /* seconds offset from gmt to local time */
89
90 extern volatile pid_t child_pid;
91
92 /* Externs */
93 extern void bpf_dump(struct bpf_program *, int);
94 extern int esp_init(char *);
95
96 /* Forwards */
97 void cleanup(int);
98 void gotchld(int);
99 extern __dead void usage(void);
100
101 /* Length of saved portion of packet. */
102 int snaplen = 0;
103
104 struct printer {
105 pcap_handler f;
106 int type;
107 };
108
109 /* XXX needed if using old bpf.h */
110 #ifndef DLT_ATM_RFC1483
111 #define DLT_ATM_RFC1483 11
112 #endif
113
114 static struct printer printers[] = {
115 { ether_if_print, DLT_EN10MB },
116 { ether_if_print, DLT_IEEE802 },
117 { sl_if_print, DLT_SLIP },
118 { sl_bsdos_if_print, DLT_SLIP_BSDOS },
119 { ppp_if_print, DLT_PPP },
120 { ppp_hdlc_if_print, DLT_PPP_SERIAL },
121 { fddi_if_print, DLT_FDDI },
122 { null_if_print, DLT_NULL },
123 { raw_if_print, DLT_RAW },
124 { atm_if_print, DLT_ATM_RFC1483 },
125 { loop_if_print, DLT_LOOP },
126 { enc_if_print, DLT_ENC },
127 { pflog_if_print, DLT_PFLOG },
128 { pfsync_if_print, DLT_PFSYNC },
129 { ppp_ether_if_print, DLT_PPP_ETHER },
130 { ieee802_11_if_print, DLT_IEEE802_11 },
131 { ieee802_11_radio_if_print, DLT_IEEE802_11_RADIO },
132 { ofp_if_print, DLT_OPENFLOW },
133 { usbpcap_if_print, DLT_USBPCAP },
134 { NULL, 0 },
135 };
136
137 static pcap_handler
lookup_printer(int type)138 lookup_printer(int type)
139 {
140 struct printer *p;
141
142 for (p = printers; p->f; ++p) {
143 if (type == p->type)
144 return p->f;
145 }
146
147 error("unknown data link type 0x%x", type);
148 /* NOTREACHED */
149 }
150
151 static int
init_pfosfp(void)152 init_pfosfp(void)
153 {
154 pf_osfp_initialize();
155 if (pfctl_file_fingerprints(-1,
156 PF_OPT_QUIET|PF_OPT_NOACTION, PF_OSFP_FILE) == 0)
157 return 1;
158 return 0;
159 }
160
161 static pcap_t *pd;
162
163 /* Multiple DLT support */
164 void pcap_list_linktypes(pcap_t *);
165 void pcap_print_linktype(u_int);
166
167 void
pcap_print_linktype(u_int dlt)168 pcap_print_linktype(u_int dlt)
169 {
170 const char *name;
171
172 if ((name = pcap_datalink_val_to_name(dlt)) != NULL)
173 fprintf(stderr, "%s\n", name);
174 else
175 fprintf(stderr, "<unknown: %u>\n", dlt);
176 }
177
178 void
pcap_list_linktypes(pcap_t * p)179 pcap_list_linktypes(pcap_t *p)
180 {
181 int fd = p->fd;
182 u_int n;
183
184 #define MAXDLT 100
185
186 u_int dltlist[MAXDLT];
187 struct bpf_dltlist dl = {MAXDLT, dltlist};
188
189 if (fd < 0)
190 error("Invalid bpf descriptor");
191
192 if (ioctl(fd, BIOCGDLTLIST, &dl) == -1)
193 err(1, "BIOCGDLTLIST");
194
195 if (dl.bfl_len > MAXDLT)
196 error("Invalid number of linktypes: %u", dl.bfl_len);
197
198 fprintf(stderr, "%d link type%s supported:\n", dl.bfl_len,
199 dl.bfl_len == 1 ? "" : "s");
200
201 for (n = 0; n < dl.bfl_len; n++) {
202 fprintf(stderr, "\t");
203 pcap_print_linktype(dltlist[n]);
204 }
205 }
206
207 int
main(int argc,char ** argv)208 main(int argc, char **argv)
209 {
210 int cnt = -1, op, i;
211 bpf_u_int32 localnet, netmask;
212 char *cp, *RFileName = NULL;
213 char ebuf[PCAP_ERRBUF_SIZE], *WFileName = NULL;
214 pcap_handler printer;
215 struct bpf_program *fcode;
216 u_char *pcap_userdata;
217 u_int dirfilt = 0, dlt = (u_int) -1;
218 const char *errstr;
219
220 if ((cp = strrchr(argv[0], '/')) != NULL)
221 program_name = cp + 1;
222 else
223 program_name = argv[0];
224
225 /* '-P' used internally, exec privileged portion */
226 if (argc >= 2 && strcmp("-P", argv[1]) == 0)
227 priv_exec(argc, argv);
228
229 if (priv_init(argc, argv))
230 error("Failed to setup privsep");
231
232 /* state: STATE_INIT */
233
234 opterr = 0;
235 while ((op = getopt(argc, argv,
236 "AaB:c:D:deE:fF:i:IlLnNOopqr:s:StT:vw:xXy:")) != -1)
237 switch (op) {
238
239 case 'A':
240 xflag = 1;
241 Aflag = 1;
242 break;
243
244 case 'a':
245 aflag = 1;
246 break;
247
248 case 'B':
249 if (strcasecmp(optarg, "pass") == 0)
250 Bflag = BPF_FILDROP_PASS;
251 else if (strcasecmp(optarg, "capture") == 0)
252 Bflag = BPF_FILDROP_CAPTURE;
253 else if (strcasecmp(optarg, "drop") == 0)
254 Bflag = BPF_FILDROP_DROP;
255 else {
256 error("invalid BPF fildrop option: %s",
257 optarg);
258 }
259 break;
260
261 case 'c':
262 cnt = strtonum(optarg, 1, INT_MAX, &errstr);
263 if (errstr)
264 error("invalid packet count %s: %s",
265 optarg, errstr);
266 break;
267
268 case 'D':
269 if (strcasecmp(optarg, "in") == 0)
270 dirfilt = BPF_DIRECTION_OUT;
271 else if (strcasecmp(optarg, "out") == 0)
272 dirfilt = BPF_DIRECTION_IN;
273 else
274 error("invalid traffic direction %s", optarg);
275 break;
276
277 case 'd':
278 ++dflag;
279 break;
280 case 'e':
281 eflag = 1;
282 break;
283
284 case 'f':
285 fflag = 1;
286 break;
287
288 case 'F':
289 break;
290
291 case 'i':
292 device = optarg;
293 break;
294
295 case 'I':
296 Iflag = 1;
297 break;
298
299 case 'l':
300 setvbuf(stdout, NULL, _IOLBF, 0);
301 break;
302 case 'L':
303 Lflag = 1;
304 break;
305 case 'n':
306 nflag = 1;
307 break;
308
309 case 'N':
310 Nflag = 1;
311 break;
312
313 case 'O':
314 Oflag = 0;
315 break;
316
317 case 'o':
318 oflag = 1;
319 break;
320
321 case 'p':
322 pflag = 1;
323 break;
324
325 case 'q':
326 qflag = 1;
327 break;
328
329 case 'r':
330 RFileName = optarg;
331 break;
332
333 case 's':
334 snaplen = strtonum(optarg, 1, INT_MAX, &errstr);
335 if (errstr)
336 error("invalid snaplen %s: %s", optarg, errstr);
337 break;
338
339 case 'S':
340 Sflag = 1;
341 break;
342
343 case 't':
344 --tflag;
345 break;
346
347 case 'T':
348 if (strcasecmp(optarg, "vat") == 0)
349 packettype = PT_VAT;
350 else if (strcasecmp(optarg, "wb") == 0)
351 packettype = PT_WB;
352 else if (strcasecmp(optarg, "rpc") == 0)
353 packettype = PT_RPC;
354 else if (strcasecmp(optarg, "rtp") == 0)
355 packettype = PT_RTP;
356 else if (strcasecmp(optarg, "rtcp") == 0)
357 packettype = PT_RTCP;
358 else if (strcasecmp(optarg, "cnfp") == 0)
359 packettype = PT_CNFP;
360 else if (strcasecmp(optarg, "vrrp") == 0)
361 packettype = PT_VRRP;
362 else if (strcasecmp(optarg, "tcp") == 0)
363 packettype = PT_TCP;
364 else if (strcasecmp(optarg, "gre") == 0)
365 packettype = PT_GRE;
366 else if (strcasecmp(optarg, "vxlan") == 0)
367 packettype = PT_VXLAN;
368 else if (strcasecmp(optarg, "geneve") == 0)
369 packettype = PT_GENEVE;
370 else if (strcasecmp(optarg, "erspan") == 0)
371 packettype = PT_ERSPAN;
372 else if (strcasecmp(optarg, "mpls") == 0)
373 packettype = PT_MPLS;
374 else if (strcasecmp(optarg, "tftp") == 0)
375 packettype = PT_TFTP;
376 else if (strcasecmp(optarg, "wg") == 0)
377 packettype = PT_WIREGUARD;
378 else if (strcasecmp(optarg, "sack") == 0)
379 /*
380 * kept for compatibility; DEFAULT_SNAPLEN
381 * used to be too short to capture SACK.
382 */
383 ;
384 else
385 error("unknown packet type `%s'", optarg);
386 break;
387
388 case 'v':
389 ++vflag;
390 break;
391
392 case 'w':
393 WFileName = optarg;
394 break;
395
396 case 'y':
397 i = pcap_datalink_name_to_val(optarg);
398 if (i < 0)
399 error("invalid data link type: %s", optarg);
400 dlt = (u_int)i;
401 break;
402
403 case 'x':
404 xflag = 1;
405 break;
406
407 case 'X':
408 Xflag = 1;
409 xflag = 1;
410 break;
411
412 case 'E':
413 if (esp_init(optarg) < 0)
414 error("bad esp specification `%s'", optarg);
415 break;
416
417 default:
418 usage();
419 /* NOTREACHED */
420 }
421
422 if (snaplen == 0) {
423 switch (dlt) {
424 case DLT_IEEE802_11:
425 snaplen = IEEE802_11_SNAPLEN;
426 break;
427 case DLT_IEEE802_11_RADIO:
428 snaplen = IEEE802_11_RADIO_SNAPLEN;
429 break;
430 default:
431 snaplen = DEFAULT_SNAPLEN;
432 break;
433 }
434 }
435
436 if (aflag && nflag)
437 error("-a and -n options are incompatible");
438
439 if (RFileName != NULL) {
440 pd = priv_pcap_offline(RFileName, ebuf);
441 if (pd == NULL)
442 error("%s", ebuf);
443 /* state: STATE_BPF */
444 localnet = 0;
445 netmask = 0;
446 if (fflag != 0)
447 error("-f and -r options are incompatible");
448 } else {
449 if (device == NULL) {
450 device = pcap_lookupdev(ebuf);
451 if (device == NULL)
452 error("%s", ebuf);
453 }
454 pd = priv_pcap_live(device, snaplen, !pflag, 1000, ebuf,
455 dlt, dirfilt, Bflag);
456 if (pd == NULL)
457 error("%s", ebuf);
458
459 /* state: STATE_BPF */
460 if (pcap_lookupnet(device, &localnet, &netmask, ebuf)) {
461 if (fflag)
462 warning("%s", ebuf);
463 localnet = 0;
464 netmask = 0;
465 }
466 }
467 i = pcap_snapshot(pd);
468 if (snaplen < i) {
469 warning("snaplen raised from %d to %d", snaplen, i);
470 snaplen = i;
471 }
472
473 if (Lflag) {
474 pcap_list_linktypes(pd);
475 exit(0);
476 }
477
478 fcode = priv_pcap_setfilter(pd, Oflag, netmask);
479 /* state: STATE_FILTER */
480 if (fcode == NULL)
481 error("%s", pcap_geterr(pd));
482 if (dflag) {
483 bpf_dump(fcode, dflag);
484 exit(0);
485 }
486 if (oflag)
487 oflag = init_pfosfp();
488 init_addrtoname(localnet, netmask);
489
490 if (WFileName) {
491 pcap_dumper_t *p;
492
493 p = priv_pcap_dump_open(pd, WFileName);
494 /* state: STATE_RUN */
495 if (p == NULL)
496 error("%s", pcap_geterr(pd));
497 {
498 FILE *fp = (FILE *)p; /* XXX touching pcap guts! */
499 fflush(fp);
500 setvbuf(fp, NULL, _IONBF, 0);
501 }
502 printer = pcap_dump;
503 pcap_userdata = (u_char *)p;
504 } else {
505 printer = lookup_printer(pcap_datalink(pd));
506 pcap_userdata = NULL;
507 priv_init_done();
508 /* state: STATE_RUN */
509 }
510 if (RFileName == NULL) {
511 (void)fprintf(stderr, "%s: listening on %s, link-type ",
512 program_name, device);
513 pcap_print_linktype(pd->linktype);
514 (void)fflush(stderr);
515 }
516
517 if (tflag > 0)
518 thiszone = gmt2local(0);
519
520 if (pledge("stdio", NULL) == -1)
521 err(1, "pledge");
522
523 if (pcap_loop(pd, cnt, printer, pcap_userdata) < 0) {
524 (void)fprintf(stderr, "%s: pcap_loop: %s\n",
525 program_name, pcap_geterr(pd));
526 exit(1);
527 }
528 pcap_close(pd);
529 exit(0);
530 }
531
532 /* make a clean exit on interrupts */
533 void
cleanup(int signo)534 cleanup(int signo)
535 {
536 struct pcap_stat stat;
537 sigset_t allsigs;
538
539 sigfillset(&allsigs);
540 sigprocmask(SIG_BLOCK, &allsigs, NULL);
541
542 /* Can't print the summary if reading from a savefile */
543 dprintf(STDERR_FILENO, "\n");
544 if (pd != NULL && pcap_file(pd) == NULL) {
545 if (priv_pcap_stats(&stat) < 0) {
546 dprintf(STDERR_FILENO,
547 "pcap_stats: %s\n", pcap_geterr(pd));
548 } else {
549 dprintf(STDERR_FILENO,
550 "%u packets received by filter\n", stat.ps_recv);
551 dprintf(STDERR_FILENO,
552 "%u packets dropped by kernel\n", stat.ps_drop);
553 }
554 }
555 _exit(0);
556 }
557
558 void
gotchld(int signo)559 gotchld(int signo)
560 {
561 pid_t pid;
562 int status;
563 int save_err = errno;
564
565 do {
566 pid = waitpid(child_pid, &status, WNOHANG);
567 if (pid > 0 && (WIFEXITED(status) || WIFSIGNALED(status)))
568 cleanup(0);
569 } while (pid == -1 && errno == EINTR);
570
571 if (pid == -1)
572 _exit(1);
573
574 errno = save_err;
575 }
576
577 /* dump the buffer in `emacs-hexl' style */
578 void
default_print_hexl(const u_char * cp,unsigned int length)579 default_print_hexl(const u_char *cp, unsigned int length)
580 {
581 unsigned int i, j, jm;
582 int c;
583 char ln[128], buf[128];
584
585 printf("\n");
586 for (i = 0; i < length; i += 0x10) {
587 snprintf(ln, sizeof(ln), " %04x: ", (unsigned int)i);
588 jm = length - i;
589 jm = jm > 16 ? 16 : jm;
590
591 for (j = 0; j < jm; j++) {
592 if ((j % 2) == 1)
593 snprintf(buf, sizeof(buf), "%02x ",
594 (unsigned int)cp[i+j]);
595 else
596 snprintf(buf, sizeof(buf), "%02x",
597 (unsigned int)cp[i+j]);
598 strlcat(ln, buf, sizeof ln);
599 }
600 for (; j < 16; j++) {
601 if ((j % 2) == 1)
602 snprintf(buf, sizeof buf, " ");
603 else
604 snprintf(buf, sizeof buf, " ");
605 strlcat(ln, buf, sizeof ln);
606 }
607
608 strlcat(ln, " ", sizeof ln);
609 for (j = 0; j < jm; j++) {
610 c = cp[i+j];
611 c = isprint(c) ? c : '.';
612 buf[0] = c;
613 buf[1] = '\0';
614 strlcat(ln, buf, sizeof ln);
615 }
616 printf("%s\n", ln);
617 }
618 }
619
620 /* dump the text from the buffer */
621 void
default_print_ascii(const u_char * cp,unsigned int length)622 default_print_ascii(const u_char *cp, unsigned int length)
623 {
624 int c, i;
625
626 printf("\n");
627 for (i = 0; i < length; i++) {
628 c = cp[i];
629 if (isprint(c) || c == '\t' || c == '\n' || c == '\r')
630 putchar(c);
631 else
632 putchar('.');
633 }
634 }
635
636 void
default_print(const u_char * bp,u_int length)637 default_print(const u_char *bp, u_int length)
638 {
639 u_int i;
640 int nshorts;
641
642 if (snapend - bp < length)
643 length = snapend - bp;
644
645 if (Xflag) {
646 /* dump the buffer in `emacs-hexl' style */
647 default_print_hexl(bp, length);
648 } else if (Aflag) {
649 /* dump the text in the buffer */
650 default_print_ascii(bp, length);
651 } else {
652 u_short sp;
653
654 /* dump the buffer in old tcpdump style */
655 nshorts = (u_int) length / sizeof(u_short);
656 i = 0;
657 while (--nshorts >= 0) {
658 if ((i++ % 8) == 0)
659 printf("\n\t\t\t");
660
661 sp = EXTRACT_16BITS(bp);
662 bp += sizeof(sp);
663 printf(" %04x", sp);
664 }
665 if (length & 1) {
666 if ((i % 8) == 0)
667 printf("\n\t\t\t");
668 printf(" %02x", *bp);
669 }
670 }
671 }
672
673 void
set_slave_signals(void)674 set_slave_signals(void)
675 {
676 setsignal(SIGTERM, cleanup);
677 setsignal(SIGINT, cleanup);
678 setsignal(SIGCHLD, gotchld);
679 setsignal(SIGHUP, cleanup);
680 }
681
682 __dead void
usage(void)683 usage(void)
684 {
685 (void)fprintf(stderr,
686 "Usage: %s [-AadefILlNnOopqStvXx] [-B fildrop] [-c count] [-D direction]\n",
687 program_name);
688 (void)fprintf(stderr,
689 "\t [-E [espalg:]espkey] [-F file] [-i interface] [-r file]\n");
690 (void)fprintf(stderr,
691 "\t [-s snaplen] [-T type] [-w file] [-y datalinktype] [expression]\n");
692 exit(1);
693 }
694