/** * add new entry */ static void _add_new_interface(netsnmp_interface_entry *ifentry, netsnmp_container *container) { ifTable_rowreq_ctx *rowreq_ctx; DEBUGMSGTL(("ifTable:access", "creating new entry\n")); /* * allocate an row context and set the index(es), then add it to * the container and set ifTableLastChanged. */ rowreq_ctx = ifTable_allocate_rowreq_ctx(ifentry); if ((NULL != rowreq_ctx) && (MFD_SUCCESS == ifTable_indexes_set(rowreq_ctx, ifentry->index))) { CONTAINER_INSERT(container, rowreq_ctx); /* * fix this when we hit an arch that reports its own last change */ netsnmp_assert(0 == (ifentry->ns_flags & NETSNMP_INTERFACE_FLAGS_HAS_LASTCHANGE)); if (0 == _first_load) { rowreq_ctx->data.ifLastChange = netsnmp_get_agent_uptime(); ifTable_lastChange_set(rowreq_ctx->data.ifLastChange); } #ifdef USING_IP_MIB_IPV4INTERFACETABLE_IPV4INTERFACETABLE_MODULE /* * give ipv4If table a crack at the entry */ ipv4InterfaceTable_check_entry_for_updates(rowreq_ctx, ifentry); #endif #ifdef USING_IP_MIB_IPV6INTERFACETABLE_IPV6INTERFACETABLE_MODULE /* * give ipv6If table a crack at the entry */ ipv6InterfaceTable_check_entry_for_updates(rowreq_ctx, ifentry); #endif } else { if (rowreq_ctx) { snmp_log(LOG_ERR, "error setting index while loading " "ifTable cache.\n"); ifTable_release_rowreq_ctx(rowreq_ctx); } else { snmp_log(LOG_ERR, "memory allocation failed while loading " "ifTable cache.\n"); netsnmp_access_interface_entry_free(ifentry); } } }
/* * @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 {
/** * check entry for update * */ static void _check_interface_entry_for_updates(ifTable_rowreq_ctx * rowreq_ctx, netsnmp_container *ifcontainer) { char oper_changed = 0; /* * check for matching entry. We can do this directly, since * both containers use the same index. */ netsnmp_interface_entry *ifentry = CONTAINER_FIND(ifcontainer, rowreq_ctx); #ifdef USING_IP_MIB_IPV4INTERFACETABLE_IPV4INTERFACETABLE_MODULE /* * give ipv4If table a crack at the entry */ ipv4InterfaceTable_check_entry_for_updates(rowreq_ctx, ifentry); #endif #ifdef USING_IP_MIB_IPV6INTERFACETABLE_IPV6INTERFACETABLE_MODULE /* * give ipv6If table a crack at the entry */ ipv6InterfaceTable_check_entry_for_updates(rowreq_ctx, ifentry); #endif if (NULL == ifentry) { /* * if this is the first time we detected that this interface is * missing, set admin/oper status down, and set last change. * * yyy-rks: when, if ever, would we consider an entry * deleted (and thus need to update ifTableLastChanged)? */ if (!rowreq_ctx->known_missing) { DEBUGMSGTL(("ifTable:access", "updating missing entry\n")); rowreq_ctx->known_missing = 1; rowreq_ctx->data.ifAdminStatus = IFADMINSTATUS_DOWN; if ((!(rowreq_ctx->data.ifentry->ns_flags & NETSNMP_INTERFACE_FLAGS_HAS_LASTCHANGE)) && (rowreq_ctx->data.ifOperStatus != IFOPERSTATUS_DOWN)) oper_changed = 1; rowreq_ctx->data.ifOperStatus = IFOPERSTATUS_DOWN; } } else { DEBUGMSGTL(("ifTable:access", "updating existing entry\n")); #ifdef USING_IF_MIB_IFXTABLE_IFXTABLE_MODULE { int rc = strcmp(rowreq_ctx->data.ifName, ifentry->name); netsnmp_assert(rc == 0); } #endif /* * if the interface was missing, but came back, clear the * missing flag and set the discontinuity time. (if an os keeps * persistent counters, tough cookies. We'll cross that * bridge if we come to it). */ if (rowreq_ctx->known_missing) { rowreq_ctx->known_missing = 0; #ifdef USING_IF_MIB_IFXTABLE_IFXTABLE_MODULE rowreq_ctx->data.ifCounterDiscontinuityTime = netsnmp_get_agent_uptime(); #endif } /* * Check for changes, then update */ if ((!(ifentry->ns_flags & NETSNMP_INTERFACE_FLAGS_HAS_LASTCHANGE)) && (rowreq_ctx->data.ifOperStatus != ifentry->oper_status)) oper_changed = 1; netsnmp_access_interface_entry_copy(rowreq_ctx->data.ifentry, ifentry); /* * remove entry from temporary ifcontainer */ CONTAINER_REMOVE(ifcontainer, ifentry); netsnmp_access_interface_entry_free(ifentry); } /* * if ifOperStatus changed, update ifLastChange */ if (oper_changed) rowreq_ctx->data.ifLastChange = netsnmp_get_agent_uptime(); }
static void _access_interface_entry_release(netsnmp_interface_entry * entry, void *context) { netsnmp_access_interface_entry_free(entry); }