fixes #119 - add support for pcap capture filters

This commit is contained in:
Jason Antman
2017-08-27 08:00:38 -04:00
parent e5455240c9
commit 7f02b84ced
6 changed files with 94 additions and 20 deletions

View File

@@ -77,13 +77,42 @@ struct dp_handle *dp_open_offline(char *fname, char *ebuf) {
}
struct dp_handle *dp_open_live(const char *device, int snaplen, int promisc,
int to_ms, char *errbuf) {
int to_ms, char *filter, char *errbuf) {
struct bpf_program fp; // compiled filter program
bpf_u_int32 maskp; // subnet mask
bpf_u_int32 netp; // interface IP
pcap_t *temp = pcap_open_live(device, snaplen, promisc, to_ms, errbuf);
if (temp == NULL) {
return NULL;
}
if (filter != NULL) {
pcap_lookupnet(device, &netp, &maskp, errbuf);
/* Compile the filter */
if(pcap_compile(temp, &fp, filter, 1, netp) == -1) {
fprintf(
stderr,
"Error calling pcap_compile for filter on device %s: %s\n",
device, pcap_geterr(temp)
);
return NULL;
}
/* set the filter */
if(pcap_setfilter(temp, &fp) == -1) {
fprintf(
stderr,
"Error setting capture filter on device %s: %s\n",
device, pcap_geterr(temp)
);
return NULL;
}
}
return dp_fillhandle(temp);
}

View File

@@ -65,7 +65,7 @@ struct dp_handle {
/* functions to set up a handle (which is basically just a pcap handle) */
struct dp_handle *dp_open_live(const char *device, int snaplen, int promisc,
int to_ms, char *errbuf);
int to_ms, char *filter, char *errbuf);
struct dp_handle *dp_open_offline(char *fname, char *ebuf);
/* functions to add callbacks */

View File

