Fix 'Decode As' when used with IPv6-in-IPv6 packets

Add the ability to identify an instance of the dissector table to be modified by 'Decode As' thanks to pinfo->curr_layer_num
For now only IPv6 makes use of it but it could be extended to any other protocol
Also get rid of ipv6.nxt protocol: it is not required for 'Decode As' functionality and was colliding with ipv6.nxt field

Change-Id: I3c7403c77328ad7170e13af028d178f962a2b508
Reviewed-on: https://code.wireshark.org/review/10552
Petri-Dish: Pascal Quantin <pascal.quantin@gmail.com>
Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org>
Reviewed-by: João Valverde <j@v6e.pt>
Reviewed-by: Pascal Quantin <pascal.quantin@gmail.com>
This commit is contained in:
Pascal Quantin 2015-09-16 23:58:49 +02:00
parent 608029b331
commit 1d7bcb28f9
3 changed files with 47 additions and 20 deletions

View File

@ -107,7 +107,6 @@ typedef struct {
static int ipv6_tap = -1;
static int proto_ipv6 = -1;
static int proto_ipv6_nxt = -1;
static int proto_ipv6_hopopts = -1;
static int proto_ipv6_routing = -1;
static int proto_ipv6_shim6 = -1;
@ -340,23 +339,23 @@ static expert_field ei_ipv6_invalid_header = EI_INIT;
static void ipv6_prompt(packet_info *pinfo, gchar* result)
{
g_snprintf(result, MAX_DECODE_AS_PROMPT_LEN, "IP protocol %u as",
GPOINTER_TO_UINT(p_get_proto_data(pinfo->pool, pinfo, proto_ipv6, IPV6_PROTO_VALUE)));
GPOINTER_TO_UINT(p_get_proto_data(pinfo->pool, pinfo, proto_ipv6, (pinfo->curr_layer_num<<8) | IPV6_PROTO_VALUE)));
}
static gpointer ipv6_value(packet_info *pinfo)
{
return p_get_proto_data(pinfo->pool, pinfo, proto_ipv6, IPV6_PROTO_VALUE);
return p_get_proto_data(pinfo->pool, pinfo, proto_ipv6, (pinfo->curr_layer_num<<8) | IPV6_PROTO_VALUE);
}
static void ipv6_next_header_prompt(packet_info *pinfo, gchar* result)
{
g_snprintf(result, MAX_DECODE_AS_PROMPT_LEN, "IP Next Header %u as",
GPOINTER_TO_UINT(p_get_proto_data(pinfo->pool, pinfo, proto_ipv6, IPV6_PROTO_NXT_HDR)));
GPOINTER_TO_UINT(p_get_proto_data(pinfo->pool, pinfo, proto_ipv6, (pinfo->curr_layer_num<<8) | IPV6_PROTO_NXT_HDR)));
}
static gpointer ipv6_next_header_value(packet_info *pinfo)
{
return p_get_proto_data(pinfo->pool, pinfo, proto_ipv6, IPV6_PROTO_NXT_HDR);
return p_get_proto_data(pinfo->pool, pinfo, proto_ipv6, (pinfo->curr_layer_num<<8) | IPV6_PROTO_NXT_HDR);
}
static const char* ipv6_conv_get_filter_type(conv_item_t* conv, conv_filter_type_e filter)
@ -2036,12 +2035,7 @@ dissect_ipv6(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
offset + IP6H_CTL_PLEN, 2, ENC_BIG_ENDIAN);
proto_tree_add_item(ipv6_tree, hf_ipv6_nxt, tvb, offset + IP6H_CTL_NXT, 1, ENC_NA);
}
/* Needed for Decode As */
wmem_list_append(pinfo->layers, GINT_TO_POINTER(proto_ipv6_nxt));
if (tree) {
proto_tree_add_item(ipv6_tree, hf_ipv6_hlim, tvb,
offset + IP6H_CTL_HLIM, 1, ENC_BIG_ENDIAN);
@ -2237,7 +2231,7 @@ dissect_ipv6(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
/* start of the new header (could be a extension header) */
nxt = tvb_get_guint8(tvb, offset + 6);
/* Save next header value for Decode As dialog */
p_add_proto_data(pinfo->pool, pinfo, proto_ipv6, IPV6_PROTO_NXT_HDR, GUINT_TO_POINTER((guint)nxt));
p_add_proto_data(pinfo->pool, pinfo, proto_ipv6, (pinfo->curr_layer_num<<8) | IPV6_PROTO_NXT_HDR, GUINT_TO_POINTER((guint)nxt));
offset += (int)sizeof(struct ip6_hdr);
offlg = 0;
ident = 0;
@ -2351,7 +2345,7 @@ again:
proto_item_set_len (ipv6_item, offset);
/* collect packet info */
p_add_proto_data(pinfo->pool, pinfo, proto_ipv6, IPV6_PROTO_VALUE, GUINT_TO_POINTER((guint)nxt));
p_add_proto_data(pinfo->pool, pinfo, proto_ipv6, (pinfo->curr_layer_num<<8) | IPV6_PROTO_VALUE, GUINT_TO_POINTER((guint)nxt));
tap_queue_packet(ipv6_tap, pinfo, ipv6);
if (offlg & IP6F_OFF_MASK || (ipv6_reassemble && offlg & IP6F_MORE_FRAG)) {
@ -3185,7 +3179,7 @@ proto_register_ipv6(void)
static build_valid_func ipv6_next_header_da_build_value[1] = {ipv6_next_header_value};
static decode_as_value_t ipv6_next_header_da_values = {ipv6_next_header_prompt, 1, ipv6_next_header_da_build_value};
static decode_as_t ipv6_next_header_da = {"ipv6.nxt", "IPv6 Next Header", "ipv6.nxt", 1, 0, &ipv6_next_header_da_values, NULL, NULL,
static decode_as_t ipv6_next_header_da = {"ipv6", "IPv6 Next Header", "ipv6.nxt", 1, 0, &ipv6_next_header_da_values, NULL, NULL,
decode_as_default_populate_list, decode_as_default_reset, decode_as_default_change, NULL};
module_t *ipv6_module;
@ -3197,7 +3191,6 @@ proto_register_ipv6(void)
expert_ipv6 = expert_register_protocol(proto_ipv6);
expert_register_field_array(expert_ipv6, ei, array_length(ei));
proto_ipv6_nxt = proto_register_protocol("IPv6 Next Header", "IPv6 Next Header", "ipv6.nxt");
proto_ipv6_hopopts = proto_register_protocol("IPv6 Hop-by-Hop Options", "IPv6 Hop-by-Hop", "ipv6.hopopts");
proto_ipv6_routing = proto_register_protocol("IPv6 Routing", "IPv6 Routing", "ipv6.routing_hdr");
proto_ipv6_shim6 = proto_register_protocol("IPv6 SHIM6", "SHIM6", "ipv6.shim6");

View File

@ -79,10 +79,11 @@
#define E_LIST_S_MAX E_LIST_S_TABLE
#define E_LIST_S_COLUMNS (E_LIST_S_MAX + 1)
#define E_PAGE_LIST "notebook_page_list"
#define E_PAGE_TABLE "notebook_page_table_name"
#define E_PAGE_TITLE "notebook_page_title"
#define E_PAGE_VALUE "notebook_page_value"
#define E_PAGE_LIST "notebook_page_list"
#define E_PAGE_TABLE "notebook_page_table_name"
#define E_PAGE_TITLE "notebook_page_title"
#define E_PAGE_VALUE "notebook_page_value"
#define E_PAGE_CURR_LAYER_NUM "notebook_page_curr_layer_num"
#define E_PAGE_ACTION "notebook_page_action"
@ -671,12 +672,15 @@ decode_simple (GtkWidget *notebook_pg)
/* Apply values to dissector table (stored in entry) */
for (value_loop = 0; value_loop < entry->values[requested_index].num_values; value_loop++)
{
guint8 saved_curr_layer_num = cfile.edt->pi.curr_layer_num;
cfile.edt->pi.curr_layer_num = (guint8)GPOINTER_TO_UINT(g_object_get_data(G_OBJECT(notebook_pg), E_PAGE_CURR_LAYER_NUM));
value_ptr = entry->values[requested_index].build_values[value_loop](&cfile.edt->pi);
if (abbrev != NULL && strcmp(abbrev, "(default)") == 0) {
add_reset_list = entry->reset_value(table_name, value_ptr);
} else {
add_reset_list = entry->change_value(table_name, value_ptr, &handle, abbrev);
}
cfile.edt->pi.curr_layer_num = saved_curr_layer_num;
if (add_reset_list) {
selector_type = g_new(guint,1);
@ -1214,6 +1218,7 @@ decode_add_simple_page (decode_as_t *entry)
if (entry->num_items == 1)
{
g_object_set_data(G_OBJECT(page), E_PAGE_VALUE, entry->values[0].build_values[0](&cfile.edt->pi));
g_object_set_data(G_OBJECT(page), E_PAGE_CURR_LAYER_NUM, GUINT_TO_POINTER(cfile.edt->pi.curr_layer_num));
/* Always enabled */
entry->values->label_func(&cfile.edt->pi, prompt);
@ -1303,6 +1308,9 @@ decode_add_notebook (GtkWidget *format_hb)
const char* proto_name;
GList *list_entry;
decode_as_t *entry;
guint8 saved_curr_layer_num = cfile.edt->pi.curr_layer_num;
cfile.edt->pi.curr_layer_num = 1;
/* Start a nootbook for flipping between sets of changes */
notebook = gtk_notebook_new();
@ -1332,8 +1340,11 @@ decode_add_notebook (GtkWidget *format_hb)
}
protos = wmem_list_frame_next(protos);
cfile.edt->pi.curr_layer_num++;
}
cfile.edt->pi.curr_layer_num = saved_curr_layer_num;
/* Select the last added page (selects first by default) */
/* Notebook must be visible for set_page to work. */
gtk_widget_show_all(notebook);

View File

@ -62,6 +62,13 @@ typedef struct _dissector_info_t {
Q_DECLARE_METATYPE(dissector_info_t *)
typedef struct _table_item_t {
const gchar* proto_name;
guint8 curr_layer_num;
} table_item_t;
Q_DECLARE_METATYPE(table_item_t)
DecodeAsDialog::DecodeAsDialog(QWidget *parent, capture_file *cf, bool create_new) :
QDialog(parent),
ui(new Ui::DecodeAsDialog),
@ -220,6 +227,7 @@ void DecodeAsDialog::on_decodeAsTreeWidget_itemActivated(QTreeWidgetItem *item,
if (cap_file_ && cap_file_->edt) {
bool copying = !current_text.isEmpty();
wmem_list_frame_t * protos = wmem_list_head(cap_file_->edt->pi.layers);
guint8 curr_layer_num = 1;
while (protos != NULL) {
int proto_id = GPOINTER_TO_INT(wmem_list_frame_data(protos));
const gchar * proto_name = proto_get_protocol_filter_name(proto_id);
@ -227,7 +235,10 @@ void DecodeAsDialog::on_decodeAsTreeWidget_itemActivated(QTreeWidgetItem *item,
decode_as_t *entry = (decode_as_t *) cur->data;
if (g_strcmp0(proto_name, entry->name) == 0) {
QString table_ui_name = get_dissector_table_ui_name(entry->table_name);
table_names_combo_box_->insertItem(0, table_ui_name, entry->table_name);
table_item_t table_item;
table_item.proto_name = proto_name;
table_item.curr_layer_num = curr_layer_num;
table_names_combo_box_->insertItem(0, table_ui_name, QVariant::fromValue<table_item_t>(table_item));
da_set.remove(table_ui_name);
if (!copying) {
current_text = table_ui_name;
@ -235,6 +246,7 @@ void DecodeAsDialog::on_decodeAsTreeWidget_itemActivated(QTreeWidgetItem *item,
}
}
protos = wmem_list_frame_next(protos);
curr_layer_num++;
}
}
@ -424,11 +436,21 @@ void DecodeAsDialog::tableNamesCurrentIndexChanged(const QString &text)
selector_combo_box_->clear();
QVariant variant = table_names_combo_box_->itemData(table_names_combo_box_->currentIndex());
gint8 curr_layer_num_saved = cap_file_->edt->pi.curr_layer_num;
const gchar *proto_name = NULL;
if (variant.canConvert<table_item_t>()) {
table_item_t table_item = variant.value<table_item_t>();
cap_file_->edt->pi.curr_layer_num = table_item.curr_layer_num;
proto_name = table_item.proto_name;
}
QSet<dissector_info_t *> dissector_info_set;
GList *cur;
for (cur = decode_as_list; cur; cur = cur->next) {
decode_as_t *entry = (decode_as_t *) cur->data;
if (g_strcmp0(ui_name_to_name_[text], entry->table_name) == 0) {
if ((g_strcmp0(proto_name, entry->name) == 0) &&
(g_strcmp0(ui_name_to_name_[text], entry->table_name) == 0)) {
if (cap_file_ && cap_file_->edt) {
for (uint ni = 0; ni < entry->num_items; ni++) {
if (entry->values[ni].num_values == 1) { // Skip over multi-value ("both") entries
@ -441,6 +463,7 @@ void DecodeAsDialog::tableNamesCurrentIndexChanged(const QString &text)
entry->populate_list(entry->table_name, decodeAddProtocol, &dissector_info_set);
}
}
cap_file_->edt->pi.curr_layer_num = curr_layer_num_saved;
if (selector_combo_box_->count() > 0) {
selector_combo_box_->setCurrentIndex(0);
} else {