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);
On Thu, Aug 30, 2012 at 06:42:07PM +0200, Nikola Pajkovsky wrote:
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);
NAK, I've sent an explanation in private mail (in czech).
Vita
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);
-- 1.7.11.5
On Thu, Aug 30, 2012 at 06:42:07PM +0200, Nikola Pajkovsky wrote:
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);
^^^^^^^^^^^^^^^^^ better: promisc_init(&promisc_list, ifname)
if ifname is set, then get only promisc state of given interface if ifname is NULL, then get promisc state of all interfaces but push on list only those which have IFF_PROMISC cleared. Main reason for this is not to change interfaces we are not listening on.
If you will go the way you allow only one instance of iptraf-ng in time, you also need to rewrite instances.c.
Vita
promisc_set(promisc_list);
... ...
exit/error path promisc_restore(promisc_list); destroy_promisc_list(&promisc_list);
Vitezslav Samel vitezslav@samel.cz writes:
On Thu, Aug 30, 2012 at 06:42:07PM +0200, Nikola Pajkovsky wrote:
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);
^^^^^^^^^^^^^^^^^ better: promisc_init(&promisc_list, ifname)
if ifname is set, then get only promisc state of given interface if ifname is NULL, then get promisc state of all interfaces but push on list only those which have IFF_PROMISC cleared. Main reason for this is not to change interfaces we are not listening on.
yea, that idea comes to mine mind too, when I was rewriting it. Sad is, it was written wrong before too.
If you will go the way you allow only one instance of iptraf-ng in time, you also need to rewrite instances.c.
I will create a pid file in (/run/ or /var/run/) and check it right at the beginning of the program.
On Fri, Aug 31, 2012 at 02:10:54PM +0200, Nikola Pajkovsky wrote:
Vitezslav Samel vitezslav@samel.cz writes:
On Thu, Aug 30, 2012 at 06:42:07PM +0200, Nikola Pajkovsky wrote:
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);
^^^^^^^^^^^^^^^^^ better: promisc_init(&promisc_list, ifname)
if ifname is set, then get only promisc state of given interface if ifname is NULL, then get promisc state of all interfaces but push on list only those which have IFF_PROMISC cleared.
^^^^ and we want to make it promiscuous.
Main reason for this is not to change interfaces we are not listening on.
yea, that idea comes to mine mind too, when I was rewriting it. Sad is, it was written wrong before too.
If you will go the way you allow only one instance of iptraf-ng in time, you also need to rewrite instances.c.
I will create a pid file in (/run/ or /var/run/) and check it right at the beginning of the program.
OK, this is the best solution. Please, make the PID file location configurable (via cmdline argument preferably).
Vita
iptraf-ng@lists.fedorahosted.org