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

📄 interface_linux.c

📁 开发snmp的开发包有两个开放的SNMP开发库
💻 C
📖 第 1 页 / 共 2 页
字号:
}/* * * @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];    netsnmp_interface_entry *entry = NULL;    static char     scan_expected = 0;    int             fd;#ifdef NETSNMP_ENABLE_IPV6    netsnmp_container *addr_container;#endif    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;    }#ifdef NETSNMP_ENABLE_IPV6    /*     * get ipv6 addresses     */    addr_container = netsnmp_access_ipaddress_container_load(NULL, 0);#endif    /*     * 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);    if( 0 == scan_expected ) {        if (strstr(line, "compressed")) {            scan_expected = 10;            DEBUGMSGTL(("access:interface",                        "using linux 2.2 kernel /proc/net/dev\n"));        } else {            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;        u_int           flags;        oid             if_index;        flags = 0;        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_expected == 10) && ((stats - line) < 6)) {            snmp_log(LOG_ERR,                     "interface data format error 2 (%d < 6), line ==|%s|\n",                     stats - line, 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 */        if_index = netsnmp_arch_interface_index_find(ifstart);        /*         * set address type flags.         * the only way I know of to check an interface for         * ip version is to look for ip addresses. If anyone         * knows a better way, put it here!         */#ifdef NETSNMP_ENABLE_IPV6        _arch_interface_has_ipv6(if_index, &flags, addr_container);#endif        netsnmp_access_interface_ioctl_has_ipv4(fd, ifstart, 0, &flags);        /*         * do we only want one address type?         */        if (((load_flags & NETSNMP_ACCESS_INTERFACE_LOAD_IP4_ONLY) &&             ((flags & NETSNMP_INTERFACE_FLAGS_HAS_IPV4) == 0)) ||            ((load_flags & NETSNMP_ACCESS_INTERFACE_LOAD_IP6_ONLY) &&             ((flags & NETSNMP_INTERFACE_FLAGS_HAS_IPV6) == 0))) {            DEBUGMSGTL(("9:access:ifcontainer",                        "interface '%s' excluded by ip version\n",                        ifstart));            continue;        }        entry = netsnmp_access_interface_entry_create(ifstart, 0);        if(NULL == entry) {#ifdef NETSNMP_ENABLE_IPV6            netsnmp_access_ipaddress_container_free(addr_container, 0);#endif            netsnmp_access_interface_container_free(container,                                                    NETSNMP_ACCESS_INTERFACE_FREE_NOFLAGS);            fclose(devin);            close(fd);            return -3;        }        entry->ns_flags = flags; /* initial flags; we'll set more later */        /*         * xxx-rks: get descr by linking mem from /proc/pci and /proc/iomem         */        /*         * use ioctls for some stuff         *  (ignore rc, so we get as much info as possible)         */        netsnmp_access_interface_ioctl_physaddr_get(fd, entry);        /*         * physaddr should have set type. make some guesses (based         * on name) if not.         */        if(0 == entry->type) {            typedef struct _match_if {               int             mi_type;               const char     *mi_name;            }              *pmatch_if, match_if;                        static match_if lmatch_if[] = {                {IANAIFTYPE_SOFTWARELOOPBACK, "lo"},                {IANAIFTYPE_ETHERNETCSMACD, "eth"},                {IANAIFTYPE_ETHERNETCSMACD, "vmnet"},                {IANAIFTYPE_ISO88025TOKENRING, "tr"},                {IANAIFTYPE_FASTETHER, "feth"},                {IANAIFTYPE_GIGABITETHERNET,"gig"},                {IANAIFTYPE_PPP, "ppp"},                {IANAIFTYPE_SLIP, "sl"},                {IANAIFTYPE_TUNNEL, "sit"},                {IANAIFTYPE_BASICISDN, "ippp"},                {IANAIFTYPE_PROPVIRTUAL, "bond"}, /* Bonding driver find fastest slave */                {IANAIFTYPE_PROPVIRTUAL, "vad"},  /* ANS driver - ?speed? */                {0, 0}                  /* end of list */            };            int             ii, len;            register pmatch_if pm;                        for (ii = 0, pm = lmatch_if; pm->mi_name; pm++) {                len = strlen(pm->mi_name);                if (0 == strncmp(entry->name, pm->mi_name, len)) {                    entry->type = pm->mi_type;                    break;                }            }            if(NULL == pm->mi_name)                entry->type = IANAIFTYPE_OTHER;        }        if (IANAIFTYPE_ETHERNETCSMACD == entry->type)            entry->speed =                netsnmp_linux_interface_get_if_speed(fd, entry->name);#ifdef APPLIED_PATCH_836390   /* xxx-rks ifspeed fixes */        else if (IANAIFTYPE_PROPVIRTUAL == entry->type)            entry->speed = _get_bonded_if_speed(entry);#endif        else            netsnmp_access_interface_entry_guess_speed(entry);                netsnmp_access_interface_ioctl_flags_get(fd, entry);        netsnmp_access_interface_ioctl_mtu_get(fd, entry);        /*         * Zero speed means link problem.         * - i'm not sure this is always true...         */        if((entry->speed == 0) && (entry->os_flags & IFF_UP)) {            entry->os_flags &= ~IFF_RUNNING;        }        /*         * check for promiscuous mode.         *  NOTE: there are 2 ways to set promiscuous mode in Linux         *  (kernels later than 2.2.something) - using ioctls and         *  using setsockopt. The ioctl method tested here does not         *  detect if an interface was set using setsockopt. google         *  on IFF_PROMISC and linux to see lots of arguments about it.         */        if(entry->os_flags & IFF_PROMISC) {            entry->promiscuous = 1; /* boolean */        }        /*         * hardcoded max packet size         * (see ip_frag_reasm: if(len > 65535) goto out_oversize;)         */        entry->reasm_max_v4 = entry->reasm_max_v6 = 65535;        entry->ns_flags |=             NETSNMP_INTERFACE_FLAGS_HAS_V4_REASMMAX |            NETSNMP_INTERFACE_FLAGS_HAS_V6_REASMMAX;        netsnmp_access_interface_entry_overrides(entry);        entry->speed_high = entry->speed / 1000000;        if (! (load_flags & NETSNMP_ACCESS_INTERFACE_LOAD_NO_STATS))            _parse_stats(entry, stats, scan_expected);        if (flags & NETSNMP_INTERFACE_FLAGS_HAS_IPV4)            _arch_interface_flags_v4_get(entry);#ifdef NETSNMP_ENABLE_IPV6        if (flags & NETSNMP_INTERFACE_FLAGS_HAS_IPV6)            _arch_interface_flags_v6_get(entry);#endif /* NETSNMP_ENABLE_IPV6 */        /*         * add to container         */        CONTAINER_INSERT(container, entry);    }#ifdef NETSNMP_ENABLE_IPV6    netsnmp_access_ipaddress_container_free(addr_container, 0);#endif    fclose(devin);    close(fd);    return 0;}intnetsnmp_arch_set_admin_status(netsnmp_interface_entry * entry,                              int ifAdminStatus_val){    int and_complement;        DEBUGMSGTL(("access:interface:arch", "set_admin_status\n"));    if(IFADMINSTATUS_UP == ifAdminStatus_val)        and_complement = 0; /* |= */    else        and_complement = 1; /* &= ~ */    return netsnmp_access_interface_ioctl_flags_set(-1, entry,                                                    IFF_UP, and_complement);}#ifdef HAVE_LINUX_ETHTOOL_H/** * Determines network interface speed from ETHTOOL_GSET */unsigned intnetsnmp_linux_interface_get_if_speed(int fd, const char *name){    struct ifreq ifr;    struct ethtool_cmd edata;    memset(&ifr, 0, sizeof(ifr));    edata.cmd = ETHTOOL_GSET;        strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)-1);    ifr.ifr_data = (char *) &edata;        if (ioctl(fd, SIOCETHTOOL, &ifr) == -1) {        DEBUGMSGTL(("mibII/interfaces", "ETHTOOL_GSET on %s failed\n",                    ifr.ifr_name));        return netsnmp_linux_interface_get_if_speed_mii(fd,name);    }        if (edata.speed != SPEED_10 && edata.speed != SPEED_100 &&        edata.speed != SPEED_1000) {        DEBUGMSGTL(("mibII/interfaces", "fallback to mii for %s\n",                    ifr.ifr_name));        /* try MII */        return netsnmp_linux_interface_get_if_speed_mii(fd,name);    }    /* return in bps */    DEBUGMSGTL(("mibII/interfaces", "ETHTOOL_GSET on %s speed = %d\n",                ifr.ifr_name, edata.speed));    return edata.speed*1000*1000;}#endif /** * Determines network interface speed from MII */unsigned int#ifdef HAVE_LINUX_ETHTOOL_Hnetsnmp_linux_interface_get_if_speed_mii(int fd, const char *name)#elsenetsnmp_linux_interface_get_if_speed(int fd, const char *name)#endif{    unsigned int retspeed = 10000000;    struct ifreq ifr;    /* the code is based on mii-diag utility by Donald Becker     * see ftp://ftp.scyld.com/pub/diag/mii-diag.c     */    ushort *data = (ushort *)(&ifr.ifr_data);    unsigned phy_id;    unsigned char new_ioctl_nums = 0;    int mii_reg, i;    ushort mii_val[32];    ushort bmcr, bmsr, nway_advert, lkpar;    const unsigned int media_speeds[] = {10000000, 10000000, 100000000, 100000000, 10000000, 0};	    /* It corresponds to "10baseT", "10baseT-FD", "100baseTx", "100baseTx-FD", "100baseT4", "Flow-control", 0, */    strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));    ifr.ifr_name[ sizeof(ifr.ifr_name)-1 ] = 0;    data[0] = 0;        if (ioctl(fd, 0x8947, &ifr) >= 0) {        new_ioctl_nums = 1;    } else if (ioctl(fd, SIOCDEVPRIVATE, &ifr) >= 0) {        new_ioctl_nums = 0;    } else {        DEBUGMSGTL(("mibII/interfaces", "SIOCGMIIPHY on %s failed\n",                    ifr.ifr_name));        return retspeed;    }    /* Begin getting mii register values */    phy_id = data[0];    for (mii_reg = 0; mii_reg < 8; mii_reg++){        data[0] = phy_id;        data[1] = mii_reg;        if(ioctl(fd, new_ioctl_nums ? 0x8948 : SIOCDEVPRIVATE+1, &ifr) <0){            DEBUGMSGTL(("mibII/interfaces", "SIOCGMIIREG on %s failed\n", ifr.ifr_name));        }        mii_val[mii_reg] = data[3];		    }    /*Parsing of mii values*/    /*Invalid basic mode control register*/    if (mii_val[0] == 0xffff  ||  mii_val[1] == 0x0000) {        DEBUGMSGTL(("mibII/interfaces", "No MII transceiver present!.\n"));        return retspeed;    }    /* Descriptive rename. */    bmcr = mii_val[0]; 	  /*basic mode control register*/    bmsr = mii_val[1]; 	  /* basic mode status register*/    nway_advert = mii_val[4]; /* autonegotiation advertisement*/    lkpar = mii_val[5]; 	  /*link partner ability*/        /*Check for link existence, returns 0 if link is absent*/    if ((bmsr & 0x0016) != 0x0004){        DEBUGMSGTL(("mibII/interfaces", "No link...\n"));        retspeed = 0;        return retspeed;    }        if(!(bmcr & 0x1000) ){        DEBUGMSGTL(("mibII/interfaces", "Auto-negotiation disabled.\n"));        retspeed = bmcr & 0x2000 ? 100000000 : 10000000;        return retspeed;    }    /* Link partner got our advertised abilities */	    if (lkpar & 0x4000) {        int negotiated = nway_advert & lkpar & 0x3e0;        int max_capability = 0;        /* Scan for the highest negotiated capability, highest priority           (100baseTx-FDX) to lowest (10baseT-HDX). */        int media_priority[] = {8, 9, 7, 6, 5}; 	/* media_names[i-5] */        for (i = 0; media_priority[i]; i++){            if (negotiated & (1 << media_priority[i])) {                max_capability = media_priority[i];                break;            }        }        if (max_capability)            retspeed = media_speeds[max_capability - 5];        else            DEBUGMSGTL(("mibII/interfaces", "No common media type was autonegotiated!\n"));    }else if(lkpar & 0x00A0){        retspeed = (lkpar & 0x0080) ? 100000000 : 10000000;    }    return retspeed;}

⌨️ 快捷键说明

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