/** * 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); } }
/** * Update given entry with new data. Calculate new arp_last_updated, if any * field is changed. */ void netsnmp_access_arp_entry_update(netsnmp_arp_entry *entry, netsnmp_arp_entry *new_data) { int modified = 0; if (entry->arp_ipaddress_len != new_data->arp_ipaddress_len || memcmp(entry->arp_ipaddress, new_data->arp_ipaddress, entry->arp_ipaddress_len) != 0 ) { modified = 1; entry->arp_ipaddress_len = new_data->arp_ipaddress_len; memcpy(entry->arp_ipaddress, new_data->arp_ipaddress, sizeof(entry->arp_ipaddress)); } if (entry->arp_physaddress_len != new_data->arp_physaddress_len || memcmp(entry->arp_physaddress, new_data->arp_physaddress, entry->arp_physaddress_len) != 0) { modified = 1; entry->arp_physaddress_len = new_data->arp_physaddress_len; memcpy(entry->arp_physaddress, new_data->arp_physaddress, sizeof(entry->arp_physaddress_len)); } if (entry->arp_state != new_data->arp_state) { modified = 1; entry->arp_state = new_data->arp_state; } if (entry->arp_type != new_data->arp_type) { modified = 1; entry->arp_type = new_data->arp_type; } if (entry->flags != new_data->flags) { modified = 1; entry->flags = new_data->flags; } if (modified) entry->arp_last_updated = netsnmp_get_agent_uptime(); }
struct agent_netsnmp_set_info * save_set_vars(netsnmp_session * ss, netsnmp_pdu *pdu) { struct agent_netsnmp_set_info *ptr; ptr = (struct agent_netsnmp_set_info *) malloc(sizeof(struct agent_netsnmp_set_info)); if (ptr == NULL) return NULL; /* * Save the important information */ ptr->transID = pdu->transid; ptr->sess = ss; ptr->mode = SNMP_MSG_INTERNAL_SET_RESERVE1; ptr->uptime = netsnmp_get_agent_uptime(); ptr->var_list = snmp_clone_varbind(pdu->variables); if (ptr->var_list == NULL) { free(ptr); return NULL; } ptr->next = Sets; Sets = ptr; return ptr; }
static int handle_sysUpTime(netsnmp_mib_handler *handler, netsnmp_handler_registration *reginfo, netsnmp_agent_request_info *reqinfo, netsnmp_request_info *requests) { snmp_set_var_typed_integer(requests->requestvb, ASN_TIMETICKS, netsnmp_get_agent_uptime()); return SNMP_ERR_NOERROR; }
int sctpAssocTable_add_or_update(netsnmp_container *assocTable, sctpAssocTable_entry * entry) { /* * we have full sctpAssocTable entry, update or add it in the container */ sctpAssocTable_entry *old; entry->valid = 1; /* * try to find it in the container */ sctpAssocTable_entry_update_index(entry); old = CONTAINER_FIND(assocTable, entry); if (old != NULL) { /* * update existing entry, don't overwrite the timestamp */ time_t timestamp = old->sctpAssocStartTime; if (timestamp == 0 && entry->sctpAssocStartTime == 0 && entry->sctpAssocState >= SCTPASSOCSTATE_ESTABLISHED) timestamp = netsnmp_get_agent_uptime(); /* set the timestamp if it was not set before and entry reaches the right state */ sctpAssocTable_entry_copy(entry, old); old->sctpAssocStartTime = timestamp; sctpAssocTable_entry_free(entry); } else { /* * the entry is new, add it there */ if (entry->sctpAssocStartTime == 0 && entry->sctpAssocState >= SCTPASSOCSTATE_ESTABLISHED) { entry->sctpAssocStartTime = netsnmp_get_agent_uptime(); } CONTAINER_INSERT(assocTable, entry); } return SNMP_ERR_NOERROR; }
u_char * var_system(struct variable *vp, oid * name, size_t * length, int exact, size_t * var_len, WriteMethod ** write_method) { static u_long ulret; if (header_generic(vp, name, length, exact, var_len, write_method) == MATCH_FAILED) return NULL; switch (vp->magic) { case VERSION_DESCR: *var_len = strlen(version_descr); return (u_char *) version_descr; case VERSIONID: *var_len = sysObjectIDLength * sizeof(sysObjectID[0]); return (u_char *)sysObjectID; case UPTIME: ulret = netsnmp_get_agent_uptime(); return ((u_char *) & ulret); case SYSCONTACT: *var_len = strlen(sysContact); *write_method = writeSystem; return (u_char *) sysContact; case SYSTEMNAME: *var_len = strlen(sysName); *write_method = writeSystem; return (u_char *) sysName; case SYSLOCATION: *var_len = strlen(sysLocation); *write_method = writeSystem; return (u_char *) sysLocation; case SYSSERVICES: #if NETSNMP_NO_DUMMY_VALUES if (!sysServicesConfiged) return NULL; #endif long_return = sysServices; return (u_char *) & long_return; #ifdef USING_MIBII_SYSORTABLE_MODULE case SYSORLASTCHANGE: ulret = netsnmp_timeval_uptime(&sysOR_lastchange); return ((u_char *) & ulret); #endif default: DEBUGMSGTL(("snmpd", "unknown sub-id %d in var_system\n", vp->magic)); } return NULL; }
/** * 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); } } }
/** * add new entry */ static void _add_new_entry(netsnmp_ipaddress_entry *ipaddress_entry, netsnmp_container *container) { ipAddressTable_rowreq_ctx *rowreq_ctx; DEBUGMSGTL(("ipAddressTable:access", "creating new entry\n")); netsnmp_assert(NULL != ipaddress_entry); netsnmp_assert(NULL != container); /* * allocate an row context and set the index(es) */ rowreq_ctx = ipAddressTable_allocate_rowreq_ctx(ipaddress_entry, NULL); if ((NULL != rowreq_ctx) && (MFD_SUCCESS == ipAddressTable_indexes_set(rowreq_ctx, ipaddress_entry->ia_address_len, ipaddress_entry->ia_address, ipaddress_entry->ia_address_len))) { if (CONTAINER_INSERT(container, rowreq_ctx) < 0) { DEBUGMSGTL (("ipAddressTable:access","container insert failed for new entry\n")); ipAddressTable_release_rowreq_ctx(rowreq_ctx); return; } rowreq_ctx->ipAddressLastChanged = rowreq_ctx->ipAddressCreated = netsnmp_get_agent_uptime(); } else { if (NULL != rowreq_ctx) { snmp_log(LOG_ERR, "error setting index while loading " "ipAddressTable cache.\n"); ipAddressTable_release_rowreq_ctx(rowreq_ctx); } else { snmp_log(LOG_ERR, "memory allocation failed while loading " "ipAddressTable cache.\n"); netsnmp_access_ipaddress_entry_free(ipaddress_entry); } return; } /*------------------------------------------------------------------- * handle data that isn't part of the data_access ipaddress structure */ rowreq_ctx->ipAddressRowStatus = ROWSTATUS_ACTIVE; }
/** * check entry for update */ static void _check_entry_for_updates(ipAddressTable_rowreq_ctx * rowreq_ctx, void **magic) { netsnmp_container *ipaddress_container = (netsnmp_container*)magic[0]; netsnmp_container *to_delete = (netsnmp_container*)magic[1]; /* * check for matching entry using secondary index. */ netsnmp_ipaddress_entry *ipaddress_entry = (netsnmp_ipaddress_entry*) CONTAINER_FIND(ipaddress_container, rowreq_ctx->data); if (NULL == ipaddress_entry) { DEBUGMSGTL(("ipAddressTable:access", "removing missing entry\n")); if (NULL == to_delete) { magic[1] = to_delete = netsnmp_container_find("lifo"); if (NULL == to_delete) snmp_log(LOG_ERR, "couldn't create delete container\n"); } if (NULL != to_delete) CONTAINER_INSERT(to_delete, rowreq_ctx); } else { DEBUGMSGTL(("ipAddressTable:access", "updating existing entry\n")); /* * Check for changes & update */ if (netsnmp_access_ipaddress_entry_update(rowreq_ctx->data, ipaddress_entry) > 0) rowreq_ctx->ipAddressLastChanged = netsnmp_get_agent_uptime(); /* * remove entry from ifcontainer */ CONTAINER_REMOVE(ipaddress_container, ipaddress_entry); netsnmp_access_ipaddress_entry_free(ipaddress_entry); } }
/** * add new entry */ static void _add_new(netsnmp_systemstats_entry *ifstats_entry, netsnmp_container *container) { ipIfStatsTable_rowreq_ctx *rowreq_ctx; DEBUGMSGTL(("ipIfStatsTable:access", "creating new entry\n")); netsnmp_assert(NULL != ifstats_entry); netsnmp_assert(NULL != container); /* * allocate an row context and set the index(es) */ rowreq_ctx = ipIfStatsTable_allocate_rowreq_ctx(ifstats_entry, NULL); if ((NULL != rowreq_ctx) && (MFD_SUCCESS == ipIfStatsTable_indexes_set(rowreq_ctx, ifstats_entry->index[0], ifstats_entry->index[1]))) { rowreq_ctx->ipIfStatsRefreshRate = ipis_cache_refresh * 1000; /* milli-seconds */ CONTAINER_INSERT(container, rowreq_ctx); ipIfStatsTable_lastChange_set(netsnmp_get_agent_uptime()); } else { if (NULL != rowreq_ctx) { snmp_log(LOG_ERR, "error setting index while loading " "ipIfStatsTable cache.\n"); ipIfStatsTable_release_rowreq_ctx(rowreq_ctx); } else { snmp_log(LOG_ERR, "memory allocation failed while loading " "ipIfStatsTable cache.\n"); netsnmp_access_systemstats_entry_free(ifstats_entry); } } }
/** * 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(); }
/** * @internal * determine if we want a ifTable row in our container */ void ipv6InterfaceTable_check_entry_for_updates(const ifTable_rowreq_ctx * ift_rrc, netsnmp_interface_entry *entry) { netsnmp_container *c = ipv6InterfaceTable_container_get(); ifTable_rowreq_ctx *ip6if_rrc; int changed = 0; DEBUGMSGTL(("verbose:ipv6InterfaceTable:check_entry_for_updates", "called\n")); /* * do we have a corresponding row? */ ip6if_rrc = CONTAINER_FIND(c, ift_rrc); if (NULL == ip6if_rrc) { /* * no corresponding row. should we have one? */ if ((NULL != entry) && (entry->ns_flags & NETSNMP_INTERFACE_FLAGS_HAS_IPV6)) { /* * yes. */ DEBUGMSGTL(("ipv6InterfaceTable:check_entry_for_updates", "inserted row for index %d\n", entry->index)); CONTAINER_INSERT(c, ift_rrc); changed = 1; } } else { /* * found corresponding row. is it still applicable? */ if ((NULL == entry) || (0 == (entry->ns_flags & NETSNMP_INTERFACE_FLAGS_HAS_IPV6))) { /* * no */ DEBUGMSGTL(("ipv6InterfaceTable:check_entry_for_updates", "removed row for index %d\n", ift_rrc->data.ifentry->index)); CONTAINER_REMOVE(c, ift_rrc); changed = 1; } else { /* * still applicable. anything changed? */ if (/** retransmit */ ((entry-> ns_flags & NETSNMP_INTERFACE_FLAGS_HAS_V6_RETRANSMIT) && (entry->retransmit_v6 != ift_rrc->data.ifentry->retransmit_v6)) || /** reasm */ ((entry-> ns_flags & NETSNMP_INTERFACE_FLAGS_HAS_V6_REASMMAX) && (entry->reasm_max_v6 != ift_rrc->data.ifentry->reasm_max_v6)) || /** reachable time */ ((entry-> ns_flags & NETSNMP_INTERFACE_FLAGS_HAS_V6_REACHABLE) && (entry->reachable_time != ift_rrc->data.ifentry->reachable_time)) || /** if id */ ((entry->ns_flags & NETSNMP_INTERFACE_FLAGS_HAS_V6_IFID) && ((entry->v6_if_id_len != ift_rrc->data.ifentry->v6_if_id_len) || (0 != memcmp(entry->v6_if_id, ift_rrc->data.ifentry->v6_if_id, entry->v6_if_id_len)))) || /** forwarding */ ((entry-> ns_flags & NETSNMP_INTERFACE_FLAGS_HAS_V6_FORWARDING) && (entry->forwarding_v6 != ift_rrc->data.ifentry->forwarding_v6))) { DEBUGMSGTL(("ipv6InterfaceTable:check_entry_for_updates", "row changed for index %d\n", ift_rrc->data.ifentry->index)); changed = 1; } } } /* * if something changed, update table last changed */ if (changed) ipv6InterfaceTable_lastChange_set(netsnmp_get_agent_uptime()); }
/** handles requests for the tlstmCertToTSNTable table */ static int tlstmCertToTSNTable_handler(netsnmp_mib_handler *handler, netsnmp_handler_registration *reginfo, netsnmp_agent_request_info *reqinfo, netsnmp_request_info *requests) { oid tsnm[] = { SNMP_TLS_TM_BASE, 1, 1, 0 }; static const int tsnm_pos = OID_LENGTH(tsnm) - 1; netsnmp_request_info *request = NULL; netsnmp_table_request_info *info; netsnmp_tdata *table; netsnmp_tdata_row *row; certToTSN_entry *entry; int ret = SNMP_ERR_NOERROR; DEBUGMSGTL(("tlstmCertToSN:handler", "Processing request (mode %s (%d))\n", se_find_label_in_slist("agent_mode", reqinfo->mode), reqinfo->mode)); switch (reqinfo->mode) { /** ######################################################### GET ##### * * Read-support (also covers GetNext requests) */ case MODE_GET: for (request = requests; request; request = request->next) { if (request->processed) continue; entry = (certToTSN_entry *) netsnmp_tdata_extract_entry(request); info = netsnmp_extract_table_info(request); netsnmp_assert(entry && info); switch (info->colnum) { case COL_SNMPTLSTMCERTTOTSN_FINGERPRINT: { /* * build SnmpTLSFingerprint */ u_char bin[42], *ptr = bin; size_t len = sizeof(bin); int rc; rc = netsnmp_tls_fingerprint_build(entry->hashType, entry->fingerprint, &ptr, &len, 0); if (SNMPERR_SUCCESS != rc) netsnmp_set_request_error(reqinfo, request, SNMP_ERR_GENERR); else snmp_set_var_typed_value(request->requestvb, ASN_OCTET_STR, bin, len); } break; /* case COL_SNMPTLSTMCERTTOTSN_FINGERPRINT */ case COL_SNMPTLSTMCERTTOTSN_MAPTYPE: tsnm[tsnm_pos] = entry->mapType; snmp_set_var_typed_value(request->requestvb, ASN_OBJECT_ID, tsnm, sizeof(tsnm)); break; /* case COL_SNMPTLSTMCERTTOTSN_MAPTYPE */ case COL_SNMPTLSTMCERTTOTSN_DATA: snmp_set_var_typed_value(request->requestvb, ASN_OCTET_STR, entry->data, entry->data_len); break; /* case COL_SNMPTLSTMCERTTOTSN_DATA */ case COL_SNMPTLSTMCERTTOTSN_STORAGETYPE: snmp_set_var_typed_integer(request->requestvb, ASN_INTEGER, entry->storageType); break; /* case COL_SNMPTLSTMCERTTOTSN_STORAGETYPE */ case COL_SNMPTLSTMCERTTOTSN_ROWSTATUS: snmp_set_var_typed_integer(request->requestvb, ASN_INTEGER, entry->rowStatus); break; /* case COL_SNMPTLSTMCERTTOTSN_ROWSTATUS */ default: netsnmp_set_request_error(reqinfo, request, SNMP_NOSUCHOBJECT); break; } /* switch colnum */ } /* for requests */ break; /* case MODE_GET */ /* * Write-support */ /** #################################################### RESERVE1 ##### * * In RESERVE1 we are just checking basic ASN.1 size/type restrictions. * You probably don't need to change any of this code. Don't change any * of the column values here. Save that for the ACTION phase. * * The next phase is RESERVE2 or FREE. */ case MODE_SET_RESERVE1: for (request = requests; request; request = request->next) { netsnmp_assert(request->processed == 0); entry = (certToTSN_entry *) netsnmp_tdata_extract_entry(request); info = netsnmp_extract_table_info(request); if ((NULL != entry) && (ST_READONLY == entry->storageType)) { ret = SNMP_ERR_NOTWRITABLE; break; } switch (info->colnum) { case COL_SNMPTLSTMCERTTOTSN_FINGERPRINT: ret = netsnmp_check_vb_type_and_max_size (request->requestvb, ASN_OCTET_STR, sizeof(entry->fingerprint)); /** check len/algorithm MIB requirements */ if (ret == SNMP_ERR_NOERROR) ret = netsnmp_cert_check_vb_fingerprint(request->requestvb); break; /* case COL_SNMPTLSTMCERTTOTSN_FINGERPRINT */ case COL_SNMPTLSTMCERTTOTSN_MAPTYPE: ret = netsnmp_check_vb_type_and_max_size (request->requestvb, ASN_OBJECT_ID, SNMPTLSTMCERTTOTSN_MAPTYPE_MAX_SIZE); if (ret == SNMP_ERR_NOERROR) { if (_oid2type(request->requestvb->val.objid, request->requestvb->val_len) > TSNM_tlstmCert_MAX) ret = SNMP_ERR_WRONGVALUE; } break; /* case COL_SNMPTLSTMCERTTOTSN_MAPTYPE */ case COL_SNMPTLSTMCERTTOTSN_DATA: ret = netsnmp_check_vb_type_and_max_size (request->requestvb, ASN_OCTET_STR, sizeof(entry->data)); break; /* case COL_SNMPTLSTMCERTTOTSN_DATA */ case COL_SNMPTLSTMCERTTOTSN_STORAGETYPE: ret = netsnmp_check_vb_storagetype (request->requestvb,(entry ? entry->storageType : ST_NONE)); break; /* case COL_SNMPTLSTMCERTTOTSN_STORAGETYPE */ case COL_SNMPTLSTMCERTTOTSN_ROWSTATUS: ret = netsnmp_check_vb_rowstatus_with_storagetype (request->requestvb, (entry ? entry->rowStatus :RS_NONEXISTENT), (entry ? entry->storageType :ST_NONE)); break; /* case COL_SNMPTLSTMCERTTOTSN_ROWSTATUS */ default: ret = SNMP_ERR_NOTWRITABLE; } /* switch colnum */ if (ret != SNMP_ERR_NOERROR) break; } /* for requests */ break; /* case MODE_SET_RESERVE1 */ /** #################################################### RESERVE2 ##### * * RESERVE2 is for checking additional restrictions from the MIB. * Since these restrictions are often in the description of the object, * mib2c can't generate code. It's possible that you need to add * additional checks here. However, don't change any of the column * values here. Save that for the ACTION phase. * * The next phase is ACTION or FREE. */ case MODE_SET_RESERVE2: for (request = requests; request; request = request->next) { netsnmp_assert(request->processed == 0); entry = (certToTSN_entry *) netsnmp_tdata_extract_entry(request); table = netsnmp_tdata_extract_table(request); info = netsnmp_extract_table_info(request); /* * if no row, create one */ if (!entry) { row = tlstmCertToTSNTable_createEntry (table,*info->indexes->val.integer); if (!row) { ret = SNMP_ERR_RESOURCEUNAVAILABLE; break; } entry = row->data; _allocUndo(entry); if (!entry->undo) { tlstmCertToTSNTable_removeEntry(table, row); row = NULL; ret = SNMP_ERR_RESOURCEUNAVAILABLE; break; } entry->undo->fate = FATE_NEWLY_CREATED; /** associate row with requests */ netsnmp_insert_tdata_row(request, row); } /** allocate undo structure, if needed */ if (!entry->undo) { _allocUndo(entry); if (!entry->undo) { ret = SNMP_ERR_RESOURCEUNAVAILABLE; break; } } /* * save request ptr for column. if we already * have a value, bail. */ if (entry->undo->req[info->colnum]) { DEBUGMSGT(("tlstmCertToSN:reserve2", "multiple sets to col %d in request\n", info->colnum)); if (FATE_NEWLY_CREATED == entry->undo->fate) ret = SNMP_ERR_INCONSISTENTNAME; else ret = SNMP_ERR_INCONSISTENTVALUE; break; } entry->undo->req[info->colnum] = request; if (ret != SNMP_ERR_NOERROR) break; } /* for requests */ if (ret == SNMP_ERR_NOERROR) { /** make sure rowstatus is used to create rows */ for (request = requests; request; request = request->next) { if (request->processed) continue; entry = (certToTSN_entry *) netsnmp_tdata_extract_entry(request); if ((entry->undo->fate != FATE_NEWLY_CREATED) || (entry->undo->req[COL_SNMPTLSTMCERTTOTSN_ROWSTATUS])) continue; ret = SNMP_ERR_INCONSISTENTNAME; break; } /* creation for requests */ } /* no error */ break; /* case MODE_SET_RESERVE2 */ /** ######################################################## FREE ##### * * FREE is for cleaning up after a failed request (during either * RESERVE1 or RESERVE2). So any allocated resources need to be * released. * * This the final phase for this path in the state machine. */ case MODE_SET_FREE: /* * release undo resources * remove any newly created rows */ for (request = requests; request; request = request->next) { table = netsnmp_tdata_extract_table(request); row = netsnmp_tdata_extract_row(request); entry = (certToTSN_entry *) netsnmp_tdata_extract_entry(request); if (!entry || !entry->undo) continue; /** disassociate row with requests */ netsnmp_remove_tdata_row(request, row); if (FATE_NEWLY_CREATED == entry->undo->fate) tlstmCertToTSNTable_removeEntry(table, row); else _freeUndo(entry); } break; /* case MODE_SET_FREE */ /** ###################################################### ACTION ##### * * In the ACTION phase, we perform any sets that can be undone. * (Save anything that can't be undone for the COMMIT phase.) * * After individual columns have been done, you should check that the * row as a whole is consistent. * * The next phase is UNDO or COMMIT. */ case MODE_SET_ACTION: for (request = requests; request; request = request->next) { entry = (certToTSN_entry *) netsnmp_tdata_extract_entry(request); info = netsnmp_extract_table_info(request); /** reserve2 should enforce this */ netsnmp_assert(request == entry->undo->req[info->colnum]); /* * for each col, save old value and the set new value */ switch (info->colnum) { case COL_SNMPTLSTMCERTTOTSN_FINGERPRINT: { u_char *tmp = (u_char*)entry->fingerprint; u_int size = sizeof(entry->fingerprint); netsnmp_variable_list *vb = request->requestvb; memcpy(entry->undo->fingerprint, entry->fingerprint, sizeof(entry->fingerprint)); entry->undo->fingerprint_len = entry->fingerprint_len; entry->undo->hashType = entry->hashType; memset(entry->fingerprint, 0, sizeof(entry->fingerprint)); (void)netsnmp_tls_fingerprint_parse(vb->val.string, vb->val_len, (char**)&tmp, &size, 0, &entry->hashType); entry->fingerprint_len = size; if (0 == entry->fingerprint_len) ret = SNMP_ERR_GENERR; } break; /* case COL_SNMPTLSTMCERTTOTSN_FINGERPRINT */ case COL_SNMPTLSTMCERTTOTSN_MAPTYPE: entry->undo->mapType = entry->mapType; entry->mapType = _oid2type(request->requestvb->val.objid, request->requestvb->val_len); break; /* case COL_SNMPTLSTMCERTTOTSN_MAPTYPE */ case COL_SNMPTLSTMCERTTOTSN_DATA: memcpy(entry->undo->data, entry->data, sizeof(entry->data)); entry->undo->data_len = entry->data_len; memset(entry->data, 0, sizeof(entry->data)); memcpy(entry->data, request->requestvb->val.string, request->requestvb->val_len); entry->data_len = request->requestvb->val_len; break; /* case COL_SNMPTLSTMCERTTOTSN_DATA */ case COL_SNMPTLSTMCERTTOTSN_STORAGETYPE: entry->undo->storageType = entry->storageType; entry->storageType = *request->requestvb->val.integer; break; /* case COL_SNMPTLSTMCERTTOTSN_STORAGETYPE */ case COL_SNMPTLSTMCERTTOTSN_ROWSTATUS: entry->undo->rowStatus = entry->rowStatus; entry->rowStatus = *request->requestvb->val.integer; break; /* case COL_SNMPTLSTMCERTTOTSN_ROWSTATUS */ } /* switch colnum */ } /* set values for requests */ if (ret != SNMP_ERR_NOERROR) break; /* skip consistency if we've already got error */ /* * All columns now have their final values set. check the * internal consistency of each row. */ for (request = requests; request; request = request->next) { entry = (certToTSN_entry *) netsnmp_tdata_extract_entry(request); info = netsnmp_extract_table_info(request); if (entry->undo->is_consistent != -1) continue; /* already checked */ /** assume consistency */ entry->undo->is_consistent = 1; /* * per mib, can't have empty fingerprint and must * have data if indicated by map type. */ if (0 == entry->fingerprint_len) { DEBUGMSGTL(("tlstmCertToTSNTable:inconsistent", "fingerprint must not be empty\n")); entry->undo->is_consistent = 0; } else if ((TSNM_tlstmCertSpecified == entry->mapType) && (0 == entry->data_len)) { DEBUGMSGTL(("tlstmCertToTSNTable:inconsistent", "must specify Data for CertSpecified identity\n")); entry->undo->is_consistent = 0; } if ((RS_IS_ACTIVE(entry->rowStatus)) && ((!entry->undo->req[COL_SNMPTLSTMCERTTOTSN_ROWSTATUS]) || (RS_IS_ACTIVE(entry->undo->rowStatus)))) { /* * per mib, can't modify these while row active */ char _cols[3] = { COL_SNMPTLSTMCERTTOTSN_FINGERPRINT, COL_SNMPTLSTMCERTTOTSN_MAPTYPE, COL_SNMPTLSTMCERTTOTSN_DATA }; int i; for (i=0; i < 3; ++i ) { if (!entry->undo->req[i]) continue; DEBUGMSGTL(("tlstmCertToTSNTable:inconsistent", "can't modify row %d while active\n", _cols[i])); entry->undo->is_consistent = 0; ret = SNMP_ERR_NOTWRITABLE; request= entry->undo->req[i]; break; } } else if (RS_IS_GOING_ACTIVE(entry->rowStatus)) { /* * if going active, inconsistency is fatal */ if (!entry->undo->is_consistent) { netsnmp_assert(entry->undo->req[COL_SNMPTLSTMCERTTOTSN_ROWSTATUS]); if (FATE_NEWLY_CREATED == entry->undo->fate) ret = SNMP_ERR_INCONSISTENTNAME; else ret = SNMP_ERR_INCONSISTENTVALUE; request = entry->undo->req[COL_SNMPTLSTMCERTTOTSN_ROWSTATUS]; } } else if (RS_DESTROY == entry->rowStatus) { /* * can't destroy active row */ if (RS_IS_ACTIVE(entry->undo->rowStatus)) { DEBUGMSGTL(("tlstmCertToTSNTable:inconsistent", "can't destroy active row\n")); netsnmp_assert(entry->undo->req[COL_SNMPTLSTMCERTTOTSN_ROWSTATUS]); ret = SNMP_ERR_INCONSISTENTVALUE; request = entry->undo->req[COL_SNMPTLSTMCERTTOTSN_ROWSTATUS]; } } if (ret != SNMP_ERR_NOERROR) break; } /* consistency for requests */ break; /* case MODE_SET_ACTION */ /** ######################################################## UNDO ##### * * UNDO is for cleaning up any failed requests that went through the * ACTION phase. * * This the final phase for this path in the state machine. */ case MODE_SET_UNDO: for (request = requests; request; request = request->next) { row = netsnmp_tdata_extract_row(request); entry = (certToTSN_entry *) netsnmp_tdata_extract_entry(request); info = netsnmp_extract_table_info(request); /* * skip newly created rows, as we're going to delete * them below anyways */ if (FATE_NEWLY_CREATED == entry->undo->fate) continue; /* * restore values */ switch (info->colnum) { case COL_SNMPTLSTMCERTTOTSN_FINGERPRINT: memcpy(entry->fingerprint, entry->undo->fingerprint, sizeof(entry->fingerprint)); entry->fingerprint_len = entry->undo->fingerprint_len; entry->hashType = entry->undo->hashType; break; /* case COL_SNMPTLSTMCERTTOTSN_FINGERPRINT */ case COL_SNMPTLSTMCERTTOTSN_MAPTYPE: entry->mapType = entry->undo->mapType; break; /* case COL_SNMPTLSTMCERTTOTSN_MAPTYPE */ case COL_SNMPTLSTMCERTTOTSN_DATA: memcpy(entry->data, entry->undo->data, sizeof(entry->data)); entry->data_len = entry->undo->data_len; break; /* case COL_SNMPTLSTMCERTTOTSN_DATA */ case COL_SNMPTLSTMCERTTOTSN_STORAGETYPE: entry->storageType = entry->undo->storageType; break; /* case COL_SNMPTLSTMCERTTOTSN_STORAGETYPE */ case COL_SNMPTLSTMCERTTOTSN_ROWSTATUS: entry->rowStatus = entry->undo->rowStatus; break; /* case COL_SNMPTLSTMCERTTOTSN_ROWSTATUS */ } /* switch colnum */ } /* for requests */ /* * release undo data * or remove any newly created rows */ for (request = requests; request; request = request->next) { table = netsnmp_tdata_extract_table(request); row = netsnmp_tdata_extract_row(request); entry = (certToTSN_entry *) netsnmp_tdata_extract_entry(request); if (!entry || !entry->undo) continue; /** disassociate row with requests */ netsnmp_remove_tdata_row(request, row); if (FATE_NEWLY_CREATED == entry->undo->fate) tlstmCertToTSNTable_removeEntry(table, row); else _freeUndo(entry); } /* for requests */ break; /* case MODE_SET_UNDO */ /** ###################################################### COMMIT ##### * * COMMIT is the final success state, when all changes are finalized. * There is not recovery state should something faile here. * * This the final phase for this path in the state machine. */ case MODE_SET_COMMIT: for (request = requests; request; request = request->next) { row = netsnmp_tdata_extract_row(request); table = netsnmp_tdata_extract_table(request); info = netsnmp_extract_table_info(request); entry = (certToTSN_entry *) netsnmp_tdata_extract_entry(request); if ((RS_NOTREADY == entry->rowStatus) && entry->undo->is_consistent) entry->rowStatus = RS_NOTINSERVICE; else if ((RS_NOTINSERVICE == entry->rowStatus) && (0 == entry->undo->is_consistent)) entry->rowStatus = RS_NOTREADY; /** release undo data for requests with no rowstatus */ if (entry->undo && !entry->undo->req[COL_SNMPTLSTMCERTTOTSN_ROWSTATUS]) { _freeUndo(entry); if ((0 == entry->map_flags) && (entry->rowStatus == RS_ACTIVE)) _cert_map_add(entry); else if ((0 != entry->map_flags) && (entry->rowStatus == RS_DESTROY)) _cert_map_remove(entry); } switch (info->colnum) { case COL_SNMPTLSTMCERTTOTSN_ROWSTATUS: switch (entry->rowStatus) { case RS_CREATEANDGO: /** Fall-through */ case RS_ACTIVE: netsnmp_assert(entry->undo->is_consistent); entry->rowStatus = RS_ACTIVE; if (0 == entry->map_flags) _cert_map_add(entry); break; case RS_CREATEANDWAIT: /** Fall-through */ case RS_NOTINSERVICE: /** simply set status based on consistency */ if (entry->undo->is_consistent) entry->rowStatus = RS_NOTINSERVICE; else entry->rowStatus = RS_NOTREADY; if (0 != entry->map_flags) _cert_map_remove(entry); break; case RS_DESTROY: /** remove from cert map */ if (0 != entry->map_flags) _cert_map_remove(entry); /** disassociate row with requests */ netsnmp_remove_tdata_row(request, row); tlstmCertToTSNTable_removeEntry(table, row); row = NULL; entry = NULL; } /** release undo data */ _freeUndo(entry); break; /* case COL_SNMPTLSTMCERTTOTSN_ROWSTATUS */ case COL_SNMPTLSTMCERTTOTSN_STORAGETYPE: if (RS_ACTIVE == entry->rowStatus) _cert_map_tweak_storage(entry); break; /* case COL_SNMPTLSTMCERTTOTSN_STORAGETYPE */ case COL_SNMPTLSTMCERTTOTSN_FINGERPRINT: case COL_SNMPTLSTMCERTTOTSN_MAPTYPE: case COL_SNMPTLSTMCERTTOTSN_DATA: break; } /* switch colnum */ } /* for requests */ /** update last changed */ _last_changed = netsnmp_get_agent_uptime(); /** set up to save persistent store */ snmp_store_needed(NULL); break; /* case MODE_SET_COMMIT */ } /* switch (reqinfo->mode) */ if (ret != SNMP_ERR_NOERROR) netsnmp_set_request_error(reqinfo, request, ret); return SNMP_ERR_NOERROR; }
int handle_master_agentx_packet(int operation, netsnmp_session * session, int reqid, netsnmp_pdu *pdu, void *magic) { netsnmp_agent_session *asp; if (operation == NETSNMP_CALLBACK_OP_DISCONNECT) { DEBUGMSGTL(("agentx/master", "transport disconnect on session %8p\n", session)); /* * Shut this session down gracefully. */ close_agentx_session(session, -1); return 1; } else if (operation == NETSNMP_CALLBACK_OP_CONNECT) { DEBUGMSGTL(("agentx/master", "transport connect on session %8p\n", session)); return 1; } else if (operation != NETSNMP_CALLBACK_OP_RECEIVED_MESSAGE) { DEBUGMSGTL(("agentx/master", "unexpected callback op %d\n", operation)); return 1; } /* * Okay, it's a NETSNMP_CALLBACK_OP_RECEIVED_MESSAGE op. */ if (magic) { asp = (netsnmp_agent_session *) magic; } else { asp = init_agent_snmp_session(session, pdu); } DEBUGMSGTL(("agentx/master", "handle pdu (req=0x%lx,trans=0x%lx,sess=0x%lx)\n", (unsigned long)pdu->reqid, (unsigned long)pdu->transid, (unsigned long)pdu->sessid)); switch (pdu->command) { case AGENTX_MSG_OPEN: asp->pdu->sessid = open_agentx_session(session, pdu); if (asp->pdu->sessid == -1) asp->status = session->s_snmp_errno; break; case AGENTX_MSG_CLOSE: asp->status = close_agentx_session(session, pdu->sessid); break; case AGENTX_MSG_REGISTER: asp->status = register_agentx_list(session, pdu); break; case AGENTX_MSG_UNREGISTER: asp->status = unregister_agentx_list(session, pdu); break; case AGENTX_MSG_INDEX_ALLOCATE: asp->status = allocate_idx_list(session, asp->pdu); if (asp->status != AGENTX_ERR_NOERROR) { snmp_free_pdu(asp->pdu); asp->pdu = snmp_clone_pdu(pdu); } break; case AGENTX_MSG_INDEX_DEALLOCATE: asp->status = release_idx_list(session, pdu); break; case AGENTX_MSG_ADD_AGENT_CAPS: asp->status = add_agent_caps_list(session, pdu); break; case AGENTX_MSG_REMOVE_AGENT_CAPS: asp->status = remove_agent_caps_list(session, pdu); break; case AGENTX_MSG_NOTIFY: asp->status = agentx_notify(session, pdu); break; case AGENTX_MSG_PING: asp->status = agentx_ping_response(session, pdu); break; /* * TODO: Other admin packets */ case AGENTX_MSG_GET: case AGENTX_MSG_GETNEXT: case AGENTX_MSG_GETBULK: case AGENTX_MSG_TESTSET: case AGENTX_MSG_COMMITSET: case AGENTX_MSG_UNDOSET: case AGENTX_MSG_CLEANUPSET: case AGENTX_MSG_RESPONSE: /* * Shouldn't be handled here */ break; default: asp->status = AGENTX_ERR_PARSE_FAILED; break; } asp->pdu->time = netsnmp_get_agent_uptime(); asp->pdu->command = AGENTX_MSG_RESPONSE; asp->pdu->errstat = asp->status; DEBUGMSGTL(("agentx/master", "send response, stat %d (req=0x%lx,trans=" "0x%lx,sess=0x%lx)\n", asp->status, (unsigned long)pdu->reqid, (unsigned long)pdu->transid, (unsigned long)pdu->sessid)); if (!snmp_send(asp->session, asp->pdu)) { char *eb = NULL; int pe, pse; snmp_error(asp->session, &pe, &pse, &eb); snmp_free_pdu(asp->pdu); DEBUGMSGTL(("agentx/master", "FAILED %d %d %s\n", pe, pse, eb)); free(eb); } asp->pdu = NULL; free_agent_snmp_session(asp); return 1; }
void send_enterprise_trap_vars(int trap, int specific, oid * enterprise, int enterprise_length, netsnmp_variable_list * vars) { netsnmp_variable_list uptime_var, snmptrap_var, enterprise_var; netsnmp_variable_list *v2_vars, *last_var = NULL; netsnmp_pdu *template_pdu; u_long uptime; in_addr_t *pdu_in_addr_t; struct trap_sink *sink; #ifdef BRCM_SNMP_MIB_SUPPORT oid temp_oid[MAX_OID_LEN]; #endif /* * Initialise SNMPv2 required variables */ uptime = netsnmp_get_agent_uptime(); memset(&uptime_var, 0, sizeof(netsnmp_variable_list)); snmp_set_var_objid(&uptime_var, sysuptime_oid, OID_LENGTH(sysuptime_oid)); snmp_set_var_value(&uptime_var, (u_char *) & uptime, sizeof(uptime)); uptime_var.type = ASN_TIMETICKS; uptime_var.next_variable = &snmptrap_var; memset(&snmptrap_var, 0, sizeof(netsnmp_variable_list)); snmp_set_var_objid(&snmptrap_var, snmptrap_oid, OID_LENGTH(snmptrap_oid)); /* * value set later .... */ snmptrap_var.type = ASN_OBJECT_ID; if (vars) snmptrap_var.next_variable = vars; else snmptrap_var.next_variable = &enterprise_var; /* * find end of provided varbind list, * ready to append the enterprise info if necessary */ last_var = vars; while (last_var && last_var->next_variable) last_var = last_var->next_variable; memset(&enterprise_var, 0, sizeof(netsnmp_variable_list)); snmp_set_var_objid(&enterprise_var, snmptrapenterprise_oid, OID_LENGTH(snmptrapenterprise_oid)); snmp_set_var_value(&enterprise_var, (u_char *) enterprise, enterprise_length * sizeof(oid)); enterprise_var.type = ASN_OBJECT_ID; enterprise_var.next_variable = NULL; v2_vars = &uptime_var; /* * Create a template PDU, ready for sending */ template_pdu = snmp_pdu_create(SNMP_MSG_TRAP); if (template_pdu == NULL) { /* * Free memory if value stored dynamically */ snmp_set_var_value(&enterprise_var, NULL, 0); return; } template_pdu->trap_type = trap; template_pdu->specific_type = specific; if (snmp_clone_mem((void **) &template_pdu->enterprise, enterprise, enterprise_length * sizeof(oid))) { snmp_free_pdu(template_pdu); snmp_set_var_value(&enterprise_var, NULL, 0); return; } template_pdu->enterprise_length = enterprise_length; template_pdu->flags |= UCD_MSG_FLAG_FORCE_PDU_COPY; pdu_in_addr_t = (in_addr_t *) template_pdu->agent_addr; *pdu_in_addr_t = get_myaddr(); template_pdu->time = uptime; /* * Now use the parameters to determine * which v2 variables are needed, * and what values they should take. */ switch (trap) { case -1: /* * SNMPv2 only * Check to see whether the variables provided * are sufficient for SNMPv2 notifications */ if (vars && netsnmp_oid_equals(vars->name, vars->name_length, sysuptime_oid, OID_LENGTH(sysuptime_oid)) == 0) v2_vars = vars; else if (vars && netsnmp_oid_equals(vars->name, vars->name_length, snmptrap_oid, OID_LENGTH(snmptrap_oid)) == 0) uptime_var.next_variable = vars; else { /* * Hmmm... we don't seem to have a value - oops! */ snmptrap_var.next_variable = vars; } last_var = NULL; /* Don't need enterprise info */ convert_v2_to_v1(vars, template_pdu); break; /* * "Standard" SNMPv1 traps */ case SNMP_TRAP_COLDSTART: snmp_set_var_value(&snmptrap_var, (u_char *) cold_start_oid, sizeof(cold_start_oid)); break; case SNMP_TRAP_WARMSTART: snmp_set_var_value(&snmptrap_var, (u_char *) warm_start_oid, sizeof(warm_start_oid)); break; case SNMP_TRAP_LINKDOWN: snmp_set_var_value(&snmptrap_var, (u_char *) link_down_oid, sizeof(link_down_oid)); break; case SNMP_TRAP_LINKUP: snmp_set_var_value(&snmptrap_var, (u_char *) link_up_oid, sizeof(link_up_oid)); break; case SNMP_TRAP_AUTHFAIL: if (snmp_enableauthentraps == SNMP_AUTHENTICATED_TRAPS_DISABLED) { snmp_free_pdu(template_pdu); snmp_set_var_value(&enterprise_var, NULL, 0); return; } snmp_set_var_value(&snmptrap_var, (u_char *) auth_fail_oid, sizeof(auth_fail_oid)); break; case SNMP_TRAP_EGPNEIGHBORLOSS: snmp_set_var_value(&snmptrap_var, (u_char *) egp_xxx_oid, sizeof(egp_xxx_oid)); break; #ifdef BRCM_SNMP_MIB_SUPPORT case SNMP_TRAP_ENTERPRISESPECIFIC: memcpy(temp_oid, (char *) enterprise, (enterprise_length) * sizeof(oid)); temp_oid[enterprise_length] = 0; temp_oid[enterprise_length + 1] = specific; snmp_set_var_value(&snmptrap_var, (u_char *) temp_oid, (enterprise_length + 2) * sizeof(oid)); snmptrap_var.next_variable = vars; last_var = NULL; /* Don't need version info */ break; #endif /* BRCM_SNMP_MIB_SUPPORT */ } /* * Now loop through the list of trap sinks, * sending an appropriately formatted PDU to each */ for (sink = sinks; sink; sink = sink->next) { if (sink->version == SNMP_VERSION_1 && trap == -1) continue; /* Skip v1 sinks for v2 only traps */ template_pdu->command = sink->pdutype; if (sink->version != SNMP_VERSION_1) { template_pdu->variables = v2_vars; if (last_var) last_var->next_variable = &enterprise_var; } else template_pdu->variables = vars; send_trap_to_sess(sink->sesp, template_pdu); if (sink->version != SNMP_VERSION_1 && last_var) last_var->next_variable = NULL; } /* * send stuff to registered callbacks */ /* * v2 traps/informs */ template_pdu->variables = v2_vars; if (last_var) last_var->next_variable = &enterprise_var; snmp_call_callbacks(SNMP_CALLBACK_APPLICATION, SNMPD_CALLBACK_SEND_TRAP2, template_pdu); if (last_var) last_var->next_variable = NULL; /* * v1 traps */ template_pdu->command = SNMP_MSG_TRAP; template_pdu->variables = vars; snmp_call_callbacks(SNMP_CALLBACK_APPLICATION, SNMPD_CALLBACK_SEND_TRAP1, template_pdu); /* * Free memory if values stored dynamically */ snmp_set_var_value(&enterprise_var, NULL, 0); snmp_set_var_value(&snmptrap_var, NULL, 0); /* * Ensure we don't free anything we shouldn't */ if (last_var) last_var->next_variable = NULL; template_pdu->variables = NULL; snmp_free_pdu(template_pdu); }
/** * This function allows you to make a distinction between generic * traps from different classes of equipment. For example, you may want * to handle a SNMP_TRAP_LINKDOWN trap for a particular device in a * different manner to a generic system SNMP_TRAP_LINKDOWN trap. * * * @param trap is the generic trap type. The trap types are: * - SNMP_TRAP_COLDSTART: * cold start * - SNMP_TRAP_WARMSTART: * warm start * - SNMP_TRAP_LINKDOWN: * link down * - SNMP_TRAP_LINKUP: * link up * - SNMP_TRAP_AUTHFAIL: * authentication failure * - SNMP_TRAP_EGPNEIGHBORLOSS: * egp neighbor loss * - SNMP_TRAP_ENTERPRISESPECIFIC: * enterprise specific * * @param specific is the specific trap value. * * @param enterprise is an enterprise oid in which you want to send specifc * traps from. * * @param enterprise_length is the length of the enterprise oid, use macro, * OID_LENGTH, to compute length. * * @param vars is used to supply list of variable bindings to form an SNMPv2 * trap. * * @param context currently unused * * @param flags currently unused * * @return void * * @see send_easy_trap * @see send_v2trap */ int netsnmp_send_traps(int trap, int specific, oid * enterprise, int enterprise_length, netsnmp_variable_list * vars, char * context, int flags) { netsnmp_pdu *template_v1pdu; netsnmp_pdu *template_v2pdu; netsnmp_variable_list *vblist = NULL; netsnmp_variable_list *trap_vb; netsnmp_variable_list *var; in_addr_t *pdu_in_addr_t; u_long uptime; struct trap_sink *sink; DEBUGMSGTL(( "trap", "send_trap %d %d ", trap, specific)); DEBUGMSGOID(("trap", enterprise, enterprise_length)); DEBUGMSG(( "trap", "\n")); if (vars) { vblist = snmp_clone_varbind( vars ); if (!vblist) { snmp_log(LOG_WARNING, "send_trap: failed to clone varbind list\n"); return -1; } } if ( trap == -1 ) { /* * Construct the SNMPv2-style notification PDU */ if (!vblist) { snmp_log(LOG_WARNING, "send_trap: called with NULL v2 information\n"); return -1; } template_v2pdu = snmp_pdu_create(SNMP_MSG_TRAP2); if (!template_v2pdu) { snmp_log(LOG_WARNING, "send_trap: failed to construct v2 template PDU\n"); snmp_free_varbind(vblist); return -1; } /* * Check the varbind list we've been given. * If it starts with a 'sysUptime.0' varbind, then use that. * Otherwise, prepend a suitable 'sysUptime.0' varbind. */ if (!snmp_oid_compare( vblist->name, vblist->name_length, sysuptime_oid, sysuptime_oid_len )) { template_v2pdu->variables = vblist; trap_vb = vblist->next_variable; } else { uptime = netsnmp_get_agent_uptime(); var = NULL; snmp_varlist_add_variable( &var, sysuptime_oid, sysuptime_oid_len, ASN_TIMETICKS, (u_char*)&uptime, sizeof(uptime)); if (!var) { snmp_log(LOG_WARNING, "send_trap: failed to insert sysUptime varbind\n"); snmp_free_pdu(template_v2pdu); snmp_free_varbind(vblist); return -1; } template_v2pdu->variables = var; var->next_variable = vblist; trap_vb = vblist; } /* * 'trap_vb' should point to the snmpTrapOID.0 varbind, * identifying the requested trap. If not then bomb out. * If it's a 'standard' trap, then we need to append an * snmpEnterprise varbind (if there isn't already one). */ if (!trap_vb || snmp_oid_compare(trap_vb->name, trap_vb->name_length, snmptrap_oid, snmptrap_oid_len)) { snmp_log(LOG_WARNING, "send_trap: no v2 trapOID varbind provided\n"); snmp_free_pdu(template_v2pdu); return -1; } if (!snmp_oid_compare(vblist->val.objid, OID_LENGTH(trap_prefix), trap_prefix, OID_LENGTH(trap_prefix))) { var = find_varbind_in_list( template_v2pdu->variables, snmptrapenterprise_oid, snmptrapenterprise_oid_len); if (!var && !snmp_varlist_add_variable( &(template_v2pdu->variables), snmptrapenterprise_oid, snmptrapenterprise_oid_len, ASN_OBJECT_ID, (char*)enterprise, enterprise_length*sizeof(oid))) { snmp_log(LOG_WARNING, "send_trap: failed to add snmpEnterprise to v2 trap\n"); snmp_free_pdu(template_v2pdu); return -1; } } /* * If everything's OK, convert the v2 template into an SNMPv1 trap PDU. */ template_v1pdu = convert_v2pdu_to_v1( template_v2pdu ); if (!template_v1pdu) { snmp_log(LOG_WARNING, "send_trap: failed to convert v2->v1 template PDU\n"); } } else { /* * Construct the SNMPv1 trap PDU.... */ template_v1pdu = snmp_pdu_create(SNMP_MSG_TRAP); if (!template_v1pdu) { snmp_log(LOG_WARNING, "send_trap: failed to construct v1 template PDU\n"); snmp_free_varbind(vblist); return -1; } template_v1pdu->trap_type = trap; template_v1pdu->specific_type = specific; template_v1pdu->time = netsnmp_get_agent_uptime(); if (snmp_clone_mem((void **) &template_v1pdu->enterprise, enterprise, enterprise_length * sizeof(oid))) { snmp_log(LOG_WARNING, "send_trap: failed to set v1 enterprise OID\n"); snmp_free_varbind(vblist); snmp_free_pdu(template_v1pdu); return -1; } template_v1pdu->enterprise_length = enterprise_length; template_v1pdu->flags |= UCD_MSG_FLAG_FORCE_PDU_COPY; template_v1pdu->variables = vblist; /* * ... and convert it into an SNMPv2-style notification PDU. */ template_v2pdu = convert_v1pdu_to_v2( template_v1pdu ); if (!template_v2pdu) { snmp_log(LOG_WARNING, "send_trap: failed to convert v1->v2 template PDU\n"); } } /* * Check whether we're ignoring authFail traps */ if (template_v1pdu) { if (template_v1pdu->trap_type == SNMP_TRAP_AUTHFAIL && snmp_enableauthentraps == SNMP_AUTHENTICATED_TRAPS_DISABLED) { snmp_free_pdu(template_v1pdu); snmp_free_pdu(template_v2pdu); return 0; } /* * Ensure that the v1 trap PDU includes the local IP address */ pdu_in_addr_t = (in_addr_t *) template_v1pdu->agent_addr; *pdu_in_addr_t = get_myaddr(); } /* * Now loop through the list of trap sinks * and call the trap callback routines, * providing an appropriately formatted PDU in each case */ for (sink = sinks; sink; sink = sink->next) { #ifndef NETSNMP_DISABLE_SNMPV1 if (sink->version == SNMP_VERSION_1) { if (template_v1pdu) { send_trap_to_sess(sink->sesp, template_v1pdu); } } else { #endif if (template_v2pdu) { template_v2pdu->command = sink->pdutype; send_trap_to_sess(sink->sesp, template_v2pdu); } #ifndef NETSNMP_DISABLE_SNMPV1 } #endif } if (template_v1pdu) snmp_call_callbacks(SNMP_CALLBACK_APPLICATION, SNMPD_CALLBACK_SEND_TRAP1, template_v1pdu); if (template_v2pdu) snmp_call_callbacks(SNMP_CALLBACK_APPLICATION, SNMPD_CALLBACK_SEND_TRAP2, template_v2pdu); snmp_free_pdu(template_v1pdu); snmp_free_pdu(template_v2pdu); return 0; }
/** * @internal * determine if we want a ifTable row in our container */ void ipv4InterfaceTable_check_entry_for_updates(const ifTable_rowreq_ctx * ift_rrc, netsnmp_interface_entry *entry) { netsnmp_container *c = ipv4InterfaceTable_container_get(); ifTable_rowreq_ctx *ip4if_rrc; int changed = 0; DEBUGMSGTL(("verbose:ipv4InterfaceTable:check_entry_for_updates", "called\n")); /* * do we have a corresponding row? */ ip4if_rrc = CONTAINER_FIND(c, ift_rrc); if (NULL == ip4if_rrc) { /* * no corresponding row. should we have one? */ if ((NULL != entry) && (entry->ns_flags & NETSNMP_INTERFACE_FLAGS_HAS_IPV4)) { /* * yes. */ DEBUGMSGTL(("ipv4InterfaceTable:check_entry_for_updates", "inserted row for %d\n", entry->index)); CONTAINER_INSERT(c, ift_rrc); changed = 1; } } else { /* * found corresponding row. is it still applicable? */ if ((NULL == entry) || (0 == (entry->ns_flags & NETSNMP_INTERFACE_FLAGS_HAS_IPV4))) { /* * no */ DEBUGMSGTL(("ipv4InterfaceTable:check_entry_for_updates", "removed row for %d\n", ift_rrc->data.ifentry->index)); CONTAINER_REMOVE(c, ift_rrc); changed = 1; } else { /* * still applicable. anything changed? */ if ((entry->retransmit_v4 != ift_rrc->data.ifentry->retransmit_v4) || (entry->reasm_max_v4 != ift_rrc->data.ifentry->reasm_max_v4)) { DEBUGMSGTL(("ipv4InterfaceTable:check_entry_for_updates", "row changed for %d\n", ift_rrc->data.ifentry->index)); changed = 1; } } } /* * if something changed, update table last changed */ if (changed) ipv4InterfaceTable_lastChange_set(netsnmp_get_agent_uptime()); }
/** Initializes the sysORTable module */ void init_sysORTable(void) { const oid sysORLastChange_oid[] = { 1, 3, 6, 1, 2, 1, 1, 8 }; const oid sysORTable_oid[] = { 1, 3, 6, 1, 2, 1, 1, 9 }; sysORTable_table_info = SNMP_MALLOC_TYPEDEF(netsnmp_table_registration_info); table = netsnmp_container_find("sysORTable:table_container"); if (sysORTable_table_info == NULL || table == NULL) { SNMP_FREE(sysORTable_table_info); CONTAINER_FREE(table); return; } table->container_name = strdup("sysORTable"); netsnmp_table_helper_add_indexes(sysORTable_table_info, ASN_INTEGER, /** index: sysORIndex */ 0); sysORTable_table_info->min_column = COLUMN_SYSORID; sysORTable_table_info->max_column = COLUMN_SYSORUPTIME; sysORLastChange_reg = netsnmp_create_handler_registration( "mibII/sysORLastChange", NULL, sysORLastChange_oid, OID_LENGTH(sysORLastChange_oid), HANDLER_CAN_RONLY); netsnmp_init_watcher_info( &sysORLastChange_winfo, &sysORLastChange, sizeof(u_long), ASN_TIMETICKS, WATCHER_FIXED_SIZE); netsnmp_register_watched_scalar(sysORLastChange_reg, &sysORLastChange_winfo); sysORTable_reg = netsnmp_create_handler_registration( "mibII/sysORTable", sysORTable_handler, sysORTable_oid, OID_LENGTH(sysORTable_oid), HANDLER_CAN_RONLY); netsnmp_container_table_register(sysORTable_reg, sysORTable_table_info, table, TABLE_CONTAINER_KEY_NETSNMP_INDEX); sysORLastChange = netsnmp_get_agent_uptime(); /* * Initialise the contents of the table here */ netsnmp_sysORTable_foreach(®ister_foreach, NULL); /* * Register callbacks */ snmp_register_callback(SNMP_CALLBACK_APPLICATION, SNMPD_CALLBACK_REG_SYSOR, register_cb, NULL); snmp_register_callback(SNMP_CALLBACK_APPLICATION, SNMPD_CALLBACK_UNREG_SYSOR, unregister_cb, NULL); #ifdef USING_MIBII_SYSTEM_MIB_MODULE if (++system_module_count == 3) REGISTER_SYSOR_TABLE(system_module_oid, system_module_oid_len, "The MIB module for SNMPv2 entities"); #endif }