📄 iftable.c
字号:
break; } return SNMP_ERR_NOERROR;} /* * Architecture-independent routines to locate * and/or create the entry for a given interface */netsnmp_ifentry *ifTable_ifentry_get_by_name(netsnmp_cache * cache, char *name, int create){ netsnmp_ifentry tmp; netsnmp_ifentry *entry; netsnmp_container *container, *container_by_name; if ((NULL == cache) || (NULL == cache->magic)) { snmp_log(LOG_ERR, "invalid cache for ifTable\n"); return NULL; } container = (netsnmp_container *) cache->magic; container_by_name = container->next; if (NULL == container_by_name) { snmp_log(LOG_ERR, "invalid cache for ifTable_ifentry_get_by_name\n"); return NULL; } tmp.if_name = name; entry = CONTAINER_FIND(container_by_name, &tmp); if ((NULL == entry) && (create)) { entry = SNMP_MALLOC_TYPEDEF(netsnmp_ifentry); entry->if_name = strdup(name); /* * XXX - initialise the "static" information * a) Using the configure overrides * b) Via (architecture-specific) utility routines */ ifTable_ifentry_info_init(entry); /* * If we've met this interface before, use the same index. * Otherwise find an unused index value and use that. */ entry->index = se_find_value_in_slist("interfaces", name); if (entry->index == SE_DNE) { entry->index = se_find_free_value_in_slist("interfaces"); if (entry->index == SE_DNE) entry->index = 1; /* Completely new list! */ se_add_pair_to_slist("interfaces", strdup(name), entry->index); } /* * inserting in container will also handle container_by_name */ CONTAINER_INSERT(container, entry); DEBUGMSGTL(("mibII/ifTable", "Creating entry for %s (%d)\n", name, entry->index)); } if (entry) entry->flags &= NETSNMP_IF_FLAGS_ACTIVE; return entry;}netsnmp_ifentry *ifTable_ifentry_get_by_index(netsnmp_cache * cache, int index){ netsnmp_index tmp; netsnmp_container *container; if ((NULL == cache) || (NULL == cache->magic)) { snmp_log(LOG_ERR, "invalid cache for ifTable_ifentry_get_by_index\n"); return NULL; } container = (netsnmp_container *) cache->magic; tmp.len = 1; tmp.oids = (oid *) & index; return (netsnmp_ifentry *) CONTAINER_FIND(container, &tmp);} /* * The cache-handler loading routines are the * main place for architecture-specific code * * This is actually split into two for each architecture. * ifTable_load identifies the list of interfaces that * are currently present, and retrieves the dynamic * information for them (mostly statistic counters). * ifTable_info_init sets up the static information for a * given interface, and this will typically be * retained even after the interface disappears. */#ifdef linuxunsigned long longget_ifspeed(netsnmp_ifentry * entry){ return 10000000;}intget_iftype(netsnmp_ifentry * entry){ return 6;}intifTable_ifentry_info_init(netsnmp_ifentry * entry){ if (!entry) return -1; entry->oid_index.len = 1; entry->oid_index.oids = (oid *) & entry->index; if (!entry->if_speed) entry->if_speed = get_ifspeed(entry); if (!entry->if_type) entry->if_type = get_iftype(entry); entry->if_descr = strdup(entry->if_name); return 0;}intifTable_load(netsnmp_cache * cache, void *vmagic){ FILE *devin; char line[256]; const char *scan_line_2_2 = "%llu %llu %llu %llu %*llu %*llu %*llu %*llu %llu %llu %llu %llu %*llu %llu"; const char *scan_line_2_0 = "%lu %lu %*lu %*lu %*lu %lu %lu %*lu %*lu %lu"; const char *scan_line_to_use; int scan_count; unsigned long long int rec_pkt, rec_oct, rec_err, rec_drop; unsigned long long int snd_pkt, snd_oct, snd_err, snd_drop, coll; netsnmp_ifentry *entry; netsnmp_container *container; if ((NULL == cache) || (NULL == cache->magic)) { snmp_log(LOG_ERR, "invalid cache for ifTable_load\n"); return -1; } DEBUGMSGTL(("ifTable/cache", "ifTable_load %p/%p\n", cache, cache->magic)); container = (netsnmp_container *) cache->magic; if (cache->valid) ifTable_free(cache, NULL); if (!(devin = fopen("/proc/net/dev", "r"))) { DEBUGMSGTL(("mibII/ifTable", "Failed to load Interface Table (linux1)\n")); snmp_log(LOG_ERR, "snmpd: cannot open /proc/net/dev ...\n"); return -1; } /* * 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. * xxx - couldn't this result be cached at startup? can the format * change without a reboot?? * * 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. * * Robert suggests that once we have the table index, we could store the * raw data and save the parsing for later. Wouldn't save much work during * a walk, but if there are lots of interfaces and only a few are being * polled, it would save some parsing... */ fgets(line, sizeof(line), devin); fgets(line, sizeof(line), devin); /* * XXX - What's the format for the 2.6 kernel ? */ if (strstr(line, "compressed")) { scan_line_to_use = scan_line_2_2; DEBUGMSGTL(("mibII/ifTable", "using linux 2.2 kernel /proc/net/dev\n")); } else { scan_line_to_use = scan_line_2_0; DEBUGMSGTL(("mibII/ifTable", "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, "/proc/net/dev data format error, line ==|%s|", line); continue; } if ((scan_line_to_use == scan_line_2_2) && ((stats - line) < 6)) { snmp_log(LOG_ERR, "/proc/net/dev data format error, line ==|%s|", line); } *stats = 0; entry = ifTable_ifentry_get_by_name(cache, ifstart, 1); *stats++ = ':'; while (*stats == ' ') stats++; /* * 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 flags field to indicate which counters are valid */ /* * XXX - may need another block for the 2.6 kernel */ rec_pkt = rec_oct = rec_err = rec_drop = 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, &snd_oct, &snd_pkt, &snd_err, &snd_drop, &coll); if (scan_count == 9) { entry->flags |= NETSNMP_IF_FLAGS_ACTIVE; entry->flags |= NETSNMP_IF_FLAGS_HAS_BYTES; entry->flags |= NETSNMP_IF_FLAGS_HAS_DROPS; /* * 2.4 kernel includes a single multicast (input) counter? */ entry->flags |= NETSNMP_IF_FLAGS_HAS_MCAST_PKTS; entry->flags |= NETSNMP_IF_FLAGS_HAS_HIGH_SPEED; entry->flags |= NETSNMP_IF_FLAGS_HAS_HIGH_BYTES; entry->flags |= NETSNMP_IF_FLAGS_HAS_HIGH_PACKETS; } } else { scan_count = sscanf(stats, scan_line_to_use, &rec_pkt, &rec_err, &snd_pkt, &snd_err, &coll); if (scan_count == 5) { entry->flags |= NETSNMP_IF_FLAGS_ACTIVE; entry->flags &= ~NETSNMP_IF_FLAGS_HAS_MCAST_PKTS; rec_oct = rec_drop = 0; snd_oct = snd_drop = 0; } } /* * linux previous to 1.3.~13 may miss transmitted loopback pkts: */ if (!strcmp(entry->if_name, "lo") && rec_pkt > 0 && !snd_pkt) snd_pkt = rec_pkt; if (entry->flags & NETSNMP_IF_FLAGS_ACTIVE) { entry->if_ibytes.low = rec_oct & 0xffffffff; entry->if_ibytes.high = rec_oct >> 32; entry->if_iucast.low = rec_pkt & 0xffffffff; entry->if_iucast.high = rec_pkt >> 32; entry->if_ierrors = rec_err; entry->if_idiscards = rec_drop; entry->if_obytes.low = snd_oct & 0xffffffff; entry->if_obytes.high = snd_oct >> 32; entry->if_oucast.low = snd_pkt & 0xffffffff; entry->if_oucast.high = snd_pkt >> 32; entry->if_oerrors = snd_err; entry->if_odiscards = snd_drop; entry->if_collisions = coll; } } fclose(devin); return 0;}#endif /* linux */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -