snmp_agent.c

来自「eCos操作系统源码」· C语言 代码 · 共 887 行 · 第 1/2 页

C
887
字号
	    allDone = TRUE;		/* Check for some content */	    for ( var_ptr = asp->start;		  var_ptr != asp->end->next_variable;		  var_ptr = var_ptr->next_variable ) {				/* XXX: we don't know the size of the next					OID, so assume the maximum length */		if ( var_ptr->type != SNMP_ENDOFMIBVIEW )		{		var_ptr2 = snmp_add_null_var(asp->pdu, var_ptr->name, MAX_OID_LEN);		for ( i=var_ptr->name_length ; i<MAX_OID_LEN ; i++)		    var_ptr2->name[i] = 0;		var_ptr2->name_length = var_ptr->name_length;		    allDone = FALSE;		}	    }	    if ( allDone )		break;	    asp->start = asp->end->next_variable;	    while ( asp->end->next_variable != NULL )		asp->end = asp->end->next_variable;	    	    status = handle_next_pass( asp );	    if ( status != SNMP_ERR_NOERROR )		break;	    if ( asp->outstanding_requests != NULL )		return 1;	}	break;    case SNMP_MSG_SET:    	    /*	     * SETS require 3-4 passes through the var_op_list.  The first two	     * passes verify that all types, lengths, and values are valid	     * and may reserve resources and the third does the set and a	     * fourth executes any actions.  Then the identical GET RESPONSE	     * packet is returned.	     * If either of the first two passes returns an error, another	     * pass is made so that any reserved resources can be freed.	     * If the third pass returns an error, another pass is made so that	     * any changes can be reversed.	     * If the fourth pass (or any of the error handling passes)	     * return an error, we'd rather not know about it!	     */	if ( asp->mode == RESERVE1 ) {            snmp_increment_statistic(STAT_SNMPINSETREQUESTS);	    asp->rw      = WRITE;	    status = handle_next_pass( asp );	    if ( status != SNMP_ERR_NOERROR )	        asp->mode = FREE;	    else	        asp->mode = RESERVE2;	    if ( asp->outstanding_requests != NULL )		return 1;	}	if ( asp->mode == RESERVE2 ) {	    status = handle_next_pass( asp );	    if ( status != SNMP_ERR_NOERROR )	        asp->mode = FREE;	    else	        asp->mode = ACTION;	    if ( asp->outstanding_requests != NULL )		return 1;	}	if ( asp->mode == ACTION ) {	    status = handle_next_pass( asp );	    if ( status != SNMP_ERR_NOERROR )	        asp->mode = UNDO;	    else	        asp->mode = COMMIT;	    if ( asp->outstanding_requests != NULL )		return 1;	}	if ( asp->mode == COMMIT ) {	    status = handle_next_pass( asp );	    if ( status != SNMP_ERR_NOERROR ) {		status    = SNMP_ERR_COMMITFAILED;	        asp->mode = FINISHED_FAILURE;	    }	    else	        asp->mode = FINISHED_SUCCESS;	    if ( asp->outstanding_requests != NULL )		return 1;	}	if ( asp->mode == UNDO ) {	    if (handle_next_pass( asp ) != SNMP_ERR_NOERROR )		status = SNMP_ERR_UNDOFAILED;	    asp->mode = FINISHED_FAILURE;	    break;	}	if ( asp->mode == FREE ) {	    (void) handle_next_pass( asp );	    break;	}	break;    case SNMP_MSG_RESPONSE:        snmp_increment_statistic(STAT_SNMPINGETRESPONSES);	free( asp );	return 0;    case SNMP_MSG_TRAP:    case SNMP_MSG_TRAP2:        snmp_increment_statistic(STAT_SNMPINTRAPS);	free( asp );	return 0;    default:        snmp_increment_statistic(STAT_SNMPINASNPARSEERRS);	free( asp );	return 0;    }    if ( asp->outstanding_requests != NULL ) {	asp->status = status;	asp->next = agent_session_list;	agent_session_list = asp;    }    else {		/*		 * May need to "dumb down" a SET error status for a		 *  v1 query.  See RFC2576 - section 4.3		 */	if (( asp->pdu->command == SNMP_MSG_SET ) &&	    ( asp->pdu->version == SNMP_VERSION_1 )) {	    switch ( status ) {		case SNMP_ERR_WRONGVALUE:		case SNMP_ERR_WRONGENCODING:		case SNMP_ERR_WRONGTYPE:		case SNMP_ERR_WRONGLENGTH:		case SNMP_ERR_INCONSISTENTVALUE:			status = SNMP_ERR_BADVALUE;			break;		case SNMP_ERR_NOACCESS:		case SNMP_ERR_NOTWRITABLE:		case SNMP_ERR_NOCREATION:		case SNMP_ERR_INCONSISTENTNAME:		case SNMP_ERR_AUTHORIZATIONERROR:			status = SNMP_ERR_NOSUCHNAME;			break;		case SNMP_ERR_RESOURCEUNAVAILABLE:		case SNMP_ERR_COMMITFAILED:		case SNMP_ERR_UNDOFAILED:			status = SNMP_ERR_GENERR;			break;	    }	}		/*		 * Similarly we may need to "dumb down" v2 exception		 *  types to throw an error for a v1 query.		 *  See RFC2576 - section 4.1.2.3		 */	if (( asp->pdu->command != SNMP_MSG_SET ) &&	    ( asp->pdu->version == SNMP_VERSION_1 )) {		for ( var_ptr = asp->pdu->variables, i=0 ;			var_ptr != NULL ;			var_ptr = var_ptr->next_variable, i++ ) {		    switch ( var_ptr->type ) {			case SNMP_NOSUCHOBJECT:			case SNMP_NOSUCHINSTANCE:			case SNMP_ENDOFMIBVIEW:			case ASN_COUNTER64:				status = SNMP_ERR_NOSUCHNAME;				asp->pdu->errindex=i;				break;		    }		}	}	if ( status == SNMP_ERR_NOERROR ) {	    snmp_increment_statistic_by(		(asp->pdu->command == SNMP_MSG_SET ?			STAT_SNMPINTOTALSETVARS : STAT_SNMPINTOTALREQVARS ),	    	count_varbinds( asp->pdu ));	}	else {		/*		 * Use a copy of the original request		 *   to report failures.		 */	    i = asp->pdu->errindex;	    snmp_free_pdu( asp->pdu );	    asp->pdu = snmp_clone_pdu( pdu );	    asp->pdu->errindex = i;	}	asp->pdu->command = SNMP_MSG_RESPONSE;	asp->pdu->errstat = status;	snmp_send( asp->session, asp->pdu );	snmp_increment_statistic(STAT_SNMPOUTPKTS);	snmp_increment_statistic(STAT_SNMPOUTGETRESPONSES);	free( asp );    }    return 1;}inthandle_next_pass(struct agent_snmp_session  *asp){    int status;    struct snmp_pdu *pdu = asp->pdu;    struct request_list *req_p, *next_req;        if ( asp->outstanding_requests != NULL )	    return SNMP_ERR_NOERROR;	status = handle_var_list( asp );        if ( asp->outstanding_requests != NULL ) {	    if ( status == SNMP_ERR_NOERROR ) {		/* Send out any subagent requests */		for ( req_p = asp->outstanding_requests ;			req_p != NULL ; req_p = req_p->next_request ) {		    snmp_async_send( req_p->session,  req_p->pdu,				      req_p->callback, req_p->cb_data );		}		asp->pdu = snmp_clone_pdu( pdu );		asp->pdu->variables = pdu->variables;		pdu->variables = NULL;	    }	    else {	    	/* discard outstanding requests */		for ( req_p = asp->outstanding_requests ;			req_p != NULL ; req_p = next_req ) {						next_req = req_p->next_request;			free( req_p );		}		asp->outstanding_requests = NULL;	    }	}	return status;}inthandle_var_list(struct agent_snmp_session  *asp){    struct variable_list *varbind_ptr;    u_char  statType;    u_char *statP;    size_t  statLen;    u_short acl;    WriteMethod *write_method;    AddVarMethod *add_method;    int	    noSuchObject = TRUE;    int     count, view;        count = 0;    varbind_ptr = asp->start;    if ( !varbind_ptr ) {	return SNMP_ERR_NOERROR;    }    while (1) {    	count++;statp_loop:	statP = getStatPtr(  varbind_ptr->name,			   &varbind_ptr->name_length,			   &statType, &statLen, &acl,			   asp->exact, &write_method, asp->pdu, &noSuchObject);			   	if (statP == NULL && (asp->rw != WRITE || write_method == NULL)) {	        /*  Careful -- if the varbind was lengthy, it will have		    allocated some memory.  */	        snmp_set_var_value(varbind_ptr, NULL, 0);	    	varbind_ptr->val.integer   = NULL;	    	varbind_ptr->val_len = 0;		if ( asp->exact ) {	            if ( noSuchObject == TRUE ){		        statType = SNMP_NOSUCHOBJECT;		    } else {		        statType = SNMP_NOSUCHINSTANCE;		    }		} else {	            statType = SNMP_ENDOFMIBVIEW;		}		if (asp->pdu->version == SNMP_VERSION_1) {		    asp->pdu->errstat = SNMP_ERR_NOSUCHNAME;		    asp->pdu->errindex = count;		    return SNMP_ERR_NOSUCHNAME;		}		else if (asp->rw == WRITE) {		    asp->pdu->errstat =			( noSuchObject	? SNMP_ERR_NOTWRITABLE					: SNMP_ERR_NOCREATION );		    asp->pdu->errindex = count;		    return asp->pdu->errstat;		}		else		    varbind_ptr->type = statType;	}                /* Delegated variables should be added to the                   relevant outgoing request */        else if ( IS_DELEGATED(statType)) {                add_method = (AddVarMethod*)statP;                statType = (*add_method)( asp, varbind_ptr );        }		/* GETNEXT/GETBULK should just skip inaccessible entries */	else if ((view = in_a_view(varbind_ptr->name, &varbind_ptr->name_length,				   asp->pdu, varbind_ptr->type))			 && !asp->exact) {		if (view != 5) send_easy_trap(SNMP_TRAP_AUTHFAIL, 0);		goto statp_loop;	}		/* Other access problems are permanent */	else if (( asp->rw == WRITE && !(acl & 2)) || view) {	    if (asp->pdu->version == SNMP_VERSION_1 || asp->rw != WRITE) {		if (ds_get_boolean(DS_APPLICATION_ID, DS_AGENT_VERBOSE))                  DEBUGMSGTL(("snmp_agent", "    >> noSuchName (read-only)\n"));		ERROR_MSG("read-only");		statType = SNMP_ERR_NOSUCHNAME;	    }	    else {		if (ds_get_boolean(DS_APPLICATION_ID, DS_AGENT_VERBOSE))                  DEBUGMSGTL(("snmp_agent", "    >> notWritable\n"));		ERROR_MSG("Not Writable");		statType = SNMP_ERR_NOTWRITABLE;	    }	    asp->pdu->errstat = statType;	    asp->pdu->errindex = count;	    send_easy_trap(SNMP_TRAP_AUTHFAIL, 0);	    return statType;        }	else {            /* dump verbose info */	    if (ds_get_boolean(DS_APPLICATION_ID, DS_AGENT_VERBOSE) && statP)	        dump_var(varbind_ptr->name, varbind_ptr->name_length,				statType, statP, statLen);		/*  FINALLY we can act on SET requests ....*/	    if ( asp->rw == WRITE ) {	        if ( write_method != NULL ) {		    statType = (*write_method)(asp->mode,                                               varbind_ptr->val.string,                                               varbind_ptr->type,                                               varbind_ptr->val_len, statP,                                               varbind_ptr->name,                                               varbind_ptr->name_length);                    if (statType != SNMP_ERR_NOERROR) {                      asp->pdu->errstat = statType;                      asp->pdu->errindex = count;                      return statType;                    }		}		else {                    if (!goodValue(varbind_ptr->type, varbind_ptr->val_len,                                    statType, statLen)){                        if (asp->pdu->version == SNMP_VERSION_1)                            statType = SNMP_ERR_BADVALUE;                        else                            statType = SNMP_ERR_WRONGTYPE; /* poor approximation */			asp->pdu->errstat = statType;			asp->pdu->errindex = count;			return statType;                    }                    /* actually do the set if necessary */                    if (asp->mode == COMMIT)                        setVariable(varbind_ptr->val.string, varbind_ptr->type,                                    varbind_ptr->val_len, statP, statLen);                }	    }		/* ... or save the results from assorted GETs */	    else {		     snmp_set_var_value(varbind_ptr, statP, statLen);		     varbind_ptr->type = statType;	    }	}		if ( varbind_ptr == asp->end )	     return SNMP_ERR_NOERROR;	varbind_ptr = varbind_ptr->next_variable;	if ( asp->mode == RESERVE1 )	    snmp_vars_inc++;    }}static intgoodValue(u_char inType, 	  size_t inLen,	  u_char actualType,	  size_t actualLen){    if (inLen > actualLen)	return FALSE;    return (inType == actualType);}static voidsetVariable(u_char *var_val,	    u_char var_val_type,	    size_t var_val_len,	    u_char *statP,	    size_t statLen){    size_t buffersize = 1000;    switch(var_val_type){	case ASN_INTEGER:	    asn_parse_int(var_val, &buffersize, &var_val_type, (long *)statP, statLen);	    break;	case ASN_COUNTER:	case ASN_GAUGE:	case ASN_TIMETICKS:	    asn_parse_unsigned_int(var_val, &buffersize, &var_val_type, (u_long *)statP, statLen);	    break;	case ASN_COUNTER64:	    asn_parse_unsigned_int64(var_val, &buffersize, &var_val_type,				     (struct counter64 *)statP, statLen);	    break;	case ASN_OCTET_STR:	case ASN_IPADDRESS:	case ASN_OPAQUE:	case ASN_NSAP:	    asn_parse_string(var_val, &buffersize, &var_val_type, statP, &statLen);	    break;	case ASN_OBJECT_ID:	    asn_parse_objid(var_val, &buffersize, &var_val_type, (oid *)statP, &statLen);	    break;	case ASN_BIT_STR:	    asn_parse_bitstring(var_val, &buffersize, &var_val_type, statP, &statLen);	    break;    }}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?