$NetBSD: patch-aa,v 1.5 2012/08/11 17:20:23 marino Exp $ FreeBSD changes taken from FreeBSD ports --- ioctl_stat.c.orig 2000-02-01 07:11:24.000000000 +0000 +++ ioctl_stat.c @@ -30,6 +30,15 @@ #include /* open */ #include /* ioctl */ #include +#if defined(__FreeBSD__) || defined(__DragonFly__) +#define __FreeFly__ 1 +#endif +#if __FreeFly__ +#include +#include +#include +#include +#endif #ifndef STREAMS /* Linux, FreeBSD, NetBSD, Ultrix */ # include /* socket */ @@ -39,8 +48,10 @@ # include # else /* most everything else */ # include +# ifndef __FreeFly__ # include # include +# endif /* FreeBSD | DragonFly */ # endif /* linux && __GLIBC__ < 2 */ #else /* STREAMS */ /* Solaris, SunOS, OSF/1, SVR4 */ # include @@ -61,7 +72,21 @@ void getsocket(if_data *ifd) void ioctl_stat(if_data *ifd) { struct ifreq ifr; +#if __FreeFly__ + static int if_ix = -1; + struct ifmibdata ifmd; + size_t ifmd_sz = sizeof(ifmd); + int nr_ifs; + size_t nr_ifs_sz = sizeof(nr_ifs); + int name[6]; + int i; +#else +#ifdef SIOCGIFDATA + struct ifdatareq ifdr; + struct if_data * const ifi = &ifdr.ifdr_data; +#endif struct ifpppstatsreq req; +#endif /* FreeBSD | DragonFly */ if (!ifd->s) getsocket(ifd); @@ -76,7 +101,9 @@ void ioctl_stat(if_data *ifd) return; } +#ifndef __FreeFly__ memset(&req, 0, sizeof(req)); +#endif #ifdef linux req.stats_ptr = (caddr_t) &req.stats; @@ -84,6 +111,60 @@ void ioctl_stat(if_data *ifd) #define ifr_name ifr__name #endif +#ifdef __NetBSD__ + strncpy(ifr.ifr_name, ifd->device, sizeof(ifr.ifr_name)); + if (ioctl(ifd->s, SIOCGIFFLAGS, (caddr_t)&ifr) < 0 || + !(ifr.ifr_flags&IFF_UP)) + { + /* invalid interface, or interface down */ + ifd->in_bytes = 0UL; + ifd->out_bytes = 0UL; + return; + } +#endif + +#if __FreeFly__ + name[0] = CTL_NET; + name[1] = PF_LINK; + name[2] = NETLINK_GENERIC; + name[3] = IFMIB_IFDATA; + name[5] = IFDATA_GENERAL; + + if (if_ix < 0) { + if (sysctlbyname("net.link.generic.system.ifcount", (void *) &nr_ifs, &nr_ifs_sz, (void *) 0, 0) < 0) { + return; + } + for (i = 1; i <= nr_ifs; i++) { + name[4] = i; /* row of the ifmib table */ + + if (sysctl(name, 6, (void *) &ifmd, &ifmd_sz, (void *) 0, 0) < 0) { + continue; + } + if (strncmp(ifmd.ifmd_name, ifr.ifr_name, strlen(ifr.ifr_name)) == 0) { + if_ix = i; + break; + } + } + } + + name[4] = if_ix; + if (sysctl(name, 6, (void *) &ifmd, &ifmd_sz, (void *) 0, 0) >= 0) { + ifd->in_bytes = ifmd.ifmd_data.ifi_ibytes; + ifd->out_bytes = ifmd.ifmd_data.ifi_obytes; + } +#elif defined(__NetBSD__) && defined(SIOCGIFDATA) + /* prefer the generic interface statistics over the PPP specific ones */ + strncpy(ifdr.ifdr_name, ifd->device, sizeof(ifdr.ifdr_name)); + if (ioctl(ifd->s, SIOCGIFDATA, &ifdr) == -1) + { + /* non-existent device? */ + ifd->in_bytes = 0UL; + ifd->out_bytes = 0UL; + return; + } + ifd->in_bytes = ifi->ifi_ibytes; + ifd->out_bytes = ifi->ifi_obytes; +#else strncpy(req.ifr_name, ifd->device, sizeof(req.ifr_name)); if (ioctl(ifd->s, SIOCGPPPSTATS, &req) != 0) { @@ -95,6 +176,7 @@ void ioctl_stat(if_data *ifd) ifd->in_bytes = (unsigned long)req.stats.p.ppp_ibytes; ifd->out_bytes = (unsigned long)req.stats.p.ppp_obytes; +#endif return; }