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
save_promisc_list
srpromisc
destroy_promisc_list
...
...
exit/error path
load_promisc_list
srpromisc
destroy_promisc_list
now it does
init path:
promisc_init
promisc_set_list
...
exit/error path
promisc_restore_list
promisc_destroy
Aslo code is intend to be as initialization for locking iptraf only for
one instance (it was buggy).
Signed-off-by: Nikola Pajkovsky <npajkovs(a)redhat.com>
---
src/detstats.c | 15 ++---
src/hostmon.c | 16 ++---
src/ifaces.c | 26 +++++---
src/ifaces.h | 11 +---
src/ifstats.c | 16 ++---
src/itrafmon.c | 17 ++---
src/list.h | 6 ++
src/pktsize.c | 14 ++--
src/promisc.c | 198 +++++++++++++--------------------------------------------
src/promisc.h | 28 ++------
src/serv.c | 14 ++--
11 files changed, 110 insertions(+), 251 deletions(-)
diff --git a/src/detstats.c b/src/detstats.c
index c1e415f..43b442a 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()) {
+ promisc_init(&promisc, iface);
+ promisc_set_list(&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_list(&promisc);
+ promisc_destroy(&promisc);
}
adjust_instance_count(PROCCOUNTFILE, -1);
diff --git a/src/hostmon.c b/src/hostmon.c
index 21b1797..b807926 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()) {
+ promisc_init(&promisc, ifptr);
+ promisc_set_list(&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_list(&promisc);
+ promisc_destroy(&promisc);
}
adjust_instance_count(PROCCOUNTFILE, -1);
diff --git a/src/ifaces.c b/src/ifaces.c
index 88151ef..a3a7b08 100644
--- a/src/ifaces.c
+++ b/src/ifaces.c
@@ -211,16 +211,6 @@ err: /* need to preserve errno across call to close() */
return ir;
}
-int dev_set_promisc(char *ifname)
-{
- return dev_set_flags(ifname, IFF_PROMISC);
-}
-
-int dev_clear_promisc(char *ifname)
-{
- return dev_clear_flags(ifname, IFF_PROMISC);
-}
-
int dev_get_ifname(int ifindex, char *ifname)
{
int fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
@@ -282,3 +272,19 @@ char *gen_iface_msg(char *ifptr)
return if_msg;
}
+
+
+int dev_promisc_flag(const char *dev_name)
+{
+ int flags = dev_get_flags(dev_name);
+ if (flags < 0) {
+ write_error("Unable to obtain interface parameters for %s",
+ dev_name);
+ return -1;
+ }
+
+ if (flags & IFF_PROMISC)
+ return -1;
+
+ return flags;
+}
diff --git a/src/ifaces.h b/src/ifaces.h
index d753cac..97d01ba 100644
--- a/src/ifaces.h
+++ b/src/ifaces.h
@@ -1,12 +1,8 @@
#ifndef IPTRAF_NG_IFACES_H
#define IPTRAF_NG_IFACES_H
-/***
-
-ifaces.h - prototype declaration for interface support determination
- routine.
-
-***/
+#define dev_set_promisc(dev) dev_set_flags((dev), IFF_PROMISC)
+#define dev_clr_promisc(dev) dev_clear_flags((dev), IFF_PROMISC)
FILE *open_procnetdev(void);
int get_next_iface(FILE * fd, char *ifname, int n);
@@ -17,11 +13,10 @@ int dev_get_mtu(const char *iface);
int dev_get_flags(const char *iface);
int dev_set_flags(const char *iface, int flags);
int dev_clear_flags(const char *iface, int flags);
-int dev_set_promisc(char *ifname);
-int dev_clear_promisc(char *ifname);
int dev_get_ifname(int ifindex, char *ifname);
int dev_bind_ifindex(const int fd, const int ifindex);
int dev_bind_ifname(const int fd, const char const *ifname);
char *gen_iface_msg(char *ifptr);
+int dev_promisc_flag(const char *dev_name);
#endif /* IPTRAF_NG_IFACES_H */
diff --git a/src/ifstats.c b/src/ifstats.c
index 8214838..f8943bc 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()) {
+ promisc_init(&promisc, NULL);
+ promisc_set_list(&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_list(&promisc);
+ promisc_destroy(&promisc);
}
adjust_instance_count(PROCCOUNTFILE, -1);
diff --git a/src/itrafmon.c b/src/itrafmon.c
index b35468f..a2cbc52 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,12 +626,10 @@ void ipmon(time_t facilitytime, char *ifptr)
}
}
- if (options.promisc) {
- if (first_active_facility()) {
- init_promisc_list(&promisc_list);
- save_promisc_list(promisc_list);
- srpromisc(1, promisc_list);
- }
+ LIST_HEAD(promisc);
+ if (options.promisc && first_active_facility()) {
+ promisc_init(&promisc, ifptr);
+ promisc_set_list(&promisc);
}
/*
@@ -1188,9 +1184,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_list(&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..b54d79b 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);
+ promisc_init(&promisc, ifname);
+ promisc_set_list(&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_list(&promisc);
+ promisc_destroy(&promisc);
}
adjust_instance_count(PROCCOUNTFILE, -1);
diff --git a/src/promisc.c b/src/promisc.c
index a0f5364..ffab126 100644
--- a/src/promisc.c
+++ b/src/promisc.c
@@ -13,182 +13,72 @@ promisc.c - handles the promiscuous mode flag for the Ethernet/FDDI/
#include "ifaces.h"
#include "error.h"
#include "promisc.h"
-#include "dirs.h"
-#define PROMISC_MSG_MAX 80
-
-void init_promisc_list(struct promisc_states **list)
+static void promisc_add_dev(struct list_head *promisc, const char *dev_name)
{
- 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;
- }
- }
- }
- }
-}
+ struct promisc_list *p = xmallocz(sizeof(*p));
+ strcpy(p->ifname, dev_name);
+ INIT_LIST_HEAD(&p->list);
-/*
- * 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.
- */
+ list_add_tail(&p->list, promisc);
+}
-void save_promisc_list(struct promisc_states *list)
+void promisc_init(struct list_head *promisc, const char *device_name)
{
- int fd;
- struct promisc_states *ptmp = list;
+ if (device_name) {
+ int flags = dev_promisc_flag(device_name);
+ if (flags < 0)
+ return;
- fd = open(PROMISCLISTFILE, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
+ promisc_add_dev(promisc, device_name);
- if (fd < 0) {
- write_error("Unable to save interface flags");
return;
}
- while (ptmp != NULL) {
- write(fd, &(ptmp->params), sizeof(struct promisc_params));
- ptmp = ptmp->next_entry;
- }
+ FILE *fp = open_procnetdev();
+ if (!fp)
+ die_errno("%s: open_procnetdev", __func__);
- close(fd);
-}
-
-/*
- * Load promiscuous states into list
- */
-
-void load_promisc_list(struct promisc_states **list)
-{
- int fd;
- struct promisc_states *ptmp = NULL;
- struct promisc_states *tail = NULL;
- int br;
+ char dev_name[IFNAMSIZ];
+ while (get_next_iface(fp, dev_name, sizeof(dev_name))) {
+ if (!strcmp(dev_name, ""))
+ continue;
- fd = open(PROMISCLISTFILE, O_RDONLY);
+ int flags = dev_promisc_flag(dev_name);
+ if (flags < 0)
+ continue;
- if (fd < 0) {
- write_error("Unable to retrieve saved interface flags");
- *list = NULL;
- return;
+ promisc_add_dev(promisc, dev_name);
}
- 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);
+ fclose(fp);
}
-/*
- * Set/restore interface promiscuous mode.
- */
-
-void srpromisc(int mode, struct promisc_states *list)
+void promisc_set_list(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) {
+ int r = dev_set_promisc(entry->ifname);
+ if (r < 0)
+ write_error("Failed to set promiscuous mode on %s", entry->ifname);
}
}
-void destroy_promisc_list(struct promisc_states **list)
+void promisc_restore_list(struct list_head *promisc)
{
- struct promisc_states *ptmp = *list;
- struct promisc_states *ctmp;
-
- if (ptmp != NULL)
- ctmp = ptmp->next_entry;
+ struct promisc_list *entry = NULL;
+ list_for_each_entry(entry, promisc, list) {
+ int r = dev_clr_promisc(entry->ifname);
+ if (r < 0)
+ write_error("Failed to clear promiscuous mode on %s", entry->ifname);
+ }
+}
- while (ptmp != NULL) {
- free(ptmp);
- ptmp = ctmp;
- if (ctmp != NULL)
- ctmp = ctmp->next_entry;
+void promisc_destroy(struct list_head *promisc)
+{
+ 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..79587dc 100644
--- a/src/promisc.h
+++ b/src/promisc.h
@@ -1,31 +1,17 @@
#ifndef IPTRAF_NG_PROMISC_H
#define IPTRAF_NG_PROMISC_H
-/*
- * promisc.h - definitions for promiscuous state save/recovery
- *
- * Thanks to Holger Friese
- * <evildead(a)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 state_valid;
};
-struct promisc_states {
- struct promisc_params params;
- struct promisc_states *next_entry;
-};
+void promisc_init(struct list_head *promisc, const char *device_name);
+void promisc_destroy(struct list_head *promisc);
-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 promisc_set_list(struct list_head *promisc);
+void promisc_restore_list(struct list_head *promisc);
#endif /* IPTRAF_NG_PROMISC_H */
diff --git a/src/serv.c b/src/serv.c
index 513cc94..84e4e94 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);
+ promisc_init(&promisc, ifname);
+ promisc_set_list(&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_list(&promisc);
+ promisc_destroy(&promisc);
}
adjust_instance_count(PROCCOUNTFILE, -1);
--
1.7.11.5