diff options
author | Michael Mann <mmann78@netscape.net> | 2017-07-09 13:44:06 -0400 |
---|---|---|
committer | Michael Mann <mmann78@netscape.net> | 2017-09-16 11:12:52 +0000 |
commit | 69250aa51eac68015e520f5680970ded2db1ee14 (patch) | |
tree | 7c437441cf41433d203d24850c7d440d2fa08045 | |
parent | 7d65b573f2734017be416f31852c4ede42bd987b (diff) |
Add support for dissector tables of type FT_NONE.
This is for dissectors that have "payloads" that don't have
a unique identifier to determine a sub dissector.
For the command line parameter -d, specifying a selector is no longer
required for dissector tables of type FT_NONE.
Change-Id: I3370d9e0dc147deeca4f26b842fe35dc3bda876e
Reviewed-on: https://code.wireshark.org/review/22574
Reviewed-by: Michael Mann <mmann78@netscape.net>
-rw-r--r-- | epan/decode_as.c | 26 | ||||
-rw-r--r-- | epan/dissectors/packet-bthci_evt.c | 22 | ||||
-rw-r--r-- | epan/packet.c | 45 | ||||
-rw-r--r-- | epan/packet.h | 19 | ||||
-rw-r--r-- | ui/decode_as_utils.c | 65 | ||||
-rw-r--r-- | ui/gtk/decode_as_dlg.c | 4 | ||||
-rw-r--r-- | ui/gtk/dissector_tables_dlg.c | 2 | ||||
-rw-r--r-- | ui/qt/models/decode_as_model.cpp | 31 |
8 files changed, 185 insertions, 29 deletions
diff --git a/epan/decode_as.c b/epan/decode_as.c index 30e60abd86..43405fa3e9 100644 --- a/epan/decode_as.c +++ b/epan/decode_as.c @@ -143,6 +143,9 @@ gboolean decode_as_default_reset(const gchar *name, gconstpointer pattern) case FT_UINT32: dissector_reset_uint(name, GPOINTER_TO_UINT(pattern)); return TRUE; + case FT_NONE: + dissector_reset_payload(name); + return TRUE; case FT_STRING: case FT_STRINGZ: case FT_UINT_STRING: @@ -167,6 +170,9 @@ gboolean decode_as_default_change(const gchar *name, gconstpointer pattern, gpoi case FT_UINT32: dissector_change_uint(name, GPOINTER_TO_UINT(pattern), *dissector); return TRUE; + case FT_NONE: + dissector_change_payload(name, *dissector); + return TRUE; case FT_STRING: case FT_STRINGZ: case FT_UINT_STRING: @@ -349,6 +355,17 @@ decode_as_write_entry (const gchar *table_name, ftenum_t selector_type, table_name, GPOINTER_TO_UINT(key), initial_proto_name, current_proto_name); break; + case FT_NONE: + /* + * XXX - Just put a placeholder for the key value. Currently + * FT_NONE dissector table uses a single uint value for + * a placeholder + */ + fprintf (da_file, + DECODE_AS_ENTRY ": %s,0,%s,%s\n", + table_name, initial_proto_name, + current_proto_name); + break; case FT_STRING: case FT_STRINGZ: @@ -436,6 +453,11 @@ decode_build_reset_list (const gchar *table_name, ftenum_t selector_type, item->ddi_selector.sel_uint = GPOINTER_TO_UINT(key); break; + case FT_NONE: + /* Not really needed, but prevents the assert */ + item->ddi_selector.sel_uint = 0; + break; + case FT_STRING: case FT_STRINGZ: case FT_UINT_STRING: @@ -470,6 +492,10 @@ decode_clear_all(void) item->ddi_selector.sel_uint); break; + case FT_NONE: + dissector_reset_payload(item->ddi_table_name); + break; + case FT_STRING: case FT_STRINGZ: case FT_UINT_STRING: diff --git a/epan/dissectors/packet-bthci_evt.c b/epan/dissectors/packet-bthci_evt.c index c32e74c9de..6269e25602 100644 --- a/epan/dissectors/packet-bthci_evt.c +++ b/epan/dissectors/packet-bthci_evt.c @@ -918,6 +918,11 @@ static void bthci_evt_vendor_prompt(packet_info *pinfo _U_, gchar* result) g_snprintf(result, MAX_DECODE_AS_PROMPT_LEN, "Vendor as"); } +static gpointer bthci_evt_vendor_value(packet_info *pinfo _U_) +{ + return NULL; +} + static void add_opcode(wmem_list_t *opcode_list, guint16 opcode, enum command_status command_status) { opcode_list_data_t *opcode_list_data; @@ -1924,7 +1929,7 @@ dissect_bthci_evt_command_status(tvbuff_t *tvb, int offset, packet_info *pinfo, if (ogf == HCI_OGF_VENDOR_SPECIFIC) { col_append_fstr(pinfo->cinfo, COL_INFO, " (Vendor Command 0x%04X [(opcode 0x%04X])", opcode & 0x03ff, opcode); - if (!dissector_try_uint_new(vendor_dissector_table, HCI_VENDOR_DEFAULT, tvb, pinfo, main_tree, TRUE, bluetooth_data)) { + if (!dissector_try_payload_new(vendor_dissector_table, tvb, pinfo, main_tree, TRUE, bluetooth_data)) { if (bluetooth_data) { hci_vendor_data_t *hci_vendor_data; wmem_tree_key_t key[3]; @@ -2755,7 +2760,7 @@ dissect_bthci_evt_command_complete(tvbuff_t *tvb, int offset, if (ogf == HCI_OGF_VENDOR_SPECIFIC) { col_append_fstr(pinfo->cinfo, COL_INFO, " (Vendor Command 0x%04X [opcode 0x%04X])", opcode & 0x03ff, opcode); - if (!dissector_try_uint_new(vendor_dissector_table, HCI_VENDOR_DEFAULT, tvb, pinfo, main_tree, TRUE, bluetooth_data)) { + if (!dissector_try_payload_new(vendor_dissector_table, tvb, pinfo, main_tree, TRUE, bluetooth_data)) { if (bluetooth_data) { hci_vendor_data_t *hci_vendor_data; @@ -5516,7 +5521,7 @@ dissect_bthci_evt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *dat break; case 0xff: /* Vendor-Specific */ - if (!dissector_try_uint_new(vendor_dissector_table, HCI_VENDOR_DEFAULT, tvb, pinfo, tree, TRUE, bluetooth_data)) { + if (!dissector_try_payload_new(vendor_dissector_table, tvb, pinfo, tree, TRUE, bluetooth_data)) { if (bluetooth_data) { hci_vendor_data_t *hci_vendor_data; wmem_tree_key_t key[3]; @@ -7971,6 +7976,15 @@ proto_register_bthci_evt(void) &ett_expert }; + /* Decode As handling + This doesn't use register_decode_as_next_proto because it shares a dissector table + with "bthci_cmd.vendor" */ + static build_valid_func bthci_evt_vendor_da_build_value[1] = {bthci_evt_vendor_value}; + static decode_as_value_t bthci_evt_vendor_da_values = {bthci_evt_vendor_prompt, 1, bthci_evt_vendor_da_build_value}; + static decode_as_t bthci_evt_vendor_da = {"bthci_cmd", "Vendor", "bthci_cmd.vendor", 1, 0, &bthci_evt_vendor_da_values, NULL, NULL, + decode_as_default_populate_list, decode_as_default_reset, decode_as_default_change, NULL}; + + /* Register the protocol name and description */ proto_bthci_evt = proto_register_protocol("Bluetooth HCI Event", "HCI_EVT", "bthci_evt"); @@ -7988,7 +8002,7 @@ proto_register_bthci_evt(void) "Bluetooth HCI version: 4.0 (Core) + Addendum 4", "Version of protocol supported by this dissector."); - register_decode_as_next_proto("bthci_cmd", "Vendor", "bthci_cmd.vendor", (build_label_func*)&bthci_evt_vendor_prompt); + register_decode_as(&bthci_evt_vendor_da); } diff --git a/epan/packet.c b/epan/packet.c index 542277db24..b416c8c03c 100644 --- a/epan/packet.c +++ b/epan/packet.c @@ -915,6 +915,9 @@ find_uint_dtbl_entry(dissector_table_t sub_dissectors, const guint32 pattern) * You can do a uint lookup in these tables. */ break; + case FT_NONE: + /* For now treat as uint */ + break; default: /* @@ -1856,6 +1859,36 @@ dissector_handle_t dissector_get_guid_handle( return NULL; } +/* Use the currently assigned payload dissector for the dissector table and, + if any, call the dissector with the arguments supplied, and return the + number of bytes consumed, otherwise return 0. */ +int dissector_try_payload(dissector_table_t sub_dissectors, + tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) +{ + return dissector_try_uint(sub_dissectors, 0, tvb, pinfo, tree); +} + +/* Use the currently assigned payload dissector for the dissector table and, + if any, call the dissector with the arguments supplied, and return the + number of bytes consumed, otherwise return 0. */ +int dissector_try_payload_new(dissector_table_t sub_dissectors, + tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, const gboolean add_proto_name, void *data) +{ + return dissector_try_uint_new(sub_dissectors, 0, tvb, pinfo, tree, add_proto_name, data); +} + +/* Change the entry for a dissector in a payload (FT_NONE) dissector table + with a particular pattern to use a new dissector handle. */ +void dissector_change_payload(const char *abbrev, dissector_handle_t handle) +{ + dissector_change_uint(abbrev, 0, handle); +} + +/* Reset payload (FT_NONE) dissector table to its initial value. */ +void dissector_reset_payload(const char *name) +{ + dissector_reset_uint(name, 0); +} dissector_handle_t dtbl_entry_get_handle (dtbl_entry_t *dtbl_entry) @@ -2349,6 +2382,18 @@ register_dissector_table(const char *name, const char *ui_name, const int proto, NULL, &g_free ); break; + + case FT_NONE: + /* Dissector tables with FT_NONE don't have values associated with + dissectors so this will always be a hash table size of 1 just + to store the single dtbl_entry_t */ + sub_dissectors->hash_func = g_direct_hash; + sub_dissectors->hash_table = g_hash_table_new_full( g_direct_hash, + g_direct_equal, + NULL, + &g_free ); + break; + default: g_error("The dissector table %s (%s) is registering an unsupported type - are you using a buggy plugin?", name, ui_name); g_assert_not_reached(); diff --git a/epan/packet.h b/epan/packet.h index 84aa4912f5..ffe23285a4 100644 --- a/epan/packet.h +++ b/epan/packet.h @@ -367,6 +367,25 @@ WS_DLL_PUBLIC int dissector_try_guid_new(dissector_table_t sub_dissectors, WS_DLL_PUBLIC dissector_handle_t dissector_get_guid_handle( dissector_table_t const sub_dissectors, guid_key* guid_val); +/* Use the currently assigned payload dissector for the dissector table and, + if any, call the dissector with the arguments supplied, and return the + number of bytes consumed, otherwise return 0. */ +WS_DLL_PUBLIC int dissector_try_payload(dissector_table_t sub_dissectors, + tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree); + +/* Use the currently assigned payload dissector for the dissector table and, + if any, call the dissector with the arguments supplied, and return the + number of bytes consumed, otherwise return 0. */ +WS_DLL_PUBLIC int dissector_try_payload_new(dissector_table_t sub_dissectors, + tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, const gboolean add_proto_name, void *data); + +/* Change the entry for a dissector in a payload (FT_NONE) dissector table + with a particular pattern to use a new dissector handle. */ +WS_DLL_PUBLIC void dissector_change_payload(const char *abbrev, dissector_handle_t handle); + +/* Reset payload (FT_NONE) dissector table to its initial value. */ +WS_DLL_PUBLIC void dissector_reset_payload(const char *name); + /* Add a handle to the list of handles that *could* be used with this table. That list is used by the "Decode As"/"-d" code in the UI. */ WS_DLL_PUBLIC void dissector_add_for_decode_as(const char *name, diff --git a/ui/decode_as_utils.c b/ui/decode_as_utils.c index 173d82fe0b..0cf5942d57 100644 --- a/ui/decode_as_utils.c +++ b/ui/decode_as_utils.c @@ -187,7 +187,7 @@ gboolean decode_as_command_option(const gchar *cl_param) guint32 selector, selector2; gchar *decoded_param; gchar *remaining_param; - gchar *selector_str; + gchar *selector_str = NULL; gchar *dissector_str; dissector_handle_t dissector_matching; dissector_table_t table_matching; @@ -212,7 +212,14 @@ gboolean decode_as_command_option(const gchar *cl_param) remaining_param = strchr(table_name, '='); if (remaining_param == NULL) { - cmdarg_err("Parameter \"%s\" doesn't follow the template \"%s\"", cl_param, DECODE_AS_ARG_TEMPLATE); + /* Dissector tables of type FT_NONE aren't required to specify a value, so for now + just check for comma */ + remaining_param = strchr(table_name, ','); + if (remaining_param == NULL) { + cmdarg_err("Parameter \"%s\" doesn't follow the template \"%s\"", cl_param, DECODE_AS_ARG_TEMPLATE); + } else { + *remaining_param = '\0'; /* Terminate the layer type string (table_name) where ',' was detected */ + } /* If the argument does not follow the template, carry on anyway to check if the table name is at least correct. If remaining_param is NULL, we'll exit anyway further down */ @@ -254,31 +261,34 @@ gboolean decode_as_command_option(const gchar *cl_param) return FALSE; } - if (*(remaining_param + 1) != '=') { /* Check for "==" and not only '=' */ - cmdarg_err("WARNING: -d requires \"==\" instead of \"=\". Option will be treated as \"%s==%s\"", table_name, remaining_param + 1); - } - else { - remaining_param++; /* Move to the second '=' */ - *remaining_param = '\0'; /* Remove the second '=' */ - } - remaining_param++; /* Position after the layer type string */ + dissector_table_selector_type = get_dissector_table_selector_type(table_name); - /* This section extracts a selector value (selector_str) from decoded_param */ + if (dissector_table_selector_type != FT_NONE) { + if (*(remaining_param + 1) != '=') { /* Check for "==" and not only '=' */ + cmdarg_err("WARNING: -d requires \"==\" instead of \"=\". Option will be treated as \"%s==%s\"", table_name, remaining_param + 1); + } + else { + remaining_param++; /* Move to the second '=' */ + *remaining_param = '\0'; /* Remove the second '=' */ + } + remaining_param++; /* Position after the layer type string */ - selector_str = remaining_param; /* Next part starts with the selector number */ - remaining_param = strchr(selector_str, ','); - if (remaining_param == NULL) { - cmdarg_err("Parameter \"%s\" doesn't follow the template \"%s\"", cl_param, DECODE_AS_ARG_TEMPLATE); - /* If the argument does not follow the template, carry on anyway to check - if the selector value is at least correct. If remaining_param is NULL, - we'll exit anyway further down */ - } - else { - *remaining_param = '\0'; /* Terminate the selector number string (selector_str) where ',' was detected */ - } + /* This section extracts a selector value (selector_str) from decoded_param */ - dissector_table_selector_type = get_dissector_table_selector_type(table_name); + selector_str = remaining_param; /* Next part starts with the selector number */ + + remaining_param = strchr(selector_str, ','); + if (remaining_param == NULL) { + cmdarg_err("Parameter \"%s\" doesn't follow the template \"%s\"", cl_param, DECODE_AS_ARG_TEMPLATE); + /* If the argument does not follow the template, carry on anyway to check + if the selector value is at least correct. If remaining_param is NULL, + we'll exit anyway further down */ + } + else { + *remaining_param = '\0'; /* Terminate the selector number string (selector_str) where ',' was detected */ + } + } switch (dissector_table_selector_type) { @@ -328,6 +338,10 @@ gboolean decode_as_command_option(const gchar *cl_param) /* The selector for this table is a string. */ break; + case FT_NONE: + /* There is no selector for this table */ + break; + default: /* There are currently no dissector tables with any types other than the ones listed above. */ @@ -440,6 +454,11 @@ gboolean decode_as_command_option(const gchar *cl_param) dissector_change_string(table_name, selector_str, dissector_matching); break; + case FT_NONE: + /* Just directly set the dissector found. */ + dissector_change_payload(table_name, dissector_matching); + break; + default: /* There are currently no dissector tables with any types other than the ones listed above. */ diff --git a/ui/gtk/decode_as_dlg.c b/ui/gtk/decode_as_dlg.c index 4e8292b439..86f231bc63 100644 --- a/ui/gtk/decode_as_dlg.c +++ b/ui/gtk/decode_as_dlg.c @@ -323,6 +323,10 @@ decode_build_show_list (const gchar *table_name, ftenum_t selector_type, selector_name = string1; break; + case FT_NONE: + selector_name = NULL; + break; + case FT_STRING: case FT_STRINGZ: case FT_UINT_STRING: diff --git a/ui/gtk/dissector_tables_dlg.c b/ui/gtk/dissector_tables_dlg.c index e57a6a6eba..40289936df 100644 --- a/ui/gtk/dissector_tables_dlg.c +++ b/ui/gtk/dissector_tables_dlg.c @@ -153,6 +153,7 @@ decode_proto_add_to_list (const gchar *table_name _U_, ftenum_t selector_type, case FT_BYTES: case FT_GUID: + case FT_NONE: dissector_name_str = dissector_handle_get_dissector_name(handle); if (dissector_name_str == NULL) dissector_name_str = "<Unknown>"; @@ -244,6 +245,7 @@ display_dissector_table_names(const char *table_name, const char *ui_name, void break; case FT_BYTES: case FT_GUID: + case FT_NONE: table_name_add_to_list(tree_info, dis_tbl_trees->custom_tree_wgt, table_name, ui_name); break; default: diff --git a/ui/qt/models/decode_as_model.cpp b/ui/qt/models/decode_as_model.cpp index 2c15e419fc..e4e654ddb1 100644 --- a/ui/qt/models/decode_as_model.cpp +++ b/ui/qt/models/decode_as_model.cpp @@ -61,14 +61,22 @@ Qt::ItemFlags DecodeAsModel::flags(const QModelIndex &index) const if (!index.isValid()) return 0; + DecodeAsItem* item = decode_as_items_[index.row()]; + Qt::ItemFlags flags = QAbstractTableModel::flags(index); switch(index.column()) { case DecodeAsModel::colTable: - case DecodeAsModel::colSelector: case DecodeAsModel::colProtocol: flags |= Qt::ItemIsEditable; break; + case DecodeAsModel::colSelector: + { + ftenum_t selector_type = get_dissector_table_selector_type(item->tableName_); + if (selector_type != FT_NONE) + flags |= Qt::ItemIsEditable; + break; + } } return flags; @@ -126,7 +134,7 @@ QVariant DecodeAsModel::data(const QModelIndex &index, int role) const if (IS_FT_STRING(selector_type)) { return tr("String"); - } else { + } else if (IS_FT_UINT(selector_type)) { QString type_desc = tr("Integer, base "); switch (get_dissector_table_param(item->tableName_)) { case BASE_OCT: @@ -142,6 +150,8 @@ QVariant DecodeAsModel::data(const QModelIndex &index, int role) const type_desc.append(tr("unknown")); } return type_desc; + } else if (selector_type == FT_NONE) { + return tr("<none>"); } } case colDefault: @@ -313,6 +323,9 @@ bool DecodeAsModel::insertRows(int row, int count, const QModelIndex &/*parent*/ } dissector = dissector_get_default_uint_handle(entry->table_name, item->selectorUint_); + } else if (selector_type == FT_NONE) { + // There is no default for an FT_NONE dissector table + dissector = NULL; } if (dissector != NULL) { @@ -437,6 +450,10 @@ QString DecodeAsModel::entryString(const gchar *table_name, gpointer value) //TODO: DCE/RPC dissector table break; + case FT_NONE: + //doesn't really matter, just avoiding the assert + return "0"; + default: g_assert_not_reached(); break; @@ -519,6 +536,12 @@ void DecodeAsModel::gatherChangedEntries(const gchar *table_name, case FT_UINT32: model->changed_uint_entries_ << UintPair(table_name, GPOINTER_TO_UINT(key)); break; + case FT_NONE: + //need to reset dissector table, so this needs to be in a changed list, + //might as well be the uint one. + model->changed_uint_entries_ << UintPair(table_name, 0); + break; + case FT_STRING: case FT_STRINGZ: case FT_UINT_STRING: @@ -597,6 +620,10 @@ void DecodeAsModel::applyChanges() byteArray = item->selectorString_.toUtf8(); selector_value = (gpointer) byteArray.constData(); break; + case FT_NONE: + //selector value is ignored, but dissector table needs to happen + selector_value = NULL; + break; default: continue; } |