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