Right now on every received packet we get the interface name
on which it arrived. This is not needed and is slow.
Make use of ifindex and retrieve interface name only when needed
(when capturing on "All interfaces").
Signed-off-by: Vitezslav Samel <vitezslav(a)samel.cz>
---
src/hostmon.c | 20 ++++++++++++++--
src/ifaces.c | 50 ++++++++++++++++++++++++++++++++++++++++++
src/ifaces.h | 2 +
src/ifstats.c | 66 ++++++++++++++++++++++++++++---------------------------
src/ifstats.h | 1 +
src/itrafmon.c | 20 ++++++++++++++--
src/packet.c | 8 ++++--
src/pktsize.c | 5 +--
src/serv.c | 5 +--
9 files changed, 130 insertions(+), 47 deletions(-)
diff --git a/src/hostmon.c b/src/hostmon.c
index 32e1f1a..5f3dd8a 100644
--- a/src/hostmon.c
+++ b/src/hostmon.c
@@ -678,7 +678,7 @@ void hostmon(const struct OPTIONS *options, int facilitytime, char
*ifptr,
int is_ip;
int ch;
- char ifname[IFNAMSIZ];
+ char *ifname = ifptr;
struct timeval tv;
unsigned long starttime;
@@ -814,7 +814,7 @@ void hostmon(const struct OPTIONS *options, int facilitytime, char
*ifptr,
&& (((now - statbegin) / 60) >= facilitytime))
exitloop = 1;
- getpacket(fd, buf, &fromaddr, &ch, &br, ifname, table.tabwin);
+ getpacket(fd, buf, &fromaddr, &ch, &br, NULL, table.tabwin);
if (ch != ERR) {
if (keymode == 0) {
@@ -860,16 +860,30 @@ void hostmon(const struct OPTIONS *options, int facilitytime, char
*ifptr,
}
}
if (br > 0) {
+ char ifnamebuf[IFNAMSIZ];
+
pkt_result =
processpacket(buf, &ipacket, (unsigned int *) &br,
NULL, NULL, NULL, &fromaddr,
ofilter,
- MATCH_OPPOSITE_USECONFIG, ifname,
+ MATCH_OPPOSITE_USECONFIG, NULL,
0);
if (pkt_result != PACKET_OK)
continue;
+ if (!ifptr) {
+ /* we're capturing on "All interfaces", */
+ /* so get the name of the interface */
+ /* of this packet */
+ int r = iface_get_ifname(fromaddr.sll_ifindex, ifnamebuf);
+ if (r != 0) {
+ write_error("Unable to get interface name");
+ break; /* can't get interface name, get out! */
+ }
+ ifname = ifnamebuf;
+ }
+
if ((fromaddr.sll_hatype == ARPHRD_ETHER)
|| (fromaddr.sll_hatype == ARPHRD_FDDI)
/* fix me
diff --git a/src/ifaces.c b/src/ifaces.c
index c1e0be5..bb47142 100644
--- a/src/ifaces.c
+++ b/src/ifaces.c
@@ -100,6 +100,56 @@ void err_iface_down(void)
write_error("Specified interface not active");
}
+int iface_get_ifindex(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, SIOCGIFINDEX, &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_ifindex;
+}
+
+int iface_get_ifname(int ifindex, char *ifname)
+{
+ int fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
+ if (fd == -1)
+ return fd;
+
+ struct ifreq ifr = {
+ .ifr_ifindex = ifindex
+ };
+ int ir = ioctl(fd, SIOCGIFNAME, &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;
+ }
+
+ strncpy(ifname, ifr.ifr_name, IFNAMSIZ);
+ return ir;
+}
+
void isdn_iface_check(int *fd, char *ifname)
{
if (*fd == -1) {
diff --git a/src/ifaces.h b/src/ifaces.h
index 5bf313d..fa20324 100644
--- a/src/ifaces.h
+++ b/src/ifaces.h
@@ -11,6 +11,8 @@ ifaces.h - prototype declaration for interface support determination
FILE *open_procnetdev(void);
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_ifname(int ifindex, char *ifname);
void err_iface_down(void);
void isdn_iface_check(int *fd, char *ifname);
char *gen_iface_msg(char *ifptr);
diff --git a/src/ifstats.c b/src/ifstats.c
index d34db9e..dbde9ea 100644
--- a/src/ifstats.c
+++ b/src/ifstats.c
@@ -130,6 +130,9 @@ void initiflist(struct iflist **list)
if (!iface_up(ifname))
continue;
+ int ifindex = iface_get_ifindex(ifname);
+ if (ifindex < 0)
+ continue;
/*
* At this point, the interface is now sure to be up and running.
*/
@@ -137,6 +140,7 @@ void initiflist(struct iflist **list)
itmp = xmalloc(sizeof(struct iflist));
memset(itmp, 0, sizeof(struct iflist));
strcpy(itmp->ifname, ifname);
+ itmp->ifindex = ifindex;
index++;
itmp->index = index;
@@ -155,36 +159,33 @@ void initiflist(struct iflist **list)
fclose(fd);
}
-void positionptr(struct iftab *table, struct iflist **ptmp, char *ifname)
+struct iflist *positionptr(struct iflist *iflist, const int ifindex)
{
- struct iflist *plast = NULL;
- int ok = 0;
-
- *ptmp = table->head;
-
- while ((*ptmp != NULL) && (!ok)) {
- ok = (strcmp((*ptmp)->ifname, ifname) == 0);
+ struct iflist *ptmp = iflist;
+ struct iflist *last = ptmp;
- if (!ok) {
- if ((*ptmp)->next_entry == NULL)
- plast = *ptmp;
-
- *ptmp = (*ptmp)->next_entry;
- }
+ while ((ptmp != NULL) && (ptmp->ifindex != ifindex)) {
+ last = ptmp;
+ ptmp = ptmp->next_entry;
}
+ /* no interface was found, try to create new one */
+ if (ptmp == NULL) {
+ struct iflist *itmp = xmallocz(sizeof(struct iflist));
+ itmp->ifindex = ifindex;
+ itmp->index = last->index + 1;
+ int r = iface_get_ifname(ifindex, itmp->ifname);
+ if (r != 0) {
+ write_error("Error getting interface name");
+ return(NULL);
+ }
- if (*ptmp == NULL) {
- *ptmp = xmalloc(sizeof(struct iflist));
- memset(*ptmp, 0, sizeof(struct iflist));
- (*ptmp)->index = plast->index + 1;
- plast->next_entry = *ptmp;
- (*ptmp)->prev_entry = plast;
- (*ptmp)->next_entry = NULL;
- strcpy((*ptmp)->ifname, ifname);
-
- if ((*ptmp)->index <= LINES - 4)
- table->lastvisible = *ptmp;
+ /* last can't be NULL otherwise we will have empty iflist */
+ last->next_entry = itmp;
+ itmp->prev_entry = last;
+ itmp->next_entry = NULL;
+ ptmp = itmp;
}
+ return(ptmp);
}
void destroyiflist(struct iflist *list)
@@ -406,7 +407,6 @@ void ifstats(const struct OPTIONS *options, struct filterstate
*ofilter,
FILE *logfile = NULL;
int br;
- char ifname[IFNAMSIZ];
int ch;
@@ -520,7 +520,7 @@ void ifstats(const struct OPTIONS *options, struct filterstate
*ofilter,
&& (((now - statbegin) / 60) >= facilitytime))
exitloop = 1;
- getpacket(fd, buf, &fromaddr, &ch, &br, ifname, table.statwin);
+ getpacket(fd, buf, &fromaddr, &ch, &br, NULL, table.statwin);
switch (ch) {
case ERR:
@@ -561,13 +561,15 @@ void ifstats(const struct OPTIONS *options, struct filterstate
*ofilter,
NULL, NULL, NULL, &fromaddr,
ofilter,
MATCH_OPPOSITE_USECONFIG,
- ifname, options->v6inv4asv6);
+ NULL, options->v6inv4asv6);
if (pkt_result != PACKET_OK
&& pkt_result != MORE_FRAGMENTS)
continue;
- positionptr(&table, &ptmp, ifname);
+ ptmp = positionptr(table.head, fromaddr.sll_ifindex);
+ if (!ptmp)
+ continue;
ptmp->total++;
@@ -743,7 +745,6 @@ void detstats(char *iface, const struct OPTIONS *options, int
facilitytime,
struct iphdr *ipacket = NULL;
struct ip6_hdr *ip6packet = NULL;
- char ifname[IFNAMSIZ];
struct sockaddr_ll fromaddr;
int br;
@@ -981,7 +982,7 @@ void detstats(char *iface, const struct OPTIONS *options, int
facilitytime,
&& (((now - statbegin) / 60) >= facilitytime))
exitloop = 1;
- getpacket(fd, buf, &fromaddr, &ch, &br, ifname, statwin);
+ getpacket(fd, buf, &fromaddr, &ch, &br, NULL, statwin);
switch (ch) {
case ERR:
@@ -1011,7 +1012,7 @@ void detstats(char *iface, const struct OPTIONS *options, int
facilitytime,
processpacket(buf, &packet, (unsigned int *) &br,
NULL, NULL, NULL, &fromaddr,
ofilter,
- MATCH_OPPOSITE_USECONFIG, ifname,
+ MATCH_OPPOSITE_USECONFIG, NULL,
options->v6inv4asv6);
if (pkt_result != PACKET_OK
@@ -1124,6 +1125,7 @@ void selectiface(char *ifname, int withall, int *aborted)
if ((withall) && (list != NULL)) {
ptmp = xmalloc(sizeof(struct iflist));
strncpy(ptmp->ifname, "All interfaces", sizeof(ptmp->ifname));
+ ptmp->ifindex = 0;
ptmp->prev_entry = NULL;
list->prev_entry = ptmp;
diff --git a/src/ifstats.h b/src/ifstats.h
index 781c8df..1dfb517 100644
--- a/src/ifstats.h
+++ b/src/ifstats.h
@@ -9,6 +9,7 @@ ifstats.h - structure definitions for interface counts
struct iflist {
char ifname[IFNAMSIZ];
+ int ifindex;
unsigned int encap;
unsigned long long iptotal;
unsigned long long ip6total;
diff --git a/src/itrafmon.c b/src/itrafmon.c
index dea71b2..c32c19d 100644
--- a/src/itrafmon.c
+++ b/src/itrafmon.c
@@ -602,7 +602,7 @@ void ipmon(struct OPTIONS *options, struct filterstate *ofilter,
int curwin = 0;
int readlen;
- char ifname[IFNAMSIZ];
+ char *ifname = ifptr;
unsigned long long total_pkts = 0;
@@ -758,6 +758,8 @@ void ipmon(struct OPTIONS *options, struct filterstate *ofilter,
starttime = timeint = closedint = tv.tv_sec;
while (!exitloop) {
+ char ifnamebuf[IFNAMSIZ];
+
gettimeofday(&tv, NULL);
now = tv.tv_sec;
unow = tv.tv_sec * 1e+06 + tv.tv_usec;
@@ -833,7 +835,7 @@ void ipmon(struct OPTIONS *options, struct filterstate *ofilter,
rotate_flag = 0;
}
- getpacket(fd, tpacket, &fromaddr, &ch, &readlen, ifname,
+ getpacket(fd, tpacket, &fromaddr, &ch, &readlen, NULL,
table.tcpscreen);
if (ch == ERR)
@@ -1042,11 +1044,23 @@ void ipmon(struct OPTIONS *options, struct filterstate *ofilter,
(unsigned int *) &readlen, &br,
&sport, &dport, &fromaddr,
ofilter, MATCH_OPPOSITE_ALWAYS,
- ifname, options->v6inv4asv6);
+ NULL, options->v6inv4asv6);
if (pkt_result != PACKET_OK)
continue;
+ if (!ifptr) {
+ /* we're capturing on "All interfaces", */
+ /* so get the name of the interface */
+ /* of this packet */
+ int r = iface_get_ifname(fromaddr.sll_ifindex, ifnamebuf);
+ if (r != 0) {
+ write_error("Unable to get interface name");
+ break; /* error getting interface name, get out! */
+ }
+ ifname = ifnamebuf;
+ }
+
switch(fromaddr.sll_protocol) {
case ETH_P_IP:
ippacket = (struct iphdr *) packet;
diff --git a/src/packet.c b/src/packet.c
index c012d17..0753ee0 100644
--- a/src/packet.c
+++ b/src/packet.c
@@ -160,9 +160,11 @@ void getpacket(int fd, char *buf, struct sockaddr_ll *fromaddr, int
*ch,
fromlen = sizeof(struct sockaddr_ll);
*br = recvfrom(fd, buf, MAX_PACKET_SIZE, 0,
(struct sockaddr *) fromaddr, &fromlen);
- ifr.ifr_ifindex = fromaddr->sll_ifindex;
- ioctl(fd, SIOCGIFNAME, &ifr);
- strcpy(ifname, ifr.ifr_name);
+ if (ifname) {
+ ifr.ifr_ifindex = fromaddr->sll_ifindex;
+ ioctl(fd, SIOCGIFNAME, &ifr);
+ strcpy(ifname, ifr.ifr_name);
+ }
}
if (!daemonized && FD_ISSET(0, &set))
*ch = wgetch(win);
diff --git a/src/pktsize.c b/src/pktsize.c
index 5bfbeaf..ce0fd78 100644
--- a/src/pktsize.c
+++ b/src/pktsize.c
@@ -155,7 +155,6 @@ void packet_size_breakdown(struct OPTIONS *options, char *ifname,
char buf[MAX_PACKET_SIZE];
int br;
char *ipacket;
- char iface[IFNAMSIZ];
unsigned int mtu;
struct sockaddr_ll fromaddr;
@@ -294,7 +293,7 @@ void packet_size_breakdown(struct OPTIONS *options, char *ifname,
&& (((now - starttime) / 60) >= facilitytime))
exitloop = 1;
- getpacket(fd, buf, &fromaddr, &ch, &br, iface, win);
+ getpacket(fd, buf, &fromaddr, &ch, &br, NULL, win);
if (ch != ERR) {
switch (ch) {
@@ -317,7 +316,7 @@ void packet_size_breakdown(struct OPTIONS *options, char *ifname,
processpacket(buf, &ipacket, (unsigned int *) &br,
NULL, NULL, NULL, &fromaddr,
ofilter,
- MATCH_OPPOSITE_USECONFIG, iface,
+ MATCH_OPPOSITE_USECONFIG, NULL,
0);
if (pkt_result != PACKET_OK)
diff --git a/src/serv.c b/src/serv.c
index 74a3c6c..f0cd39f 100644
--- a/src/serv.c
+++ b/src/serv.c
@@ -699,7 +699,6 @@ void servmon(char *ifname, struct porttab *ports, const struct OPTIONS
*options,
struct sockaddr_ll fromaddr;
int br;
- char iface[IFNAMSIZ];
unsigned int idx = 1;
unsigned int sport = 0;
@@ -863,7 +862,7 @@ void servmon(char *ifname, struct porttab *ports, const struct OPTIONS
*options,
&& (((now - starttime) / 60) >= facilitytime))
exitloop = 1;
- getpacket(fd, buf, &fromaddr, &ch, &br, iface, list.win);
+ getpacket(fd, buf, &fromaddr, &ch, &br, NULL, list.win);
if (ch == ERR)
goto no_key_ready;
@@ -998,7 +997,7 @@ void servmon(char *ifname, struct porttab *ports, const struct OPTIONS
*options,
processpacket(buf, &ipacket, (unsigned int *) &br,
&tot_br, &sport, &dport, &fromaddr,
ofilter,
- MATCH_OPPOSITE_USECONFIG, iface,
+ MATCH_OPPOSITE_USECONFIG, NULL,
options->v6inv4asv6);
if (pkt_result != PACKET_OK)
--
1.7.8.4