/* This file is part of pload - a program to monitor ppp activity for X Copyright (C) 1999-2000 Matt Smith This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* Thanks to David Brownlee for catching the bug concerning * non-reseting stats after a disconnect for the non-streams section */ /* ioctl_stat.c */ #include /* memset, strncpy */ #include #include /* socket */ #include /* open */ #include /* open */ #include /* ioctl */ #include #ifdef __FreeBSD__ #include #include #include #include #endif #ifndef STREAMS /* Linux, FreeBSD, NetBSD, Ultrix */ # include /* socket */ # if ( defined linux ) && ( __GLIBC__ < 2 ) /* old libc5 linux */ # include # include # include # else /* most everything else */ # include # include # include # endif /* linux && __GLIBC__ < 2 */ #else /* STREAMS */ /* Solaris, SunOS, OSF/1, SVR4 */ # include # include #endif /* STREAMS */ #include "pload.h" #ifndef STREAMS /***************************************/ void getsocket(if_data *ifd) { if ((ifd->s = socket(AF_INET, SOCK_DGRAM, 0)) == -1) die("socket"); return; } void ioctl_stat(if_data *ifd) { struct ifreq ifr; struct ifpppstatsreq req; #ifdef __FreeBSD__ 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; #endif if (!ifd->s) getsocket(ifd); memset(&ifr, 0, sizeof(ifr)); 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; } memset(&req, 0, sizeof(req)); #ifdef linux req.stats_ptr = (caddr_t) &req.stats; #undef ifr_name #define ifr_name ifr__name #endif #ifdef __FreeBSD__ 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; } #endif return; } #else /*STREAMS */ /******************************************/ void getsocket(if_data *ifd) /* not really a socket... */ { #ifdef osf if ((ifd->s = open("/dev/streams/ppp", O_RDONLY)) == -1) die("couldn't open /dev/streams/ppp"); #else if ((ifd->s = open("/dev/ppp", O_RDONLY)) == -1) die("couldn't open /dev/ppp"); #endif return; } void ioctl_stat(if_data *ifd) { struct ppp_stats req; if (!ifd->s) getsocket(ifd); memset(&req, 0, sizeof(req)); if (strioctl(ifd->s, PPPIO_GETSTAT, &req, 0, sizeof(req)) == -1) { if (errno == EINVAL) /* invalid interface, or interface down */ { /* try to attach */ (void)strioctl(ifd->s, PPPIO_ATTACH, &ifd->dev_n, sizeof(ifd->dev_n), 0); } /* no connection */ ifd->in_bytes = 0UL; ifd->out_bytes = 0UL; return; } ifd->in_bytes = (unsigned long)req.p.ppp_ibytes; ifd->out_bytes = (unsigned long)req.p.ppp_obytes; return; } #endif /*STREAMS */ /******************************************/