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