"Fossies" - the Fresh Open Source Software Archive

Member "ngrep-1_47/ngrep.c" (7 Sep 2017, 41892 Bytes) of package /linux/misc/ngrep-1_47.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "ngrep.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes reports: 1_45_vs_1_47 or 1_46_1_vs_1_47.

    1 /*
    2  * Copyright (c) 2017  Jordan Ritter <jpr5@darkridge.com>
    3  *
    4  * Please refer to the LICENSE file for more information.
    5  *
    6  */
    7 
    8 #if defined(BSD) || defined(SOLARIS) || defined(MACOSX)
    9 #include <unistd.h>
   10 #include <ctype.h>
   11 #include <sys/types.h>
   12 #include <sys/socket.h>
   13 #include <netinet/in.h>
   14 #include <netinet/in_systm.h>
   15 #include <net/if.h>
   16 #include <arpa/inet.h>
   17 #include <sys/tty.h>
   18 #include <pwd.h>
   19 #endif
   20 
   21 #if defined(OSF1)
   22 #include <sys/types.h>
   23 #include <sys/socket.h>
   24 #include <netinet/in.h>
   25 #include <netinet/in_systm.h>
   26 #include <net/route.h>
   27 #include <sys/mbuf.h>
   28 #include <arpa/inet.h>
   29 #include <unistd>
   30 #include <pwd.h>
   31 #endif
   32 
   33 #if defined(LINUX) || defined(__GLIBC__) || defined(__GNU__)
   34 #include <getopt.h>
   35 #include <arpa/inet.h>
   36 #include <ctype.h>
   37 #include <time.h>
   38 #include <unistd.h>
   39 #include <pwd.h>
   40 #include <grp.h>
   41 #endif
   42 
   43 #if defined(AIX)
   44 #include <sys/machine.h>
   45 #include <sys/types.h>
   46 #include <netinet/in.h>
   47 #include <time.h>
   48 #include <unistd.h>
   49 #include <pwd.h>
   50 #endif
   51 
   52 #if defined(_WIN32)
   53 #include <io.h>
   54 #include <getopt.h>
   55 #include <winsock2.h>
   56 #include <ws2tcpip.h>
   57 #include <types.h>
   58 #include <config.h>
   59 
   60 #define strcasecmp stricmp
   61 #define strncasecmp strnicmp
   62 
   63 #else
   64 
   65 #include <netinet/ip.h>
   66 #include <netinet/tcp.h>
   67 #include <netinet/udp.h>
   68 #include <netinet/ip_icmp.h>
   69 #include <netinet/igmp.h>
   70 
   71 #endif
   72 
   73 #include <stdlib.h>
   74 #include <string.h>
   75 #include <signal.h>
   76 #include <locale.h>
   77 
   78 #if !defined(_WIN32)
   79 #include <errno.h>
   80 #include <sys/ioctl.h>
   81 #endif
   82 
   83 #include <pcap.h>
   84 
   85 #ifdef HAVE_CONFIG_H
   86 #include "config.h"
   87 #endif
   88 
   89 #if USE_IPv6 && !defined(_WIN32)
   90 #include <netinet/ip6.h>
   91 #include <netinet/icmp6.h>
   92 #endif
   93 
   94 #if USE_PCRE
   95 #include <pcre.h>
   96 #else
   97 #include <regex.h>
   98 #endif
   99 
  100 #include "ngrep.h"
  101 
  102 
  103 /*
  104  * Configuration Options
  105  */
  106 
  107 uint32_t snaplen = 65535, limitlen = 65535, promisc = 1, to = 100;
  108 uint32_t match_after = 0, keep_matching = 0, matches = 0, max_matches = 0;
  109 uint32_t seen_frames = 0;
  110 
  111 #if USE_TCPKILL
  112 uint32_t tcpkill_active = 0;
  113 #endif
  114 
  115 uint8_t  re_match_word = 0, re_ignore_case = 0, re_multiline_match = 1;
  116 uint8_t  show_empty = 0, show_hex = 0, show_proto = 0, quiet = 0;
  117 uint8_t  invert_match = 0, bin_match = 0;
  118 uint8_t  live_read = 1, want_delay = 0;
  119 uint8_t  dont_dropprivs = 0;
  120 uint8_t  enable_hilite = 0;
  121 
  122 char *read_file = NULL, *dump_file = NULL;
  123 char *usedev = NULL;
  124 
  125 char nonprint_char = '.';
  126 
  127 /*
  128  * GNU Regex/PCRE
  129  */
  130 
  131 #if USE_PCRE
  132 int32_t err_offset;
  133 char *re_err = NULL;
  134 
  135 pcre *pattern = NULL;
  136 pcre_extra *pattern_extra = NULL;
  137 #else
  138 const char *re_err = NULL;
  139 
  140 struct re_pattern_buffer pattern;
  141 #endif
  142 
  143 /*
  144  * Matching
  145  */
  146 
  147 char *match_data = NULL, *bin_data = NULL;
  148 uint16_t match_len = 0;
  149 int8_t (*match_func)() = &blank_match_func;
  150 
  151 int8_t dump_single = 0;
  152 void (*dump_func)(unsigned char *, uint32_t, uint16_t, uint16_t) = &dump_formatted;
  153 
  154 /*
  155  * BPF/Network
  156  */
  157 
  158 char *filter = NULL, *filter_file = NULL;
  159 char pc_err[PCAP_ERRBUF_SIZE];
  160 uint8_t link_offset;
  161 uint8_t radiotap_present = 0;
  162 uint8_t include_vlan = USE_VLAN_HACK;
  163 
  164 pcap_t *pd = NULL, *pd_dumppcap = NULL;
  165 pcap_dumper_t *pd_dump = NULL;
  166 struct bpf_program pcapfilter;
  167 struct in_addr net, mask;
  168 
  169 /*
  170  * Timestamp/delay functionality
  171  */
  172 
  173 struct timeval prev_ts = {0, 0}, prev_delay_ts = {0,0};
  174 #if defined(_WIN32)
  175 struct timeval delay_tv;
  176 FD_SET delay_fds;
  177 SOCKET delay_socket = 0;
  178 #endif
  179 
  180 void (*print_time)() = NULL, (*dump_delay)() = dump_delay_proc_init;
  181 
  182 
  183 /*
  184  * Window-size functionality (adjust output based on width of console display)
  185  */
  186 
  187 uint32_t ws_row, ws_col = 80, ws_col_forced = 0;
  188 
  189 
  190 int main(int argc, char **argv) {
  191     int32_t c;
  192 
  193     signal(SIGINT,   clean_exit);
  194     signal(SIGABRT,  clean_exit);
  195 
  196 #if !defined(_WIN32)
  197     signal(SIGQUIT,  clean_exit);
  198     signal(SIGPIPE,  clean_exit);
  199     signal(SIGWINCH, update_windowsize);
  200 #endif
  201 
  202     setlocale(LC_ALL, "");
  203 
  204 #if !defined(_WIN32)
  205     {
  206         char const *locale = getenv("LANG");
  207         if (locale == NULL)
  208             locale = "en_US";
  209 
  210         setlocale(LC_CTYPE, locale);
  211     }
  212 #endif
  213 
  214     while ((c = getopt(argc, argv, "LNhXViwqpevxlDtTRMK:Cs:n:c:d:A:I:O:S:P:F:W:")) != EOF) {
  215         switch (c) {
  216             case 'W': {
  217                 if (!strcasecmp(optarg, "normal"))
  218                     dump_func = &dump_formatted;
  219                 else if (!strcasecmp(optarg, "byline"))
  220                     dump_func = &dump_byline;
  221                 else if (!strcasecmp(optarg, "none"))
  222                     dump_func = &dump_unwrapped;
  223                 else if (!strcasecmp(optarg, "single")) {
  224                     dump_func = &dump_unwrapped;
  225                     dump_single = 1;
  226                 } else {
  227                     printf("fatal: unknown wrap method '%s'\n", optarg);
  228                     usage();
  229                 }
  230             } break;
  231 
  232             case 'F':
  233                 filter_file = optarg;
  234                 break;
  235             case 'P':
  236                 nonprint_char = *optarg;
  237                 break;
  238             case 'S': {
  239                 limitlen = _atoui32(optarg);
  240                 break;
  241             }
  242             case 'O':
  243                 dump_file = optarg;
  244                 break;
  245             case 'I':
  246                 read_file = optarg;
  247                 break;
  248             case 'A':
  249                 match_after = _atoui32(optarg);
  250                 if (match_after < UINT32_MAX)
  251                     match_after++;
  252                 break;
  253 #if defined(_WIN32)
  254             case 'L':
  255                 win32_listdevices();
  256                 clean_exit(2);
  257             case 'd':
  258                 usedev = win32_usedevice(optarg);
  259                 break;
  260 #else
  261             case 'L':
  262                 perror("-L is a Win32-only option");
  263                 clean_exit(2);
  264             case 'd':
  265                 usedev = optarg;
  266                 /* Linux: any = DLT_LINUX_SLL, pcap says incompatible with VLAN */
  267                 if (!strncasecmp(usedev, "any", 3))
  268                     include_vlan = 0;
  269                 break;
  270 #endif
  271             case 'c':
  272                 ws_col_forced = atoi(optarg);
  273                 break;
  274             case 'n':
  275                 max_matches = _atoui32(optarg);
  276                 break;
  277             case 's': {
  278                 uint16_t value = _atoui32(optarg);
  279                 if (value > 0)
  280                     snaplen = value;
  281             } break;
  282             case 'C':
  283                 enable_hilite = 1;
  284                 break;
  285             case 'M':
  286                 re_multiline_match = 0;
  287                 break;
  288             case 'R':
  289                 dont_dropprivs = 1;
  290                 break;
  291             case 'T':
  292                 if (print_time == &print_time_diff) {
  293                     print_time = print_time_offset;
  294                     memset(&prev_ts, 0, sizeof(prev_ts));
  295                 } else {
  296                     print_time = &print_time_diff;
  297 #if defined(_WIN32)
  298                     prev_ts.tv_sec  = (uint32_t)time(NULL);
  299                     prev_ts.tv_usec = 0;
  300 #else
  301                     gettimeofday(&prev_ts, NULL);
  302 #endif
  303                 }
  304                 break;
  305             case 't':
  306                 print_time = &print_time_absolute;
  307                 break;
  308             case 'D':
  309                 want_delay = 1;
  310                 break;
  311             case 'l':
  312                 setvbuf(stdout, NULL, _IOLBF, 0);
  313                 break;
  314             case 'x':
  315                 show_hex++;
  316                 break;
  317             case 'v':
  318                 invert_match++;
  319                 break;
  320             case 'e':
  321                 show_empty++;
  322                 break;
  323             case 'p':
  324                 promisc = 0;
  325                 break;
  326             case 'q':
  327                 quiet++;
  328                 break;
  329             case 'w':
  330                 re_match_word++;
  331                 break;
  332             case 'i':
  333                 re_ignore_case++;
  334                 break;
  335             case 'V':
  336                 version();
  337             case 'X':
  338                 bin_match++;
  339                 break;
  340             case 'N':
  341                 show_proto++;
  342                 break;
  343 #if USE_TCPKILL
  344             case 'K':
  345                 tcpkill_active = _atoui32(optarg);
  346                 break;
  347 #endif
  348             case 'h':
  349                 usage();
  350             default:
  351                 usage();
  352         }
  353     }
  354 
  355     if (show_hex && dump_func != &dump_formatted) {
  356         printf("fatal: -x (hex dump) is incompatible with -W (alternate format)\n");
  357         usage();
  358     }
  359 
  360     if (argv[optind])
  361         match_data = argv[optind++];
  362 
  363 #if USE_TCPKILL
  364     if (tcpkill_active)
  365         tcpkill_init();
  366 #endif
  367 
  368     /* Setup PCAP input */
  369 
  370     if (setup_pcap_source())
  371         clean_exit(2);
  372 
  373     /* Setup BPF filter */
  374 
  375     if (setup_bpf_filter(argv)) {
  376         include_vlan = 0;
  377         if (filter) { free(filter); filter = NULL; }
  378 
  379         if (setup_bpf_filter(argv)) {
  380             pcap_perror(pd, "pcap");
  381             clean_exit(2);
  382         }
  383     }
  384 
  385     if (filter) {
  386         if (quiet < 2)
  387             printf("filter: %s\n", filter);
  388         free(filter);
  389     }
  390 
  391     /* Setup matcher */
  392 
  393     if (match_data) {
  394         if (setup_matcher())
  395             clean_exit(2);
  396 
  397         if (quiet < 2 && strlen(match_data))
  398             printf("%smatch: %s%s\n", invert_match?"don't ":"",
  399                    (bin_data && !strchr(match_data, 'x'))?"0x":"", match_data);
  400 
  401         if (re_match_word) free(match_data);
  402     }
  403 
  404     /* Misc */
  405 
  406     if (dump_file) {
  407         pd_dump = pcap_dump_open(pd, dump_file);
  408         if (!pd_dump) {
  409             fprintf(stderr, "fatal: %s\n", pcap_geterr(pd));
  410             clean_exit(2);
  411         } else printf("output: %s\n", dump_file);
  412     }
  413 
  414     update_windowsize(0);
  415 
  416 #if defined(_WIN32)
  417     win32_initwinsock();
  418 #endif
  419 
  420 #if !defined(_WIN32) && USE_DROPPRIVS
  421     drop_privs();
  422 #endif
  423 
  424     while (pcap_loop(pd, -1, (pcap_handler)process, 0));
  425 
  426     clean_exit(0);
  427 
  428     /* NOT REACHED */
  429     return 0;
  430 }
  431 
  432 int setup_pcap_source(void) {
  433     if (read_file) {
  434 
  435         if (!(pd = pcap_open_offline(read_file, pc_err))) {
  436             perror(pc_err);
  437             return 1;
  438         }
  439 
  440         live_read = 0;
  441         printf("input: %s\n", read_file);
  442 
  443     } else {
  444 
  445         char *dev = usedev ? usedev :
  446 #if defined(_WIN32)
  447             win32_choosedevice();
  448 #else
  449             pcap_lookupdev(pc_err);
  450 #endif
  451 
  452         if (!dev) {
  453             perror(pc_err);
  454             return 1;
  455         }
  456 
  457         if ((pd = pcap_open_live(dev, snaplen, promisc, to, pc_err)) == NULL) {
  458             perror(pc_err);
  459             return 1;
  460         }
  461 
  462         if (pcap_lookupnet(dev, &net.s_addr, &mask.s_addr, pc_err) == -1) {
  463             perror(pc_err);
  464             memset(&net, 0, sizeof(net));
  465             memset(&mask, 0, sizeof(mask));
  466         }
  467 
  468         if (quiet < 2) {
  469             printf("interface: %s", dev);
  470             if (net.s_addr && mask.s_addr) {
  471                 printf(" (%s/", inet_ntoa(net));
  472                 printf("%s)", inet_ntoa(mask));
  473             }
  474             printf("\n");
  475         }
  476     }
  477 
  478     switch(pcap_datalink(pd)) {
  479         case DLT_EN10MB:
  480             link_offset = ETHHDR_SIZE;
  481             break;
  482 
  483         case DLT_IEEE802:
  484             link_offset = TOKENRING_SIZE;
  485             break;
  486 
  487         case DLT_FDDI:
  488             link_offset = FDDIHDR_SIZE;
  489             break;
  490 
  491         case DLT_SLIP:
  492             link_offset = SLIPHDR_SIZE;
  493             break;
  494 
  495         case DLT_PPP:
  496             link_offset = PPPHDR_SIZE;
  497             break;
  498 
  499 #if HAVE_DLT_LOOP
  500         case DLT_LOOP:
  501 #endif
  502         case DLT_NULL:
  503             link_offset = LOOPHDR_SIZE;
  504             break;
  505 
  506 #if HAVE_DLT_RAW
  507         case DLT_RAW:
  508             link_offset = RAWHDR_SIZE;
  509             break;
  510 #endif
  511 
  512 #if HAVE_DLT_LINUX_SLL
  513         case DLT_LINUX_SLL:
  514             link_offset = ISDNHDR_SIZE;
  515             include_vlan = 0;
  516             break;
  517 #endif
  518 
  519 #if HAVE_DLT_IEEE802_11_RADIO
  520         case DLT_IEEE802_11_RADIO:
  521             radiotap_present = 1;
  522 #endif
  523 
  524 #if HAVE_DLT_IEEE802_11
  525         case DLT_IEEE802_11:
  526             link_offset = IEEE80211HDR_SIZE;
  527             break;
  528 #endif
  529 
  530 #if HAVE_DLT_PFLOG
  531         case DLT_PFLOG:
  532             link_offset = PFLOGHDR_SIZE;
  533             break;
  534 #endif
  535 
  536 #if HAVE_DLT_IPNET
  537         case DLT_IPNET:
  538             link_offset = IPNETHDR_SIZE;
  539             include_vlan = 0;
  540             break;
  541 #endif
  542 
  543         default:
  544             fprintf(stderr, "fatal: unsupported interface type %u\n", pcap_datalink(pd));
  545             return 1;
  546     }
  547 
  548     return 0;
  549 }
  550 
  551 int setup_bpf_filter(char **argv) {
  552     if (filter_file) {
  553         char buf[1024] = {0};
  554         FILE *f = fopen(filter_file, "r");
  555 
  556         if (!f || !fgets(buf, sizeof(buf)-1, f)) {
  557             fprintf(stderr, "fatal: unable to get filter from %s: %s\n", filter_file, strerror(errno));
  558             usage();
  559         }
  560 
  561         fclose(f);
  562 
  563         filter = get_filter_from_string(buf);
  564 
  565         if (pcap_compile(pd, &pcapfilter, filter, 0, mask.s_addr))
  566             return 1;
  567 
  568     } else if (argv[optind]) {
  569         filter = get_filter_from_argv(&argv[optind]);
  570 
  571         if (pcap_compile(pd, &pcapfilter, filter, 0, mask.s_addr)) {
  572             free(filter);
  573             filter = get_filter_from_argv(&argv[optind-1]);
  574 
  575 #if USE_PCAP_RESTART
  576             PCAP_RESTART_FUNC();
  577 #endif
  578 
  579             if (pcap_compile(pd, &pcapfilter, filter, 0, mask.s_addr))
  580                 return 1;
  581 
  582             match_data = NULL;
  583         }
  584 
  585     } else {
  586         filter = include_vlan ? strdup(BPF_TEMPLATE_IP_VLAN) : strdup(BPF_TEMPLATE_IP);
  587 
  588         if (pcap_compile(pd, &pcapfilter, filter, 0, mask.s_addr))
  589             return 1;
  590     }
  591 
  592     if (pcap_setfilter(pd, &pcapfilter))
  593         return 1;
  594 
  595     return 0;
  596 }
  597 
  598 int setup_matcher(void) {
  599     if (bin_match) {
  600         uint32_t i = 0, n;
  601         uint32_t len;
  602         char *s, *d;
  603 
  604         if (re_match_word || re_ignore_case) {
  605             fprintf(stderr, "fatal: regex switches are incompatible with binary matching\n");
  606             return 1;
  607         }
  608 
  609         len = (uint32_t)strlen(match_data);
  610         if (len % 2 != 0 || !strishex(match_data)) {
  611             fprintf(stderr, "fatal: invalid hex string specified\n");
  612             return 1;
  613         }
  614 
  615         bin_data = (char*)malloc(len / 2);
  616         memset(bin_data, 0, len / 2);
  617         d = bin_data;
  618 
  619         if ((s = strchr(match_data, 'x')))
  620             len -= (uint32_t)(++s - match_data - 1);
  621         else s = match_data;
  622 
  623         while (i <= len) {
  624             sscanf(s+i, "%2x", &n);
  625             *d++ = n;
  626             i += 2;
  627         }
  628 
  629         match_len = len / 2;
  630         match_func = &bin_match_func;
  631 
  632     } else {
  633 
  634 #if USE_PCRE
  635         uint32_t pcre_options = PCRE_UNGREEDY;
  636 
  637         if (re_ignore_case)
  638             pcre_options |= PCRE_CASELESS;
  639 
  640         if (re_multiline_match)
  641             pcre_options |= PCRE_DOTALL;
  642 #else
  643         re_syntax_options = RE_CHAR_CLASSES | RE_NO_BK_PARENS | RE_NO_BK_VBAR |
  644             RE_CONTEXT_INDEP_ANCHORS | RE_CONTEXT_INDEP_OPS;
  645 
  646         if (re_multiline_match)
  647             re_syntax_options |= RE_DOT_NEWLINE;
  648 
  649         if (re_ignore_case) {
  650             uint32_t i;
  651             char *s;
  652 
  653             pattern.translate = (char*)malloc(256);
  654             s = pattern.translate;
  655 
  656             for (i = 0; i < 256; i++)
  657                 s[i] = i;
  658             for (i = 'A'; i <= 'Z'; i++)
  659                 s[i] = i + 32;
  660 
  661             s = match_data;
  662             while (*s) {
  663                 *s = tolower(*s);
  664                 s++;
  665             }
  666 
  667         } else pattern.translate = NULL;
  668 #endif
  669 
  670         if (re_match_word) {
  671             char *word_regex = (char*)malloc(strlen(match_data) * 3 + strlen(WORD_REGEX));
  672             sprintf(word_regex, WORD_REGEX, match_data, match_data, match_data);
  673             match_data = word_regex;
  674         }
  675 
  676 #if USE_PCRE
  677         pattern = pcre_compile(match_data, pcre_options, (const char **)&re_err, &err_offset, 0);
  678 
  679         if (!pattern) {
  680             fprintf(stderr, "compile failed: %s\n", re_err);
  681             return 1;
  682         }
  683 
  684         pattern_extra = pcre_study(pattern, 0, (const char **)&re_err);
  685 #else
  686         re_err = re_compile_pattern(match_data, strlen(match_data), &pattern);
  687         if (re_err) {
  688             fprintf(stderr, "regex compile: %s\n", re_err);
  689             return 1;
  690         }
  691 
  692         pattern.fastmap = (char*)malloc(256);
  693         if (re_compile_fastmap(&pattern)) {
  694             perror("fastmap compile failed");
  695             return 1;
  696         }
  697 #endif
  698 
  699         match_func = &re_match_func;
  700     }
  701 
  702     return 0;
  703 }
  704 
  705 static inline uint8_t vlan_frame_count(u_char *p, uint16_t limit) {
  706   uint8_t *et = (uint8_t*)(p + 12);
  707   uint16_t ether_type = EXTRACT_16BITS(et);
  708   uint8_t count = 0;
  709 
  710   while ((void*)et < (void*)(p + limit) &&
  711          ether_type != ETHERTYPE_IP &&
  712          ether_type != ETHERTYPE_IPV6) {
  713       count++;
  714       et += VLANHDR_SIZE;
  715       ether_type = EXTRACT_16BITS(et);
  716   }
  717 
  718   return count;
  719 }
  720 
  721 void process(u_char *d, struct pcap_pkthdr *h, u_char *p) {
  722     uint8_t vlan_offset = include_vlan ? vlan_frame_count(p, h->caplen) * VLANHDR_SIZE : 0;
  723 
  724     struct ip      *ip4_pkt = (struct ip *)    (p + link_offset + vlan_offset);
  725 #if USE_IPv6
  726     struct ip6_hdr *ip6_pkt = (struct ip6_hdr*)(p + link_offset + vlan_offset);
  727 #endif
  728 
  729     uint32_t ip_ver;
  730 
  731     uint8_t  ip_proto = 0;
  732     uint32_t ip_hl    = 0;
  733     uint32_t ip_off   = 0;
  734 
  735     uint8_t  fragmented  = 0;
  736     uint16_t frag_offset = 0;
  737     uint32_t frag_id     = 0;
  738 
  739     char ip_src[INET6_ADDRSTRLEN + 1],
  740          ip_dst[INET6_ADDRSTRLEN + 1];
  741 
  742     unsigned char *data;
  743     uint32_t len = h->caplen - vlan_offset;
  744 
  745     seen_frames++;
  746 
  747 #if HAVE_DLT_IEEE802_11_RADIO
  748     if (radiotap_present) {
  749         uint16_t radio_len = ((struct NGREP_rtaphdr_t *)(p))->it_len;
  750         ip4_pkt = (struct ip *)(p + link_offset + radio_len);
  751         len    -= radio_len;
  752     }
  753 #endif
  754 
  755     ip_ver = ip4_pkt->ip_v;
  756 
  757     switch (ip_ver) {
  758 
  759         case 4: {
  760 #if defined(AIX)
  761 #undef ip_hl
  762             ip_hl       = ip4_pkt->ip_ff.ip_fhl * 4;
  763 #else
  764             ip_hl       = ip4_pkt->ip_hl * 4;
  765 #endif
  766             ip_proto    = ip4_pkt->ip_p;
  767             ip_off      = ntohs(ip4_pkt->ip_off);
  768 
  769             fragmented  = ip_off & (IP_MF | IP_OFFMASK);
  770             frag_offset = (fragmented) ? (ip_off & IP_OFFMASK) * 8 : 0;
  771             frag_id     = ntohs(ip4_pkt->ip_id);
  772 
  773             inet_ntop(AF_INET, (const void *)&ip4_pkt->ip_src, ip_src, sizeof(ip_src));
  774             inet_ntop(AF_INET, (const void *)&ip4_pkt->ip_dst, ip_dst, sizeof(ip_dst));
  775         } break;
  776 
  777 #if USE_IPv6
  778         case 6: {
  779             ip_hl    = sizeof(struct ip6_hdr);
  780             ip_proto = ip6_pkt->ip6_nxt;
  781 
  782             if (ip_proto == IPPROTO_FRAGMENT) {
  783                 struct ip6_frag *ip6_fraghdr;
  784 
  785                 ip6_fraghdr = (struct ip6_frag *)((unsigned char *)(ip6_pkt) + ip_hl);
  786                 ip_hl      += sizeof(struct ip6_frag);
  787                 ip_proto    = ip6_fraghdr->ip6f_nxt;
  788 
  789                 fragmented  = 1;
  790                 frag_offset = ntohs(ip6_fraghdr->ip6f_offlg & IP6F_OFF_MASK);
  791                 frag_id     = ntohl(ip6_fraghdr->ip6f_ident);
  792             }
  793 
  794             inet_ntop(AF_INET6, (const void *)&ip6_pkt->ip6_src, ip_src, sizeof(ip_src));
  795             inet_ntop(AF_INET6, (const void *)&ip6_pkt->ip6_dst, ip_dst, sizeof(ip_dst));
  796         } break;
  797 #endif
  798     }
  799 
  800     if (quiet < 1) {
  801         printf("#");
  802         fflush(stdout);
  803     }
  804 
  805     switch (ip_proto) {
  806         case IPPROTO_TCP: {
  807             struct tcphdr *tcp_pkt = (struct tcphdr *)((unsigned char *)(ip4_pkt) + ip_hl);
  808             uint16_t tcphdr_offset = (frag_offset) ? 0 : (tcp_pkt->th_off * 4);
  809 
  810             data = (unsigned char *)(tcp_pkt) + tcphdr_offset;
  811             len -= link_offset + ip_hl + tcphdr_offset;
  812 
  813             if ((int32_t)len < 0)
  814                 len = 0;
  815 
  816             dump_packet(h, p, ip_proto, data, len,
  817                         ip_src, ip_dst, ntohs(tcp_pkt->th_sport), ntohs(tcp_pkt->th_dport), tcp_pkt->th_flags,
  818                         tcphdr_offset, fragmented, frag_offset, frag_id);
  819         } break;
  820 
  821         case IPPROTO_UDP: {
  822             struct udphdr *udp_pkt = (struct udphdr *)((unsigned char *)(ip4_pkt) + ip_hl);
  823             uint16_t udphdr_offset = (frag_offset) ? 0 : sizeof(*udp_pkt);
  824 
  825             data = (unsigned char *)(udp_pkt) + udphdr_offset;
  826             len -= link_offset + ip_hl + udphdr_offset;
  827 
  828             if ((int32_t)len < 0)
  829                 len = 0;
  830 
  831             dump_packet(h, p, ip_proto, data, len, ip_src, ip_dst,
  832                         ntohs(udp_pkt->uh_sport), ntohs(udp_pkt->uh_dport), 0,
  833                         udphdr_offset, fragmented, frag_offset, frag_id);
  834         } break;
  835 
  836         case IPPROTO_ICMP: {
  837             struct icmp *icmp4_pkt   = (struct icmp *)((unsigned char *)(ip4_pkt) + ip_hl);
  838             uint16_t icmp4hdr_offset = (frag_offset) ? 0 : 4;
  839 
  840             data = (unsigned char *)(icmp4_pkt) + icmp4hdr_offset;
  841             len -= link_offset + ip_hl + icmp4hdr_offset;
  842 
  843             if ((int32_t)len < 0)
  844                 len = 0;
  845 
  846             dump_packet(h, p, ip_proto, data, len,
  847                         ip_src, ip_dst, icmp4_pkt->icmp_type, icmp4_pkt->icmp_code, 0,
  848                         icmp4hdr_offset, fragmented, frag_offset, frag_id);
  849         } break;
  850 
  851 #if USE_IPv6
  852         case IPPROTO_ICMPV6: {
  853             struct icmp6_hdr *icmp6_pkt = (struct icmp6_hdr *)((unsigned char *)(ip6_pkt) + ip_hl);
  854             uint16_t icmp6hdr_offset    = (frag_offset) ? 0 : 4;
  855 
  856             data = (unsigned char *)(icmp6_pkt) + icmp6hdr_offset;
  857             len -= link_offset + ip_hl + icmp6hdr_offset;
  858 
  859             if ((int32_t)len < 0)
  860                 len = 0;
  861 
  862             dump_packet(h, p, ip_proto, data, len,
  863                         ip_src, ip_dst, icmp6_pkt->icmp6_type, icmp6_pkt->icmp6_code, 0,
  864                         icmp6hdr_offset, fragmented, frag_offset, frag_id);
  865         } break;
  866 #endif
  867 
  868         case IPPROTO_IGMP: {
  869             struct igmp *igmp_pkt   = (struct igmp *)((unsigned char *)(ip4_pkt) + ip_hl);
  870             uint16_t igmphdr_offset = (frag_offset) ? 0 : 4;
  871 
  872             data = (unsigned char *)(igmp_pkt) + igmphdr_offset;
  873             len -= link_offset + ip_hl + igmphdr_offset;
  874 
  875             if ((int32_t)len < 0)
  876                 len = 0;
  877 
  878             dump_packet(h, p, ip_proto, data, len,
  879                         ip_src, ip_dst, igmp_pkt->igmp_type, igmp_pkt->igmp_code, 0,
  880                         igmphdr_offset, fragmented, frag_offset, frag_id);
  881         } break;
  882 
  883         default: {
  884             data = (unsigned char *)(ip4_pkt) + ip_hl;
  885             len -= link_offset + ip_hl;
  886 
  887             if ((int32_t)len < 0)
  888                 len = 0;
  889 
  890             dump_packet(h, p, ip_proto, data, len,
  891                         ip_src, ip_dst, 0, 0, 0,
  892                         0, fragmented, frag_offset, frag_id);
  893         } break;
  894 
  895     }
  896 
  897     if (max_matches && matches >= max_matches)
  898         clean_exit(0);
  899 
  900     if (match_after && keep_matching)
  901         keep_matching--;
  902 }
  903 
  904 void dump_packet(struct pcap_pkthdr *h, u_char *p, uint8_t proto, unsigned char *data, uint32_t len,
  905                  const char *ip_src, const char *ip_dst, uint16_t sport, uint16_t dport, uint8_t flags,
  906                  uint16_t hdr_offset, uint8_t frag, uint16_t frag_offset, uint32_t frag_id) {
  907 
  908     uint16_t match_size, match_index;
  909 
  910     if (!show_empty && len == 0)
  911         return;
  912 
  913     if (len > limitlen)
  914         len = limitlen;
  915 
  916     if ((len > 0 && match_func(data, len, &match_index, &match_size) == invert_match) && !keep_matching)
  917         return;
  918 
  919     if (!live_read && want_delay)
  920         dump_delay(h);
  921 
  922     {
  923         char ident;
  924 
  925         switch (proto) {
  926             case IPPROTO_TCP:    ident = TCP;     break;
  927             case IPPROTO_UDP:    ident = UDP;     break;
  928             case IPPROTO_ICMP:   ident = ICMP;    break;
  929             case IPPROTO_ICMPV6: ident = ICMPv6;  break;
  930             case IPPROTO_IGMP:   ident = IGMP;    break;
  931             default:             ident = UNKNOWN; break;
  932         }
  933 
  934         printf("\n%c", ident);
  935     }
  936 
  937     if (show_proto)
  938         printf("(%u)", proto);
  939 
  940     printf(" ");
  941 
  942     if (print_time)
  943         print_time(h);
  944 
  945     if ((proto == IPPROTO_TCP || proto == IPPROTO_UDP) && (sport || dport) && (hdr_offset || frag_offset == 0))
  946 
  947         printf("%s:%u -> %s:%u", ip_src, sport, ip_dst, dport);
  948 
  949     else
  950 
  951         printf("%s -> %s", ip_src, ip_dst);
  952 
  953     if (proto == IPPROTO_TCP && flags)
  954         printf(" [%s%s%s%s%s%s%s%s]",
  955                (flags & TH_ACK) ? "A" : "",
  956                (flags & TH_SYN) ? "S" : "",
  957                (flags & TH_RST) ? "R" : "",
  958                (flags & TH_FIN) ? "F" : "",
  959                (flags & TH_URG) ? "U" : "",
  960                (flags & TH_PUSH)? "P" : "",
  961                (flags & TH_ECE) ? "E" : "",
  962                (flags & TH_CWR) ? "C" : "");
  963 
  964     switch (proto) {
  965         case IPPROTO_ICMP:
  966         case IPPROTO_ICMPV6:
  967         case IPPROTO_IGMP:
  968             printf(" %u:%u", sport, dport);
  969     }
  970 
  971     if (frag)
  972         printf(" %s%u@%u:%u",
  973                frag_offset?"+":"", frag_id, frag_offset, len);
  974 
  975     if (dump_single)
  976         printf(" ");
  977     else
  978         printf(" #%u\n", seen_frames);
  979 
  980     if (quiet < 3)
  981         dump_func(data, len, match_index, match_size);
  982 
  983     if (pd_dump)
  984         pcap_dump((u_char*)pd_dump, h, p);
  985 
  986 #if USE_TCPKILL
  987     if (tcpkill_active)
  988         tcpkill_kill(h, p, link_offset, tcpkill_active);
  989 #endif
  990 }
  991 
  992 int8_t re_match_func(unsigned char *data, uint32_t len, uint16_t *mindex, uint16_t *msize) {
  993 #if USE_PCRE
  994 
  995     static int sub[2];
  996     switch(pcre_exec(pattern, 0, (char const *)data, (int32_t)len, 0, 0, 0, 0)) {
  997         case PCRE_ERROR_NULL:
  998         case PCRE_ERROR_BADOPTION:
  999         case PCRE_ERROR_BADMAGIC:
 1000         case PCRE_ERROR_UNKNOWN_NODE:
 1001         case PCRE_ERROR_NOMEMORY:
 1002             perror("she's dead, jim\n");
 1003             clean_exit(2);
 1004 
 1005         case PCRE_ERROR_NOMATCH:
 1006             return 0;
 1007 
 1008         default:
 1009             *mindex = sub[0];
 1010             *msize  = sub[1] - sub[0];
 1011     }
 1012 #else
 1013 
 1014     static struct re_registers regs;
 1015     switch (re_search(&pattern, (char const *)data, (int32_t)len, 0, len, &regs)) {
 1016         case -2:
 1017             perror("she's dead, jim\n");
 1018             clean_exit(2);
 1019 
 1020         case -1:
 1021             return 0;
 1022 
 1023         default:
 1024             *mindex = regs.start[0];
 1025             *msize  = regs.end[0] - regs.start[0];
 1026     }
 1027 #endif
 1028 
 1029     matches++;
 1030 
 1031     if (match_after && keep_matching != match_after)
 1032         keep_matching = match_after;
 1033 
 1034     return 1;
 1035 }
 1036 
 1037 int8_t bin_match_func(unsigned char *data, uint32_t len, uint16_t *mindex, uint16_t *msize) {
 1038     int32_t stop = len - match_len;
 1039     int32_t i    = 0;
 1040 
 1041     if (stop < 0)
 1042         return 0;
 1043 
 1044     while (i <= stop)
 1045         if (!memcmp(data+(i++), bin_data, match_len)) {
 1046             matches++;
 1047 
 1048             if (match_after && keep_matching != match_after)
 1049                 keep_matching = match_after;
 1050 
 1051             *mindex = i - 1;
 1052             *msize  = match_len;
 1053 
 1054             return 1;
 1055         }
 1056 
 1057     return 0;
 1058 }
 1059 
 1060 int8_t blank_match_func(unsigned char *data, uint32_t len, uint16_t *mindex, uint16_t *msize) {
 1061     matches++;
 1062 
 1063     *mindex = 0;
 1064     *msize  = 0;
 1065 
 1066     return 1;
 1067 }
 1068 
 1069 void dump_byline(unsigned char *data, uint32_t len, uint16_t mindex, uint16_t msize) {
 1070     if (len > 0) {
 1071         const unsigned char *s      = data;
 1072         uint8_t should_hilite       = (msize && enable_hilite);
 1073         unsigned char *hilite_start = data + mindex;
 1074         unsigned char *hilite_end   = hilite_start + msize;
 1075 
 1076         while (s < data + len) {
 1077             if (should_hilite && s == hilite_start)
 1078                 printf("%s", ANSI_hilite);
 1079 
 1080             printf("%c", (*s == '\n' || isprint(*s)) ? *s : nonprint_char);
 1081             s++;
 1082 
 1083             if (should_hilite && s == hilite_end)
 1084                 printf("%s", ANSI_off);
 1085         }
 1086 
 1087         printf("\n");
 1088     }
 1089 }
 1090 
 1091 void dump_unwrapped(unsigned char *data, uint32_t len, uint16_t mindex, uint16_t msize) {
 1092     if (len > 0) {
 1093         const unsigned char *s      = data;
 1094         uint8_t should_hilite       = (msize && enable_hilite);
 1095         unsigned char *hilite_start = data + mindex;
 1096         unsigned char *hilite_end   = hilite_start + msize;
 1097 
 1098         while (s < data + len) {
 1099             if (should_hilite && s == hilite_start)
 1100                 printf("%s", ANSI_hilite);
 1101 
 1102             printf("%c", isprint(*s) ? *s : nonprint_char);
 1103             s++;
 1104 
 1105             if (should_hilite && s == hilite_end)
 1106                 printf("%s", ANSI_off);
 1107         }
 1108 
 1109         printf("\n");
 1110     }
 1111 }
 1112 
 1113 void dump_formatted(unsigned char *data, uint32_t len, uint16_t mindex, uint16_t msize) {
 1114     if (len > 0) {
 1115         uint8_t should_hilite = (msize && enable_hilite);
 1116            unsigned char *str = data;
 1117              uint8_t hiliting = 0;
 1118                 uint8_t width = show_hex ? 16 : (ws_col-5);
 1119                    uint32_t i = 0,
 1120                             j = 0;
 1121 
 1122         while (i < len) {
 1123             printf("  ");
 1124 
 1125             if (show_hex) {
 1126                 for (j = 0; j < width; j++) {
 1127                     if (should_hilite && (mindex <= (i+j) && (i+j) < mindex + msize)) {
 1128                         hiliting = 1;
 1129                         printf("%s", ANSI_hilite);
 1130                     }
 1131 
 1132                     if (i + j < len)
 1133                         printf("%02x ", str[j]);
 1134                     else printf("   ");
 1135 
 1136                     if ((j+1) % (width/2) == 0)
 1137                         printf("   ");
 1138 
 1139                     if (hiliting) {
 1140                         hiliting = 0;
 1141                         printf("%s", ANSI_off);
 1142                     }
 1143                 }
 1144             }
 1145 
 1146             for (j = 0; j < width; j++) {
 1147                 if (should_hilite && mindex <= (i+j) && (i+j) < mindex + msize) {
 1148                     hiliting = 1;
 1149                     printf("%s", ANSI_hilite);
 1150                 }
 1151 
 1152                 if (i + j < len)
 1153                     printf("%c", isprint(str[j]) ? str[j] : nonprint_char);
 1154                 else printf(" ");
 1155 
 1156                 if (hiliting) {
 1157                     hiliting = 0;
 1158                     printf("%s", ANSI_off);
 1159                 }
 1160             }
 1161 
 1162             str += width;
 1163             i   += j;
 1164 
 1165             printf("\n");
 1166         }
 1167     }
 1168 }
 1169 
 1170 char *get_filter_from_string(char *str) {
 1171     const char *template = include_vlan ? BPF_TEMPLATE_USERSPEC_IP_VLAN : BPF_TEMPLATE_USERSPEC_IP;
 1172     char *mine, *s;
 1173     uint32_t len;
 1174 
 1175     if (!str || !*str)
 1176         return NULL;
 1177 
 1178     len = (uint32_t)strlen(str);
 1179 
 1180     for (s = str; *s; s++)
 1181         if (*s == '\r' || *s == '\n')
 1182             *s = ' ';
 1183 
 1184     if (!(mine = (char*)malloc(len + strlen(template) + 1)))
 1185         return NULL;
 1186 
 1187     memset(mine, 0, len + strlen(template) + 1);
 1188 
 1189     sprintf(mine, template, str);
 1190 
 1191     return mine;
 1192 }
 1193 
 1194 char *get_filter_from_argv(char **argv) {
 1195     const char *template = include_vlan ? BPF_TEMPLATE_USERSPEC_IP_VLAN : BPF_TEMPLATE_USERSPEC_IP;
 1196     char **arg = argv, *theirs, *mine;
 1197     char *from, *to;
 1198     uint32_t len = 0;
 1199 
 1200     if (!*arg)
 1201         return NULL;
 1202 
 1203     while (*arg)
 1204         len += (uint32_t)strlen(*arg++) + 1;
 1205 
 1206     if (!(theirs = (char*)malloc(len + 1)) ||
 1207         !(mine = (char*)malloc(len + strlen(template) + 1)))
 1208         return NULL;
 1209 
 1210     memset(theirs, 0, len + 1);
 1211     memset(mine, 0, len + strlen(template) + 1);
 1212 
 1213     arg = argv;
 1214     to = theirs;
 1215 
 1216     while ((from = *arg++)) {
 1217         while ((*to++ = *from++));
 1218         *(to-1) = ' ';
 1219     }
 1220 
 1221     sprintf(mine, template, theirs);
 1222 
 1223     free(theirs);
 1224     return mine;
 1225 }
 1226 
 1227 
 1228 uint8_t strishex(char *str) {
 1229     char *s;
 1230 
 1231     if ((s = strchr(str, 'x')))
 1232         s++;
 1233     else
 1234         s = str;
 1235 
 1236     while (*s)
 1237         if (!isxdigit(*s++))
 1238             return 0;
 1239 
 1240     return 1;
 1241 }
 1242 
 1243 
 1244 void print_time_absolute(struct pcap_pkthdr *h) {
 1245     struct tm *t = localtime((const time_t *)&h->ts.tv_sec);
 1246 
 1247     printf("%02u/%02u/%02u %02u:%02u:%02u.%06u ",
 1248            t->tm_year+1900, t->tm_mon+1, t->tm_mday, t->tm_hour,
 1249            t->tm_min, t->tm_sec, (uint32_t)h->ts.tv_usec);
 1250 }
 1251 
 1252 void print_time_diff(struct pcap_pkthdr *h) {
 1253     uint32_t secs, usecs;
 1254 
 1255     secs = h->ts.tv_sec - prev_ts.tv_sec;
 1256     if (h->ts.tv_usec >= prev_ts.tv_usec)
 1257         usecs = h->ts.tv_usec - prev_ts.tv_usec;
 1258     else {
 1259         secs--;
 1260         usecs = 1000000 - (prev_ts.tv_usec - h->ts.tv_usec);
 1261     }
 1262 
 1263     printf("+%u.%06u ", secs, usecs);
 1264 
 1265     prev_ts.tv_sec  = h->ts.tv_sec;
 1266     prev_ts.tv_usec = h->ts.tv_usec;
 1267 }
 1268 
 1269 void print_time_offset(struct pcap_pkthdr *h) {
 1270     uint32_t secs, usecs;
 1271 
 1272     secs = h->ts.tv_sec - prev_ts.tv_sec;
 1273     if (h->ts.tv_usec >= prev_ts.tv_usec)
 1274         usecs = h->ts.tv_usec - prev_ts.tv_usec;
 1275     else {
 1276         secs--;
 1277         usecs = 1000000 - (prev_ts.tv_usec - h->ts.tv_usec);
 1278     }
 1279 
 1280     if (prev_ts.tv_sec == 0 && prev_ts.tv_usec == 0) {
 1281         prev_ts.tv_sec  = h->ts.tv_sec;
 1282         prev_ts.tv_usec = h->ts.tv_usec;
 1283         secs  = 0;
 1284         usecs = 0;
 1285     }
 1286 
 1287     printf("+%u.%06u ", secs, usecs);
 1288 }
 1289 
 1290 void dump_delay_proc_init(struct pcap_pkthdr *h) {
 1291     dump_delay = &dump_delay_proc;
 1292 
 1293     prev_delay_ts.tv_sec  = h->ts.tv_sec;
 1294     prev_delay_ts.tv_usec = h->ts.tv_usec;
 1295 
 1296     dump_delay(h);
 1297 }
 1298 
 1299 void dump_delay_proc(struct pcap_pkthdr *h) {
 1300     uint32_t secs, usecs;
 1301 
 1302     secs = h->ts.tv_sec - prev_delay_ts.tv_sec;
 1303     if (h->ts.tv_usec >= prev_delay_ts.tv_usec)
 1304         usecs = h->ts.tv_usec - prev_delay_ts.tv_usec;
 1305     else {
 1306         secs--;
 1307         usecs = 1000000 - (prev_delay_ts.tv_usec - h->ts.tv_usec);
 1308     }
 1309 
 1310 #ifdef _WIN32
 1311     {
 1312         // grevious hack, yes, but windows sucks.  sorry. :(   --jordan
 1313         if ((delay_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) {
 1314             perror("delay socket creation failed, disabling -D");
 1315             Sleep(3000); // give them time to read the message
 1316             want_delay = 0;
 1317             return;
 1318         }
 1319 
 1320         FD_ZERO(&delay_fds);
 1321         FD_SET(delay_socket, &delay_fds);
 1322 
 1323         delay_tv.tv_sec  = secs;
 1324         delay_tv.tv_usec = usecs;
 1325 
 1326         if (select(0, &delay_fds, 0, 0, &delay_tv) == -1)
 1327             fprintf(stderr, "WSAGetLastError = %u\n", WSAGetLastError());
 1328 
 1329         closesocket(delay_socket);
 1330         delay_socket = 0; // in case someone ^C's out of me
 1331     }
 1332 #else
 1333     sleep(secs);
 1334     usleep(usecs);
 1335 #endif
 1336 
 1337     prev_delay_ts.tv_sec  = h->ts.tv_sec;
 1338     prev_delay_ts.tv_usec = h->ts.tv_usec;
 1339 }
 1340 
 1341 void update_windowsize(int32_t e) {
 1342     if (e == 0 && ws_col_forced)
 1343 
 1344         ws_col = ws_col_forced;
 1345 
 1346     else if (!ws_col_forced) {
 1347 
 1348 #if !defined(_WIN32)
 1349         const struct winsize ws;
 1350 
 1351         if (!ioctl(0, TIOCGWINSZ, &ws)) {
 1352             ws_row = ws.ws_row;
 1353             ws_col = ws.ws_col;
 1354         }
 1355 #else
 1356         CONSOLE_SCREEN_BUFFER_INFO csbi;
 1357         if (GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi)) {
 1358             ws_row = csbi.dwSize.Y;
 1359             ws_col = csbi.dwSize.X;
 1360         }
 1361 #endif
 1362         else {
 1363             ws_row = 24;
 1364             ws_col = 80;
 1365         }
 1366 
 1367     }
 1368 }
 1369 
 1370 #if !defined(_WIN32) && USE_DROPPRIVS
 1371 void drop_privs(void) {
 1372     struct passwd *pw;
 1373     uid_t newuid;
 1374     gid_t newgid;
 1375 
 1376     if ((getuid() || geteuid()) || dont_dropprivs)
 1377         return;
 1378 
 1379     pw = getpwnam(DROPPRIVS_USER);
 1380     if (!pw) {
 1381         perror("attempt to drop privileges failed: getpwnam failed");
 1382         clean_exit(2);
 1383     }
 1384 
 1385     newgid = pw->pw_gid;
 1386     newuid = pw->pw_uid;
 1387 
 1388     if (getgroups(0, NULL) > 0)
 1389         if (setgroups(1, &newgid) == -1) {
 1390             perror("attempt to drop privileges failed");
 1391             clean_exit(2);
 1392         }
 1393 
 1394     if (((getgid()  != newgid) && (setgid(newgid)  == -1)) ||
 1395         ((getegid() != newgid) && (setegid(newgid) == -1)) ||
 1396         ((getuid()  != newuid) && (setuid(newuid)  == -1)) ||
 1397         ((geteuid() != newuid) && (seteuid(newuid) == -1))) {
 1398 
 1399         perror("attempt to drop privileges failed");
 1400         clean_exit(2);
 1401     }
 1402 }
 1403 
 1404 #endif
 1405 
 1406 void usage(void) {
 1407     printf("usage: ngrep <-"
 1408 #if defined(_WIN32)
 1409            "L"
 1410 #endif
 1411            "hNXViwqpevxlDtTRM> <-IO pcap_dump> <-n num> <-d dev> <-A num>\n"
 1412            "             <-s snaplen> <-S limitlen> <-W normal|byline|single|none> <-c cols>\n"
 1413            "             <-P char> <-F file>"
 1414 #if USE_TCPKILL
 1415            "             <-K count>"
 1416 #endif
 1417            "\n"
 1418            "             <match expression> <bpf filter>\n"
 1419            "   -h  is help/usage\n"
 1420            "   -V  is version information\n"
 1421            "   -q  is be quiet (don't print packet reception hash marks)\n"
 1422            "   -e  is show empty packets\n"
 1423            "   -i  is ignore case\n"
 1424            "   -v  is invert match\n"
 1425            "   -R  is don't do privilege revocation logic\n"
 1426            "   -x  is print in alternate hexdump format\n"
 1427            "   -X  is interpret match expression as hexadecimal\n"
 1428            "   -w  is word-regex (expression must match as a word)\n"
 1429            "   -p  is don't go into promiscuous mode\n"
 1430            "   -l  is make stdout line buffered\n"
 1431            "   -D  is replay pcap_dumps with their recorded time intervals\n"
 1432            "   -t  is print timestamp every time a packet is matched\n"
 1433            "   -T  is print delta timestamp every time a packet is matched\n"
 1434            "         specify twice for delta from first match\n"
 1435            "   -M  is don't do multi-line match (do single-line match instead)\n"
 1436            "   -I  is read packet stream from pcap format file pcap_dump\n"
 1437            "   -O  is dump matched packets in pcap format to pcap_dump\n"
 1438            "   -n  is look at only num packets\n"
 1439            "   -A  is dump num packets after a match\n"
 1440            "   -s  is set the bpf caplen\n"
 1441            "   -S  is set the limitlen on matched packets\n"
 1442            "   -W  is set the dump format (normal, byline, single, none)\n"
 1443            "   -c  is force the column width to the specified size\n"
 1444            "   -P  is set the non-printable display char to what is specified\n"
 1445            "   -F  is read the bpf filter from the specified file\n"
 1446            "   -N  is show sub protocol number\n"
 1447 #if defined(_WIN32)
 1448            "   -d  is use specified device (index) instead of the pcap default\n"
 1449            "   -L  is show the winpcap device list index\n"
 1450 #else
 1451            "   -d  is use specified device instead of the pcap default\n"
 1452 #endif
 1453 #if USE_TCPKILL
 1454            "   -K  is send N packets to kill observed connections\n"
 1455 #endif
 1456            "");
 1457 
 1458     exit(2);
 1459 }
 1460 
 1461 
 1462 void version(void) {
 1463     printf("ngrep: V%s, %s\n", VERSION, pcap_lib_version());
 1464     exit(0);
 1465 }
 1466 
 1467 
 1468 void clean_exit(int32_t sig) {
 1469     struct pcap_stat s;
 1470 
 1471     signal(SIGINT,   SIG_IGN);
 1472     signal(SIGABRT,  SIG_IGN);
 1473 #if !defined(_WIN32)
 1474     signal(SIGQUIT,  SIG_IGN);
 1475     signal(SIGPIPE,  SIG_IGN);
 1476     signal(SIGWINCH, SIG_IGN);
 1477 #endif
 1478 
 1479     if (quiet < 1 && sig >= 0)
 1480         printf("exit\n");
 1481 
 1482 #if USE_PCRE
 1483     if (pattern)       pcre_free(pattern);
 1484     if (pattern_extra) pcre_free(pattern_extra);
 1485 #else
 1486     if (pattern.translate) free(pattern.translate);
 1487     if (pattern.fastmap)   free(pattern.fastmap);
 1488 #endif
 1489 
 1490     if (bin_data)          free(bin_data);
 1491 
 1492     /* We used to report pcap_stats; but PCAP manpage says pcap_stats "may or
 1493        may not" be accurate. So useless. :-( And confusing for a user to see
 1494        counts not match what ngrep thinks. */
 1495     if (quiet < 1 && sig >= 0 && !read_file)
 1496         printf("%u received, %u matched\n", seen_frames, matches);
 1497 
 1498     if (pd)           pcap_close(pd);
 1499     if (pd_dumppcap)  pcap_close(pd_dumppcap);
 1500     if (pd_dump)      pcap_dump_close(pd_dump);
 1501 
 1502 #if defined(_WIN32)
 1503     if (delay_socket) closesocket(delay_socket);
 1504     if (want_delay)   WSACleanup();
 1505     if (usedev)       free(usedev);
 1506 #endif
 1507 
 1508     exit(matches ? 0 : 1);
 1509 }
 1510 
 1511 #if defined(_WIN32)
 1512 int8_t win32_initwinsock(void) {
 1513     WORD wVersionRequested = MAKEWORD(2, 0);
 1514     WSADATA wsaData;
 1515 
 1516     if (WSAStartup(wVersionRequested, &wsaData)) {
 1517         perror("unable to initialize winsock");
 1518         return 0;
 1519     }
 1520 
 1521     // we want at least major version 2
 1522     if (LOBYTE(wsaData.wVersion) < 2) {
 1523         fprintf(stderr, "unable to find winsock 2.0 or greater (found %u.%u)\n",
 1524                 LOBYTE(wsaData.wVersion), HIBYTE(wsaData.wVersion));
 1525         WSACleanup();
 1526         return 0;
 1527     }
 1528 
 1529     return 1;
 1530 }
 1531 
 1532 void win32_listdevices(void) {
 1533     uint32_t i = 0;
 1534     pcap_if_t *alldevs, *d;
 1535     char errbuf[PCAP_ERRBUF_SIZE];
 1536 
 1537     if (pcap_findalldevs(&alldevs, errbuf) == -1) {
 1538         perror("unable to enumerate device list");
 1539         clean_exit(2);
 1540     }
 1541 
 1542     printf("idx\tdev\n");
 1543     printf("---\t---\n");
 1544 
 1545     for (d = alldevs; d != NULL; d = d->next) {
 1546         printf("%2u:\t%s", ++i, d->name);
 1547 
 1548         if (d->description)
 1549             printf(" (%s)\n", d->description);
 1550     }
 1551 
 1552     pcap_freealldevs(alldevs);
 1553 }
 1554 
 1555 char *win32_usedevice(const char *index) {
 1556     int32_t idx = atoi(index), i = 0;
 1557     pcap_if_t *alldevs, *d;
 1558     char errbuf[PCAP_ERRBUF_SIZE];
 1559     char *dev = NULL;
 1560 
 1561     if (idx <= 0) {
 1562         perror("invalid device index");
 1563         clean_exit(2);
 1564     }
 1565 
 1566     if (pcap_findalldevs(&alldevs, errbuf) == -1) {
 1567         perror("unable to enumerate devices");
 1568         clean_exit(2);
 1569     }
 1570 
 1571     for (d = alldevs; d != NULL && i != idx; d = d->next)
 1572         if (++i == idx)
 1573             dev = _strdup(d->name);
 1574 
 1575     if (i <= 0) {
 1576         perror("no known devices");
 1577         clean_exit(2);
 1578     }
 1579 
 1580     if (i != idx) {
 1581         perror("unknown device specified");
 1582         clean_exit(2);
 1583     }
 1584 
 1585     pcap_freealldevs(alldevs);
 1586 
 1587     return dev;
 1588 }
 1589 
 1590 char *win32_choosedevice(void) {
 1591     pcap_if_t *alldevs, *d;
 1592     char errbuf[PCAP_ERRBUF_SIZE];
 1593     char *dev = NULL;
 1594 
 1595     if (pcap_findalldevs(&alldevs, errbuf) == -1) {
 1596         perror("unable to enumerate devices");
 1597         clean_exit(2);
 1598     }
 1599 
 1600     for (d = alldevs; d != NULL; d = d->next)
 1601         if ((d->addresses) && (d->addresses->addr))
 1602             dev = _strdup(d->name);
 1603 
 1604     pcap_freealldevs(alldevs);
 1605 
 1606     if (!dev)
 1607         dev = pcap_lookupdev(errbuf);
 1608 
 1609     return dev;
 1610 }
 1611 #endif