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; }
/* 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); }
/* 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); }