"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "ngrep.c" between
ngrep-1_45.tar.gz and ngrep-1_47.tar.gz

About: ngrep (network grep) applies GNU grep’s common features to the network layer.

ngrep.c  (ngrep-1_45):ngrep.c  (ngrep-1_47)
/* /*
* $Id$ * Copyright (c) 2017 Jordan Ritter <jpr5@darkridge.com>
*
* Copyright (c) 2006 Jordan Ritter <jpr5@darkridge.com>
* *
* Please refer to the LICENSE file for more information. * Please refer to the LICENSE file for more information.
* *
*/ */
#if defined(BSD) || defined(SOLARIS) || defined(MACOSX) #if defined(BSD) || defined(SOLARIS) || defined(MACOSX)
#include <unistd.h> #include <unistd.h>
#include <ctype.h> #include <ctype.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/socket.h> #include <sys/socket.h>
skipping to change at line 35 skipping to change at line 33
#include <sys/socket.h> #include <sys/socket.h>
#include <netinet/in.h> #include <netinet/in.h>
#include <netinet/in_systm.h> #include <netinet/in_systm.h>
#include <net/route.h> #include <net/route.h>
#include <sys/mbuf.h> #include <sys/mbuf.h>
#include <arpa/inet.h> #include <arpa/inet.h>
#include <unistd> #include <unistd>
#include <pwd.h> #include <pwd.h>
#endif #endif
#if defined(LINUX) #if defined(LINUX) || defined(__GLIBC__) || defined(__GNU__)
#include <getopt.h> #include <getopt.h>
#include <arpa/inet.h> #include <arpa/inet.h>
#include <ctype.h> #include <ctype.h>
#include <time.h> #include <time.h>
#include <unistd.h> #include <unistd.h>
#include <pwd.h> #include <pwd.h>
#include <grp.h> #include <grp.h>
#endif #endif
#if defined(AIX) #if defined(AIX)
skipping to change at line 58 skipping to change at line 56
#include <netinet/in.h> #include <netinet/in.h>
#include <time.h> #include <time.h>
#include <unistd.h> #include <unistd.h>
#include <pwd.h> #include <pwd.h>
#endif #endif
#if defined(_WIN32) #if defined(_WIN32)
#include <io.h> #include <io.h>
#include <getopt.h> #include <getopt.h>
#include <winsock2.h> #include <winsock2.h>
#include <ws2tcpip.h>
#include <types.h> #include <types.h>
#include <inet_ntop.h>
#include <config.h> #include <config.h>
#define strcasecmp stricmp #define strcasecmp stricmp
#define strncasecmp strnicmp
#else #else
#include <netinet/ip.h> #include <netinet/ip.h>
#include <netinet/tcp.h> #include <netinet/tcp.h>
#include <netinet/udp.h> #include <netinet/udp.h>
#include <netinet/ip_icmp.h> #include <netinet/ip_icmp.h>
#include <netinet/igmp.h> #include <netinet/igmp.h>
#endif #endif
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <signal.h> #include <signal.h>
#include <locale.h>
#if !defined(_WIN32) #if !defined(_WIN32)
#include <errno.h> #include <errno.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
#endif #endif
#include <pcap.h> #include <pcap.h>
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
#include "config.h" #include "config.h"
#endif #endif
#if USE_IPv6 && !defined(_WIN32) #if USE_IPv6 && !defined(_WIN32)
#include <netinet/ip6.h> #include <netinet/ip6.h>
#include <netinet/icmp6.h> #include <netinet/icmp6.h>
#endif #endif
#if USE_PCRE #if USE_PCRE
#include "pcre-5.0/pcre.h" #include <pcre.h>
#else #else
#include "regex-0.12/regex.h" #include <regex.h>
#endif #endif
#include "ngrep.h" #include "ngrep.h"
static char rcsver[] = "$Revision$";
/* /*
* Configuration Options * Configuration Options
*/ */
uint16_t snaplen = 65535, limitlen = 65535, promisc = 1, to = 100; uint32_t snaplen = 65535, limitlen = 65535, promisc = 1, to = 100;
uint16_t match_after = 0, keep_matching = 0, matches = 0, max_matches = 0; uint32_t match_after = 0, keep_matching = 0, matches = 0, max_matches = 0;
uint32_t seen_frames = 0;
#if USE_TCPKILL
uint32_t tcpkill_active = 0;
#endif
uint8_t re_match_word = 0, re_ignore_case = 0, re_multiline_match = 1; uint8_t re_match_word = 0, re_ignore_case = 0, re_multiline_match = 1;
uint8_t show_empty = 0, show_hex = 0, show_proto = 0, quiet = 0; uint8_t show_empty = 0, show_hex = 0, show_proto = 0, quiet = 0;
uint8_t invert_match = 0, bin_match = 0; uint8_t invert_match = 0, bin_match = 0;
uint8_t live_read = 1, want_delay = 0; uint8_t live_read = 1, want_delay = 0;
uint8_t dont_dropprivs = 0; uint8_t dont_dropprivs = 0;
uint8_t enable_hilite = 0;
char *read_file = NULL, *dump_file = NULL; char *read_file = NULL, *dump_file = NULL;
char *usedev = NULL; char *usedev = NULL;
char nonprint_char = '.'; char nonprint_char = '.';
/* /*
* GNU Regex/PCRE * GNU Regex/PCRE
*/ */
skipping to change at line 147 skipping to change at line 151
/* /*
* Matching * Matching
*/ */
char *match_data = NULL, *bin_data = NULL; char *match_data = NULL, *bin_data = NULL;
uint16_t match_len = 0; uint16_t match_len = 0;
int8_t (*match_func)() = &blank_match_func; int8_t (*match_func)() = &blank_match_func;
int8_t dump_single = 0; int8_t dump_single = 0;
void (*dump_func)(unsigned char *, uint32_t) = &dump_formatted; void (*dump_func)(unsigned char *, uint32_t, uint16_t, uint16_t) = &dump_formatt ed;
/* /*
* BPF/Network * BPF/Network
*/ */
char *filter = NULL, *filter_file = NULL; char *filter = NULL, *filter_file = NULL;
char pc_err[PCAP_ERRBUF_SIZE]; char pc_err[PCAP_ERRBUF_SIZE];
uint8_t link_offset; uint8_t link_offset;
uint8_t radiotap_present = 0; uint8_t radiotap_present = 0;
uint8_t include_vlan = USE_VLAN_HACK;
pcap_t *pd = NULL; pcap_t *pd = NULL, *pd_dumppcap = NULL;
pcap_dumper_t *pd_dump = NULL; pcap_dumper_t *pd_dump = NULL;
struct bpf_program pcapfilter; struct bpf_program pcapfilter;
struct in_addr net, mask; struct in_addr net, mask;
/* /*
* Timestamp/delay functionality * Timestamp/delay functionality
*/ */
struct timeval prev_ts = {0, 0}, prev_delay_ts = {0,0}; struct timeval prev_ts = {0, 0}, prev_delay_ts = {0,0};
#if defined(_WIN32) #if defined(_WIN32)
struct timeval delay_tv; struct timeval delay_tv;
FD_SET delay_fds; FD_SET delay_fds;
SOCKET delay_socket = 0; SOCKET delay_socket = 0;
#endif #endif
void (*print_time)() = NULL, (*dump_delay)() = dump_delay_proc_init; void (*print_time)() = NULL, (*dump_delay)() = dump_delay_proc_init;
/* /*
* When !Win32, windowsize stuff. We leave it in regardless to avoid * Window-size functionality (adjust output based on width of console display)
* any additional #if complication/obfuscation.
*/ */
uint32_t ws_row, ws_col = 80, ws_col_forced = 0; uint32_t ws_row, ws_col = 80, ws_col_forced = 0;
int main(int argc, char **argv) { int main(int argc, char **argv) {
int32_t c; int32_t c;
signal(SIGINT, clean_exit); signal(SIGINT, clean_exit);
signal(SIGABRT, clean_exit); signal(SIGABRT, clean_exit);
#if !defined(_WIN32) #if !defined(_WIN32)
signal(SIGQUIT, clean_exit); signal(SIGQUIT, clean_exit);
signal(SIGPIPE, clean_exit); signal(SIGPIPE, clean_exit);
signal(SIGWINCH, update_windowsize); signal(SIGWINCH, update_windowsize);
#endif #endif
while ((c = getopt(argc, argv, "LNhXViwqpevxlDtTRMs:n:c:d:A:I:O:S:P:F:W:")) setlocale(LC_ALL, "");
!= EOF) {
#if !defined(_WIN32)
{
char const *locale = getenv("LANG");
if (locale == NULL)
locale = "en_US";
setlocale(LC_CTYPE, locale);
}
#endif
while ((c = getopt(argc, argv, "LNhXViwqpevxlDtTRMK:Cs:n:c:d:A:I:O:S:P:F:W:"
)) != EOF) {
switch (c) { switch (c) {
case 'W': { case 'W': {
if (!strcasecmp(optarg, "normal")) if (!strcasecmp(optarg, "normal"))
dump_func = &dump_formatted; dump_func = &dump_formatted;
else if (!strcasecmp(optarg, "byline")) else if (!strcasecmp(optarg, "byline"))
dump_func = &dump_byline; dump_func = &dump_byline;
else if (!strcasecmp(optarg, "none")) else if (!strcasecmp(optarg, "none"))
dump_func = &dump_unwrapped; dump_func = &dump_unwrapped;
else if (!strcasecmp(optarg, "single")) { else if (!strcasecmp(optarg, "single")) {
dump_func = &dump_unwrapped; dump_func = &dump_unwrapped;
dump_single = 1; dump_single = 1;
} else { } else {
printf("fatal: unknown wrap method '%s'\n", optarg); printf("fatal: unknown wrap method '%s'\n", optarg);
usage(-1); usage();
} }
} break; } break;
case 'F': case 'F':
filter_file = optarg; filter_file = optarg;
break; break;
case 'P': case 'P':
nonprint_char = *optarg; nonprint_char = *optarg;
break; break;
case 'S': case 'S': {
limitlen = atoi(optarg); limitlen = _atoui32(optarg);
break; break;
}
case 'O': case 'O':
dump_file = optarg; dump_file = optarg;
break; break;
case 'I': case 'I':
read_file = optarg; read_file = optarg;
break; break;
case 'A': case 'A':
match_after = atoi(optarg) + 1; match_after = _atoui32(optarg);
if (match_after < UINT32_MAX)
match_after++;
break; break;
#if defined(_WIN32) #if defined(_WIN32)
case 'L': case 'L':
win32_listdevices(); win32_listdevices();
clean_exit(0); clean_exit(2);
case 'd': case 'd':
usedev = win32_usedevice(optarg); usedev = win32_usedevice(optarg);
break; break;
#else #else
case 'L': case 'L':
perror("-L is a Win32-only option"); perror("-L is a Win32-only option");
clean_exit(-1); clean_exit(2);
case 'd': case 'd':
usedev = optarg; usedev = optarg;
/* Linux: any = DLT_LINUX_SLL, pcap says incompatible with VLAN
*/
if (!strncasecmp(usedev, "any", 3))
include_vlan = 0;
break; break;
#endif #endif
case 'c': case 'c':
ws_col_forced = atoi(optarg); ws_col_forced = atoi(optarg);
break; break;
case 'n': case 'n':
max_matches = atoi(optarg); max_matches = _atoui32(optarg);
break; break;
case 's': { case 's': {
uint16_t value = atoi(optarg); uint16_t value = _atoui32(optarg);
if (value > 0) if (value > 0)
snaplen = value; snaplen = value;
} break; } break;
case 'C':
enable_hilite = 1;
break;
case 'M': case 'M':
re_multiline_match = 0; re_multiline_match = 0;
break; break;
case 'R': case 'R':
dont_dropprivs = 1; dont_dropprivs = 1;
break; break;
case 'T': case 'T':
print_time = &print_time_diff; if (print_time == &print_time_diff) {
print_time = print_time_offset;
memset(&prev_ts, 0, sizeof(prev_ts));
} else {
print_time = &print_time_diff;
#if defined(_WIN32) #if defined(_WIN32)
prev_ts.tv_sec = (uint32_t)time(NULL); prev_ts.tv_sec = (uint32_t)time(NULL);
prev_ts.tv_usec = 0; prev_ts.tv_usec = 0;
#else #else
gettimeofday(&prev_ts, NULL); gettimeofday(&prev_ts, NULL);
#endif #endif
}
break; break;
case 't': case 't':
print_time = &print_time_absolute; print_time = &print_time_absolute;
break; break;
case 'D': case 'D':
want_delay = 1; want_delay = 1;
break; break;
case 'l': case 'l':
setvbuf(stdout, NULL, _IOLBF, 0); setvbuf(stdout, NULL, _IOLBF, 0);
break; break;
skipping to change at line 310 skipping to change at line 340
re_ignore_case++; re_ignore_case++;
break; break;
case 'V': case 'V':
version(); version();
case 'X': case 'X':
bin_match++; bin_match++;
break; break;
case 'N': case 'N':
show_proto++; show_proto++;
break; break;
#if USE_TCPKILL
case 'K':
tcpkill_active = _atoui32(optarg);
break;
#endif
case 'h': case 'h':
usage(0); usage();
default: default:
usage(-1); usage();
} }
} }
if (show_hex && dump_func != &dump_formatted) { if (show_hex && dump_func != &dump_formatted) {
printf("fatal: -x (hex dump) is incompatible with -W (alternate format)\ n"); printf("fatal: -x (hex dump) is incompatible with -W (alternate format)\ n");
usage(-1); usage();
} }
if (argv[optind]) if (argv[optind])
match_data = argv[optind++]; match_data = argv[optind++];
if (read_file) { #if USE_TCPKILL
if (tcpkill_active)
if (!(pd = pcap_open_offline(read_file, pc_err))) { tcpkill_init();
perror(pc_err); #endif
clean_exit(-1);
}
live_read = 0;
printf("input: %s\n", read_file);
} else { /* Setup PCAP input */
char *dev = usedev ? usedev : pcap_lookupdev(pc_err); if (setup_pcap_source())
clean_exit(2);
if (!dev) { /* Setup BPF filter */
perror(pc_err);
clean_exit(-1);
}
if ((pd = pcap_open_live(dev, snaplen, promisc, to, pc_err)) == NULL) { if (setup_bpf_filter(argv)) {
perror(pc_err); include_vlan = 0;
clean_exit(-1); if (filter) { free(filter); filter = NULL; }
}
if (pcap_lookupnet(dev, &net.s_addr, &mask.s_addr, pc_err) == -1) {
perror(pc_err);
memset(&net, 0, sizeof(net));
memset(&mask, 0, sizeof(mask));
}
if (quiet < 2) { if (setup_bpf_filter(argv)) {
printf("interface: %s", dev); pcap_perror(pd, "pcap");
if (net.s_addr && mask.s_addr) { clean_exit(2);
printf(" (%s/", inet_ntoa(net));
printf("%s)", inet_ntoa(mask));
}
printf("\n");
} }
} }
if (filter_file) { if (filter) {
char buf[1024] = {0}; if (quiet < 2)
FILE *f = fopen(filter_file, "r"); printf("filter: %s\n", filter);
free(filter);
if (!f || !fgets(buf, sizeof(buf)-1, f)) { }
fprintf(stderr, "fatal: unable to get filter from %s: %s\n", filter_
file, strerror(errno));
usage(-1);
}
fclose(f);
filter = get_filter_from_string(buf);
if (pcap_compile(pd, &pcapfilter, filter, 0, mask.s_addr)) {
pcap_perror(pd, "pcap compile");
clean_exit(-1);
}
} else if (argv[optind]) {
filter = get_filter_from_argv(&argv[optind]);
if (pcap_compile(pd, &pcapfilter, filter, 0, mask.s_addr)) { /* Setup matcher */
free(filter);
filter = get_filter_from_argv(&argv[optind-1]);
#if USE_PCAP_RESTART if (match_data) {
PCAP_RESTART_FUNC(); if (setup_matcher())
#endif clean_exit(2);
if (pcap_compile(pd, &pcapfilter, filter, 0, mask.s_addr)) {
pcap_perror(pd, "pcap compile");
clean_exit(-1);
} else match_data = NULL;
}
} else { if (quiet < 2 && strlen(match_data))
char *default_filter = BPF_FILTER_IP; printf("%smatch: %s%s\n", invert_match?"don't ":"",
(bin_data && !strchr(match_data, 'x'))?"0x":"", match_data);
if (pcap_compile(pd, &pcapfilter, default_filter, 0, mask.s_addr)) { if (re_match_word) free(match_data);
pcap_perror(pd, "pcap compile");
clean_exit(-1);
}
} }
if (filter && quiet < 2) /* Misc */
printf("filter: %s\n", filter);
if (pcap_setfilter(pd, &pcapfilter)) { if (dump_file) {
pcap_perror(pd, "pcap set"); pd_dump = pcap_dump_open(pd, dump_file);
clean_exit(-1); if (!pd_dump) {
fprintf(stderr, "fatal: %s\n", pcap_geterr(pd));
clean_exit(2);
} else printf("output: %s\n", dump_file);
} }
if (match_data) { update_windowsize(0);
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 bin
ary matching\n");
clean_exit(-1);
}
len = (uint32_t)strlen(match_data); #if defined(_WIN32)
if (len % 2 != 0 || !strishex(match_data)) { win32_initwinsock();
fprintf(stderr, "fatal: invalid hex string specified\n"); #endif
clean_exit(-1);
}
bin_data = malloc(len / 2); #if !defined(_WIN32) && USE_DROPPRIVS
memset(bin_data, 0, len / 2); drop_privs();
d = bin_data; #endif
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;
}
match_len = len / 2; while (pcap_loop(pd, -1, (pcap_handler)process, 0));
match_func = &bin_match_func;
} else { clean_exit(0);
#if USE_PCRE /* NOT REACHED */
uint32_t pcre_options = PCRE_UNGREEDY; return 0;
}
if (re_ignore_case) int setup_pcap_source(void) {
pcre_options |= PCRE_CASELESS; if (read_file) {
if (re_multiline_match) if (!(pd = pcap_open_offline(read_file, pc_err))) {
pcre_options |= PCRE_DOTALL; perror(pc_err);
#else return 1;
re_syntax_options = RE_CHAR_CLASSES | RE_NO_BK_PARENS | RE_NO_BK_VBA }
R |
RE_CONTEXT_INDEP_ANCHORS | RE_CONTEXT_INDEP_OPS;
if (re_multiline_match) live_read = 0;
re_syntax_options |= RE_DOT_NEWLINE; printf("input: %s\n", read_file);
if (re_ignore_case) { } else {
uint32_t i;
char *s;
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;
s = match_data;
while (*s) {
*s = tolower(*s);
s++;
}
} else pattern.translate = NULL; char *dev = usedev ? usedev :
#if defined(_WIN32)
win32_choosedevice();
#else
pcap_lookupdev(pc_err);
#endif #endif
if (re_match_word) { if (!dev) {
char *word_regex = malloc(strlen(match_data) * 3 + strlen(WORD_R perror(pc_err);
EGEX)); return 1;
sprintf(word_regex, WORD_REGEX, match_data, match_data, match_da }
ta);
match_data = word_regex;
}
#if USE_PCRE
pattern = pcre_compile(match_data, pcre_options, (const char **)&re_
err, &err_offset, 0);
if (!pattern) { if ((pd = pcap_open_live(dev, snaplen, promisc, to, pc_err)) == NULL) {
fprintf(stderr, "compile failed: %s\n", re_err); perror(pc_err);
clean_exit(-1); return 1;
} }
pattern_extra = pcre_study(pattern, 0, (const char **)&re_err); if (pcap_lookupnet(dev, &net.s_addr, &mask.s_addr, pc_err) == -1) {
#else perror(pc_err);
re_err = re_compile_pattern(match_data, strlen(match_data), &pattern memset(&net, 0, sizeof(net));
); memset(&mask, 0, sizeof(mask));
if (re_err) { }
fprintf(stderr, "regex compile: %s\n", re_err);
clean_exit(-1);
}
pattern.fastmap = (char*)malloc(256); if (quiet < 2) {
if (re_compile_fastmap(&pattern)) { printf("interface: %s", dev);
perror("fastmap compile failed"); if (net.s_addr && mask.s_addr) {
clean_exit(-1); printf(" (%s/", inet_ntoa(net));
printf("%s)", inet_ntoa(mask));
} }
#endif printf("\n");
match_func = &re_match_func;
} }
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);
switch(pcap_datalink(pd)) { switch(pcap_datalink(pd)) {
case DLT_EN10MB: case DLT_EN10MB:
link_offset = ETHHDR_SIZE; link_offset = ETHHDR_SIZE;
break; break;
case DLT_IEEE802: case DLT_IEEE802:
link_offset = TOKENRING_SIZE; link_offset = TOKENRING_SIZE;
break; break;
case DLT_FDDI: case DLT_FDDI:
skipping to change at line 565 skipping to change at line 512
#if HAVE_DLT_RAW #if HAVE_DLT_RAW
case DLT_RAW: case DLT_RAW:
link_offset = RAWHDR_SIZE; link_offset = RAWHDR_SIZE;
break; break;
#endif #endif
#if HAVE_DLT_LINUX_SLL #if HAVE_DLT_LINUX_SLL
case DLT_LINUX_SLL: case DLT_LINUX_SLL:
link_offset = ISDNHDR_SIZE; link_offset = ISDNHDR_SIZE;
include_vlan = 0;
break; break;
#endif #endif
#if HAVE_DLT_IEEE802_11_RADIO #if HAVE_DLT_IEEE802_11_RADIO
case DLT_IEEE802_11_RADIO: case DLT_IEEE802_11_RADIO:
radiotap_present = 1; radiotap_present = 1;
#endif #endif
#if HAVE_DLT_IEEE802_11 #if HAVE_DLT_IEEE802_11
case DLT_IEEE802_11: case DLT_IEEE802_11:
link_offset = IEEE80211HDR_SIZE; link_offset = IEEE80211HDR_SIZE;
break; break;
#endif #endif
#if HAVE_DLT_PFLOG
case DLT_PFLOG:
link_offset = PFLOGHDR_SIZE;
break;
#endif
#if HAVE_DLT_IPNET
case DLT_IPNET:
link_offset = IPNETHDR_SIZE;
include_vlan = 0;
break;
#endif
default: default:
fprintf(stderr, "fatal: unsupported interface type %u\n", pcap_datal ink(pd)); fprintf(stderr, "fatal: unsupported interface type %u\n", pcap_datal ink(pd));
clean_exit(-1); return 1;
} }
if (dump_file) { return 0;
if (!(pd_dump = pcap_dump_open(pd, dump_file))) { }
fprintf(stderr, "fatal: %s\n", pcap_geterr(pd));
clean_exit(-1);
} else printf("output: %s\n", dump_file);
}
#if !defined(_WIN32) int setup_bpf_filter(char **argv) {
update_windowsize(0); if (filter_file) {
#endif char buf[1024] = {0};
FILE *f = fopen(filter_file, "r");
#if defined(_WIN32) if (!f || !fgets(buf, sizeof(buf)-1, f)) {
win32_initwinsock(); fprintf(stderr, "fatal: unable to get filter from %s: %s\n", filter_
file, strerror(errno));
usage();
}
fclose(f);
filter = get_filter_from_string(buf);
if (pcap_compile(pd, &pcapfilter, filter, 0, mask.s_addr))
return 1;
} else if (argv[optind]) {
filter = get_filter_from_argv(&argv[optind]);
if (pcap_compile(pd, &pcapfilter, filter, 0, mask.s_addr)) {
free(filter);
filter = get_filter_from_argv(&argv[optind-1]);
#if USE_PCAP_RESTART
PCAP_RESTART_FUNC();
#endif #endif
#if !defined(_WIN32) && USE_DROPPRIVS if (pcap_compile(pd, &pcapfilter, filter, 0, mask.s_addr))
drop_privs(); return 1;
match_data = NULL;
}
} else {
filter = include_vlan ? strdup(BPF_TEMPLATE_IP_VLAN) : strdup(BPF_TEMPLA
TE_IP);
if (pcap_compile(pd, &pcapfilter, filter, 0, mask.s_addr))
return 1;
}
if (pcap_setfilter(pd, &pcapfilter))
return 1;
return 0;
}
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");
return 1;
}
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;
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;
}
match_len = len / 2;
match_func = &bin_match_func;
} else {
#if USE_PCRE
uint32_t pcre_options = PCRE_UNGREEDY;
if (re_ignore_case)
pcre_options |= PCRE_CASELESS;
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;
if (re_multiline_match)
re_syntax_options |= RE_DOT_NEWLINE;
if (re_ignore_case) {
uint32_t i;
char *s;
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;
s = match_data;
while (*s) {
*s = tolower(*s);
s++;
}
} else pattern.translate = NULL;
#endif #endif
while (pcap_loop(pd, 0, (pcap_handler)process, 0)); if (re_match_word) {
char *word_regex = (char*)malloc(strlen(match_data) * 3 + strlen(WOR
D_REGEX));
sprintf(word_regex, WORD_REGEX, match_data, match_data, match_data);
match_data = word_regex;
}
clean_exit(0); #if USE_PCRE
pattern = pcre_compile(match_data, pcre_options, (const char **)&re_err,
&err_offset, 0);
if (!pattern) {
fprintf(stderr, "compile failed: %s\n", re_err);
return 1;
}
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);
return 1;
}
pattern.fastmap = (char*)malloc(256);
if (re_compile_fastmap(&pattern)) {
perror("fastmap compile failed");
return 1;
}
#endif
match_func = &re_match_func;
}
/* NOT REACHED */
return 0; return 0;
} }
static inline uint8_t vlan_frame_count(u_char *p, uint16_t limit) {
uint8_t *et = (uint8_t*)(p + 12);
uint16_t ether_type = EXTRACT_16BITS(et);
uint8_t count = 0;
while ((void*)et < (void*)(p + limit) &&
ether_type != ETHERTYPE_IP &&
ether_type != ETHERTYPE_IPV6) {
count++;
et += VLANHDR_SIZE;
ether_type = EXTRACT_16BITS(et);
}
return count;
}
void process(u_char *d, struct pcap_pkthdr *h, u_char *p) { void process(u_char *d, struct pcap_pkthdr *h, u_char *p) {
struct ip *ip4_pkt = (struct ip *) (p + link_offset); uint8_t vlan_offset = include_vlan ? vlan_frame_count(p, h->caplen) * VLANHD
R_SIZE : 0;
struct ip *ip4_pkt = (struct ip *) (p + link_offset + vlan_offset);
#if USE_IPv6 #if USE_IPv6
struct ip6_hdr *ip6_pkt = (struct ip6_hdr*)(p + link_offset); struct ip6_hdr *ip6_pkt = (struct ip6_hdr*)(p + link_offset + vlan_offset);
#endif #endif
uint32_t ip_ver; uint32_t ip_ver;
uint8_t ip_proto = 0; uint8_t ip_proto = 0;
uint32_t ip_hl = 0; uint32_t ip_hl = 0;
uint32_t ip_off = 0; uint32_t ip_off = 0;
uint8_t fragmented = 0; uint8_t fragmented = 0;
uint16_t frag_offset = 0; uint16_t frag_offset = 0;
uint32_t frag_id = 0; uint32_t frag_id = 0;
char ip_src[INET6_ADDRSTRLEN + 1], char ip_src[INET6_ADDRSTRLEN + 1],
ip_dst[INET6_ADDRSTRLEN + 1]; ip_dst[INET6_ADDRSTRLEN + 1];
unsigned char *data; unsigned char *data;
uint32_t len = h->caplen; uint32_t len = h->caplen - vlan_offset;
seen_frames++;
#if HAVE_DLT_IEEE802_11_RADIO #if HAVE_DLT_IEEE802_11_RADIO
if (radiotap_present) { if (radiotap_present) {
uint16_t radio_len = ((struct NGREP_rtaphdr_t *)(p))->it_len; uint16_t radio_len = ((struct NGREP_rtaphdr_t *)(p))->it_len;
ip4_pkt = (struct ip *)(p + link_offset + radio_len); ip4_pkt = (struct ip *)(p + link_offset + radio_len);
len -= radio_len; len -= radio_len;
} }
#endif #endif
ip_ver = ip4_pkt->ip_v; ip_ver = ip4_pkt->ip_v;
skipping to change at line 699 skipping to change at line 810
} }
switch (ip_proto) { switch (ip_proto) {
case IPPROTO_TCP: { case IPPROTO_TCP: {
struct tcphdr *tcp_pkt = (struct tcphdr *)((unsigned char *)(ip4_pkt ) + ip_hl); struct tcphdr *tcp_pkt = (struct tcphdr *)((unsigned char *)(ip4_pkt ) + ip_hl);
uint16_t tcphdr_offset = (frag_offset) ? 0 : (tcp_pkt->th_off * 4); uint16_t tcphdr_offset = (frag_offset) ? 0 : (tcp_pkt->th_off * 4);
data = (unsigned char *)(tcp_pkt) + tcphdr_offset; data = (unsigned char *)(tcp_pkt) + tcphdr_offset;
len -= link_offset + ip_hl + tcphdr_offset; len -= link_offset + ip_hl + tcphdr_offset;
#if USE_IPv6
if (ip_ver == 6)
len -= ntohs(ip6_pkt->ip6_plen);
#endif
if ((int32_t)len < 0) if ((int32_t)len < 0)
len = 0; len = 0;
dump_packet(h, p, ip_proto, data, len, dump_packet(h, p, ip_proto, data, len,
ip_src, ip_dst, ntohs(tcp_pkt->th_sport), ntohs(tcp_pkt- >th_dport), tcp_pkt->th_flags, ip_src, ip_dst, ntohs(tcp_pkt->th_sport), ntohs(tcp_pkt- >th_dport), tcp_pkt->th_flags,
tcphdr_offset, fragmented, frag_offset, frag_id); tcphdr_offset, fragmented, frag_offset, frag_id);
} break; } break;
case IPPROTO_UDP: { case IPPROTO_UDP: {
struct udphdr *udp_pkt = (struct udphdr *)((unsigned char *)(ip4_pkt ) + ip_hl); struct udphdr *udp_pkt = (struct udphdr *)((unsigned char *)(ip4_pkt ) + ip_hl);
uint16_t udphdr_offset = (frag_offset) ? 0 : sizeof(*udp_pkt); uint16_t udphdr_offset = (frag_offset) ? 0 : sizeof(*udp_pkt);
data = (unsigned char *)(udp_pkt) + udphdr_offset; data = (unsigned char *)(udp_pkt) + udphdr_offset;
len -= link_offset + ip_hl + udphdr_offset; len -= link_offset + ip_hl + udphdr_offset;
#if USE_IPv6
if (ip_ver == 6)
len -= ntohs(ip6_pkt->ip6_plen);
#endif
if ((int32_t)len < 0) if ((int32_t)len < 0)
len = 0; len = 0;
dump_packet(h, p, ip_proto, data, len, ip_src, ip_dst, dump_packet(h, p, ip_proto, data, len, ip_src, ip_dst,
#if HAVE_DUMB_UDPHDR
ntohs(udp_pkt->source), ntohs(udp_pkt->dest), 0,
#else
ntohs(udp_pkt->uh_sport), ntohs(udp_pkt->uh_dport), 0, ntohs(udp_pkt->uh_sport), ntohs(udp_pkt->uh_dport), 0,
#endif
udphdr_offset, fragmented, frag_offset, frag_id); udphdr_offset, fragmented, frag_offset, frag_id);
} break; } break;
case IPPROTO_ICMP: { case IPPROTO_ICMP: {
struct icmp *icmp4_pkt = (struct icmp *)((unsigned char *)(ip4_pkt ) + ip_hl); struct icmp *icmp4_pkt = (struct icmp *)((unsigned char *)(ip4_pkt ) + ip_hl);
uint16_t icmp4hdr_offset = (frag_offset) ? 0 : 4; uint16_t icmp4hdr_offset = (frag_offset) ? 0 : 4;
data = (unsigned char *)(icmp4_pkt) + icmp4hdr_offset; data = (unsigned char *)(icmp4_pkt) + icmp4hdr_offset;
len -= link_offset + ip_hl + icmp4hdr_offset; len -= link_offset + ip_hl + icmp4hdr_offset;
skipping to change at line 757 skipping to change at line 854
ip_src, ip_dst, icmp4_pkt->icmp_type, icmp4_pkt->icmp_co de, 0, ip_src, ip_dst, icmp4_pkt->icmp_type, icmp4_pkt->icmp_co de, 0,
icmp4hdr_offset, fragmented, frag_offset, frag_id); icmp4hdr_offset, fragmented, frag_offset, frag_id);
} break; } break;
#if USE_IPv6 #if USE_IPv6
case IPPROTO_ICMPV6: { case IPPROTO_ICMPV6: {
struct icmp6_hdr *icmp6_pkt = (struct icmp6_hdr *)((unsigned char *) (ip6_pkt) + ip_hl); struct icmp6_hdr *icmp6_pkt = (struct icmp6_hdr *)((unsigned char *) (ip6_pkt) + ip_hl);
uint16_t icmp6hdr_offset = (frag_offset) ? 0 : 4; uint16_t icmp6hdr_offset = (frag_offset) ? 0 : 4;
data = (unsigned char *)(icmp6_pkt) + icmp6hdr_offset; data = (unsigned char *)(icmp6_pkt) + icmp6hdr_offset;
len -= link_offset + ip_hl + ntohs(ip6_pkt->ip6_plen) + icmp6hdr_off set; len -= link_offset + ip_hl + icmp6hdr_offset;
if ((int32_t)len < 0) if ((int32_t)len < 0)
len = 0; len = 0;
dump_packet(h, p, ip_proto, data, len, dump_packet(h, p, ip_proto, data, len,
ip_src, ip_dst, icmp6_pkt->icmp6_type, icmp6_pkt->icmp6_ code, 0, ip_src, ip_dst, icmp6_pkt->icmp6_type, icmp6_pkt->icmp6_ code, 0,
icmp6hdr_offset, fragmented, frag_offset, frag_id); icmp6hdr_offset, fragmented, frag_offset, frag_id);
} break; } break;
#endif #endif
skipping to change at line 808 skipping to change at line 905
clean_exit(0); clean_exit(0);
if (match_after && keep_matching) if (match_after && keep_matching)
keep_matching--; keep_matching--;
} }
void dump_packet(struct pcap_pkthdr *h, u_char *p, uint8_t proto, unsigned char *data, uint32_t len, void dump_packet(struct pcap_pkthdr *h, u_char *p, uint8_t proto, unsigned char *data, uint32_t len,
const char *ip_src, const char *ip_dst, uint16_t sport, uint16_ t dport, uint8_t flags, const char *ip_src, const char *ip_dst, uint16_t sport, uint16_ t dport, uint8_t flags,
uint16_t hdr_offset, uint8_t frag, uint16_t frag_offset, uint32 _t frag_id) { uint16_t hdr_offset, uint8_t frag, uint16_t frag_offset, uint32 _t frag_id) {
uint16_t match_size, match_index;
if (!show_empty && len == 0) if (!show_empty && len == 0)
return; return;
if (len > limitlen) if (len > limitlen)
len = limitlen; len = limitlen;
if ((len > 0 && match_func(data, len) == invert_match) && !keep_matching) if ((len > 0 && match_func(data, len, &match_index, &match_size) == invert_m atch) && !keep_matching)
return; return;
if (!live_read && want_delay) if (!live_read && want_delay)
dump_delay(h); dump_delay(h);
{ {
char ident; char ident;
switch (proto) { switch (proto) {
case IPPROTO_TCP: ident = TCP; break; case IPPROTO_TCP: ident = TCP; break;
skipping to change at line 876 skipping to change at line 975
printf(" %u:%u", sport, dport); printf(" %u:%u", sport, dport);
} }
if (frag) if (frag)
printf(" %s%u@%u:%u", printf(" %s%u@%u:%u",
frag_offset?"+":"", frag_id, frag_offset, len); frag_offset?"+":"", frag_id, frag_offset, len);
if (dump_single) if (dump_single)
printf(" "); printf(" ");
else else
printf("\n"); printf(" #%u\n", seen_frames);
if (quiet < 3) if (quiet < 3)
dump_func(data, len); dump_func(data, len, match_index, match_size);
if (pd_dump) if (pd_dump)
pcap_dump((u_char*)pd_dump, h, p); pcap_dump((u_char*)pd_dump, h, p);
#if USE_TCPKILL
if (tcpkill_active)
tcpkill_kill(h, p, link_offset, tcpkill_active);
#endif
} }
int8_t re_match_func(unsigned char *data, uint32_t len) { int8_t re_match_func(unsigned char *data, uint32_t len, uint16_t *mindex, uint16 _t *msize) {
#if USE_PCRE #if USE_PCRE
switch(pcre_exec(pattern, 0, data, (int32_t)len, 0, 0, 0, 0)) {
static int sub[2];
switch(pcre_exec(pattern, 0, (char const *)data, (int32_t)len, 0, 0, 0, 0))
{
case PCRE_ERROR_NULL: case PCRE_ERROR_NULL:
case PCRE_ERROR_BADOPTION: case PCRE_ERROR_BADOPTION:
case PCRE_ERROR_BADMAGIC: case PCRE_ERROR_BADMAGIC:
case PCRE_ERROR_UNKNOWN_NODE: case PCRE_ERROR_UNKNOWN_NODE:
case PCRE_ERROR_NOMEMORY: case PCRE_ERROR_NOMEMORY:
perror("she's dead, jim\n"); perror("she's dead, jim\n");
clean_exit(-2); clean_exit(2);
case PCRE_ERROR_NOMATCH: case PCRE_ERROR_NOMATCH:
return 0; return 0;
default:
*mindex = sub[0];
*msize = sub[1] - sub[0];
} }
#else #else
switch (re_search(&pattern, data, (int32_t)len, 0, len, 0)) {
static struct re_registers regs;
switch (re_search(&pattern, (char const *)data, (int32_t)len, 0, len, &regs)
) {
case -2: case -2:
perror("she's dead, jim\n"); perror("she's dead, jim\n");
clean_exit(-2); clean_exit(2);
case -1: case -1:
return 0; return 0;
default:
*mindex = regs.start[0];
*msize = regs.end[0] - regs.start[0];
} }
#endif #endif
if (max_matches) matches++;
matches++;
if (match_after && keep_matching != match_after) if (match_after && keep_matching != match_after)
keep_matching = match_after; keep_matching = match_after;
return 1; return 1;
} }
int8_t bin_match_func(unsigned char *data, uint32_t len) { int8_t bin_match_func(unsigned char *data, uint32_t len, uint16_t *mindex, uint1 6_t *msize) {
int32_t stop = len - match_len; int32_t stop = len - match_len;
int32_t i = 0; int32_t i = 0;
if (stop < 0) if (stop < 0)
return 0; return 0;
while (i <= stop) while (i <= stop)
if (!memcmp(data+(i++), bin_data, match_len)) { if (!memcmp(data+(i++), bin_data, match_len)) {
if (max_matches) matches++;
matches++;
if (match_after && keep_matching != match_after) if (match_after && keep_matching != match_after)
keep_matching = match_after; keep_matching = match_after;
*mindex = i - 1;
*msize = match_len;
return 1; return 1;
} }
return 0; return 0;
} }
int8_t blank_match_func(unsigned char *data, uint32_t len) { int8_t blank_match_func(unsigned char *data, uint32_t len, uint16_t *mindex, uin
if (max_matches) t16_t *msize) {
matches++; matches++;
*mindex = 0;
*msize = 0;
return 1; return 1;
} }
void dump_byline(unsigned char *data, uint32_t len) { void dump_byline(unsigned char *data, uint32_t len, uint16_t mindex, uint16_t ms ize) {
if (len > 0) { if (len > 0) {
const unsigned char *s = data; const unsigned char *s = data;
uint8_t should_hilite = (msize && enable_hilite);
unsigned char *hilite_start = data + mindex;
unsigned char *hilite_end = hilite_start + msize;
while (s < data + len) { while (s < data + len) {
if (should_hilite && s == hilite_start)
printf("%s", ANSI_hilite);
printf("%c", (*s == '\n' || isprint(*s)) ? *s : nonprint_char); printf("%c", (*s == '\n' || isprint(*s)) ? *s : nonprint_char);
s++; s++;
if (should_hilite && s == hilite_end)
printf("%s", ANSI_off);
} }
printf("\n"); printf("\n");
} }
} }
void dump_unwrapped(unsigned char *data, uint32_t len) { void dump_unwrapped(unsigned char *data, uint32_t len, uint16_t mindex, uint16_t msize) {
if (len > 0) { if (len > 0) {
const unsigned char *s = data; const unsigned char *s = data;
uint8_t should_hilite = (msize && enable_hilite);
unsigned char *hilite_start = data + mindex;
unsigned char *hilite_end = hilite_start + msize;
while (s < data + len) { while (s < data + len) {
if (should_hilite && s == hilite_start)
printf("%s", ANSI_hilite);
printf("%c", isprint(*s) ? *s : nonprint_char); printf("%c", isprint(*s) ? *s : nonprint_char);
s++; s++;
if (should_hilite && s == hilite_end)
printf("%s", ANSI_off);
} }
printf("\n"); printf("\n");
} }
} }
void dump_formatted(unsigned char *data, uint32_t len) { void dump_formatted(unsigned char *data, uint32_t len, uint16_t mindex, uint16_t msize) {
if (len > 0) { if (len > 0) {
unsigned char *str = data; uint8_t should_hilite = (msize && enable_hilite);
uint8_t width = show_hex ? 16 : (ws_col-5); unsigned char *str = data;
uint32_t i = 0, uint8_t hiliting = 0;
j = 0; uint8_t width = show_hex ? 16 : (ws_col-5);
uint32_t i = 0,
j = 0;
while (i < len) { while (i < len) {
printf(" "); printf(" ");
if (show_hex) if (show_hex) {
for (j = 0; j < width; j++) { for (j = 0; j < width; j++) {
if (should_hilite && (mindex <= (i+j) && (i+j) < mindex + ms
ize)) {
hiliting = 1;
printf("%s", ANSI_hilite);
}
if (i + j < len) if (i + j < len)
printf("%02x ", str[j]); printf("%02x ", str[j]);
else printf(" "); else printf(" ");
if ((j+1) % (width/2) == 0) if ((j+1) % (width/2) == 0)
printf(" "); printf(" ");
if (hiliting) {
hiliting = 0;
printf("%s", ANSI_off);
}
}
}
for (j = 0; j < width; j++) {
if (should_hilite && mindex <= (i+j) && (i+j) < mindex + msize)
{
hiliting = 1;
printf("%s", ANSI_hilite);
} }
for (j = 0; j < width; j++)
if (i + j < len) if (i + j < len)
printf("%c", isprint(str[j]) ? str[j] : nonprint_char); printf("%c", isprint(str[j]) ? str[j] : nonprint_char);
else printf(" "); else printf(" ");
if (hiliting) {
hiliting = 0;
printf("%s", ANSI_off);
}
}
str += width; str += width;
i += j; i += j;
printf("\n"); printf("\n");
} }
} }
} }
char *get_filter_from_string(char *str) { char *get_filter_from_string(char *str) {
const char *template = include_vlan ? BPF_TEMPLATE_USERSPEC_IP_VLAN : BPF_TE MPLATE_USERSPEC_IP;
char *mine, *s; char *mine, *s;
uint32_t len; uint32_t len;
if (!str || !*str) if (!str || !*str)
return NULL; return NULL;
len = (uint32_t)strlen(str); len = (uint32_t)strlen(str);
for (s = str; *s; s++) for (s = str; *s; s++)
if (*s == '\r' || *s == '\n') if (*s == '\r' || *s == '\n')
*s = ' '; *s = ' ';
if (!(mine = (char*)malloc(len + sizeof(BPF_MAIN_FILTER)))) if (!(mine = (char*)malloc(len + strlen(template) + 1)))
return NULL; return NULL;
memset(mine, 0, len + sizeof(BPF_MAIN_FILTER)); memset(mine, 0, len + strlen(template) + 1);
sprintf(mine, BPF_MAIN_FILTER, str); sprintf(mine, template, str);
return mine; return mine;
} }
char *get_filter_from_argv(char **argv) { char *get_filter_from_argv(char **argv) {
const char *template = include_vlan ? BPF_TEMPLATE_USERSPEC_IP_VLAN : BPF_TE MPLATE_USERSPEC_IP;
char **arg = argv, *theirs, *mine; char **arg = argv, *theirs, *mine;
char *from, *to; char *from, *to;
uint32_t len = 0; uint32_t len = 0;
if (!*arg) if (!*arg)
return NULL; return NULL;
while (*arg) while (*arg)
len += (uint32_t)strlen(*arg++) + 1; len += (uint32_t)strlen(*arg++) + 1;
if (!(theirs = (char*)malloc(len + 1)) || if (!(theirs = (char*)malloc(len + 1)) ||
!(mine = (char*)malloc(len + sizeof(BPF_MAIN_FILTER)))) !(mine = (char*)malloc(len + strlen(template) + 1)))
return NULL; return NULL;
memset(theirs, 0, len + 1); memset(theirs, 0, len + 1);
memset(mine, 0, len + sizeof(BPF_MAIN_FILTER)); memset(mine, 0, len + strlen(template) + 1);
arg = argv; arg = argv;
to = theirs; to = theirs;
while ((from = *arg++)) { while ((from = *arg++)) {
while ((*to++ = *from++)); while ((*to++ = *from++));
*(to-1) = ' '; *(to-1) = ' ';
} }
sprintf(mine, BPF_MAIN_FILTER, theirs); sprintf(mine, template, theirs);
free(theirs); free(theirs);
return mine; return mine;
} }
uint8_t strishex(char *str) { uint8_t strishex(char *str) {
char *s; char *s;
if ((s = strchr(str, 'x'))) if ((s = strchr(str, 'x')))
s++; s++;
skipping to change at line 1101 skipping to change at line 1264
secs--; secs--;
usecs = 1000000 - (prev_ts.tv_usec - h->ts.tv_usec); usecs = 1000000 - (prev_ts.tv_usec - h->ts.tv_usec);
} }
printf("+%u.%06u ", secs, usecs); printf("+%u.%06u ", secs, usecs);
prev_ts.tv_sec = h->ts.tv_sec; prev_ts.tv_sec = h->ts.tv_sec;
prev_ts.tv_usec = h->ts.tv_usec; prev_ts.tv_usec = h->ts.tv_usec;
} }
void print_time_offset(struct pcap_pkthdr *h) {
uint32_t secs, usecs;
secs = h->ts.tv_sec - prev_ts.tv_sec;
if (h->ts.tv_usec >= prev_ts.tv_usec)
usecs = h->ts.tv_usec - prev_ts.tv_usec;
else {
secs--;
usecs = 1000000 - (prev_ts.tv_usec - h->ts.tv_usec);
}
if (prev_ts.tv_sec == 0 && prev_ts.tv_usec == 0) {
prev_ts.tv_sec = h->ts.tv_sec;
prev_ts.tv_usec = h->ts.tv_usec;
secs = 0;
usecs = 0;
}
printf("+%u.%06u ", secs, usecs);
}
void dump_delay_proc_init(struct pcap_pkthdr *h) { void dump_delay_proc_init(struct pcap_pkthdr *h) {
dump_delay = &dump_delay_proc; dump_delay = &dump_delay_proc;
prev_delay_ts.tv_sec = h->ts.tv_sec; prev_delay_ts.tv_sec = h->ts.tv_sec;
prev_delay_ts.tv_usec = h->ts.tv_usec; prev_delay_ts.tv_usec = h->ts.tv_usec;
dump_delay(h); dump_delay(h);
} }
void dump_delay_proc(struct pcap_pkthdr *h) { void dump_delay_proc(struct pcap_pkthdr *h) {
skipping to change at line 1152 skipping to change at line 1336
} }
#else #else
sleep(secs); sleep(secs);
usleep(usecs); usleep(usecs);
#endif #endif
prev_delay_ts.tv_sec = h->ts.tv_sec; prev_delay_ts.tv_sec = h->ts.tv_sec;
prev_delay_ts.tv_usec = h->ts.tv_usec; prev_delay_ts.tv_usec = h->ts.tv_usec;
} }
#if !defined(_WIN32)
void update_windowsize(int32_t e) { void update_windowsize(int32_t e) {
if (e == 0 && ws_col_forced) if (e == 0 && ws_col_forced)
ws_col = ws_col_forced; ws_col = ws_col_forced;
else if (!ws_col_forced) { else if (!ws_col_forced) {
#if !defined(_WIN32)
const struct winsize ws; const struct winsize ws;
if (!ioctl(0, TIOCGWINSZ, &ws)) { if (!ioctl(0, TIOCGWINSZ, &ws)) {
ws_row = ws.ws_row; ws_row = ws.ws_row;
ws_col = ws.ws_col; ws_col = ws.ws_col;
} else { }
#else
CONSOLE_SCREEN_BUFFER_INFO csbi;
if (GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi))
{
ws_row = csbi.dwSize.Y;
ws_col = csbi.dwSize.X;
}
#endif
else {
ws_row = 24; ws_row = 24;
ws_col = 80; ws_col = 80;
} }
} }
} }
#if USE_DROPPRIVS #if !defined(_WIN32) && USE_DROPPRIVS
void drop_privs(void) { void drop_privs(void) {
struct passwd *pw; struct passwd *pw;
uid_t newuid; uid_t newuid;
gid_t newgid; gid_t newgid;
if ((getuid() || geteuid()) || dont_dropprivs) if ((getuid() || geteuid()) || dont_dropprivs)
return; return;
pw = getpwnam(DROPPRIVS_USER); pw = getpwnam(DROPPRIVS_USER);
if (!pw) { if (!pw) {
perror("attempt to drop privileges failed: getpwnam failed"); perror("attempt to drop privileges failed: getpwnam failed");
clean_exit(-1); clean_exit(2);
} }
newgid = pw->pw_gid; newgid = pw->pw_gid;
newuid = pw->pw_uid; newuid = pw->pw_uid;
if (getgroups(0, NULL) > 0) if (getgroups(0, NULL) > 0)
if (setgroups(1, &newgid) == -1) { if (setgroups(1, &newgid) == -1) {
perror("attempt to drop privileges failed"); perror("attempt to drop privileges failed");
clean_exit(-1); clean_exit(2);
} }
if (((getgid() != newgid) && (setgid(newgid) == -1)) || if (((getgid() != newgid) && (setgid(newgid) == -1)) ||
((getegid() != newgid) && (setegid(newgid) == -1)) || ((getegid() != newgid) && (setegid(newgid) == -1)) ||
((getuid() != newuid) && (setuid(newuid) == -1)) || ((getuid() != newuid) && (setuid(newuid) == -1)) ||
((geteuid() != newuid) && (seteuid(newuid) == -1))) { ((geteuid() != newuid) && (seteuid(newuid) == -1))) {
perror("attempt to drop privileges failed"); perror("attempt to drop privileges failed");
clean_exit(-1); clean_exit(2);
} }
} }
#endif #endif
#endif
void usage(int8_t e) { void usage(void) {
printf("usage: ngrep <-" printf("usage: ngrep <-"
#if defined(_WIN32) #if defined(_WIN32)
"L" "L"
#endif #endif
"hNXViwqpevxlDtTRM> <-IO pcap_dump> <-n num> <-d dev> <-A num>\n" "hNXViwqpevxlDtTRM> <-IO pcap_dump> <-n num> <-d dev> <-A num>\n"
" <-s snaplen> <-S limitlen> <-W normal|byline|single|non e> <-c cols>\n" " <-s snaplen> <-S limitlen> <-W normal|byline|single|non e> <-c cols>\n"
" <-P char> <-F file> <match expression> <bpf filter>\n" " <-P char> <-F file>"
#if USE_TCPKILL
" <-K count>"
#endif
"\n"
" <match expression> <bpf filter>\n"
" -h is help/usage\n" " -h is help/usage\n"
" -V is version information\n" " -V is version information\n"
" -q is be quiet (don't print packet reception hash marks)\n" " -q is be quiet (don't print packet reception hash marks)\n"
" -e is show empty packets\n" " -e is show empty packets\n"
" -i is ignore case\n" " -i is ignore case\n"
" -v is invert match\n" " -v is invert match\n"
" -R is don't do privilege revocation logic\n" " -R is don't do privilege revocation logic\n"
" -x is print in alternate hexdump format\n" " -x is print in alternate hexdump format\n"
" -X is interpret match expression as hexadecimal\n" " -X is interpret match expression as hexadecimal\n"
" -w is word-regex (expression must match as a word)\n" " -w is word-regex (expression must match as a word)\n"
" -p is don't go into promiscuous mode\n" " -p is don't go into promiscuous mode\n"
" -l is make stdout line buffered\n" " -l is make stdout line buffered\n"
" -D is replay pcap_dumps with their recorded time intervals\n" " -D is replay pcap_dumps with their recorded time intervals\n"
" -t is print timestamp every time a packet is matched\n" " -t is print timestamp every time a packet is matched\n"
" -T is print delta timestamp every time a packet is matched\n" " -T is print delta timestamp every time a packet is matched\n"
" specify twice for delta from first match\n"
" -M is don't do multi-line match (do single-line match instead)\n " " -M is don't do multi-line match (do single-line match instead)\n "
" -I is read packet stream from pcap format file pcap_dump\n" " -I is read packet stream from pcap format file pcap_dump\n"
" -O is dump matched packets in pcap format to pcap_dump\n" " -O is dump matched packets in pcap format to pcap_dump\n"
" -n is look at only num packets\n" " -n is look at only num packets\n"
" -A is dump num packets after a match\n" " -A is dump num packets after a match\n"
" -s is set the bpf caplen\n" " -s is set the bpf caplen\n"
" -S is set the limitlen on matched packets\n" " -S is set the limitlen on matched packets\n"
" -W is set the dump format (normal, byline, single, none)\n" " -W is set the dump format (normal, byline, single, none)\n"
" -c is force the column width to the specified size\n" " -c is force the column width to the specified size\n"
" -P is set the non-printable display char to what is specified\n" " -P is set the non-printable display char to what is specified\n"
" -F is read the bpf filter from the specified file\n" " -F is read the bpf filter from the specified file\n"
" -N is show sub protocol number\n" " -N is show sub protocol number\n"
#if defined(_WIN32) #if defined(_WIN32)
" -d is use specified device (index) instead of the pcap default\n " " -d is use specified device (index) instead of the pcap default\n "
" -L is show the winpcap device list index\n" " -L is show the winpcap device list index\n"
#else #else
" -d is use specified device instead of the pcap default\n" " -d is use specified device instead of the pcap default\n"
#endif #endif
#if USE_TCPKILL
" -K is send N packets to kill observed connections\n"
#endif
""); "");
exit(e); exit(2);
} }
void version(void) { void version(void) {
printf("ngrep: V%s, %s\n", VERSION, rcsver); printf("ngrep: V%s, %s\n", VERSION, pcap_lib_version());
exit(0); exit(0);
} }
void clean_exit(int32_t sig) { void clean_exit(int32_t sig) {
struct pcap_stat s; struct pcap_stat s;
signal(SIGINT, SIG_IGN); signal(SIGINT, SIG_IGN);
signal(SIGABRT, SIG_IGN); signal(SIGABRT, SIG_IGN);
#if !defined(_WIN32) #if !defined(_WIN32)
signal(SIGQUIT, SIG_IGN); signal(SIGQUIT, SIG_IGN);
skipping to change at line 1283 skipping to change at line 1485
#if USE_PCRE #if USE_PCRE
if (pattern) pcre_free(pattern); if (pattern) pcre_free(pattern);
if (pattern_extra) pcre_free(pattern_extra); if (pattern_extra) pcre_free(pattern_extra);
#else #else
if (pattern.translate) free(pattern.translate); if (pattern.translate) free(pattern.translate);
if (pattern.fastmap) free(pattern.fastmap); if (pattern.fastmap) free(pattern.fastmap);
#endif #endif
if (bin_data) free(bin_data); if (bin_data) free(bin_data);
if (quiet < 1 && sig >= 0 && !read_file /* We used to report pcap_stats; but PCAP manpage says pcap_stats "may or
&& pd && !pcap_stats(pd, &s)) may not" be accurate. So useless. :-( And confusing for a user to see
printf("%u received, %u dropped\n", s.ps_recv, s.ps_drop); counts not match what ngrep thinks. */
if (quiet < 1 && sig >= 0 && !read_file)
if (pd) pcap_close(pd); printf("%u received, %u matched\n", seen_frames, matches);
if (pd_dump) pcap_dump_close(pd_dump);
if (pd) pcap_close(pd);
if (pd_dumppcap) pcap_close(pd_dumppcap);
if (pd_dump) pcap_dump_close(pd_dump);
#if defined(_WIN32) #if defined(_WIN32)
if (delay_socket) closesocket(delay_socket); if (delay_socket) closesocket(delay_socket);
if (want_delay) WSACleanup(); if (want_delay) WSACleanup();
if (usedev) free(usedev); if (usedev) free(usedev);
#endif #endif
exit(sig); exit(matches ? 0 : 1);
} }
#if defined(_WIN32) #if defined(_WIN32)
int8_t win32_initwinsock(void) { int8_t win32_initwinsock(void) {
WORD wVersionRequested = MAKEWORD(2, 0); WORD wVersionRequested = MAKEWORD(2, 0);
WSADATA wsaData; WSADATA wsaData;
if (WSAStartup(wVersionRequested, &wsaData)) { if (WSAStartup(wVersionRequested, &wsaData)) {
perror("unable to initialize winsock"); perror("unable to initialize winsock");
return 0; return 0;
skipping to change at line 1327 skipping to change at line 1532
return 1; return 1;
} }
void win32_listdevices(void) { void win32_listdevices(void) {
uint32_t i = 0; uint32_t i = 0;
pcap_if_t *alldevs, *d; pcap_if_t *alldevs, *d;
char errbuf[PCAP_ERRBUF_SIZE]; char errbuf[PCAP_ERRBUF_SIZE];
if (pcap_findalldevs(&alldevs, errbuf) == -1) { if (pcap_findalldevs(&alldevs, errbuf) == -1) {
perror("unable to enumerate device list"); perror("unable to enumerate device list");
clean_exit(-1); clean_exit(2);
} }
printf("idx\tdev\n"); printf("idx\tdev\n");
printf("---\t---\n"); printf("---\t---\n");
for (d = alldevs; d != NULL; d = d->next) { for (d = alldevs; d != NULL; d = d->next) {
printf("%2u:\t%s", ++i, d->name); printf("%2u:\t%s", ++i, d->name);
if (d->description) if (d->description)
printf(" (%s)\n", d->description); printf(" (%s)\n", d->description);
skipping to change at line 1351 skipping to change at line 1556
} }
char *win32_usedevice(const char *index) { char *win32_usedevice(const char *index) {
int32_t idx = atoi(index), i = 0; int32_t idx = atoi(index), i = 0;
pcap_if_t *alldevs, *d; pcap_if_t *alldevs, *d;
char errbuf[PCAP_ERRBUF_SIZE]; char errbuf[PCAP_ERRBUF_SIZE];
char *dev = NULL; char *dev = NULL;
if (idx <= 0) { if (idx <= 0) {
perror("invalid device index"); perror("invalid device index");
clean_exit(-1); clean_exit(2);
} }
if (pcap_findalldevs(&alldevs, errbuf) == -1) { if (pcap_findalldevs(&alldevs, errbuf) == -1) {
perror("unable to enumerate devices"); perror("unable to enumerate devices");
clean_exit(-1); clean_exit(2);
} }
for (d = alldevs; d != NULL && i != idx; d = d->next) for (d = alldevs; d != NULL && i != idx; d = d->next)
if (++i == idx) if (++i == idx)
dev = _strdup(d->name); dev = _strdup(d->name);
if (i <= 0) { if (i <= 0) {
perror("no known devices"); perror("no known devices");
clean_exit(-1); clean_exit(2);
} }
if (i != idx) { if (i != idx) {
perror("unknown device specified"); perror("unknown device specified");
clean_exit(-1); clean_exit(2);
} }
pcap_freealldevs(alldevs); pcap_freealldevs(alldevs);
return dev; return dev;
} }
char *win32_choosedevice(void) {
pcap_if_t *alldevs, *d;
char errbuf[PCAP_ERRBUF_SIZE];
char *dev = NULL;
if (pcap_findalldevs(&alldevs, errbuf) == -1) {
perror("unable to enumerate devices");
clean_exit(2);
}
for (d = alldevs; d != NULL; d = d->next)
if ((d->addresses) && (d->addresses->addr))
dev = _strdup(d->name);
pcap_freealldevs(alldevs);
if (!dev)
dev = pcap_lookupdev(errbuf);
return dev;
}
#endif #endif
 End of changes. 148 change blocks. 
297 lines changed or deleted 530 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)