Skip site navigation (1)Skip section navigation (2)
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>