... and use it where appropriate.
Signed-off-by: Vitezslav Samel vitezslav@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);