/* * DisMan Expression MIB: * Core implementation of expression object handling */ #include #include #include #include "disman/expr/expObject.h" #include "disman/expr/expExpression.h" netsnmp_tdata *expObject_table_data; /* * Initializes the container for the expression object table, * regardless of which module is initialised first. */ void init_expObject_table_data(void) { DEBUGMSGTL(("disman:expr:init", "init expObject container\n")); if (!expObject_table_data) { expObject_table_data = netsnmp_tdata_create_table("expObjectTable", 0); DEBUGMSGTL(("disman:expr:init", "create expObject container (%p)\n", expObject_table_data)); } } /* Initialize the expObject module */ void init_expObject(void) { init_expObject_table_data(); } /* * Create a new row in the object table */ struct expObject * expObject_createEntry(const char *expOwner, const char *expName, long expIndex, int fixed) { netsnmp_tdata_row *row; row = expObject_createRow(expOwner, expName, expIndex, fixed); return row ? (struct expObject *)row->data : NULL; } netsnmp_tdata_row * expObject_createRow( const char *expOwner, const char *expName, long expIndex, int fixed) { struct expObject *entry; netsnmp_tdata_row *row; size_t expOwner_len = (expOwner) ? strlen(expOwner) : 0; size_t expName_len = (expName) ? strlen(expName) : 0; /* * Create the expObject entry, and the * (table-independent) row wrapper structure... */ entry = SNMP_MALLOC_TYPEDEF(struct expObject); if (!entry) return NULL; row = netsnmp_tdata_create_row(); if (!row) { SNMP_FREE(entry); return NULL; } row->data = entry; /* * ... initialize this row with the indexes supplied * and the default values for the row... */ if (expOwner) memcpy(entry->expOwner, expOwner, expOwner_len); netsnmp_tdata_row_add_index(row, ASN_OCTET_STR, entry->expOwner, expOwner_len); if (expName) memcpy(entry->expName, expName, expName_len); netsnmp_tdata_row_add_index(row, ASN_OCTET_STR, entry->expName, expName_len); entry->expObjectIndex = expIndex; netsnmp_tdata_row_add_index(row, ASN_INTEGER, &entry->expObjectIndex, sizeof(long)); entry->expObjectSampleType = 1; /* absoluteValue */ entry->expObjDiscontinuityType = 1; /* timeTicks */ if (fixed) entry->flags |= EXP_OBJ_FLAG_FIXED; /* * ... and insert the row into the table container. */ netsnmp_tdata_add_row(expObject_table_data, row); return row; } /* * Remove a row from the expression object table */ void expObject_removeEntry(netsnmp_tdata_row * row) { struct expObject *entry; if (!row) return; /* Nothing to remove */ entry = (struct expObject *) netsnmp_tdata_remove_and_delete_row(expObject_table_data, row); if (entry) { if (entry->vars ) snmp_free_varbind( entry->vars ); if (entry->old_vars ) snmp_free_varbind( entry->old_vars ); if (entry->dvars ) snmp_free_varbind( entry->dvars ); if (entry->old_dvars ) snmp_free_varbind( entry->old_dvars ); if (entry->cvars ) snmp_free_varbind( entry->cvars ); SNMP_FREE(entry); } } netsnmp_tdata_row * expObject_getFirst( const char *expOwner, const char *expName ) { netsnmp_tdata_row *row; struct expObject *entry; netsnmp_variable_list owner_var; netsnmp_variable_list name_var; if (!expOwner || !expName) return NULL; /* * Find the first object entry that could potentially * refer to the specified expression... */ memset(&owner_var, 0, sizeof(netsnmp_variable_list)); memset(&name_var, 0, sizeof(netsnmp_variable_list)); snmp_set_var_typed_value( &owner_var, ASN_OCTET_STR, (const u_char*)expOwner, strlen(expOwner)); snmp_set_var_typed_value( &name_var, ASN_OCTET_STR, (const u_char*)expName, strlen(expName)); owner_var.next_variable = &name_var; row = netsnmp_tdata_row_next_byidx( expObject_table_data, &owner_var ); /* * ... and check that it does! */ if (!row || !row->data) return NULL; entry = (struct expObject *)row->data; if ((strcmp( entry->expOwner, expOwner ) != 0) || (strcmp( entry->expName, expName ) != 0)) return NULL; return row; } netsnmp_tdata_row * expObject_getNext( netsnmp_tdata_row *thisRow ) { struct expObject *thisEntry; struct expObject *nextEntry; netsnmp_tdata_row *nextRow; if (!thisRow || !thisRow->data) return NULL; thisEntry = (struct expObject *)thisRow->data; /* * Retrieve the next row, and check whether this * refers to the same expression too. */ nextRow = netsnmp_tdata_row_next( expObject_table_data, thisRow ); if (!nextRow || !nextRow->data) return NULL; nextEntry = (struct expObject *)nextRow->data; if ((strcmp( nextEntry->expOwner, thisEntry->expOwner ) != 0) || (strcmp( nextEntry->expName, thisEntry->expName ) != 0)) return NULL; return nextRow; } netsnmp_variable_list * _expObject_buildList( oid *root, size_t root_len, size_t prefix_len, netsnmp_variable_list *template_list ) { netsnmp_variable_list *query_list = NULL; netsnmp_variable_list *vp1, *vp2 = NULL; oid name[ MAX_OID_LEN ]; int i; if ( prefix_len ) { /* * For wildcarded objects, build a list of all relevant * instances, using the template_list to provide the * necessary instance suffixes. */ memset( name, 0, sizeof(name)); memcpy( name, root, root_len*sizeof(oid)); for ( vp1 = template_list; vp1; vp1=vp1->next_variable ) { /* * Append a new varbind to the list for this object ... */ if ( !query_list ) { query_list = (netsnmp_variable_list*) SNMP_MALLOC_TYPEDEF( netsnmp_variable_list ); vp2 = query_list; } else { vp2->next_variable = (netsnmp_variable_list*) SNMP_MALLOC_TYPEDEF( netsnmp_variable_list ); vp2 = vp2->next_variable; } /* * ... and set the OID using the template suffix */ for ( i=0; i <= vp1->name_length - prefix_len; i++) name[ root_len+i ] = vp1->name[ prefix_len+i ]; snmp_set_var_objid( vp2, name, root_len+i ); } } else { /* * Otherwise, just use the (single) OID provided. */ query_list = (netsnmp_variable_list*) SNMP_MALLOC_TYPEDEF( netsnmp_variable_list ); snmp_set_var_objid( query_list, root, root_len ); } return query_list; } void expObject_getData( struct expExpression *expr, struct expObject *obj ) { netsnmp_variable_list *var; /* * 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 ); } 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 ); 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?) */ netsnmp_query_get( var, expr->session ); if ( obj->cvars ) snmp_free_varbind( obj->cvars ); obj->cvars = var; } }