aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--pcap-linux.c44
1 files changed, 36 insertions, 8 deletions
diff --git a/pcap-linux.c b/pcap-linux.c
index 949895e9..9a5d98d5 100644
--- a/pcap-linux.c
+++ b/pcap-linux.c
@@ -303,7 +303,7 @@ typedef int socklen_t;
*/
struct pcap_linux {
u_int packets_read; /* count of packets read with recvfrom() */
- long sysfs_dropped; /* packets reported dropped by /sys/class/net/{if_name}/statistics/rx_{missed,fifo}_errors */
+ long long sysfs_dropped; /* packets reported dropped by /sys/class/net/{if_name}/statistics/rx_{missed,fifo}_errors */
struct pcap_stat stat;
char *device; /* device name */
@@ -1179,7 +1179,7 @@ pcap_can_set_rfmon_linux(pcap_t *handle)
* but may be unimplemented and just return 0.
* The author has found no straigthforward way to check for support.
*/
-static long int
+static long long int
linux_get_stat(const char * if_name, const char * stat) {
ssize_t bytes_read;
int fd;
@@ -1196,14 +1196,14 @@ linux_get_stat(const char * if_name, const char * stat) {
return 0;
buffer[bytes_read] = '\0';
- return strtol(buffer, NULL, 10);
+ return strtoll(buffer, NULL, 10);
}
-static long int
+static long long int
linux_if_drops(const char * if_name)
{
- long int missed = linux_get_stat(if_name, "rx_missed_errors");
- long int fifo = linux_get_stat(if_name, "rx_fifo_errors");
+ long long int missed = linux_get_stat(if_name, "rx_missed_errors");
+ long long int fifo = linux_get_stat(if_name, "rx_fifo_errors");
return missed + fifo;
}
@@ -2335,7 +2335,7 @@ pcap_stats_linux(pcap_t *handle, struct pcap_stat *stats)
socklen_t len = sizeof (struct tpacket_stats);
#endif /* HAVE_STRUCT_TPACKET_STATS */
- long if_dropped = 0;
+ long long if_dropped = 0;
/*
* To fill in ps_ifdrop, we parse
@@ -2344,9 +2344,37 @@ pcap_stats_linux(pcap_t *handle, struct pcap_stat *stats)
*/
if (handle->opt.promisc)
{
+ /*
+ * XXX - is there any reason to do this by remembering
+ * the last counts value, subtracting it from the
+ * current counts value, and adding that to stat.ps_ifdrop,
+ * maintaining stat.ps_ifdrop as a count, rather than just
+ * saving the *initial* counts value and setting
+ * stat.ps_ifdrop to the difference between the current
+ * value and the initial value?
+ *
+ * One reason might be to handle the count wrapping
+ * around, on platforms where the count is 32 bits
+ * and where you might get more than 2^32 dropped
+ * packets; is there any other reason?
+ *
+ * (We maintain the count as a long long int so that,
+ * if the kernel maintains the counts as 64-bit even
+ * on 32-bit platforms, we can handle the real count.
+ *
+ * Unfortunately, we can't report 64-bit counts; we
+ * need a better API for reporting statistics, such as
+ * one that reports them in a style similar to the
+ * pcapng Interface Statistics Block, so that 1) the
+ * counts are 64-bit, 2) it's easier to add new statistics
+ * without breaking the ABI, and 3) it's easier to
+ * indicate to a caller that wants one particular
+ * statistic that it's not available by just not supplying
+ * it.)
+ */
if_dropped = handlep->sysfs_dropped;
handlep->sysfs_dropped = linux_if_drops(handlep->device);
- handlep->stat.ps_ifdrop += (handlep->sysfs_dropped - if_dropped);
+ handlep->stat.ps_ifdrop += (u_int)(handlep->sysfs_dropped - if_dropped);
}
#ifdef HAVE_STRUCT_TPACKET_STATS