Date: Thu, 2 Oct 2014 17:55:33 +0000 (UTC) From: Gleb Smirnoff <glebius@FreeBSD.org> To: ports-committers@freebsd.org, svn-ports-all@freebsd.org, svn-ports-head@freebsd.org Subject: svn commit: r369841 - in head/net/wmnet: . files Message-ID: <201410021755.s92HtXhS011638@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: glebius (src committer) Date: Thu Oct 2 17:55:32 2014 New Revision: 369841 URL: https://svnweb.freebsd.org/changeset/ports/369841 QAT: https://qat.redports.org/buildarchive/r369841/ Log: Rewrite if.c so that it uses getifaddrs(3) instead of nosing in kernel memory via kvm(3). Approved by: bapt (blanket) Modified: head/net/wmnet/Makefile head/net/wmnet/files/patch-if.c Modified: head/net/wmnet/Makefile ============================================================================== --- head/net/wmnet/Makefile Thu Oct 2 17:32:34 2014 (r369840) +++ head/net/wmnet/Makefile Thu Oct 2 17:55:32 2014 (r369841) @@ -3,7 +3,7 @@ PORTNAME= wmnet PORTVERSION= 1.2 -PORTREVISION= 2 +PORTREVISION= 3 CATEGORIES= net windowmaker MASTER_SITES= ftp://ftp.enteract.com/users/rneswold/ \ ${MASTER_SITE_LOCAL} Modified: head/net/wmnet/files/patch-if.c ============================================================================== --- head/net/wmnet/files/patch-if.c Thu Oct 2 17:32:34 2014 (r369840) +++ head/net/wmnet/files/patch-if.c Thu Oct 2 17:55:32 2014 (r369841) @@ -1,89 +1,430 @@ ---- if.c.orig Sun Oct 11 19:13:16 1998 -+++ if.c Fri May 21 01:11:19 2004 -@@ -88,8 +88,13 @@ - - if (!newData) { - size -= IF_STEP; -+#if defined(__FreeBSD__) && __FreeBSD_version < 501113 - fprintf(stderr, "wmnet: Warning -- low memory; " - "ignoring %s interface\n", theData->if_name); -+#else -+ fprintf(stderr, "wmnet: Warning -- low memory; " -+ "ignoring %s interface\n", theData->if_xname); -+#endif - return 0; - } - -@@ -118,10 +123,13 @@ - ptr->flags = 0; - - #ifndef NDEBUG -+#if defined(__FreeBSD__) && __FreeBSD_version < 501113 - printf("Added '%.*s%d' to list.\n", IFNAMSIZ, theData->if_name, - theData->if_unit); -+#else -+ printf("Added '%.*s' to list.\n", IFNAMSIZ, theData->if_xname); -+#endif - #endif +--- if.c.orig 1998-10-12 06:13:16.000000000 +0400 ++++ if.c 2014-10-02 21:48:19.000000000 +0400 +@@ -11,32 +11,28 @@ + #include <string.h> + #include <unistd.h> + #include <limits.h> ++#include <errno.h> + #include <err.h> + #include <sys/param.h> + #include <sys/types.h> + #include <sys/ioctl.h> + #include <sys/socket.h> + #include <net/if.h> +-#if (__FreeBSD_version >= 300003) +-#include <net/if_var.h> + #include <net/if_types.h> +-#endif + #include <fcntl.h> +-#include <kvm.h> +-#include <nlist.h> + #include <assert.h> ++#include <ifaddrs.h> + #include "wmnet.h" + + #define IF_STEP 10 ++#define IFA_STAT(s) (((struct if_data *)ifa->ifa_data)->ifi_ ## s) + + /* + Local data types... + */ + typedef struct { +- unsigned long ifNetAddr; +- ++ char name[IFNAMSIZ]; + unsigned long flags; +- + unsigned current; + unsigned long xmt[G_WIDTH], xmtLast; + unsigned long rcv[G_WIDTH], rcvLast; +@@ -45,19 +41,15 @@ + /* + Local prototypes... + */ +-static int addIfData(unsigned long); +-static struct ifnet const* dereference(unsigned long); +-static void ifTerm(void); ++static int addIfData(struct ifaddrs *); + + /* + Local data... + */ +-static kvm_t* kd = 0; +-static unsigned long root = 0; - - // Bump the total. + static int total = 0; + static int size = 0; + static IfData* ifData = 0; ++static int sock; - ++total; -@@ -144,7 +152,9 @@ + /*------------------------------------------------------------------------------ + addIfData +@@ -66,134 +58,57 @@ + out of space, more space is allocated. If the interface already + exists in the list, we don't do anything. + ------------------------------------------------------------------------------*/ +-static int addIfData(unsigned long theAddr) ++static int addIfData(struct ifaddrs *ifa) { - static unsigned long c = 0; - static struct ifnet d; -+#if defined(__FreeBSD__) && __FreeBSD_version < 501113 - static char name[IFNAMSIZ]; -+#endif - - /* If we are passed a NULL, the caller wants us to stop caching - the current interface. */ -@@ -161,6 +171,7 @@ - return &d; - else if (sizeof(d) == kvm_read(kd, a, &d, sizeof(d))) { - -+#if defined(__FreeBSD__) && __FreeBSD_version < 501113 - /* We've read the structure's data, but the 'name' field still - points to kernel memory. We transfer the name to a local - buffer, and then modify the pointer to point to our -@@ -172,6 +183,7 @@ - if (sizeof(name) == n) { - name[IFNAMSIZ - 1] = '\0'; - d.if_name = name; -+#endif - #ifndef NDEBUG +- struct ifnet const* const theData = dereference(theAddr); ++ IfData* ptr = 0; ++ int ii; - /* These are other pointer fields that we shouldn't need -@@ -186,12 +198,13 @@ - #endif - d.if_bpf = 0; - d.if_linkmib = 0; + assert(total <= size); + +- /* Now read in the data so we can get to some of its goodies. */ +- +- if (0 != theData) { +- IfData* ptr = 0; +- int ii; +- +- /* First check to see if we have enough space in the list. If +- we don't, we'll have to add more space. */ +- +- if (total == size) { +- IfData* const newData = +- (IfData*) realloc(ifData, +- (size += IF_STEP) * sizeof(IfData)); +- +- if (!newData) { +- size -= IF_STEP; +- fprintf(stderr, "wmnet: Warning -- low memory; " +- "ignoring %s interface\n", theData->if_name); +- return 0; +- } +- +- /* Good. we got more space. */ +- +- ifData = newData; ++ /* First check to see if we have enough space in the list. If ++ we don't, we'll have to add more space. */ ++ if (total == size) { ++ IfData *newData; ++ ++ newData = realloc(ifData, (size += IF_STEP) * sizeof(IfData)); ++ ++ if (!newData) { ++ size -= IF_STEP; ++ fprintf(stderr, "wmnet: Warning -- low memory; " ++ "ignoring %s interface\n", ifa->ifa_name); ++ return ENOMEM; + } + +- assert(0 != ifData); +- assert(total < size); +- +- /* If we reached here, then 'total' points to the next +- bucket. Initialize the new bucket. XXX: This would be a +- good spot to insert-sort the new record. As it stands, the +- list builds up by the order that the interfaces were +- bootstrapped. */ +- +- ptr = ifData + total; +- +- ptr->ifNetAddr = theAddr; +- for (ii = 0; ii < G_WIDTH; ++ii) +- ptr->rcv[ii] = ptr->xmt[ii] = 0; +- ptr->rcvLast = theData->if_ibytes; +- ptr->xmtLast = theData->if_obytes; +- ptr->current = 0; +- ptr->flags = 0; +- +-#ifndef NDEBUG +- printf("Added '%.*s%d' to list.\n", IFNAMSIZ, theData->if_name, +- theData->if_unit); +-#endif +- +- // Bump the total. +- +- ++total; +- } else +- fprintf(stderr, "Couldn't read interface information\n"); +- return 1; +-} +- +-/*------------------------------------------------------------------------------ +- dereference +- +- Takes the kernel memory "pointer" and copies its pointed-to data +- into a local buffer. The only type of "pointer" we're using is a +- struct ifnet*, so this function only returns this type of data. +- +- Passing in 0 will reset the address cache and force the function +- to reload the data. +-------------------------------------------------------------------------------*/ +-static struct ifnet const* dereference(unsigned long a) +-{ +- static unsigned long c = 0; +- static struct ifnet d; +- static char name[IFNAMSIZ]; +- +- /* If we are passed a NULL, the caller wants us to stop caching +- the current interface. */ +- +- if (!a) { +- c = 0; +- return 0; ++ /* Good. we got more space. */ ++ ifData = newData; + } + +- /* If the requested address is the same that has been cached, just +- return the data. */ ++ assert(0 != ifData); ++ assert(total < size); + +- else if (a == c) +- return &d; +- else if (sizeof(d) == kvm_read(kd, a, &d, sizeof(d))) { +- +- /* We've read the structure's data, but the 'name' field still +- points to kernel memory. We transfer the name to a local +- buffer, and then modify the pointer to point to our +- buffer. */ +- +- ssize_t const n = kvm_read(kd, (unsigned long) d.if_name, name, +- sizeof(name)); +- +- if (sizeof(name) == n) { +- name[IFNAMSIZ - 1] = '\0'; +- d.if_name = name; +-#ifndef NDEBUG ++ /* If we reached here, then 'total' points to the next ++ bucket. Initialize the new bucket. XXX: This would be a ++ good spot to insert-sort the new record. As it stands, the ++ list builds up by the order that the interfaces were ++ bootstrapped. */ ++ ++ ptr = ifData + total; ++ ++ strncpy(ptr->name, ifa->ifa_name, IFNAMSIZ); ++ for (ii = 0; ii < G_WIDTH; ++ii) ++ ptr->rcv[ii] = ptr->xmt[ii] = 0; ++ ptr->rcvLast = IFA_STAT(ibytes); ++ ptr->xmtLast = IFA_STAT(obytes); ++ ptr->current = 0; ++ ptr->flags = 0; + +- /* These are other pointer fields that we shouldn't need +- to look at. While debugging, set these to NULL to trap +- any attempts. */ +- +- d.if_softc = 0; +-#if (__FreeBSD_version >= 300003) +- d.if_addrhead.tqh_first = 0; +-#else +- d.if_addrlist = 0; +-#endif +- d.if_bpf = 0; +- d.if_linkmib = 0; - d.if_poll_slowq = 0; ++#ifndef NDEBUG ++ printf("Added '%.*s' to list.\n", IFNAMSIZ, ifa->ifa_name); #endif - c = a; - return &d; -+#if defined(__FreeBSD__) && __FreeBSD_version < 501113 - } else - return 0; -+#endif - } else - return 0; +- c = a; +- return &d; +- } else +- return 0; +- } else +- return 0; ++ // Bump the total. ++ ++total; ++ ++ return 0; } -@@ -306,12 +319,16 @@ - if (idx < total) { - struct ifnet const* const ptr = dereference(ifData[idx].ifNetAddr); - -+#if defined(__FreeBSD__) && __FreeBSD_version < 501113 - if (ptr) { - static char buffer[IFNAMSIZ + 1]; - sprintf(buffer, "%.*s%d", IFNAMSIZ - 1, ptr->if_name, ptr->if_unit); - return buffer; + /*------------------------------------------------------------------------------ +@@ -222,56 +137,30 @@ + ------------------------------------------------------------------------------*/ + int ifInit(void) + { +- char errBuf[_POSIX2_LINE_MAX]; ++ struct ifaddrs *ifap, *ifa; + +- /* First try to open the kernel image. If we can't, the rest of +- the program is essentially useless. */ ++ sock = socket(AF_INET, SOCK_DGRAM, 0); ++ if (sock < 0) ++ fprintf(stderr, "socket(): %d\n", errno); ++ ++ if (getifaddrs(&ifap) != 0) { ++ fprintf(stderr, "getifaddrs(): %d\n", errno); ++ return (errno); ++ } + +- if (0 != (kd = kvm_openfiles(0, 0, 0, O_RDONLY, errBuf))) { +- static struct nlist nl[] = { +- { "_ifnet" }, +- { "" } +- }; +- +- /* Try to pull the address for the global kernel variable, +- ifnet. This variable is the root of the singly-linked list +- of network interfaces. */ +- +- if (0 == kvm_nlist(kd, nl)) { +- ssize_t const n = kvm_read(kd, nl[0].n_value, &root, sizeof(root)); +- +- /* We'll go ahead and make one dereference. We never +- really want this variable. We want what it points to. */ +- +- if (sizeof(root) == n) { +- unsigned long current = root; +- +- while (current) { +- addIfData(current); +-#if (__FreeBSD_version >= 300003) +- current = (unsigned long) dereference(current)->if_link.tqe_next; +-#else +- current = (unsigned long) dereference(current)->if_next; +-#endif +- } ++ for (ifa = ifap; ifa; ifa = ifa->ifa_next) { ++ int error; + +- /* Try to register our termination function. If it +- returns an error, we essentially ignore it because +- the OS will clean up our resources. */ +- +- (void) atexit(ifTerm); +- return 1; +- } ++ if (ifa->ifa_addr->sa_family != AF_LINK) ++ continue; ++ if ((error = addIfData(ifa)) != 0) { ++ freeifaddrs(ifap); ++ return (error); } -+#else -+ return ptr->if_xname; -+#endif ++ } + +- /* If we can't get a symbol list, close the kernel image and +- return an error. */ +- +- kvm_close(kd); +- kd = 0; +- } else +- fprintf(stderr, "kvm_open: %s\n", errBuf); +- return 0; ++ freeifaddrs(ifap); ++ return (0); + } + + /*------------------------------------------------------------------------------ +@@ -303,17 +192,7 @@ + ------------------------------------------------------------------------------*/ + char const* ifName(unsigned idx) + { +- if (idx < total) { +- struct ifnet const* const ptr = dereference(ifData[idx].ifNetAddr); +- +- if (ptr) { +- static char buffer[IFNAMSIZ + 1]; +- +- sprintf(buffer, "%.*s%d", IFNAMSIZ - 1, ptr->if_name, ptr->if_unit); +- return buffer; +- } +- } +- return 0; ++ return ifData[idx].name; + } + + /*------------------------------------------------------------------------------ +@@ -324,68 +203,53 @@ + ------------------------------------------------------------------------------*/ + int ifSample(void) + { ++ struct ifaddrs *ifap; + int ii; + +- /* Flush the kernel memory cache so that we're guaranteed to get +- new data during the next dereference(). */ +- +- dereference(0); ++ if (getifaddrs(&ifap) != 0) { ++ fprintf(stderr, "getifaddrs(): %d\n", errno); ++ return (errno); ++ } + + /* Loop through all the network interfaces. Even though we display + one interface's statistics, we keep track of all of them. */ +- + for (ii = 0; ii < total; ++ii) { +- IfData* const d = ifData + ii; +- struct ifnet const* const ptr = dereference(d->ifNetAddr); +- +- if (!ptr) { +- fprintf(stderr, "couldn't sample interface.\n"); +- return 0; +- } +- +- d->flags = ptr->if_flags; ++ struct ifreq ifr; ++ struct ifaddrs *ifa; ++ IfData *d; ++ ++ d = ifData + ii; ++ ++ for (ifa = ifap; ifa; ifa = ifa->ifa_next) ++ if (ifa->ifa_addr->sa_family == AF_LINK && ++ strcmp(ifa->ifa_name, d->name) == 0) ++ break; ++ ++ if (ifa == NULL) ++ /* Interface disappeared? */ ++ continue; + + /* Save the new delta for the transmit channel. */ +- +- d->xmt[d->current] = ptr->if_obytes - d->xmtLast; +- d->xmtLast = ptr->if_obytes; ++ d->xmt[d->current] = IFA_STAT(obytes) - d->xmtLast; ++ d->xmtLast = IFA_STAT(obytes); + + /* Save the new delta for the receive channel. */ +- +- d->rcv[d->current] = ptr->if_ibytes - d->rcvLast; +- d->rcvLast = ptr->if_ibytes; ++ d->rcv[d->current] = IFA_STAT(ibytes) - d->rcvLast; ++ d->rcvLast = IFA_STAT(ibytes); + + /* Prep the index for the next location to be written. */ +- + d->current = (d->current + 1) % G_WIDTH; +- } +- return 1; +-} +- +-/*------------------------------------------------------------------------------ +- ifTerm + +- This function will be called once when the application is ready to exit +-------------------------------------------------------------------------------*/ +-static void ifTerm(void) +-{ +-#ifndef NDEBUG +- printf("Cleaning up resources.\n"); +-#endif +- +- /* If the kernel image is open, close it. */ +- +- if (0 != kd) { +- kvm_close(kd); +- kd = 0; ++ memset(&ifr, 0, sizeof(ifr)); ++ strncpy(ifr.ifr_name, ifa->ifa_name, sizeof(ifr.ifr_name)); ++ if (ioctl(sock, SIOCGIFFLAGS, (caddr_t)&ifr) < 0) ++ continue; ++ d->flags = (ifr.ifr_flags & 0xffff) | (ifr.ifr_flagshigh << 16); } - return 0; + +- /* Now free up any memory we're using. */ ++ freeifaddrs(ifap); + +- if (ifData) { +- free(ifData); +- ifData = 0; +- } ++ return (0); } + + /*------------------------------------------------------------------------------
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201410021755.s92HtXhS011638>