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";
60 static const gchar* JXTA_WELCOME_MSG_VERSION_3_0 = "3.0";
62 static const int JXTA_MSG_VERSION_1 = 0;
63 static const int JXTA_MSG_VERSION_2 = 1;
65 static const int JXTAMSG1_ELMFLAG_TYPE = 1 << 0;
66 static const int JXTAMSG1_ELMFLAG_ENCODING = 1 << 1;
67 static const int JXTAMSG1_ELMFLAG_SIGNATURE = 1 << 2;
69 static const int JXTAMSG2_ELMFLAG_UINT64_LENS = 1 << 0;
70 static const int JXTAMSG2_ELMFLAG_NAME_LITERAL = 1 << 1;
71 static const int JXTAMSG2_ELMFLAG_TYPE = 1 << 2;
72 static const int JXTAMSG2_ELMFLAG_SIGNATURE = 1 << 3;
73 static const int JXTAMSG2_ELMFLAG_ENCODINGS = 1 << 4;
75 static int proto_jxta = -1;
76 static int proto_message_jxta = -1;
77 static int jxta_tap = -1;
79 static dissector_table_t media_type_dissector_table = NULL;
80 static dissector_handle_t data_handle = NULL;
81 static dissector_handle_t stream_jxta_handle = NULL;
82 static dissector_handle_t message_jxta_handle;
84 static int hf_jxta_udp = -1;
85 static int hf_jxta_udpsig = -1;
86 static int hf_jxta_welcome = -1;
87 static int hf_jxta_welcome_initiator = -1;
88 static int hf_jxta_welcome_sig = -1;
89 static int hf_jxta_welcome_destAddr = -1;
90 static int hf_jxta_welcome_pubAddr = -1;
91 static int hf_jxta_welcome_peerid = -1;
92 static int hf_jxta_welcome_noProp = -1;
93 static int hf_jxta_welcome_msgVers = -1;
94 static int hf_jxta_welcome_variable = -1;
95 static int hf_jxta_welcome_version = -1;
96 static int hf_jxta_framing = -1;
97 static int hf_jxta_framing_header = -1;
98 static int hf_jxta_framing_header_name = -1;
99 static int hf_jxta_framing_header_value_length = -1;
100 static int hf_jxta_framing_header_value = -1;
101 static int hf_jxta_message_address = -1;
102 static int hf_jxta_message_src = -1;
103 static int hf_jxta_message_dst = -1;
104 static int hf_jxta_message_sig = -1;
105 static int hf_jxta_message_version = -1;
106 static int hf_jxta_message_flags = -1;
107 static int hf_jxta_message_flag_utf16be = -1;
108 static int hf_jxta_message_flag_ucs32be = -1;
109 static int hf_jxta_message_names_count = -1;
110 static int hf_jxta_message_names_name = -1;
111 static int hf_jxta_message_element_count = -1;
112 static int hf_jxta_element = -1;
113 static int hf_jxta_element_sig = -1;
114 static int hf_jxta_element1_namespaceid = -1;
115 static int hf_jxta_element2_namespaceid = -1;
116 static int hf_jxta_element2_nameid = -1;
117 static int hf_jxta_element2_mimeid = -1;
118 static int hf_jxta_element2_encodingid = -1;
119 static int hf_jxta_element_flags = -1;
120 static int hf_jxta_element1_flag_hasType = -1;
121 static int hf_jxta_element1_flag_hasEncoding = -1;
122 static int hf_jxta_element1_flag_hasSignature = -1;
123 static int hf_jxta_element2_flag_64bitlens = -1;
124 static int hf_jxta_element2_flag_nameLiteral = -1;
125 static int hf_jxta_element2_flag_hasType = -1;
126 static int hf_jxta_element2_flag_hasSignature = -1;
127 static int hf_jxta_element2_flag_hasEncoding = -1;
128 static int hf_jxta_element2_flag_sigOfEncoded = -1;
129 static int hf_jxta_element_name = -1;
130 static int hf_jxta_element_type = -1;
131 static int hf_jxta_element_encoding = -1;
132 static int hf_jxta_element_content_len = -1;
133 static int hf_jxta_element_content_len64 = -1;
134 static int hf_jxta_element_content = -1;
136 /** our header fields */
137 static hf_register_info hf[] = {
139 {"JXTA UDP", "jxta.udp", FT_NONE, BASE_NONE, NULL, 0x0,
143 {"Signature", "jxta.udpsig", FT_STRING, BASE_NONE, NULL, 0x0,
144 "JXTA UDP Signature", HFILL}
147 {"Welcome", "jxta.welcome", FT_NONE, BASE_NONE, NULL, 0x00,
148 "JXTA Connection Welcome Message", HFILL}
150 {&hf_jxta_welcome_initiator,
151 {"Initiator", "jxta.welcome.initiator", FT_BOOLEAN, BASE_NONE, NULL, 0x00,
152 "JXTA Connection Welcome Message Initiator", HFILL}
154 {&hf_jxta_welcome_sig,
155 {"Signature", "jxta.welcome.signature", FT_STRING, BASE_NONE, NULL, 0x0,
156 "JXTA Connection Welcome Message Signature", HFILL}
158 {&hf_jxta_welcome_destAddr,
159 {"Destination Address", "jxta.welcome.destAddr", FT_STRING, BASE_NONE, NULL, 0x0,
160 "JXTA Connection Welcome Message Destination Address", HFILL}
162 {&hf_jxta_welcome_pubAddr,
163 {"Public Address", "jxta.welcome.pubAddr", FT_STRING, BASE_NONE, NULL, 0x0,
164 "JXTA Connection Welcome Message Public Address", HFILL}
166 {&hf_jxta_welcome_peerid,
167 {"PeerID", "jxta.welcome.peerid", FT_STRING, BASE_NONE, NULL, 0x0,
168 "JXTA Connection Welcome Message PeerID", HFILL}
170 {&hf_jxta_welcome_noProp,
171 {"No Propagate Flag", "jxta.welcome.noPropFlag", FT_STRING, BASE_NONE, NULL, 0x0,
172 "JXTA Connection Welcome Message No Propagate Flag", HFILL}
174 {&hf_jxta_welcome_msgVers,
175 {"Preferred Message Version", "jxta.welcome.msgVersion", FT_STRING, BASE_NONE, NULL, 0x0,
176 "JXTA Connection Welcome Message Preferred Message Version", HFILL}
178 {&hf_jxta_welcome_variable,
179 {"Variable Parameter", "jxta.welcome.variable", FT_STRING, BASE_NONE, NULL, 0x0,
180 "JXTA Connection Welcome Message Variable Parameter", HFILL}
182 {&hf_jxta_welcome_version,
183 {"Version", "jxta.welcome.version", FT_STRING, BASE_NONE, NULL, 0x0,
184 "JXTA Connection Welcome Message Version", HFILL}
187 {"Framing", "jxta.framing", FT_NONE, BASE_NONE, NULL, 0x0,
188 "JXTA Message Framing", HFILL}
190 {&hf_jxta_framing_header,
191 {"Header", "jxta.framing.header", FT_NONE, BASE_NONE, NULL, 0x0,
192 "JXTA Message Framing Header", HFILL}
194 {&hf_jxta_framing_header_name,
195 {"Name", "jxta.framing.header.name", FT_UINT_STRING, BASE_NONE, NULL, 0x0,
196 "JXTA Message Framing Header Name", HFILL}
198 {&hf_jxta_framing_header_value_length,
199 {"Value Length", "jxta.framing.header.valuelen", FT_UINT16, BASE_DEC, NULL, 0x0,
200 "JXTA Message Framing Header Value Length", HFILL}
202 {&hf_jxta_framing_header_value,
203 {"Value", "jxta.framing.header.value", FT_BYTES, BASE_HEX, NULL, 0x0,
204 "JXTA Message Framing Header Value", HFILL}
206 {&hf_jxta_message_address,
207 {"Address", "jxta.message.address", FT_STRING, BASE_NONE, NULL, 0x0,
208 "JXTA Message Address (source or destination)", HFILL}
210 {&hf_jxta_message_src,
211 {"Source", "jxta.message.source", FT_STRING, BASE_NONE, NULL, 0x0,
212 "JXTA Message Source", HFILL}
214 {&hf_jxta_message_dst,
215 {"Destination", "jxta.message.destination", FT_STRING, BASE_NONE, NULL, 0x0,
216 "JXTA Message Destination", HFILL}
218 {&hf_jxta_message_sig,
219 {"Signature", "jxta.message.signature", FT_STRING, BASE_NONE, NULL, 0x0,
220 "JXTA Message Signature", HFILL}
222 {&hf_jxta_message_version,
223 {"Version", "jxta.message.version", FT_UINT8, BASE_DEC, NULL, 0x0,
224 "JXTA Message Version", HFILL}
226 {&hf_jxta_message_flags,
227 {"Flags", "jxta.message.flags", FT_UINT8, BASE_HEX, NULL, 0x0,
228 "JXTA Message Flags", HFILL}
230 {&hf_jxta_message_flag_utf16be,
231 {"UTF16BE", "jxta.message.flags.UTF-16BE", FT_BOOLEAN, 2, TFS(&flags_set_truth), 0x01,
232 "JXTA Message Element Flag -- UTF16-BE Strings", HFILL}
234 {&hf_jxta_message_flag_ucs32be,
235 {"UCS32BE", "jxta.message.flags.UCS32BE", FT_BOOLEAN, 2, TFS(&flags_set_truth), 0x02,
236 "JXTA Message Flag -- UCS32-BE Strings", HFILL}
238 {&hf_jxta_message_names_count,
239 {"Names Count", "jxta.message.names", FT_UINT16, BASE_DEC, NULL, 0x0,
240 "JXTA Message Names Table", HFILL}
242 {&hf_jxta_message_names_name,
243 {"Names Table Name", "jxta.message.names.name", FT_UINT_STRING, BASE_NONE, NULL, 0x0,
244 "JXTA Message Names Table Name", HFILL}
246 {&hf_jxta_message_element_count,
247 {"Element Count", "jxta.message.elements", FT_UINT16, BASE_DEC, NULL, 0x0,
248 "JXTA Message Element Count", HFILL}
251 {"JXTA Message Element", "jxta.message.element", FT_NONE, BASE_NONE, NULL, 0x0,
252 "JXTA Message Element", HFILL}
254 {&hf_jxta_element_sig,
255 {"Signature", "jxta.message.element.signature", FT_STRING, BASE_NONE, NULL, 0x0,
256 "JXTA Message Element Signature", HFILL}
258 {&hf_jxta_element1_namespaceid,
259 {"Namespace ID", "jxta.message.element.namespaceid", FT_UINT8, BASE_DEC, NULL, 0x0,
260 "JXTA Message Element Namespace ID", HFILL}
262 {&hf_jxta_element2_namespaceid,
263 {"Namespace ID", "jxta.message.element.namespaceid", FT_UINT16, BASE_DEC, NULL, 0x0,
264 "JXTA Message Element Namespace ID", HFILL}
266 {&hf_jxta_element_flags,
267 {"Flags", "jxta.message.element.flags", FT_UINT8, BASE_HEX, NULL, 0x0,
268 "JXTA Message Element Flags", HFILL}
270 {&hf_jxta_element1_flag_hasType,
271 {"hasType", "jxta.message.element.flags.hasType", FT_BOOLEAN, 3, TFS(&flags_set_truth), 0x01,
272 "JXTA Message Element Flag -- hasType", HFILL}
274 {&hf_jxta_element1_flag_hasEncoding,
275 {"hasEncoding", "jxta.message.element.flags.hasEncoding", FT_BOOLEAN, 3, TFS(&flags_set_truth), 0x02,
276 "JXTA Message Element Flag -- hasEncoding", HFILL}
278 {&hf_jxta_element1_flag_hasSignature,
279 {"hasSignature", "jxta.message.element.flags.hasSignature", FT_BOOLEAN, 3, TFS(&flags_set_truth), 0x04,
280 "JXTA Message Element Flag -- hasSignature", HFILL}
282 {&hf_jxta_element2_flag_64bitlens,
283 {"uint64Lens", "jxta.message.element.flags.uint64Lens", FT_BOOLEAN, 6, TFS(&flags_set_truth), 0x01,
284 "JXTA Message Element Flag -- uint64Lens", HFILL}
286 {&hf_jxta_element2_flag_nameLiteral,
287 {"nameLiteral", "jxta.message.element.flags.nameLiteral", FT_BOOLEAN, 6, TFS(&flags_set_truth), 0x02,
288 "JXTA Message Element Flag -- nameLiteral", HFILL}
290 {&hf_jxta_element2_flag_hasType,
291 {"hasEncoding", "jxta.message.element.flags.hasType", FT_BOOLEAN, 6, TFS(&flags_set_truth), 0x04,
292 "JXTA Message Element Flag -- hasType", HFILL}
294 {&hf_jxta_element2_flag_hasSignature,
295 {"hasSignature", "jxta.message.element.flags.hasSignature", FT_BOOLEAN, 6, TFS(&flags_set_truth), 0x08,
296 "JXTA Message Element Flag -- hasSignature", HFILL}
298 {&hf_jxta_element2_flag_hasEncoding,
299 {"hasSignature", "jxta.message.element.flags.hasEncoding", FT_BOOLEAN, 6, TFS(&flags_set_truth), 0x10,
300 "JXTA Message Element Flag -- hasEncoding", HFILL}
302 {&hf_jxta_element2_flag_sigOfEncoded,
303 {"sigOfEncoded", "jxta.message.element.flags.sigOfEncoded", FT_BOOLEAN, 6, TFS(&flags_set_truth), 0x20,
304 "JXTA Message Element Flag -- sigOfEncoded", HFILL}
306 {&hf_jxta_element2_nameid,
307 {"Name ID", "jxta.message.element.nameid", FT_UINT16, BASE_DEC, NULL, 0x0,
308 "JXTA Message Element Name ID", HFILL}
310 {&hf_jxta_element_name,
311 {"Element Name", "jxta.message.element.name", FT_UINT_STRING, BASE_NONE, NULL, 0x0,
312 "JXTA Message Element Name", HFILL}
314 {&hf_jxta_element2_mimeid,
315 {"MIME ID", "jxta.message.element.mimeid", FT_UINT16, BASE_DEC, NULL, 0x0,
316 "JXTA Message Element MIME ID", HFILL}
318 {&hf_jxta_element_type,
319 {"Element Type", "jxta.message.element.type", FT_UINT_STRING, BASE_NONE, NULL, 0x0,
320 "JXTA Message Element Name", HFILL}
322 {&hf_jxta_element_encoding,
323 {"Element Type", "jxta.message.element.encoding", FT_UINT_STRING, BASE_NONE, NULL, 0x0,
324 "JXTA Message Element Encoding", HFILL}
326 {&hf_jxta_element_content_len,
327 {"Element Content Length", "jxta.message.element.content.length", FT_UINT32, BASE_DEC, NULL, 0x0,
328 "JXTA Message Element Content Length", HFILL}
330 {&hf_jxta_element_content_len64,
331 {"Element Content Length", "jxta.message.element.content.length", FT_UINT64, BASE_DEC, NULL, 0x0,
332 "JXTA Message Element Content Length", HFILL}
334 {&hf_jxta_element_content,
335 {"Element Content", "jxta.message.element.content", FT_BYTES, BASE_HEX, NULL, 0x0,
336 "JXTA Message Element Content", HFILL}
341 * JXTA Protocol subtree handles
343 static gint ett_jxta = -1;
344 static gint ett_jxta_welcome = -1;
345 static gint ett_jxta_udp = -1;
346 static gint ett_jxta_framing = -1;
347 static gint ett_jxta_framing_header = -1;
348 static gint ett_jxta_msg = -1;
349 static gint ett_jxta_msg_flags = -1;
350 static gint ett_jxta_elem = -1;
351 static gint ett_jxta_elem_1_flags = -1;
352 static gint ett_jxta_elem_2_flags = -1;
355 * JXTA Protocol subtree array
357 static gint *const ett[] = {
362 &ett_jxta_framing_header,
366 &ett_jxta_elem_1_flags,
367 &ett_jxta_elem_2_flags
373 static gboolean gDESEGMENT = TRUE;
374 static gboolean gUDP_HEUR = TRUE;
375 static gboolean gTCP_HEUR = TRUE;
376 static gboolean gSCTP_HEUR = FALSE;
379 * Stream Conversation data
381 struct jxta_stream_conversation_data {
384 address initiator_tpt_address;
385 guint32 initiator_tpt_port;
386 guint32 initiator_welcome_frame;
387 address initiator_address;
389 address receiver_tpt_address;
390 guint32 receiver_tpt_port;
391 guint32 receiver_welcome_frame;
392 address receiver_address;
395 typedef struct jxta_stream_conversation_data jxta_stream_conversation_data;
400 static gboolean dissect_jxta_UDP_heur(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree);
401 static gboolean dissect_jxta_TCP_heur(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree);
402 static gboolean dissect_jxta_SCTP_heur(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree);
404 static int dissect_jxta_udp(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree);
405 static int dissect_jxta_stream(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree);
406 static conversation_t *get_tpt_conversation(packet_info * pinfo, gboolean create);
408 static int dissect_jxta_welcome(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, address * found_addr, gboolean initiator);
409 static int dissect_jxta_message_framing(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, guint64 * content_length,
410 gchar ** content_type);
411 static int dissect_jxta_message(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree);
412 static int dissect_jxta_message_element_1(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, guint ns_count,
413 const gchar ** namespaces);
414 static int dissect_jxta_message_element_2(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, guint ns_count,
415 const gchar ** namespaces);
417 void proto_reg_handoff_jxta(void);
420 * Heuristically dissect a tvbuff containing a JXTA UDP Message
422 * @param tvb The buffer to dissect.
423 * @param pinfo Packet Info.
424 * @param tree The protocol tree.
425 * @return TRUE if the tvb contained JXTA data which was dissected otherwise FALSE
427 static gboolean dissect_jxta_UDP_heur(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
429 /* This is a heuristic dissector, which means we get all the UDP
430 * traffic not sent to a known dissector and not claimed by
431 * a heuristic dissector called before us!
433 int save_desegment_offset;
434 guint32 save_desegment_len;
440 if (tvb_memeql(tvb, 0, JXTA_UDP_SIG, sizeof(JXTA_UDP_SIG)) != 0) {
444 save_desegment_offset = pinfo->desegment_offset;
445 save_desegment_len = pinfo->desegment_len;
446 ret = dissect_jxta_udp(tvb, pinfo, tree);
449 * UDP is not a packet stream protocol, so the UDP dissector
450 * should not, and will not, do the sort of dissection help
451 * that the TCP dissector will. If JXTA messages don't
452 * start and end on UDP packet boundaries, the JXTA dissector
453 * will have to do its own byte stream reassembly.
455 pinfo->desegment_offset = save_desegment_offset;
456 pinfo->desegment_len = save_desegment_len;
458 } else if (ret == 0) {
462 pinfo->desegment_offset = save_desegment_offset;
463 pinfo->desegment_len = save_desegment_len;
467 * A clear acceptance.
474 * Heuristically dissect a tvbuff containing a JXTA TCP Stream
476 * @param tvb The buffer to dissect.
477 * @param pinfo Packet Info.
478 * @param tree The protocol tree.
479 * @return TRUE if the tvb contained JXTA data which was dissected otherwise FALSE
481 static gboolean dissect_jxta_TCP_heur(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
483 /* This is a heuristic dissector, which means we get all the TCP
484 * traffic not sent to a known dissector and not claimed by
485 * a heuristic dissector called before us!
487 int save_desegment_offset;
488 guint32 save_desegment_len;
494 save_desegment_offset = pinfo->desegment_offset;
495 save_desegment_len = pinfo->desegment_len;
496 ret = dissect_jxta_stream(tvb, pinfo, tree);
499 * A heuristic dissector for a TCP-based protocol can reject
500 * a packet, or it can request that more data be provided.
501 * It must not attempt to do both, as the notion of doing both
502 * is nonsensical - if the packet isn't considered a packet
503 * for the dissector's protocol, that dissector won't be
504 * dissecting it no matter *how* much more data is added.
506 * Therefore, we treat a negative return from
507 * dissect_jxta_stream() as a rejection.
509 * If that's not desired - i.e., if we should keep trying to get
510 * more data, in the hopes that we'll eventually be able to
511 * determine whether the packet is a JXTA packet or not - we
512 * should, in this case, leave pinfo->desegment_offset and
513 * pinfo->desegment_len alone, and return TRUE, *NOT* FALSE.
515 pinfo->desegment_offset = save_desegment_offset;
516 pinfo->desegment_len = save_desegment_len;
518 } else if (ret == 0) {
522 pinfo->desegment_offset = save_desegment_offset;
523 pinfo->desegment_len = save_desegment_len;
527 * A clear acceptance.
534 * Heuristically dissect a tvbuff containing a JXTA SCTP Stream
536 * @param tvb The buffer to dissect.
537 * @param pinfo Packet Info.
538 * @param tree The protocol tree.
539 * @return TRUE if the tvb contained JXTA data which was dissected otherwise FALSE
541 static gboolean dissect_jxta_SCTP_heur(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
543 /* This is a heuristic dissector, which means we get all the SCTP
544 * traffic not sent to a known dissector and not claimed by
545 * a heuristic dissector called before us!
547 int save_desegment_offset;
548 guint32 save_desegment_len;
554 save_desegment_offset = pinfo->desegment_offset;
555 save_desegment_len = pinfo->desegment_len;
556 ret = dissect_jxta_stream(tvb, pinfo, tree);
559 * SCTP is not a byte stream protocol, so the SCTP dissector
560 * should not, and will not, do the sort of dissection help
561 * that the SCTP dissector will. If JXTA messages don't
562 * start and end on SCTP packet boundaries, the JXTA dissector
563 * will have to do its own byte stream reassembly.
565 * The SCTP dissector currently won't do reassembly. If that
566 * causes a problem for the JXTA dissector, the correct fix
567 * is to implement reassembly in the SCTP dissector, so *all*
568 * dissectors for protocols running atop SCTP can benefit from
571 pinfo->desegment_offset = save_desegment_offset;
572 pinfo->desegment_len = save_desegment_len;
574 } else if (ret == 0) {
578 pinfo->desegment_offset = save_desegment_offset;
579 pinfo->desegment_len = save_desegment_len;
583 * A clear acceptance.
590 * Dissect a tvbuff containing a JXTA UDP header, JXTA Message framing and a JXTA Message
592 * @param tvb The buffer to dissect.
593 * @param pinfo Packet Info.
594 * @param tree The protocol tree.
595 * @return Number of bytes from the tvbuff_t which were processed, 0 (zero) if
596 * the packet was not recognized as a JXTA packet and negative if the
597 * dissector needs more bytes in order to process a PDU.
599 static int dissect_jxta_udp(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
605 conversation_t *conversation =
606 find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
608 if (conversation == NULL) {
610 * No conversation exists yet - create one.
613 conversation_new(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
616 DISSECTOR_ASSERT(find_dissector("jxta.udp"));
618 conversation_set_dissector(conversation, find_dissector("jxta.udp"));
621 tvbuff_t *jxta_message_framing_tvb;
623 guint64 content_length = -1;
624 gchar *content_type = NULL;
626 available = tvb_reported_length_remaining(tvb, offset);
627 if (available < sizeof(JXTA_UDP_SIG)) {
628 needed = (gint) (sizeof(JXTA_UDP_SIG) - available);
632 if (tvb_memeql(tvb, offset, JXTA_UDP_SIG, sizeof(JXTA_UDP_SIG)) != 0) {
637 offset += sizeof(JXTA_UDP_SIG);
639 jxta_message_framing_tvb = tvb_new_subset(tvb, offset, -1, -1);
640 processed = dissect_jxta_message_framing(jxta_message_framing_tvb, pinfo, NULL, &content_length, &content_type);
642 if ((0 == processed) || (NULL == content_type) || (content_length <= 0) || (content_length > UINT_MAX)) {
643 /** Buffer did not begin with valid framing headers */
652 /* Redo header processing, this time populating the tree. */
653 processed = dissect_jxta_message_framing(jxta_message_framing_tvb, pinfo, tree, &content_length, &content_type);
658 available = tvb_reported_length_remaining(tvb, offset);
659 if (available < content_length) {
660 needed = (gint) (content_length - available);
664 offset += (guint) content_length;
669 if ((needed > 0) && gDESEGMENT && pinfo->can_desegment) {
670 pinfo->desegment_offset = 0;
671 pinfo->desegment_len = needed;
675 if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
676 col_set_str(pinfo->cinfo, COL_PROTOCOL, "JXTA");
680 guint tree_offset = 0;
681 proto_item *jxta_tree_item =
682 proto_tree_add_protocol_format(tree, proto_jxta, tvb, offset, -1, "JXTA" );
683 proto_tree *jxta_tree = proto_item_add_subtree(jxta_tree_item, ett_jxta);
684 proto_item *jxta_udp_tree_item =
685 proto_tree_add_none_format(jxta_tree, hf_jxta_udp, tvb, tree_offset, -1, "JXTA UDP Message");
686 proto_tree *jxta_udp_tree = proto_item_add_subtree(jxta_udp_tree_item, ett_jxta_udp);
687 tvbuff_t *jxta_message_framing_tvb;
688 guint64 content_length = -1;
689 gchar *content_type = NULL;
690 tvbuff_t *jxta_message_tvb;
691 gboolean dissected = FALSE;
694 proto_tree_add_item(jxta_udp_tree, hf_jxta_udpsig, tvb, tree_offset, sizeof(JXTA_UDP_SIG), FALSE);
695 tree_offset += sizeof(JXTA_UDP_SIG);
697 jxta_message_framing_tvb = tvb_new_subset(tvb, tree_offset, -1, -1);
698 processed = dissect_jxta_message_framing(jxta_message_framing_tvb, pinfo, NULL, &content_length, &content_type);
700 if ((0 == processed) || (NULL == content_type) || (content_length <= 0) || (content_length > UINT_MAX)) {
701 /** Buffer did not begin with valid framing headers */
705 processed = dissect_jxta_message_framing(jxta_message_framing_tvb, pinfo, tree, &content_length, &content_type);
707 tree_offset += processed;
709 jxta_message_tvb = tvb_new_subset(tvb, tree_offset, (gint) content_length, (gint) content_length);
711 dissected = dissector_try_string(media_type_dissector_table, content_type, jxta_message_tvb, pinfo, tree);
714 call_dissector(data_handle, jxta_message_tvb, pinfo, tree);
717 tree_offset += (guint) content_length;
719 proto_item_set_end(jxta_udp_tree_item, tvb, tree_offset);
721 DISSECTOR_ASSERT(offset == tree_offset);
728 * Dissect a tvbuff containing JXTA stream PDUs. This commonly includes
729 * connections over TCP sockets.
731 * <p/>The stream (in both directions) will consist of a JXTA Welcome Message
732 * followed by an indeterminate number of JXTA Message Framing Headers and
735 * @param tvb The buffer to dissect.
736 * @param pinfo Packet Info.
737 * @param tree The protocol tree.
738 * @return Number of bytes from the tvbuff_t which were processed, 0 (zero) if
739 * the packet was not recognized as a JXTA packet and negative if the
740 * dissector needs more bytes in order to process a PDU.
742 static int dissect_jxta_stream(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
745 guint available = tvb_reported_length_remaining(tvb, offset);
748 conversation_t *tpt_conversation = NULL;
749 jxta_stream_conversation_data *tpt_conv_data = NULL;
750 proto_item *jxta_tree_item = NULL;
751 proto_tree *jxta_tree = NULL;
753 /*g_message("Dissecting %s : %d", (NULL != tree) ? "for display" : "", pinfo->fd->num );*/
755 if (available < sizeof(JXTA_WELCOME_MSG_SIG)) {
756 needed = (gint) (sizeof(JXTA_WELCOME_MSG_SIG) - available);
760 if (0 == tvb_memeql(tvb, 0, JXTA_WELCOME_MSG_SIG, sizeof(JXTA_WELCOME_MSG_SIG))) {
761 /* The beginning of a JXTA stream connection */
762 address *welcome_addr;
763 gboolean initiator = FALSE;
765 tpt_conversation = get_tpt_conversation(pinfo, TRUE);
766 tpt_conv_data = (jxta_stream_conversation_data *) conversation_get_proto_data(tpt_conversation, proto_jxta);
768 if (0 == tpt_conv_data->initiator_welcome_frame) {
769 /* The initiator welcome frame */
770 tpt_conv_data->tpt_ptype = pinfo->ptype;
771 tpt_conv_data->initiator_welcome_frame = pinfo->fd->num;
772 SE_COPY_ADDRESS(&tpt_conv_data->initiator_tpt_address, &pinfo->src);
773 tpt_conv_data->initiator_tpt_port = pinfo->srcport;
775 welcome_addr = &tpt_conv_data->initiator_address;
778 if (tpt_conv_data->initiator_welcome_frame >= pinfo->fd->num) {
779 /* what we saw previously was the receiver welcome message */
780 tpt_conv_data->receiver_welcome_frame = tpt_conv_data->initiator_welcome_frame;
781 tpt_conv_data->receiver_tpt_address = tpt_conv_data->initiator_tpt_address;
782 tpt_conv_data->receiver_tpt_port = tpt_conv_data->initiator_tpt_port;
783 tpt_conv_data->receiver_address = tpt_conv_data->initiator_address;
784 tpt_conv_data->initiator_welcome_frame = pinfo->fd->num;
785 SE_COPY_ADDRESS(&tpt_conv_data->initiator_tpt_address, &pinfo->src);
786 tpt_conv_data->initiator_tpt_port = pinfo->srcport;
788 welcome_addr = &tpt_conv_data->initiator_address;
791 /* The receiver welcome frame */
792 tpt_conv_data->tpt_ptype = pinfo->ptype;
793 tpt_conv_data->receiver_welcome_frame = pinfo->fd->num;
794 SE_COPY_ADDRESS(&tpt_conv_data->receiver_tpt_address, &pinfo->src);
795 tpt_conv_data->receiver_tpt_port = pinfo->srcport;
797 welcome_addr = &tpt_conv_data->receiver_address;
802 processed = dissect_jxta_welcome(tvb, pinfo, NULL, welcome_addr, initiator);
804 if( processed < 0 ) {
809 /* redo, this time creating the display tree. */
811 proto_tree_add_protocol_format(tree, proto_jxta, tvb, offset, -1, "JXTA" );
812 jxta_tree = proto_item_add_subtree(jxta_tree_item, ett_jxta);
814 processed = dissect_jxta_welcome(tvb, pinfo, jxta_tree, welcome_addr, initiator);
816 /* Somewhere in the middle of a JXTA stream connection */
817 guint64 content_length = -1;
818 gchar *content_type = NULL;
819 gint headers_len = dissect_jxta_message_framing(tvb, pinfo, NULL, &content_length, &content_type);
821 /*g_message("%d Tpt %s:%d -> %s:%d tvb len=%d\n\t%s %u", pinfo->fd->num,
822 address_to_str(&pinfo->src), pinfo->srcport,
823 address_to_str(&pinfo->dst), pinfo->destport,
824 tvb_reported_length_remaining(tvb, 0),
825 (content_type) ? content_type : "[unknown content type]", (guint) content_length);*/
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 if (headers_len < 0) {
833 /* negative headers_len means we need more bytes */
834 needed = -headers_len;
838 available = tvb_reported_length_remaining(tvb, offset + headers_len);
839 if (available >= content_length) {
840 tvbuff_t *jxta_message_tvb = tvb_new_subset(tvb, offset + headers_len, (gint) content_length, (gint) content_length);
841 conversation_t *peer_conversation = NULL;
842 address saved_src_addr;
843 guint32 saved_src_port = 0;
844 address saved_dst_addr;
845 guint32 saved_dst_port = 0;
846 port_type saved_port_type = PT_NONE;
850 proto_tree_add_protocol_format(tree, proto_jxta, tvb, offset, -1, "JXTA" );
851 jxta_tree = proto_item_add_subtree(jxta_tree_item, ett_jxta);
853 /* Redo header processing, this time populating the tree. */
854 headers_len = dissect_jxta_message_framing(tvb, pinfo, jxta_tree, &content_length, &content_type);
856 tpt_conversation = get_tpt_conversation(pinfo, TRUE);
858 if (NULL != tpt_conversation) {
859 tpt_conv_data = (jxta_stream_conversation_data *) conversation_get_proto_data(tpt_conversation, proto_jxta);
861 if ((AT_NONE != tpt_conv_data->initiator_address.type) && (AT_NONE != tpt_conv_data->receiver_address.type)) {
863 find_conversation(pinfo->fd->num, &tpt_conv_data->initiator_address, &tpt_conv_data->receiver_address,
864 PT_NONE, 0, 0, NO_PORT_B);
866 if (NULL == peer_conversation) {
868 conversation_new(pinfo->fd->num, &tpt_conv_data->initiator_address,
869 &tpt_conv_data->receiver_address, PT_NONE, 0, 0, NO_PORT_B);
870 conversation_set_dissector(peer_conversation, stream_jxta_handle);
874 g_warning("Uninitialized peer conversation");
878 /* Use our source and destination addresses if we have them */
879 if (NULL != peer_conversation) {
880 saved_src_addr = pinfo->src;
881 saved_src_port = pinfo->srcport;
882 saved_dst_addr = pinfo->dst;
883 saved_dst_port = pinfo->destport;
884 saved_port_type = pinfo->ptype;
885 /*g_message("%d Tpt %s:%d -> %s:%d", pinfo->fd->num, ip_to_str(tpt_conv_data->initiator_tpt_address.data),
886 tpt_conv_data->initiator_tpt_port, ip_to_str(tpt_conv_data->receiver_tpt_address.data),
887 tpt_conv_data->receiver_tpt_port);*/
888 if (ADDRESSES_EQUAL(&pinfo->src, &tpt_conv_data->initiator_tpt_address)
889 && tpt_conv_data->initiator_tpt_port == pinfo->srcport) {
890 /*g_message("%d From initiator : %s -> %s ", pinfo->fd->num, tpt_conv_data->initiator_address.data,
891 tpt_conv_data->receiver_address.data);*/
892 pinfo->src = tpt_conv_data->initiator_address;
893 pinfo->dst = tpt_conv_data->receiver_address;
894 } else if (ADDRESSES_EQUAL(&pinfo->src, &tpt_conv_data->receiver_tpt_address) &&
895 tpt_conv_data->receiver_tpt_port == pinfo->srcport) {
896 /*g_message("%d From receiver : %s -> %s ", pinfo->fd->num, tpt_conv_data->receiver_address.data,
897 tpt_conv_data->initiator_address.data);*/
898 pinfo->src = tpt_conv_data->receiver_address;
899 pinfo->dst = tpt_conv_data->initiator_address;
901 /*g_message("%d Nothing matches %s:%d -> %s:%d", pinfo->fd->num, ip_to_str(pinfo->src.data), pinfo->srcport,
902 ip_to_str(pinfo->dst.data), pinfo->destport);*/
904 /* JXTA doesn't use ports */
905 pinfo->ptype = PT_NONE;
909 /* Just to avoid compilers from thinking (falsely) that these
910 * could be unitialized
912 memset(&saved_src_addr, 0, sizeof(saved_src_addr));
913 memset(&saved_dst_addr, 0, sizeof(saved_dst_addr));
918 dissector_try_string(media_type_dissector_table, content_type, jxta_message_tvb, pinfo, tree);
921 call_dissector(data_handle, jxta_message_tvb, pinfo, jxta_tree);
924 /* Restore the saved src and dst addresses */
925 if (NULL != peer_conversation) {
926 pinfo->src = saved_src_addr;
927 pinfo->srcport = saved_src_port;
928 pinfo->dst = saved_dst_addr;
929 pinfo->destport = saved_dst_port;
930 pinfo->ptype = saved_port_type;
933 processed = (guint) content_length + headers_len;
935 /* we need more bytes before we can process message body. */
936 needed = (gint) ((guint) content_length - available);
944 if ((needed > 0) && gDESEGMENT && pinfo->can_desegment) {
945 /*g_message( "Requesting %d more bytes", needed );*/
946 pinfo->desegment_offset = offset;
947 pinfo->desegment_len = needed;
955 * Find or possibly create a transport conversation object for the connection
956 * which is associated with the packet info.
958 * @param pinfo The packet info from the underlying transport.
959 * @param create If TRUE then create a new conversation object if necessary.
961 static conversation_t *get_tpt_conversation(packet_info * pinfo, gboolean create)
963 conversation_t *tpt_conversation =
964 find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
965 jxta_stream_conversation_data *tpt_conv_data;
967 if (tpt_conversation == NULL) {
973 * No conversation exists yet - create one.
976 conversation_new(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
979 conversation_set_dissector(tpt_conversation, stream_jxta_handle);
981 tpt_conv_data = (jxta_stream_conversation_data *) conversation_get_proto_data(tpt_conversation, proto_jxta);
983 if (NULL == tpt_conv_data) {
984 tpt_conv_data = se_alloc(sizeof(jxta_stream_conversation_data));
985 tpt_conv_data->tpt_ptype = pinfo->ptype;
987 SE_COPY_ADDRESS(&tpt_conv_data->initiator_tpt_address, &pinfo->src);
988 tpt_conv_data->initiator_tpt_port = pinfo->srcport;
989 tpt_conv_data->initiator_welcome_frame = 0;
990 /* XXX bondolo This is not quite correct as it should include port until a peerid can be associated. */
991 SE_COPY_ADDRESS(&tpt_conv_data->initiator_address, &pinfo->src);
993 SE_COPY_ADDRESS(&tpt_conv_data->receiver_tpt_address, &pinfo->dst);
994 tpt_conv_data->receiver_tpt_port = pinfo->destport;
995 tpt_conv_data->receiver_welcome_frame = 0;
996 /* XXX bondolo This is not quite correct as it should include port until a peerid can be associated. */
997 SE_COPY_ADDRESS(&tpt_conv_data->receiver_address, &pinfo->dst);
999 conversation_add_proto_data(tpt_conversation, proto_jxta, tpt_conv_data);
1002 return tpt_conversation;
1006 * Dissect a tvbuff containing a JXTA Welcome Message
1008 * @param tvb The buffer to dissect.
1009 * @param pinfo Packet Info.
1010 * @param tree The protocol tree.
1011 * @param found_addr The address found in the welcome message.
1012 * @param initiator If TRUE then we believe this welcome message to be the initiator's.
1013 * @return Number of bytes from the tvbuff_t which were processed, 0 (zero) if
1014 * the packet was not recognized as a JXTA packet and negative if the
1015 * dissector needs more bytes in order to process a PDU.
1017 static int dissect_jxta_welcome(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, address * found_addr, gboolean initiator)
1022 guint available = tvb_reported_length_remaining(tvb, offset);
1023 gchar **tokens = NULL;
1025 if (available < sizeof(JXTA_WELCOME_MSG_SIG)) {
1026 return (gint) (available - sizeof(JXTA_WELCOME_MSG_SIG));
1029 if (0 != tvb_memeql(tvb, 0, JXTA_WELCOME_MSG_SIG, sizeof(JXTA_WELCOME_MSG_SIG))) {
1034 first_linelen = tvb_find_line_end(tvb, offset, -1, &afterwelcome, gDESEGMENT && pinfo->can_desegment);
1036 if (-1 == first_linelen) {
1037 if (available > 4096) {
1038 /* it's too far too be reasonable */
1041 /* ask for more bytes */
1046 /* Dissect the Welcome Message */
1048 if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
1049 col_set_str(pinfo->cinfo, COL_PROTOCOL, "JXTA");
1052 if (check_col(pinfo->cinfo, COL_INFO)) {
1053 col_add_str(pinfo->cinfo, COL_INFO, "Welcome");
1057 gchar *welcomeline = tvb_get_ephemeral_string(tvb, offset, first_linelen);
1058 gchar **current_token;
1059 guint token_offset = offset;
1060 proto_item *jxta_welcome_tree_item = NULL;
1061 proto_tree *jxta_welcome_tree = NULL;
1063 tokens = g_strsplit(welcomeline, " ", 255);
1064 current_token = tokens;
1067 jxta_welcome_tree_item =
1068 proto_tree_add_none_format(tree, hf_jxta_welcome, tvb, offset, afterwelcome,
1069 "JXTA Connection Welcome Message, %s", welcomeline);
1070 jxta_welcome_tree = proto_item_add_subtree(jxta_welcome_tree_item, ett_jxta_welcome);
1073 if (jxta_welcome_tree) {
1074 proto_item *jxta_welcome_initiator_item =
1075 proto_tree_add_boolean(jxta_welcome_tree, hf_jxta_welcome_initiator, tvb, 0, 0, initiator);
1076 PROTO_ITEM_SET_GENERATED(jxta_welcome_initiator_item);
1079 if (NULL != *current_token) {
1080 if (jxta_welcome_tree) {
1081 proto_tree_add_item(jxta_welcome_tree, hf_jxta_welcome_sig, tvb, token_offset, strlen(*current_token), FALSE);
1084 token_offset += strlen(*current_token) + 1;
1087 /* invalid welcome message */
1092 if (NULL != *current_token) {
1093 if (jxta_welcome_tree) {
1094 proto_tree_add_item(jxta_welcome_tree, hf_jxta_welcome_destAddr, tvb, token_offset, strlen(*current_token),
1098 token_offset += strlen(*current_token) + 1;
1101 /* invalid welcome message */
1106 if (NULL != *current_token) {
1107 if (jxta_welcome_tree) {
1108 proto_tree_add_item(jxta_welcome_tree, hf_jxta_welcome_pubAddr, tvb, token_offset, strlen(*current_token), FALSE);
1111 token_offset += strlen(*current_token) + 1;
1114 /* invalid welcome message */
1119 if (NULL != *current_token) {
1120 if (jxta_welcome_tree) {
1121 proto_tree_add_item(jxta_welcome_tree, hf_jxta_welcome_peerid, tvb, token_offset, strlen(*current_token), FALSE);
1124 if (check_col(pinfo->cinfo, COL_INFO)) {
1125 col_append_str(pinfo->cinfo, COL_INFO, (initiator ? " -> " : " <- ") );
1126 col_append_str(pinfo->cinfo, COL_INFO, *current_token);
1129 if (NULL != found_addr) {
1130 found_addr->type = AT_URI;
1131 found_addr->len = strlen(*current_token);
1132 /* FIXME 20050605 bondolo THIS ALLOCATION IS A MEMORY LEAK! */
1133 found_addr->data = g_strdup(*current_token);
1136 token_offset += strlen(*current_token) + 1;
1139 /* invalid welcome message */
1144 if (NULL != *current_token) {
1145 int variable_tokens = 0;
1146 gchar **variable_token = current_token;
1148 while(NULL != *variable_token) {
1153 if( variable_tokens < 1 ) {
1154 /* invalid welcome message */
1159 if( (2 == variable_tokens) && (0 == strcmp(JXTA_WELCOME_MSG_VERSION_1_1, current_token[variable_tokens -1])) ) {
1160 if (jxta_welcome_tree) {
1161 proto_tree_add_item(jxta_welcome_tree, hf_jxta_welcome_noProp, tvb, token_offset, strlen(*current_token), FALSE);
1164 token_offset += strlen(*current_token) + 1;
1167 if (jxta_welcome_tree) {
1168 proto_tree_add_item(jxta_welcome_tree, hf_jxta_welcome_version, tvb, token_offset, strlen(*current_token), FALSE);
1170 } else if( (3 == variable_tokens) && (0 == strcmp(JXTA_WELCOME_MSG_VERSION_3_0, current_token[variable_tokens -1])) ) {
1171 if (jxta_welcome_tree) {
1172 proto_tree_add_item(jxta_welcome_tree, hf_jxta_welcome_noProp, tvb, token_offset, strlen(*current_token), FALSE);
1175 token_offset += strlen(*current_token) + 1;
1178 if (jxta_welcome_tree) {
1179 proto_tree_add_item(jxta_welcome_tree, hf_jxta_welcome_msgVers, tvb, token_offset, strlen(*current_token), FALSE);
1182 token_offset += strlen(*current_token) + 1;
1185 if (jxta_welcome_tree) {
1186 proto_tree_add_item(jxta_welcome_tree, hf_jxta_welcome_version, tvb, token_offset, strlen(*current_token), FALSE);
1189 /* Unrecognized Welcome Version */
1190 int each_variable_token;
1192 for( each_variable_token = 0; each_variable_token < variable_tokens; each_variable_token++ ) {
1193 if (jxta_welcome_tree) {
1194 jxta_welcome_tree_item = proto_tree_add_item(jxta_welcome_tree,
1195 (each_variable_token < (variable_tokens -1) ? hf_jxta_welcome_variable : hf_jxta_welcome_version),
1196 tvb, token_offset, strlen(*current_token), FALSE);
1198 proto_item_append_text(jxta_welcome_tree_item, " (UNRECOGNIZED)");
1201 token_offset += strlen(*current_token) + 1;
1206 /* invalid welcome message */
1215 col_set_writable(pinfo->cinfo, FALSE);
1217 return afterwelcome;
1221 * Dissect a tvbuff containing JXTA Message framing.
1223 * @param tvb The buffer to dissect.
1224 * @param pinfo Packet Info.
1225 * @param tree The protocol tree.
1226 * @param content_length Pointer to a buffer for storing the value of the
1227 * "content-length" header or NULL.
1228 * @param content_type Pointer-to-a-pointer for a new buffer for storing the
1229 * value of the "content_type-length" header or NULL.
1230 * @return Number of bytes from the tvbuff_t which were processed, 0 (zero) if
1231 * the packet was not recognized as a JXTA packet and negative if the
1232 * dissector needs more bytes in order to process a PDU.
1234 static int dissect_jxta_message_framing(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, guint64 * content_length,
1235 gchar ** content_type)
1242 * First go around. Make sure all of the bytes are there.
1245 guint8 headername_len;
1246 guint8 headername_offset;
1247 guint16 headervalue_len;
1248 guint16 headervalue_offset;
1250 available = tvb_reported_length_remaining(tvb, offset);
1251 if (available < sizeof(guint8)) {
1252 needed = (gint) (sizeof(guint8) - available);
1255 headername_len = tvb_get_guint8(tvb, offset);
1256 offset += sizeof(guint8);
1257 headername_offset = offset;
1259 available = tvb_reported_length_remaining(tvb, offset);
1260 if (available < headername_len) {
1261 needed = (gint) (headername_len - available);
1265 if (0 == headername_len) {
1268 offset += headername_len;
1271 available = tvb_reported_length_remaining(tvb, offset);
1272 if (available < sizeof(guint16)) {
1273 needed = (gint) (sizeof(guint16) - available);
1276 headervalue_len = tvb_get_ntohs(tvb, offset);
1277 offset += sizeof(guint16);
1278 headervalue_offset = offset;
1280 available = tvb_reported_length_remaining(tvb, offset);
1281 if (available < headervalue_len) {
1282 needed = (gint) (headervalue_len - available);
1286 offset += headervalue_len;
1289 if (content_type && (sizeof("content-type") - 1) == headername_len) {
1290 if (0 == tvb_strncaseeql(tvb, headername_offset, "content-type", sizeof("content-type") - 1)) {
1291 *content_type = tvb_get_ephemeral_string(tvb, headervalue_offset, headervalue_len);
1296 if (content_length && (sizeof(guint64) == headervalue_len) && ((sizeof("content-length") - 1) == headername_len)) {
1297 if (0 == tvb_strncaseeql(tvb, headername_offset, "content-length", sizeof("content-length") - 1)) {
1298 *content_length = tvb_get_ntoh64(tvb, headervalue_offset);
1303 if ((needed > 0) && gDESEGMENT && pinfo->can_desegment) {
1304 pinfo->desegment_offset = 0;
1305 pinfo->desegment_len = needed;
1310 * Second (optional pass) Now that we are sure that all the bytes are there we update the protocol tree.
1313 guint tree_offset = 0;
1314 proto_item *framing_tree_item =
1315 proto_tree_add_none_format(tree, hf_jxta_framing, tvb, tree_offset, -1, "JXTA Message Framing Headers");
1316 proto_tree *framing_tree = proto_item_add_subtree(framing_tree_item, ett_jxta_framing);
1318 /* parse framing headers */
1320 guint8 headernamelen = tvb_get_guint8(tvb, tree_offset);
1321 proto_item *framing_header_tree_item =
1322 proto_tree_add_item(framing_tree, hf_jxta_framing_header, tvb, tree_offset, -1, FALSE);
1323 proto_tree *framing_header_tree = proto_item_add_subtree(framing_header_tree_item, ett_jxta_framing_header);
1326 * Put header name into the protocol tree
1328 proto_tree_add_item(framing_header_tree, hf_jxta_framing_header_name, tvb, tree_offset, 1, headernamelen);
1331 * Append header name into the header protocol item. It's a nice hint so you don't have to reveal all headers.
1333 if (headernamelen > 0) {
1334 proto_item_append_text(framing_header_tree_item, " \"%s\"",
1335 tvb_format_text(tvb, tree_offset + sizeof(guint8), headernamelen));
1338 tree_offset += sizeof(guint8) + headernamelen;
1340 if (headernamelen > 0) {
1341 guint16 headervaluelen = tvb_get_ntohs(tvb, tree_offset);
1344 proto_tree_add_uint(framing_header_tree, hf_jxta_framing_header_value_length, tvb, tree_offset,
1345 sizeof(guint16), headervaluelen);
1347 /** TODO bondolo Add specific handling for known header types */
1350 * Put header value into protocol tree.
1352 proto_tree_add_item(framing_header_tree, hf_jxta_framing_header_value, tvb, tree_offset + sizeof(guint16),
1353 headervaluelen, FALSE);
1356 tree_offset += sizeof(guint16) + headervaluelen;
1359 proto_item_set_end(framing_header_tree_item, tvb, tree_offset);
1361 if (0 == headernamelen) {
1366 proto_item_set_end(framing_tree_item, tvb, tree_offset);
1368 DISSECTOR_ASSERT(offset == tree_offset);
1371 /* return how many bytes we used up. */
1376 * Dissect a tvbuff containing a JXTA Message.
1378 * @param tvb The buffer to dissect.
1379 * @param pinfo Packet Info.
1380 * @param tree The protocol tree.
1381 * @return Number of bytes from the tvbuff_t which were processed, 0 (zero) if
1382 * the packet was not recognized as a JXTA packet and negative if the
1383 * dissector needs more bytes in order to process a PDU.
1385 static int dissect_jxta_message(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
1392 guint8 message_version;
1394 /* First pass. Make sure all of the bytes we need are available */
1395 available = tvb_reported_length_remaining(tvb, offset);
1396 if (available < sizeof(JXTA_MSG_SIG)) {
1397 needed = (gint) (sizeof(JXTA_MSG_SIG) - available);
1401 if (tvb_memeql(tvb, offset, JXTA_MSG_SIG, sizeof(JXTA_MSG_SIG)) != 0) {
1402 /* It is not one of ours */
1406 offset += sizeof(JXTA_MSG_SIG);
1408 available = tvb_reported_length_remaining(tvb, offset);
1409 if (available < sizeof(guint8)) {
1410 needed = (gint) (sizeof(guint8) - available);
1413 message_version = tvb_get_guint8(tvb, offset);
1415 offset += sizeof(guint8);
1417 if ((JXTA_MSG_VERSION_1 != message_version) && (JXTA_MSG_VERSION_2 != message_version)) {
1418 /* Sort of a lie, we say that we don't recognize it at all. */
1423 /* Read the flags (Version 2 and later) */
1424 if(message_version > 0) {
1425 available = tvb_reported_length_remaining(tvb, offset);
1426 if (available < sizeof(guint8)) {
1427 needed = (gint) (sizeof(guint8) - available);
1430 offset += sizeof(guint8);
1434 /* Read names table */
1435 available = tvb_reported_length_remaining(tvb, offset);
1436 if (available < sizeof(guint16)) {
1437 needed = (gint) (sizeof(guint16) - available);
1440 guint16 msg_names_count = tvb_get_ntohs(tvb, offset);
1443 offset += sizeof(guint16);
1445 for (each_name = 0; each_name < msg_names_count; each_name++) {
1448 available = tvb_reported_length_remaining(tvb, offset);
1449 if (available < sizeof(name_len)) {
1450 needed = (gint) (sizeof(name_len) - available);
1454 name_len = tvb_get_ntohs(tvb, offset);
1456 available = tvb_reported_length_remaining(tvb, offset + sizeof(name_len));
1457 if (available < name_len) {
1458 needed = (gint) (name_len - available);
1462 offset += sizeof(name_len) + name_len;
1466 /* parse element count */
1467 available = tvb_reported_length_remaining(tvb, offset);
1468 if (available < sizeof(guint16)) {
1469 needed = (gint) (sizeof(guint16) - available);
1472 guint16 elem_count = tvb_get_ntohs(tvb, offset);
1475 offset += sizeof(guint16);
1477 /* parse elements */
1479 for (each_elem = 0; each_elem < elem_count; each_elem++) {
1480 tvbuff_t *jxta_message_element_tvb = tvb_new_subset(tvb, offset, -1, -1);
1483 if(JXTA_MSG_VERSION_1 == message_version) {
1484 processed = dissect_jxta_message_element_1(jxta_message_element_tvb, pinfo, NULL, 0, NULL);
1485 } else if(JXTA_MSG_VERSION_2 == message_version) {
1486 processed = dissect_jxta_message_element_2(jxta_message_element_tvb, pinfo, NULL, 0, NULL);
1488 /* Sort of a lie, we say that we don't recognize it at all. */
1492 if (processed < 0) {
1493 needed = -processed;
1497 if (0 == processed) {
1498 /* XXX bondolo Not really clear what we should do! */
1499 g_warning( "Failure processing message element #%d of %d of frame %d", each_elem, elem_count, pinfo->fd->num );
1503 offset += processed;
1510 if ((needed > 0) && gDESEGMENT && pinfo->can_desegment) {
1511 pinfo->desegment_offset = 0;
1512 pinfo->desegment_len = needed;
1516 if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
1517 col_set_str(pinfo->cinfo, COL_PROTOCOL, "JXTA");
1520 if (check_col(pinfo->cinfo, COL_INFO)) {
1521 gchar src_addr[MAX_ADDR_STR_LEN];
1522 gchar dst_addr[MAX_ADDR_STR_LEN];
1524 address_to_str_buf(&pinfo->src, src_addr, sizeof src_addr);
1525 address_to_str_buf(&pinfo->dst, dst_addr, sizeof dst_addr);
1527 /* append the port if appropriate */
1528 if (PT_NONE != pinfo->ptype) {
1529 size_t len = strlen(src_addr);
1530 src_addr[len] = ':';
1531 g_snprintf(&src_addr[len + 1], 256 - len - 1, "%d", pinfo->srcport);
1533 len = strlen(dst_addr);
1534 dst_addr[len] = ':';
1535 g_snprintf(&dst_addr[len + 1], 256 - len - 1, "%d", pinfo->destport);
1538 col_add_fstr(pinfo->cinfo, COL_INFO, "Message, %s -> %s", src_addr, dst_addr);
1540 col_set_writable(pinfo->cinfo, FALSE);
1544 guint tree_offset = 0;
1545 proto_item *jxta_msg_tree_item = NULL;
1546 proto_tree *jxta_msg_tree = NULL;
1547 guint8 message_version;
1548 const gchar **names_table = NULL;
1549 guint16 msg_names_count;
1553 gchar src_addr[256];
1554 gchar dst_addr[256];
1555 proto_item *tree_item;
1557 address_to_str_buf(&pinfo->src, src_addr, sizeof src_addr);
1558 address_to_str_buf(&pinfo->dst, dst_addr, sizeof dst_addr);
1560 if (PT_NONE != pinfo->ptype) {
1561 size_t len = strlen(src_addr);
1562 src_addr[len] = ':';
1563 g_snprintf(&src_addr[len + 1], 256 - len - 1, "%d", pinfo->srcport);
1565 len = strlen(dst_addr);
1566 dst_addr[len] = ':';
1567 g_snprintf(&dst_addr[len + 1], 256 - len - 1, "%d", pinfo->destport);
1570 jxta_msg_tree_item = proto_tree_add_protocol_format(tree, proto_message_jxta, tvb, tree_offset, -1,
1571 "JXTA Message, %s -> %s", src_addr, dst_addr);
1573 jxta_msg_tree = proto_item_add_subtree(jxta_msg_tree_item, ett_jxta_msg);
1575 proto_tree_add_item(jxta_msg_tree, hf_jxta_message_sig, tvb, tree_offset, sizeof(JXTA_MSG_SIG), FALSE);
1576 tree_offset += sizeof(JXTA_MSG_SIG);
1578 tree_item = proto_tree_add_string(jxta_msg_tree, hf_jxta_message_src, tvb, 0, 0, src_addr);
1579 PROTO_ITEM_SET_GENERATED(tree_item);
1581 tree_item = proto_tree_add_string(jxta_msg_tree, hf_jxta_message_address, tvb, 0, 0, src_addr);
1582 PROTO_ITEM_SET_HIDDEN(tree_item);
1583 PROTO_ITEM_SET_GENERATED(tree_item);
1585 tree_item = proto_tree_add_string(jxta_msg_tree, hf_jxta_message_dst, tvb, 0, 0, dst_addr);
1586 PROTO_ITEM_SET_GENERATED(tree_item);
1588 tree_item = proto_tree_add_string(jxta_msg_tree, hf_jxta_message_address, tvb, 0, 0, dst_addr);
1589 PROTO_ITEM_SET_HIDDEN(tree_item);
1590 PROTO_ITEM_SET_GENERATED(tree_item);
1592 message_version = tvb_get_guint8(tvb, tree_offset);
1593 proto_tree_add_uint(jxta_msg_tree, hf_jxta_message_version, tvb, tree_offset, sizeof(guint8), message_version);
1594 tree_offset += sizeof(guint8);
1596 if( message_version > 0 ) {
1597 guint8 flags = tvb_get_guint8(tvb, tree_offset);
1598 proto_item *flags_ti = proto_tree_add_uint(jxta_msg_tree, hf_jxta_message_flags, tvb, tree_offset, sizeof(guint8), flags);
1599 proto_tree *jxta_msg_flags_tree = proto_item_add_subtree(flags_ti, ett_jxta_msg_flags);
1600 proto_tree_add_boolean(jxta_msg_flags_tree, hf_jxta_message_flag_utf16be, tvb, tree_offset, 1, flags);
1601 proto_tree_add_boolean(jxta_msg_flags_tree, hf_jxta_message_flag_ucs32be, tvb, tree_offset, 1, flags);
1602 tree_offset += sizeof(guint8);
1605 msg_names_count = tvb_get_ntohs(tvb, tree_offset);
1606 proto_tree_add_uint(jxta_msg_tree, hf_jxta_message_names_count, tvb, tree_offset, sizeof(guint16), msg_names_count);
1607 tree_offset += sizeof(guint16);
1609 names_table = ep_alloc((msg_names_count + 2) * sizeof(const gchar *));
1610 names_table[0] = "";
1611 names_table[1] = "jxta";
1614 for (each_name = 0; each_name < msg_names_count; each_name++) {
1615 guint16 name_len = tvb_get_ntohs(tvb, tree_offset);
1617 names_table[2 + each_name] = tvb_get_ephemeral_string(tvb, tree_offset + sizeof(name_len), name_len);
1618 proto_tree_add_item(jxta_msg_tree, hf_jxta_message_names_name, tvb, tree_offset, sizeof(name_len), FALSE);
1619 tree_offset += sizeof(name_len) + name_len;
1622 /* parse element count */
1623 elem_count = tvb_get_ntohs(tvb, tree_offset);
1624 proto_tree_add_item(jxta_msg_tree, hf_jxta_message_element_count, tvb, tree_offset, sizeof(guint16), FALSE);
1625 tree_offset += sizeof(guint16);
1627 /* parse elements */
1628 for (each_elem = 0; each_elem < elem_count; each_elem++) {
1629 tvbuff_t *jxta_message_element_tvb = tvb_new_subset(tvb, tree_offset, -1, -1);
1631 if(JXTA_MSG_VERSION_1 == message_version) {
1633 dissect_jxta_message_element_1(jxta_message_element_tvb, pinfo, jxta_msg_tree, msg_names_count + 2, names_table);
1634 } else if(JXTA_MSG_VERSION_2 == message_version) {
1636 dissect_jxta_message_element_2(jxta_message_element_tvb, pinfo, jxta_msg_tree, msg_names_count + 2, names_table);
1638 /* Sort of a lie, we say that we don't recognize it at all. */
1643 proto_item_set_end(jxta_msg_tree_item, tvb, tree_offset);
1645 DISSECTOR_ASSERT(tree_offset == offset);
1648 if ((offset > 0) && (AT_URI == pinfo->src.type) && (AT_URI == pinfo->dst.type)) {
1649 jxta_tap_header *tap_header = se_alloc(sizeof(jxta_tap_header));
1651 tap_header->src_address = pinfo->src;
1652 tap_header->dest_address = pinfo->dst;
1653 tap_header->size = offset;
1655 tap_queue_packet(jxta_tap, pinfo, tap_header);
1662 * Dissect a tvbuff containing a JXTA Message Element (Version 1).
1664 * @param tvb The buffer to dissect.
1665 * @param pinfo Packet Info.
1666 * @param tree The protocol tree.
1667 * @return Number of bytes from the tvbuff_t which were processed, 0 (zero) if
1668 * the packet was not recognized as a JXTA packet and negative if the
1669 * dissector needs more bytes in order to process a PDU.
1671 static int dissect_jxta_message_element_1(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, guint ns_count,
1672 const gchar ** names_table)
1679 /* First pass. Make sure all of the bytes we need are available */
1682 /* signature field */
1683 available = tvb_reported_length_remaining(tvb, offset);
1684 if (available < sizeof(JXTA_MSGELEM_SIG)) {
1685 needed = (gint) (sizeof(JXTA_MSGELEM_SIG) - available);
1688 if (tvb_memeql(tvb, offset, JXTA_MSGELEM_SIG, sizeof(JXTA_MSGELEM_SIG)) != 0) {
1689 /* It is not one of ours */
1693 offset += sizeof(JXTA_MSGELEM_SIG);
1695 /* namespace id field */
1696 available = tvb_reported_length_remaining(tvb, offset);
1697 if (available < sizeof(guint8)) {
1698 needed = (gint) (sizeof(guint8) - available);
1702 offset += sizeof(guint8);
1705 available = tvb_reported_length_remaining(tvb, offset);
1706 if (available < sizeof(guint8)) {
1707 needed = (gint) (sizeof(guint8) - available);
1710 flags = tvb_get_guint8(tvb, offset);
1711 offset += sizeof(guint8);
1715 available = tvb_reported_length_remaining(tvb, offset);
1716 if (available < sizeof(guint16)) {
1717 needed = (gint) (sizeof(guint16) - available);
1720 guint16 name_len = tvb_get_ntohs(tvb, offset);
1721 offset += sizeof(guint16);
1723 available = tvb_reported_length_remaining(tvb, offset);
1724 if (available < name_len) {
1725 needed = (gint) (name_len - available);
1733 if ((flags & JXTAMSG1_ELMFLAG_TYPE) != 0) {
1736 available = tvb_reported_length_remaining(tvb, offset);
1737 if (available < sizeof(guint16)) {
1738 needed = (gint) (sizeof(guint16) - available);
1742 type_len = tvb_get_ntohs(tvb, offset);
1743 offset += sizeof(guint16);
1745 available = tvb_reported_length_remaining(tvb, offset);
1746 if (available < type_len) {
1747 needed = (gint) (type_len - available);
1754 /* encoding field */
1755 if ((flags & JXTAMSG1_ELMFLAG_ENCODING) != 0) {
1756 guint16 encoding_len;
1758 available = tvb_reported_length_remaining(tvb, offset);
1759 if (available < sizeof(guint16)) {
1760 needed = (gint) (sizeof(guint16) - available);
1764 encoding_len = tvb_get_ntohs(tvb, offset);
1765 offset += sizeof(guint16);
1767 available = tvb_reported_length_remaining(tvb, offset);
1768 if (available < encoding_len) {
1769 needed = (gint) (encoding_len - available);
1773 offset += encoding_len;
1777 available = tvb_reported_length_remaining(tvb, offset);
1778 if (available < sizeof(guint16)) {
1779 needed = (gint) (sizeof(guint16) - available);
1782 guint32 content_len = tvb_get_ntohl(tvb, offset);
1783 offset += sizeof(guint32);
1785 available = tvb_reported_length_remaining(tvb, offset);
1786 if (available < content_len) {
1787 needed = (gint) (content_len - available);
1791 offset += content_len;
1794 /* signature element field */
1795 if ((flags & JXTAMSG1_ELMFLAG_SIGNATURE) != 0) {
1796 tvbuff_t *jxta_signature_element_tvb;
1799 jxta_signature_element_tvb = tvb_new_subset(tvb, offset, -1, -1);
1801 processed = dissect_jxta_message_element_1(jxta_signature_element_tvb, pinfo, NULL, 0, NULL);
1803 if (processed == 0) {
1807 if (processed < 0) {
1808 needed = -processed;
1812 offset += processed;
1818 if ((needed > 0) && gDESEGMENT && pinfo->can_desegment) {
1819 pinfo->desegment_offset = 0;
1820 pinfo->desegment_len = needed;
1824 /* Second (optional) pass : build the proto tree */
1826 guint tree_offset = 0;
1827 proto_item *jxta_elem_tree_item = proto_tree_add_item(tree, hf_jxta_element, tvb, tree_offset, -1, FALSE);
1828 proto_tree *jxta_elem_tree = proto_item_add_subtree(jxta_elem_tree_item, ett_jxta_elem);
1830 proto_item *namespace_ti;
1832 proto_item *flags_ti;
1833 proto_tree *jxta_elem_flags_tree = NULL;
1834 guint32 content_len;
1835 gchar *mediatype = NULL;
1836 gboolean media_type_recognized = FALSE;
1837 tvbuff_t *element_content_tvb;
1838 proto_item * jxta_elem_length_item = NULL;
1840 proto_tree_add_item(jxta_elem_tree, hf_jxta_element_sig, tvb, tree_offset, sizeof(JXTA_MSGELEM_SIG), FALSE);
1841 tree_offset += sizeof(JXTA_MSGELEM_SIG);
1843 namespaceID = tvb_get_guint8(tvb, tree_offset);
1845 proto_tree_add_uint(jxta_elem_tree, hf_jxta_element1_namespaceid, tvb, tree_offset, sizeof(guint8), namespaceID);
1846 if (namespaceID < ns_count) {
1847 proto_item_append_text(namespace_ti, " (%s)", names_table[namespaceID]);
1849 proto_item_append_text(namespace_ti, " * BAD *");
1851 tree_offset += sizeof(guint8);
1853 flags = tvb_get_guint8(tvb, tree_offset);
1854 flags_ti = proto_tree_add_uint(jxta_elem_tree, hf_jxta_element_flags, tvb, tree_offset, sizeof(guint8), flags);
1855 jxta_elem_flags_tree = proto_item_add_subtree(flags_ti, ett_jxta_elem_1_flags);
1856 proto_tree_add_boolean(jxta_elem_flags_tree, hf_jxta_element1_flag_hasType, tvb, tree_offset, 1, flags);
1857 proto_tree_add_boolean(jxta_elem_flags_tree, hf_jxta_element1_flag_hasEncoding, tvb, tree_offset, 1, flags);
1858 proto_tree_add_boolean(jxta_elem_flags_tree, hf_jxta_element1_flag_hasSignature, tvb, tree_offset, 1, flags);
1859 tree_offset += sizeof(guint8);
1861 name_len = tvb_get_ntohs(tvb, tree_offset);
1862 proto_item_append_text(jxta_elem_tree_item, " \"%s\"", tvb_format_text(tvb, tree_offset + sizeof(guint16), name_len));
1863 proto_tree_add_item(jxta_elem_tree, hf_jxta_element_name, tvb, tree_offset, sizeof(guint16), FALSE);
1864 tree_offset += sizeof(guint16) + name_len;
1867 if ((flags & JXTAMSG1_ELMFLAG_TYPE) != 0) {
1868 guint16 type_len = tvb_get_ntohs(tvb, tree_offset);
1869 proto_tree_add_item(jxta_elem_tree, hf_jxta_element_type, tvb, tree_offset, sizeof(guint16), FALSE);
1870 tree_offset += sizeof(guint16);
1872 mediatype = tvb_get_ephemeral_string(tvb, tree_offset, type_len);
1874 /* remove any params */
1876 gchar *parms_at = strchr(mediatype, ';');
1878 if (NULL != parms_at) {
1883 /* force to lower case */
1884 #if GLIB_MAJOR_VERSION < 2
1885 g_strdown(mediatype);
1888 gchar *mediatype_lowercase = g_ascii_strdown(mediatype, -1);
1889 mediatype = mediatype_lowercase;
1892 tree_offset += type_len;
1895 /* process encoding */
1896 if ((flags & JXTAMSG1_ELMFLAG_ENCODING) != 0) {
1897 guint16 encoding_len = tvb_get_ntohs(tvb, tree_offset);
1898 proto_tree_add_item(jxta_elem_tree, hf_jxta_element_encoding, tvb, tree_offset, sizeof(guint16), FALSE);
1899 tree_offset += sizeof(guint16) + encoding_len;
1903 content_len = tvb_get_ntohl(tvb, tree_offset);
1904 jxta_elem_length_item = proto_tree_add_item(jxta_elem_tree, hf_jxta_element_content_len, tvb, tree_offset, sizeof(guint32), FALSE);
1905 tree_offset += sizeof(guint32);
1907 element_content_tvb = tvb_new_subset(tvb, tree_offset, content_len, content_len);
1910 if (0 == strcmp("application/x-jxta-tls-block", mediatype)) {
1911 /* If we recognize it as a TLS packet then we shuffle it off to ssl dissector. */
1912 dissector_handle_t ssl_handle = find_dissector("ssl");
1913 if (NULL != ssl_handle) {
1914 int processed = call_dissector(ssl_handle, element_content_tvb, pinfo, jxta_elem_tree);
1915 media_type_recognized = processed != 0;
1917 } else if (0 == strcmp("application/gzip", mediatype)) {
1918 tvbuff_t *uncomp_tvb = tvb_uncompress(element_content_tvb, 0, tvb_length(element_content_tvb));
1920 if( NULL != uncomp_tvb ) {
1921 proto_item_append_text( jxta_elem_length_item, " -> (%u uncompressed)", tvb_length(uncomp_tvb) );
1923 tvb_set_child_real_data_tvbuff(element_content_tvb, uncomp_tvb);
1924 add_new_data_source(pinfo, uncomp_tvb, "Uncompressed Element Content");
1926 /* XXX bondolo 20060201 Force XML for uncompressed data. */
1927 media_type_recognized = dissector_try_string(media_type_dissector_table,
1928 "text/xml", uncomp_tvb, pinfo, jxta_elem_tree);
1931 media_type_recognized = dissector_try_string(media_type_dissector_table,
1932 mediatype, element_content_tvb, pinfo, jxta_elem_tree);
1937 if (!media_type_recognized) {
1938 /* display it as raw data */
1939 call_dissector(data_handle, element_content_tvb, pinfo, jxta_elem_tree);
1941 tree_offset += content_len;
1943 /* process the signature element */
1944 if ((flags & JXTAMSG1_ELMFLAG_SIGNATURE) != 0) {
1945 tvbuff_t *jxta_message_element_tvb = tvb_new_subset(tvb, tree_offset, -1, -1);
1947 tree_offset += dissect_jxta_message_element_1(jxta_message_element_tvb, pinfo, jxta_elem_tree, ns_count, names_table);
1950 proto_item_set_end(jxta_elem_tree_item, tvb, tree_offset);
1952 DISSECTOR_ASSERT(tree_offset == offset);
1959 * Dissect a tvbuff containing a JXTA Message Element (Version 2).
1961 * WARNING : The Version 2 Message Format is still under development and may change without notice (breaking this dissector).
1963 * @param tvb The buffer to dissect.
1964 * @param pinfo Packet Info.
1965 * @param tree The protocol tree.
1966 * @param names_count The number of elements in the names table.
1967 * @param names The table of names.
1968 * @return Number of bytes from the tvbuff_t which were processed, 0 (zero) if
1969 * the packet was not recognized as a JXTA packet and negative if the
1970 * dissector needs more bytes in order to process a PDU.
1972 static int dissect_jxta_message_element_2(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, guint names_count,
1973 const gchar ** names_table)
1980 /* First pass. Make sure all of the bytes we need are available */
1983 /* signature field */
1984 available = tvb_reported_length_remaining(tvb, offset);
1985 if (available < sizeof(JXTA_MSGELEM_SIG)) {
1986 needed = (gint) (sizeof(JXTA_MSGELEM_SIG) - available);
1989 if (tvb_memeql(tvb, offset, JXTA_MSGELEM_SIG, sizeof(JXTA_MSGELEM_SIG)) != 0) {
1990 /* It is not one of ours */
1994 offset += sizeof(JXTA_MSGELEM_SIG);
1997 available = tvb_reported_length_remaining(tvb, offset);
1998 if (available < sizeof(guint8)) {
1999 needed = (gint) (sizeof(guint8) - available);
2002 flags = tvb_get_guint8(tvb, offset);
2003 offset += sizeof(guint8);
2006 /* namespace id field */
2007 available = tvb_reported_length_remaining(tvb, offset);
2008 if (available < sizeof(guint16)) {
2009 needed = (gint) (sizeof(guint16) - available);
2013 offset += sizeof(guint16);
2016 if ((flags & JXTAMSG2_ELMFLAG_NAME_LITERAL) == 0) {
2017 available = tvb_reported_length_remaining(tvb, offset);
2018 if (available < sizeof(guint16)) {
2019 needed = (gint) (sizeof(guint16) - available);
2023 offset += sizeof(guint16);
2025 /* literal name field */
2026 available = tvb_reported_length_remaining(tvb, offset);
2027 if (available < sizeof(guint16)) {
2028 needed = (gint) (sizeof(guint16) - available);
2031 guint16 name_len = tvb_get_ntohs(tvb, offset);
2032 offset += sizeof(guint16);
2034 available = tvb_reported_length_remaining(tvb, offset);
2035 if (available < name_len) {
2036 needed = (gint) (name_len - available);
2045 if ((flags & JXTAMSG2_ELMFLAG_TYPE) != 0) {
2046 available = tvb_reported_length_remaining(tvb, offset);
2047 if (available < sizeof(guint16)) {
2048 needed = (gint) (sizeof(guint16) - available);
2052 offset += sizeof(guint16);
2055 /* encoding field */
2056 if ((flags & JXTAMSG2_ELMFLAG_ENCODINGS) != 0) {
2057 available = tvb_reported_length_remaining(tvb, offset);
2058 if (available < sizeof(guint16)) {
2059 needed = (gint) (sizeof(guint16) - available);
2063 offset += sizeof(guint16);
2068 if ((flags & JXTAMSG2_ELMFLAG_UINT64_LENS) != 0) {
2069 available = tvb_reported_length_remaining(tvb, offset);
2070 if (available < sizeof(guint64)) {
2071 needed = (gint) (sizeof(guint64) - available);
2074 guint64 content_len = tvb_get_ntoh64(tvb, offset);
2075 offset += sizeof(guint64);
2077 available = tvb_reported_length_remaining(tvb, offset);
2078 if (available < content_len) {
2079 needed = (gint) (content_len - available);
2083 offset += (guint) content_len;
2086 available = tvb_reported_length_remaining(tvb, offset);
2087 if (available < sizeof(guint32)) {
2088 needed = (gint) (sizeof(guint32) - available);
2091 guint64 content_len = tvb_get_ntohl(tvb, offset);
2092 offset += sizeof(guint32);
2094 available = tvb_reported_length_remaining(tvb, offset);
2095 if (available < content_len) {
2096 needed = (gint) (content_len - available);
2100 offset += (guint) content_len;
2104 /* signature element field */
2105 if ((flags & JXTAMSG2_ELMFLAG_SIGNATURE) != 0) {
2106 tvbuff_t *jxta_signature_element_tvb;
2109 jxta_signature_element_tvb = tvb_new_subset(tvb, offset, -1, -1);
2111 processed = dissect_jxta_message_element_2(jxta_signature_element_tvb, pinfo, NULL, 0, NULL);
2113 if (processed == 0) {
2117 if (processed < 0) {
2118 needed = -processed;
2122 offset += processed;
2128 if ((needed > 0) && gDESEGMENT && pinfo->can_desegment) {
2129 pinfo->desegment_offset = 0;
2130 pinfo->desegment_len = needed;
2134 /* Second (optional) pass : build the proto tree */
2136 guint tree_offset = 0;
2137 proto_item *jxta_elem_tree_item = proto_tree_add_item(tree, hf_jxta_element, tvb, tree_offset, -1, FALSE);
2138 proto_tree *jxta_elem_tree = proto_item_add_subtree(jxta_elem_tree_item, ett_jxta_elem);
2139 proto_item *flags_ti;
2140 proto_tree *jxta_elem_flags_tree = NULL;
2141 guint16 namespaceID;
2142 proto_item *namespace_ti;
2144 proto_item *name_ti;
2145 guint64 content_len;
2146 gchar *mediatype = NULL;
2147 gboolean media_type_recognized = FALSE;
2148 tvbuff_t *element_content_tvb;
2149 proto_item * jxta_elem_length_item = NULL;
2151 proto_tree_add_item(jxta_elem_tree, hf_jxta_element_sig, tvb, tree_offset, sizeof(JXTA_MSGELEM_SIG), FALSE);
2152 tree_offset += sizeof(JXTA_MSGELEM_SIG);
2154 flags = tvb_get_guint8(tvb, tree_offset);
2155 flags_ti = proto_tree_add_uint(jxta_elem_tree, hf_jxta_element_flags, tvb, tree_offset, sizeof(guint8), flags);
2156 jxta_elem_flags_tree = proto_item_add_subtree(flags_ti, ett_jxta_elem_2_flags);
2157 proto_tree_add_boolean(jxta_elem_flags_tree, hf_jxta_element2_flag_64bitlens, tvb, tree_offset, 1, flags);
2158 proto_tree_add_boolean(jxta_elem_flags_tree, hf_jxta_element2_flag_nameLiteral, tvb, tree_offset, 1, flags);
2159 proto_tree_add_boolean(jxta_elem_flags_tree, hf_jxta_element2_flag_hasType, tvb, tree_offset, 1, flags);
2160 proto_tree_add_boolean(jxta_elem_flags_tree, hf_jxta_element2_flag_hasSignature, tvb, tree_offset, 1, flags);
2161 proto_tree_add_boolean(jxta_elem_flags_tree, hf_jxta_element2_flag_hasEncoding, tvb, tree_offset, 1, flags);
2162 proto_tree_add_boolean(jxta_elem_flags_tree, hf_jxta_element2_flag_sigOfEncoded, tvb, tree_offset, 1, flags);
2163 tree_offset += sizeof(guint8);
2166 namespaceID = tvb_get_ntohs(tvb, tree_offset);
2168 proto_tree_add_uint(jxta_elem_tree, hf_jxta_element2_namespaceid, tvb, tree_offset, sizeof(guint16), namespaceID);
2169 if (namespaceID < names_count) {
2170 proto_item_append_text(namespace_ti, " (%s)", names_table[namespaceID]);
2172 proto_item_append_text(namespace_ti, " * BAD *");
2174 tree_offset += sizeof(guint16);
2177 if ((flags & JXTAMSG2_ELMFLAG_NAME_LITERAL) == 0) {
2178 nameID = tvb_get_ntohs(tvb, tree_offset);
2180 proto_tree_add_uint(jxta_elem_tree, hf_jxta_element2_nameid, tvb, tree_offset, sizeof(guint16), nameID);
2181 if (namespaceID < names_count) {
2182 proto_item_append_text(name_ti, " (%s)", names_table[nameID]);
2184 proto_item_append_text(name_ti, " * BAD *");
2186 tree_offset += sizeof(guint16);
2189 guint16 name_len = tvb_get_ntohs(tvb, tree_offset);
2190 proto_item_append_text(jxta_elem_tree_item, " \"%s\"", tvb_format_text(tvb, tree_offset + sizeof(guint16), name_len));
2191 proto_tree_add_item(jxta_elem_tree, hf_jxta_element_name, tvb, tree_offset, sizeof(guint16), FALSE);
2192 tree_offset += sizeof(guint16) + name_len;
2196 if ((flags & JXTAMSG2_ELMFLAG_TYPE) != 0) {
2197 guint16 mimeID = tvb_get_ntohs(tvb, tree_offset);
2198 proto_item *mime_ti =
2199 proto_tree_add_uint(jxta_elem_tree, hf_jxta_element2_mimeid, tvb, tree_offset, sizeof(guint16), mimeID);
2201 if (mimeID < names_count) {
2202 proto_item_append_text(mime_ti, " (%s)", names_table[mimeID]);
2203 mediatype = strdup( names_table[mimeID] );
2205 /* remove any params */
2207 gchar *parms_at = strchr(mediatype, ';');
2209 if (NULL != parms_at) {
2214 /* force to lower case */
2215 #if GLIB_MAJOR_VERSION < 2
2216 g_strdown(mediatype);
2219 gchar *mediatype_lowercase = g_ascii_strdown(mediatype, -1);
2220 mediatype = mediatype_lowercase;
2224 proto_item_append_text(mime_ti, " * BAD *");
2227 tree_offset += sizeof(guint16);
2229 mediatype = strdup( "application/octect-stream" );
2232 /* process encoding */
2233 if ((flags & JXTAMSG2_ELMFLAG_ENCODINGS) != 0) {
2234 guint16 encodingID = tvb_get_ntohs(tvb, tree_offset);
2235 proto_item *encoding_ti =
2236 proto_tree_add_uint(jxta_elem_tree, hf_jxta_element2_encodingid, tvb, tree_offset, sizeof(guint16), encodingID);
2238 if (encodingID < names_count) {
2239 proto_item_append_text(encoding_ti, " (%s)", names_table[encodingID]);
2241 proto_item_append_text(encoding_ti, " * BAD *");
2244 tree_offset += sizeof(guint16);
2248 if ((flags & JXTAMSG2_ELMFLAG_UINT64_LENS) != 0) {
2249 content_len = tvb_get_ntoh64(tvb, tree_offset);
2250 jxta_elem_length_item = proto_tree_add_item(jxta_elem_tree, hf_jxta_element_content_len64, tvb, tree_offset, sizeof(guint64), FALSE);
2251 tree_offset += sizeof(guint64);
2253 content_len = tvb_get_ntohl(tvb, tree_offset);
2254 jxta_elem_length_item = proto_tree_add_item(jxta_elem_tree, hf_jxta_element_content_len, tvb, tree_offset, sizeof(guint32), FALSE);
2255 tree_offset += sizeof(guint32);
2259 element_content_tvb = tvb_new_subset(tvb, tree_offset, (gint)content_len, (gint)content_len);
2262 if (0 == strcmp("application/x-jxta-tls-block", mediatype)) {
2263 /* If we recognize it as a TLS packet then we shuffle it off to ssl dissector. */
2264 dissector_handle_t ssl_handle = find_dissector("ssl");
2265 if (NULL != ssl_handle) {
2266 int processed = call_dissector(ssl_handle, element_content_tvb, pinfo, jxta_elem_tree);
2267 media_type_recognized = processed != 0;
2269 } else if (0 == strcmp("application/gzip", mediatype)) {
2270 tvbuff_t *uncomp_tvb = tvb_uncompress(element_content_tvb, 0, tvb_length(element_content_tvb));
2272 if( NULL != uncomp_tvb ) {
2273 proto_item_append_text( jxta_elem_length_item, " -> (%u uncompressed)", tvb_length(uncomp_tvb) );
2275 tvb_set_child_real_data_tvbuff(element_content_tvb, uncomp_tvb);
2276 add_new_data_source(pinfo, uncomp_tvb, "Uncompressed Element Content");
2278 /* XXX bondolo 20060201 Force XML for uncompressed data. */
2279 media_type_recognized = dissector_try_string(media_type_dissector_table,
2280 "text/xml", uncomp_tvb, pinfo, jxta_elem_tree);
2283 media_type_recognized = dissector_try_string(media_type_dissector_table,
2284 mediatype, element_content_tvb, pinfo, jxta_elem_tree);
2289 if (!media_type_recognized) {
2290 /* display it as raw data */
2291 call_dissector(data_handle, element_content_tvb, pinfo, jxta_elem_tree);
2293 tree_offset += (guint) content_len;
2295 /* process the signature element */
2296 if ((flags & JXTAMSG2_ELMFLAG_SIGNATURE) != 0) {
2297 tvbuff_t *jxta_message_element_tvb = tvb_new_subset(tvb, tree_offset, -1, -1);
2299 tree_offset += dissect_jxta_message_element_1(jxta_message_element_tvb, pinfo, jxta_elem_tree, names_count, names_table);
2302 proto_item_set_end(jxta_elem_tree_item, tvb, tree_offset);
2304 DISSECTOR_ASSERT(tree_offset == offset);
2311 * Register jxta protocol and jxta message protocol, header fields, subtree types, preferences.
2313 void proto_register_jxta(void)
2315 module_t *jxta_module;
2317 media_type_dissector_table = find_dissector_table("media_type");
2319 data_handle = find_dissector("data");
2321 proto_jxta = proto_register_protocol("JXTA P2P", "JXTA", "jxta");
2323 jxta_tap = register_tap("jxta");
2325 /* The JXTA Binary Message Wire Format : Registered and dissected by MIME type */
2326 proto_message_jxta = proto_register_protocol("JXTA Message", "JXTA Message", "jxta.message");
2328 message_jxta_handle = new_create_dissector_handle(dissect_jxta_message, proto_message_jxta);
2330 dissector_add_string("media_type", "application/x-jxta-msg", message_jxta_handle);
2332 /* Register header fields */
2333 proto_register_field_array(proto_jxta, hf, array_length(hf));
2335 /* Register JXTA Sub-tree */
2336 proto_register_subtree_array(ett, array_length(ett));
2338 /* Register preferences */
2339 /* register re-init routine */
2340 jxta_module = prefs_register_protocol(proto_jxta, proto_reg_handoff_jxta);
2342 prefs_register_bool_preference(jxta_module, "desegment",
2343 "Reassemble JXTA messages spanning multiple UDP/TCP/HTTP segments",
2344 "Whether the JXTA dissector should reassemble messages spanning multiple UDP/HTTP/TCP segments."
2345 " To use this option you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings "
2346 " and enable \"Reassemble fragmented IP datagrams\" in the IP protocol settings.",
2349 prefs_register_bool_preference(jxta_module, "udp.heuristic", "Try to discover JXTA in UDP datagrams",
2350 "Enable to inspect UDP datagrams for JXTA messages.", &gUDP_HEUR);
2352 prefs_register_bool_preference(jxta_module, "tcp.heuristic", "Try to discover JXTA in TCP connections",
2353 "Enable to inspect TCP connections for JXTA conversations.", &gTCP_HEUR);
2355 prefs_register_bool_preference(jxta_module, "sctp.heuristic", "Try to discover JXTA in SCTP connections",
2356 "Enable to inspect SCTP connections for JXTA conversations.", &gSCTP_HEUR);
2360 * Update registrations in response to
2362 void proto_reg_handoff_jxta(void)
2364 static gboolean init_done = FALSE;
2367 /* XXX 20051004 bondolo We could dynamically add dissectors based upon prefs. */
2368 new_register_dissector("jxta.udp", dissect_jxta_udp, proto_jxta);
2369 heur_dissector_add("udp", dissect_jxta_UDP_heur, proto_jxta);
2371 new_register_dissector("jxta.stream", dissect_jxta_stream, proto_jxta);
2372 stream_jxta_handle = find_dissector("jxta.stream");
2373 heur_dissector_add("tcp", dissect_jxta_TCP_heur, proto_jxta);
2374 heur_dissector_add("sctp", dissect_jxta_SCTP_heur, proto_jxta);