... and use it where appropriate.
Signed-off-by: Vitezslav Samel <vitezslav(a)samel.cz>
---
Makefile | 4 ++
src/capt-recvmsg.c | 89 ++++++++++++++++++++++++++++++++++
src/capt-recvmsg.h | 6 +++
src/capt.c | 139 +++++++++++++++++++++++++++++++++++++++++++++++++++++
src/capt.h | 31 ++++++++++++
src/capture-pkt.c | 18 +++----
src/detstats.c | 27 ++++-------
src/hostmon.c | 26 ++++------
src/ifstats.c | 21 ++++----
src/itrafmon.c | 23 +++------
src/packet.c | 92 ++---------------------------------
src/packet.h | 13 +----
src/pktsize.c | 25 ++++------
src/serv.c | 26 ++++------
14 files changed, 340 insertions(+), 200 deletions(-)
create mode 100644 src/capt-recvmsg.c
create mode 100644 src/capt-recvmsg.h
create mode 100644 src/capt.c
create mode 100644 src/capt.h
diff --git a/Makefile b/Makefile
index 59b7c6f..64ca213 100644
--- a/Makefile
+++ b/Makefile
@@ -115,6 +115,8 @@ iptraf-h += src/counters.h
iptraf-h += src/rate.h
iptraf-h += src/built-in.h
iptraf-h += src/sockaddr.h
+iptraf-h += src/capt.h
+iptraf-h += src/capt-recvmsg.h
iptraf-o += src/tui/input.o
iptraf-o += src/tui/labels.o
@@ -157,6 +159,8 @@ iptraf-o += src/counters.o
iptraf-o += src/rate.o
iptraf-o += src/capture-pkt.o
iptraf-o += src/sockaddr.o
+iptraf-o += src/capt.o
+iptraf-o += src/capt-recvmsg.o
rvnamed-o += src/rvnamed.o
rvnamed-o += src/getpath.o
diff --git a/src/capt-recvmsg.c b/src/capt-recvmsg.c
new file mode 100644
index 0000000..a9ad343
--- /dev/null
+++ b/src/capt-recvmsg.c
@@ -0,0 +1,89 @@
+/* For terms of usage/redistribution/modification see the LICENSE file */
+/* For authors and contributors see the AUTHORS file */
+
+#include "iptraf-ng-compat.h"
+
+#include "packet.h"
+#include "capt.h"
+
+struct capt_data_recvmsg {
+ char *buf;
+
+ struct iovec iov;
+ struct msghdr *msg;
+ struct sockaddr_ll *from;
+};
+
+static unsigned int capt_have_packet_recvmsg(struct capt *capt __unused)
+{
+ return 0;
+}
+
+static int capt_get_packet_recvmsg(struct capt *capt, struct pkt_hdr *pkt)
+{
+ struct capt_data_recvmsg *data = capt->priv;
+
+ /* these are set upon return from recvmsg() so clean */
+ /* them beforehand */
+ data->msg->msg_controllen = 0;
+ data->msg->msg_flags = 0;
+
+ ssize_t len = recvmsg(capt->fd, data->msg, MSG_TRUNC | MSG_DONTWAIT);
+ if (len > 0) {
+ pkt->pkt_len = len;
+ pkt->pkt_caplen = len;
+ if (pkt->pkt_caplen > MAX_PACKET_SIZE)
+ pkt->pkt_caplen = MAX_PACKET_SIZE;
+ pkt->pkt_buf = data->buf;
+ pkt->from = data->from;
+ pkt->pkt_payload = NULL;
+ pkt->pkt_protocol = ntohs(pkt->from->sll_protocol);
+ }
+ return len;
+}
+
+static void capt_cleanup_recvmsg(struct capt *capt)
+{
+ struct capt_data_recvmsg *data = capt->priv;
+
+ capt->cleanup = NULL;
+ capt->put_packet = NULL;
+ capt->get_packet = NULL;
+ capt->have_packet = NULL;
+
+ free(data->from);
+ data->from = NULL;
+ free(data->msg);
+ data->msg = NULL;
+
+ free(data->buf);
+ data->buf = NULL;
+ free(capt->priv);
+ capt->priv = NULL;
+}
+
+int capt_setup_recvmsg(struct capt *capt)
+{
+ struct capt_data_recvmsg *data = xmallocz(sizeof(struct capt_data_recvmsg));
+
+ data->buf = xmallocz(MAX_PACKET_SIZE);
+ data->iov.iov_len = MAX_PACKET_SIZE;
+ data->iov.iov_base = data->buf;
+
+ data->msg = xmallocz(sizeof(*data->msg));
+ data->from = xmallocz(sizeof(*data->from));
+
+ data->msg->msg_name = data->from;
+ data->msg->msg_namelen = sizeof(*data->from);
+ data->msg->msg_iov = &data->iov;
+ data->msg->msg_iovlen = 1;
+ data->msg->msg_control = NULL;
+
+ capt->priv = data;
+ capt->have_packet = capt_have_packet_recvmsg;
+ capt->get_packet = capt_get_packet_recvmsg;
+ capt->put_packet = NULL;
+ capt->cleanup = capt_cleanup_recvmsg;
+
+ return 0;
+}
diff --git a/src/capt-recvmsg.h b/src/capt-recvmsg.h
new file mode 100644
index 0000000..243761e
--- /dev/null
+++ b/src/capt-recvmsg.h
@@ -0,0 +1,6 @@
+#ifndef IPTRAF_NG_CAPT_RECVMSG_H
+#define IPTRAF_NG_CAPT_RECVMSG_H
+
+int capt_setup_recvmsg(struct capt *capt);
+
+#endif /* IPTRAF_NG_CAPT_RECVMSG_H */
diff --git a/src/capt.c b/src/capt.c
new file mode 100644
index 0000000..9c0d6d4
--- /dev/null
+++ b/src/capt.c
@@ -0,0 +1,139 @@
+/* For terms of usage/redistribution/modification see the LICENSE file */
+/* For authors and contributors see the AUTHORS file */
+
+#include "iptraf-ng-compat.h"
+
+#include "error.h"
+#include "ifaces.h"
+#include "packet.h"
+#include "capt.h"
+#include "capt-recvmsg.h"
+
+static int capt_set_recv_timeout(int fd, unsigned int msec)
+{
+ struct timeval timeout;
+ socklen_t len = sizeof(timeout);
+
+ timeout.tv_sec = msec / 1000;
+ timeout.tv_usec = (msec % 1000) * 1000;
+ if(setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &timeout, len) != 0)
+ return -1;
+ else
+ return 0;
+}
+
+int capt_init(struct capt *capt, char *ifname)
+{
+ capt->have_packet = NULL;
+ capt->get_packet = NULL;
+ capt->put_packet = NULL;
+ capt->cleanup = NULL;
+
+ capt->dropped = 0UL;
+
+ /* initialize socket */
+ int fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
+ if (fd == -1)
+ return fd;
+ capt->fd = fd;
+
+ /* bind socket to interface */
+ if (ifname && dev_bind_ifname(capt->fd, ifname) == -1)
+ goto out;
+
+ /* set socket receive timeout */
+ if (capt_set_recv_timeout(capt->fd, 250) == -1)
+ goto out;
+
+ /* try packet recvmsg() */
+ if (capt_setup_recvmsg(capt) == 0)
+ return 0;
+out:
+ close(capt->fd);
+ capt->fd = -1;
+
+ return -1;
+}
+
+void capt_destroy(struct capt *capt)
+{
+ if (capt->cleanup)
+ capt->cleanup(capt);
+
+ close(capt->fd);
+ capt->fd = -1;
+}
+
+unsigned long capt_get_dropped(struct capt *capt)
+{
+ struct tpacket_stats stats;
+ socklen_t len = sizeof(stats);
+
+ memset(&stats, 0, len);
+ int err = getsockopt(capt->fd, SOL_PACKET, PACKET_STATISTICS, &stats, &len);
+ if (err < 0)
+ die_errno("%s(): getsockopt(PACKET_STATISTICS)", __func__);
+
+ capt->dropped += stats.tp_drops;
+
+ return capt->dropped;
+}
+
+int capt_get_packet(struct capt *capt, struct pkt_hdr *pkt, int *ch, WINDOW *win)
+{
+ struct pollfd pfds[2];
+ nfds_t nfds = 0;
+ int pfd_packet = -1;
+ int pfd_key = -1;
+ int ss = 0;
+ int poll_packet = !capt->have_packet(capt);
+ int timeout = DEFAULT_UPDATE_DELAY;
+
+ /* Monitor raw socket */
+ if (poll_packet) {
+ pfds[nfds].fd = capt->fd;
+ pfds[nfds].events = POLLIN;
+ pfd_packet = nfds;
+ nfds++;
+ }
+
+ /* Monitor stdin only if in interactive, not daemon mode. */
+ if (ch && !daemonized) {
+ pfds[nfds].fd = 0;
+ pfds[nfds].events = POLLIN;
+ pfd_key = nfds;
+ nfds++;
+ if (!poll_packet)
+ timeout = 0;
+ }
+
+ if (nfds > 0)
+ do {
+ ss = poll(pfds, nfds, timeout);
+ } while ((ss == -1) && (errno == EINTR));
+
+ /* no packet ready yet */
+ pkt->pkt_len = 0;
+
+ if (!poll_packet || ((pfd_packet != -1) && (ss > 0) &&
((pfds[pfd_packet].revents & POLLIN) != 0))) {
+ int ret = capt->get_packet(capt, pkt);
+ if (ret <= 0)
+ ss = ret;
+ }
+
+ if (ch) {
+ *ch = ERR; /* signalize we have no key ready */
+ if (!daemonized && (((pfd_key != -1) && ((ss > 0) &&
((pfds[pfd_key].revents & POLLIN) != 0)))))
+ *ch = wgetch(win);
+ }
+
+ return ss;
+}
+
+int capt_put_packet(struct capt *capt, struct pkt_hdr *pkt)
+{
+ if (capt->put_packet)
+ capt->put_packet(capt, pkt);
+
+ return 0;
+}
diff --git a/src/capt.h b/src/capt.h
new file mode 100644
index 0000000..cec57ba
--- /dev/null
+++ b/src/capt.h
@@ -0,0 +1,31 @@
+#ifndef IPTRAF_NG_CAPT_H
+#define IPTRAF_NG_CAPT_H
+
+/*
+ * Number of bytes from captured packet to move into a buffer.
+ * 96 bytes should be enough for the IP header, TCP/UDP/ICMP/whatever header
+ * with reasonable numbers of options.
+ *
+ * NOTE: keep it aligned to multiple of 16
+ */
+#define MAX_PACKET_SIZE 96
+
+struct capt {
+ int fd;
+ unsigned long dropped;
+
+ void *priv;
+
+ unsigned int (*have_packet)(struct capt *capt);
+ int (*get_packet)(struct capt *capt, struct pkt_hdr *pkt);
+ int (*put_packet)(struct capt *capt, struct pkt_hdr *pkt);
+ void (*cleanup)(struct capt *capt);
+};
+
+int capt_init(struct capt *capt, char *ifname);
+void capt_destroy(struct capt *capt);
+unsigned long capt_get_dropped(struct capt *capt);
+int capt_get_packet(struct capt *capt, struct pkt_hdr *pkt, int *ch, WINDOW *win);
+int capt_put_packet(struct capt *capt, struct pkt_hdr *pkt);
+
+#endif /* IPTRAF_NG_CAPT_H */
diff --git a/src/capture-pkt.c b/src/capture-pkt.c
index 93f0b58..1faccec 100644
--- a/src/capture-pkt.c
+++ b/src/capture-pkt.c
@@ -7,6 +7,7 @@
#include "parse-options.h"
#include "ifaces.h"
#include "packet.h"
+#include "capt.h"
static const char *const capture_usage[] = {
IPTRAF_NAME " capture [-c] <device>",
@@ -33,12 +34,9 @@ int cmd_capture(int argc, char **argv)
char *dev = argv[0];
- int fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
- if (fd < 0)
- die_errno("Unable to obtain monitoring socket");
-
- if (dev_bind_ifname(fd, dev) < 0)
- perror("Unable to bind device on the socket");
+ struct capt capt;
+ if (capt_init(&capt, dev) == -1)
+ die_errno("Unable to initialize packet capture interface");
FILE *fp = NULL;
if (ofilename) {
@@ -52,7 +50,7 @@ int cmd_capture(int argc, char **argv)
int captured = 0;
for (;;) {
- if (packet_get(fd, &pkt, NULL, NULL) == -1)
+ if (capt_get_packet(&capt, &pkt, NULL, NULL) == -1)
die_errno("fail to get packet");
if (!pkt.pkt_len)
@@ -64,6 +62,8 @@ int cmd_capture(int argc, char **argv)
if (fp)
fwrite(&pkt, sizeof(pkt), 1, fp);
+ capt_put_packet(&capt, &pkt);
+
if (++captured == cap_nr_pkt)
break;
}
@@ -71,10 +71,10 @@ int cmd_capture(int argc, char **argv)
packet_destroy(&pkt);
- close(fd);
-
if (fp)
fclose(fp);
+ capt_destroy(&capt);
+
return 0;
}
diff --git a/src/detstats.c b/src/detstats.c
index fd1b99a..9315055 100644
--- a/src/detstats.c
+++ b/src/detstats.c
@@ -27,6 +27,7 @@ detstats.c - the interface statistics module
#include "error.h"
#include "detstats.h"
#include "rate.h"
+#include "capt.h"
struct ifcounts {
struct proto_counter total;
@@ -517,12 +518,10 @@ void detstats(char *iface, time_t facilitytime)
int ch;
- int fd;
+ struct capt capt;
struct pkt_hdr pkt;
- unsigned long dropped = 0UL;
-
if (!dev_up(iface)) {
err_iface_down();
return;
@@ -551,15 +550,10 @@ void detstats(char *iface, time_t facilitytime)
promisc_set_list(&promisc);
}
- fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
- if(fd == -1) {
- write_error("Unable to obtain monitoring socket");
+ if (capt_init(&capt, iface) == -1) {
+ write_error("Unable to initialize packet capture interface");
goto err;
}
- if(dev_bind_ifname(fd, iface) == -1) {
- write_error("Unable to bind interface on the socket");
- goto err_close;
- }
ifcounts_init(&ifcounts);
ifrates_init(&ifrates);
@@ -623,8 +617,7 @@ void detstats(char *iface, time_t facilitytime)
wattrset(statwin, BOXATTR);
printelapsedtime(now.tv_sec - starttime, 1, statwin);
- dropped += packet_get_dropped(fd);
- print_packet_drops(dropped, statwin, 49);
+ print_packet_drops(capt_get_dropped(&capt), statwin, 49);
if (now.tv_sec > endtime)
exitloop = 1;
@@ -647,7 +640,7 @@ void detstats(char *iface, time_t facilitytime)
last_update = now;
}
- if (packet_get(fd, &pkt, &ch, statwin) == -1) {
+ if (capt_get_packet(&capt, &pkt, &ch, statwin) == -1) {
write_error("Packet receive failed");
exitloop = 1;
break;
@@ -656,8 +649,10 @@ void detstats(char *iface, time_t facilitytime)
if (ch != ERR)
detstats_process_key(ch);
- if (pkt.pkt_len > 0)
+ if (pkt.pkt_len > 0) {
detstats_process_packet(&ifcounts, &pkt);
+ capt_put_packet(&capt, &pkt);
+ }
}
packet_destroy(&pkt);
@@ -674,9 +669,7 @@ void detstats(char *iface, time_t facilitytime)
ifrates_destroy(&ifrates);
ifcounts_destroy(&ifcounts);
-
-err_close:
- close(fd);
+ capt_destroy(&capt);
err:
if (options.promisc) {
promisc_restore_list(&promisc);
diff --git a/src/hostmon.c b/src/hostmon.c
index 8711513..49d8da5 100644
--- a/src/hostmon.c
+++ b/src/hostmon.c
@@ -28,6 +28,7 @@ Discovers LAN hosts and displays packet statistics for them
#include "promisc.h"
#include "error.h"
#include "rate.h"
+#include "capt.h"
#define SCROLLUP 0
#define SCROLLDOWN 1
@@ -905,12 +906,10 @@ void hostmon(time_t facilitytime, char *ifptr)
FILE *logfile = NULL;
- int fd;
+ struct capt capt;
struct pkt_hdr pkt;
- unsigned long dropped = 0UL;
-
if (ifptr && !dev_up(ifptr)) {
err_iface_down();
return;
@@ -924,15 +923,10 @@ void hostmon(time_t facilitytime, char *ifptr)
promisc_set_list(&promisc);
}
- fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
- if(fd == -1) {
- write_error("Unable to obtain monitoring socket");
+ if (capt_init(&capt, ifptr) == -1) {
+ write_error("Unable to initialize packet capture interface");
goto err;
}
- if(ifptr && dev_bind_ifname(fd, ifptr) == -1) {
- write_error("Unable to bind interface on the socket");
- goto err_close;
- }
if (logging) {
if (strcmp(current_logfile, "") == 0) {
@@ -986,8 +980,7 @@ void hostmon(time_t facilitytime, char *ifptr)
printelapsedtime(now.tv_sec - starttime, 15, table.borderwin);
- dropped += packet_get_dropped(fd);
- print_packet_drops(dropped, table.borderwin, 49);
+ print_packet_drops(capt_get_dropped(&capt), table.borderwin, 49);
if (logging && (now.tv_sec > log_next)) {
check_rotate_flag(&logfile);
@@ -1009,7 +1002,7 @@ void hostmon(time_t facilitytime, char *ifptr)
last_update = now;
}
- if (packet_get(fd, &pkt, &ch, table.tabwin) == -1) {
+ if (capt_get_packet(&capt, &pkt, &ch, table.tabwin) == -1) {
write_error("Packet receive failed");
exitloop = 1;
break;
@@ -1018,8 +1011,10 @@ void hostmon(time_t facilitytime, char *ifptr)
if (ch != ERR)
hostmon_process_key(&table, ch);
- if (pkt.pkt_len > 0)
+ if (pkt.pkt_len > 0) {
hostmon_process_packet(&table, &pkt, ifptr);
+ capt_put_packet(&capt, &pkt);
+ }
}
@@ -1034,8 +1029,7 @@ void hostmon(time_t facilitytime, char *ifptr)
}
strcpy(current_logfile, "");
-err_close:
- close(fd);
+ capt_destroy(&capt);
err:
if (options.promisc) {
promisc_restore_list(&promisc);
diff --git a/src/ifstats.c b/src/ifstats.c
index f095b08..ac0b0ee 100644
--- a/src/ifstats.c
+++ b/src/ifstats.c
@@ -29,6 +29,7 @@ ifstats.c - the interface statistics module
#include "error.h"
#include "ifstats.h"
#include "rate.h"
+#include "capt.h"
#define SCROLLUP 0
#define SCROLLDOWN 1
@@ -500,12 +501,10 @@ void ifstats(time_t facilitytime)
int ch;
- int fd;
+ struct capt capt;
struct pkt_hdr pkt;
- unsigned long dropped = 0UL;
-
initiflist(&(table.head));
if (!table.head) {
no_ifaces_error();
@@ -520,9 +519,8 @@ void ifstats(time_t facilitytime)
promisc_set_list(&promisc);
}
- fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
- if(fd == -1) {
- write_error("Unable to obtain monitoring socket");
+ if (capt_init(&capt, NULL) == -1) {
+ write_error("Unable to initialize packet capture interface");
goto err;
}
@@ -584,8 +582,7 @@ void ifstats(time_t facilitytime)
printelapsedtime(now.tv_sec - starttime, 1, table.borderwin);
- dropped += packet_get_dropped(fd);
- print_packet_drops(dropped, table.borderwin, 49);
+ print_packet_drops(capt_get_dropped(&capt), table.borderwin, 49);
if (logging && (now.tv_sec > log_next)) {
check_rotate_flag(&logfile);
@@ -606,7 +603,7 @@ void ifstats(time_t facilitytime)
last_update = now;
}
- if (packet_get(fd, &pkt, &ch, table.statwin) == -1) {
+ if (capt_get_packet(&capt, &pkt, &ch, table.statwin) == -1) {
write_error("Packet receive failed");
exitloop = 1;
break;
@@ -615,8 +612,10 @@ void ifstats(time_t facilitytime)
if (ch != ERR)
ifstats_process_key(&table, ch);
- if (pkt.pkt_len > 0)
+ if (pkt.pkt_len > 0) {
ifstats_process_packet(&table, &pkt);
+ capt_put_packet(&capt, &pkt);
+ }
}
packet_destroy(&pkt);
@@ -630,7 +629,7 @@ void ifstats(time_t facilitytime)
}
strcpy(current_logfile, "");
- close(fd);
+ capt_destroy(&capt);
err:
if (options.promisc) {
promisc_restore_list(&promisc);
diff --git a/src/itrafmon.c b/src/itrafmon.c
index f19eb61..eb5f54b 100644
--- a/src/itrafmon.c
+++ b/src/itrafmon.c
@@ -31,6 +31,7 @@ itrafmon.c - the IP traffic monitor module
#include "logvars.h"
#include "itrafmon.h"
#include "sockaddr.h"
+#include "capt.h"
#define SCROLLUP 0
#define SCROLLDOWN 1
@@ -848,12 +849,10 @@ void ipmon(time_t facilitytime, char *ifptr)
struct othptable othptbl;
- int fd;
+ struct capt capt;
struct pkt_hdr pkt;
- unsigned long dropped = 0UL;
-
int ch;
int rvnfd = 0;
@@ -871,15 +870,10 @@ void ipmon(time_t facilitytime, char *ifptr)
promisc_set_list(&promisc);
}
- fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
- if(fd == -1) {
- write_error("Unable to obtain monitoring socket");
+ if (capt_init(&capt, ifptr) == -1) {
+ write_error("Unable to initialize packet capture interface");
goto err;
}
- if(ifptr && dev_bind_ifname(fd, ifptr) == -1) {
- write_error("Unable to bind interface on the socket");
- goto err_close;
- }
if (revlook) {
if (checkrvnamed())
@@ -977,8 +971,7 @@ void ipmon(time_t facilitytime, char *ifptr)
/* print timer at bottom of screen */
printelapsedtime(now.tv_sec - starttime, 15, othptbl.borderwin);
- dropped += packet_get_dropped(fd);
- print_packet_drops(dropped, othptbl.borderwin, 40);
+ print_packet_drops(capt_get_dropped(&capt), othptbl.borderwin, 40);
mark_timeouted_entries(&table, logging, logfile);
@@ -1005,7 +998,8 @@ void ipmon(time_t facilitytime, char *ifptr)
last_time = now;
}
- if (packet_get(fd, &pkt, &ch, table.tcpscreen) == -1) {
+ capt_put_packet(&capt, &pkt);
+ if (capt_get_packet(&capt, &pkt, &ch, table.tcpscreen) == -1) {
write_error("Packet receive failed");
exitloop = 1;
break;
@@ -1043,8 +1037,7 @@ void ipmon(time_t facilitytime, char *ifptr)
killrvnamed();
close_rvn_socket(rvnfd);
-err_close:
- close(fd);
+ capt_destroy(&capt);
err:
if (options.promisc) {
promisc_restore_list(&promisc);
diff --git a/src/packet.c b/src/packet.c
index eed02dd..2e4188f 100644
--- a/src/packet.c
+++ b/src/packet.c
@@ -121,59 +121,6 @@ static void packet_set_l3_hdrp(struct pkt_hdr *pkt)
}
}
-/* IPTraf input function; reads both keystrokes and network packets. */
-int packet_get(int fd, struct pkt_hdr *pkt, int *ch, WINDOW *win)
-{
- struct pollfd pfds[2];
- nfds_t nfds = 0;
- int ss;
-
- /* Monitor raw socket */
- pfds[0].fd = fd;
- pfds[0].events = POLLIN;
- nfds++;
-
- /* Monitor stdin only if in interactive, not daemon mode. */
- if (ch && !daemonized) {
- pfds[1].fd = 0;
- pfds[1].events = POLLIN;
- nfds++;
- }
- do {
- ss = poll(pfds, nfds, DEFAULT_UPDATE_DELAY);
- } while ((ss == -1) && (errno == EINTR));
-
- /* no packet ready yet */
- pkt->pkt_len = 0;
-
- if ((ss > 0) && (pfds[0].revents & POLLIN) != 0) {
-
- /* these are set upon return from recvmsg() so clean */
- /* them beforehand */
- pkt->msg->msg_controllen = 0;
- pkt->msg->msg_flags = 0;
-
- ssize_t len = recvmsg(fd, pkt->msg, MSG_TRUNC | MSG_DONTWAIT);
- if (len > 0) {
- pkt->pkt_len = len;
- pkt->pkt_caplen = len;
- if (pkt->pkt_caplen > pkt->pkt_bufsize)
- pkt->pkt_caplen = pkt->pkt_bufsize;
- pkt->pkt_payload = NULL;
- pkt->pkt_protocol = ntohs(pkt->from->sll_protocol);
- } else
- ss = len;
- }
-
- if (ch) {
- *ch = ERR; /* signalize we have no key ready */
- if (!daemonized && (ss > 0) && ((pfds[1].revents & POLLIN) !=
0))
- *ch = wgetch(win);
- }
-
- return ss;
-}
-
int packet_process(struct pkt_hdr *pkt, unsigned int *total_br,
in_port_t *sport, in_port_t *dport,
int match_opposite, int v6inv4asv6)
@@ -319,8 +266,6 @@ again:
int packet_init(struct pkt_hdr *pkt)
{
- pkt->pkt_buf = xmallocz(MAX_PACKET_SIZE);
- pkt->pkt_bufsize = MAX_PACKET_SIZE;
pkt->pkt_payload = NULL;
pkt->ethhdr = NULL;
pkt->fddihdr = NULL;
@@ -328,48 +273,17 @@ int packet_init(struct pkt_hdr *pkt)
pkt->ip6_hdr = NULL;
pkt->pkt_len = 0; /* signalize we have no packet prepared */
- pkt->iov.iov_len = pkt->pkt_bufsize;
- pkt->iov.iov_base = pkt->pkt_buf;
-
- pkt->from = xmallocz(sizeof(*pkt->from));
- pkt->msg = xmallocz(sizeof(*pkt->msg));
-
- pkt->msg->msg_name = pkt->from;
- pkt->msg->msg_namelen = sizeof(*pkt->from);
- pkt->msg->msg_iov = &pkt->iov;
- pkt->msg->msg_iovlen = 1;
- pkt->msg->msg_control = NULL;
+ pkt->pkt_buf = NULL;
+ pkt->from = NULL;
return 0; /* all O.K. */
}
-void packet_destroy(struct pkt_hdr *pkt)
+void packet_destroy(struct pkt_hdr *pkt __unused)
{
- free(pkt->msg);
- pkt->msg = NULL;
-
- free(pkt->from);
- pkt->from = NULL;
-
- free(pkt->pkt_buf);
- pkt->pkt_buf = NULL;
-
destroyfraglist();
}
-unsigned int packet_get_dropped(int fd)
-{
- struct tpacket_stats stats;
- socklen_t len = sizeof(stats);
-
- memset(&stats, 0, len);
- int err = getsockopt(fd, SOL_PACKET, PACKET_STATISTICS, &stats, &len);
- if (err < 0)
- die_errno("%s(): getsockopt(PACKET_STATISTICS)", __func__);
-
- return stats.tp_drops;
-}
-
int packet_is_first_fragment(struct pkt_hdr *pkt)
{
switch (pkt->pkt_protocol) {
diff --git a/src/packet.h b/src/packet.h
index 1f01336..2ab69ce 100644
--- a/src/packet.h
+++ b/src/packet.h
@@ -7,13 +7,6 @@ packet.h - external declarations for packet.c
***/
-/*
- * Number of bytes from captured packet to move into a buffer.
- * 96 bytes should be enough for the IP header, TCP/UDP/ICMP/whatever header
- * with reasonable numbers of options.
- */
-#define MAX_PACKET_SIZE 96
-
#define INVALID_PACKET 0
#define PACKET_OK 1
#define CHECKSUM_ERROR 2
@@ -22,18 +15,16 @@ packet.h - external declarations for packet.c
struct pkt_hdr {
char *pkt_buf;
- size_t pkt_bufsize;
char *pkt_payload;
size_t pkt_caplen; /* bytes captured */
size_t pkt_len; /* bytes on-the-wire */
unsigned short pkt_protocol; /* Physical layer protocol: ETH_P_* */
- struct iovec iov;
struct sockaddr_ll *from;
- struct msghdr *msg;
struct ethhdr *ethhdr;
struct fddihdr *fddihdr;
+
struct iphdr *iphdr;
struct ip6_hdr *ip6_hdr;
};
@@ -61,13 +52,11 @@ static inline __u8 pkt_ip_protocol(const struct pkt_hdr *p)
return 0;
}
-int packet_get(int fd, struct pkt_hdr *pkt, int *ch, WINDOW *win);
int packet_process(struct pkt_hdr *pkt, unsigned int *total_br,
in_port_t *sport, in_port_t *dport,
int match_opposite, int v6inv4asv6);
int packet_init(struct pkt_hdr *pkt);
void packet_destroy(struct pkt_hdr *pkt);
-unsigned int packet_get_dropped(int fd);
int packet_is_first_fragment(struct pkt_hdr *pkt);
#endif /* IPTRAF_NG_PACKET_H */
diff --git a/src/pktsize.c b/src/pktsize.c
index 9e57a17..27384d2 100644
--- a/src/pktsize.c
+++ b/src/pktsize.c
@@ -24,6 +24,7 @@ pktsize.c - the packet size breakdown facility
#include "log.h"
#include "logvars.h"
#include "promisc.h"
+#include "capt.h"
#define SIZES 20
@@ -232,12 +233,10 @@ void packet_size_breakdown(char *ifname, time_t facilitytime)
struct psizetab table;
- int fd;
+ struct capt capt;
struct pkt_hdr pkt;
- unsigned long dropped = 0UL;
-
if (!dev_up(ifname)) {
err_iface_down();
return;
@@ -251,15 +250,10 @@ void packet_size_breakdown(char *ifname, time_t facilitytime)
promisc_set_list(&promisc);
}
- fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
- if(fd == -1) {
- write_error("Unable to obtain monitoring socket");
+ if (capt_init(&capt, ifname) == -1) {
+ write_error("Unable to initialize packet capture interface");
goto err;
}
- if(dev_bind_ifname(fd, ifname) == -1) {
- write_error("Unable to bind interface on the socket");
- goto err_close;
- }
int mtu = dev_get_mtu(ifname);
if (mtu < 0) {
@@ -321,8 +315,7 @@ void packet_size_breakdown(char *ifname, time_t facilitytime)
if (now.tv_sec > last_time.tv_sec) {
printelapsedtime(now.tv_sec - starttime, 1, table.borderwin);
- dropped += packet_get_dropped(fd);
- print_packet_drops(dropped, table.borderwin, 49);
+ print_packet_drops(capt_get_dropped(&capt), table.borderwin, 49);
if (logging && (now.tv_sec > log_next)) {
check_rotate_flag(&logfile);
@@ -346,7 +339,7 @@ void packet_size_breakdown(char *ifname, time_t facilitytime)
last_update = now;
}
- if (packet_get(fd, &pkt, &ch, table.win) == -1) {
+ if (capt_get_packet(&capt, &pkt, &ch, table.win) == -1) {
write_error("Packet receive failed");
exitloop = 1;
break;
@@ -355,8 +348,10 @@ void packet_size_breakdown(char *ifname, time_t facilitytime)
if (ch != ERR)
psize_process_key(ch);
- if (pkt.pkt_len > 0)
+ if (pkt.pkt_len > 0) {
psize_process_packet(&table, &pkt);
+ capt_put_packet(&capt, &pkt);
+ }
}
packet_destroy(&pkt);
@@ -371,7 +366,7 @@ void packet_size_breakdown(char *ifname, time_t facilitytime)
strcpy(current_logfile, "");
err_close:
- close(fd);
+ capt_destroy(&capt);
err:
if (options.promisc) {
promisc_restore_list(&promisc);
diff --git a/src/serv.c b/src/serv.c
index 6bd89fa..a3442d1 100644
--- a/src/serv.c
+++ b/src/serv.c
@@ -32,6 +32,7 @@ serv.c - TCP/UDP port statistics module
#include "error.h"
#include "counters.h"
#include "rate.h"
+#include "capt.h"
#define SCROLLUP 0
#define SCROLLDOWN 1
@@ -899,9 +900,7 @@ void servmon(char *ifname, time_t facilitytime)
FILE *logfile = NULL;
- int fd;
-
- unsigned long dropped = 0UL;
+ struct capt capt;
struct porttab *ports;
@@ -921,15 +920,10 @@ void servmon(char *ifname, time_t facilitytime)
promisc_set_list(&promisc);
}
- fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
- if(fd == -1) {
- write_error("Unable to obtain monitoring socket");
+ if (capt_init(&capt, ifname) == -1) {
+ write_error("Unable to initialize packet capture interface");
goto err;
}
- if(dev_bind_ifname(fd, ifname) == -1) {
- write_error("Unable to bind interface on the socket");
- goto err_close;
- }
if (logging) {
if (strcmp(current_logfile, "") == 0) {
@@ -987,8 +981,7 @@ void servmon(char *ifname, time_t facilitytime)
printelapsedtime(now.tv_sec - starttime, 20, list.borderwin);
- dropped += packet_get_dropped(fd);
- print_packet_drops(dropped, list.borderwin, 49);
+ print_packet_drops(capt_get_dropped(&capt), list.borderwin, 49);
if (now.tv_sec > endtime)
exitloop = 1;
@@ -1012,7 +1005,7 @@ void servmon(char *ifname, time_t facilitytime)
last_update = now;
}
- if (packet_get(fd, &pkt, &ch, list.win) == -1) {
+ if (capt_get_packet(&capt, &pkt, &ch, list.win) == -1) {
write_error("Packet receive failed");
exitloop = 1;
break;
@@ -1021,8 +1014,10 @@ void servmon(char *ifname, time_t facilitytime)
if (ch != ERR)
serv_process_key(&list, ch);
- if (pkt.pkt_len > 0)
+ if (pkt.pkt_len > 0) {
serv_process_packet(&list, &pkt, ports);
+ capt_put_packet(&capt, &pkt);
+ }
}
packet_destroy(&pkt);
@@ -1038,8 +1033,7 @@ void servmon(char *ifname, time_t facilitytime)
}
strcpy(current_logfile, "");
-err_close:
- close(fd);
+ capt_destroy(&capt);
err:
if (options.promisc) {
promisc_restore_list(&promisc);
--
1.9.1