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