ongrep

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

commit c67909d977b2129155c526b9a91514ed56e1f7aa
parent 49a5ee9ac8780be916b54087c79ab3a882760147
Author: Jordan Ritter <jpr5@darkridge.com>
Date:   Wed,  6 Sep 2017 17:27:41 -0700

Fallback fix for VLAN & related problems

Building off of the disable-VLAN-auto-inclusion fix, if we encounter a
problem with the PCAP filter, now we just disable VLAN from being
included in the filter and blindly try a second time.

This patch organizes the big initialization pieces into separate
routines to make the retry easier.

Diffstat:
Mngrep.c | 290+++++++++++++++++++++++++++++++++++++++++++------------------------------------
Mngrep.h | 4++++
2 files changed, 161 insertions(+), 133 deletions(-)

diff --git a/ngrep.c b/ngrep.c @@ -367,11 +367,74 @@ int main(int argc, char **argv) { /* Setup PCAP input */ + if (setup_pcap_source()) + clean_exit(2); + + /* Setup BPF filter */ + + if (setup_bpf_filter(argv)) { + include_vlan = 0; + if (filter) { free(filter); filter = NULL; } + + if (setup_bpf_filter(argv)) { + pcap_perror(pd, "pcap"); + clean_exit(2); + } + } + + if (filter) { + if (quiet < 2) + printf("filter: %s\n", filter); + free(filter); + } + + /* Setup matcher */ + + if (match_data) { + if (setup_matcher()) + clean_exit(2); + + if (quiet < 2 && strlen(match_data)) + printf("%smatch: %s%s\n", invert_match?"don't ":"", + (bin_data && !strchr(match_data, 'x'))?"0x":"", match_data); + + if (re_match_word) free(match_data); + } + + /* Misc */ + + if (dump_file) { + pd_dump = pcap_dump_open(pd, dump_file); + if (!pd_dump) { + fprintf(stderr, "fatal: %s\n", pcap_geterr(pd)); + clean_exit(2); + } else printf("output: %s\n", dump_file); + } + + update_windowsize(0); + +#if defined(_WIN32) + win32_initwinsock(); +#endif + +#if !defined(_WIN32) && USE_DROPPRIVS + drop_privs(); +#endif + + while (pcap_loop(pd, -1, (pcap_handler)process, 0)); + + clean_exit(0); + + /* NOT REACHED */ + return 0; +} + +int setup_pcap_source(void) { if (read_file) { if (!(pd = pcap_open_offline(read_file, pc_err))) { perror(pc_err); - clean_exit(2); + return 1; } live_read = 0; @@ -388,12 +451,12 @@ int main(int argc, char **argv) { if (!dev) { perror(pc_err); - clean_exit(2); + return 1; } if ((pd = pcap_open_live(dev, snaplen, promisc, to, pc_err)) == NULL) { perror(pc_err); - clean_exit(2); + return 1; } if (pcap_lookupnet(dev, &net.s_addr, &mask.s_addr, pc_err) == -1) { @@ -412,8 +475,6 @@ int main(int argc, char **argv) { } } - /* Setup link header offset */ - switch(pcap_datalink(pd)) { case DLT_EN10MB: link_offset = ETHHDR_SIZE; @@ -481,11 +542,13 @@ int main(int argc, char **argv) { default: fprintf(stderr, "fatal: unsupported interface type %u\n", pcap_datalink(pd)); - clean_exit(2); + return 1; } - /* Setup BPF filter */ + return 0; +} +int setup_bpf_filter(char **argv) { if (filter_file) { char buf[1024] = {0}; FILE *f = fopen(filter_file, "r"); @@ -499,10 +562,8 @@ int main(int argc, char **argv) { filter = get_filter_from_string(buf); - if (pcap_compile(pd, &pcapfilter, filter, 0, mask.s_addr)) { - pcap_perror(pd, "pcap compile"); - clean_exit(2); - } + if (pcap_compile(pd, &pcapfilter, filter, 0, mask.s_addr)) + return 1; } else if (argv[optind]) { filter = get_filter_from_argv(&argv[optind]); @@ -514,167 +575,130 @@ int main(int argc, char **argv) { #if USE_PCAP_RESTART PCAP_RESTART_FUNC(); #endif - if (pcap_compile(pd, &pcapfilter, filter, 0, mask.s_addr)) { - pcap_perror(pd, "pcap compile"); - clean_exit(2); - } else match_data = NULL; + + if (pcap_compile(pd, &pcapfilter, filter, 0, mask.s_addr)) + return 1; + + match_data = NULL; } } else { filter = include_vlan ? strdup(BPF_TEMPLATE_IP_VLAN) : strdup(BPF_TEMPLATE_IP); - if (pcap_compile(pd, &pcapfilter, filter, 0, mask.s_addr)) { - pcap_perror(pd, "pcap compile"); - clean_exit(2); - } + if (pcap_compile(pd, &pcapfilter, filter, 0, mask.s_addr)) + return 1; } - if (filter && quiet < 2) - printf("filter: %s\n", filter); + if (pcap_setfilter(pd, &pcapfilter)) + return 1; - if (pcap_setfilter(pd, &pcapfilter)) { - pcap_perror(pd, "pcap set"); - clean_exit(2); - } - - /* Setup matcher */ + return 0; +} - if (match_data) { - if (bin_match) { - uint32_t i = 0, n; - uint32_t len; - char *s, *d; +int setup_matcher(void) { + if (bin_match) { + uint32_t i = 0, n; + uint32_t len; + char *s, *d; - if (re_match_word || re_ignore_case) { - fprintf(stderr, "fatal: regex switches are incompatible with binary matching\n"); - clean_exit(2); - } + if (re_match_word || re_ignore_case) { + fprintf(stderr, "fatal: regex switches are incompatible with binary matching\n"); + return 1; + } - len = (uint32_t)strlen(match_data); - if (len % 2 != 0 || !strishex(match_data)) { - fprintf(stderr, "fatal: invalid hex string specified\n"); - clean_exit(2); - } + len = (uint32_t)strlen(match_data); + if (len % 2 != 0 || !strishex(match_data)) { + fprintf(stderr, "fatal: invalid hex string specified\n"); + return 1; + } - bin_data = (char*)malloc(len / 2); - memset(bin_data, 0, len / 2); - d = bin_data; + bin_data = (char*)malloc(len / 2); + memset(bin_data, 0, len / 2); + d = bin_data; - if ((s = strchr(match_data, 'x'))) - len -= (uint32_t)(++s - match_data - 1); - else s = match_data; + if ((s = strchr(match_data, 'x'))) + len -= (uint32_t)(++s - match_data - 1); + else s = match_data; - while (i <= len) { - sscanf(s+i, "%2x", &n); - *d++ = n; - i += 2; - } + while (i <= len) { + sscanf(s+i, "%2x", &n); + *d++ = n; + i += 2; + } - match_len = len / 2; - match_func = &bin_match_func; + match_len = len / 2; + match_func = &bin_match_func; - } else { + } else { #if USE_PCRE - uint32_t pcre_options = PCRE_UNGREEDY; + uint32_t pcre_options = PCRE_UNGREEDY; - if (re_ignore_case) - pcre_options |= PCRE_CASELESS; + if (re_ignore_case) + pcre_options |= PCRE_CASELESS; - if (re_multiline_match) - pcre_options |= PCRE_DOTALL; + if (re_multiline_match) + pcre_options |= PCRE_DOTALL; #else - re_syntax_options = RE_CHAR_CLASSES | RE_NO_BK_PARENS | RE_NO_BK_VBAR | - RE_CONTEXT_INDEP_ANCHORS | RE_CONTEXT_INDEP_OPS; + re_syntax_options = RE_CHAR_CLASSES | RE_NO_BK_PARENS | RE_NO_BK_VBAR | + RE_CONTEXT_INDEP_ANCHORS | RE_CONTEXT_INDEP_OPS; - if (re_multiline_match) - re_syntax_options |= RE_DOT_NEWLINE; + if (re_multiline_match) + re_syntax_options |= RE_DOT_NEWLINE; - if (re_ignore_case) { - uint32_t i; - char *s; + if (re_ignore_case) { + uint32_t i; + char *s; - pattern.translate = (char*)malloc(256); - s = pattern.translate; + pattern.translate = (char*)malloc(256); + s = pattern.translate; - for (i = 0; i < 256; i++) - s[i] = i; - for (i = 'A'; i <= 'Z'; i++) - s[i] = i + 32; + for (i = 0; i < 256; i++) + s[i] = i; + for (i = 'A'; i <= 'Z'; i++) + s[i] = i + 32; - s = match_data; - while (*s) { - *s = tolower(*s); - s++; - } + s = match_data; + while (*s) { + *s = tolower(*s); + s++; + } - } else pattern.translate = NULL; + } else pattern.translate = NULL; #endif - if (re_match_word) { - char *word_regex = (char*)malloc(strlen(match_data) * 3 + strlen(WORD_REGEX)); - sprintf(word_regex, WORD_REGEX, match_data, match_data, match_data); - match_data = word_regex; - } + if (re_match_word) { + char *word_regex = (char*)malloc(strlen(match_data) * 3 + strlen(WORD_REGEX)); + sprintf(word_regex, WORD_REGEX, match_data, match_data, match_data); + match_data = word_regex; + } #if USE_PCRE - pattern = pcre_compile(match_data, pcre_options, (const char **)&re_err, &err_offset, 0); + pattern = pcre_compile(match_data, pcre_options, (const char **)&re_err, &err_offset, 0); - if (!pattern) { - fprintf(stderr, "compile failed: %s\n", re_err); - clean_exit(2); - } + if (!pattern) { + fprintf(stderr, "compile failed: %s\n", re_err); + return 1; + } - pattern_extra = pcre_study(pattern, 0, (const char **)&re_err); + pattern_extra = pcre_study(pattern, 0, (const char **)&re_err); #else - re_err = re_compile_pattern(match_data, strlen(match_data), &pattern); - if (re_err) { - fprintf(stderr, "regex compile: %s\n", re_err); - clean_exit(2); - } - - pattern.fastmap = (char*)malloc(256); - if (re_compile_fastmap(&pattern)) { - perror("fastmap compile failed"); - clean_exit(2); - } -#endif - - match_func = &re_match_func; + re_err = re_compile_pattern(match_data, strlen(match_data), &pattern); + if (re_err) { + fprintf(stderr, "regex compile: %s\n", re_err); + return 1; } - if (quiet < 2 && match_data && strlen(match_data)) - printf("%smatch: %s%s\n", invert_match?"don't ":"", - (bin_data && !strchr(match_data, 'x'))?"0x":"", match_data); - } - - if (filter) free(filter); - if (re_match_word) free(match_data); - - - if (dump_file) { - pd_dump = pcap_dump_open(pd, dump_file); - if (!pd_dump) { - fprintf(stderr, "fatal: %s\n", pcap_geterr(pd)); - clean_exit(2); - } else printf("output: %s\n", dump_file); - } - - update_windowsize(0); - -#if defined(_WIN32) - win32_initwinsock(); -#endif - -#if !defined(_WIN32) && USE_DROPPRIVS - drop_privs(); + pattern.fastmap = (char*)malloc(256); + if (re_compile_fastmap(&pattern)) { + perror("fastmap compile failed"); + return 1; + } #endif - while (pcap_loop(pd, -1, (pcap_handler)process, 0)); - - clean_exit(0); + match_func = &re_match_func; + } - /* NOT REACHED */ return 0; } diff --git a/ngrep.h b/ngrep.h @@ -108,6 +108,10 @@ typedef enum { * Prototypes function signatures. */ +int setup_pcap_source(void); +int setup_bpf_filter(char **); +int setup_matcher(void); + void process(u_char *, struct pcap_pkthdr *, u_char *); void version(void);