⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 drivers.c

📁 ifstat源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * ifstat - InterFace STATistics * Copyright (c) 2001, Ga雔 Roualland <gael.roualland@dial.oleane.com> * * 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. * * $Id: drivers.c,v 1.45 2003/11/22 01:27:51 gael Exp $ */#ifdef HAVE_CONFIG_H#include <config.h>#endif#ifdef HAVE_SYS_TYPES_H#include <sys/types.h>#endif#ifdef HAVE_SYS_PARAM_H#include <sys/param.h>#endif#ifdef HAVE_UNISTD_H#include <unistd.h>#endif#if STDC_HEADERS#include <string.h>#else# ifndef HAVE_STRCHR#  define strchr index#  define strrchr rindex# endifchar *strchr (), *strrchr ();# ifndef HAVE_MEMCPY#  define memcpy(d, s, n) bcopy ((s), (d), (n))#  define memmove(d, s, n) bcopy ((s), (d), (n))# endif#endif#ifdef HAVE_CTYPE_H#include <ctype.h>#endif#ifdef HAVE_SYS_SOCKET_H#include <sys/socket.h>#endif#ifdef HAVE_SYS_SOCKIO_H#include <sys/sockio.h>#endif#ifdef HAVE_SYS_IOCTL_H#include <sys/ioctl.h>#endif#ifdef HAVE_NET_SOIOCTL_H#include <net/soioctl.h>#endif#ifdef HAVE_SYS_MBUF_H#include <sys/mbuf.h>#endif#ifdef HAVE_NET_ROUTE_H#include <net/route.h>#endif#ifdef HAVE_NET_IF_H#include <net/if.h>#endif#ifdef HAVE_SYS_SYSCTL_H#include <sys/sysctl.h>#endif#ifdef HAVE_NET_IF_MIB_H#include <net/if_mib.h>#endif#ifdef HAVE_NET_IF_VAR_H#include <net/if_var.h>#endif#ifdef HAVE_NET_IF_TYPES_H#include <net/if_types.h>#endif#ifdef HAVE_NET_IF_DL_H#include <net/if_dl.h>#endif#ifdef HAVE_SYS_DLPI_H#include <sys/dlpi.h>#endif#ifdef HAVE_SYS_DLPI_EXT_H#include <sys/dlpi_ext.h>#endif#ifdef HAVE_STROPTS_H#include <stropts.h>#endif#ifdef HAVE_SYS_MIB_H#include <sys/mib.h>#endif#ifdef HAVE_KSTAT_H#include <kstat.h>#endif#ifdef HAVE_FCNTL_H#include <fcntl.h>#endif#ifdef HAVE_KVM_H#include <kvm.h>#endif#ifdef HAVE_ERRNO_H#include <errno.h>#endif#ifdef HAVE_LIMITS_H#include <limits.h>#endif#ifdef HAVE_NLIST_H#include <nlist.h>#endif#ifdef HAVE_PATHS_H#include <paths.h>#endif#include <stdio.h>#include <stdlib.h>#include "ifstat.h"#ifdef USE_SNMP  #include "snmp.h"#endif#ifndef IFNAMSIZ#define IFNAMSIZ 16#endif#ifdef USE_WIN32#include <windows.h>#include <iphlpapi.h>#ifndef IFF_UP#define IFF_UP       1#endif#ifndef IFF_LOOPBACK#define IFF_LOOPBACK 2#endif#endifstatic void examine_interface(struct ifstat_list *ifs, char *name,			      int ifflags, int iftype) {#ifdef IFF_LOOPBACK  if ((ifflags & IFF_LOOPBACK) && !(ifs->flags & IFSTAT_LOOPBACK))    return;#endif#ifdef IFF_UP  if (!(ifflags & IFF_UP) && !(ifs->flags & IFSTAT_DOWN))    return;#endif  #ifdef IFT_PFLOG  /* assume PFLOG interfaces are loopbacks (on OpenBSD) */  if (iftype == IFT_PFLOG && !(ifs->flags & IFSTAT_LOOPBACK))    return;#endif  ifstat_add_interface(ifs, name, 0);}#ifdef USE_IOCTL#ifdef USE_IFNAMEINDEXstatic int ioctl_map_ifs(int sd,			 int (*mapf)(int sd, struct ifreq *ifr, void *data),			 void *mdata) {  struct if_nameindex *iflist, *cur;  struct ifreq ifr;    if ((iflist = if_nameindex()) == NULL) {    ifstat_perror("if_nameindex");    return 0;  }  for(cur = iflist; cur->if_index != 0 && cur->if_name != NULL; cur++) {    memcpy(ifr.ifr_name, cur->if_name, sizeof(ifr.ifr_name));    ifr.ifr_name[sizeof(ifr.ifr_name) - 1] = '\0';    if (!mapf(sd, &ifr, mdata))      return 0;  }  if_freenameindex(iflist);  return 1;}#elsestatic int ioctl_map_ifs(int sd,			 int (*mapf)(int sd, struct ifreq *ifr, void *data),			 void *mdata) {  struct ifconf ifc;  struct ifreq *ifr;  int len, n, res = 0;  char *buf;#ifdef SIOCGIFNUM  if (ioctl(sd, SIOCGIFNUM, &n) < 0) {    ifstat_perror("ioctl(SIOCGIFNUM):");    goto end;  }  n += 2;#else  n = 256; /* bad bad bad... */#endif  len = n * sizeof(struct ifreq);  if ((buf = malloc(len)) == NULL) {    ifstat_perror("malloc");    return 0;  }  ifc.ifc_buf = buf;  ifc.ifc_len = len;  if (ioctl(sd, SIOCGIFCONF, (char *)&ifc) < 0) {    ifstat_perror("ioctl(SIOCGIFCONF):");    goto end;  }  n = 0;  while (n < ifc.ifc_len) {    ifr = (struct ifreq *) (buf + n);#ifdef HAVE_SOCKADDR_SA_LEN        n += sizeof(ifr->ifr_name) + ifr->ifr_addr.sa_len;#else    n += sizeof(struct ifreq);#endif    if (!mapf(sd, ifr, mdata))      goto end;  }  res = 1;   end:  free(buf);  return res;}#endifstatic int ioctl_map_scan(int sd, struct ifreq *ifr, void *data) {    if (ioctl(sd, SIOCGIFFLAGS, (char *)ifr) != 0)    return 1;  examine_interface((struct ifstat_list *) data, ifr->ifr_name,		    ifr->ifr_flags, 0);  return 1;}static int ioctl_scan_interfaces(struct ifstat_driver *driver,				 struct ifstat_list *ifs) {  int sd;  if ((sd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {    ifstat_perror("socket");    return 0;  }  ioctl_map_ifs(sd, &ioctl_map_scan, (void *) ifs);  close(sd);    return 1;} #endif#ifdef USE_KSTATstatic int get_kstat_long(kstat_t *ksp, char *name, unsigned long *value) {  kstat_named_t *data;  if ((data = kstat_data_lookup(ksp, name)) == NULL)    return 0;  switch (data->data_type) {#ifdef KSTAT_DATA_INT32    /* solaris 2.6 and over */      case KSTAT_DATA_INT32:    *value = data->value.i32;    break;  case KSTAT_DATA_INT64:    *value = data->value.i64;    break;  case KSTAT_DATA_UINT32:    *value = data->value.ui32;    break;  case KSTAT_DATA_UINT64:    *value = data->value.ui64;    break;#else  case KSTAT_DATA_LONGLONG:    *value = data->value.ll;    break;  case KSTAT_DATA_ULONGLONG:    *value = data->value.ull;    break;  case KSTAT_DATA_LONG:    *value = data->value.l;    break;  case KSTAT_DATA_ULONG:    *value = data->value.ul;    break;#endif      default:    return 0;  }  return 1;}static int kstat_open_driver(struct ifstat_driver *driver,			     char *options) {  kstat_ctl_t *kc;    if ((kc = kstat_open()) == NULL) {    ifstat_perror("kstat_open");    return 0;  }  driver->data = (void *) kc;  return 1;}static int kstat_get_stats(struct ifstat_driver *driver,			   struct ifstat_list *ifs) {  unsigned long bytesin, bytesout;  struct ifstat_data *cur;  kstat_ctl_t *kc = driver->data;  kstat_t *ksp;  for (cur = ifs->first; cur != NULL; cur = cur->next) {    if (cur->flags & IFSTAT_TOTAL)      continue;    if ((ksp = kstat_lookup(kc, NULL, -1, cur->name)) == NULL ||	ksp->ks_type != KSTAT_TYPE_NAMED)      continue;    if (kstat_read(kc, ksp, 0) >= 0 &&	get_kstat_long(ksp, "obytes", &bytesout) &&	get_kstat_long(ksp, "rbytes", &bytesin))      ifstat_set_interface_stats(cur, bytesin, bytesout);  }  return 1;}static void kstat_close_driver(struct ifstat_driver *driver) {  kstat_close(((kstat_ctl_t *) driver->data));}#endif#ifdef USE_KVM#ifndef HAVE_KVM/* use internal emulation using open/read/nlist */#ifndef _POSIX2_LINE_MAX#define _POSIX2_LINE_MAX 2048#endif#ifndef _PATH_KMEM#define _PATH_KMEM "/dev/kmem"#endif#ifndef _PATH_UNIX#define _PATH_UNIX "/vmunix"#endiftypedef struct _kvm_t {  int fd;  char *errbuf;  char *execfile;} kvm_t;static void _kvm_error(char *errbuf, char *message) {  strncpy(errbuf, message ? message : strerror(errno),	  _POSIX2_LINE_MAX - 1);  errbuf[_POSIX2_LINE_MAX - 1] = '\0';}static kvm_t *kvm_openfiles(const char *execfile, const char *corefile,			    const char *swapfile, int flags, char *errbuf) {  kvm_t *kd;  if (swapfile != NULL) {    _kvm_error(errbuf, "swap file option not supported");    return NULL;  }    if ((kd = malloc(sizeof(kvm_t))) == NULL) {    _kvm_error(errbuf, NULL);    return NULL;  }  if ((kd->fd = open(corefile ? corefile : _PATH_KMEM, flags)) < 0) {    _kvm_error(errbuf, NULL);    free(kd);    return NULL;  }  kd->execfile = execfile ? strdup(execfile) : NULL;  kd->errbuf = errbuf;  return kd;}static int kvm_nlist (kvm_t *kd, struct nlist *nl) {  int count;  #ifdef HAVE_KNLIST  if (kd->execfile == NULL) {#ifdef HAVE_KNLIST_ARGS3     for(count = 0; nl[count].n_name != NULL; count++);    count = knlist(nl, count, sizeof(struct nlist));#else    count = knlist(nl);#endif    if (count < 0)      _kvm_error(kd->errbuf, "error looking up symbol in live kernel");    return count;  }#endif    if ((count = nlist(kd->execfile ? kd->execfile : _PATH_UNIX, nl)) < 0)    _kvm_error(kd->errbuf, "error looking up symbol in kernel file");  return count;}#ifdef HAVE_READX#define KOFFSET(x) ((x) & 0x7FFFFFFF)#define KREAD(fd, buf, size, addr) readx((fd), (buf), (size), ((off_t) (addr)) < 0 ? 1 : 0)#else#define KOFFSET(x) (x)#define KREAD(fd, buf, size, addr) read((fd), (buf), (size))#endifstatic ssize_t kvm_read(kvm_t *kd, unsigned long addr, void *buf, size_t nbytes) {  ssize_t len;  if (lseek(kd->fd, KOFFSET(addr), SEEK_SET) == -1) {    _kvm_error(kd->errbuf, NULL);    return -1;  }  if ((len = KREAD(kd->fd, buf, nbytes, addr)) < 0) {    _kvm_error(kd->errbuf, NULL);    return -1;  }  return len;}static int kvm_close(kvm_t *kd) {  close(kd->fd);  free(kd->execfile);  free(kd);  return 0;}#endifstruct kvm_driver_data {  kvm_t *kvmfd;  unsigned long ifnetaddr;  char errbuf[_POSIX2_LINE_MAX + 1];};static int kvm_open_driver(struct ifstat_driver *driver,			   char *options) {  struct kvm_driver_data *data;  struct nlist kvm_syms[2];  unsigned long ifnetaddr;  char *files[3] = { NULL /* execfile */,		     NULL /* corefile */,		     NULL /* swapfile */ };  int i;    if ((data = malloc(sizeof(struct kvm_driver_data))) == NULL) {    ifstat_perror("malloc");    return 0;  }  data->errbuf[0] = '\0';  /* cut options : [execfile][,[corefile][,[swapfile]]] */  i = 0;  while (options != NULL && i < 3) {    char *v = strchr(options, ',');    if (v != NULL)      *v++ = '\0';    if (*options != '\0')      files[i] = options;    i++;    options = v;  }  if ((data->kvmfd = kvm_openfiles(files[0], files[1], files[2],

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -