unsigned int decode_snmp_oid (unsigned char *data, size_t data_len) { oid this_oid[MAX_OID_LEN]; size_t oid_len = MAX_OID_LEN; unsigned char type; void *retval; /* generic pointer, will only use to check return value */ size_t len; static char outbuf[1024]; memset (outbuf, 0, 1024); len = data_len; /* The last char is the enable/disable switch */ if ((retval = asn_parse_objid (data, &len, &type, this_oid, &oid_len)) == NULL) { fprintf(stderr, "OID.parse.error"); return 0; } else { netsnmp_ds_set_int (NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OID_OUTPUT_FORMAT, NETSNMP_OID_OUTPUT_NUMERIC); snprint_objid (outbuf, 1023, this_oid, oid_len); } /* fprintf(stderr, "%s %d", outbuf, (int) data[data_len - 1]); */ printf("%s", outbuf); return 1; }
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; } }
u_char * snmp_parse_var_op(u_char *data, oid *var_name, size_t *var_name_len, u_char *var_val_type, size_t *var_val_len, u_char **var_val, size_t *listlength) { u_char var_op_type; size_t var_op_len = *listlength; u_char *var_op_start = data; data = asn_parse_sequence(data, &var_op_len, &var_op_type, (ASN_SEQUENCE | ASN_CONSTRUCTOR), "var_op"); if (data == NULL) { /* msg detail is set */ return NULL; } data = asn_parse_objid(data, &var_op_len, &var_op_type, var_name, var_name_len); if (data == NULL) { ERROR_MSG("No OID for variable"); return NULL; } if (var_op_type != (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OBJECT_ID)) return NULL; *var_val = data; /* save pointer to this object */ /* find out what type of object this is */ data = asn_parse_header(data, &var_op_len, var_val_type); if (data == NULL) { ERROR_MSG("No header for value"); return NULL; } /* XXX no check for type! */ *var_val_len = var_op_len; data += var_op_len; *listlength -= (int)(data - var_op_start); return data; }
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 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); }