use iface_get_flags()/iface_set_flags() in the code
instead of open coded ioctl(SIOCGIFFLAGS)
Signed-off-by: Vitezslav Samel <vitezslav(a)samel.cz>
---
src/ifaces.c | 90 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
src/ifaces.h | 5 +++
src/promisc.c | 54 +++++++++++-----------------------
3 files changed, 112 insertions(+), 37 deletions(-)
diff --git a/src/ifaces.c b/src/ifaces.c
index 6640723..f84a950 100644
--- a/src/ifaces.c
+++ b/src/ifaces.c
@@ -148,6 +148,96 @@ int iface_get_mtu(const char *iface)
return ifr.ifr_mtu;
}
+int iface_get_flags(const char *iface)
+{
+ int fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
+ if (fd == -1)
+ return fd;
+
+ struct ifreq ifr;
+ strcpy(ifr.ifr_name, iface);
+ int ir = ioctl(fd, SIOCGIFFLAGS, &ifr);
+
+ /* need to preserve errno across call to close() */
+ int saved_errno = errno;
+
+ close(fd);
+
+ /* bug out if ioctl() failed */
+ if (ir != 0) {
+ errno = saved_errno;
+ return ir;
+ }
+
+ return ifr.ifr_flags;
+}
+
+int iface_set_flags(const char *iface, int flags)
+{
+ int fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
+ if (fd == -1)
+ return fd;
+
+ struct ifreq ifr;
+ strcpy(ifr.ifr_name, iface);
+ int ir = ioctl(fd, SIOCGIFFLAGS, &ifr);
+ if (ir == -1)
+ goto err;
+
+ ifr.ifr_flags |= flags;
+ ir = ioctl(fd, SIOCSIFFLAGS, &ifr);
+
+ int saved_errno;
+err: /* need to preserve errno across call to close() */
+ saved_errno = errno;
+
+ close(fd);
+
+ /* bug out if ioctl() failed */
+ if (ir != 0)
+ errno = saved_errno;
+
+ return ir;
+}
+
+int iface_clear_flags(const char *iface, int flags)
+{
+ int fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
+ if (fd == -1)
+ return fd;
+
+ struct ifreq ifr;
+ strcpy(ifr.ifr_name, iface);
+ int ir = ioctl(fd, SIOCGIFFLAGS, &ifr);
+ if (ir == -1)
+ goto err;
+
+ ifr.ifr_flags &= ~flags;
+ ir = ioctl(fd, SIOCSIFFLAGS, &ifr);
+
+ int saved_errno;
+err: /* need to preserve errno across call to close() */
+ saved_errno = errno;
+
+ close(fd);
+
+ /* bug out if ioctl() failed */
+ if (ir != 0)
+ errno = saved_errno;
+
+ return ir;
+}
+
+int iface_set_promisc(char *ifname)
+{
+ return iface_set_flags(ifname, IFF_PROMISC);
+}
+
+int iface_clear_promisc(char *ifname)
+{
+ return iface_clear_flags(ifname, IFF_PROMISC);
+}
+
int iface_get_ifname(int ifindex, char *ifname)
{
int fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
diff --git a/src/ifaces.h b/src/ifaces.h
index 4d553a6..1aa7627 100644
--- a/src/ifaces.h
+++ b/src/ifaces.h
@@ -13,6 +13,11 @@ int get_next_iface(FILE * fd, char *ifname, int n);
int iface_up(char *iface);
int iface_get_ifindex(const char *iface);
int iface_get_mtu(const char *iface);
+int iface_get_flags(const char *iface);
+int iface_set_flags(const char *iface, int flags);
+int iface_clear_flags(const char *iface, int flags);
+int iface_set_promisc(char *ifname);
+int iface_clear_promisc(char *ifname);
int iface_get_ifname(int ifindex, char *ifname);
void err_iface_down(void);
void isdn_iface_check(int *fd, char *ifname);
diff --git a/src/promisc.c b/src/promisc.c
index 633d72f..f6b54f0 100644
--- a/src/promisc.c
+++ b/src/promisc.c
@@ -34,14 +34,9 @@ details.
void init_promisc_list(struct promisc_states **list)
{
FILE *fd;
- int ifd;
char buf[IFNAMSIZ];
struct promisc_states *ptmp;
struct promisc_states *tail = NULL;
- struct ifreq ifr;
- int istat;
-
- ifd = socket(PF_INET, SOCK_DGRAM, 0);
*list = NULL;
fd = open_procnetdev();
@@ -76,17 +71,14 @@ void init_promisc_list(struct promisc_states **list)
|| (strncmp(buf, "vmnet", 5) == 0)
|| (strncmp(ptmp->params.ifname, "wvlan", 4) == 0)
|| (strncmp(ptmp->params.ifname, "lec", 3) == 0)) {
- strcpy(ifr.ifr_name, buf);
-
- istat = ioctl(ifd, SIOCGIFFLAGS, &ifr);
+ int flags = iface_get_flags(buf);
- if (istat < 0) {
+ if (flags < 0) {
write_error("Unable to obtain interface parameters for %s",
buf);
ptmp->params.state_valid = 0;
} else {
- ptmp->params.saved_state =
- ifr.ifr_flags;
+ ptmp->params.saved_state = flags;
ptmp->params.state_valid = 1;
}
}
@@ -166,20 +158,10 @@ void load_promisc_list(struct promisc_states **list)
void srpromisc(int mode, struct promisc_states *list)
{
- int fd;
- struct ifreq ifr;
struct promisc_states *ptmp;
- int istat;
ptmp = list;
- fd = socket(PF_INET, SOCK_DGRAM, 0);
-
- if (fd < 0) {
- write_error("Unable to open socket for flag change");
- return;
- }
-
while (ptmp != NULL) {
if (((strncmp(ptmp->params.ifname, "eth", 3) == 0)
|| (strncmp(ptmp->params.ifname, "fddi", 4) == 0)
@@ -189,26 +171,24 @@ void srpromisc(int mode, struct promisc_states *list)
|| (strncmp(ptmp->params.ifname, "wvlan", 4) == 0)
|| (strncmp(ptmp->params.ifname, "lec", 3) == 0))
&& (ptmp->params.state_valid)) {
-
- strcpy(ifr.ifr_name, ptmp->params.ifname);
-
- if (mode)
- ifr.ifr_flags =
- ptmp->params.saved_state | IFF_PROMISC;
- else
- ifr.ifr_flags = ptmp->params.saved_state;
-
- istat = ioctl(fd, SIOCSIFFLAGS, &ifr);
-
- if (istat < 0) {
- write_error("Promisc change failed for %s",
- ptmp->params.ifname);
+ if (mode) {
+ /* set promiscuous */
+ int r = iface_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 = iface_clear_promisc(ptmp->params.ifname);
+ if(r < 0)
+ write_error("Failed to clear promiscuous mode on %s",
ptmp->params.ifname);
}
}
ptmp = ptmp->next_entry;
}
-
- close(fd);
}
void destroy_promisc_list(struct promisc_states **list)
--
1.7.8.4