//* //*--------------------------------------------------------------------------------- //* Function Name: snmp_parse_auth //* Description : Get the community name and version number by parsing snmp //* message. The message is decoded in BER deconding rules. //* Return Value : Community Name and its length, version number and new pointer to //* next snmp fields //* Calling To : asn_parse_header, asn_parse_int, asn_parse_string //* Called By : snmp_parse //*--------------------------------------------------------------------------------- //* uint8 *snmp_parse_auth( uint8 *data, int *length, uint8 *community, int *community_len, long *version ) { uint8 type; data = asn_parse_header(data, length, &type); if (data == NULL) { return (NULL); //------SNMP: Parse authority failure. } if (type != (ASN_SEQUENCE | ASN_CONSTRUCTOR)) return (NULL); //------SNMP: Wrong auth header type. data = asn_parse_int(data, length, &type, version, sizeof(*version)); if (data == NULL) return (NULL); //------SNMP: Bad parse of version. data = asn_parse_string(data, length, &type, community, community_len); if (data == NULL) return (NULL); //------SNMP: Bad parse of community. community[*community_len] = '\0'; return (data); }
u_char * snmp_msg_Decode(u_char * Packet, int *PacketLenP, u_char * Community, int *CommLenP, int *Version, struct snmp_pdu * PDU) { u_char *bufp; u_char type; bufp = asn_parse_header(Packet, PacketLenP, &type); if (bufp == NULL) { snmplib_debug(4, "snmp_msg_Decode:Error decoding SNMP Message Header (Header)!\n"); ASN_PARSE_ERROR(NULL); } if (type != (ASN_SEQUENCE | ASN_CONSTRUCTOR)) { snmplib_debug(4, "snmp_msg_Decode:Error decoding SNMP Message Header (Header)!\n"); ASN_PARSE_ERROR(NULL); } bufp = asn_parse_int(bufp, PacketLenP, &type, (int *) Version, sizeof(*Version)); if (bufp == NULL) { snmplib_debug(4, "snmp_msg_Decode:Error decoding SNMP Message Header (Version)!\n"); ASN_PARSE_ERROR(NULL); } bufp = asn_parse_string(bufp, PacketLenP, &type, Community, CommLenP); if (bufp == NULL) { snmplib_debug(4, "snmp_msg_Decode:Error decoding SNMP Message Header (Community)!\n"); ASN_PARSE_ERROR(NULL); } Community[*CommLenP] = '\0'; if ((*Version != SNMP_VERSION_1) && (*Version != SNMP_VERSION_2)) { /* Don't know how to handle this one. */ snmplib_debug(4, "snmp_msg_Decode:Unable to parse Version %u\n", *Version); snmplib_debug(4, "snmp_msg_Decode:Continuing anyway\n"); } /* Now that we know the header, decode the PDU */ /* XXXXX -- More than one PDU? */ bufp = snmp_pdu_decode(bufp, PacketLenP, PDU); if (bufp == NULL) /* snmp_pdu_decode registered failure */ return (NULL); bufp = snmp_var_DecodeVarBind(bufp, PacketLenP, &(PDU->variables), *Version); if (bufp == NULL) /* snmp_var_DecodeVarBind registered failure */ return (NULL); return (u_char *) bufp; }
int writeSystem(int action, u_char *var_val, u_char var_val_type, int var_val_len, u_char *statP, oid *name, int name_len) { int bigsize = 1000; u_char buf[sizeof(version_descr)], *cp; int count, size; if (var_val_type != ASN_OCTET_STR){ printf("not string\n"); return SNMP_ERR_WRONGTYPE; } if (var_val_len > sizeof(version_descr)-1){ printf("bad length\n"); return SNMP_ERR_WRONGLENGTH; } size = sizeof(buf); asn_parse_string(var_val, &bigsize, &var_val_type, buf, &size); for(cp = buf, count = 0; count < size; count++, cp++){ if (!isprint(*cp)){ printf("not print %x\n", *cp); return SNMP_ERR_WRONGVALUE; } } buf[size] = 0; if (action == COMMIT){ switch((char)name[7]){ case 1: strcpy(version_descr, (char *) buf); break; case 4: strcpy(sysContact, (char *) buf); break; case 5: strcpy(sysName, (char *) buf); break; case 6: strcpy(sysLocation, (char *) buf); break; } } return SNMP_ERR_NOERROR; } /* end of writeSystem */
/*******************************************************************-o-****** * snmp_comstr_parse * * Parameters: * *data (I) Message. * *length (I/O) Bytes left in message. * *psid (O) Community string. * *slen (O) Length of community string. * *version (O) Message version. * * Returns: * Pointer to the remainder of data. * * * Parse the header of a community string-based message such as that found * in SNMPv1 and SNMPv2c. */ u_char * snmp_comstr_parse(u_char * data, size_t * length, u_char * psid, size_t * slen, long *version) { u_char type; long ver; size_t origlen = *slen; /* * Message is an ASN.1 SEQUENCE. */ data = asn_parse_sequence(data, length, &type, (ASN_SEQUENCE | ASN_CONSTRUCTOR), "auth message"); if (data == NULL) { return NULL; } /* * First field is the version. */ DEBUGDUMPHEADER("recv", "SNMP version"); data = asn_parse_int(data, length, &type, &ver, sizeof(ver)); DEBUGINDENTLESS(); *version = ver; if (data == NULL) { ERROR_MSG("bad parse of version"); return NULL; } /* * second field is the community string for SNMPv1 & SNMPv2c */ DEBUGDUMPHEADER("recv", "community string"); data = asn_parse_string(data, length, &type, psid, slen); DEBUGINDENTLESS(); if (data == NULL) { ERROR_MSG("bad parse of community"); return NULL; } psid[SNMP_MIN(*slen, origlen - 1)] = '\0'; return (u_char *) data; } /* end snmp_comstr_parse() */
void setVariable(uint8 *var_val,uint8 var_val_type,int var_val_len,uint8 *statP,int statLen) { int buffersize = 1000; switch(var_val_type){ case ASN_INTEGER: case COUNTER: case GAUGE: case TIMETICKS: asn_parse_int(var_val, &buffersize, &var_val_type, (long *)statP, statLen); break; case ASN_OCTET_STRING: case IPADDRESS: case OPAQUE: 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; } }
static void setVariable(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; } }
int decode_vbind (unsigned char *data, unsigned int vb_len) { unsigned char *var_val; oid var_name[MAX_OID_LEN]; /* To test the objid */ size_t name_len = MAX_OID_LEN; /* To test the objid */ int badtype=0; size_t len; struct variable_list *vp; oid objid[MAX_OID_LEN]; char _docsis_snmp_label[50]; /* To hold the 'name' of the type, i.e. Integer etc */ char *enum_string = NULL; static char outbuf[16384]; struct tree *subtree; struct enum_list *enums; memset (outbuf, 0, 16384); vp = (struct variable_list *) malloc (sizeof (struct variable_list)); if (vp == NULL) { fprintf (stderr, "Out of memory\n"); return 0; } memset (vp, 0, sizeof (struct variable_list)); vp->next_variable = NULL; vp->val.string = NULL; vp->name_length = MAX_OID_LEN; vp->name = 0; data = snmp_parse_var_op (data, objid, &vp->name_length, &vp->type, &vp->val_len, &var_val, (size_t *) & vb_len); if (data == NULL) return -1; if (snmp_set_var_objid (vp, objid, vp->name_length)) return -1; len = PACKET_LENGTH; if (netsnmp_ds_get_boolean (NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_EXTENDED_INDEX)) { netsnmp_ds_toggle_boolean (NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_EXTENDED_INDEX); } /* Disable extended index format ... makes it harder to parse tokens in lex */ if (!netsnmp_ds_get_boolean (NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PRINT_NUMERIC_ENUM)) { netsnmp_ds_toggle_boolean (NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PRINT_NUMERIC_ENUM); } /* Enable printing numeric enums */ if (netsnmp_ds_get_boolean (NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_ESCAPE_QUOTES)) { netsnmp_ds_toggle_boolean (NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_ESCAPE_QUOTES); } /* Disable escape quotes in string index output */ netsnmp_ds_set_int (NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OID_OUTPUT_FORMAT, NETSNMP_OID_OUTPUT_SUFFIX); if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_OID_OUTPUT_NUMERIC)) { netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OID_OUTPUT_FORMAT, NETSNMP_OID_OUTPUT_NUMERIC); } snprint_objid (outbuf, 1023, vp->name, vp->name_length); if (!get_node (outbuf, var_name, &name_len)) { if (!read_objid (outbuf, var_name, &name_len)) { fprintf (stderr, "/* Hmm ... can't find oid %s at line %d ... perhaps the MIBs are not installed ? */\n", outbuf, line); /* temporarily set full output format */ netsnmp_ds_set_int (NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OID_OUTPUT_FORMAT, NETSNMP_OID_OUTPUT_FULL); memset (outbuf, 0, 1024); snprint_objid (outbuf, 1023, vp->name, vp->name_length); /* Go back to suffix-mode for better readability */ netsnmp_ds_set_int (NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OID_OUTPUT_FORMAT, NETSNMP_OID_OUTPUT_SUFFIX); } } printf("%s", outbuf); /* save the subtree - we need it later to show enums */ subtree = get_tree (var_name, name_len, get_tree_head() ); /* This first switch is just for saving the type in the format we actually want to print. */ switch ((short) vp->type) { case ASN_INTEGER: memset (_docsis_snmp_label, 0, 50); sprintf (_docsis_snmp_label, "Integer"); break; case ASN_COUNTER: memset (_docsis_snmp_label, 0, 50); sprintf (_docsis_snmp_label, "Counter32"); break; case ASN_GAUGE: memset (_docsis_snmp_label, 0, 50); sprintf (_docsis_snmp_label, "Gauge32"); break; case ASN_TIMETICKS: memset (_docsis_snmp_label, 0, 50); sprintf (_docsis_snmp_label, "TimeTicks"); break; case ASN_UINTEGER: memset (_docsis_snmp_label, 0, 50); sprintf (_docsis_snmp_label, "Unsigned32"); break; #ifdef OPAQUE_SPECIAL_TYPES case ASN_OPAQUE_COUNTER64: memset (_docsis_snmp_label, 0, 50); sprintf (_docsis_snmp_label, "OpaqueCounter64"); break; case ASN_OPAQUE_U64: memset (_docsis_snmp_label, 0, 50); sprintf (_docsis_snmp_label, "OpaqueU64"); break; #endif /* OPAQUE_SPECIAL_TYPES */ case ASN_COUNTER64: memset (_docsis_snmp_label, 0, 50); sprintf (_docsis_snmp_label, "Counter64"); break; #ifdef OPAQUE_SPECIAL_TYPES case ASN_OPAQUE_FLOAT: memset (_docsis_snmp_label, 0, 50); sprintf (_docsis_snmp_label, "OpaqueFloat"); break; case ASN_OPAQUE_DOUBLE: memset (_docsis_snmp_label, 0, 50); sprintf (_docsis_snmp_label, "OpaqueDouble"); break; case ASN_OPAQUE_I64: memset (_docsis_snmp_label, 0, 50); sprintf (_docsis_snmp_label, "OpaqueI64"); break; #endif /* OPAQUE_SPECIAL_TYPES */ case ASN_OCTET_STR: memset (_docsis_snmp_label, 0, 50); sprintf (_docsis_snmp_label, "String"); break; case ASN_IPADDRESS: memset (_docsis_snmp_label, 0, 50); sprintf (_docsis_snmp_label, "IPAddress"); break; case ASN_OPAQUE: memset (_docsis_snmp_label, 0, 50); sprintf (_docsis_snmp_label, "Opaque"); break; case ASN_NSAP: memset (_docsis_snmp_label, 0, 50); sprintf (_docsis_snmp_label, "NSAP"); break; case ASN_OBJECT_ID: memset (_docsis_snmp_label, 0, 50); sprintf (_docsis_snmp_label, "ObjectID"); break; case ASN_BIT_STR: memset (_docsis_snmp_label, 0, 50); sprintf (_docsis_snmp_label, "BitString"); break; } switch ((short) vp->type) { case ASN_INTEGER: vp->val.integer = (long *) vp->buf; vp->val_len = sizeof (long); asn_parse_int (var_val, &len, &vp->type, (long *) vp->val.integer, sizeof (vp->val.integer)); break; case ASN_COUNTER: case ASN_GAUGE: case ASN_TIMETICKS: case ASN_UINTEGER: vp->val.integer = (long *) vp->buf; vp->val_len = sizeof (u_long); asn_parse_unsigned_int (var_val, &len, &vp->type, (u_long *) vp->val.integer, sizeof (vp->val.integer)); break; #ifdef OPAQUE_SPECIAL_TYPES case ASN_OPAQUE_COUNTER64: case ASN_OPAQUE_U64: #endif /* OPAQUE_SPECIAL_TYPES */ case ASN_COUNTER64: vp->val.counter64 = (struct counter64 *) vp->buf; vp->val_len = sizeof (struct counter64); asn_parse_unsigned_int64 (var_val, &len, &vp->type, (struct counter64 *) vp->val.counter64, sizeof (*vp->val.counter64)); break; #ifdef OPAQUE_SPECIAL_TYPES case ASN_OPAQUE_FLOAT: vp->val.floatVal = (float *) vp->buf; vp->val_len = sizeof (float); asn_parse_float (var_val, &len, &vp->type, vp->val.floatVal, vp->val_len); break; case ASN_OPAQUE_DOUBLE: vp->val.doubleVal = (double *) vp->buf; vp->val_len = sizeof (double); asn_parse_double (var_val, &len, &vp->type, vp->val.doubleVal, vp->val_len); break; case ASN_OPAQUE_I64: vp->val.counter64 = (struct counter64 *) vp->buf; vp->val_len = sizeof (struct counter64); asn_parse_signed_int64 (var_val, &len, &vp->type, (struct counter64 *) vp->val.counter64, sizeof (*vp->val.counter64)); break; #endif /* OPAQUE_SPECIAL_TYPES */ case ASN_OCTET_STR: case ASN_IPADDRESS: case ASN_OPAQUE: case ASN_NSAP: if (vp->val_len < sizeof (vp->buf)) { vp->val.string = (u_char *) vp->buf; } else { vp->val.string = (u_char *) malloc ((unsigned) vp->val_len+1); memset(vp->val.string, 0, vp->val_len+1); } asn_parse_string (var_val, &len, &vp->type, vp->val.string, &vp->val_len); break; case ASN_OBJECT_ID: vp->val_len = MAX_OID_LEN; asn_parse_objid (var_val, &len, &vp->type, objid, &vp->val_len); vp->val_len *= sizeof (oid); vp->val.objid = (oid *) malloc ((unsigned) vp->val_len); memmove (vp->val.objid, objid, vp->val_len); break; case SNMP_NOSUCHOBJECT: case SNMP_NOSUCHINSTANCE: case SNMP_ENDOFMIBVIEW: case ASN_NULL: break; case ASN_BIT_STR: vp->val.bitstring = (u_char *) malloc (vp->val_len); asn_parse_bitstring (var_val, &len, &vp->type, vp->val.bitstring, &vp->val_len); break; default: fprintf(stderr, "Error: bad type returned (%x)\n", vp->type); badtype = 1; break; } if (!netsnmp_ds_get_boolean (NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PRINT_FULL_OID)) { netsnmp_ds_toggle_boolean (NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PRINT_FULL_OID); } if (!netsnmp_ds_get_boolean (NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PRINT_NUMERIC_OIDS)) { netsnmp_ds_toggle_boolean (NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PRINT_NUMERIC_OIDS); } if (!netsnmp_ds_get_boolean (NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT)) { netsnmp_ds_toggle_boolean (NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT); } if (!strcmp (_docsis_snmp_label, "String")) /* Strings need special treatment - see below */ { netsnmp_ds_toggle_boolean (NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT); netsnmp_ds_toggle_boolean (NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_ESCAPE_QUOTES); } switch ((short) vp->type) { case ASN_OCTET_STR: if (str_isprint((char *) vp->val.string, vp->val_len)) { snprintf(outbuf, vp->val_len+5, "\"%s\"", vp->val.string); } else { snprint_hexadecimal (outbuf, 16383, (char *) vp->val.string, vp->val_len); memset (_docsis_snmp_label, 0, 50); sprintf (_docsis_snmp_label, "HexString"); } break; case ASN_BIT_STR: snprint_hexadecimal (outbuf, 1023, (char *) vp->val.bitstring, vp->val_len); break; case ASN_OBJECT_ID: netsnmp_ds_set_int (NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OID_OUTPUT_FORMAT, NETSNMP_OID_OUTPUT_NUMERIC); snprint_value (outbuf, 1023, vp->name, vp->name_length, vp); netsnmp_ds_set_int (NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OID_OUTPUT_FORMAT, NETSNMP_OID_OUTPUT_SUFFIX); break; default: snprint_value (outbuf, 1023, vp->name, vp->name_length, vp); } if ( subtree ) { enums = subtree->enums; for (; enums; enums = enums->next) { if (enums->value == *vp->val.integer) { enum_string = enums->label; break; } } } if (enum_string) printf(" %s %s; /* %s */", _docsis_snmp_label, outbuf, enum_string); else printf(" %s %s;", _docsis_snmp_label, outbuf); snmp_free_var (vp); return badtype; }
// Parse the given buffer as a SNMPv3-Message. int v3MP::snmp_parse(Snmp *snmp_session, struct snmp_pdu *pdu, unsigned char *inBuf, int inBufLength, OctetStr &securityEngineID, OctetStr &securityName, OctetStr &contextEngineID, OctetStr &contextName, long &securityLevel, long &msgSecurityModel, snmp_version &spp_version, UdpAddress from_address) { debugprintf(3, "mp is parsing incoming message:"); debughexprintf(25, inBuf, inBufLength); if (inBufLength > MAX_SNMP_PACKET) return SNMPv3_MP_ERROR; unsigned char type; long version; int origLength = inBufLength; unsigned char *inBufPtr = inBuf; long msgID, msgMaxSize; unsigned char msgFlags; Buffer<unsigned char> msgSecurityParameters(MAX_SNMP_PACKET); Buffer<unsigned char> msgData(MAX_SNMP_PACKET); int msgSecurityParametersLength = inBufLength, msgDataLength = inBufLength; Buffer<unsigned char> scopedPDU(MAX_SNMP_PACKET); int scopedPDULength = MAX_SNMP_PACKET; long maxSizeResponseScopedPDU = 0; struct SecurityStateReference *securityStateReference = NULL; int securityParametersPosition; int rc; int errorCode = 0; // get the type inBuf = asn_parse_header( inBuf, &inBufLength, &type); if (inBuf == NULL){ debugprintf(0, "snmp_parse: bad header"); return SNMPv3_MP_PARSE_ERROR; } if (type != (ASN_SEQ_CON)){ debugprintf(0, "snmp_parse: wrong auth header type"); return SNMPv3_MP_PARSE_ERROR; } if (origLength != inBufLength + (inBuf - inBufPtr)) { debugprintf(0, "snmp_parse: wrong length of received packet"); return SNMPv3_MP_PARSE_ERROR; } // get the version inBuf = asn_parse_int(inBuf, &inBufLength, &type, &version); if (inBuf == NULL){ debugprintf(0, "snmp_parse: bad parse of version"); return SNMPv3_MP_PARSE_ERROR; } debugprintf(3, "Parsed length(%x), version(0x%lx)", inBufLength, version); if ( version != SNMP_VERSION_3 ) return SNMPv3_MP_PARSE_ERROR; spp_version = (snmp_version) version; inBuf = asn1_parse_header_data(inBuf, &inBufLength, &msgID, &msgMaxSize, &msgFlags, &msgSecurityModel); if (inBuf == NULL){ debugprintf(0, "snmp_parse: bad parse of msgHeaderData"); return SNMPv3_MP_PARSE_ERROR; } pdu->msgid = msgID; if ((msgMaxSize < 484) || (msgMaxSize > 0x7FFFFFFF)) { debugprintf(0, "snmp_parse: bad parse of msgMaxSize"); return SNMPv3_MP_PARSE_ERROR; } // do not allow larger messages than this entity can handle if (msgMaxSize > MAX_SNMP_PACKET) msgMaxSize = MAX_SNMP_PACKET; pdu->maxsize_scopedpdu = msgMaxSize; inBuf = asn_parse_string( inBuf, &inBufLength, &type, msgSecurityParameters.get_ptr(), &msgSecurityParametersLength); if (inBuf == NULL){ debugprintf(0, "snmp_parse: bad parse of msgSecurityParameters"); return SNMPv3_MP_PARSE_ERROR; } securityParametersPosition= SAFE_INT_CAST(inBuf - inBufPtr) - msgSecurityParametersLength; // the rest of the message is passed directly to the security module msgDataLength = origLength - SAFE_INT_CAST(inBuf - inBufPtr); memcpy(msgData.get_ptr(), inBuf, msgDataLength); debugprintf(3, "Parsed msgdata length(0x%x), " "msgSecurityParameters length(0x%x)", msgDataLength, msgSecurityParametersLength); switch (msgFlags & 0x03) { case 3: { securityLevel = SNMP_SECURITY_LEVEL_AUTH_PRIV; break;} case 0: { securityLevel = SNMP_SECURITY_LEVEL_NOAUTH_NOPRIV; break;} case 1: { securityLevel = SNMP_SECURITY_LEVEL_AUTH_NOPRIV; break;} default: { securityLevel = SNMP_SECURITY_LEVEL_NOAUTH_NOPRIV; snmpInvalidMsgs++; // do not send back report return SNMPv3_MP_INVALID_MESSAGE; break; } } bool reportableFlag; if (msgFlags & 0x04) reportableFlag = true; else reportableFlag = false; securityStateReference = usm->get_new_sec_state_reference(); if (!securityStateReference) return SNMPv3_MP_ERROR; switch (msgSecurityModel) { case SNMP_SECURITY_MODEL_USM: { rc = usm->process_msg( msgMaxSize, msgSecurityParameters.get_ptr(), msgSecurityParametersLength, securityParametersPosition, securityLevel, inBufPtr, origLength, //wholeMsg msgData.get_ptr(), msgDataLength, securityEngineID, securityName, scopedPDU.get_ptr(), &scopedPDULength, &maxSizeResponseScopedPDU, securityStateReference, from_address); pdu->maxsize_scopedpdu = maxSizeResponseScopedPDU; if (rc != SNMPv3_USM_OK) { if (rc == SNMPv3_USM_NOT_IN_TIME_WINDOW) { errorCode = SNMPv3_MP_NOT_IN_TIME_WINDOW; } else { // error handling! rfc2262 page 31 debugprintf(0, "mp: error while executing USM::process_msg"); errorCode = rc; } } if (errorCode != SNMPv3_USM_PARSE_ERROR) if (securityEngineID.len() == 0) errorCode = SNMPv3_MP_INVALID_ENGINEID; break; } default: { snmpUnknownSecurityModels++; usm->delete_sec_state_reference(securityStateReference); debugprintf(0, "SecurityModel of incomming Message not supported!"); // Message should be dropped without a report return SNMPv3_MP_UNSUPPORTED_SECURITY_MODEL; } } // process scopedPDU debughexcprintf(21, "scoped PDU", scopedPDU.get_ptr(), scopedPDULength); unsigned char *scopedPDUPtr= scopedPDU.get_ptr(); unsigned char tmp_contextEngineID[MAXLENGTH_ENGINEID]; unsigned char tmp_contextName[MAXLENGTH_CONTEXT_NAME]; int tmp_contextEngineIDLength = MAXLENGTH_ENGINEID; int tmp_contextNameLength = MAXLENGTH_CONTEXT_NAME; unsigned char *data; int dataLength; debugprintf(1,"ErrorCode is %i",errorCode); if (!errorCode) { data = asn1_parse_scoped_pdu(scopedPDUPtr, &scopedPDULength, tmp_contextEngineID, &tmp_contextEngineIDLength, tmp_contextName, &tmp_contextNameLength); if (data == NULL) { debugprintf(0, "mp: Error Parsing scopedPDU!"); usm->delete_sec_state_reference(securityStateReference); return SNMPv3_MP_PARSE_ERROR; } dataLength = scopedPDULength; contextEngineID.set_data(tmp_contextEngineID, tmp_contextEngineIDLength); contextName.set_data(tmp_contextName, tmp_contextNameLength); // parse data of scopedPDU if (snmp_parse_data_pdu(pdu, data, dataLength) != SNMP_CLASS_SUCCESS) { debugprintf(0, "mp: Error parsing PDU!"); usm->delete_sec_state_reference(securityStateReference); return SNMPv3_MP_PARSE_ERROR; } if (SNMP_CLASS_SUCCESS != snmp_parse_vb(pdu, data, dataLength)) { debugprintf(0, "mp: Error parsing Vb"); usm->delete_sec_state_reference(securityStateReference); return SNMPv3_MP_PARSE_ERROR; } if ((tmp_contextEngineIDLength == 0) && ((pdu->command == GET_REQ_MSG) || (pdu->command == GETNEXT_REQ_MSG) || (pdu->command == SET_REQ_MSG) || (pdu->command == GETBULK_REQ_MSG) || (pdu->command == TRP_REQ_MSG) || (pdu->command == INFORM_REQ_MSG) || (pdu->command == TRP2_REQ_MSG))) { // RFC 2572 � 4.2.2.1 (2a) debugprintf(2, "mp: received request message with zero length" " contextEngineID -> unknownPduHandlers."); inc_stats_unknown_pdu_handlers(); errorCode = SNMPv3_MP_UNKNOWN_PDU_HANDLERS; } } if (errorCode) { if ((reportableFlag) && (errorCode != SNMPv3_USM_PARSE_ERROR)) { // error occured: prepare reportpdu in agent cache.add_entry(msgID, pdu->reqid, securityEngineID, msgSecurityModel, securityName, securityLevel, "", "", securityStateReference, errorCode, CACHE_REMOTE_REQ); send_report(scopedPDUPtr, scopedPDULength, pdu, errorCode, securityLevel, msgSecurityModel, securityName, from_address, snmp_session); clear_pdu(pdu, true); // Clear pdu and free all content AND IDs! } else { usm->delete_sec_state_reference(securityStateReference); } return errorCode; } struct Cache::Entry_T centry; if ((pdu->command == GET_RSP_MSG) || (pdu->command == REPORT_MSG)) { rc = cache.get_entry(msgID, true, ¢ry); if (rc != SNMPv3_MP_OK) { // RFC 2572 � 4 debugprintf(2, "Received rspMsg without outstanding request." " -> SnmpUnknownPduHandler"); usm->delete_sec_state_reference(securityStateReference); inc_stats_unknown_pdu_handlers(); return SNMPv3_MP_UNKNOWN_PDU_HANDLERS; } if (((pdu->reqid == 0) || (pdu->reqid == 0x7fffffff)) && (pdu->command == REPORT_MSG)) pdu->reqid = centry.req_id; #ifdef BUGGY_REPORT_REQID if ((pdu->reqid != centry.req_id) && (pdu->command == REPORT_MSG)) { debugprintf(0, "WARNING: setting reqid of REPORT PDU (from) (to): (%ld) (%ld)", pdu->reqid, centry.req_id); pdu->reqid = centry.req_id; } #endif } if (pdu->command == REPORT_MSG) { // !! rfc2262 page 33 debugprintf(2, "*** Receiving a ReportPDU ***"); if (/*((securityEngineID != centry.sec_engine_id) && (centry.sec_engine_id.len() != 0)) ||*/ ((msgSecurityModel != centry.sec_model) && (msgSecurityModel != SNMP_SECURITY_MODEL_USM)) || ((securityName != centry.sec_name) && (securityName.len() != 0))) { debugprintf(0, "Received report message doesn't match sent message!"); usm->delete_sec_state_reference(securityStateReference); return SNMPv3_MP_MATCH_ERROR; } usm->delete_sec_state_reference(securityStateReference); cache.delete_content(centry); debugprintf(1, "mp finished (OK)"); return SNMPv3_MP_OK; } if (pdu->command == GET_RSP_MSG) { if (((securityEngineID != centry.sec_engine_id) && (centry.sec_engine_id.len() != 0)) || (msgSecurityModel != centry.sec_model) || (securityName != centry.sec_name) || (securityLevel != centry.sec_level) || ((contextEngineID != centry.context_engine_id) && (centry.context_engine_id.len() != 0))|| ((contextName != centry.context_name) && (centry.context_name.len() != 0))) { debugprintf(0, "Received response message doesn't match sent message!"); usm->delete_sec_state_reference(securityStateReference); cache.delete_content(centry); return SNMPv3_MP_MATCH_ERROR; } usm->delete_sec_state_reference(securityStateReference); cache.delete_content(centry); debugprintf(1, "mp finished (OK)"); return SNMPv3_MP_OK; } if ((pdu->command == GET_REQ_MSG) || (pdu->command == GETNEXT_REQ_MSG) || (pdu->command == SET_REQ_MSG) || (pdu->command == GETBULK_REQ_MSG) || (pdu->command == INFORM_REQ_MSG)) { if (securityEngineID.len() == 0) { debugprintf(2, "Received Message with engineID = 0."); } else { if (!(unsignedCharCompare(securityEngineID.data(), securityEngineID.len(), own_engine_id, own_engine_id_len))) { debugprintf(0, "snmp_parse: securityEngineID doesn't match own_engine_id."); /* we are authoritative but engine id of message is wrong if discovery in USM is enabled: - remove automatically added illegal engine id from USM tables - send a report */ if (usm->is_discovery_enabled()) { // TODO: try to remove engine id from USM if (reportableFlag) { cache.add_entry(msgID, pdu->reqid, securityEngineID, msgSecurityModel, securityName, securityLevel, "", "", securityStateReference, SNMPv3_MP_INVALID_ENGINEID, CACHE_REMOTE_REQ); send_report(0, MAX_SNMP_PACKET, pdu, SNMPv3_MP_INVALID_ENGINEID, SNMP_SECURITY_LEVEL_NOAUTH_NOPRIV, msgSecurityModel, securityName, from_address, snmp_session); clear_pdu(pdu, true); // Clear pdu and free all content AND IDs! } else { usm->delete_sec_state_reference(securityStateReference); } return SNMPv3_MP_INVALID_ENGINEID; } usm->delete_sec_state_reference(securityStateReference); return SNMPv3_MP_MATCH_ERROR; } } int ret = cache.add_entry(msgID, pdu->reqid, securityEngineID, msgSecurityModel, securityName, securityLevel, contextEngineID, contextName, securityStateReference, SNMPv3_MP_OK, CACHE_REMOTE_REQ); if (ret == SNMPv3_MP_DOUBLED_MESSAGE) { debugprintf(0, "*** received doubled message ***"); // message will be ignored so return OK usm->delete_sec_state_reference(securityStateReference); } debugprintf(1, "mp: parsing finished (ok)."); return SNMPv3_MP_OK; } if ((pdu->command == TRP_REQ_MSG) || (pdu->command == TRP2_REQ_MSG)) { usm->delete_sec_state_reference(securityStateReference); return SNMPv3_MP_OK; } debugprintf(0, "mp error: This line should not be executed."); usm->delete_sec_state_reference(securityStateReference); return SNMPv3_MP_ERROR; }
/* Parse all Vars from the buffer */ u_char *snmp_var_DecodeVarBind(u_char *Buffer, int *BufLen, struct variable_list **VarP, int Version) { struct variable_list *Var, **VarLastP; u_char *bufp, *tmp; u_char VarBindType; u_char *DataPtr; int DataLen; oid TmpBuf[MAX_NAME_LEN]; int AllVarLen = *BufLen; int ThisVarLen = 0; VarLastP = VarP; #ifdef DEBUG_VARS_DECODE printf("VARS: Decoding buffer of length %d\n", *BufLen); #endif /* Now parse the variables */ bufp = asn_parse_header(Buffer, &AllVarLen, &VarBindType); if (bufp == NULL) ASN_PARSE_ERROR(NULL); if (VarBindType != (u_char)(ASN_SEQUENCE | ASN_CONSTRUCTOR)) { snmp_set_api_error(SNMPERR_PDU_PARSE); ASN_PARSE_ERROR(NULL); } #ifdef DEBUG_VARS_DECODE printf("VARS: All Variable length %d\n", AllVarLen); #endif /* We know how long the variable list is. Parse it. */ while ((int)AllVarLen > 0) { /* Create a new variable */ Var = snmp_var_new(NULL, MAX_NAME_LEN); if (Var == NULL) return(NULL); /* Parse the header to find out the length of this variable. */ ThisVarLen = AllVarLen; tmp = asn_parse_header(bufp, &ThisVarLen, &VarBindType); if (tmp == NULL) ASN_PARSE_ERROR(NULL); /* Now that we know the length , figure out how it relates to * the entire variable list */ AllVarLen = AllVarLen - (ThisVarLen + (tmp - bufp)); bufp = tmp; /* Is it valid? */ if (VarBindType != (u_char)(ASN_SEQUENCE | ASN_CONSTRUCTOR)) { snmp_set_api_error(SNMPERR_PDU_PARSE); ASN_PARSE_ERROR(NULL); } #ifdef DEBUG_VARS_DECODE printf("VARS: Header type 0x%x (%d bytes left)\n", VarBindType, ThisVarLen); #endif /* Parse the OBJID */ bufp = asn_parse_objid(bufp, &ThisVarLen, &VarBindType, Var->name, &(Var->name_length)); if (bufp == NULL) ASN_PARSE_ERROR(NULL); if (VarBindType != (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OBJECT_ID)) { snmp_set_api_error(SNMPERR_PDU_PARSE); ASN_PARSE_ERROR(NULL); } #ifdef DEBUG_VARS_DECODE printf("VARS: Decoded OBJID (%d bytes). (%d bytes left)\n", Var->name_length, ThisVarLen); #endif /* Keep a pointer to this object */ DataPtr = bufp; DataLen = ThisVarLen; /* find out type of object */ bufp = asn_parse_header(bufp, &ThisVarLen, &(Var->type)); if (bufp == NULL) ASN_PARSE_ERROR(NULL); ThisVarLen = DataLen; #ifdef DEBUG_VARS_DECODE printf("VARS: Data type %d\n", Var->type); #endif /* Parse the type */ switch((short)Var->type){ case ASN_INTEGER: Var->val.integer = (int *)malloc(sizeof(int)); if (Var->val.integer == NULL) { snmp_set_api_error(SNMPERR_OS_ERR); return(NULL); } Var->val_len = sizeof(int); bufp = asn_parse_int(DataPtr, &ThisVarLen, &Var->type, (int *)Var->val.integer, Var->val_len); #ifdef DEBUG_VARS_DECODE printf("VARS: Decoded integer '%d' (%d bytes left)\n", *(Var->val.integer), ThisVarLen); #endif break; case SMI_COUNTER32: case SMI_GAUGE32: /* case SMI_UNSIGNED32: */ case SMI_TIMETICKS: Var->val.integer = (int *)malloc(sizeof(u_int)); if (Var->val.integer == NULL) { snmp_set_api_error(SNMPERR_OS_ERR); return(NULL); } Var->val_len = sizeof(u_int); bufp = asn_parse_unsigned_int(DataPtr, &ThisVarLen, &Var->type, (u_int *)Var->val.integer, Var->val_len); #ifdef DEBUG_VARS_DECODE printf("VARS: Decoded timeticks '%d' (%d bytes left)\n", *(Var->val.integer), ThisVarLen); #endif break; case ASN_OCTET_STR: case SMI_IPADDRESS: case SMI_OPAQUE: Var->val_len = *&ThisVarLen; /* String is this at most */ Var->val.string = (u_char *)malloc((unsigned)Var->val_len); if (Var->val.string == NULL) { snmp_set_api_error(SNMPERR_OS_ERR); return(NULL); } bufp = asn_parse_string(DataPtr, &ThisVarLen, &Var->type, Var->val.string, &Var->val_len); #ifdef DEBUG_VARS_DECODE printf("VARS: Decoded string '%s' (length %d) (%d bytes left)\n", (Var->val.string), Var->val_len, ThisVarLen); #endif break; case ASN_OBJECT_ID: Var->val_len = MAX_NAME_LEN; bufp = asn_parse_objid(DataPtr, &ThisVarLen, &Var->type, TmpBuf, &Var->val_len); Var->val_len *= sizeof(oid); Var->val.objid = (oid *)malloc((unsigned)Var->val_len); if (Var->val.integer == NULL) { snmp_set_api_error(SNMPERR_OS_ERR); return(NULL); } /* Only copy if we successfully decoded something */ if (bufp) { memcpy((char *)Var->val.objid, (char *)TmpBuf, Var->val_len); } #ifdef DEBUG_VARS_DECODE printf("VARS: Decoded OBJID (length %d) (%d bytes left)\n", Var->val_len, ThisVarLen); #endif break; case ASN_NULL: case SMI_NOSUCHINSTANCE: case SMI_NOSUCHOBJECT: case SMI_ENDOFMIBVIEW: Var->val_len = 0; Var->val.objid = NULL; bufp = asn_parse_null(DataPtr, &ThisVarLen, &Var->type); #ifdef DEBUG_VARS_DECODE printf("VARS: Decoded ASN_NULL (length %d) (%d bytes left)\n", Var->val_len, ThisVarLen); #endif break; case SMI_COUNTER64: #ifdef STDERR_OUTPUT fprintf(stderr, WIDE("Unable to parse type SMI_COUNTER64!\n")); #endif snmp_set_api_error(SNMPERR_UNSUPPORTED_TYPE); return(NULL); break; default: #ifdef STDERR_OUTPUT fprintf(stderr, WIDE("bad type returned (%x)\n"), Var->type); #endif snmp_set_api_error(SNMPERR_PDU_PARSE); return(NULL); break; } /* End of var type switch */ /* Why is this here? XXXXX */ if (bufp == NULL) return(NULL); #ifdef DEBUG_VARS_DECODE printf("VARS: Adding to list of decoded variables. (%d bytes remain.)\n", AllVarLen); #endif /* Add variable to the list */ *VarLastP = Var; VarLastP = &(Var->next_variable); } return(bufp); }
char * snmp_parse_trap(u_char * trapdata, /* IN - actual trap data from packet */ unsigned datalen, /* IN - length of trapdata */ struct trap_info * trapInfo) /* IN/OUT - struct to fill in */ { u_char * more; /* pointer to next unparsed PDU data */ u_char * nextVar; /* pointer to next unparsed TRAP variable */ unsigned left; /* length of more */ long version; /* SNMP version, always v1 */ u_char type; /* data types for checking */ u_char * varValPtr; int vars_in_struct; struct trapVar * vars; /* trap variables data structures */ u_long trapType; unsigned length; /* scratch for passing to asn1 */ /* do some basic setup of the passed data structures */ vars_in_struct = trapInfo->trapVars; trapInfo->trapVars = 0; /* bump later if vars are present */ left = datalen; more = snmp_auth_parse(trapdata, &left, (u_char*)trapInfo->community, (unsigned*)&trapInfo->commLen, &version); if (!more) return "community parse"; more = asn_parse_header(more, &left, &type); if (!more || type != TRP_REQ_MSG) return "trap pdu header"; more = asn_parse_objid(more, &left, &type, &trapInfo->objId[0], (unsigned*)&trapInfo->objLen); if (!more || type != ASN_OBJECT_ID) return "sys ObjId"; length = 4; /* number of bytes in IP address buffer */ more = asn_parse_string(more, &left, &type, (u_char*)(&trapInfo->agent_ip), &length); if (!more || type != IPADDRESS) return "agent's IP address"; more = asn_parse_int(more, &left, &type, (long*)&trapType, sizeof(long)); if (!more || type != ASN_INTEGER || trapType > 6) return "trap type"; trapInfo->trapType = trapType; more = asn_parse_int(more, &left, &type, (long*)&trapType, sizeof(long)); if (!more || type != ASN_INTEGER) return "specific type"; trapInfo->trapSpecific = trapType; more = asn_parse_int(more, &left, &type, (long*)&trapInfo->time, sizeof(long)); if (!more || type != TIMETICKS) return "timestamp"; if (!left) /* no variables in trap ? */ return NULL; /* rest of packet is a sequence of variables */ more = asn_parse_header(more, &left, &type); /* strip off leading SEQ */ if (!more || type != SEQUENCE) return "trap vars header"; vars = trapInfo->vars; /* set pointer array to receive variables data */ while (left) /* keep parsing & counting vars as long as there's data */ { /* extract variable info for this var */ length = left; /* number of valid bytes left in packet buffer */ varNameLen = MAX_OID_LEN ; /* define the max size of varName */ nextVar = snmp_parse_var_op(more, varName, &varNameLen, &varType, &varLen, &varValPtr, &left); if (!nextVar) /* quit if parse failed */ return ("var_op header"); /* extract the variable's value; pointed to by varValPtr: */ length -= more - nextVar; /* deduct size of header -> max. length of var */ switch (varType) { case ASN_INTEGER: case GAUGE: case COUNTER: case TIMETICKS: varLen = sizeof(long); /* size required by asn_parse_int() */ nextVar = asn_parse_int(varValPtr, &length, &varType, (long *)(&varVal[0]), varLen); break; case ASN_OCTET_STR: case IPADDRESS: case OPAQUE: varLen = MAX_TRAP_VAR; nextVar = asn_parse_string(varValPtr, &length, &varType, varVal, &varLen); break; case ASN_OBJECT_ID: varLen = MAX_TRAP_VAR; nextVar = asn_parse_objid(varValPtr, &length, &varType, (oid *)(&varVal[0]), &varLen); break; case ASN_NULL: nextVar = asn_parse_null(varValPtr, &length, &varType); break; default: SNMPERROR("wrong type"); return NULL; } if (!nextVar) return("variable"); /* if another trap variable info slot is available, fill it in */ if (trapInfo->trapVars <= vars_in_struct) { oidcpy(vars->varName, varName, varNameLen); if (vars->varBufLen <= varLen) /* need to truncate? */ vars->varValLen = vars->varBufLen-1; else /* we have room for the full variable data field */ vars->varValLen = varLen; MEMCPY(vars->varBuf, varVal, vars->varValLen); vars->varNameLen = varNameLen; vars->varType = varType; vars++; /* point to next variable info structure */ } trapInfo->trapVars++; /* another var */ more = nextVar; /* bump pointer to pdu */ } return NULL; }
/* FUNCTION: snmp_print_value() * Print the value into a buffer and return the buffer. * * Buffer is static to this function. * * PARAM1: u_char * var_val - ASN.1 encoded value * PARAM1: u_char var_val_type - ASN.1 type of value * * RETURNS: */ char * snmp_print_value(u_char *var_val, u_char var_val_type) { /* set an abritrarily large buffer parm for asn1 parsing. * We don't use the returned value for this anyway. */ unsigned asn_buf_size = 1000; /* */ unsigned set_var_size = _MAX_PATH; /* bytes in field to set */ long tmpvalue=0; static char datastr[_MAX_PATH]; static char datatmp[_MAX_PATH]; static oid dataoid[_MAX_PATH]; datastr[0]=0; /* null terminate */ if (!var_val) return datastr; switch (var_val_type) { case ASN_INTEGER: case COUNTER: case GAUGE: /* valid for GAUGE32 and UNSIGNED32 too */ case TIMETICKS: if (!asn_parse_int(var_val, &asn_buf_size, &var_val_type, &tmpvalue, sizeof(long))) { break; } sprintf(datastr,"%ld",tmpvalue) ; break; case ASN_BIT_STR: if (!asn_parse_bits(var_val, &asn_buf_size, &var_val_type, (unsigned char *)datatmp, &set_var_size)) { break; } strcpy(datastr,datatmp); break; case ASN_OCTET_STR: case IPADDRESS: case OPAQUE: if (!asn_parse_string(var_val, &asn_buf_size, &var_val_type, (unsigned char *)datatmp, &set_var_size)) { break; } *(datatmp + set_var_size) = '\0'; /* null terminate the strings */ strcpy(datastr,datatmp); break; case ASN_OBJECT_ID: if (!asn_parse_objid(var_val, &asn_buf_size, &var_val_type, dataoid, &set_var_size)) { break; } strcpy(datastr, print_oid(dataoid, set_var_size)); break; case ASN_NULL: strcpy (datastr, "<NULL>"); break; } return datastr; }
//* //*--------------------------------------------------------------------------------- //* Function Name: snmp_parse_var //* Description : Get variables by parsing snmp message. The message is decoded in //* BER deconding rules. //* Return Value : Pointer of decoding variables //* Calling To : asn_parse_header, asn_parse_objid, asn_parse_int, //* asn_parse_string //* Called By : snmp_parse //*--------------------------------------------------------------------------------- //* variable_list *snmp_parse_var(uint8 *data,int length) { uint8 type; variable_list vh, *vp; uint8 *varBindP; int varBind_len; uint8 objId[SNMP_MAX_NAME_LEN]; uint8 *varVal; int parse_ok; data = asn_parse_header(data, &length, &type); if ((data == NULL) || (type != (uint8) (ASN_SEQUENCE | ASN_CONSTRUCTOR))) return ( NULL ); vh.next = NULL; vp = &vh; varBindP = data; parse_ok = TRUE; while (length > 0) { varBind_len = length; vp->next = (variable_list *) malloc(sizeof(variable_list)); if (vp->next == NULL) { parse_ok = FALSE; break; //---SNMP: Memory allocation error on 'snmp_parse_var'. } else { vp = vp->next; vp->next = NULL; vp->name = NULL; vp->name_len = SNMP_MAX_NAME_LEN; vp->val.string = NULL; } varBindP = asn_parse_header(varBindP, &varBind_len, &type); if ((varBindP == NULL) || (type != (uint8) (ASN_SEQUENCE | ASN_CONSTRUCTOR))) { parse_ok = FALSE; break; } //* //* Parse variable bind name. //* varBindP = asn_parse_objid(varBindP, &varBind_len, &type, objId, &vp->name_len); if ((varBindP == NULL) || (type != (uint8) (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OBJECT_ID))) { parse_ok = FALSE; break; } vp->name = (oid *) malloc((unsigned) vp->name_len * sizeof(oid)); if (vp->name == NULL) { parse_ok = FALSE; break; //-----SNMP: Memory alloc error on 'snmp_parse_var'. } else { bcopy((char *) objId, (char *) vp->name, vp->name_len * sizeof(oid)); } //* //* Parse variable bind value. //* varVal = varBindP; varBindP = asn_parse_header(varBindP, &varBind_len, &vp->type); if (varBindP == NULL) { parse_ok = FALSE; break; } else { vp->val_len = varBind_len; varBindP = varBindP + varBind_len; // skip value body to next variable length = length - (int)(varBindP - data); data = varBindP; varBind_len = SNMP_MAX_LEN; } switch (vp->type) { case ASN_INTEGER: case COUNTER: case GAUGE: case TIMETICKS: vp->val_len = sizeof(long); // support long intger only vp->val.integer = (long *) malloc(vp->val_len); if (vp->val.integer == NULL) { parse_ok = FALSE; break; //---SNMP:Memory alloc error on 'snmp_parse_var'. } asn_parse_int(varVal, &varBind_len, &vp->type, (long *) vp->val.integer, vp->val_len); break; case ASN_OCTET_STRING: case IPADDRESS: case OPAQUE: vp->val.string = (uint8 *) malloc(vp->val_len); if (vp->val.string == NULL) { parse_ok = FALSE; break; //----SNMP:Memory alloc error on 'snmp_parse_var'. } asn_parse_string(varVal, &varBind_len, &vp->type, vp->val.string, &vp->val_len); break; case ASN_OBJECT_ID: vp->val_len = SNMP_MAX_NAME_LEN; asn_parse_objid(varVal, &varBind_len, &vp->type, objId, &vp->val_len); vp->val_len = vp->val_len * sizeof(oid); vp->val.objid = (oid *) malloc((unsigned) vp->val_len); if (vp->val.objid == NULL) { parse_ok = FALSE; break; //---SNMP:Memory alloc error on 'snmp_parse_var'. } bcopy((char *) objId, (char *) vp->val.objid, vp->val_len); break; case ASN_NULL: break; default: parse_ok = FALSE; //-----Warning: Bad type received. break; } if ( ! parse_ok ) break; } if ( parse_ok ) { return( vh.next ); } else { while ( vh.next ) { vp = vh.next; vh.next = vp->next; if (vp->name != NULL) free((char *) vp->name); if (vp->val.string != NULL) free((char *) vp->val.string); free((char *) vp); } return ( NULL ); } }
/* Decodes PDU from Packet into PDU. * * Returns a pointer to the next byte of the packet, which is where the * Variable Bindings start. */ u_char *snmp_pdu_decode(u_char *Packet, /* data */ int *Length, /* &length */ struct snmp_pdu *PDU) /* pdu */ { u_char *bufp; u_char PDUType; int four; u_char ASNType; oid objid[MAX_NAME_LEN]; bufp = asn_parse_header(Packet, Length, &PDUType); if (bufp == NULL) ASN_PARSE_ERROR(NULL); #ifdef DEBUG_PDU_DECODE printf("PDU Type: %d\n", PDUType); #endif PDU->command = PDUType; switch (PDUType) { case TRP_REQ_MSG: /* SNMPv1 Trap Message */ /* enterprise */ PDU->enterprise_length = MAX_NAME_LEN; bufp = asn_parse_objid(bufp, Length, &ASNType, objid, &PDU->enterprise_length); if (bufp == NULL) ASN_PARSE_ERROR(NULL); PDU->enterprise = (oid *)malloc(PDU->enterprise_length * sizeof(oid)); if (PDU->enterprise == NULL) { snmp_set_api_error(SNMPERR_OS_ERR); return(NULL); } memcpy((char *)PDU->enterprise, (char *)objid, PDU->enterprise_length * sizeof(oid)); /* Agent-addr */ four = 4; bufp = asn_parse_string(bufp, Length, &ASNType, (u_char *)&PDU->agent_addr.sin_addr.s_addr, &four); if (bufp == NULL) ASN_PARSE_ERROR(NULL); /* Generic trap */ bufp = asn_parse_int(bufp, Length, &ASNType, (int *)&PDU->trap_type, sizeof(PDU->trap_type)); if (bufp == NULL) ASN_PARSE_ERROR(NULL); /* Specific Trap */ bufp = asn_parse_int(bufp, Length, &ASNType, (int *)&PDU->specific_type, sizeof(PDU->specific_type)); if (bufp == NULL) ASN_PARSE_ERROR(NULL); /* Timestamp */ bufp = asn_parse_unsigned_int(bufp, Length, &ASNType, &PDU->time, sizeof(PDU->time)); if (bufp == NULL) ASN_PARSE_ERROR(NULL); break; /**********************************************************************/ case SNMP_PDU_GETBULK: /* SNMPv2 Bulk Request */ /* request id */ bufp = asn_parse_int(bufp, Length, &ASNType, &PDU->reqid, sizeof(PDU->reqid)); if (bufp == NULL) ASN_PARSE_ERROR(NULL); /* non-repeaters */ bufp = asn_parse_int(bufp, Length, &ASNType, &PDU->non_repeaters, sizeof(PDU->non_repeaters)); if (bufp == NULL) ASN_PARSE_ERROR(NULL); /* max-repetitions */ bufp = asn_parse_int(bufp, Length, &ASNType, &PDU->max_repetitions, sizeof(PDU->max_repetitions)); if (bufp == NULL) ASN_PARSE_ERROR(NULL); break; /**********************************************************************/ default: /* Normal PDU Encoding */ /* request id */ bufp = asn_parse_int(bufp, Length, &ASNType, &PDU->reqid, sizeof(PDU->reqid)); if (bufp == NULL) ASN_PARSE_ERROR(NULL); #ifdef DEBUG_PDU_DECODE printf("PDU Request ID: %d\n", PDU->reqid); #endif /* error status */ bufp = asn_parse_int(bufp, Length, &ASNType, &PDU->errstat, sizeof(PDU->errstat)); if (bufp == NULL) ASN_PARSE_ERROR(NULL); #ifdef DEBUG_PDU_DECODE printf("PDU Error Status: %d\n", PDU->errstat); #endif /* error index */ bufp = asn_parse_int(bufp, Length, &ASNType, &PDU->errindex, sizeof(PDU->errindex)); if (bufp == NULL) ASN_PARSE_ERROR(NULL); #ifdef DEBUG_PDU_DECODE printf("PDU Error Index: %d\n", PDU->errindex); #endif break; } return(bufp); }