Added initial config file support.
This commit is contained in:
@@ -15,12 +15,14 @@ sbin_PROGRAMS = iftop
|
||||
iftop_SOURCES = addr_hash.c edline.c hash.c iftop.c ns_hash.c \
|
||||
options.c resolver.c screenfilter.c serv_hash.c \
|
||||
sorted_list.c threadprof.c ui.c util.c \
|
||||
addrs_ioctl.c addrs_dlpi.c dlcommon.c
|
||||
addrs_ioctl.c addrs_dlpi.c dlcommon.c \
|
||||
stringmap.c cfgfile.c vector.c
|
||||
|
||||
noinst_HEADERS = addr_hash.h ether.h ethertype.h extract.h hash.h iftop.h \
|
||||
integers.h ip.h llc.h ns_hash.h options.h resolver.h \
|
||||
screenfilter.h serv_hash.h sll.h sorted_list.h tcp.h \
|
||||
threadprof.h token.h ui.h dlcommon.h
|
||||
threadprof.h token.h ui.h dlcommon.h stringmap.h \
|
||||
vector.h
|
||||
|
||||
man_MANS = iftop.8
|
||||
|
||||
|
||||
3
TODO
3
TODO
@@ -24,3 +24,6 @@ $Id$
|
||||
|
||||
* Linear bar graphs.
|
||||
|
||||
* Count obscured connections.
|
||||
|
||||
* Startup warnings cause pause.
|
||||
|
||||
251
cfgfile.c
Normal file
251
cfgfile.c
Normal file
@@ -0,0 +1,251 @@
|
||||
/*
|
||||
* cfgfile.c:
|
||||
*
|
||||
* Copyright (c) 2003 DecisionSoft Ltd.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "stringmap.h"
|
||||
#include "iftop.h"
|
||||
#include "options.h"
|
||||
#include "cfgfile.h"
|
||||
|
||||
#define CONFIG_TYPE_STRING 0
|
||||
#define CONFIG_TYPE_BOOL 1
|
||||
#define CONFIG_TYPE_INT 2
|
||||
|
||||
#define MAX_CONFIG_LINE 2048
|
||||
|
||||
typedef struct {
|
||||
char * name;
|
||||
int type;
|
||||
} config_item_type;
|
||||
|
||||
config_item_type config_directives[] = {
|
||||
{ "interface", CONFIG_TYPE_STRING },
|
||||
{ "dns-resolution", CONFIG_TYPE_BOOL },
|
||||
{ "port-resolution", CONFIG_TYPE_BOOL },
|
||||
{ "filter-code", CONFIG_TYPE_STRING },
|
||||
{ "show-bars", CONFIG_TYPE_BOOL },
|
||||
{ "promiscuous", CONFIG_TYPE_BOOL },
|
||||
{ "show-ports", CONFIG_TYPE_INT },
|
||||
{ "hide-source", CONFIG_TYPE_INT },
|
||||
{ "hide-destination", CONFIG_TYPE_INT },
|
||||
{ "use-bytes", CONFIG_TYPE_INT },
|
||||
{ "sort", CONFIG_TYPE_INT },
|
||||
{ "line-display", CONFIG_TYPE_INT },
|
||||
{ "show-totals", CONFIG_TYPE_INT },
|
||||
{ "log-scale", CONFIG_TYPE_INT },
|
||||
{ "max-bandwidth", CONFIG_TYPE_INT },
|
||||
{ "net-filter", CONFIG_TYPE_INT },
|
||||
{ "port-display", CONFIG_TYPE_INT },
|
||||
{ NULL, 0}
|
||||
};
|
||||
|
||||
stringmap config;
|
||||
|
||||
extern options_t options ;
|
||||
|
||||
int is_cfgdirective_valid(const char *s) {
|
||||
config_item_type* t;
|
||||
for (t = config_directives; t->name != NULL; ++t)
|
||||
if (strcmp(s, t->name) == 0) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int config_init() {
|
||||
config = stringmap_new();
|
||||
return config != NULL;
|
||||
}
|
||||
|
||||
/* read_config_file:
|
||||
* Read a configuration file consisting of key: value tuples, returning a
|
||||
* stringmap of the results. Prints errors to stderr, rather than using
|
||||
* syslog, since this file is called at program startup. Returns 1 on success
|
||||
* or 0 on failure. */
|
||||
int read_config_file(const char *f) {
|
||||
int ret = 0;
|
||||
FILE *fp;
|
||||
char *line;
|
||||
int i = 1;
|
||||
|
||||
line = xmalloc(MAX_CONFIG_LINE);
|
||||
|
||||
fp = fopen(f, "rt");
|
||||
if (!fp) {
|
||||
fprintf(stderr, "%s: %s\n", f, strerror(errno));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
while (fgets(line, MAX_CONFIG_LINE, fp)) {
|
||||
char *key, *value, *r;
|
||||
|
||||
for (r = line + strlen(line) - 1; r > line && *r == '\n'; *(r--) = 0);
|
||||
|
||||
/* Get continuation lines. Ugly. */
|
||||
while (*(line + strlen(line) - 1) == '\\') {
|
||||
if (!fgets(line + strlen(line) - 1, MAX_CONFIG_LINE - strlen(line), fp))
|
||||
break;
|
||||
for (r = line + strlen(line) - 1; r > line && *r == '\n'; *(r--) = 0);
|
||||
}
|
||||
|
||||
/* Strip comment. */
|
||||
key = strpbrk(line, "#\n");
|
||||
if (key) *key = 0;
|
||||
|
||||
/* foo : bar baz quux
|
||||
* key^ ^value */
|
||||
key = line + strspn(line, " \t");
|
||||
value = strchr(line, ':');
|
||||
|
||||
if (value) {
|
||||
/* foo : bar baz quux
|
||||
* key^ ^r ^value */
|
||||
++value;
|
||||
|
||||
r = key + strcspn(key, " \t:");
|
||||
if (r != key) {
|
||||
item *I;
|
||||
*r = 0;
|
||||
|
||||
/* foo\0: bar baz quux
|
||||
* key^ ^value ^r */
|
||||
value += strspn(value, " \t");
|
||||
r = value + strlen(value) - 1;
|
||||
while (strchr(" \t", *r) && r > value) --r;
|
||||
*(r + 1) = 0;
|
||||
|
||||
/* (Removed check for zero length value.) */
|
||||
|
||||
/* Check that this is a valid key. */
|
||||
if (!is_cfgdirective_valid(key))
|
||||
fprintf(stderr, "%s:%d: warning: unknown directive \"%s\"\n", f, i, key);
|
||||
else if ((I = stringmap_insert(config, key, item_ptr(xstrdup(value)))))
|
||||
/* Don't warn of repeated directives, because they
|
||||
* may have been specified via the command line
|
||||
* Previous option takes precedence.
|
||||
*/
|
||||
fprintf(stderr, "%s:%d: warning: repeated directive \"%s\"\n", f, i, key);
|
||||
}
|
||||
}
|
||||
|
||||
memset(line, 0, MAX_CONFIG_LINE); /* security paranoia */
|
||||
|
||||
++i;
|
||||
}
|
||||
|
||||
ret = 1;
|
||||
|
||||
fail:
|
||||
if (fp) fclose(fp);
|
||||
if (line) xfree(line);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int config_get_int(const char *directive, int *value) {
|
||||
stringmap S;
|
||||
char *s, *t;
|
||||
|
||||
if (!value) return -1;
|
||||
|
||||
S = stringmap_find(config, directive);
|
||||
if (!S) return 0;
|
||||
|
||||
s = (char*)S->d.v;
|
||||
if (!*s) return -1;
|
||||
errno = 0;
|
||||
*value = strtol(s, &t, 10);
|
||||
if (*t) return -1;
|
||||
|
||||
return errno == ERANGE ? -1 : 1;
|
||||
}
|
||||
|
||||
/* config_get_float:
|
||||
* Get an integer value from a config string. Returns 1 on success, -1 on
|
||||
* failure, or 0 if no value was found. */
|
||||
int config_get_float(const char *directive, float *value) {
|
||||
item *I;
|
||||
char *s, *t;
|
||||
|
||||
if (!value) return -1;
|
||||
|
||||
I = stringmap_find(config, directive);
|
||||
if (!I) return 0;
|
||||
|
||||
s = (char*)I->v;
|
||||
if (!*s) return -1;
|
||||
errno = 0;
|
||||
*value = strtod(s, &t);
|
||||
if (*t) return -1;
|
||||
|
||||
return errno == ERANGE ? -1 : 1;
|
||||
}
|
||||
|
||||
/* config_get_string;
|
||||
* Get a string value from the config file. Returns NULL if it is not
|
||||
* present. */
|
||||
char *config_get_string(const char *directive) {
|
||||
stringmap S;
|
||||
|
||||
S = stringmap_find(config, directive);
|
||||
if (S) return (char*)S->d.v;
|
||||
else return NULL;
|
||||
}
|
||||
|
||||
/* config_get_bool:
|
||||
* Get a boolean value from the config file. Returns false if not present. */
|
||||
int config_get_bool(const char *directive) {
|
||||
char *s;
|
||||
|
||||
s = config_get_string(directive);
|
||||
if (s && (strcmp(s, "yes") == 0 || strcmp(s, "true") == 0))
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* config_get_enum:
|
||||
* Get an enumeration value from the config file. Returns false if not
|
||||
* present or an invalid value is found. */
|
||||
int config_get_enum(const char *directive, config_enumeration_type *enumeration, int *value) {
|
||||
char *s;
|
||||
config_enumeration_type *t;
|
||||
s = config_get_string(directive);
|
||||
if(s) {
|
||||
for(t = enumeration; t->name; t++) {
|
||||
if(strcmp(s,t->name) == 0) {
|
||||
*value = t->value;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
fprintf(stderr,"Invalid enumeration value \"%s\" for directive \"%s\"\n", s, directive);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* config_set_string; Sets a value in the config, possibly overriding
|
||||
* an existing value
|
||||
*/
|
||||
void config_set_string(const char *directive, const char* s) {
|
||||
stringmap S;
|
||||
|
||||
S = stringmap_find(config, directive);
|
||||
if (S) stringmap_delete_free(S);
|
||||
stringmap_insert(config, directive, item_ptr(xstrdup(s)));
|
||||
}
|
||||
|
||||
int read_config(char *file) {
|
||||
config_item_type* t;
|
||||
void* o;
|
||||
|
||||
read_config_file(file);
|
||||
if(config == NULL) {
|
||||
fprintf(stderr,"Unable to read config file\n");
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
26
cfgfile.h
Normal file
26
cfgfile.h
Normal file
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* cfgfile.h:
|
||||
*
|
||||
* Copyright (c) 2003 DecisionSoft Ltd.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __CFGFILE_H_ /* include guard */
|
||||
#define __CFGFILE_H_
|
||||
|
||||
typedef struct {
|
||||
char *name;
|
||||
int value;
|
||||
} config_enumeration_type;
|
||||
|
||||
int read_config();
|
||||
|
||||
char *config_get_string(const char *directive);
|
||||
int config_get_bool(const char *directive);
|
||||
int config_get_int(const char *directive, int *value);
|
||||
int config_get_float(const char *directive, float *value);
|
||||
int config_init();
|
||||
|
||||
|
||||
|
||||
#endif /* __CFGFILE_H_ */
|
||||
8
iftop.c
8
iftop.c
@@ -42,6 +42,7 @@
|
||||
#include "llc.h"
|
||||
#include "extract.h"
|
||||
#include "ethertype.h"
|
||||
#include "cfgfile.h"
|
||||
|
||||
|
||||
/* ethernet address of interface. */
|
||||
@@ -517,7 +518,12 @@ int main(int argc, char **argv) {
|
||||
pthread_t thread;
|
||||
struct sigaction sa = {};
|
||||
|
||||
options_read(argc, argv);
|
||||
/* read command line options and config file */
|
||||
config_init();
|
||||
options_set_defaults();
|
||||
options_read_args(argc, argv);
|
||||
read_config(options.config_file);
|
||||
options_make();
|
||||
|
||||
sa.sa_handler = finish;
|
||||
sigaction(SIGINT, &sa, NULL);
|
||||
|
||||
238
options.c
238
options.c
@@ -21,6 +21,7 @@
|
||||
|
||||
#include "iftop.h"
|
||||
#include "options.h"
|
||||
#include "cfgfile.h"
|
||||
|
||||
#if !defined(HAVE_INET_ATON) && defined(HAVE_INET_PTON)
|
||||
# define inet_aton(a, b) inet_pton(AF_INET, (a), (b))
|
||||
@@ -39,14 +40,39 @@ char optstr[] = "+i:f:nN:hpbBPm:";
|
||||
* likely to want to listen. We also compare candidate interfaces to lo. */
|
||||
static char *bad_interface_names[] = {
|
||||
"lo:",
|
||||
"lo",
|
||||
"stf", /* pseudo-device 6to4 tunnel interface */
|
||||
"gif", /* psuedo-device generic tunnel interface */
|
||||
"lo",
|
||||
"stf", /* pseudo-device 6to4 tunnel interface */
|
||||
"gif", /* psuedo-device generic tunnel interface */
|
||||
"dummy",
|
||||
"vmnet",
|
||||
NULL /* last entry must be NULL */
|
||||
};
|
||||
|
||||
config_enumeration_type sort_enumeration[] = {
|
||||
{ "2s", OPTION_SORT_DIV1 },
|
||||
{ "10", OPTION_SORT_DIV2 },
|
||||
{ "40", OPTION_SORT_DIV3 },
|
||||
{ "source", OPTION_SORT_SRC },
|
||||
{ "destination", OPTION_SORT_SRC },
|
||||
{ NULL, -1 }
|
||||
};
|
||||
|
||||
config_enumeration_type linedisplay_enumeration[] = {
|
||||
{ "two-line", OPTION_LINEDISPLAY_TWO_LINE },
|
||||
{ "one-line-both", OPTION_LINEDISPLAY_ONE_LINE_BOTH },
|
||||
{ "one-line-sent", OPTION_LINEDISPLAY_ONE_LINE_SENT },
|
||||
{ "one-line-received", OPTION_LINEDISPLAY_ONE_LINE_RECV },
|
||||
{ NULL, -1 }
|
||||
};
|
||||
|
||||
config_enumeration_type showports_enumeration[] = {
|
||||
{ "off", OPTION_PORTS_OFF },
|
||||
{ "source-only", OPTION_PORTS_SRC },
|
||||
{ "destination-only", OPTION_PORTS_DEST },
|
||||
{ "on", OPTION_PORTS_ON },
|
||||
{ NULL, -1 }
|
||||
};
|
||||
|
||||
static int is_bad_interface_name(char *i) {
|
||||
char **p;
|
||||
for (p = bad_interface_names; *p; ++p)
|
||||
@@ -65,7 +91,7 @@ static char *get_first_interface(void) {
|
||||
|
||||
nameindex = if_nameindex();
|
||||
if(nameindex == NULL) {
|
||||
return NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
while(nameindex[j].if_index != 0) {
|
||||
@@ -79,7 +105,8 @@ static char *get_first_interface(void) {
|
||||
return i;
|
||||
}
|
||||
|
||||
static void set_defaults() {
|
||||
void options_set_defaults() {
|
||||
char *s;
|
||||
/* Should go through the list of interfaces, and find the first one which
|
||||
* is up and is not lo or dummy*. */
|
||||
options.interface = get_first_interface();
|
||||
@@ -115,6 +142,18 @@ static void set_defaults() {
|
||||
options.max_bandwidth = 0; /* auto */
|
||||
options.log_scale = 0;
|
||||
options.bar_interval = 1;
|
||||
|
||||
s = getenv("HOME");
|
||||
if(s != NULL) {
|
||||
int i = strlen(s) + 9 + 1;
|
||||
options.config_file = xmalloc(i);
|
||||
snprintf(options.config_file,i,"%s/.iftoprc",s);
|
||||
fprintf(stderr,options.config_file);
|
||||
}
|
||||
else {
|
||||
options.config_file = xstrdup("iftoprc");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void die(char *msg) {
|
||||
@@ -216,11 +255,9 @@ static void usage(FILE *fp) {
|
||||
);
|
||||
}
|
||||
|
||||
void options_read(int argc, char **argv) {
|
||||
void options_read_args(int argc, char **argv) {
|
||||
int opt;
|
||||
|
||||
set_defaults();
|
||||
|
||||
opterr = 0;
|
||||
while ((opt = getopt(argc, argv, optstr)) != -1) {
|
||||
switch (opt) {
|
||||
@@ -229,41 +266,39 @@ void options_read(int argc, char **argv) {
|
||||
exit(0);
|
||||
|
||||
case 'n':
|
||||
options.dnsresolution = 0;
|
||||
config_set_string("dns-resolution","true");
|
||||
break;
|
||||
|
||||
case 'i':
|
||||
options.interface = optarg;
|
||||
config_set_string("interface", optarg);
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
options.filtercode = xstrdup(optarg);
|
||||
config_set_string("filter-code", optarg);
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
options.promiscuous = 1;
|
||||
options.promiscuous_but_choosy = 0;
|
||||
config_set_string("promiscuous", "true");
|
||||
break;
|
||||
|
||||
case 'P':
|
||||
options.showports = OPTION_PORTS_ON;
|
||||
config_set_string("port-display", "on");
|
||||
break;
|
||||
|
||||
case 'N':
|
||||
set_net_filter(optarg);
|
||||
config_set_string("net-filter", optarg);
|
||||
break;
|
||||
|
||||
case 'm':
|
||||
set_max_bandwidth(optarg);
|
||||
config_set_string("max-bandwidth", optarg);
|
||||
break;
|
||||
|
||||
|
||||
case 'b':
|
||||
options.showbars = 0;
|
||||
config_set_string("show-bars", "true");
|
||||
break;
|
||||
|
||||
case 'B':
|
||||
options.bandwidth_in_bytes = 1;
|
||||
config_set_string("use-bytes", "true");
|
||||
break;
|
||||
|
||||
case '?':
|
||||
@@ -285,3 +320,168 @@ void options_read(int argc, char **argv) {
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
/* options_config_get_string:
|
||||
* Gets a value from the config, sets *value to a copy of the value, if
|
||||
* found. Leaves the option unchanged otherwise. */
|
||||
int options_config_get_string(const char *name, char** value) {
|
||||
char *s;
|
||||
s = config_get_string(name);
|
||||
if(s != NULL) {
|
||||
*value = xstrdup(s);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int options_config_get_bool(const char *name, int* value) {
|
||||
if(config_get_string(name)) {
|
||||
*value = config_get_bool(name);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int options_config_get_int(const char *name, int* value) {
|
||||
if(config_get_string(name)) {
|
||||
config_get_int(name, value);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int options_config_get_enum(char *name, config_enumeration_type* enumeration, int *result) {
|
||||
int i;
|
||||
if(config_get_string(name)) {
|
||||
if(config_get_enum(name, enumeration, &i)) {
|
||||
*result = i;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int options_config_get_promiscuous() {
|
||||
if(config_get_string("promiscuous")) {
|
||||
options.promiscuous = config_get_bool("promiscuous");
|
||||
if(options.promiscuous) {
|
||||
/* User has explicitly requested promiscuous mode, so don't be
|
||||
* choosy */
|
||||
options.promiscuous_but_choosy = 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int options_config_get_bw_rate(char *directive, long long* result) {
|
||||
char* units;
|
||||
long long mult = 1;
|
||||
long long value;
|
||||
char *s;
|
||||
s = config_get_string(directive);
|
||||
if(s) {
|
||||
units = s + strspn(s, "0123456789");
|
||||
if(strlen(units) > 1) {
|
||||
fprintf(stderr, "Invalid units in value: %s\n", s);
|
||||
return 0;
|
||||
}
|
||||
if(strlen(units) == 1) {
|
||||
if(*units == 'k' || *units == 'K') {
|
||||
mult = 1024;
|
||||
}
|
||||
else if(*units == 'm' || *units == 'M') {
|
||||
mult = 1024 * 1024;
|
||||
}
|
||||
else if(*units == 'g' || *units == 'G') {
|
||||
mult = 1024 * 1024 * 1024;
|
||||
}
|
||||
else if(*units == 'b' || *units == 'B') {
|
||||
/* bits => mult = 1 */
|
||||
}
|
||||
else {
|
||||
fprintf(stderr, "Invalid units in value: %s\n", s);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
*units = '\0';
|
||||
if(sscanf(s, "%lld", &value) != 1) {
|
||||
fprintf(stderr, "Error reading rate: %s\n", s);
|
||||
}
|
||||
options.max_bandwidth = value * mult;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read the net filter option.
|
||||
*/
|
||||
int options_config_get_net_filter() {
|
||||
char* s;
|
||||
s = config_get_string("net-filter");
|
||||
if(s) {
|
||||
char* mask;
|
||||
|
||||
mask = strchr(s, '/');
|
||||
if (mask == NULL) {
|
||||
fprintf(stderr, "Could not parse net/mask: %s\n", s);
|
||||
return 0;
|
||||
}
|
||||
*mask = '\0';
|
||||
mask++;
|
||||
if (inet_aton(s, &options.netfilternet) == 0) {
|
||||
fprintf(stderr, "Invalid network address: %s\n", s);
|
||||
return 0;
|
||||
}
|
||||
/* Accept a netmask like /24 or /255.255.255.0. */
|
||||
if (mask[strspn(mask, "0123456789")] == '\0') {
|
||||
/* Whole string is numeric */
|
||||
int n;
|
||||
n = atoi(mask);
|
||||
if (n > 32) {
|
||||
fprintf(stderr, "Invalid netmask: %s\n", s);
|
||||
}
|
||||
else {
|
||||
if(n == 32) {
|
||||
/* This needs to be special cased, although I don't fully
|
||||
* understand why -pdw
|
||||
*/
|
||||
options.netfiltermask.s_addr = htonl(0xffffffffl);
|
||||
}
|
||||
else {
|
||||
u_int32_t mm = 0xffffffffl;
|
||||
mm >>= n;
|
||||
options.netfiltermask.s_addr = htonl(~mm);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (inet_aton(mask, &options.netfiltermask) == 0) {
|
||||
fprintf(stderr, "Invalid netmask: %s\n", s);
|
||||
}
|
||||
options.netfilternet.s_addr = options.netfilternet.s_addr & options.netfiltermask.s_addr;
|
||||
options.netfilter = 1;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void options_make() {
|
||||
options_config_get_string("interface", &options.interface);
|
||||
options_config_get_bool("dns-resolution", &options.dnsresolution);
|
||||
options_config_get_bool("port-resolution", &options.portresolution);
|
||||
options_config_get_string("filter-code", &options.filtercode);
|
||||
options_config_get_bool("show-bars", &options.showbars);
|
||||
options_config_get_promiscuous();
|
||||
options_config_get_bool("hide-source", &options.aggregate_src);
|
||||
options_config_get_bool("hide-destination", &options.aggregate_dest);
|
||||
options_config_get_bool("use-bytes", &options.bandwidth_in_bytes);
|
||||
options_config_get_enum("sort", sort_enumeration, (int*)&options.sort);
|
||||
options_config_get_enum("line-display", linedisplay_enumeration, (int*)&options.linedisplay);
|
||||
options_config_get_bool("show-totals", &options.show_totals);
|
||||
options_config_get_bool("log-scale", &options.log_scale);
|
||||
options_config_get_bw_rate("max-bandwidth", &options.max_bandwidth);
|
||||
options_config_get_enum("port-display", showports_enumeration, (int*)&options.showports);
|
||||
options_config_get_net_filter();
|
||||
};
|
||||
|
||||
28
options.h
28
options.h
@@ -33,23 +33,24 @@ typedef enum {
|
||||
OPTION_LINEDISPLAY_ONE_LINE_SENT
|
||||
} option_linedisplay_t;
|
||||
|
||||
/*
|
||||
* This structure has to be defined in the same order as the config
|
||||
* directives in cfgfile.c. Clearly this is EBW.
|
||||
*/
|
||||
typedef struct {
|
||||
/* interface on which to listen */
|
||||
char *interface;
|
||||
|
||||
int dnsresolution;
|
||||
int portresolution;
|
||||
/* pcap filter code */
|
||||
char *filtercode;
|
||||
|
||||
/* Cross network filter */
|
||||
int netfilter;
|
||||
struct in_addr netfilternet;
|
||||
struct in_addr netfiltermask;
|
||||
int dnsresolution;
|
||||
int portresolution;
|
||||
int promiscuous;
|
||||
int promiscuous_but_choosy;
|
||||
int showbars;
|
||||
option_port_t showports;
|
||||
|
||||
int promiscuous;
|
||||
int promiscuous_but_choosy;
|
||||
int aggregate_src;
|
||||
int aggregate_dest;
|
||||
int paused;
|
||||
@@ -71,6 +72,17 @@ typedef struct {
|
||||
long long max_bandwidth;
|
||||
int log_scale;
|
||||
|
||||
/* Cross network filter */
|
||||
int netfilter;
|
||||
struct in_addr netfilternet;
|
||||
struct in_addr netfiltermask;
|
||||
|
||||
char *config_file;
|
||||
|
||||
} options_t;
|
||||
|
||||
|
||||
void options_set_defaults();
|
||||
void options_read(int argc, char **argv);
|
||||
|
||||
#endif /* __OPTIONS_H_ */
|
||||
|
||||
111
stringmap.c
Normal file
111
stringmap.c
Normal file
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* stringmap.c: sucky implementation of binary trees
|
||||
*
|
||||
* This makes no attempt to balance the tree, so has bad worst-case behaviour.
|
||||
* Also, I haven't implemented removal of items from the tree. So sue me.
|
||||
*
|
||||
* Copyright (c) 2001 Chris Lightfoot. All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
static const char rcsid[] = "$Id$";
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "stringmap.h"
|
||||
#include "vector.h"
|
||||
/*include "util.h"*/
|
||||
|
||||
/* stringmap_new:
|
||||
* Allocate memory for a new stringmap. */
|
||||
stringmap stringmap_new() {
|
||||
stringmap S;
|
||||
|
||||
S = xcalloc(sizeof *S, 1);
|
||||
|
||||
return S;
|
||||
}
|
||||
|
||||
/* stringmap_delete:
|
||||
* Free memory for a stringmap. */
|
||||
void stringmap_delete(stringmap S) {
|
||||
if (!S) return;
|
||||
if (S->l) stringmap_delete(S->l);
|
||||
if (S->g) stringmap_delete(S->g);
|
||||
|
||||
xfree(S->key);
|
||||
xfree(S);
|
||||
}
|
||||
|
||||
/* stringmap_delete_free:
|
||||
* Free memory for a stringmap, and the objects contained in it, assuming that
|
||||
* they are pointers to memory allocated by xmalloc(3). */
|
||||
void stringmap_delete_free(stringmap S) {
|
||||
if (!S) return;
|
||||
if (S->l) stringmap_delete_free(S->l);
|
||||
if (S->g) stringmap_delete_free(S->g);
|
||||
|
||||
xfree(S->key);
|
||||
xfree(S->d.v);
|
||||
xfree(S);
|
||||
}
|
||||
|
||||
/* stringmap_insert:
|
||||
* Insert into S an item having key k and value d. Returns an existing key
|
||||
* or NULL if it was inserted.
|
||||
*/
|
||||
item *stringmap_insert(stringmap S, const char *k, const item d) {
|
||||
if (!S) return 0;
|
||||
if (S->key == NULL) {
|
||||
S->key = xstrdup(k);
|
||||
S->d = d;
|
||||
return NULL;
|
||||
} else {
|
||||
stringmap S2;
|
||||
for (S2 = S;;) {
|
||||
int i = strcmp(k, S2->key);
|
||||
if (i == 0) {
|
||||
return &(S2->d);
|
||||
}
|
||||
else if (i < 0) {
|
||||
if (S2->l) S2 = S2->l;
|
||||
else {
|
||||
if (!(S2->l = stringmap_new())) return NULL;
|
||||
S2->l->key = xstrdup(k);
|
||||
S2->l->d = d;
|
||||
return NULL;
|
||||
}
|
||||
} else if (i > 0) {
|
||||
if (S2->g) S2 = S2->g;
|
||||
else {
|
||||
if (!(S2->g = stringmap_new())) return NULL;
|
||||
S2->g->key = xstrdup(k);
|
||||
S2->g->d = d;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* stringmap_find:
|
||||
* Find in d an item having key k in the stringmap S, returning the item found
|
||||
* on success NULL if no key was found. */
|
||||
stringmap stringmap_find(const stringmap S, const char *k) {
|
||||
stringmap S2;
|
||||
int i;
|
||||
if (!S || S->key == NULL) return 0;
|
||||
for (S2 = S;;) {
|
||||
i = strcmp(k, S2->key);
|
||||
if (i == 0) return S2;
|
||||
else if (i < 0) {
|
||||
if (S2->l) S2 = S2->l;
|
||||
else return NULL;
|
||||
} else if (i > 0) {
|
||||
if (S2->g) S2 = S2->g;
|
||||
else return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
33
stringmap.h
Normal file
33
stringmap.h
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* stringmap.h:
|
||||
* map of strings
|
||||
*
|
||||
* Copyright (c) 2001 Chris Lightfoot. All rights reserved.
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __STRINGMAP_H_ /* include guard */
|
||||
#define __STRINGMAP_H_
|
||||
|
||||
#include "vector.h"
|
||||
|
||||
typedef struct _stringmap {
|
||||
char *key;
|
||||
item d;
|
||||
struct _stringmap *l, *g;
|
||||
} *stringmap;
|
||||
|
||||
stringmap stringmap_new(void);
|
||||
void stringmap_delete(stringmap);
|
||||
void stringmap_delete_free(stringmap);
|
||||
|
||||
/* Try to insert an item into a stringmap, returning 1 if the map already
|
||||
* contained an item with that key.
|
||||
*/
|
||||
item *stringmap_insert(stringmap, const char*, const item);
|
||||
/* Find an item in a stringmap */
|
||||
stringmap stringmap_find(const stringmap, const char*);
|
||||
|
||||
#endif /* __STRINGMAP_H_ */
|
||||
81
vector.c
Normal file
81
vector.c
Normal file
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* vector.c:
|
||||
* simple vectors
|
||||
*
|
||||
* Copyright (c) 2001 Chris Lightfoot. All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
static const char rcsid[] = "$Id$";
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
/*include "configuration.h"*/
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "vector.h"
|
||||
/*include "util.h"*/
|
||||
|
||||
vector vector_new(void) {
|
||||
vector v;
|
||||
|
||||
v = xcalloc(1, sizeof *v);
|
||||
if (!v) return NULL;
|
||||
|
||||
v->ary = xcalloc(16, sizeof *v->ary);
|
||||
v->n = 16;
|
||||
v->n_used = 0;
|
||||
return v;
|
||||
}
|
||||
|
||||
void vector_delete(vector v) {
|
||||
xfree(v->ary);
|
||||
xfree(v);
|
||||
}
|
||||
|
||||
void vector_delete_free(vector v) {
|
||||
item *i;
|
||||
vector_iterate(v, i) {
|
||||
xfree(i->v);
|
||||
}
|
||||
xfree(v->ary);
|
||||
xfree(v);
|
||||
}
|
||||
|
||||
void vector_push_back(vector v, const item t) {
|
||||
if (v->n_used == v->n) vector_reallocate(v, v->n * 2);
|
||||
v->ary[v->n_used++] = t;
|
||||
}
|
||||
|
||||
void vector_pop_back(vector v) {
|
||||
if (v->n_used > 0) {
|
||||
--v->n_used;
|
||||
if (v->n_used < v->n / 2) vector_reallocate(v, v->n / 2);
|
||||
}
|
||||
}
|
||||
|
||||
item vector_back(vector v) {
|
||||
return v->ary[v->n_used - 1];
|
||||
}
|
||||
|
||||
item *vector_remove(vector v, item *t) {
|
||||
if (t >= v->ary + v->n_used) return NULL;
|
||||
if (t < v->ary + v->n_used - 1)
|
||||
memmove(t, t + 1, (v->n_used - (t - v->ary)) * sizeof(item));
|
||||
memset(v->ary + v->n_used--, 0, sizeof(item));
|
||||
if (v->n_used < v->n / 2 && v->n > 16) {
|
||||
size_t i = t - v->ary;
|
||||
vector_reallocate(v, v->n / 2);
|
||||
t = v->ary + i;
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
void vector_reallocate(vector v, const size_t n) {
|
||||
if (n < v->n_used || n <= 0) return;
|
||||
v->ary = xrealloc(v->ary, n * sizeof(item));
|
||||
memset(v->ary + v->n_used, 0, (v->n - v->n_used) * sizeof(item));
|
||||
v->n = n;
|
||||
}
|
||||
44
vector.h
Normal file
44
vector.h
Normal file
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* vector.h:
|
||||
* simple vectors
|
||||
*
|
||||
* Copyright (c) 2001 Chris Lightfoot. All rights reserved.
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __VECTOR_H_ /* include guard */
|
||||
#define __VECTOR_H_
|
||||
|
||||
typedef union _item {
|
||||
void *v;
|
||||
long l;
|
||||
} item;
|
||||
|
||||
#define _inline inline
|
||||
|
||||
static _inline item item_long(const long l) { item u; u.l = l; return u; }
|
||||
static _inline item item_ptr(void *const v) { item u; u.v = v; return u; }
|
||||
|
||||
typedef struct _vector{
|
||||
item *ary;
|
||||
size_t n, n_used;
|
||||
} *vector;
|
||||
|
||||
vector vector_new(void);
|
||||
void vector_delete(vector);
|
||||
void vector_delete_free(vector);
|
||||
|
||||
void vector_push_back(vector, const item);
|
||||
void vector_pop_back(vector);
|
||||
item vector_back(const vector);
|
||||
|
||||
item *vector_remove(vector, item *t);
|
||||
|
||||
void vector_reallocate(vector, const size_t n);
|
||||
|
||||
/* A macro to iterate over a vector */
|
||||
#define vector_iterate(_v, _t) for ((_t) = (_v)->ary; (_t) < (_v)->ary + (_v)->n_used; ++(_t))
|
||||
|
||||
#endif /* __VECTOR_H_ */
|
||||
Reference in New Issue
Block a user