summaryrefslogtreecommitdiff
path: root/epan/dissectors/packet-btobex.c
diff options
context:
space:
mode:
authorKovarththanan Rajaratnam <kovarththanan.rajaratnam@gmail.com>2011-01-02 08:13:40 +0000
committerKovarththanan Rajaratnam <kovarththanan.rajaratnam@gmail.com>2011-01-02 08:13:40 +0000
commit46dd093b945d4bc088741e22b9c0a87024fc6fe4 (patch)
tree5752f0f5c73ffd81be6abe6c2331f8e2ce71dbf5 /epan/dissectors/packet-btobex.c
parent388453b79dcc220ced63cd854924cd0ad1411077 (diff)
downloadwireshark-46dd093b945d4bc088741e22b9c0a87024fc6fe4.tar.gz
From Allan M. Madsen via. bug 5445:
Bluetooth profiles and protocols above RFCOMM and L2CAP can not be dissected correctly because the required information (server channel and dynamic PSM value mappings to services/profiles) about the type of data carried in the payload is not available. RFCOMM is currently hardcoded to handoff all payload data to the obex dissector though it may carry e.g. handsfree, dial-up networking or serial port profile related data. The patch consists of modifcations to the following dissectors: btsdp: Extraction of RFCOMM server channel and L2CAP dynamic PSM with service mapping is provided to RFCOMM and L2CAP through a tap interface. In addition, the packet list info is beautyfied and extended with more details for better overview. btl2cap: Adds a new dissector table with services and dynamic PSM mapping which is filled by a tap listner catching the info from btsdp. More info added to packet list. btrfcomm: Adds a new dissector table with services and server channel mapping which is filled by a tap listner catching the info from btsdp. Dissectors for handsfree, dial-up netorking and serial port profiles (all based on RFCOMM) are also added. btobex: Registers several obex based profiles (e.g. obex push, file transfer, basic printing etc.) in both RFCOMM and L2CAP. Some cleanup. svn path=/trunk/; revision=35323
Diffstat (limited to 'epan/dissectors/packet-btobex.c')
-rw-r--r--epan/dissectors/packet-btobex.c985
1 files changed, 498 insertions, 487 deletions
diff --git a/epan/dissectors/packet-btobex.c b/epan/dissectors/packet-btobex.c
index c5890439c9..2c807916ac 100644
--- a/epan/dissectors/packet-btobex.c
+++ b/epan/dissectors/packet-btobex.c
@@ -1,7 +1,7 @@
/* packet-btobex.c
- * Routines for the Bluetooth OBEX dissection
+ * Routines for Bluetooth OBEX dissection
*
- * Allan M. Madsen 2010
+ * Copyright 2010, Allan M. Madsen
*
* $Id$
*
@@ -36,6 +36,7 @@
#include <epan/emem.h>
#include <epan/reassemble.h>
#include "packet-btl2cap.h"
+#include "packet-btsdp.h"
/* Initialize the protocol and registered fields */
static int proto_btobex = -1;
@@ -55,7 +56,6 @@ static int hf_hdr_val_unicode = -1;
static int hf_hdr_val_byte_seq = -1;
static int hf_hdr_val_byte = -1;
static int hf_hdr_val_long = -1;
-static int hf_data = -1;
/* ************************************************************************* */
/* Header values for reassembly */
@@ -209,7 +209,7 @@ static const value_string header_id_vals[] = {
{ 0x4f, "Object Class" },
{ 0xc0, "Count" },
{ 0xc3, "Length" },
- { 0xC4, "Time" },
+ { 0xc4, "Time" },
{ 0xcb, "Connection Id" },
{ 0x30, "User Defined" },
{ 0x31, "User Defined" },
@@ -230,521 +230,532 @@ static const value_string header_id_vals[] = {
{ 0, NULL }
};
-static void defragment_init(void)
+static void
+defragment_init(void)
{
- fragment_table_init(&fragment_table);
- reassembled_table_init(&reassembled_table);
+ fragment_table_init(&fragment_table);
+ reassembled_table_init(&reassembled_table);
}
-static int is_ascii_str(const guint8 *str, int length)
+static int
+is_ascii_str(const guint8 *str, int length)
{
- int i;
+ int i;
- if( (length < 1) || (str[length-1] != '\0') )
- return 0;
+ if( (length < 1) || (str[length-1] != '\0') )
+ return 0;
- for(i=0; i<length-1; i++)
- {
- if( (str[i] < 0x20) && (str[i] != 0x0a) ) /* not strict ascii */
- break;
- }
+ for(i=0; i<length-1; i++) {
+ if( (str[i] < 0x20) && (str[i] != 0x0a) ) /* not strict ascii */
+ break;
+ }
- if(i<(length-1))
- return 0;
+ if(i<(length-1))
+ return 0;
- return 1;
+ return 1;
}
-static int display_unicode_string(tvbuff_t *tvb, proto_tree *tree, int offset, char **data)
+static int
+display_unicode_string(tvbuff_t *tvb, proto_tree *tree, int offset, char **data)
{
- char *str, *p;
- int len;
- int charoffset;
- guint16 character;
-
- /* display a unicode string from the tree and return new offset */
- /*
- * Get the length of the string.
- */
- len = 0;
- while ((character = tvb_get_ntohs(tvb, offset + len)) != '\0')
- len += 2;
- len += 2; /* count the '\0' too */
-
- /*
- * Allocate a buffer for the string; "len" is the length in
- * bytes, not the length in characters.
- */
- str = ep_alloc(len/2);
-
- /* - this assumes the string is just ISO 8859-1 */
- charoffset = offset;
- p = str;
- while ((character = tvb_get_ntohs(tvb, charoffset)) != '\0') {
- *p++ = (char) character;
- charoffset += 2;
- }
- *p = '\0';
-
- if(!is_ascii_str(str, len/2))
- {
- *str = '\0';
- }
-
- proto_tree_add_string(tree, hf_hdr_val_unicode, tvb, offset, len, str);
-
- if (data)
- *data = str;
-
- return offset+len;
+ char *str, *p;
+ int len;
+ int charoffset;
+ guint16 character;
+
+ /* display a unicode string from the tree and return new offset */
+ /*
+ * Get the length of the string.
+ */
+ len = 0;
+ while ((character = tvb_get_ntohs(tvb, offset + len)) != '\0')
+ len += 2;
+
+ len += 2; /* count the '\0' too */
+
+ /*
+ * Allocate a buffer for the string; "len" is the length in
+ * bytes, not the length in characters.
+ */
+ str = ep_alloc(len/2);
+
+ /* - this assumes the string is just ISO 8859-1 */
+ charoffset = offset;
+ p = str;
+ while ((character = tvb_get_ntohs(tvb, charoffset)) != '\0') {
+ *p++ = (char) character;
+ charoffset += 2;
+ }
+ *p = '\0';
+
+ if(!is_ascii_str(str, len/2)) {
+ *str = '\0';
+ }
+
+ proto_tree_add_string(tree, hf_hdr_val_unicode, tvb, offset, len, str);
+
+ if (data)
+ *data = str;
+
+ return offset+len;
}
static int
dissect_headers(proto_tree *tree, tvbuff_t *tvb, int offset, packet_info *pinfo)
{
- proto_tree *hdrs_tree=NULL;
- proto_item *hdrs=NULL;
- proto_tree *hdr_tree=NULL;
- proto_item *hdr=NULL;
- proto_item *handle_item;
- gint item_length = -1;
- guint8 hdr_id, i;
- const guint8 *ptr;
-
- if(tvb_length_remaining(tvb, offset)>0)
- {
- hdrs = proto_tree_add_text(tree, tvb, offset, item_length, "Headers");
- hdrs_tree=proto_item_add_subtree(hdrs, ett_btobex_hdrs);
- }
- else
- {
- return offset;
- }
-
- while(tvb_length_remaining(tvb, offset)>0)
- {
- hdr_id = tvb_get_guint8(tvb, offset);
-
- switch(0xC0 & hdr_id)
- {
- case 0x00:
- item_length = tvb_get_ntohs(tvb, offset+1);
- break;
- case 0x40: /* byte sequence */
- item_length = tvb_get_ntohs(tvb, offset+1);
- break;
- case 0x80: /* 1 byte */
- item_length = 2;
- break;
- case 0xc0: /* 4 bytes */
- item_length = 5;
- break;
- }
-
- hdr = proto_tree_add_text(hdrs_tree, tvb, offset, item_length, "%s", val_to_str(hdr_id, header_id_vals, "Unknown"));
- hdr_tree=proto_item_add_subtree(hdr, ett_btobex_hdr);
-
- proto_tree_add_item(hdr_tree, hf_hdr_id, tvb, offset, 1, FALSE);
-
- offset++;
-
- switch(0xC0 & hdr_id)
- {
- case 0x00: /* null terminated unicode */
- {
- proto_tree_add_item(hdr_tree, hf_hdr_length, tvb, offset, 2, FALSE);
- offset += 2;
-
- if( (item_length - 3) > 0 )
- {
- char *str;
- display_unicode_string(tvb, hdr_tree, offset, &str);
-
- proto_item_append_text(hdr_tree, " (\"%s\")", str);
-
- col_append_fstr(pinfo->cinfo, COL_INFO, " \"%s\"", str);
- }
- else
- {
- col_append_str(pinfo->cinfo, COL_INFO, " \"\"");
- }
-
- offset += item_length - 3;
- }
- break;
- case 0x40: /* byte sequence */
- proto_tree_add_item(hdr_tree, hf_hdr_length, tvb, offset, 2, FALSE);
- offset += 2;
-
- handle_item = proto_tree_add_item(hdr_tree, hf_hdr_val_byte_seq, tvb, offset, item_length - 3, FALSE);
-
- if( ((hdr_id == 0x46) || (hdr_id == 0x4a)) && (item_length == 19) ) /* target or who */
- {
- ptr = tvb_get_ptr(tvb, offset, item_length - 3);
- for( i=0; target_vals[i].strptr != NULL; i++)
- {
- if( memcmp(ptr, target_vals[i].value, 16) == 0 )
- {
- proto_item_append_text(handle_item, ": %s", target_vals[i].strptr);
-
- proto_item_append_text(hdr_tree, " (%s)", target_vals[i].strptr);
-
- col_append_fstr(pinfo->cinfo, COL_INFO, " - %s", target_vals[i].strptr);
- }
- }
- }
-
- if( !tvb_strneql(tvb, offset, "<?xml", 5) )
- {
- tvbuff_t* next_tvb = tvb_new_subset(tvb, offset, -1, -1);
-
- call_dissector(xml_handle, next_tvb, pinfo, tree);
- }
- else if(is_ascii_str(tvb_get_ptr(tvb, offset,item_length - 3), item_length - 3))
- {
- proto_item_append_text(hdr_tree, " (\"%s\")", tvb_get_ptr(tvb, offset,item_length - 3));
-
- col_append_fstr(pinfo->cinfo, COL_INFO, " \"%s\"", tvb_get_ptr(tvb, offset,item_length - 3));
- }
-
- offset += item_length - 3;
- break;
- case 0x80: /* 1 byte */
- proto_item_append_text(hdr_tree, " (%i)", tvb_get_ntohl(tvb, offset));
- proto_tree_add_item(hdr_tree, hf_hdr_val_byte, tvb, offset, 1, FALSE);
- offset++;
- break;
- case 0xc0: /* 4 bytes */
- proto_item_append_text(hdr_tree, " (%i)", tvb_get_ntohl(tvb, offset));
- proto_tree_add_item(hdr_tree, hf_hdr_val_long, tvb, offset, 4, FALSE);
- offset += 4;
- break;
- default:
- break;
- }
-
- }
-
- return offset;
+ proto_tree *hdrs_tree=NULL;
+ proto_item *hdrs=NULL;
+ proto_tree *hdr_tree=NULL;
+ proto_item *hdr=NULL;
+ proto_item *handle_item;
+ gint item_length = -1;
+ guint8 hdr_id, i;
+ const guint8 *ptr;
+
+ if(tvb_length_remaining(tvb, offset)>0) {
+ hdrs = proto_tree_add_text(tree, tvb, offset, item_length, "Headers");
+ hdrs_tree=proto_item_add_subtree(hdrs, ett_btobex_hdrs);
+ }
+ else {
+ return offset;
+ }
+
+ while(tvb_length_remaining(tvb, offset)>0) {
+ hdr_id = tvb_get_guint8(tvb, offset);
+
+ switch(0xC0 & hdr_id)
+ {
+ case 0x00: /* null terminated unicode */
+ item_length = tvb_get_ntohs(tvb, offset+1);
+ break;
+ case 0x40: /* byte sequence */
+ item_length = tvb_get_ntohs(tvb, offset+1);
+ break;
+ case 0x80: /* 1 byte */
+ item_length = 2;
+ break;
+ case 0xc0: /* 4 bytes */
+ item_length = 5;
+ break;
+ }
+
+ hdr = proto_tree_add_text(hdrs_tree, tvb, offset, item_length, "%s", val_to_str(hdr_id, header_id_vals, "Unknown"));
+ hdr_tree=proto_item_add_subtree(hdr, ett_btobex_hdr);
+
+ proto_tree_add_item(hdr_tree, hf_hdr_id, tvb, offset, 1, FALSE);
+
+ offset++;
+
+ switch(0xC0 & hdr_id)
+ {
+ case 0x00: /* null terminated unicode */
+ {
+ proto_tree_add_item(hdr_tree, hf_hdr_length, tvb, offset, 2, FALSE);
+ offset += 2;
+
+ if( (item_length - 3) > 0 ) {
+ char *str;
+
+ display_unicode_string(tvb, hdr_tree, offset, &str);
+ proto_item_append_text(hdr_tree, " (\"%s\")", str);
+ col_append_fstr(pinfo->cinfo, COL_INFO, " \"%s\"", str);
+ }
+ else {
+ col_append_str(pinfo->cinfo, COL_INFO, " \"\"");
+ }
+
+ offset += item_length - 3;
+ }
+ break;
+ case 0x40: /* byte sequence */
+ proto_tree_add_item(hdr_tree, hf_hdr_length, tvb, offset, 2, FALSE);
+ offset += 2;
+
+ handle_item = proto_tree_add_item(hdr_tree, hf_hdr_val_byte_seq, tvb, offset, item_length - 3, FALSE);
+
+ if( ((hdr_id == 0x46) || (hdr_id == 0x4a)) && (item_length == 19) ) { /* target or who */
+ ptr = tvb_get_ptr(tvb, offset, item_length - 3);
+ for( i=0; target_vals[i].strptr != NULL; i++) {
+ if( memcmp(ptr, target_vals[i].value, 16) == 0 ) {
+ proto_item_append_text(handle_item, ": %s", target_vals[i].strptr);
+ proto_item_append_text(hdr_tree, " (%s)", target_vals[i].strptr);
+ col_append_fstr(pinfo->cinfo, COL_INFO, " - %s", target_vals[i].strptr);
+ }
+ }
+ }
+
+ if( !tvb_strneql(tvb, offset, "<?xml", 5) )
+ {
+ tvbuff_t* next_tvb = tvb_new_subset(tvb, offset, -1, -1);
+
+ call_dissector(xml_handle, next_tvb, pinfo, tree);
+ }
+ else if(is_ascii_str(tvb_get_ptr(tvb, offset,item_length - 3), item_length - 3))
+ {
+ proto_item_append_text(hdr_tree, " (\"%s\")", tvb_get_ptr(tvb, offset,item_length - 3));
+ col_append_fstr(pinfo->cinfo, COL_INFO, " \"%s\"", tvb_get_ptr(tvb, offset,item_length - 3));
+ }
+
+ offset += item_length - 3;
+ break;
+ case 0x80: /* 1 byte */
+ proto_item_append_text(hdr_tree, " (%i)", tvb_get_ntohl(tvb, offset));
+ proto_tree_add_item(hdr_tree, hf_hdr_val_byte, tvb, offset, 1, FALSE);
+ offset++;
+ break;
+ case 0xc0: /* 4 bytes */
+ proto_item_append_text(hdr_tree, " (%i)", tvb_get_ntohl(tvb, offset));
+ proto_tree_add_item(hdr_tree, hf_hdr_val_long, tvb, offset, 4, FALSE);
+ offset += 4;
+ break;
+ default:
+ break;
+ }
+ }
+
+ return offset;
}
static void
dissect_btobex(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
- proto_item *ti;
- proto_tree *st;
- fragment_data *frag_msg = NULL;
- gboolean save_fragmented, complete;
- tvbuff_t* new_tvb = NULL;
- tvbuff_t* next_tvb = NULL;
- guint32 no_of_segments = 0;
- int offset=0;
-
- save_fragmented = pinfo->fragmented;
-
- frag_msg = NULL;
- complete = FALSE;
-
- if( fragment_get(pinfo, pinfo->p2p_dir, fragment_table) )
- {
- /* not the first fragment */
- frag_msg = fragment_add_seq_next(tvb, 0, pinfo, pinfo->p2p_dir,
- fragment_table, reassembled_table, tvb_length(tvb), TRUE);
-
- new_tvb = process_reassembled_data(tvb, 0, pinfo,
- "Reassembled Obex packet", frag_msg, &btobex_frag_items, NULL, tree);
-
- if(frag_msg != NULL) /* last fragment */
- complete = TRUE;
-
- }
- else
- {
- if(tvb_length(tvb) < tvb_get_ntohs(tvb, offset+1))
- {
- /* first fragment in a sequence */
- no_of_segments = tvb_get_ntohs(tvb, offset+1)/tvb_length(tvb);
- if ( tvb_get_ntohs(tvb, offset+1) > (no_of_segments * tvb_length(tvb)))
- no_of_segments++;
-
- frag_msg = fragment_add_seq_next(tvb, 0, pinfo, pinfo->p2p_dir,
- fragment_table, reassembled_table, tvb_length(tvb), TRUE);
-
- fragment_set_tot_len(pinfo, pinfo->p2p_dir, fragment_table, no_of_segments-1);
-
- new_tvb = process_reassembled_data(tvb, 0, pinfo,
- "Reassembled Obex packet", frag_msg, &btobex_frag_items, NULL, tree);
-
- pinfo->fragmented = TRUE;
- }
- else if( tvb_length(tvb) == tvb_get_ntohs(tvb, offset+1) )
- {
- /* non-fragmented */
- complete = TRUE;
- pinfo->fragmented = FALSE;
- }
- }
-
- if (new_tvb) { /* take it all */
- next_tvb = new_tvb;
- complete = TRUE;
- } else { /* make a new subset */
- next_tvb = tvb_new_subset(tvb, offset, -1, -1);
- }
-
- if( complete )
- {
- guint8 code;
-
- /* fully dissectable packet ready */
- col_set_str(pinfo->cinfo, COL_PROTOCOL, "OBEX");
-
- ti = proto_tree_add_item(tree, proto_btobex, next_tvb, 0, -1, FALSE);
- st = proto_item_add_subtree(ti, ett_btobex);
-
- /* op/response code */
- code = tvb_get_guint8(next_tvb, offset) & BTOBEX_CODE_VALS_MASK;
-
- col_add_fstr(pinfo->cinfo, COL_INFO, "%s %s",
- pinfo->p2p_dir==P2P_DIR_SENT?"Sent":"Rcvd",
- val_to_str(code, code_vals, "Unknown"));
-
- if( (code < BTOBEX_CODE_VALS_CONTINUE) || (code == BTOBEX_CODE_VALS_ABORT))
- {
- proto_tree_add_item(st, hf_opcode, next_tvb, offset, 1, FALSE);
- last_opcode[pinfo->p2p_dir] = code;
- }
- else
- {
- proto_tree_add_item(st, hf_response_code, next_tvb, offset, 1, FALSE);
- }
- proto_tree_add_item(st, hf_final_flag, next_tvb, offset, 1, FALSE);
- offset++;
-
- /* length */
- proto_tree_add_item(st, hf_length, next_tvb, offset, 2, FALSE);
- offset += 2;
-
- switch(code)
- {
- case BTOBEX_CODE_VALS_CONNECT:
- proto_tree_add_item(st, hf_version, next_tvb, offset, 1, FALSE);
- offset++;
-
- proto_tree_add_item(st, hf_flags, next_tvb, offset, 1, FALSE);
- offset++;
-
- proto_tree_add_item(st, hf_max_pkt_len, next_tvb, offset, 2, FALSE);
- offset += 2;
- break;
-
- case BTOBEX_CODE_VALS_PUT:
- case BTOBEX_CODE_VALS_GET:
- col_append_fstr(pinfo->cinfo, COL_INFO, " %s",
- (tvb_get_guint8(next_tvb, offset) & 0x80)==0x80?"final":"continue");
- break;
-
- case BTOBEX_CODE_VALS_SET_PATH:
- proto_tree_add_item(st, hf_flags, next_tvb, offset, 1, FALSE);
- proto_tree_add_item(st, hf_set_path_flags_0, next_tvb, offset, 1, FALSE);
- proto_tree_add_item(st, hf_set_path_flags_1, next_tvb, offset, 1, FALSE);
- offset++;
-
- proto_tree_add_item(st, hf_constants, next_tvb, offset, 1, FALSE);
- offset++;
- break;
-
- case BTOBEX_CODE_VALS_DISCONNECT:
- case BTOBEX_CODE_VALS_ABORT:
- break;
-
- default:
- {
- guint8 response_opcode = last_opcode[(pinfo->p2p_dir + 1) & 0x01];
-
- if(response_opcode == BTOBEX_CODE_VALS_CONNECT)
- {
- proto_tree_add_item(st, hf_version, next_tvb, offset, 1, FALSE);
- offset++;
-
- proto_tree_add_item(st, hf_flags, next_tvb, offset, 1, FALSE);
- offset++;
-
- proto_tree_add_item(st, hf_max_pkt_len, next_tvb, offset, 2, FALSE);
- offset += 2;
- }
- }
- break;
- }
-
- offset = dissect_headers(st, next_tvb, offset, pinfo);
- }
- else
- {
- /* packet fragment */
- col_add_fstr(pinfo->cinfo, COL_INFO, "%s Obex fragment",
- pinfo->p2p_dir==P2P_DIR_SENT?"Sent":"Rcvd");
-
- call_dissector(data_handle, next_tvb, pinfo, tree);
- }
-
- pinfo->fragmented = save_fragmented;
+ proto_item *ti;
+ proto_tree *st;
+ fragment_data *frag_msg = NULL;
+ gboolean save_fragmented, complete;
+ tvbuff_t* new_tvb = NULL;
+ tvbuff_t* next_tvb = NULL;
+ guint32 no_of_segments = 0;
+ int offset=0;
+
+ save_fragmented = pinfo->fragmented;
+
+ frag_msg = NULL;
+ complete = FALSE;
+
+ if( fragment_get(pinfo, pinfo->p2p_dir, fragment_table) ) {
+ /* not the first fragment */
+ frag_msg = fragment_add_seq_next(tvb, 0, pinfo, pinfo->p2p_dir,
+ fragment_table, reassembled_table, tvb_length(tvb), TRUE);
+
+ new_tvb = process_reassembled_data(tvb, 0, pinfo,
+ "Reassembled Obex packet", frag_msg, &btobex_frag_items, NULL, tree);
+
+ pinfo->fragmented = TRUE;
+ }
+ else {
+ if(tvb_length(tvb) < tvb_get_ntohs(tvb, offset+1)) {
+ /* first fragment in a sequence */
+ no_of_segments = tvb_get_ntohs(tvb, offset+1)/tvb_length(tvb);
+ if ( tvb_get_ntohs(tvb, offset+1) > (no_of_segments * tvb_length(tvb)))
+ no_of_segments++;
+
+ frag_msg = fragment_add_seq_next(tvb, 0, pinfo, pinfo->p2p_dir,
+ fragment_table, reassembled_table, tvb_length(tvb), TRUE);
+
+ fragment_set_tot_len(pinfo, pinfo->p2p_dir, fragment_table, no_of_segments-1);
+
+ new_tvb = process_reassembled_data(tvb, 0, pinfo,
+ "Reassembled Obex packet", frag_msg, &btobex_frag_items, NULL, tree);
+
+ pinfo->fragmented = TRUE;
+ }
+ else if( tvb_length(tvb) == tvb_get_ntohs(tvb, offset+1) ) {
+ /* non-fragmented */
+ complete = TRUE;
+ pinfo->fragmented = FALSE;
+ }
+ }
+
+ if (new_tvb) { /* take it all */
+ next_tvb = new_tvb;
+ complete = TRUE;
+ }
+ else { /* make a new subset */
+ next_tvb = tvb_new_subset(tvb, offset, -1, -1);
+ }
+
+ if( complete ) {
+ guint8 code, final_flag;
+
+ /* fully dissectable packet ready */
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "OBEX");
+
+ ti = proto_tree_add_item(tree, proto_btobex, next_tvb, 0, -1, FALSE);
+ st = proto_item_add_subtree(ti, ett_btobex);
+
+ /* op/response code */
+ code = tvb_get_guint8(next_tvb, offset) & BTOBEX_CODE_VALS_MASK;
+ final_flag = tvb_get_guint8(next_tvb, offset) & 0x80;
+
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s %s",
+ pinfo->p2p_dir==P2P_DIR_SENT?"Sent":"Rcvd",
+ val_to_str(code, code_vals, "Unknown"));
+
+ if( (code < BTOBEX_CODE_VALS_CONTINUE) || (code == BTOBEX_CODE_VALS_ABORT)) {
+ proto_tree_add_item(st, hf_opcode, next_tvb, offset, 1, FALSE);
+ last_opcode[pinfo->p2p_dir] = code;
+ }
+ else {
+ proto_tree_add_item(st, hf_response_code, next_tvb, offset, 1, FALSE);
+ }
+ proto_tree_add_item(st, hf_final_flag, next_tvb, offset, 1, FALSE);
+ offset++;
+
+ /* length */
+ proto_tree_add_item(st, hf_length, next_tvb, offset, 2, FALSE);
+ offset += 2;
+
+ switch(code)
+ {
+ case BTOBEX_CODE_VALS_CONNECT:
+ proto_tree_add_item(st, hf_version, next_tvb, offset, 1, FALSE);
+ offset++;
+
+ proto_tree_add_item(st, hf_flags, next_tvb, offset, 1, FALSE);
+ offset++;
+
+ proto_tree_add_item(st, hf_max_pkt_len, next_tvb, offset, 2, FALSE);
+ offset += 2;
+ break;
+
+ case BTOBEX_CODE_VALS_PUT:
+ case BTOBEX_CODE_VALS_GET:
+ col_append_fstr(pinfo->cinfo, COL_INFO, " %s", final_flag==0x80?"final":"continue");
+ break;
+
+ case BTOBEX_CODE_VALS_SET_PATH:
+ proto_tree_add_item(st, hf_flags, next_tvb, offset, 1, FALSE);
+ proto_tree_add_item(st, hf_set_path_flags_0, next_tvb, offset, 1, FALSE);
+ proto_tree_add_item(st, hf_set_path_flags_1, next_tvb, offset, 1, FALSE);
+ offset++;
+
+ proto_tree_add_item(st, hf_constants, next_tvb, offset, 1, FALSE);
+ offset++;
+ break;
+
+ case BTOBEX_CODE_VALS_DISCONNECT:
+ case BTOBEX_CODE_VALS_ABORT:
+ break;
+
+ default:
+ {
+ guint8 response_opcode = last_opcode[(pinfo->p2p_dir + 1) & 0x01];
+
+ if(response_opcode == BTOBEX_CODE_VALS_CONNECT) {
+ proto_tree_add_item(st, hf_version, next_tvb, offset, 1, FALSE);
+ offset++;
+
+ proto_tree_add_item(st, hf_flags, next_tvb, offset, 1, FALSE);
+ offset++;
+
+ proto_tree_add_item(st, hf_max_pkt_len, next_tvb, offset, 2, FALSE);
+ offset += 2;
+ }
+ }
+ break;
+ }
+
+ offset = dissect_headers(st, next_tvb, offset, pinfo);
+ }
+ else
+ {
+ /* packet fragment */
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s Obex fragment",
+ pinfo->p2p_dir==P2P_DIR_SENT?"Sent":"Rcvd");
+
+ call_dissector(data_handle, next_tvb, pinfo, tree);
+ }
+
+ pinfo->fragmented = save_fragmented;
}
void
proto_register_btobex(void)
{
- static hf_register_info hf[] = {
- {&hf_opcode,
- {"Opcode", "btobex.opcode",
- FT_UINT8, BASE_HEX, VALS(code_vals), BTOBEX_CODE_VALS_MASK,
- "Request Opcode", HFILL}
- },
- {&hf_response_code,
- {"Response Code", "btobex.resp_code",
- FT_UINT8, BASE_HEX, VALS(code_vals), BTOBEX_CODE_VALS_MASK,
- NULL, HFILL}
- },
- {&hf_final_flag,
- {"Final Flag", "btobex.final_flag",
- FT_BOOLEAN, BASE_HEX, TFS(&true_false), 0x80,
- NULL, HFILL}
- },
- {&hf_length,
- {"Packet Length", "btobex.pkt_len",
- FT_UINT16, BASE_DEC, NULL, 0,
- NULL, HFILL}
- },
- {&hf_version,
- {"Version", "btobex.version",
- FT_UINT8, BASE_HEX, VALS(version_vals), 0x00,
- "Obex Version", HFILL}
- },
- {&hf_flags,
- {"Flags", "btobex.flags",
- FT_UINT8, BASE_HEX, NULL, 0x00,
- NULL, HFILL}
- },
- {&hf_constants,
- {"Constants", "btobex.constants",
- FT_UINT8, BASE_HEX, NULL, 0x00,
- NULL, HFILL}
- },
- {&hf_max_pkt_len,
- {"Max. Packet Length", "btobex.max_pkt_len",
- FT_UINT16, BASE_DEC, NULL, 0,
- "Maximum Packet Length", HFILL}
- },
- {&hf_set_path_flags_0,
- {"Go back one folder (../) first", "btobex.set_path_flags_0",
- FT_BOOLEAN, 8, TFS(&true_false), 0x01,
- NULL, HFILL}
- },
- {&hf_set_path_flags_1,
- {"Do not create folder, if not existing", "btobex.set_path_flags_1",
- FT_BOOLEAN, 8, TFS(&true_false), 0x02,
- NULL, HFILL}
- },
- {&hf_hdr_id,
- {"Header Id", "btobex.hdr_id",
- FT_UINT8, BASE_HEX, VALS(header_id_vals), 0x00,
- NULL, HFILL}
- },
- {&hf_hdr_length,
- {"Length", "btobex.pkt_hdr_len",
- FT_UINT16, BASE_DEC, NULL, 0,
- "Header Length", HFILL}
- },
- {&hf_hdr_val_unicode,
- { "Value", "btobex.pkt_hdr_val_uc",
- FT_STRING, BASE_NONE, NULL, 0,
- "Unicode Value", HFILL }
- },
- {&hf_hdr_val_byte_seq,
- {"Value", "btobex.hdr_val_byte_seq",
- FT_BYTES, BASE_NONE, NULL, 0,
- "Byte Value", HFILL}
- },
- {&hf_hdr_val_byte,
- {"Value", "btobex.hdr_val_byte",
- FT_UINT8, BASE_HEX, NULL, 0,
- "Byte Sequence Value", HFILL}
- },
- {&hf_hdr_val_long,
- {"Value", "btobex.hdr_val_long",
- FT_UINT32, BASE_DEC, NULL, 0,
- "4-byte Value", HFILL}
- },
- {&hf_data,
- {"Obex Data", "btobex.data",
- FT_NONE, BASE_NONE, NULL, 0,
- NULL, HFILL}
- },
-
- /* for fragmentation */
- { &hf_btobex_fragment_overlap,
- { "Fragment overlap", "btobex.fragment.overlap", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
- "Fragment overlaps with other fragments", HFILL }},
-
- { &hf_btobex_fragment_overlap_conflict,
- { "Conflicting data in fragment overlap", "btobex.fragment.overlap.conflict", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
- "Overlapping fragments contained conflicting data", HFILL }},
-
- { &hf_btobex_fragment_multiple_tails,
- { "Multiple tail fragments found", "btobex.fragment.multipletails", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
- "Several tails were found when defragmenting the packet", HFILL }},
-
- { &hf_btobex_fragment_too_long_fragment,
- { "Fragment too long", "btobex.fragment.toolongfragment", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
- "Fragment contained data past end of packet", HFILL }},
-
- { &hf_btobex_fragment_error,
- { "Defragmentation error", "btobex.fragment.error", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
- "Defragmentation error due to illegal fragments", HFILL }},
-
- { &hf_btobex_fragment,
- { "OBEX Fragment", "btobex.fragment", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
- "btobex Fragment", HFILL }},
-
- { &hf_btobex_fragments,
- { "OBEX Fragments", "btobex.fragments", FT_NONE, BASE_NONE, NULL, 0x0,
- "btobex Fragments", HFILL }},
-
- { &hf_btobex_reassembled_in,
- { "Reassembled OBEX in frame", "btobex.reassembled_in", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
- "This OBEX frame is reassembled in this frame", HFILL }},
-
- { &hf_btobex_reassembled_length,
- { "Reassembled OBEX length", "btobex.reassembled.length", FT_UINT32, BASE_DEC, NULL, 0x0,
- "The total length of the reassembled payload", HFILL }}
- };
-
- /* Setup protocol subtree array */
- static gint *ett[] = {
- &ett_btobex,
- &ett_btobex_hdrs,
- &ett_btobex_hdr,
- &ett_btobex_fragment,
- &ett_btobex_fragments
- };
-
- proto_btobex = proto_register_protocol("Bluetooth OBEX", "OBEX", "btobex");
-
- register_dissector("btobex", dissect_btobex, proto_btobex);
-
- /* Required function calls to register the header fields and subtrees used */
- proto_register_field_array(proto_btobex, hf, array_length(hf));
- proto_register_subtree_array(ett, array_length(ett));
-
- register_init_routine(&defragment_init);
+ static hf_register_info hf[] = {
+ {&hf_opcode,
+ {"Opcode", "btobex.opcode",
+ FT_UINT8, BASE_HEX, VALS(code_vals), BTOBEX_CODE_VALS_MASK,
+ "Request Opcode", HFILL}
+ },
+ {&hf_response_code,
+ {"Response Code", "btobex.resp_code",
+ FT_UINT8, BASE_HEX, VALS(code_vals), BTOBEX_CODE_VALS_MASK,
+ NULL, HFILL}
+ },
+ {&hf_final_flag,
+ {"Final Flag", "btobex.final_flag",
+ FT_BOOLEAN, BASE_HEX, TFS(&true_false), 0x80,
+ NULL, HFILL}
+ },
+ {&hf_length,
+ {"Packet Length", "btobex.pkt_len",
+ FT_UINT16, BASE_DEC, NULL, 0,
+ NULL, HFILL}
+ },
+ {&hf_version,
+ {"Version", "btobex.version",
+ FT_UINT8, BASE_HEX, VALS(version_vals), 0x00,
+ "Obex Protocol Version", HFILL}
+ },
+ {&hf_flags,
+ {"Flags", "btobex.flags",
+ FT_UINT8, BASE_HEX, NULL, 0x00,
+ NULL, HFILL}
+ },
+ {&hf_constants,
+ {"Constants", "btobex.constants",
+ FT_UINT8, BASE_HEX, NULL, 0x00,
+ NULL, HFILL}
+ },
+ {&hf_max_pkt_len,
+ {"Max. Packet Length", "btobex.max_pkt_len",
+ FT_UINT16, BASE_DEC, NULL, 0,
+ NULL, HFILL}
+ },
+ {&hf_set_path_flags_0,
+ {"Go back one folder (../) first", "btobex.set_path_flags_0",
+ FT_BOOLEAN, 8, TFS(&true_false), 0x01,
+ NULL, HFILL}
+ },
+ {&hf_set_path_flags_1,
+ {"Do not create folder, if not existing", "btobex.set_path_flags_1",
+ FT_BOOLEAN, 8, TFS(&true_false), 0x02,
+ NULL, HFILL}
+ },
+ {&hf_hdr_id,
+ {"Header Id", "btobex.hdr_id",
+ FT_UINT8, BASE_HEX, VALS(header_id_vals), 0x00,
+ NULL, HFILL}
+ },
+ {&hf_hdr_length,
+ {"Length", "btobex.pkt_hdr_len",
+ FT_UINT16, BASE_DEC, NULL, 0,
+ "Header Length", HFILL}
+ },
+ {&hf_hdr_val_unicode,
+ { "Value", "btobex.pkt_hdr_val_uc",
+ FT_STRING, BASE_NONE, NULL, 0,
+ "Unicode Value", HFILL }
+ },
+ {&hf_hdr_val_byte_seq,
+ {"Value", "btobex.hdr_val_byte_seq",
+ FT_BYTES, BASE_NONE, NULL, 0,
+ "Byte Value", HFILL}
+ },
+ {&hf_hdr_val_byte,
+ {"Value", "btobex.hdr_val_byte",
+ FT_UINT8, BASE_HEX, NULL, 0,
+ "Byte Sequence Value", HFILL}
+ },
+ {&hf_hdr_val_long,
+ {"Value", "btobex.hdr_val_long",
+ FT_UINT32, BASE_DEC, NULL, 0,
+ "4-byte Value", HFILL}
+ },
+
+ /* for fragmentation */
+ { &hf_btobex_fragment_overlap,
+ { "Fragment overlap", "btobex.fragment.overlap", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "Fragment overlaps with other fragments", HFILL }
+ },
+ { &hf_btobex_fragment_overlap_conflict,
+ { "Conflicting data in fragment overlap", "btobex.fragment.overlap.conflict", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "Overlapping fragments contained conflicting data", HFILL }
+ },
+ { &hf_btobex_fragment_multiple_tails,
+ { "Multiple tail fragments found", "btobex.fragment.multipletails", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "Several tails were found when defragmenting the packet", HFILL }
+ },
+ { &hf_btobex_fragment_too_long_fragment,
+ { "Fragment too long", "btobex.fragment.toolongfragment", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "Fragment contained data past end of packet", HFILL }
+ },
+ { &hf_btobex_fragment_error,
+ { "Defragmentation error", "btobex.fragment.error", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
+ "Defragmentation error due to illegal fragments", HFILL }
+ },
+ { &hf_btobex_fragment,
+ { "OBEX Fragment", "btobex.fragment", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
+ "btobex Fragment", HFILL }
+ },
+ { &hf_btobex_fragments,
+ { "OBEX Fragments", "btobex.fragments", FT_NONE, BASE_NONE, NULL, 0x0,
+ "btobex Fragments", HFILL }
+ },
+ { &hf_btobex_reassembled_in,
+ { "Reassembled OBEX in frame", "btobex.reassembled_in", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
+ "This OBEX frame is reassembled in this frame", HFILL }
+ },
+ { &hf_btobex_reassembled_length,
+ { "Reassembled OBEX length", "btobex.reassembled.length", FT_UINT32, BASE_DEC, NULL, 0x0,
+ "The total length of the reassembled payload", HFILL }
+ }
+ };
+
+ /* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_btobex,
+ &ett_btobex_hdrs,
+ &ett_btobex_hdr,
+ &ett_btobex_fragment,
+ &ett_btobex_fragments
+ };
+
+ proto_btobex = proto_register_protocol("Bluetooth OBEX Protocol", "OBEX", "btobex");
+
+ register_dissector("btobex", dissect_btobex, proto_btobex);
+
+ /* Required function calls to register the header fields and subtrees used */
+ proto_register_field_array(proto_btobex, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ register_init_routine(&defragment_init);
}
void
proto_reg_handoff_btobex(void)
{
- xml_handle = find_dissector("xml");
- data_handle = find_dissector("data");
+ dissector_handle_t btobex_handle;
+
+ btobex_handle = find_dissector("btobex");
+
+ /* register in rfcomm and l2cap the profiles/services this dissector should handle */
+ dissector_add_uint("btrfcomm.service", BTSDP_OPP_SERVICE_UUID, btobex_handle);
+ dissector_add_uint("btrfcomm.service", BTSDP_FTP_SERVICE_UUID, btobex_handle);
+ dissector_add_uint("btrfcomm.service", BTSDP_BPP_SERVICE_UUID, btobex_handle);
+ dissector_add_uint("btrfcomm.service", BTSDP_BPP_STATUS_SERVICE_UUID, btobex_handle);
+ dissector_add_uint("btrfcomm.service", BTSDP_BIP_SERVICE_UUID, btobex_handle);
+ dissector_add_uint("btrfcomm.service", BTSDP_BIP_RESPONDER_SERVICE_UUID, btobex_handle);
+ dissector_add_uint("btrfcomm.service", BTSDP_BIP_AUTO_ARCH_SERVICE_UUID, btobex_handle);
+ dissector_add_uint("btrfcomm.service", BTSDP_BIP_REF_OBJ_SERVICE_UUID, btobex_handle);
+ dissector_add_uint("btrfcomm.service", BTSDP_PBAP_PCE_SERVICE_UUID, btobex_handle);
+ dissector_add_uint("btrfcomm.service", BTSDP_PBAP_PSE_SERVICE_UUID, btobex_handle);
+ dissector_add_uint("btrfcomm.service", BTSDP_PBAP_SERVICE_UUID, btobex_handle);
+ dissector_add_uint("btrfcomm.service", BTSDP_MAP_SERVICE_UUID, btobex_handle);
+ dissector_add_uint("btrfcomm.service", BTSDP_MAP_ACCESS_SRV_SERVICE_UUID, btobex_handle);
+ dissector_add_uint("btrfcomm.service", BTSDP_MAP_NOIYFY_SRV_SERVICE_UUID, btobex_handle);
+
+ dissector_add_uint("btl2cap.service", BTSDP_OPP_SERVICE_UUID, btobex_handle);
+ dissector_add_uint("btl2cap.service", BTSDP_FTP_SERVICE_UUID, btobex_handle);
+ dissector_add_uint("btl2cap.service", BTSDP_BPP_SERVICE_UUID, btobex_handle);
+ dissector_add_uint("btl2cap.service", BTSDP_BPP_STATUS_SERVICE_UUID, btobex_handle);
+ dissector_add_uint("btl2cap.service", BTSDP_BIP_SERVICE_UUID, btobex_handle);
+ dissector_add_uint("btl2cap.service", BTSDP_BIP_RESPONDER_SERVICE_UUID, btobex_handle);
+ dissector_add_uint("btl2cap.service", BTSDP_BIP_AUTO_ARCH_SERVICE_UUID, btobex_handle);
+ dissector_add_uint("btl2cap.service", BTSDP_BIP_REF_OBJ_SERVICE_UUID, btobex_handle);
+ dissector_add_uint("btl2cap.service", BTSDP_PBAP_PCE_SERVICE_UUID, btobex_handle);
+ dissector_add_uint("btl2cap.service", BTSDP_PBAP_PSE_SERVICE_UUID, btobex_handle);
+ dissector_add_uint("btl2cap.service", BTSDP_PBAP_SERVICE_UUID, btobex_handle);
+ dissector_add_uint("btl2cap.service", BTSDP_MAP_SERVICE_UUID, btobex_handle);
+ dissector_add_uint("btl2cap.service", BTSDP_MAP_ACCESS_SRV_SERVICE_UUID, btobex_handle);
+ dissector_add_uint("btl2cap.service", BTSDP_MAP_NOIYFY_SRV_SERVICE_UUID, btobex_handle);
+
+ xml_handle = find_dissector("xml");
+ data_handle = find_dissector("data");
}