$OpenBSD: patch-drivers_c,v 1.6 2015/12/07 18:00:42 jasper Exp $
--- drivers.c.orig	Fri May  5 02:34:29 2000
+++ drivers.c	Mon Dec  7 18:51:16 2015
@@ -9,18 +9,21 @@
  *  great, but please send me the diff.  
  */
 
-#include<stdlib.h>
-#include<stdio.h>
-#include<string.h>
-#include<X11/Xlib.h>
-#include<fcntl.h>
-#include<sys/types.h>
-#include<sys/stat.h>
-#include<sys/socket.h>
-#include<unistd.h>
-#include"config.h"
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
 
+#include <X11/Xlib.h>
 
+#include <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "config.h"
+#include "wmnet.h"
+
 /* For FreeBSD */
 #ifdef USE_KVM
 #include<net/if.h>
@@ -57,18 +60,6 @@ static struct ifpppstatsreq ppp_stats_req;
 #define ACCOUNT_IN_FOUND        1
 #define ACCOUNT_OUT_FOUND       2
 
-extern char buffer[256];
-extern char *in_rule_string, *out_rule_string, *device;
-extern unsigned long totalbytes_in, totalbytes_out, lastbytes_in, lastbytes_out;
-extern unsigned long totalpackets_in, totalpackets_out, lastpackets_in, lastpackets_out;
-extern unsigned int diffpackets_in, diffpackets_out, diffbytes_in, diffbytes_out;
-extern unsigned int out_rule, in_rule;  /* number of rule in /proc/net/ip_acct to use */
-extern Bool current_tx, current_rx, rx, tx;
-
-
-
-char *available_drivers(void);
-
 #ifdef USE_IPFWADM
 int updateStats_ipfwadm(void);
 int ipfwadm_test(void);
@@ -81,11 +72,16 @@ int ipchains_test(void);
 int updateStats_dev(void);
 int dev_test(void);
 #endif
+#ifdef USE_GETIFADDRS
+#include <ifaddrs.h>
+#include <net/if.h>
 
+int updateStats_bsd(struct if_data_t *);
+int bsd_test(struct if_data_t *);
+#endif
 
-typedef int (*parser_func)(void);
 static struct drivers_struct {
- char * name;
+ char *name;
  parser_func function;
  parser_func test;
 } drivers[] = {
@@ -104,10 +100,14 @@ static struct drivers_struct {
 #ifdef USE_KVM
  {"kmem",kvm_updateStats, kvm_test},
 #endif
+#ifdef USE_GETIFADDRS
+ {"bsd", updateStats_bsd, bsd_test},
+#endif
  {NULL, NULL}
 };
 
-char* available_drivers(void) {
+char *
+available_drivers(void) {
  int ind = 0;
  int len = 0;
  char *string, *ptr;
@@ -127,14 +127,12 @@ char* available_drivers(void) {
  *(--string) = '\0';
  return ptr; 
 } 
-   
 
-
-parser_func find_driver(void) {
+parser_func find_driver(struct if_data_t *id) {
  int ind = 0;
  while(drivers[ind].name != NULL) {
-  if(drivers[ind].test()) {
-   return drivers[ind].function;
+  if(drivers[ind].test(id)) {
+   return (parser_func)drivers[ind].function;
   }
   ind++;
  }
@@ -143,12 +141,13 @@ parser_func find_driver(void) {
 }
 
 
-parser_func setup_driver(char * parser_name) {
+setup_func
+setup_driver(char *parser_name, struct if_data_t *id) {
  int ind = 0;
- if (parser_name == NULL) return find_driver(); 
+ if (parser_name == NULL) return (void *)find_driver(id); 
  while(drivers[ind].name != NULL) {
   if(!strcmp(parser_name, drivers[ind].name)) {
-    if (drivers[ind].test()) return drivers[ind].function;
+    if (drivers[ind].test(id)) return (void *)drivers[ind].function;
     fprintf(stderr, "wmnet: driver %s not appropriate for this machine\n", parser_name);
     exit(18);
   }
@@ -157,10 +156,7 @@ parser_func setup_driver(char * parser_name) {
  fprintf(stderr, "wmnet: no driver %s\n", parser_name);
  exit(18);
 }
-  
 
-
-
 #ifdef linux
 /* All the data gathering is done in here. 
  * Return True if no change to tx/rx.
@@ -503,7 +499,71 @@ int kvm_updateStats(void) {
 
 
 #endif
-  
 
-   
-  
+
+#ifdef USE_GETIFADDRS
+int bsd_test(struct if_data_t *id) {
+	struct ifaddrs *ifa;
+
+	if (getifaddrs(&ifa) != 0) {
+		freeifaddrs(ifa);
+		return False;
+	}
+
+	warnx("using getifaddrs(3) to monitor %s", id->device);
+	return True;
+}
+
+int updateStats_bsd(struct if_data_t *id) {
+	struct ifaddrs *ifap, *ifa;
+
+	id->rx = False;
+	id->tx = False;
+
+	if (getifaddrs(&ifap) != 0) {
+		freeifaddrs(ifap);
+		return False;
+	}
+
+       for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) {
+               if (strcmp(id->device, ifa->ifa_name)) {
+                       continue;
+               }
+
+               if (ifa->ifa_addr->sa_family == AF_LINK) {
+                       struct if_data *ifd = NULL;
+
+                       ifd = ifa->ifa_data;
+
+                       if (ifd != NULL) {
+			       totalpackets_in = ifd->ifi_ipackets;
+			       if (totalpackets_in != lastpackets_in) {
+				       totalbytes_in = ifd->ifi_ibytes;
+				       diffpackets_in += totalpackets_in - lastpackets_in;
+				       diffbytes_in += totalbytes_in - lastbytes_in;
+				       lastpackets_in = totalpackets_in;
+				       lastbytes_in = totalbytes_in;
+				       id->rx = True;
+			       }
+
+			       totalpackets_out = ifd->ifi_opackets;
+			       if (totalpackets_out != lastpackets_out) {
+				       totalbytes_out =ifd->ifi_ibytes;
+				       diffpackets_out += totalpackets_out - lastpackets_out;
+				       diffbytes_out += totalbytes_out - lastbytes_out;
+				       lastpackets_out = totalpackets_out;
+				       lastbytes_out = totalbytes_out;
+				       id->tx = True;
+			       }
+
+			       return 0;
+			}
+	       }
+	}
+
+	/* return True if no change to tx/rx
+	 * return False if display will need to be updated
+	*/
+	return ((id->rx == id->current_rx) && (id->tx == id->current_tx));
+}
+#endif
