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 + -
显示快捷键?