diff options
author | Tomas Kukosa <tomas.kukosa@siemens.com> | 2005-12-02 13:16:58 +0000 |
---|---|---|
committer | Tomas Kukosa <tomas.kukosa@siemens.com> | 2005-12-02 13:16:58 +0000 |
commit | dcae7d303f0669cee025a52fbc22d3e7c4d535bc (patch) | |
tree | d41f358db1ab3107d4951c04b41d4c148c8d4e06 /epan | |
parent | a809b11b2bee93510dd001a96a7d01f78e2a7030 (diff) |
new field type FT_OID for OBJECT IDENTIFIERs
svn path=/trunk/; revision=16652
Diffstat (limited to 'epan')
-rw-r--r-- | epan/dfilter/semcheck.c | 5 | ||||
-rw-r--r-- | epan/dissectors/packet-ber.c | 6 | ||||
-rw-r--r-- | epan/dissectors/packet-per.c | 4 | ||||
-rw-r--r-- | epan/ftypes/ftype-bytes.c | 93 | ||||
-rw-r--r-- | epan/ftypes/ftypes.h | 1 | ||||
-rw-r--r-- | epan/proto.c | 96 | ||||
-rw-r--r-- | epan/proto.h | 32 | ||||
-rw-r--r-- | epan/strutil.c | 57 | ||||
-rw-r--r-- | epan/strutil.h | 9 | ||||
-rw-r--r-- | epan/to_str.c | 26 |
10 files changed, 313 insertions, 16 deletions
diff --git a/epan/dfilter/semcheck.c b/epan/dfilter/semcheck.c index 8316f6d3f9..b575be7a96 100644 --- a/epan/dfilter/semcheck.c +++ b/epan/dfilter/semcheck.c @@ -75,7 +75,8 @@ compatible_ftypes(ftenum_t a, ftenum_t b) case FT_BYTES: case FT_UINT_BYTES: case FT_GUID: - return (b == FT_ETHER || b == FT_BYTES || b == FT_UINT_BYTES || b == FT_GUID); + case FT_OID: + return (b == FT_ETHER || b == FT_BYTES || b == FT_UINT_BYTES || b == FT_GUID || b == FT_OID); case FT_BOOLEAN: case FT_FRAMENUM: @@ -167,6 +168,7 @@ mk_fvalue_from_val_string(header_field_info *hfinfo, char *s) case FT_INT64: case FT_PCRE: case FT_GUID: + case FT_OID: return FALSE; case FT_BOOLEAN: @@ -237,6 +239,7 @@ is_bytes_type(enum ftenum type) case FT_UINT_BYTES: case FT_IPv6: case FT_GUID: + case FT_OID: return TRUE; case FT_NONE: diff --git a/epan/dissectors/packet-ber.c b/epan/dissectors/packet-ber.c index ed40536ad2..781032b6c5 100644 --- a/epan/dissectors/packet-ber.c +++ b/epan/dissectors/packet-ber.c @@ -1775,9 +1775,9 @@ printf("OBJECT IDENTIFIER dissect_ber_object_identifier(%s) entered\n",name); str = oid_to_str(tvb_get_ptr(tvb, offset, len), len); hfi = proto_registrar_get_nth(hf_id); - /*if (hfi->type == FT_OID) { - item = proto_tree_add_item(tree, hf_index, tvb, offset, len, FALSE); - } else*/ if (IS_FT_STRING(hfi->type)) { + if (hfi->type == FT_OID) { + item = proto_tree_add_item(tree, hf_id, tvb, offset, len, FALSE); + } else if (IS_FT_STRING(hfi->type)) { item = proto_tree_add_string(tree, hf_id, tvb, offset, len, str); } else { DISSECTOR_ASSERT_NOT_REACHED(); diff --git a/epan/dissectors/packet-per.c b/epan/dissectors/packet-per.c index a6ecb567cd..ce644a127a 100644 --- a/epan/dissectors/packet-per.c +++ b/epan/dissectors/packet-per.c @@ -617,9 +617,9 @@ DEBUG_ENTRY("dissect_per_object_identifier"); str = oid_to_str(tvb_get_ptr(tvb, offset>>3, length), length); hfi = proto_registrar_get_nth(hf_index); - /*if (hfi->type == FT_OID) { + if (hfi->type == FT_OID) { item = proto_tree_add_item(tree, hf_index, tvb, offset>>3, length, FALSE); - } else*/ if (IS_FT_STRING(hfi->type)) { + } else if (IS_FT_STRING(hfi->type)) { item = proto_tree_add_string(tree, hf_index, tvb, offset>>3, length, str); } else { DISSECTOR_ASSERT_NOT_REACHED(); diff --git a/epan/ftypes/ftype-bytes.c b/epan/ftypes/ftype-bytes.c index b2e713d57d..acb9b3373a 100644 --- a/epan/ftypes/ftype-bytes.c +++ b/epan/ftypes/ftype-bytes.c @@ -88,6 +88,19 @@ guid_to_repr(fvalue_t *fv, ftrepr_t rtype _U_, char *buf) guid_to_str_buf(fv->value.bytes->data, buf, GUID_STR_LEN); } +static int +oid_repr_len(fvalue_t *fv _U_, ftrepr_t rtype _U_) +{ + /* more exact computation will come later */ + return fv->value.bytes->len * 3 + 16; +} + +static void +oid_to_repr(fvalue_t *fv, ftrepr_t rtype _U_, char *buf) +{ + oid_to_str_buf(fv->value.bytes->data, fv->value.bytes->len, buf, oid_repr_len(fv, rtype)); +} + static void bytes_to_repr(fvalue_t *fv, ftrepr_t rtype _U_, char *buf) { @@ -141,6 +154,18 @@ guid_fvalue_set(fvalue_t *fv, gpointer value, gboolean already_copied) common_fvalue_set(fv, value, GUID_LEN); } +static void +oid_fvalue_set(fvalue_t *fv, gpointer value, gboolean already_copied) +{ + g_assert(already_copied); + + /* Free up the old value, if we have one */ + bytes_fvalue_free(fv); + + fv->value.bytes = value; +} + + static gpointer value_get(fvalue_t *fv) { @@ -316,6 +341,38 @@ guid_from_unparsed(fvalue_t *fv, char *s, gboolean allow_partial_value, LogFunc return TRUE; } +static gboolean +oid_from_unparsed(fvalue_t *fv, char *s, gboolean allow_partial_value, 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. + */ + if (bytes_from_unparsed(fv, s, TRUE, NULL)) { + return TRUE; + } + + bytes = g_byte_array_new(); + res = oid_str_to_bytes(s, bytes); + if (!res) { + if (logfunc != NULL) + logfunc("\"%s\" is not a valid OBJECT IDENTIFIER.", 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) { @@ -680,9 +737,45 @@ ftype_register_bytes(void) slice, }; + static ftype_t oid_type = { + "OID", /* name */ + "OBJECT IDENTIFIER", /* pretty_name */ + 0, /* wire_size */ + bytes_fvalue_new, /* new_value */ + bytes_fvalue_free, /* free_value */ + oid_from_unparsed, /* val_from_unparsed */ + NULL, /* val_from_string */ + oid_to_repr, /* val_to_string_repr */ + oid_repr_len, /* len_string_repr */ + + oid_fvalue_set, /* set_value */ + NULL, /* set_value_integer */ + NULL, /* set_value_integer64 */ + NULL, /* set_value_floating */ + + value_get, /* get_value */ + NULL, /* get_value_integer */ + NULL, /* get_value_integer64 */ + NULL, /* get_value_floating */ + + cmp_eq, + cmp_ne, + cmp_gt, + cmp_ge, + cmp_lt, + cmp_le, + cmp_bytes_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_ETHER, ðer_type); ftype_register(FT_IPv6, &ipv6_type); ftype_register(FT_GUID, &guid_type); + ftype_register(FT_OID, &oid_type); } diff --git a/epan/ftypes/ftypes.h b/epan/ftypes/ftypes.h index 83a24a5ff4..5fbf163dc9 100644 --- a/epan/ftypes/ftypes.h +++ b/epan/ftypes/ftypes.h @@ -61,6 +61,7 @@ enum ftenum { FT_FRAMENUM, /* a UINT32, but if selected lets you go to frame with that numbe */ FT_PCRE, /* a compiled Perl-Compatible Regular Expression object */ FT_GUID, /* GUID, UUID */ + FT_OID, /* OBJECT IDENTIFIER */ FT_NUM_TYPES /* last item number plus one */ }; diff --git a/epan/proto.c b/epan/proto.c index 08c97357fc..9f588a1819 100644 --- a/epan/proto.c +++ b/epan/proto.c @@ -152,6 +152,10 @@ proto_tree_set_guid(field_info *fi, const guint8* value_ptr); static void proto_tree_set_guid_tvb(field_info *fi, tvbuff_t *tvb, gint start); static void +proto_tree_set_oid(field_info *fi, const guint8* value_ptr, gint length); +static void +proto_tree_set_oid_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length); +static void proto_tree_set_boolean(field_info *fi, guint32 value); static void proto_tree_set_float(field_info *fi, float value); @@ -898,6 +902,10 @@ proto_tree_new_item(field_info *new_fi, proto_tree *tree, int hfindex, proto_tree_set_guid_tvb(new_fi, tvb, start); break; + case FT_OID: + proto_tree_set_oid_tvb(new_fi, tvb, start, length); + break; + case FT_FLOAT: DISSECTOR_ASSERT(length == 4); if (little_endian) @@ -1600,6 +1608,83 @@ proto_tree_set_guid_tvb(field_info *fi, tvbuff_t *tvb, gint start) proto_tree_set_guid(fi, tvb_get_ptr(tvb, start, 16)); } +/* Add a FT_OID to a proto_tree */ +proto_item * +proto_tree_add_oid(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length, + const guint8* value_ptr) +{ + proto_item *pi; + field_info *new_fi; + header_field_info *hfinfo; + + if (!tree) + return (NULL); + + TRY_TO_FAKE_THIS_ITEM(tree, hfindex); + + PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo); + DISSECTOR_ASSERT(hfinfo->type == FT_OID); + + pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi); + proto_tree_set_oid(new_fi, value_ptr, length); + + return pi; +} + +proto_item * +proto_tree_add_oid_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length, + const guint8* value_ptr) +{ + proto_item *pi; + + pi = proto_tree_add_oid(tree, hfindex, tvb, start, length, value_ptr); + if (pi == NULL) + return (NULL); + + PROTO_ITEM_SET_HIDDEN(pi); + + return pi; +} + +proto_item * +proto_tree_add_oid_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length, + const guint8* value_ptr, const char *format, ...) +{ + proto_item *pi; + va_list ap; + + pi = proto_tree_add_oid(tree, hfindex, tvb, start, length, value_ptr); + if (pi == NULL) + return (NULL); + + va_start(ap, format); + proto_tree_set_representation(pi, format, ap); + va_end(ap); + + return pi; +} + +/* Set the FT_OID value */ +static void +proto_tree_set_oid(field_info *fi, const guint8* value_ptr, gint length) +{ + GByteArray *bytes; + + DISSECTOR_ASSERT(value_ptr != NULL); + + bytes = g_byte_array_new(); + if (length > 0) { + g_byte_array_append(bytes, value_ptr, length); + } + fvalue_set(&fi->value, bytes, TRUE); +} + +static void +proto_tree_set_oid_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length) +{ + proto_tree_set_oid(fi, tvb_get_ptr(tvb, start, length), length); +} + static void proto_tree_set_uint64(field_info *fi, guint64 value) { @@ -3415,6 +3500,15 @@ proto_item_fill_label(field_info *fi, gchar *label_str) label_str[ITEM_LABEL_LENGTH - 1] = '\0'; break; + case FT_OID: + bytes = fvalue_get(&fi->value); + ret = g_snprintf(label_str, ITEM_LABEL_LENGTH, + "%s: %s", hfinfo->name, + oid_to_str(bytes, fvalue_length(&fi->value))); + if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH)) + label_str[ITEM_LABEL_LENGTH - 1] = '\0'; + break; + case FT_STRING: case FT_STRINGZ: case FT_UINT_STRING: @@ -4629,6 +4723,7 @@ proto_can_match_selected(field_info *finfo, epan_dissect_t *edt) case FT_UINT_BYTES: case FT_PROTOCOL: case FT_GUID: + case FT_OID: /* * These all have values, so we can match. */ @@ -4791,6 +4886,7 @@ proto_construct_dfilter_string(field_info *finfo, epan_dissect_t *edt) case FT_IPv4: case FT_IPv6: case FT_GUID: + case FT_OID: /* Figure out the string length needed. * The ft_repr length. * 4 bytes for " == ". diff --git a/epan/proto.h b/epan/proto.h index 7962fd0a50..56536b6fa5 100644 --- a/epan/proto.h +++ b/epan/proto.h @@ -730,6 +730,38 @@ extern proto_item * proto_tree_add_guid_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length, const guint8* value_ptr, const char *format, ...) GNUC_FORMAT_CHECK(printf,7,8); +/** Add a FT_OID to a proto_tree. + @param tree the tree to append this item to + @param hfindex field index + @param tvb the tv buffer of the current data + @param start start of data in tvb + @param length length of data in tvb + @param value_ptr data to display + @return the newly created item */ +extern proto_item * +proto_tree_add_oid(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, + gint length, const guint8* value_ptr); + +/** Add a hidden FT_OID to a proto_tree. + @deprecated use proto_tree_add_guid() and a subsequent call to PROTO_ITEM_SET_HIDDEN() instead */ +extern proto_item * +proto_tree_add_oid_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, + gint length, const guint8* value_ptr); + +/** Add a formatted FT_OID to a proto_tree. + @param tree the tree to append this item to + @param hfindex field index + @param tvb the tv buffer of the current data + @param start start of data in tvb + @param length length of data in tvb + @param value_ptr data to display + @param format printf like format string + @param ... printf like parameters + @return the newly created item */ +extern proto_item * +proto_tree_add_oid_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, + gint length, const guint8* value_ptr, const char *format, ...) GNUC_FORMAT_CHECK(printf,7,8); + /** Add a FT_STRING to a proto_tree. @param tree the tree to append this item to @param hfindex field index diff --git a/epan/strutil.c b/epan/strutil.c index bba8e19651..53b4780a3d 100644 --- a/epan/strutil.c +++ b/epan/strutil.c @@ -393,6 +393,63 @@ hex_str_to_bytes(const char *hex_str, GByteArray *bytes, gboolean force_separato return TRUE; } +#define SUBID_BUF_LEN 5 +gboolean +oid_str_to_bytes(const char *oid_str, GByteArray *bytes) { + guint32 subid0, subid, sicnt, i; + const char *p, *dot; + guint8 buf[SUBID_BUF_LEN]; + + g_byte_array_set_size(bytes, 0); + + /* check syntax */ + p = oid_str; + dot = NULL; + while (*p) { + if (!isdigit(*p) && (*p != '.')) return FALSE; + if (*p == '.') { + if (p == oid_str) return FALSE; + if (!*(p+1)) return FALSE; + if ((p-1) == dot) return FALSE; + dot = p; + } + p++; + } + if (!dot) return FALSE; + + p = oid_str; + sicnt = 0; + while (*p) { + subid = 0; + while (isdigit(*p)) { + subid *= 10; + subid += *p - '0'; + p++; + } + if (sicnt == 0) { + subid0 = subid; + if (subid0 > 2) return FALSE; + } else if (sicnt == 1) { + if ((subid0 < 2) && (subid > 39)) return FALSE; + subid += 40 * subid0; + } + if (sicnt) { + i = SUBID_BUF_LEN; + do { + i--; + buf[i] = 0x80 | (subid % 0x80); + subid >>= 7; + } while (subid && i); + buf[SUBID_BUF_LEN-1] &= 0x7F; + g_byte_array_append(bytes, buf + i, SUBID_BUF_LEN - i); + } + sicnt++; + if (*p) p++; + } + + return TRUE; +} + /* Return a XML escaped representation of the unescaped string. * The returned string must be freed when no longer in use. */ diff --git a/epan/strutil.h b/epan/strutil.h index 9e8c632a09..ac5dc5aaab 100644 --- a/epan/strutil.h +++ b/epan/strutil.h @@ -99,6 +99,15 @@ gchar* bytes_to_str_punct(const guint8 *bd, int bd_len, gchar punct); gboolean hex_str_to_bytes(const char *hex_str, GByteArray *bytes, gboolean force_separators); +/** Turn a OID string representation (dot notaion) 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. + * @return True if the string was converted successfully + */ +gboolean oid_str_to_bytes(const char *oid_str, GByteArray *bytes); + /** Return a XML escaped representation of the unescaped string. * The returned string must be freed when no longer in use. * diff --git a/epan/to_str.c b/epan/to_str.c index 138d831e99..14ccbcfc8b 100644 --- a/epan/to_str.c +++ b/epan/to_str.c @@ -840,26 +840,32 @@ gchar* oid_to_str(const guint8 *oid, gint oid_len) { gchar* oid_to_str_buf(const guint8 *oid, gint oid_len, gchar *buf, int buf_len) { gint i; guint8 byte; - guint32 value; + guint32 subid0, subid; + gboolean is_first; gchar *bufp; - bufp = buf; value=0; + bufp = buf; subid = 0; is_first = TRUE; for (i=0; i<oid_len; i++){ byte = oid[i]; - if ((bufp - buf) > (MAX_OID_STR_LEN - 16)) { /* "4294967295" + ".>>>" + '\0' + 1 */ + if ((bufp - buf) > (buf_len - 12)) { bufp += g_snprintf(bufp, buf_len-(bufp-buf), ".>>>"); break; } - if (i == 0) { - bufp += g_snprintf(bufp, buf_len-(bufp-buf), "%u.%u", byte/40, byte%40); - continue; - } - value = (value << 7) | (byte & 0x7F); + subid <<= 7; + subid |= byte & 0x7F; if (byte & 0x80) { continue; } - bufp += g_snprintf(bufp, buf_len-(bufp-buf), ".%u", value); - value = 0; + if (is_first) { + subid0 = 0; + if (subid >= 40) { subid0++; subid-=40; } + if (subid >= 40) { subid0++; subid-=40; } + bufp += g_snprintf(bufp, buf_len-(bufp-buf), "%u.%u", subid0, subid); + is_first = FALSE; + } else { + bufp += g_snprintf(bufp, buf_len-(bufp-buf), ".%u", subid); + } + subid = 0; } *bufp = '\0'; |