/** * add new entry */ static void _add_new(netsnmp_systemstats_entry *systemstats_entry, netsnmp_container *container) { ipSystemStatsTable_rowreq_ctx *rowreq_ctx; DEBUGMSGTL(("ipSystemStatsTable:access", "creating new entry\n")); netsnmp_assert(NULL != systemstats_entry); netsnmp_assert(NULL != container); /* * allocate an row context and set the index(es) */ rowreq_ctx = ipSystemStatsTable_allocate_rowreq_ctx(systemstats_entry, NULL); if ((NULL != rowreq_ctx) && (MFD_SUCCESS == ipSystemStatsTable_indexes_set(rowreq_ctx, systemstats_entry-> index[0]))) { rowreq_ctx->ipSystemStatsRefreshRate = ipss_cache_refresh * 1000; /* milli-seconds */ CONTAINER_INSERT(container, rowreq_ctx); } else { if (NULL != rowreq_ctx) { snmp_log(LOG_ERR, "error setting index while loading " "ipSystemStatsTable cache.\n"); ipSystemStatsTable_release_rowreq_ctx(rowreq_ctx); } else { snmp_log(LOG_ERR, "memory allocation failed while loading " "ipSystemStatsTable cache.\n"); netsnmp_access_systemstats_entry_free(systemstats_entry); } } }
/** * check entry for update */ static void _check_for_updates(ipIfStatsTable_rowreq_ctx * rowreq_ctx, netsnmp_container *stats) { netsnmp_systemstats_entry *ifstats_entry; /* * check for matching entry. works because indexes are the same. */ ifstats_entry = (netsnmp_systemstats_entry*)CONTAINER_FIND(stats, rowreq_ctx->data); if (NULL == ifstats_entry) { DEBUGMSGTL(("ipIfStatsTable:access", "updating missing entry\n")); /* * mark row as missing, so we can set discontinuity * when it comes back. * * what else should we do? set refresh to 0? that's not quite right... */ rowreq_ctx->known_missing = 1; } else { DEBUGMSGTL(("ipIfStatsTable:access", "updating existing entry\n")); /* * Check for changes & update */ netsnmp_access_systemstats_entry_update(rowreq_ctx->data, ifstats_entry); /* * set discontinuity if previously missing. */ if (1 == rowreq_ctx->known_missing) { rowreq_ctx->known_missing = 0; rowreq_ctx->ipIfStatsDiscontinuityTime = netsnmp_get_agent_uptime(); ipIfStatsTable_lastChange_set(netsnmp_get_agent_uptime()); } /* * remove entry from container */ CONTAINER_REMOVE(stats, ifstats_entry); netsnmp_access_systemstats_entry_free(ifstats_entry); } }
/* * Based on load_flags, load ipSystemStatsTable or ipIfStatsTable for ipv4 entries. */ static int _systemstats_v4(netsnmp_container* container, u_int load_flags) { FILE *devin; char line[1024]; netsnmp_systemstats_entry *entry = NULL; int scan_count; char *stats, *start = line; int len; unsigned long long scan_vals[19]; DEBUGMSGTL(("access:systemstats:container:arch", "load v4 (flags %x)\n", load_flags)); netsnmp_assert(container != NULL); /* load function shoulda checked this */ if (load_flags & NETSNMP_ACCESS_SYSTEMSTATS_LOAD_IFTABLE) { /* we do not support ipIfStatsTable for ipv4 */ return 0; } if (!(devin = fopen("/proc/net/snmp", "r"))) { DEBUGMSGTL(("access:systemstats", "Failed to load Systemstats Table (linux1)\n")); NETSNMP_LOGONCE((LOG_ERR, "cannot open /proc/net/snmp ...\n")); return -2; } /* * skip header, but make sure it's the length we expect... */ fgets(line, sizeof(line), devin); len = strlen(line); if (224 != len) { fclose(devin); snmp_log(LOG_ERR, "unexpected header length in /proc/net/snmp." " %d != 224\n", len); return -4; } /* * This file provides the statistics for each systemstats. * Read in each line in turn, isolate the systemstats name * and retrieve (or create) the corresponding data structure. */ start = fgets(line, sizeof(line), devin); fclose(devin); if (start) { len = strlen(line); if (line[len - 1] == '\n') line[len - 1] = '\0'; while (*start && *start == ' ') start++; if ((!*start) || ((stats = strrchr(start, ':')) == NULL)) { snmp_log(LOG_ERR, "systemstats data format error 1, line ==|%s|\n", line); return -4; } DEBUGMSGTL(("access:systemstats", "processing '%s'\n", start)); *stats++ = 0; /* null terminate name */ while (*stats == ' ') /* skip spaces before stats */ stats++; entry = netsnmp_access_systemstats_entry_create(1, 0, "ipSystemStatsTable.ipv4"); if(NULL == entry) { netsnmp_access_systemstats_container_free(container, NETSNMP_ACCESS_SYSTEMSTATS_FREE_NOFLAGS); return -3; } /* * OK - we've now got (or created) the data structure for * this systemstats, 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. */ memset(scan_vals, 0x0, sizeof(scan_vals)); scan_count = sscanf(stats, "%llu %llu %llu %llu %llu %llu %llu %llu %llu %llu" "%llu %llu %llu %llu %llu %llu %llu %llu %llu", &scan_vals[0],&scan_vals[1],&scan_vals[2], &scan_vals[3],&scan_vals[4],&scan_vals[5], &scan_vals[6],&scan_vals[7],&scan_vals[8], &scan_vals[9],&scan_vals[10],&scan_vals[11], &scan_vals[12],&scan_vals[13],&scan_vals[14], &scan_vals[15],&scan_vals[16],&scan_vals[17], &scan_vals[18]); DEBUGMSGTL(("access:systemstats", " read %d values\n", scan_count)); if(scan_count != 19) { snmp_log(LOG_ERR, "error scanning systemstats data (expected %d, got %d)\n", 19, scan_count); netsnmp_access_systemstats_entry_free(entry); return -4; } /* entry->stats. = scan_vals[0]; / * Forwarding */ /* entry->stats. = scan_vals[1]; / * DefaultTTL */ entry->stats.HCInReceives.low = scan_vals[2] & 0xffffffff; entry->stats.HCInReceives.high = scan_vals[2] >> 32; entry->stats.InHdrErrors = scan_vals[3]; entry->stats.InAddrErrors = scan_vals[4]; entry->stats.HCOutForwDatagrams.low = scan_vals[5] & 0xffffffff; entry->stats.HCOutForwDatagrams.high = scan_vals[5] >> 32; entry->stats.InUnknownProtos = scan_vals[6]; entry->stats.InDiscards = scan_vals[7]; entry->stats.HCInDelivers.low = scan_vals[8] & 0xffffffff; entry->stats.HCInDelivers.high = scan_vals[8] >> 32; entry->stats.HCOutRequests.low = scan_vals[9] & 0xffffffff; entry->stats.HCOutRequests.high = scan_vals[9] >> 32; entry->stats.HCOutDiscards.low = scan_vals[10] & 0xffffffff;; entry->stats.HCOutDiscards.high = scan_vals[10] >> 32; entry->stats.HCOutNoRoutes.low = scan_vals[11] & 0xffffffff;; entry->stats.HCOutNoRoutes.high = scan_vals[11] >> 32; /* entry->stats. = scan_vals[12]; / * ReasmTimeout */ entry->stats.ReasmReqds = scan_vals[13]; entry->stats.ReasmOKs = scan_vals[14]; entry->stats.ReasmFails = scan_vals[15]; entry->stats.HCOutFragOKs.low = scan_vals[16] & 0xffffffff;; entry->stats.HCOutFragOKs.high = scan_vals[16] >> 32; entry->stats.HCOutFragFails.low = scan_vals[17] & 0xffffffff;; entry->stats.HCOutFragFails.high = scan_vals[17] >> 32; entry->stats.HCOutFragCreates.low = scan_vals[18] & 0xffffffff;; entry->stats.HCOutFragCreates.high = scan_vals[18] >> 32; entry->stats.columnAvail[IPSYSTEMSTATSTABLE_HCINRECEIVES] = 1; entry->stats.columnAvail[IPSYSTEMSTATSTABLE_INHDRERRORS] = 1; entry->stats.columnAvail[IPSYSTEMSTATSTABLE_INADDRERRORS] = 1; entry->stats.columnAvail[IPSYSTEMSTATSTABLE_HCOUTFORWDATAGRAMS] = 1; entry->stats.columnAvail[IPSYSTEMSTATSTABLE_INUNKNOWNPROTOS] = 1; entry->stats.columnAvail[IPSYSTEMSTATSTABLE_INDISCARDS] = 1; entry->stats.columnAvail[IPSYSTEMSTATSTABLE_HCINDELIVERS] = 1; entry->stats.columnAvail[IPSYSTEMSTATSTABLE_HCOUTREQUESTS] = 1; entry->stats.columnAvail[IPSYSTEMSTATSTABLE_HCOUTDISCARDS] = 1; entry->stats.columnAvail[IPSYSTEMSTATSTABLE_HCOUTNOROUTES] = 1; entry->stats.columnAvail[IPSYSTEMSTATSTABLE_REASMREQDS] = 1; entry->stats.columnAvail[IPSYSTEMSTATSTABLE_REASMOKS] = 1; entry->stats.columnAvail[IPSYSTEMSTATSTABLE_REASMFAILS] = 1; entry->stats.columnAvail[IPSYSTEMSTATSTABLE_HCOUTFRAGOKS] = 1; entry->stats.columnAvail[IPSYSTEMSTATSTABLE_HCOUTFRAGFAILS] = 1; entry->stats.columnAvail[IPSYSTEMSTATSTABLE_HCOUTFRAGCREATES] = 1; entry->stats.columnAvail[IPSYSTEMSTATSTABLE_DISCONTINUITYTIME] = 1; entry->stats.columnAvail[IPSYSTEMSTATSTABLE_REFRESHRATE] = 1; /* * load addtional statistics defined by RFC 4293 * As these are supported linux 2.6.22 or later, it is no problem * if loading them are failed. */ _additional_systemstats_v4(entry, load_flags); /* * add to container */ if (CONTAINER_INSERT(container, entry) < 0) { DEBUGMSGTL(("access:systemstats:container","error with systemstats_entry: insert into container failed.\n")); netsnmp_access_systemstats_entry_free(entry); } } return 0; }
/** * \internal */ static void _entry_release(netsnmp_systemstats_entry * entry, void *context) { netsnmp_access_systemstats_entry_free(entry); }