agent_registry.c
来自「eCos操作系统源码」· C语言 代码 · 共 1,474 行 · 第 1/3 页
C
1,474 行
/* * 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 */intrelease_index(struct variable_list *varbind){ return( unregister_index( varbind, TRUE, NULL ));} /* * Completely remove an allocated index, * due to errors in the registration process. */intremove_index(struct variable_list *varbind, struct snmp_session *ss){ return( unregister_index( varbind, FALSE, ss ));}voidunregister_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;}intunregister_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 TESTINGstruct variable_list varbind;struct snmp_session main_sess, *main_session=&main_sess;voidtest_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);}voidtest_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);}voidtest_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);}voidmain( 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 + =
减小字号Ctrl + -
显示快捷键?