netsnmp_pdu* convert_v2pdu_to_v1( netsnmp_pdu* template_v2pdu ) { netsnmp_pdu *template_v1pdu; netsnmp_variable_list *first_vb, *vblist; netsnmp_variable_list *var; size_t len; /* * Make a copy of the v2 Trap PDU * before starting to convert this * into a v1 Trap PDU. */ template_v1pdu = snmp_clone_pdu( template_v2pdu); if (!template_v1pdu) { snmp_log(LOG_WARNING, "send_trap: failed to copy v1 template PDU\n"); return NULL; } template_v1pdu->command = SNMP_MSG_TRAP; first_vb = template_v1pdu->variables; vblist = template_v1pdu->variables; /* * The first varbind should be the system uptime. */ if (!vblist || snmp_oid_compare(vblist->name, vblist->name_length, sysuptime_oid, sysuptime_oid_len)) { snmp_log(LOG_WARNING, "send_trap: no v2 sysUptime varbind to set from\n"); snmp_free_pdu(template_v1pdu); return NULL; } template_v1pdu->time = *vblist->val.integer; vblist = vblist->next_variable; /* * The second varbind should be the snmpTrapOID. */ if (!vblist || snmp_oid_compare(vblist->name, vblist->name_length, snmptrap_oid, snmptrap_oid_len)) { snmp_log(LOG_WARNING, "send_trap: no v2 trapOID varbind to set from\n"); snmp_free_pdu(template_v1pdu); return NULL; } /* * Check the v2 varbind list for any varbinds * that are not valid in an SNMPv1 trap. * This basically means Counter64 values. * * RFC 2089 said to omit such varbinds from the list. * RFC 2576/3584 say to drop the trap completely. */ for (var = vblist->next_variable; var; var = var->next_variable) { if ( var->type == ASN_COUNTER64 ) { snmp_log(LOG_WARNING, "send_trap: v1 traps can't carry Counter64 varbinds\n"); snmp_free_pdu(template_v1pdu); return NULL; } } /* * Set the generic & specific trap types, * and the enterprise field from the v2 varbind list. * If there's an agentIPAddress varbind, set the agent_addr too */ if (!snmp_oid_compare(vblist->val.objid, OID_LENGTH(trap_prefix), trap_prefix, OID_LENGTH(trap_prefix))) { /* * For 'standard' traps, extract the generic trap type * from the snmpTrapOID value, and take the enterprise * value from the 'snmpEnterprise' varbind. */ template_v1pdu->trap_type = vblist->val.objid[OID_LENGTH(trap_prefix)] - 1; template_v1pdu->specific_type = 0; var = find_varbind_in_list( vblist, snmptrapenterprise_oid, snmptrapenterprise_oid_len); if (var) { memdup((u_char**)&template_v1pdu->enterprise, (const u_char*)var->val.objid, var->val_len); template_v1pdu->enterprise_length = var->val_len/sizeof(oid); } else { template_v1pdu->enterprise = NULL; template_v1pdu->enterprise_length = 0; /* XXX ??? */ } } else { /* * For enterprise-specific traps, split the snmpTrapOID value * into enterprise and specific trap */ len = vblist->val_len / sizeof(oid); if ( len <= 2 ) { snmp_log(LOG_WARNING, "send_trap: v2 trapOID too short (%d)\n", len); snmp_free_pdu(template_v1pdu); return NULL; } template_v1pdu->trap_type = SNMP_TRAP_ENTERPRISESPECIFIC; template_v1pdu->specific_type = vblist->val.objid[len - 1]; len--; if (vblist->val.objid[len-1] == 0) len--; SNMP_FREE(template_v1pdu->enterprise); memdup((u_char**)&template_v1pdu->enterprise, (u_char *)vblist->val.objid, len*sizeof(oid)); template_v1pdu->enterprise_length = len; } var = find_varbind_in_list( vblist, agentaddr_oid, agentaddr_oid_len); if (var) { memcpy(template_v1pdu->agent_addr, var->val.string, 4); } /* * The remainder of the v2 varbind list is kept * as the v2 varbind list. Update the PDU and * free the two redundant varbinds. */ template_v1pdu->variables = vblist->next_variable; vblist->next_variable = NULL; snmp_free_varbind( first_vb ); return template_v1pdu; }
void expObject_getData( struct expExpression *expr, struct expObject *obj ) { netsnmp_variable_list *var; int res; /* * Retrieve and store the basic object value(s) * (keeping the previous values if necessary) */ if (obj->flags & EXP_OBJ_FLAG_PREFIX ) { /* * If this is the expExpressionPrefix object, then * we already have the necessary list of values. * There's no need to retrieve it again. * This also takes care of releasing the prefix list * once the results are no longer needed. */ var = expr->pvars; } else { if (!(obj->flags & EXP_OBJ_FLAG_OWILD )) /* * Set up the request 'list' for an * exact (non-wildcarded) object. */ var = _expObject_buildList( obj->expObjectID, obj->expObjectID_len, 0, NULL ); else { if ( !expr->expPrefix_len ) { /* * You can't really have wildcarded objects unless * the expression as a whole is wildcarded too. */ return; } /* * Set up the request list for a wildcarded object */ var = _expObject_buildList( obj->expObjectID, obj->expObjectID_len, expr->expPrefix_len, expr->pvars ); } res = netsnmp_query_get( var, expr->session ); } if ( obj->expObjectSampleType != EXPSAMPLETYPE_ABSOLUTE ) { /* * For Delta (and Changed) samples, we need * to store the previous value as well. */ if ( obj->old_vars ) snmp_free_varbind( obj->old_vars ); obj->old_vars = obj->vars; } else snmp_free_varbind( obj->vars ); obj->vars = var; /* * For Delta samples, there may be a discontinuity marker * (or set of wildcarded markers) to be sampled as well. * This necessarily requires storing the previous marker(s). */ if (( obj->expObjectSampleType != EXPSAMPLETYPE_ABSOLUTE ) && ( obj->flags & EXP_OBJ_FLAG_DDISC )) { if ( obj->flags & EXP_OBJ_FLAG_DWILD ) var = _expObject_buildList( obj->expObjDeltaD, obj->expObjDeltaD_len, expr->expPrefix_len, expr->pvars ); else var = _expObject_buildList( obj->expObjDeltaD, obj->expObjDeltaD_len, 0, NULL ); res = netsnmp_query_get( var, expr->session ); if ( obj->old_dvars ) snmp_free_varbind( obj->old_dvars ); obj->old_dvars = obj->dvars; obj->dvars = var; } /* * If there's an expObjectConditional value specified * (or set of wildcarded values) then add these to the * ever-growing collection of retrieved values. */ if ( obj->expObjCond_len ) { if ( obj->flags & EXP_OBJ_FLAG_CWILD ) var = _expObject_buildList( obj->expObjCond, obj->expObjCond_len, expr->expPrefix_len, expr->pvars ); else var = _expObject_buildList( obj->expObjCond, obj->expObjCond_len, 0, NULL ); /* * XXX - Check when to use GetNext * * (The MIB description seems bogus?) */ res = netsnmp_query_get( var, expr->session ); if ( obj->cvars ) snmp_free_varbind( obj->cvars ); obj->cvars = var; } }
/** * Adds a row of data to a given table (stored in proper lexographical order). * * returns SNMPERR_SUCCESS on successful addition. * or SNMPERR_GENERR on failure (E.G., indexes already existed) */ int netsnmp_table_data_add_row(netsnmp_table_data *table, netsnmp_table_row *row) { int rc, dup = 0; netsnmp_table_row *nextrow = NULL, *prevrow; if (!row || !table) return SNMPERR_GENERR; if (row->indexes) netsnmp_table_data_generate_index_oid(row); /* * we don't store the index info as it * takes up memory. */ if (!table->store_indexes) { snmp_free_varbind(row->indexes); row->indexes = NULL; } if (!row->index_oid) { snmp_log(LOG_ERR, "illegal data attempted to be added to table %s (no index)\n", table->name); return SNMPERR_GENERR; } /* * check for simple append */ if ((prevrow = table->last_row) != NULL) { rc = snmp_oid_compare(prevrow->index_oid, prevrow->index_oid_len, row->index_oid, row->index_oid_len); if (0 == rc) dup = 1; } else rc = 1; /* * if no last row, or newrow < last row, search the table and * insert it into the table in the proper oid-lexographical order */ if (rc > 0) { for (nextrow = table->first_row, prevrow = NULL; nextrow != NULL; prevrow = nextrow, nextrow = nextrow->next) { if (NULL == nextrow->index_oid) { DEBUGMSGT(("table_data_add_data", "row doesn't have index!\n")); /** xxx-rks: remove invalid row? */ continue; } rc = snmp_oid_compare(nextrow->index_oid, nextrow->index_oid_len, row->index_oid, row->index_oid_len); if(rc > 0) break; if (0 == rc) { dup = 1; break; } } } if (dup) { /* * exact match. Duplicate entries illegal */ snmp_log(LOG_WARNING, "duplicate table data attempted to be entered. row exists\n"); return SNMPERR_GENERR; } /* * ok, we have the location of where it should go */ /* * (after prevrow, and before nextrow) */ row->next = nextrow; row->prev = prevrow; if (row->next) row->next->prev = row; if (row->prev) row->prev->next = row; if (NULL == row->prev) /* it's the (new) first row */ table->first_row = row; if (NULL == row->next) /* it's the last row */ table->last_row = row; DEBUGMSGTL(("table_data_add_data", "added something...\n")); return SNMPERR_SUCCESS; }
static void event_send_trap(CRTL_ENTRY_T * evptr, u_char is_rising, u_int alarm_index, u_int value, u_int the_threshold, oid * alarmed_var, size_t alarmed_var_length, u_int sample_type) { static oid objid_snmptrap[] = { 1, 3, 6, 1, 6, 3, 1, 1, 4, 1, 0 }; static oid rmon1_trap_oid[] = { 1, 3, 6, 1, 2, 1, 16, 0, 0 }; static oid alarm_index_oid[] = { 1, 3, 6, 1, 2, 1, 16, 3, 1, 1, 1, 0 }; static oid alarmed_var_oid[] = { 1, 3, 6, 1, 2, 1, 16, 3, 1, 1, 3, 0 }; static oid sample_type_oid[] = { 1, 3, 6, 1, 2, 1, 16, 3, 1, 1, 4, 0 }; static oid value_oid[] = { 1, 3, 6, 1, 2, 1, 16, 3, 1, 1, 5, 0 }; static oid threshold_oid[] = { 1, 3, 6, 1, 2, 1, 16, 3, 1, 1, 7, 0 }; /* rising case */ netsnmp_variable_list *var_list = NULL; /* * set the last 'oid' : risingAlarm or fallingAlarm */ if (is_rising) { rmon1_trap_oid[8] = 1; threshold_oid[10] = 7; } else { rmon1_trap_oid[8] = 2; threshold_oid[10] = 8; } alarm_index_oid[11] = alarm_index; alarmed_var_oid[11] = alarm_index; sample_type_oid[11] = alarm_index; value_oid[11] = alarm_index; threshold_oid[11] = alarm_index; /* * build the var list */ snmp_varlist_add_variable(&var_list, objid_snmptrap, OID_LENGTH(objid_snmptrap), ASN_OBJECT_ID, (u_char *) rmon1_trap_oid, sizeof(rmon1_trap_oid)); snmp_varlist_add_variable(&var_list, alarm_index_oid, OID_LENGTH(alarm_index_oid), ASN_INTEGER, (u_char *) &alarm_index, sizeof(u_int)); snmp_varlist_add_variable(&var_list, alarmed_var_oid, OID_LENGTH(alarmed_var_oid), ASN_OBJECT_ID, (u_char *) alarmed_var, alarmed_var_length * sizeof(oid)); snmp_varlist_add_variable(&var_list, sample_type_oid, OID_LENGTH(sample_type_oid), ASN_INTEGER, (u_char *) &sample_type, sizeof(u_int)); snmp_varlist_add_variable(&var_list, value_oid, OID_LENGTH(value_oid), ASN_INTEGER, (u_char *) &value, sizeof(u_int)); snmp_varlist_add_variable(&var_list, threshold_oid, OID_LENGTH(threshold_oid), ASN_INTEGER, (u_char *) &the_threshold, sizeof(u_int)); send_v2trap(var_list); ag_trace("rmon trap has been sent"); snmp_free_varbind(var_list); }
/** here we send a SNMP v2 trap (which can be sent through snmpv3 and * snmpv1 as well) and send it out. */ void send_example_notification(unsigned int clientreg, void *clientarg) { /* * define the OID for the notification we're going to send * NET-SNMP-EXAMPLES-MIB::netSnmpExampleNotification */ oid notification_oid[] = { 1, 3, 6, 1, 4, 1, 8072, 2, 3, 1 }; size_t notification_oid_len = OID_LENGTH(notification_oid); /* * In the notification, we have to assign our notification OID to * the snmpTrapOID.0 object. Here is it's definition. */ oid objid_snmptrap[] = { 1, 3, 6, 1, 6, 3, 1, 1, 4, 1, 0 }; size_t objid_snmptrap_len = OID_LENGTH(objid_snmptrap); /* * here is where we store the variables to be sent in the trap */ netsnmp_variable_list *notification_vars = NULL; DEBUGMSGTL(("example_notification", "defining the trap\n")); /* * add in the trap definition object */ snmp_varlist_add_variable(¬ification_vars, /* * the snmpTrapOID.0 variable */ objid_snmptrap, objid_snmptrap_len, /* * value type is an OID */ ASN_OBJECT_ID, /* * value contents is our notification OID */ (u_char *) notification_oid, /* * size in bytes = oid length * sizeof(oid) */ notification_oid_len * sizeof(oid)); /* * if we wanted to insert additional objects, we'd do it here */ /* * send the trap out. This will send it to all registered * receivers (see the "SETTING UP TRAP AND/OR INFORM DESTINATIONS" * section of the snmpd.conf manual page. */ DEBUGMSGTL(("example_notification", "sending the trap\n")); send_v2trap(notification_vars); /* * free the created notification variable list */ DEBUGMSGTL(("example_notification", "cleaning up\n")); snmp_free_varbind(notification_vars); }
/*ARGSUSED*/ static void send_trap(fmd_hdl_t *hdl, const char *uuid, const char *code, const char *url) { static const oid sunFmProblemTrap_oid[] = { SUNFMPROBLEMTRAP_OID }; const size_t sunFmProblemTrap_len = OID_LENGTH(sunFmProblemTrap_oid); static const oid sunFmProblemUUID_oid[] = { SUNFMPROBLEMTABLE_OID, 1, SUNFMPROBLEM_COL_UUID }; static const oid sunFmProblemCode_oid[] = { SUNFMPROBLEMTABLE_OID, 1, SUNFMPROBLEM_COL_CODE }; static const oid sunFmProblemURL_oid[] = { SUNFMPROBLEMTABLE_OID, 1, SUNFMPROBLEM_COL_URL }; const size_t sunFmProblem_base_len = OID_LENGTH(sunFmProblemUUID_oid); size_t uuid_len = strlen(uuid); size_t var_len = sunFmProblem_base_len + 1 + uuid_len; oid var_name[MAX_OID_LEN]; int i; netsnmp_variable_list *notification_vars = NULL; /* * The format of our trap varbinds' oids is as follows: * * +-----------------------+---+--------+----------+------+ * | SUNFMPROBLEMTABLE_OID | 1 | column | uuid_len | uuid | * +-----------------------+---+--------+----------+------+ * \---- index ----/ * * A common mistake here is to send the trap with varbinds that * do not contain the index. All the indices are the same, and * all the oids are the same length, so the only thing we need to * do for each varbind is set the table and column parts of the * variable name. */ if (var_len > MAX_OID_LEN) { snmp_stats.bad_uuid.fmds_value.ui64++; return; } var_name[sunFmProblem_base_len] = (oid)uuid_len; for (i = 0; i < uuid_len; i++) var_name[i + sunFmProblem_base_len + 1] = (oid)uuid[i]; /* * Ordinarily, we would need to add the OID of the trap itself * to the head of the variable list; this is required by SNMP v2. * However, send_enterprise_trap_vars does this for us as a part * of converting between v1 and v2 traps, so we skip directly to * the objects we're sending. */ (void) memcpy(var_name, sunFmProblemUUID_oid, sunFmProblem_base_len * sizeof (oid)); (void) snmp_varlist_add_variable(¬ification_vars, var_name, var_len, ASN_OCTET_STR, (uchar_t *)uuid, strlen(uuid)); (void) memcpy(var_name, sunFmProblemCode_oid, sunFmProblem_base_len * sizeof (oid)); (void) snmp_varlist_add_variable(¬ification_vars, var_name, var_len, ASN_OCTET_STR, (uchar_t *)code, strlen(code)); (void) memcpy(var_name, sunFmProblemURL_oid, sunFmProblem_base_len * sizeof (oid)); (void) snmp_varlist_add_variable(¬ification_vars, var_name, var_len, ASN_OCTET_STR, (uchar_t *)url, strlen(url)); /* * This function is capable of sending both v1 and v2/v3 traps. * Which is sent to a specific destination is determined by the * configuration file(s). */ send_enterprise_trap_vars(SNMP_TRAP_ENTERPRISESPECIFIC, sunFmProblemTrap_oid[sunFmProblemTrap_len - 1], (oid *)sunFmProblemTrap_oid, sunFmProblemTrap_len - 2, notification_vars); snmp_free_varbind(notification_vars); }
/* * Unlike the equivalent IPv4 statistics display routine, * the IPv6 version must walk the columns of a table * and total the statistics for each column (rather * than simply retrieving individual scalar values) */ void _dump_v6stats( const char *name, oid *oid_buf, size_t buf_len, struct stat_table *stable ) { netsnmp_variable_list *var, *vp; struct stat_table *sp; long *stats; oid stat; unsigned int max_stat = 0; int active = 0; var = NULL; for (sp=stable; sp->entry; sp++) { oid_buf[buf_len-1] = sp->entry; if (sp->entry > max_stat) max_stat = sp->entry; snmp_varlist_add_variable( &var, oid_buf, buf_len, ASN_NULL, NULL, 0); } oid_buf[buf_len-1] = stable[0].entry; stats = (long *)calloc(max_stat+1, sizeof(long)); /* * Walk the specified column(s), and total the individual statistics */ while (1) { if (netsnmp_query_getnext( var, ss ) != SNMP_ERR_NOERROR) break; if ( snmp_oid_compare( oid_buf, buf_len, var->name, buf_len) != 0 ) break; /* End of Table */ for ( vp=var; vp; vp=vp->next_variable ) { stat = vp->name[ buf_len-1 ]; stats[stat] += *vp->val.integer; } active=1; } if (!active) { free( stats ); snmp_free_varbind( var ); return; /* No statistics to display */ } /* * Display the results */ printf("%s:\n", name); for (sp=stable; sp->entry; sp++) { /* * If '-Cs' was specified twice, * then only display non-zero stats. */ if ( stats[sp->entry] > 0 || sflag == 1 ) { putchar('\t'); printf(sp->description, stats[sp->entry], plural(stats[sp->entry])); putchar('\n'); } } free( stats ); snmp_free_varbind( var ); }
/* * Populates up to FIVE different rows: * - RDR * - Sensor * - Inventory * - Control * - Watchdog */ int populate_rdr (SaHpiRptEntryT * rpt_entry, oid * rpt_oid, size_t rpt_oid_len, oid * resource_oid, size_t resource_oid_len) { SaErrorT err; SaHpiEntryIdT current_rdr; SaHpiEntryIdT next_rdr; SaHpiRdrT rdr_entry; SaHpiSessionIdT session_id; long backup_count = rdr_count; int rc = AGENT_ERR_NOERROR; oid rdr_oid[RDR_INDEX_NR]; oid full_oid[MAX_OID_LEN]; oid child_oid[MAX_OID_LEN]; size_t child_oid_len; oid column[2]; int column_len = 2; int full_oid_len; unsigned long child_id = 0xDEADBEEF; netsnmp_index rdr_index; saHpiRdrTable_context *rdr_context; oid *trap_oid; trap_vars *trap = NULL; size_t trap_len; netsnmp_variable_list *trap_var; DEBUGMSGTL ((AGENT, "\n\t--- populate_rdr: Entry.\n")); if ((rc = getSaHpiSession (&session_id)) == AGENT_ERR_NOERROR) { rdr_index.len = RDR_INDEX_NR; next_rdr = SAHPI_FIRST_ENTRY; do { current_rdr = next_rdr; memset (&rdr_entry, 0x00, sizeof (SaHpiRdrT)); err = saHpiRdrGet (session_id, rpt_entry->ResourceId, current_rdr, &next_rdr, &rdr_entry); if (err == SA_OK) { rdr_mutex = AGENT_TRUE; // Look at the MIB to find out what the indexs are rdr_oid[0] = rpt_entry->DomainId; rdr_oid[1] = rpt_entry->ResourceId; rdr_oid[2] = rdr_entry.RecordId; // The type is +1 from the SAF HPI SA spec rdr_oid[3] = rdr_entry.RdrType+1; rdr_index.oids = (oid *) & rdr_oid; if (backup_count == 0) { rdr_context = saHpiRdrTable_create_row (&rdr_index); rdr_new_entry_count++; } else { // See if it exists. rdr_context = NULL; rdr_context = CONTAINER_FIND (cb.container, &rdr_index); // If we don't find it - we create it. if (!rdr_context) { // New entry. Add it rdr_context = saHpiRdrTable_create_row (&rdr_index); rdr_new_entry_count++; } if (!rdr_context) { snmp_log (LOG_ERR, "Not enough memory for a RDR row!"); return AGENT_ERR_INTERNAL_ERROR; } } column[0] = 1; column[1] = COLUMN_SAHPIRDRRESOURCEID; build_full_oid (saHpiRdrTable_oid, saHpiRdrTable_oid_len, column, column_len, &rdr_index, full_oid, MAX_OID_LEN, &full_oid_len); child_oid_len = 0; if (rdr_entry.RdrType == SAHPI_SENSOR_RDR) { child_id = rdr_entry.RdrTypeUnion.SensorRec.Num; DEBUGMSGTL ((AGENT, "Calling populate_sensor; RPT: %d, RDR: %d, SensorRec.Num: %d\n", rpt_entry->ResourceId, rdr_entry.RecordId, child_id)); rc = populate_sensor (rdr_entry.RecordId, &rdr_entry.RdrTypeUnion.SensorRec, rpt_entry, full_oid, full_oid_len, child_oid, &child_oid_len); DEBUGMSGTL ((AGENT, "Called populate_sensor(); rc: %d\n", rc)); } if (rdr_entry.RdrType == SAHPI_CTRL_RDR) { child_id = rdr_entry.RdrTypeUnion.CtrlRec.Num; DEBUGMSGTL ((AGENT, "Calling populate_control; RPT: %d, RDR: %d, CtrlRec.Num: %d\n", rpt_entry->ResourceId, rdr_entry.RecordId, child_id)); rc = populate_control (rdr_entry.RecordId,&rdr_entry.RdrTypeUnion.CtrlRec, rpt_entry, full_oid, full_oid_len, child_oid, &child_oid_len); DEBUGMSGTL ((AGENT, "Called populate_control(); rc: %d\n", rc)); } if (rdr_entry.RdrType == SAHPI_INVENTORY_RDR) { child_id = rdr_entry.RdrTypeUnion.InventoryRec.EirId; DEBUGMSGTL ((AGENT, "Calling populate_inventory; RPT: %d, RDR: %d, InventoryRec.EirId: %d\n", rpt_entry->ResourceId, rdr_entry.RecordId, child_id)); rc = populate_inventory (rdr_entry.RecordId,&rdr_entry.RdrTypeUnion.InventoryRec, rpt_entry, full_oid, full_oid_len, child_oid, &child_oid_len); DEBUGMSGTL ((AGENT, "Called populate_inventory(); rc: %d\n", rc)); } if (rdr_entry.RdrType == SAHPI_WATCHDOG_RDR) { child_id = rdr_entry.RdrTypeUnion.WatchdogRec.WatchdogNum; DEBUGMSGTL ((AGENT, "Calling populate_watchdog; RPT: %d, RDR: %d, CtrlRec.Num: %d\n", rpt_entry->ResourceId, rdr_entry.RecordId, child_id)); rc = populate_watchdog (rdr_entry.RecordId,&rdr_entry.RdrTypeUnion.WatchdogRec, rpt_entry, full_oid, full_oid_len, child_oid, &child_oid_len); DEBUGMSGTL ((AGENT, "Called populate_watchdog(); rc: %d\n", rc)); } // Mark this ctx as touched, or cleaned rdr_context->dirty_bit = AGENT_FALSE; // By this stage, rdr_context surely has something in it. // '*_modify_context' does a checksum check to see if // the record needs to be altered, and if so populates with // information from RDR and the OIDs passed. if (saHpiRdrTable_modify_context (rpt_entry, &rdr_entry, rdr_context, rpt_oid, rpt_oid_len, child_oid, child_oid_len, child_id, &trap, &trap_len, &trap_oid) == AGENT_NEW_ENTRY) { CONTAINER_INSERT (cb.container, rdr_context); rdr_count = CONTAINER_SIZE (cb.container); if (send_traps == AGENT_TRUE) { if (trap != NULL) { trap_var = build_notification (&rdr_index, trap, trap_len, saHpiResourceDataRecordNotification_oid, OID_LENGTH (saHpiResourceDataRecordNotification_oid), saHpiRdrTable_oid, saHpiRdrTable_oid_len, rpt_entry->DomainId, rpt_oid, rpt_oid_len, rpt_entry-> ResourceId, resource_oid, resource_oid_len); if (trap_var != NULL) { // Add some more (entryCount, and entryUpdate) snmp_varlist_add_variable (&trap_var, saHpiRdrCount_oid, OID_LENGTH (saHpiRdrCount_oid), ASN_COUNTER, (u_char *) & rdr_count, sizeof (rdr_count)); DEBUGMSGTL ((AGENT, "Sending RDR TRAP/EVENT\n")); send_v2trap (trap_var); snmp_free_varbind (trap_var); } else { snmp_log (LOG_WARNING, "Could not build a RDR TRAP/EVENT message.\n"); rc = AGENT_ERR_BUILD_TRAP; } } } } } else { // Bail out. // This can happend if there are no entries for that Resource rc = AGENT_ERR_OPERATION; break; } } while (next_rdr != SAHPI_LAST_ENTRY); } DEBUGMSGTL ((AGENT, "\n\t--- populate_rdr. Exit\n")); return rc; }
int handle_subagent_set_response(int op, netsnmp_session * session, int reqid, netsnmp_pdu *pdu, void *magic) { netsnmp_session *retsess; struct agent_netsnmp_set_info *asi; int result; if (op != NETSNMP_CALLBACK_OP_RECEIVED_MESSAGE || magic == NULL) { return 1; } DEBUGMSGTL(("agentx/subagent", "handling agentx subagent set response (mode=%d,req=0x%x," "trans=0x%x,sess=0x%x)\n", (unsigned)pdu->command, (unsigned)pdu->reqid, (unsigned)pdu->transid, (unsigned)pdu->sessid)); pdu = snmp_clone_pdu(pdu); asi = (struct agent_netsnmp_set_info *) magic; retsess = asi->sess; asi->errstat = pdu->errstat; if (asi->mode == SNMP_MSG_INTERNAL_SET_RESERVE1) { /* * reloop for RESERVE2 mode, an internal only agent mode */ /* * XXX: check exception statuses of reserve1 first */ if (!pdu->errstat) { asi->mode = pdu->command = SNMP_MSG_INTERNAL_SET_RESERVE2; result = snmp_async_send(agentx_callback_sess, pdu, handle_subagent_set_response, asi); if (result == 0) { snmp_free_pdu( pdu ); } DEBUGMSGTL(("agentx/subagent", " going from RESERVE1 -> RESERVE2\n")); return 1; } } else { if (asi->mode == SNMP_MSG_INTERNAL_SET_FREE || asi->mode == SNMP_MSG_INTERNAL_SET_UNDO || asi->mode == SNMP_MSG_INTERNAL_SET_COMMIT) { free_set_vars(retsess, pdu); } snmp_free_varbind(pdu->variables); pdu->variables = NULL; /* the variables were added by us */ } netsnmp_assert(retsess != NULL); pdu->command = AGENTX_MSG_RESPONSE; pdu->version = retsess->version; if (!snmp_send(retsess, pdu)) { snmp_free_pdu(pdu); } DEBUGMSGTL(("agentx/subagent", " FINISHED\n")); return 1; }
int _mteEvent_fire_notify (struct mteEvent *entry, /* The event to fire */ struct mteTrigger *trigger, /* Trigger that fired */ oid * suffix, size_t sfx_len) /* Matching instance */ { netsnmp_variable_list *var, *v2; extern const oid snmptrap_oid[]; extern const size_t snmptrap_oid_len; netsnmp_session *s; /* * The Event-MIB specification says that objects from the * mteEventTable should come after those from the trigger, * but things actually work better if these come first. * Allow the agent to be configured either way. */ int strictOrdering = netsnmp_ds_get_boolean (NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_STRICT_DISMAN); var = (netsnmp_variable_list *) SNMP_MALLOC_TYPEDEF (netsnmp_variable_list); if (!var) return -1; /* * Set the basic notification OID... */ memset (var, 0, sizeof (netsnmp_variable_list)); snmp_set_var_objid (var, snmptrap_oid, snmptrap_oid_len); snmp_set_var_typed_value (var, ASN_OBJECT_ID, (u_char *) entry->mteNotification, entry->mteNotification_len * sizeof (oid)); /* * ... then add the specified objects from the Objects Table. * * Strictly speaking, the objects from the EventTable are meant * to be listed last (after the various trigger objects). * But logically things actually work better if the event objects * are placed first. So this code handles things either way :-) */ if (!strictOrdering) { DEBUGMSGTL (("disman:event:fire", "Adding event objects (first)\n")); if (strcmp (entry->mteNotifyOwner, "_snmpd") != 0) mteObjects_vblist (var, entry->mteNotifyOwner, entry->mteNotifyObjects, suffix, sfx_len); } DEBUGMSGTL (("disman:event:fire", "Adding trigger objects (general)\n")); mteObjects_vblist (var, trigger->mteTriggerOOwner, trigger->mteTriggerObjects, suffix, sfx_len); DEBUGMSGTL (("disman:event:fire", "Adding trigger objects (specific)\n")); mteObjects_vblist (var, trigger->mteTriggerXOwner, trigger->mteTriggerXObjects, suffix, sfx_len); if (strictOrdering) { DEBUGMSGTL (("disman:event:fire", "Adding event objects (last)\n")); if (strcmp (entry->mteNotifyOwner, "_snmpd") != 0) mteObjects_vblist (var, entry->mteNotifyOwner, entry->mteNotifyObjects, suffix, sfx_len); } /* * Query the agent to retrieve the necessary values... * (skipping the initial snmpTrapOID varbind) */ v2 = var->next_variable; if (entry->session) s = entry->session; else s = trigger->session; netsnmp_query_get (v2, s); /* * ... add any "internal" objects... * (skipped by the processing above, and best handled directly) */ if (strcmp (entry->mteNotifyOwner, "_snmpd") == 0) { DEBUGMSGTL (("disman:event:fire", "Adding event objects (internal)\n")); if (!strictOrdering) { mteObjects_internal_vblist (var, entry->mteNotifyObjects, trigger, s); } else { for (v2 = var; v2 && v2->next_variable; v2 = v2->next_variable) ; mteObjects_internal_vblist (v2, entry->mteNotifyObjects, trigger, s); } } /* * ... and send the resulting varbind list as a notification */ send_v2trap (var); snmp_free_varbind (var); return 0; }
void send_notification(unsigned int clientreg, void *clientarg) { /* * define the OID for the notification we're going to send * NET-SNMP-EXAMPLES-MIB::netSnmpExampleNotification */ oid notification_oid[] = { 1, 3, 6, 1, 4, 1, 8072, 2, 3, 1 }; size_t notification_oid_len = OID_LENGTH(notification_oid); /* * In the notification, we have to assign our notification OID to * the snmpTrapOID.0 object. Here is it's definition. */ oid objid_snmptrap[] = { 1, 3, 6, 1, 6, 3, 1, 1, 4, 1, 0 }; size_t objid_snmptrap_len = OID_LENGTH(objid_snmptrap); netsnmp_index *index; oid tmp[2]; netSnmpIETFWGTable_context *x; /* * here is where we store the variables to be sent in the trap */ netsnmp_variable_list *notification_vars = NULL; DEBUGMSGTL(("example_notification", "defining the trap\n")); // Lets find the sucker index = SNMP_MALLOC_TYPEDEF(netsnmp_index); tmp[0] = 1; tmp[1] = 'a' + number; index->oids = tmp; index->len = 2; x = CONTAINER_FIND(cb.container, index); free(index); if (x) { DEBUGMSGTL((AGENT,"Found the object! ")); DEBUGMSGOID((AGENT,x->index.oids, x->index.len)); snmp_varlist_add_variable(¬ification_vars, //x->index.oids, x->index.len, objid_snmptrap, objid_snmptrap_len, ASN_OCTET_STR, x->nsIETFWGName, x->nsIETFWGName_len * sizeof(oid)); } /* * add in the trap definition object */ snmp_varlist_add_variable(¬ification_vars, /* * the snmpTrapOID.0 variable */ objid_snmptrap, objid_snmptrap_len, /* * value type is an OID */ ASN_OBJECT_ID, /* * value contents is our notification OID */ (u_char *) notification_oid, /* * size in bytes = oid length * sizeof(oid) */ notification_oid_len * sizeof(oid)); /* * if we wanted to insert additional objects, we'd do it here */ /* * send the trap out. This will send it to all registered * receivers (see the "SETTING UP TRAP AND/OR INFORM DESTINATIONS" * section of the snmpd.conf manual page. */ DEBUGMSGTL(("example_notification", "sending the trap\n")); send_v2trap(notification_vars); /* * free the created notification variable list */ DEBUGMSGTL(("example_notification", "cleaning up\n")); snmp_free_varbind(notification_vars); }
/* implements the table_iterator helper */ int netsnmp_table_iterator_helper_handler(netsnmp_mib_handler *handler, netsnmp_handler_registration *reginfo, netsnmp_agent_request_info *reqinfo, netsnmp_request_info *requests) { netsnmp_table_registration_info *tbl_info; netsnmp_table_request_info *table_info = NULL; oid coloid[MAX_OID_LEN]; size_t coloid_len; int ret = SNMP_ERR_NOERROR; static oid myname[MAX_OID_LEN]; size_t myname_len; int oldmode = 0; netsnmp_iterator_info *iinfo; int notdone; int hintok = 0; netsnmp_request_info *request, *reqtmp = NULL; netsnmp_variable_list *index_search = NULL; netsnmp_variable_list *free_this_index_search = NULL; void *callback_loop_context = NULL, *last_loop_context; void *callback_data_context = NULL; ti_cache_info *ti_info = NULL; int request_count = 0; netsnmp_oid_stash_node **cinfo = NULL; netsnmp_variable_list *old_indexes = NULL, *vb; netsnmp_table_registration_info *table_reg_info = NULL; int i; netsnmp_data_list *ldata = NULL; iinfo = (netsnmp_iterator_info *) handler->myvoid; if (!iinfo || !reginfo || !reqinfo) return SNMP_ERR_GENERR; tbl_info = iinfo->table_reginfo; /* * copy in the table registration oid for later use */ coloid_len = reginfo->rootoid_len + 2; memcpy(coloid, reginfo->rootoid, reginfo->rootoid_len * sizeof(oid)); coloid[reginfo->rootoid_len] = 1; /* table.entry node */ /* * illegally got here if these functions aren't defined */ if (iinfo->get_first_data_point == NULL || iinfo->get_next_data_point == NULL) { snmp_log(LOG_ERR, "table_iterator helper called without data accessor functions\n"); return SNMP_ERR_GENERR; } /* preliminary analysis */ switch (reqinfo->mode) { case MODE_GET_STASH: cinfo = netsnmp_extract_stash_cache(reqinfo); table_reg_info = netsnmp_find_table_registration_info(reginfo); /* XXX: move this malloc to stash_cache handler? */ reqtmp = SNMP_MALLOC_TYPEDEF(netsnmp_request_info); if (reqtmp == NULL) return SNMP_ERR_GENERR; reqtmp->subtree = requests->subtree; table_info = netsnmp_extract_table_info(requests); netsnmp_request_add_list_data(reqtmp, netsnmp_create_data_list (TABLE_HANDLER_NAME, (void *) table_info, NULL)); /* remember the indexes that were originally parsed. */ old_indexes = table_info->indexes; break; case MODE_GETNEXT: for(request = requests ; request; request = request->next) { if (request->processed) continue; table_info = netsnmp_extract_table_info(request); if (table_info == NULL) { /* * Cleanup */ if (free_this_index_search) snmp_free_varbind(free_this_index_search); return SNMP_ERR_GENERR; } if (table_info->colnum < tbl_info->min_column - 1) { /* XXX: optimize better than this */ /* for now, just increase to colnum-1 */ /* we need to jump to the lowest result of the min_column and take it, comparing to nothing from the request */ table_info->colnum = tbl_info->min_column - 1; } else if (table_info->colnum > tbl_info->max_column) { request->processed = TABLE_ITERATOR_NOTAGAIN; } ti_info = netsnmp_request_get_list_data(request, TI_REQUEST_CACHE); if (!ti_info) { ti_info = SNMP_MALLOC_TYPEDEF(ti_cache_info); if (ti_info == NULL) { /* * Cleanup */ if (free_this_index_search) snmp_free_varbind(free_this_index_search); return SNMP_ERR_GENERR; } netsnmp_request_add_list_data(request, netsnmp_create_data_list (TI_REQUEST_CACHE, ti_info, netsnmp_free_ti_cache)); } /* XXX: if no valid requests, don't even loop below */ } break; } /* * collect all information for each needed row */ if (reqinfo->mode == MODE_GET || reqinfo->mode == MODE_GETNEXT || reqinfo->mode == MODE_GET_STASH || reqinfo->mode == MODE_SET_RESERVE1) { /* * Count the number of request in the list, * so that we'll know when we're finished */ for(request = requests ; request; request = request->next) if (!request->processed) request_count++; notdone = 1; hintok = 1; while(notdone) { notdone = 0; /* find first data point */ if (!index_search) { if (free_this_index_search) { /* previously done */ index_search = free_this_index_search; } else { for(request=requests ; request; request=request->next) { table_info = netsnmp_extract_table_info(request); if (table_info) break; } if (!table_info) { snmp_log(LOG_WARNING, "no valid requests for iterator table %s\n", reginfo->handlerName); netsnmp_free_request_data_sets(reqtmp); SNMP_FREE(reqtmp); return SNMP_ERR_NOERROR; } index_search = snmp_clone_varbind(table_info->indexes); free_this_index_search = index_search; /* setup, malloc search data: */ if (!index_search) { /* * hmmm.... invalid table? */ snmp_log(LOG_WARNING, "invalid index list or failed malloc for table %s\n", reginfo->handlerName); netsnmp_free_request_data_sets(reqtmp); SNMP_FREE(reqtmp); return SNMP_ERR_NOERROR; } } } /* if sorted, pass in a hint */ if (hintok && (iinfo->flags & NETSNMP_ITERATOR_FLAG_SORTED)) { callback_loop_context = table_info; } index_search = (iinfo->get_first_data_point) (&callback_loop_context, &callback_data_context, index_search, iinfo); /* loop over each data point */ while(index_search) { /* remember to free this later */ free_this_index_search = index_search; /* compare against each request*/ for(request = requests ; request; request = request->next) { if (request->processed) continue; /* XXX: store in an array for faster retrival */ table_info = netsnmp_extract_table_info(request); if (table_info == NULL) { /* * Cleanup */ if (free_this_index_search) snmp_free_varbind(free_this_index_search); return SNMP_ERR_GENERR; } coloid[reginfo->rootoid_len + 1] = table_info->colnum; ti_info = netsnmp_request_get_list_data(request, TI_REQUEST_CACHE); switch(reqinfo->mode) { case MODE_GET: case MODE_SET_RESERVE1: /* looking for exact matches */ build_oid_noalloc(myname, MAX_OID_LEN, &myname_len, coloid, coloid_len, index_search); if (snmp_oid_compare(myname, myname_len, request->requestvb->name, request->requestvb->name_length) == 0) { /* * keep this */ if (netsnmp_iterator_remember(request, myname, myname_len, callback_data_context, callback_loop_context, iinfo) == NULL) { /* * Cleanup */ if (free_this_index_search) snmp_free_varbind (free_this_index_search); return SNMP_ERR_GENERR; } request_count--; /* One less to look for */ } else { if (iinfo->free_data_context && callback_data_context) { (iinfo->free_data_context)(callback_data_context, iinfo); } } break; case MODE_GET_STASH: /* collect data for each column for every row */ build_oid_noalloc(myname, MAX_OID_LEN, &myname_len, coloid, coloid_len, index_search); reqinfo->mode = MODE_GET; if (reqtmp) ldata = netsnmp_get_list_node(reqtmp->parent_data, TABLE_ITERATOR_NAME); if (!ldata) { netsnmp_request_add_list_data(reqtmp, netsnmp_create_data_list (TABLE_ITERATOR_NAME, callback_data_context, NULL)); } else { /* may have changed */ ldata->data = callback_data_context; } table_info->indexes = index_search; for(i = table_reg_info->min_column; i <= (int)table_reg_info->max_column; i++) { myname[reginfo->rootoid_len + 1] = i; table_info->colnum = i; vb = reqtmp->requestvb = SNMP_MALLOC_TYPEDEF(netsnmp_variable_list); if (vb == NULL) { /* * Cleanup */ if (free_this_index_search) snmp_free_varbind (free_this_index_search); return SNMP_ERR_GENERR; } vb->type = ASN_NULL; snmp_set_var_objid(vb, myname, myname_len); netsnmp_call_next_handler(handler, reginfo, reqinfo, reqtmp); reqtmp->requestvb = NULL; reqtmp->processed = 0; if (vb->type != ASN_NULL) { /* XXX, not all */ netsnmp_oid_stash_add_data(cinfo, myname, myname_len, vb); } else { snmp_free_var(vb); } } reqinfo->mode = MODE_GET_STASH; break; case MODE_GETNEXT: /* looking for "next" matches */ if (netsnmp_check_getnext_reply (request, coloid, coloid_len, index_search, &ti_info->results)) { if (netsnmp_iterator_remember(request, ti_info-> results->name, ti_info-> results-> name_length, callback_data_context, callback_loop_context, iinfo) == NULL) { /* * Cleanup */ if (free_this_index_search) snmp_free_varbind (free_this_index_search); return SNMP_ERR_GENERR; } /* * If we've been told that the rows are sorted, * then the first valid one we find * must be the right one. */ if (iinfo->flags & NETSNMP_ITERATOR_FLAG_SORTED) request_count--; } else { if (iinfo->free_data_context && callback_data_context) { (iinfo->free_data_context)(callback_data_context, iinfo); } } break; case MODE_SET_RESERVE2: case MODE_SET_FREE: case MODE_SET_UNDO: case MODE_SET_COMMIT: /* needed processing already done in RESERVE1 */ break; default: snmp_log(LOG_ERR, "table_iterator called with unsupported mode\n"); break; /* XXX return */ } } /* Is there any point in carrying on? */ if (!request_count) break; /* get the next search possibility */ last_loop_context = callback_loop_context; index_search = (iinfo->get_next_data_point) (&callback_loop_context, &callback_data_context, index_search, iinfo); if (iinfo->free_loop_context && last_loop_context && callback_data_context != last_loop_context) { (iinfo->free_loop_context) (last_loop_context, iinfo); last_loop_context = NULL; } } /* free loop context before going on */ if (callback_loop_context && iinfo->free_loop_context_at_end) { (iinfo->free_loop_context_at_end) (callback_loop_context, iinfo); callback_loop_context = NULL; } /* decide which (GETNEXT) requests are not yet filled */ if (reqinfo->mode == MODE_GETNEXT) { for(request = requests ; request; request = request->next) { if (request->processed) continue; ti_info = netsnmp_request_get_list_data(request, TI_REQUEST_CACHE); if (!ti_info->results) { int nc; table_info = netsnmp_extract_table_info(request); nc = netsnmp_table_next_column(table_info); if (0 == nc) { coloid[reginfo->rootoid_len+1] = table_info->colnum+1; snmp_set_var_objid(request->requestvb, coloid, reginfo->rootoid_len+2); request->processed = TABLE_ITERATOR_NOTAGAIN; break; } else { table_info->colnum = nc; hintok = 0; notdone = 1; } } } } } } if (reqinfo->mode == MODE_GET || reqinfo->mode == MODE_GETNEXT || reqinfo->mode == MODE_SET_RESERVE1) { /* per request last minute processing */ for(request = requests ; request; request = request->next) { if (request->processed) continue; ti_info = netsnmp_request_get_list_data(request, TI_REQUEST_CACHE); table_info = netsnmp_extract_table_info(request); if (!ti_info) continue; switch(reqinfo->mode) { case MODE_GETNEXT: if (ti_info->best_match_len) snmp_set_var_objid(request->requestvb, ti_info->best_match, ti_info->best_match_len); else { coloid[reginfo->rootoid_len+1] = netsnmp_table_next_column(table_info); if (0 == coloid[reginfo->rootoid_len+1]) { /* out of range. */ coloid[reginfo->rootoid_len+1] = tbl_info->max_column + 1; request->processed = TABLE_ITERATOR_NOTAGAIN; } snmp_set_var_objid(request->requestvb, coloid, reginfo->rootoid_len+2); request->processed = 1; } snmp_free_varbind(table_info->indexes); table_info->indexes = snmp_clone_varbind(ti_info->results); /* FALL THROUGH */ case MODE_GET: case MODE_SET_RESERVE1: if (ti_info->data_context) /* we don't add a free pointer, since it's in the TI_REQUEST_CACHE instead */ netsnmp_request_add_list_data(request, netsnmp_create_data_list (TABLE_ITERATOR_NAME, ti_info->data_context, NULL)); break; default: break; } } /* we change all GETNEXT operations into GET operations. why? because we're just so nice to the lower levels. maybe someday they'll pay us for it. doubtful though. */ oldmode = reqinfo->mode; if (reqinfo->mode == MODE_GETNEXT) { reqinfo->mode = MODE_GET; } } else if (reqinfo->mode == MODE_GET_STASH) { netsnmp_free_request_data_sets(reqtmp); SNMP_FREE(reqtmp); table_info->indexes = old_indexes; } /* Finally, we get to call the next handler below us. Boy, wasn't all that simple? They better be glad they don't have to do it! */ if (reqinfo->mode != MODE_GET_STASH) { DEBUGMSGTL(("table_iterator", "call subhandler for mode: %s\n", se_find_label_in_slist("agent_mode", oldmode))); ret = netsnmp_call_next_handler(handler, reginfo, reqinfo, requests); } /* reverse the previously saved mode if we were a getnext */ if (oldmode == MODE_GETNEXT) { reqinfo->mode = oldmode; } /* cleanup */ if (free_this_index_search) snmp_free_varbind(free_this_index_search); return ret; }
void * netsnmp_iterator_row_next_byoid( netsnmp_iterator_info *iinfo, oid *instance, size_t len ) { oid dummy[] = {0,0}; oid this_inst[ MAX_OID_LEN]; size_t this_len; oid best_inst[ MAX_OID_LEN]; size_t best_len = 0; netsnmp_variable_list *vp1, *vp2; void *ctx1, *ctx2; int n; if (!iinfo || !iinfo->get_first_data_point || !iinfo->get_next_data_point ) return NULL; vp1 = snmp_clone_varbind(iinfo->indexes); vp2 = iinfo->get_first_data_point( &ctx1, &ctx2, vp1, iinfo ); DEBUGMSGTL(("table:iterator:get", "first DP: %p %p %p\n", ctx1, ctx2, vp2)); if ( !instance || !len ) { snmp_free_varbind( vp1 ); return ( vp2 ? ctx2 : NULL ); /* First entry */ } /* XXX - free context ? */ while ( vp2 ) { this_len = MAX_OID_LEN; build_oid_noalloc(this_inst, MAX_OID_LEN, &this_len, dummy, 2, vp2); n = snmp_oid_compare( instance, len, this_inst+2, this_len-2 ); /* * Look for the best-fit candidate for the next row * (bearing in mind the rows may not be ordered "correctly") */ if ( n > 0 ) { if ( best_len == 0 ) { memcpy( best_inst, this_inst, sizeof( this_inst )); best_len = this_len; if (iinfo->flags & NETSNMP_ITERATOR_FLAG_SORTED) break; } else { n = snmp_oid_compare( best_inst, best_len, this_inst, this_len ); if ( n < 0 ) { memcpy( best_inst, this_inst, sizeof( this_inst )); best_len = this_len; if (iinfo->flags & NETSNMP_ITERATOR_FLAG_SORTED) break; } } } vp2 = iinfo->get_next_data_point( &ctx1, &ctx2, vp2, iinfo ); DEBUGMSGTL(("table:iterator:get", "next DP: %p %p %p\n", ctx1, ctx2, vp2)); /* XXX - free context ? */ } /* XXX - final free context ? */ snmp_free_varbind( vp1 ); return ( vp2 ? ctx2 : NULL ); }
void tcpprotopr(const char *name) { netsnmp_variable_list *var, *vp; oid tcpConnState_oid[] = { 1,3,6,1,2,1,6,13,1,1 }; size_t tcpConnState_len = OID_LENGTH( tcpConnState_oid ); int state, width; union { struct in_addr addr; char data[4]; } tmpAddr; oid localPort, remotePort; struct in_addr localAddr, remoteAddr; char *cp; int first = 1; /* * Walking the tcpConnState column will provide all * the necessary information. */ var = NULL; snmp_varlist_add_variable( &var, tcpConnState_oid, tcpConnState_len, ASN_NULL, NULL, 0); if (!var) return; if (netsnmp_query_walk( var, ss ) != SNMP_ERR_NOERROR) return; for (vp = var; vp ; vp=vp->next_variable) { state = *vp->val.integer; if (!aflag && state == MIB_TCPCONNSTATE_LISTEN) continue; if (first) { printf("Active Internet (%s) Connections", name); if (aflag) printf(" (including servers)"); putchar('\n'); width = Aflag ? 18 : 22; printf("%-5.5s %*.*s %*.*s %s\n", "Proto", -width, width, "Local Address", -width, width, "Remote Address", "(state)"); first=0; } /* Extract the local/remote information from the index values */ cp = tmpAddr.data; cp[0] = vp->name[ 10 ] & 0xff; cp[1] = vp->name[ 11 ] & 0xff; cp[2] = vp->name[ 12 ] & 0xff; cp[3] = vp->name[ 13 ] & 0xff; localAddr.s_addr = tmpAddr.addr.s_addr; localPort = ntohs((u_short)(vp->name[ 14 ])); cp = tmpAddr.data; cp[0] = vp->name[ 15 ] & 0xff; cp[1] = vp->name[ 16 ] & 0xff; cp[2] = vp->name[ 17 ] & 0xff; cp[3] = vp->name[ 18 ] & 0xff; remoteAddr.s_addr = tmpAddr.addr.s_addr; remotePort = ntohs((u_short)(vp->name[ 19 ])); printf("%-5.5s", name); inetprint(&localAddr, localPort, name, 1); inetprint(&remoteAddr, remotePort, name, 0); if ( state < 1 || state > TCP_NSTATES ) printf("%d\n", state ); else printf("%s\n", tcpstates[ state ]); } snmp_free_varbind( var ); }
/** * 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; }
int handle_subagent_response(int op, netsnmp_session * session, int reqid, netsnmp_pdu *pdu, void *magic) { ns_subagent_magic *smagic = (ns_subagent_magic *) magic; netsnmp_variable_list *u = NULL, *v = NULL; int rc = 0; if (op != NETSNMP_CALLBACK_OP_RECEIVED_MESSAGE || magic == NULL) { return 1; } pdu = snmp_clone_pdu(pdu); DEBUGMSGTL(("agentx/subagent", "handling AgentX response (cmd 0x%02x orig_cmd 0x%02x)\n", pdu->command, smagic->original_command)); if (pdu->command == SNMP_MSG_INTERNAL_SET_FREE || pdu->command == SNMP_MSG_INTERNAL_SET_UNDO || pdu->command == SNMP_MSG_INTERNAL_SET_COMMIT) { free_set_vars(smagic->session, pdu); } if (smagic->original_command == AGENTX_MSG_GETNEXT) { DEBUGMSGTL(("agentx/subagent", "do getNext scope processing %p %p\n", smagic->ovars, pdu->variables)); for (u = smagic->ovars, v = pdu->variables; u != NULL && v != NULL; u = u->next_variable, v = v->next_variable) { if (snmp_oid_compare (u->val.objid, u->val_len / sizeof(oid), nullOid, nullOidLen) != 0) { /* * The master agent requested scoping for this variable. */ rc = snmp_oid_compare(v->name, v->name_length, u->val.objid, u->val_len / sizeof(oid)); DEBUGMSGTL(("agentx/subagent", "result ")); DEBUGMSGOID(("agentx/subagent", v->name, v->name_length)); DEBUGMSG(("agentx/subagent", " scope to ")); DEBUGMSGOID(("agentx/subagent", u->val.objid, u->val_len / sizeof(oid))); DEBUGMSG(("agentx/subagent", " result %d\n", rc)); if (rc >= 0) { /* * The varbind is out of scope. From RFC2741, p. 66: "If * the subagent cannot locate an appropriate variable, * v.name is set to the starting OID, and the VarBind is * set to `endOfMibView'". */ snmp_set_var_objid(v, u->name, u->name_length); snmp_set_var_typed_value(v, SNMP_ENDOFMIBVIEW, 0, 0); DEBUGMSGTL(("agentx/subagent", "scope violation -- return endOfMibView\n")); } } else { DEBUGMSGTL(("agentx/subagent", "unscoped var\n")); } } } /* * XXXJBPN: similar for GETBULK but the varbinds can get re-ordered I * think which makes it er more difficult. */ if (smagic->ovars != NULL) { snmp_free_varbind(smagic->ovars); } pdu->command = AGENTX_MSG_RESPONSE; pdu->version = smagic->session->version; if (!snmp_send(smagic->session, pdu)) { snmp_free_pdu(pdu); } DEBUGMSGTL(("agentx/subagent", " FINISHED\n")); free(smagic); return 1; }
int send_saHpiHotSwapNotification_trap( void ) { netsnmp_variable_list *var_list = NULL; oid saHpiHotSwapNotification_oid[] = { 1,3,6,1,4,1,18568,2,1,1,5,6 }; oid saHpiDomainId_oid[] = { 1,3,6,1,4,1,18568,2,1,1,2,2,1,1, /* insert index here */ }; oid saHpiResourceId_oid[] = { 1,3,6,1,4,1,18568,2,1,1,2,8,1,1, /* insert index here */ }; oid saHpiEventSeverity_oid[] = { 1,3,6,1,4,1,18568,2,1,1,3,1,3,1,3, /* insert index here */ }; oid saHpiHotSwapEventState_oid[] = { 1,3,6,1,4,1,18568,2,1,1,3,1,18,1,3, /* insert index here */ }; oid saHpiHotSwapEventPreviousState_oid[] = { 1,3,6,1,4,1,18568,2,1,1,3,1,18,1,4, /* insert index here */ }; /* * Set the snmpTrapOid.0 value */ snmp_varlist_add_variable(&var_list, snmptrap_oid, OID_LENGTH(snmptrap_oid), ASN_OBJECT_ID, saHpiHotSwapNotification_oid, sizeof(saHpiHotSwapNotification_oid)); /* * Add any objects from the trap definition */ snmp_varlist_add_variable(&var_list, saHpiDomainId_oid, OID_LENGTH(saHpiDomainId_oid), ASN_UNSIGNED, /* Set an appropriate value for saHpiDomainId */ NULL, 0); snmp_varlist_add_variable(&var_list, saHpiResourceId_oid, OID_LENGTH(saHpiResourceId_oid), ASN_UNSIGNED, /* Set an appropriate value for saHpiResourceId */ NULL, 0); snmp_varlist_add_variable(&var_list, saHpiEventSeverity_oid, OID_LENGTH(saHpiEventSeverity_oid), ASN_INTEGER, /* Set an appropriate value for saHpiEventSeverity */ NULL, 0); snmp_varlist_add_variable(&var_list, saHpiHotSwapEventState_oid, OID_LENGTH(saHpiHotSwapEventState_oid), ASN_INTEGER, /* Set an appropriate value for saHpiHotSwapEventState */ NULL, 0); snmp_varlist_add_variable(&var_list, saHpiHotSwapEventPreviousState_oid, OID_LENGTH(saHpiHotSwapEventPreviousState_oid), ASN_INTEGER, /* Set an appropriate value for saHpiHotSwapEventPreviousState */ NULL, 0); /* * Add any extra (optional) objects here */ /* * Send the trap to the list of configured destinations * and clean up */ send_v2trap( var_list ); snmp_free_varbind( var_list ); return SNMP_ERR_NOERROR; }
/** ************************************************************************** * * param rows * */ netsnmp_variable_list * params_row_create(const char *param_name, int hash_type, const char *fp, uint32_t st, int *row_status_index) { oid name[MAX_OID_LEN]; int name_len, col_pos, rc, rs_index = 2; u_char bin_fp[SNMP_MAXBUF_SMALL], *bin_fp_ptr = bin_fp; u_int rs; size_t bin_fp_len; netsnmp_variable_list *vl = NULL, *vb; netsnmp_require_ptr_LRV( param_name, NULL ); netsnmp_require_ptr_LRV( fp, NULL ); DEBUGMSGT(("params:create", "creating varbinds for %s params, fp %s\n", param_name, fp)); /* * build base name */ name_len = OID_LENGTH(paramsTbl); memcpy(name, paramsTbl, sizeof(paramsTbl)); name[name_len++] = 1; /* entry */ col_pos = name_len++; /* column */ while (*param_name) name[name_len++] = *param_name++; bin_fp_len = sizeof(bin_fp); rc = netsnmp_tls_fingerprint_build(hash_type, fp, &bin_fp_ptr, &bin_fp_len, 0); name[col_pos] = COLUMN_SNMPTLSTMPARAMSCLIENTFINGERPRINT; vl = snmp_varlist_add_variable(&vl, name, name_len, ASN_OCTET_STR, &bin_fp, bin_fp_len); netsnmp_require_ptr_LRV(vl, NULL); if (st) { name[col_pos] = COLUMN_SNMPTLSTMPARAMSSTORAGETYPE; vb = snmp_varlist_add_variable(&vl, name, name_len, ASN_INTEGER, &st, sizeof(st)); if (NULL == vb) { snmp_free_varbind(vl); return NULL; } } else --rs_index; name[col_pos] = COLUMN_SNMPTLSTMPARAMSROWSTATUS; rs = RS_CREATEANDGO; vb = snmp_varlist_add_variable(&vl, name, name_len, ASN_INTEGER, &rs, sizeof(rs)); if (NULL == vb) { snmp_free_varbind(vl); return NULL; } if (row_status_index) *row_status_index = rs_index; return vl; }
void mteTrigger_run( unsigned int reg, void *clientarg) { struct mteTrigger *entry = (struct mteTrigger *)clientarg; netsnmp_variable_list *var, *vtmp; netsnmp_variable_list *vp1, *vp1_prev; netsnmp_variable_list *vp2, *vp2_prev; netsnmp_variable_list *dvar = NULL; netsnmp_variable_list *dv1 = NULL, *dv2 = NULL; netsnmp_variable_list sysUT_var; int cmp = 0, n, n2; long value; const char *reason; if (!entry) { snmp_alarm_unregister( reg ); return; } if (!(entry->flags & MTE_TRIGGER_FLAG_ENABLED ) || !(entry->flags & MTE_TRIGGER_FLAG_ACTIVE ) || !(entry->flags & MTE_TRIGGER_FLAG_VALID )) { return; } { extern netsnmp_agent_session *netsnmp_processing_set; if (netsnmp_processing_set) { /* * netsnmp_handle_request will not be responsive to our efforts to * Retrieve the requested MIB value(s)... * so we will skip it. * https://sourceforge.net/tracker/ * index.php?func=detail&aid=1557406&group_id=12694&atid=112694 */ DEBUGMSGTL(("disman:event:trigger:monitor", "Skipping trigger (%s) while netsnmp_processing_set\n", entry->mteTName)); return; } } /* * Retrieve the requested MIB value(s)... */ DEBUGMSGTL(( "disman:event:trigger:monitor", "Running trigger (%s)\n", entry->mteTName)); var = (netsnmp_variable_list *)SNMP_MALLOC_TYPEDEF( netsnmp_variable_list ); if (!var) { _mteTrigger_failure("failed to create mteTrigger query varbind"); return; } snmp_set_var_objid( var, entry->mteTriggerValueID, entry->mteTriggerValueID_len ); if ( entry->flags & MTE_TRIGGER_FLAG_VWILD ) { n = netsnmp_query_walk( var, entry->session ); } else { n = netsnmp_query_get( var, entry->session ); } if ( n != SNMP_ERR_NOERROR ) { DEBUGMSGTL(( "disman:event:trigger:monitor", "Trigger query (%s) failed: %d\n", (( entry->flags & MTE_TRIGGER_FLAG_VWILD ) ? "walk" : "get"), n)); _mteTrigger_failure( "failed to run mteTrigger query" ); snmp_free_varbind(var); return; } /* * ... canonicalise the results (to simplify later comparisons)... */ vp1 = var; vp1_prev = NULL; vp2 = entry->old_results; vp2_prev = NULL; entry->count=0; while (vp1) { /* * Flatten various missing values/exceptions into a single form */ switch (vp1->type) { case SNMP_NOSUCHINSTANCE: case SNMP_NOSUCHOBJECT: case ASN_PRIV_RETRY: /* Internal only ? */ vp1->type = ASN_NULL; } /* * Keep track of how many entries have been retrieved. */ entry->count++; /* * Ensure previous and current result match * (with corresponding entries in both lists) * and set the flags indicating which triggers are armed */ if (vp2) { cmp = snmp_oid_compare(vp1->name, vp1->name_length, vp2->name, vp2->name_length); if ( cmp < 0 ) { /* * If a new value has appeared, insert a matching * dummy entry into the previous result list. * * XXX - check how this is best done. */ vtmp = SNMP_MALLOC_TYPEDEF( netsnmp_variable_list ); if (!vtmp) { _mteTrigger_failure( "failed to create mteTrigger temp varbind"); snmp_free_varbind(var); return; } vtmp->type = ASN_NULL; snmp_set_var_objid( vtmp, vp1->name, vp1->name_length ); vtmp->next_variable = vp2; if (vp2_prev) { vp2_prev->next_variable = vtmp; } else { entry->old_results = vtmp; } vp2_prev = vtmp; vp1->index = MTE_ARMED_ALL; /* XXX - plus a new flag */ vp1_prev = vp1; vp1 = vp1->next_variable; } else if ( cmp == 0 ) { /* * If it's a continuing entry, just copy across the armed flags */ vp1->index = vp2->index; vp1_prev = vp1; vp1 = vp1->next_variable; vp2_prev = vp2; vp2 = vp2->next_variable; } else { /* * If a value has just disappeared, insert a * matching dummy entry into the current result list. * * XXX - check how this is best done. * */ if ( vp2->type != ASN_NULL ) { vtmp = SNMP_MALLOC_TYPEDEF( netsnmp_variable_list ); if (!vtmp) { _mteTrigger_failure( "failed to create mteTrigger temp varbind"); snmp_free_varbind(var); return; } vtmp->type = ASN_NULL; snmp_set_var_objid( vtmp, vp2->name, vp2->name_length ); vtmp->next_variable = vp1; if (vp1_prev) { vp1_prev->next_variable = vtmp; } else { var = vtmp; } vp1_prev = vtmp; vp2_prev = vp2; vp2 = vp2->next_variable; } else { /* * But only if this entry has *just* disappeared. If the * entry from the last run was a dummy too, then remove it. * (leaving vp2_prev unchanged) */ vtmp = vp2; if (vp2_prev) { vp2_prev->next_variable = vp2->next_variable; } else { entry->old_results = vp2->next_variable; } vp2 = vp2->next_variable; vtmp->next_variable = NULL; snmp_free_varbind( vtmp ); } } } else { /* * No more old results to compare. * Either all remaining values have only just been created ... * (and we need to create dummy 'old' entries for them) */ if ( vp2_prev ) { vtmp = SNMP_MALLOC_TYPEDEF( netsnmp_variable_list ); if (!vtmp) { _mteTrigger_failure( "failed to create mteTrigger temp varbind"); snmp_free_varbind(var); return; } vtmp->type = ASN_NULL; snmp_set_var_objid( vtmp, vp1->name, vp1->name_length ); vtmp->next_variable = vp2_prev->next_variable; vp2_prev->next_variable = vtmp; vp2_prev = vtmp; } /* * ... or this is the first run through * (and there were no old results at all) * * In either case, mark the current entry as armed and new. * Note that we no longer need to maintain 'vp1_prev' */ vp1->index = MTE_ARMED_ALL; /* XXX - plus a new flag */ vp1 = vp1->next_variable; } } /* * ... and then work through these result(s), deciding * whether or not to trigger the corresponding event. * * Note that there's no point in evaluating Existence or * Boolean tests if there's no corresponding event. * (Even if the trigger matched, nothing would be done anyway). */ if ((entry->mteTriggerTest & MTE_TRIGGER_EXISTENCE) && (entry->mteTExEvent[0] != '\0' )) { /* * If we don't have a record of previous results, * this must be the first time through, so consider * the mteTriggerExistenceStartup tests. */ if ( !entry->old_results ) { /* * With the 'present(0)' test, the trigger should fire * for each value in the varbind list returned * (whether the monitored value is wildcarded or not). */ if (entry->mteTExTest & entry->mteTExStartup & MTE_EXIST_PRESENT) { for (vp1 = var; vp1; vp1=vp1->next_variable) { DEBUGMSGTL(( "disman:event:trigger:fire", "Firing initial existence test: ")); DEBUGMSGOID(("disman:event:trigger:fire", vp1->name, vp1->name_length)); DEBUGMSG(( "disman:event:trigger:fire", " (present)\n"));; entry->mteTriggerXOwner = entry->mteTExObjOwner; entry->mteTriggerXObjects = entry->mteTExObjects; entry->mteTriggerFired = vp1; n = entry->mteTriggerValueID_len; mteEvent_fire(entry->mteTExEvOwner, entry->mteTExEvent, entry, vp1->name+n, vp1->name_length-n); } } /* * An initial 'absent(1)' test only makes sense when * monitoring a non-wildcarded OID (how would we know * which rows of the table "ought" to exist, but don't?) */ if (entry->mteTExTest & entry->mteTExStartup & MTE_EXIST_ABSENT) { if (!(entry->flags & MTE_TRIGGER_FLAG_VWILD) && var->type == ASN_NULL ) { DEBUGMSGTL(( "disman:event:trigger:fire", "Firing initial existence test: ")); DEBUGMSGOID(("disman:event:trigger:fire", var->name, var->name_length)); DEBUGMSG(( "disman:event:trigger:fire", " (absent)\n"));; entry->mteTriggerXOwner = entry->mteTExObjOwner; entry->mteTriggerXObjects = entry->mteTExObjects; /* * It's unclear what value the 'mteHotValue' payload * should take when a monitored instance does not * exist on startup. The only sensible option is * to report a NULL value, but this clashes with * the syntax of the mteHotValue MIB object. */ entry->mteTriggerFired = var; n = entry->mteTriggerValueID_len; mteEvent_fire(entry->mteTExEvOwner, entry->mteTExEvent, entry, var->name+n, var->name_length-n); } } } /* !old_results */ /* * Otherwise, compare the current set of results with * the previous ones, looking for changes. We can * assume that the two lists match (see above). */ else { for (vp1 = var, vp2 = entry->old_results; vp1; vp1=vp1->next_variable, vp2=vp2->next_variable) { /* Use this field to indicate that the trigger should fire */ entry->mteTriggerFired = NULL; reason = NULL; if ((entry->mteTExTest & MTE_EXIST_PRESENT) && (vp1->type != ASN_NULL) && (vp2->type == ASN_NULL)) { /* A new instance has appeared */ entry->mteTriggerFired = vp1; reason = "(present)"; } else if ((entry->mteTExTest & MTE_EXIST_ABSENT) && (vp1->type == ASN_NULL) && (vp2->type != ASN_NULL)) { /* * A previous instance has disappeared. * * It's unclear what value the 'mteHotValue' payload * should take when this happens - the previous * value (vp2), or a NULL value (vp1) ? * NULL makes more sense logically, but clashes * with the syntax of the mteHotValue MIB object. */ entry->mteTriggerFired = vp2; reason = "(absent)"; } else if ((entry->mteTExTest & MTE_EXIST_CHANGED) && ((vp1->val_len != vp2->val_len) || (memcmp( vp1->val.string, vp2->val.string, vp1->val_len) != 0 ))) { /* * This comparison detects changes in *any* type * of value, numeric or string (or even OID). * * Unfortunately, the default 'mteTriggerFired' * notification payload can't report non-numeric * changes properly (see syntax of 'mteHotValue') */ entry->mteTriggerFired = vp1; reason = "(changed)"; } if ( entry->mteTriggerFired ) { /* * One of the above tests has matched, * so fire the trigger. */ DEBUGMSGTL(( "disman:event:trigger:fire", "Firing existence test: ")); DEBUGMSGOID(("disman:event:trigger:fire", vp1->name, vp1->name_length)); DEBUGMSG(( "disman:event:trigger:fire", " %s\n", reason));; entry->mteTriggerXOwner = entry->mteTExObjOwner; entry->mteTriggerXObjects = entry->mteTExObjects; n = entry->mteTriggerValueID_len; mteEvent_fire(entry->mteTExEvOwner, entry->mteTExEvent, entry, vp1->name+n, vp1->name_length-n); } } } /* !old_results - end of else block */ } /* MTE_TRIGGER_EXISTENCE */ if (( entry->mteTriggerTest & MTE_TRIGGER_BOOLEAN ) || ( entry->mteTriggerTest & MTE_TRIGGER_THRESHOLD )) { /* * Although Existence tests can work with any syntax values, * Boolean and Threshold tests are integer-only. Ensure that * the returned value(s) are appropriate. * * Note that we only need to check the first value, since all * instances of a given object should have the same syntax. */ switch (var->type) { case ASN_INTEGER: case ASN_COUNTER: case ASN_GAUGE: case ASN_TIMETICKS: case ASN_UINTEGER: case ASN_COUNTER64: #ifdef NETSNMP_WITH_OPAQUE_SPECIAL_TYPES case ASN_OPAQUE_COUNTER64: case ASN_OPAQUE_U64: case ASN_OPAQUE_I64: #endif /* OK */ break; default: /* * Other syntax values can't be used for Boolean/Theshold * tests. Report this as an error, and then rotate the * results ready for the next run, (which will presumably * also detect this as an error once again!) */ DEBUGMSGTL(( "disman:event:trigger:fire", "Returned non-integer result(s): ")); DEBUGMSGOID(("disman:event:trigger:fire", var->name, var->name_length)); DEBUGMSG(( "disman:event:trigger:fire", " (boolean/threshold) %d\n", var->type));; snmp_free_varbind( entry->old_results ); entry->old_results = var; return; } /* * Retrieve the discontinuity markers for delta-valued samples. * (including sysUpTime.0 if not specified explicitly). */ if ( entry->flags & MTE_TRIGGER_FLAG_DELTA ) { /* * We'll need sysUpTime.0 regardless... */ DEBUGMSGTL(("disman:event:delta", "retrieve sysUpTime.0\n")); memset( &sysUT_var, 0, sizeof( netsnmp_variable_list )); snmp_set_var_objid( &sysUT_var, _sysUpTime_instance, _sysUpTime_inst_len ); netsnmp_query_get( &sysUT_var, entry->session ); if (!(entry->flags & MTE_TRIGGER_FLAG_SYSUPT)) { /* * ... but only retrieve the configured discontinuity * marker(s) if they refer to something different. */ DEBUGMSGTL(( "disman:event:delta", "retrieve discontinuity marker(s): ")); DEBUGMSGOID(("disman:event:delta", entry->mteDeltaDiscontID, entry->mteDeltaDiscontID_len )); DEBUGMSG(( "disman:event:delta", " %s\n", (entry->flags & MTE_TRIGGER_FLAG_DWILD ? " (wild)" : ""))); dvar = (netsnmp_variable_list *) SNMP_MALLOC_TYPEDEF( netsnmp_variable_list ); if (!dvar) { _mteTrigger_failure( "failed to create mteTrigger delta query varbind"); return; } snmp_set_var_objid( dvar, entry->mteDeltaDiscontID, entry->mteDeltaDiscontID_len ); if ( entry->flags & MTE_TRIGGER_FLAG_DWILD ) { n = netsnmp_query_walk( dvar, entry->session ); } else { n = netsnmp_query_get( dvar, entry->session ); } if ( n != SNMP_ERR_NOERROR ) { _mteTrigger_failure( "failed to run mteTrigger delta query" ); snmp_free_varbind( dvar ); return; } } /* * We can't calculate delta values the first time through, * so there's no point in evaluating the remaining tests. * * Save the results (and discontinuity markers), * ready for the next run. */ if ( !entry->old_results ) { entry->old_results = var; entry->old_deltaDs = dvar; entry->sysUpTime = *sysUT_var.val.integer; return; } /* * If the sysUpTime marker has been reset (or strictly, * has advanced by less than the monitor frequency), * there's no point in trying the remaining tests. */ if (*sysUT_var.val.integer < entry->sysUpTime) { DEBUGMSGTL(( "disman:event:delta", "single discontinuity: (sysUT)\n")); snmp_free_varbind( entry->old_results ); snmp_free_varbind( entry->old_deltaDs ); entry->old_results = var; entry->old_deltaDs = dvar; entry->sysUpTime = *sysUT_var.val.integer; return; } /* * Similarly if a separate (non-wildcarded) discontinuity * marker has changed, then there's no * point in trying to evaluate these tests either. */ if (!(entry->flags & MTE_TRIGGER_FLAG_DWILD) && !(entry->flags & MTE_TRIGGER_FLAG_SYSUPT) && (!entry->old_deltaDs || (entry->old_deltaDs->val.integer != dvar->val.integer))) { DEBUGMSGTL(( "disman:event:delta", "single discontinuity: (")); DEBUGMSGOID(( "disman:event:delta", entry->mteDeltaDiscontID, entry->mteDeltaDiscontID_len)); DEBUGMSG(( "disman:event:delta", ")\n")); snmp_free_varbind( entry->old_results ); snmp_free_varbind( entry->old_deltaDs ); entry->old_results = var; entry->old_deltaDs = dvar; entry->sysUpTime = *sysUT_var.val.integer; return; } /* * Ensure that the list of (wildcarded) discontinuity * markers matches the list of monitored values * (inserting/removing discontinuity varbinds as needed) * * XXX - An alternative approach would be to use the list * of monitored values (instance subidentifiers) to build * the exact list of delta markers to retrieve earlier. */ if (entry->flags & MTE_TRIGGER_FLAG_DWILD) { vp1 = var; vp2 = dvar; vp2_prev = NULL; n = entry->mteTriggerValueID_len; n2 = entry->mteDeltaDiscontID_len; while (vp1) { /* * For each monitored instance, check whether * there's a matching discontinuity entry. */ cmp = snmp_oid_compare(vp1->name+n, vp1->name_length-n, vp2->name+n2, vp2->name_length-n2 ); if ( cmp < 0 ) { /* * If a discontinuity entry is missing, * insert a (dummy) varbind. * The corresponding delta calculation will * fail, but this simplifies the later code. */ vtmp = (netsnmp_variable_list *) SNMP_MALLOC_TYPEDEF( netsnmp_variable_list ); if (!vtmp) { _mteTrigger_failure( "failed to create mteTrigger discontinuity varbind"); snmp_free_varbind(dvar); return; } snmp_set_var_objid(vtmp, entry->mteDeltaDiscontID, entry->mteDeltaDiscontID_len); /* XXX - append instance subids */ vtmp->next_variable = vp2; vp2_prev->next_variable = vtmp; vp2_prev = vtmp; vp1 = vp1->next_variable; } else if ( cmp == 0 ) { /* * Matching discontinuity entry - all OK. */ vp2_prev = vp2; vp2 = vp2->next_variable; vp1 = vp1->next_variable; } else { /* * Remove unneeded discontinuity entry */ vtmp = vp2; vp2_prev->next_variable = vp2->next_variable; vp2 = vp2->next_variable; vtmp->next_variable = NULL; snmp_free_varbind( vtmp ); } } /* * XXX - Now need to ensure that the old list of * delta discontinuity markers matches as well. */ } } /* delta samples */ } /* Boolean/Threshold test checks */ /* * Only run the Boolean tests if there's an event to be triggered */ if ((entry->mteTriggerTest & MTE_TRIGGER_BOOLEAN) && (entry->mteTBoolEvent[0] != '\0' )) { if (entry->flags & MTE_TRIGGER_FLAG_DELTA) { vp2 = entry->old_results; if (entry->flags & MTE_TRIGGER_FLAG_DWILD) { dv1 = dvar; dv2 = entry->old_deltaDs; } } for ( vp1 = var; vp1; vp1=vp1->next_variable ) { /* * Determine the value to be monitored... */ if ( !vp1->val.integer ) { /* No value */ if ( vp2 ) vp2 = vp2->next_variable; continue; } if (entry->flags & MTE_TRIGGER_FLAG_DELTA) { if (entry->flags & MTE_TRIGGER_FLAG_DWILD) { /* * We've already checked any non-wildcarded * discontinuity markers (inc. sysUpTime.0). * Validate this particular sample against * the relevant wildcarded marker... */ if ((dv1->type == ASN_NULL) || (dv1->type != dv2->type) || (*dv1->val.integer != *dv2->val.integer)) { /* * Bogus or changed discontinuity marker. * Need to skip this sample. */ DEBUGMSGTL(( "disman:event:delta", "discontinuity occurred: ")); DEBUGMSGOID(("disman:event:delta", vp1->name, vp1->name_length )); DEBUGMSG(( "disman:event:delta", " \n" )); vp2 = vp2->next_variable; continue; } } /* * ... and check there is a previous sample to calculate * the delta value against (regardless of whether the * discontinuity marker was wildcarded or not). */ if (vp2->type == ASN_NULL) { DEBUGMSGTL(( "disman:event:delta", "missing sample: ")); DEBUGMSGOID(("disman:event:delta", vp1->name, vp1->name_length )); DEBUGMSG(( "disman:event:delta", " \n" )); vp2 = vp2->next_variable; continue; } value = (*vp1->val.integer - *vp2->val.integer); DEBUGMSGTL(( "disman:event:delta", "delta sample: ")); DEBUGMSGOID(("disman:event:delta", vp1->name, vp1->name_length )); DEBUGMSG(( "disman:event:delta", " (%ld - %ld) = %ld\n", *vp1->val.integer, *vp2->val.integer, value)); vp2 = vp2->next_variable; } else { value = *vp1->val.integer; } /* * ... evaluate the comparison ... */ switch (entry->mteTBoolComparison) { case MTE_BOOL_UNEQUAL: cmp = ( value != entry->mteTBoolValue ); break; case MTE_BOOL_EQUAL: cmp = ( value == entry->mteTBoolValue ); break; case MTE_BOOL_LESS: cmp = ( value < entry->mteTBoolValue ); break; case MTE_BOOL_LESSEQUAL: cmp = ( value <= entry->mteTBoolValue ); break; case MTE_BOOL_GREATER: cmp = ( value > entry->mteTBoolValue ); break; case MTE_BOOL_GREATEREQUAL: cmp = ( value >= entry->mteTBoolValue ); break; } DEBUGMSGTL(( "disman:event:delta", "Bool comparison: (%ld %s %ld) %d\n", value, _ops[entry->mteTBoolComparison], entry->mteTBoolValue, cmp)); /* * ... and decide whether to trigger the event. * (using the 'index' field of the varbind structure * to remember whether the trigger has already fired) */ if ( cmp ) { if (vp1->index & MTE_ARMED_BOOLEAN ) { vp1->index &= ~MTE_ARMED_BOOLEAN; /* * NB: Clear the trigger armed flag even if the * (starting) event dosn't actually fire. * Otherwise initially true (but suppressed) * triggers will fire on the *second* probe. */ if ( entry->old_results || (entry->flags & MTE_TRIGGER_FLAG_BSTART)) { DEBUGMSGTL(( "disman:event:trigger:fire", "Firing boolean test: ")); DEBUGMSGOID(("disman:event:trigger:fire", vp1->name, vp1->name_length)); DEBUGMSG(( "disman:event:trigger:fire", "%s\n", (entry->old_results ? "" : " (startup)"))); entry->mteTriggerXOwner = entry->mteTBoolObjOwner; entry->mteTriggerXObjects = entry->mteTBoolObjects; /* * XXX - when firing a delta-based trigger, should * 'mteHotValue' report the actual value sampled * (as here), or the delta that triggered the event ? */ entry->mteTriggerFired = vp1; n = entry->mteTriggerValueID_len; mteEvent_fire(entry->mteTBoolEvOwner, entry->mteTBoolEvent, entry, vp1->name+n, vp1->name_length-n); } } } else { vp1->index |= MTE_ARMED_BOOLEAN; } } } /* * Only run the basic threshold tests if there's an event to * be triggered. (Either rising or falling will do) */ if (( entry->mteTriggerTest & MTE_TRIGGER_THRESHOLD ) && ((entry->mteTThRiseEvent[0] != '\0' ) || (entry->mteTThFallEvent[0] != '\0' ))) { /* * The same delta-sample validation from Boolean * tests also applies here too. */ if (entry->flags & MTE_TRIGGER_FLAG_DELTA) { vp2 = entry->old_results; if (entry->flags & MTE_TRIGGER_FLAG_DWILD) { dv1 = dvar; dv2 = entry->old_deltaDs; } } for ( vp1 = var; vp1; vp1=vp1->next_variable ) { /* * Determine the value to be monitored... */ if ( !vp1->val.integer ) { /* No value */ if ( vp2 ) vp2 = vp2->next_variable; continue; } if (entry->flags & MTE_TRIGGER_FLAG_DELTA) { if (entry->flags & MTE_TRIGGER_FLAG_DWILD) { /* * We've already checked any non-wildcarded * discontinuity markers (inc. sysUpTime.0). * Validate this particular sample against * the relevant wildcarded marker... */ if ((dv1->type == ASN_NULL) || (dv1->type != dv2->type) || (*dv1->val.integer != *dv2->val.integer)) { /* * Bogus or changed discontinuity marker. * Need to skip this sample. */ vp2 = vp2->next_variable; continue; } } /* * ... and check there is a previous sample to calculate * the delta value against (regardless of whether the * discontinuity marker was wildcarded or not). */ if (vp2->type == ASN_NULL) { vp2 = vp2->next_variable; continue; } value = (*vp1->val.integer - *vp2->val.integer); vp2 = vp2->next_variable; } else { value = *vp1->val.integer; } /* * ... evaluate the single-value comparisons, * and decide whether to trigger the event. */ cmp = vp1->index; /* working copy of 'armed' flags */ if ( value >= entry->mteTThRiseValue ) { if (cmp & MTE_ARMED_TH_RISE ) { cmp &= ~MTE_ARMED_TH_RISE; cmp |= MTE_ARMED_TH_FALL; /* * NB: Clear the trigger armed flag even if the * (starting) event dosn't actually fire. * Otherwise initially true (but suppressed) * triggers will fire on the *second* probe. * Similarly for falling thresholds (see below). */ if ( entry->old_results || (entry->mteTThStartup & MTE_THRESH_START_RISE)) { DEBUGMSGTL(( "disman:event:trigger:fire", "Firing rising threshold test: ")); DEBUGMSGOID(("disman:event:trigger:fire", vp1->name, vp1->name_length)); DEBUGMSG(( "disman:event:trigger:fire", "%s\n", (entry->old_results ? "" : " (startup)"))); /* * If no riseEvent is configured, we need still to * set the armed flags appropriately, but there's * no point in trying to fire the (missing) event. */ if (entry->mteTThRiseEvent[0] != '\0' ) { entry->mteTriggerXOwner = entry->mteTThObjOwner; entry->mteTriggerXObjects = entry->mteTThObjects; entry->mteTriggerFired = vp1; n = entry->mteTriggerValueID_len; mteEvent_fire(entry->mteTThRiseOwner, entry->mteTThRiseEvent, entry, vp1->name+n, vp1->name_length-n); } } } } if ( value <= entry->mteTThFallValue ) { if (cmp & MTE_ARMED_TH_FALL ) { cmp &= ~MTE_ARMED_TH_FALL; cmp |= MTE_ARMED_TH_RISE; /* Clear the trigger armed flag (see above) */ if ( entry->old_results || (entry->mteTThStartup & MTE_THRESH_START_FALL)) { DEBUGMSGTL(( "disman:event:trigger:fire", "Firing falling threshold test: ")); DEBUGMSGOID(("disman:event:trigger:fire", vp1->name, vp1->name_length)); DEBUGMSG(( "disman:event:trigger:fire", "%s\n", (entry->old_results ? "" : " (startup)"))); /* * Similarly, if no fallEvent is configured, * there's no point in trying to fire it either. */ if (entry->mteTThRiseEvent[0] != '\0' ) { entry->mteTriggerXOwner = entry->mteTThObjOwner; entry->mteTriggerXObjects = entry->mteTThObjects; entry->mteTriggerFired = vp1; n = entry->mteTriggerValueID_len; mteEvent_fire(entry->mteTThFallOwner, entry->mteTThFallEvent, entry, vp1->name+n, vp1->name_length-n); } } } } vp1->index = cmp; } } /* * The same processing also works for delta-threshold tests (if configured) */ if (( entry->mteTriggerTest & MTE_TRIGGER_THRESHOLD ) && ((entry->mteTThDRiseEvent[0] != '\0' ) || (entry->mteTThDFallEvent[0] != '\0' ))) { /* * Delta-threshold tests can only be used with * absolute valued samples. */ vp2 = entry->old_results; if (entry->flags & MTE_TRIGGER_FLAG_DELTA) { DEBUGMSGTL(( "disman:event:trigger", "Delta-threshold on delta-sample\n")); } else if ( vp2 != NULL ) { for ( vp1 = var; vp1; vp1=vp1->next_variable ) { /* * Determine the value to be monitored... * (similar to previous delta-sample processing, * but without the discontinuity marker checks) */ if (!vp2) { break; /* Run out of 'old' values */ } if (( !vp1->val.integer ) || (vp2->type == ASN_NULL)) { vp2 = vp2->next_variable; continue; } value = (*vp1->val.integer - *vp2->val.integer); vp2 = vp2->next_variable; /* * ... evaluate the single-value comparisons, * and decide whether to trigger the event. */ cmp = vp1->index; /* working copy of 'armed' flags */ if ( value >= entry->mteTThDRiseValue ) { if (vp1->index & MTE_ARMED_TH_DRISE ) { DEBUGMSGTL(( "disman:event:trigger:fire", "Firing rising delta threshold test: ")); DEBUGMSGOID(("disman:event:trigger:fire", vp1->name, vp1->name_length)); DEBUGMSG(( "disman:event:trigger:fire", "\n")); cmp &= ~MTE_ARMED_TH_DRISE; cmp |= MTE_ARMED_TH_DFALL; /* * If no riseEvent is configured, we need still to * set the armed flags appropriately, but there's * no point in trying to fire the (missing) event. */ if (entry->mteTThDRiseEvent[0] != '\0' ) { entry->mteTriggerXOwner = entry->mteTThObjOwner; entry->mteTriggerXObjects = entry->mteTThObjects; entry->mteTriggerFired = vp1; n = entry->mteTriggerValueID_len; mteEvent_fire(entry->mteTThDRiseOwner, entry->mteTThDRiseEvent, entry, vp1->name+n, vp1->name_length-n); } } } if ( value <= entry->mteTThDFallValue ) { if (vp1->index & MTE_ARMED_TH_DFALL ) { DEBUGMSGTL(( "disman:event:trigger:fire", "Firing falling delta threshold test: ")); DEBUGMSGOID(("disman:event:trigger:fire", vp1->name, vp1->name_length)); DEBUGMSG(( "disman:event:trigger:fire", "\n")); cmp &= ~MTE_ARMED_TH_DFALL; cmp |= MTE_ARMED_TH_DRISE; /* * Similarly, if no fallEvent is configured, * there's no point in trying to fire it either. */ if (entry->mteTThDRiseEvent[0] != '\0' ) { entry->mteTriggerXOwner = entry->mteTThObjOwner; entry->mteTriggerXObjects = entry->mteTThObjects; entry->mteTriggerFired = vp1; n = entry->mteTriggerValueID_len; mteEvent_fire(entry->mteTThDFallOwner, entry->mteTThDFallEvent, entry, vp1->name+n, vp1->name_length-n); } } } vp1->index = cmp; } } } /* * Finally, rotate the results - ready for the next run. */ snmp_free_varbind( entry->old_results ); entry->old_results = var; if ( entry->flags & MTE_TRIGGER_FLAG_DELTA ) { snmp_free_varbind( entry->old_deltaDs ); entry->old_deltaDs = dvar; entry->sysUpTime = *sysUT_var.val.integer; } }
/** ************************************************************************** * * addr rows * */ netsnmp_variable_list * addr_row_create(const char *target_name, int hash_type, const char *fp, const char *identity, uint32_t st, int *row_status_index) { oid name[MAX_OID_LEN]; int name_len, col_pos, rc, rs_index = 3; u_char bin_fp[SNMP_MAXBUF_SMALL], *bin_fp_ptr = bin_fp; u_int rs; size_t bin_fp_len; netsnmp_variable_list *vl = NULL, *vb; netsnmp_require_ptr_LRV( target_name, NULL ); DEBUGMSGT(("addr:create", "creating varbinds for %s addr, fp %s, id %s\n", target_name, fp, identity)); /* * build base name */ name_len = OID_LENGTH(addrTbl); memcpy(name, addrTbl, sizeof(addrTbl)); name[name_len++] = 1; /* entry */ col_pos = name_len++; /* column */ while (*target_name) name[name_len++] = *target_name++; if (fp) { bin_fp_len = sizeof(bin_fp); rc = netsnmp_tls_fingerprint_build(hash_type, fp, &bin_fp_ptr, &bin_fp_len, 0); name[col_pos] = COLUMN_SNMPTLSTMADDRSERVERFINGERPRINT; vl = snmp_varlist_add_variable(&vl, name, name_len, ASN_OCTET_STR, &bin_fp, bin_fp_len); netsnmp_require_ptr_LRV(vl, NULL); } else --rs_index; if (identity) { name[col_pos] = COLUMN_SNMPTLSTMADDRSERVERIDENTITY; vl = snmp_varlist_add_variable(&vl, name, name_len, ASN_OCTET_STR, identity, strlen(identity)); netsnmp_require_ptr_LRV(vl, NULL); } else --rs_index; if (st) { name[col_pos] = COLUMN_SNMPTLSTMADDRSTORAGETYPE; vb = snmp_varlist_add_variable(&vl, name, name_len, ASN_INTEGER, &st, sizeof(st)); if (NULL == vb) { snmp_free_varbind(vl); return NULL; } } else --rs_index; name[col_pos] = COLUMN_SNMPTLSTMADDRROWSTATUS; rs = RS_CREATEANDGO; vb = snmp_varlist_add_variable(&vl, name, name_len, ASN_INTEGER, &rs, sizeof(rs)); if (NULL == vb) { snmp_free_varbind(vl); return NULL; } if (row_status_index) *row_status_index = rs_index; return vl; }
/* * send trap */ void run_mte_events(struct mteTriggerTable_data *item, oid * name_oid, size_t name_oid_len, const char *eventobjowner, const char *eventobjname) { static oid objid_snmptrap[] = { 1, 3, 6, 1, 6, 3, 1, 1, 4, 1, 0 }; /* snmpTrapIOD.0 */ netsnmp_variable_list *var_list = NULL; netsnmp_table_row *row, *notif_row; netsnmp_table_data_set_storage *col1, *tc, *no, *noo; for(row = table_set->table->first_row; row; row = row->next) { if (strcmp(row->indexes->val.string, eventobjowner) == 0 && strcmp(row->indexes->next_variable->val.string, eventobjname) == 0) { /* run this event */ col1 = (netsnmp_table_data_set_storage *) row->data; tc = netsnmp_table_data_set_find_column(col1, COLUMN_MTEEVENTACTIONS); if (!tc->data.bitstring[0] & 0x80) { /* not a notification. next! (XXX: do sets) */ continue; } tc = netsnmp_table_data_set_find_column(col1, COLUMN_MTEEVENTENABLED); if (*(tc->data.integer) != 1) { /* not enabled. next! */ continue; } if (!mteEventNotif_table_set) { /* no notification info */ continue; } /* send the notification */ var_list = NULL; /* XXX: get notif information */ for(notif_row = mteEventNotif_table_set->table->first_row; notif_row; notif_row = notif_row->next) { if (strcmp(notif_row->indexes->val.string, eventobjowner) == 0 && strcmp(notif_row->indexes->next_variable->val.string, eventobjname) == 0) { /* run this event */ col1 = (netsnmp_table_data_set_storage *) notif_row->data; tc = netsnmp_table_data_set_find_column(col1, COLUMN_MTEEVENTNOTIFICATION); no = netsnmp_table_data_set_find_column(col1, COLUMN_MTEEVENTNOTIFICATIONOBJECTS); noo = netsnmp_table_data_set_find_column(col1, COLUMN_MTEEVENTNOTIFICATIONOBJECTSOWNER); if (!tc) continue; /* no notification to be had. XXX: return? */ /* * snmpTrap oid */ snmp_varlist_add_variable(&var_list, objid_snmptrap, sizeof(objid_snmptrap) / sizeof(oid), ASN_OBJECT_ID, (u_char *) tc->data.objid, tc->data_len); /* XXX: add objects from the mteObjectsTable */ DEBUGMSGTL(("mteEventTable:send_events", "no: %x, no->data: %s", no, no->data.string)); DEBUGMSGTL(("mteEventTable:send_events", "noo: %x, noo->data: %s", noo, noo->data.string)); DEBUGMSGTL(("mteEventTable:send_events", "name_oid: %x",name_oid)); if (no && no->data.string && noo && noo->data.string && name_oid) { char *tmpowner = netsnmp_strdup_and_null(noo->data.string, noo->data_len); char *tmpname = netsnmp_strdup_and_null(no->data.string, no->data_len); DEBUGMSGTL(("mteEventTable:send_events", "Adding objects for owner=%s name=%s", tmpowner, tmpname)); mte_add_objects(var_list, item, tmpowner, tmpname, name_oid + item->mteTriggerValueIDLen, name_oid_len - item->mteTriggerValueIDLen); free(tmpowner); free(tmpname); } DEBUGMSGTL(("mteEventTable:send_events", "sending an event ")); DEBUGMSGOID(("mteEventTable:send_events", tc->data.objid, tc->data_len / sizeof(oid))); DEBUGMSG(("mteEventTable:send_events", "\n")); send_v2trap(var_list); snmp_free_varbind(var_list); } } } } }
/** ************************************************************************** * * cert rows * */ netsnmp_variable_list * cert_row_create(uint32_t priority, int hash_type, const char *fp, const oid *map_type, int map_type_len, const u_char *data, int data_len, uint32_t st, int *row_status_index) { oid name[] = { SNMP_TLS_TM_CERT_TABLE, 1, -1, -1 }; int name_len = OID_LENGTH(name), col_pos = name_len - 2; int rc, rs_index = 4; u_char bin_fp[SNMP_MAXBUF_SMALL], *bin_fp_ptr = bin_fp; u_int rs; size_t bin_fp_len; netsnmp_variable_list *vl = NULL, *vb; netsnmp_require_ptr_LRV( fp, NULL ); DEBUGMSGT(("cert:create", "creating varbinds for pri %d, fp %s\n", priority, fp)); bin_fp_len = sizeof(bin_fp); rc = netsnmp_tls_fingerprint_build(hash_type, fp, &bin_fp_ptr, &bin_fp_len, 0); name[name_len-1] = priority; name[col_pos] = COL_SNMPTLSTMCERTTOTSN_FINGERPRINT; vl = snmp_varlist_add_variable(&vl, name, name_len, ASN_OCTET_STR, &bin_fp, bin_fp_len); netsnmp_require_ptr_LRV(vl, NULL); if (map_type_len && map_type) { name[col_pos] = COL_SNMPTLSTMCERTTOTSN_MAPTYPE; vb = snmp_varlist_add_variable(&vl, name, name_len, ASN_OBJECT_ID, map_type, map_type_len * sizeof(oid)); if (NULL == vb) { snmp_free_varbind(vl); return NULL; } } else --rs_index; if (data) { name[col_pos] = COL_SNMPTLSTMCERTTOTSN_DATA; vb = snmp_varlist_add_variable(&vl, name, name_len, ASN_OCTET_STR, data, data_len); if (NULL == vb) { snmp_free_varbind(vl); return NULL; } } else --rs_index; if (st) { name[col_pos] = COL_SNMPTLSTMCERTTOTSN_STORAGETYPE; vb = snmp_varlist_add_variable(&vl, name, name_len, ASN_INTEGER, &st, sizeof(st)); if (NULL == vb) { snmp_free_varbind(vl); return NULL; } } else --rs_index; name[col_pos] = COL_SNMPTLSTMCERTTOTSN_ROWSTATUS; rs = RS_CREATEANDGO; vb = snmp_varlist_add_variable(&vl, name, name_len, ASN_INTEGER, &rs, sizeof(rs)); if (NULL == vb) { snmp_free_varbind(vl); return NULL; } if (row_status_index) *row_status_index = rs_index; return vl; }
/** implements the table_iterator helper */ int netsnmp_table_iterator_helper_handler(netsnmp_mib_handler *handler, netsnmp_handler_registration *reginfo, netsnmp_agent_request_info *reqinfo, netsnmp_request_info *requests) { netsnmp_table_registration_info *tbl_info; oid coloid[MAX_OID_LEN]; size_t coloid_len; int ret; static oid myname[MAX_OID_LEN]; size_t myname_len; int oldmode; netsnmp_iterator_info *iinfo; iinfo = (netsnmp_iterator_info *) handler->myvoid; if (!iinfo || !reginfo || !reqinfo) return SNMPERR_GENERR; tbl_info = iinfo->table_reginfo; /* * copy in the table registration oid for later use */ coloid_len = reginfo->rootoid_len + 2; memcpy(coloid, reginfo->rootoid, reginfo->rootoid_len * sizeof(oid)); coloid[reginfo->rootoid_len] = 1; /* table.entry node */ /* * illegally got here if these functions aren't defined */ if (iinfo->get_first_data_point == NULL || iinfo->get_next_data_point == NULL) { snmp_log(LOG_ERR, "table_iterator helper called without data accessor functions\n"); return SNMP_ERR_GENERR; } /* * XXXWWW: deal with SET caching */ #ifdef NOT_SERIALIZED while (requests) /* XXX: currently only serialized */ #endif { /* * XXXWWW: optimize by reversing loops (look through data only once) */ netsnmp_variable_list *results = NULL; netsnmp_variable_list *index_search = NULL; /* WWW: move up? */ netsnmp_variable_list *free_this_index_search = NULL; netsnmp_table_request_info *table_info = netsnmp_extract_table_info(requests); void *callback_loop_context = NULL; void *callback_data_context = NULL; void *callback_data_keep = NULL; if (requests->processed != 0) { #ifdef NOT_SERIALIZED continue; #else return SNMP_ERR_NOERROR; #endif } if (reqinfo->mode != MODE_GET && reqinfo->mode != MODE_GETNEXT && reqinfo->mode != MODE_GETBULK && /* XXX */ reqinfo->mode != MODE_SET_RESERVE1) { goto skip_processing; } if (table_info->colnum > tbl_info->max_column) { requests->processed = 1; #ifdef NOT_SERIALIZED break; #else return SNMP_ERR_NOERROR; #endif } /* * XXX: if loop through everything, these are never free'd * since iterator returns NULL and thus we forget about * these */ index_search = snmp_clone_varbind(table_info->indexes); if (!index_search) { /* * hmmm.... invalid table? */ snmp_log(LOG_WARNING, "invalid index list or failed malloc for table %s\n", reginfo->handlerName); return SNMP_ERR_NOERROR; } free_this_index_search = index_search; /* * below our minimum column? */ if (table_info->colnum < tbl_info->min_column) { results = (iinfo->get_first_data_point) (&callback_loop_context, &callback_data_context, index_search, iinfo); if (iinfo->free_loop_context) { (iinfo->free_loop_context) (callback_loop_context, iinfo); callback_loop_context = NULL; } goto got_results; } /* * XXX: do "only got some indexes" */ /* * find the next legal result to return */ /* * find the first node */ index_search = (iinfo->get_first_data_point) (&callback_loop_context, &callback_data_context, index_search, iinfo); /* * table.entry.column node */ coloid[reginfo->rootoid_len + 1] = table_info->colnum; switch (reqinfo->mode) { case MODE_GETNEXT: case MODE_GETBULK: /* XXXWWW */ /* * loop through all data and find next one */ while (index_search) { /* * compare the node with previous results */ if (netsnmp_check_getnext_reply (requests, coloid, coloid_len, index_search, &results)) { /* * result is our current choice, so keep a pointer to * the data that the lower handler wants us to * remember (possibly freeing the last known "good" * result data pointer) */ if (callback_data_keep && iinfo->free_data_context) { (iinfo->free_data_context) (callback_data_keep, iinfo); callback_data_keep = NULL; } if (iinfo->make_data_context && !callback_data_context) { callback_data_context = (iinfo-> make_data_context) (callback_loop_context, iinfo); } callback_data_keep = callback_data_context; callback_data_context = NULL; } else { if (callback_data_context && iinfo->free_data_context) (iinfo->free_data_context) (callback_data_context, iinfo); callback_data_context = NULL; } /* * get the next node in the data chain */ index_search = (iinfo->get_next_data_point) (&callback_loop_context, &callback_data_context, index_search, iinfo); if (!index_search && !results && tbl_info->max_column > table_info->colnum) { /* * restart loop. XXX: Should cache this better */ table_info->colnum++; coloid[reginfo->rootoid_len + 1] = table_info->colnum; if (free_this_index_search != NULL) snmp_free_varbind(free_this_index_search); index_search = snmp_clone_varbind(table_info->indexes); free_this_index_search = index_search; if (callback_loop_context && iinfo->free_loop_context_at_end) { (iinfo->free_loop_context_at_end)(callback_loop_context, iinfo); callback_loop_context = NULL; } if (iinfo->free_loop_context && callback_loop_context) { (iinfo->free_loop_context) (callback_loop_context, iinfo); callback_loop_context = NULL; } if (callback_data_context && iinfo->free_data_context) { (iinfo->free_data_context) (callback_data_context, iinfo); callback_data_context = NULL; } index_search = (iinfo-> get_first_data_point) (&callback_loop_context, &callback_data_context, index_search, iinfo); } } break; case MODE_GET: case MODE_SET_RESERVE1: /* * loop through all data till exact results are found */ while (index_search) { build_oid_noalloc(myname, MAX_OID_LEN, &myname_len, coloid, coloid_len, index_search); if (snmp_oid_compare(myname, myname_len, requests->requestvb->name, requests->requestvb->name_length) == 0) { /* * found the exact match, so we're done */ if (iinfo->make_data_context && !callback_data_context) { callback_data_context = (iinfo-> make_data_context) (callback_loop_context, iinfo); } callback_data_keep = callback_data_context; callback_data_context = NULL; results = snmp_clone_varbind(index_search); snmp_set_var_objid(results, myname, myname_len); goto got_results; } else { /* * free not-needed data context */ if (callback_data_context && iinfo->free_data_context) { (iinfo->free_data_context) (callback_data_context, iinfo); callback_data_context = NULL; } } /* * get the next node in the data chain */ index_search = (iinfo->get_next_data_point) (&callback_loop_context, &callback_data_context, index_search, iinfo); } break; default: /* * the rest of the set states have been dealt with already */ goto got_results; } /* * XXX: free index_search? */ if (callback_loop_context && iinfo->free_loop_context) { (iinfo->free_loop_context) (callback_loop_context, iinfo); callback_loop_context = NULL; } got_results: /* not milk */ /* * This free_data_context call is required in the event that your * get_next_data_point method allocates new memory, even during the * calls where it eventually returns a NULL */ if (callback_data_context && iinfo->free_data_context) { (iinfo->free_data_context) (callback_data_context, iinfo); callback_data_context = NULL; } if (!results && !MODE_IS_SET(reqinfo->mode)) { /* * no results found. */ /* * XXX: check for at least one entry at the very top */ #ifdef NOT_SERIALIZED break; #else if (callback_loop_context && iinfo->free_loop_context_at_end) { (iinfo->free_loop_context_at_end) (callback_loop_context, iinfo); callback_loop_context = NULL; } if (free_this_index_search != NULL) { snmp_free_varbind(free_this_index_search); } return SNMP_ERR_NOERROR; #endif } skip_processing: /* * OK, here results should be a pointer to the data that we * actually need to GET */ oldmode = reqinfo->mode; if (reqinfo->mode == MODE_GETNEXT || reqinfo->mode == MODE_GETBULK) { /* XXX */ snmp_set_var_objid(requests->requestvb, results->name, results->name_length); reqinfo->mode = MODE_GET; } if (reqinfo->mode == MODE_GET || reqinfo->mode == MODE_GETNEXT || reqinfo->mode == MODE_GETBULK || /* XXX */ reqinfo->mode == MODE_SET_RESERVE1) { /* * first (or only) pass stuff */ /* * let set requsets use previously constructed data */ snmp_free_varbind(results); if (callback_data_keep) netsnmp_request_add_list_data(requests, netsnmp_create_data_list (TABLE_ITERATOR_NAME, callback_data_keep, NULL)); netsnmp_request_add_list_data(requests, netsnmp_create_data_list (TABLE_ITERATOR_LAST_CONTEXT, callback_loop_context, NULL)); } DEBUGMSGTL(("table_iterator", "doing mode: %s\n", se_find_label_in_slist("agent_mode", oldmode))); ret = netsnmp_call_next_handler(handler, reginfo, reqinfo, requests); if (oldmode == MODE_GETNEXT || oldmode == MODE_GETBULK) { /* XXX */ if (requests->requestvb->type == ASN_NULL || requests->requestvb->type == SNMP_NOSUCHINSTANCE) { /* * get next skipped this value for this column, we * need to keep searching forward */ requests->requestvb->type = ASN_PRIV_RETRY; } reqinfo->mode = oldmode; } callback_data_keep = netsnmp_request_get_list_data(requests, TABLE_ITERATOR_NAME); callback_loop_context = netsnmp_request_get_list_data(requests, TABLE_ITERATOR_LAST_CONTEXT); /* * This has to be done to prevent a memory leak. Notice that on * SET_RESERVE1 we're assigning something to * 'free_this_index_search' at the beginning of this handler (right * above the line that says 'below our minimum column?'), * but we're not given a chance to free it below with the other * SET modes, hence our doing it here. */ if (reqinfo->mode == MODE_SET_RESERVE1) { if (free_this_index_search) { snmp_free_varbind(free_this_index_search); free_this_index_search = NULL; } } if (reqinfo->mode == MODE_GET || reqinfo->mode == MODE_GETNEXT || reqinfo->mode == MODE_GETBULK || /* XXX */ reqinfo->mode == MODE_SET_FREE || reqinfo->mode == MODE_SET_UNDO || reqinfo->mode == MODE_SET_COMMIT) { if (callback_data_keep && iinfo->free_data_context) { (iinfo->free_data_context) (callback_data_keep, iinfo); callback_data_keep = NULL; } if (free_this_index_search) { snmp_free_varbind(free_this_index_search); free_this_index_search = NULL; } #ifndef NOT_SERIALIZED if (callback_loop_context && iinfo->free_loop_context_at_end) { (iinfo->free_loop_context_at_end) (callback_loop_context, iinfo); callback_loop_context = NULL; } #endif } #ifdef NOT_SERIALIZED return ret; #else requests = requests->next; #endif } #ifdef NOT_SERIALIZED if (reqinfo->mode == MODE_GET || reqinfo->mode == MODE_GETNEXT || reqinfo->mode == MODE_GETBULK || /* XXX */ reqinfo->mode == MODE_SET_FREE || reqinfo->mode == MODE_SET_UNDO || reqinfo->mode == MODE_SET_COMMIT) { if (callback_loop_context && iinfo->free_loop_context_at_end) { (iinfo->free_loop_context_at_end) (callback_loop_context, iinfo); callback_loop_context = NULL; } } #endif return SNMP_ERR_NOERROR; }
static void event_send_trap(CRTL_ENTRY_T * evptr, u_char is_rising, u_int alarm_index, u_int value, u_int the_threshold, oid * alarmed_var, size_t alarmed_var_length, u_int sample_type) { static oid rmon1_trap_oid[] = { 1, 3, 6, 1, 2, 1, 16, 0, 0 }; static oid alarm_index_oid[] = { 1, 3, 6, 1, 2, 1, 16, 3, 1, 1, 1 }; static oid alarmed_var_oid[] = { 1, 3, 6, 1, 2, 1, 16, 3, 1, 1, 3 }; static oid sample_type_oid[] = { 1, 3, 6, 1, 2, 1, 16, 3, 1, 1, 4 }; static oid value_oid[] = { 1, 3, 6, 1, 2, 1, 16, 3, 1, 1, 5 }; static oid threshold_oid[] = { 1, 3, 6, 1, 2, 1, 16, 3, 1, 1, 7 }; /* rising case */ netsnmp_variable_list *top = NULL; register int iii; /* * set the last 'oid' : risingAlarm or fallingAlarm */ if (is_rising) { iii = OID_LENGTH(rmon1_trap_oid); rmon1_trap_oid[iii - 1] = 1; iii = OID_LENGTH(threshold_oid); threshold_oid[iii - 1] = 7; } else { iii = OID_LENGTH(rmon1_trap_oid); rmon1_trap_oid[iii - 1] = 0; iii = OID_LENGTH(threshold_oid); threshold_oid[iii - 1] = 8; } /* * build the var list */ top = oa_bind_var(top, &alarm_index, ASN_INTEGER, sizeof(u_int), alarm_index_oid, OID_LENGTH(alarm_index_oid)); top = oa_bind_var(top, alarmed_var, ASN_OBJECT_ID, sizeof(oid) * alarmed_var_length, alarmed_var_oid, OID_LENGTH(alarmed_var_oid)); top = oa_bind_var(top, &sample_type, ASN_INTEGER, sizeof(u_int), sample_type_oid, OID_LENGTH(sample_type_oid)); top = oa_bind_var(top, &value, ASN_INTEGER, sizeof(u_int), value_oid, OID_LENGTH(value_oid)); top = oa_bind_var(top, &the_threshold, ASN_INTEGER, sizeof(u_int), threshold_oid, OID_LENGTH(threshold_oid)); send_enterprise_trap_vars(SNMP_TRAP_ENTERPRISESPECIFIC, 0, rmon1_trap_oid, OID_LENGTH(rmon1_trap_oid), top); ag_trace("rmon trap has been sent"); snmp_free_varbind(top); }