@@ -72,7 +72,8 @@ static bool wait_for_next_trigger() {
return true;
}
static int nethogsmonitor_init(int devc, char **devicenames, bool all) {
static int nethogsmonitor_init(int devc, char **devicenames,
bool all, char *filter) {
process_init();
device *devices = get_devices(devc, devicenames, all);
@@ -100,7 +101,8 @@ static int nethogsmonitor_init(int devc, char **devicenames, bool all) {
char errbuf[PCAP_ERRBUF_SIZE];
dp_handle *newhandle =
dp_open_live(current_dev->name, BUFSIZ, promiscuous, 100, errbuf);
dp_open_live(current_dev->name, BUFSIZ, promiscuous,
100, filter, errbuf);
if (newhandle != NULL) {
dp_addcb(newhandle, dp_packet_ip, process_ip);
dp_addcb(newhandle, dp_packet_ip6, process_ip6);
@@ -271,17 +273,17 @@ static void nethogsmonitor_clean_up() {
procclean();
}
int nethogsmonitor_loop(NethogsMonitorCallback cb) {
return nethogsmonitor_loop_devices(cb, 0, NULL, false);
int nethogsmonitor_loop(NethogsMonitorCallback cb, char *filter) {
return nethogsmonitor_loop_devices(cb, filter, 0, NULL, false);
}
int nethogsmonitor_loop_devices(NethogsMonitorCallback cb,
int nethogsmonitor_loop_devices(NethogsMonitorCallback cb, char *filter,
int devc, char **devicenames, bool all) {
if (monitor_run_flag) {
return NETHOGS_STATUS_FAILURE;
}
int return_value = nethogsmonitor_init(devc, devicenames, all);
int return_value = nethogsmonitor_init(devc, devicenames, all, filter);
if (return_value != NETHOGS_STATUS_OK) {
return return_value;
}

View File

@@ -53,9 +53,13 @@ typedef void (*NethogsMonitorCallback)(int action,
* occurs.
* @param cb A pointer to a callback function following the
* NethogsMonitorCallback definition
* @param filter A string (char array) pcap filter to restrict what packets
* are captured, or NULL. The filter string format is the same as that of
* tcpdump(1); for full details, see the man page for pcap-filter(7).
*/
NETHOGS_DSO_VISIBLE int nethogsmonitor_loop(NethogsMonitorCallback cb);
NETHOGS_DSO_VISIBLE int nethogsmonitor_loop(NethogsMonitorCallback cb,
char *filter);
/**
* @brief Enter the process monitoring loop and reports updates using the
@@ -65,6 +69,9 @@ NETHOGS_DSO_VISIBLE int nethogsmonitor_loop(NethogsMonitorCallback cb);
* occurs.
* @param cb A pointer to a callback function following the
* NethogsMonitorCallback definition
* @param filter A string (char array) pcap filter to restrict what packets
* are captured, or NULL. The filter string format is the same as that of
* tcpdump(1); for full details, see the man page for pcap-filter(7).
* @param devc number of values in devicenames array
* @param devicenames pointer to array of devicenames (char arrays)
* @param all when false, loopback interface and down/not running interfaces
@@ -72,7 +79,8 @@ NETHOGS_DSO_VISIBLE int nethogsmonitor_loop(NethogsMonitorCallback cb);
*/
NETHOGS_DSO_VISIBLE int nethogsmonitor_loop_devices(NethogsMonitorCallback cb,
int devc, char **devicenames,
char *filter, int devc,
char **devicenames,
bool all);
/**

View File

@@ -27,7 +27,8 @@ static void help(bool iserror) {
// output << "usage: nethogs [-V] [-b] [-d seconds] [-t] [-p] [-f (eth|ppp))]
// [device [device [device ...]]]\n";
output << "usage: nethogs [-V] [-h] [-b] [-d seconds] [-v mode] [-c count] "
"[-t] [-p] [-s] [-a] [-l] [device [device [device ...]]]\n";
"[-t] [-p] [-s] [-a] [-l] [-f filter] "
"[device [device [device ...]]]\n";
output << " -V : prints version.\n";
output << " -h : prints this help.\n";
output << " -b : bughunt mode - implies tracemode.\n";
@@ -45,6 +46,7 @@ static void help(bool iserror) {
output << " -a : monitor all devices, even loopback/stopped ones.\n";
output << " device : device(s) to monitor. default is all "
"interfaces up and running excluding loopback\n";
output << " -f : specify string pcap filter (like tcpdump).\n";
output << std::endl;
output << "When nethogs is running, press:\n";
output << " q: quit\n";
@@ -133,9 +135,10 @@ int main(int argc, char **argv) {
int promisc = 0;
bool all = false;
char *filter = NULL;
int opt;
while ((opt = getopt(argc, argv, "Vhbtpsd:v:c:la")) != -1) {
while ((opt = getopt(argc, argv, "Vhbtpsd:v:c:laf:")) != -1) {
switch (opt) {
case 'V':
versiondisplay();
@@ -171,6 +174,9 @@ int main(int argc, char **argv) {
case 'a':
all = true;
break;
case 'f':
filter = optarg;
break;
default:
help(true);
exit(EXIT_FAILURE);
@@ -216,16 +222,20 @@ int main(int argc, char **argv) {
char errbuf[PCAP_ERRBUF_SIZE];
int nb_devices = 0;
int nb_failed_devices = 0;
handle *handles = NULL;
device *current_dev = devices;
while (current_dev != NULL) {
++nb_devices;
if (!getLocal(current_dev->name, tracemode)) {
forceExit(false, "getifaddrs failed while establishing local IP.");
}
dp_handle *newhandle =
dp_open_live(current_dev->name, BUFSIZ, promisc, 100, errbuf);
dp_open_live(current_dev->name, BUFSIZ, promisc, 100, filter, errbuf);
if (newhandle != NULL) {
dp_addcb(newhandle, dp_packet_ip, process_ip);
dp_addcb(newhandle, dp_packet_ip6, process_ip6);
@@ -258,11 +268,16 @@ int main(int argc, char **argv) {
} else {
fprintf(stderr, "Error opening handler for device %s\n",
current_dev->name);
++nb_failed_devices;
}
current_dev = current_dev->next;
}
if (nb_devices == nb_failed_devices) {
forceExit(false, "Error opening pcap handlers for all devices.\n");
}
signal(SIGINT, &quit_cb);
struct dpargs *userdata = (dpargs *)malloc(sizeof(struct dpargs));