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>
49 #include <epan/ws_strsplit.h>
51 #include "packet-jxta.h"
53 static const gchar JXTA_UDP_SIG[] = { 'J', 'X', 'T', 'A' };
54 static const gchar JXTA_MSG_SIG[] = { 'j', 'x', 'm', 'g' };
55 static const gchar JXTA_MSGELEM_SIG[] = { 'j', 'x', 'e', 'l' };
57 static const gchar JXTA_WELCOME_MSG_SIG[] = { 'J', 'X', 'T', 'A', 'H', 'E', 'L', 'L', 'O', ' ' };
59 static const gchar* JXTA_WELCOME_MSG_VERSION_1_1 = "1.1";
61 static int proto_jxta = -1;
62 static int proto_message_jxta = -1;
63 static int jxta_tap = -1;
65 static dissector_table_t media_type_dissector_table = NULL;
66 static dissector_handle_t data_handle = NULL;
67 static dissector_handle_t stream_jxta_handle = NULL;
68 static dissector_handle_t message_jxta_handle;
70 static int hf_jxta_udp = -1;
71 static int hf_jxta_udpsig = -1;
72 static int hf_jxta_welcome = -1;
73 static int hf_jxta_welcome_initiator = -1;
74 static int hf_jxta_welcome_sig = -1;
75 static int hf_jxta_welcome_destAddr = -1;
76 static int hf_jxta_welcome_pubAddr = -1;
77 static int hf_jxta_welcome_peerid = -1;
78 static int hf_jxta_welcome_noProp = -1;
79 static int hf_jxta_welcome_variable = -1;
80 static int hf_jxta_welcome_version = -1;
81 static int hf_jxta_framing = -1;
82 static int hf_jxta_framing_header = -1;
83 static int hf_jxta_framing_header_name = -1;
84 static int hf_jxta_framing_header_value_length = -1;
85 static int hf_jxta_framing_header_value = -1;
86 static int hf_jxta_message_address = -1;
87 static int hf_jxta_message_src = -1;
88 static int hf_jxta_message_dst = -1;
89 static int hf_jxta_message_sig = -1;
90 static int hf_jxta_message_version = -1;
91 static int hf_jxta_message_namespaces_count = -1;
92 static int hf_jxta_message_namespace_name = -1;
93 static int hf_jxta_message_element_count = -1;
94 static int hf_jxta_element = -1;
95 static int hf_jxta_element_sig = -1;
96 static int hf_jxta_element_namespaceid = -1;
97 static int hf_jxta_element_flags = -1;
98 static int hf_jxta_element_flag_hasType = -1;
99 static int hf_jxta_element_flag_hasEncoding = -1;
100 static int hf_jxta_element_flag_hasSignature = -1;
101 static int hf_jxta_element_name = -1;
102 static int hf_jxta_element_type = -1;
103 static int hf_jxta_element_encoding = -1;
104 static int hf_jxta_element_content_len = -1;
105 static int hf_jxta_element_content = -1;
107 /** our header fields */
108 static hf_register_info hf[] = {
110 {"JXTA UDP", "jxta.udp", FT_NONE, BASE_NONE, NULL, 0x0,
114 {"Signature", "jxta.udpsig", FT_STRING, BASE_NONE, NULL, 0x0,
115 "JXTA UDP Signature", HFILL}
118 {"Welcome", "jxta.welcome", FT_NONE, BASE_NONE, NULL, 0x00,
119 "JXTA Connection Welcome Message", HFILL}
121 {&hf_jxta_welcome_initiator,
122 {"Initiator", "jxta.welcome.initiator", FT_BOOLEAN, BASE_NONE, NULL, 0x00,
123 "JXTA Connection Welcome Message Initiator", HFILL}
125 {&hf_jxta_welcome_sig,
126 {"Signature", "jxta.welcome.signature", FT_STRING, BASE_NONE, NULL, 0x0,
127 "JXTA Connection Welcome Message Signature", HFILL}
129 {&hf_jxta_welcome_destAddr,
130 {"Destination Address", "jxta.welcome.destAddr", FT_STRING, BASE_NONE, NULL, 0x0,
131 "JXTA Connection Welcome Message Destination Address", HFILL}
133 {&hf_jxta_welcome_pubAddr,
134 {"Public Address", "jxta.welcome.pubAddr", FT_STRING, BASE_NONE, NULL, 0x0,
135 "JXTA Connection Welcome Message Public Address", HFILL}
137 {&hf_jxta_welcome_peerid,
138 {"PeerID", "jxta.welcome.peerid", FT_STRING, BASE_NONE, NULL, 0x0,
139 "JXTA Connection Welcome Message PeerID", HFILL}
141 {&hf_jxta_welcome_noProp,
142 {"No Propagate Flag", "jxta.welcome.noPropFlag", FT_STRING, BASE_NONE, NULL, 0x0,
143 "JXTA Connection Welcome Message No Propagate Flag", HFILL}
145 {&hf_jxta_welcome_variable,
146 {"Variable Parameter", "jxta.welcome.variable", FT_STRING, BASE_NONE, NULL, 0x0,
147 "JXTA Connection Welcome Message Variable Parameter", HFILL}
149 {&hf_jxta_welcome_version,
150 {"Version", "jxta.welcome.version", FT_STRING, BASE_NONE, NULL, 0x0,
151 "JXTA Connection Welcome Message Version", HFILL}
154 {"Framing", "jxta.framing", FT_NONE, BASE_NONE, NULL, 0x0,
155 "JXTA Message Framing", HFILL}
157 {&hf_jxta_framing_header,
158 {"Header", "jxta.framing.header", FT_NONE, BASE_NONE, NULL, 0x0,
159 "JXTA Message Framing Header", HFILL}
161 {&hf_jxta_framing_header_name,
162 {"Name", "jxta.framing.header.name", FT_UINT_STRING, BASE_NONE, NULL, 0x0,
163 "JXTA Message Framing Header Name", HFILL}
165 {&hf_jxta_framing_header_value_length,
166 {"Value Length", "jxta.framing.header.valuelen", FT_UINT16, BASE_DEC, NULL, 0x0,
167 "JXTA Message Framing Header Value Length", HFILL}
169 {&hf_jxta_framing_header_value,
170 {"Value", "jxta.framing.header.value", FT_BYTES, BASE_HEX, NULL, 0x0,
171 "JXTA Message Framing Header Value", HFILL}
173 {&hf_jxta_message_address,
174 {"Address", "jxta.message.address", FT_STRING, BASE_NONE, NULL, 0x0,
175 "JXTA Message Address (source or destination)", HFILL}
177 {&hf_jxta_message_src,
178 {"Source", "jxta.message.source", FT_STRING, BASE_NONE, NULL, 0x0,
179 "JXTA Message Source", HFILL}
181 {&hf_jxta_message_dst,
182 {"Destination", "jxta.message.destination", FT_STRING, BASE_NONE, NULL, 0x0,
183 "JXTA Message Destination", HFILL}
185 {&hf_jxta_message_sig,
186 {"Signature", "jxta.message.signature", FT_STRING, BASE_NONE, NULL, 0x0,
187 "JXTA Message Signature", HFILL}
189 {&hf_jxta_message_version,
190 {"Version", "jxta.message.version", FT_UINT8, BASE_DEC, NULL, 0x0,
191 "JXTA Message Version", HFILL}
193 {&hf_jxta_message_namespaces_count,
194 {"Namespace Count", "jxta.message.namespaces", FT_UINT16, BASE_DEC, NULL, 0x0,
195 "JXTA Message Namespaces", HFILL}
197 {&hf_jxta_message_namespace_name,
198 {"Namespace Name", "jxta.message.namespace.name", FT_UINT_STRING, BASE_NONE, NULL, 0x0,
199 "JXTA Message Namespace Name", HFILL}
201 {&hf_jxta_message_element_count,
202 {"Element Count", "jxta.message.elements", FT_UINT16, BASE_DEC, NULL, 0x0,
203 "JXTA Message Element Count", HFILL}
206 {"JXTA Message Element", "jxta.message.element", FT_NONE, BASE_NONE, NULL, 0x0,
207 "JXTA Message Element", HFILL}
209 {&hf_jxta_element_sig,
210 {"Signature", "jxta.message.element.signature", FT_STRING, BASE_NONE, NULL, 0x0,
211 "JXTA Message Element Signature", HFILL}
213 {&hf_jxta_element_namespaceid,
214 {"Namespace ID", "jxta.message.element.namespaceid", FT_UINT8, BASE_DEC, NULL, 0x0,
215 "JXTA Message Element Namespace ID", HFILL}
217 {&hf_jxta_element_flags,
218 {"Flags", "jxta.message.element.flags", FT_UINT8, BASE_HEX, NULL, 0x0,
219 "JXTA Message Element Flags", HFILL}
221 {&hf_jxta_element_flag_hasType,
222 {"hasType", "jxta.message.element.flags.hasType", FT_BOOLEAN, 3, TFS(&flags_set_truth), 0x01,
223 "JXTA Message Element Flag -- hasType", HFILL}
225 {&hf_jxta_element_flag_hasEncoding,
226 {"hasEncoding", "jxta.message.element.flags.hasEncoding", FT_BOOLEAN, 3, TFS(&flags_set_truth), 0x02,
227 "JXTA Message Element Flag -- hasEncoding", HFILL}
229 {&hf_jxta_element_flag_hasSignature,
230 {"hasSignature", "jxta.message.element.flags.hasSignature", FT_BOOLEAN, 3, TFS(&flags_set_truth), 0x04,
231 "JXTA Message Element Flag -- hasSignature", HFILL}
233 {&hf_jxta_element_name,
234 {"Element Name", "jxta.message.element.name", FT_UINT_STRING, BASE_NONE, NULL, 0x0,
235 "JXTA Message Element Name", HFILL}
237 {&hf_jxta_element_type,
238 {"Element Type", "jxta.message.element.type", FT_UINT_STRING, BASE_NONE, NULL, 0x0,
239 "JXTA Message Element Name", HFILL}
241 {&hf_jxta_element_encoding,
242 {"Element Type", "jxta.message.element.encoding", FT_UINT_STRING, BASE_NONE, NULL, 0x0,
243 "JXTA Message Element Encoding", HFILL}
245 {&hf_jxta_element_content_len,
246 {"Element Content Length", "jxta.message.element.content.length", FT_UINT32, BASE_DEC, NULL, 0x0,
247 "JXTA Message Element Content Length", HFILL}
249 {&hf_jxta_element_content,
250 {"Element Content", "jxta.message.element.content", FT_BYTES, BASE_HEX, NULL, 0x0,
251 "JXTA Message Element Content", HFILL}
256 * JXTA Protocol subtree handles
258 static gint ett_jxta = -1;
259 static gint ett_jxta_welcome = -1;
260 static gint ett_jxta_udp = -1;
261 static gint ett_jxta_framing = -1;
262 static gint ett_jxta_framing_header = -1;
263 static gint ett_jxta_msg = -1;
264 static gint ett_jxta_elem = -1;
265 static gint ett_jxta_elem_flags = -1;
268 * JXTA Protocol subtree array
270 static gint *const ett[] = {
275 &ett_jxta_framing_header,
284 static gboolean gDESEGMENT = TRUE;
285 static gboolean gUDP_HEUR = TRUE;
286 static gboolean gTCP_HEUR = TRUE;
287 static gboolean gSCTP_HEUR = FALSE;
290 * Stream Conversation data
292 struct jxta_stream_conversation_data {
295 address initiator_tpt_address;
296 guint32 initiator_tpt_port;
297 guint32 initiator_welcome_frame;
298 address initiator_address;
300 address receiver_tpt_address;
301 guint32 receiver_tpt_port;
302 guint32 receiver_welcome_frame;
303 address receiver_address;
306 typedef struct jxta_stream_conversation_data jxta_stream_conversation_data;
311 static gboolean dissect_jxta_UDP_heur(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree);
312 static gboolean dissect_jxta_TCP_heur(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree);
313 static gboolean dissect_jxta_SCTP_heur(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree);
315 static int dissect_jxta_udp(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree);
316 static int dissect_jxta_stream(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree);
317 static conversation_t *get_tpt_conversation(packet_info * pinfo, gboolean create);
319 static int dissect_jxta_welcome(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, address * found_addr, gboolean initiator);
320 static int dissect_jxta_message_framing(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, guint64 * content_length,
321 gchar ** content_type);
322 static int dissect_jxta_message(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree);
323 static int dissect_jxta_message_element(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, guint ns_count,
324 const gchar ** namespaces);
326 void proto_reg_handoff_jxta(void);
329 * Heuristically dissect a tvbuff containing a JXTA UDP Message
331 * @param tvb The buffer to dissect.
332 * @param pinfo Packet Info.
333 * @param tree The protocol tree.
334 * @return TRUE if the tvb contained JXTA data which was dissected otherwise FALSE
336 static gboolean dissect_jxta_UDP_heur(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
338 /* This is a heuristic dissector, which means we get all the UDP
339 * traffic not sent to a known dissector and not claimed by
340 * a heuristic dissector called before us!
342 int save_desegment_offset;
343 guint32 save_desegment_len;
349 if (tvb_memeql(tvb, 0, JXTA_UDP_SIG, sizeof(JXTA_UDP_SIG)) != 0) {
353 save_desegment_offset = pinfo->desegment_offset;
354 save_desegment_len = pinfo->desegment_len;
355 ret = dissect_jxta_udp(tvb, pinfo, tree);
358 * UDP is not a packet stream protocol, so the UDP dissector
359 * should not, and will not, do the sort of dissection help
360 * that the TCP dissector will. If JXTA messages don't
361 * start and end on UDP packet boundaries, the JXTA dissector
362 * will have to do its own byte stream reassembly.
364 pinfo->desegment_offset = save_desegment_offset;
365 pinfo->desegment_len = save_desegment_len;
367 } else if (ret == 0) {
371 pinfo->desegment_offset = save_desegment_offset;
372 pinfo->desegment_len = save_desegment_len;
376 * A clear acceptance.
383 * Heuristically dissect a tvbuff containing a JXTA TCP Stream
385 * @param tvb The buffer to dissect.
386 * @param pinfo Packet Info.
387 * @param tree The protocol tree.
388 * @return TRUE if the tvb contained JXTA data which was dissected otherwise FALSE
390 static gboolean dissect_jxta_TCP_heur(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
392 /* This is a heuristic dissector, which means we get all the TCP
393 * traffic not sent to a known dissector and not claimed by
394 * a heuristic dissector called before us!
396 int save_desegment_offset;
397 guint32 save_desegment_len;
403 save_desegment_offset = pinfo->desegment_offset;
404 save_desegment_len = pinfo->desegment_len;
405 ret = dissect_jxta_stream(tvb, pinfo, tree);
408 * A heuristic dissector for a TCP-based protocol can reject
409 * a packet, or it can request that more data be provided.
410 * It must not attempt to do both, as the notion of doing both
411 * is nonsensical - if the packet isn't considered a packet
412 * for the dissector's protocol, that dissector won't be
413 * dissecting it no matter *how* much more data is added.
415 * Therefore, we treat a negative return from
416 * dissect_jxta_stream() as a rejection.
418 * If that's not desired - i.e., if we should keep trying to get
419 * more data, in the hopes that we'll eventually be able to
420 * determine whether the packet is a JXTA packet or not - we
421 * should, in this case, leave pinfo->desegment_offset and
422 * pinfo->desegment_len alone, and return TRUE, *NOT* FALSE.
424 pinfo->desegment_offset = save_desegment_offset;
425 pinfo->desegment_len = save_desegment_len;
427 } else if (ret == 0) {
431 pinfo->desegment_offset = save_desegment_offset;
432 pinfo->desegment_len = save_desegment_len;
436 * A clear acceptance.
443 * Heuristically dissect a tvbuff containing a JXTA SCTP Stream
445 * @param tvb The buffer to dissect.
446 * @param pinfo Packet Info.
447 * @param tree The protocol tree.
448 * @return TRUE if the tvb contained JXTA data which was dissected otherwise FALSE
450 static gboolean dissect_jxta_SCTP_heur(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
452 /* This is a heuristic dissector, which means we get all the SCTP
453 * traffic not sent to a known dissector and not claimed by
454 * a heuristic dissector called before us!
456 int save_desegment_offset;
457 guint32 save_desegment_len;
463 save_desegment_offset = pinfo->desegment_offset;
464 save_desegment_len = pinfo->desegment_len;
465 ret = dissect_jxta_stream(tvb, pinfo, tree);
468 * SCTP is not a byte stream protocol, so the SCTP dissector
469 * should not, and will not, do the sort of dissection help
470 * that the SCTP dissector will. If JXTA messages don't
471 * start and end on SCTP packet boundaries, the JXTA dissector
472 * will have to do its own byte stream reassembly.
474 * The SCTP dissector currently won't do reassembly. If that
475 * causes a problem for the JXTA dissector, the correct fix
476 * is to implement reassembly in the SCTP dissector, so *all*
477 * dissectors for protocols running atop SCTP can benefit from
480 pinfo->desegment_offset = save_desegment_offset;
481 pinfo->desegment_len = save_desegment_len;
483 } else if (ret == 0) {
487 pinfo->desegment_offset = save_desegment_offset;
488 pinfo->desegment_len = save_desegment_len;
492 * A clear acceptance.
499 * Dissect a tvbuff containing a JXTA UDP header, JXTA Message framing and a JXTA Message
501 * @param tvb The buffer to dissect.
502 * @param pinfo Packet Info.
503 * @param tree The protocol tree.
504 * @return Number of bytes from the tvbuff_t which were processed, 0 (zero) if
505 * the packet was not recognized as a JXTA packet and negative if the
506 * dissector needs more bytes in order to process a PDU.
508 static int dissect_jxta_udp(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
514 conversation_t *conversation =
515 find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
517 if (conversation == NULL) {
519 * No conversation exists yet - create one.
522 conversation_new(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
525 DISSECTOR_ASSERT(find_dissector("jxta.udp"));
527 conversation_set_dissector(conversation, find_dissector("jxta.udp"));
530 tvbuff_t *jxta_message_framing_tvb;
532 guint64 content_length = -1;
533 gchar *content_type = NULL;
535 available = tvb_reported_length_remaining(tvb, offset);
536 if (available < sizeof(JXTA_UDP_SIG)) {
537 needed = (gint) (sizeof(JXTA_UDP_SIG) - available);
541 if (tvb_memeql(tvb, offset, JXTA_UDP_SIG, sizeof(JXTA_UDP_SIG)) != 0) {
546 offset += sizeof(JXTA_UDP_SIG);
548 jxta_message_framing_tvb = tvb_new_subset(tvb, offset, -1, -1);
549 processed = dissect_jxta_message_framing(jxta_message_framing_tvb, pinfo, NULL, &content_length, &content_type);
551 if ((0 == processed) || (NULL == content_type) || (content_length <= 0) || (content_length > UINT_MAX)) {
552 /** Buffer did not begin with valid framing headers */
561 /* Redo header processing, this time populating the tree. */
562 processed = dissect_jxta_message_framing(jxta_message_framing_tvb, pinfo, tree, &content_length, &content_type);
567 available = tvb_reported_length_remaining(tvb, offset);
568 if (available < content_length) {
569 needed = (gint) (content_length - available);
573 offset += (guint) content_length;
578 if ((needed > 0) && gDESEGMENT && pinfo->can_desegment) {
579 pinfo->desegment_offset = 0;
580 pinfo->desegment_len = needed;
584 if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
585 col_set_str(pinfo->cinfo, COL_PROTOCOL, "JXTA");
589 guint tree_offset = 0;
590 proto_item *jxta_tree_item =
591 proto_tree_add_protocol_format(tree, proto_jxta, tvb, offset, -1, "JXTA" );
592 proto_tree *jxta_tree = proto_item_add_subtree(jxta_tree_item, ett_jxta);
593 proto_item *jxta_udp_tree_item =
594 proto_tree_add_none_format(jxta_tree, hf_jxta_udp, tvb, tree_offset, -1, "JXTA UDP Message");
595 proto_tree *jxta_udp_tree = proto_item_add_subtree(jxta_udp_tree_item, ett_jxta_udp);
596 tvbuff_t *jxta_message_framing_tvb;
597 guint64 content_length = -1;
598 gchar *content_type = NULL;
599 tvbuff_t *jxta_message_tvb;
600 gboolean dissected = FALSE;
603 proto_tree_add_item(jxta_udp_tree, hf_jxta_udpsig, tvb, tree_offset, sizeof(JXTA_UDP_SIG), FALSE);
604 tree_offset += sizeof(JXTA_UDP_SIG);
606 jxta_message_framing_tvb = tvb_new_subset(tvb, tree_offset, -1, -1);
607 processed = dissect_jxta_message_framing(jxta_message_framing_tvb, pinfo, NULL, &content_length, &content_type);
609 if ((0 == processed) || (NULL == content_type) || (content_length <= 0) || (content_length > UINT_MAX)) {
610 /** Buffer did not begin with valid framing headers */
614 processed = dissect_jxta_message_framing(jxta_message_framing_tvb, pinfo, tree, &content_length, &content_type);
616 tree_offset += processed;
618 jxta_message_tvb = tvb_new_subset(tvb, tree_offset, (gint) content_length, (gint) content_length);
620 dissected = dissector_try_string(media_type_dissector_table, content_type, jxta_message_tvb, pinfo, tree);
623 call_dissector(data_handle, jxta_message_tvb, pinfo, tree);
626 tree_offset += (guint) content_length;
628 proto_item_set_end(jxta_udp_tree_item, tvb, tree_offset);
630 DISSECTOR_ASSERT(offset == tree_offset);
637 * Dissect a tvbuff containing JXTA stream PDUs. This commonly includes
638 * connections over TCP sockets.
640 * <p/>The stream (in both directions) will consist of a JXTA Welcome Message
641 * followed by an indeterminate number of JXTA Message Framing Headers and
644 * @param tvb The buffer to dissect.
645 * @param pinfo Packet Info.
646 * @param tree The protocol tree.
647 * @return Number of bytes from the tvbuff_t which were processed, 0 (zero) if
648 * the packet was not recognized as a JXTA packet and negative if the
649 * dissector needs more bytes in order to process a PDU.
651 static int dissect_jxta_stream(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
654 guint available = tvb_reported_length_remaining(tvb, offset);
657 conversation_t *tpt_conversation = NULL;
658 jxta_stream_conversation_data *tpt_conv_data = NULL;
659 proto_item *jxta_tree_item = NULL;
660 proto_tree *jxta_tree = NULL;
662 /*g_message("Dissecting %s : %d", (NULL != tree) ? "for display" : "", pinfo->fd->num );*/
664 if (available < sizeof(JXTA_WELCOME_MSG_SIG)) {
665 needed = (gint) (sizeof(JXTA_WELCOME_MSG_SIG) - available);
669 if (0 == tvb_memeql(tvb, 0, JXTA_WELCOME_MSG_SIG, sizeof(JXTA_WELCOME_MSG_SIG))) {
670 /* The beginning of a JXTA stream connection */
671 address *welcome_addr;
672 gboolean initiator = FALSE;
674 tpt_conversation = get_tpt_conversation(pinfo, TRUE);
675 tpt_conv_data = (jxta_stream_conversation_data *) conversation_get_proto_data(tpt_conversation, proto_jxta);
677 if (0 == tpt_conv_data->initiator_welcome_frame) {
678 /* The initiator welcome frame */
679 tpt_conv_data->tpt_ptype = pinfo->ptype;
680 tpt_conv_data->initiator_welcome_frame = pinfo->fd->num;
681 COPY_ADDRESS(&tpt_conv_data->initiator_tpt_address, &pinfo->src);
682 tpt_conv_data->initiator_tpt_port = pinfo->srcport;
684 welcome_addr = &tpt_conv_data->initiator_address;
687 if (tpt_conv_data->initiator_welcome_frame >= pinfo->fd->num) {
688 /* what we saw previously was the receiver welcome message */
689 tpt_conv_data->receiver_welcome_frame = tpt_conv_data->initiator_welcome_frame;
690 tpt_conv_data->receiver_tpt_address = tpt_conv_data->initiator_tpt_address;
691 tpt_conv_data->receiver_tpt_port = tpt_conv_data->initiator_tpt_port;
692 tpt_conv_data->receiver_address = tpt_conv_data->initiator_address;
693 tpt_conv_data->initiator_welcome_frame = pinfo->fd->num;
694 COPY_ADDRESS(&tpt_conv_data->initiator_tpt_address, &pinfo->src);
695 tpt_conv_data->initiator_tpt_port = pinfo->srcport;
697 welcome_addr = &tpt_conv_data->initiator_address;
700 /* The receiver welcome frame */
701 tpt_conv_data->tpt_ptype = pinfo->ptype;
702 tpt_conv_data->receiver_welcome_frame = pinfo->fd->num;
703 COPY_ADDRESS(&tpt_conv_data->receiver_tpt_address, &pinfo->src);
704 tpt_conv_data->receiver_tpt_port = pinfo->srcport;
706 welcome_addr = &tpt_conv_data->receiver_address;
711 processed = dissect_jxta_welcome(tvb, pinfo, NULL, welcome_addr, initiator);
713 if( processed < 0 ) {
718 /* redo, this time creating the display tree. */
720 proto_tree_add_protocol_format(tree, proto_jxta, tvb, offset, -1, "JXTA" );
721 jxta_tree = proto_item_add_subtree(jxta_tree_item, ett_jxta);
723 processed = dissect_jxta_welcome(tvb, pinfo, jxta_tree, welcome_addr, initiator);
725 /* Somewhere in the middle of a JXTA stream connection */
726 guint64 content_length = -1;
727 gchar *content_type = NULL;
728 gint headers_len = dissect_jxta_message_framing(tvb, pinfo, NULL, &content_length, &content_type);
730 /*g_message("%d Tpt %s:%d -> %s:%d tvb len=%d\n\t%s %u", pinfo->fd->num,
731 address_to_str(&pinfo->src), pinfo->srcport,
732 address_to_str(&pinfo->dst), pinfo->destport,
733 tvb_reported_length_remaining(tvb, 0),
734 (content_type) ? content_type : "[unknown content type]", (guint) content_length);*/
736 if ((0 == headers_len) || (NULL == content_type) || (content_length <= 0) || (content_length > UINT_MAX)) {
737 /** Buffer did not begin with valid framing headers */
741 if (headers_len < 0) {
742 /* negative headers_len means we need more bytes */
743 needed = -headers_len;
748 proto_tree_add_protocol_format(tree, proto_jxta, tvb, offset, -1, "JXTA" );
749 jxta_tree = proto_item_add_subtree(jxta_tree_item, ett_jxta);
751 /* Redo header processing, this time populating the tree. */
752 headers_len = dissect_jxta_message_framing(tvb, pinfo, jxta_tree, &content_length, &content_type);
754 available = tvb_reported_length_remaining(tvb, offset + headers_len);
755 if (available >= content_length) {
756 tvbuff_t *jxta_message_tvb = tvb_new_subset(tvb, offset + headers_len, (gint) content_length, (gint) content_length);
757 conversation_t *peer_conversation = NULL;
758 address saved_src_addr;
759 guint32 saved_src_port = 0;
760 address saved_dst_addr;
761 guint32 saved_dst_port = 0;
762 port_type saved_port_type = PT_NONE;
765 tpt_conversation = get_tpt_conversation(pinfo, TRUE);
767 if (NULL != tpt_conversation) {
768 tpt_conv_data = (jxta_stream_conversation_data *) conversation_get_proto_data(tpt_conversation, proto_jxta);
770 if ((AT_NONE != tpt_conv_data->initiator_address.type) && (AT_NONE != tpt_conv_data->receiver_address.type)) {
772 find_conversation(pinfo->fd->num, &tpt_conv_data->initiator_address, &tpt_conv_data->receiver_address,
773 PT_NONE, 0, 0, NO_PORT_B);
775 if (NULL == peer_conversation) {
777 conversation_new(pinfo->fd->num, &tpt_conv_data->initiator_address,
778 &tpt_conv_data->receiver_address, PT_NONE, 0, 0, NO_PORT_B);
779 conversation_set_dissector(peer_conversation, stream_jxta_handle);
783 g_warning("Uninitialized peer conversation");
787 /* Use our source and destination addresses if we have them */
788 if (NULL != peer_conversation) {
789 saved_src_addr = pinfo->src;
790 saved_src_port = pinfo->srcport;
791 saved_dst_addr = pinfo->dst;
792 saved_dst_port = pinfo->destport;
793 saved_port_type = pinfo->ptype;
794 /*g_message("%d Tpt %s:%d -> %s:%d", pinfo->fd->num, ip_to_str(tpt_conv_data->initiator_tpt_address.data),
795 tpt_conv_data->initiator_tpt_port, ip_to_str(tpt_conv_data->receiver_tpt_address.data),
796 tpt_conv_data->receiver_tpt_port);*/
797 if (ADDRESSES_EQUAL(&pinfo->src, &tpt_conv_data->initiator_tpt_address)
798 && tpt_conv_data->initiator_tpt_port == pinfo->srcport) {
799 /*g_message("%d From initiator : %s -> %s ", pinfo->fd->num, tpt_conv_data->initiator_address.data,
800 tpt_conv_data->receiver_address.data);*/
801 pinfo->src = tpt_conv_data->initiator_address;
802 pinfo->dst = tpt_conv_data->receiver_address;
803 } else if (ADDRESSES_EQUAL(&pinfo->src, &tpt_conv_data->receiver_tpt_address) &&
804 tpt_conv_data->receiver_tpt_port == pinfo->srcport) {
805 /*g_message("%d From receiver : %s -> %s ", pinfo->fd->num, tpt_conv_data->receiver_address.data,
806 tpt_conv_data->initiator_address.data);*/
807 pinfo->src = tpt_conv_data->receiver_address;
808 pinfo->dst = tpt_conv_data->initiator_address;
810 /*g_message("%d Nothing matches %s:%d -> %s:%d", pinfo->fd->num, ip_to_str(pinfo->src.data), pinfo->srcport,
811 ip_to_str(pinfo->dst.data), pinfo->destport);*/
813 /* JXTA doesn't use ports */
814 pinfo->ptype = PT_NONE;
820 dissector_try_string(media_type_dissector_table, content_type, jxta_message_tvb, pinfo, tree);
823 call_dissector(data_handle, jxta_message_tvb, pinfo, jxta_tree);
826 /* Restore the saved src and dst addresses */
827 if (NULL != peer_conversation) {
828 pinfo->src = saved_src_addr;
829 pinfo->srcport = saved_src_port;
830 pinfo->dst = saved_dst_addr;
831 pinfo->destport = saved_dst_port;
832 pinfo->ptype = saved_port_type;
835 processed = (guint) content_length + headers_len;
837 /* we need more bytes before we can process message body. */
838 needed = (gint) ((guint) content_length - available);
846 if ((needed > 0) && gDESEGMENT && pinfo->can_desegment) {
847 /*g_message( "Requesting %d more bytes", needed );*/
848 pinfo->desegment_offset = offset;
849 pinfo->desegment_len = needed;
857 * Find or possibly create a transport conversation object for the connection
858 * which is associated with the packet info.
860 * @param pinfo The packet info from the underlying transport.
861 * @param create If TRUE then create a new conversation object if necessary.
863 static conversation_t *get_tpt_conversation(packet_info * pinfo, gboolean create)
865 conversation_t *tpt_conversation =
866 find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
867 jxta_stream_conversation_data *tpt_conv_data;
869 if (tpt_conversation == NULL) {
875 * No conversation exists yet - create one.
878 conversation_new(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
881 conversation_set_dissector(tpt_conversation, stream_jxta_handle);
883 tpt_conv_data = (jxta_stream_conversation_data *) conversation_get_proto_data(tpt_conversation, proto_jxta);
885 if (NULL == tpt_conv_data) {
886 tpt_conv_data = se_alloc(sizeof(jxta_stream_conversation_data));
887 tpt_conv_data->tpt_ptype = pinfo->ptype;
889 COPY_ADDRESS(&tpt_conv_data->initiator_tpt_address, &pinfo->src);
890 tpt_conv_data->initiator_tpt_port = pinfo->srcport;
891 tpt_conv_data->initiator_welcome_frame = 0;
892 /* XXX bondolo This is not quite correct as it should include port until a peerid can be associated. */
893 COPY_ADDRESS(&tpt_conv_data->initiator_address, &pinfo->src);
895 COPY_ADDRESS(&tpt_conv_data->receiver_tpt_address, &pinfo->dst);
896 tpt_conv_data->receiver_tpt_port = pinfo->destport;
897 tpt_conv_data->receiver_welcome_frame = 0;
898 /* XXX bondolo This is not quite correct as it should include port until a peerid can be associated. */
899 COPY_ADDRESS(&tpt_conv_data->receiver_address, &pinfo->dst);
901 conversation_add_proto_data(tpt_conversation, proto_jxta, tpt_conv_data);
904 return tpt_conversation;
908 * Dissect a tvbuff containing a JXTA Welcome Message
910 * @param tvb The buffer to dissect.
911 * @param pinfo Packet Info.
912 * @param tree The protocol tree.
913 * @param found_addr The address found in the welcome message.
914 * @param initiator If TRUE then we believe this welcome message to be the initiator's.
915 * @return Number of bytes from the tvbuff_t which were processed, 0 (zero) if
916 * the packet was not recognized as a JXTA packet and negative if the
917 * dissector needs more bytes in order to process a PDU.
919 static int dissect_jxta_welcome(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, address * found_addr, gboolean initiator)
924 guint available = tvb_reported_length_remaining(tvb, offset);
925 gchar **tokens = NULL;
927 if (available < sizeof(JXTA_WELCOME_MSG_SIG)) {
928 return (gint) (available - sizeof(JXTA_WELCOME_MSG_SIG));
931 if (0 != tvb_memeql(tvb, 0, JXTA_WELCOME_MSG_SIG, sizeof(JXTA_WELCOME_MSG_SIG))) {
936 first_linelen = tvb_find_line_end(tvb, offset, -1, &afterwelcome, gDESEGMENT && pinfo->can_desegment);
938 if (-1 == first_linelen) {
939 if (available > 4096) {
940 /* it's too far too be reasonable */
943 /* ask for more bytes */
948 /* Dissect the Welcome Message */
950 if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
951 col_set_str(pinfo->cinfo, COL_PROTOCOL, "JXTA");
954 if (check_col(pinfo->cinfo, COL_INFO)) {
955 col_add_str(pinfo->cinfo, COL_INFO, "Welcome");
959 gchar *welcomeline = tvb_get_ephemeral_string(tvb, offset, first_linelen);
960 gchar **current_token;
961 guint token_offset = offset;
962 proto_item *jxta_welcome_tree_item = NULL;
963 proto_tree *jxta_welcome_tree = NULL;
965 tokens = g_strsplit(welcomeline, " ", 255);
966 current_token = tokens;
969 jxta_welcome_tree_item =
970 proto_tree_add_none_format(tree, hf_jxta_welcome, tvb, offset, afterwelcome,
971 "JXTA Connection Welcome Message, %s", welcomeline);
972 jxta_welcome_tree = proto_item_add_subtree(jxta_welcome_tree_item, ett_jxta_welcome);
975 if (jxta_welcome_tree) {
976 proto_item *jxta_welcome_initiator_item =
977 proto_tree_add_boolean(jxta_welcome_tree, hf_jxta_welcome_initiator, tvb, 0, 0, initiator);
978 PROTO_ITEM_SET_GENERATED(jxta_welcome_initiator_item);
981 if (NULL != *current_token) {
982 if (jxta_welcome_tree) {
983 proto_tree_add_item(jxta_welcome_tree, hf_jxta_welcome_sig, tvb, token_offset, strlen(*current_token), FALSE);
986 token_offset += strlen(*current_token) + 1;
989 /* invalid welcome message */
994 if (NULL != *current_token) {
995 if (jxta_welcome_tree) {
996 proto_tree_add_item(jxta_welcome_tree, hf_jxta_welcome_destAddr, tvb, token_offset, strlen(*current_token),
1000 token_offset += strlen(*current_token) + 1;
1003 /* invalid welcome message */
1008 if (NULL != *current_token) {
1009 if (jxta_welcome_tree) {
1010 proto_tree_add_item(jxta_welcome_tree, hf_jxta_welcome_pubAddr, tvb, token_offset, strlen(*current_token), FALSE);
1013 token_offset += strlen(*current_token) + 1;
1016 /* invalid welcome message */
1021 if (NULL != *current_token) {
1022 if (jxta_welcome_tree) {
1023 proto_tree_add_item(jxta_welcome_tree, hf_jxta_welcome_peerid, tvb, token_offset, strlen(*current_token), FALSE);
1026 if (check_col(pinfo->cinfo, COL_INFO)) {
1027 col_append_str(pinfo->cinfo, COL_INFO, (initiator ? " -> " : " <- ") );
1028 col_append_str(pinfo->cinfo, COL_INFO, *current_token);
1031 if (NULL != found_addr) {
1032 found_addr->type = AT_URI;
1033 found_addr->len = strlen(*current_token);
1034 /* FIXME 20050605 bondolo THIS ALLOCATION IS A MEMORY LEAK! */
1035 found_addr->data = g_strdup(*current_token);
1038 token_offset += strlen(*current_token) + 1;
1041 /* invalid welcome message */
1046 if (NULL != *current_token) {
1047 int variable_tokens = 0;
1048 gchar **variable_token = current_token;
1050 while(NULL != *variable_token) {
1055 if( variable_tokens < 1 ) {
1056 /* invalid welcome message */
1061 if( (2 == variable_tokens) && (0 == strcmp(JXTA_WELCOME_MSG_VERSION_1_1, current_token[variable_tokens -1])) ) {
1062 if (jxta_welcome_tree) {
1063 proto_tree_add_item(jxta_welcome_tree, hf_jxta_welcome_noProp, tvb, token_offset, strlen(*current_token), FALSE);
1066 token_offset += strlen(*current_token) + 1;
1069 if (jxta_welcome_tree) {
1070 proto_tree_add_item(jxta_welcome_tree, hf_jxta_welcome_version, tvb, token_offset, strlen(*current_token), FALSE);
1073 /* Unrecognized Welcome Version */
1074 int each_variable_token;
1076 for( each_variable_token = 0; each_variable_token < variable_tokens; each_variable_token++ ) {
1077 if (jxta_welcome_tree) {
1078 jxta_welcome_tree_item = proto_tree_add_item(jxta_welcome_tree,
1079 (each_variable_token < (variable_tokens -1) ? hf_jxta_welcome_variable : hf_jxta_welcome_version),
1080 tvb, token_offset, strlen(*current_token), FALSE);
1082 proto_item_append_text(jxta_welcome_tree_item, " (UNRECOGNIZED)");
1085 token_offset += strlen(*current_token) + 1;
1090 /* invalid welcome message */
1099 col_set_writable(pinfo->cinfo, FALSE);
1101 return afterwelcome;
1105 * Dissect a tvbuff containing JXTA Message framing.
1107 * @param tvb The buffer to dissect.
1108 * @param pinfo Packet Info.
1109 * @param tree The protocol tree.
1110 * @param content_length Pointer to a buffer for storing the value of the
1111 * "content-length" header or NULL.
1112 * @param content_type Pointer-to-a-pointer for a new buffer for storing the
1113 * value of the "content_type-length" header or NULL.
1114 * @return Number of bytes from the tvbuff_t which were processed, 0 (zero) if
1115 * the packet was not recognized as a JXTA packet and negative if the
1116 * dissector needs more bytes in order to process a PDU.
1118 static int dissect_jxta_message_framing(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, guint64 * content_length,
1119 gchar ** content_type)
1126 * First go around. Make sure all of the bytes are there.
1129 guint8 headername_len;
1130 guint8 headername_offset;
1131 guint16 headervalue_len;
1132 guint16 headervalue_offset;
1134 available = tvb_reported_length_remaining(tvb, offset);
1135 if (available < sizeof(guint8)) {
1136 needed = (gint) (sizeof(guint8) - available);
1139 headername_len = tvb_get_guint8(tvb, offset);
1140 offset += sizeof(guint8);
1141 headername_offset = offset;
1143 available = tvb_reported_length_remaining(tvb, offset);
1144 if (available < headername_len) {
1145 needed = (gint) (headername_len - available);
1149 if (0 == headername_len) {
1152 offset += headername_len;
1155 available = tvb_reported_length_remaining(tvb, offset);
1156 if (available < sizeof(guint16)) {
1157 needed = (gint) (sizeof(guint16) - available);
1160 headervalue_len = tvb_get_ntohs(tvb, offset);
1161 offset += sizeof(guint16);
1162 headervalue_offset = offset;
1164 available = tvb_reported_length_remaining(tvb, offset);
1165 if (available < headervalue_len) {
1166 needed = (gint) (headervalue_len - available);
1170 offset += headervalue_len;
1173 if (content_type && (sizeof("content-type") - 1) == headername_len) {
1174 if (0 == tvb_strncaseeql(tvb, headername_offset, "content-type", sizeof("content-type") - 1)) {
1175 *content_type = tvb_get_ephemeral_string(tvb, headervalue_offset, headervalue_len);
1180 if (content_length && (sizeof(guint64) == headervalue_len) && ((sizeof("content-length") - 1) == headername_len)) {
1181 if (0 == tvb_strncaseeql(tvb, headername_offset, "content-length", sizeof("content-length") - 1)) {
1182 *content_length = tvb_get_ntoh64(tvb, headervalue_offset);
1187 if ((needed > 0) && gDESEGMENT && pinfo->can_desegment) {
1188 pinfo->desegment_offset = 0;
1189 pinfo->desegment_len = needed;
1194 * Second (optional pass) Now that we are sure that all the bytes are there we update the protocol tree.
1197 guint tree_offset = 0;
1198 proto_item *framing_tree_item =
1199 proto_tree_add_none_format(tree, hf_jxta_framing, tvb, tree_offset, -1, "JXTA Message Framing Headers");
1200 proto_tree *framing_tree = proto_item_add_subtree(framing_tree_item, ett_jxta_framing);
1202 /* parse framing headers */
1204 guint8 headernamelen = tvb_get_guint8(tvb, tree_offset);
1205 proto_item *framing_header_tree_item =
1206 proto_tree_add_item(framing_tree, hf_jxta_framing_header, tvb, tree_offset, -1, FALSE);
1207 proto_tree *framing_header_tree = proto_item_add_subtree(framing_header_tree_item, ett_jxta_framing_header);
1210 * Put header name into the protocol tree
1212 proto_tree_add_item(framing_header_tree, hf_jxta_framing_header_name, tvb, tree_offset, 1, headernamelen);
1215 * Append header name into the header protocol item. It's a nice hint so you don't have to reveal all headers.
1217 if (headernamelen > 0) {
1218 proto_item_append_text(framing_header_tree_item, " \"%s\"",
1219 tvb_format_text(tvb, tree_offset + sizeof(guint8), headernamelen));
1222 tree_offset += sizeof(guint8) + headernamelen;
1224 if (headernamelen > 0) {
1225 guint16 headervaluelen = tvb_get_ntohs(tvb, tree_offset);
1228 proto_tree_add_uint(framing_header_tree, hf_jxta_framing_header_value_length, tvb, tree_offset,
1229 sizeof(guint16), headervaluelen);
1231 /** TODO bondolo Add specific handling for known header types */
1234 * Put header value into protocol tree.
1236 proto_tree_add_item(framing_header_tree, hf_jxta_framing_header_value, tvb, tree_offset + sizeof(guint16),
1237 headervaluelen, FALSE);
1240 tree_offset += sizeof(guint16) + headervaluelen;
1243 proto_item_set_end(framing_header_tree_item, tvb, tree_offset);
1245 if (0 == headernamelen) {
1250 proto_item_set_end(framing_tree_item, tvb, tree_offset);
1252 DISSECTOR_ASSERT(offset == tree_offset);
1255 /* return how many bytes we used up. */
1260 * Dissect a tvbuff containing a JXTA Message.
1262 * @param tvb The buffer to dissect.
1263 * @param pinfo Packet Info.
1264 * @param tree The protocol tree.
1265 * @return Number of bytes from the tvbuff_t which were processed, 0 (zero) if
1266 * the packet was not recognized as a JXTA packet and negative if the
1267 * dissector needs more bytes in order to process a PDU.
1269 static int dissect_jxta_message(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
1276 /* First pass. Make sure all of the bytes we need are available */
1277 available = tvb_reported_length_remaining(tvb, offset);
1278 if (available < sizeof(JXTA_MSG_SIG)) {
1279 needed = (gint) (sizeof(JXTA_MSG_SIG) - available);
1283 if (tvb_memeql(tvb, offset, JXTA_MSG_SIG, sizeof(JXTA_MSG_SIG)) != 0) {
1284 /* It is not one of ours */
1288 offset += sizeof(JXTA_MSG_SIG);
1290 available = tvb_reported_length_remaining(tvb, offset);
1291 if (available < sizeof(guint8)) {
1292 needed = (gint) (sizeof(guint8) - available);
1295 guint8 message_version = tvb_get_guint8(tvb, offset);
1297 offset += sizeof(guint8);
1299 if (0 != message_version) {
1300 /* Sort of a lie, we say that we don't recognize it at all. */
1305 available = tvb_reported_length_remaining(tvb, offset);
1306 if (available < sizeof(guint16)) {
1307 needed = (gint) (sizeof(guint16) - available);
1310 guint16 msg_ns_count = tvb_get_ntohs(tvb, offset);
1311 guint each_namespace;
1313 offset += sizeof(guint16);
1315 for (each_namespace = 0; each_namespace < msg_ns_count; each_namespace++) {
1316 guint16 namespace_len;
1318 available = tvb_reported_length_remaining(tvb, offset);
1319 if (available < sizeof(namespace_len)) {
1320 needed = (gint) (sizeof(namespace_len) - available);
1324 namespace_len = tvb_get_ntohs(tvb, offset);
1326 available = tvb_reported_length_remaining(tvb, offset + sizeof(namespace_len));
1327 if (available < namespace_len) {
1328 needed = (gint) (namespace_len - available);
1332 offset += sizeof(namespace_len) + namespace_len;
1336 /* parse element count */
1337 available = tvb_reported_length_remaining(tvb, offset);
1338 if (available < sizeof(guint16)) {
1339 needed = (gint) (sizeof(guint16) - available);
1342 guint16 elem_count = tvb_get_ntohs(tvb, offset);
1345 offset += sizeof(guint16);
1347 /* parse elements */
1349 for (each_elem = 0; each_elem < elem_count; each_elem++) {
1350 tvbuff_t *jxta_message_element_tvb = tvb_new_subset(tvb, offset, -1, -1);
1351 int processed = dissect_jxta_message_element(jxta_message_element_tvb, pinfo, NULL, 0, NULL);
1353 if (processed < 0) {
1354 needed = -processed;
1358 if (0 == processed) {
1359 /* XXX bondolo Not really clear what we should do! */
1360 g_warning( "Failure processing message element #%d of %d of frame %d", each_elem, elem_count, pinfo->fd->num );
1364 offset += processed;
1371 if ((needed > 0) && gDESEGMENT && pinfo->can_desegment) {
1372 pinfo->desegment_offset = 0;
1373 pinfo->desegment_len = needed;
1377 if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
1378 col_set_str(pinfo->cinfo, COL_PROTOCOL, "JXTA");
1381 if (check_col(pinfo->cinfo, COL_INFO)) {
1382 gchar src_addr[MAX_ADDR_STR_LEN];
1383 gchar dst_addr[MAX_ADDR_STR_LEN];
1385 address_to_str_buf(&pinfo->src, src_addr, sizeof src_addr);
1386 address_to_str_buf(&pinfo->dst, dst_addr, sizeof dst_addr);
1388 /* append the port if appropriate */
1389 if (PT_NONE != pinfo->ptype) {
1390 size_t len = strlen(src_addr);
1391 src_addr[len] = ':';
1392 g_snprintf(&src_addr[len + 1], 256 - len - 1, "%d", pinfo->srcport);
1394 len = strlen(dst_addr);
1395 dst_addr[len] = ':';
1396 g_snprintf(&dst_addr[len + 1], 256 - len - 1, "%d", pinfo->destport);
1399 col_add_fstr(pinfo->cinfo, COL_INFO, "Message, %s -> %s", src_addr, dst_addr);
1401 col_set_writable(pinfo->cinfo, FALSE);
1405 guint tree_offset = 0;
1406 proto_item *jxta_msg_tree_item = NULL;
1407 proto_tree *jxta_msg_tree = NULL;
1408 guint8 message_version;
1409 const gchar **namespaces = NULL;
1410 guint16 msg_ns_count;
1411 guint each_namespace;
1414 gchar src_addr[256];
1415 gchar dst_addr[256];
1416 proto_item *tree_item;
1418 address_to_str_buf(&pinfo->src, src_addr, sizeof src_addr);
1419 address_to_str_buf(&pinfo->dst, dst_addr, sizeof dst_addr);
1421 if (PT_NONE != pinfo->ptype) {
1422 size_t len = strlen(src_addr);
1423 src_addr[len] = ':';
1424 g_snprintf(&src_addr[len + 1], 256 - len - 1, "%d", pinfo->srcport);
1426 len = strlen(dst_addr);
1427 dst_addr[len] = ':';
1428 g_snprintf(&dst_addr[len + 1], 256 - len - 1, "%d", pinfo->destport);
1431 jxta_msg_tree_item = proto_tree_add_protocol_format(tree, proto_message_jxta, tvb, tree_offset, -1,
1432 "JXTA Message, %s -> %s", src_addr, dst_addr);
1434 jxta_msg_tree = proto_item_add_subtree(jxta_msg_tree_item, ett_jxta_msg);
1436 proto_tree_add_item(jxta_msg_tree, hf_jxta_message_sig, tvb, tree_offset, sizeof(JXTA_MSG_SIG), FALSE);
1437 tree_offset += sizeof(JXTA_MSG_SIG);
1439 tree_item = proto_tree_add_string(jxta_msg_tree, hf_jxta_message_src, tvb, 0, 0, src_addr);
1440 PROTO_ITEM_SET_GENERATED(tree_item);
1442 tree_item = proto_tree_add_string(jxta_msg_tree, hf_jxta_message_address, tvb, 0, 0, src_addr);
1443 PROTO_ITEM_SET_HIDDEN(tree_item);
1444 PROTO_ITEM_SET_GENERATED(tree_item);
1446 tree_item = proto_tree_add_string(jxta_msg_tree, hf_jxta_message_dst, tvb, 0, 0, dst_addr);
1447 PROTO_ITEM_SET_GENERATED(tree_item);
1449 tree_item = proto_tree_add_string(jxta_msg_tree, hf_jxta_message_address, tvb, 0, 0, dst_addr);
1450 PROTO_ITEM_SET_HIDDEN(tree_item);
1451 PROTO_ITEM_SET_GENERATED(tree_item);
1453 message_version = tvb_get_guint8(tvb, tree_offset);
1454 proto_tree_add_uint(jxta_msg_tree, hf_jxta_message_version, tvb, tree_offset, sizeof(guint8), message_version);
1455 tree_offset += sizeof(guint8);
1457 msg_ns_count = tvb_get_ntohs(tvb, tree_offset);
1458 proto_tree_add_uint(jxta_msg_tree, hf_jxta_message_namespaces_count, tvb, tree_offset, sizeof(guint16), msg_ns_count);
1459 tree_offset += sizeof(guint16);
1461 namespaces = ep_alloc((msg_ns_count + 2) * sizeof(const gchar *));
1463 namespaces[1] = "jxta";
1465 /* parse namespaces */
1466 for (each_namespace = 0; each_namespace < msg_ns_count; each_namespace++) {
1467 guint16 namespace_len = tvb_get_ntohs(tvb, tree_offset);
1469 namespaces[2 + each_namespace] = tvb_get_ephemeral_string(tvb, tree_offset + sizeof(namespace_len), namespace_len);
1470 proto_tree_add_item(jxta_msg_tree, hf_jxta_message_namespace_name, tvb, tree_offset, sizeof(namespace_len), FALSE);
1471 tree_offset += sizeof(namespace_len) + namespace_len;
1474 /* parse element count */
1475 elem_count = tvb_get_ntohs(tvb, tree_offset);
1476 proto_tree_add_item(jxta_msg_tree, hf_jxta_message_element_count, tvb, tree_offset, sizeof(guint16), FALSE);
1477 tree_offset += sizeof(guint16);
1479 /* parse elements */
1480 for (each_elem = 0; each_elem < elem_count; each_elem++) {
1481 tvbuff_t *jxta_message_element_tvb = tvb_new_subset(tvb, tree_offset, -1, -1);
1484 dissect_jxta_message_element(jxta_message_element_tvb, pinfo, jxta_msg_tree, msg_ns_count + 2, namespaces);
1487 proto_item_set_end(jxta_msg_tree_item, tvb, tree_offset);
1489 DISSECTOR_ASSERT(tree_offset == offset);
1492 if ((offset > 0) && (AT_URI == pinfo->src.type) && (AT_URI == pinfo->dst.type)) {
1493 jxta_tap_header *tap_header = se_alloc(sizeof(jxta_tap_header));
1495 tap_header->src_address = pinfo->src;
1496 tap_header->dest_address = pinfo->dst;
1497 tap_header->size = offset;
1499 tap_queue_packet(jxta_tap, pinfo, tap_header);
1506 * Dissect a tvbuff containing a JXTA Message Element.
1508 * @param tvb The buffer to dissect.
1509 * @param pinfo Packet Info.
1510 * @param tree The protocol tree.
1511 * @return Number of bytes from the tvbuff_t which were processed, 0 (zero) if
1512 * the packet was not recognized as a JXTA packet and negative if the
1513 * dissector needs more bytes in order to process a PDU.
1515 static int dissect_jxta_message_element(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, guint ns_count,
1516 const gchar ** namespaces)
1523 /* First pass. Make sure all of the bytes we need are available */
1526 /* signature field */
1527 available = tvb_reported_length_remaining(tvb, offset);
1528 if (available < sizeof(JXTA_MSGELEM_SIG)) {
1529 needed = (gint) (sizeof(JXTA_MSGELEM_SIG) - available);
1532 if (tvb_memeql(tvb, offset, JXTA_MSGELEM_SIG, sizeof(JXTA_MSGELEM_SIG)) != 0) {
1533 /* It is not one of ours */
1537 offset += sizeof(JXTA_MSGELEM_SIG);
1539 /* namespace id field */
1540 available = tvb_reported_length_remaining(tvb, offset);
1541 if (available < sizeof(guint8)) {
1542 needed = (gint) (sizeof(guint8) - available);
1546 offset += sizeof(guint8);
1549 available = tvb_reported_length_remaining(tvb, offset);
1550 if (available < sizeof(guint8)) {
1551 needed = (gint) (sizeof(guint8) - available);
1554 flags = tvb_get_guint8(tvb, offset);
1555 offset += sizeof(guint8);
1559 available = tvb_reported_length_remaining(tvb, offset);
1560 if (available < sizeof(guint16)) {
1561 needed = (gint) (sizeof(guint16) - available);
1564 guint16 name_len = tvb_get_ntohs(tvb, offset);
1565 offset += sizeof(guint16);
1567 available = tvb_reported_length_remaining(tvb, offset);
1568 if (available < name_len) {
1569 needed = (gint) (name_len - available);
1577 if ((flags & 0x01) != 0) {
1580 available = tvb_reported_length_remaining(tvb, offset);
1581 if (available < sizeof(guint16)) {
1582 needed = (gint) (sizeof(guint16) - available);
1586 type_len = tvb_get_ntohs(tvb, offset);
1587 offset += sizeof(guint16);
1589 available = tvb_reported_length_remaining(tvb, offset);
1590 if (available < type_len) {
1591 needed = (gint) (type_len - available);
1598 /* encoding field */
1599 if ((flags & 0x02) != 0) {
1600 guint16 encoding_len;
1602 available = tvb_reported_length_remaining(tvb, offset);
1603 if (available < sizeof(guint16)) {
1604 needed = (gint) (sizeof(guint16) - available);
1608 encoding_len = tvb_get_ntohs(tvb, offset);
1609 offset += sizeof(guint16);
1611 available = tvb_reported_length_remaining(tvb, offset);
1612 if (available < encoding_len) {
1613 needed = (gint) (encoding_len - available);
1617 offset += encoding_len;
1621 available = tvb_reported_length_remaining(tvb, offset);
1622 if (available < sizeof(guint16)) {
1623 needed = (gint) (sizeof(guint16) - available);
1626 guint32 content_len = tvb_get_ntohl(tvb, offset);
1627 offset += sizeof(guint32);
1629 available = tvb_reported_length_remaining(tvb, offset);
1630 if (available < content_len) {
1631 needed = (gint) (content_len - available);
1635 offset += content_len;
1638 /* signature element field */
1639 if ((flags & 0x04) != 0) {
1640 tvbuff_t *jxta_signature_element_tvb;
1643 jxta_signature_element_tvb = tvb_new_subset(tvb, offset, -1, -1);
1645 processed = dissect_jxta_message_element(jxta_signature_element_tvb, pinfo, NULL, 0, NULL);
1647 if (processed == 0) {
1651 if (processed < 0) {
1652 needed = -processed;
1656 offset += processed;
1662 if ((needed > 0) && gDESEGMENT && pinfo->can_desegment) {
1663 pinfo->desegment_offset = 0;
1664 pinfo->desegment_len = needed;
1668 /* Second (optional) pass : build the proto tree */
1670 guint tree_offset = 0;
1671 proto_item *jxta_elem_tree_item = proto_tree_add_item(tree, hf_jxta_element, tvb, tree_offset, -1, FALSE);
1672 proto_tree *jxta_elem_tree = proto_item_add_subtree(jxta_elem_tree_item, ett_jxta_elem);
1674 proto_item *namespace_ti;
1676 proto_item *flags_ti;
1677 proto_tree *jxta_elem_flags_tree = NULL;
1678 guint32 content_len;
1679 gchar *mediatype = NULL;
1680 gboolean media_type_recognized = FALSE;
1681 tvbuff_t *element_content_tvb;
1682 proto_item * jxta_elem_length_item = NULL;
1684 proto_tree_add_item(jxta_elem_tree, hf_jxta_element_sig, tvb, tree_offset, sizeof(JXTA_MSGELEM_SIG), FALSE);
1685 tree_offset += sizeof(JXTA_MSGELEM_SIG);
1687 namespaceID = tvb_get_guint8(tvb, tree_offset);
1689 proto_tree_add_uint(jxta_elem_tree, hf_jxta_element_namespaceid, tvb, tree_offset, sizeof(guint8), namespaceID);
1690 if (namespaceID < ns_count) {
1691 proto_item_append_text(namespace_ti, " (%s)", namespaces[namespaceID]);
1693 proto_item_append_text(namespace_ti, " * BAD *");
1695 tree_offset += sizeof(guint8);
1697 flags = tvb_get_guint8(tvb, tree_offset);
1698 flags_ti = proto_tree_add_uint(jxta_elem_tree, hf_jxta_element_flags, tvb, tree_offset, sizeof(guint8), flags);
1699 jxta_elem_flags_tree = proto_item_add_subtree(flags_ti, ett_jxta_elem_flags);
1700 proto_tree_add_boolean(jxta_elem_flags_tree, hf_jxta_element_flag_hasType, tvb, tree_offset, 1, flags);
1701 proto_tree_add_boolean(jxta_elem_flags_tree, hf_jxta_element_flag_hasEncoding, tvb, tree_offset, 1, flags);
1702 proto_tree_add_boolean(jxta_elem_flags_tree, hf_jxta_element_flag_hasSignature, tvb, tree_offset, 1, flags);
1703 tree_offset += sizeof(guint8);
1705 name_len = tvb_get_ntohs(tvb, tree_offset);
1706 proto_item_append_text(jxta_elem_tree_item, " \"%s\"", tvb_format_text(tvb, tree_offset + sizeof(guint16), name_len));
1707 proto_tree_add_item(jxta_elem_tree, hf_jxta_element_name, tvb, tree_offset, sizeof(guint16), FALSE);
1708 tree_offset += sizeof(guint16) + name_len;
1711 if ((flags & 0x01) != 0) {
1712 guint16 type_len = tvb_get_ntohs(tvb, tree_offset);
1713 proto_tree_add_item(jxta_elem_tree, hf_jxta_element_type, tvb, tree_offset, sizeof(guint16), FALSE);
1714 tree_offset += sizeof(guint16);
1716 mediatype = tvb_get_ephemeral_string(tvb, tree_offset, type_len);
1718 /* remove any params */
1720 gchar *parms_at = strchr(mediatype, ';');
1722 if (NULL != parms_at) {
1727 /* force to lower case */
1728 #if GLIB_MAJOR_VERSION < 2
1729 g_strdown(mediatype);
1732 gchar *mediatype_lowercase = g_ascii_strdown(mediatype, -1);
1733 mediatype = mediatype_lowercase;
1736 tree_offset += type_len;
1739 /* process encoding */
1740 if ((flags & 0x02) != 0) {
1741 guint16 encoding_len = tvb_get_ntohs(tvb, tree_offset);
1742 proto_tree_add_item(jxta_elem_tree, hf_jxta_element_encoding, tvb, tree_offset, sizeof(guint16), FALSE);
1743 tree_offset += sizeof(guint16) + encoding_len;
1747 content_len = tvb_get_ntohl(tvb, tree_offset);
1748 jxta_elem_length_item = proto_tree_add_item(jxta_elem_tree, hf_jxta_element_content_len, tvb, tree_offset, sizeof(guint32), FALSE);
1749 tree_offset += sizeof(guint32);
1751 element_content_tvb = tvb_new_subset(tvb, tree_offset, content_len, content_len);
1754 if (0 == strcmp("application/x-jxta-tls-block", mediatype)) {
1755 /* If we recognize it as a TLS packet then we shuffle it off to ssl dissector. */
1756 dissector_handle_t ssl_handle = find_dissector("ssl");
1757 if (NULL != ssl_handle) {
1758 int processed = call_dissector(ssl_handle, element_content_tvb, pinfo, jxta_elem_tree);
1759 media_type_recognized = processed != 0;
1761 } else if (0 == strcmp("application/gzip", mediatype)) {
1762 tvbuff_t *uncomp_tvb = tvb_uncompress(element_content_tvb, 0, tvb_length(element_content_tvb));
1764 if( NULL != uncomp_tvb ) {
1765 proto_item_append_text( jxta_elem_length_item, " -> (%u uncompressed)", tvb_length(uncomp_tvb) );
1767 tvb_set_child_real_data_tvbuff(element_content_tvb, uncomp_tvb);
1768 add_new_data_source(pinfo, uncomp_tvb, "Uncompressed Element Content");
1770 /* XXX bondolo 20060201 Force XML for uncompressed data. */
1771 media_type_recognized = dissector_try_string(media_type_dissector_table,
1772 "text/xml", uncomp_tvb, pinfo, jxta_elem_tree);
1775 media_type_recognized = dissector_try_string(media_type_dissector_table,
1776 mediatype, element_content_tvb, pinfo, jxta_elem_tree);
1781 if (!media_type_recognized) {
1782 /* display it as raw data */
1783 call_dissector(data_handle, element_content_tvb, pinfo, jxta_elem_tree);
1785 tree_offset += content_len;
1787 /* process the signature element */
1788 if ((flags & 0x04) != 0) {
1789 tvbuff_t *jxta_message_element_tvb = tvb_new_subset(tvb, tree_offset, -1, -1);
1791 tree_offset += dissect_jxta_message_element(jxta_message_element_tvb, pinfo, jxta_elem_tree, ns_count, namespaces);
1794 proto_item_set_end(jxta_elem_tree_item, tvb, tree_offset);
1796 DISSECTOR_ASSERT(tree_offset == offset);
1803 * Register jxta protocol and jxta message protocol, header fields, subtree types, preferences.
1805 void proto_register_jxta(void)
1807 module_t *jxta_module;
1809 media_type_dissector_table = find_dissector_table("media_type");
1811 data_handle = find_dissector("data");
1813 proto_jxta = proto_register_protocol("JXTA P2P", "JXTA", "jxta");
1815 jxta_tap = register_tap("jxta");
1817 /* The JXTA Binary Message Wire Format : Registered and dissected by MIME type */
1818 proto_message_jxta = proto_register_protocol("JXTA Message", "JXTA Message", "jxta.message");
1820 message_jxta_handle = new_create_dissector_handle(dissect_jxta_message, proto_message_jxta);
1822 dissector_add_string("media_type", "application/x-jxta-msg", message_jxta_handle);
1824 /* Register header fields */
1825 proto_register_field_array(proto_jxta, hf, array_length(hf));
1827 /* Register JXTA Sub-tree */
1828 proto_register_subtree_array(ett, array_length(ett));
1830 /* Register preferences */
1831 /* register re-init routine */
1832 jxta_module = prefs_register_protocol(proto_jxta, proto_reg_handoff_jxta);
1834 prefs_register_bool_preference(jxta_module, "desegment",
1835 "Reassemble JXTA messages spanning multiple UDP/TCP/HTTP segments",
1836 "Whether the JXTA dissector should reassemble messages spanning multiple UDP/HTTP/TCP segments."
1837 " To use this option you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings "
1838 " and enable \"Reassemble fragmented IP datagrams\" in the IP protocol settings.",
1841 prefs_register_bool_preference(jxta_module, "udp.heuristic", "Try to discover JXTA in UDP datagrams",
1842 "Enable to inspect UDP datagrams for JXTA messages.", &gUDP_HEUR);
1844 prefs_register_bool_preference(jxta_module, "tcp.heuristic", "Try to discover JXTA in TCP connections",
1845 "Enable to inspect TCP connections for JXTA conversations.", &gTCP_HEUR);
1847 prefs_register_bool_preference(jxta_module, "sctp.heuristic", "Try to discover JXTA in SCTP connections",
1848 "Enable to inspect SCTP connections for JXTA conversations.", &gSCTP_HEUR);
1852 * Update registrations in response to
1854 void proto_reg_handoff_jxta(void)
1856 static gboolean init_done = FALSE;
1859 /* XXX 20051004 bondolo We could dynamically add dissectors based upon prefs. */
1860 new_register_dissector("jxta.udp", dissect_jxta_udp, proto_jxta);
1861 heur_dissector_add("udp", dissect_jxta_UDP_heur, proto_jxta);
1863 new_register_dissector("jxta.stream", dissect_jxta_stream, proto_jxta);
1864 stream_jxta_handle = find_dissector("jxta.stream");
1865 heur_dissector_add("tcp", dissect_jxta_TCP_heur, proto_jxta);
1866 heur_dissector_add("sctp", dissect_jxta_SCTP_heur, proto_jxta);