diff options
author | Michael Mann <mmann78@netscape.net> | 2016-12-29 19:41:33 -0500 |
---|---|---|
committer | Michael Mann <mmann78@netscape.net> | 2016-12-31 13:08:41 +0000 |
commit | a0be5ad6f1b964db0cc7fc948d1deb9ac89971b8 (patch) | |
tree | 9a960b1a0a4e188c8eff7e81c1a998733fa360b6 /epan | |
parent | 6a5fcc5a38936d940e4fa50294be0648a3ab6ea9 (diff) |
Add interface for "pinos" (Protocols in name only)
This is for dissectors that need distinguishing names either for registering
multiple dissection functions in a single dissector table or for "internal"
dissectors whose just need a name associated with the dissection function.
Features like enable/disable are handled by the "parent" protocol.
This avoids clutter in the "official" protocol list.
Change-Id: I69e7d27d332ae85286f254e95e8d79920da7a9e2
Reviewed-on: https://code.wireshark.org/review/19464
Petri-Dish: Michael Mann <mmann78@netscape.net>
Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org>
Reviewed-by: Michael Mann <mmann78@netscape.net>
Diffstat (limited to 'epan')
-rw-r--r-- | epan/packet.c | 4 | ||||
-rw-r--r-- | epan/proto.c | 126 | ||||
-rw-r--r-- | epan/proto.h | 24 |
3 files changed, 147 insertions, 7 deletions
diff --git a/epan/packet.c b/epan/packet.c index 5a0b2e115a..67ebb65f4b 100644 --- a/epan/packet.c +++ b/epan/packet.c @@ -642,7 +642,7 @@ call_dissector_through_handle(dissector_handle_t handle, tvbuff_t *tvb, saved_proto = pinfo->current_proto; - if (handle->protocol != NULL) { + if ((handle->protocol != NULL) && (!proto_is_pino(handle->protocol))) { pinfo->current_proto = proto_get_protocol_short_name(handle->protocol); } @@ -702,7 +702,7 @@ call_dissector_work(dissector_handle_t handle, tvbuff_t *tvb, packet_info *pinfo */ pinfo->saved_can_desegment = saved_can_desegment; pinfo->can_desegment = saved_can_desegment-(saved_can_desegment>0); - if (handle->protocol != NULL) { + if ((handle->protocol != NULL) && (!proto_is_pino(handle->protocol))) { pinfo->current_proto = proto_get_protocol_short_name(handle->protocol); diff --git a/epan/proto.c b/epan/proto.c index ceb74c6f1e..d42ac90a7a 100644 --- a/epan/proto.c +++ b/epan/proto.c @@ -315,11 +315,16 @@ struct _protocol { gboolean is_enabled; /* TRUE if protocol is enabled */ gboolean enabled_by_default; /* TRUE if protocol is enabled by default */ gboolean can_toggle; /* TRUE if is_enabled can be changed */ + int parent_proto_id; /* Used to identify "pino"s (Protocol In Name Only). + For dissectors that need a protocol name so they + can be added to a dissector table, but use the + parent_proto_id for things like enable/disable */ GList *heur_list; /* Heuristic dissectors associated with this protocol */ }; /* List of all protocols */ static GList *protocols = NULL; +static GList *pino_protocols = NULL; /* Deregistered fields */ static GPtrArray *deregistered_fields = NULL; @@ -568,6 +573,9 @@ proto_init(void (register_all_protocols_func)(register_cb cb, gpointer client_da void proto_cleanup(void) { + protocol_t *protocol; + header_field_info *hfinfo; + /* Free the abbrev/ID hash table */ if (gpa_name_map) { g_hash_table_destroy(gpa_name_map); @@ -577,8 +585,7 @@ proto_cleanup(void) last_field_name = NULL; while (protocols) { - protocol_t *protocol = (protocol_t *)protocols->data; - header_field_info *hfinfo; + protocol = (protocol_t *)protocols->data; PROTO_REGISTRAR_GET_NTH(protocol->proto_id, hfinfo); DISSECTOR_ASSERT(protocol->proto_id == hfinfo->id); @@ -591,6 +598,17 @@ proto_cleanup(void) g_free(protocol); } + while (pino_protocols) { + protocol = (protocol_t *)pino_protocols->data; + PROTO_REGISTRAR_GET_NTH(protocol->proto_id, hfinfo); + DISSECTOR_ASSERT(protocol->proto_id == hfinfo->id); + DISSECTOR_ASSERT(protocol->fields == NULL); //helpers should not have any registered fields + g_slice_free(header_field_info, hfinfo); + DISSECTOR_ASSERT(protocol->heur_list == NULL); //helpers should not have a heuristic list + pino_protocols = g_list_remove(pino_protocols, protocol); + g_free(protocol); + } + if (proto_names) { g_hash_table_destroy(proto_names); proto_names = NULL; @@ -5821,6 +5839,7 @@ proto_register_protocol(const char *name, const char *short_name, protocol->is_enabled = TRUE; /* protocol is enabled by default */ protocol->enabled_by_default = TRUE; /* see previous comment */ protocol->can_toggle = TRUE; + protocol->parent_proto_id = -1; protocol->heur_list = NULL; /* list will be sorted later by name, when all protocols completed registering */ protocols = g_list_prepend(protocols, protocol); @@ -5844,6 +5863,77 @@ proto_register_protocol(const char *name, const char *short_name, return proto_id; } +int +proto_register_protocol_in_name_only(const char *name, const char *short_name, const char *filter_name, int parent_proto, enum ftenum field_type) +{ + protocol_t *protocol; + header_field_info *hfinfo; + guint i; + gchar c; + gboolean found_invalid = FALSE; + + /* + * Helper protocols don't need the strict rules as a "regular" protocol + * Just register it in a list and make a hf_ field from it + */ + if ((field_type != FT_PROTOCOL) && (field_type != FT_BYTES)) { + g_error("Pino \"%s\" must be of type FT_PROTOCOL or FT_BYTES.", name); + } + + if (parent_proto < 0) { + g_error("Must have a valid parent protocol for helper protocol \"%s\"!" + " This might be caused by an inappropriate plugin or a development error.", name); + } + + for (i = 0; filter_name[i]; i++) { + c = filter_name[i]; + if (!(g_ascii_islower(c) || g_ascii_isdigit(c) || c == '-' || c == '_' || c == '.')) { + found_invalid = TRUE; + } + } + if (found_invalid) { + g_error("Protocol filter name \"%s\" has one or more invalid characters." + " Allowed are lower characters, digits, '-', '_' and '.'." + " This might be caused by an inappropriate plugin or a development error.", filter_name); + } + + /* Add this protocol to the list of helper protocols (just so it can be properly freed) */ + protocol = g_new(protocol_t, 1); + protocol->name = name; + protocol->short_name = short_name; + protocol->filter_name = filter_name; + protocol->fields = NULL; + + /* Enabling and toggling is really determined by parent protocol, + but provide default values here */ + protocol->is_enabled = TRUE; + protocol->enabled_by_default = TRUE; + protocol->can_toggle = TRUE; + + protocol->parent_proto_id = parent_proto; + protocol->heur_list = NULL; + /* list will be sorted later by name, when all protocols completed registering */ + pino_protocols = g_list_prepend(pino_protocols, protocol); + + /* Here we allocate a new header_field_info struct */ + hfinfo = g_slice_new(header_field_info); + hfinfo->name = name; + hfinfo->abbrev = filter_name; + hfinfo->type = field_type; + hfinfo->display = BASE_NONE; + if (field_type == FT_BYTES) { + hfinfo->display |= (BASE_NO_DISPLAY_VALUE|BASE_PROTOCOL_INFO); + } + hfinfo->strings = protocol; + hfinfo->bitmask = 0; + hfinfo->ref_type = HF_REF_TYPE_NONE; + hfinfo->blurb = NULL; + hfinfo->parent = -1; /* this field differentiates protos and fields */ + + protocol->proto_id = proto_register_field_init(hfinfo, hfinfo->parent); + return protocol->proto_id; +} + gboolean proto_deregister_protocol(const char *short_name) { @@ -5972,7 +6062,9 @@ find_protocol_by_id(const int proto_id) return NULL; PROTO_REGISTRAR_GET_NTH(proto_id, hfinfo); - DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_PROTOCOL); + if (hfinfo->type != FT_PROTOCOL) { + DISSECTOR_ASSERT(hfinfo->display & BASE_PROTOCOL_INFO); + } return (protocol_t *)hfinfo->strings; } @@ -6150,16 +6242,29 @@ proto_is_frame_protocol(const wmem_list_t *layers, const char* proto_name) return FALSE; } +gboolean +proto_is_pino(const protocol_t *protocol) +{ + return (protocol->parent_proto_id != -1); +} gboolean proto_is_protocol_enabled(const protocol_t *protocol) { + //parent protocol determines enable/disable for helper dissectors + if (proto_is_pino(protocol)) + return proto_is_protocol_enabled(find_protocol_by_id(protocol->parent_proto_id)); + return protocol->is_enabled; } gboolean proto_is_protocol_enabled_by_default(const protocol_t *protocol) { + //parent protocol determines enable/disable for helper dissectors + if (proto_is_pino(protocol)) + return proto_is_protocol_enabled_by_default(find_protocol_by_id(protocol->parent_proto_id)); + return protocol->enabled_by_default; } @@ -6169,6 +6274,10 @@ proto_can_toggle_protocol(const int proto_id) protocol_t *protocol; protocol = find_protocol_by_id(proto_id); + //parent protocol determines toggling for helper dissectors + if (proto_is_pino(protocol)) + return proto_can_toggle_protocol(protocol->parent_proto_id); + return protocol->can_toggle; } @@ -6179,6 +6288,7 @@ proto_disable_by_default(const int proto_id) protocol = find_protocol_by_id(proto_id); DISSECTOR_ASSERT(protocol->can_toggle); + DISSECTOR_ASSERT(proto_is_pino(protocol) == FALSE); protocol->is_enabled = FALSE; protocol->enabled_by_default = FALSE; } @@ -6190,6 +6300,7 @@ proto_set_decoding(const int proto_id, const gboolean enabled) protocol = find_protocol_by_id(proto_id); DISSECTOR_ASSERT(protocol->can_toggle); + DISSECTOR_ASSERT(proto_is_pino(protocol) == FALSE); protocol->is_enabled = enabled; } @@ -6577,6 +6688,12 @@ tmp_fld_check_assert(header_field_info *hfinfo) break; //fallthrough + case FT_BYTES: + //allowed to support string if its a protocol (for pinos) + if (hfinfo->display & BASE_PROTOCOL_INFO) + break; + + //fallthrough default: g_error("Field '%s' (%s) has a 'strings' value but is of type %s" " (which is not allowed to have strings)\n", @@ -6790,7 +6907,8 @@ tmp_fld_check_assert(header_field_info *hfinfo) g_error("Field '%s' (%s) is an %s but has a bitmask\n", hfinfo->name, hfinfo->abbrev, ftype_name(hfinfo->type)); - if (hfinfo->strings != NULL) + //allowed to support string if its a protocol (for pinos) + if ((hfinfo->strings != NULL) && (!(hfinfo->display & BASE_PROTOCOL_INFO))) g_error("Field '%s' (%s) is an %s but has a strings value\n", hfinfo->name, hfinfo->abbrev, ftype_name(hfinfo->type)); diff --git a/epan/proto.h b/epan/proto.h index ed4b6971e6..80756281c5 100644 --- a/epan/proto.h +++ b/epan/proto.h @@ -554,6 +554,7 @@ typedef enum { #define BASE_UNIT_STRING 0x1000 /**< Add unit text to the field value */ #define BASE_NO_DISPLAY_VALUE 0x2000 /**< Just display the field name with no value. Intended for byte arrays or header fields above a subtree */ +#define BASE_PROTOCOL_INFO 0x4000 /**< protocol_t in [FIELDCONVERT]. Internal use only. */ /** BASE_ values that cause the field value to be displayed twice */ #define IS_BASE_DUAL(b) ((b)==BASE_DEC_HEX||(b)==BASE_HEX_DEC) @@ -582,7 +583,7 @@ struct _header_field_info { int display; /**< [FIELDDISPLAY] one of BASE_, or field bit-width if FT_BOOLEAN and non-zero bitmask */ const void *strings; /**< [FIELDCONVERT] value_string, val64_string, range_string or true_false_string, typically converted by VALS(), RVALS() or TFS(). - If this is an FT_PROTOCOL then it points to the + If this is an FT_PROTOCOL or BASE_PROTOCOL_INFO then it points to the associated protocol_t structure */ guint64 bitmask; /**< [BITMASK] bitmask of interesting bits */ const char *blurb; /**< [FIELDDESCR] Brief description of field */ @@ -2096,6 +2097,23 @@ proto_item_fill_label(field_info *fi, gchar *label_str); WS_DLL_PUBLIC int proto_register_protocol(const char *name, const char *short_name, const char *filter_name); +/** Register a "helper" protocol (pino - protocol in name only). + This is for dissectors that need distinguishing names and don't need the other + features (like enable/disable). One use case is a protocol with multiple dissection + functions in a single dissector table needing unique "dissector names" to remove + confusion with Decode As dialog. Another use case is for a dissector table set + up to handle TLVs within a single protocol (and allow "external" TLVs being + registered through the dissector table). + @param name the full name of the new protocol + @param short_name abbreviated name of the new protocol + @param filter_name protocol name used for a display filter string + @param parent_proto the "real" protocol for the helper. The parent decides enable/disable + @param field_type FT_PROTOCOL or FT_BYTES. Allows removal of "protocol highlighting" (FT_BYTES) + if pino is part of TLV. + @return the new protocol handle */ +WS_DLL_PUBLIC int +proto_register_protocol_in_name_only(const char *name, const char *short_name, const char *filter_name, int parent_proto, enum ftenum field_type); + /** Deregister a protocol. @param short_name abbreviated name of the protocol @return TRUE if protocol is removed */ @@ -2256,6 +2274,10 @@ WS_DLL_PUBLIC gboolean proto_is_protocol_enabled(const protocol_t *protocol); @return TRUE if decoding is enabled by default, FALSE if not */ WS_DLL_PUBLIC gboolean proto_is_protocol_enabled_by_default(const protocol_t *protocol); +/** Is this a protocol in name only (i.e. not a real one)? + @return TRUE if helper, FALSE if not */ +WS_DLL_PUBLIC gboolean proto_is_pino(const protocol_t *protocol); + /** Get a protocol's filter name by its item number. @param proto_id protocol id (0-indexed) @return its filter name. */ |