3 * Routines for JXTA packet dissection
4 * JXTA specification from https://jxta-spec.dev.java.net
6 * Copyright 2004-08, Mike Duigou <bondolo@dev.java.net>
8 * Heavily based on packet-jabber.c, which in turn is heavily based on
9 * on packet-acap.c, which in turn is heavily based on
10 * packet-imap.c, Copyright 1999, Richard Sharpe <rsharpe@ns.aus.com>
11 * Copied from packet-pop.c, packet-jabber.c, packet-udp.c, packet-http.c
15 * Wireshark - Network traffic analyzer
16 * By Gerald Combs <gerald@wireshark.org>
17 * Copyright 2000 Gerald Combs
19 * This program is free software; you can redistribute it and/or
20 * modify it under the terms of the GNU General Public License
21 * as published by the Free Software Foundation; either version 2
22 * of the License, or (at your option) any later version.
24 * This program is distributed in the hope that it will be useful,
25 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27 * GNU General Public License for more details.
29 * You should have received a copy of the GNU General Public License
30 * along with this program; if not, write to the Free Software
31 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
42 #define G_LOG_DOMAIN "jxta"
46 #include <epan/packet.h>
47 #include <epan/conversation.h>
48 #include <epan/strutil.h>
49 #include <epan/prefs.h>
51 #include <epan/emem.h>
52 #include <epan/ws_strsplit.h>
54 #include "packet-jxta.h"
56 static const gchar JXTA_UDP_SIG[] = { 'J', 'X', 'T', 'A' };
57 static const gchar JXTA_MSG_SIG[] = { 'j', 'x', 'm', 'g' };
58 static const gchar JXTA_MSGELEM_SIG[] = { 'j', 'x', 'e', 'l' };
60 static const gchar JXTA_WELCOME_MSG_SIG[] = { 'J', 'X', 'T', 'A', 'H', 'E', 'L', 'L', 'O', ' ' };
62 static const gchar* JXTA_WELCOME_MSG_VERSION_1_1 = "1.1";
63 static const gchar* JXTA_WELCOME_MSG_VERSION_3_0 = "3.0";
65 static const int JXTA_MSG_VERSION_1 = 0;
66 static const int JXTA_MSG_VERSION_2 = 1;
68 static const int JXTAMSG1_ELMFLAG_TYPE = 1 << 0;
69 static const int JXTAMSG1_ELMFLAG_ENCODING = 1 << 1;
70 static const int JXTAMSG1_ELMFLAG_SIGNATURE = 1 << 2;
72 static const int JXTAMSG2_ELMFLAG_UINT64_LENS = 1 << 0;
73 static const int JXTAMSG2_ELMFLAG_NAME_LITERAL = 1 << 1;
74 static const int JXTAMSG2_ELMFLAG_TYPE = 1 << 2;
75 static const int JXTAMSG2_ELMFLAG_SIGNATURE = 1 << 3;
76 static const int JXTAMSG2_ELMFLAG_ENCODINGS = 1 << 4;
78 static int proto_jxta = -1;
79 static int proto_message_jxta = -1;
80 static int jxta_tap = -1;
82 static dissector_table_t media_type_dissector_table = NULL;
83 static dissector_handle_t media_handle = NULL;
84 static dissector_handle_t data_handle = NULL;
85 static dissector_handle_t stream_jxta_handle = NULL;
86 static dissector_handle_t message_jxta_handle;
88 static int hf_uri_addr = -1;
89 static int hf_uri_src = -1;
90 static int hf_uri_dst = -1;
91 static int hf_jxta_udp = -1;
92 static int hf_jxta_udpsig = -1;
93 static int hf_jxta_welcome = -1;
94 static int hf_jxta_welcome_initiator = -1;
95 static int hf_jxta_welcome_sig = -1;
96 static int hf_jxta_welcome_destAddr = -1;
97 static int hf_jxta_welcome_pubAddr = -1;
98 static int hf_jxta_welcome_peerid = -1;
99 static int hf_jxta_welcome_noProp = -1;
100 static int hf_jxta_welcome_msgVers = -1;
101 static int hf_jxta_welcome_variable = -1;
102 static int hf_jxta_welcome_version = -1;
103 static int hf_jxta_framing = -1;
104 static int hf_jxta_framing_header = -1;
105 static int hf_jxta_framing_header_name = -1;
106 static int hf_jxta_framing_header_value_length = -1;
107 static int hf_jxta_framing_header_value = -1;
108 static int hf_jxta_message_address = -1;
109 static int hf_jxta_message_src = -1;
110 static int hf_jxta_message_dst = -1;
111 static int hf_jxta_message_sig = -1;
112 static int hf_jxta_message_version = -1;
113 static int hf_jxta_message_flags = -1;
114 static int hf_jxta_message_flag_utf16be = -1;
115 static int hf_jxta_message_flag_ucs32be = -1;
116 static int hf_jxta_message_names_count = -1;
117 static int hf_jxta_message_names_name = -1;
118 static int hf_jxta_message_element_count = -1;
119 static int hf_jxta_element = -1;
120 static int hf_jxta_element_sig = -1;
121 static int hf_jxta_element1_namespaceid = -1;
122 static int hf_jxta_element2_namespaceid = -1;
123 static int hf_jxta_element2_nameid = -1;
124 static int hf_jxta_element2_mimeid = -1;
125 static int hf_jxta_element2_encodingid = -1;
126 static int hf_jxta_element_flags = -1;
127 static int hf_jxta_element1_flag_hasType = -1;
128 static int hf_jxta_element1_flag_hasEncoding = -1;
129 static int hf_jxta_element1_flag_hasSignature = -1;
130 static int hf_jxta_element2_flag_64bitlens = -1;
131 static int hf_jxta_element2_flag_nameLiteral = -1;
132 static int hf_jxta_element2_flag_hasType = -1;
133 static int hf_jxta_element2_flag_hasSignature = -1;
134 static int hf_jxta_element2_flag_hasEncoding = -1;
135 static int hf_jxta_element2_flag_sigOfEncoded = -1;
136 static int hf_jxta_element_name = -1;
137 static int hf_jxta_element_type = -1;
138 static int hf_jxta_element_encoding = -1;
139 static int hf_jxta_element_content_len = -1;
140 static int hf_jxta_element_content_len64 = -1;
141 static int hf_jxta_element_content = -1;
143 /** our header fields */
144 static hf_register_info hf[] = {
146 {"Address", "uri.addr", FT_STRING, BASE_NONE, NULL, 0x0,
147 "URI Address (source or destination)", HFILL}
150 {"Source", "uri.src", FT_STRING, BASE_NONE, NULL, 0x0,
154 {"Destination", "uri.dst", FT_STRING, BASE_NONE, NULL, 0x0,
155 "URI Destination", HFILL}
158 {"JXTA UDP", "jxta.udp", FT_NONE, BASE_NONE, NULL, 0x0,
162 {"Signature", "jxta.udpsig", FT_STRING, BASE_NONE, NULL, 0x0,
163 "JXTA UDP Signature", HFILL}
166 {"Welcome", "jxta.welcome", FT_NONE, BASE_NONE, NULL, 0x00,
167 "JXTA Connection Welcome Message", HFILL}
169 {&hf_jxta_welcome_initiator,
170 {"Initiator", "jxta.welcome.initiator", FT_BOOLEAN, BASE_NONE, NULL, 0x00,
171 "JXTA Connection Welcome Message Initiator", HFILL}
173 {&hf_jxta_welcome_sig,
174 {"Signature", "jxta.welcome.signature", FT_STRING, BASE_NONE, NULL, 0x0,
175 "JXTA Connection Welcome Message Signature", HFILL}
177 {&hf_jxta_welcome_destAddr,
178 {"Destination Address", "jxta.welcome.destAddr", FT_STRING, BASE_NONE, NULL, 0x0,
179 "JXTA Connection Welcome Message Destination Address", HFILL}
181 {&hf_jxta_welcome_pubAddr,
182 {"Public Address", "jxta.welcome.pubAddr", FT_STRING, BASE_NONE, NULL, 0x0,
183 "JXTA Connection Welcome Message Public Address", HFILL}
185 {&hf_jxta_welcome_peerid,
186 {"PeerID", "jxta.welcome.peerid", FT_STRING, BASE_NONE, NULL, 0x0,
187 "JXTA Connection Welcome Message PeerID", HFILL}
189 {&hf_jxta_welcome_noProp,
190 {"No Propagate Flag", "jxta.welcome.noPropFlag", FT_STRING, BASE_NONE, NULL, 0x0,
191 "JXTA Connection Welcome Message No Propagate Flag", HFILL}
193 {&hf_jxta_welcome_msgVers,
194 {"Preferred Message Version", "jxta.welcome.msgVersion", FT_STRING, BASE_NONE, NULL, 0x0,
195 "JXTA Connection Welcome Message Preferred Message Version", HFILL}
197 {&hf_jxta_welcome_variable,
198 {"Variable Parameter", "jxta.welcome.variable", FT_STRING, BASE_NONE, NULL, 0x0,
199 "JXTA Connection Welcome Message Variable Parameter", HFILL}
201 {&hf_jxta_welcome_version,
202 {"Version", "jxta.welcome.version", FT_STRING, BASE_NONE, NULL, 0x0,
203 "JXTA Connection Welcome Message Version", HFILL}
206 {"Framing", "jxta.framing", FT_NONE, BASE_NONE, NULL, 0x0,
207 "JXTA Message Framing", HFILL}
209 {&hf_jxta_framing_header,
210 {"Header", "jxta.framing.header", FT_NONE, BASE_NONE, NULL, 0x0,
211 "JXTA Message Framing Header", HFILL}
213 {&hf_jxta_framing_header_name,
214 {"Name", "jxta.framing.header.name", FT_UINT_STRING, BASE_NONE, NULL, 0x0,
215 "JXTA Message Framing Header Name", HFILL}
217 {&hf_jxta_framing_header_value_length,
218 {"Value Length", "jxta.framing.header.valuelen", FT_UINT16, BASE_DEC, NULL, 0x0,
219 "JXTA Message Framing Header Value Length", HFILL}
221 {&hf_jxta_framing_header_value,
222 {"Value", "jxta.framing.header.value", FT_BYTES, BASE_HEX, NULL, 0x0,
223 "JXTA Message Framing Header Value", HFILL}
225 {&hf_jxta_message_address,
226 {"Address", "jxta.message.address", FT_STRING, BASE_NONE, NULL, 0x0,
227 "JXTA Message Address (source or destination)", HFILL}
229 {&hf_jxta_message_src,
230 {"Source", "jxta.message.source", FT_STRING, BASE_NONE, NULL, 0x0,
231 "JXTA Message Source", HFILL}
233 {&hf_jxta_message_dst,
234 {"Destination", "jxta.message.destination", FT_STRING, BASE_NONE, NULL, 0x0,
235 "JXTA Message Destination", HFILL}
237 {&hf_jxta_message_sig,
238 {"Signature", "jxta.message.signature", FT_STRING, BASE_NONE, NULL, 0x0,
239 "JXTA Message Signature", HFILL}
241 {&hf_jxta_message_version,
242 {"Version", "jxta.message.version", FT_UINT8, BASE_DEC, NULL, 0x0,
243 "JXTA Message Version", HFILL}
245 {&hf_jxta_message_flags,
246 {"Flags", "jxta.message.flags", FT_UINT8, BASE_HEX, NULL, 0x0,
247 "JXTA Message Flags", HFILL}
249 {&hf_jxta_message_flag_utf16be,
250 {"UTF16BE", "jxta.message.flags.UTF-16BE", FT_BOOLEAN, 2, TFS(&flags_set_truth), 0x01,
251 "JXTA Message Element Flag -- UTF16-BE Strings", HFILL}
253 {&hf_jxta_message_flag_ucs32be,
254 {"UCS32BE", "jxta.message.flags.UCS32BE", FT_BOOLEAN, 2, TFS(&flags_set_truth), 0x02,
255 "JXTA Message Flag -- UCS32-BE Strings", HFILL}
257 {&hf_jxta_message_names_count,
258 {"Names Count", "jxta.message.names", FT_UINT16, BASE_DEC, NULL, 0x0,
259 "JXTA Message Names Table", HFILL}
261 {&hf_jxta_message_names_name,
262 {"Names Table Name", "jxta.message.names.name", FT_UINT_STRING, BASE_NONE, NULL, 0x0,
263 "JXTA Message Names Table Name", HFILL}
265 {&hf_jxta_message_element_count,
266 {"Element Count", "jxta.message.elements", FT_UINT16, BASE_DEC, NULL, 0x0,
267 "JXTA Message Element Count", HFILL}
270 {"JXTA Message Element", "jxta.message.element", FT_NONE, BASE_NONE, NULL, 0x0,
271 "JXTA Message Element", HFILL}
273 {&hf_jxta_element_sig,
274 {"Signature", "jxta.message.element.signature", FT_STRING, BASE_NONE, NULL, 0x0,
275 "JXTA Message Element Signature", HFILL}
277 {&hf_jxta_element1_namespaceid,
278 {"Namespace ID", "jxta.message.element.namespaceid", FT_UINT8, BASE_DEC, NULL, 0x0,
279 "JXTA Message Element Namespace ID", HFILL}
281 {&hf_jxta_element2_namespaceid,
282 {"Namespace ID", "jxta.message.element.namespaceid", FT_UINT16, BASE_DEC, NULL, 0x0,
283 "JXTA Message Element Namespace ID", HFILL}
285 {&hf_jxta_element_flags,
286 {"Flags", "jxta.message.element.flags", FT_UINT8, BASE_HEX, NULL, 0x0,
287 "JXTA Message Element Flags", HFILL}
289 {&hf_jxta_element1_flag_hasType,
290 {"hasType", "jxta.message.element.flags.hasType", FT_BOOLEAN, 3, TFS(&flags_set_truth), 0x01,
291 "JXTA Message Element Flag -- hasType", HFILL}
293 {&hf_jxta_element1_flag_hasEncoding,
294 {"hasEncoding", "jxta.message.element.flags.hasEncoding", FT_BOOLEAN, 3, TFS(&flags_set_truth), 0x02,
295 "JXTA Message Element Flag -- hasEncoding", HFILL}
297 {&hf_jxta_element1_flag_hasSignature,
298 {"hasSignature", "jxta.message.element.flags.hasSignature", FT_BOOLEAN, 3, TFS(&flags_set_truth), 0x04,
299 "JXTA Message Element Flag -- hasSignature", HFILL}
301 {&hf_jxta_element2_flag_64bitlens,
302 {"uint64Lens", "jxta.message.element.flags.uint64Lens", FT_BOOLEAN, 6, TFS(&flags_set_truth), 0x01,
303 "JXTA Message Element Flag -- uint64Lens", HFILL}
305 {&hf_jxta_element2_flag_nameLiteral,
306 {"nameLiteral", "jxta.message.element.flags.nameLiteral", FT_BOOLEAN, 6, TFS(&flags_set_truth), 0x02,
307 "JXTA Message Element Flag -- nameLiteral", HFILL}
309 {&hf_jxta_element2_flag_hasType,
310 {"hasEncoding", "jxta.message.element.flags.hasType", FT_BOOLEAN, 6, TFS(&flags_set_truth), 0x04,
311 "JXTA Message Element Flag -- hasType", HFILL}
313 {&hf_jxta_element2_flag_hasSignature,
314 {"hasSignature", "jxta.message.element.flags.hasSignature", FT_BOOLEAN, 6, TFS(&flags_set_truth), 0x08,
315 "JXTA Message Element Flag -- hasSignature", HFILL}
317 {&hf_jxta_element2_flag_hasEncoding,
318 {"hasSignature", "jxta.message.element.flags.hasEncoding", FT_BOOLEAN, 6, TFS(&flags_set_truth), 0x10,
319 "JXTA Message Element Flag -- hasEncoding", HFILL}
321 {&hf_jxta_element2_flag_sigOfEncoded,
322 {"sigOfEncoded", "jxta.message.element.flags.sigOfEncoded", FT_BOOLEAN, 6, TFS(&flags_set_truth), 0x20,
323 "JXTA Message Element Flag -- sigOfEncoded", HFILL}
325 {&hf_jxta_element2_nameid,
326 {"Name ID", "jxta.message.element.nameid", FT_UINT16, BASE_DEC, NULL, 0x0,
327 "JXTA Message Element Name ID", HFILL}
329 {&hf_jxta_element_name,
330 {"Element Name", "jxta.message.element.name", FT_UINT_STRING, BASE_NONE, NULL, 0x0,
331 "JXTA Message Element Name", HFILL}
333 {&hf_jxta_element2_mimeid,
334 {"MIME ID", "jxta.message.element.mimeid", FT_UINT16, BASE_DEC, NULL, 0x0,
335 "JXTA Message Element MIME ID", HFILL}
337 {&hf_jxta_element2_encodingid,
338 {"Encoding ID", "jxta.message.element.encodingid", FT_UINT16, BASE_DEC, NULL, 0x0,
339 "JXTA Message Element Encoding ID", HFILL}
341 {&hf_jxta_element_type,
342 {"Element Type", "jxta.message.element.type", FT_UINT_STRING, BASE_NONE, NULL, 0x0,
343 "JXTA Message Element Name", HFILL}
345 {&hf_jxta_element_encoding,
346 {"Element Type", "jxta.message.element.encoding", FT_UINT_STRING, BASE_NONE, NULL, 0x0,
347 "JXTA Message Element Encoding", HFILL}
349 {&hf_jxta_element_content_len,
350 {"Element Content Length", "jxta.message.element.content.length", FT_UINT32, BASE_DEC, NULL, 0x0,
351 "JXTA Message Element Content Length", HFILL}
353 {&hf_jxta_element_content_len64,
354 {"Element Content Length", "jxta.message.element.content.length", FT_UINT64, BASE_DEC, NULL, 0x0,
355 "JXTA Message Element Content Length", HFILL}
357 {&hf_jxta_element_content,
358 {"Element Content", "jxta.message.element.content", FT_BYTES, BASE_HEX, NULL, 0x0,
359 "JXTA Message Element Content", HFILL}
364 * JXTA Protocol subtree handles
366 static gint ett_jxta = -1;
367 static gint ett_jxta_welcome = -1;
368 static gint ett_jxta_udp = -1;
369 static gint ett_jxta_framing = -1;
370 static gint ett_jxta_framing_header = -1;
371 static gint ett_jxta_msg = -1;
372 static gint ett_jxta_msg_flags = -1;
373 static gint ett_jxta_elem = -1;
374 static gint ett_jxta_elem_1_flags = -1;
375 static gint ett_jxta_elem_2_flags = -1;
378 * JXTA Protocol subtree array
380 static gint *const ett[] = {
385 &ett_jxta_framing_header,
389 &ett_jxta_elem_1_flags,
390 &ett_jxta_elem_2_flags
396 static gboolean gDESEGMENT = TRUE;
397 static gboolean gUDP_HEUR = TRUE;
398 static gboolean gTCP_HEUR = TRUE;
399 static gboolean gSCTP_HEUR = TRUE;
400 static gboolean gMSG_MEDIA = TRUE;
403 * Stream Conversation data
405 struct jxta_stream_conversation_data {
408 address initiator_tpt_address;
409 guint32 initiator_tpt_port;
410 guint32 initiator_welcome_frame;
411 address initiator_address;
413 address receiver_tpt_address;
414 guint32 receiver_tpt_port;
415 guint32 receiver_welcome_frame;
416 address receiver_address;
419 typedef struct jxta_stream_conversation_data jxta_stream_conversation_data;
424 static gboolean dissect_jxta_UDP_heur(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree);
425 static gboolean dissect_jxta_TCP_heur(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree);
426 static gboolean dissect_jxta_SCTP_heur(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree);
428 static int dissect_jxta_udp(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree);
429 static int dissect_jxta_stream(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree);
430 static conversation_t *get_tpt_conversation(packet_info * pinfo, gboolean create);
431 static conversation_t *get_peer_conversation(packet_info * pinfo, jxta_stream_conversation_data* tpt_conv_data, gboolean create);
433 static int dissect_jxta_welcome(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, address * found_addr, gboolean initiator);
434 static int dissect_jxta_message_framing(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, guint64 * content_length,
435 gchar ** content_type);
436 static int dissect_jxta_message(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree);
437 static int dissect_jxta_message_element_1(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, guint ns_count,
438 const gchar ** namespaces);
439 static int dissect_jxta_message_element_2(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, guint ns_count,
440 const gchar ** namespaces);
441 static int dissect_media( const gchar* fullmediatype, tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree);
443 void proto_reg_handoff_jxta(void);
446 * Heuristically dissect a tvbuff containing a JXTA UDP Message
448 * @param tvb The buffer to dissect.
449 * @param pinfo Packet Info.
450 * @param tree The protocol tree.
451 * @return TRUE if the tvb contained JXTA data which was dissected otherwise FALSE
453 static gboolean dissect_jxta_UDP_heur(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
455 /* This is a heuristic dissector, which means we get all the UDP
456 * traffic not sent to a known dissector and not claimed by
457 * a heuristic dissector called before us!
459 int save_desegment_offset;
460 guint32 save_desegment_len;
463 if (tvb_memeql(tvb, 0, JXTA_UDP_SIG, sizeof(JXTA_UDP_SIG)) != 0) {
467 save_desegment_offset = pinfo->desegment_offset;
468 save_desegment_len = pinfo->desegment_len;
469 ret = dissect_jxta_udp(tvb, pinfo, tree);
471 /* g_message( "%d Heuristic UDP Dissection : %d", pinfo->fd->num, ret ); */
475 * UDP is not a packet stream protocol, so the UDP dissector
476 * should not, and will not, do the sort of dissection help
477 * that the TCP dissector will. If JXTA messages don't
478 * start and end on UDP packet boundaries, the JXTA dissector
479 * will have to do its own byte stream reassembly.
481 pinfo->desegment_offset = save_desegment_offset;
482 pinfo->desegment_len = save_desegment_len;
484 } else if (ret == 0) {
488 pinfo->desegment_offset = save_desegment_offset;
489 pinfo->desegment_len = save_desegment_len;
493 * A clear acceptance.
500 * Heuristically dissect a tvbuff containing a JXTA TCP Stream
502 * @param tvb The buffer to dissect.
503 * @param pinfo Packet Info.
504 * @param tree The protocol tree.
505 * @return TRUE if the tvb contained JXTA data which was dissected otherwise FALSE
507 static gboolean dissect_jxta_TCP_heur(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
509 /* This is a heuristic dissector, which means we get all the TCP
510 * traffic not sent to a known dissector and not claimed by
511 * a heuristic dissector called before us!
513 int save_desegment_offset;
514 guint32 save_desegment_len;
517 save_desegment_offset = pinfo->desegment_offset;
518 save_desegment_len = pinfo->desegment_len;
519 ret = dissect_jxta_stream(tvb, pinfo, tree);
521 /* g_message( "%d Heuristic TCP Dissection : %d", pinfo->fd->num, ret ); */
525 * A heuristic dissector for a TCP-based protocol can reject
526 * a packet, or it can request that more data be provided.
527 * It must not attempt to do both, as the notion of doing both
528 * is nonsensical - if the packet isn't considered a packet
529 * for the dissector's protocol, that dissector won't be
530 * dissecting it no matter *how* much more data is added.
532 * Therefore, we treat a negative return from
533 * dissect_jxta_stream() as a rejection.
535 * If that's not desired - i.e., if we should keep trying to get
536 * more data, in the hopes that we'll eventually be able to
537 * determine whether the packet is a JXTA packet or not - we
538 * should, in this case, leave pinfo->desegment_offset and
539 * pinfo->desegment_len alone, and return TRUE, *NOT* FALSE.
541 pinfo->desegment_offset = save_desegment_offset;
542 pinfo->desegment_len = save_desegment_len;
544 } else if (ret == 0) {
548 pinfo->desegment_offset = save_desegment_offset;
549 pinfo->desegment_len = save_desegment_len;
553 * A clear acceptance.
560 * Heuristically dissect a tvbuff containing a JXTA SCTP Stream
562 * @param tvb The buffer to dissect.
563 * @param pinfo Packet Info.
564 * @param tree The protocol tree.
565 * @return TRUE if the tvb contained JXTA data which was dissected otherwise FALSE
567 static gboolean dissect_jxta_SCTP_heur(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
569 /* This is a heuristic dissector, which means we get all the SCTP
570 * traffic not sent to a known dissector and not claimed by
571 * a heuristic dissector called before us!
573 int save_desegment_offset;
574 guint32 save_desegment_len;
577 save_desegment_offset = pinfo->desegment_offset;
578 save_desegment_len = pinfo->desegment_len;
579 ret = dissect_jxta_stream(tvb, pinfo, tree);
581 /* g_message( "%d Heuristic SCTP Dissection : %d", pinfo->fd->num, ret ); */
585 * SCTP is not a byte stream protocol, so the SCTP dissector
586 * should not, and will not, do the sort of dissection help
587 * that the SCTP dissector will. If JXTA messages don't
588 * start and end on SCTP packet boundaries, the JXTA dissector
589 * will have to do its own byte stream reassembly.
591 * The SCTP dissector currently won't do reassembly. If that
592 * causes a problem for the JXTA dissector, the correct fix
593 * is to implement reassembly in the SCTP dissector, so *all*
594 * dissectors for protocols running atop SCTP can benefit from
597 pinfo->desegment_offset = save_desegment_offset;
598 pinfo->desegment_len = save_desegment_len;
600 } else if (ret == 0) {
604 pinfo->desegment_offset = save_desegment_offset;
605 pinfo->desegment_len = save_desegment_len;
609 * A clear acceptance.
616 * Dissect a tvbuff containing a JXTA UDP header, JXTA Message framing and a JXTA Message
618 * @param tvb The buffer to dissect.
619 * @param pinfo Packet Info.
620 * @param tree The protocol tree.
621 * @return Number of bytes from the tvbuff_t which were processed, 0 (zero) if
622 * the packet was not recognized as a JXTA packet and negative if the
623 * dissector needs more bytes in order to process a PDU.
625 static int dissect_jxta_udp(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
631 conversation_t *conversation =
632 find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
634 if (conversation == NULL) {
636 * No conversation exists yet - create one.
639 conversation_new(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
642 DISSECTOR_ASSERT(find_dissector("jxta.udp"));
644 conversation_set_dissector(conversation, find_dissector("jxta.udp"));
647 tvbuff_t *jxta_message_framing_tvb;
649 guint64 content_length = -1;
650 gchar *content_type = NULL;
652 available = tvb_reported_length_remaining(tvb, offset);
653 if (available < sizeof(JXTA_UDP_SIG)) {
654 needed = (gint) (sizeof(JXTA_UDP_SIG) - available);
658 if (tvb_memeql(tvb, offset, JXTA_UDP_SIG, sizeof(JXTA_UDP_SIG)) != 0) {
663 offset += sizeof(JXTA_UDP_SIG);
665 jxta_message_framing_tvb = tvb_new_subset(tvb, offset, -1, -1);
666 processed = dissect_jxta_message_framing(jxta_message_framing_tvb, pinfo, NULL, &content_length, &content_type);
668 if ((0 == processed) || (NULL == content_type) || (content_length <= 0) || (content_length > UINT_MAX)) {
669 /** Buffer did not begin with valid framing headers */
680 available = tvb_reported_length_remaining(tvb, offset);
681 if (available < content_length) {
682 needed = (gint) (content_length - available);
686 offset += (guint) content_length;
691 if ((needed > 0) && gDESEGMENT && pinfo->can_desegment) {
692 /* g_message( "UDP requesting %d more bytes", needed ); */
693 pinfo->desegment_offset = 0;
694 pinfo->desegment_len = needed;
698 if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
699 col_set_str(pinfo->cinfo, COL_PROTOCOL, "JXTA");
703 guint tree_offset = 0;
704 proto_item *jxta_tree_item =
705 proto_tree_add_protocol_format(tree, proto_jxta, tvb, offset, -1, "JXTA" );
706 proto_tree *jxta_tree = proto_item_add_subtree(jxta_tree_item, ett_jxta);
707 proto_item *jxta_udp_tree_item =
708 proto_tree_add_none_format(jxta_tree, hf_jxta_udp, tvb, tree_offset, -1, "JXTA UDP Message");
709 proto_tree *jxta_udp_tree = proto_item_add_subtree(jxta_udp_tree_item, ett_jxta_udp);
710 tvbuff_t *jxta_message_framing_tvb;
711 guint64 content_length = -1;
712 gchar *content_type = NULL;
713 tvbuff_t *jxta_message_tvb;
715 proto_tree_add_item(jxta_udp_tree, hf_jxta_udpsig, tvb, tree_offset, sizeof(JXTA_UDP_SIG), FALSE);
716 tree_offset += sizeof(JXTA_UDP_SIG);
718 jxta_message_framing_tvb = tvb_new_subset(tvb, tree_offset, -1, -1);
720 tree_offset += dissect_jxta_message_framing(jxta_message_framing_tvb, pinfo, jxta_tree, &content_length, &content_type);
722 jxta_message_tvb = tvb_new_subset(tvb, tree_offset, (gint) content_length, (gint) content_length);
724 tree_offset += dissect_media(content_type, jxta_message_tvb, pinfo, tree);
726 proto_item_set_end(jxta_udp_tree_item, tvb, tree_offset);
728 DISSECTOR_ASSERT(offset == tree_offset);
735 * Dissect a tvbuff containing JXTA stream PDUs. This commonly includes
736 * connections over TCP sockets.
738 * <p/>The stream (in both directions) will consist of a JXTA Welcome Message
739 * followed by an indeterminate number of JXTA Message Framing Headers and
742 * @param tvb The buffer to dissect.
743 * @param pinfo Packet Info.
744 * @param tree The protocol tree.
745 * @return Number of bytes from the tvbuff_t which were processed, 0 (zero) if
746 * the packet was not recognized as a JXTA packet and negative if the
747 * dissector needs more bytes in order to process a PDU.
749 static int dissect_jxta_stream(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
752 guint available = tvb_reported_length_remaining(tvb, offset);
755 conversation_t *tpt_conversation = NULL;
756 jxta_stream_conversation_data *tpt_conv_data = NULL;
757 proto_item *jxta_tree_item = NULL;
758 proto_tree *jxta_tree = NULL;
760 /* g_message("Dissecting%s : %d", (NULL != tree) ? " for display" : "", pinfo->fd->num ); */
762 if (available < sizeof(JXTA_WELCOME_MSG_SIG)) {
763 needed = (gint) (sizeof(JXTA_WELCOME_MSG_SIG) - available);
767 if (0 == tvb_memeql(tvb, 0, JXTA_WELCOME_MSG_SIG, sizeof(JXTA_WELCOME_MSG_SIG))) {
768 /* The beginning of a JXTA stream connection */
769 address *welcome_addr;
770 gboolean initiator = FALSE;
772 tpt_conversation = get_tpt_conversation(pinfo, TRUE);
773 tpt_conv_data = (jxta_stream_conversation_data *) conversation_get_proto_data(tpt_conversation, proto_jxta);
775 if (0 == tpt_conv_data->initiator_welcome_frame) {
776 /* The initiator welcome frame */
777 tpt_conv_data->tpt_ptype = pinfo->ptype;
778 tpt_conv_data->initiator_welcome_frame = pinfo->fd->num;
779 SE_COPY_ADDRESS(&tpt_conv_data->initiator_tpt_address, &pinfo->src);
780 tpt_conv_data->initiator_tpt_port = pinfo->srcport;
782 welcome_addr = &tpt_conv_data->initiator_address;
785 if (tpt_conv_data->initiator_welcome_frame >= pinfo->fd->num) {
786 /* what we saw previously was the receiver welcome message */
787 tpt_conv_data->receiver_welcome_frame = tpt_conv_data->initiator_welcome_frame;
788 tpt_conv_data->receiver_tpt_address = tpt_conv_data->initiator_tpt_address;
789 tpt_conv_data->receiver_tpt_port = tpt_conv_data->initiator_tpt_port;
790 tpt_conv_data->receiver_address = tpt_conv_data->initiator_address;
791 tpt_conv_data->initiator_welcome_frame = pinfo->fd->num;
792 SE_COPY_ADDRESS(&tpt_conv_data->initiator_tpt_address, &pinfo->src);
793 tpt_conv_data->initiator_tpt_port = pinfo->srcport;
795 welcome_addr = &tpt_conv_data->initiator_address;
798 /* The receiver welcome frame */
799 tpt_conv_data->tpt_ptype = pinfo->ptype;
800 tpt_conv_data->receiver_welcome_frame = pinfo->fd->num;
801 SE_COPY_ADDRESS(&tpt_conv_data->receiver_tpt_address, &pinfo->src);
802 tpt_conv_data->receiver_tpt_port = pinfo->srcport;
804 welcome_addr = &tpt_conv_data->receiver_address;
809 processed = dissect_jxta_welcome(tvb, pinfo, NULL, welcome_addr, initiator);
811 if( processed < 0 ) {
816 /* redo, this time creating the display tree. */
817 jxta_tree_item = proto_tree_add_protocol_format(tree, proto_jxta, tvb, offset, -1, "JXTA" );
818 jxta_tree = proto_item_add_subtree(jxta_tree_item, ett_jxta);
820 processed = dissect_jxta_welcome(tvb, pinfo, jxta_tree, welcome_addr, initiator);
822 /* Somewhere in the middle of a JXTA stream connection */
823 gint64 content_length = -1L;
824 gchar *content_type = NULL;
825 gint headers_len = dissect_jxta_message_framing(tvb, pinfo, NULL, (guint64*) &content_length, &content_type);
827 if ((0 == headers_len) || (NULL == content_type) || (content_length <= 0) || (content_length > UINT_MAX)) {
828 /** Buffer did not begin with valid framing headers */
832 /* g_message("%d Tpt %s:%d -> %s:%d tvb len=%d\n\t%s %d", pinfo->fd->num,
833 address_to_str(&pinfo->src), pinfo->srcport,
834 address_to_str(&pinfo->dst), pinfo->destport,
835 tvb_reported_length_remaining(tvb, 0),
836 content_type ? content_type : "[unknown content type]", (gint) content_length); */
838 if (headers_len < 0) {
839 /* negative headers_len means we need more bytes */
840 needed = -headers_len;
844 available = tvb_reported_length_remaining(tvb, offset + headers_len);
845 if (available >= content_length) {
846 tvbuff_t *jxta_message_tvb = tvb_new_subset(tvb, offset + headers_len, (gint) content_length, (gint) content_length);
847 conversation_t *peer_conversation = NULL;
849 jxta_tree_item = proto_tree_add_protocol_format(tree, proto_jxta, tvb, offset, -1, "JXTA" );
850 jxta_tree = proto_item_add_subtree(jxta_tree_item, ett_jxta);
852 /* Redo header processing, this time populating the tree. */
853 headers_len = dissect_jxta_message_framing(tvb, pinfo, jxta_tree, &content_length, &content_type);
855 tpt_conversation = get_tpt_conversation(pinfo, TRUE);
857 if (NULL != tpt_conversation) {
858 tpt_conv_data = (jxta_stream_conversation_data *) conversation_get_proto_data(tpt_conversation, proto_jxta);
860 peer_conversation = get_peer_conversation(pinfo, tpt_conv_data, TRUE);
864 /* Use our source and destination addresses if we have them */
865 if (NULL != peer_conversation) {
866 /* g_message("%d Tpt %s:%d -> %s:%d", pinfo->fd->num,
867 address_to_str(&tpt_conv_data->initiator_tpt_address), tpt_conv_data->initiator_tpt_port,
868 address_to_str(&tpt_conv_data->receiver_tpt_address), tpt_conv_data->receiver_tpt_port); */
870 if (ADDRESSES_EQUAL(&pinfo->src, &tpt_conv_data->initiator_tpt_address)
871 && tpt_conv_data->initiator_tpt_port == pinfo->srcport) {
872 /* g_message("%d From initiator : %s -> %s ", pinfo->fd->num,
873 address_to_str(&tpt_conv_data->initiator_address),
874 address_to_str(&tpt_conv_data->receiver_address)); */
875 pinfo->src = tpt_conv_data->initiator_address;
877 pinfo->dst = tpt_conv_data->receiver_address;
879 pinfo->ptype = PT_NONE;
880 } else if (ADDRESSES_EQUAL(&pinfo->src, &tpt_conv_data->receiver_tpt_address) &&
881 tpt_conv_data->receiver_tpt_port == pinfo->srcport) {
882 /* g_message("%d From receiver : %s -> %s ", pinfo->fd->num,
883 address_to_str(&tpt_conv_data->receiver_address),
884 address_to_str(&tpt_conv_data->initiator_address)); */
885 pinfo->src = tpt_conv_data->receiver_address;
887 pinfo->dst = tpt_conv_data->initiator_address;
889 pinfo->ptype = PT_NONE;
891 /* g_message("%d Nothing matches %s:%d -> %s:%d", pinfo->fd->num,
892 address_to_str(&pinfo->src), pinfo->srcport,
893 address_to_str(&pinfo->dst), pinfo->destport); */
897 processed = headers_len;
899 processed += dissect_media(content_type, jxta_message_tvb, pinfo, tree);
901 /* we need more bytes before we can process message body. */
902 needed = (gint) ((guint) content_length - available);
910 if ((needed > 0) && gDESEGMENT && pinfo->can_desegment) {
911 /* g_message( "Stream requesting %d more bytes", needed ); */
912 pinfo->desegment_offset = offset;
913 pinfo->desegment_len = needed;
921 * Find or possibly create a transport conversation object for the connection
922 * which is associated with the packet info.
924 * @param pinfo The packet info from the underlying transport.
925 * @param create If TRUE then create a new conversation object if necessary.
927 static conversation_t *get_tpt_conversation(packet_info * pinfo, gboolean create)
929 conversation_t *tpt_conversation =
930 find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
931 jxta_stream_conversation_data *tpt_conv_data;
933 if (tpt_conversation == NULL) {
939 * No conversation exists yet - create one.
942 conversation_new(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
945 conversation_set_dissector(tpt_conversation, stream_jxta_handle);
947 tpt_conv_data = (jxta_stream_conversation_data *) conversation_get_proto_data(tpt_conversation, proto_jxta);
949 if (NULL == tpt_conv_data) {
950 tpt_conv_data = se_alloc(sizeof(jxta_stream_conversation_data));
951 tpt_conv_data->tpt_ptype = pinfo->ptype;
953 SE_COPY_ADDRESS(&tpt_conv_data->initiator_tpt_address, &pinfo->src);
954 tpt_conv_data->initiator_tpt_port = pinfo->srcport;
955 tpt_conv_data->initiator_welcome_frame = 0;
956 tpt_conv_data->initiator_address.type = AT_NONE;
957 tpt_conv_data->initiator_address.len = 0;
958 tpt_conv_data->initiator_address.data = NULL;
960 SE_COPY_ADDRESS(&tpt_conv_data->receiver_tpt_address, &pinfo->dst);
961 tpt_conv_data->receiver_tpt_port = pinfo->destport;
962 tpt_conv_data->receiver_welcome_frame = 0;
963 tpt_conv_data->receiver_address.type = AT_NONE;
964 tpt_conv_data->receiver_address.len = 0;
965 tpt_conv_data->receiver_address.data = NULL;
967 conversation_add_proto_data(tpt_conversation, proto_jxta, tpt_conv_data);
970 return tpt_conversation;
974 * Find or possibly create a peer conversation object for the connection
975 * which is associated with the packet info.
977 * @param tpt_conv_data The transport conversation from which we will locate the peer conversation.
978 * @param create If TRUE then create a new conversation object if necessary.
980 static conversation_t *get_peer_conversation(packet_info * pinfo, jxta_stream_conversation_data* tpt_conv_data, gboolean create)
982 conversation_t * peer_conversation = NULL;
984 if ((AT_NONE != tpt_conv_data->initiator_address.type) && (AT_NONE != tpt_conv_data->receiver_address.type)) {
985 peer_conversation = find_conversation(pinfo->fd->num, &tpt_conv_data->initiator_address, &tpt_conv_data->receiver_address,
986 PT_NONE, 0, 0, NO_PORT_B);
988 if (create && (NULL == peer_conversation)) {
989 peer_conversation = conversation_new(pinfo->fd->num, &tpt_conv_data->initiator_address,
990 &tpt_conv_data->receiver_address, PT_NONE, 0, 0, NO_PORT_B);
991 conversation_set_dissector(peer_conversation, stream_jxta_handle);
995 g_warning("Uninitialized peer conversation");
998 return peer_conversation;
1002 * Dissect a tvbuff containing a JXTA Welcome Message
1004 * @param tvb The buffer to dissect.
1005 * @param pinfo Packet Info.
1006 * @param tree The protocol tree.
1007 * @param found_addr The address found in the welcome message.
1008 * @param initiator If TRUE then we believe this welcome message to be the initiator's.
1009 * @return Number of bytes from the tvbuff_t which were processed, 0 (zero) if
1010 * the packet was not recognized as a JXTA packet and negative if the
1011 * dissector needs more bytes in order to process a PDU.
1013 static int dissect_jxta_welcome(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, address * found_addr, gboolean initiator)
1018 guint available = tvb_reported_length_remaining(tvb, offset);
1019 gchar **tokens = NULL;
1021 if (available < sizeof(JXTA_WELCOME_MSG_SIG)) {
1022 return (gint) (available - sizeof(JXTA_WELCOME_MSG_SIG));
1025 if (0 != tvb_memeql(tvb, 0, JXTA_WELCOME_MSG_SIG, sizeof(JXTA_WELCOME_MSG_SIG))) {
1030 first_linelen = tvb_find_line_end(tvb, offset, -1, &afterwelcome, gDESEGMENT && pinfo->can_desegment);
1032 if (-1 == first_linelen) {
1033 if (available > 4096) {
1034 /* it's too far too be reasonable */
1037 /* ask for more bytes */
1042 /* Dissect the Welcome Message */
1044 if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
1045 col_set_str(pinfo->cinfo, COL_PROTOCOL, "JXTA");
1048 if (check_col(pinfo->cinfo, COL_INFO)) {
1049 col_set_str(pinfo->cinfo, COL_INFO, "Welcome");
1053 gchar *welcomeline = tvb_get_ephemeral_string(tvb, offset, first_linelen);
1054 gchar **current_token;
1055 guint token_offset = offset;
1056 proto_item *jxta_welcome_tree_item = NULL;
1057 proto_tree *jxta_welcome_tree = NULL;
1059 tokens = g_strsplit(welcomeline, " ", 255);
1060 current_token = tokens;
1063 jxta_welcome_tree_item =
1064 proto_tree_add_none_format(tree, hf_jxta_welcome, tvb, offset, afterwelcome,
1065 "JXTA Connection Welcome Message, %s", welcomeline);
1066 jxta_welcome_tree = proto_item_add_subtree(jxta_welcome_tree_item, ett_jxta_welcome);
1069 if (jxta_welcome_tree) {
1070 proto_item *jxta_welcome_initiator_item =
1071 proto_tree_add_boolean(jxta_welcome_tree, hf_jxta_welcome_initiator, tvb, 0, 0, initiator);
1072 PROTO_ITEM_SET_GENERATED(jxta_welcome_initiator_item);
1075 if (NULL != *current_token) {
1076 if (jxta_welcome_tree) {
1077 proto_tree_add_item(jxta_welcome_tree, hf_jxta_welcome_sig, tvb, token_offset, strlen(*current_token), FALSE);
1080 token_offset += strlen(*current_token) + 1;
1083 /* invalid welcome message */
1088 if (NULL != *current_token) {
1089 if (jxta_welcome_tree) {
1090 proto_tree_add_item(jxta_welcome_tree, hf_jxta_welcome_destAddr, tvb, token_offset, strlen(*current_token),
1094 token_offset += strlen(*current_token) + 1;
1097 /* invalid welcome message */
1102 if (NULL != *current_token) {
1103 if (jxta_welcome_tree) {
1104 proto_tree_add_item(jxta_welcome_tree, hf_jxta_welcome_pubAddr, tvb, token_offset, strlen(*current_token), FALSE);
1107 token_offset += strlen(*current_token) + 1;
1110 /* invalid welcome message */
1115 if (NULL != *current_token) {
1116 if (jxta_welcome_tree) {
1117 proto_tree_add_item(jxta_welcome_tree, hf_jxta_welcome_peerid, tvb, token_offset, strlen(*current_token), FALSE);
1120 if (check_col(pinfo->cinfo, COL_INFO)) {
1121 col_append_str(pinfo->cinfo, COL_INFO, (initiator ? " -> " : " <- ") );
1122 col_append_str(pinfo->cinfo, COL_INFO, *current_token);
1125 if (NULL != found_addr) {
1126 found_addr->type = AT_URI;
1127 found_addr->len = strlen(*current_token);
1128 found_addr->data = se_strdup(*current_token);
1131 token_offset += strlen(*current_token) + 1;
1134 /* invalid welcome message */
1139 if (NULL != *current_token) {
1140 int variable_tokens = 0;
1141 gchar **variable_token = current_token;
1143 while(NULL != *variable_token) {
1148 if( variable_tokens < 1 ) {
1149 /* invalid welcome message */
1154 if( (2 == variable_tokens) && (0 == strcmp(JXTA_WELCOME_MSG_VERSION_1_1, current_token[variable_tokens -1])) ) {
1155 if (jxta_welcome_tree) {
1156 proto_tree_add_item(jxta_welcome_tree, hf_jxta_welcome_noProp, tvb, token_offset, strlen(*current_token), FALSE);
1159 token_offset += strlen(*current_token) + 1;
1162 if (jxta_welcome_tree) {
1163 proto_tree_add_item(jxta_welcome_tree, hf_jxta_welcome_version, tvb, token_offset, strlen(*current_token), FALSE);
1165 } else if( (3 == variable_tokens) && (0 == strcmp(JXTA_WELCOME_MSG_VERSION_3_0, current_token[variable_tokens -1])) ) {
1166 if (jxta_welcome_tree) {
1167 proto_tree_add_item(jxta_welcome_tree, hf_jxta_welcome_noProp, tvb, token_offset, strlen(*current_token), FALSE);
1170 token_offset += strlen(*current_token) + 1;
1173 if (jxta_welcome_tree) {
1174 proto_tree_add_item(jxta_welcome_tree, hf_jxta_welcome_msgVers, tvb, token_offset, strlen(*current_token), FALSE);
1177 token_offset += strlen(*current_token) + 1;
1180 if (jxta_welcome_tree) {
1181 proto_tree_add_item(jxta_welcome_tree, hf_jxta_welcome_version, tvb, token_offset, strlen(*current_token), FALSE);
1184 /* Unrecognized Welcome Version */
1185 int each_variable_token;
1187 for( each_variable_token = 0; each_variable_token < variable_tokens; each_variable_token++ ) {
1188 if (jxta_welcome_tree) {
1189 jxta_welcome_tree_item = proto_tree_add_item(jxta_welcome_tree,
1190 (each_variable_token < (variable_tokens -1) ? hf_jxta_welcome_variable : hf_jxta_welcome_version),
1191 tvb, token_offset, strlen(*current_token), FALSE);
1193 proto_item_append_text(jxta_welcome_tree_item, " (UNRECOGNIZED)");
1196 token_offset += strlen(*current_token) + 1;
1201 /* invalid welcome message */
1210 col_set_writable(pinfo->cinfo, FALSE);
1212 return afterwelcome;
1216 * Dissect a tvbuff containing JXTA Message framing.
1218 * @param tvb The buffer to dissect.
1219 * @param pinfo Packet Info.
1220 * @param tree The protocol tree.
1221 * @param content_length Pointer to a buffer for storing the value of the
1222 * "content-length" header or NULL.
1223 * @param content_type Pointer-to-a-pointer for a new buffer for storing the
1224 * value of the "content_type-length" header or NULL.
1225 * @return Number of bytes from the tvbuff_t which were processed, 0 (zero) if
1226 * the packet was not recognized as a JXTA packet and negative if the
1227 * dissector needs more bytes in order to process a PDU.
1229 static int dissect_jxta_message_framing(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, guint64 * content_length,
1230 gchar ** content_type)
1237 * First go around. Make sure all of the bytes are there.
1240 guint8 headername_len;
1241 guint8 headername_offset;
1242 guint16 headervalue_len;
1243 guint16 headervalue_offset;
1245 available = tvb_reported_length_remaining(tvb, offset);
1246 if (available < sizeof(guint8)) {
1247 needed = (gint) (sizeof(guint8) - available);
1250 headername_len = tvb_get_guint8(tvb, offset);
1251 offset += sizeof(guint8);
1252 headername_offset = offset;
1254 available = tvb_reported_length_remaining(tvb, offset);
1255 if (available < headername_len) {
1256 needed = (gint) (headername_len - available);
1260 if (0 == headername_len) {
1263 offset += headername_len;
1266 available = tvb_reported_length_remaining(tvb, offset);
1267 if (available < sizeof(guint16)) {
1268 needed = (gint) (sizeof(guint16) - available);
1271 headervalue_len = tvb_get_ntohs(tvb, offset);
1272 offset += sizeof(guint16);
1273 headervalue_offset = offset;
1275 available = tvb_reported_length_remaining(tvb, offset);
1276 if (available < headervalue_len) {
1277 needed = (gint) (headervalue_len - available);
1281 offset += headervalue_len;
1284 if (content_type && (sizeof("content-type") - 1) == headername_len) {
1285 if (0 == tvb_strncaseeql(tvb, headername_offset, "content-type", sizeof("content-type") - 1)) {
1286 *content_type = tvb_get_ephemeral_string(tvb, headervalue_offset, headervalue_len);
1291 if (content_length && (sizeof(guint64) == headervalue_len) && ((sizeof("content-length") - 1) == headername_len)) {
1292 if (0 == tvb_strncaseeql(tvb, headername_offset, "content-length", sizeof("content-length") - 1)) {
1293 *content_length = tvb_get_ntoh64(tvb, headervalue_offset);
1298 if ((needed > 0) && gDESEGMENT && pinfo->can_desegment) {
1299 /* g_message( "Framing requesting %d more bytes", needed ); */
1300 pinfo->desegment_offset = 0;
1301 pinfo->desegment_len = needed;
1306 * Second (optional pass) Now that we are sure that all the bytes are there we update the protocol tree.
1309 guint tree_offset = 0;
1310 proto_item *framing_tree_item =
1311 proto_tree_add_none_format(tree, hf_jxta_framing, tvb, tree_offset, -1, "JXTA Message Framing Headers");
1312 proto_tree *framing_tree = proto_item_add_subtree(framing_tree_item, ett_jxta_framing);
1314 /* parse framing headers */
1316 guint8 headernamelen = tvb_get_guint8(tvb, tree_offset);
1317 proto_item *framing_header_tree_item =
1318 proto_tree_add_item(framing_tree, hf_jxta_framing_header, tvb, tree_offset, -1, FALSE);
1319 proto_tree *framing_header_tree = proto_item_add_subtree(framing_header_tree_item, ett_jxta_framing_header);
1322 * Put header name into the protocol tree
1324 proto_tree_add_item(framing_header_tree, hf_jxta_framing_header_name, tvb, tree_offset, 1, headernamelen);
1327 * Append header name into the header protocol item. It's a nice hint so you don't have to reveal all headers.
1329 if (headernamelen > 0) {
1330 proto_item_append_text(framing_header_tree_item, " \"%s\"",
1331 tvb_format_text(tvb, tree_offset + sizeof(guint8), headernamelen));
1334 tree_offset += sizeof(guint8) + headernamelen;
1336 if (headernamelen > 0) {
1337 guint16 headervaluelen = tvb_get_ntohs(tvb, tree_offset);
1340 proto_tree_add_uint(framing_header_tree, hf_jxta_framing_header_value_length, tvb, tree_offset,
1341 sizeof(guint16), headervaluelen);
1343 /** TODO bondolo Add specific handling for known header types */
1346 * Put header value into protocol tree.
1348 proto_tree_add_item(framing_header_tree, hf_jxta_framing_header_value, tvb, tree_offset + sizeof(guint16),
1349 headervaluelen, FALSE);
1352 tree_offset += sizeof(guint16) + headervaluelen;
1355 proto_item_set_end(framing_header_tree_item, tvb, tree_offset);
1357 if (0 == headernamelen) {
1362 proto_item_set_end(framing_tree_item, tvb, tree_offset);
1364 DISSECTOR_ASSERT(offset == tree_offset);
1367 /* return how many bytes we used up. */
1372 * Dissect a tvbuff containing one or more JXTA Messages.
1374 * @param tvb The buffer to dissect.
1375 * @param pinfo Packet Info.
1376 * @param tree The protocol tree.
1377 * @return Number of bytes from the tvbuff_t which were processed, 0 (zero) if
1378 * the packet was not recognized as a JXTA packet and negative if the
1379 * dissector needs more bytes in order to process a PDU.
1381 static int dissect_jxta_message(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
1383 gint complete_messages = 0;
1385 guint tree_offset = 0;
1392 guint8 message_version;
1393 guint message_start_offset = offset;
1395 /* First pass. Make sure all of the bytes we need are available */
1396 available = tvb_reported_length_remaining(tvb, offset);
1398 if((0 == available) && (0 != complete_messages)) {
1399 /* We have discovered all of the complete messages in the tvbuff. */
1403 if (available < sizeof(JXTA_MSG_SIG)) {
1404 needed = (gint) (sizeof(JXTA_MSG_SIG) - available);
1408 if (tvb_memeql(tvb, offset, JXTA_MSG_SIG, sizeof(JXTA_MSG_SIG)) != 0) {
1409 /* It is not one of ours */
1413 offset += sizeof(JXTA_MSG_SIG);
1415 available = tvb_reported_length_remaining(tvb, offset);
1416 if (available < sizeof(guint8)) {
1417 needed = (gint) (sizeof(guint8) - available);
1420 message_version = tvb_get_guint8(tvb, offset);
1422 offset += sizeof(guint8);
1424 if ((JXTA_MSG_VERSION_1 != message_version) && (JXTA_MSG_VERSION_2 != message_version)) {
1425 /* Sort of a lie, we say that we don't recognize it at all. */
1430 /* Read the flags (Version 2 and later) */
1431 if(message_version > 0) {
1432 available = tvb_reported_length_remaining(tvb, offset);
1433 if (available < sizeof(guint8)) {
1434 needed = (gint) (sizeof(guint8) - available);
1437 offset += sizeof(guint8);
1441 /* Read names table */
1442 available = tvb_reported_length_remaining(tvb, offset);
1443 if (available < sizeof(guint16)) {
1444 needed = (gint) (sizeof(guint16) - available);
1447 guint16 msg_names_count = tvb_get_ntohs(tvb, offset);
1450 offset += sizeof(guint16);
1452 for (each_name = 0; each_name < msg_names_count; each_name++) {
1455 available = tvb_reported_length_remaining(tvb, offset);
1456 if (available < sizeof(name_len)) {
1457 needed = (gint) (sizeof(name_len) - available);
1461 name_len = tvb_get_ntohs(tvb, offset);
1463 available = tvb_reported_length_remaining(tvb, offset + sizeof(name_len));
1464 if (available < name_len) {
1465 needed = (gint) (name_len - available);
1469 offset += sizeof(name_len) + name_len;
1473 /* parse element count */
1474 available = tvb_reported_length_remaining(tvb, offset);
1475 if (available < sizeof(guint16)) {
1476 needed = (gint) (sizeof(guint16) - available);
1479 guint16 elem_count = tvb_get_ntohs(tvb, offset);
1482 offset += sizeof(guint16);
1484 /* parse elements */
1485 for (each_elem = 0; each_elem < elem_count; each_elem++) {
1486 tvbuff_t *jxta_message_element_tvb = tvb_new_subset(tvb, offset, -1, -1);
1489 if(JXTA_MSG_VERSION_1 == message_version) {
1490 processed = dissect_jxta_message_element_1(jxta_message_element_tvb, pinfo, NULL, 0, NULL);
1491 } else if(JXTA_MSG_VERSION_2 == message_version) {
1492 processed = dissect_jxta_message_element_2(jxta_message_element_tvb, pinfo, NULL, 0, NULL);
1494 /* Sort of a lie, we say that we don't recognize it at all. */
1498 if (processed < 0) {
1499 needed = -processed;
1503 if (0 == processed) {
1504 /* XXX bondolo Not really clear what we should do! */
1505 g_warning( "Failure processing message element #%d of %d of frame %d", each_elem, elem_count, pinfo->fd->num );
1509 offset += processed;
1513 if ((AT_URI == pinfo->src.type) && (AT_URI == pinfo->dst.type)) {
1514 jxta_tap_header *tap_header = se_alloc(sizeof(jxta_tap_header));
1516 tap_header->src_address = pinfo->src;
1517 tap_header->dest_address = pinfo->dst;
1518 tap_header->size = offset - message_start_offset ;
1520 tap_queue_packet(jxta_tap, pinfo, tap_header);
1523 complete_messages++;
1525 /* g_message( "%d Scanned message #%d: ", pinfo->fd->num, complete_messages ); */
1528 if ((needed > 0) && gDESEGMENT && pinfo->can_desegment) {
1529 /* g_message( "Message requesting %d more bytes", needed ); */
1530 pinfo->desegment_offset = 0;
1531 pinfo->desegment_len = needed;
1535 src_addr = address_to_str(&pinfo->src);
1536 dst_addr = address_to_str(&pinfo->dst);
1538 /* append the port if appropriate */
1539 if (PT_NONE != pinfo->ptype) {
1540 size_t len = strlen(src_addr);
1541 src_addr[len] = ':';
1542 g_snprintf(&src_addr[len + 1], MAX_ADDR_STR_LEN - len - 1, "%d", pinfo->srcport);
1544 len = strlen(dst_addr);
1545 dst_addr[len] = ':';
1546 g_snprintf(&dst_addr[len + 1], MAX_ADDR_STR_LEN - len - 1, "%d", pinfo->destport);
1549 if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
1550 col_set_str(pinfo->cinfo, COL_PROTOCOL, "JXTA");
1553 if (check_col(pinfo->cinfo, COL_INFO)) {
1554 if( complete_messages > 1 ) {
1555 col_add_fstr(pinfo->cinfo, COL_INFO, "%d Messages, %s -> %s", complete_messages, src_addr, dst_addr);
1557 col_add_fstr(pinfo->cinfo, COL_INFO, "Message, %s -> %s", src_addr, dst_addr);
1560 col_set_writable(pinfo->cinfo, FALSE);
1563 while( tree && (complete_messages > 0) ) {
1564 proto_item *jxta_msg_tree_item = NULL;
1565 proto_tree *jxta_msg_tree = NULL;
1566 guint8 message_version;
1567 const gchar **names_table = NULL;
1568 guint16 msg_names_count;
1572 proto_item *tree_item;
1574 jxta_msg_tree_item = proto_tree_add_protocol_format(tree, proto_message_jxta, tvb, tree_offset, -1,
1575 "JXTA Message, %s -> %s", src_addr, dst_addr);
1577 jxta_msg_tree = proto_item_add_subtree(jxta_msg_tree_item, ett_jxta_msg);
1579 proto_tree_add_item(jxta_msg_tree, hf_jxta_message_sig, tvb, tree_offset, sizeof(JXTA_MSG_SIG), FALSE);
1580 tree_offset += sizeof(JXTA_MSG_SIG);
1582 tree_item = proto_tree_add_string(jxta_msg_tree, hf_jxta_message_src, tvb, 0, 0, src_addr);
1583 PROTO_ITEM_SET_GENERATED(tree_item);
1585 tree_item = proto_tree_add_string(jxta_msg_tree, hf_jxta_message_address, tvb, 0, 0, src_addr);
1586 PROTO_ITEM_SET_HIDDEN(tree_item);
1587 PROTO_ITEM_SET_GENERATED(tree_item);
1589 if(AT_URI == pinfo->src.type) {
1590 tree_item = proto_tree_add_string(jxta_msg_tree, hf_uri_src, tvb, 0, 0, src_addr);
1591 PROTO_ITEM_SET_HIDDEN(tree_item);
1592 PROTO_ITEM_SET_GENERATED(tree_item);
1593 tree_item = proto_tree_add_string(jxta_msg_tree, hf_uri_addr, tvb, 0, 0, src_addr);
1594 PROTO_ITEM_SET_HIDDEN(tree_item);
1595 PROTO_ITEM_SET_GENERATED(tree_item);
1598 tree_item = proto_tree_add_string(jxta_msg_tree, hf_jxta_message_dst, tvb, 0, 0, dst_addr);
1599 PROTO_ITEM_SET_GENERATED(tree_item);
1601 tree_item = proto_tree_add_string(jxta_msg_tree, hf_jxta_message_address, tvb, 0, 0, dst_addr);
1602 PROTO_ITEM_SET_HIDDEN(tree_item);
1603 PROTO_ITEM_SET_GENERATED(tree_item);
1605 if(AT_URI == pinfo->dst.type) {
1606 tree_item = proto_tree_add_string(jxta_msg_tree, hf_uri_dst, tvb, 0, 0, src_addr);
1607 PROTO_ITEM_SET_HIDDEN(tree_item);
1608 PROTO_ITEM_SET_GENERATED(tree_item);
1609 tree_item = proto_tree_add_string(jxta_msg_tree, hf_uri_addr, tvb, 0, 0, dst_addr);
1610 PROTO_ITEM_SET_HIDDEN(tree_item);
1611 PROTO_ITEM_SET_GENERATED(tree_item);
1614 message_version = tvb_get_guint8(tvb, tree_offset);
1615 proto_tree_add_uint(jxta_msg_tree, hf_jxta_message_version, tvb, tree_offset, sizeof(guint8), message_version);
1616 tree_offset += sizeof(guint8);
1618 if( message_version > 0 ) {
1619 guint8 flags = tvb_get_guint8(tvb, tree_offset);
1620 proto_item *flags_ti = proto_tree_add_uint(jxta_msg_tree, hf_jxta_message_flags, tvb, tree_offset, sizeof(guint8), flags);
1621 proto_tree *jxta_msg_flags_tree = proto_item_add_subtree(flags_ti, ett_jxta_msg_flags);
1622 proto_tree_add_boolean(jxta_msg_flags_tree, hf_jxta_message_flag_utf16be, tvb, tree_offset, 1, flags);
1623 proto_tree_add_boolean(jxta_msg_flags_tree, hf_jxta_message_flag_ucs32be, tvb, tree_offset, 1, flags);
1624 tree_offset += sizeof(guint8);
1627 msg_names_count = tvb_get_ntohs(tvb, tree_offset);
1628 proto_tree_add_uint(jxta_msg_tree, hf_jxta_message_names_count, tvb, tree_offset, sizeof(guint16), msg_names_count);
1629 tree_offset += sizeof(guint16);
1631 names_table = ep_alloc((msg_names_count + 2) * sizeof(const gchar *));
1632 names_table[0] = "";
1633 names_table[1] = "jxta";
1636 for (each_name = 0; each_name < msg_names_count; each_name++) {
1637 guint16 name_len = tvb_get_ntohs(tvb, tree_offset);
1639 names_table[2 + each_name] = tvb_get_ephemeral_string(tvb, tree_offset + sizeof(name_len), name_len);
1640 proto_tree_add_item(jxta_msg_tree, hf_jxta_message_names_name, tvb, tree_offset, sizeof(name_len), FALSE);
1641 tree_offset += sizeof(name_len) + name_len;
1644 /* parse element count */
1645 elem_count = tvb_get_ntohs(tvb, tree_offset);
1646 proto_tree_add_item(jxta_msg_tree, hf_jxta_message_element_count, tvb, tree_offset, sizeof(guint16), FALSE);
1647 tree_offset += sizeof(guint16);
1649 /* FIXME bondolo Element count 0 (Process elements until FIN) should be supported. */
1651 /* parse elements */
1652 for (each_elem = 0; each_elem < elem_count; each_elem++) {
1653 tvbuff_t *jxta_message_element_tvb = tvb_new_subset(tvb, tree_offset, -1, -1);
1655 if(JXTA_MSG_VERSION_1 == message_version) {
1657 dissect_jxta_message_element_1(jxta_message_element_tvb, pinfo, jxta_msg_tree, msg_names_count + 2, names_table);
1658 } else if(JXTA_MSG_VERSION_2 == message_version) {
1660 dissect_jxta_message_element_2(jxta_message_element_tvb, pinfo, jxta_msg_tree, msg_names_count + 2, names_table);
1662 /* Sort of a lie, we say that we don't recognize it at all. */
1667 proto_item_set_end(jxta_msg_tree_item, tvb, tree_offset);
1669 complete_messages--;
1673 /* g_message( "%d tvb offset : %d tree offset : %d", pinfo->fd->num, offset, tree_offset ); */
1674 DISSECTOR_ASSERT(tree_offset == offset);
1681 * Dissect a tvbuff containing a JXTA Message Element (Version 1).
1683 * @param tvb The buffer to dissect.
1684 * @param pinfo Packet Info.
1685 * @param tree The protocol tree.
1686 * @return Number of bytes from the tvbuff_t which were processed, 0 (zero) if
1687 * the packet was not recognized as a JXTA packet and negative if the
1688 * dissector needs more bytes in order to process a PDU.
1690 static int dissect_jxta_message_element_1(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, guint ns_count,
1691 const gchar ** names_table)
1698 /* First pass. Make sure all of the bytes we need are available */
1701 /* signature field */
1702 available = tvb_reported_length_remaining(tvb, offset);
1703 if (available < sizeof(JXTA_MSGELEM_SIG)) {
1704 needed = (gint) (sizeof(JXTA_MSGELEM_SIG) - available);
1707 if (tvb_memeql(tvb, offset, JXTA_MSGELEM_SIG, sizeof(JXTA_MSGELEM_SIG)) != 0) {
1708 /* It is not one of ours */
1712 offset += sizeof(JXTA_MSGELEM_SIG);
1714 /* namespace id field */
1715 available = tvb_reported_length_remaining(tvb, offset);
1716 if (available < sizeof(guint8)) {
1717 needed = (gint) (sizeof(guint8) - available);
1721 offset += sizeof(guint8);
1724 available = tvb_reported_length_remaining(tvb, offset);
1725 if (available < sizeof(guint8)) {
1726 needed = (gint) (sizeof(guint8) - available);
1729 flags = tvb_get_guint8(tvb, offset);
1730 offset += sizeof(guint8);
1734 available = tvb_reported_length_remaining(tvb, offset);
1735 if (available < sizeof(guint16)) {
1736 needed = (gint) (sizeof(guint16) - available);
1739 guint16 name_len = tvb_get_ntohs(tvb, offset);
1740 offset += sizeof(guint16);
1742 available = tvb_reported_length_remaining(tvb, offset);
1743 if (available < name_len) {
1744 needed = (gint) (name_len - available);
1752 if ((flags & JXTAMSG1_ELMFLAG_TYPE) != 0) {
1755 available = tvb_reported_length_remaining(tvb, offset);
1756 if (available < sizeof(guint16)) {
1757 needed = (gint) (sizeof(guint16) - available);
1761 type_len = tvb_get_ntohs(tvb, offset);
1762 offset += sizeof(guint16);
1764 available = tvb_reported_length_remaining(tvb, offset);
1765 if (available < type_len) {
1766 needed = (gint) (type_len - available);
1773 /* encoding field */
1774 if ((flags & JXTAMSG1_ELMFLAG_ENCODING) != 0) {
1775 guint16 encoding_len;
1777 available = tvb_reported_length_remaining(tvb, offset);
1778 if (available < sizeof(guint16)) {
1779 needed = (gint) (sizeof(guint16) - available);
1783 encoding_len = tvb_get_ntohs(tvb, offset);
1784 offset += sizeof(guint16);
1786 available = tvb_reported_length_remaining(tvb, offset);
1787 if (available < encoding_len) {
1788 needed = (gint) (encoding_len - available);
1792 offset += encoding_len;
1796 available = tvb_reported_length_remaining(tvb, offset);
1797 if (available < sizeof(guint16)) {
1798 needed = (gint) (sizeof(guint16) - available);
1801 guint32 content_len = tvb_get_ntohl(tvb, offset);
1802 offset += sizeof(guint32);
1804 available = tvb_reported_length_remaining(tvb, offset);
1805 if (available < content_len) {
1806 needed = (gint) (content_len - available);
1810 offset += content_len;
1813 /* signature element field */
1814 if ((flags & JXTAMSG1_ELMFLAG_SIGNATURE) != 0) {
1815 tvbuff_t *jxta_signature_element_tvb;
1818 jxta_signature_element_tvb = tvb_new_subset(tvb, offset, -1, -1);
1820 processed = dissect_jxta_message_element_1(jxta_signature_element_tvb, pinfo, NULL, 0, NULL);
1822 if (processed == 0) {
1826 if (processed < 0) {
1827 needed = -processed;
1831 offset += processed;
1837 if ((needed > 0) && gDESEGMENT && pinfo->can_desegment) {
1838 /* g_message( "Element1 requesting %d more bytes", needed ); */
1839 pinfo->desegment_offset = 0;
1840 pinfo->desegment_len = needed;
1844 /* Second (optional) pass : build the proto tree */
1846 guint tree_offset = 0;
1847 proto_item *jxta_elem_tree_item = proto_tree_add_item(tree, hf_jxta_element, tvb, tree_offset, -1, FALSE);
1848 proto_tree *jxta_elem_tree = proto_item_add_subtree(jxta_elem_tree_item, ett_jxta_elem);
1850 proto_item *namespace_ti;
1852 proto_item *flags_ti;
1853 proto_tree *jxta_elem_flags_tree = NULL;
1854 guint32 content_len;
1855 gchar *mediatype = NULL;
1856 tvbuff_t *element_content_tvb;
1857 proto_item * jxta_elem_length_item = NULL;
1859 proto_tree_add_item(jxta_elem_tree, hf_jxta_element_sig, tvb, tree_offset, sizeof(JXTA_MSGELEM_SIG), FALSE);
1860 tree_offset += sizeof(JXTA_MSGELEM_SIG);
1862 namespaceID = tvb_get_guint8(tvb, tree_offset);
1864 proto_tree_add_uint(jxta_elem_tree, hf_jxta_element1_namespaceid, tvb, tree_offset, sizeof(guint8), namespaceID);
1865 if (namespaceID < ns_count) {
1866 proto_item_append_text(namespace_ti, " (%s)", names_table[namespaceID]);
1868 proto_item_append_text(namespace_ti, " * BAD *");
1870 tree_offset += sizeof(guint8);
1872 flags = tvb_get_guint8(tvb, tree_offset);
1873 flags_ti = proto_tree_add_uint(jxta_elem_tree, hf_jxta_element_flags, tvb, tree_offset, sizeof(guint8), flags);
1874 jxta_elem_flags_tree = proto_item_add_subtree(flags_ti, ett_jxta_elem_1_flags);
1875 proto_tree_add_boolean(jxta_elem_flags_tree, hf_jxta_element1_flag_hasType, tvb, tree_offset, 1, flags);
1876 proto_tree_add_boolean(jxta_elem_flags_tree, hf_jxta_element1_flag_hasEncoding, tvb, tree_offset, 1, flags);
1877 proto_tree_add_boolean(jxta_elem_flags_tree, hf_jxta_element1_flag_hasSignature, tvb, tree_offset, 1, flags);
1878 tree_offset += sizeof(guint8);
1880 name_len = tvb_get_ntohs(tvb, tree_offset);
1881 proto_item_append_text(jxta_elem_tree_item, " \"%s\"", tvb_format_text(tvb, tree_offset + sizeof(guint16), name_len));
1882 proto_tree_add_item(jxta_elem_tree, hf_jxta_element_name, tvb, tree_offset, sizeof(guint16), FALSE);
1883 tree_offset += sizeof(guint16) + name_len;
1886 if ((flags & JXTAMSG1_ELMFLAG_TYPE) != 0) {
1887 guint16 type_len = tvb_get_ntohs(tvb, tree_offset);
1888 proto_tree_add_item(jxta_elem_tree, hf_jxta_element_type, tvb, tree_offset, sizeof(guint16), FALSE);
1889 tree_offset += sizeof(guint16);
1891 mediatype = tvb_get_ephemeral_string(tvb, tree_offset, type_len);
1893 tree_offset += type_len;
1896 /* process encoding */
1897 if ((flags & JXTAMSG1_ELMFLAG_ENCODING) != 0) {
1898 guint16 encoding_len = tvb_get_ntohs(tvb, tree_offset);
1899 proto_tree_add_item(jxta_elem_tree, hf_jxta_element_encoding, tvb, tree_offset, sizeof(guint16), FALSE);
1900 tree_offset += sizeof(guint16) + encoding_len;
1904 content_len = tvb_get_ntohl(tvb, tree_offset);
1905 jxta_elem_length_item = proto_tree_add_item(jxta_elem_tree, hf_jxta_element_content_len, tvb, tree_offset, sizeof(guint32), FALSE);
1906 tree_offset += sizeof(guint32);
1908 element_content_tvb = tvb_new_subset(tvb, tree_offset, content_len, content_len);
1910 tree_offset += dissect_media(mediatype, element_content_tvb, pinfo, jxta_elem_tree);
1912 /* process the signature element */
1913 if ((flags & JXTAMSG1_ELMFLAG_SIGNATURE) != 0) {
1914 tvbuff_t *jxta_message_element_tvb = tvb_new_subset(tvb, tree_offset, -1, -1);
1916 tree_offset += dissect_jxta_message_element_1(jxta_message_element_tvb, pinfo, jxta_elem_tree, ns_count, names_table);
1919 proto_item_set_end(jxta_elem_tree_item, tvb, tree_offset);
1921 DISSECTOR_ASSERT(tree_offset == offset);
1928 * Dissect a tvbuff containing a JXTA Message Element (Version 2).
1930 * @param tvb The buffer to dissect.
1931 * @param pinfo Packet Info.
1932 * @param tree The protocol tree.
1933 * @param names_count The number of elements in the names table.
1934 * @param names The table of names.
1935 * @return Number of bytes from the tvbuff_t which were processed, 0 (zero) if
1936 * the packet was not recognized as a JXTA packet and negative if the
1937 * dissector needs more bytes in order to process a PDU.
1939 static int dissect_jxta_message_element_2(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, guint names_count,
1940 const gchar ** names_table)
1947 /* First pass. Make sure all of the bytes we need are available */
1950 /* signature field */
1951 available = tvb_reported_length_remaining(tvb, offset);
1952 if (available < sizeof(JXTA_MSGELEM_SIG)) {
1953 needed = (gint) (sizeof(JXTA_MSGELEM_SIG) - available);
1956 if (tvb_memeql(tvb, offset, JXTA_MSGELEM_SIG, sizeof(JXTA_MSGELEM_SIG)) != 0) {
1957 /* It is not one of ours */
1961 offset += sizeof(JXTA_MSGELEM_SIG);
1964 available = tvb_reported_length_remaining(tvb, offset);
1965 if (available < sizeof(guint8)) {
1966 needed = (gint) (sizeof(guint8) - available);
1969 flags = tvb_get_guint8(tvb, offset);
1970 offset += sizeof(guint8);
1973 /* namespace id field */
1974 available = tvb_reported_length_remaining(tvb, offset);
1975 if (available < sizeof(guint16)) {
1976 needed = (gint) (sizeof(guint16) - available);
1980 offset += sizeof(guint16);
1983 if ((flags & JXTAMSG2_ELMFLAG_NAME_LITERAL) == 0) {
1984 available = tvb_reported_length_remaining(tvb, offset);
1985 if (available < sizeof(guint16)) {
1986 needed = (gint) (sizeof(guint16) - available);
1990 offset += sizeof(guint16);
1992 /* literal name field */
1993 available = tvb_reported_length_remaining(tvb, offset);
1994 if (available < sizeof(guint16)) {
1995 needed = (gint) (sizeof(guint16) - available);
1998 guint16 name_len = tvb_get_ntohs(tvb, offset);
1999 offset += sizeof(guint16);
2001 available = tvb_reported_length_remaining(tvb, offset);
2002 if (available < name_len) {
2003 needed = (gint) (name_len - available);
2012 if ((flags & JXTAMSG2_ELMFLAG_TYPE) != 0) {
2013 available = tvb_reported_length_remaining(tvb, offset);
2014 if (available < sizeof(guint16)) {
2015 needed = (gint) (sizeof(guint16) - available);
2019 offset += sizeof(guint16);
2022 /* encoding field */
2023 if ((flags & JXTAMSG2_ELMFLAG_ENCODINGS) != 0) {
2024 available = tvb_reported_length_remaining(tvb, offset);
2025 if (available < sizeof(guint16)) {
2026 needed = (gint) (sizeof(guint16) - available);
2030 offset += sizeof(guint16);
2035 if ((flags & JXTAMSG2_ELMFLAG_UINT64_LENS) != 0) {
2036 available = tvb_reported_length_remaining(tvb, offset);
2037 if (available < sizeof(guint64)) {
2038 needed = (gint) (sizeof(guint64) - available);
2041 guint64 content_len = tvb_get_ntoh64(tvb, offset);
2042 offset += sizeof(guint64);
2044 available = tvb_reported_length_remaining(tvb, offset);
2045 if (available < content_len) {
2046 needed = (gint) (content_len - available);
2050 offset += (guint) content_len;
2053 available = tvb_reported_length_remaining(tvb, offset);
2054 if (available < sizeof(guint32)) {
2055 needed = (gint) (sizeof(guint32) - available);
2058 guint64 content_len = tvb_get_ntohl(tvb, offset);
2059 offset += sizeof(guint32);
2061 available = tvb_reported_length_remaining(tvb, offset);
2062 if (available < content_len) {
2063 needed = (gint) (content_len - available);
2067 offset += (guint) content_len;
2071 /* signature element field */
2072 if ((flags & JXTAMSG2_ELMFLAG_SIGNATURE) != 0) {
2073 tvbuff_t *jxta_signature_element_tvb;
2076 jxta_signature_element_tvb = tvb_new_subset(tvb, offset, -1, -1);
2078 processed = dissect_jxta_message_element_2(jxta_signature_element_tvb, pinfo, NULL, 0, NULL);
2080 if (processed == 0) {
2084 if (processed < 0) {
2085 needed = -processed;
2089 offset += processed;
2095 if ((needed > 0) && gDESEGMENT && pinfo->can_desegment) {
2096 /* g_message( "Element2 requesting %d more bytes", needed ); */
2097 pinfo->desegment_offset = 0;
2098 pinfo->desegment_len = needed;
2102 /* Second (optional) pass : build the proto tree */
2104 guint tree_offset = 0;
2105 proto_item *jxta_elem_tree_item = proto_tree_add_item(tree, hf_jxta_element, tvb, tree_offset, -1, FALSE);
2106 proto_tree *jxta_elem_tree = proto_item_add_subtree(jxta_elem_tree_item, ett_jxta_elem);
2107 proto_item *flags_ti;
2108 proto_tree *jxta_elem_flags_tree = NULL;
2109 guint16 namespaceID;
2110 proto_item *namespace_ti;
2112 proto_item *name_ti;
2113 guint64 content_len;
2114 gchar *mediatype = NULL;
2115 tvbuff_t *element_content_tvb;
2116 proto_item * jxta_elem_length_item = NULL;
2118 proto_tree_add_item(jxta_elem_tree, hf_jxta_element_sig, tvb, tree_offset, sizeof(JXTA_MSGELEM_SIG), FALSE);
2119 tree_offset += sizeof(JXTA_MSGELEM_SIG);
2121 flags = tvb_get_guint8(tvb, tree_offset);
2122 flags_ti = proto_tree_add_uint(jxta_elem_tree, hf_jxta_element_flags, tvb, tree_offset, sizeof(guint8), flags);
2123 jxta_elem_flags_tree = proto_item_add_subtree(flags_ti, ett_jxta_elem_2_flags);
2124 proto_tree_add_boolean(jxta_elem_flags_tree, hf_jxta_element2_flag_64bitlens, tvb, tree_offset, 1, flags);
2125 proto_tree_add_boolean(jxta_elem_flags_tree, hf_jxta_element2_flag_nameLiteral, tvb, tree_offset, 1, flags);
2126 proto_tree_add_boolean(jxta_elem_flags_tree, hf_jxta_element2_flag_hasType, tvb, tree_offset, 1, flags);
2127 proto_tree_add_boolean(jxta_elem_flags_tree, hf_jxta_element2_flag_hasSignature, tvb, tree_offset, 1, flags);
2128 proto_tree_add_boolean(jxta_elem_flags_tree, hf_jxta_element2_flag_hasEncoding, tvb, tree_offset, 1, flags);
2129 proto_tree_add_boolean(jxta_elem_flags_tree, hf_jxta_element2_flag_sigOfEncoded, tvb, tree_offset, 1, flags);
2130 tree_offset += sizeof(guint8);
2133 namespaceID = tvb_get_ntohs(tvb, tree_offset);
2135 proto_tree_add_uint(jxta_elem_tree, hf_jxta_element2_namespaceid, tvb, tree_offset, sizeof(guint16), namespaceID);
2136 if (namespaceID < names_count) {
2137 proto_item_append_text(namespace_ti, " (%s)", names_table[namespaceID]);
2139 proto_item_append_text(namespace_ti, " * BAD *");
2141 tree_offset += sizeof(guint16);
2144 if ((flags & JXTAMSG2_ELMFLAG_NAME_LITERAL) == 0) {
2145 nameID = tvb_get_ntohs(tvb, tree_offset);
2147 proto_tree_add_uint(jxta_elem_tree, hf_jxta_element2_nameid, tvb, tree_offset, sizeof(guint16), nameID);
2148 if (namespaceID < names_count) {
2149 proto_item_append_text(name_ti, " (%s)", names_table[nameID]);
2151 proto_item_append_text(name_ti, " * BAD *");
2153 tree_offset += sizeof(guint16);
2156 guint16 name_len = tvb_get_ntohs(tvb, tree_offset);
2157 proto_item_append_text(jxta_elem_tree_item, " \"%s\"", tvb_format_text(tvb, tree_offset + sizeof(guint16), name_len));
2158 proto_tree_add_item(jxta_elem_tree, hf_jxta_element_name, tvb, tree_offset, sizeof(guint16), FALSE);
2159 tree_offset += sizeof(guint16) + name_len;
2163 if ((flags & JXTAMSG2_ELMFLAG_TYPE) != 0) {
2164 guint16 mimeID = tvb_get_ntohs(tvb, tree_offset);
2165 proto_item *mime_ti =
2166 proto_tree_add_uint(jxta_elem_tree, hf_jxta_element2_mimeid, tvb, tree_offset, sizeof(guint16), mimeID);
2168 if (mimeID < names_count) {
2169 proto_item_append_text(mime_ti, " (%s)", names_table[mimeID]);
2170 mediatype = ep_strdup( names_table[mimeID] );
2172 proto_item_append_text(mime_ti, " * BAD *");
2175 tree_offset += sizeof(guint16);
2177 mediatype = "application/octect-stream";
2180 /* process encoding */
2181 if ((flags & JXTAMSG2_ELMFLAG_ENCODINGS) != 0) {
2182 guint16 encodingID = tvb_get_ntohs(tvb, tree_offset);
2183 proto_item *encoding_ti =
2184 proto_tree_add_uint(jxta_elem_tree, hf_jxta_element2_encodingid, tvb, tree_offset, sizeof(guint16), encodingID);
2186 if (encodingID < names_count) {
2187 proto_item_append_text(encoding_ti, " (%s)", names_table[encodingID]);
2189 proto_item_append_text(encoding_ti, " * BAD *");
2192 tree_offset += sizeof(guint16);
2196 if ((flags & JXTAMSG2_ELMFLAG_UINT64_LENS) != 0) {
2197 content_len = tvb_get_ntoh64(tvb, tree_offset);
2198 jxta_elem_length_item = proto_tree_add_item(jxta_elem_tree, hf_jxta_element_content_len64, tvb, tree_offset, sizeof(guint64), FALSE);
2199 tree_offset += sizeof(guint64);
2201 content_len = tvb_get_ntohl(tvb, tree_offset);
2202 jxta_elem_length_item = proto_tree_add_item(jxta_elem_tree, hf_jxta_element_content_len, tvb, tree_offset, sizeof(guint32), FALSE);
2203 tree_offset += sizeof(guint32);
2207 element_content_tvb = tvb_new_subset(tvb, tree_offset, (gint)content_len, (gint)content_len);
2209 tree_offset += dissect_media(mediatype, element_content_tvb, pinfo, jxta_elem_tree);
2211 /* process the signature element */
2212 if ((flags & JXTAMSG2_ELMFLAG_SIGNATURE) != 0) {
2213 tvbuff_t *jxta_message_element_tvb = tvb_new_subset(tvb, tree_offset, -1, -1);
2215 tree_offset += dissect_jxta_message_element_1(jxta_message_element_tvb, pinfo, jxta_elem_tree, names_count, names_table);
2218 proto_item_set_end(jxta_elem_tree_item, tvb, tree_offset);
2220 DISSECTOR_ASSERT(tree_offset == offset);
2227 * Dissect a tvbuff containing arbitrary typed data.
2229 * <p/>We provide special handling for type media types :
2231 * <dt>application/x-jxta-tls-block</dt>
2232 * <dd>We hand this data off to SSL to dissect.</dd>
2233 * <dt>application/gzip</dt>
2234 * <dd>We decompress the data and then dissect the contents as <tt>text/xml;charset="UTF-8"</tt></dd>
2237 * @param fullmediatype The full media type of the buffer to dissect including params
2238 * @param tvb The buffer to dissect.
2239 * @param pinfo Packet Info.
2240 * @param tree The protocol tree.
2241 * @return Number of bytes from the tvbuff_t which were processed, 0 (zero) if
2242 * the packet was not recognized and negative if the dissector needs
2243 * more bytes in order to process a PDU.
2245 static int dissect_media( const gchar* fullmediatype, tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree) {
2248 if (fullmediatype) {
2249 gchar *mediatype = ep_strdup(fullmediatype);
2250 gchar *parms_at = strchr(mediatype, ';');
2251 const char *save_match_string = pinfo->match_string;
2252 void * save_private_data = pinfo->private_data;
2254 /* Based upon what is done in packet-media.c we set up type and params */
2255 if (NULL != parms_at) {
2256 pinfo->private_data = ep_strdup( parms_at + 1 );
2259 pinfo->private_data = NULL;
2262 /* Set the version that goes to packet-media.c before converting case */
2263 pinfo->match_string = ep_strdup(mediatype);
2265 /* force to lower case */
2266 #if GLIB_MAJOR_VERSION < 2
2267 g_strdown(mediatype);
2270 gchar *mediatype_lowercase = g_ascii_strdown(mediatype, -1);
2271 mediatype = ep_strdup(mediatype_lowercase);
2272 g_free(mediatype_lowercase);
2276 if (0 == strcmp("application/x-jxta-tls-block", mediatype)) {
2277 /* If we recognize it as a TLS packet then we shuffle it off to ssl dissector. */
2278 dissector_handle_t ssl_handle = find_dissector("ssl");
2279 if (NULL != ssl_handle) {
2280 dissected = call_dissector(ssl_handle, tvb, pinfo, tree);
2282 } else if (0 == strcmp("application/gzip", mediatype)) {
2283 tvbuff_t *uncomp_tvb = tvb_uncompress(tvb, 0, tvb_length(tvb));
2285 if( NULL != uncomp_tvb ) {
2286 tvb_set_child_real_data_tvbuff(tvb, uncomp_tvb);
2287 add_new_data_source(pinfo, uncomp_tvb, "Uncompressed Element Content");
2289 /* XXX bondolo 20060201 Force XML for uncompressed data. */
2290 dissected = dissect_media("text/xml;charset=\"UTF-8\"", uncomp_tvb, pinfo, tree);
2292 if( dissected > 0 ) {
2293 /* report back the uncompressed length. */
2294 dissected = tvb_length(tvb);
2298 dissected = dissector_try_string(media_type_dissector_table, mediatype, tvb, pinfo, tree) ? tvb_length(tvb) : 0;
2300 if( dissected != (int) tvb_length(tvb) ) {
2301 /* g_message( "%s : %d expected, %d dissected", mediatype, tvb_length(tvb), dissected ); */
2305 if (0 == dissected) {
2306 dissected = call_dissector(media_handle, tvb, pinfo, tree);
2309 pinfo->match_string = save_match_string;
2310 pinfo->private_data = save_private_data;
2313 if(0 == dissected) {
2314 /* display it as raw data */
2315 dissected = call_dissector_only(data_handle, tvb, pinfo, tree);
2322 * Register jxta protocol and jxta message protocol, header fields, subtree types, preferences.
2324 void proto_register_jxta(void)
2326 module_t *jxta_module;
2328 proto_jxta = proto_register_protocol("JXTA P2P", "JXTA", "jxta");
2330 jxta_tap = register_tap("jxta");
2332 proto_message_jxta = proto_register_protocol("JXTA Message", "JXTA Message", "jxta.message");
2334 message_jxta_handle = new_create_dissector_handle(dissect_jxta_message, proto_message_jxta);
2336 /* Register header fields */
2337 proto_register_field_array(proto_jxta, hf, array_length(hf));
2339 /* Register JXTA Sub-tree */
2340 proto_register_subtree_array(ett, array_length(ett));
2342 /* Register preferences */
2343 /* register re-init routine */
2344 jxta_module = prefs_register_protocol(proto_jxta, proto_reg_handoff_jxta);
2346 prefs_register_bool_preference(jxta_module, "msg.mediatype", "Register binary JXTA Message as a media type",
2347 "Enable to have correctly typed MIME media dissected as JXTA Messages.", &gMSG_MEDIA);
2349 prefs_register_bool_preference(jxta_module, "desegment",
2350 "Reassemble JXTA messages spanning multiple UDP/TCP/SCTP segments",
2351 "Whether the JXTA dissector should reassemble messages spanning multiple UDP/TCP/SCTP segments."
2352 " To use this option you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings "
2353 " and enable \"Reassemble fragmented IP datagrams\" in the IP protocol settings.",
2356 prefs_register_bool_preference(jxta_module, "udp.heuristic", "Try to discover JXTA in UDP datagrams",
2357 "Enable to inspect UDP datagrams for JXTA messages.", &gUDP_HEUR);
2359 prefs_register_bool_preference(jxta_module, "tcp.heuristic", "Try to discover JXTA in TCP connections",
2360 "Enable to inspect TCP connections for JXTA conversations.", &gTCP_HEUR);
2362 prefs_register_bool_preference(jxta_module, "sctp.heuristic", "Try to discover JXTA in SCTP connections",
2363 "Enable to inspect SCTP connections for JXTA conversations.", &gSCTP_HEUR);
2368 * Update registrations in response to preferences changes.
2370 void proto_reg_handoff_jxta(void)
2372 static gboolean init_done = FALSE;
2374 static gboolean msg_media_register_done = FALSE;
2376 static gboolean udp_register_done = FALSE;
2377 static gboolean tcp_register_done = FALSE;
2378 static gboolean sctp_register_done = FALSE;
2381 media_type_dissector_table = find_dissector_table("media_type");
2383 data_handle = find_dissector("data");
2385 media_handle = find_dissector("media");
2387 new_register_dissector("jxta.udp", dissect_jxta_udp, proto_jxta);
2389 new_register_dissector("jxta.stream", dissect_jxta_stream, proto_jxta);
2390 stream_jxta_handle = find_dissector("jxta.stream");
2396 if( !msg_media_register_done ) {
2397 /* g_message( "Registering JXTA Message media type" ); */
2398 dissector_add_string("media_type", "application/x-jxta-msg", message_jxta_handle);
2399 msg_media_register_done = TRUE;
2402 if( msg_media_register_done ) {
2403 /* g_message( "Deregistering JXTA Message media type" ); */
2404 dissector_delete_string("media_type", "application/x-jxta-msg", message_jxta_handle);
2405 msg_media_register_done = FALSE;
2410 if( !udp_register_done ) {
2411 /* g_message( "Registering UDP Heuristic dissector" ); */
2412 heur_dissector_add("udp", dissect_jxta_UDP_heur, proto_jxta);
2413 udp_register_done = TRUE;
2416 if( udp_register_done ) {
2417 /* g_message( "Deregistering UDP Heuristic dissector" ); */
2418 heur_dissector_delete("udp", dissect_jxta_UDP_heur, proto_jxta);
2419 udp_register_done = FALSE;
2424 if( !tcp_register_done ) {
2425 /* g_message( "Registering TCP Heuristic dissector" ); */
2426 heur_dissector_add("tcp", dissect_jxta_TCP_heur, proto_jxta);
2427 tcp_register_done = TRUE;
2430 if( tcp_register_done ) {
2431 /* g_message( "Deregistering TCP Heuristic dissector" ); */
2432 heur_dissector_delete("tcp", dissect_jxta_TCP_heur, proto_jxta);
2433 tcp_register_done = FALSE;
2438 if( !sctp_register_done ) {
2439 /* g_message( "Registering SCTP Heuristic dissector" ); */
2440 heur_dissector_add("sctp", dissect_jxta_SCTP_heur, proto_jxta);
2441 sctp_register_done = TRUE;
2444 if( sctp_register_done ) {
2445 /* g_message( "Deregistering SCTP Heuristic dissector" ); */
2446 heur_dissector_delete("sctp", dissect_jxta_SCTP_heur, proto_jxta);
2447 sctp_register_done = FALSE;