📄 agent_registry.c
字号:
/*
* OK - we've now located where the new entry needs to
* be fitted into the index registry tree
* To recap:
* 'prev_oid_ptr' points to the head of the OID index
* list prior to this one. If this is null, then
* it means that this is the first OID in the list.
* 'idxptr' points either to the head of this OID list,
* or the next OID (if this is a new OID request)
* These can be distinguished by the value of 'res'.
*
* 'prev_idx_ptr' points to the index entry that sorts
* immediately prior to the requested value (if any).
* If an arbitrary value is required, then this will
* point to the last allocated index.
* If this pointer is null, then either this is a new
* OID request, or the requested value is the first
* in the list.
* 'idxptr2' points to the next sorted index (if any)
* but is not actually needed any more.
*
* Clear? Good!
* I hope you've been paying attention.
* There'll be a test later :-)
*/
/*
* We proceed by creating the new entry
* (by copying the entry provided)
*/
new_index = (struct snmp_index *)malloc( sizeof( struct snmp_index ));
if (new_index == NULL)
return NULL;
if (snmp_clone_var( varbind, &new_index->varbind ) != 0 ) {
free( new_index );
return NULL;
}
new_index->session = ss;
if ( varbind->type == ASN_OCTET_STR && flags == ALLOCATE_THIS_INDEX )
new_index->varbind.val.string[new_index->varbind.val_len] = 0;
/*
* If we've been given a value, then we can use that, but
* otherwise, we need to create a new value for this entry.
* Note that ANY_INDEX and NEW_INDEX are both covered by this
* test (since NEW_INDEX & ANY_INDEX = ANY_INDEX, remember?)
*/
if ( flags & ALLOCATE_ANY_INDEX ) {
if ( prev_idx_ptr ) {
if ( snmp_clone_var( &prev_idx_ptr->varbind, &new_index->varbind ) != 0 ) {
free( new_index );
return NULL;
}
}
else
new_index->varbind.val.string = new_index->varbind.buf;
switch ( varbind->type ) {
case ASN_INTEGER:
if ( prev_idx_ptr ) {
(*new_index->varbind.val.integer)++;
}
else
*(new_index->varbind.val.integer) = 1;
new_index->varbind.val_len = sizeof(long);
break;
case ASN_OCTET_STR:
if ( prev_idx_ptr ) {
i = new_index->varbind.val_len-1;
while ( new_index->varbind.buf[ i ] == 'z' ) {
new_index->varbind.buf[ i ] = 'a';
i--;
if ( i < 0 ) {
i = new_index->varbind.val_len;
new_index->varbind.buf[ i ] = 'a';
new_index->varbind.buf[ i+1 ] = 0;
}
}
new_index->varbind.buf[ i ]++;
}
else
strcpy((char *)new_index->varbind.buf, "aaaa");
new_index->varbind.val_len = strlen((char *)new_index->varbind.buf);
break;
case ASN_OBJECT_ID:
if ( prev_idx_ptr ) {
i = prev_idx_ptr->varbind.val_len/sizeof(oid) -1;
while ( new_index->varbind.val.objid[ i ] == 255 ) {
new_index->varbind.val.objid[ i ] = 1;
i--;
if ( i == 0 && new_index->varbind.val.objid[0] == 2 ) {
new_index->varbind.val.objid[ 0 ] = 1;
i = new_index->varbind.val_len/sizeof(oid);
new_index->varbind.val.objid[ i ] = 0;
new_index->varbind.val_len += sizeof(oid);
}
}
new_index->varbind.val.objid[ i ]++;
}
else {
/* If the requested OID name is small enough,
* append another OID (1) and use this as the
* default starting value for new indexes.
*/
if ( (varbind->name_length+1) * sizeof(oid) <= 40 ) {
for ( i = 0 ; i < (int)varbind->name_length ; i++ )
new_index->varbind.val.objid[i] = varbind->name[i];
new_index->varbind.val.objid[varbind->name_length] = 1;
new_index->varbind.val_len =
(varbind->name_length+1) * sizeof(oid);
}
else {
/* Otherwise use '.1.1.1.1...' */
i = 40/sizeof(oid);
if ( i > 4 )
i = 4;
new_index->varbind.val_len = i * (sizeof(oid));
for (i-- ; i>=0 ; i-- )
new_index->varbind.val.objid[i] = 1;
}
}
break;
default:
free( new_index );
return NULL; /* Index type not supported */
}
}
/*
* Right - we've set up the new entry.
* All that remains is to link it into the tree.
* There are a number of possible cases here,
* so watch carefully.
*/
if ( prev_idx_ptr ) {
new_index->next_idx = prev_idx_ptr->next_idx;
new_index->next_oid = prev_idx_ptr->next_oid;
prev_idx_ptr->next_idx = new_index;
}
else {
if ( res == 0 && idxptr ) {
new_index->next_idx = idxptr;
new_index->next_oid = idxptr->next_oid;
}
else {
new_index->next_idx = NULL;
new_index->next_oid = idxptr;
}
if ( prev_oid_ptr ) {
while ( prev_oid_ptr ) {
prev_oid_ptr->next_oid = new_index;
prev_oid_ptr = prev_oid_ptr->next_idx;
}
}
else
snmp_index_head = new_index;
}
return &new_index->varbind;
}
/*
* Release an allocated index,
* to allow it to be used elsewhere
*/
int
release_index(struct variable_list *varbind)
{
return( unregister_index( varbind, TRUE, NULL ));
}
/*
* Completely remove an allocated index,
* due to errors in the registration process.
*/
int
remove_index(struct variable_list *varbind, struct snmp_session *ss)
{
return( unregister_index( varbind, FALSE, ss ));
}
void
unregister_index_by_session(struct snmp_session *ss)
{
struct snmp_index *idxptr, *idxptr2;
for(idxptr = snmp_index_head ; idxptr != NULL; idxptr = idxptr->next_oid)
for(idxptr2 = idxptr ; idxptr2 != NULL; idxptr2 = idxptr2->next_idx)
if ( idxptr2->session == ss )
idxptr2->session = NULL;
}
int
unregister_index(struct variable_list *varbind, int remember, struct snmp_session *ss)
{
struct snmp_index *idxptr, *idxptr2;
struct snmp_index *prev_oid_ptr, *prev_idx_ptr;
int res, res2, i;
#if defined(USING_AGENTX_SUBAGENT_MODULE) && !defined(TESTING)
if (ds_get_boolean(DS_APPLICATION_ID, DS_AGENT_ROLE) == SUB_AGENT )
return( agentx_unregister_index( ss, varbind ));
#endif
/* Look for the requested OID entry */
prev_oid_ptr = NULL;
prev_idx_ptr = NULL;
res = 1;
res2 = 1;
for( idxptr = snmp_index_head ; idxptr != NULL;
prev_oid_ptr = idxptr, idxptr = idxptr->next_oid) {
if ((res = snmp_oid_compare(varbind->name, varbind->name_length,
idxptr->varbind.name,
idxptr->varbind.name_length)) <= 0 )
break;
}
if ( res != 0 )
return INDEX_ERR_NOT_ALLOCATED;
if ( varbind->type != idxptr->varbind.type )
return INDEX_ERR_WRONG_TYPE;
for(idxptr2 = idxptr ; idxptr2 != NULL;
prev_idx_ptr = idxptr2, idxptr2 = idxptr2->next_idx) {
i = SNMP_MIN(varbind->val_len, idxptr2->varbind.val_len);
res2 = memcmp(varbind->val.string, idxptr2->varbind.val.string, i);
if ( res2 <= 0 )
break;
}
if ( res2 != 0 )
return INDEX_ERR_NOT_ALLOCATED;
if ( ss != idxptr2->session )
return INDEX_ERR_WRONG_SESSION;
/*
* If this is a "normal" index unregistration,
* mark the index entry as unused, but leave
* it in situ. This allows differentiation
* between ANY_INDEX and NEW_INDEX
*/
if ( remember ) {
idxptr2->session = NULL; /* Unused index */
return SNMP_ERR_NOERROR;
}
/*
* If this is a failed attempt to register a
* number of indexes, the successful ones
* must be removed completely.
*/
if ( prev_idx_ptr ) {
prev_idx_ptr->next_idx = idxptr2->next_idx;
}
else if ( prev_oid_ptr ) {
if ( idxptr2->next_idx ) /* Use p_idx_ptr as a temp variable */
prev_idx_ptr = idxptr2->next_idx;
else
prev_idx_ptr = idxptr2->next_oid;
while ( prev_oid_ptr ) {
prev_oid_ptr->next_oid = prev_idx_ptr;
prev_oid_ptr = prev_oid_ptr->next_idx;
}
}
else {
if ( idxptr2->next_idx )
snmp_index_head = idxptr2->next_idx;
else
snmp_index_head = idxptr2->next_oid;
}
snmp_free_var( (struct variable_list *)idxptr2 );
return SNMP_ERR_NOERROR;
}
void dump_registry( void )
{
struct subtree *myptr, *myptr2;
struct snmp_index *idxptr, *idxptr2;
char start_oid[SPRINT_MAX_LEN];
char end_oid[SPRINT_MAX_LEN];
for( myptr = subtrees ; myptr != NULL; myptr = myptr->next) {
sprint_objid(start_oid, myptr->start, myptr->start_len);
sprint_objid(end_oid, myptr->end, myptr->end_len);
printf("%c %s - %s %c\n",
( myptr->variables ? ' ' : '(' ),
start_oid, end_oid,
( myptr->variables ? ' ' : ')' ));
for( myptr2 = myptr ; myptr2 != NULL; myptr2 = myptr2->children) {
if ( myptr2->label && myptr2->label[0] )
printf("\t%s\n", myptr2->label);
}
}
if ( snmp_index_head )
printf("\nIndex Allocations:\n");
for( idxptr = snmp_index_head ; idxptr != NULL; idxptr = idxptr->next_oid) {
sprint_objid(start_oid, idxptr->varbind.name, idxptr->varbind.name_length);
printf("%s indexes:\n", start_oid);
for( idxptr2 = idxptr ; idxptr2 != NULL; idxptr2 = idxptr2->next_idx) {
switch( idxptr2->varbind.type ) {
case ASN_INTEGER:
printf(" %c %ld %c\n",
( idxptr2->session ? ' ' : '(' ),
*idxptr2->varbind.val.integer,
( idxptr2->session ? ' ' : ')' ));
break;
case ASN_OCTET_STR:
printf(" %c %s %c\n",
( idxptr2->session ? ' ' : '(' ),
idxptr2->varbind.val.string,
( idxptr2->session ? ' ' : ')' ));
break;
case ASN_OBJECT_ID:
sprint_objid(end_oid, idxptr2->varbind.val.objid,
idxptr2->varbind.val_len/sizeof(oid));
printf(" %c %s %c\n",
( idxptr2->session ? ' ' : '(' ),
end_oid,
( idxptr2->session ? ' ' : ')' ));
break;
default:
printf("unsupported type (%d)\n",
idxptr2->varbind.type);
}
}
}
}
#ifdef TESTING
struct variable_list varbind;
struct snmp_session main_sess, *main_session=&main_sess;
void
test_string_register( int n, char *cp )
{
varbind.name[4] = n;
if (register_string_index(varbind.name, varbind.name_length, cp) == NULL)
printf("allocating %s failed\n", cp);
}
void
test_int_register( int n, int val )
{
varbind.name[4] = n;
if (register_int_index( varbind.name, varbind.name_length, val ) == -1 )
printf("allocating %d/%d failed\n", n, val);
}
void
test_oid_register( int n, int subid )
{
struct variable_list *res;
varbind.name[4] = n;
if ( subid != -1 ) {
varbind.val.objid[5] = subid;
res = register_oid_index(varbind.name, varbind.name_length,
varbind.val.objid,
varbind.val_len/sizeof(oid) );
}
else
res = register_oid_index(varbind.name, varbind.name_length, NULL, 0);
if (res == NULL )
printf("allocating %d/%d failed\n", n, subid);
}
void
main( int argc, char argv[] )
{
oid name[] = { 1, 2, 3, 4, 0 };
int i;
memset( &varbind, 0, sizeof(struct variable_list));
snmp_set_var_objid( &varbind, name, 5 );
varbind.type = ASN_OCTET_STR;
/*
* Test index structure linking:
* a) sorted by OID
*/
test_string_register( 20, "empty OID" );
test_string_register( 10, "first OID" );
test_string_register( 40, "last OID" );
test_string_register( 30, "middle OID" );
/*
* b) sorted by index value
*/
test_string_register( 25, "eee: empty IDX" );
test_string_register( 25, "aaa: first IDX" );
test_string_register( 25, "zzz: last IDX" );
test_string_register( 25, "mmm: middle IDX" );
printf("This next one should fail....\n");
test_string_register( 25, "eee: empty IDX" ); /* duplicate */
printf("done\n");
/*
* c) test initial index linking
*/
test_string_register( 5, "eee: empty initial IDX" );
test_string_register( 5, "aaa: replace initial IDX" );
/*
* Did it all work?
*/
dump_registry();
unregister_index_by_session( main_session );
/*
* Now test index allocation
* a) integer values
*/
test_int_register( 110, -1 ); /* empty */
test_int_register( 110, -1 ); /* append */
test_int_register( 110, 10 ); /* append exact */
printf("This next one should fail....\n");
test_int_register( 110, 10 ); /* exact duplicate */
printf("done\n");
test_int_register( 110, -1 ); /* append */
test_int_register( 110, 5 ); /* insert exact */
/*
* b) string values
*/
test_string_register( 120, NULL ); /* empty */
test_string_register( 120, NULL ); /* append */
test_string_register( 120, "aaaz" );
test_string_register( 120, NULL ); /* minor rollover */
test_string_register( 120, "zzzz" );
test_string_register( 120, NULL ); /* major rollover */
/*
* c) OID values
*/
test_oid_register( 130, -1 ); /* empty */
test_oid_register( 130, -1 ); /* append */
varbind.val_len = varbind.name_length*sizeof(oid);
memcpy( varbind.buf, varbind.name, varbind.val_len);
varbind.val.objid = (oid*) varbind.buf;
varbind.val_len += sizeof(oid);
test_oid_register( 130, 255 ); /* append exact */
test_oid_register( 130, -1 ); /* minor rollover */
test_oid_register( 130, 100 ); /* insert exact */
printf("This next one should fail....\n");
test_oid_register( 130, 100 ); /* exact duplicate */
printf("done\n");
varbind.val.objid = (oid*)varbind.buf;
for ( i=0; i<6; i++ )
varbind.val.objid[i]=255;
varbind.val.objid[0]=1;
test_oid_register( 130, 255 ); /* set up rollover */
test_oid_register( 130, -1 ); /* medium rollover */
for ( i=0; i<6; i++ )
varbind.val.objid[i]=255;
varbind.val.objid[0]=2;
test_oid_register( 130, 255 ); /* set up rollover */
test_oid_register( 130, -1 ); /* major rollover */
/*
* Did it all work?
*/
dump_registry();
/*
* Test the various "invalid" requests
* (unsupported types, mis-matched types, etc)
*/
printf("The rest of these should fail....\n");
test_oid_register( 110, -1 );
test_oid_register( 110, 100 );
test_oid_register( 120, -1 );
test_oid_register( 120, 100 );
test_string_register( 110, NULL );
test_string_register( 110, "aaaa" );
test_string_register( 130, NULL );
test_string_register( 130, "aaaa" );
test_int_register( 120, -1 );
test_int_register( 120, 1 );
test_int_register( 130, -1 );
test_int_register( 130, 1 );
printf("done - this dump should be the same as before\n");
dump_registry();
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -