diff options
-rw-r--r-- | asn1/snmp/packet-snmp-template.c | 1056 | ||||
-rw-r--r-- | asn1/snmp/snmp.asn | 728 | ||||
-rw-r--r-- | asn1/snmp/snmp.cnf | 83 | ||||
-rw-r--r-- | epan/oids.c | 331 | ||||
-rw-r--r-- | epan/oids.h | 15 |
5 files changed, 739 insertions, 1474 deletions
diff --git a/asn1/snmp/packet-snmp-template.c b/asn1/snmp/packet-snmp-template.c index 4d53dcf127..db30e139de 100644 --- a/asn1/snmp/packet-snmp-template.c +++ b/asn1/snmp/packet-snmp-template.c @@ -69,32 +69,6 @@ #include "packet-ber.h" -#ifdef HAVE_NET_SNMP -# include <net-snmp/net-snmp-config.h> -# include <net-snmp/mib_api.h> -# include <net-snmp/library/default_store.h> -# include <net-snmp/config_api.h> - -#ifdef _WIN32 -# include <epan/filesystem.h> -#endif /* _WIN32 */ - - /* - * Define values "sprint_realloc_value()" expects. - */ -# define VALTYPE_INTEGER ASN_INTEGER -# define VALTYPE_COUNTER ASN_COUNTER -# define VALTYPE_GAUGE ASN_GAUGE -# define VALTYPE_TIMETICKS ASN_TIMETICKS -# define VALTYPE_STRING ASN_OCTET_STR -# define VALTYPE_IPADDR ASN_IPADDRESS -# define VALTYPE_OPAQUE ASN_OPAQUE -# define VALTYPE_NSAP ASN_NSAP -# define VALTYPE_OBJECTID ASN_OBJECT_ID -# define VALTYPE_BITSTR ASN_BIT_STR -# define VALTYPE_COUNTER64 ASN_COUNTER64 - -#endif /* HAVE_NET_SNMP */ #include "packet-snmp.h" #include "format-oid.h" @@ -102,6 +76,7 @@ #include <epan/crypt/crypt-md5.h> #include <epan/expert.h> #include <epan/report_err.h> +#include <epan/oids.h> #ifdef _WIN32 #include <winposixtype.h> @@ -111,7 +86,6 @@ #include <gcrypt.h> #endif - /* Take a pointer that may be null and return a pointer that's not null by turning null pointers into pointers to the above null string, and, if the argument pointer wasn't null, make sure we handle @@ -145,10 +119,7 @@ static int proto_smux = -1; # define IMPORT_SEPARATOR ";" #endif /* _WIN32 */ -static const gchar *mib_modules = DEF_MIB_MODULES; static gboolean display_oid = TRUE; -static gboolean snmp_var_in_tree = TRUE; - static gboolean snmp_usm_auth_md5(snmp_usm_params_t* p, guint8**, guint*, gchar const**); static gboolean snmp_usm_auth_sha1(snmp_usm_params_t* p, guint8**, guint*, gchar const**); @@ -224,11 +195,29 @@ static int hf_snmp_engineid_mac = -1; static int hf_snmp_engineid_text = -1; static int hf_snmp_engineid_time = -1; static int hf_snmp_engineid_data = -1; -static int hf_snmp_counter64 = -1; static int hf_snmp_decryptedPDU = -1; static int hf_snmp_msgAuthentication = -1; -static int hf_snmp_internet_ipv6 = -1; -static int hf_snmp_internet_other = -1; + +static int hf_snmp_noSuchObject_value = -1; +static int hf_snmp_noSuchInstance_value = -1; +static int hf_snmp_endOfMibView_value = -1; +static int hf_snmp_integer32_value = -1; +static int hf_snmp_octestring_value = -1; +static int hf_snmp_oid_value = -1; +static int hf_snmp_null_value = -1; +static int hf_snmp_ipv4_value = -1; +static int hf_snmp_ipv6_value = -1; +static int hf_snmp_anyaddress_value = -1; +static int hf_snmp_unsigned32_value = -1; +static int hf_snmp_unknown_value = -1; +static int hf_snmp_opaque_value = -1; +static int hf_snmp_nsap_value = -1; +static int hf_snmp_counter_value = -1; +static int hf_snmp_timeticks_value = -1; +static int hf_snmp_arbitrary_value = -1; +static int hf_snmp_big_counter_value = -1; +static int hf_snmp_gauge32_value = -1; +static int hf_snmp_objectname = -1; #include "packet-snmp-hf.c" @@ -244,13 +233,11 @@ static gint ett_encryptedPDU = -1; static gint ett_decrypted = -1; static gint ett_authParameters = -1; static gint ett_internet = -1; +static gint ett_varbind = -1; +static gint ett_decoding_error = -1; #include "packet-snmp-ett.c" - -static int dissect_snmp_IpAddressIpv6(gboolean, tvbuff_t* ,int , asn1_ctx_t* , proto_tree*, int); -static int dissect_snmp_IpAddressOther(gboolean, tvbuff_t* ,int , asn1_ctx_t* , proto_tree*, int); - static const true_false_string auth_flags = { "OK", "Failed" @@ -301,7 +288,6 @@ static const value_string smux_types[] = { { 0, NULL } }; -/* SNMP Tags */ #define SNMP_IPA 0 /* IP Address */ #define SNMP_CNT 1 /* Counter (Counter32) */ @@ -316,367 +302,231 @@ static const value_string smux_types[] = { #define SERR_NSI 1 #define SERR_EOM 2 -/* SNMPv1 Types */ - -#define SNMP_NULL 0 -#define SNMP_INTEGER 1 /* l */ -#define SNMP_OCTETSTR 2 /* c */ -#define SNMP_DISPLAYSTR 2 /* c */ -#define SNMP_OBJECTID 3 /* ul */ -#define SNMP_IPADDR 4 /* uc */ -#define SNMP_COUNTER 5 /* ul */ -#define SNMP_GAUGE 6 /* ul */ -#define SNMP_TIMETICKS 7 /* ul */ -#define SNMP_OPAQUE 8 /* c */ - -/* additional SNMPv2 Types */ - -#define SNMP_UINTEGER 5 /* ul */ -#define SNMP_BITSTR 9 /* uc */ -#define SNMP_NSAP 10 /* uc */ -#define SNMP_COUNTER64 11 /* ul */ -#define SNMP_NOSUCHOBJECT 12 -#define SNMP_NOSUCHINSTANCE 13 -#define SNMP_ENDOFMIBVIEW 14 - - -typedef struct _SNMP_CNV SNMP_CNV; - -struct _SNMP_CNV -{ - guint class; - guint tag; - gint syntax; - const gchar *name; -}; - -static SNMP_CNV SnmpCnv [] = -{ - {BER_CLASS_UNI, BER_UNI_TAG_NULL, SNMP_NULL, "NULL"}, - {BER_CLASS_UNI, BER_UNI_TAG_INTEGER, SNMP_INTEGER, "INTEGER"}, - {BER_CLASS_UNI, BER_UNI_TAG_OCTETSTRING, SNMP_OCTETSTR, "OCTET STRING"}, - {BER_CLASS_UNI, BER_UNI_TAG_OID, SNMP_OBJECTID, "OBJECTID"}, - {BER_CLASS_APP, SNMP_IPA, SNMP_IPADDR, "IPADDR"}, - {BER_CLASS_APP, SNMP_CNT, SNMP_COUNTER, "COUNTER"}, /* Counter32 */ - {BER_CLASS_APP, SNMP_GGE, SNMP_GAUGE, "GAUGE"}, /* Gauge32 == Unsigned32 */ - {BER_CLASS_APP, SNMP_TIT, SNMP_TIMETICKS, "TIMETICKS"}, - {BER_CLASS_APP, SNMP_OPQ, SNMP_OPAQUE, "OPAQUE"}, - -/* SNMPv2 data types and errors */ - - {BER_CLASS_UNI, BER_UNI_TAG_BITSTRING, SNMP_BITSTR, "BITSTR"}, - {BER_CLASS_APP, SNMP_C64, SNMP_COUNTER64, "COUNTER64"}, - {BER_CLASS_CON, SERR_NSO, SNMP_NOSUCHOBJECT, "NOSUCHOBJECT"}, - {BER_CLASS_CON, SERR_NSI, SNMP_NOSUCHINSTANCE, "NOSUCHINSTANCE"}, - {BER_CLASS_CON, SERR_EOM, SNMP_ENDOFMIBVIEW, "ENDOFMIBVIEW"}, - {0, 0, -1, NULL} -}; - -/* - * NAME: g_snmp_tag_cls2syntax - * SYNOPSIS: gboolean g_snmp_tag_cls2syntax - * ( - * guint tag, - * guint cls, - * gushort *syntax - * ) - * DESCRIPTION: Converts ASN1 tag and class to Syntax tag and name. - * See SnmpCnv for conversion. - * RETURNS: name on success, NULL on failure - */ - -static const gchar * -snmp_tag_cls2syntax ( guint tag, guint cls, gushort *syntax) -{ - SNMP_CNV *cnv; - - cnv = SnmpCnv; - while (cnv->syntax != -1) - { - if (cnv->tag == tag && cnv->class == cls) - { - *syntax = cnv->syntax; - return cnv->name; - } - cnv++; - } - return NULL; -} - -int oid_to_subid_buf(const guint8 *oid, gint oid_len, subid_t *buf, int buf_len) { - int i, out_len; - guint8 byte; - guint32 value; - gboolean is_first; - - value=0; out_len = 0; byte =0; is_first = TRUE; - for (i=0; i<oid_len; i++){ - if (out_len >= buf_len) - break; - byte = oid[i]; - value = (value << 7) | (byte & 0x7F); - if (byte & 0x80) { - continue; - } - if (is_first) { - if ( value<40 ){ - buf[0] = 0; - buf[1] = value; - }else if ( value < 80 ){ - buf[0] = 1; - buf[1] = value - 40; - }else { - buf[0] = 2; - buf[1] = value - 80; - } - out_len= out_len+2; - is_first = FALSE; - }else{ - buf[out_len++] = value; - } - value = 0; - } - - return out_len; -} - -gchar * -format_oid(subid_t *oid, guint oid_length) -{ - char *result; - int result_len; - int len; - unsigned int i; - char *buf; -#ifdef HAVE_NET_SNMP - guchar *oid_string; - size_t oid_string_len; - size_t oid_out_len; -#endif - - result_len = oid_length * 22; - -#ifdef HAVE_NET_SNMP - /* - * Get the decoded form of the OID, and add its length to the - * length of the result string. - * - * XXX - check for "sprint_realloc_objid()" failure. - */ - oid_string_len = 1024; - oid_string = ep_alloc(oid_string_len); - *oid_string = '\0'; - oid_out_len = 0; - /* We pass an ep allocated block here, NOT a malloced block - * so we MUST NOT allow reallocation, hence the fourth - * parameter MUST be 0/FALSE - */ - sprint_realloc_objid(&oid_string, &oid_string_len, &oid_out_len, FALSE, - oid, oid_length); - result_len += strlen(oid_string) + 3; -#endif - - result = ep_alloc(result_len + 1); - buf = result; - len = g_snprintf(buf, result_len + 1 - (buf-result), "%lu", (unsigned long)oid[0]); - buf += len; - for (i = 1; i < oid_length;i++) { - len = g_snprintf(buf, result_len + 1 - (buf-result), ".%lu", (unsigned long)oid[i]); - buf += len; +static int dissect_snmp_VarBind(gboolean implicit_tag _U_, + tvbuff_t *tvb, + int offset, + asn1_ctx_t *actx, + proto_tree *tree, + int hf_index _U_) { + int seq_offset, name_offset, value_offset, value_start; + guint32 seq_len, name_len, value_len; + gint8 ber_class; + gboolean pc; + gint32 tag; + gboolean ind; + guint8* oid_bytes; + oid_info_t* oid_info; + guint oid_matched, oid_left; + proto_item *pi_varbind, *pi_value = NULL; + proto_tree *pt; + char* label; + int hfid = -1; + int min_len = 0, max_len = 0; + + seq_offset = offset; + + /* first we must read the VarBind's sequence header */ + offset = get_ber_identifier(tvb, offset, &ber_class, &pc, &tag); + offset = get_ber_length(NULL, tvb, offset, &seq_len, &ind); + + seq_len += offset - seq_offset; + + if (!pc && ber_class==BER_CLASS_UNI && tag==BER_UNI_TAG_SEQUENCE) { + proto_item* pi = proto_tree_add_text(tree, tvb, seq_offset, seq_len,"VarBind must be an universal class sequence"); + pt = proto_item_add_subtree(pi,ett_decoding_error); + expert_add_info_format(actx->pinfo, pi, PI_MALFORMED, PI_WARN, "VarBind is not an universal class sequence"); + return dissect_unknown_ber(actx->pinfo, tvb, seq_offset, pt); } - -#ifdef HAVE_NET_SNMP - /* - * Append the decoded form of the OID. - */ - g_snprintf(buf, result_len + 1 -(buf-result), " (%s)", oid_string); -#endif - - return result; -} - -/* returns the decoded (can be NULL) and non_decoded OID strings */ -void -new_format_oid(subid_t *oid, guint oid_length, - gchar **non_decoded, gchar **decoded) -{ - int non_decoded_len; - int len; - unsigned int i; - char *buf; -#ifdef HAVE_NET_SNMP - guchar *oid_string; - size_t oid_string_len; - size_t oid_out_len; -#endif - - if (oid == NULL || oid_length < 1) { - *decoded = NULL; - return; + + if (ind){ + proto_item* pi = proto_tree_add_text(tree, tvb, seq_offset, seq_len,"Indicator must be clear in VarBind"); + pt = proto_item_add_subtree(pi,ett_decoding_error); + expert_add_info_format(actx->pinfo, pi, PI_MALFORMED, PI_WARN, "VarBind has indicator set"); + return dissect_unknown_ber(actx->pinfo, tvb, seq_offset, pt); } - -#ifdef HAVE_NET_SNMP - /* - * Get the decoded form of the OID, and add its length to the - * length of the result string. - */ - - /* - * XXX - if we convert this to ep_alloc(), make sure the fourth - * argument to sprint_realloc_objid() is FALSE. - */ - - oid_string_len = 1024; - oid_string = ep_alloc(oid_string_len); - if (oid_string != NULL) { - *oid_string = '\0'; - oid_out_len = 0; - /* We pass an ep allocated block here, NOT a malloced block - * so we MUST NOT allow reallocation, hence the fourth - * parameter MUST be 0/FALSE - */ - sprint_realloc_objid(&oid_string, &oid_string_len, &oid_out_len, FALSE, - oid, oid_length); + + /* then we have the name's header */ + + offset = get_ber_identifier(tvb, offset, &ber_class, &pc, &tag); + name_offset = offset = get_ber_length(NULL, tvb, offset, &name_len, &ind); + + if (! ( !pc && ber_class==BER_CLASS_UNI && tag==BER_UNI_TAG_OID) ) { + proto_item* pi = proto_tree_add_text(tree, tvb, seq_offset, seq_len,"ObjectName must be an OID in primitive encoding"); + pt = proto_item_add_subtree(pi,ett_decoding_error); + expert_add_info_format(actx->pinfo, pi, PI_MALFORMED, PI_WARN, "ObjectName not an OID"); + return dissect_unknown_ber(actx->pinfo, tvb, seq_offset, pt); } - *decoded = oid_string; -#else - *decoded = NULL; -#endif - - non_decoded_len = oid_length * 22 + 1; - *non_decoded = ep_alloc(non_decoded_len); - buf = *non_decoded; - len = g_snprintf(buf, non_decoded_len-(buf-*non_decoded), "%lu", (unsigned long)oid[0]); - buf += len; - for (i = 1; i < oid_length; i++) { - len = g_snprintf(buf, non_decoded_len-(buf-*non_decoded), ".%lu", (unsigned long)oid[i]); - buf += len; + + if (ind){ + proto_item* pi = proto_tree_add_text(tree, tvb, seq_offset, seq_len,"Indicator must be clear in ObjectName"); + pt = proto_item_add_subtree(pi,ett_decoding_error); + expert_add_info_format(actx->pinfo, pi, PI_MALFORMED, PI_WARN, "ObjectName has indicator set"); + return dissect_unknown_ber(actx->pinfo, tvb, seq_offset, pt); } -} - -#ifdef HAVE_NET_SNMP -static gboolean -check_var_length(guint vb_length, guint required_length, guchar **errmsg) -{ - gchar *buf; - static const char badlen_fmt[] = "Length is %u, should be %u"; - - if (vb_length != required_length) { - /* Enough room for the largest "Length is XXX, - should be XXX" message - 10 digits for each - XXX. */ - buf = ep_alloc(sizeof badlen_fmt + 10 + 10); - if (buf != NULL) { - g_snprintf(buf, sizeof badlen_fmt + 10 + 10, - badlen_fmt, vb_length, required_length); - } - *errmsg = buf; - return FALSE; + + offset += name_len; + value_start = offset; + offset = get_ber_identifier(tvb, offset, &ber_class, &pc, &tag); + value_offset = offset = get_ber_length(NULL, tvb, offset, &value_len, &ind); + + if (! (!pc) ) { + proto_item* pi = proto_tree_add_text(tree, tvb, seq_offset, seq_len,"the value must be in primitive encoding"); + pt = proto_item_add_subtree(pi,ett_decoding_error); + expert_add_info_format(actx->pinfo, pi, PI_MALFORMED, PI_WARN, "value not in primitive encoding"); + return dissect_unknown_ber(actx->pinfo, tvb, seq_offset, pt); } - return TRUE; /* length is OK */ -} - -static gchar * -format_var(struct variable_list *variable, subid_t *variable_oid, - guint variable_oid_length, gushort vb_type, guint val_len) -{ - guchar *buf; - size_t buf_len; - size_t out_len; - - if (variable_oid == NULL || variable_oid_length == 0) - return NULL; - - switch (vb_type) { - - case SNMP_IPADDR: - /* Length has to be 4 bytes. */ - if (!check_var_length(val_len, 4, &buf)) - return buf; /* it's not 4 bytes */ - break; - -#ifdef REMOVED - /* not all counters are encoded as a full 64bit integer */ - case SNMP_COUNTER64: - /* Length has to be 8 bytes. */ - if (!check_var_length(val_len, 8, &buf)) - return buf; /* it's not 8 bytes */ - break; -#endif - default: - break; + + oid_bytes = ep_tvb_memdup(tvb, name_offset, name_len); + oid_info = oid_get_from_encoded(oid_bytes, name_len, &oid_matched, &oid_left); + + if (oid_left == 1 && ber_class != BER_CLASS_CON && tag != BER_UNI_TAG_NULL) { + if ((oid_info->value_type->ber_class != BER_CLASS_ANY) && + (ber_class != oid_info->value_type->ber_class)) + goto expected_different; + + if ((oid_info->value_type->ber_tag != BER_TAG_ANY) && + (tag != oid_info->value_type->ber_tag)) + goto expected_different; + + max_len = oid_info->value_type->max_len == -1 ? 0xffffff : oid_info->value_type->max_len; + min_len = oid_info->value_type->min_len; + + if ((int)value_len < min_len || (int)value_len > max_len) + goto expected_other_size; + + pi_varbind = proto_tree_add_item(tree,oid_info->value_hfid,tvb,value_offset,value_len,FALSE); + } else { + pi_varbind = proto_tree_add_text(tree,tvb,seq_offset,seq_len,"VarBind"); } + + pt = proto_item_add_subtree(pi_varbind,ett_varbind); + proto_tree_add_item(pt,hf_snmp_objectname,tvb,name_offset,name_len,FALSE); + + if (ber_class == BER_CLASS_CON) { + if (value_len != 0) + goto expected_other_size; + + switch (tag) { + case SERR_NSO: + hfid = hf_snmp_noSuchObject_value; + break; + case SERR_NSI: + hfid = hf_snmp_noSuchInstance_value; + break; + case SERR_EOM: + hfid = hf_snmp_endOfMibView_value; + break; + default: { + proto_item* pi = proto_tree_add_text(tree,tvb,0,0,"Wrong tag for Error Value: expected [0,1,2] got: %d",tag); + pt = proto_item_add_subtree(pi,ett_decoding_error); + expert_add_info_format(actx->pinfo, pi, PI_MALFORMED, PI_WARN, "Wrong tag for SNMP VarBind error value"); + return dissect_unknown_ber(actx->pinfo, tvb, value_start, tree); + } + } + } else { + + switch(ber_class|(tag<<4)) { + case BER_CLASS_UNI|(BER_UNI_TAG_INTEGER<<4): + max_len = 4; min_len = 1; + if (value_len > (guint)max_len && value_len < (guint)min_len) goto expected_other_size; + hfid = hf_snmp_integer32_value; + break; + case BER_CLASS_UNI|(BER_UNI_TAG_OCTETSTRING<<4): + hfid = hf_snmp_octestring_value; + break; + case BER_CLASS_UNI|(BER_UNI_TAG_OID<<4): + max_len = -1; min_len = 2; + if (value_len < (guint)min_len) goto expected_other_size; + hfid = hf_snmp_oid_value; + break; + case BER_CLASS_UNI|(BER_UNI_TAG_NULL<<4): + max_len = 0; min_len = 0; + if (value_len != 0) goto expected_other_size; + hfid = hf_snmp_null_value; + break; + case BER_CLASS_APP: /* | (SNMP_IPA<<4)*/ + switch(value_len) { + case 4: hfid = hf_snmp_ipv4_value; break; + case 16: hfid = hf_snmp_ipv6_value; break; + default: hfid = hf_snmp_anyaddress_value; break; + } + break; + case BER_CLASS_APP|(SNMP_U32<<4): + hfid = hf_snmp_unsigned32_value; + break; + case BER_CLASS_APP|(SNMP_GGE<<4): + hfid = hf_snmp_gauge32_value; + break; + case BER_CLASS_APP|(SNMP_CNT<<4): + hfid = hf_snmp_counter_value; + break; + case BER_CLASS_APP|(SNMP_TIT<<4): + hfid = hf_snmp_timeticks_value; + break; + case BER_CLASS_APP|(SNMP_OPQ<<4): + hfid = hf_snmp_opaque_value; + break; + case BER_CLASS_APP|(SNMP_NSP<<4): + hfid = hf_snmp_nsap_value; + break; + case BER_CLASS_APP|(SNMP_C64<<4): + hfid = hf_snmp_big_counter_value; + break; + default: + hfid = hf_snmp_unknown_value; + break; + } + } + + pi_value = proto_tree_add_item(pt,hfid,tvb,value_offset,value_len,FALSE); + + if (oid_left != 1) { + const char* unres = oid_encoded2string(oid_bytes, name_len); + char* repr = ep_alloc(ITEM_LABEL_LENGTH+1); + + proto_item_fill_label(pi_value->finfo, repr); + repr = strstr(repr,": "); + + label = g_strdup_printf("%s: %s",unres,repr); + proto_item_set_text(pi_varbind,label); - variable->next_variable = NULL; - variable->name = variable_oid; - variable->name_length = variable_oid_length; - switch (vb_type) { - - case SNMP_INTEGER: - variable->type = VALTYPE_INTEGER; - break; - - case SNMP_COUNTER: - variable->type = VALTYPE_COUNTER; - break; - - case SNMP_GAUGE: - variable->type = VALTYPE_GAUGE; - break; - - case SNMP_TIMETICKS: - variable->type = VALTYPE_TIMETICKS; - break; - - case SNMP_OCTETSTR: - variable->type = VALTYPE_STRING; - break; + } - case SNMP_IPADDR: - variable->type = VALTYPE_IPADDR; - break; - case SNMP_OPAQUE: - variable->type = VALTYPE_OPAQUE; - break; + return seq_offset + seq_len; - case SNMP_NSAP: - variable->type = VALTYPE_NSAP; - break; +expected_other_size: { + proto_item* pi = proto_tree_add_text(tree,tvb,0,0,"Wrong value length: %u expecting: %u <= len <= %u", + value_len, + min_len, + max_len == -1 ? 0xFFFFFF : max_len); + pt = proto_item_add_subtree(pi,ett_decoding_error); + expert_add_info_format(actx->pinfo, pi, PI_MALFORMED, PI_WARN, "Wrong length for SNMP VarBind/value"); + return dissect_unknown_ber(actx->pinfo, tvb, value_start, pt); + } - case SNMP_OBJECTID: - variable->type = VALTYPE_OBJECTID; - break; +expected_different: { + proto_item* pi = proto_tree_add_text(tree,tvb,0,0,"Wrong class/tag for Value expected: %d,%d got: %d,%d", + oid_info->value_type->ber_class, + oid_info->value_type->ber_tag, + ber_class, + tag); + pt = proto_item_add_subtree(pi,ett_decoding_error); + expert_add_info_format(actx->pinfo, pi, PI_MALFORMED, PI_WARN, "Wrong class/tag for SNMP VarBind/value"); + return dissect_unknown_ber(actx->pinfo, tvb, value_start, tree); + } - case SNMP_BITSTR: - variable->type = VALTYPE_BITSTR; - break; +} - case SNMP_COUNTER64: - variable->type = VALTYPE_COUNTER64; - break; - } - variable->val_len = val_len; - /* - * XXX - check for "sprint_realloc_objid()" failure. - */ +gchar* format_oid(subid_t *oid, guint oid_length) { + return (void*)oid_resolved(oid_length,oid); +} - buf_len = 1024; - buf = ep_alloc(buf_len); - if (buf != NULL) { - *buf = '\0'; - out_len = 0; - /* We pass an ep allocated block here, NOT a malloced block - * so we MUST NOT allow reallocation, hence the fourth - * parameter MUST be 0/FALSE - */ - sprint_realloc_value(&buf, &buf_len, &out_len, FALSE, - variable_oid, variable_oid_length, variable); - } - return buf; +void new_format_oid(subid_t *oid, guint oid_length, gchar **non_decoded, gchar **decoded) { + *decoded = (void*)oid_resolved(oid_length,oid); + *non_decoded = (void*)oid_subid2string(oid,oid_length); } -#endif #define F_SNMP_ENGINEID_CONFORM 0x80 @@ -824,279 +674,6 @@ dissect_snmp_engineid(proto_tree *tree, tvbuff_t *tvb, int offset, int len) return offset; } -/* This code is copied from the original SNMP dissector with minor changes to adapt it to use packet-ber.c routines - * TODO: - * - Rewrite it completly as OID as subid_t could be returned from dissect_ber_objectidentifier - * - vb_type_name is known when calling this routine(?) - * - All branches not needed(?) - * ... - */ - -static void -snmp_variable_decode(tvbuff_t *tvb, proto_tree *snmp_tree, asn1_ctx_t *actx,tvbuff_t *oid_tvb, - int offset, guint *lengthp, tvbuff_t **out_tvb) -{ - int start, vb_value_start; - guint length; - guint vb_length; - gushort vb_type; - const gchar *vb_type_name; - gint32 vb_integer_value; - guint32 vb_uinteger_value; - guint8 *vb_octet_string; - const guint8 *oid_buf; - subid_t *vb_oid; - guint vb_oid_length; - gchar *vb_display_string = NULL; - subid_t *variable_oid = NULL; - gint oid_len; - guint variable_oid_length = 0; - const guint8 *var_oid_buf; -#ifdef HAVE_NET_SNMP - struct variable_list variable; - long value; -#endif - unsigned int i; - gchar *buf; - int len; - gint8 class; - gboolean pc, ind = 0; - gint32 ber_tag; - - start = offset; - /* parse the type of the object */ - offset = dissect_ber_identifier(actx->pinfo, snmp_tree, tvb, start, &class, &pc, &ber_tag); - offset = dissect_ber_length(actx->pinfo, snmp_tree, tvb, offset, &vb_length, &ind); - - if(vb_length == 0){ - length = offset - start; - *lengthp = length; - return; - } - - vb_value_start = offset; - - /* Convert the class, constructed flag, and tag to a type. */ - vb_type_name = snmp_tag_cls2syntax(ber_tag, class, &vb_type); - - if (vb_type_name == NULL) { - /* - * Unsupported type. - * Dissect the value as an opaque string of octets. - */ - vb_type_name = "unsupported type"; - vb_type = SNMP_OPAQUE; - } - /* construct subid_t variable_oid from oid_tvb */ - if (oid_tvb){ - oid_len = tvb_length_remaining(oid_tvb,0); - var_oid_buf = tvb_get_ptr(oid_tvb, 0, oid_len); - variable_oid = ep_alloc((oid_len+1) * sizeof(gulong)); - variable_oid_length = oid_to_subid_buf(var_oid_buf, oid_len, variable_oid, ((oid_len+1) * sizeof(gulong))); - } - /* parse the value */ - switch (vb_type) { - - case SNMP_INTEGER: - offset = dissect_ber_integer(FALSE, actx, NULL, tvb, start, -1, (void*)&(vb_integer_value)); - length = offset - vb_value_start; - if (snmp_tree) { -#ifdef HAVE_NET_SNMP - value = vb_integer_value; - variable.val.integer = &value; - vb_display_string = format_var(&variable, - variable_oid, variable_oid_length, vb_type, - vb_length); -#else - vb_display_string = NULL; -#endif - if (vb_display_string != NULL) { - proto_tree_add_text(snmp_tree, tvb, - vb_value_start, length, - "Value: %s", vb_display_string); - } else { - proto_tree_add_text(snmp_tree,tvb, - vb_value_start, length, - "Value: %s: %d (%#x)", vb_type_name, - vb_integer_value, vb_integer_value); - } - } - break; - - case SNMP_COUNTER: - case SNMP_GAUGE: - case SNMP_TIMETICKS: - offset = dissect_ber_integer(FALSE, actx, NULL, tvb, start, -1, &vb_uinteger_value); - length = offset - vb_value_start; - if (snmp_tree) { -#ifdef HAVE_NET_SNMP - value = vb_uinteger_value; - variable.val.integer = &value; - vb_display_string = format_var(&variable, - variable_oid, variable_oid_length, vb_type, - vb_length); -#else - vb_display_string = NULL; -#endif - if (vb_display_string != NULL) { - proto_tree_add_text(snmp_tree, tvb, - vb_value_start, length, - "Value: %s", vb_display_string); - } else { - proto_tree_add_text(snmp_tree, tvb, - vb_value_start, length, - "Value: %s: %u (%#x)", vb_type_name, - vb_uinteger_value, vb_uinteger_value); - } - } - break; - case SNMP_COUNTER64: - offset=dissect_ber_integer64(TRUE, actx, snmp_tree, tvb, offset, hf_snmp_counter64, NULL); - break; - case SNMP_OCTETSTR: - case SNMP_IPADDR: - case SNMP_OPAQUE: - case SNMP_NSAP: - case SNMP_BITSTR: - offset = dissect_ber_octet_string(FALSE, actx, NULL, tvb, start, -1, out_tvb); - vb_octet_string = ep_tvb_memdup(tvb, vb_value_start, vb_length); - - length = offset - vb_value_start; - if (snmp_tree) { -#ifdef HAVE_NET_SNMP - variable.val.string = vb_octet_string; - vb_display_string = format_var(&variable, - variable_oid, variable_oid_length, vb_type, - vb_length); -#else - vb_display_string = NULL; -#endif - if (vb_display_string != NULL) { - proto_tree_add_text(snmp_tree, tvb, - vb_value_start, length, - "Value: %s", vb_display_string); - } else { - /* - * If some characters are not printable, - * display the string as bytes. - */ - for (i = 0; i < vb_length; i++) { - if (!(isprint(vb_octet_string[i]) - || isspace(vb_octet_string[i]))) - break; - } - if (i < vb_length) { - /* - * We stopped, due to a non-printable - * character, before we got to the end - * of the string. - */ - vb_display_string = ep_alloc(4*vb_length); - buf = vb_display_string; - len = g_snprintf(buf, 4*vb_length, "%03u", vb_octet_string[0]); - buf += len; - for (i = 1; i < vb_length; i++) { - len = g_snprintf(buf, 4*vb_length-(buf-vb_display_string), ".%03u", - vb_octet_string[i]); - buf += len; - } - proto_tree_add_text(snmp_tree, tvb, vb_value_start, - length, - "Value: %s: %s", vb_type_name, - vb_display_string); - } else { - proto_tree_add_text(snmp_tree, tvb, vb_value_start, - length, - "Value: %s: %s", vb_type_name, - SAFE_STRING(vb_octet_string, vb_length)); - } - } - } - break; - - case SNMP_NULL: - dissect_ber_null(FALSE, actx, NULL, tvb, start, -1); - length = offset - vb_value_start; - if (snmp_tree) { - proto_tree_add_text(snmp_tree, tvb, vb_value_start, length, - "Value: %s", vb_type_name); - } - break; - - case SNMP_OBJECTID: - /* XXX Redo this using dissect_ber_object_identifier when - it returns tvb or some other binary form of an OID */ - oid_buf = tvb_get_ptr(tvb, vb_value_start, vb_length); - vb_oid = ep_alloc((vb_length+1) * sizeof(gulong)); - vb_oid_length = oid_to_subid_buf(oid_buf, vb_length, vb_oid, ((vb_length+1) * sizeof(gulong))); - - offset = offset + vb_length; - length = offset - vb_value_start; - if (snmp_tree) { -#ifdef HAVE_NET_SNMP - variable.val.objid = vb_oid; - vb_display_string = format_var(&variable, - variable_oid, variable_oid_length, vb_type, - vb_oid_length * sizeof (subid_t)); - if (vb_display_string != NULL) { - proto_tree_add_text(snmp_tree, tvb, - vb_value_start, length, - "Value: %s", vb_display_string); - } else { - proto_tree_add_text(snmp_tree, tvb, - vb_value_start, length, - "Value: %s: [Out of memory]", vb_type_name); - } -#else /* HAVE_NET_SNMP */ - vb_display_string = format_oid(vb_oid, vb_oid_length); - if (vb_display_string != NULL) { - proto_tree_add_text(snmp_tree, tvb, - vb_value_start, length, - "Value: %s: %s", vb_type_name, - vb_display_string); - } else { - proto_tree_add_text(snmp_tree, tvb, - vb_value_start, length, - "Value: %s: [Out of memory]", vb_type_name); - } -#endif /* HAVE_NET_SNMP */ - } - break; - - case SNMP_NOSUCHOBJECT: - length = offset - start; - if (snmp_tree) { - proto_tree_add_text(snmp_tree, tvb, offset, length, - "Value: %s: no such object", vb_type_name); - } - break; - - case SNMP_NOSUCHINSTANCE: - length = offset - start; - if (snmp_tree) { - proto_tree_add_text(snmp_tree, tvb, offset, length, - "Value: %s: no such instance", vb_type_name); - } - break; - - case SNMP_ENDOFMIBVIEW: - length = offset - start; - if (snmp_tree) { - proto_tree_add_text(snmp_tree, tvb, offset, length, - "Value: %s: end of mib view", vb_type_name); - } - break; - - default: - DISSECTOR_ASSERT_NOT_REACHED(); - return; - } - length = offset - start; - *lengthp = length; - return; -} - - static void set_ue_keys(snmp_ue_assoc_t* n ) { guint key_size = n->user.authModel->key_size; @@ -1879,62 +1456,7 @@ static void snmp_usm_password_to_key_sha1(const guint8 *password, } -static void -process_prefs(void) -{ -#ifdef HAVE_NET_SNMP - gchar *tmp_mib_modules; - static gboolean mibs_loaded = FALSE; - - if (mibs_loaded) { - /* - * Unload the MIBs, as we'll be reloading them based on - * the current preference setting. - */ - shutdown_mib(); /* unload MIBs */ - } - - /* - * Cannot check if MIBS is already set, as it could be set by Wireshark. - * - * If we have a list of modules to load, put that list in MIBS, - * otherwise clear MIBS. - */ - if (mib_modules != NULL) { - tmp_mib_modules = g_strconcat("MIBS=", mib_modules, NULL); - /* - * Try to be clever and replace colons for semicolons under - * Windows. Do the converse on non-Windows systems. This - * handles cases where we've copied a preferences file - * between a non-Windows box and a Windows box or upgraded - * from an older version of Wireshark under Windows. - */ - g_strdelimit(tmp_mib_modules, IMPORT_SEPARATOR, ENV_SEPARATOR_CHAR); - -#ifdef _WIN32 - _putenv(tmp_mib_modules); -#else - putenv(tmp_mib_modules); -#endif /*_WIN32*/ - } else { -#ifdef _WIN32 - _putenv("MIBS"); -#else - putenv("MIBS"); -#endif /* _WIN32 */ - } - - /* - * Load the MIBs. - */ - register_mib_handlers(); - read_premib_configs(); - init_mib(); - read_configs(); - mibs_loaded = TRUE; -#endif /* HAVE_NET_SNMP */ - -} +static void process_prefs(void) {} static void* snmp_users_copy_cb(void* dest, const void* orig, unsigned len _U_) { const snmp_ue_assoc_t* o = orig; @@ -2006,16 +1528,8 @@ UAT_BUFFER_CB_DEF(snmp_users,engine_id,snmp_ue_assoc_t,engine.data,engine.len) UAT_VS_DEF(snmp_users,auth_model,snmp_ue_assoc_t,0,"MD5") UAT_VS_DEF(snmp_users,priv_proto,snmp_ue_assoc_t,0,"DES") - /*--- proto_register_snmp -------------------------------------------*/ void proto_register_snmp(void) { -#if defined(_WIN32) && defined(HAVE_NET_SNMP) - char *mib_path; - int mib_path_len; -#define MIB_PATH_APPEND "snmp\\mibs" -#endif - gchar *tmp_mib_modules; - /* List of fields */ static hf_register_info hf[] = { { &hf_snmp_v3_flags_auth, @@ -2054,21 +1568,31 @@ void proto_register_snmp(void) { { &hf_snmp_engineid_data, { "Engine ID Data", "snmp.engineid.data", FT_BYTES, BASE_HEX, NULL, 0, "Engine ID Data", HFILL }}, - { &hf_snmp_counter64, { - "Value", "snmp.counter64", FT_INT64, BASE_DEC, - NULL, 0, "A counter64 value", HFILL }}, { &hf_snmp_msgAuthentication, { "Authentication", "snmp.v3.auth", FT_BOOLEAN, 8, TFS(&auth_flags), 0, "", HFILL }}, { &hf_snmp_decryptedPDU, { "Decrypted ScopedPDU", "snmp.decrypted_pdu", FT_BYTES, BASE_HEX, NULL, 0, "Decrypted PDU", HFILL }}, - { &hf_snmp_internet_ipv6, { - "internet", "snmp.internet", FT_IPv6, BASE_NONE, - NULL, 0, "", HFILL }}, - { &hf_snmp_internet_other, { - "internet", "snmp.internet", FT_BYTES, BASE_NONE, - NULL, 0, "", HFILL }}, + { &hf_snmp_noSuchObject_value, { "noSuchObject", "snmp.noSuchObject", FT_NONE, BASE_NONE, NULL, 0, "", HFILL }}, + { &hf_snmp_noSuchInstance_value, { "noSuchInstance", "snmp.noSuchInstance", FT_NONE, BASE_DEC, NULL, 0, "", HFILL }}, + { &hf_snmp_endOfMibView_value, { "endOfMibView", "snmp.endOfMibView", FT_NONE, BASE_DEC, NULL, 0, "", HFILL }}, + { &hf_snmp_integer32_value, { "Value (Integer32)", "snmp.value.int", FT_INT64, BASE_DEC, NULL, 0, "", HFILL }}, + { &hf_snmp_octestring_value, { "Value (OctetString)", "snmp.value.octets", FT_BYTES, BASE_NONE, NULL, 0, "", HFILL }}, + { &hf_snmp_oid_value, { "Value (OID)", "snmp.value.oid", FT_OID, BASE_NONE, NULL, 0, "", HFILL }}, + { &hf_snmp_null_value, { "Value (Null)", "snmp.value.null", FT_NONE, BASE_NONE, NULL, 0, "", HFILL }}, + { &hf_snmp_ipv4_value, { "Value (IpAddress)", "snmp.value.ipv4", FT_IPv4, BASE_NONE, NULL, 0, "", HFILL }}, + { &hf_snmp_ipv6_value, { "Value (IpAddress)", "snmp.value.ipv6", FT_IPv6, BASE_NONE, NULL, 0, "", HFILL }}, + { &hf_snmp_anyaddress_value, { "Value (IpAddress)", "snmp.value.addr", FT_BYTES, BASE_DEC, NULL, 0, "", HFILL }}, + { &hf_snmp_unsigned32_value, { "Value (Unsigned32)", "snmp.value.u32", FT_INT64, BASE_DEC, NULL, 0, "", HFILL }}, + { &hf_snmp_gauge32_value, { "Value (Gauge32)", "snmp.value.g32", FT_INT64, BASE_DEC, NULL, 0, "", HFILL }}, + { &hf_snmp_unknown_value, { "Value (Unknown)", "snmp.value.unk", FT_BYTES, BASE_NONE, NULL, 0, "", HFILL }}, + { &hf_snmp_counter_value, { "Value (Counter32)", "snmp.value.counter", FT_UINT64, BASE_DEC, NULL, 0, "", HFILL }}, + { &hf_snmp_nsap_value, { "Value (NSAP)", "snmp.value.nsap", FT_UINT64, BASE_DEC, NULL, 0, "", HFILL }}, + { &hf_snmp_timeticks_value, { "Value (Timeticks)", "snmp.value.timeticks", FT_UINT64, BASE_DEC, NULL, 0, "", HFILL }}, + { &hf_snmp_opaque_value, { "Value (Opaque)", "snmp.value.opaque", FT_BYTES, BASE_NONE, NULL, 0, "", HFILL }}, + { &hf_snmp_objectname, { "Object Name", "snmp.name", FT_OID, BASE_NONE, NULL, 0, "", HFILL }}, + #include "packet-snmp-hfarr.c" }; @@ -2081,11 +1605,12 @@ void proto_register_snmp(void) { &ett_decrypted, &ett_authParameters, &ett_internet, - + &ett_varbind, + &ett_decoding_error, #include "packet-snmp-ettarr.c" }; module_t *snmp_module; - static uat_field_t fields[] = { + static uat_field_t users_fields[] = { UAT_FLD_BUFFER(snmp_users,engine_id,"Engine-id for this entry (empty = any)"), UAT_FLD_LSTRING(snmp_users,userName,"The username"), UAT_FLD_VS(snmp_users,auth_model,auth_types,"Algorithm to be used for authentication."), @@ -2094,7 +1619,7 @@ void proto_register_snmp(void) { UAT_FLD_LSTRING(snmp_users,privPassword,"The password used for encrypting packets for this entry"), UAT_END_FIELDS }; - + assocs_uat = uat_new("SNMP Users", sizeof(snmp_ue_assoc_t), "snmp_users", @@ -2105,37 +1630,8 @@ void proto_register_snmp(void) { snmp_users_copy_cb, snmp_users_update_cb, snmp_users_free_cb, - fields); - -#ifdef HAVE_NET_SNMP - -#ifdef _WIN32 - /* Set MIBDIRS so that the SNMP library can find its mibs. */ - /* XXX - Should we set MIBS or MIBFILES as well? */ - mib_path_len=strlen(get_datafile_dir()) + strlen(MIB_PATH_APPEND) + 20; - mib_path = ep_alloc (mib_path_len); - g_snprintf (mib_path, mib_path_len, "MIBDIRS=%s\\%s", get_datafile_dir(), MIB_PATH_APPEND); - /* Amazingly enough, Windows does not provide setenv(). */ - if (getenv("MIBDIRS") == NULL) - _putenv(mib_path); - -#endif /* _WIN32 */ - - /* - * Suppress warnings about unknown tokens - we aren't initializing - * Net-SNMP in its entirety, we're just initializing the - * MIB-handling part because that's all we're using, which - * means that entries in the configuration file for other - * pars of the library will not be handled, and we don't want - * the config file reading code to whine about that. - */ - netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, - NETSNMP_DS_LIB_NO_TOKEN_WARNINGS, TRUE); - netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID, - NETSNMP_DS_LIB_PRINT_SUFFIX_ONLY, 2); -#endif /* HAVE_NET_SNMP */ - - + users_fields); + /* Register protocol */ proto_snmp = proto_register_protocol(PNAME, PSNAME, PFNAME); new_register_dissector("snmp", dissect_snmp, proto_snmp); @@ -2152,42 +1648,26 @@ void proto_register_snmp(void) { "Whether the SNMP OID should be shown in the info column", &display_oid); - /* - * Set the default value of "mib_modules". - * - * If the MIBS environment variable is set, make its value - * the value of "mib_modules", otherwise, set "mib_modules" - * to DEF_MIB_MODULES. - */ - tmp_mib_modules = getenv("MIBS"); - if (tmp_mib_modules != NULL) - mib_modules = tmp_mib_modules; - prefs_register_string_preference(snmp_module, "mib_modules", - "MIB modules to load", - "List of MIB modules to load (the list is set to environment variable MIBS if the variable is not already set)" - "The list must be separated by colons (:) on non-Windows systems and semicolons (;) on Windows systems", - &mib_modules); + prefs_register_obsolete_preference(snmp_module, "mib_modules"); + prefs_register_obsolete_preference(snmp_module, "var_in_tree"); + prefs_register_obsolete_preference(snmp_module, "users_file"); + prefs_register_bool_preference(snmp_module, "desegment", "Reassemble SNMP-over-TCP messages\nspanning multiple TCP segments", "Whether the SNMP dissector should reassemble messages spanning multiple TCP segments." " To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.", &snmp_desegment); - prefs_register_bool_preference(snmp_module, "var_in_tree", - "Display dissected variables inside SNMP tree", - "ON - display dissected variables inside SNMP tree, OFF - display dissected variables in root tree after SNMP", - &snmp_var_in_tree); - - prefs_register_obsolete_preference(snmp_module, "users_file"); prefs_register_uat_preference(snmp_module, "users_table", "Users Table", "Table of engine-user associations used for authentication and decryption", assocs_uat); - - variable_oid_dissector_table = - register_dissector_table("snmp.variable_oid", - "SNMP Variable OID", FT_STRING, BASE_NONE); + + + variable_oid_dissector_table = register_dissector_table("snmp.variable_oid", + "SNMP Variable OID", + FT_STRING, BASE_NONE); register_init_routine(renew_ue_cache); } diff --git a/asn1/snmp/snmp.asn b/asn1/snmp/snmp.asn index 8091733647..d9c7e1c33b 100644 --- a/asn1/snmp/snmp.asn +++ b/asn1/snmp/snmp.asn @@ -1,568 +1,338 @@ -- $Id$ - RFC1157-SNMP DEFINITIONS ::= BEGIN - +RFC1157-SNMP DEFINITIONS ::= BEGIN + -- IMPORTS -- ObjectName, ObjectSyntax, NetworkAddress, IpAddress, TimeTicks -- FROM RFC1155-SMI; - +-- -- Local imports -- IMPORTS -- ObjectName, ObjectSyntax, NetworkAddress, IpAddress, TimeTicks -- FROM RFC1155-SMI; - +-- -- names of objects -- (Note that these definitions of ObjectName and NotificationName -- are not to be IMPORTed by MIB modules.) +-- -ObjectName ::= - OBJECT IDENTIFIER +--ObjectSyntax ::= CHOICE { +-- simple SimpleSyntax, +-- application-wide ApplicationSyntax +--} -NotificationName ::= - OBJECT IDENTIFIER +--SimpleSyntax ::= CHOICE { +-- integer-value Integer-value, +-- string-value String-value, +-- objectID-value ObjectID-value, +-- empty Empty +--} --- syntax of objects +--String-value ::= OCTET STRING (SIZE (0..65535)) --- the "base types" defined here are: --- 3 built-in ASN.1 types: INTEGER, OCTET STRING, OBJECT IDENTIFIER --- 8 application-defined types: Integer32, IpAddress, Counter32, --- Gauge32, Unsigned32, TimeTicks, Opaque, and Counter64 + -- includes Integer32 +--Integer-value ::= INTEGER (-2147483648..2147483647) -ObjectSyntax ::= - CHOICE { - simple - SimpleSyntax, +--Integer32 ::= INTEGER (-2147483648..2147483647) - -- note that SEQUENCEs for conceptual tables and - -- rows are not mentioned here... +--ObjectID-value ::= OBJECT IDENTIFIER - application-wide - ApplicationSyntax - } --- built-in ASN.1 types +--Empty ::= NULL -SimpleSyntax ::= - CHOICE { - -- INTEGERs with a more restrictive range - -- may also be used - integer-value Integer-value, + -- hundredths of seconds since an event, usualy the last restart +--TimeTicks ::= [APPLICATION 3] IMPLICIT INTEGER (0..4294967295) - -- OCTET STRINGs with a more restrictive size - -- may also be used - string-value String-value, +--Opaque ::= [APPLICATION 4] IMPLICIT OCTET STRING - objectID-value ObjectID-value, - empty Empty - -- Added from RFC 1155 for Wireshark - } -String-value ::= OCTET STRING (SIZE (0..65535)) +--Counter64 ::= [APPLICATION 6] IMPLICIT INTEGER (0..18446744073709551615) -Integer-value ::= -- includes Integer32 - INTEGER (-2147483648..2147483647) - -- OCTET STRINGs with a more restrictive size - -- may also be used +--ApplicationSyntax ::= CHOICE { +-- ipAddress-value IpAddress, +-- counter-value Counter32, +-- timeticks-value TimeTicks, +-- arbitrary-value Opaque, +-- big-counter-value Counter64, +-- unsigned-integer-value Unsigned32 + -- includes Gauge32 +--} +--NetworkAddress ::= CHOICE { internet IpAddress } +--IpAddress ::= [APPLICATION 0] IMPLICIT OCTET STRING (SIZE (4)) --- indistinguishable from INTEGER, but never needs more than --- 32-bits for a two's complement representation +NotificationName ::= OBJECT IDENTIFIER +NetworkAddress ::= [APPLICATION 0] IMPLICIT OCTET STRING (SIZE (4)) +TimeTicks ::= [APPLICATION 3] IMPLICIT INTEGER (0..4294967295) Integer32 ::= INTEGER (-2147483648..2147483647) +ObjectName ::= OBJECT IDENTIFIER +--Counter32 ::= [APPLICATION 1] IMPLICIT INTEGER (0..4294967295) +--Gauge32 ::= [APPLICATION 2] IMPLICIT INTEGER (0..4294967295) +--Unsigned32 ::= [APPLICATION 2] IMPLICIT INTEGER (0..4294967295) -ObjectID-value ::= OBJECT IDENTIFIER - -Empty ::= NULL - -- Added from RFC 1155 for Wireshark - --- application-wide types - -ApplicationSyntax ::= - CHOICE { - ipAddress-value - IpAddress, - - counter-value - Counter32, - - timeticks-value - TimeTicks, - - arbitrary-value - Opaque, - - big-counter-value - Counter64, - - unsigned-integer-value -- includes Gauge32 - Unsigned32 - } - -NetworkAddress ::= - CHOICE { - internet - IpAddress - } - --- in network-byte order --- (this is a tagged type for historical reasons) -IpAddress ::= - [APPLICATION 0] - IMPLICIT OCTET STRING (SIZE (4)) - --- see http://bugs.wireshark.org/bugzilla/show_bug.cgi?id=1125 -IpAddressIpv6 ::= [APPLICATION 0] IMPLICIT OCTET STRING (SIZE (16)) -IpAddressOther ::= [APPLICATION 0] IMPLICIT OCTET STRING - --- this wraps -Counter32 ::= - [APPLICATION 1] - IMPLICIT INTEGER (0..4294967295) - --- this doesn't wrap -Gauge32 ::= - [APPLICATION 2] - IMPLICIT INTEGER (0..4294967295) - --- an unsigned 32-bit quantity --- indistinguishable from Gauge32 -Unsigned32 ::= - [APPLICATION 2] - IMPLICIT INTEGER (0..4294967295) - --- hundredths of seconds since an epoch -TimeTicks ::= - [APPLICATION 3] - IMPLICIT INTEGER (0..4294967295) +-- End Import --- for backward-compatibility only -Opaque ::= - [APPLICATION 4] - IMPLICIT OCTET STRING +Message ::= SEQUENCE { + version Version, + community OCTET STRING, + data PDUs +} --- for counters that wrap in less than one hour with only 32 bits -Counter64 ::= - [APPLICATION 6] - IMPLICIT INTEGER (0..18446744073709551615) +Version ::= INTEGER { version-1(0), v2c(1), v2u (2), snmpv3(3) } +Messagev2u ::= + SEQUENCE { + version Version, + parameters OCTET STRING, + -- <model=1> + -- <qoS><agentID><agentBoots><agentTime><maxSize> + -- <userLen><userName><authLen><authDigest> + -- <contextSelector> + datav2u CHOICE { + plaintext PDUs, + encrypted OCTET STRING + } +} --- End Import - -- top-level message - - Message ::= - SEQUENCE { - version Version, -- version-1 for this RFC - - community -- community name - OCTET STRING, - - data -- e.g., PDUs if trivial - PDUs --- ANY --- authentication is being used - } - -Version ::= INTEGER { - version-1(0), - v2c(1), - v2u (2), - snmpv3(3) - } - - - Messagev2u ::= - SEQUENCE { - version Version, --- INTEGER { v2 (2) }, - - parameters - OCTET STRING, - -- <model=1> - -- <qoS><agentID><agentBoots><agentTime><maxSize> - -- <userLen><userName><authLen><authDigest> - -- <contextSelector> - - datav2u - CHOICE { - plaintext - PDUs, - encrypted - OCTET STRING - } - } -- USMSecurityParametersSyntax DEFINITIONS IMPLICIT TAGS ::= BEGIN - UsmSecurityParameters ::= - SEQUENCE { - -- global User-based security parameters - msgAuthoritativeEngineID SnmpEngineID, - msgAuthoritativeEngineBoots INTEGER (0..2147483647), - msgAuthoritativeEngineTime INTEGER (0..2147483647), - msgUserName OCTET STRING (SIZE(1..32)), - -- authentication protocol specific parameters - msgAuthenticationParameters OCTET STRING, - -- privacy protocol specific parameters - msgPrivacyParameters OCTET STRING - } +UsmSecurityParameters ::= SEQUENCE { + -- global User-based security parameters + msgAuthoritativeEngineID SnmpEngineID, + msgAuthoritativeEngineBoots INTEGER (0..2147483647), + msgAuthoritativeEngineTime INTEGER (0..2147483647), + msgUserName OCTET STRING (SIZE(1..32)), + -- authentication protocol specific parameters + msgAuthenticationParameters OCTET STRING, + -- privacy protocol specific parameters + msgPrivacyParameters OCTET STRING +} -- END USMSecurityParametersSyntax SnmpEngineID ::= OCTET STRING -- SNMPv3MessageSyntax DEFINITIONS IMPLICIT TAGS ::= BEGIN - SNMPv3Message ::= SEQUENCE { - -- identify the layout of the SNMPv3Message - -- this element is in same position as in SNMPv1 - -- and SNMPv2c, allowing recognition - -- the value 3 is used for snmpv3 - msgVersion Version, - -- INTEGER ( 0 .. 2147483647 ), - -- administrative parameters - msgGlobalData HeaderData, - -- security model-specific parameters - -- format defined by Security Model - msgSecurityParameters OCTET STRING, - msgData ScopedPduData - } - - HeaderData ::= SEQUENCE { - msgID INTEGER (0..2147483647), - msgMaxSize INTEGER (484..2147483647), - - msgFlags OCTET STRING (SIZE(1)), - -- .... ...1 authFlag - -- .... ..1. privFlag - -- .... .1.. reportableFlag - -- Please observe: - -- .... ..00 is OK, means noAuthNoPriv - -- .... ..01 is OK, means authNoPriv - -- .... ..10 reserved, must NOT be used. - -- .... ..11 is OK, means authPriv - - msgSecurityModel INTEGER (1..2147483647) - } - - - ScopedPduData ::= CHOICE { - plaintext ScopedPDU, - encryptedPDU OCTET STRING -- encrypted scopedPDU value - } - - ScopedPDU ::= SEQUENCE { - contextEngineID OCTET STRING, - contextName OCTET STRING, - data PDUs - -- ANY - -- e.g., PDUs as defined in RFC 1905 - } +SNMPv3Message ::= SEQUENCE { + -- identify the layout of the SNMPv3Message + -- this element is in same position as in SNMPv1 + -- and SNMPv2c, allowing recognition + -- the value 3 is used for snmpv3 + msgVersion Version, + -- INTEGER ( 0 .. 2147483647 ), + -- administrative parameters + msgGlobalData HeaderData, + -- security model-specific parameters + -- format defined by Security Model + msgSecurityParameters OCTET STRING, + msgData ScopedPduData +} + +HeaderData ::= SEQUENCE { + msgID INTEGER (0..2147483647), + msgMaxSize INTEGER (484..2147483647), + + msgFlags OCTET STRING (SIZE(1)), + -- .... ...1 authFlag + -- .... ..1. privFlag + -- .... .1.. reportableFlag + -- Please observe: + -- .... ..00 is OK, means noAuthNoPriv + -- .... ..01 is OK, means authNoPriv + -- .... ..10 reserved, must NOT be used. + -- .... ..11 is OK, means authPriv + + msgSecurityModel INTEGER (1..2147483647) +} + + +ScopedPduData ::= CHOICE { + plaintext ScopedPDU, + encryptedPDU OCTET STRING -- encrypted scopedPDU value +} + +ScopedPDU ::= SEQUENCE { + contextEngineID OCTET STRING, + contextName OCTET STRING, + data PDUs + -- ANY + -- e.g., PDUs as defined in RFC 1905 +} -- END SNMPv3MessageSyntax -- protocol data units - PDUs ::= - CHOICE { - get-request - GetRequest-PDU, - - get-next-request - GetNextRequest-PDU, - - get-response - GetResponse-PDU, - - set-request - SetRequest-PDU, +PDUs ::= CHOICE { + get-request GetRequest-PDU, + get-next-request GetNextRequest-PDU, + get-response GetResponse-PDU, + set-request SetRequest-PDU, + trap Trap-PDU, + getBulkRequest GetBulkRequest-PDU, + informRequest InformRequest-PDU, + sNMPv2-Trap SNMPv2-Trap-PDU, + report Report-PDU +} - trap - Trap-PDU, - -- v2 added ? +-- PDUs - getBulkRequest - GetBulkRequest-PDU, +GetRequest-PDU ::= [0] IMPLICIT PDU +GetNextRequest-PDU ::= [1] IMPLICIT PDU +GetResponse-PDU ::= [2] IMPLICIT PDU - informRequest - InformRequest-PDU, +SetRequest-PDU ::= [3] IMPLICIT PDU - sNMPv2-Trap - SNMPv2-Trap-PDU, - - report - Report-PDU - } - - -- PDUs - - GetRequest-PDU ::= - [0] - IMPLICIT PDU - - GetNextRequest-PDU ::= - [1] - IMPLICIT PDU - - GetResponse-PDU ::= - [2] - IMPLICIT PDU - - SetRequest-PDU ::= - [3] - IMPLICIT PDU -- v2 added - -- [4] is obsolete - - GetBulkRequest-PDU ::= - [5] - IMPLICIT BulkPDU - - InformRequest-PDU ::= - [6] - IMPLICIT PDU - - SNMPv2-Trap-PDU ::= - [7] - IMPLICIT PDU +-- [4] is obsolete +GetBulkRequest-PDU ::= [5] IMPLICIT BulkPDU +InformRequest-PDU ::= [6] IMPLICIT PDU +SNMPv2-Trap-PDU ::= [7] IMPLICIT PDU -- Usage and precise semantics of Report-PDU are not presently -- defined. Any SNMP administrative framework making use of -- this PDU must define its usage and semantics. - Report-PDU ::= - [8] - IMPLICIT PDU - - - PDU ::= - SEQUENCE { - request-id - INTEGER, - - error-status -- sometimes ignored - INTEGER { - noError(0), - tooBig(1), - noSuchName(2), -- for proxy compatibility - badValue(3), -- for proxy compatibility - readOnly(4), -- for proxy compatibility - genErr(5), - noAccess(6), - wrongType(7), - wrongLength(8), - wrongEncoding(9), - wrongValue(10), - noCreation(11), - inconsistentValue(12), - resourceUnavailable(13), - commitFailed(14), - undoFailed(15), - authorizationError(16), - notWritable(17), - inconsistentName(18) - }, - - - error-index -- sometimes ignored - INTEGER, - - variable-bindings -- values are sometimes ignored - VarBindList - } --- v2 - BulkPDU ::= -- MUST be identical in - SEQUENCE { -- structure to PDU - request-id - Integer32, - - non-repeaters - INTEGER (0..2147483647), +Report-PDU ::= [8] IMPLICIT PDU + + +PDU ::= SEQUENCE { + request-id INTEGER, + error-status INTEGER { + noError(0), + tooBig(1), + noSuchName(2), -- for proxy compatibility + badValue(3), -- for proxy compatibility + readOnly(4), -- for proxy compatibility + genErr(5), + noAccess(6), + wrongType(7), + wrongLength(8), + wrongEncoding(9), + wrongValue(10), + noCreation(11), + inconsistentValue(12), + resourceUnavailable(13), + commitFailed(14), + undoFailed(15), + authorizationError(16), + notWritable(17), + inconsistentName(18) + }, + error-index INTEGER, + variable-bindings VarBindList +} - max-repetitions - INTEGER (0..2147483647), - - variable-bindings -- values are ignored - VarBindList - } +-- v2 +BulkPDU ::= SEQUENCE { -- MUST be identical in structure to PDU + request-id Integer32, + non-repeaters INTEGER (0..2147483647), + max-repetitions INTEGER (0..2147483647), + variable-bindings VarBindList +} -- end v2 - Trap-PDU ::= - [4] - IMPLICIT SEQUENCE { - enterprise -- type of object generating - -- trap, see sysObjectID in [5] - - - OBJECT IDENTIFIER, - - agent-addr -- address of object generating - NetworkAddress, -- trap - - generic-trap -- generic trap type - INTEGER { - coldStart(0), - warmStart(1), - linkDown(2), - linkUp(3), - authenticationFailure(4), - egpNeighborLoss(5), - enterpriseSpecific(6) - }, - - specific-trap INTEGER, --- specific code, present even --- if generic-trap is not --- enterpriseSpecific - - time-stamp TimeTicks, --- time elapsed between the last --- (re)initialization of the network --- entity and the generation of the trap - - variable-bindings VarBindList --- "interesting" information - } +Trap-PDU ::= [4] IMPLICIT SEQUENCE { + enterprise OBJECT IDENTIFIER, -- type of object generating trap, see sysObjectID in [5] + agent-addr NetworkAddress, -- address of object generating trap + generic-trap INTEGER { -- generic trap type + coldStart(0), + warmStart(1), + linkDown(2), + linkUp(3), + authenticationFailure(4), + egpNeighborLoss(5), + enterpriseSpecific(6) + }, + specific-trap INTEGER, -- specific code, present even if generic-trap is not enterpriseSpecific + time-stamp TimeTicks, -- time elapsed between the last (re)initialization of the network entity and the generation of the trap + variable-bindings VarBindList -- "interesting" information +} -- variable bindings - VarBind ::= - SEQUENCE { - name - ObjectName, - - valueType ValueType - } - -ValueType ::= - CHOICE { - value - ObjectSyntax, - - unSpecified -- in retrieval requests - NULL, - - -- exceptions in responses - noSuchObject[0] - IMPLICIT NULL, - - noSuchInstance[1] - IMPLICIT NULL, +VarBind ::= SEQUENCE { name ObjectName, valueType NULL } +-- SEQUENCE { +-- name ObjectName, +-- valueType ValueType +-- } - endOfMibView[2] - IMPLICIT NULL - } - +--ValueType ::= CHOICE { +-- value ObjectSyntax, +-- unSpecified NULL, + -- in retrieval requests + -- exceptions in responses +-- noSuchObject[0] IMPLICIT NULL, +-- noSuchInstance[1] IMPLICIT NULL, +-- endOfMibView[2] IMPLICIT NULL +--} - VarBindList ::= - SEQUENCE OF - VarBind +VarBindList ::= SEQUENCE OF VarBind -- SMUX DEFINITIONS ::= BEGIN RFC 1227 -SMUX-PDUs ::= - CHOICE { - open -- SMUX peer uses - OpenPDU, -- immediately after TCP open - - close -- either uses immediately before TCP close - ClosePDU, - - registerRequest -- SMUX peer uses - RReqPDU, +SMUX-PDUs ::= CHOICE { + open OpenPDU,-- SMUX peer uses immediately after TCP open + close ClosePDU, -- either uses immediately before TCP close + registerRequest RReqPDU, -- SMUX peer uses -- registerResponse .. SNMP agent uses -- RRspPDU, -- -- PDUs, --- Revritten - registerResponse RegisterResponse, - -- note that roles are reversed: - -- SNMP agent does get/get-next/set - -- SMUX peer does get-response/trap +-- Rewritten + registerResponse RegisterResponse, + -- note that roles are reversed: + -- SNMP agent does get/get-next/set + -- SMUX peer does get-response/trap - commitOrRollback -- SNMP agent uses - SOutPDU - } + commitOrRollback -- SNMP agent uses + SOutPDU +} RegisterResponse ::= CHOICE { rRspPDU RRspPDU, pDUs PDUs - } +} -- open PDU -- currently only simple authentication - OpenPDU ::= - CHOICE { - smux-simple - - SimpleOpen - } +OpenPDU ::= CHOICE { + smux-simple SimpleOpen +} - SimpleOpen ::= - [APPLICATION 0] IMPLICIT - SEQUENCE { - smux-version -- of SMUX protocol - INTEGER { - version-1(0) - }, - - identity -- of SMUX peer, authoritative - OBJECT IDENTIFIER, - - description -- of SMUX peer, implementation-specific - DisplayString, - - password -- zero length indicates no authentication - OCTET STRING - } +SimpleOpen ::= [APPLICATION 0] IMPLICIT SEQUENCE { + smux-version INTEGER { version-1(0) }, -- of SMUX protocol + identity OBJECT IDENTIFIER, -- of SMUX peer, authoritative + description DisplayString, -- of SMUX peer, implementation-specific + password OCTET STRING -- zero length indicates no authentication +} DisplayString ::= OCTET STRING - -- close PDU - ClosePDU ::= - [APPLICATION 1] IMPLICIT - INTEGER { - goingDown(0), - unsupportedVersion(1), - packetFormat(2), - protocolError(3), - internalError(4), - authenticationFailure(5) - } +ClosePDU ::= [APPLICATION 1] IMPLICIT INTEGER { + goingDown(0), + unsupportedVersion(1), + packetFormat(2), + protocolError(3), + internalError(4), + authenticationFailure(5) +} -- insert PDU +RReqPDU ::= [APPLICATION 2] IMPLICIT SEQUENCE { + subtree ObjectName, + priority INTEGER (-1..2147483647), -- the lower the better, "-1" means default + + operation INTEGER { + delete(0), -- remove registration + readOnly(1), -- add registration, objects are RO + readWrite(2) -- .., objects are RW + } +} - RReqPDU ::= - [APPLICATION 2] IMPLICIT - SEQUENCE { - subtree - ObjectName, - - priority -- the lower the better, "-1" means default - INTEGER (-1..2147483647), - - operation - - INTEGER { - delete(0), -- remove registration - readOnly(1), -- add registration, objects are RO - readWrite(2) -- .., objects are RW - } - } - - RRspPDU ::= - [APPLICATION 3] IMPLICIT - INTEGER { - failure(-1) - - -- on success the non-negative priority is returned - } - - SOutPDU ::= - [APPLICATION 4] IMPLICIT - INTEGER { - commit(0), - rollback(1) - } - - +RRspPDU ::= [APPLICATION 3] IMPLICIT INTEGER { failure(-1) } -- on success the non-negative priority is returned +SOutPDU ::= [APPLICATION 4] IMPLICIT INTEGER { commit(0), rollback(1) } - END +END diff --git a/asn1/snmp/snmp.cnf b/asn1/snmp/snmp.cnf index 7d75cf261d..486da745ef 100644 --- a/asn1/snmp/snmp.cnf +++ b/asn1/snmp/snmp.cnf @@ -12,9 +12,9 @@ GetNextRequest-PDU GetResponse-PDU SetRequest-PDU GetRequest-PDU -Gauge32 NotificationName SnmpEngineID +VarBind #.TYPE_RENAME @@ -221,6 +221,9 @@ gint pdu_type; expert_add_info_format(actx->pinfo, cause, PI_MALFORMED, PI_WARN, "Failed to decrypt encryptedPDU: %%s", error); + + if (check_col(actx->pinfo->cinfo, COL_INFO)) + col_add_str(actx->pinfo->cinfo, COL_INFO, "encryptedPDU: Failed to decrypt"); return offset; } else { @@ -233,10 +236,14 @@ gint pdu_type; expert_add_info_format(actx->pinfo, cause, PI_MALFORMED, PI_WARN, "Decrypted data not formated as expected"); + + if (check_col(actx->pinfo->cinfo, COL_INFO)) + col_add_str(actx->pinfo->cinfo, COL_INFO, "encryptedPDU: Decrypted data not formated as expected"); return offset; } + add_new_data_source(actx->pinfo, cleartext_tvb, "Decrypted ScopedPDU"); tvb_set_child_real_data_tvbuff(tvb, cleartext_tvb); @@ -244,6 +251,9 @@ gint pdu_type; decrypted_tree = proto_item_add_subtree(decrypted_item,ett_decrypted); dissect_snmp_ScopedPDU(FALSE, cleartext_tvb, 0, actx, decrypted_tree, -1); } + } else { + if (check_col(actx->pinfo->cinfo, COL_INFO)) + col_add_str(actx->pinfo->cinfo, COL_INFO, "encryptedPDU: privKey Unknown"); } #.FN_BODY SNMPv3Message/msgSecurityParameters @@ -319,79 +329,8 @@ gint pdu_type; usm_p.authenticated = v3_flags & TH_AUTH ? TRUE : FALSE; } -#.FN_BODY VarBind - oid_tvb = NULL; - value_tvb = NULL; - %(DEFAULT_BODY)s - if (oid_tvb && value_tvb) { - next_tvb_add_string(&var_list, value_tvb, (snmp_var_in_tree) ? tree : NULL, - variable_oid_dissector_table, - oid_to_str(tvb_get_ptr(oid_tvb, 0, tvb_length(oid_tvb)), tvb_length(oid_tvb))); - } - -#.FN_PARS ObjectName - - VAL_PTR = &oid_tvb - -#.FN_BODY String-value - guint length; - - snmp_variable_decode(tvb, tree, actx, oid_tvb, offset, &length, &value_tvb); - offset = offset + length; - -#.FN_BODY Integer-value - guint length; - - snmp_variable_decode(tvb, tree, actx, oid_tvb, offset, &length, NULL); - offset = offset + length; - -#.FN_BODY ObjectID-value - guint length; - - snmp_variable_decode(tvb, tree, actx, oid_tvb, offset, &length, NULL); - offset = offset + length; - -#.FN_BODY Empty - guint length; - - snmp_variable_decode(tvb, tree, actx, oid_tvb, offset, &length, NULL); - offset = offset + length; - -#.FN_BODY NetworkAddress/internet - /* see http://bugs.wireshark.org/bugzilla/show_bug.cgi?id=1125 */ - guint32 len; - int cur_offset; - - cur_offset = get_ber_identifier(tvb, offset, NULL, NULL, NULL); - get_ber_length(NULL, tvb, cur_offset, &len, NULL); - - switch (len) { - case 4: offset = dissect_snmp_IpAddress(FALSE, tvb, offset, actx, tree, hf_snmp_internet); break; - case 16: offset = dissect_snmp_IpAddressIpv6(FALSE, tvb, offset, actx, tree, hf_snmp_internet_ipv6); break; - default: offset = dissect_snmp_IpAddressOther(FALSE, tvb, offset, actx, tree, hf_snmp_internet_other); break; - } - - if (len != 4) { - proto_item* pi = get_ber_last_created_item(); - proto_tree* pt = proto_item_add_subtree(pi,ett_internet); - /* - * It might be possible to do so, although the dissector should probably still put - * a complaint into the protocol tree ("not irritating Cisco by pointing out where - * they're violating the standard" is not a project goal for Wireshark :-)). - * -- Guy Harris - */ - pi = proto_tree_add_text(pt,tvb,cur_offset,len, - "The host that generated this packet is violating" - "the SNMP protocol definition and sends corrupt and invalid packets"); - PROTO_ITEM_SET_GENERATED(pi); - expert_add_info_format( actx->pinfo, pi, PI_MALFORMED, PI_ERROR, - "Corrupt and Invalid packet" ); - } - #.TYPE_ATTR -Counter64 TYPE = FT_UINT64 DISPLAY = BASE_DEC STRINGS = NULL -IpAddress TYPE = FT_IPv4 DISPLAY = BASE_NONE STRINGS = NULL Message/community TYPE = FT_STRING DISPLAY = BASE_HEX STRINGS = NULL HeaderData/msgSecurityModel TYPE = FT_UINT32 DISPLAY = BASE_DEC STRINGS = VALS(sec_models) UsmSecurityParameters/msgUserName TYPE = FT_STRING DISPLAY = BASE_HEX STRINGS = NULL diff --git a/epan/oids.c b/epan/oids.c index f232babc6a..4d6756134b 100644 --- a/epan/oids.c +++ b/epan/oids.c @@ -34,9 +34,10 @@ #include <ctype.h> #include "emem.h" -#include "uat.h" +#include "uat-int.h" #include "packet.h" #include "report_err.h" +#include "dissectors/packet-ber.h" #ifdef HAVE_SMI #include <smi.h> @@ -44,13 +45,29 @@ #include "oids.h" -static oid_info_t oid_root = { 0, "", NULL, SMI_BASETYPE_UNKNOWN, -1, NULL, NULL}; +static const oid_value_type_t integer_type = { FT_INT32, BASE_DEC, BER_CLASS_UNI, BER_UNI_TAG_INTEGER, 1, 4 }; +static const oid_value_type_t bytes_type = { FT_BYTES, BASE_NONE, BER_CLASS_UNI, BER_UNI_TAG_OCTETSTRING, 0, -1 }; +static const oid_value_type_t oid_type = { FT_OID, BASE_NONE, BER_CLASS_UNI, BER_UNI_TAG_OID, 1, -1 }; +static const oid_value_type_t ipv4_type = { FT_IPv4, BASE_NONE, BER_CLASS_APP, 0, 4, 4 }; +static const oid_value_type_t counter32_type = { FT_UINT32, BASE_DEC, BER_CLASS_APP, 1, 1, 4 }; +static const oid_value_type_t unsigned32_type = { FT_UINT32, BASE_DEC, BER_CLASS_APP, 2, 1, 4 }; +static const oid_value_type_t timeticks_type = { FT_UINT32, BASE_DEC, BER_CLASS_APP, 3, 1, 4 }; +static const oid_value_type_t opaque_type = { FT_BYTES, BASE_NONE, BER_CLASS_APP, 4, 1, 4 }; +static const oid_value_type_t counter64_type = { FT_UINT64, BASE_NONE, BER_CLASS_APP, 6, 8, 8 }; +static const oid_value_type_t ipv6_type = {FT_IPv6, BASE_NONE, BER_CLASS_UNI, BER_UNI_TAG_OCTETSTRING, 16, 16 }; +static const oid_value_type_t float_type = {FT_FLOAT, BASE_DEC, BER_CLASS_UNI, BER_UNI_TAG_OCTETSTRING, 4, 4 }; +static const oid_value_type_t double_type = {FT_DOUBLE, BASE_DEC, BER_CLASS_UNI, BER_UNI_TAG_OCTETSTRING, 8, 8 }; +static const oid_value_type_t ether_type = {FT_ETHER, BASE_NONE, BER_CLASS_UNI, BER_UNI_TAG_OCTETSTRING, 6, 6 }; +static const oid_value_type_t string_type = {FT_STRING, BASE_NONE, BER_CLASS_UNI, BER_UNI_TAG_OCTETSTRING, 0, -1 }; +static const oid_value_type_t unknown_type = {FT_BYTES, BASE_NONE, BER_CLASS_ANY, BER_TAG_ANY, 0, -1 }; + +static oid_info_t oid_root = { 0, NULL, NULL, &unknown_type,-1, NULL, NULL}; static emem_tree_t* oids_by_name = NULL; -static oid_info_t* add_oid(char* name, int type, guint oid_len, guint32 *subids) { +static oid_info_t* add_oid(char* name, const oid_value_type_t* type, guint oid_len, guint32 *subids) { guint i = 0; oid_info_t* c = &oid_root; - + oid_len--; do { @@ -58,39 +75,32 @@ static oid_info_t* add_oid(char* name, int type, guint oid_len, guint32 *subids) if(n) { if (i == oid_len) { - if (!n->name) + if (n->name) { n->name = g_strdup(name); - - if (n->value_type == SMI_BASETYPE_UNKNOWN) n->value_type = type; + } return n; - } else { - c = n; - continue; - } - } else { - oid_info_t* o = g_malloc(sizeof(oid_info_t)); - o->subid = subids[i]; - o->children = pe_tree_create(EMEM_TREE_TYPE_RED_BLACK,"oid_children"); - o->value_hfid = -1; - o->parent = c; - o->bits = NULL; + } } else { + n = g_malloc(sizeof(oid_info_t)); + n->subid = subids[i]; + n->children = pe_tree_create(EMEM_TREE_TYPE_RED_BLACK,"oid_children"); + n->value_hfid = -1; + n->parent = c; + n->bits = NULL; - emem_tree_insert32(c->children,o->subid,o); + emem_tree_insert32(c->children,n->subid,n); if (i == oid_len) { - o->name = g_strdup(name); - o->value_type = type; - return o; + n->name = g_strdup(name); + n->value_type = type; + return n; } else { - o->name = NULL; - o->value_type = SMI_BASETYPE_UNKNOWN; - c = o; - continue; + n->name = g_strdup(name); + n->value_type = NULL; } } - + c = n; } while(++i); g_assert_not_reached(); @@ -98,7 +108,7 @@ static oid_info_t* add_oid(char* name, int type, guint oid_len, guint32 *subids) } extern void oid_add(char* name, guint oid_len, guint32 *subids) { - add_oid(name,SMI_BASETYPE_UNKNOWN,oid_len,subids); + add_oid(name,&unknown_type,oid_len,subids); } #ifdef HAVE_SMI @@ -146,60 +156,61 @@ static char* alnumerize(const char* name) { return s; } -struct _smi_type_data { - char* name; - enum SmiBasetype base; - enum ftenum type; - int display; -}; - -const struct _smi_type_data* get_typedata(SmiType* smiType) { - static const struct _smi_type_data types_by_name[] = { - {"IpAddress",0,FT_IPv4,BASE_NONE}, - {"InetAddressIPv4",0,FT_IPv4,BASE_NONE}, - {"InetAddressIPv6",0,FT_IPv4,BASE_NONE}, - {"NetworkAddress",0,FT_IPv4,BASE_NONE}, - {"MacAddress",0,FT_ETHER,BASE_NONE}, - {"TimeTicks",0,FT_RELATIVE_TIME,BASE_NONE}, - {"Ipv6Address",0,FT_IPv4,BASE_NONE}, - {"TimeStamp",0,FT_RELATIVE_TIME,BASE_NONE} - }; - static const struct _smi_type_data types_by_base[] = { - {NULL,SMI_BASETYPE_UNKNOWN,FT_BYTES,BASE_NONE}, - {NULL,SMI_BASETYPE_INTEGER32,FT_INT32,BASE_DEC}, - {NULL,SMI_BASETYPE_OCTETSTRING,FT_BYTES,BASE_NONE}, - {NULL,SMI_BASETYPE_OBJECTIDENTIFIER,FT_OID,BASE_NONE}, - {NULL,SMI_BASETYPE_UNSIGNED32,FT_UINT32,BASE_NONE}, - {NULL,SMI_BASETYPE_UNSIGNED64,FT_UINT64,BASE_DEC}, - {NULL,SMI_BASETYPE_FLOAT32,FT_FLOAT,BASE_DEC}, - {NULL,SMI_BASETYPE_FLOAT64,FT_DOUBLE,BASE_DEC}, - {NULL,SMI_BASETYPE_FLOAT128,FT_BYTES,BASE_NONE}, - {NULL,SMI_BASETYPE_ENUM,FT_UINT32,BASE_DEC}, - {NULL,SMI_BASETYPE_BITS,FT_BYTES,BASE_DEC}, +typedef struct { + char* name; + SmiBasetype base; + const oid_value_type_t* type; +} oid_value_type_mapping_t; + +const oid_value_type_t* get_typedata(SmiType* smiType) { + static const oid_value_type_mapping_t types[] = { + {"IpAddress", SMI_BASETYPE_UNKNOWN, &ipv4_type}, + {"InetAddressIPv4",SMI_BASETYPE_UNKNOWN,&ipv4_type}, + {"InetAddressIPv6",SMI_BASETYPE_UNKNOWN,&ipv6_type}, + {"NetworkAddress",SMI_BASETYPE_UNKNOWN,&ipv4_type}, + {"MacAddress",SMI_BASETYPE_UNKNOWN,ðer_type}, + {"TimeTicks",SMI_BASETYPE_UNKNOWN,&timeticks_type}, + {"Ipv6Address",SMI_BASETYPE_UNKNOWN,&ipv6_type}, + {"TimeStamp",SMI_BASETYPE_UNKNOWN,&integer_type}, + {"DisplayString",SMI_BASETYPE_UNKNOWN,&string_type}, + {"DateAndTime",SMI_BASETYPE_UNKNOWN,&string_type}, + {"Counter32",SMI_BASETYPE_UNKNOWN,&counter32_type}, + {"Unsigned32",SMI_BASETYPE_UNKNOWN,&unsigned32_type}, + {"Gauge32",SMI_BASETYPE_UNKNOWN,&unsigned32_type}, + {"unk",SMI_BASETYPE_UNKNOWN,&unknown_type}, + {"i32",SMI_BASETYPE_INTEGER32,&integer_type}, + {"octets",SMI_BASETYPE_OCTETSTRING,&bytes_type}, + {"oid",SMI_BASETYPE_OBJECTIDENTIFIER,&oid_type}, + {"u32",SMI_BASETYPE_UNSIGNED32,&unsigned32_type}, + {"u64",SMI_BASETYPE_UNSIGNED64,&counter64_type}, + {"f32",SMI_BASETYPE_FLOAT32,&float_type}, + {"f64",SMI_BASETYPE_FLOAT64,&double_type}, + {"f128",SMI_BASETYPE_FLOAT128,&bytes_type}, + {"enum",SMI_BASETYPE_ENUM,&integer_type}, + {"bits",SMI_BASETYPE_BITS,&bytes_type}, + {NULL,0,NULL} }; - const struct _smi_type_data* type = NULL; + const oid_value_type_mapping_t* t; SmiType* sT = smiType; - guint i; - + if (!smiType) return NULL; + do { - for (i = 0; i < array_length(types_by_name) ; i++ ) { + for (t = types; t->type ; t++ ) { const char* name = smiRenderType(sT, SMI_RENDER_NAME); - type = &(types_by_name[i]); - if (name && g_str_equal(name, types_by_name[i].name)) { - return type; + if (name && t->name && g_str_equal(name, t->name )) { + return t->type; } } } while(( sT = smiGetParentType(sT) )); - if (! type) { - for (i = 0; i < array_length(types_by_base) ; i++ ) { - if(sT->basetype == types_by_base[i].base) { - return type; - } + for (t = types; t->type ; t++ ) { + if(smiType->basetype == t->base) { + return t->type; } } - return types_by_base; + + return &unknown_type; } #define IS_ENUMABLE(ft) (( (ft == FT_UINT8) || (ft == FT_UINT16) || (ft == FT_UINT24) || (ft == FT_UINT32) \ @@ -212,8 +223,6 @@ void register_mibs(void) { guint i; int proto_smi = -1; - - GArray* hfa = g_array_new(FALSE,TRUE,sizeof(hf_register_info)); GArray* etta = g_array_new(FALSE,TRUE,sizeof(gint*)); static uat_field_t smi_fields[] = { @@ -254,23 +263,23 @@ void register_mibs(void) { smiNode = smiGetNextNode(smiNode, SMI_NODEKIND_ANY)) { SmiType* smiType = smiGetNodeType(smiNode); - + const oid_value_type_t* typedata = get_typedata(smiType); oid_info_t* oid_data = add_oid(smiRenderOID(smiNode->oidlen, smiNode->oid, SMI_RENDER_QUALIFIED), - smiType ? smiType->basetype : SMI_BASETYPE_UNKNOWN, + typedata, smiNode->oidlen, smiNode->oid); - - if (smiType) { + + if (typedata) { SmiNamedNumber* smiEnum; - const struct _smi_type_data* typedata = get_typedata(smiType); - hf_register_info hf = { NULL, { NULL, NULL, FT_NONE, BASE_NONE, NULL, 0, "", HFILL }}; - - hf.hfinfo.name = oid_data->name; - hf.p_id = &(oid_data->value_hfid); - hf.hfinfo.type = typedata->type; - hf.hfinfo.display = typedata->display; - hf.hfinfo.abbrev = alnumerize(hf.hfinfo.name); - hf.hfinfo.blurb = g_strdup(smiRenderOID(smiNode->oidlen, smiNode->oid, SMI_RENDER_ALL)); + hf_register_info hf = { &(oid_data->value_hfid), { + oid_data->name, + alnumerize(oid_data->name), + typedata->ft_type, + typedata->display, + NULL, + 0, + g_strdup(smiRenderOID(smiNode->oidlen, smiNode->oid, SMI_RENDER_ALL)), + HFILL }}; if ( IS_ENUMABLE(hf.hfinfo.type) && (smiEnum = smiGetFirstNamedNumber(smiType))) { GArray* vals = g_array_new(TRUE,TRUE,sizeof(value_string)); @@ -296,7 +305,7 @@ void register_mibs(void) { for(;smiEnum; smiEnum = smiGetNextNamedNumber(smiEnum), bits->num++); - bits->data = g_malloc(sizeof(struct _oid_bit_t)); + bits->data = g_malloc(sizeof(struct _oid_bit_t)*bits->num); for(smiEnum = smiGetFirstNamedNumber(smiType),n=0; smiEnum; @@ -342,19 +351,19 @@ void oid_init(void) { } const char* oid_subid2string(guint32* subids, guint len) { - char* s = ep_alloc(len*11); - char* w = s; + char* s = ep_alloc0(len*11); + char* w = s; do { w += sprintf(w,"%u.",*subids++); } while(--len); - *w = '\0'; + if (w!=s) *(w-1) = '\0'; else *(w) = '\0'; return s; } -guint chech_num_oid(const char* str) { +guint check_num_oid(const char* str) { const char* r = str; char c = '\0'; guint n = 0; @@ -362,18 +371,18 @@ guint chech_num_oid(const char* str) { if (*r == '.') return 0; do { - switch(*r) { + switch(*r++) { case '.': n++; - if (c == '.') return 0; - case '1' : case '2' : case '3' : case '4' : case '5' : - case '6' : case '7' : case '8' : case '9' : case '0' : - continue; - case '\0': - break; - default: - return 0; - } + if (c == '.') return 0; + case '1' : case '2' : case '3' : case '4' : case '5' : + case '6' : case '7' : case '8' : case '9' : case '0' : + continue; + case '\0': + break; + default: + return 0; + } c = *r; } while(1); @@ -385,7 +394,12 @@ guint chech_num_oid(const char* str) { guint oid_string2subid(const char* str, guint32** subids_p) { const char* r = str; guint32* subids; - guint n = chech_num_oid(str); + guint n = check_num_oid(str); + + if (!n) { + *subids_p = NULL; + return 0; + } *subids_p = subids = ep_alloc_array(guint32,n); @@ -415,11 +429,7 @@ guint oid_encoded2subid(const guint8 *oid_bytes, gint oid_len, guint32** subids_ gboolean is_first = TRUE; guint32* subids; - for (i=0; i<oid_len; i++){ - guint8 byte = oid_bytes[i]; - if (byte & 0x80) continue; - n++; - } + for (i=0; i<oid_len; i++) { if (! (oid_bytes[i] & 0x80 )) n++; } *subids_p = subids = ep_alloc(sizeof(guint32)*n); @@ -436,8 +446,8 @@ guint oid_encoded2subid(const guint8 *oid_bytes, gint oid_len, guint32** subids_ if (is_first) { guint32 subid0 = 0; - if (subid >= 40) { (*subids)++; subid-=40; } - if (subid >= 40) { (*subids)++; subid-=40; } + if (subid >= 40) { subid0++; subid-=40; } + if (subid >= 40) { subid0++; subid-=40; } *subids++ = subid0; @@ -548,37 +558,55 @@ guint oid_subid2encoded(guint subids_len, guint32* subids, guint8** bytes_p) { guint8* bytes; guint8* b; - if (subids_len < 2) return 0; + if (subids_len < 2) { + *bytes_p = NULL; + return 0; + } - subid = (subids[1] * 40) + subids[0]; + subid = (subids[0] * 40) + subids[1]; + i = 2; - for( i = 2; i < subids_len; i++ ) { - if (subid & 0xF0000000) { - bytelen += 5; - } else if (subid & 0x0FE00000) { - bytelen += 4; - } else if (subid & 0x001FC000) { - bytelen += 3; - } else if (subid & 0x00003F10) { + do { + if (subid <= 0x0000007F) { + bytelen += 1; + } else if (subid <= 0x00003FFF ) { bytelen += 2; + } else if (subid <= 0x001FFFFF ) { + bytelen += 3; + } else if (subid <= 0x0FFFFFFF ) { + bytelen += 4; } else { - bytelen += 1; + bytelen += 5; } - } + + subid = subids[i]; + } while ( i++ < subids_len ); *bytes_p = b = bytes = ep_alloc(bytelen); - subid = (subids[1] * 40) + subids[0]; + subid = (subids[0] * 40) + subids[1]; + i = 2; - for (i = 2; i<subids_len; i++) { - guint32 v; + do { + guint len; - if (( v = subid & 0xF0000000 )) *(b++) = v << 28; - if (( v = subid & 0x0FE00000 )) *(b++) = v << 21; - if (( v = subid & 0x001FC000 )) *(b++) = v << 21; - if (( v = subid & 0x00003F10 )) *(b++) = v << 21; - *(b++) = subid & 0x0000007F; - } + if ((subid <= 0x0000007F )) len = 1; + else if ((subid <= 0x00003FFF )) len = 2; + else if ((subid <= 0x001FFFFF )) len = 3; + else if ((subid <= 0x0FFFFFFF )) len = 4; + else len = 5; + + switch(len) { + default: DISSECTOR_ASSERT_NOT_REACHED(); break; + case 5: *(b++) = ((subid & 0xF0000000) << 28) | 0x80; + case 4: *(b++) = ((subid & 0x0FE00000 ) >> 21) | 0x80; + case 3: *(b++) = ((subid & 0x001FC000 ) >> 14) | 0x80; + case 2: *(b++) = ((subid & 0x00003F10 ) >> 7) | 0x80; + case 1: *(b++) = subid & 0x0000007F ; break; + } + + subid = subids[i]; + } while ( i++ < subids_len); return bytelen; } @@ -631,13 +659,50 @@ const gchar *oid_resolved_from_string(const gchar *oid_str) { } } +extern char* oid_test_a2b(guint32 num_subids, guint32* subids); +char* oid_test_a2b(guint32 num_subids, guint32* subids) { + guint8* sub2enc; + guint8* str2enc; + guint32* enc2sub; + guint32* str2sub; + const char* sub2str = oid_subid2string(subids, num_subids); + guint sub2enc_len = oid_subid2encoded(num_subids, subids,&sub2enc); + guint enc2sub_len = oid_encoded2subid(sub2enc, sub2enc_len, &enc2sub); + const char* enc2str = oid_encoded2string(sub2enc, sub2enc_len); + guint str2enc_len = oid_string2encoded(sub2str,&str2enc); + guint str2sub_len = oid_string2subid(sub2str,&str2sub); + + return ep_strdup_printf( + "oid_subid2string=%s \n" + "oid_subid2encoded=[%d]%s \n" + "oid_encoded2subid=%s \n " + "oid_encoded2string=%s \n" + "oid_string2encoded=[%d]%s \n" + "oid_string2subid=%s \n " + ,sub2str + ,sub2enc_len,bytestring_to_str(sub2enc, sub2enc_len, ':') + ,enc2sub ? oid_subid2string(enc2sub,enc2sub_len) : "-" + ,enc2str + ,str2enc_len,bytestring_to_str(str2enc, str2enc_len, ':') + ,str2sub ? oid_subid2string(str2sub,str2sub_len) : "-" + ); +} + const gchar *oid_resolved(guint32 num_subids, guint32* subids) { guint matched; guint left; oid_info_t* oid = oid_get(num_subids, subids, &matched, &left); - return oid2str(oid, subids, num_subids, left); + while (! oid->name ) { + if (!(oid = oid->parent)) { + return oid_subid2string(subids,num_subids); + } + left++; + matched--; + } + + return ep_strdup_printf("%s.%s", + oid->name, + oid_subid2string(&(subids[matched]),left)); } - - diff --git a/epan/oids.h b/epan/oids.h index e40eb378ac..9ebe74dfa9 100644 --- a/epan/oids.h +++ b/epan/oids.h @@ -1,4 +1,4 @@ -/* oid.h +/* oids.h * Definitions for OBJECT IDENTIFIER operations * * $Id$ @@ -27,6 +27,8 @@ #ifndef __OIDS_H__ #define __OIDS_H__ +#define BER_TAG_ANY -1 + struct _oid_bit_t { guint offset; int hfid; @@ -38,11 +40,20 @@ typedef struct _oid_bits_info_t { struct _oid_bit_t* data; } oid_bits_info_t; +typedef struct _oid_value_type_t { + enum ftenum ft_type; + int display; + gint8 ber_class; + gint32 ber_tag; + int min_len; + int max_len; +} oid_value_type_t; + typedef struct _oid_info_t { guint32 subid; char* name; void* children; /* an emem_tree_t* */ - int value_type; + const oid_value_type_t* value_type; int value_hfid; oid_bits_info_t* bits; struct _oid_info_t* parent; |