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

📄 interface_linux.c

📁 开发snmp的开发包有两个开放的SNMP开发库
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *  Interface MIB architecture support * * $Id: interface_linux.c 16595 2007-07-06 21:14:03Z rstory $ */#include <net-snmp/net-snmp-config.h>#include <net-snmp/net-snmp-includes.h>#ifdef HAVE_LINUX_ETHTOOL_H#include <linux/types.h>typedef __u64 u64;         /* hack, so we may include kernel's ethtool.h */typedef __u32 u32;         /* ditto */typedef __u16 u16;         /* ditto */typedef __u8 u8;           /* ditto */#include <linux/ethtool.h>#endif /* HAVE_LINUX_ETHTOOL_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 <net-snmp/data_access/ipaddress.h>#include "if-mib/data_access/interface.h"#include "interface_ioctl.h"#include <sys/types.h>#include <sys/stat.h>#include <unistd.h>#include <linux/sockios.h>#ifndef IF_NAMESIZE#define IF_NAMESIZE 16#endifunsigned intnetsnmp_linux_interface_get_if_speed(int fd, const char *name);#ifdef HAVE_LINUX_ETHTOOL_Hunsigned intnetsnmp_linux_interface_get_if_speed_mii(int fd, const char *name);#endif#define PROC_SYS_NET_IPVx_NEIGH_RETRANS_TIME_MS "/proc/sys/net/ipv%d/neigh/%s/retrans_time_ms"#define PROC_SYS_NET_IPVx_NEIGH_RETRANS_TIME    "/proc/sys/net/ipv%d/neigh/%s/retrans_time"static const char *proc_sys_retrans_time;static unsigned short retrans_time_factor = 1;#define PROC_SYS_NET_IPVx_BASE_REACHABLE_TIME_MS "/proc/sys/net/ipv%d/neigh/%s/base_reachable_time_ms"#define PROC_SYS_NET_IPVx_BASE_REACHABLE_TIME "/proc/sys/net/ipv%d/neigh/%s/base_reachable_time"static const char *proc_sys_basereachable_time;static unsigned short basereachable_time_ms = 0;voidnetsnmp_arch_interface_init(void){    /*     * Check which retransmit time interface is available     */    char proc_path[ 64+IF_NAMESIZE];    char proc_path2[64+IF_NAMESIZE];    struct stat st;    snprintf(proc_path,  sizeof(proc_path),             PROC_SYS_NET_IPVx_NEIGH_RETRANS_TIME_MS, 6, "default");    snprintf(proc_path2, sizeof(proc_path2),             PROC_SYS_NET_IPVx_NEIGH_RETRANS_TIME_MS, 4, "default");    if ((stat(proc_path, &st) == 0) || (stat(proc_path2, &st) == 0)) {        proc_sys_retrans_time = PROC_SYS_NET_IPVx_NEIGH_RETRANS_TIME_MS;    } else {        proc_sys_retrans_time = PROC_SYS_NET_IPVx_NEIGH_RETRANS_TIME;        retrans_time_factor = 10;    }    snprintf(proc_path,  sizeof(proc_path),  PROC_SYS_NET_IPVx_BASE_REACHABLE_TIME_MS, 6, "default");    snprintf(proc_path2,  sizeof(proc_path),  PROC_SYS_NET_IPVx_BASE_REACHABLE_TIME, 4, "default");    if ((stat(proc_path, &st) == 0) || (stat(proc_path2, &st) == 0)) {        proc_sys_basereachable_time = PROC_SYS_NET_IPVx_BASE_REACHABLE_TIME_MS;        basereachable_time_ms = 1;    }    else {        proc_sys_basereachable_time = PROC_SYS_NET_IPVx_BASE_REACHABLE_TIME;    }}/* * 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);}/* * check for ipv6 addresses */void_arch_interface_has_ipv6(oid if_index, u_int *flags,                         netsnmp_container *addr_container){#ifdef NETSNMP_ENABLE_IPV6    netsnmp_ipaddress_entry *addr_entry = NULL;    netsnmp_iterator        *addr_it = NULL;    u_int                    addr_container_flags = 0; /* must init to 0 */#endif    if (NULL == flags)        return;    *flags &= ~NETSNMP_INTERFACE_FLAGS_HAS_IPV6;#ifdef NETSNMP_ENABLE_IPV6    /*     * get ipv6 addresses     */    if (NULL == addr_container) {        /*         * we only care about ipv6, if we need to allocate our own         * temporary container. set the flags (which we also use later         * to determine if we need to free the container).         */        addr_container_flags = NETSNMP_ACCESS_IPADDRESS_LOAD_IPV6_ONLY;        addr_container =            netsnmp_access_ipaddress_container_load(NULL,                                                    addr_container_flags);        if (NULL == addr_container) {            DEBUGMSGTL(("access:ifcontainer",                        "couldn't get ip addresses container\n"));            return;        }    }    else {        /*         * addr_container flags must be 0, so we don't release the         * user's container.         */        netsnmp_assert(0 == addr_container_flags);    }    /*     * get an ipaddress container iterator, and look for ipv6 addrs     */       addr_it = CONTAINER_ITERATOR(addr_container);    if (NULL == addr_it) {        DEBUGMSGTL(("access:ifcontainer",                    "couldn't get ip addresses iterator\n"));        if (0!=addr_container_flags)            netsnmp_access_ipaddress_container_free(addr_container, 0);        return;    }    addr_entry = ITERATOR_FIRST(addr_it);    for( ; addr_entry ; addr_entry = ITERATOR_NEXT(addr_it) ) {        /*         * skip non matching indexes and ipv4 addresses         */        if ((if_index != addr_entry->if_index) ||            (4 == addr_entry->ia_address_len))            continue;        /*         * found one! no need to keep looking, set the flag and bail         */        *flags |= NETSNMP_INTERFACE_FLAGS_HAS_IPV6;        break;    }    /*     * make mama proud and clean up after ourselves     */    ITERATOR_RELEASE(addr_it);    if (0!=addr_container_flags)        netsnmp_access_ipaddress_container_free(addr_container, 0);    #endif}/** * @internal */static void_arch_interface_flags_v4_get(netsnmp_interface_entry *entry){    FILE           *fin;    char            line[256];    /*     * get the retransmit time     */    snprintf(line,sizeof(line), proc_sys_retrans_time, 4,             entry->name);    if (!(fin = fopen(line, "r"))) {        DEBUGMSGTL(("access:interface",                    "Failed to open %s\n", line));    }    else {        if (fgets(line, sizeof(line), fin)) {            entry->retransmit_v4 = atoi(line) * retrans_time_factor;            entry->ns_flags |= NETSNMP_INTERFACE_FLAGS_HAS_V4_RETRANSMIT;        }        fclose(fin);    }}#ifdef NETSNMP_ENABLE_IPV6/** * @internal */static void_arch_interface_flags_v6_get(netsnmp_interface_entry *entry){    FILE           *fin;    char            line[256];    /*     * get the retransmit time     */    snprintf(line,sizeof(line), proc_sys_retrans_time, 6,             entry->name);    if (!(fin = fopen(line, "r"))) {        DEBUGMSGTL(("access:interface",                    "Failed to open %s\n", line));    }    else {        if (fgets(line, sizeof(line), fin)) {            entry->retransmit_v6 = atoi(line) * retrans_time_factor;            entry->ns_flags |= NETSNMP_INTERFACE_FLAGS_HAS_V6_RETRANSMIT;        }        fclose(fin);    }    /*     * get the forwarding status     */    snprintf(line, sizeof(line), "/proc/sys/net/ipv6/conf/%s/forwarding",             entry->name);    if (!(fin = fopen(line, "r"))) {        DEBUGMSGTL(("access:interface",                    "Failed to open %s\n", line));    }    else {        if (fgets(line, sizeof(line), fin)) {            entry->forwarding_v6 = atoi(line);            entry->ns_flags |= NETSNMP_INTERFACE_FLAGS_HAS_V6_FORWARDING;        }        fclose(fin);    }    /*     * get the reachable time     */    snprintf(line, sizeof(line), proc_sys_basereachable_time, 6, entry->name);    if (!(fin = fopen(line, "r"))) {        DEBUGMSGTL(("access:interface",                    "Failed to open %s\n", line));    }    else {        if (fgets(line, sizeof(line), fin)) {            if (basereachable_time_ms) {                entry->reachable_time = atoi(line); /* millisec */            } else {                entry->reachable_time = atoi(line)*1000; /* sec to  millisec */            }            entry->ns_flags |= NETSNMP_INTERFACE_FLAGS_HAS_V6_REACHABLE;        }        fclose(fin);    }}#endif /* NETSNMP_ENABLE_IPV6 *//** * @internal */static int_parse_stats(netsnmp_interface_entry *entry, char *stats, int expected){    /*     * 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;    int             scan_count;    if (10 == expected)        scan_line_to_use = scan_line_2_2;    else {        netsnmp_assert(5 == expected);        scan_line_to_use = scan_line_2_0;    }    while (*stats == ' ')        stats++;    if ((*stats == 'N') &&        (0 == strncmp(stats, "No statistics available",                      sizeof("No statistics available"))))        return -1;    /*     * Now parse the rest of the line (i.e. starting from 'stats')     *      to extract the relevant statistics, and populate     *      data structure accordingly.     * Use the entry flags field to indicate which counters are valid     */    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 == 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 == expected) {            entry->ns_flags &= ~NETSNMP_INTERFACE_FLAGS_HAS_MCAST_PKTS;            rec_oct = rec_drop = 0;            snd_oct = snd_drop = 0;        }    }    if(scan_count != expected) {        snmp_log(LOG_ERR,                 "error scanning interface data (expected %d, got %d)\n",                 expected, scan_count);        return scan_count;    }    entry->ns_flags |= NETSNMP_INTERFACE_FLAGS_ACTIVE;        /*     * linux previous to 1.3.~13 may miss transmitted loopback pkts:      */    if (!strcmp(entry->name, "lo") && rec_pkt > 0 && !snd_pkt)        snd_pkt = rec_pkt;        /*     * subtract out multicast packets from rec_pkt before     * we store it as unicast counter.     */    rec_pkt -= rec_mcast;    entry->stats.ibytes.low = rec_oct & 0xffffffff;    entry->stats.iucast.low = rec_pkt & 0xffffffff;    entry->stats.imcast.low = rec_mcast & 0xffffffff;    entry->stats.obytes.low = snd_oct & 0xffffffff;    entry->stats.oucast.low = snd_pkt & 0xffffffff;#ifdef SCNuMAX   /* XXX - should be flag for 64-bit variables */    entry->stats.ibytes.high = rec_oct >> 32;    entry->stats.iucast.high = rec_pkt >> 32;    entry->stats.imcast.high = rec_mcast >> 32;    entry->stats.obytes.high = snd_oct >> 32;    entry->stats.oucast.high = snd_pkt >> 32;#endif    entry->stats.ierrors   = rec_err;    entry->stats.idiscards = rec_drop;    entry->stats.oerrors   = snd_err;    entry->stats.odiscards = snd_drop;    entry->stats.collisions = coll;        /*     * calculated stats.     *     *  we have imcast, but not ibcast.     */    entry->stats.inucast = entry->stats.imcast.low +        entry->stats.ibcast.low;    entry->stats.onucast = entry->stats.omcast.low +        entry->stats.obcast.low;        return 0;

⌨️ 快捷键说明

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