/* * @retval 0 success * @retval -1 no container specified * @retval -2 could not create entry (probably malloc) */ int netsnmp_arch_interface_container_load (netsnmp_container * container, u_int l_flags) { netsnmp_interface_entry *entry = NULL; mib2_ifEntry_t ife; int rc; req_e req = GET_FIRST; int error = 0; DEBUGMSGTL (("access:interface:container:arch", "load (flags %u)\n", l_flags)); if (container == NULL) { snmp_log (LOG_ERR, "no container specified/found for interface\n"); return -1; } while ((rc = getMibstat (MIB_INTERFACES, &ife, sizeof (ife), req, &Get_everything, NULL)) == 0) { req = GET_NEXT; DEBUGMSGTL (("access:interface:container:arch", "processing '%s'\n", ife.ifDescr.o_bytes)); entry = netsnmp_access_interface_entry_create (ife.ifDescr.o_bytes, ife.ifIndex); if (entry == NULL) { error = 1; break; } entry->ns_flags = 0; if (l_flags & NETSNMP_ACCESS_INTERFACE_LOAD_IP4_ONLY && _set_ip_flags_v4 (entry, &ife) == 0) { netsnmp_access_interface_entry_free (entry); continue; } else if (l_flags & NETSNMP_ACCESS_INTERFACE_LOAD_IP6_ONLY && _set_ip_flags_v6 (entry, &ife) == 0) { netsnmp_access_interface_entry_free (entry); continue; } else { (void) _set_ip_flags_v4 (entry, &ife); (void) _set_ip_flags_v6 (entry, &ife); } /* * collect the information needed by IF-MIB */ entry->paddr = (char *) malloc (ife.ifPhysAddress.o_length); if (entry->paddr == NULL) { netsnmp_access_interface_entry_free (entry); error = 1; break; } entry->paddr_len = ife.ifPhysAddress.o_length; (void) memcpy (entry->paddr, ife.ifPhysAddress.o_bytes, ife.ifPhysAddress.o_length); entry->type = ife.ifType; entry->mtu = ife.ifMtu; entry->speed = ife.ifSpeed; entry->speed_high = entry->speed / 1000000; entry->ns_flags |= NETSNMP_INTERFACE_FLAGS_HAS_HIGH_SPEED; entry->oper_status = ife.ifOperStatus; entry->admin_status = ife.ifAdminStatus; if (ife.flags & IFF_PROMISC) entry->promiscuous = 1; entry->ns_flags |= NETSNMP_INTERFACE_FLAGS_ACTIVE; /* * Interface Stats. */ if (!(l_flags & NETSNMP_ACCESS_INTERFACE_LOAD_NO_STATS)) { entry->ns_flags |= NETSNMP_INTERFACE_FLAGS_HAS_BYTES | NETSNMP_INTERFACE_FLAGS_HAS_DROPS | NETSNMP_INTERFACE_FLAGS_HAS_MCAST_PKTS; if (ife.ifHCInOctets > 0 || ife.ifHCOutOctets > 0) { /* * We make the assumption that if we have * a 64-bit Octet counter, then the other * counters are 64-bit as well. */ DEBUGMSGTL (("access:interface:container:arch", "interface '%s' have 64-bit stat counters\n", entry->name)); entry->ns_flags |= NETSNMP_INTERFACE_FLAGS_HAS_HIGH_BYTES | NETSNMP_INTERFACE_FLAGS_HAS_HIGH_PACKETS; /* in stats */ entry->stats.ibytes.low = ife.ifHCInOctets & 0xffffffff; entry->stats.ibytes.high = ife.ifHCInOctets >> 32; entry->stats.iucast.low = ife.ifHCInUcastPkts & 0xffffffff; entry->stats.iucast.high = ife.ifHCInUcastPkts >> 32; entry->stats.imcast.low = ife.ifHCInMulticastPkts & 0xffffffff; entry->stats.imcast.high = ife.ifHCInMulticastPkts >> 32; entry->stats.ibcast.low = ife.ifHCInBroadcastPkts & 0xffffffff; entry->stats.ibcast.high = ife.ifHCInBroadcastPkts >> 32; /* out stats */ entry->stats.obytes.low = ife.ifHCOutOctets & 0xffffffff; entry->stats.obytes.high = ife.ifHCOutOctets >> 32; entry->stats.oucast.low = ife.ifHCOutUcastPkts & 0xffffffff; entry->stats.oucast.high = ife.ifHCOutUcastPkts >> 32; entry->stats.omcast.low = ife.ifHCOutMulticastPkts & 0xffffffff; entry->stats.omcast.high = ife.ifHCOutMulticastPkts >> 32; entry->stats.obcast.low = ife.ifHCOutBroadcastPkts & 0xffffffff; entry->stats.obcast.high = ife.ifHCOutBroadcastPkts >> 32; } else {
/* * * @retval 0 success * @retval -1 no container specified * @retval -2 could not open /proc/net/dev * @retval -3 could not create entry (probably malloc) */ int netsnmp_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 = // 10000000;//incifer 20091027, fix read RTL8306 ocurred error. 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; }