1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171
|
/*
Copyright (C) 1997,1998 Dimitrios P. Bouras
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.
For author contact information, look in the README file.
*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <net/if.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>
#ifdef SUNOS41x
extern int socket(), ioctl(), sscanf(), printf(), pclose();
#elif defined(SUNOS5x)
#include <sys/sockio.h>
#else
/* Returns kernel revision number (10*major+minor). Only used on Linux to
figure out what kind of parsing format to use for /proc/net/dev output */
static int kernelRevNo(void)
{
int major, minor, ver = -1;
FILE *pfp;
pfp = popen("/bin/uname -r 2>&1", "r");
if (pfp != NULL && fscanf(pfp, "%d.%d.%*d", &major, &minor) > 1)
ver = major*10 + minor;
pclose(pfp);
return ver;
}
#endif
/* Gets interface address by reading /proc/net/route to make sure the
desired interface exists, and then requesting its address. For
SunOS-4.1.x/5.x, it parses the output of `netstat -nr` to avoid need
for group suid privileges. Returns pointer to a string representation
of the IP address, or NULL. */
char *IFAddr(char *IFName, int dest)
{
int skfd = -1, request = SIOCGIFADDR;
static char IP[16]={0};
struct ifreq ifr;
struct sockaddr_in *sinp;
skfd = socket(AF_INET, SOCK_DGRAM, 0); /* open net channel */
if (skfd < 0) /* make sure all is OK */
return NULL; /* if failed, bail out */
do {
strcpy(ifr.ifr_name, IFName);
if (dest) /* dest rather than src? */
request = SIOCGIFDSTADDR; /* yes, adjust request */
if (ioctl(skfd, request, &ifr) < 0) { /* get interface address */
close(skfd); /* if failed, close */
return NULL; /* socket and exit */
}
sinp = (struct sockaddr_in*)&ifr.ifr_addr; /* point to data */
} while (! sinp->sin_addr.s_addr); /* sometimes 0 returned */
close(skfd); /* close the socket */
strcpy(IP, inet_ntoa(sinp->sin_addr)); /* copy converted string */
return IP; /* return its address */
}
/* System dependent macros for pppAddr() */
#ifdef SUNOS41x
#define AddrOpen popen("/usr/ucb/netstat -nr", "r")
#define AddrScanf sscanf(routeLine, "%*s %*s %*s %*s %*s %s", IF)
#define AddrClose while (fgets(routeLine,128,infofp) != NULL); pclose(infofp)
#elif defined(SUNOS5x)
#define AddrOpen popen("/usr/bin/netstat -nr", "r")
#define AddrScanf sscanf(routeLine, "%*s %*s %*s %*s %*s %s", IF)
#define AddrClose while (fgets(routeLine,128,infofp) != NULL); pclose(infofp)
#else
#define AddrOpen fopen("/proc/net/route", "r")
#define AddrScanf sscanf(routeLine,"%s", IF)
#define AddrClose fclose(infofp)
#endif
char *pppAddr(char *IFName)
{
int IFLen = strlen(IFName);
FILE *infofp;
char routeLine[129], IF[8];
infofp = AddrOpen; /* open route info stream */
if (infofp == NULL) /* failed to open? */
return NULL; /* return NULL string */
while (fgets(routeLine, 128, infofp) != NULL) { /* open OK, read line */
if (AddrScanf) /* parse interface */
if (! strncmp(IF,IFName,IFLen)) { /* desired interface? */
AddrClose; /* close info stream */
return IFAddr(IF, 0); /* return its address */
}
}
AddrClose; /* nothing found, close */
return NULL; /* node and return NULL */
}
/* Using the /prod/net/dev entry, it parses and returns the sum
of TX and RX packets on the requested network interface. For
SunOS-4.1.x/5.x it parses the output of `netstat -n -I<IF>`
to avoid group suid privileges. */
/* System dependent macros for pppPkts() */
#ifdef SUNOS41x
#define PktsOpen popen(sprintf(line,"/usr/ucb/netstat -n -I%s",IFName), "r")
#define PktsScanf sscanf(line, "%s %*s %*s %*s %u %*s %u", \
interface, &recv, &trans)
#define PktsClose while (fgets(line,128,infofp) != NULL); pclose(infofp)
#elif defined(SUNOS5x)
#define PktsOpen popen((sprintf(line,"/usr/bin/netstat -n -I %s",IFName)) ? \
line:line, "r")
#define PktsScanf sscanf(line, "%s %*s %*s %*s %u %*s %u", \
interface, &recv, &trans)
#define PktsClose while (fgets(line,128,infofp) != NULL); pclose(infofp)
#else
#define PktsOpen fopen("/proc/net/dev", "r")
#define PktsScanf sscanf(line, ((kernelRevNo()>20) ? \
"%s %*s %u %*s %*s %*s %*s %*s %u": \
"%s %u %*s %*s %*s %*s %u"), \
interface, &recv, &trans)
#define PktsClose fclose(infofp)
#endif
unsigned pppPkts(char *IFName, unsigned long *pTX, unsigned long *pRX)
{
int IFLen = strlen(IFName);
FILE *infofp;
char line[129], interface[16];
unsigned recv = 0, trans = 0;
infofp = PktsOpen; /* open IF stats info stream */
while (fgets(line, 128, infofp) != NULL) {
PktsScanf; /* read line by line */
if (!strncmp(interface,IFName,IFLen)) { /* scanning for interface */
PktsClose; /* found, close info stream */
if (pTX) *pTX = trans; /* if return storage avail */
if (pRX) *pRX = recv; /* save TXed/RXed separately */
return (recv + trans); /* return total I/O packets */
}
}
PktsClose; /* close info stream */
if (pTX) *pTX = 0; /* indicate nothing found */
if (pRX) *pRX = 0;
return -1;
}
|