code was so difficult to read, that I had to rewrite it from scratch. Original code was using list structure designed only for promisc code, and that means it has to have its own adding / removing / traversing code. Not smart idea. Also I removed the code which stores and loads from disk state of promosic mode. Code does:
init path init_promisc_list(&promisc_list); save_promisc_list(promisc_list); srpromisc(1, promisc_list); destroy_promisc_list(&promisc_list);
... ...
exit/error path load_promisc_list(&promisc_list); srpromisc(0, promisc_list); destroy_promisc_list(&promisc_list);
now it does
init path init_promisc_list(&promisc_list); promisc_set(promisc_list);
... ...
exit/error path promisc_restore(promisc_list); destroy_promisc_list(&promisc_list);
Signed-off-by: Nikola Pajkovsky npajkovs@redhat.com --- src/detstats.c | 15 ++--- src/hostmon.c | 16 ++--- src/ifstats.c | 16 ++--- src/itrafmon.c | 14 ++-- src/list.h | 6 ++ src/pktsize.c | 14 ++-- src/promisc.c | 200 +++++++++++++-------------------------------------------- src/promisc.h | 28 +++----- src/serv.c | 14 ++-- 9 files changed, 92 insertions(+), 231 deletions(-)
diff --git a/src/detstats.c b/src/detstats.c index c1e415f..02b243e 100644 --- a/src/detstats.c +++ b/src/detstats.c @@ -291,7 +291,6 @@ void detstats(char *iface, time_t facilitytime) unsigned long peakpps_in = 0; unsigned long peakpps_out = 0;
- struct promisc_states *promisc_list; int fd;
/* @@ -312,11 +311,10 @@ void detstats(char *iface, time_t facilitytime) return; }
- if (first_active_facility() && options.promisc) { - init_promisc_list(&promisc_list); - save_promisc_list(promisc_list); - srpromisc(1, promisc_list); - destroy_promisc_list(&promisc_list); + LIST_HEAD(promisc); + if (options.promisc && first_active_facility()) { + init_promisc_list(&promisc); + promisc_set(&promisc); }
adjust_instance_count(PROCCOUNTFILE, 1); @@ -594,9 +592,8 @@ err: rate_destroy(&rate);
if (options.promisc && is_last_instance()) { - load_promisc_list(&promisc_list); - srpromisc(0, promisc_list); - destroy_promisc_list(&promisc_list); + promisc_restore(&promisc); + promisc_destroy(&promisc); }
adjust_instance_count(PROCCOUNTFILE, -1); diff --git a/src/hostmon.c b/src/hostmon.c index 21b1797..8b98cef 100644 --- a/src/hostmon.c +++ b/src/hostmon.c @@ -778,8 +778,6 @@ void hostmon(time_t facilitytime, char *ifptr)
int fd;
- struct promisc_states *promisc_list; - if (!facility_active(LANMONIDFILE, ifptr)) mark_facility(LANMONIDFILE, "LAN monitor", ifptr); else { @@ -796,11 +794,10 @@ void hostmon(time_t facilitytime, char *ifptr) } }
- if (first_active_facility() && options.promisc) { - init_promisc_list(&promisc_list); - save_promisc_list(promisc_list); - srpromisc(1, promisc_list); - destroy_promisc_list(&promisc_list); + LIST_HEAD(promisc); + if (options.promisc && first_active_facility()) { + init_promisc_list(&promisc); + promisc_set(&promisc); }
adjust_instance_count(PROCCOUNTFILE, 1); @@ -1031,9 +1028,8 @@ err_close:
err: if (options.promisc && is_last_instance()) { - load_promisc_list(&promisc_list); - srpromisc(0, promisc_list); - destroy_promisc_list(&promisc_list); + promisc_restore(&promisc); + promisc_destroy(&promisc); }
adjust_instance_count(PROCCOUNTFILE, -1); diff --git a/src/ifstats.c b/src/ifstats.c index 8214838..6712ed5 100644 --- a/src/ifstats.c +++ b/src/ifstats.c @@ -451,8 +451,6 @@ void ifstats(time_t facilitytime) time_t startlog = 0; struct timeval updtime;
- struct promisc_states *promisc_list; - if (!facility_active(GSTATIDFILE, "")) mark_facility(GSTATIDFILE, "general interface statistics", ""); else { @@ -469,11 +467,10 @@ void ifstats(time_t facilitytime)
initiftab(&table);
- if (first_active_facility() && options.promisc) { - init_promisc_list(&promisc_list); - save_promisc_list(promisc_list); - srpromisc(1, promisc_list); - destroy_promisc_list(&promisc_list); + LIST_HEAD(promisc); + if (options.promisc && first_active_facility()) { + init_promisc_list(&promisc); + promisc_set(&promisc); }
adjust_instance_count(PROCCOUNTFILE, 1); @@ -630,9 +627,8 @@ void ifstats(time_t facilitytime)
err: if (options.promisc && is_last_instance()) { - load_promisc_list(&promisc_list); - srpromisc(0, promisc_list); - destroy_promisc_list(&promisc_list); + promisc_restore(&promisc); + promisc_destroy(&promisc); }
adjust_instance_count(PROCCOUNTFILE, -1); diff --git a/src/itrafmon.c b/src/itrafmon.c index b35468f..b27722e 100644 --- a/src/itrafmon.c +++ b/src/itrafmon.c @@ -599,8 +599,6 @@ void ipmon(time_t facilitytime, char *ifptr) int keymode = 0; char msgstring[80];
- struct promisc_states *promisc_list; - int rvnfd = 0;
int instance_id; @@ -628,11 +626,12 @@ void ipmon(time_t facilitytime, char *ifptr) } }
+ LIST_HEAD(promisc); + if (options.promisc) { if (first_active_facility()) { - init_promisc_list(&promisc_list); - save_promisc_list(promisc_list); - srpromisc(1, promisc_list); + init_promisc_list(&promisc); + promisc_set(&promisc); } }
@@ -1188,9 +1187,8 @@ err: close_rvn_socket(rvnfd);
if (options.promisc && is_last_instance()) { - load_promisc_list(&promisc_list); - srpromisc(0, promisc_list); - destroy_promisc_list(&promisc_list); + promisc_restore(&promisc); + promisc_destroy(&promisc); }
attrset(STDATTR); diff --git a/src/list.h b/src/list.h index daa7628..a7b495e 100644 --- a/src/list.h +++ b/src/list.h @@ -80,4 +80,10 @@ static inline int list_empty(const struct list_head *head) &pos->member != (head); \ pos = list_entry(pos->member.next, typeof(*pos), member))
+#define list_for_each_entry_safe(pos, n, head, member) \ + for (pos = list_entry((head)->next, typeof(*pos), member), \ + n = list_entry(pos->member.next, typeof(*pos), member); \ + &pos->member != (head); \ + pos = n, n = list_entry(n->member.next, typeof(*n), member)) + #endif /* IPTRAF_NG_LIST_H */ diff --git a/src/pktsize.c b/src/pktsize.c index 44bc61f..c5af7fa 100644 --- a/src/pktsize.c +++ b/src/pktsize.c @@ -161,8 +161,6 @@ void packet_size_breakdown(char *ifname, time_t facilitytime) int logging = options.logging; FILE *logfile = NULL;
- struct promisc_states *promisc_list; - int fd;
if (!facility_active(PKTSIZEIDFILE, ifname)) @@ -241,11 +239,10 @@ void packet_size_breakdown(char *ifname, time_t facilitytime) updtime = tv; now = starttime = startlog = timeint = tv.tv_sec;
+ LIST_HEAD(promisc); if (first_active_facility() && options.promisc) { - init_promisc_list(&promisc_list); - save_promisc_list(promisc_list); - srpromisc(1, promisc_list); - destroy_promisc_list(&promisc_list); + init_promisc_list(&promisc); + promisc_set(&promisc); }
adjust_instance_count(PROCCOUNTFILE, 1); @@ -337,9 +334,8 @@ err: }
if (options.promisc && is_last_instance()) { - load_promisc_list(&promisc_list); - srpromisc(0, promisc_list); - destroy_promisc_list(&promisc_list); + promisc_restore(&promisc); + promisc_destroy(&promisc); }
adjust_instance_count(PROCCOUNTFILE, -1); diff --git a/src/promisc.c b/src/promisc.c index a0f5364..bc0e1fb 100644 --- a/src/promisc.c +++ b/src/promisc.c @@ -17,178 +17,66 @@ promisc.c - handles the promiscuous mode flag for the Ethernet/FDDI/
#define PROMISC_MSG_MAX 80
-void init_promisc_list(struct promisc_states **list) +void init_promisc_list(struct list_head *promisc) { - FILE *fd; char buf[IFNAMSIZ]; - struct promisc_states *ptmp; - struct promisc_states *tail = NULL; - - *list = NULL; - fd = open_procnetdev(); - - while (get_next_iface(fd, buf, sizeof(buf))) { - if (strcmp(buf, "") != 0) { - ptmp = xmalloc(sizeof(struct promisc_states)); - strcpy(ptmp->params.ifname, buf); - - if (*list == NULL) { - *list = ptmp; - } else - tail->next_entry = ptmp; - - tail = ptmp; - ptmp->next_entry = NULL; - - /* - * Retrieve and save interface flags - */ - - if ((strncmp(buf, "eth", 3) == 0) - || (strncmp(buf, "ra", 2) == 0) - || (strncmp(buf, "fddi", 4) == 0) - || (strncmp(buf, "tr", 2) == 0) - || (strncmp(buf, "ath", 3) == 0) - || (strncmp(buf, "bnep", 4) == 0) - || (strncmp(buf, "ni", 2) == 0) - || (strncmp(buf, "tap", 3) == 0) - || (strncmp(buf, "dummy", 5) == 0) - || (strncmp(buf, "br", 2) == 0) - || (strncmp(buf, "vmnet", 5) == 0) - || (strncmp(ptmp->params.ifname, "wvlan", 4) == 0) - || (strncmp(ptmp->params.ifname, "lec", 3) == 0)) { - int flags = dev_get_flags(buf); - - if (flags < 0) { - write_error("Unable to obtain interface parameters for %s", - buf); - ptmp->params.state_valid = 0; - } else { - ptmp->params.saved_state = flags; - ptmp->params.state_valid = 1; - } - } - } - } -} - -/* - * Save interfaces and their states to a temporary file. Used only by the - * first IPTraf instance. Needed in case there are subsequent, simultaneous - * instances of IPTraf, which may still need promiscuous mode even after - * the first instance exits. These subsequent instances will need to restore - * the promiscuous state from this file. - */ - -void save_promisc_list(struct promisc_states *list) -{ - int fd; - struct promisc_states *ptmp = list; - - fd = open(PROMISCLISTFILE, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
- if (fd < 0) { - write_error("Unable to save interface flags"); - return; - } + FILE *fp = open_procnetdev(); + if (!fp) + die_errno("%s: open_procnetdev", __func__); + + while (get_next_iface(fp, buf, sizeof(buf))) { + if (!strcmp(buf, "")) + continue; + + struct promisc_list *p = xmallocz(sizeof(*p)); + strcpy(p->ifname, buf); + INIT_LIST_HEAD(&p->list); + + int flags = dev_get_flags(buf); + if (flags < 0) { + write_error("Unable to obtain interface parameters for %s", + buf); + } else { + p->flags = flags; + p->state_valid = 1; + }
- while (ptmp != NULL) { - write(fd, &(ptmp->params), sizeof(struct promisc_params)); - ptmp = ptmp->next_entry; + list_add_tail(&p->list, promisc); }
- close(fd); + fclose(fp); }
-/* - * Load promiscuous states into list - */ - -void load_promisc_list(struct promisc_states **list) +void promisc_set(struct list_head *promisc) { - int fd; - struct promisc_states *ptmp = NULL; - struct promisc_states *tail = NULL; - int br; - - fd = open(PROMISCLISTFILE, O_RDONLY); - - if (fd < 0) { - write_error("Unable to retrieve saved interface flags"); - *list = NULL; - return; + struct promisc_list *entry = NULL; + list_for_each_entry(entry, promisc, list) { + int r = dev_set_promisc(entry->ifname); + if (r < 0) + write_error("Failed to set promiscuous mode on %s", + entry->ifname); } - - do { - ptmp = xmalloc(sizeof(struct promisc_states)); - br = read(fd, &(ptmp->params), sizeof(struct promisc_params)); - - if (br > 0) { - if (tail != NULL) - tail->next_entry = ptmp; - else - *list = ptmp; - - ptmp->next_entry = NULL; - tail = ptmp; - } else - free(ptmp); - } while (br > 0); - - close(fd); }
-/* - * Set/restore interface promiscuous mode. - */ - -void srpromisc(int mode, struct promisc_states *list) +void promisc_restore(struct list_head *promisc) { - struct promisc_states *ptmp; - - ptmp = list; - - while (ptmp != NULL) { - if (((strncmp(ptmp->params.ifname, "eth", 3) == 0) - || (strncmp(ptmp->params.ifname, "fddi", 4) == 0) - || (strncmp(ptmp->params.ifname, "tr", 2) == 0) - || (strncmp(ptmp->params.ifname, "ra", 2) == 0) - || (strncmp(ptmp->params.ifname, "ath", 3) == 0) - || (strncmp(ptmp->params.ifname, "wvlan", 4) == 0) - || (strncmp(ptmp->params.ifname, "lec", 3) == 0)) - && (ptmp->params.state_valid)) { - if (mode) { - /* set promiscuous */ - int r = dev_set_promisc(ptmp->params.ifname); - if(r < 0) - write_error("Failed to set promiscuous mode on %s", ptmp->params.ifname); - } else { - /* restore saved state */ - if (ptmp->params.saved_state & IFF_PROMISC) - /* was promisc, so leave it as is */ - continue; - /* wasn't promisc, clear it */ - int r = dev_clear_promisc(ptmp->params.ifname); - if(r < 0) - write_error("Failed to clear promiscuous mode on %s", ptmp->params.ifname); - } - } - ptmp = ptmp->next_entry; + struct promisc_list *entry = NULL; + list_for_each_entry(entry, promisc, list) { + if (entry->flags & IFF_PROMISC) + continue; + + int r = dev_clear_promisc(entry->ifname); + if (r < 0) + write_error("Failed to clear promiscuous mode on %s", entry->ifname); } }
-void destroy_promisc_list(struct promisc_states **list) +void promisc_destroy(struct list_head *promisc) { - struct promisc_states *ptmp = *list; - struct promisc_states *ctmp; - - if (ptmp != NULL) - ctmp = ptmp->next_entry; - - while (ptmp != NULL) { - free(ptmp); - ptmp = ctmp; - if (ctmp != NULL) - ctmp = ctmp->next_entry; + struct promisc_list *entry, *tmp; + list_for_each_entry_safe(entry, tmp, promisc, list) { + list_del(&entry->list); + free(entry); } } diff --git a/src/promisc.h b/src/promisc.h index f062ca1..c4150b3 100644 --- a/src/promisc.h +++ b/src/promisc.h @@ -1,31 +1,19 @@ #ifndef IPTRAF_NG_PROMISC_H #define IPTRAF_NG_PROMISC_H
-/* - * promisc.h - definitions for promiscuous state save/recovery - * - * Thanks to Holger Friese - * evildead@bs-pc5.et-inf.fho-emden.de for the base patch. - * Applied it, but then additional issues came up and I ended up doing more - * than slight modifications. struct iflist is becoming way too large for - * comfort and for something as little as this. - */ +#include "list.h"
-struct promisc_params { +struct promisc_list { + struct list_head list; char ifname[IFNAMSIZ]; - int saved_state; + int flags; int state_valid; };
-struct promisc_states { - struct promisc_params params; - struct promisc_states *next_entry; -};
-void init_promisc_list(struct promisc_states **list); -void save_promisc_list(struct promisc_states *list); -void load_promisc_list(struct promisc_states **list); -void srpromisc(int mode, struct promisc_states *promisc_list); -void destroy_promisc_list(struct promisc_states **list); +void init_promisc_list(struct list_head *promisc); +void promisc_set(struct list_head *promisc); +void promisc_restore(struct list_head *promisc); +void promisc_destroy(struct list_head *promisc);
#endif /* IPTRAF_NG_PROMISC_H */ diff --git a/src/serv.c b/src/serv.c index 513cc94..f0bbd46 100644 --- a/src/serv.c +++ b/src/serv.c @@ -779,8 +779,6 @@ void servmon(char *ifname, time_t facilitytime)
FILE *logfile = NULL;
- struct promisc_states *promisc_list; - WINDOW *sortwin; PANEL *sortpanel;
@@ -812,11 +810,10 @@ void servmon(char *ifname, time_t facilitytime)
loadaddports(&ports);
+ LIST_HEAD(promisc); if (first_active_facility() && options.promisc) { - init_promisc_list(&promisc_list); - save_promisc_list(promisc_list); - srpromisc(1, promisc_list); - destroy_promisc_list(&promisc_list); + init_promisc_list(&promisc); + promisc_set(&promisc); }
adjust_instance_count(PROCCOUNTFILE, 1); @@ -1091,9 +1088,8 @@ err: endservent();
if (options.promisc && is_last_instance()) { - load_promisc_list(&promisc_list); - srpromisc(0, promisc_list); - destroy_promisc_list(&promisc_list); + promisc_restore(&promisc); + promisc_destroy(&promisc); }
adjust_instance_count(PROCCOUNTFILE, -1);