ongrep

A cleaned up fork of ngrep for OpenBSD
git clone git://git.sgregoratto.me/ongrep
Log | Files | Refs | README | LICENSE

ngrep.c (28911B)


      1 /*
      2  * Copyright (c) 2017  Jordan Ritter <jpr5@darkridge.com>
      3  * Copyright (c) 2020  Stephen Gregoratto <dev@sgregoratto.me>
      4  *
      5  * Please refer to the LICENSE file for more information.
      6  *
      7  */
      8 #include <sys/types.h>
      9 #include <sys/ioctl.h>
     10 #include <sys/limits.h>
     11 #include <sys/socket.h>
     12 #include <sys/stat.h>
     13 
     14 #include <net/ethertypes.h>
     15 #include <net/if.h>
     16 #include <netinet/in.h>
     17 #include <netinet/icmp6.h>
     18 #include <netinet/igmp.h>
     19 #include <netinet/ip.h>
     20 #include <netinet/ip6.h>
     21 #include <netinet/ip_icmp.h>
     22 #include <netinet/tcp.h>
     23 #include <netinet/udp.h>
     24 
     25 #include <arpa/inet.h>
     26 #include <ctype.h>
     27 #include <err.h>
     28 #include <errno.h>
     29 #include <fcntl.h>
     30 #include <pcap.h>
     31 #include <pcre.h>
     32 #include <pwd.h>
     33 #include <signal.h>
     34 #include <stdint.h>
     35 #include <stdio.h>
     36 #include <stdlib.h>
     37 #include <string.h>
     38 #include <time.h>
     39 #include <unistd.h>
     40 
     41 #include "ngrep.h"
     42 
     43 /* Configuration Options */
     44 uint32_t	snaplen = 65535;
     45 uint32_t	limitlen = 65535;
     46 uint32_t	promisc = 1;
     47 uint32_t	to = 100;
     48 uint32_t	match_after = 0;
     49 uint32_t	keep_matching = 0;
     50 uint32_t	matches = 0;
     51 uint32_t	max_matches = 0;
     52 uint32_t	seen_frames = 0;
     53 
     54 uint8_t		re_match_word = 0;
     55 uint8_t		re_ignore_case = 0;
     56 uint8_t		re_multiline_match = 1;
     57 uint8_t		show_empty = 0;
     58 uint8_t		show_hex = 0;
     59 uint8_t		show_proto = 0;
     60 uint8_t		quiet = 0;
     61 uint8_t		invert_match = 0;
     62 uint8_t		bin_match = 0;
     63 uint8_t		live_read = 1;
     64 uint8_t		want_delay = 0;
     65 uint8_t		enable_hilite = 0;
     66 
     67 char		*read_file = NULL;
     68 char		*dump_file = NULL;
     69 char		*usedev = NULL;
     70 
     71 char		nonprint_char = '.';
     72 
     73 /* PCRE and matching */
     74 int		 err_offset;
     75 const char	*re_err = NULL;
     76 
     77 pcre		*pattern = NULL;
     78 pcre_extra	*pattern_extra = NULL;
     79 
     80 char		*match_data = NULL;
     81 char		*bin_data = NULL;
     82 int		 hex_exp_pfx = 1;
     83 uint16_t	 match_len = 0;
     84 match_func	 matcher = blank_match_func;
     85 
     86 int8_t		dump_single = 0;
     87 dump_func	dumper = &dump_formatted;
     88 
     89 /* BPF/Network */
     90 char		*filter = NULL;
     91 char		*filter_file = NULL;
     92 char		 pc_err[PCAP_ERRBUF_SIZE];
     93 uint8_t		 link_offset;
     94 uint8_t		 radiotap_present = 0;
     95 uint8_t		 include_vlan = 1;
     96 
     97 pcap_t			*pd = NULL;
     98 pcap_t			*pd_dumppcap = NULL;
     99 pcap_dumper_t		*pd_dump = NULL;
    100 struct bpf_program	 pcapfilter;
    101 struct in_addr		 net, mask;
    102 
    103 /* Timestamp/delay functionality */
    104 struct timeval	prev_ts = {0, 0};
    105 struct timeval	prev_delay_ts = {0, 0};
    106 delay_func	dump_delay = dump_delay_proc_init;
    107 ts_func		print_time = NULL;
    108 
    109 /*
    110  * Window-size functionality
    111  * (adjust output based on width of console display)
    112  */
    113 uint32_t	ws_row, ws_col = 80, ws_col_forced = 0;
    114 
    115 const char	*optstring = "A:Cc:d:DeF:hiI:lMn:NO:pP:qs:S:tTvwW:xX";
    116 
    117 int
    118 main(int argc, char **argv)
    119 {
    120 	int c;
    121 	const char *errstr;
    122 
    123 	if (unveil("/etc/services", "r") == -1)
    124 		err(2, "unveil");
    125 	if (unveil("/etc/protocols", "r") == -1)
    126 		err(2, "unveil");
    127 	if (unveil("/etc/pwd.db", "r") == -1)
    128 		err(2, "unveil");
    129 	/*
    130 	 * XXX: pcap_open_live opens /dev/bpf as RW,
    131 	 * even though we don't write to it.
    132 	 *
    133 	 * The base programs work around this by implementing their own version
    134 	 * of pcap_open_live and setting the hidden members of pcap_t. Lame.
    135 	 */
    136 	if (unveil("/dev/bpf", "rw") == -1)
    137 		err(1, "unveil");
    138 	if (unveil("/var/empty", "r") == -1)
    139 		err(1, "unveil");
    140 
    141 	signal(SIGINT, clean_exit);
    142 	signal(SIGABRT, clean_exit);
    143 	signal(SIGQUIT, clean_exit);
    144 	signal(SIGPIPE, clean_exit);
    145 	signal(SIGWINCH, update_windowsize);
    146 
    147 	while ((c = getopt(argc, argv, optstring)) != EOF) {
    148 		switch (c) {
    149 		case 'A':
    150 			match_after = strtonum(optarg, 1, UINT32_MAX, &errstr);
    151 			if (errstr != NULL)
    152 				errx(2, "num is %s: %s", errstr, optarg);
    153 			if (match_after < UINT32_MAX)
    154 				match_after++;
    155 			break;
    156 		case 'c':
    157 			ws_col_forced = strtonum(optarg, 1, UINT32_MAX, &errstr);
    158 			if (errstr != NULL)
    159 				errx(2, "cols is %s: %s", errstr, optarg);
    160 			break;
    161 		case 'C':
    162 			enable_hilite = 1;
    163 			break;
    164 		case 'd':
    165 			usedev = optarg;
    166 			break;
    167 		case 'D':
    168 			want_delay = 1;
    169 			break;
    170 		case 'e':
    171 			show_empty++;
    172 			break;
    173 		case 'F':
    174 			filter_file = optarg;
    175 			if (unveil(filter_file, "r") == -1)
    176 				err(2, "unveil");
    177 			break;
    178 		case 'i':
    179 			re_ignore_case++;
    180 			break;
    181 		case 'I':
    182 			read_file = optarg;
    183 			if (unveil(read_file, "r") == -1)
    184 				err(2, "unveil");
    185 			break;
    186 		case 'l':
    187 			setvbuf(stdout, NULL, _IOLBF, 0);
    188 			break;
    189 		case 'M':
    190 			re_multiline_match = 0;
    191 			break;
    192 		case 'n':
    193 			max_matches = strtonum(optarg, 1, UINT32_MAX, &errstr);
    194 			if (errstr != NULL)
    195 				errx(2, "num is %s: %s", errstr, optarg);
    196 			break;
    197 		case 'N':
    198 			show_proto++;
    199 			break;
    200 		case 'O':
    201 			dump_file = optarg;
    202 			if (unveil(dump_file, "wc") == -1)
    203 				err(2, "unveil");
    204 			break;
    205 		case 'p':
    206 			promisc = 0;
    207 			break;
    208 		case 'P':
    209 			nonprint_char = *optarg;
    210 			break;
    211 		case 'q':
    212 			quiet++;
    213 			break;
    214 		case 's':
    215 			snaplen = strtonum(optarg, 1, UINT32_MAX, &errstr);
    216 			if (errstr != NULL)
    217 				errx(2, "snaplen is %s: %s", errstr, optarg);
    218 		case 'S':
    219 			limitlen = strtonum(optarg, 1, UINT32_MAX, &errstr);
    220 			if (errstr != NULL)
    221 				errx(2, "limitlen is %s: %s", errstr, optarg);
    222 			break;
    223 		case 't':
    224 			print_time = &print_time_absolute;
    225 			break;
    226 		case 'v':
    227 			invert_match++;
    228 			break;
    229 		case 'T':
    230 			if (print_time == &print_time_diff) {
    231 				print_time = print_time_offset;
    232 				memset(&prev_ts, 0, sizeof(prev_ts));
    233 			} else {
    234 				print_time = &print_time_diff;
    235 				gettimeofday(&prev_ts, NULL);
    236 			}
    237 			break;
    238 		case 'w':
    239 			re_match_word++;
    240 			break;
    241 		case 'W':
    242 			if (!strcasecmp(optarg, "normal"))
    243 				dumper = &dump_formatted;
    244 			else if (!strcasecmp(optarg, "byline"))
    245 				dumper = &dump_byline;
    246 			else if (!strcasecmp(optarg, "none"))
    247 				dumper = &dump_unwrapped;
    248 			else if (!strcasecmp(optarg, "single")) {
    249 				dumper = &dump_unwrapped;
    250 				dump_single = 1;
    251 			} else {
    252 				warnx("invalid wrap method: %s", optarg);
    253 				usage();
    254 			}
    255 			break;
    256 		case 'x':
    257 			show_hex++;
    258 			break;
    259 		case 'X':
    260 			bin_match++;
    261 			break;
    262 		case 'h':
    263 			/* FALLTHROUGH */
    264 		default:
    265 			usage();
    266 		}
    267 	}
    268 
    269 	if (unveil(NULL, NULL) == -1)
    270 		err(2, "unveil");
    271 
    272 	if (show_hex && dumper != &dump_formatted) {
    273 		warnx("-x is incompatible with -W");
    274 		usage();
    275 	}
    276 	if (bin_match) {
    277 		if (re_ignore_case) {
    278 			warnx("-i is incompatible with -X");
    279 			usage();
    280 		} else if (re_multiline_match == 0) {
    281 			warnx("-M is incompatible with -X");
    282 			usage();
    283 		} else if (re_match_word) {
    284 			warnx("-w is incompatible with -X");
    285 			usage();
    286 		}
    287 	}
    288 	if (argv[optind])
    289 		match_data = argv[optind++];
    290 
    291 	/* Setup PCAP input */
    292 	if (setup_pcap_source() == -1)
    293 		clean_exit(-1);
    294 
    295 	/*
    296 	 * XXX: Originally, the filter would be setup again without the vlan
    297 	 * hack if the first one failed. Not sure if we need to do this.
    298 	 */
    299 	if (setup_bpf_filter(argv) == -1) {
    300 		warnx("cannot compile filter: %s", pcap_geterr(pd));
    301 		clean_exit(-1);
    302 	}
    303 
    304 	drop_privs();
    305 
    306 	if (quiet < 2)
    307 		printf("filter: %s\n", filter);
    308 	free(filter);
    309 	filter = NULL;
    310 
    311 	/* Setup matcher */
    312 	if (match_data) {
    313 		if (bin_match) {
    314 			if (setup_hex_match() == -1)
    315 				clean_exit(-1);
    316 		} else {
    317 			if (setup_pattern_match() == -1)
    318 				clean_exit(-1);
    319 		}
    320 
    321 		if (quiet < 2)
    322 			printf("%smatch: %s%s\n",
    323 			       invert_match ? "don't " : "",
    324 			       (bin_match && hex_exp_pfx) ? "0x" : "",
    325 			       match_data);
    326 
    327 		if (re_match_word)
    328 			free(match_data);
    329 	}
    330 
    331 	/* Misc */
    332 	if (dump_file) {
    333 		if ((pd_dump = pcap_dump_open(pd, dump_file)) == NULL) {
    334 			warnx("pcap_dump_open: %s", pcap_geterr(pd));
    335 			clean_exit(-2);
    336 		} else {
    337 			printf("output: %s\n", dump_file);
    338 		}
    339 	}
    340 	update_windowsize(0);
    341 
    342 	while (pcap_loop(pd, -1, (pcap_handler)process, 0))
    343 		;
    344 
    345 	clean_exit(0);
    346 
    347 	/* NOT REACHED */
    348 	return 0;
    349 }
    350 
    351 int
    352 setup_pcap_source(void)
    353 {
    354 	if (read_file) {
    355 		if ((pd = pcap_open_offline(read_file, pc_err)) == NULL) {
    356 			warnx("pcap_open_offline: %s", pc_err);
    357 			return -1;
    358 		}
    359 		live_read = 0;
    360 		printf("input: %s\n", read_file);
    361 	} else {
    362 		char *dev;
    363 		pcap_if_t *devs = NULL;
    364 
    365 		if (usedev != NULL) {
    366 			dev = usedev;
    367 		} else {
    368 			if (pcap_findalldevs(&devs, pc_err) == PCAP_ERROR) {
    369 				warnx("pcap_findalldevs: %s", pc_err);
    370 				return -1;
    371 			}
    372 			if (devs == NULL) {
    373 				warnx("pcap_findalldevs: no devices found");
    374 				return -1;
    375 			}
    376 
    377 			dev = devs->name;
    378 		}
    379 
    380 		pd = pcap_open_live(dev, snaplen, promisc, to, pc_err);
    381 		if (pd == NULL) {
    382 			warnx("pcap_open_live: %s", pc_err);
    383 			return -1;
    384 		}
    385 		if (pcap_lookupnet(dev, &net.s_addr, &mask.s_addr, pc_err) ==
    386 		    PCAP_ERROR) {
    387 			warnx("pcap_lookupnet: %s", pc_err);
    388 			memset(&net, 0, sizeof(net));
    389 			memset(&mask, 0, sizeof(mask));
    390 		}
    391 		if (quiet < 2) {
    392 			printf("interface: %s", dev);
    393 			if (net.s_addr && mask.s_addr)
    394 				printf(" (%s/%s)",
    395 				       inet_ntoa(net), inet_ntoa(mask));
    396 			printf("\n");
    397 		}
    398 
    399 		pcap_freealldevs(devs);
    400 	}
    401 
    402 	switch (pcap_datalink(pd)) {
    403 	case DLT_EN10MB:
    404 		link_offset = ETHHDR_SIZE;
    405 		break;
    406 	case DLT_IEEE802:
    407 		link_offset = TOKENRING_SIZE;
    408 		break;
    409 	case DLT_FDDI:
    410 		link_offset = FDDIHDR_SIZE;
    411 		break;
    412 	case DLT_SLIP:
    413 		link_offset = SLIPHDR_SIZE;
    414 		break;
    415 	case DLT_PPP:
    416 		link_offset = PPPHDR_SIZE;
    417 		break;
    418 	case DLT_LOOP:
    419 		/* FALLTHROUGH */
    420 	case DLT_NULL:
    421 		link_offset = LOOPHDR_SIZE;
    422 		break;
    423 	case DLT_RAW:
    424 		link_offset = RAWHDR_SIZE;
    425 		break;
    426 	case DLT_IEEE802_11_RADIO:
    427 		radiotap_present = 1;
    428 	case DLT_IEEE802_11:
    429 		link_offset = IEEE80211HDR_SIZE;
    430 		break;
    431 	case DLT_PFLOG:
    432 		link_offset = PFLOGHDR_SIZE;
    433 		break;
    434 	default:
    435 		warnx("fatal: unsupported interface type %u",
    436 		      pcap_datalink(pd));
    437 		return -1;
    438 	}
    439 
    440 	return 0;
    441 }
    442 
    443 int
    444 setup_bpf_filter(char **argv)
    445 {
    446 	if (filter_file) {
    447 		filter = get_filter_from_file();
    448 		if (pcap_compile(pd, &pcapfilter, filter, 0, mask.s_addr) == -1)
    449 			return -1;
    450 	} else if (argv[optind]) {
    451 		/*
    452 		 * XXX: Find a better way of doing this that doesn't eat memory.
    453 		 *
    454 		 * If the filter doesn't compile the first time,
    455 		 * we assume that there is no match expression and include the
    456 		 * previous argument in the filter.
    457 		 */
    458 		filter = get_filter_from_argv(&argv[optind]);
    459 
    460 		if (pcap_compile(pd, &pcapfilter, filter, 0, mask.s_addr)) {
    461 			free(filter);
    462 			filter = get_filter_from_argv(&argv[optind - 1]);
    463 
    464 			if (pcap_compile(pd, &pcapfilter, filter, 0,
    465 					 mask.s_addr))
    466 				return -1;
    467 
    468 			match_data = NULL;
    469 		}
    470 	} else {
    471 		filter = include_vlan ? strdup(BPF_TEMPLATE_IP_VLAN)
    472 				      : strdup(BPF_TEMPLATE_IP);
    473 		if (filter == NULL)
    474 			err(2, "strdup");
    475 
    476 		if (pcap_compile(pd, &pcapfilter, filter, 0, mask.s_addr))
    477 			return -1;
    478 	}
    479 
    480 	if (pcap_setfilter(pd, &pcapfilter))
    481 		return -1;
    482 
    483 	return 0;
    484 }
    485 
    486 int
    487 hextoc(char d, char *c)
    488 {
    489 	if (c == NULL)
    490 		return -1;
    491 
    492 	if (d >= '0' && d <= '9')
    493 		*c = d - '0';
    494 	else if (d >= 'A' && d <= 'F')
    495 		*c = d - 'A' + 10;
    496 	else if (d >= 'a' && d <= 'f')
    497 		*c = d - 'a' + 10;
    498 	else
    499 		return -1;
    500 
    501 	return 0;
    502 }
    503 
    504 int
    505 setup_hex_match(void)
    506 {
    507 	size_t len;
    508 	char *bytes = NULL, *str = match_data;
    509 	char ld, rd;
    510 
    511 	if (str == NULL || *str == '\0') {
    512 		warnx("hex expression is empty");
    513 		goto err;
    514 	}
    515 
    516 	len = strlen(str);
    517 	if (len % 2 != 0) {
    518 		warnx("hex expression has odd digits: %s", match_data);
    519 		goto err;
    520 	}
    521 
    522 	if (str[0] == '0' && (str[1] == 'X' || str[1] == 'x')) {
    523 		hex_exp_pfx = 0;
    524 		str += 2;
    525 		len -= 2;
    526 	}
    527 	if (len == 0) {
    528 		warnx("hex expression has no digits after prefix: %s",
    529 		      match_data);
    530 		goto err;
    531 	} else if (len / 2 > UINT16_MAX) {
    532 		/* XXX: Check bin_match_func to see if this is needed */
    533 		warnx("hex expression is too long: %s", match_data);
    534 		goto err;
    535 	}
    536 
    537 	if ((bytes = calloc(len / 2, 1)) == NULL)
    538 		err(2, "calloc");
    539 
    540 	for (size_t i = 0, j = 0; j < len; j += 2, i++) {
    541 		if (hextoc(str[j], &ld) == -1) {
    542 			warnx("hex expression has invalid digit '%c': %s",
    543 			      str[j], match_data);
    544 			goto err;
    545 		}
    546 		if (hextoc(str[j + 1], &rd) == -1) {
    547 			warnx("hex expression has invalid digit '%c': %s",
    548 			      str[j + 1], match_data);
    549 			goto err;
    550 		}
    551 		bytes[i] = (ld << 4) | rd;
    552 	}
    553 
    554 	bin_data = bytes;
    555 	match_len = len / 2;
    556 	matcher = bin_match_func;
    557 
    558 	return 0;
    559 err:
    560 	free(bytes);
    561 
    562 	return -1;
    563 }
    564 
    565 int
    566 setup_pattern_match(void)
    567 {
    568 	int pcre_options = PCRE_UNGREEDY;
    569 	char *word_regex;
    570 
    571 	if (re_ignore_case)
    572 		pcre_options |= PCRE_CASELESS;
    573 	if (re_multiline_match)
    574 		pcre_options |= PCRE_DOTALL;
    575 
    576 	if (re_match_word) {
    577 		if (asprintf(&word_regex, WORD_REGEX,
    578 			     match_data, match_data, match_data) < 0) {
    579 			warn("asprintf");
    580 			return -1;
    581 		}
    582 		match_data = word_regex;
    583 	}
    584 
    585 	pattern = pcre_compile(match_data, pcre_options, &re_err, &err_offset,
    586 			       NULL);
    587 	if (!pattern) {
    588 		warnx("pcre_compile: %s", re_err);
    589 		return -1;
    590 	}
    591 	pattern_extra = pcre_study(pattern, 0, &re_err);
    592 	matcher = re_match_func;
    593 
    594 	return 0;
    595 }
    596 
    597 static inline uint8_t
    598 vlan_frame_count(u_char *p, uint16_t limit)
    599 {
    600 	uint8_t *et = (uint8_t *)(p + 12);
    601 	uint16_t ether_type = EXTRACT_16BITS(et);
    602 	uint8_t count = 0;
    603 
    604 	while ((void *)et < (void *)(p + limit) &&
    605 	       ether_type != ETHERTYPE_IP &&
    606 	       ether_type != ETHERTYPE_IPV6) {
    607 		count++;
    608 		et += VLANHDR_SIZE;
    609 		ether_type = EXTRACT_16BITS(et);
    610 	}
    611 
    612 	return count;
    613 }
    614 
    615 void
    616 process(UNUSED u_char *d, struct pcap_pkthdr *h, u_char *p)
    617 {
    618 	uint8_t vlan_offset =
    619 	    include_vlan ? vlan_frame_count(p, h->caplen) * VLANHDR_SIZE : 0;
    620 
    621 	struct ip *ip4_pkt = (struct ip *)(p + link_offset + vlan_offset);
    622 	struct ip6_hdr *ip6_pkt =
    623 	    (struct ip6_hdr *)(p + link_offset + vlan_offset);
    624 
    625 	uint32_t ip_ver;
    626 
    627 	uint8_t ip_proto = 0;
    628 	uint32_t ip_hl = 0;
    629 	uint32_t ip_off = 0;
    630 
    631 	uint8_t fragmented = 0;
    632 	uint16_t frag_offset = 0;
    633 	uint32_t frag_id = 0;
    634 
    635 	char ip_src[INET6_ADDRSTRLEN + 1];
    636 	char ip_dst[INET6_ADDRSTRLEN + 1];
    637 
    638 	unsigned char *data;
    639 	uint32_t len = h->caplen - vlan_offset;
    640 
    641 	seen_frames++;
    642 
    643 	if (radiotap_present) {
    644 		uint16_t radio_len = ((struct NGREP_rtaphdr_t *)p)->it_len;
    645 		ip4_pkt = (struct ip *)(p + link_offset + radio_len);
    646 		len -= radio_len;
    647 	}
    648 	ip_ver = ip4_pkt->ip_v;
    649 
    650 	switch (ip_ver) {
    651 	case 4: {
    652 		ip_hl = ip4_pkt->ip_hl * 4;
    653 		ip_proto = ip4_pkt->ip_p;
    654 		ip_off = ntohs(ip4_pkt->ip_off);
    655 
    656 		fragmented = ip_off & (IP_MF | IP_OFFMASK);
    657 		frag_offset = (fragmented) ? (ip_off & IP_OFFMASK) * 8 : 0;
    658 		frag_id = ntohs(ip4_pkt->ip_id);
    659 
    660 		inet_ntop(AF_INET, &ip4_pkt->ip_src, ip_src, sizeof(ip_src));
    661 		inet_ntop(AF_INET, &ip4_pkt->ip_dst, ip_dst, sizeof(ip_dst));
    662 	} break;
    663 	case 6: {
    664 		ip_hl = sizeof(struct ip6_hdr);
    665 		ip_proto = ip6_pkt->ip6_nxt;
    666 
    667 		if (ip_proto == IPPROTO_FRAGMENT) {
    668 			struct ip6_frag *ip6_fraghdr;
    669 
    670 			ip6_fraghdr =
    671 			    (struct ip6_frag *)((unsigned char *)ip6_pkt +
    672 						ip_hl);
    673 			ip_hl += sizeof(struct ip6_frag);
    674 			ip_proto = ip6_fraghdr->ip6f_nxt;
    675 
    676 			fragmented = 1;
    677 			frag_offset =
    678 			    ntohs(ip6_fraghdr->ip6f_offlg & IP6F_OFF_MASK);
    679 			frag_id = ntohl(ip6_fraghdr->ip6f_ident);
    680 		}
    681 		inet_ntop(AF_INET6, &ip6_pkt->ip6_src, ip_src, sizeof(ip_src));
    682 		inet_ntop(AF_INET6, &ip6_pkt->ip6_dst, ip_dst, sizeof(ip_dst));
    683 	} break;
    684 	}
    685 
    686 	if (quiet < 1) {
    687 		printf("#");
    688 		fflush(stdout);
    689 	}
    690 
    691 	switch (ip_proto) {
    692 	case IPPROTO_TCP: {
    693 		struct tcphdr *tcp_pkt =
    694 		    (struct tcphdr *)((unsigned char *)ip4_pkt + ip_hl);
    695 		uint16_t tcphdr_offset = frag_offset ? 0 : tcp_pkt->th_off * 4;
    696 
    697 		data = (unsigned char *)tcp_pkt + tcphdr_offset;
    698 		len -= link_offset + ip_hl + tcphdr_offset;
    699 
    700 		if ((int32_t)len < 0)
    701 			len = 0;
    702 
    703 		dump_packet(h, p, ip_proto, data, len, ip_src, ip_dst,
    704 			    ntohs(tcp_pkt->th_sport), ntohs(tcp_pkt->th_dport),
    705 			    tcp_pkt->th_flags, tcphdr_offset, fragmented,
    706 			    frag_offset, frag_id);
    707 	} break;
    708 	case IPPROTO_UDP: {
    709 		struct udphdr *udp_pkt =
    710 		    (struct udphdr *)((unsigned char *)ip4_pkt + ip_hl);
    711 		uint16_t udphdr_offset = frag_offset ? 0 : sizeof(*udp_pkt);
    712 
    713 		data = (unsigned char *)udp_pkt + udphdr_offset;
    714 		len -= link_offset + ip_hl + udphdr_offset;
    715 
    716 		if ((int32_t)len < 0)
    717 			len = 0;
    718 
    719 		dump_packet(h, p, ip_proto, data, len, ip_src, ip_dst,
    720 			    ntohs(udp_pkt->uh_sport), ntohs(udp_pkt->uh_dport),
    721 			    0, udphdr_offset, fragmented, frag_offset, frag_id);
    722 	} break;
    723 
    724 	case IPPROTO_ICMP: {
    725 		struct icmp *icmp4_pkt =
    726 		    (struct icmp *)((unsigned char *)ip4_pkt + ip_hl);
    727 		uint16_t icmp4hdr_offset = frag_offset ? 0 : 4;
    728 
    729 		data = (unsigned char *)icmp4_pkt + icmp4hdr_offset;
    730 		len -= link_offset + ip_hl + icmp4hdr_offset;
    731 
    732 		if ((int32_t)len < 0)
    733 			len = 0;
    734 
    735 		dump_packet(h, p, ip_proto, data, len, ip_src, ip_dst,
    736 			    icmp4_pkt->icmp_type, icmp4_pkt->icmp_code, 0,
    737 			    icmp4hdr_offset, fragmented, frag_offset, frag_id);
    738 	} break;
    739 	case IPPROTO_ICMPV6: {
    740 		struct icmp6_hdr *icmp6_pkt =
    741 		    (struct icmp6_hdr *)((unsigned char *)ip6_pkt + ip_hl);
    742 		uint16_t icmp6hdr_offset = frag_offset ? 0 : 4;
    743 
    744 		data = (unsigned char *)icmp6_pkt + icmp6hdr_offset;
    745 		len -= link_offset + ip_hl + icmp6hdr_offset;
    746 
    747 		if ((int32_t)len < 0)
    748 			len = 0;
    749 
    750 		dump_packet(h, p, ip_proto, data, len, ip_src, ip_dst,
    751 			    icmp6_pkt->icmp6_type, icmp6_pkt->icmp6_code, 0,
    752 			    icmp6hdr_offset, fragmented, frag_offset, frag_id);
    753 	} break;
    754 	case IPPROTO_IGMP: {
    755 		struct igmp *igmp_pkt =
    756 		    (struct igmp *)((unsigned char *)ip4_pkt + ip_hl);
    757 		uint16_t igmphdr_offset = frag_offset ? 0 : 4;
    758 
    759 		data = (unsigned char *)igmp_pkt + igmphdr_offset;
    760 		len -= link_offset + ip_hl + igmphdr_offset;
    761 
    762 		if ((int32_t)len < 0)
    763 			len = 0;
    764 
    765 		dump_packet(h, p, ip_proto, data, len, ip_src, ip_dst,
    766 			    igmp_pkt->igmp_type, igmp_pkt->igmp_code, 0,
    767 			    igmphdr_offset, fragmented, frag_offset, frag_id);
    768 	} break;
    769 
    770 	default: {
    771 		data = (unsigned char *)ip4_pkt + ip_hl;
    772 		len -= link_offset + ip_hl;
    773 
    774 		if ((int32_t)len < 0)
    775 			len = 0;
    776 
    777 		dump_packet(h, p, ip_proto, data, len, ip_src, ip_dst, 0, 0, 0,
    778 			    0, fragmented, frag_offset, frag_id);
    779 	} break;
    780 	}
    781 
    782 	if (max_matches && matches >= max_matches)
    783 		clean_exit(0);
    784 
    785 	if (match_after && keep_matching)
    786 		keep_matching--;
    787 }
    788 
    789 void
    790 dump_packet(struct pcap_pkthdr *h, u_char *p, uint8_t proto,
    791 	    unsigned char *data, uint32_t len, const char *ip_src,
    792 	    const char *ip_dst, uint16_t sport, uint16_t dport, uint8_t flags,
    793 	    uint16_t hdr_offset, uint8_t frag, uint16_t frag_offset,
    794 	    uint32_t frag_id)
    795 {
    796 	uint16_t match_size, match_index;
    797 	char ident = '?';
    798 
    799 	if (!show_empty && len == 0)
    800 		return;
    801 
    802 	if (len > limitlen)
    803 		len = limitlen;
    804 
    805 	if (len > 0 &&
    806 	    matcher(data, len, &match_index, &match_size) == invert_match &&
    807 	    !keep_matching)
    808 		return;
    809 
    810 	if (!live_read && want_delay)
    811 		dump_delay(h);
    812 
    813 	switch (proto) {
    814 	case IPPROTO_TCP:
    815 		ident = 'T';
    816 		break;
    817 	case IPPROTO_UDP:
    818 		ident = 'U';
    819 		break;
    820 	case IPPROTO_ICMP:
    821 		/* FALLTHROUGH */
    822 	case IPPROTO_ICMPV6:
    823 		ident = 'I';
    824 		break;
    825 	case IPPROTO_IGMP:
    826 		ident = 'G';
    827 		break;
    828 	}
    829 
    830 	printf("\n%c", ident);
    831 
    832 	if (show_proto)
    833 		printf("(%u)", proto);
    834 
    835 	printf(" ");
    836 
    837 	if (print_time)
    838 		print_time(h);
    839 
    840 	if ((proto == IPPROTO_TCP || proto == IPPROTO_UDP) &&
    841 	    (sport || dport) && (hdr_offset || frag_offset == 0))
    842 		printf("%s:%u -> %s:%u", ip_src, sport, ip_dst, dport);
    843 	else
    844 		printf("%s -> %s", ip_src, ip_dst);
    845 
    846 	if (proto == IPPROTO_TCP && flags)
    847 		printf(" [%s%s%s%s%s%s%s%s]",
    848 		       (flags & TH_ACK)  ? "A" : "",
    849 		       (flags & TH_SYN)  ? "S" : "",
    850 		       (flags & TH_RST)  ? "R" : "",
    851 		       (flags & TH_FIN)  ? "F" : "",
    852 		       (flags & TH_URG)  ? "U" : "",
    853 		       (flags & TH_PUSH) ? "P" : "",
    854 		       (flags & TH_ECE)  ? "E" : "",
    855 		       (flags & TH_CWR)  ? "C" : "");
    856 
    857 	switch (proto) {
    858 	case IPPROTO_ICMP:
    859 		/* FALLTHROUTH */
    860 	case IPPROTO_ICMPV6:
    861 		/* FALLTHROUGH */
    862 	case IPPROTO_IGMP:
    863 		printf(" %u:%u", sport, dport);
    864 	}
    865 
    866 	if (frag)
    867 		printf(" %s%u@%u:%u", frag_offset ? "+" : "",
    868 		       frag_id, frag_offset, len);
    869 
    870 	if (dump_single)
    871 		printf(" ");
    872 	else
    873 		printf(" #%u\n", seen_frames);
    874 
    875 	if (quiet < 3 && len > 0)
    876 		dumper(data, len, match_index, match_size);
    877 
    878 	if (pd_dump)
    879 		pcap_dump((u_char *)pd_dump, h, p);
    880 }
    881 
    882 int8_t
    883 re_match_func(unsigned char *data, uint32_t len, uint16_t *mindex,
    884 	      uint16_t *msize)
    885 {
    886 	static int matchpos[2] = {0};
    887 	int did_match = pcre_exec(pattern, 0, (const char *)data, (int)len,
    888 				  0, 0, matchpos, 2);
    889 	if (did_match < 0) {
    890 		if (did_match == PCRE_ERROR_NOMATCH) {
    891 			return 0;
    892 		} else {
    893 			warnx("pcre_exec: returned %d", did_match);
    894 			clean_exit(-1);
    895 		}
    896 	}
    897 
    898 	*mindex = matchpos[0];
    899 	*msize = matchpos[1] - matchpos[0];
    900 	matches++;
    901 
    902 	if (match_after && keep_matching != match_after)
    903 		keep_matching = match_after;
    904 
    905 	return 1;
    906 }
    907 
    908 int8_t
    909 bin_match_func(unsigned char *data, uint32_t len, uint16_t *mindex,
    910 	       uint16_t *msize)
    911 {
    912 	int32_t stop = len - match_len;
    913 	unsigned char *p;
    914 
    915 	if (stop < 0)
    916 		return 0;
    917 
    918 	if ((p = memmem(data, len, bin_data, match_len)) != NULL) {
    919 		matches++;
    920 
    921 		if (match_after && keep_matching != match_after)
    922 			keep_matching = match_after;
    923 
    924 		*mindex = (uint16_t)(p - data);
    925 		*msize = match_len;
    926 
    927 		return 1;
    928 	}
    929 
    930 	return 0;
    931 }
    932 
    933 int8_t
    934 blank_match_func(UNUSED unsigned char *data, UNUSED uint32_t len,
    935 		 uint16_t *mindex, uint16_t *msize)
    936 {
    937 	matches++;
    938 
    939 	*mindex = 0;
    940 	*msize = 0;
    941 
    942 	return 1;
    943 }
    944 
    945 void
    946 dump_byline(unsigned char *data, uint32_t len, uint16_t mindex, uint16_t msize)
    947 {
    948 	const unsigned char *s = data;
    949 	uint8_t should_hilite = (msize && enable_hilite);
    950 	unsigned char *hilite_start = data + mindex;
    951 	unsigned char *hilite_end = hilite_start + msize;
    952 
    953 	while (s < data + len) {
    954 		if (should_hilite && s == hilite_start)
    955 			printf("%s", ANSI_hilite);
    956 
    957 		printf("%c", (*s == '\n' || isprint(*s)) ? *s : nonprint_char);
    958 		s++;
    959 
    960 		if (should_hilite && s == hilite_end)
    961 			printf("%s", ANSI_off);
    962 	}
    963 
    964 	printf("\n");
    965 }
    966 
    967 void
    968 dump_unwrapped(unsigned char *data, uint32_t len, uint16_t mindex,
    969 	       uint16_t msize)
    970 {
    971 	const unsigned char *s = data;
    972 	uint8_t should_hilite = (msize && enable_hilite);
    973 	unsigned char *hilite_start = data + mindex;
    974 	unsigned char *hilite_end = hilite_start + msize;
    975 
    976 	while (s < data + len) {
    977 		if (should_hilite && s == hilite_start)
    978 			printf("%s", ANSI_hilite);
    979 
    980 		printf("%c", isprint(*s) ? *s : nonprint_char);
    981 		s++;
    982 
    983 		if (should_hilite && s == hilite_end)
    984 			printf("%s", ANSI_off);
    985 	}
    986 
    987 	printf("\n");
    988 }
    989 
    990 void
    991 dump_formatted(unsigned char *data, uint32_t len, uint16_t mindex,
    992 	       uint16_t msize)
    993 {
    994 	uint8_t should_hilite = (msize && enable_hilite);
    995 	unsigned char *str = data;
    996 	uint8_t hiliting = 0;
    997 	uint8_t width = show_hex ? 16 : (ws_col - 5);
    998 	uint32_t i = 0, j = 0;
    999 
   1000 	while (i < len) {
   1001 		printf("  ");
   1002 
   1003 		if (show_hex) {
   1004 			for (j = 0; j < width; j++) {
   1005 				if (should_hilite && mindex <= i + j &&
   1006 				    i + j < mindex + msize) {
   1007 					hiliting = 1;
   1008 					printf("%s", ANSI_hilite);
   1009 				}
   1010 
   1011 				if (i + j < len)
   1012 					printf("%02x ", str[j]);
   1013 				else
   1014 					printf("   ");
   1015 
   1016 				if ((j + 1) % (width / 2) == 0)
   1017 					printf("   ");
   1018 
   1019 				if (hiliting) {
   1020 					hiliting = 0;
   1021 					printf("%s", ANSI_off);
   1022 				}
   1023 			}
   1024 		}
   1025 
   1026 		for (j = 0; j < width; j++) {
   1027 			if (should_hilite && mindex <= i + j &&
   1028 			    i + j < mindex + msize) {
   1029 				hiliting = 1;
   1030 				printf("%s", ANSI_hilite);
   1031 			}
   1032 
   1033 			if (i + j < len)
   1034 				printf("%c", isprint(str[j]) ? str[j]
   1035 							     : nonprint_char);
   1036 			else
   1037 				printf(" ");
   1038 
   1039 			if (hiliting) {
   1040 				hiliting = 0;
   1041 				printf("%s", ANSI_off);
   1042 			}
   1043 		}
   1044 
   1045 		str += width;
   1046 		i += j;
   1047 
   1048 		printf("\n");
   1049 	}
   1050 }
   1051 
   1052 char *
   1053 get_filter_from_file(void)
   1054 {
   1055 	char *fstr;
   1056 	size_t size;
   1057 	const char *template;
   1058 	int fd;
   1059 	struct stat st;
   1060 	ssize_t flen;
   1061 
   1062 	template = include_vlan ? BPF_TEMPLATE_IP_VLAN : BPF_TEMPLATE_IP;
   1063 
   1064 	if ((fd = open(filter_file, O_RDONLY)) == -1) {
   1065 		warn("cannot open %s", filter_file);
   1066 		clean_exit(-1);
   1067 	}
   1068 	if (fstat(fd, &st) == -1) {
   1069 		warn("cannot stat %s", filter_file);
   1070 		clean_exit(-1);
   1071 	}
   1072 	if (st.st_size >= SSIZE_MAX) {
   1073 		warn("file too long: %s", filter_file);
   1074 		clean_exit(-1);
   1075 	}
   1076 
   1077 	/* filter = "( " + file + " ) and " + template + '\0' */
   1078 	size = 2 + st.st_size + 7 + strlen(template) + 1;
   1079 	if (size >= SIZE_MAX)
   1080 		warnx("filter too long: %s", filter_file);
   1081 	if ((fstr = malloc(size)) == NULL)
   1082 		err(2, "malloc");
   1083 
   1084 	(void)strlcpy(fstr, "( ", size);
   1085 	flen = read(fd, fstr + 2, st.st_size);
   1086 	if (flen == -1) {
   1087 		warn("read %s", filter_file);
   1088 		clean_exit(-1);
   1089 	} else if (flen != st.st_size) {
   1090 		warn("short read of %s: expected %lld, got %zu",
   1091 		     filter_file, st.st_size, flen);
   1092 		clean_exit(-1);
   1093 	}
   1094 	for (char *s = fstr + 2; *s; s++)
   1095 		if (*s == '\n' || *s == '\r')
   1096 			*s = ' ';
   1097 	/*
   1098 	 * XXX: looks ugly if the file doesn't end in a newline.
   1099 	 * Then again, do we even need to pad the parens?
   1100 	 */
   1101 	(void)strlcat(fstr, ") and ", size);
   1102 	(void)strlcat(fstr, template, size);
   1103 
   1104 	return fstr;
   1105 }
   1106 
   1107 char *
   1108 get_filter_from_argv(char **argv)
   1109 {
   1110 	char *fstr;
   1111 	size_t size = 0;
   1112 	char **arg = argv;
   1113 	const char *template;
   1114 
   1115 	template = include_vlan ? BPF_TEMPLATE_IP_VLAN : BPF_TEMPLATE_IP;
   1116 
   1117 	if (arg == NULL)
   1118 		return NULL;
   1119 
   1120 	for (; *arg != NULL; arg++)
   1121 		size += strlen(*arg) + 1;
   1122 
   1123 	/* filter = "( " + args + ") and " + template + '\0' */
   1124 	size = 2 + size + 6 + strlen(template) + 1;
   1125 	if (size >= SIZE_MAX) {
   1126 		warnx("filter too long");
   1127 		clean_exit(-1);
   1128 	}
   1129 
   1130 	if ((fstr = malloc(size)) == NULL)
   1131 		err(2, "malloc");
   1132 
   1133 	(void)strlcpy(fstr, "( ", size);
   1134 	for (arg = argv; *arg != NULL; arg++) {
   1135 		(void)strlcat(fstr, *arg, size);
   1136 		(void)strlcat(fstr, " ", size);
   1137 	}
   1138 	(void)strlcat(fstr, ") and ", size);
   1139 	(void)strlcat(fstr, template, size);
   1140 
   1141 	return fstr;
   1142 }
   1143 
   1144 void
   1145 print_time_absolute(struct pcap_pkthdr *h)
   1146 {
   1147 	struct tm *t = localtime((const time_t *)&h->ts.tv_sec);
   1148 
   1149 	printf("%02u/%02u/%02u %02u:%02u:%02u.%06u ",
   1150 	       t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour,
   1151 	       t->tm_min, t->tm_sec, (uint32_t)h->ts.tv_usec);
   1152 }
   1153 
   1154 void
   1155 print_time_diff(struct pcap_pkthdr *h)
   1156 {
   1157 	uint32_t secs, usecs;
   1158 
   1159 	secs = h->ts.tv_sec - prev_ts.tv_sec;
   1160 	if (h->ts.tv_usec >= prev_ts.tv_usec)
   1161 		usecs = h->ts.tv_usec - prev_ts.tv_usec;
   1162 	else {
   1163 		secs--;
   1164 		usecs = 1000000 - (prev_ts.tv_usec - h->ts.tv_usec);
   1165 	}
   1166 
   1167 	printf("+%u.%06u ", secs, usecs);
   1168 
   1169 	prev_ts.tv_sec = h->ts.tv_sec;
   1170 	prev_ts.tv_usec = h->ts.tv_usec;
   1171 }
   1172 
   1173 void
   1174 print_time_offset(struct pcap_pkthdr *h)
   1175 {
   1176 	uint32_t secs, usecs;
   1177 
   1178 	secs = h->ts.tv_sec - prev_ts.tv_sec;
   1179 	if (h->ts.tv_usec >= prev_ts.tv_usec)
   1180 		usecs = h->ts.tv_usec - prev_ts.tv_usec;
   1181 	else {
   1182 		secs--;
   1183 		usecs = 1000000 - (prev_ts.tv_usec - h->ts.tv_usec);
   1184 	}
   1185 
   1186 	if (prev_ts.tv_sec == 0 && prev_ts.tv_usec == 0) {
   1187 		prev_ts.tv_sec = h->ts.tv_sec;
   1188 		prev_ts.tv_usec = h->ts.tv_usec;
   1189 		secs = 0;
   1190 		usecs = 0;
   1191 	}
   1192 	printf("+%u.%06u ", secs, usecs);
   1193 }
   1194 
   1195 void
   1196 dump_delay_proc_init(struct pcap_pkthdr *h)
   1197 {
   1198 	dump_delay = &dump_delay_proc;
   1199 
   1200 	prev_delay_ts.tv_sec = h->ts.tv_sec;
   1201 	prev_delay_ts.tv_usec = h->ts.tv_usec;
   1202 
   1203 	dump_delay(h);
   1204 }
   1205 
   1206 void
   1207 dump_delay_proc(struct pcap_pkthdr *h)
   1208 {
   1209 	uint32_t secs, usecs;
   1210 
   1211 	secs = h->ts.tv_sec - prev_delay_ts.tv_sec;
   1212 	if (h->ts.tv_usec >= prev_delay_ts.tv_usec)
   1213 		usecs = h->ts.tv_usec - prev_delay_ts.tv_usec;
   1214 	else {
   1215 		secs--;
   1216 		usecs = 1000000 - (prev_delay_ts.tv_usec - h->ts.tv_usec);
   1217 	}
   1218 
   1219 	sleep(secs);
   1220 	usleep(usecs);
   1221 
   1222 	prev_delay_ts.tv_sec = h->ts.tv_sec;
   1223 	prev_delay_ts.tv_usec = h->ts.tv_usec;
   1224 }
   1225 
   1226 void
   1227 update_windowsize(int32_t e)
   1228 {
   1229 	if (e == 0 && ws_col_forced)
   1230 		ws_col = ws_col_forced;
   1231 	else if (!ws_col_forced) {
   1232 		const struct winsize ws;
   1233 
   1234 		if (!ioctl(0, TIOCGWINSZ, &ws)) {
   1235 			ws_row = ws.ws_row;
   1236 			ws_col = ws.ws_col;
   1237 		} else {
   1238 			ws_row = 24;
   1239 			ws_col = 80;
   1240 		}
   1241 	}
   1242 }
   1243 
   1244 void
   1245 drop_privs(void)
   1246 {
   1247 	struct passwd *pw;
   1248 	gid_t gidset[1];
   1249 
   1250 	if ((pw = getpwnam(UNPRIV_USER)) == NULL) {
   1251 		warn("cannot drop privileges: getpwnam");
   1252 		clean_exit(-1);
   1253 	}
   1254 	endpwent();
   1255 
   1256 	if (chroot("/var/empty") == -1) {
   1257 		warn("cannot drop privileges: chroot");
   1258 		clean_exit(-1);
   1259 	}
   1260 	if (chdir("/") == -1) {
   1261 		warn("cannot drop privileges: chdir");
   1262 		clean_exit(-1);
   1263 	}
   1264 
   1265 	gidset[0] = pw->pw_gid;
   1266 	if (setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) == -1) {
   1267 		warn("cannot drop privileges: setresgid");
   1268 		clean_exit(-1);
   1269 	}
   1270 	if (setgroups(1, gidset) == -1) {
   1271 		warn("cannot drop privileges: setgroups");
   1272 		clean_exit(-1);
   1273 	}
   1274 	if (setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid) == -1) {
   1275 		warn("cannot drop privileges: setresuid");
   1276 		clean_exit(-1);
   1277 	}
   1278 
   1279 }
   1280 
   1281 void
   1282 usage(void)
   1283 {
   1284 	fprintf(stderr,
   1285 		"usage: %s [-CDeilMNpqtTvwxX] [-A num] [-c cols] [-d dev] [-F file] [-I pcap_dump]\n"
   1286 		"             [-n num] [-O pcap_dump] [-P char] [-S limitlen] [-s snaplen]\n"
   1287 		"             [-W normal | byline | single | none] [expression] [filter]\n",
   1288 		getprogname());
   1289 
   1290 	exit(2);
   1291 }
   1292 
   1293 void
   1294 clean_exit(int sig)
   1295 {
   1296 	int code;
   1297 
   1298 	signal(SIGINT, SIG_IGN);
   1299 	signal(SIGABRT, SIG_IGN);
   1300 	signal(SIGQUIT, SIG_IGN);
   1301 	signal(SIGPIPE, SIG_IGN);
   1302 	signal(SIGWINCH, SIG_IGN);
   1303 
   1304 	if (sig == -1)
   1305 		code = 2;
   1306 	else if (matches > 0)
   1307 		code = 0;
   1308 	else
   1309 		code = 1;
   1310 
   1311 	if (quiet < 1 && sig >= 0)
   1312 		puts("exit");
   1313 
   1314 	if (pattern)
   1315 		pcre_free(pattern);
   1316 	if (pattern_extra)
   1317 		pcre_free(pattern_extra);
   1318 	if (bin_data)
   1319 		free(bin_data);
   1320 
   1321 	/*
   1322 	 * We used to report pcap_stats; but PCAP manpage says pcap_stats
   1323 	 * "may or may not" be accurate. So useless. :-( And confusing for a
   1324 	 * user to see counts not match what ngrep thinks.
   1325 	 */
   1326 	if (quiet < 1 && sig >= 0 && read_file == NULL)
   1327 		printf("%u received, %u matched\n", seen_frames, matches);
   1328 
   1329 	if (pd)
   1330 		pcap_close(pd);
   1331 	if (pd_dumppcap)
   1332 		pcap_close(pd_dumppcap);
   1333 	if (pd_dump)
   1334 		pcap_dump_close(pd_dump);
   1335 
   1336 	exit(code);
   1337 }