$NetBSD: patch-ac,v 1.5 2006/03/23 17:36:16 joerg Exp $ --- drivers.c.orig 2000-05-05 00:34:29.000000000 +0000 +++ drivers.c @@ -24,6 +24,9 @@ /* For FreeBSD */ #ifdef USE_KVM #include +#if defined(__DragonFly__) +#include +#endif #include #include @@ -37,6 +40,14 @@ int kvm_test(void); int kvm_updateStats(void); #endif /* USE_KVM */ +/* For Solaris */ +#ifdef USE_KSTAT +#include + +int kstat_test(void); +int kstat_updateStats(void); +#endif /* USE_KSTAT */ + #ifdef USE_LINUX_PPP #include @@ -57,7 +68,7 @@ static struct ifpppstatsreq ppp_stats_re #define ACCOUNT_IN_FOUND 1 #define ACCOUNT_OUT_FOUND 2 -extern char buffer[256]; +extern char buffer[2048]; 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; @@ -104,6 +115,9 @@ static struct drivers_struct { #ifdef USE_KVM {"kmem",kvm_updateStats, kvm_test}, #endif +#ifdef USE_KSTAT + {"kstat", kstat_updateStats, kstat_test}, +#endif {NULL, NULL} }; @@ -445,7 +459,7 @@ int kvm_test(void) { if (((kvmfd = kvm_open(NULL, NULL, NULL, O_RDONLY, buffer)) == NULL) || (kvm_nlist(kvmfd, symbols) < 0) || kvm_read(kvmfd, (unsigned long)symbols[0].n_value, &ifnet_savedaddr, sizeof(unsigned long)) == -1 ) return False; - if(device == NULL) device = "ec0"; + if(device == NULL) device = "ppp0"; fprintf(stderr, "wmnet: using kmem driver to monitor %s\n", device); return True; } @@ -457,7 +471,7 @@ int kvm_updateStats(void) { int flag = 0; while (ifnet_addr && flag != (ACCOUNT_IN_FOUND|ACCOUNT_OUT_FOUND)) { kvm_read(kvmfd, ifnet_addr, buffer, sizeof(struct ifnet)); -#ifdef __OpenBSD__ +#if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__) snprintf(devname, 15, "%s", ifnet->if_xname); #else kvm_read(kvmfd, (unsigned long)ifnet->if_name, devname, 15); @@ -487,7 +501,7 @@ int kvm_updateStats(void) { flag = (ACCOUNT_IN_FOUND|ACCOUNT_OUT_FOUND); } else { -#ifdef __OpenBSD__ +#if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__) ifnet_addr = (unsigned long)ifnet->if_list.tqe_next; #else ifnet_addr = (unsigned long)ifnet->if_next; @@ -502,8 +516,119 @@ int kvm_updateStats(void) { } -#endif +#endif /* KVM */ +#ifdef USE_KSTAT +kstat_ctl_t *kc = NULL; +kstat_t *if_ksp = NULL; + +int kstat_test(void) +{ + kstat_t *ksp; + + if (kc == NULL) { + if ((kc = kstat_open()) == NULL) { + perror("wmnet [kstat]: can't open /dev/kstat\n"); + return (False); + } + } + + /* + * If no device given, take the first thing we find of class 'net' + * which exports the four kstats we need. + */ + if (device == NULL) { + for (ksp = kc->kc_chain; ksp; ksp = ksp->ks_next) { + if (strcmp(ksp->ks_class, "net") == 0) { + kstat_read(kc, ksp, NULL); + if (kstat_data_lookup(ksp, "ipackets") && + kstat_data_lookup(ksp, "opackets") && + kstat_data_lookup(ksp, "rbytes") && + kstat_data_lookup(ksp, "obytes")) { + if_ksp = ksp; + break; + } + } + } + if (if_ksp == NULL) { + fprintf(stderr, "wmnet [kstat]: no network interface " + "exporting kstats found\n"); + return (False); + } else { + fprintf(stderr, "wmnet [kstat]: monitoring %s\n", + ksp->ks_name); + } + } else { + if ((if_ksp = (kstat_lookup(kc, NULL, -1, device))) == NULL) { + fprintf(stderr, "wmnet [kstat]: no network interface " + "%s exporting kstats found\n", device); + return (False); + } + } + + return (True); +} + +int kstat_updateStats(void) +{ + kstat_named_t *in_pkt, *in_byte, *out_pkt, *out_byte; + tx = rx = False; + + if (kstat_read(kc, if_ksp, NULL) == -1) { + (void) fprintf(stderr, "wmnet [kstat]: kstat_read failed\n"); + exit (1); + } + + if ((in_pkt = (kstat_named_t *) kstat_data_lookup(if_ksp, "ipackets")) + == NULL) { + (void) fprintf(stderr, "wmnet [kstat]: kstat_data_lookup " + "(ipackets) failed\n"); + exit (1); + } + + totalpackets_in = (in_pkt->value.ui32); + if (totalpackets_in != lastpackets_in) { + if ((in_byte = (kstat_named_t *) kstat_data_lookup(if_ksp, + "rbytes")) == NULL) { + (void) fprintf(stderr, "wmnet [kstat]: " + "kstat_data_lookup (rbytes) failed\n"); + exit (1); + } + totalbytes_in = in_byte->value.ui32; + diffpackets_in += totalpackets_in - lastpackets_in; + diffbytes_in += totalbytes_in - lastbytes_in; + lastpackets_in = totalpackets_in; + lastbytes_in = totalbytes_in; + rx = True; + } + + if ((out_pkt = (kstat_named_t *) kstat_data_lookup(if_ksp, "opackets")) + == NULL) { + (void) fprintf(stderr, "wmnet [kstat]: kstat_data_lookup " + "(opackets) failed\n"); + exit (1); + } + + totalpackets_out = (out_pkt->value.ui32); + if (totalpackets_out != lastpackets_out) { + if ((out_byte = (kstat_named_t *) kstat_data_lookup(if_ksp, + "obytes")) == NULL) { + (void) fprintf(stderr, "wmnet [kstat]: " + "kstat_data_lookup (obytes) failed\n"); + exit (1); + } + totalbytes_out = out_byte->value.ui32; + diffpackets_out += totalpackets_out - lastpackets_out; + diffbytes_out += totalbytes_out - lastbytes_out; + lastpackets_out = totalpackets_out; + lastbytes_out = totalbytes_out; + tx = True; + } + + return ((rx == current_rx) && (tx == current_tx)); +} + +#endif /* KSTAT */