From ee208c8dcc371ca10986b7e8ea28c933e4bfaae9 Mon Sep 17 00:00:00 2001 From: Michael Mann Date: Sun, 6 Oct 2013 02:31:10 +0000 Subject: [PATCH] Add support for RELATIVE-OID ASN.1 type. Bug 9192 (https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=9192) From Ed Beroset. svn path=/trunk/; revision=52393 --- doc/README.dissector | 8 +- doc/dfilter2pod.pl | 1 + docbook/dfilter2xml.pl | 1 + epan/dfilter/semcheck.c | 5 +- epan/dissectors/packet-ber.c | 116 ++++++++++++++++++++++++--- epan/dissectors/packet-ber.h | 5 ++ epan/ftypes/ftype-bytes.c | 93 ++++++++++++++++++++- epan/ftypes/ftypes.h | 1 + epan/oids.c | 30 ++++++- epan/oids.h | 6 ++ epan/proto.c | 27 +++++++ epan/strutil.c | 9 ++- epan/strutil.h | 11 +++ epan/wslua/wslua_field.c | 1 + epan/wslua/wslua_proto.c | 3 + epan/wslua/wslua_tree.c | 1 + epan/wspython/wspy_dissector.py | 3 +- rawshark.c | 2 + tools/asn2wrs.py | 2 +- tools/convert_proto_tree_add_text.pl | 2 +- tools/fix-encoding-args.pl | 3 +- ui/packet_list_utils.c | 2 +- 22 files changed, 308 insertions(+), 24 deletions(-) diff --git a/doc/README.dissector b/doc/README.dissector index a4949d7e83..94871fae5a 100644 --- a/doc/README.dissector +++ b/doc/README.dissector @@ -113,7 +113,8 @@ FIELDTYPE FT_NONE, FT_BOOLEAN, FT_UINT8, FT_UINT16, FT_UINT24, FT_INT64, FT_FLOAT, FT_DOUBLE, FT_ABSOLUTE_TIME, FT_RELATIVE_TIME, FT_STRING, FT_STRINGZ, FT_EUI64, FT_UINT_STRING, FT_ETHER, FT_BYTES, FT_UINT_BYTES, FT_IPv4, - FT_IPv6, FT_IPXNET, FT_FRAMENUM, FT_PROTOCOL, FT_GUID, FT_OID + FT_IPv6, FT_IPXNET, FT_FRAMENUM, FT_PROTOCOL, FT_GUID, FT_OID, + FT_REL_OID FIELDDISPLAY --For FT_UINT{8,16,24,32,64} and FT_INT{8,16,24,32,64): BASE_DEC, BASE_HEX, BASE_OCT, BASE_DEC_HEX, BASE_HEX_DEC, @@ -725,6 +726,7 @@ The type of value this field holds. The current field types are: address. FT_GUID A Globally Unique Identifier FT_OID An ASN.1 Object Identifier + FT_REL_OID An ASN.1 Relative Object Identifier FT_EUI64 A EUI-64 Address Some of these field types are still not handled in the display filter @@ -1331,8 +1333,8 @@ proto_register_*() function) and a value. The value will be fetched from the tvbuff by proto_tree_add_item(), based on the type of the field and the encoding of the value as specified by the "encoding" argument. -For FT_NONE, FT_BYTES, FT_ETHER, FT_IPv6, FT_IPXNET, FT_OID fields, -and 'protocol' fields the encoding is not relevant; the 'encoding' +For FT_NONE, FT_BYTES, FT_ETHER, FT_IPv6, FT_IPXNET, FT_OID, FT_REL_OID +fields, and 'protocol' fields the encoding is not relevant; the 'encoding' argument should be ENC_NA (Not Applicable). For integral, floating-point, Boolean, FT_GUID, and FT_EUI64 fields, diff --git a/doc/dfilter2pod.pl b/doc/dfilter2pod.pl index 849e695edc..26ff75eea9 100755 --- a/doc/dfilter2pod.pl +++ b/doc/dfilter2pod.pl @@ -45,6 +45,7 @@ use Getopt::Std; 'FT_PCRE', 'Perl Compatible Regular Expression', 'FT_GUID', 'Globally Unique Identifier', 'FT_OID', 'Object Identifier', + 'FT_REL_OID', 'Relative Object Identifier', ); getopts('e'); diff --git a/docbook/dfilter2xml.pl b/docbook/dfilter2xml.pl index 56206ef70f..c38cf11f1e 100755 --- a/docbook/dfilter2xml.pl +++ b/docbook/dfilter2xml.pl @@ -43,6 +43,7 @@ 'FT_PCRE', 'Perl Compatible Regular Expression', 'FT_GUID', 'Globally Unique Identifier', 'FT_OID', 'Object Identifier', + 'FT_REL_OID', 'Relative Object Identifier', ); # Read all the data into memory diff --git a/epan/dfilter/semcheck.c b/epan/dfilter/semcheck.c index c2d33bcf06..27b2d3e925 100644 --- a/epan/dfilter/semcheck.c +++ b/epan/dfilter/semcheck.c @@ -83,8 +83,9 @@ compatible_ftypes(ftenum_t a, ftenum_t b) case FT_OID: case FT_AX25: case FT_VINES: + case FT_REL_OID: - return (b == FT_ETHER || b == FT_BYTES || b == FT_UINT_BYTES || b == FT_GUID || b == FT_OID || b == FT_AX25 || b == FT_VINES); + return (b == FT_ETHER || b == FT_BYTES || b == FT_UINT_BYTES || b == FT_GUID || b == FT_OID || b == FT_AX25 || b == FT_VINES || b == FT_REL_OID); case FT_BOOLEAN: case FT_FRAMENUM: @@ -189,6 +190,7 @@ mk_fvalue_from_val_string(header_field_info *hfinfo, char *s) case FT_PCRE: case FT_GUID: case FT_OID: + case FT_REL_OID: return NULL; case FT_BOOLEAN: @@ -296,6 +298,7 @@ is_bytes_type(enum ftenum type) case FT_IPv6: case FT_GUID: case FT_OID: + case FT_REL_OID: return TRUE; case FT_NONE: diff --git a/epan/dissectors/packet-ber.c b/epan/dissectors/packet-ber.c index 9d5ccf6898..d1f75ecfe8 100644 --- a/epan/dissectors/packet-ber.c +++ b/epan/dissectors/packet-ber.c @@ -849,6 +849,9 @@ try_dissect_unknown_ber(packet_info *pinfo, tvbuff_t *tvb, volatile int offset, case BER_UNI_TAG_OID: offset = dissect_ber_object_identifier_str(FALSE, &asn1_ctx, tree, tvb, start_offset, hf_ber_unknown_OID, NULL); break; + case BER_UNI_TAG_RELATIVE_OID: + offset = dissect_ber_relative_oid_str(FALSE, &asn1_ctx, tree, tvb, start_offset, hf_ber_unknown_OID, NULL); + break; case BER_UNI_TAG_NumericString: offset = dissect_ber_octet_string(FALSE, &asn1_ctx, tree, tvb, start_offset, hf_ber_unknown_NumericString, NULL); break; @@ -3229,7 +3232,6 @@ dissect_ber_choice(asn1_ctx_t *actx, proto_tree *parent_tree, tvbuff_t *tvb, int #ifdef DEBUG_BER_CHOICE { const char *name; -header_field_info *hfinfo; if (hf_id >= 0) { hfinfo = proto_registrar_get_nth(hf_id); name = hfinfo->name; @@ -3356,7 +3358,6 @@ printf("CHOICE testing potential subdissector class[%p]:%d:(expected)%d tag:%d: #ifdef DEBUG_BER_CHOICE { const char *name; -header_field_info *hfinfo; if (hf_id >= 0) { hfinfo = proto_registrar_get_nth(hf_id); name = hfinfo->name; @@ -3381,7 +3382,6 @@ printf("CHOICE dissect_ber_choice(%s) calling subdissector len:%d\n", name, tvb_ #ifdef DEBUG_BER_CHOICE { const char *name; -header_field_info *hfinfo; if (hf_id >= 0) { hfinfo = proto_registrar_get_nth(hf_id); name = hfinfo->name; @@ -3397,7 +3397,6 @@ printf("CHOICE dissect_ber_choice(%s) subdissector ate %d bytes\n", name, count) #ifdef DEBUG_BER_CHOICE { const char *name; -header_field_info *hfinfo; if (hf_id >= 0) { hfinfo = proto_registrar_get_nth(hf_id); name = hfinfo->name; @@ -3465,7 +3464,6 @@ dissect_ber_old_choice(asn1_ctx_t *actx, proto_tree *parent_tree, tvbuff_t *tvb, #ifdef DEBUG_BER_CHOICE { const char *name; -header_field_info *hfinfo; if (hf_id >= 0) { hfinfo = proto_registrar_get_nth(hf_id); name = hfinfo->name; @@ -3592,7 +3590,6 @@ printf("CHOICE testing potential subdissector class[%p]:%d:(expected)%d tag:%d: #ifdef DEBUG_BER_CHOICE { const char *name; -header_field_info *hfinfo; if (hf_id >= 0) { hfinfo = proto_registrar_get_nth(hf_id); name = hfinfo->name; @@ -3614,7 +3611,6 @@ printf("CHOICE dissect_ber_old_choice(%s) calling subdissector len:%d\n", name, #ifdef DEBUG_BER_CHOICE { const char *name; -header_field_info *hfinfo; if (hf_id >= 0) { hfinfo = proto_registrar_get_nth(hf_id); name = hfinfo->name; @@ -3630,7 +3626,6 @@ printf("CHOICE dissect_ber_old_choice(%s) subdissector ate %d bytes\n", name, co #ifdef DEBUG_BER_CHOICE { const char *name; -header_field_info *hfinfo; if (hf_id >= 0) { hfinfo = proto_registrar_get_nth(hf_id); name = hfinfo->name; @@ -3833,6 +3828,110 @@ dissect_ber_GeneralString(asn1_ctx_t *actx, proto_tree *tree, tvbuff_t *tvb, int return offset; } +/* 8.19 Encoding of a relative object identifier value. + */ +int +dissect_ber_relative_oid(gboolean implicit_tag, asn1_ctx_t *actx, proto_tree *tree, tvbuff_t *tvb, int offset, gint hf_id, tvbuff_t **value_tvb) +{ + gint8 ber_class; + gboolean pc; + gint32 tag; + guint32 len; + int eoffset; + int hoffset; + const char *str; + proto_item *cause; + const gchar *name; + header_field_info *hfi; + +#ifdef DEBUG_BER +{ +header_field_info *hfinfo; +if (hf_id >= 0) { +hfinfo = proto_registrar_get_nth(hf_id); +name = hfinfo->name; +} else { +name = "unnamed"; +} +if (tvb_length_remaining(tvb, offset) > 3) { +printf("OBJECT IDENTIFIER dissect_ber_relative_oid(%s) entered implicit_tag:%d offset:%d len:%d %02x:%02x:%02x\n", name, implicit_tag, offset, tvb_length_remaining(tvb, offset), tvb_get_guint8(tvb, offset), tvb_get_guint8(tvb, offset+1), tvb_get_guint8(tvb, offset+2)); +} else { +printf("OBJECT IDENTIFIER dissect_ber_relative_oid(%s) entered\n", name); +} +} +#endif + + if (!implicit_tag) { + hoffset = offset; + /* sanity check */ + offset = dissect_ber_identifier(actx->pinfo, tree, tvb, offset, &ber_class, &pc, &tag); + offset = dissect_ber_length(actx->pinfo, tree, tvb, offset, &len, NULL); + eoffset = offset + len; + if ( (ber_class != BER_CLASS_UNI) + || (tag != BER_UNI_TAG_OID) ) { + tvb_ensure_bytes_exist(tvb, hoffset, 2); + cause = proto_tree_add_string_format( + tree, hf_ber_error, tvb, offset, len, "oid_expected", + "BER Error: Object Identifier expected but class:%s(%d) %s tag:%d was unexpected", + val_to_str_const(ber_class, ber_class_codes, "Unknown"), + ber_class, + pc ? ber_pc_codes_short.true_string : ber_pc_codes_short.false_string, + tag); + expert_add_info(actx->pinfo, cause, &ei_ber_expected_object_identifier); + if (decode_unexpected) { + proto_tree *unknown_tree = proto_item_add_subtree(cause, ett_ber_unknown); + dissect_unknown_ber(actx->pinfo, tvb, hoffset, unknown_tree); + } + return eoffset; + } + } else { + len = tvb_length_remaining(tvb, offset); + eoffset = offset+len; + } + + actx->created_item = NULL; + hfi = proto_registrar_get_nth(hf_id); + if (hfi->type == FT_REL_OID) { + actx->created_item = proto_tree_add_item(tree, hf_id, tvb, offset, len, ENC_BIG_ENDIAN); + } else if (IS_FT_STRING(hfi->type)) { + str = oid_encoded2string(tvb_get_ptr(tvb, offset, len), len); + actx->created_item = proto_tree_add_string(tree, hf_id, tvb, offset, len, str); + if (actx->created_item) { + /* see if we know the name of this oid */ + name = oid_resolved_from_encoded(tvb_get_ptr(tvb, offset, len), len); + if (name) { + proto_item_append_text(actx->created_item, " (%s)", name); + } + } + } else { + DISSECTOR_ASSERT_NOT_REACHED(); + } + + if (value_tvb) + *value_tvb = tvb_new_subset(tvb, offset, len, len); + + return eoffset; +} + +int +dissect_ber_relative_oid_str(gboolean implicit_tag, asn1_ctx_t *actx, proto_tree *tree, tvbuff_t *tvb, int offset, gint hf_id, const char **value_stringx) +{ + tvbuff_t *value_tvb = NULL; + guint length; + + offset = dissect_ber_object_identifier(implicit_tag, actx, tree, tvb, offset, hf_id, (value_stringx) ? &value_tvb : NULL); + + if (value_stringx) { + if (value_tvb && (length = tvb_length(value_tvb))) { + *value_stringx = oid_encoded2string(tvb_get_ptr(value_tvb, 0, length), length); + } else { + *value_stringx = ""; + } + } + + return offset; +} + /* 8.19 Encoding of an object identifier value. */ int @@ -3851,7 +3950,6 @@ dissect_ber_object_identifier(gboolean implicit_tag, asn1_ctx_t *actx, proto_tre #ifdef DEBUG_BER { -const char *name; header_field_info *hfinfo; if (hf_id >= 0) { hfinfo = proto_registrar_get_nth(hf_id); diff --git a/epan/dissectors/packet-ber.h b/epan/dissectors/packet-ber.h index 28c50228e9..cde878590a 100644 --- a/epan/dissectors/packet-ber.h +++ b/epan/dissectors/packet-ber.h @@ -195,6 +195,11 @@ extern int dissect_ber_GeneralString(asn1_ctx_t *actx, proto_tree *tree, tvbuff_ WS_DLL_PUBLIC int dissect_ber_object_identifier(gboolean implicit_tag, asn1_ctx_t *actx, proto_tree *tree, tvbuff_t *tvb, int offset, gint hf_id, tvbuff_t **value_tvb); WS_DLL_PUBLIC int dissect_ber_object_identifier_str(gboolean implicit_tag, asn1_ctx_t *actx, proto_tree *tree, tvbuff_t *tvb, int offset, gint hf_id, const char **value_stringx); +/* this function dissects a BER Relative Object Identifier + */ +WS_DLL_PUBLIC int dissect_ber_relative_oid(gboolean implicit_tag, asn1_ctx_t *actx, proto_tree *tree, tvbuff_t *tvb, int offset, gint hf_id, tvbuff_t **value_tvb); +WS_DLL_PUBLIC int dissect_ber_relative_oid_str(gboolean implicit_tag, asn1_ctx_t *actx, proto_tree *tree, tvbuff_t *tvb, int offset, gint hf_id, const char **value_stringx); + /* this function dissects a BER sequence of */ extern int dissect_ber_constrained_sequence_of(gboolean implicit_tag, asn1_ctx_t *actx, proto_tree *parent_tree, tvbuff_t *tvb, int offset, gint32 min_len, gint32 max_len, const ber_sequence_t *seq, gint hf_id, gint ett_id); diff --git a/epan/ftypes/ftype-bytes.c b/epan/ftypes/ftype-bytes.c index 07fef709f7..de7adac863 100644 --- a/epan/ftypes/ftype-bytes.c +++ b/epan/ftypes/ftype-bytes.c @@ -77,6 +77,8 @@ bytes_repr_len(fvalue_t *fv, ftrepr_t rtype _U_) * OID_REPR_LEN: * * 5 for the first byte ([0-2].[0-39].) + * + * REL_OID_REPR_LEN: * for each extra byte if the sub-id is: * 1 byte it can be at most "127." (4 bytes we give it 4) * 2 bytes it can be at most "16383." (6 bytes we give it 8) @@ -87,7 +89,8 @@ bytes_repr_len(fvalue_t *fv, ftrepr_t rtype _U_) * a 5 bytes encoded subid can already overflow the guint32 that holds a sub-id, * making it a completely different issue! */ -#define OID_REPR_LEN(fv) (5 + (4 * ((fv)->value.bytes->len-1))) +#define REL_OID_REPR_LEN(fv) (4 * ((fv)->value.bytes->len)) +#define OID_REPR_LEN(fv) (1 + REL_OID_REPR_LEN(fv)) static int oid_repr_len(fvalue_t *fv _U_, ftrepr_t rtype _U_) @@ -109,6 +112,27 @@ oid_to_repr(fvalue_t *fv, ftrepr_t rtype _U_, char *buf) strncpy(buf,oid_str,OID_REPR_LEN(fv)); } +static int +rel_oid_repr_len(fvalue_t *fv _U_, ftrepr_t rtype _U_) +{ + return REL_OID_REPR_LEN(fv); +} + +static void +rel_oid_to_repr(fvalue_t *fv, ftrepr_t rtype _U_, char *buf) +{ + const char* oid_str = rel_oid_encoded2string(fv->value.bytes->data,fv->value.bytes->len); + /* + * XXX: + * I'm assuming that oid_repr_len is going to be called before to set buf's size. + * or else we might have a BO. + * I guess that is why this callback is not passed a length. + * -- lego + */ + *buf++ = '.'; + strncpy(buf,oid_str,REL_OID_REPR_LEN(fv)); +} + static void bytes_to_repr(fvalue_t *fv, ftrepr_t rtype _U_, char *buf) { @@ -378,6 +402,34 @@ oid_from_unparsed(fvalue_t *fv, char *s, gboolean allow_partial_value _U_, LogFu return TRUE; } +static gboolean +rel_oid_from_unparsed(fvalue_t *fv, char *s, gboolean allow_partial_value _U_, LogFunc logfunc) +{ + GByteArray *bytes; + gboolean res; + + + /* + * Don't log a message if this fails; we'll try looking it + * up as an OID if it does, and if that fails, + * we'll log a message. + */ + bytes = g_byte_array_new(); + res = rel_oid_str_to_bytes(s, bytes, FALSE); + if (!res) { + if (logfunc != NULL) + logfunc("\"%s\" is not a valid RELATIVE-OID.", s); + g_byte_array_free(bytes, TRUE); + return FALSE; + } + + /* Free up the old value, if we have one */ + bytes_fvalue_free(fv); + fv->value.bytes = bytes; + + return TRUE; +} + static guint len(fvalue_t *fv) { @@ -811,10 +863,49 @@ ftype_register_bytes(void) slice, }; + static ftype_t rel_oid_type = { + FT_REL_OID, /* ftype */ + "FT_REL_OID", /* name */ + "ASN.1 relative object identifier", /* pretty_name */ + 0, /* wire_size */ + bytes_fvalue_new, /* new_value */ + bytes_fvalue_free, /* free_value */ + rel_oid_from_unparsed, /* val_from_unparsed */ + NULL, /* val_from_string */ + rel_oid_to_repr, /* val_to_string_repr */ + rel_oid_repr_len, /* len_string_repr */ + + oid_fvalue_set, /* set_value (same as full oid) */ + NULL, /* set_value_uinteger */ + NULL, /* set_value_sinteger */ + NULL, /* set_value_integer64 */ + NULL, /* set_value_floating */ + + value_get, /* get_value */ + NULL, /* get_value_uinteger */ + NULL, /* get_value_sinteger */ + NULL, /* get_value_integer64 */ + NULL, /* get_value_floating */ + + cmp_eq, + cmp_ne, + cmp_gt, + cmp_ge, + cmp_lt, + cmp_le, + cmp_bitwise_and, + cmp_contains, + NULL, /* cmp_matches */ + + len, + slice, + }; + ftype_register(FT_BYTES, &bytes_type); ftype_register(FT_UINT_BYTES, &uint_bytes_type); ftype_register(FT_AX25, &ax25_type); ftype_register(FT_VINES, &vines_type); ftype_register(FT_ETHER, ðer_type); ftype_register(FT_OID, &oid_type); + ftype_register(FT_REL_OID, &rel_oid_type); } diff --git a/epan/ftypes/ftypes.h b/epan/ftypes/ftypes.h index 11c850b6ce..5f4183a3b9 100644 --- a/epan/ftypes/ftypes.h +++ b/epan/ftypes/ftypes.h @@ -69,6 +69,7 @@ enum ftenum { FT_EUI64, FT_AX25, FT_VINES, + FT_REL_OID, /* RELATIVE-OID */ FT_NUM_TYPES /* last item number plus one */ }; diff --git a/epan/oids.c b/epan/oids.c index 62405bee1a..61177ed0d8 100644 --- a/epan/oids.c +++ b/epan/oids.c @@ -829,11 +829,16 @@ void oids_cleanup(void) { } const char* oid_subid2string(guint32* subids, guint len) { + return rel_oid_subid2string(subids, len, TRUE); +} +const char* rel_oid_subid2string(guint32* subids, guint len, gboolean is_absolute) { char* s = (char *)ep_alloc0(((len)*11)+1); char* w = s; if(!subids) return "*** Empty OID ***"; + if (!is_absolute) + *w++ = '.'; do { w += g_snprintf(w,12,"%u.",*subids++); @@ -919,9 +924,12 @@ guint oid_string2subid(const char* str, guint32** subids_p) { guint oid_encoded2subid(const guint8 *oid_bytes, gint oid_len, guint32** subids_p) { + return oid_encoded2subid_sub(oid_bytes, oid_len, subids_p, TRUE); +} +guint oid_encoded2subid_sub(const guint8 *oid_bytes, gint oid_len, guint32** subids_p, + gboolean is_first) { gint i; - guint n = 1; - gboolean is_first = TRUE; + guint n = is_first ? 1 : 0; guint32* subids; guint32* subid_overflow; /* @@ -939,7 +947,7 @@ guint oid_encoded2subid(const guint8 *oid_bytes, gint oid_len, guint32** subids_ * so initialize our one byte to zero and return. This *seems* to be * the right thing to do in this situation, and at the very least it * avoids uninitialized memory errors that would otherwise occur. */ - if (n == 1) { + if ((is_first && n == 0) || (!is_first && n == 1)) { *subids = 0; return n; } @@ -1019,6 +1027,13 @@ const gchar *oid_resolved_from_encoded(const guint8 *oid, gint oid_len) { return oid_resolved(subid_oid_length, subid_oid); } +const gchar *rel_oid_resolved_from_encoded(const guint8 *oid, gint oid_len) { + guint32 *subid_oid; + guint subid_oid_length = oid_encoded2subid_sub(oid, oid_len, &subid_oid, FALSE); + + return rel_oid_subid2string(subid_oid, subid_oid_length, FALSE); +} + guint oid_subid2encoded(guint subids_len, guint32* subids, guint8** bytes_p) { guint bytelen = 0; @@ -1090,7 +1105,16 @@ const gchar* oid_encoded2string(const guint8* encoded, guint len) { } } +const gchar* rel_oid_encoded2string(const guint8* encoded, guint len) { + guint32* subids; + guint subids_len = oid_encoded2subid_sub(encoded, len, &subids, FALSE); + if (subids_len) { + return rel_oid_subid2string(subids,subids_len, FALSE); + } else { + return ""; + } +} guint oid_string2encoded(const char *oid_str, guint8 **bytes) { guint32* subids; diff --git a/epan/oids.h b/epan/oids.h index e8221d4241..3297202ce0 100644 --- a/epan/oids.h +++ b/epan/oids.h @@ -142,14 +142,20 @@ guint oid_string2encoded(const gchar *oid_str, guint8** encoded_p); WS_DLL_PUBLIC guint oid_encoded2subid(const guint8 *oid, gint len, guint32** subids_p); WS_DLL_PUBLIC +guint oid_encoded2subid_sub(const guint8 *oid_bytes, gint oid_len, guint32** subids_pi, + gboolean is_first); +WS_DLL_PUBLIC guint oid_string2subid(const gchar *oid_str, guint32** subids_p); WS_DLL_PUBLIC const gchar* oid_encoded2string(const guint8* encoded, guint len); +WS_DLL_PUBLIC const gchar* rel_oid_encoded2string(const guint8* encoded, guint len); WS_DLL_PUBLIC const gchar* oid_subid2string(guint32 *subids, guint len); +WS_DLL_PUBLIC const gchar* rel_oid_subid2string(guint32 *subids, guint len, gboolean is_relative); /* these return a formated string as human readable as posible */ WS_DLL_PUBLIC const gchar *oid_resolved(guint len, guint32 *subids); WS_DLL_PUBLIC const gchar *oid_resolved_from_encoded(const guint8 *oid, gint len); +WS_DLL_PUBLIC const gchar *rel_oid_resolved_from_encoded(const guint8 *oid, gint len); WS_DLL_PUBLIC const gchar *oid_resolved_from_string(const gchar *oid_str); /* these yield two formated strings one resolved and one numeric */ diff --git a/epan/proto.c b/epan/proto.c index 1a8475a241..6743a036fc 100644 --- a/epan/proto.c +++ b/epan/proto.c @@ -1406,6 +1406,7 @@ proto_tree_new_item(field_info *new_fi, proto_tree *tree, break; case FT_OID: + case FT_REL_OID: proto_tree_set_oid_tvb(new_fi, tvb, start, length); break; @@ -3876,6 +3877,17 @@ proto_custom_set(proto_tree* tree, const int field_id, gint occurrence, size-offset_r); break; + case FT_REL_OID: + bytes = (guint8 *)fvalue_get(&finfo->value); + offset_r += protoo_strlcpy(result+offset_r, + rel_oid_resolved_from_encoded(bytes, + fvalue_length(&finfo->value)), + size-offset_r); + offset_e += protoo_strlcpy(expr+offset_e, + rel_oid_encoded2string(bytes, fvalue_length(&finfo->value)), + size-offset_e); + break; + case FT_OID: bytes = (guint8 *)fvalue_get(&finfo->value); offset_r += protoo_strlcpy(result+offset_r, @@ -3933,6 +3945,7 @@ proto_custom_set(proto_tree* tree, const int field_id, gint occurrence, case FT_INT24: case FT_INT32: case FT_OID: + case FT_REL_OID: /* for these types, "expr" is filled in the loop above */ break; @@ -4785,6 +4798,7 @@ static const value_string hf_types[] = { { FT_PCRE, "FT_PCR" }, { FT_GUID, "FT_GUID" }, { FT_OID, "FT_OID" }, + { FT_REL_OID, "FT_REL_OID" }, { 0, NULL } }; static const value_string hf_display[] = { @@ -5385,6 +5399,19 @@ proto_item_fill_label(field_info *fi, gchar *label_str) oid_encoded2string(bytes, fvalue_length(&fi->value))); } break; + + case FT_REL_OID: + bytes = (guint8 *)fvalue_get(&fi->value); + name = rel_oid_resolved_from_encoded(bytes, fvalue_length(&fi->value)); + if (name) { + label_fill_descr(label_str, 0, hfinfo, + rel_oid_encoded2string(bytes, fvalue_length(&fi->value)), name); + } else { + label_fill(label_str, 0, hfinfo, + rel_oid_encoded2string(bytes, fvalue_length(&fi->value))); + } + break; + case FT_EUI64: integer64 = fvalue_get_integer64(&fi->value); label_fill_descr(label_str, 0, hfinfo, diff --git a/epan/strutil.c b/epan/strutil.c index 6c77002b5d..4446a45979 100644 --- a/epan/strutil.c +++ b/epan/strutil.c @@ -617,6 +617,10 @@ byte_array_dup(GByteArray *ba) { #define SUBID_BUF_LEN 5 gboolean oid_str_to_bytes(const char *oid_str, GByteArray *bytes) { + return rel_oid_str_to_bytes(oid_str, bytes, TRUE); +} +gboolean +rel_oid_str_to_bytes(const char *oid_str, GByteArray *bytes, gboolean is_absolute) { guint32 subid0, subid, sicnt, i; const char *p, *dot; guint8 buf[SUBID_BUF_LEN]; @@ -629,7 +633,7 @@ oid_str_to_bytes(const char *oid_str, GByteArray *bytes) { while (*p) { if (!isdigit((guchar)*p) && (*p != '.')) return FALSE; if (*p == '.') { - if (p == oid_str) return FALSE; + if (p == oid_str && is_absolute) return FALSE; if (!*(p+1)) return FALSE; if ((p-1) == dot) return FALSE; dot = p; @@ -639,7 +643,8 @@ oid_str_to_bytes(const char *oid_str, GByteArray *bytes) { if (!dot) return FALSE; p = oid_str; - sicnt = 0; + sicnt = is_absolute ? 0 : 2; + if (!is_absolute) p++; subid0 = 0; /* squelch GCC complaints */ while (*p) { subid = 0; diff --git a/epan/strutil.h b/epan/strutil.h index 2e25d7d172..255993da65 100644 --- a/epan/strutil.h +++ b/epan/strutil.h @@ -151,6 +151,17 @@ gboolean uri_str_to_bytes(const char *uri_str, GByteArray *bytes); WS_DLL_PUBLIC const gchar* format_uri(const GByteArray *bytes, const gchar *reserved_chars); +/** Turn a OID string representation (dot notation) into a byte array. + * + * @param oid_str The OID string (dot notaion). + * @param bytes The GByteArray that will receive the bytes. This + * must be initialized by the caller. + * @param is_absolute True if this is an absolute OID; false for relative OID. + * @return True if the string was converted successfully + */ +WS_DLL_PUBLIC +gboolean rel_oid_str_to_bytes(const char *oid_str, GByteArray *bytes, gboolean is_absolute); + /** Turn a OID string representation (dot notation) into a byte array. * * @param oid_str The OID string (dot notaion). diff --git a/epan/wslua/wslua_field.c b/epan/wslua/wslua_field.c index c4eb7e36e7..6ecd2f44aa 100644 --- a/epan/wslua/wslua_field.c +++ b/epan/wslua/wslua_field.c @@ -155,6 +155,7 @@ WSLUA_METAMETHOD FieldInfo__call(lua_State* L) { case FT_UINT_BYTES: case FT_GUID: case FT_PROTOCOL: + case FT_REL_OID: case FT_OID: { ByteArray ba = g_byte_array_new(); g_byte_array_append(ba, (const guint8 *)tvb_memdup(wmem_packet_scope(),fi->ds_tvb,fi->start,fi->length),fi->length); diff --git a/epan/wslua/wslua_proto.c b/epan/wslua/wslua_proto.c index 9d99e55213..3700ed00a6 100644 --- a/epan/wslua/wslua_proto.c +++ b/epan/wslua/wslua_proto.c @@ -459,6 +459,7 @@ static const wslua_ft_types_t ftenums[] = { {"ftypes.FRAMENUM", FT_FRAMENUM}, {"ftypes.GUID", FT_GUID}, {"ftypes.OID", FT_OID}, + {"ftypes.REL_OID", FT_REL_OID}, {NULL, FT_NONE} }; @@ -1185,6 +1186,7 @@ PROTOFIELD_OTHER(bytes,FT_BYTES) PROTOFIELD_OTHER(ubytes,FT_UINT_BYTES) PROTOFIELD_OTHER(guid,FT_GUID) PROTOFIELD_OTHER(oid,FT_OID) +PROTOFIELD_OTHER(rel_oid,FT_REL_OID) WSLUA_METAMETHOD ProtoField__tostring(lua_State* L) { /* Returns a string with info about a protofield (for debugging purposes) */ @@ -1246,6 +1248,7 @@ static const luaL_Reg ProtoField_methods[] = { {"ubytes",ProtoField_ubytes}, {"guid",ProtoField_guid}, {"oid",ProtoField_oid}, + {"rel_oid",ProtoField_rel_oid}, { NULL, NULL } }; diff --git a/epan/wslua/wslua_tree.c b/epan/wslua/wslua_tree.c index 192f61e318..6246e3862f 100644 --- a/epan/wslua/wslua_tree.c +++ b/epan/wslua/wslua_tree.c @@ -225,6 +225,7 @@ static int TreeItem_add_item_any(lua_State *L, gboolean little_endian) { case FT_IPXNET: case FT_GUID: case FT_OID: + case FT_REL_OID: default: luaL_error(L,"FT_ not yet supported"); return 0; diff --git a/epan/wspython/wspy_dissector.py b/epan/wspython/wspy_dissector.py index aee71d090d..e8993cd13e 100755 --- a/epan/wspython/wspy_dissector.py +++ b/epan/wspython/wspy_dissector.py @@ -66,7 +66,8 @@ FT_IPXNET, FT_FRAMENUM, FT_PCRE, FT_GUID, -FT_OID) = map(int, range(31)) +FT_OID, +FT_REL_OID) = map(int, range(32)) # hf_register_info from usual dissectors class register_info(object): diff --git a/rawshark.c b/rawshark.c index c71c31c638..c36f156b0c 100644 --- a/rawshark.c +++ b/rawshark.c @@ -1239,6 +1239,8 @@ static const char* ftenum_to_string(header_field_info *hfi) return "FT_GUID"; case FT_OID: return "FT_OID"; + case FT_REL_OID: + return "FT_REL_OID"; case FT_NUM_TYPES: return "FT_NUM_TYPES"; default: diff --git a/tools/asn2wrs.py b/tools/asn2wrs.py index 7475c467b3..8efda1fddf 100755 --- a/tools/asn2wrs.py +++ b/tools/asn2wrs.py @@ -5301,7 +5301,7 @@ class RelativeOIDType (Type): return 'RELATIVE_OID' def eth_ftype(self, ectx): - return ('FT_BYTES', 'BASE_NONE') + return ('FT_REL_OID', 'BASE_NONE') def GetTTag(self, ectx): return ('BER_CLASS_UNI', 'BER_UNI_TAG_RELATIVE_OID') diff --git a/tools/convert_proto_tree_add_text.pl b/tools/convert_proto_tree_add_text.pl index f1f20396eb..94b8f1f8a4 100755 --- a/tools/convert_proto_tree_add_text.pl +++ b/tools/convert_proto_tree_add_text.pl @@ -86,7 +86,7 @@ my %FIELD_TYPE = ('FT_NONE' => "FT_NONE", 'FT_PROTOCOL' => "FT_PROTOCOL", 'FT_BO 'FT_STRING' => "FT_STRING", 'FT_STRINGZ' => "FT_STRINGZ", 'FT_UINT_STRING' => "FT_UINT_STRING", 'FT_ETHER' => "FT_ETHER", 'FT_BYTES' => "FT_BYTES", 'FT_UINT_BYTES' => "FT_UINT_BYTES", 'FT_IPv4' => "FT_IPv4", 'FT_IPv6' => "FT_IPv6", 'FT_IPXNET' => "FT_IPXNET", 'FT_AX25' => "FT_AX25", 'FT_VINES' => "FT_VINES", - 'FT_FRAMENUM' => "FT_FRAMENUM", 'FT_PCRE' => "FT_PCRE", 'FT_GUID' => "FT_GUID", 'FT_OID' => "FT_OID", 'FT_EUI64' => "FT_EUI64"); + 'FT_FRAMENUM' => "FT_FRAMENUM", 'FT_PCRE' => "FT_PCRE", 'FT_GUID' => "FT_GUID", 'FT_OID' => "FT_OID", 'FT_REL_OID' => "FT_REL_OID", 'FT_EUI64' => "FT_EUI64"); my %EXPERT_SEVERITY = ('PI_COMMENT' => "PI_COMMENT", 'PI_CHAT' => "PI_CHAT", diff --git a/tools/fix-encoding-args.pl b/tools/fix-encoding-args.pl index 63a8d9c8c7..910d106ef1 100755 --- a/tools/fix-encoding-args.pl +++ b/tools/fix-encoding-args.pl @@ -76,7 +76,7 @@ my $searchReplaceEncNAHRef = my @types_NA = ( - [ qw (FT_NONE FT_BYTES FT_ETHER FT_IPv6 FT_IPXNET FT_OID)], + [ qw (FT_NONE FT_BYTES FT_ETHER FT_IPv6 FT_IPXNET FT_OID FT_REL_OID)], $searchReplaceEncNAHRef ); @@ -179,6 +179,7 @@ my @types_ALL = FT_PCRE FT_GUID FT_OID + FT_REL_OID FT_EUI64 )], {# valid encoding args diff --git a/ui/packet_list_utils.c b/ui/packet_list_utils.c index 24f0dd47b5..5426334663 100644 --- a/ui/packet_list_utils.c +++ b/ui/packet_list_utils.c @@ -92,7 +92,7 @@ resolve_column (gint col, capture_file *cf) /* Check if this is a valid field */ if (hfi != NULL) { /* Check if we have an OID or a strings table with integer values */ - if ((hfi->type == FT_OID) || + if ((hfi->type == FT_OID) || (hfi->type == FT_REL_OID) || ((hfi->strings != NULL) && ((hfi->type == FT_BOOLEAN) || (hfi->type == FT_FRAMENUM) || IS_FT_INT(hfi->type) || IS_FT_UINT(hfi->type)))) {