2 * Routines for JXTA packet dissection
3 * Copyright 2004-06, Mike Duigou <bondolo@jxta.org>
4 * Heavily based on packet-jabber.c, which in turn is heavily based on
5 * on packet-acap.c, which in turn is heavily based on
6 * packet-imap.c, Copyright 1999, Richard Sharpe <rsharpe@ns.aus.com>
10 * Wireshark - Network traffic analyzer
11 * By Gerald Combs <gerald@wireshark.org>
12 * Copyright 1998 Gerald Combs
14 * Copied from packet-pop.c, packet-jabber.c, packet-udp.c
16 * JXTA specification from http://spec.jxta.org
18 * This program is free software; you can redistribute it and/or
19 * modify it under the terms of the GNU General Public License
20 * as published by the Free Software Foundation; either version 2
21 * of the License, or (at your option) any later version.
23 * This program is distributed in the hope that it will be useful,
24 * but WITHOUT ANY WARRANTY; without even the implied warranty of
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 * GNU General Public License for more details.
28 * You should have received a copy of the GNU General Public License
29 * along with this program; if not, write to the Free Software
30 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
43 #include <epan/packet.h>
44 #include <epan/conversation.h>
45 #include <epan/strutil.h>
46 #include <epan/prefs.h>
48 #include <epan/emem.h>
50 #include "packet-jxta.h"
52 static const gchar JXTA_UDP_SIG[] = { 'J', 'X', 'T', 'A' };
53 static const gchar JXTA_MSG_SIG[] = { 'j', 'x', 'm', 'g' };
54 static const gchar JXTA_MSGELEM_SIG[] = { 'j', 'x', 'e', 'l' };
56 static const gchar JXTA_WELCOME_MSG_SIG[] = { 'J', 'X', 'T', 'A', 'H', 'E', 'L', 'L', 'O', ' ' };
58 static const gchar* JXTA_WELCOME_MSG_VERSION_1_1 = "1.1";
60 static int proto_jxta = -1;
61 static int proto_message_jxta = -1;
62 static int jxta_tap = -1;
64 static dissector_table_t media_type_dissector_table = NULL;
65 static dissector_handle_t data_handle = NULL;
66 static dissector_handle_t stream_jxta_handle = NULL;
67 static dissector_handle_t message_jxta_handle;
69 static int hf_jxta_udp = -1;
70 static int hf_jxta_udpsig = -1;
71 static int hf_jxta_welcome = -1;
72 static int hf_jxta_welcome_initiator = -1;
73 static int hf_jxta_welcome_sig = -1;
74 static int hf_jxta_welcome_destAddr = -1;
75 static int hf_jxta_welcome_pubAddr = -1;
76 static int hf_jxta_welcome_peerid = -1;
77 static int hf_jxta_welcome_noProp = -1;
78 static int hf_jxta_welcome_variable = -1;
79 static int hf_jxta_welcome_version = -1;
80 static int hf_jxta_framing = -1;
81 static int hf_jxta_framing_header = -1;
82 static int hf_jxta_framing_header_name = -1;
83 static int hf_jxta_framing_header_value_length = -1;
84 static int hf_jxta_framing_header_value = -1;
85 static int hf_jxta_message_address = -1;
86 static int hf_jxta_message_src = -1;
87 static int hf_jxta_message_dst = -1;
88 static int hf_jxta_message_sig = -1;
89 static int hf_jxta_message_version = -1;
90 static int hf_jxta_message_namespaces_count = -1;
91 static int hf_jxta_message_namespace_name = -1;
92 static int hf_jxta_message_element_count = -1;
93 static int hf_jxta_element = -1;
94 static int hf_jxta_element_sig = -1;
95 static int hf_jxta_element_namespaceid = -1;
96 static int hf_jxta_element_flags = -1;
97 static int hf_jxta_element_flag_hasType = -1;
98 static int hf_jxta_element_flag_hasEncoding = -1;
99 static int hf_jxta_element_flag_hasSignature = -1;
100 static int hf_jxta_element_name = -1;
101 static int hf_jxta_element_type = -1;
102 static int hf_jxta_element_encoding = -1;
103 static int hf_jxta_element_content_len = -1;
104 static int hf_jxta_element_content = -1;
106 /** our header fields */
107 static hf_register_info hf[] = {
109 {"JXTA UDP", "jxta.udp", FT_NONE, BASE_NONE, NULL, 0x0,
113 {"Signature", "jxta.udpsig", FT_STRING, BASE_NONE, NULL, 0x0,
114 "JXTA UDP Signature", HFILL}
117 {"Welcome", "jxta.welcome", FT_NONE, BASE_NONE, NULL, 0x00,
118 "JXTA Connection Welcome Message", HFILL}
120 {&hf_jxta_welcome_initiator,
121 {"Initiator", "jxta.welcome.initiator", FT_BOOLEAN, BASE_NONE, NULL, 0x00,
122 "JXTA Connection Welcome Message Initiator", HFILL}
124 {&hf_jxta_welcome_sig,
125 {"Signature", "jxta.welcome.signature", FT_STRING, BASE_NONE, NULL, 0x0,
126 "JXTA Connection Welcome Message Signature", HFILL}
128 {&hf_jxta_welcome_destAddr,
129 {"Destination Address", "jxta.welcome.destAddr", FT_STRING, BASE_NONE, NULL, 0x0,
130 "JXTA Connection Welcome Message Destination Address", HFILL}
132 {&hf_jxta_welcome_pubAddr,
133 {"Public Address", "jxta.welcome.pubAddr", FT_STRING, BASE_NONE, NULL, 0x0,
134 "JXTA Connection Welcome Message Public Address", HFILL}
136 {&hf_jxta_welcome_peerid,
137 {"PeerID", "jxta.welcome.peerid", FT_STRING, BASE_NONE, NULL, 0x0,
138 "JXTA Connection Welcome Message PeerID", HFILL}
140 {&hf_jxta_welcome_noProp,
141 {"No Propagate Flag", "jxta.welcome.noPropFlag", FT_STRING, BASE_NONE, NULL, 0x0,
142 "JXTA Connection Welcome Message No Propagate Flag", HFILL}
144 {&hf_jxta_welcome_variable,
145 {"Variable Parameter", "jxta.welcome.variable", FT_STRING, BASE_NONE, NULL, 0x0,
146 "JXTA Connection Welcome Message Variable Parameter", HFILL}
148 {&hf_jxta_welcome_version,
149 {"Version", "jxta.welcome.version", FT_STRING, BASE_NONE, NULL, 0x0,
150 "JXTA Connection Welcome Message Version", HFILL}
153 {"Framing", "jxta.framing", FT_NONE, BASE_NONE, NULL, 0x0,
154 "JXTA Message Framing", HFILL}
156 {&hf_jxta_framing_header,
157 {"Header", "jxta.framing.header", FT_NONE, BASE_NONE, NULL, 0x0,
158 "JXTA Message Framing Header", HFILL}
160 {&hf_jxta_framing_header_name,
161 {"Name", "jxta.framing.header.name", FT_UINT_STRING, BASE_NONE, NULL, 0x0,
162 "JXTA Message Framing Header Name", HFILL}
164 {&hf_jxta_framing_header_value_length,
165 {"Value Length", "jxta.framing.header.valuelen", FT_UINT16, BASE_DEC, NULL, 0x0,
166 "JXTA Message Framing Header Value Length", HFILL}
168 {&hf_jxta_framing_header_value,
169 {"Value", "jxta.framing.header.value", FT_BYTES, BASE_HEX, NULL, 0x0,
170 "JXTA Message Framing Header Value", HFILL}
172 {&hf_jxta_message_address,
173 {"Address", "jxta.message.address", FT_STRING, BASE_NONE, NULL, 0x0,
174 "JXTA Message Address (source or destination)", HFILL}
176 {&hf_jxta_message_src,
177 {"Source", "jxta.message.source", FT_STRING, BASE_NONE, NULL, 0x0,
178 "JXTA Message Source", HFILL}
180 {&hf_jxta_message_dst,
181 {"Destination", "jxta.message.destination", FT_STRING, BASE_NONE, NULL, 0x0,
182 "JXTA Message Destination", HFILL}
184 {&hf_jxta_message_sig,
185 {"Signature", "jxta.message.signature", FT_STRING, BASE_NONE, NULL, 0x0,
186 "JXTA Message Signature", HFILL}
188 {&hf_jxta_message_version,
189 {"Version", "jxta.message.version", FT_UINT8, BASE_DEC, NULL, 0x0,
190 "JXTA Message Version", HFILL}
192 {&hf_jxta_message_namespaces_count,
193 {"Namespace Count", "jxta.message.namespaces", FT_UINT16, BASE_DEC, NULL, 0x0,
194 "JXTA Message Namespaces", HFILL}
196 {&hf_jxta_message_namespace_name,
197 {"Namespace Name", "jxta.message.namespace.name", FT_UINT_STRING, BASE_NONE, NULL, 0x0,
198 "JXTA Message Namespace Name", HFILL}
200 {&hf_jxta_message_element_count,
201 {"Element Count", "jxta.message.elements", FT_UINT16, BASE_DEC, NULL, 0x0,
202 "JXTA Message Element Count", HFILL}
205 {"JXTA Message Element", "jxta.message.element", FT_NONE, BASE_NONE, NULL, 0x0,
206 "JXTA Message Element", HFILL}
208 {&hf_jxta_element_sig,
209 {"Signature", "jxta.message.element.signature", FT_STRING, BASE_NONE, NULL, 0x0,
210 "JXTA Message Element Signature", HFILL}
212 {&hf_jxta_element_namespaceid,
213 {"Namespace ID", "jxta.message.element.namespaceid", FT_UINT8, BASE_DEC, NULL, 0x0,
214 "JXTA Message Element Namespace ID", HFILL}
216 {&hf_jxta_element_flags,
217 {"Flags", "jxta.message.element.flags", FT_UINT8, BASE_HEX, NULL, 0x0,
218 "JXTA Message Element Flags", HFILL}
220 {&hf_jxta_element_flag_hasType,
221 {"hasType", "jxta.message.element.flags.hasType", FT_BOOLEAN, 3, TFS(&flags_set_truth), 0x01,
222 "JXTA Message Element Flag -- hasType", HFILL}
224 {&hf_jxta_element_flag_hasEncoding,
225 {"hasEncoding", "jxta.message.element.flags.hasEncoding", FT_BOOLEAN, 3, TFS(&flags_set_truth), 0x02,
226 "JXTA Message Element Flag -- hasEncoding", HFILL}
228 {&hf_jxta_element_flag_hasSignature,
229 {"hasSignature", "jxta.message.element.flags.hasSignature", FT_BOOLEAN, 3, TFS(&flags_set_truth), 0x04,
230 "JXTA Message Element Flag -- hasSignature", HFILL}
232 {&hf_jxta_element_name,
233 {"Element Name", "jxta.message.element.name", FT_UINT_STRING, BASE_NONE, NULL, 0x0,
234 "JXTA Message Element Name", HFILL}
236 {&hf_jxta_element_type,
237 {"Element Type", "jxta.message.element.type", FT_UINT_STRING, BASE_NONE, NULL, 0x0,
238 "JXTA Message Element Name", HFILL}
240 {&hf_jxta_element_encoding,
241 {"Element Type", "jxta.message.element.encoding", FT_UINT_STRING, BASE_NONE, NULL, 0x0,
242 "JXTA Message Element Encoding", HFILL}
244 {&hf_jxta_element_content_len,
245 {"Element Content Length", "jxta.message.element.content.length", FT_UINT32, BASE_DEC, NULL, 0x0,
246 "JXTA Message Element Content Length", HFILL}
248 {&hf_jxta_element_content,
249 {"Element Content", "jxta.message.element.content", FT_BYTES, BASE_HEX, NULL, 0x0,
250 "JXTA Message Element Content", HFILL}
255 * JXTA Protocol subtree handles
257 static gint ett_jxta = -1;
258 static gint ett_jxta_welcome = -1;
259 static gint ett_jxta_udp = -1;
260 static gint ett_jxta_framing = -1;
261 static gint ett_jxta_framing_header = -1;
262 static gint ett_jxta_msg = -1;
263 static gint ett_jxta_elem = -1;
264 static gint ett_jxta_elem_flags = -1;
267 * JXTA Protocol subtree array
269 static gint *const ett[] = {
274 &ett_jxta_framing_header,
283 static gboolean gDESEGMENT = TRUE;
284 static gboolean gUDP_HEUR = TRUE;
285 static gboolean gTCP_HEUR = TRUE;
286 static gboolean gSCTP_HEUR = FALSE;
289 * Stream Conversation data
291 struct jxta_stream_conversation_data {
294 address initiator_tpt_address;
295 guint32 initiator_tpt_port;
296 guint32 initiator_welcome_frame;
297 address initiator_address;
299 address receiver_tpt_address;
300 guint32 receiver_tpt_port;
301 guint32 receiver_welcome_frame;
302 address receiver_address;
305 typedef struct jxta_stream_conversation_data jxta_stream_conversation_data;
310 static gboolean dissect_jxta_UDP_heur(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree);
311 static gboolean dissect_jxta_TCP_heur(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree);
312 static gboolean dissect_jxta_SCTP_heur(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree);
314 static int dissect_jxta_udp(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree);
315 static int dissect_jxta_stream(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree);
316 static conversation_t *get_tpt_conversation(packet_info * pinfo, gboolean create);
318 static int dissect_jxta_welcome(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, address * found_addr, gboolean initiator);
319 static int dissect_jxta_message_framing(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, guint64 * content_length,
320 gchar ** content_type);
321 static int dissect_jxta_message(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree);
322 static int dissect_jxta_message_element(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, guint ns_count,
323 const gchar ** namespaces);
325 void proto_reg_handoff_jxta(void);
328 * Heuristically dissect a tvbuff containing a JXTA UDP Message
330 * @param tvb The buffer to dissect.
331 * @param pinfo Packet Info.
332 * @param tree The protocol tree.
333 * @return TRUE if the tvb contained JXTA data which was dissected otherwise FALSE
335 static gboolean dissect_jxta_UDP_heur(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
337 /* This is a heuristic dissector, which means we get all the UDP
338 * traffic not sent to a known dissector and not claimed by
339 * a heuristic dissector called before us!
341 int save_desegment_offset;
342 guint32 save_desegment_len;
348 if (tvb_memeql(tvb, 0, JXTA_UDP_SIG, sizeof(JXTA_UDP_SIG)) != 0) {
352 save_desegment_offset = pinfo->desegment_offset;
353 save_desegment_len = pinfo->desegment_len;
354 ret = dissect_jxta_udp(tvb, pinfo, tree);
357 * UDP is not a packet stream protocol, so the UDP dissector
358 * should not, and will not, do the sort of dissection help
359 * that the TCP dissector will. If JXTA messages don't
360 * start and end on UDP packet boundaries, the JXTA dissector
361 * will have to do its own byte stream reassembly.
363 pinfo->desegment_offset = save_desegment_offset;
364 pinfo->desegment_len = save_desegment_len;
366 } else if (ret == 0) {
370 pinfo->desegment_offset = save_desegment_offset;
371 pinfo->desegment_len = save_desegment_len;
375 * A clear acceptance.
382 * Heuristically dissect a tvbuff containing a JXTA TCP Stream
384 * @param tvb The buffer to dissect.
385 * @param pinfo Packet Info.
386 * @param tree The protocol tree.
387 * @return TRUE if the tvb contained JXTA data which was dissected otherwise FALSE
389 static gboolean dissect_jxta_TCP_heur(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
391 /* This is a heuristic dissector, which means we get all the TCP
392 * traffic not sent to a known dissector and not claimed by
393 * a heuristic dissector called before us!
395 int save_desegment_offset;
396 guint32 save_desegment_len;
402 save_desegment_offset = pinfo->desegment_offset;
403 save_desegment_len = pinfo->desegment_len;
404 ret = dissect_jxta_stream(tvb, pinfo, tree);
407 * A heuristic dissector for a TCP-based protocol can reject
408 * a packet, or it can request that more data be provided.
409 * It must not attempt to do both, as the notion of doing both
410 * is nonsensical - if the packet isn't considered a packet
411 * for the dissector's protocol, that dissector won't be
412 * dissecting it no matter *how* much more data is added.
414 * Therefore, we treat a negative return from
415 * dissect_jxta_stream() as a rejection.
417 * If that's not desired - i.e., if we should keep trying to get
418 * more data, in the hopes that we'll eventually be able to
419 * determine whether the packet is a JXTA packet or not - we
420 * should, in this case, leave pinfo->desegment_offset and
421 * pinfo->desegment_len alone, and return TRUE, *NOT* FALSE.
423 pinfo->desegment_offset = save_desegment_offset;
424 pinfo->desegment_len = save_desegment_len;
426 } else if (ret == 0) {
430 pinfo->desegment_offset = save_desegment_offset;
431 pinfo->desegment_len = save_desegment_len;
435 * A clear acceptance.
442 * Heuristically dissect a tvbuff containing a JXTA SCTP Stream
444 * @param tvb The buffer to dissect.
445 * @param pinfo Packet Info.
446 * @param tree The protocol tree.
447 * @return TRUE if the tvb contained JXTA data which was dissected otherwise FALSE
449 static gboolean dissect_jxta_SCTP_heur(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
451 /* This is a heuristic dissector, which means we get all the SCTP
452 * traffic not sent to a known dissector and not claimed by
453 * a heuristic dissector called before us!
455 int save_desegment_offset;
456 guint32 save_desegment_len;
462 save_desegment_offset = pinfo->desegment_offset;
463 save_desegment_len = pinfo->desegment_len;
464 ret = dissect_jxta_stream(tvb, pinfo, tree);
467 * SCTP is not a byte stream protocol, so the SCTP dissector
468 * should not, and will not, do the sort of dissection help
469 * that the SCTP dissector will. If JXTA messages don't
470 * start and end on SCTP packet boundaries, the JXTA dissector
471 * will have to do its own byte stream reassembly.
473 * The SCTP dissector currently won't do reassembly. If that
474 * causes a problem for the JXTA dissector, the correct fix
475 * is to implement reassembly in the SCTP dissector, so *all*
476 * dissectors for protocols running atop SCTP can benefit from
479 pinfo->desegment_offset = save_desegment_offset;
480 pinfo->desegment_len = save_desegment_len;
482 } else if (ret == 0) {
486 pinfo->desegment_offset = save_desegment_offset;
487 pinfo->desegment_len = save_desegment_len;
491 * A clear acceptance.
498 * Dissect a tvbuff containing a JXTA UDP header, JXTA Message framing and a JXTA Message
500 * @param tvb The buffer to dissect.
501 * @param pinfo Packet Info.
502 * @param tree The protocol tree.
503 * @return Number of bytes from the tvbuff_t which were processed, 0 (zero) if
504 * the packet was not recognized as a JXTA packet and negative if the
505 * dissector needs more bytes in order to process a PDU.
507 static int dissect_jxta_udp(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
513 conversation_t *conversation =
514 find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
516 if (conversation == NULL) {
518 * No conversation exists yet - create one.
521 conversation_new(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
524 DISSECTOR_ASSERT(find_dissector("jxta.udp"));
526 conversation_set_dissector(conversation, find_dissector("jxta.udp"));
529 tvbuff_t *jxta_message_framing_tvb;
531 guint64 content_length = -1;
532 gchar *content_type = NULL;
534 available = tvb_reported_length_remaining(tvb, offset);
535 if (available < sizeof(JXTA_UDP_SIG)) {
536 needed = (gint) (sizeof(JXTA_UDP_SIG) - available);
540 if (tvb_memeql(tvb, offset, JXTA_UDP_SIG, sizeof(JXTA_UDP_SIG)) != 0) {
545 offset += sizeof(JXTA_UDP_SIG);
547 jxta_message_framing_tvb = tvb_new_subset(tvb, offset, -1, -1);
548 processed = dissect_jxta_message_framing(jxta_message_framing_tvb, pinfo, NULL, &content_length, &content_type);
550 if ((0 == processed) || (NULL == content_type) || (content_length <= 0) || (content_length > UINT_MAX)) {
551 /** Buffer did not begin with valid framing headers */
560 /* Redo header processing, this time populating the tree. */
561 processed = dissect_jxta_message_framing(jxta_message_framing_tvb, pinfo, tree, &content_length, &content_type);
566 available = tvb_reported_length_remaining(tvb, offset);
567 if (available < content_length) {
568 needed = (gint) (content_length - available);
572 offset += (guint) content_length;
577 if ((needed > 0) && gDESEGMENT && pinfo->can_desegment) {
578 pinfo->desegment_offset = 0;
579 pinfo->desegment_len = needed;
583 if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
584 col_set_str(pinfo->cinfo, COL_PROTOCOL, "JXTA");
588 guint tree_offset = 0;
589 proto_item *jxta_tree_item =
590 proto_tree_add_protocol_format(tree, proto_jxta, tvb, offset, -1, "JXTA" );
591 proto_tree *jxta_tree = proto_item_add_subtree(jxta_tree_item, ett_jxta);
592 proto_item *jxta_udp_tree_item =
593 proto_tree_add_none_format(jxta_tree, hf_jxta_udp, tvb, tree_offset, -1, "JXTA UDP Message");
594 proto_tree *jxta_udp_tree = proto_item_add_subtree(jxta_udp_tree_item, ett_jxta_udp);
595 tvbuff_t *jxta_message_framing_tvb;
596 guint64 content_length = -1;
597 gchar *content_type = NULL;
598 tvbuff_t *jxta_message_tvb;
599 gboolean dissected = FALSE;
602 proto_tree_add_item(jxta_udp_tree, hf_jxta_udpsig, tvb, tree_offset, sizeof(JXTA_UDP_SIG), FALSE);
603 tree_offset += sizeof(JXTA_UDP_SIG);
605 jxta_message_framing_tvb = tvb_new_subset(tvb, tree_offset, -1, -1);
606 processed = dissect_jxta_message_framing(jxta_message_framing_tvb, pinfo, NULL, &content_length, &content_type);
608 if ((0 == processed) || (NULL == content_type) || (content_length <= 0) || (content_length > UINT_MAX)) {
609 /** Buffer did not begin with valid framing headers */
613 processed = dissect_jxta_message_framing(jxta_message_framing_tvb, pinfo, tree, &content_length, &content_type);
615 tree_offset += processed;
617 jxta_message_tvb = tvb_new_subset(tvb, tree_offset, (gint) content_length, (gint) content_length);
619 dissected = dissector_try_string(media_type_dissector_table, content_type, jxta_message_tvb, pinfo, tree);
622 call_dissector(data_handle, jxta_message_tvb, pinfo, tree);
625 tree_offset += (guint) content_length;
627 proto_item_set_end(jxta_udp_tree_item, tvb, tree_offset);
629 DISSECTOR_ASSERT(offset == tree_offset);
636 * Dissect a tvbuff containing JXTA stream PDUs. This commonly includes
637 * connections over TCP sockets.
639 * <p/>The stream (in both directions) will consist of a JXTA Welcome Message
640 * followed by an indeterminate number of JXTA Message Framing Headers and
643 * @param tvb The buffer to dissect.
644 * @param pinfo Packet Info.
645 * @param tree The protocol tree.
646 * @return Number of bytes from the tvbuff_t which were processed, 0 (zero) if
647 * the packet was not recognized as a JXTA packet and negative if the
648 * dissector needs more bytes in order to process a PDU.
650 static int dissect_jxta_stream(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
653 guint available = tvb_reported_length_remaining(tvb, offset);
656 conversation_t *tpt_conversation = NULL;
657 jxta_stream_conversation_data *tpt_conv_data = NULL;
658 proto_item *jxta_tree_item = NULL;
659 proto_tree *jxta_tree = NULL;
661 /*g_message("Dissecting %s : %d", (NULL != tree) ? "for display" : "", pinfo->fd->num );*/
663 if (available < sizeof(JXTA_WELCOME_MSG_SIG)) {
664 needed = (gint) (sizeof(JXTA_WELCOME_MSG_SIG) - available);
668 if (0 == tvb_memeql(tvb, 0, JXTA_WELCOME_MSG_SIG, sizeof(JXTA_WELCOME_MSG_SIG))) {
669 /* The beginning of a JXTA stream connection */
670 address *welcome_addr;
671 gboolean initiator = FALSE;
673 tpt_conversation = get_tpt_conversation(pinfo, TRUE);
674 tpt_conv_data = (jxta_stream_conversation_data *) conversation_get_proto_data(tpt_conversation, proto_jxta);
676 if (0 == tpt_conv_data->initiator_welcome_frame) {
677 /* The initiator welcome frame */
678 tpt_conv_data->tpt_ptype = pinfo->ptype;
679 tpt_conv_data->initiator_welcome_frame = pinfo->fd->num;
680 COPY_ADDRESS(&tpt_conv_data->initiator_tpt_address, &pinfo->src);
681 tpt_conv_data->initiator_tpt_port = pinfo->srcport;
683 welcome_addr = &tpt_conv_data->initiator_address;
686 if (tpt_conv_data->initiator_welcome_frame >= pinfo->fd->num) {
687 /* what we saw previously was the receiver welcome message */
688 tpt_conv_data->receiver_welcome_frame = tpt_conv_data->initiator_welcome_frame;
689 tpt_conv_data->receiver_tpt_address = tpt_conv_data->initiator_tpt_address;
690 tpt_conv_data->receiver_tpt_port = tpt_conv_data->initiator_tpt_port;
691 tpt_conv_data->receiver_address = tpt_conv_data->initiator_address;
692 tpt_conv_data->initiator_welcome_frame = pinfo->fd->num;
693 COPY_ADDRESS(&tpt_conv_data->initiator_tpt_address, &pinfo->src);
694 tpt_conv_data->initiator_tpt_port = pinfo->srcport;
696 welcome_addr = &tpt_conv_data->initiator_address;
699 /* The receiver welcome frame */
700 tpt_conv_data->tpt_ptype = pinfo->ptype;
701 tpt_conv_data->receiver_welcome_frame = pinfo->fd->num;
702 COPY_ADDRESS(&tpt_conv_data->receiver_tpt_address, &pinfo->src);
703 tpt_conv_data->receiver_tpt_port = pinfo->srcport;
705 welcome_addr = &tpt_conv_data->receiver_address;
710 processed = dissect_jxta_welcome(tvb, pinfo, NULL, welcome_addr, initiator);
712 if( processed < 0 ) {
717 /* redo, this time creating the display tree. */
719 proto_tree_add_protocol_format(tree, proto_jxta, tvb, offset, -1, "JXTA" );
720 jxta_tree = proto_item_add_subtree(jxta_tree_item, ett_jxta);
722 processed = dissect_jxta_welcome(tvb, pinfo, jxta_tree, welcome_addr, initiator);
724 /* Somewhere in the middle of a JXTA stream connection */
725 guint64 content_length = -1;
726 gchar *content_type = NULL;
727 gint headers_len = dissect_jxta_message_framing(tvb, pinfo, NULL, &content_length, &content_type);
729 /*g_message("%d Tpt %s:%d -> %s:%d tvb len=%d\n\t%s %u", pinfo->fd->num,
730 address_to_str(&pinfo->src), pinfo->srcport,
731 address_to_str(&pinfo->dst), pinfo->destport,
732 tvb_reported_length_remaining(tvb, 0),
733 (content_type) ? content_type : "[unknown content type]", (guint) content_length);*/
735 if ((0 == headers_len) || (NULL == content_type) || (content_length <= 0) || (content_length > UINT_MAX)) {
736 /** Buffer did not begin with valid framing headers */
740 if (headers_len < 0) {
741 /* negative headers_len means we need more bytes */
742 needed = -headers_len;
747 proto_tree_add_protocol_format(tree, proto_jxta, tvb, offset, -1, "JXTA" );
748 jxta_tree = proto_item_add_subtree(jxta_tree_item, ett_jxta);
750 /* Redo header processing, this time populating the tree. */
751 headers_len = dissect_jxta_message_framing(tvb, pinfo, jxta_tree, &content_length, &content_type);
753 available = tvb_reported_length_remaining(tvb, offset + headers_len);
754 if (available >= content_length) {
755 tvbuff_t *jxta_message_tvb = tvb_new_subset(tvb, offset + headers_len, (gint) content_length, (gint) content_length);
756 conversation_t *peer_conversation = NULL;
757 address saved_src_addr;
758 guint32 saved_src_port = 0;
759 address saved_dst_addr;
760 guint32 saved_dst_port = 0;
761 port_type saved_port_type = PT_NONE;
764 tpt_conversation = get_tpt_conversation(pinfo, TRUE);
766 if (NULL != tpt_conversation) {
767 tpt_conv_data = (jxta_stream_conversation_data *) conversation_get_proto_data(tpt_conversation, proto_jxta);
769 if ((AT_NONE != tpt_conv_data->initiator_address.type) && (AT_NONE != tpt_conv_data->receiver_address.type)) {
771 find_conversation(pinfo->fd->num, &tpt_conv_data->initiator_address, &tpt_conv_data->receiver_address,
772 PT_NONE, 0, 0, NO_PORT_B);
774 if (NULL == peer_conversation) {
776 conversation_new(pinfo->fd->num, &tpt_conv_data->initiator_address,
777 &tpt_conv_data->receiver_address, PT_NONE, 0, 0, NO_PORT_B);
778 conversation_set_dissector(peer_conversation, stream_jxta_handle);
782 g_warning("Uninitialized peer conversation");
786 /* Use our source and destination addresses if we have them */
787 if (NULL != peer_conversation) {
788 saved_src_addr = pinfo->src;
789 saved_src_port = pinfo->srcport;
790 saved_dst_addr = pinfo->dst;
791 saved_dst_port = pinfo->destport;
792 saved_port_type = pinfo->ptype;
793 /*g_message("%d Tpt %s:%d -> %s:%d", pinfo->fd->num, ip_to_str(tpt_conv_data->initiator_tpt_address.data),
794 tpt_conv_data->initiator_tpt_port, ip_to_str(tpt_conv_data->receiver_tpt_address.data),
795 tpt_conv_data->receiver_tpt_port);*/
796 if (ADDRESSES_EQUAL(&pinfo->src, &tpt_conv_data->initiator_tpt_address)
797 && tpt_conv_data->initiator_tpt_port == pinfo->srcport) {
798 /*g_message("%d From initiator : %s -> %s ", pinfo->fd->num, tpt_conv_data->initiator_address.data,
799 tpt_conv_data->receiver_address.data);*/
800 pinfo->src = tpt_conv_data->initiator_address;
801 pinfo->dst = tpt_conv_data->receiver_address;
802 } else if (ADDRESSES_EQUAL(&pinfo->src, &tpt_conv_data->receiver_tpt_address) &&
803 tpt_conv_data->receiver_tpt_port == pinfo->srcport) {
804 /*g_message("%d From receiver : %s -> %s ", pinfo->fd->num, tpt_conv_data->receiver_address.data,
805 tpt_conv_data->initiator_address.data);*/
806 pinfo->src = tpt_conv_data->receiver_address;
807 pinfo->dst = tpt_conv_data->initiator_address;
809 /*g_message("%d Nothing matches %s:%d -> %s:%d", pinfo->fd->num, ip_to_str(pinfo->src.data), pinfo->srcport,
810 ip_to_str(pinfo->dst.data), pinfo->destport);*/
812 /* JXTA doesn't use ports */
813 pinfo->ptype = PT_NONE;
819 dissector_try_string(media_type_dissector_table, content_type, jxta_message_tvb, pinfo, tree);
822 call_dissector(data_handle, jxta_message_tvb, pinfo, jxta_tree);
825 /* Restore the saved src and dst addresses */
826 if (NULL != peer_conversation) {
827 pinfo->src = saved_src_addr;
828 pinfo->srcport = saved_src_port;
829 pinfo->dst = saved_dst_addr;
830 pinfo->destport = saved_dst_port;
831 pinfo->ptype = saved_port_type;
834 processed = (guint) content_length + headers_len;
836 /* we need more bytes before we can process message body. */
837 needed = (gint) ((guint) content_length - available);
845 if ((needed > 0) && gDESEGMENT && pinfo->can_desegment) {
846 /*g_message( "Requesting %d more bytes", needed );*/
847 pinfo->desegment_offset = offset;
848 pinfo->desegment_len = needed;
856 * Find or possibly create a transport conversation object for the connection
857 * which is associated with the packet info.
859 * @param pinfo The packet info from the underlying transport.
860 * @param create If TRUE then create a new conversation object if necessary.
862 static conversation_t *get_tpt_conversation(packet_info * pinfo, gboolean create)
864 conversation_t *tpt_conversation =
865 find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
866 jxta_stream_conversation_data *tpt_conv_data;
868 if (tpt_conversation == NULL) {
874 * No conversation exists yet - create one.
877 conversation_new(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
880 conversation_set_dissector(tpt_conversation, stream_jxta_handle);
882 tpt_conv_data = (jxta_stream_conversation_data *) conversation_get_proto_data(tpt_conversation, proto_jxta);
884 if (NULL == tpt_conv_data) {
885 tpt_conv_data = se_alloc(sizeof(jxta_stream_conversation_data));
886 tpt_conv_data->tpt_ptype = pinfo->ptype;
888 COPY_ADDRESS(&tpt_conv_data->initiator_tpt_address, &pinfo->src);
889 tpt_conv_data->initiator_tpt_port = pinfo->srcport;
890 tpt_conv_data->initiator_welcome_frame = 0;
891 /* XXX bondolo This is not quite correct as it should include port until a peerid can be associated. */
892 COPY_ADDRESS(&tpt_conv_data->initiator_address, &pinfo->src);
894 COPY_ADDRESS(&tpt_conv_data->receiver_tpt_address, &pinfo->dst);
895 tpt_conv_data->receiver_tpt_port = pinfo->destport;
896 tpt_conv_data->receiver_welcome_frame = 0;
897 /* XXX bondolo This is not quite correct as it should include port until a peerid can be associated. */
898 COPY_ADDRESS(&tpt_conv_data->receiver_address, &pinfo->dst);
900 conversation_add_proto_data(tpt_conversation, proto_jxta, tpt_conv_data);
903 return tpt_conversation;
907 * Dissect a tvbuff containing a JXTA Welcome Message
909 * @param tvb The buffer to dissect.
910 * @param pinfo Packet Info.
911 * @param tree The protocol tree.
912 * @param found_addr The address found in the welcome message.
913 * @param initiator If TRUE then we believe this welcome message to be the initiator's.
914 * @return Number of bytes from the tvbuff_t which were processed, 0 (zero) if
915 * the packet was not recognized as a JXTA packet and negative if the
916 * dissector needs more bytes in order to process a PDU.
918 static int dissect_jxta_welcome(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, address * found_addr, gboolean initiator)
923 guint available = tvb_reported_length_remaining(tvb, offset);
924 gchar **tokens = NULL;
926 if (available < sizeof(JXTA_WELCOME_MSG_SIG)) {
927 return (gint) (available - sizeof(JXTA_WELCOME_MSG_SIG));
930 if (0 != tvb_memeql(tvb, 0, JXTA_WELCOME_MSG_SIG, sizeof(JXTA_WELCOME_MSG_SIG))) {
935 first_linelen = tvb_find_line_end(tvb, offset, -1, &afterwelcome, gDESEGMENT && pinfo->can_desegment);
937 if (-1 == first_linelen) {
938 if (available > 4096) {
939 /* it's too far too be reasonable */
942 /* ask for more bytes */
947 /* Dissect the Welcome Message */
949 if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
950 col_set_str(pinfo->cinfo, COL_PROTOCOL, "JXTA");
953 if (check_col(pinfo->cinfo, COL_INFO)) {
954 col_add_str(pinfo->cinfo, COL_INFO, "Welcome");
958 gchar *welcomeline = tvb_get_ephemeral_string(tvb, offset, first_linelen);
959 gchar **current_token;
960 guint token_offset = offset;
961 proto_item *jxta_welcome_tree_item = NULL;
962 proto_tree *jxta_welcome_tree = NULL;
964 tokens = g_strsplit(welcomeline, " ", 255);
965 current_token = tokens;
968 jxta_welcome_tree_item =
969 proto_tree_add_none_format(tree, hf_jxta_welcome, tvb, offset, afterwelcome,
970 "JXTA Connection Welcome Message, %s", welcomeline);
971 jxta_welcome_tree = proto_item_add_subtree(jxta_welcome_tree_item, ett_jxta_welcome);
974 if (jxta_welcome_tree) {
975 proto_item *jxta_welcome_initiator_item =
976 proto_tree_add_boolean(jxta_welcome_tree, hf_jxta_welcome_initiator, tvb, 0, 0, initiator);
977 PROTO_ITEM_SET_GENERATED(jxta_welcome_initiator_item);
980 if (NULL != *current_token) {
981 if (jxta_welcome_tree) {
982 proto_tree_add_item(jxta_welcome_tree, hf_jxta_welcome_sig, tvb, token_offset, strlen(*current_token), FALSE);
985 token_offset += strlen(*current_token) + 1;
988 /* invalid welcome message */
993 if (NULL != *current_token) {
994 if (jxta_welcome_tree) {
995 proto_tree_add_item(jxta_welcome_tree, hf_jxta_welcome_destAddr, tvb, token_offset, strlen(*current_token),
999 token_offset += strlen(*current_token) + 1;
1002 /* invalid welcome message */
1007 if (NULL != *current_token) {
1008 if (jxta_welcome_tree) {
1009 proto_tree_add_item(jxta_welcome_tree, hf_jxta_welcome_pubAddr, tvb, token_offset, strlen(*current_token), FALSE);
1012 token_offset += strlen(*current_token) + 1;
1015 /* invalid welcome message */
1020 if (NULL != *current_token) {
1021 if (jxta_welcome_tree) {
1022 proto_tree_add_item(jxta_welcome_tree, hf_jxta_welcome_peerid, tvb, token_offset, strlen(*current_token), FALSE);
1025 if (check_col(pinfo->cinfo, COL_INFO)) {
1026 col_append_str(pinfo->cinfo, COL_INFO, (initiator ? " -> " : " <- ") );
1027 col_append_str(pinfo->cinfo, COL_INFO, *current_token);
1030 if (NULL != found_addr) {
1031 found_addr->type = AT_URI;
1032 found_addr->len = strlen(*current_token);
1033 /* FIXME 20050605 bondolo THIS ALLOCATION IS A MEMORY LEAK! */
1034 found_addr->data = g_strdup(*current_token);
1037 token_offset += strlen(*current_token) + 1;
1040 /* invalid welcome message */
1045 if (NULL != *current_token) {
1046 int variable_tokens = 0;
1047 gchar **variable_token = current_token;
1049 while(NULL != *variable_token) {
1054 if( variable_tokens < 1 ) {
1055 /* invalid welcome message */
1060 if( (2 == variable_tokens) && (0 == strcmp(JXTA_WELCOME_MSG_VERSION_1_1, current_token[variable_tokens -1])) ) {
1061 if (jxta_welcome_tree) {
1062 proto_tree_add_item(jxta_welcome_tree, hf_jxta_welcome_noProp, tvb, token_offset, strlen(*current_token), FALSE);
1065 token_offset += strlen(*current_token) + 1;
1068 if (jxta_welcome_tree) {
1069 proto_tree_add_item(jxta_welcome_tree, hf_jxta_welcome_version, tvb, token_offset, strlen(*current_token), FALSE);
1072 /* Unrecognized Welcome Version */
1073 int each_variable_token;
1075 for( each_variable_token = 0; each_variable_token < variable_tokens; each_variable_token++ ) {
1076 if (jxta_welcome_tree) {
1077 jxta_welcome_tree_item = proto_tree_add_item(jxta_welcome_tree,
1078 (each_variable_token < (variable_tokens -1) ? hf_jxta_welcome_variable : hf_jxta_welcome_version),
1079 tvb, token_offset, strlen(*current_token), FALSE);
1081 proto_item_append_text(jxta_welcome_tree_item, " (UNRECOGNIZED)");
1084 token_offset += strlen(*current_token) + 1;
1089 /* invalid welcome message */
1098 col_set_writable(pinfo->cinfo, FALSE);
1100 return afterwelcome;
1104 * Dissect a tvbuff containing JXTA Message framing.
1106 * @param tvb The buffer to dissect.
1107 * @param pinfo Packet Info.
1108 * @param tree The protocol tree.
1109 * @param content_length Pointer to a buffer for storing the value of the
1110 * "content-length" header or NULL.
1111 * @param content_type Pointer-to-a-pointer for a new buffer for storing the
1112 * value of the "content_type-length" header or NULL.
1113 * @return Number of bytes from the tvbuff_t which were processed, 0 (zero) if
1114 * the packet was not recognized as a JXTA packet and negative if the
1115 * dissector needs more bytes in order to process a PDU.
1117 static int dissect_jxta_message_framing(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, guint64 * content_length,
1118 gchar ** content_type)
1125 * First go around. Make sure all of the bytes are there.
1128 guint8 headername_len;
1129 guint8 headername_offset;
1130 guint16 headervalue_len;
1131 guint16 headervalue_offset;
1133 available = tvb_reported_length_remaining(tvb, offset);
1134 if (available < sizeof(guint8)) {
1135 needed = (gint) (sizeof(guint8) - available);
1138 headername_len = tvb_get_guint8(tvb, offset);
1139 offset += sizeof(guint8);
1140 headername_offset = offset;
1142 available = tvb_reported_length_remaining(tvb, offset);
1143 if (available < headername_len) {
1144 needed = (gint) (headername_len - available);
1148 if (0 == headername_len) {
1151 offset += headername_len;
1154 available = tvb_reported_length_remaining(tvb, offset);
1155 if (available < sizeof(guint16)) {
1156 needed = (gint) (sizeof(guint16) - available);
1159 headervalue_len = tvb_get_ntohs(tvb, offset);
1160 offset += sizeof(guint16);
1161 headervalue_offset = offset;
1163 available = tvb_reported_length_remaining(tvb, offset);
1164 if (available < headervalue_len) {
1165 needed = (gint) (headervalue_len - available);
1169 offset += headervalue_len;
1172 if (content_type && (sizeof("content-type") - 1) == headername_len) {
1173 if (0 == tvb_strncaseeql(tvb, headername_offset, "content-type", sizeof("content-type") - 1)) {
1174 *content_type = tvb_get_ephemeral_string(tvb, headervalue_offset, headervalue_len);
1179 if (content_length && (sizeof(guint64) == headervalue_len) && ((sizeof("content-length") - 1) == headername_len)) {
1180 if (0 == tvb_strncaseeql(tvb, headername_offset, "content-length", sizeof("content-length") - 1)) {
1181 *content_length = tvb_get_ntoh64(tvb, headervalue_offset);
1186 if ((needed > 0) && gDESEGMENT && pinfo->can_desegment) {
1187 pinfo->desegment_offset = 0;
1188 pinfo->desegment_len = needed;
1193 * Second (optional pass) Now that we are sure that all the bytes are there we update the protocol tree.
1196 guint tree_offset = 0;
1197 proto_item *framing_tree_item =
1198 proto_tree_add_none_format(tree, hf_jxta_framing, tvb, tree_offset, -1, "JXTA Message Framing Headers");
1199 proto_tree *framing_tree = proto_item_add_subtree(framing_tree_item, ett_jxta_framing);
1201 /* parse framing headers */
1203 guint8 headernamelen = tvb_get_guint8(tvb, tree_offset);
1204 proto_item *framing_header_tree_item =
1205 proto_tree_add_item(framing_tree, hf_jxta_framing_header, tvb, tree_offset, -1, FALSE);
1206 proto_tree *framing_header_tree = proto_item_add_subtree(framing_header_tree_item, ett_jxta_framing_header);
1209 * Put header name into the protocol tree
1211 proto_tree_add_item(framing_header_tree, hf_jxta_framing_header_name, tvb, tree_offset, 1, headernamelen);
1214 * Append header name into the header protocol item. It's a nice hint so you don't have to reveal all headers.
1216 if (headernamelen > 0) {
1217 proto_item_append_text(framing_header_tree_item, " \"%s\"",
1218 tvb_format_text(tvb, tree_offset + sizeof(guint8), headernamelen));
1221 tree_offset += sizeof(guint8) + headernamelen;
1223 if (headernamelen > 0) {
1224 guint16 headervaluelen = tvb_get_ntohs(tvb, tree_offset);
1227 proto_tree_add_uint(framing_header_tree, hf_jxta_framing_header_value_length, tvb, tree_offset,
1228 sizeof(guint16), headervaluelen);
1230 /** TODO bondolo Add specific handling for known header types */
1233 * Put header value into protocol tree.
1235 proto_tree_add_item(framing_header_tree, hf_jxta_framing_header_value, tvb, tree_offset + sizeof(guint16),
1236 headervaluelen, FALSE);
1239 tree_offset += sizeof(guint16) + headervaluelen;
1242 proto_item_set_end(framing_header_tree_item, tvb, tree_offset);
1244 if (0 == headernamelen) {
1249 proto_item_set_end(framing_tree_item, tvb, tree_offset);
1251 DISSECTOR_ASSERT(offset == tree_offset);
1254 /* return how many bytes we used up. */
1259 * Dissect a tvbuff containing a JXTA Message.
1261 * @param tvb The buffer to dissect.
1262 * @param pinfo Packet Info.
1263 * @param tree The protocol tree.
1264 * @return Number of bytes from the tvbuff_t which were processed, 0 (zero) if
1265 * the packet was not recognized as a JXTA packet and negative if the
1266 * dissector needs more bytes in order to process a PDU.
1268 static int dissect_jxta_message(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
1275 /* First pass. Make sure all of the bytes we need are available */
1276 available = tvb_reported_length_remaining(tvb, offset);
1277 if (available < sizeof(JXTA_MSG_SIG)) {
1278 needed = (gint) (sizeof(JXTA_MSG_SIG) - available);
1282 if (tvb_memeql(tvb, offset, JXTA_MSG_SIG, sizeof(JXTA_MSG_SIG)) != 0) {
1283 /* It is not one of ours */
1287 offset += sizeof(JXTA_MSG_SIG);
1289 available = tvb_reported_length_remaining(tvb, offset);
1290 if (available < sizeof(guint8)) {
1291 needed = (gint) (sizeof(guint8) - available);
1294 guint8 message_version = tvb_get_guint8(tvb, offset);
1296 offset += sizeof(guint8);
1298 if (0 != message_version) {
1299 /* Sort of a lie, we say that we don't recognize it at all. */
1304 available = tvb_reported_length_remaining(tvb, offset);
1305 if (available < sizeof(guint16)) {
1306 needed = (gint) (sizeof(guint16) - available);
1309 guint16 msg_ns_count = tvb_get_ntohs(tvb, offset);
1310 guint each_namespace;
1312 offset += sizeof(guint16);
1314 for (each_namespace = 0; each_namespace < msg_ns_count; each_namespace++) {
1315 guint16 namespace_len;
1317 available = tvb_reported_length_remaining(tvb, offset);
1318 if (available < sizeof(namespace_len)) {
1319 needed = (gint) (sizeof(namespace_len) - available);
1323 namespace_len = tvb_get_ntohs(tvb, offset);
1325 available = tvb_reported_length_remaining(tvb, offset + sizeof(namespace_len));
1326 if (available < namespace_len) {
1327 needed = (gint) (namespace_len - available);
1331 offset += sizeof(namespace_len) + namespace_len;
1335 /* parse element count */
1336 available = tvb_reported_length_remaining(tvb, offset);
1337 if (available < sizeof(guint16)) {
1338 needed = (gint) (sizeof(guint16) - available);
1341 guint16 elem_count = tvb_get_ntohs(tvb, offset);
1344 offset += sizeof(guint16);
1346 /* parse elements */
1348 for (each_elem = 0; each_elem < elem_count; each_elem++) {
1349 tvbuff_t *jxta_message_element_tvb = tvb_new_subset(tvb, offset, -1, -1);
1350 int processed = dissect_jxta_message_element(jxta_message_element_tvb, pinfo, NULL, 0, NULL);
1352 if (processed < 0) {
1353 needed = -processed;
1357 if (0 == processed) {
1358 /* XXX bondolo Not really clear what we should do! */
1359 g_warning( "Failure processing message element #%d of %d of frame %d", each_elem, elem_count, pinfo->fd->num );
1363 offset += processed;
1370 if ((needed > 0) && gDESEGMENT && pinfo->can_desegment) {
1371 pinfo->desegment_offset = 0;
1372 pinfo->desegment_len = needed;
1376 if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
1377 col_set_str(pinfo->cinfo, COL_PROTOCOL, "JXTA");
1380 if (check_col(pinfo->cinfo, COL_INFO)) {
1381 gchar src_addr[256];
1382 gchar dst_addr[256];
1384 address_to_str_buf(&pinfo->src, src_addr, sizeof src_addr);
1385 address_to_str_buf(&pinfo->dst, dst_addr, sizeof dst_addr);
1387 /* append the port if appropriate */
1388 if (PT_NONE != pinfo->ptype) {
1389 size_t len = strlen(src_addr);
1390 src_addr[len] = ':';
1391 g_snprintf(&src_addr[len + 1], 256 - len - 1, "%d", pinfo->srcport);
1393 len = strlen(dst_addr);
1394 dst_addr[len] = ':';
1395 g_snprintf(&dst_addr[len + 1], 256 - len - 1, "%d", pinfo->destport);
1398 col_add_fstr(pinfo->cinfo, COL_INFO, "Message, %s -> %s", src_addr, dst_addr);
1400 col_set_writable(pinfo->cinfo, FALSE);
1404 guint tree_offset = 0;
1405 proto_item *jxta_msg_tree_item = NULL;
1406 proto_tree *jxta_msg_tree = NULL;
1407 guint8 message_version;
1408 const gchar **namespaces = NULL;
1409 guint16 msg_ns_count;
1410 guint each_namespace;
1413 gchar src_addr[256];
1414 gchar dst_addr[256];
1415 proto_item *tree_item;
1417 address_to_str_buf(&pinfo->src, src_addr, sizeof src_addr);
1418 address_to_str_buf(&pinfo->dst, dst_addr, sizeof dst_addr);
1420 if (PT_NONE != pinfo->ptype) {
1421 size_t len = strlen(src_addr);
1422 src_addr[len] = ':';
1423 g_snprintf(&src_addr[len + 1], 256 - len - 1, "%d", pinfo->srcport);
1425 len = strlen(dst_addr);
1426 dst_addr[len] = ':';
1427 g_snprintf(&dst_addr[len + 1], 256 - len - 1, "%d", pinfo->destport);
1430 jxta_msg_tree_item = proto_tree_add_protocol_format(tree, proto_message_jxta, tvb, tree_offset, -1,
1431 "JXTA Message, %s -> %s", src_addr, dst_addr);
1433 jxta_msg_tree = proto_item_add_subtree(jxta_msg_tree_item, ett_jxta_msg);
1435 proto_tree_add_item(jxta_msg_tree, hf_jxta_message_sig, tvb, tree_offset, sizeof(JXTA_MSG_SIG), FALSE);
1436 tree_offset += sizeof(JXTA_MSG_SIG);
1438 tree_item = proto_tree_add_string(jxta_msg_tree, hf_jxta_message_src, tvb, 0, 0, src_addr);
1439 PROTO_ITEM_SET_GENERATED(tree_item);
1441 tree_item = proto_tree_add_string(jxta_msg_tree, hf_jxta_message_address, tvb, 0, 0, src_addr);
1442 PROTO_ITEM_SET_HIDDEN(tree_item);
1443 PROTO_ITEM_SET_GENERATED(tree_item);
1445 tree_item = proto_tree_add_string(jxta_msg_tree, hf_jxta_message_dst, tvb, 0, 0, dst_addr);
1446 PROTO_ITEM_SET_GENERATED(tree_item);
1448 tree_item = proto_tree_add_string(jxta_msg_tree, hf_jxta_message_address, tvb, 0, 0, dst_addr);
1449 PROTO_ITEM_SET_HIDDEN(tree_item);
1450 PROTO_ITEM_SET_GENERATED(tree_item);
1452 message_version = tvb_get_guint8(tvb, tree_offset);
1453 proto_tree_add_uint(jxta_msg_tree, hf_jxta_message_version, tvb, tree_offset, sizeof(guint8), message_version);
1454 tree_offset += sizeof(guint8);
1456 msg_ns_count = tvb_get_ntohs(tvb, tree_offset);
1457 proto_tree_add_uint(jxta_msg_tree, hf_jxta_message_namespaces_count, tvb, tree_offset, sizeof(guint16), msg_ns_count);
1458 tree_offset += sizeof(guint16);
1460 namespaces = ep_alloc((msg_ns_count + 2) * sizeof(const gchar *));
1462 namespaces[1] = "jxta";
1464 /* parse namespaces */
1465 for (each_namespace = 0; each_namespace < msg_ns_count; each_namespace++) {
1466 guint16 namespace_len = tvb_get_ntohs(tvb, tree_offset);
1468 namespaces[2 + each_namespace] = tvb_get_ephemeral_string(tvb, tree_offset + sizeof(namespace_len), namespace_len);
1469 proto_tree_add_item(jxta_msg_tree, hf_jxta_message_namespace_name, tvb, tree_offset, sizeof(namespace_len), FALSE);
1470 tree_offset += sizeof(namespace_len) + namespace_len;
1473 /* parse element count */
1474 elem_count = tvb_get_ntohs(tvb, tree_offset);
1475 proto_tree_add_item(jxta_msg_tree, hf_jxta_message_element_count, tvb, tree_offset, sizeof(guint16), FALSE);
1476 tree_offset += sizeof(guint16);
1478 /* parse elements */
1479 for (each_elem = 0; each_elem < elem_count; each_elem++) {
1480 tvbuff_t *jxta_message_element_tvb = tvb_new_subset(tvb, tree_offset, -1, -1);
1483 dissect_jxta_message_element(jxta_message_element_tvb, pinfo, jxta_msg_tree, msg_ns_count + 2, namespaces);
1486 proto_item_set_end(jxta_msg_tree_item, tvb, tree_offset);
1488 DISSECTOR_ASSERT(tree_offset == offset);
1491 if ((offset > 0) && (AT_URI == pinfo->src.type) && (AT_URI == pinfo->dst.type)) {
1492 jxta_tap_header *tap_header = se_alloc(sizeof(jxta_tap_header));
1494 tap_header->src_address = pinfo->src;
1495 tap_header->dest_address = pinfo->dst;
1496 tap_header->size = offset;
1498 tap_queue_packet(jxta_tap, pinfo, tap_header);
1505 * Dissect a tvbuff containing a JXTA Message Element.
1507 * @param tvb The buffer to dissect.
1508 * @param pinfo Packet Info.
1509 * @param tree The protocol tree.
1510 * @return Number of bytes from the tvbuff_t which were processed, 0 (zero) if
1511 * the packet was not recognized as a JXTA packet and negative if the
1512 * dissector needs more bytes in order to process a PDU.
1514 static int dissect_jxta_message_element(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, guint ns_count,
1515 const gchar ** namespaces)
1522 /* First pass. Make sure all of the bytes we need are available */
1525 /* signature field */
1526 available = tvb_reported_length_remaining(tvb, offset);
1527 if (available < sizeof(JXTA_MSGELEM_SIG)) {
1528 needed = (gint) (sizeof(JXTA_MSGELEM_SIG) - available);
1531 if (tvb_memeql(tvb, offset, JXTA_MSGELEM_SIG, sizeof(JXTA_MSGELEM_SIG)) != 0) {
1532 /* It is not one of ours */
1536 offset += sizeof(JXTA_MSGELEM_SIG);
1538 /* namespace id field */
1539 available = tvb_reported_length_remaining(tvb, offset);
1540 if (available < sizeof(guint8)) {
1541 needed = (gint) (sizeof(guint8) - available);
1545 offset += sizeof(guint8);
1548 available = tvb_reported_length_remaining(tvb, offset);
1549 if (available < sizeof(guint8)) {
1550 needed = (gint) (sizeof(guint8) - available);
1553 flags = tvb_get_guint8(tvb, offset);
1554 offset += sizeof(guint8);
1558 available = tvb_reported_length_remaining(tvb, offset);
1559 if (available < sizeof(guint16)) {
1560 needed = (gint) (sizeof(guint16) - available);
1563 guint16 name_len = tvb_get_ntohs(tvb, offset);
1564 offset += sizeof(guint16);
1566 available = tvb_reported_length_remaining(tvb, offset);
1567 if (available < name_len) {
1568 needed = (gint) (name_len - available);
1576 if ((flags & 0x01) != 0) {
1579 available = tvb_reported_length_remaining(tvb, offset);
1580 if (available < sizeof(guint16)) {
1581 needed = (gint) (sizeof(guint16) - available);
1585 type_len = tvb_get_ntohs(tvb, offset);
1586 offset += sizeof(guint16);
1588 available = tvb_reported_length_remaining(tvb, offset);
1589 if (available < type_len) {
1590 needed = (gint) (type_len - available);
1597 /* encoding field */
1598 if ((flags & 0x02) != 0) {
1599 guint16 encoding_len;
1601 available = tvb_reported_length_remaining(tvb, offset);
1602 if (available < sizeof(guint16)) {
1603 needed = (gint) (sizeof(guint16) - available);
1607 encoding_len = tvb_get_ntohs(tvb, offset);
1608 offset += sizeof(guint16);
1610 available = tvb_reported_length_remaining(tvb, offset);
1611 if (available < encoding_len) {
1612 needed = (gint) (encoding_len - available);
1616 offset += encoding_len;
1620 available = tvb_reported_length_remaining(tvb, offset);
1621 if (available < sizeof(guint16)) {
1622 needed = (gint) (sizeof(guint16) - available);
1625 guint32 content_len = tvb_get_ntohl(tvb, offset);
1626 offset += sizeof(guint32);
1628 available = tvb_reported_length_remaining(tvb, offset);
1629 if (available < content_len) {
1630 needed = (gint) (content_len - available);
1634 offset += content_len;
1637 /* signature element field */
1638 if ((flags & 0x04) != 0) {
1639 tvbuff_t *jxta_signature_element_tvb;
1642 jxta_signature_element_tvb = tvb_new_subset(tvb, offset, -1, -1);
1644 processed = dissect_jxta_message_element(jxta_signature_element_tvb, pinfo, NULL, 0, NULL);
1646 if (processed == 0) {
1650 if (processed < 0) {
1651 needed = -processed;
1655 offset += processed;
1661 if ((needed > 0) && gDESEGMENT && pinfo->can_desegment) {
1662 pinfo->desegment_offset = 0;
1663 pinfo->desegment_len = needed;
1667 /* Second (optional) pass : build the proto tree */
1669 guint tree_offset = 0;
1670 proto_item *jxta_elem_tree_item = proto_tree_add_item(tree, hf_jxta_element, tvb, tree_offset, -1, FALSE);
1671 proto_tree *jxta_elem_tree = proto_item_add_subtree(jxta_elem_tree_item, ett_jxta_elem);
1673 proto_item *namespace_ti;
1675 proto_item *flags_ti;
1676 proto_tree *jxta_elem_flags_tree = NULL;
1677 guint32 content_len;
1678 gchar *mediatype = NULL;
1679 gboolean media_type_recognized = FALSE;
1680 tvbuff_t *element_content_tvb;
1681 proto_item * jxta_elem_length_item = NULL;
1683 proto_tree_add_item(jxta_elem_tree, hf_jxta_element_sig, tvb, tree_offset, sizeof(JXTA_MSGELEM_SIG), FALSE);
1684 tree_offset += sizeof(JXTA_MSGELEM_SIG);
1686 namespaceID = tvb_get_guint8(tvb, tree_offset);
1688 proto_tree_add_uint(jxta_elem_tree, hf_jxta_element_namespaceid, tvb, tree_offset, sizeof(guint8), namespaceID);
1689 if (namespaceID < ns_count) {
1690 proto_item_append_text(namespace_ti, " (%s)", namespaces[namespaceID]);
1692 proto_item_append_text(namespace_ti, " * BAD *");
1694 tree_offset += sizeof(guint8);
1696 flags = tvb_get_guint8(tvb, tree_offset);
1697 flags_ti = proto_tree_add_uint(jxta_elem_tree, hf_jxta_element_flags, tvb, tree_offset, sizeof(guint8), flags);
1698 jxta_elem_flags_tree = proto_item_add_subtree(flags_ti, ett_jxta_elem_flags);
1699 proto_tree_add_boolean(jxta_elem_flags_tree, hf_jxta_element_flag_hasType, tvb, tree_offset, 1, flags);
1700 proto_tree_add_boolean(jxta_elem_flags_tree, hf_jxta_element_flag_hasEncoding, tvb, tree_offset, 1, flags);
1701 proto_tree_add_boolean(jxta_elem_flags_tree, hf_jxta_element_flag_hasSignature, tvb, tree_offset, 1, flags);
1702 tree_offset += sizeof(guint8);
1704 name_len = tvb_get_ntohs(tvb, tree_offset);
1705 proto_item_append_text(jxta_elem_tree_item, " \"%s\"", tvb_format_text(tvb, tree_offset + sizeof(guint16), name_len));
1706 proto_tree_add_item(jxta_elem_tree, hf_jxta_element_name, tvb, tree_offset, sizeof(guint16), FALSE);
1707 tree_offset += sizeof(guint16) + name_len;
1710 if ((flags & 0x01) != 0) {
1711 guint16 type_len = tvb_get_ntohs(tvb, tree_offset);
1712 proto_tree_add_item(jxta_elem_tree, hf_jxta_element_type, tvb, tree_offset, sizeof(guint16), FALSE);
1713 tree_offset += sizeof(guint16);
1715 mediatype = tvb_get_ephemeral_string(tvb, tree_offset, type_len);
1717 /* remove any params */
1719 gchar *parms_at = strchr(mediatype, ';');
1721 if (NULL != parms_at) {
1726 /* force to lower case */
1727 #if GLIB_MAJOR_VERSION < 2
1728 g_strdown(mediatype);
1731 gchar *mediatype_lowercase = g_ascii_strdown(mediatype, -1);
1732 mediatype = mediatype_lowercase;
1735 tree_offset += type_len;
1738 /* process encoding */
1739 if ((flags & 0x02) != 0) {
1740 guint16 encoding_len = tvb_get_ntohs(tvb, tree_offset);
1741 proto_tree_add_item(jxta_elem_tree, hf_jxta_element_encoding, tvb, tree_offset, sizeof(guint16), FALSE);
1742 tree_offset += sizeof(guint16) + encoding_len;
1746 content_len = tvb_get_ntohl(tvb, tree_offset);
1747 jxta_elem_length_item = proto_tree_add_item(jxta_elem_tree, hf_jxta_element_content_len, tvb, tree_offset, sizeof(guint32), FALSE);
1748 tree_offset += sizeof(guint32);
1750 element_content_tvb = tvb_new_subset(tvb, tree_offset, content_len, content_len);
1753 if (0 == strcmp("application/x-jxta-tls-block", mediatype)) {
1754 /* If we recognize it as a TLS packet then we shuffle it off to ssl dissector. */
1755 dissector_handle_t ssl_handle = find_dissector("ssl");
1756 if (NULL != ssl_handle) {
1757 int processed = call_dissector(ssl_handle, element_content_tvb, pinfo, jxta_elem_tree);
1758 media_type_recognized = processed != 0;
1760 } else if (0 == strcmp("application/gzip", mediatype)) {
1761 tvbuff_t *uncomp_tvb = tvb_uncompress(element_content_tvb, 0, tvb_length(element_content_tvb));
1763 if( NULL != uncomp_tvb ) {
1764 proto_item_append_text( jxta_elem_length_item, " -> (%u uncompressed)", tvb_length(uncomp_tvb) );
1766 tvb_set_child_real_data_tvbuff(element_content_tvb, uncomp_tvb);
1767 add_new_data_source(pinfo, uncomp_tvb, "Uncompressed Element Content");
1769 /* XXX bondolo 20060201 Force XML for uncompressed data. */
1770 media_type_recognized = dissector_try_string(media_type_dissector_table,
1771 "text/xml", uncomp_tvb, pinfo, jxta_elem_tree);
1774 media_type_recognized = dissector_try_string(media_type_dissector_table,
1775 mediatype, element_content_tvb, pinfo, jxta_elem_tree);
1780 if (!media_type_recognized) {
1781 /* display it as raw data */
1782 call_dissector(data_handle, element_content_tvb, pinfo, jxta_elem_tree);
1784 tree_offset += content_len;
1786 /* process the signature element */
1787 if ((flags & 0x04) != 0) {
1788 tvbuff_t *jxta_message_element_tvb = tvb_new_subset(tvb, tree_offset, -1, -1);
1790 tree_offset += dissect_jxta_message_element(jxta_message_element_tvb, pinfo, jxta_elem_tree, ns_count, namespaces);
1793 proto_item_set_end(jxta_elem_tree_item, tvb, tree_offset);
1795 DISSECTOR_ASSERT(tree_offset == offset);
1802 * Register jxta protocol and jxta message protocol, header fields, subtree types, preferences.
1804 void proto_register_jxta(void)
1806 module_t *jxta_module;
1808 media_type_dissector_table = find_dissector_table("media_type");
1810 data_handle = find_dissector("data");
1812 proto_jxta = proto_register_protocol("JXTA P2P", "JXTA", "jxta");
1814 jxta_tap = register_tap("jxta");
1816 /* The JXTA Binary Message Wire Format : Registered and dissected by MIME type */
1817 proto_message_jxta = proto_register_protocol("JXTA Message", "JXTA Message", "jxta.message");
1819 message_jxta_handle = new_create_dissector_handle(dissect_jxta_message, proto_message_jxta);
1821 dissector_add_string("media_type", "application/x-jxta-msg", message_jxta_handle);
1823 /* Register header fields */
1824 proto_register_field_array(proto_jxta, hf, array_length(hf));
1826 /* Register JXTA Sub-tree */
1827 proto_register_subtree_array(ett, array_length(ett));
1829 /* Register preferences */
1830 /* register re-init routine */
1831 jxta_module = prefs_register_protocol(proto_jxta, proto_reg_handoff_jxta);
1833 prefs_register_bool_preference(jxta_module, "desegment",
1834 "Reassemble JXTA messages spanning multiple UDP/TCP/HTTP segments",
1835 "Whether the JXTA dissector should reassemble messages spanning multiple UDP/HTTP/TCP segments."
1836 " To use this option you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings "
1837 " and enable \"Reassemble fragmented IP datagrams\" in the IP protocol settings.",
1840 prefs_register_bool_preference(jxta_module, "udp.heuristic", "Try to discover JXTA in UDP datagrams",
1841 "Enable to inspect UDP datagrams for JXTA messages.", &gUDP_HEUR);
1843 prefs_register_bool_preference(jxta_module, "tcp.heuristic", "Try to discover JXTA in TCP connections",
1844 "Enable to inspect TCP connections for JXTA conversations.", &gTCP_HEUR);
1846 prefs_register_bool_preference(jxta_module, "sctp.heuristic", "Try to discover JXTA in SCTP connections",
1847 "Enable to inspect SCTP connections for JXTA conversations.", &gSCTP_HEUR);
1851 * Update registrations in response to
1853 void proto_reg_handoff_jxta(void)
1855 static gboolean init_done = FALSE;
1858 /* XXX 20051004 bondolo We could dynamically add dissectors based upon prefs. */
1859 new_register_dissector("jxta.udp", dissect_jxta_udp, proto_jxta);
1860 heur_dissector_add("udp", dissect_jxta_UDP_heur, proto_jxta);
1862 new_register_dissector("jxta.stream", dissect_jxta_stream, proto_jxta);
1863 stream_jxta_handle = find_dissector("jxta.stream");
1864 heur_dissector_add("tcp", dissect_jxta_TCP_heur, proto_jxta);
1865 heur_dissector_add("sctp", dissect_jxta_SCTP_heur, proto_jxta);