Example #1
0
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;
    }
}
Example #3
0
/**
 * 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;
}
Example #4
0
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);
}
Example #5
0
/** 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(&notification_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);
}
Example #6
0
/*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(&notification_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(&notification_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(&notification_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);
}
Example #7
0
/*
 *  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 );
}
Example #8
0
/*
 * 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;
}
Example #10
0
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;
}
Example #11
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(&notification_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(&notification_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);

    
}
Example #12
0
/* 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;
}
Example #13
0
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 );
}
Example #14
0
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 );
}
Example #15
0
/**
 * 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;
}
Example #17
0
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;
}
Example #18
0
/** **************************************************************************
 *
 * 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;
}
Example #19
0
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;
    }
}
Example #20
0
/** **************************************************************************
 *
 * 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);
                }
            }
        }
    }
}
Example #22
0
/** **************************************************************************
 *
 * 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;
}
Example #23
0
/** 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;
}
Example #24
0
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);

}