diff options
author | Anders Broman <anders.broman@ericsson.com> | 2006-02-13 19:45:38 +0000 |
---|---|---|
committer | Anders Broman <anders.broman@ericsson.com> | 2006-02-13 19:45:38 +0000 |
commit | 4621cc9150c98f2cdf4e1eaae3c2ff52d379aa97 (patch) | |
tree | 40846a7d61926997a8439c6c5db2733a781e39b2 | |
parent | 36bad901afcb064943e6defb25b1ad92eba0966d (diff) |
From Mike Duigou:
- Improves ability of dissector to find conversations without seeing
whole stream.
- Fixes some issues with dissection of data which requires reassembly.
- Adds the ability to dissect jxta conversations from SCTP streams.
- Better handling of welcome message.
- Adds direct dissection of compressed SRDI data.
- Has been run through extensive fuzz testing.
- Fixes compiler warnings with previous patch 17141
svn path=/trunk/; revision=17282
-rw-r--r-- | epan/dissectors/packet-jxta.c | 402 |
1 files changed, 278 insertions, 124 deletions
diff --git a/epan/dissectors/packet-jxta.c b/epan/dissectors/packet-jxta.c index 25501764a9..4dd46ac255 100644 --- a/epan/dissectors/packet-jxta.c +++ b/epan/dissectors/packet-jxta.c @@ -1,6 +1,6 @@ /* packet-jxta.c * Routines for JXTA packet dissection - * Copyright 2004-05, Mike Duigou <bondolo@jxta.org> + * Copyright 2004-06, Mike Duigou <bondolo@jxta.org> * Heavily based on packet-jabber.c, which in turn is heavily based on * on packet-acap.c, which in turn is heavily based on * packet-imap.c, Copyright 1999, Richard Sharpe <rsharpe@ns.aus.com> @@ -55,25 +55,29 @@ static const gchar JXTA_MSGELEM_SIG[] = { 'j', 'x', 'e', 'l' }; static const gchar JXTA_WELCOME_MSG_SIG[] = { 'J', 'X', 'T', 'A', 'H', 'E', 'L', 'L', 'O', ' ' }; +static const gchar* JXTA_WELCOME_MSG_VERSION_1_1 = "1.1"; + static int proto_jxta = -1; -static int proto_welcome_jxta = -1; -static int proto_udp_jxta = -1; -static int proto_framing_jxta = -1; static int proto_message_jxta = -1; static int jxta_tap = -1; static dissector_table_t media_type_dissector_table = NULL; static dissector_handle_t data_handle = NULL; -static dissector_handle_t tcp_jxta_handle = NULL; +static dissector_handle_t stream_jxta_handle = NULL; +static dissector_handle_t message_jxta_handle; +static int hf_jxta_udp = -1; static int hf_jxta_udpsig = -1; +static int hf_jxta_welcome = -1; static int hf_jxta_welcome_initiator = -1; static int hf_jxta_welcome_sig = -1; static int hf_jxta_welcome_destAddr = -1; static int hf_jxta_welcome_pubAddr = -1; static int hf_jxta_welcome_peerid = -1; static int hf_jxta_welcome_noProp = -1; +static int hf_jxta_welcome_variable = -1; static int hf_jxta_welcome_version = -1; +static int hf_jxta_framing = -1; static int hf_jxta_framing_header = -1; static int hf_jxta_framing_header_name = -1; static int hf_jxta_framing_header_value_length = -1; @@ -101,10 +105,18 @@ static int hf_jxta_element_content = -1; /** our header fields */ static hf_register_info hf[] = { + {&hf_jxta_udp, + {"JXTA UDP", "jxta.udp", FT_NONE, BASE_NONE, NULL, 0x0, + "JXTA UDP", HFILL} + }, {&hf_jxta_udpsig, {"Signature", "jxta.udpsig", FT_STRING, BASE_NONE, NULL, 0x0, "JXTA UDP Signature", HFILL} }, + {&hf_jxta_welcome, + {"Welcome", "jxta.welcome", FT_NONE, BASE_NONE, NULL, 0x00, + "JXTA Connection Welcome Message", HFILL} + }, {&hf_jxta_welcome_initiator, {"Initiator", "jxta.welcome.initiator", FT_BOOLEAN, BASE_NONE, NULL, 0x00, "JXTA Connection Welcome Message Initiator", HFILL} @@ -129,10 +141,18 @@ static hf_register_info hf[] = { {"No Propagate Flag", "jxta.welcome.noPropFlag", FT_STRING, BASE_NONE, NULL, 0x0, "JXTA Connection Welcome Message No Propagate Flag", HFILL} }, + {&hf_jxta_welcome_variable, + {"Variable Parameter", "jxta.welcome.variable", FT_STRING, BASE_NONE, NULL, 0x0, + "JXTA Connection Welcome Message Variable Parameter", HFILL} + }, {&hf_jxta_welcome_version, {"Version", "jxta.welcome.version", FT_STRING, BASE_NONE, NULL, 0x0, "JXTA Connection Welcome Message Version", HFILL} }, + {&hf_jxta_framing, + {"Framing", "jxta.framing", FT_NONE, BASE_NONE, NULL, 0x0, + "JXTA Message Framing", HFILL} + }, {&hf_jxta_framing_header, {"Header", "jxta.framing.header", FT_NONE, BASE_NONE, NULL, 0x0, "JXTA Message Framing Header", HFILL} @@ -234,6 +254,7 @@ static hf_register_info hf[] = { /** * JXTA Protocol subtree handles **/ +static gint ett_jxta = -1; static gint ett_jxta_welcome = -1; static gint ett_jxta_udp = -1; static gint ett_jxta_framing = -1; @@ -246,6 +267,7 @@ static gint ett_jxta_elem_flags = -1; * JXTA Protocol subtree array **/ static gint *const ett[] = { + &ett_jxta, &ett_jxta_welcome, &ett_jxta_udp, &ett_jxta_framing, @@ -259,8 +281,9 @@ static gint *const ett[] = { * global preferences **/ static gboolean gDESEGMENT = TRUE; -static gboolean gUDP_HEUR = FALSE; -static gboolean gTCP_HEUR = FALSE; +static gboolean gUDP_HEUR = TRUE; +static gboolean gTCP_HEUR = TRUE; +static gboolean gSCTP_HEUR = FALSE; /** * Stream Conversation data @@ -286,6 +309,7 @@ typedef struct jxta_stream_conversation_data jxta_stream_conversation_data; **/ static gboolean dissect_jxta_UDP_heur(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree); static gboolean dissect_jxta_TCP_heur(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree); +static gboolean dissect_jxta_SCTP_heur(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree); static int dissect_jxta_udp(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree); static int dissect_jxta_stream(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree); @@ -299,7 +323,6 @@ static int dissect_jxta_message_element(tvbuff_t * tvb, packet_info * pinfo, pro const gchar ** namespaces); void proto_reg_handoff_jxta(void); -void proto_reg_handoff_message_jxta(void); /** * Heuristically dissect a tvbuff containing a JXTA UDP Message @@ -348,6 +371,27 @@ static gboolean dissect_jxta_TCP_heur(tvbuff_t * tvb, packet_info * pinfo, proto } /** +* Heuristically dissect a tvbuff containing a JXTA SCTP Stream +* +* @param tvb The buffer to dissect. +* @param pinfo Packet Info. +* @param tree The protocol tree. +* @return TRUE if the tvb contained JXTA data which was dissected otherwise FALSE +**/ +static gboolean dissect_jxta_SCTP_heur(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree) +{ + /* This is a heuristic dissector, which means we get all the SCTP + * traffic not sent to a known dissector and not claimed by + * a heuristic dissector called before us! + */ + + if (!gSCTP_HEUR) + return FALSE; + + return dissect_jxta_stream(tvb, pinfo, tree) != 0; +} + +/** * Dissect a tvbuff containing a JXTA UDP header, JXTA Message framing and a JXTA Message * * @param tvb The buffer to dissect. @@ -386,7 +430,7 @@ static int dissect_jxta_udp(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tr available = tvb_reported_length_remaining(tvb, offset); if (available < sizeof(JXTA_UDP_SIG)) { - needed = (gint) (available - sizeof(JXTA_UDP_SIG)); + needed = (gint) (sizeof(JXTA_UDP_SIG) - available); break; } @@ -414,7 +458,7 @@ static int dissect_jxta_udp(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tr available = tvb_reported_length_remaining(tvb, offset); if (available < content_length) { - needed = (gint) (available - content_length); + needed = (gint) (content_length - available); break; } @@ -435,8 +479,11 @@ static int dissect_jxta_udp(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tr if (tree) { guint tree_offset = 0; + proto_item *jxta_tree_item = + proto_tree_add_protocol_format(tree, proto_jxta, tvb, offset, -1, "JXTA" ); + proto_tree *jxta_tree = proto_item_add_subtree(jxta_tree_item, ett_jxta); proto_item *jxta_udp_tree_item = - proto_tree_add_protocol_format(tree, proto_udp_jxta, tvb, tree_offset, -1, "JXTA UDP Message"); + proto_tree_add_none_format(jxta_tree, hf_jxta_udp, tvb, tree_offset, -1, "JXTA UDP Message"); proto_tree *jxta_udp_tree = proto_item_add_subtree(jxta_udp_tree_item, ett_jxta_udp); tvbuff_t *jxta_message_framing_tvb; guint64 content_length = -1; @@ -459,8 +506,8 @@ static int dissect_jxta_udp(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tr tree_offset += processed; jxta_message_tvb = tvb_new_subset(tvb, tree_offset, (gint) content_length, (gint) content_length); - - dissected = dissector_try_string(media_type_dissector_table, content_type, jxta_message_tvb, pinfo, tree); + + dissected = dissector_try_string(media_type_dissector_table, content_type, jxta_message_tvb, pinfo, tree); if (!dissected) { call_dissector(data_handle, jxta_message_tvb, pinfo, tree); @@ -494,10 +541,33 @@ static int dissect_jxta_udp(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tr static int dissect_jxta_stream(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree) { guint offset = 0; - guint available = 0; + guint available = tvb_reported_length_remaining(tvb, offset); gint processed; + gint needed = 0; conversation_t *tpt_conversation = NULL; jxta_stream_conversation_data *tpt_conv_data = NULL; + proto_item *jxta_tree_item = NULL; + proto_tree *jxta_tree = NULL; + + g_message("Dissecting %s : %d", (NULL != tree) ? "for display" : "", pinfo->fd->num ); + + if (available < sizeof(JXTA_WELCOME_MSG_SIG)) { + needed = (gint) (sizeof(JXTA_WELCOME_MSG_SIG) - available); + goto Common_Exit; + } + + if (tree) { + jxta_tree_item = + proto_tree_add_protocol_format(tree, proto_jxta, tvb, offset, -1, "JXTA" ); + jxta_tree = proto_item_add_subtree(jxta_tree_item, ett_jxta); + + tpt_conversation = get_tpt_conversation(pinfo, FALSE); + + if( NULL != tpt_conversation ) { + tpt_conv_data = (jxta_stream_conversation_data *) conversation_get_proto_data(tpt_conversation, proto_jxta); + + } + } if (0 == tvb_memeql(tvb, 0, JXTA_WELCOME_MSG_SIG, sizeof(JXTA_WELCOME_MSG_SIG))) { /* The beginning of a JXTA stream connection */ @@ -541,27 +611,45 @@ static int dissect_jxta_stream(tvbuff_t * tvb, packet_info * pinfo, proto_tree * } } - processed = dissect_jxta_welcome(tvb, pinfo, tree, welcome_addr, initiator); + processed = dissect_jxta_welcome(tvb, pinfo, jxta_tree, welcome_addr, initiator); + + if( processed < 0 ) { + needed = -processed; + goto Common_Exit; + } } else { /* Somewhere in the middle of a JXTA stream connection */ guint64 content_length = -1; gchar *content_type = NULL; + gint headers_len = dissect_jxta_message_framing(tvb, pinfo, jxta_tree, &content_length, &content_type); - processed = dissect_jxta_message_framing(tvb, pinfo, tree, &content_length, &content_type); + g_message("%d Tpt %s:%d -> %s:%d tvb len=%d\n\t%s %u", pinfo->fd->num, + address_to_str(&pinfo->src), pinfo->srcport, + address_to_str(&pinfo->dst), pinfo->destport, + tvb_reported_length_remaining(tvb, 0), + content_type, (guint) content_length); - if ((0 == processed) || (NULL == content_type) || (content_length <= 0) || (content_length > UINT_MAX)) { + if ((0 == headers_len) || (NULL == content_type) || (content_length <= 0) || (content_length > UINT_MAX)) { /** Buffer did not begin with valid framing headers */ return 0; } - if (processed > 0) { - guint msg_offset = offset + processed; + if (headers_len < 0) { + /* negative headers_len means we need more bytes */ + needed = -headers_len; + goto Common_Exit; + } + + available = tvb_reported_length_remaining(tvb, offset + headers_len); + if (available >= content_length) { + tvbuff_t *jxta_message_tvb = tvb_new_subset(tvb, offset + headers_len, (gint) content_length, (gint) content_length); conversation_t *peer_conversation = NULL; address saved_src_addr; guint32 saved_src_port = 0; address saved_dst_addr; guint32 saved_dst_port = 0; port_type saved_port_type = PT_NONE; + gboolean dissected; tpt_conversation = get_tpt_conversation(pinfo, TRUE); @@ -575,13 +663,13 @@ static int dissect_jxta_stream(tvbuff_t * tvb, packet_info * pinfo, proto_tree * if (NULL == peer_conversation) { peer_conversation = - conversation_new(pinfo->fd->num, &tpt_conv_data->initiator_address, &tpt_conv_data->receiver_address, - PT_NONE, 0, 0, NO_PORT_B); - conversation_set_dissector(peer_conversation, tcp_jxta_handle); + conversation_new(pinfo->fd->num, &tpt_conv_data->initiator_address, + &tpt_conv_data->receiver_address, PT_NONE, 0, 0, NO_PORT_B); + conversation_set_dissector(peer_conversation, stream_jxta_handle); } } else { -/* g_warning( "Uninitialized peer conversation" ); */ + g_warning("Uninitialized peer conversation"); } } @@ -592,19 +680,24 @@ static int dissect_jxta_stream(tvbuff_t * tvb, packet_info * pinfo, proto_tree * saved_dst_addr = pinfo->dst; saved_dst_port = pinfo->destport; saved_port_type = pinfo->ptype; -/* g_warning( "%d Tpt %s:%d -> %s:%d", pinfo->fd->num, ip_to_str(tpt_conv_data->initiator_tpt_address.data), tpt_conv_data->initiator_tpt_port, ip_to_str(tpt_conv_data->receiver_tpt_address.data), tpt_conv_data->receiver_tpt_port ); */ - if (ADDRESSES_EQUAL(&pinfo->src, &tpt_conv_data->initiator_tpt_address) && - tpt_conv_data->initiator_tpt_port == pinfo->srcport) { -/* g_warning( "%d From initiator : %s -> %s ", pinfo->fd->num, tpt_conv_data->initiator_address.data, tpt_conv_data->receiver_address.data ); */ + g_message("%d Tpt %s:%d -> %s:%d", pinfo->fd->num, ip_to_str(tpt_conv_data->initiator_tpt_address.data), + tpt_conv_data->initiator_tpt_port, ip_to_str(tpt_conv_data->receiver_tpt_address.data), + tpt_conv_data->receiver_tpt_port); + if (ADDRESSES_EQUAL(&pinfo->src, &tpt_conv_data->initiator_tpt_address) + && tpt_conv_data->initiator_tpt_port == pinfo->srcport) { + g_message("%d From initiator : %s -> %s ", pinfo->fd->num, tpt_conv_data->initiator_address.data, + tpt_conv_data->receiver_address.data); pinfo->src = tpt_conv_data->initiator_address; pinfo->dst = tpt_conv_data->receiver_address; } else if (ADDRESSES_EQUAL(&pinfo->src, &tpt_conv_data->receiver_tpt_address) && tpt_conv_data->receiver_tpt_port == pinfo->srcport) { -/* g_warning( "%d From receiver : %s -> %s ", pinfo->fd->num, tpt_conv_data->receiver_address.data, tpt_conv_data->initiator_address.data ); */ + g_message("%d From receiver : %s -> %s ", pinfo->fd->num, tpt_conv_data->receiver_address.data, + tpt_conv_data->initiator_address.data); pinfo->src = tpt_conv_data->receiver_address; pinfo->dst = tpt_conv_data->initiator_address; } else { -/* g_warning( "%d Nothing matches %s:%d -> %s:%d", pinfo->fd->num, ip_to_str(pinfo->src.data), pinfo->srcport, ip_to_str(pinfo->dst.data), pinfo->destport ); */ + g_message("%d Nothing matches %s:%d -> %s:%d", pinfo->fd->num, ip_to_str(pinfo->src.data), pinfo->srcport, + ip_to_str(pinfo->dst.data), pinfo->destport); } /* JXTA doesn't use ports */ pinfo->ptype = PT_NONE; @@ -612,19 +705,11 @@ static int dissect_jxta_stream(tvbuff_t * tvb, packet_info * pinfo, proto_tree * pinfo->destport = 0; } - available = tvb_reported_length_remaining(tvb, msg_offset); - if (available >= content_length) { - tvbuff_t *jxta_message_tvb = tvb_new_subset(tvb, msg_offset, (gint) content_length, (gint) content_length); - gboolean dissected = - dissector_try_string(media_type_dissector_table, content_type, jxta_message_tvb, pinfo, tree); - - if (!dissected) { - call_dissector(data_handle, jxta_message_tvb, pinfo, tree); - } + dissected = + dissector_try_string(media_type_dissector_table, content_type, jxta_message_tvb, pinfo, tree); - processed += (guint) content_length; - } else { - processed = available - (guint) content_length; + if (!dissected) { + call_dissector(data_handle, jxta_message_tvb, pinfo, jxta_tree); } /* Restore the saved src and dst addresses */ @@ -635,17 +720,25 @@ static int dissect_jxta_stream(tvbuff_t * tvb, packet_info * pinfo, proto_tree * pinfo->destport = saved_dst_port; pinfo->ptype = saved_port_type; } + + processed = (guint) content_length + headers_len; + } else { + /* we need more bytes before we can process message body. */ + needed = (gint) ((guint) content_length - available); + goto Common_Exit; } } - if (processed <= 0) { + offset += processed; + +Common_Exit: + if ((needed > 0) && gDESEGMENT && pinfo->can_desegment) { + g_message( "Requesting %d more bytes", needed ); pinfo->desegment_offset = offset; - pinfo->desegment_len = -processed; - return processed; + pinfo->desegment_len = needed; + return -needed; } - offset += processed; - return offset; } @@ -674,25 +767,25 @@ static conversation_t *get_tpt_conversation(packet_info * pinfo, gboolean create conversation_new(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0); } - conversation_set_dissector(tpt_conversation, tcp_jxta_handle); + conversation_set_dissector(tpt_conversation, stream_jxta_handle); tpt_conv_data = (jxta_stream_conversation_data *) conversation_get_proto_data(tpt_conversation, proto_jxta); if (NULL == tpt_conv_data) { tpt_conv_data = se_alloc(sizeof(jxta_stream_conversation_data)); tpt_conv_data->tpt_ptype = pinfo->ptype; - - COPY_ADDRESS( &tpt_conv_data->initiator_tpt_address, &pinfo->src ); + + COPY_ADDRESS(&tpt_conv_data->initiator_tpt_address, &pinfo->src); tpt_conv_data->initiator_tpt_port = pinfo->srcport; tpt_conv_data->initiator_welcome_frame = 0; /* XXX bondolo This is not quite correct as it should include port until a peerid can be associated. */ - COPY_ADDRESS( &tpt_conv_data->initiator_address, &pinfo->src ); - - COPY_ADDRESS( &tpt_conv_data->receiver_tpt_address, &pinfo->dst ); + COPY_ADDRESS(&tpt_conv_data->initiator_address, &pinfo->src); + + COPY_ADDRESS(&tpt_conv_data->receiver_tpt_address, &pinfo->dst); tpt_conv_data->receiver_tpt_port = pinfo->destport; tpt_conv_data->receiver_welcome_frame = 0; /* XXX bondolo This is not quite correct as it should include port until a peerid can be associated. */ - COPY_ADDRESS( &tpt_conv_data->receiver_address, &pinfo->dst ); + COPY_ADDRESS(&tpt_conv_data->receiver_address, &pinfo->dst); conversation_add_proto_data(tpt_conversation, proto_jxta, tpt_conv_data); } @@ -718,6 +811,7 @@ static int dissect_jxta_welcome(tvbuff_t * tvb, packet_info * pinfo, proto_tree gint afterwelcome; gint first_linelen; guint available = tvb_reported_length_remaining(tvb, offset); + gchar **tokens = NULL; if (available < sizeof(JXTA_WELCOME_MSG_SIG)) { return (gint) (available - sizeof(JXTA_WELCOME_MSG_SIG)); @@ -740,6 +834,8 @@ static int dissect_jxta_welcome(tvbuff_t * tvb, packet_info * pinfo, proto_tree } } + /* Dissect the Welcome Message */ + if (check_col(pinfo->cinfo, COL_PROTOCOL)) { col_set_str(pinfo->cinfo, COL_PROTOCOL, "JXTA"); } @@ -750,16 +846,18 @@ static int dissect_jxta_welcome(tvbuff_t * tvb, packet_info * pinfo, proto_tree { gchar *welcomeline = tvb_get_ephemeral_string(tvb, offset, first_linelen); - gchar **tokens = g_strsplit(welcomeline, " ", 6); - gchar **current_token = tokens; + gchar **current_token; guint token_offset = offset; proto_item *jxta_welcome_tree_item = NULL; proto_tree *jxta_welcome_tree = NULL; + tokens = g_strsplit(welcomeline, " ", 255); + current_token = tokens; + if (tree) { jxta_welcome_tree_item = - proto_tree_add_protocol_format(tree, proto_welcome_jxta, tvb, offset, afterwelcome, - "JXTA Connection Welcome Message, %s", welcomeline); + proto_tree_add_none_format(tree, hf_jxta_welcome, tvb, offset, afterwelcome, + "JXTA Connection Welcome Message, %s", welcomeline); jxta_welcome_tree = proto_item_add_subtree(jxta_welcome_tree_item, ett_jxta_welcome); } @@ -776,6 +874,10 @@ static int dissect_jxta_welcome(tvbuff_t * tvb, packet_info * pinfo, proto_tree token_offset += strlen(*current_token) + 1; current_token++; + } else { + /* invalid welcome message */ + afterwelcome = 0; + goto Common_Exit; } if (NULL != *current_token) { @@ -786,6 +888,10 @@ static int dissect_jxta_welcome(tvbuff_t * tvb, packet_info * pinfo, proto_tree token_offset += strlen(*current_token) + 1; current_token++; + } else { + /* invalid welcome message */ + afterwelcome = 0; + goto Common_Exit; } if (NULL != *current_token) { @@ -795,6 +901,10 @@ static int dissect_jxta_welcome(tvbuff_t * tvb, packet_info * pinfo, proto_tree token_offset += strlen(*current_token) + 1; current_token++; + } else { + /* invalid welcome message */ + afterwelcome = 0; + goto Common_Exit; } if (NULL != *current_token) { @@ -803,7 +913,7 @@ static int dissect_jxta_welcome(tvbuff_t * tvb, packet_info * pinfo, proto_tree } if (check_col(pinfo->cinfo, COL_INFO)) { - col_append_str(pinfo->cinfo, COL_INFO, ", "); + col_append_str(pinfo->cinfo, COL_INFO, (initiator ? " -> " : " <- ") ); col_append_str(pinfo->cinfo, COL_INFO, *current_token); } @@ -816,28 +926,65 @@ static int dissect_jxta_welcome(tvbuff_t * tvb, packet_info * pinfo, proto_tree token_offset += strlen(*current_token) + 1; current_token++; + } else { + /* invalid welcome message */ + afterwelcome = 0; + goto Common_Exit; } if (NULL != *current_token) { - if (jxta_welcome_tree) { - proto_tree_add_item(jxta_welcome_tree, hf_jxta_welcome_noProp, tvb, token_offset, strlen(*current_token), FALSE); + int variable_tokens = 0; + gchar **variable_token = current_token; + + while(NULL != *variable_token) { + variable_tokens++; + variable_token++; } - - token_offset += strlen(*current_token) + 1; - current_token++; - } - - if (NULL != *current_token) { - if (jxta_welcome_tree) { - proto_tree_add_item(jxta_welcome_tree, hf_jxta_welcome_version, tvb, token_offset, strlen(*current_token), FALSE); + + if( variable_tokens < 1 ) { + /* invalid welcome message */ + afterwelcome = 0; + goto Common_Exit; } - token_offset += strlen(*current_token) + 1; - current_token++; + + if( (2 == variable_tokens) && (0 == strcmp(JXTA_WELCOME_MSG_VERSION_1_1, current_token[variable_tokens -1])) ) { + if (jxta_welcome_tree) { + proto_tree_add_item(jxta_welcome_tree, hf_jxta_welcome_noProp, tvb, token_offset, strlen(*current_token), FALSE); + } + + token_offset += strlen(*current_token) + 1; + current_token++; + + if (jxta_welcome_tree) { + proto_tree_add_item(jxta_welcome_tree, hf_jxta_welcome_version, tvb, token_offset, strlen(*current_token), FALSE); + } + } else { + /* Unrecognized Welcome Version */ + int each_variable_token; + + for( each_variable_token = 0; each_variable_token < variable_tokens; each_variable_token++ ) { + if (jxta_welcome_tree) { + jxta_welcome_tree_item = proto_tree_add_item(jxta_welcome_tree, + (each_variable_token < (variable_tokens -1) ? hf_jxta_welcome_variable : hf_jxta_welcome_version), + tvb, token_offset, strlen(*current_token), FALSE); + + proto_item_append_text(jxta_welcome_tree_item, " (UNRECOGNIZED)"); + } + + token_offset += strlen(*current_token) + 1; + current_token++; + } + } + } else { + /* invalid welcome message */ + afterwelcome = 0; + goto Common_Exit; } - - g_strfreev(tokens); } +Common_Exit: + g_strfreev(tokens); + col_set_writable(pinfo->cinfo, FALSE); return afterwelcome; @@ -875,7 +1022,7 @@ static int dissect_jxta_message_framing(tvbuff_t * tvb, packet_info * pinfo, pro available = tvb_reported_length_remaining(tvb, offset); if (available < sizeof(guint8)) { - needed = (gint) (available - sizeof(guint8)); + needed = (gint) (sizeof(guint8) - available); break; } else { headername_len = tvb_get_guint8(tvb, offset); @@ -884,7 +1031,7 @@ static int dissect_jxta_message_framing(tvbuff_t * tvb, packet_info * pinfo, pro available = tvb_reported_length_remaining(tvb, offset); if (available < headername_len) { - needed = (gint) (available - headername_len); + needed = (gint) (headername_len - available); break; } @@ -896,7 +1043,7 @@ static int dissect_jxta_message_framing(tvbuff_t * tvb, packet_info * pinfo, pro available = tvb_reported_length_remaining(tvb, offset); if (available < sizeof(guint16)) { - needed = (gint) (available - sizeof(guint16)); + needed = (gint) (sizeof(guint16) - available); break; } else { headervalue_len = tvb_get_ntohs(tvb, offset); @@ -905,7 +1052,7 @@ static int dissect_jxta_message_framing(tvbuff_t * tvb, packet_info * pinfo, pro available = tvb_reported_length_remaining(tvb, offset); if (available < headervalue_len) { - needed = (gint) (available - headervalue_len); + needed = (gint) (headervalue_len - available); break; } @@ -938,7 +1085,7 @@ static int dissect_jxta_message_framing(tvbuff_t * tvb, packet_info * pinfo, pro if (tree) { guint tree_offset = 0; proto_item *framing_tree_item = - proto_tree_add_protocol_format(tree, proto_framing_jxta, tvb, tree_offset, -1, "JXTA Message Framing Headers"); + proto_tree_add_none_format(tree, hf_jxta_framing, tvb, tree_offset, -1, "JXTA Message Framing Headers"); proto_tree *framing_tree = proto_item_add_subtree(framing_tree_item, ett_jxta_framing); /* parse framing headers */ @@ -1018,7 +1165,7 @@ static int dissect_jxta_message(tvbuff_t * tvb, packet_info * pinfo, proto_tree /* First pass. Make sure all of the bytes we need are available */ available = tvb_reported_length_remaining(tvb, offset); if (available < sizeof(JXTA_MSG_SIG)) { - needed = (gint) (available - sizeof(JXTA_MSG_SIG)); + needed = (gint) (sizeof(JXTA_MSG_SIG) - available); break; } @@ -1031,7 +1178,7 @@ static int dissect_jxta_message(tvbuff_t * tvb, packet_info * pinfo, proto_tree available = tvb_reported_length_remaining(tvb, offset); if (available < sizeof(guint8)) { - needed = (gint) (available - sizeof(guint8)); + needed = (gint) (sizeof(guint8) - available); break; } else { guint8 message_version = tvb_get_guint8(tvb, offset); @@ -1046,7 +1193,7 @@ static int dissect_jxta_message(tvbuff_t * tvb, packet_info * pinfo, proto_tree available = tvb_reported_length_remaining(tvb, offset); if (available < sizeof(guint16)) { - needed = (gint) (available - sizeof(guint16)); + needed = (gint) (sizeof(guint16) - available); break; } else { guint16 msg_ns_count = tvb_get_ntohs(tvb, offset); @@ -1059,7 +1206,7 @@ static int dissect_jxta_message(tvbuff_t * tvb, packet_info * pinfo, proto_tree available = tvb_reported_length_remaining(tvb, offset); if (available < sizeof(namespace_len)) { - needed = (gint) (available - sizeof(namespace_len)); + needed = (gint) (sizeof(namespace_len) - available); break; } @@ -1067,7 +1214,7 @@ static int dissect_jxta_message(tvbuff_t * tvb, packet_info * pinfo, proto_tree available = tvb_reported_length_remaining(tvb, offset + sizeof(namespace_len)); if (available < namespace_len) { - needed = (gint) (available - namespace_len); + needed = (gint) (namespace_len - available); break; } @@ -1078,7 +1225,7 @@ static int dissect_jxta_message(tvbuff_t * tvb, packet_info * pinfo, proto_tree /* parse element count */ available = tvb_reported_length_remaining(tvb, offset); if (available < sizeof(guint16)) { - needed = (gint) (available - sizeof(guint16)); + needed = (gint) (sizeof(guint16) - available); break; } else { guint16 elem_count = tvb_get_ntohs(tvb, offset); @@ -1099,7 +1246,7 @@ static int dissect_jxta_message(tvbuff_t * tvb, packet_info * pinfo, proto_tree if (0 == processed) { /* XXX bondolo Not really clear what we should do! */ -/* g_warning( "Failure processing message element #%d of %d of frame %d", each_elem, elem_count, pinfo->fd->num ); */ + g_warning( "Failure processing message element #%d of %d of frame %d", each_elem, elem_count, pinfo->fd->num ); return 0; } @@ -1127,6 +1274,7 @@ static int dissect_jxta_message(tvbuff_t * tvb, packet_info * pinfo, proto_tree address_to_str_buf(&pinfo->src, src_addr, sizeof src_addr); address_to_str_buf(&pinfo->dst, dst_addr, sizeof dst_addr); + /* append the port if appropriate */ if (PT_NONE != pinfo->ptype) { size_t len = strlen(src_addr); src_addr[len] = ':'; @@ -1267,7 +1415,7 @@ static int dissect_jxta_message_element(tvbuff_t * tvb, packet_info * pinfo, pro /* signature field */ available = tvb_reported_length_remaining(tvb, offset); if (available < sizeof(JXTA_MSGELEM_SIG)) { - needed = (gint) (available - sizeof(JXTA_MSGELEM_SIG)); + needed = (gint) (sizeof(JXTA_MSGELEM_SIG) - available); } if (tvb_memeql(tvb, offset, JXTA_MSGELEM_SIG, sizeof(JXTA_MSGELEM_SIG)) != 0) { @@ -1280,7 +1428,7 @@ static int dissect_jxta_message_element(tvbuff_t * tvb, packet_info * pinfo, pro /* namespace id field */ available = tvb_reported_length_remaining(tvb, offset); if (available < sizeof(guint8)) { - needed = (gint) (available - sizeof(guint8)); + needed = (gint) (sizeof(guint8) - available); break; } @@ -1289,7 +1437,7 @@ static int dissect_jxta_message_element(tvbuff_t * tvb, packet_info * pinfo, pro /* flags field */ available = tvb_reported_length_remaining(tvb, offset); if (available < sizeof(guint8)) { - needed = (gint) (available - sizeof(guint8)); + needed = (gint) (sizeof(guint8) - available); break; } else { flags = tvb_get_guint8(tvb, offset); @@ -1299,7 +1447,7 @@ static int dissect_jxta_message_element(tvbuff_t * tvb, packet_info * pinfo, pro /* name field */ available = tvb_reported_length_remaining(tvb, offset); if (available < sizeof(guint16)) { - needed = (gint) (available - sizeof(guint16)); + needed = (gint) (sizeof(guint16) - available); break; } else { guint16 name_len = tvb_get_ntohs(tvb, offset); @@ -1307,7 +1455,7 @@ static int dissect_jxta_message_element(tvbuff_t * tvb, packet_info * pinfo, pro available = tvb_reported_length_remaining(tvb, offset); if (available < name_len) { - needed = (gint) (available - name_len); + needed = (gint) (name_len - available); break; } @@ -1320,7 +1468,7 @@ static int dissect_jxta_message_element(tvbuff_t * tvb, packet_info * pinfo, pro available = tvb_reported_length_remaining(tvb, offset); if (available < sizeof(guint16)) { - needed = (gint) (available - sizeof(guint16)); + needed = (gint) (sizeof(guint16) - available); break; } @@ -1329,7 +1477,7 @@ static int dissect_jxta_message_element(tvbuff_t * tvb, packet_info * pinfo, pro available = tvb_reported_length_remaining(tvb, offset); if (available < type_len) { - needed = (gint) (available - type_len); + needed = (gint) (type_len - available); break; } @@ -1342,7 +1490,7 @@ static int dissect_jxta_message_element(tvbuff_t * tvb, packet_info * pinfo, pro available = tvb_reported_length_remaining(tvb, offset); if (available < sizeof(guint16)) { - needed = (gint) (available - sizeof(guint16)); + needed = (gint) (sizeof(guint16) - available); break; } @@ -1351,7 +1499,7 @@ static int dissect_jxta_message_element(tvbuff_t * tvb, packet_info * pinfo, pro available = tvb_reported_length_remaining(tvb, offset); if (available < encoding_len) { - needed = (gint) (available - encoding_len); + needed = (gint) (encoding_len - available); break; } @@ -1361,7 +1509,7 @@ static int dissect_jxta_message_element(tvbuff_t * tvb, packet_info * pinfo, pro /* content field */ available = tvb_reported_length_remaining(tvb, offset); if (available < sizeof(guint16)) { - needed = (gint) (available - sizeof(guint16)); + needed = (gint) (sizeof(guint16) - available); break; } else { guint32 content_len = tvb_get_ntohl(tvb, offset); @@ -1369,7 +1517,7 @@ static int dissect_jxta_message_element(tvbuff_t * tvb, packet_info * pinfo, pro available = tvb_reported_length_remaining(tvb, offset); if (available < content_len) { - needed = (gint) (available - content_len); + needed = (gint) (content_len - available); break; } @@ -1420,6 +1568,7 @@ static int dissect_jxta_message_element(tvbuff_t * tvb, packet_info * pinfo, pro gchar *mediatype = NULL; gboolean media_type_recognized = FALSE; tvbuff_t *element_content_tvb; + proto_item * jxta_elem_length_item = NULL; proto_tree_add_item(jxta_elem_tree, hf_jxta_element_sig, tvb, tree_offset, sizeof(JXTA_MSGELEM_SIG), FALSE); tree_offset += sizeof(JXTA_MSGELEM_SIG); @@ -1485,7 +1634,7 @@ static int dissect_jxta_message_element(tvbuff_t * tvb, packet_info * pinfo, pro /* content */ content_len = tvb_get_ntohl(tvb, tree_offset); - proto_tree_add_item(jxta_elem_tree, hf_jxta_element_content_len, tvb, tree_offset, sizeof(guint32), FALSE); + jxta_elem_length_item = proto_tree_add_item(jxta_elem_tree, hf_jxta_element_content_len, tvb, tree_offset, sizeof(guint32), FALSE); tree_offset += sizeof(guint32); element_content_tvb = tvb_new_subset(tvb, tree_offset, content_len, content_len); @@ -1496,7 +1645,20 @@ static int dissect_jxta_message_element(tvbuff_t * tvb, packet_info * pinfo, pro dissector_handle_t ssl_handle = find_dissector("ssl"); if (NULL != ssl_handle) { int processed = call_dissector(ssl_handle, element_content_tvb, pinfo, jxta_elem_tree); - media_type_recognized = processed > 0; + media_type_recognized = processed != 0; + } + } else if (0 == strcmp("application/gzip", mediatype)) { + tvbuff_t *uncomp_tvb = tvb_uncompress(element_content_tvb, 0, tvb_length(element_content_tvb)); + + if( NULL != uncomp_tvb ) { + proto_item_append_text( jxta_elem_length_item, " -> (%u uncompressed)", tvb_length(uncomp_tvb) ); + + tvb_set_child_real_data_tvbuff(element_content_tvb, uncomp_tvb); + add_new_data_source(pinfo, uncomp_tvb, "Uncompressed Element Content"); + + /* XXX bondolo 20060201 Force XML for uncompressed data. */ + media_type_recognized = dissector_try_string(media_type_dissector_table, + "text/xml", uncomp_tvb, pinfo, jxta_elem_tree); } } else { media_type_recognized = dissector_try_string(media_type_dissector_table, @@ -1533,19 +1695,20 @@ void proto_register_jxta(void) { module_t *jxta_module; - /* register re-init routine */ + media_type_dissector_table = find_dissector_table("media_type"); + + data_handle = find_dissector("data"); proto_jxta = proto_register_protocol("JXTA P2P", "JXTA", "jxta"); jxta_tap = register_tap("jxta"); - proto_welcome_jxta = proto_register_protocol("JXTA Connection Welcome Message", "JXTA Welcome", "jxta.welcome"); - - proto_udp_jxta = proto_register_protocol("JXTA UDP", "JXTA UDP", "jxta.udp"); + /* The JXTA Binary Message Wire Format : Registered and dissected by MIME type */ + proto_message_jxta = proto_register_protocol("JXTA Message", "JXTA Message", "jxta.message"); - proto_framing_jxta = proto_register_protocol("JXTA Message Framing", "JXTA Framing", "jxta.framing"); + message_jxta_handle = new_create_dissector_handle(dissect_jxta_message, proto_message_jxta); - proto_message_jxta = proto_register_protocol("JXTA Message", "JXTA Message", "jxta.message"); + dissector_add_string("media_type", "application/x-jxta-msg", message_jxta_handle); /* Register header fields */ proto_register_field_array(proto_jxta, hf, array_length(hf)); @@ -1554,6 +1717,7 @@ void proto_register_jxta(void) proto_register_subtree_array(ett, array_length(ett)); /* Register preferences */ + /* register re-init routine */ jxta_module = prefs_register_protocol(proto_jxta, proto_reg_handoff_jxta); prefs_register_bool_preference(jxta_module, "desegment", @@ -1568,37 +1732,27 @@ void proto_register_jxta(void) prefs_register_bool_preference(jxta_module, "tcp.heuristic", "Try to discover JXTA in TCP connections", "Enable to inspect TCP connections for JXTA conversations.", &gTCP_HEUR); + + prefs_register_bool_preference(jxta_module, "sctp.heuristic", "Try to discover JXTA in SCTP connections", + "Enable to inspect SCTP connections for JXTA conversations.", &gSCTP_HEUR); } +/** +* Update registrations in response to +**/ void proto_reg_handoff_jxta(void) { static gboolean init_done = FALSE; if (!init_done) { + /* XXX 20051004 bondolo We could dynamically add dissectors based upon prefs. */ new_register_dissector("jxta.udp", dissect_jxta_udp, proto_jxta); - heur_dissector_add("udp", dissect_jxta_UDP_heur, proto_udp_jxta); + heur_dissector_add("udp", dissect_jxta_UDP_heur, proto_jxta); - new_register_dissector("jxta.tcp", dissect_jxta_stream, proto_jxta); - tcp_jxta_handle = find_dissector("jxta.tcp"); + new_register_dissector("jxta.stream", dissect_jxta_stream, proto_jxta); + stream_jxta_handle = find_dissector("jxta.stream"); heur_dissector_add("tcp", dissect_jxta_TCP_heur, proto_jxta); - - init_done = TRUE; - } -} - -void proto_reg_handoff_message_jxta(void) -{ - static gboolean init_done = FALSE; - static dissector_handle_t message_jxta_handle; - - if (!init_done) { - data_handle = find_dissector("data"); - - message_jxta_handle = new_create_dissector_handle(dissect_jxta_message, proto_message_jxta); - - media_type_dissector_table = find_dissector_table("media_type"); - - dissector_add_string("media_type", "application/x-jxta-msg", message_jxta_handle); + heur_dissector_add("sctp", dissect_jxta_SCTP_heur, proto_jxta); init_done = TRUE; } |