📄 interface_linux.c
字号:
/* * Interface MIB architecture support * * $Id: interface_linux.c,v 1.20 2004/10/18 03:49:50 rstory Exp $ */#include <net-snmp/net-snmp-config.h>#include <net-snmp/net-snmp-includes.h>#include "mibII/mibII_common.h"#include "if-mib/ifTable/ifTable_constants.h"#include <net-snmp/agent/net-snmp-agent-includes.h>#if HAVE_SYS_IOCTL_H#include <sys/ioctl.h>#else#error "linux should have sys/ioctl header"#endif#include <net-snmp/data_access/interface.h>#include "if-mib/data_access/interface.h"#include "interface_ioctl.h"unsigned intnetsnmp_arch_interface_get_if_speed(int fd, const char *name);voidnetsnmp_arch_interface_init(void){ /* * nothing to do */}/* * find the ifIndex for an interface name * NOTE: The Linux version is not efficient for large numbers of calls. * consider using netsnmp_access_interface_ioctl_ifindex_get() * for loops which need to look up a lot of indexes. * * @retval 0 : no index found * @retval >0: ifIndex for interface */oidnetsnmp_arch_interface_index_find(const char *name){ return netsnmp_access_interface_ioctl_ifindex_get(-1, name);}/* * * @retval 0 success * @retval -1 no container specified * @retval -2 could not open /proc/net/dev * @retval -3 could not create entry (probably malloc) */intnetsnmp_arch_interface_container_load(netsnmp_container* container, u_int load_flags){ FILE *devin; char line[256]; /* * scanline_2_2: * [ IN ] * byte pkts errs drop fifo frame cmprs mcst | * [ OUT ] * byte pkts errs drop fifo colls carrier compressed */#ifdef SCNuMAX uintmax_t rec_pkt, rec_oct, rec_err, rec_drop, rec_mcast; uintmax_t snd_pkt, snd_oct, snd_err, snd_drop, coll; const char *scan_line_2_2 = "%" SCNuMAX " %" SCNuMAX " %" SCNuMAX " %" SCNuMAX " %*" SCNuMAX " %*" SCNuMAX " %*" SCNuMAX " %" SCNuMAX " %" SCNuMAX " %" SCNuMAX " %" SCNuMAX " %" SCNuMAX " %*" SCNuMAX " %" SCNuMAX; const char *scan_line_2_0 = "%" SCNuMAX " %" SCNuMAX " %*" SCNuMAX " %*" SCNuMAX " %*" SCNuMAX " %" SCNuMAX " %" SCNuMAX " %*" SCNuMAX " %*" SCNuMAX " %" SCNuMAX;#else unsigned long rec_pkt, rec_oct, rec_err, rec_drop, rec_mcast; unsigned long snd_pkt, snd_oct, snd_err, snd_drop, coll; const char *scan_line_2_2 = "%lu %lu %lu %lu %*lu %*lu %*lu %lu %lu %lu %lu %lu %*lu %lu"; const char *scan_line_2_0 = "%lu %lu %*lu %*lu %*lu %lu %lu %*lu %*lu %lu";#endif static const char *scan_line_to_use = NULL; static char scan_expected; int scan_count, fd; netsnmp_interface_entry *entry = NULL; struct ifreq ifrq; DEBUGMSGTL(("access:interface:container:arch", "load (flags %p)\n", load_flags)); if (NULL == container) { snmp_log(LOG_ERR, "no container specified/found for interface\n"); return -1; } if (!(devin = fopen("/proc/net/dev", "r"))) { DEBUGMSGTL(("access:interface", "Failed to load Interface Table (linux1)\n")); snmp_log(LOG_ERR, "cannot open /proc/net/dev ...\n"); return -2; } /* * create socket for ioctls */ fd = socket(AF_INET, SOCK_DGRAM, 0); if(fd < 0) { snmp_log(LOG_ERR, "could not create socket\n"); return -2; } /* * Read the first two lines of the file, containing the header * This indicates which version of the kernel we're working with, * and hence which statistics are actually available. * * Wes originally suggested parsing the field names in this header * to detect the position of individual fields directly, * but I suspect this is probably more trouble than it's worth. */ fgets(line, sizeof(line), devin); fgets(line, sizeof(line), devin); /* * XXX - What's the format for the 2.6 kernel ? */ if( NULL == scan_line_to_use ) { if (strstr(line, "compressed")) { scan_line_to_use = scan_line_2_2; scan_expected = 10; DEBUGMSGTL(("access:interface", "using linux 2.2 kernel /proc/net/dev\n")); } else { scan_line_to_use = scan_line_2_0; scan_expected = 5; DEBUGMSGTL(("access:interface", "using linux 2.0 kernel /proc/net/dev\n")); } } /* * The rest of the file provides the statistics for each interface. * Read in each line in turn, isolate the interface name * and retrieve (or create) the corresponding data structure. */ while (fgets(line, sizeof(line), devin)) { char *stats, *ifstart = line; if (line[strlen(line) - 1] == '\n') line[strlen(line) - 1] = '\0'; while (*ifstart && *ifstart == ' ') ifstart++; if ((!*ifstart) || ((stats = strrchr(ifstart, ':')) == NULL)) { snmp_log(LOG_ERR, "interface data format error 1, line ==|%s|\n", line); continue; } if ((scan_line_to_use == scan_line_2_2) && ((stats - line) < 6)) { snmp_log(LOG_ERR, "interface data format error 2 (%d < 6), line ==|%s|\n", line, stats - line); } DEBUGMSGTL(("9:access:ifcontainer", "processing '%s'\n", ifstart)); /* * get index via ioctl. * If we've met this interface before, use the same index. * Otherwise find an unused index value and use that. */ *stats++ = 0; /* null terminate name */ entry = netsnmp_access_interface_entry_create(ifstart, 0); if(NULL == entry) { netsnmp_access_interface_container_free(container, NETSNMP_ACCESS_INTERFACE_FREE_NOFLAGS); fclose(devin); close(fd); return -3; } /* * OK - we've now got (or created) the data structure for * this interface, including any "static" information. * Now parse the rest of the line (i.e. starting from 'stats') * to extract the relevant statistics, and populate * data structure accordingly. * Use the ifentry flags field to indicate which counters are valid */ while (*stats == ' ') stats++; rec_pkt = rec_oct = rec_err = rec_drop = rec_mcast = 0; snd_pkt = snd_oct = snd_err = snd_drop = coll = 0; if (scan_line_to_use == scan_line_2_2) { scan_count = sscanf(stats, scan_line_to_use, &rec_oct, &rec_pkt, &rec_err, &rec_drop, &rec_mcast, &snd_oct, &snd_pkt, &snd_err, &snd_drop, &coll); if (scan_count == scan_expected) { entry->ns_flags |= NETSNMP_INTERFACE_FLAGS_HAS_BYTES; entry->ns_flags |= NETSNMP_INTERFACE_FLAGS_HAS_DROPS; /* * 2.4 kernel includes a single multicast (input) counter? */ entry->ns_flags |= NETSNMP_INTERFACE_FLAGS_HAS_MCAST_PKTS; entry->ns_flags |= NETSNMP_INTERFACE_FLAGS_HAS_HIGH_SPEED;#ifdef SCNuMAX /* XXX - should be flag for 64-bit variables */ entry->ns_flags |= NETSNMP_INTERFACE_FLAGS_HAS_HIGH_BYTES; entry->ns_flags |= NETSNMP_INTERFACE_FLAGS_HAS_HIGH_PACKETS;#endif } } else { scan_count = sscanf(stats, scan_line_to_use, &rec_pkt, &rec_err, &snd_pkt, &snd_err, &coll); if (scan_count == scan_expected) { entry->ns_flags &= ~NETSNMP_INTERFACE_FLAGS_HAS_MCAST_PKTS; rec_oct = rec_drop = 0; snd_oct = snd_drop = 0; } } if(scan_count != scan_expected) { snmp_log(LOG_ERR, "error scanning interface data (expected %d, got %d)\n",
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -