From Michal Labedzki:

"Decode By" for Bluetooth support decoding by L2CAP service, L2CAP CID,
L2CAP PSM, RFCOMM service and RFCOMM channel.

https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=7754

svn path=/trunk/; revision=45913
This commit is contained in:
Anders Broman 2012-11-05 08:39:51 +00:00
parent 56546f1b91
commit 120dab634e
4 changed files with 206 additions and 17 deletions

View File

@ -989,7 +989,7 @@ dissect_disconnrequestresponse(tvbuff_t *tvb, int offset, packet_info *pinfo _U_
static int
dissect_b_frame(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_tree *btl2cap_tree,
guint16 psm, gboolean local_service, guint16 length, int offset)
guint16 cid, guint16 psm, gboolean local_service, guint16 length, int offset)
{
tvbuff_t *next_tvb;
@ -1013,18 +1013,21 @@ dissect_b_frame(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_tree
PROTO_ITEM_SET_GENERATED(psm_item);
/* call next dissector */
if (!dissector_try_uint(l2cap_psm_dissector_table, (guint32) psm, next_tvb, pinfo, tree)) {
/* not a known fixed PSM, try to find a registered service to a dynamic PSM */
if ((service == NULL) || !dissector_try_uint(l2cap_service_dissector_table, *service, next_tvb, pinfo, tree)) {
/* unknown protocol. declare as data */
proto_tree_add_item(btl2cap_tree, hf_btl2cap_payload, tvb, offset, length, ENC_NA);
if (!dissector_try_uint(l2cap_cid_dissector_table, (guint32) cid, next_tvb, pinfo, tree)) {
if (!dissector_try_uint(l2cap_psm_dissector_table, (guint32) psm, next_tvb, pinfo, tree)) {
/* not a known fixed PSM, try to find a registered service to a dynamic PSM */
if ((service == NULL) || !dissector_try_uint(l2cap_service_dissector_table, *service, next_tvb, pinfo, tree)) {
/* unknown protocol. declare as data */
proto_tree_add_item(btl2cap_tree, hf_btl2cap_payload, tvb, offset, length, ENC_NA);
}
}
}
offset += tvb_length_remaining(tvb, offset);
}
else {
proto_tree_add_item(btl2cap_tree, hf_btl2cap_payload, tvb, offset, length, ENC_NA);
offset += tvb_length_remaining(tvb, offset);
} else {
if (!dissector_try_uint(l2cap_cid_dissector_table, (guint32) cid, next_tvb, pinfo, tree)) {
proto_tree_add_item(btl2cap_tree, hf_btl2cap_payload, tvb, offset, length, ENC_NA);
offset += tvb_length_remaining(tvb, offset);
}
}
return offset;
}
@ -1493,7 +1496,7 @@ dissect_btl2cap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
else
config_data = &(psm_data->out);
if (config_data->mode == 0) {
dissect_b_frame(tvb, pinfo, tree, btl2cap_tree, psm, psm_data->local_service, length, offset);
dissect_b_frame(tvb, pinfo, tree, btl2cap_tree, cid, psm, psm_data->local_service, length, offset);
} else {
control = tvb_get_letohs(tvb, offset);
if (control & 0x1) {
@ -1504,7 +1507,7 @@ dissect_btl2cap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
}
} else {
psm = 0;
dissect_b_frame(tvb, pinfo, tree, btl2cap_tree, psm, FALSE, length, offset);
dissect_b_frame(tvb, pinfo, tree, btl2cap_tree, cid, psm, FALSE, length, offset);
}
}
pinfo->private_data = pd_save;

View File

@ -788,6 +788,10 @@ proto_reg_handoff_btobex(void)
xml_handle = find_dissector("xml");
data_handle = find_dissector("data");
dissector_add_handle("btrfcomm.channel", btobex_handle);
dissector_add_handle("btl2cap.psm", btobex_handle);
dissector_add_handle("btl2cap.cid", btobex_handle);
}
/*

View File

@ -1000,6 +1000,7 @@ proto_reg_handoff_btrfcomm(void)
btrfcomm_handle = find_dissector("btrfcomm");
dissector_add_uint("btl2cap.psm", BTL2CAP_PSM_RFCOMM, btrfcomm_handle);
dissector_add_handle("btl2cap.cid", btrfcomm_handle);
data_handle = find_dissector("data");

View File

@ -270,6 +270,9 @@ struct dissector_table {
int base;
};
GHashTable *value_entry_table = NULL;
/*
* A callback function to changed a dissector_handle if matched
* This is used when iterating a dissector table
@ -1815,6 +1818,98 @@ decode_add_sctp_page (const gchar *prompt, const gchar *table_name)
return(page);
}
static void
decode_bluetooth(GtkWidget *notebook_pg)
{
#ifdef DEBUG
gchar *string;
#endif
GtkWidget *list;
GtkTreeSelection *selection;
GtkTreeModel *model;
GtkTreeIter iter;
gchar *table_name;
guint value;
dissector_handle_t handle;
gchar *abbrev;
guint *value_type;
list = g_object_get_data(G_OBJECT(notebook_pg), E_PAGE_LIST);
if (requested_action == E_DECODE_NO)
gtk_tree_selection_unselect_all(gtk_tree_view_get_selection(GTK_TREE_VIEW(list)));
#ifdef DEBUG
string = g_object_get_data(G_OBJECT(notebook_pg), E_PAGE_TITLE);
decode_debug(GTK_TREE_VIEW(list), string);
#endif
table_name = g_object_get_data(G_OBJECT(notebook_pg), E_PAGE_TABLE);
selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(list));
if (gtk_tree_selection_get_selected(selection, &model, &iter) == FALSE)
{
abbrev = NULL;
handle = NULL;
} else {
gtk_tree_model_get(model, &iter, E_LIST_S_PROTO_NAME, &abbrev,
E_LIST_S_TABLE+1, &handle, -1);
}
value = strtol(gtk_entry_get_text((GtkEntry *) g_hash_table_lookup(value_entry_table, table_name)), NULL, 0);
if (abbrev != NULL && strcmp(abbrev, "(default)") == 0) {
dissector_reset_uint(table_name, value);
} else {
dissector_change_uint(table_name, value, handle);
}
value_type = g_malloc(sizeof(value_type));
*value_type = value;
decode_build_reset_list(g_strdup(table_name), FT_UINT32, value_type, NULL, NULL);
g_free(abbrev);
}
static GtkWidget *
decode_add_bluetooth_page(const gchar *prompt, const gchar *table_name, const char *value)
{
GtkWidget *page;
GtkWidget *label;
GtkWidget *scrolled_window;
GtkWidget *value_entry = NULL;
const char *empty = "";
if (value == NULL)
value = empty;
page = ws_gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 5, FALSE);
g_object_set_data(G_OBJECT(page), E_PAGE_ACTION, decode_bluetooth);
g_object_set_data(G_OBJECT(page), E_PAGE_TABLE, (gchar *) table_name);
g_object_set_data(G_OBJECT(page), E_PAGE_TITLE, (gchar *) prompt);
label = gtk_label_new(prompt);
gtk_box_pack_start(GTK_BOX(page), label, TRUE, TRUE, 0);
value_entry = g_hash_table_lookup(value_entry_table, table_name);
if (!value_entry) {
value_entry = gtk_entry_new();
g_hash_table_insert(value_entry_table, (gchar *) table_name, value_entry);
}
gtk_entry_set_text((GtkEntry *) value_entry, value);
gtk_box_pack_start(GTK_BOX(page), value_entry, TRUE, TRUE, 0);
label = gtk_label_new("as");
gtk_box_pack_start(GTK_BOX(page), label, TRUE, TRUE, 0);
decode_dimmable = g_slist_prepend(decode_dimmable, label);
scrolled_window = decode_add_simple_menu(page, table_name);
gtk_box_pack_start(GTK_BOX(page), scrolled_window, TRUE, TRUE, 0);
decode_dimmable = g_slist_prepend(decode_dimmable, scrolled_window);
return(page);
}
/*
* This routine indicates whether we'd actually have any pages in the
@ -1827,7 +1922,9 @@ decode_as_ok(void)
return (cfile.edt->pi.ethertype != G_MAXINT) || cfile.edt->pi.ipproto ||
cfile.edt->pi.ptype == PT_TCP || cfile.edt->pi.ptype == PT_UDP ||
cfile.edt->pi.mpls_label ||
cfile.cd_t == WTAP_FILE_BER;
cfile.cd_t == WTAP_FILE_BER ||
wtap_file_encap(cfile.wth) == WTAP_ENCAP_BLUETOOTH_H4 ||
wtap_file_encap(cfile.wth) == WTAP_ENCAP_BLUETOOTH_H4_WITH_PHDR;
}
@ -1897,6 +1994,7 @@ decode_add_notebook (GtkWidget *format_hb)
page = NULL;
break;
}
if (page != NULL) {
label = gtk_label_new("Transport");
gtk_notebook_append_page(GTK_NOTEBOOK(notebook), page, label);
@ -1916,11 +2014,94 @@ decode_add_notebook (GtkWidget *format_hb)
g_object_set_data(G_OBJECT(decode_w), E_PAGE_ASN1, page);
}
/* Select the last added page (selects first by default) */
/* Notebook must be visible for set_page to work. */
gtk_widget_show_all(notebook);
gtk_notebook_set_current_page(GTK_NOTEBOOK(notebook), -1);
if (wtap_file_encap(cfile.wth) == WTAP_ENCAP_BLUETOOTH_H4 ||
wtap_file_encap(cfile.wth) == WTAP_ENCAP_BLUETOOTH_H4_WITH_PHDR) {
gint page_l2cap_service;
gint page_l2cap_cid;
gint page_l2cap_psm;
gint page_rfcomm_channel;
gint page_rfcomm_service;
header_field_info *hfinfo;
GPtrArray *ga;
guint i;
field_info *v;
const gchar *cid = NULL;
const gchar *psm = NULL;
const gchar *channel = NULL;
gboolean have_rfcomm = FALSE;
ga = proto_all_finfos(cfile.edt->tree);
for (i = 0; i < ga->len; i += 1) {
v = g_ptr_array_index (ga, i);
hfinfo = v->hfinfo;
if (g_strcmp0(hfinfo->abbrev, "btl2cap.cid") == 0) {
cid = get_node_field_value(v, cfile.edt);
} else if (g_strcmp0(hfinfo->abbrev, "btl2cap.psm") == 0) {
psm = get_node_field_value(v, cfile.edt);
} else if (g_strcmp0(hfinfo->abbrev, "btrfcomm.channel") == 0) {
channel = get_node_field_value(v, cfile.edt);
}
if (have_rfcomm == FALSE && g_str_has_prefix(hfinfo->abbrev, "btrfcommm")) {
have_rfcomm = TRUE;
}
}
value_entry_table = g_hash_table_new(g_str_hash, g_str_equal);
page = decode_add_bluetooth_page("L2CAP SERVICE", "btl2cap.service", NULL);
if (page != NULL) {
label = gtk_label_new("L2CAP SERVICE");
page_l2cap_service = gtk_notebook_append_page(GTK_NOTEBOOK(notebook), page, label);
}
page = decode_add_bluetooth_page("L2CAP CID", "btl2cap.cid", cid);
if (page != NULL) {
label = gtk_label_new("L2CAP CID");
page_l2cap_cid = gtk_notebook_append_page(GTK_NOTEBOOK(notebook), page, label);
}
page = decode_add_bluetooth_page("L2CAP PSM", "btl2cap.psm", psm);
if (page != NULL) {
label = gtk_label_new("L2CAP PSM");
page_l2cap_psm = gtk_notebook_append_page(GTK_NOTEBOOK(notebook), page, label);
}
page = decode_add_bluetooth_page("RFCOMM Channel", "btrfcomm.channel", channel);
if (page != NULL) {
label = gtk_label_new("RFCOMM Channel");
page_rfcomm_channel = gtk_notebook_append_page(GTK_NOTEBOOK(notebook), page, label);
}
page = decode_add_bluetooth_page("RFCOMM SERVICE", "btrfcomm.service", NULL);
if (page != NULL) {
label = gtk_label_new("RFCOMM SERVICE");
page_rfcomm_service = gtk_notebook_append_page(GTK_NOTEBOOK(notebook), page, label);
}
page = NULL;
/* Notebook must be visible for set_page to work. */
gtk_widget_show_all(notebook);
if (channel)
gtk_notebook_set_current_page(GTK_NOTEBOOK(notebook), page_rfcomm_channel);
else if (psm)
gtk_notebook_set_current_page(GTK_NOTEBOOK(notebook), page_l2cap_psm);
else if (cid)
gtk_notebook_set_current_page(GTK_NOTEBOOK(notebook), page_l2cap_cid);
else if (have_rfcomm)
gtk_notebook_set_current_page(GTK_NOTEBOOK(notebook), page_rfcomm_service);
else
gtk_notebook_set_current_page(GTK_NOTEBOOK(notebook), page_l2cap_service);
} else {
/* Select the last added page (selects first by default) */
/* Notebook must be visible for set_page to work. */
gtk_widget_show_all(notebook);
gtk_notebook_set_current_page(GTK_NOTEBOOK(notebook), -1);
}
}