Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-jxta.c
blobb6aa35e26eac4cfffea4e00bf98d83961dab6a85
1 /* packet-jxta.c
3 * Routines for JXTA packet dissection
4 * JXTA specification from https://jxta-spec.dev.java.net (now at https://github.com/chaupal/jxta-spec ?)
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
13 * Wireshark - Network traffic analyzer
14 * By Gerald Combs <gerald@wireshark.org>
15 * Copyright 2000 Gerald Combs
17 * SPDX-License-Identifier: GPL-2.0-or-later
20 #include "config.h"
22 #define WS_LOG_DOMAIN "jxta"
24 #include <epan/packet.h>
25 #include <epan/conversation.h>
26 #include <epan/conversation_table.h>
27 #include <epan/prefs.h>
28 #include <epan/to_str.h>
29 #include <epan/address_types.h>
30 #include <epan/expert.h>
31 #include <epan/tfs.h>
32 #include <wsutil/array.h>
33 #include <wsutil/str_util.h>
35 #include "packet-jxta.h"
36 #include "packet-media-type.h"
38 void proto_register_jxta(void);
39 void proto_reg_handoff_jxta(void);
41 static const char JXTA_UDP_SIG[] = { 'J', 'X', 'T', 'A' };
42 static const char JXTA_MSG_SIG[] = { 'j', 'x', 'm', 'g' };
43 static const char JXTA_MSGELEM_SIG[] = { 'j', 'x', 'e', 'l' };
45 static const char JXTA_WELCOME_MSG_SIG[] = { 'J', 'X', 'T', 'A', 'H', 'E', 'L', 'L', 'O', ' ' };
47 static const char* JXTA_WELCOME_MSG_VERSION_1_1 = "1.1";
48 static const char* JXTA_WELCOME_MSG_VERSION_3_0 = "3.0";
50 static const int JXTA_MSG_VERSION_1;
51 static const int JXTA_MSG_VERSION_2 = 1;
53 static const int JXTAMSG1_ELMFLAG_TYPE = 1 << 0;
54 static const int JXTAMSG1_ELMFLAG_ENCODING = 1 << 1;
55 static const int JXTAMSG1_ELMFLAG_SIGNATURE = 1 << 2;
57 static const int JXTAMSG2_ELMFLAG_UINT64_LENS = 1 << 0;
58 static const int JXTAMSG2_ELMFLAG_NAME_LITERAL = 1 << 1;
59 static const int JXTAMSG2_ELMFLAG_TYPE = 1 << 2;
60 static const int JXTAMSG2_ELMFLAG_SIGNATURE = 1 << 3;
61 static const int JXTAMSG2_ELMFLAG_ENCODINGS = 1 << 4;
63 static int proto_jxta;
64 static int proto_message_jxta;
65 static int jxta_tap;
67 static dissector_table_t media_type_dissector_table;
68 static dissector_handle_t media_handle;
69 static dissector_handle_t stream_jxta_handle;
70 static dissector_handle_t tls_handle;
72 static int hf_uri_addr;
73 static int hf_uri_src;
74 static int hf_uri_dst;
75 static int hf_jxta_udp;
76 static int hf_jxta_udpsig;
77 static int hf_jxta_welcome;
78 static int hf_jxta_welcome_initiator;
79 static int hf_jxta_welcome_sig;
80 static int hf_jxta_welcome_destAddr;
81 static int hf_jxta_welcome_pubAddr;
82 static int hf_jxta_welcome_peerid;
83 static int hf_jxta_welcome_noProp;
84 static int hf_jxta_welcome_msgVers;
85 static int hf_jxta_welcome_variable;
86 static int hf_jxta_welcome_version;
87 static int hf_jxta_framing;
88 static int hf_jxta_framing_header;
89 static int hf_jxta_framing_header_name;
90 static int hf_jxta_framing_header_value_length;
91 static int hf_jxta_framing_header_value;
92 static int hf_jxta_message_address;
93 static int hf_jxta_message_src;
94 static int hf_jxta_message_dst;
95 static int hf_jxta_message_sig;
96 static int hf_jxta_message_version;
97 static int hf_jxta_message_flags;
98 static int hf_jxta_message_flag_utf16be;
99 static int hf_jxta_message_flag_ucs32be;
100 static int hf_jxta_message_names_count;
101 static int hf_jxta_message_names_name;
102 static int hf_jxta_message_element_count;
103 static int hf_jxta_element;
104 static int hf_jxta_element_sig;
105 static int hf_jxta_element1_namespaceid;
106 static int hf_jxta_element2_namespaceid;
107 static int hf_jxta_element2_nameid;
108 static int hf_jxta_element2_mimeid;
109 static int hf_jxta_element2_encodingid;
110 static int hf_jxta_element_flags;
111 static int hf_jxta_element1_flag_hasType;
112 static int hf_jxta_element1_flag_hasEncoding;
113 static int hf_jxta_element1_flag_hasSignature;
114 static int hf_jxta_element2_flag_64bitlens;
115 static int hf_jxta_element2_flag_nameLiteral;
116 static int hf_jxta_element2_flag_hasType;
117 static int hf_jxta_element2_flag_hasSignature;
118 static int hf_jxta_element2_flag_hasEncoding;
119 static int hf_jxta_element2_flag_sigOfEncoded;
120 static int hf_jxta_element_name;
121 static int hf_jxta_element_type;
122 static int hf_jxta_element_encoding;
123 static int hf_jxta_element_content_len;
124 static int hf_jxta_element_content_len64;
125 /* static int hf_jxta_element_content; */
128 * JXTA Protocol subtree handles
130 static int ett_jxta;
131 static int ett_jxta_welcome;
132 static int ett_jxta_udp;
133 static int ett_jxta_framing;
134 static int ett_jxta_framing_header;
135 static int ett_jxta_msg;
136 static int ett_jxta_msg_flags;
137 static int ett_jxta_elem;
138 static int ett_jxta_elem_1_flags;
139 static int ett_jxta_elem_2_flags;
141 static expert_field ei_media_too_short;
143 static int uri_address_type = -1;
146 * global preferences
148 static bool gDESEGMENT = true;
149 static bool gMSG_MEDIA = true;
151 static dissector_handle_t jxta_udp_handle;
154 * Stream Conversation data
156 struct jxta_stream_conversation_data {
157 port_type tpt_ptype;
159 address initiator_tpt_address;
160 uint32_t initiator_tpt_port;
161 uint32_t initiator_welcome_frame;
162 address initiator_address;
164 address receiver_tpt_address;
165 uint32_t receiver_tpt_port;
166 uint32_t receiver_welcome_frame;
167 address receiver_address;
170 typedef struct jxta_stream_conversation_data jxta_stream_conversation_data;
172 static const char* jxta_conv_get_filter_type(conv_item_t* conv, conv_filter_type_e filter)
174 if ((filter == CONV_FT_SRC_ADDRESS) && (conv->src_address.type == uri_address_type))
175 return "jxta.message.src";
177 if ((filter == CONV_FT_DST_ADDRESS) && (conv->dst_address.type == uri_address_type))
178 return "jxta.message.dst";
180 if ((filter == CONV_FT_ANY_ADDRESS) && (conv->src_address.type == uri_address_type))
181 return "jxta.message.address";
183 return CONV_FILTER_INVALID;
186 static ct_dissector_info_t jxta_ct_dissector_info = {&jxta_conv_get_filter_type};
188 static tap_packet_status
189 jxta_conversation_packet(void *pct, packet_info *pinfo _U_, epan_dissect_t *edt _U_, const void *vip, tap_flags_t flags)
191 conv_hash_t *hash = (conv_hash_t*) pct;
192 hash->flags = flags;
194 const jxta_tap_header *jxtahdr = (const jxta_tap_header *) vip;
196 add_conversation_table_data(hash, &jxtahdr->src_address, &jxtahdr->dest_address,
197 0, 0, 1, jxtahdr->size, NULL, NULL, &jxta_ct_dissector_info, CONVERSATION_NONE);
199 return TAP_PACKET_REDRAW;
202 static const char* jxta_endpoint_get_filter_type(endpoint_item_t* endpoint, conv_filter_type_e filter)
204 if ((filter == CONV_FT_ANY_ADDRESS) && (endpoint->myaddress.type == uri_address_type))
205 return "jxta.message.address";
207 return CONV_FILTER_INVALID;
210 static et_dissector_info_t jxta_endpoint_dissector_info = {&jxta_endpoint_get_filter_type};
212 static tap_packet_status
213 jxta_endpoint_packet(void *pit, packet_info *pinfo _U_, epan_dissect_t *edt _U_, const void *vip, tap_flags_t flags)
215 conv_hash_t *hash = (conv_hash_t*) pit;
216 hash->flags = flags;
218 const jxta_tap_header *jxtahdr = (const jxta_tap_header *)vip;
220 /* Take two "add" passes per packet, adding for each direction, ensures that all
221 packets are counted properly (even if address is sending to itself)
222 XXX - this could probably be done more efficiently inside endpoint_table */
223 add_endpoint_table_data(hash, &jxtahdr->src_address, 0, true, 1, jxtahdr->size, &jxta_endpoint_dissector_info, ENDPOINT_NONE);
224 add_endpoint_table_data(hash, &jxtahdr->dest_address, 0, false, 1, jxtahdr->size, &jxta_endpoint_dissector_info, ENDPOINT_NONE);
225 return TAP_PACKET_REDRAW;
228 static int uri_to_str(const address* addr, char *buf, int buf_len)
230 int copy_len = addr->len < (buf_len - 1) ? addr->len : (buf_len - 1);
231 memcpy(buf, addr->data, copy_len );
232 buf[copy_len] = '\0';
233 return copy_len+1;
236 static int uri_str_len(const address* addr)
238 return addr->len+1;
241 static const char* uri_col_filter_str(const address* addr _U_, bool is_src)
243 if (is_src)
244 return "uri.src";
246 return "uri.dst";
250 * Prototypes
252 static int dissect_jxta_udp(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, void * data);
253 static int dissect_jxta_stream(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, void * data);
254 static jxta_stream_conversation_data *get_tpt_conversation(packet_info * pinfo);
255 static conversation_t *get_peer_conversation(packet_info * pinfo, jxta_stream_conversation_data* tpt_conv_data, bool create);
257 static int dissect_jxta_welcome(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, address * found_addr, bool initiator);
258 static int dissect_jxta_message_framing(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, uint64_t * content_length,
259 char ** content_type);
260 static int dissect_jxta_message(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, void * data);
261 static int dissect_jxta_message_element_1(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, unsigned ns_count,
262 const char ** namespaces);
263 static int dissect_jxta_message_element_2(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, unsigned ns_count,
264 const char ** namespaces);
265 static int dissect_media( const char* fullmediatype, tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree);
268 * Heuristically dissect a tvbuff containing a JXTA UDP Message
270 * @param tvb The buffer to dissect.
271 * @param pinfo Packet Info.
272 * @param tree The protocol tree.
273 * @return true if the tvb contained JXTA data which was dissected otherwise false
275 static bool dissect_jxta_UDP_heur(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, void * data _U_)
277 /* This is a heuristic dissector, which means we get all the UDP
278 * traffic not sent to a known dissector and not claimed by
279 * a heuristic dissector called before us!
281 int save_desegment_offset;
282 uint32_t save_desegment_len;
283 int ret;
285 if (tvb_strneql(tvb, 0, JXTA_UDP_SIG, sizeof (JXTA_UDP_SIG)) != 0) {
286 /* Not a JXTA UDP packet (or not enough bytes to check for the sig) */
287 return false;
290 save_desegment_offset = pinfo->desegment_offset;
291 save_desegment_len = pinfo->desegment_len;
292 ret = dissect_jxta_udp(tvb, pinfo, tree, NULL);
294 /* ws_message( "%d Heuristic UDP Dissection : %d", pinfo->num, ret ); */
296 if (ret < 0) {
298 * UDP is not a packet stream protocol, so the UDP dissector
299 * should not, and will not, do the sort of dissection help
300 * that the TCP dissector will. If JXTA messages don't
301 * start and end on UDP packet boundaries, the JXTA dissector
302 * will have to do its own byte stream reassembly.
304 pinfo->desegment_offset = save_desegment_offset;
305 pinfo->desegment_len = save_desegment_len;
306 return false;
307 } else if (ret == 0) {
309 * A clear rejection.
311 pinfo->desegment_offset = save_desegment_offset;
312 pinfo->desegment_len = save_desegment_len;
313 return false;
314 } else {
316 * A clear acceptance.
318 return true;
323 * Heuristically dissect a tvbuff containing a JXTA TCP Stream
325 * @param tvb The buffer to dissect.
326 * @param pinfo Packet Info.
327 * @param tree The protocol tree.
328 * @return true if the tvb contained JXTA data which was dissected otherwise false
330 static bool dissect_jxta_TCP_heur(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, void * data _U_)
332 /* This is a heuristic dissector, which means we get all the TCP
333 * traffic not sent to a known dissector and not claimed by
334 * a heuristic dissector called before us!
336 int save_desegment_offset;
337 uint32_t save_desegment_len;
338 int ret;
340 save_desegment_offset = pinfo->desegment_offset;
341 save_desegment_len = pinfo->desegment_len;
342 ret = dissect_jxta_stream(tvb, pinfo, tree, NULL);
344 /* ws_message( "%d Heuristic TCP Dissection : %d", pinfo->num, ret ); */
346 if (ret < 0) {
348 * A heuristic dissector for a TCP-based protocol can reject
349 * a packet, or it can request that more data be provided.
350 * It must not attempt to do both, as the notion of doing both
351 * is nonsensical - if the packet isn't considered a packet
352 * for the dissector's protocol, that dissector won't be
353 * dissecting it no matter *how* much more data is added.
355 * Therefore, we treat a negative return from
356 * dissect_jxta_stream() as a rejection.
358 * If that's not desired - i.e., if we should keep trying to get
359 * more data, in the hopes that we'll eventually be able to
360 * determine whether the packet is a JXTA packet or not - we
361 * should, in this case, leave pinfo->desegment_offset and
362 * pinfo->desegment_len alone, and return true, *NOT* false.
364 pinfo->desegment_offset = save_desegment_offset;
365 pinfo->desegment_len = save_desegment_len;
366 return false;
367 } else if (ret == 0) {
369 * A clear rejection.
371 pinfo->desegment_offset = save_desegment_offset;
372 pinfo->desegment_len = save_desegment_len;
373 return false;
374 } else {
376 * A clear acceptance.
378 return true;
383 * Heuristically dissect a tvbuff containing a JXTA SCTP Stream
385 * @param tvb The buffer to dissect.
386 * @param pinfo Packet Info.
387 * @param tree The protocol tree.
388 * @return true if the tvb contained JXTA data which was dissected otherwise false
390 static bool dissect_jxta_SCTP_heur(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, void * data _U_)
392 /* This is a heuristic dissector, which means we get all the SCTP
393 * traffic not sent to a known dissector and not claimed by
394 * a heuristic dissector called before us!
396 int save_desegment_offset;
397 uint32_t save_desegment_len;
398 int ret;
400 save_desegment_offset = pinfo->desegment_offset;
401 save_desegment_len = pinfo->desegment_len;
402 ret = dissect_jxta_stream(tvb, pinfo, tree, NULL);
404 /* ws_message( "%d Heuristic SCTP Dissection : %d", pinfo->num, ret ); */
406 if (ret < 0) {
408 * SCTP is not a byte stream protocol, so the SCTP dissector
409 * should not, and will not, do the sort of dissection help
410 * that the SCTP dissector will. If JXTA messages don't
411 * start and end on SCTP packet boundaries, the JXTA dissector
412 * will have to do its own byte stream reassembly.
414 * The SCTP dissector currently won't do reassembly. If that
415 * causes a problem for the JXTA dissector, the correct fix
416 * is to implement reassembly in the SCTP dissector, so *all*
417 * dissectors for protocols running atop SCTP can benefit from
418 * it.
420 pinfo->desegment_offset = save_desegment_offset;
421 pinfo->desegment_len = save_desegment_len;
422 return false;
423 } else if (ret == 0) {
425 * A clear rejection.
427 pinfo->desegment_offset = save_desegment_offset;
428 pinfo->desegment_len = save_desegment_len;
429 return false;
430 } else {
432 * A clear acceptance.
434 return true;
439 * Dissect a tvbuff containing a JXTA UDP header, JXTA Message framing and a JXTA Message
441 * @param tvb The buffer to dissect.
442 * @param pinfo Packet Info.
443 * @param tree The protocol tree.
444 * @return Number of bytes from the tvbuff_t which were processed, 0 (zero) if
445 * the packet was not recognized as a JXTA packet and negative if the
446 * dissector needs more bytes in order to process a PDU.
448 static int dissect_jxta_udp(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, void * data _U_)
450 unsigned offset = 0;
451 unsigned available;
452 int needed = 0;
454 conversation_t *conversation = find_or_create_conversation(pinfo);
456 conversation_set_dissector(conversation, jxta_udp_handle);
458 while (true) {
459 tvbuff_t *jxta_message_framing_tvb;
460 int processed = 0;
461 uint64_t content_length = -1;
462 char *content_type = NULL;
464 available = tvb_reported_length_remaining(tvb, offset);
465 if (available < sizeof(JXTA_UDP_SIG)) {
466 needed = (int) (sizeof(JXTA_UDP_SIG) - available);
467 break;
470 if (tvb_memeql(tvb, offset, (const uint8_t*)JXTA_UDP_SIG, sizeof(JXTA_UDP_SIG)) != 0) {
471 /* not ours */
472 return 0;
475 offset += (int)sizeof(JXTA_UDP_SIG);
477 jxta_message_framing_tvb = tvb_new_subset_remaining(tvb, offset);
478 processed = dissect_jxta_message_framing(jxta_message_framing_tvb, pinfo, NULL, &content_length, &content_type);
480 if ((0 == processed) || (NULL == content_type) || (content_length <= 0) || (content_length > UINT_MAX)) {
481 /** Buffer did not begin with valid framing headers */
482 return 0;
485 if (processed < 0) {
486 needed = -processed;
487 break;
490 offset += processed;
492 available = tvb_reported_length_remaining(tvb, offset);
493 if (available < content_length) {
494 needed = (int) (content_length - available);
495 break;
498 offset += (unsigned) content_length;
500 break;
503 if ((needed > 0) && gDESEGMENT && pinfo->can_desegment) {
504 /* ws_message( "UDP requesting %d more bytes", needed ); */
505 pinfo->desegment_offset = 0;
506 pinfo->desegment_len = needed;
507 return -needed;
510 col_set_str(pinfo->cinfo, COL_PROTOCOL, "JXTA");
512 unsigned tree_offset = 0;
513 proto_item *jxta_tree_item =
514 proto_tree_add_protocol_format(tree, proto_jxta, tvb, tree_offset, -1, "JXTA" );
515 proto_tree *jxta_tree = proto_item_add_subtree(jxta_tree_item, ett_jxta);
516 proto_item *jxta_udp_tree_item =
517 proto_tree_add_none_format(jxta_tree, hf_jxta_udp, tvb, tree_offset, -1, "JXTA UDP Message");
518 proto_tree *jxta_udp_tree = proto_item_add_subtree(jxta_udp_tree_item, ett_jxta_udp);
519 tvbuff_t *jxta_message_framing_tvb;
520 uint64_t content_length = -1;
521 char *content_type = NULL;
522 tvbuff_t *jxta_message_tvb;
524 proto_tree_add_item(jxta_udp_tree, hf_jxta_udpsig, tvb, tree_offset, (int)sizeof(JXTA_UDP_SIG), ENC_ASCII);
525 tree_offset += (int)sizeof(JXTA_UDP_SIG);
527 jxta_message_framing_tvb = tvb_new_subset_remaining(tvb, tree_offset);
529 tree_offset += dissect_jxta_message_framing(jxta_message_framing_tvb, pinfo, jxta_tree, &content_length, &content_type);
531 jxta_message_tvb = tvb_new_subset_length(tvb, tree_offset, (int) content_length);
533 tree_offset += dissect_media(content_type, jxta_message_tvb, pinfo, tree);
535 proto_item_set_end(jxta_udp_tree_item, tvb, tree_offset);
537 // offset is based on reported lengths. tree_offset is based on captured lengths via dissect_media.
538 // Comment this out for now in favor of dissect_media's expert warning.
539 // DISSECTOR_ASSERT(tree_offset == offset);
541 return offset;
545 * Dissect a tvbuff containing JXTA stream PDUs. This commonly includes
546 * connections over TCP sockets.
548 * <p/>The stream (in both directions) will consist of a JXTA Welcome Message
549 * followed by an indeterminate number of JXTA Message Framing Headers and
550 * JXTA Messages.
552 * @param tvb The buffer to dissect.
553 * @param pinfo Packet Info.
554 * @param tree The protocol tree.
555 * @return Number of bytes from the tvbuff_t which were processed, 0 (zero) if
556 * the packet was not recognized as a JXTA packet and negative if the
557 * dissector needs more bytes in order to process a PDU.
559 static int dissect_jxta_stream(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, void * data _U_)
561 unsigned offset = 0;
562 unsigned available = tvb_reported_length_remaining(tvb, offset);
563 int processed = 0;
564 int needed = 0;
565 jxta_stream_conversation_data *tpt_conv_data = NULL;
566 proto_item *jxta_tree_item = NULL;
567 proto_tree *jxta_tree = NULL;
569 /* ws_message("Dissecting%s : %d", (NULL != tree) ? " for display" : "", pinfo->num ); */
571 if (available < sizeof(JXTA_WELCOME_MSG_SIG)) {
572 needed = (int) (sizeof(JXTA_WELCOME_MSG_SIG) - available);
573 goto Common_Exit;
576 if (0 == tvb_memeql(tvb, 0, (const uint8_t*)JXTA_WELCOME_MSG_SIG, sizeof(JXTA_WELCOME_MSG_SIG))) {
577 /* The beginning of a JXTA stream connection */
578 address *welcome_addr;
579 bool initiator = false;
581 tpt_conv_data = get_tpt_conversation(pinfo);
583 if (0 == tpt_conv_data->initiator_welcome_frame) {
584 /* The initiator welcome frame */
585 tpt_conv_data->tpt_ptype = pinfo->ptype;
586 tpt_conv_data->initiator_welcome_frame = pinfo->num;
587 copy_address_wmem(wmem_file_scope(), &tpt_conv_data->initiator_tpt_address, &pinfo->src);
588 tpt_conv_data->initiator_tpt_port = pinfo->srcport;
590 welcome_addr = &tpt_conv_data->initiator_address;
591 initiator = true;
592 } else {
593 if (tpt_conv_data->initiator_welcome_frame >= pinfo->num) {
594 /* what we saw previously was the receiver welcome message */
595 tpt_conv_data->receiver_welcome_frame = tpt_conv_data->initiator_welcome_frame;
596 tpt_conv_data->receiver_tpt_address = tpt_conv_data->initiator_tpt_address;
597 tpt_conv_data->receiver_tpt_port = tpt_conv_data->initiator_tpt_port;
598 tpt_conv_data->receiver_address = tpt_conv_data->initiator_address;
599 tpt_conv_data->initiator_welcome_frame = pinfo->num;
600 copy_address_wmem(wmem_file_scope(), &tpt_conv_data->initiator_tpt_address, &pinfo->src);
601 tpt_conv_data->initiator_tpt_port = pinfo->srcport;
603 welcome_addr = &tpt_conv_data->initiator_address;
604 initiator = true;
605 } else {
606 /* The receiver welcome frame */
607 tpt_conv_data->tpt_ptype = pinfo->ptype;
608 tpt_conv_data->receiver_welcome_frame = pinfo->num;
609 copy_address_wmem(wmem_file_scope(), &tpt_conv_data->receiver_tpt_address, &pinfo->src);
610 tpt_conv_data->receiver_tpt_port = pinfo->srcport;
612 welcome_addr = &tpt_conv_data->receiver_address;
613 initiator = false;
617 processed = dissect_jxta_welcome(tvb, pinfo, NULL, welcome_addr, initiator);
619 if( processed < 0 ) {
620 needed = -processed;
621 goto Common_Exit;
624 /* redo, this time creating the display tree. */
625 jxta_tree_item = proto_tree_add_protocol_format(tree, proto_jxta, tvb, offset, -1, "JXTA" );
626 jxta_tree = proto_item_add_subtree(jxta_tree_item, ett_jxta);
628 processed = dissect_jxta_welcome(tvb, pinfo, jxta_tree, welcome_addr, initiator);
629 } else {
630 /* Somewhere in the middle of a JXTA stream connection */
631 int64_t content_length = INT64_C(-1);
632 char *content_type = NULL;
633 int headers_len = dissect_jxta_message_framing(tvb, pinfo, NULL, (uint64_t*) &content_length, &content_type);
635 if ((0 == headers_len) || (NULL == content_type) || (content_length <= 0) || (content_length > UINT_MAX)) {
636 /** Buffer did not begin with valid framing headers */
637 return 0;
640 /* ws_message("%d Tpt %s:%d -> %s:%d tvb len=%d\n\t%s %d", pinfo->num,
641 address_to_str(pinfo->pool, &pinfo->src), pinfo->srcport,
642 address_to_str(pinfo->pool, &pinfo->dst), pinfo->destport,
643 tvb_reported_length_remaining(tvb, 0),
644 content_type ? content_type : "[unknown content type]", (int) content_length); */
646 if (headers_len < 0) {
647 /* negative headers_len means we need more bytes */
648 needed = -headers_len;
649 goto Common_Exit;
652 available = tvb_reported_length_remaining(tvb, offset + headers_len);
653 if (available >= content_length) {
654 tvbuff_t *jxta_message_tvb = tvb_new_subset_length(tvb, offset + headers_len, (int) content_length);
655 conversation_t *peer_conversation = NULL;
657 jxta_tree_item = proto_tree_add_protocol_format(tree, proto_jxta, tvb, offset, -1, "JXTA" );
658 jxta_tree = proto_item_add_subtree(jxta_tree_item, ett_jxta);
660 /* Redo header processing, this time populating the tree. */
661 headers_len = dissect_jxta_message_framing(tvb, pinfo, jxta_tree, &content_length, &content_type);
663 tpt_conv_data = get_tpt_conversation(pinfo);
664 peer_conversation = get_peer_conversation(pinfo, tpt_conv_data, true);
666 /* Use our source and destination addresses if we have them */
667 if (NULL != peer_conversation) {
668 /* ws_message("%d Tpt %s:%d -> %s:%d", pinfo->num,
669 address_to_str(pinfo->pool, &tpt_conv_data->initiator_tpt_address), tpt_conv_data->initiator_tpt_port,
670 address_to_str(pinfo->pool, &tpt_conv_data->receiver_tpt_address), tpt_conv_data->receiver_tpt_port); */
672 if (addresses_equal(&pinfo->src, &tpt_conv_data->initiator_tpt_address)
673 && tpt_conv_data->initiator_tpt_port == pinfo->srcport) {
674 /* ws_message("%d From initiator : %s -> %s ", pinfo->num,
675 address_to_str(pinfo->pool, &tpt_conv_data->initiator_address),
676 address_to_str(pinfo->pool, &tpt_conv_data->receiver_address)); */
677 copy_address_shallow(&pinfo->src, &tpt_conv_data->initiator_address);
678 pinfo->srcport = 0;
679 copy_address_shallow(&pinfo->dst, &tpt_conv_data->receiver_address);
680 pinfo->destport = 0;
681 pinfo->ptype = PT_NONE;
682 } else if (addresses_equal(&pinfo->src, &tpt_conv_data->receiver_tpt_address) &&
683 tpt_conv_data->receiver_tpt_port == pinfo->srcport) {
684 /* ws_message("%d From receiver : %s -> %s ", pinfo->num,
685 address_to_str(pinfo->pool, &tpt_conv_data->receiver_address),
686 address_to_str(pinfo->pool, &tpt_conv_data->initiator_address)); */
687 copy_address_shallow(&pinfo->src, &tpt_conv_data->receiver_address);
688 pinfo->srcport = 0;
689 copy_address_shallow(&pinfo->dst, &tpt_conv_data->initiator_address);
690 pinfo->destport = 0;
691 pinfo->ptype = PT_NONE;
692 } else {
693 /* ws_message("%d Nothing matches %s:%d -> %s:%d", pinfo->num,
694 address_to_str(pinfo->pool, &pinfo->src), pinfo->srcport,
695 address_to_str(pinfo->pool, &pinfo->dst), pinfo->destport); */
699 processed = headers_len;
701 processed += dissect_media(content_type, jxta_message_tvb, pinfo, tree);
702 } else {
703 /* we need more bytes before we can process message body. */
704 needed = (int) ((unsigned) content_length - available);
705 goto Common_Exit;
709 offset += processed;
711 Common_Exit:
712 if ((needed > 0) && gDESEGMENT && pinfo->can_desegment) {
713 /* ws_message( "Stream requesting %d more bytes", needed ); */
714 pinfo->desegment_offset = offset;
715 pinfo->desegment_len = needed;
716 return -needed;
719 return offset;
723 * Find or possibly create a transport conversation object for the connection
724 * which is associated with the packet info.
726 * @param pinfo The packet info from the underlying transport.
728 static jxta_stream_conversation_data *get_tpt_conversation(packet_info * pinfo)
730 conversation_t *tpt_conversation = find_or_create_conversation(pinfo);
731 jxta_stream_conversation_data *tpt_conv_data;
733 conversation_set_dissector(tpt_conversation, stream_jxta_handle);
735 tpt_conv_data = (jxta_stream_conversation_data *) conversation_get_proto_data(tpt_conversation, proto_jxta);
737 if (NULL == tpt_conv_data) {
738 tpt_conv_data = wmem_new(wmem_file_scope(), jxta_stream_conversation_data);
739 tpt_conv_data->tpt_ptype = pinfo->ptype;
741 copy_address_wmem(wmem_file_scope(), &tpt_conv_data->initiator_tpt_address, &pinfo->src);
742 tpt_conv_data->initiator_tpt_port = pinfo->srcport;
743 tpt_conv_data->initiator_welcome_frame = 0;
744 clear_address(&tpt_conv_data->initiator_address);
746 copy_address_wmem(wmem_file_scope(), &tpt_conv_data->receiver_tpt_address, &pinfo->dst);
747 tpt_conv_data->receiver_tpt_port = pinfo->destport;
748 tpt_conv_data->receiver_welcome_frame = 0;
749 clear_address(&tpt_conv_data->receiver_address);
751 conversation_add_proto_data(tpt_conversation, proto_jxta, tpt_conv_data);
754 return tpt_conv_data;
758 * Find or possibly create a peer conversation object for the connection
759 * which is associated with the packet info.
761 * @param tpt_conv_data The transport conversation from which we will locate the peer conversation.
762 * @param create If true then create a new conversation object if necessary.
764 static conversation_t *get_peer_conversation(packet_info * pinfo, jxta_stream_conversation_data* tpt_conv_data, bool create)
766 conversation_t * peer_conversation = NULL;
768 if ((AT_NONE != tpt_conv_data->initiator_address.type) && (AT_NONE != tpt_conv_data->receiver_address.type)) {
769 peer_conversation = find_conversation(pinfo->num, &tpt_conv_data->initiator_address, &tpt_conv_data->receiver_address,
770 CONVERSATION_NONE, 0, 0, NO_PORT_B);
772 if (create && (NULL == peer_conversation)) {
773 peer_conversation = conversation_new(pinfo->num, &tpt_conv_data->initiator_address,
774 &tpt_conv_data->receiver_address, CONVERSATION_NONE, 0, 0, NO_PORT2);
775 conversation_set_dissector(peer_conversation, stream_jxta_handle);
780 return peer_conversation;
784 * Dissect a tvbuff containing a JXTA Welcome Message
786 * @param tvb The buffer to dissect.
787 * @param pinfo Packet Info.
788 * @param tree The protocol tree.
789 * @param found_addr The address found in the welcome message.
790 * @param initiator If true then we believe this welcome message to be the initiator's.
791 * @return Number of bytes from the tvbuff_t which were processed, 0 (zero) if
792 * the packet was not recognized as a JXTA packet and negative if the
793 * dissector needs more bytes in order to process a PDU.
795 static int dissect_jxta_welcome(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, address * found_addr, bool initiator)
797 unsigned offset = 0;
798 int afterwelcome;
799 int first_linelen;
800 unsigned available = tvb_reported_length_remaining(tvb, offset);
801 char **tokens = NULL;
803 if (available < sizeof(JXTA_WELCOME_MSG_SIG)) {
804 return (int) (available - sizeof(JXTA_WELCOME_MSG_SIG));
807 if (0 != tvb_memeql(tvb, 0, (const uint8_t*)JXTA_WELCOME_MSG_SIG, sizeof(JXTA_WELCOME_MSG_SIG))) {
808 /* not ours! */
809 return 0;
812 first_linelen = tvb_find_line_end(tvb, offset, -1, &afterwelcome, gDESEGMENT && pinfo->can_desegment);
814 if (-1 == first_linelen) {
815 if (available > 4096) {
816 /* it's too far too be reasonable */
817 return 0;
818 } else {
819 /* ask for more bytes */
820 return -DESEGMENT_ONE_MORE_SEGMENT;
824 /* Dissect the Welcome Message */
826 col_set_str(pinfo->cinfo, COL_PROTOCOL, "JXTA");
828 col_set_str(pinfo->cinfo, COL_INFO, "Welcome");
831 char *welcomeline = tvb_get_string_enc(pinfo->pool, tvb, offset, first_linelen, ENC_ASCII);
832 char **current_token;
833 unsigned token_offset = offset;
834 proto_item *jxta_welcome_tree_item = NULL;
835 proto_tree *jxta_welcome_tree = NULL;
837 tokens = wmem_strsplit(pinfo->pool, welcomeline, " ", 255);
838 current_token = tokens;
840 if (tree) {
841 jxta_welcome_tree_item =
842 proto_tree_add_none_format(tree, hf_jxta_welcome, tvb, offset, afterwelcome,
843 "JXTA Connection Welcome Message, %s", welcomeline);
844 jxta_welcome_tree = proto_item_add_subtree(jxta_welcome_tree_item, ett_jxta_welcome);
847 if (jxta_welcome_tree) {
848 proto_item *jxta_welcome_initiator_item =
849 proto_tree_add_boolean(jxta_welcome_tree, hf_jxta_welcome_initiator, tvb, 0, 0, initiator);
850 proto_item_set_generated(jxta_welcome_initiator_item);
853 if (NULL != *current_token) {
854 proto_tree_add_item(jxta_welcome_tree, hf_jxta_welcome_sig, tvb, token_offset, (int) strlen(*current_token), ENC_ASCII);
856 token_offset += (unsigned) strlen(*current_token) + 1;
857 current_token++;
858 } else {
859 /* invalid welcome message */
860 afterwelcome = 0;
861 goto Common_Exit;
864 if (NULL != *current_token) {
865 if (jxta_welcome_tree) {
866 proto_tree_add_item(jxta_welcome_tree, hf_jxta_welcome_destAddr, tvb, token_offset, (int) strlen(*current_token),
867 ENC_ASCII);
870 token_offset += (unsigned) strlen(*current_token) + 1;
871 current_token++;
872 } else {
873 /* invalid welcome message */
874 afterwelcome = 0;
875 goto Common_Exit;
878 if (NULL != *current_token) {
879 if (jxta_welcome_tree) {
880 proto_tree_add_item(jxta_welcome_tree, hf_jxta_welcome_pubAddr, tvb, token_offset, (int) strlen(*current_token), ENC_ASCII);
883 token_offset += (unsigned) strlen(*current_token) + 1;
884 current_token++;
885 } else {
886 /* invalid welcome message */
887 afterwelcome = 0;
888 goto Common_Exit;
891 if (NULL != *current_token) {
892 if (jxta_welcome_tree) {
893 proto_tree_add_item(jxta_welcome_tree, hf_jxta_welcome_peerid, tvb, token_offset, (int) strlen(*current_token), ENC_ASCII);
896 col_append_str(pinfo->cinfo, COL_INFO, (initiator ? " -> " : " <- ") );
897 col_append_str(pinfo->cinfo, COL_INFO, *current_token);
899 if (NULL != found_addr) {
900 set_address(found_addr, uri_address_type, (int)strlen(*current_token) + 1, wmem_strdup(wmem_file_scope(), *current_token));
903 token_offset += (unsigned) strlen(*current_token) + 1;
904 current_token++;
905 } else {
906 /* invalid welcome message */
907 afterwelcome = 0;
908 goto Common_Exit;
911 if (NULL != *current_token) {
912 int variable_tokens = 0;
913 char **variable_token = current_token;
915 while(NULL != *variable_token) {
916 variable_tokens++;
917 variable_token++;
920 if( variable_tokens < 1 ) {
921 /* invalid welcome message */
922 afterwelcome = 0;
923 goto Common_Exit;
926 if( (2 == variable_tokens) && (0 == strcmp(JXTA_WELCOME_MSG_VERSION_1_1, current_token[variable_tokens -1])) ) {
927 if (jxta_welcome_tree) {
928 proto_tree_add_item(jxta_welcome_tree, hf_jxta_welcome_noProp, tvb, token_offset, (int) strlen(*current_token), ENC_ASCII);
931 token_offset += (unsigned) strlen(*current_token) + 1;
932 current_token++;
934 if (jxta_welcome_tree) {
935 proto_tree_add_item(jxta_welcome_tree, hf_jxta_welcome_version, tvb, token_offset, (int) strlen(*current_token), ENC_ASCII);
937 } else if( (3 == variable_tokens) && (0 == strcmp(JXTA_WELCOME_MSG_VERSION_3_0, current_token[variable_tokens -1])) ) {
938 if (jxta_welcome_tree) {
939 proto_tree_add_item(jxta_welcome_tree, hf_jxta_welcome_noProp, tvb, token_offset, (int) strlen(*current_token), ENC_ASCII);
942 token_offset += (unsigned) strlen(*current_token) + 1;
943 current_token++;
945 if (jxta_welcome_tree) {
946 proto_tree_add_item(jxta_welcome_tree, hf_jxta_welcome_msgVers, tvb, token_offset, (int) strlen(*current_token), ENC_ASCII);
949 token_offset += (unsigned) strlen(*current_token) + 1;
950 current_token++;
952 if (jxta_welcome_tree) {
953 proto_tree_add_item(jxta_welcome_tree, hf_jxta_welcome_version, tvb, token_offset, (int) strlen(*current_token), ENC_ASCII);
955 } else {
956 /* Unrecognized Welcome Version */
957 int each_variable_token;
959 for( each_variable_token = 0; each_variable_token < variable_tokens; each_variable_token++ ) {
960 if (jxta_welcome_tree) {
961 jxta_welcome_tree_item = proto_tree_add_item(jxta_welcome_tree,
962 (each_variable_token < (variable_tokens -1) ? hf_jxta_welcome_variable : hf_jxta_welcome_version),
963 tvb, token_offset, (int) strlen(*current_token), ENC_ASCII|ENC_NA);
965 proto_item_append_text(jxta_welcome_tree_item, " (UNRECOGNIZED)");
968 token_offset += (unsigned) strlen(*current_token) + 1;
969 current_token++;
972 } else {
973 /* invalid welcome message */
974 afterwelcome = 0;
975 goto Common_Exit;
979 Common_Exit:
980 col_set_writable(pinfo->cinfo, -1, false);
982 return afterwelcome;
986 * Dissect a tvbuff containing JXTA Message framing.
988 * @param tvb The buffer to dissect.
989 * @param pinfo Packet Info.
990 * @param tree The protocol tree.
991 * @param content_length Pointer to a buffer for storing the value of the
992 * "content-length" header or NULL.
993 * @param content_type Pointer-to-a-pointer for a new buffer for storing the
994 * value of the "content_type-length" header or NULL.
995 * @return Number of bytes from the tvbuff_t which were processed, 0 (zero) if
996 * the packet was not recognized as a JXTA packet and negative if the
997 * dissector needs more bytes in order to process a PDU.
999 static int dissect_jxta_message_framing(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, uint64_t * content_length,
1000 char ** content_type)
1002 unsigned offset = 0;
1003 unsigned available;
1004 int needed = 0;
1007 * First go around. Make sure all of the bytes are there.
1009 do {
1010 uint8_t headername_len;
1011 uint8_t headername_offset;
1012 uint16_t headervalue_len;
1013 uint16_t headervalue_offset;
1015 available = tvb_reported_length_remaining(tvb, offset);
1016 if (available < 1) {
1017 needed = 1;
1018 break;
1019 } else {
1020 headername_len = tvb_get_uint8(tvb, offset);
1021 offset++;
1022 headername_offset = offset;
1024 available = tvb_reported_length_remaining(tvb, offset);
1025 if (available < headername_len) {
1026 needed = (int) (headername_len - available);
1027 break;
1030 if (0 == headername_len) {
1031 break;
1033 offset += headername_len;
1036 available = tvb_reported_length_remaining(tvb, offset);
1037 if (available < 2) {
1038 needed = (int) (2 - available);
1039 break;
1040 } else {
1041 headervalue_len = tvb_get_ntohs(tvb, offset);
1042 offset += 2;
1043 headervalue_offset = offset;
1045 available = tvb_reported_length_remaining(tvb, offset);
1046 if (available < headervalue_len) {
1047 needed = (int) (headervalue_len - available);
1048 break;
1051 offset += headervalue_len;
1054 if (content_type && (sizeof("content-type") - 1) == headername_len) {
1055 if (0 == tvb_strncaseeql(tvb, headername_offset, "content-type", sizeof("content-type") - 1)) {
1056 *content_type = tvb_get_string_enc(pinfo->pool, tvb, headervalue_offset, headervalue_len, ENC_ASCII);
1061 if (content_length && (sizeof(uint64_t) == headervalue_len) && ((sizeof("content-length") - 1) == headername_len)) {
1062 if (0 == tvb_strncaseeql(tvb, headername_offset, "content-length", sizeof("content-length") - 1)) {
1063 *content_length = tvb_get_ntoh64(tvb, headervalue_offset);
1066 } while (true);
1068 if ((needed > 0) && gDESEGMENT && pinfo->can_desegment) {
1069 /* ws_message( "Framing requesting %d more bytes", needed ); */
1070 pinfo->desegment_offset = 0;
1071 pinfo->desegment_len = needed;
1072 return -needed;
1076 * Second (optional pass) Now that we are sure that all the bytes are there we update the protocol tree.
1078 if (tree) {
1079 unsigned tree_offset = 0;
1080 proto_item *framing_tree_item;
1081 proto_tree *framing_tree;
1083 framing_tree_item =
1084 proto_tree_add_none_format(tree, hf_jxta_framing, tvb, tree_offset, -1, "JXTA Message Framing Headers");
1085 framing_tree = proto_item_add_subtree(framing_tree_item, ett_jxta_framing);
1087 /* parse framing headers */
1088 do {
1089 uint8_t headernamelen = tvb_get_uint8(tvb, tree_offset);
1090 proto_item *framing_header_tree_item =
1091 proto_tree_add_item(framing_tree, hf_jxta_framing_header, tvb, tree_offset, -1, ENC_NA);
1092 proto_tree *framing_header_tree = proto_item_add_subtree(framing_header_tree_item, ett_jxta_framing_header);
1095 * Put header name into the protocol tree
1097 proto_tree_add_item(framing_header_tree, hf_jxta_framing_header_name, tvb, tree_offset, (int)sizeof(int8_t), ENC_ASCII|ENC_BIG_ENDIAN);
1100 * Append header name into the header protocol item. It's a nice hint so you don't have to reveal all headers.
1102 if (headernamelen > 0) {
1103 proto_item_append_text(framing_header_tree_item, " \"%s\"",
1104 tvb_format_text(pinfo->pool, tvb, tree_offset + 1, headernamelen));
1107 tree_offset += 1 + headernamelen;
1109 if (headernamelen > 0) {
1110 uint16_t headervaluelen = tvb_get_ntohs(tvb, tree_offset);
1112 if (tree) {
1113 proto_tree_add_uint(framing_header_tree, hf_jxta_framing_header_value_length, tvb, tree_offset,
1114 2, headervaluelen);
1116 /** TODO bondolo Add specific handling for known header types */
1119 * Put header value into protocol tree.
1121 proto_tree_add_item(framing_header_tree, hf_jxta_framing_header_value, tvb, tree_offset + 2,
1122 headervaluelen, ENC_NA);
1125 tree_offset += 2 + headervaluelen;
1128 proto_item_set_end(framing_header_tree_item, tvb, tree_offset);
1130 if (0 == headernamelen) {
1131 break;
1133 } while (true);
1135 proto_item_set_end(framing_tree_item, tvb, tree_offset);
1137 DISSECTOR_ASSERT(offset == tree_offset);
1140 /* return how many bytes we used up. */
1141 return offset;
1145 * Dissect a tvbuff containing one or more JXTA Messages.
1147 * @param tvb The buffer to dissect.
1148 * @param pinfo Packet Info.
1149 * @param tree The protocol tree.
1150 * @return Number of bytes from the tvbuff_t which were processed, 0 (zero) if
1151 * the packet was not recognized as a JXTA packet and negative if the
1152 * dissector needs more bytes in order to process a PDU.
1154 static int dissect_jxta_message(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, void * data _U_)
1156 int complete_messages = 0;
1157 unsigned offset = 0;
1158 unsigned tree_offset = 0;
1159 unsigned available;
1160 int needed = 0;
1161 wmem_strbuf_t* src_addr;
1162 wmem_strbuf_t* dst_addr;
1164 while (true) {
1165 uint8_t message_version;
1166 unsigned message_start_offset = offset;
1168 /* First pass. Make sure all of the bytes we need are available */
1169 available = tvb_reported_length_remaining(tvb, offset);
1171 if((0 == available) && (0 != complete_messages)) {
1172 /* We have discovered all of the complete messages in the tvbuff. */
1173 break;
1176 if (available < sizeof(JXTA_MSG_SIG)) {
1177 needed = (int) (sizeof(JXTA_MSG_SIG) - available);
1178 break;
1181 if (tvb_memeql(tvb, offset, (const uint8_t*)JXTA_MSG_SIG, sizeof(JXTA_MSG_SIG)) != 0) {
1182 /* It is not one of ours */
1183 return 0;
1186 offset += (int)sizeof(JXTA_MSG_SIG);
1188 available = tvb_reported_length_remaining(tvb, offset);
1189 if (available < 1) {
1190 needed = 1;
1191 break;
1192 } else {
1193 message_version = tvb_get_uint8(tvb, offset);
1195 offset++;
1197 if ((JXTA_MSG_VERSION_1 != message_version) && (JXTA_MSG_VERSION_2 != message_version)) {
1198 /* Sort of a lie, we say that we don't recognize it at all. */
1199 return 0;
1203 /* Read the flags (Version 2 and later) */
1204 if(message_version > 0) {
1205 available = tvb_reported_length_remaining(tvb, offset);
1206 if (available < 1) {
1207 needed = 1;
1208 break;
1209 } else {
1210 offset++;
1214 /* Read names table */
1215 available = tvb_reported_length_remaining(tvb, offset);
1216 if (available < 2) {
1217 needed = (int) (2 - available);
1218 break;
1219 } else {
1220 uint16_t msg_names_count = tvb_get_ntohs(tvb, offset);
1221 unsigned each_name;
1223 offset += 2;
1225 for (each_name = 0; each_name < msg_names_count; each_name++) {
1226 uint16_t name_len;
1228 available = tvb_reported_length_remaining(tvb, offset);
1229 if (available < sizeof(name_len)) {
1230 needed = (int) (sizeof(name_len) - available);
1231 break;
1234 name_len = tvb_get_ntohs(tvb, offset);
1236 available = tvb_reported_length_remaining(tvb, offset + (int)sizeof(name_len));
1237 if (available < name_len) {
1238 needed = (int) (name_len - available);
1239 break;
1242 offset += (int)sizeof(name_len) + name_len;
1246 /* parse element count */
1247 available = tvb_reported_length_remaining(tvb, offset);
1248 if (available < 2) {
1249 needed = (int) (2 - available);
1250 break;
1251 } else {
1252 uint16_t elem_count = tvb_get_ntohs(tvb, offset);
1253 unsigned each_elem;
1255 offset += 2;
1257 /* parse elements */
1258 for (each_elem = 0; each_elem < elem_count; each_elem++) {
1259 tvbuff_t *jxta_message_element_tvb = tvb_new_subset_remaining(tvb, offset);
1260 int processed;
1262 if (JXTA_MSG_VERSION_1 == message_version) {
1263 processed = dissect_jxta_message_element_1(jxta_message_element_tvb, pinfo, NULL, 0, NULL);
1264 } else { /* JXTA_MSG_VERSION_2 */
1265 processed = dissect_jxta_message_element_2(jxta_message_element_tvb, pinfo, NULL, 0, NULL);
1268 if (processed < 0) {
1269 needed = -processed;
1270 break;
1273 if (0 == processed) {
1274 /* XXX bondolo Not really clear what we should do! */
1275 /* eapache: based on reading the code, I believe this can occur
1276 * when the message_version is valid but the JXTA_MSGELEM_SIG
1277 * (some sort of magic number?) is not. This almost
1278 * certainly indicates a corrupt packet, so this should
1279 * probably be expert info, not a ws_warning. Pending confirmation
1280 * just comment it out since a ws_warning is definitely the
1281 * wrong thing to do.
1282 * ws_warning( "Failure processing message element #%d of %d of frame %d", each_elem, elem_count, pinfo->num );
1284 return 0;
1287 offset += processed;
1291 if ((uri_address_type == pinfo->src.type) && (uri_address_type == pinfo->dst.type)) {
1292 jxta_tap_header *tap_header = wmem_new(wmem_file_scope(), jxta_tap_header);
1294 copy_address_shallow(&tap_header->src_address, &pinfo->src);
1295 copy_address_shallow(&tap_header->dest_address, &pinfo->dst);
1296 tap_header->size = offset - message_start_offset ;
1298 tap_queue_packet(jxta_tap, pinfo, tap_header);
1301 complete_messages++;
1303 /* ws_message( "%d Scanned message #%d: ", pinfo->num, complete_messages ); */
1306 if ((needed > 0) && gDESEGMENT && pinfo->can_desegment) {
1307 /* ws_message("Frame %d: Message requesting %d more bytes", pinfo->num, needed); */
1308 pinfo->desegment_offset = 0;
1309 pinfo->desegment_len = needed;
1310 return -needed;
1313 src_addr = wmem_strbuf_create(pinfo->pool);
1314 wmem_strbuf_append(src_addr, address_to_str(pinfo->pool, &pinfo->src));
1315 dst_addr = wmem_strbuf_create(pinfo->pool);
1316 wmem_strbuf_append(dst_addr, address_to_str(pinfo->pool, &pinfo->dst));
1318 /* append the port if appropriate */
1319 if (PT_NONE != pinfo->ptype) {
1320 wmem_strbuf_append_printf(src_addr, ":%d", pinfo->srcport);
1321 wmem_strbuf_append_printf(dst_addr, ":%d", pinfo->destport);
1324 col_set_str(pinfo->cinfo, COL_PROTOCOL, "JXTA");
1326 if( complete_messages > 1 ) {
1327 col_add_fstr(pinfo->cinfo, COL_INFO, "%d Messages, %s -> %s", complete_messages,
1328 wmem_strbuf_get_str(src_addr), wmem_strbuf_get_str(dst_addr));
1329 } else {
1330 col_add_fstr(pinfo->cinfo, COL_INFO, "Message, %s -> %s",
1331 wmem_strbuf_get_str(src_addr), wmem_strbuf_get_str(dst_addr));
1334 col_set_writable(pinfo->cinfo, -1, false);
1336 while( tree && (complete_messages > 0) ) {
1337 proto_item *jxta_msg_tree_item = NULL;
1338 proto_tree *jxta_msg_tree = NULL;
1339 uint8_t message_version;
1340 const char **names_table = NULL;
1341 uint16_t msg_names_count;
1342 unsigned each_name;
1343 uint16_t elem_count;
1344 unsigned each_elem;
1345 proto_item *tree_item;
1347 jxta_msg_tree_item = proto_tree_add_protocol_format(tree, proto_message_jxta, tvb, tree_offset, -1,
1348 "JXTA Message, %s -> %s", wmem_strbuf_get_str(src_addr),
1349 wmem_strbuf_get_str(dst_addr));
1351 jxta_msg_tree = proto_item_add_subtree(jxta_msg_tree_item, ett_jxta_msg);
1353 proto_tree_add_item(jxta_msg_tree, hf_jxta_message_sig, tvb, tree_offset, (int)sizeof(JXTA_MSG_SIG), ENC_ASCII);
1354 tree_offset += (int)sizeof(JXTA_MSG_SIG);
1356 tree_item = proto_tree_add_string(jxta_msg_tree, hf_jxta_message_src, tvb, 0, 0, wmem_strbuf_get_str(src_addr));
1357 proto_item_set_generated(tree_item);
1359 tree_item = proto_tree_add_string(jxta_msg_tree, hf_jxta_message_address, tvb, 0, 0, wmem_strbuf_get_str(src_addr));
1360 proto_item_set_hidden(tree_item);
1361 proto_item_set_generated(tree_item);
1363 if(uri_address_type == pinfo->src.type) {
1364 tree_item = proto_tree_add_string(jxta_msg_tree, hf_uri_src, tvb, 0, 0, wmem_strbuf_get_str(src_addr));
1365 proto_item_set_hidden(tree_item);
1366 proto_item_set_generated(tree_item);
1367 tree_item = proto_tree_add_string(jxta_msg_tree, hf_uri_addr, tvb, 0, 0, wmem_strbuf_get_str(src_addr));
1368 proto_item_set_hidden(tree_item);
1369 proto_item_set_generated(tree_item);
1372 tree_item = proto_tree_add_string(jxta_msg_tree, hf_jxta_message_dst, tvb, 0, 0, wmem_strbuf_get_str(dst_addr));
1373 proto_item_set_generated(tree_item);
1375 tree_item = proto_tree_add_string(jxta_msg_tree, hf_jxta_message_address, tvb, 0, 0, wmem_strbuf_get_str(dst_addr));
1376 proto_item_set_hidden(tree_item);
1377 proto_item_set_generated(tree_item);
1379 if(uri_address_type == pinfo->dst.type) {
1380 tree_item = proto_tree_add_string(jxta_msg_tree, hf_uri_dst, tvb, 0, 0, wmem_strbuf_get_str(dst_addr));
1381 proto_item_set_hidden(tree_item);
1382 proto_item_set_generated(tree_item);
1383 tree_item = proto_tree_add_string(jxta_msg_tree, hf_uri_addr, tvb, 0, 0, wmem_strbuf_get_str(dst_addr));
1384 proto_item_set_hidden(tree_item);
1385 proto_item_set_generated(tree_item);
1388 message_version = tvb_get_uint8(tvb, tree_offset);
1389 proto_tree_add_uint(jxta_msg_tree, hf_jxta_message_version, tvb, tree_offset, 1, message_version);
1390 tree_offset += 1;
1392 if( message_version > 0 ) {
1393 static int * const flags[] = {
1394 &hf_jxta_message_flag_utf16be,
1395 &hf_jxta_message_flag_ucs32be,
1396 NULL
1399 proto_tree_add_bitmask(jxta_msg_tree, tvb, tree_offset, hf_jxta_message_flags, ett_jxta_msg_flags, flags, ENC_NA);
1400 tree_offset += 1;
1403 msg_names_count = tvb_get_ntohs(tvb, tree_offset);
1404 proto_tree_add_uint(jxta_msg_tree, hf_jxta_message_names_count, tvb, tree_offset, 2, msg_names_count);
1405 tree_offset += 2;
1407 names_table = (const char **)wmem_alloc(pinfo->pool, (msg_names_count + 2) * sizeof(const char *));
1408 names_table[0] = "";
1409 names_table[1] = "jxta";
1411 /* parse names */
1412 for (each_name = 0; each_name < msg_names_count; each_name++) {
1413 uint16_t name_len = tvb_get_ntohs(tvb, tree_offset);
1415 names_table[2 + each_name] = tvb_get_string_enc(pinfo->pool, tvb, tree_offset + 2, name_len, ENC_ASCII);
1416 proto_tree_add_item(jxta_msg_tree, hf_jxta_message_names_name, tvb, tree_offset, 2, ENC_ASCII|ENC_BIG_ENDIAN);
1417 tree_offset += 2 + name_len;
1420 /* parse element count */
1421 elem_count = tvb_get_ntohs(tvb, tree_offset);
1422 proto_tree_add_item(jxta_msg_tree, hf_jxta_message_element_count, tvb, tree_offset, 2, ENC_BIG_ENDIAN);
1423 tree_offset += 2;
1425 /* FIXME bondolo Element count 0 (Process elements until FIN) should be supported. */
1427 /* parse elements */
1428 for (each_elem = 0; each_elem < elem_count; each_elem++) {
1429 tvbuff_t *jxta_message_element_tvb = tvb_new_subset_remaining(tvb, tree_offset);
1431 if(JXTA_MSG_VERSION_1 == message_version) {
1432 tree_offset +=
1433 dissect_jxta_message_element_1(jxta_message_element_tvb, pinfo, jxta_msg_tree, msg_names_count + 2, names_table);
1434 } else if(JXTA_MSG_VERSION_2 == message_version) {
1435 tree_offset +=
1436 dissect_jxta_message_element_2(jxta_message_element_tvb, pinfo, jxta_msg_tree, msg_names_count + 2, names_table);
1437 } else {
1438 /* Sort of a lie, we say that we don't recognize it at all. */
1439 return 0;
1443 proto_item_set_end(jxta_msg_tree_item, tvb, tree_offset);
1445 complete_messages--;
1448 if( tree ) {
1449 /* ws_message( "%d tvb offset : %d tree offset : %d", pinfo->num, offset, tree_offset ); */
1450 DISSECTOR_ASSERT(tree_offset == offset);
1453 return offset;
1457 * Dissect a tvbuff containing a JXTA Message Element (Version 1).
1459 * @param tvb The buffer to dissect.
1460 * @param pinfo Packet Info.
1461 * @param tree The protocol tree.
1462 * @return Number of bytes from the tvbuff_t which were processed, 0 (zero) if
1463 * the packet was not recognized as a JXTA packet and negative if the
1464 * dissector needs more bytes in order to process a PDU.
1466 // NOLINTNEXTLINE(misc-no-recursion)
1467 static int dissect_jxta_message_element_1(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, unsigned ns_count,
1468 const char ** names_table)
1470 unsigned offset = 0;
1471 unsigned available;
1472 int needed = 0;
1473 uint8_t flags;
1475 /* First pass. Make sure all of the bytes we need are available */
1477 while (true) {
1478 /* signature field */
1479 available = tvb_reported_length_remaining(tvb, offset);
1480 if (available < sizeof(JXTA_MSGELEM_SIG)) {
1481 needed = (int) (sizeof(JXTA_MSGELEM_SIG) - available);
1484 if (tvb_memeql(tvb, offset, (const uint8_t*)JXTA_MSGELEM_SIG, sizeof(JXTA_MSGELEM_SIG)) != 0) {
1485 /* It is not one of ours */
1486 return 0;
1489 offset += (int)sizeof(JXTA_MSGELEM_SIG);
1491 /* namespace id field */
1492 available = tvb_reported_length_remaining(tvb, offset);
1493 if (available < 1) {
1494 needed = 1;
1495 break;
1498 offset++;
1500 /* flags field */
1501 available = tvb_reported_length_remaining(tvb, offset);
1502 if (available < 1) {
1503 needed = 1;
1504 break;
1505 } else {
1506 flags = tvb_get_uint8(tvb, offset);
1507 offset++;
1510 /* name field */
1511 available = tvb_reported_length_remaining(tvb, offset);
1512 if (available < 2) {
1513 needed = (int) (2 - available);
1514 break;
1515 } else {
1516 uint16_t name_len = tvb_get_ntohs(tvb, offset);
1517 offset += 2;
1519 available = tvb_reported_length_remaining(tvb, offset);
1520 if (available < name_len) {
1521 needed = (int) (name_len - available);
1522 break;
1525 offset += name_len;
1528 /* type field */
1529 if ((flags & JXTAMSG1_ELMFLAG_TYPE) != 0) {
1530 uint16_t type_len;
1532 available = tvb_reported_length_remaining(tvb, offset);
1533 if (available < 2) {
1534 needed = (int) (2 - available);
1535 break;
1538 type_len = tvb_get_ntohs(tvb, offset);
1539 offset += 2;
1541 available = tvb_reported_length_remaining(tvb, offset);
1542 if (available < type_len) {
1543 needed = (int) (type_len - available);
1544 break;
1547 offset += type_len;
1550 /* encoding field */
1551 if ((flags & JXTAMSG1_ELMFLAG_ENCODING) != 0) {
1552 uint16_t encoding_len;
1554 available = tvb_reported_length_remaining(tvb, offset);
1555 if (available < 2) {
1556 needed = (int) (2 - available);
1557 break;
1560 encoding_len = tvb_get_ntohs(tvb, offset);
1561 offset += 2;
1563 available = tvb_reported_length_remaining(tvb, offset);
1564 if (available < encoding_len) {
1565 needed = (int) (encoding_len - available);
1566 break;
1569 offset += encoding_len;
1572 /* content field */
1573 available = tvb_reported_length_remaining(tvb, offset);
1574 if (available < 2) {
1575 needed = (int) (2 - available);
1576 break;
1577 } else {
1578 uint32_t content_len = tvb_get_ntohl(tvb, offset);
1579 offset += 4;
1581 available = tvb_reported_length_remaining(tvb, offset);
1582 if (available < content_len) {
1583 needed = (int) (content_len - available);
1584 break;
1587 offset += content_len;
1590 /* signature element field */
1591 if ((flags & JXTAMSG1_ELMFLAG_SIGNATURE) != 0) {
1592 tvbuff_t *jxta_signature_element_tvb;
1593 int processed;
1595 jxta_signature_element_tvb = tvb_new_subset_remaining(tvb, offset);
1597 increment_dissection_depth(pinfo);
1598 processed = dissect_jxta_message_element_1(jxta_signature_element_tvb, pinfo, NULL, 0, NULL);
1599 decrement_dissection_depth(pinfo);
1601 if (processed == 0) {
1602 return offset;
1605 if (processed < 0) {
1606 needed = -processed;
1607 break;
1610 offset += processed;
1613 break;
1616 if ((needed > 0) && gDESEGMENT && pinfo->can_desegment) {
1617 /* ws_message( "Element1 requesting %d more bytes", needed ); */
1618 pinfo->desegment_offset = 0;
1619 pinfo->desegment_len = needed;
1620 return -needed;
1623 /* Second pass : build the proto tree */
1624 unsigned tree_offset = 0;
1625 proto_item *jxta_elem_tree_item = proto_tree_add_item(tree, hf_jxta_element, tvb, tree_offset, -1, ENC_NA);
1626 proto_tree *jxta_elem_tree = proto_item_add_subtree(jxta_elem_tree_item, ett_jxta_elem);
1627 uint8_t namespaceID;
1628 proto_item *namespace_ti;
1629 uint16_t name_len;
1630 uint32_t content_len;
1631 char *mediatype = NULL;
1632 tvbuff_t *element_content_tvb;
1633 static int * const element_flags[] = {
1634 &hf_jxta_element1_flag_hasType,
1635 &hf_jxta_element1_flag_hasEncoding,
1636 &hf_jxta_element1_flag_hasSignature,
1637 NULL
1640 proto_tree_add_item(jxta_elem_tree, hf_jxta_element_sig, tvb, tree_offset, (int)sizeof(JXTA_MSGELEM_SIG), ENC_ASCII);
1641 tree_offset += (int)sizeof(JXTA_MSGELEM_SIG);
1643 namespaceID = tvb_get_uint8(tvb, tree_offset);
1644 namespace_ti =
1645 proto_tree_add_uint(jxta_elem_tree, hf_jxta_element1_namespaceid, tvb, tree_offset, 1, namespaceID);
1646 if (namespaceID < ns_count) {
1647 proto_item_append_text(namespace_ti, " (%s)", names_table[namespaceID]);
1648 } else {
1649 proto_item_append_text(namespace_ti, " * BAD *");
1651 tree_offset += 1;
1653 flags = tvb_get_uint8(tvb, tree_offset);
1654 proto_tree_add_bitmask(jxta_elem_tree, tvb, tree_offset, hf_jxta_element_flags, ett_jxta_elem_1_flags, element_flags, ENC_NA);
1655 tree_offset += 1;
1657 name_len = tvb_get_ntohs(tvb, tree_offset);
1658 proto_item_append_text(jxta_elem_tree_item, " \"%s\"", tvb_format_text(pinfo->pool, tvb, tree_offset + 2, name_len));
1659 proto_tree_add_item(jxta_elem_tree, hf_jxta_element_name, tvb, tree_offset, 2, ENC_ASCII|ENC_BIG_ENDIAN);
1660 tree_offset += 2 + name_len;
1662 /* process type */
1663 if ((flags & JXTAMSG1_ELMFLAG_TYPE) != 0) {
1664 uint16_t type_len = tvb_get_ntohs(tvb, tree_offset);
1665 proto_tree_add_item(jxta_elem_tree, hf_jxta_element_type, tvb, tree_offset, 2, ENC_ASCII|ENC_BIG_ENDIAN);
1666 tree_offset += 2;
1668 mediatype = tvb_get_string_enc(pinfo->pool, tvb, tree_offset, type_len, ENC_ASCII);
1670 tree_offset += type_len;
1673 /* process encoding */
1674 if ((flags & JXTAMSG1_ELMFLAG_ENCODING) != 0) {
1675 uint16_t encoding_len = tvb_get_ntohs(tvb, tree_offset);
1676 proto_tree_add_item(jxta_elem_tree, hf_jxta_element_encoding, tvb, tree_offset, 2, ENC_ASCII|ENC_BIG_ENDIAN);
1677 tree_offset += 2 + encoding_len;
1680 /* content */
1681 content_len = tvb_get_ntohl(tvb, tree_offset);
1682 proto_tree_add_item(jxta_elem_tree, hf_jxta_element_content_len, tvb, tree_offset, 4, ENC_BIG_ENDIAN);
1683 tree_offset += 4;
1685 element_content_tvb = tvb_new_subset_length(tvb, tree_offset, content_len);
1687 tree_offset += dissect_media(mediatype, element_content_tvb, pinfo, jxta_elem_tree);
1689 /* process the signature element */
1690 if ((flags & JXTAMSG1_ELMFLAG_SIGNATURE) != 0) {
1691 tvbuff_t *jxta_message_element_tvb = tvb_new_subset_remaining(tvb, tree_offset);
1693 increment_dissection_depth(pinfo);
1694 tree_offset += dissect_jxta_message_element_1(jxta_message_element_tvb, pinfo, jxta_elem_tree, ns_count, names_table);
1695 decrement_dissection_depth(pinfo);
1698 proto_item_set_end(jxta_elem_tree_item, tvb, tree_offset);
1700 // offset is based on reported lengths. tree_offset is based on captured lengths via dissect_media.
1701 // Comment this out for now in favor of dissect_media's expert warning.
1702 // DISSECTOR_ASSERT(tree_offset == offset);
1704 return offset;
1708 * Dissect a tvbuff containing a JXTA Message Element (Version 2).
1710 * @param tvb The buffer to dissect.
1711 * @param pinfo Packet Info.
1712 * @param tree The protocol tree.
1713 * @param names_count The number of elements in the names table.
1714 * @param names_table The table of names.
1715 * @return Number of bytes from the tvbuff_t which were processed, 0 (zero) if
1716 * the packet was not recognized as a JXTA packet and negative if the
1717 * dissector needs more bytes in order to process a PDU.
1719 // NOLINTNEXTLINE(misc-no-recursion)
1720 static int dissect_jxta_message_element_2(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, unsigned names_count,
1721 const char ** names_table)
1723 unsigned offset = 0;
1724 unsigned available;
1725 int needed = 0;
1726 uint8_t flags;
1728 /* First pass. Make sure all of the bytes we need are available */
1730 while (true) {
1731 /* signature field */
1732 available = tvb_reported_length_remaining(tvb, offset);
1733 if (available < sizeof(JXTA_MSGELEM_SIG)) {
1734 needed = (int) (sizeof(JXTA_MSGELEM_SIG) - available);
1737 if (tvb_memeql(tvb, offset, (const uint8_t*)JXTA_MSGELEM_SIG, sizeof(JXTA_MSGELEM_SIG)) != 0) {
1738 /* It is not one of ours */
1739 return 0;
1742 offset += (int)sizeof(JXTA_MSGELEM_SIG);
1744 /* flags field */
1745 available = tvb_reported_length_remaining(tvb, offset);
1746 if (available < 1) {
1747 needed = 1;
1748 break;
1749 } else {
1750 flags = tvb_get_uint8(tvb, offset);
1751 offset++;
1754 /* namespace id field */
1755 available = tvb_reported_length_remaining(tvb, offset);
1756 if (available < 2) {
1757 needed = (int) (2 - available);
1758 break;
1761 offset += 2;
1763 /* name field */
1764 if ((flags & JXTAMSG2_ELMFLAG_NAME_LITERAL) == 0) {
1765 available = tvb_reported_length_remaining(tvb, offset);
1766 if (available < 2) {
1767 needed = (int) (2 - available);
1768 break;
1771 offset += 2;
1772 } else {
1773 /* literal name field */
1774 available = tvb_reported_length_remaining(tvb, offset);
1775 if (available < 2) {
1776 needed = (int) (2 - available);
1777 break;
1778 } else {
1779 uint16_t name_len = tvb_get_ntohs(tvb, offset);
1780 offset += 2;
1782 available = tvb_reported_length_remaining(tvb, offset);
1783 if (available < name_len) {
1784 needed = (int) (name_len - available);
1785 break;
1788 offset += name_len;
1792 /* type field */
1793 if ((flags & JXTAMSG2_ELMFLAG_TYPE) != 0) {
1794 available = tvb_reported_length_remaining(tvb, offset);
1795 if (available < 2) {
1796 needed = (int) (2 - available);
1797 break;
1800 offset += 2;
1803 /* encoding field */
1804 if ((flags & JXTAMSG2_ELMFLAG_ENCODINGS) != 0) {
1805 available = tvb_reported_length_remaining(tvb, offset);
1806 if (available < 2) {
1807 needed = (int) (2 - available);
1808 break;
1811 offset += 2;
1815 /* content field */
1816 if ((flags & JXTAMSG2_ELMFLAG_UINT64_LENS) != 0) {
1817 available = tvb_reported_length_remaining(tvb, offset);
1818 if (available < sizeof(uint64_t)) {
1819 needed = (int) (sizeof(uint64_t) - available);
1820 break;
1821 } else {
1822 uint64_t content_len = tvb_get_ntoh64(tvb, offset);
1823 offset += (int)sizeof(uint64_t);
1825 available = tvb_reported_length_remaining(tvb, offset);
1826 if (available < content_len) {
1827 needed = (int) (content_len - available);
1828 break;
1831 offset += (unsigned) content_len;
1833 } else {
1834 available = tvb_reported_length_remaining(tvb, offset);
1835 if (available < 4) {
1836 needed = (int) (4 - available);
1837 break;
1838 } else {
1839 uint64_t content_len = tvb_get_ntohl(tvb, offset);
1840 offset += 4;
1842 available = tvb_reported_length_remaining(tvb, offset);
1843 if (available < content_len) {
1844 needed = (int) (content_len - available);
1845 break;
1848 offset += (unsigned) content_len;
1852 /* signature element field */
1853 if ((flags & JXTAMSG2_ELMFLAG_SIGNATURE) != 0) {
1854 tvbuff_t *jxta_signature_element_tvb;
1855 int processed;
1857 jxta_signature_element_tvb = tvb_new_subset_remaining(tvb, offset);
1859 increment_dissection_depth(pinfo);
1860 processed = dissect_jxta_message_element_2(jxta_signature_element_tvb, pinfo, NULL, 0, NULL);
1861 decrement_dissection_depth(pinfo);
1863 if (processed == 0) {
1864 return offset;
1867 if (processed < 0) {
1868 needed = -processed;
1869 break;
1872 offset += processed;
1875 break;
1878 if ((needed > 0) && gDESEGMENT && pinfo->can_desegment) {
1879 /* ws_message( "Element2 requesting %d more bytes", needed ); */
1880 pinfo->desegment_offset = 0;
1881 pinfo->desegment_len = needed;
1882 return -needed;
1885 /* Second (optional) pass : build the proto tree */
1886 unsigned tree_offset = 0;
1887 proto_item *jxta_elem_tree_item = proto_tree_add_item(tree, hf_jxta_element, tvb, tree_offset, -1, ENC_NA);
1888 proto_tree *jxta_elem_tree = proto_item_add_subtree(jxta_elem_tree_item, ett_jxta_elem);
1889 uint16_t namespaceID;
1890 proto_item *namespace_ti;
1891 uint16_t nameID;
1892 proto_item *name_ti;
1893 uint64_t content_len;
1894 const char *mediatype = NULL;
1895 tvbuff_t *element_content_tvb;
1896 static int * const element_flags[] = {
1897 &hf_jxta_element2_flag_64bitlens,
1898 &hf_jxta_element2_flag_nameLiteral,
1899 &hf_jxta_element2_flag_hasType,
1900 &hf_jxta_element2_flag_hasSignature,
1901 &hf_jxta_element2_flag_hasEncoding,
1902 &hf_jxta_element2_flag_sigOfEncoded,
1903 NULL
1906 proto_tree_add_item(jxta_elem_tree, hf_jxta_element_sig, tvb, tree_offset, (int)sizeof(JXTA_MSGELEM_SIG), ENC_ASCII);
1907 tree_offset += (int)sizeof(JXTA_MSGELEM_SIG);
1909 flags = tvb_get_uint8(tvb, tree_offset);
1910 proto_tree_add_bitmask(jxta_elem_tree, tvb, tree_offset, hf_jxta_element_flags, ett_jxta_elem_2_flags, element_flags, ENC_NA);
1911 tree_offset += 1;
1913 /* Namespace */
1914 namespaceID = tvb_get_ntohs(tvb, tree_offset);
1915 namespace_ti =
1916 proto_tree_add_uint(jxta_elem_tree, hf_jxta_element2_namespaceid, tvb, tree_offset, 2, namespaceID);
1917 if (namespaceID < names_count) {
1918 proto_item_append_text(namespace_ti, " (%s)", names_table[namespaceID]);
1919 } else {
1920 proto_item_append_text(namespace_ti, " * BAD *");
1922 tree_offset += 2;
1924 /* Name */
1925 if ((flags & JXTAMSG2_ELMFLAG_NAME_LITERAL) == 0) {
1926 nameID = tvb_get_ntohs(tvb, tree_offset);
1927 name_ti =
1928 proto_tree_add_uint(jxta_elem_tree, hf_jxta_element2_nameid, tvb, tree_offset, 2, nameID);
1929 if (nameID < names_count) {
1930 proto_item_append_text(name_ti, " (%s)", names_table[nameID]);
1931 } else {
1932 proto_item_append_text(name_ti, " * BAD *");
1934 tree_offset += 2;
1935 } else {
1936 /* literal name */
1937 uint16_t name_len = tvb_get_ntohs(tvb, tree_offset);
1938 proto_item_append_text(jxta_elem_tree_item, " \"%s\"", tvb_format_text(pinfo->pool, tvb, tree_offset + 2, name_len));
1939 proto_tree_add_item(jxta_elem_tree, hf_jxta_element_name, tvb, tree_offset, 2, ENC_ASCII|ENC_BIG_ENDIAN);
1940 tree_offset += 2 + name_len;
1943 /* process type */
1944 if ((flags & JXTAMSG2_ELMFLAG_TYPE) != 0) {
1945 uint16_t mimeID = tvb_get_ntohs(tvb, tree_offset);
1946 proto_item *mime_ti =
1947 proto_tree_add_uint(jxta_elem_tree, hf_jxta_element2_mimeid, tvb, tree_offset, 2, mimeID);
1949 if (mimeID < names_count) {
1950 proto_item_append_text(mime_ti, " (%s)", names_table[mimeID]);
1951 mediatype = wmem_strdup( pinfo->pool, names_table[mimeID] );
1952 } else {
1953 proto_item_append_text(mime_ti, " * BAD *");
1956 tree_offset += 2;
1957 } else {
1958 mediatype = "application/octet-stream";
1961 /* process encoding */
1962 if ((flags & JXTAMSG2_ELMFLAG_ENCODINGS) != 0) {
1963 uint16_t encodingID = tvb_get_ntohs(tvb, tree_offset);
1964 proto_item *encoding_ti =
1965 proto_tree_add_uint(jxta_elem_tree, hf_jxta_element2_encodingid, tvb, tree_offset, 2, encodingID);
1967 if (encodingID < names_count) {
1968 proto_item_append_text(encoding_ti, " (%s)", names_table[encodingID]);
1969 } else {
1970 proto_item_append_text(encoding_ti, " * BAD *");
1973 tree_offset += 2;
1977 if ((flags & JXTAMSG2_ELMFLAG_UINT64_LENS) != 0) {
1978 content_len = tvb_get_ntoh64(tvb, tree_offset);
1979 proto_tree_add_item(jxta_elem_tree, hf_jxta_element_content_len64, tvb, tree_offset, 8, ENC_BIG_ENDIAN);
1980 tree_offset += 8;
1981 } else {
1982 content_len = tvb_get_ntohl(tvb, tree_offset);
1983 proto_tree_add_item(jxta_elem_tree, hf_jxta_element_content_len, tvb, tree_offset, 4, ENC_BIG_ENDIAN);
1984 tree_offset += 4;
1987 /* content */
1988 element_content_tvb = tvb_new_subset_length(tvb, tree_offset, (int)content_len);
1990 tree_offset += dissect_media(mediatype, element_content_tvb, pinfo, jxta_elem_tree);
1992 /* process the signature element */
1993 if ((flags & JXTAMSG2_ELMFLAG_SIGNATURE) != 0) {
1994 tvbuff_t *jxta_message_element_tvb = tvb_new_subset_remaining(tvb, tree_offset);
1996 tree_offset += dissect_jxta_message_element_1(jxta_message_element_tvb, pinfo, jxta_elem_tree, names_count, names_table);
1999 proto_item_set_end(jxta_elem_tree_item, tvb, tree_offset);
2001 // offset is based on reported lengths. tree_offset is based on captured lengths via dissect_media.
2002 // Comment this out for now in favor of dissect_media's expert warning.
2003 // DISSECTOR_ASSERT(tree_offset == offset);
2005 return offset;
2009 * Dissect a tvbuff containing arbitrary typed data.
2011 * <p/>We provide special handling for type media types :
2012 * <dl>
2013 * <dt>application/x-jxta-tls-block</dt>
2014 * <dd>We hand this data off to SSL to dissect.</dd>
2015 * <dt>application/gzip</dt>
2016 * <dd>We decompress the data and then dissect the contents as <tt>text/xml;charset="UTF-8"</tt></dd>
2017 * </dl>
2019 * @param fullmediatype The full media type of the buffer to dissect including params
2020 * @param tvb The buffer to dissect.
2021 * @param pinfo Packet Info.
2022 * @param tree The protocol tree.
2023 * @return Number of bytes from the tvbuff_t which were processed, 0 (zero) if
2024 * the packet was not recognized and negative if the dissector needs
2025 * more bytes in order to process a PDU.
2027 // NOLINTNEXTLINE(misc-no-recursion)
2028 static int dissect_media( const char* fullmediatype, tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree) {
2029 int dissected = 0;
2031 if (fullmediatype) {
2032 char *mediatype = wmem_strdup(pinfo->pool, fullmediatype);
2033 char *parms_at = strchr(mediatype, ';');
2034 const char *save_match_string = pinfo->match_string;
2035 media_content_info_t content_info = { MEDIA_CONTAINER_OTHER, NULL, NULL, NULL };
2037 /* Based upon what is done in packet-media.c we set up type and params */
2038 if (NULL != parms_at) {
2039 content_info.media_str = wmem_strdup( pinfo->pool, parms_at + 1 );
2040 *parms_at = '\0';
2043 /* Set the version that goes to packet-media.c before converting case */
2044 pinfo->match_string = wmem_strdup(pinfo->pool, mediatype);
2046 /* force to lower case */
2047 ascii_strdown_inplace(mediatype);
2049 if (0 == strcmp("application/x-jxta-tls-block", mediatype)) {
2050 /* If we recognize it as a TLS packet then we shuffle it off to tls dissector. */
2051 if (NULL != tls_handle) {
2052 dissected = call_dissector(tls_handle, tvb, pinfo, tree);
2054 } else if (0 == strcmp("application/gzip", mediatype)) {
2055 tvbuff_t *uncomp_tvb = tvb_child_uncompress_zlib(tvb, tvb, 0, tvb_captured_length(tvb));
2057 if( NULL != uncomp_tvb ) {
2058 add_new_data_source(pinfo, uncomp_tvb, "Uncompressed Element Content");
2060 /* XXX bondolo 20060201 Force XML for uncompressed data. */
2061 increment_dissection_depth(pinfo);
2062 dissected = dissect_media("text/xml;charset=\"UTF-8\"", uncomp_tvb, pinfo, tree);
2063 decrement_dissection_depth(pinfo);
2065 if( dissected > 0 ) {
2066 /* report back the uncompressed length. */
2067 dissected = tvb_captured_length(tvb);
2070 } else {
2071 dissected = dissector_try_string_with_data(media_type_dissector_table, mediatype, tvb, pinfo, tree, true, &content_info) ? tvb_captured_length(tvb) : 0;
2073 if( dissected != (int) tvb_captured_length(tvb) ) {
2074 /* ws_message( "%s : %d expected, %d dissected", mediatype, tvb_captured_length(tvb), dissected ); */
2078 if (0 == dissected) {
2079 dissected = call_dissector_with_data(media_handle, tvb, pinfo, tree, &content_info);
2082 pinfo->match_string = save_match_string;
2085 if(0 == dissected) {
2086 /* display it as raw data */
2087 dissected = call_data_dissector(tvb, pinfo, tree);
2090 if (dissected < (int) tvb_reported_length(tvb)) {
2091 proto_item *item = proto_tree_add_expert(tree, pinfo, &ei_media_too_short, tvb, 0, dissected);
2092 proto_item_set_generated(item);
2094 return dissected;
2098 * Register jxta protocol and jxta message protocol, header fields, subtree types, preferences.
2100 void proto_register_jxta(void)
2102 module_t *jxta_module;
2103 expert_module_t *expert_jxta;
2105 /** our header fields */
2106 static hf_register_info hf[] = {
2107 {&hf_uri_addr,
2108 {"Address", "jxta.uri.addr", FT_STRING, BASE_NONE, NULL, 0x0,
2109 "URI Address (source or destination)", HFILL}
2111 {&hf_uri_src,
2112 {"Source", "jxta.uri.src", FT_STRING, BASE_NONE, NULL, 0x0,
2113 "URI Source", HFILL}
2115 {&hf_uri_dst,
2116 {"Destination", "jxta.uri.dst", FT_STRING, BASE_NONE, NULL, 0x0,
2117 "URI Destination", HFILL}
2119 {&hf_jxta_udp,
2120 {"JXTA UDP", "jxta.udp", FT_NONE, BASE_NONE, NULL, 0x0,
2121 NULL, HFILL}
2123 {&hf_jxta_udpsig,
2124 {"Signature", "jxta.udpsig", FT_STRING, BASE_NONE, NULL, 0x0,
2125 "JXTA UDP Signature", HFILL}
2127 {&hf_jxta_welcome,
2128 {"Welcome", "jxta.welcome", FT_NONE, BASE_NONE, NULL, 0x00,
2129 "JXTA Connection Welcome Message", HFILL}
2131 {&hf_jxta_welcome_initiator,
2132 {"Initiator", "jxta.welcome.initiator", FT_BOOLEAN, BASE_NONE, NULL, 0x00,
2133 "JXTA Connection Welcome Message Initiator", HFILL}
2135 {&hf_jxta_welcome_sig,
2136 {"Signature", "jxta.welcome.signature", FT_STRING, BASE_NONE, NULL, 0x0,
2137 "JXTA Connection Welcome Message Signature", HFILL}
2139 {&hf_jxta_welcome_destAddr,
2140 {"Destination Address", "jxta.welcome.destAddr", FT_STRING, BASE_NONE, NULL, 0x0,
2141 "JXTA Connection Welcome Message Destination Address", HFILL}
2143 {&hf_jxta_welcome_pubAddr,
2144 {"Public Address", "jxta.welcome.pubAddr", FT_STRING, BASE_NONE, NULL, 0x0,
2145 "JXTA Connection Welcome Message Public Address", HFILL}
2147 {&hf_jxta_welcome_peerid,
2148 {"PeerID", "jxta.welcome.peerid", FT_STRING, BASE_NONE, NULL, 0x0,
2149 "JXTA Connection Welcome Message PeerID", HFILL}
2151 {&hf_jxta_welcome_noProp,
2152 {"No Propagate Flag", "jxta.welcome.noPropFlag", FT_STRING, BASE_NONE, NULL, 0x0,
2153 "JXTA Connection Welcome Message No Propagate Flag", HFILL}
2155 {&hf_jxta_welcome_msgVers,
2156 {"Preferred Message Version", "jxta.welcome.msgVersion", FT_STRING, BASE_NONE, NULL, 0x0,
2157 "JXTA Connection Welcome Message Preferred Message Version", HFILL}
2159 {&hf_jxta_welcome_variable,
2160 {"Variable Parameter", "jxta.welcome.variable", FT_STRING, BASE_NONE, NULL, 0x0,
2161 "JXTA Connection Welcome Message Variable Parameter", HFILL}
2163 {&hf_jxta_welcome_version,
2164 {"Version", "jxta.welcome.version", FT_STRING, BASE_NONE, NULL, 0x0,
2165 "JXTA Connection Welcome Message Version", HFILL}
2167 {&hf_jxta_framing,
2168 {"Framing", "jxta.framing", FT_NONE, BASE_NONE, NULL, 0x0,
2169 "JXTA Message Framing", HFILL}
2171 {&hf_jxta_framing_header,
2172 {"Header", "jxta.framing.header", FT_NONE, BASE_NONE, NULL, 0x0,
2173 "JXTA Message Framing Header", HFILL}
2175 {&hf_jxta_framing_header_name,
2176 {"Name", "jxta.framing.header.name", FT_UINT_STRING, BASE_NONE, NULL, 0x0,
2177 "JXTA Message Framing Header Name", HFILL}
2179 {&hf_jxta_framing_header_value_length,
2180 {"Value Length", "jxta.framing.header.valuelen", FT_UINT16, BASE_DEC, NULL, 0x0,
2181 "JXTA Message Framing Header Value Length", HFILL}
2183 {&hf_jxta_framing_header_value,
2184 {"Value", "jxta.framing.header.value", FT_BYTES, BASE_NONE, NULL, 0x0,
2185 "JXTA Message Framing Header Value", HFILL}
2187 {&hf_jxta_message_address,
2188 {"Address", "jxta.message.address", FT_STRING, BASE_NONE, NULL, 0x0,
2189 "JXTA Message Address (source or destination)", HFILL}
2191 {&hf_jxta_message_src,
2192 {"Source", "jxta.message.source", FT_STRING, BASE_NONE, NULL, 0x0,
2193 "JXTA Message Source", HFILL}
2195 {&hf_jxta_message_dst,
2196 {"Destination", "jxta.message.destination", FT_STRING, BASE_NONE, NULL, 0x0,
2197 "JXTA Message Destination", HFILL}
2199 {&hf_jxta_message_sig,
2200 {"Signature", "jxta.message.signature", FT_STRING, BASE_NONE, NULL, 0x0,
2201 "JXTA Message Signature", HFILL}
2203 {&hf_jxta_message_version,
2204 {"Version", "jxta.message.version", FT_UINT8, BASE_DEC, NULL, 0x0,
2205 "JXTA Message Version", HFILL}
2207 {&hf_jxta_message_flags,
2208 {"Flags", "jxta.message.flags", FT_UINT8, BASE_HEX, NULL, 0x0,
2209 "JXTA Message Flags", HFILL}
2211 {&hf_jxta_message_flag_utf16be,
2212 {"UTF16BE", "jxta.message.flags.UTF-16BE", FT_BOOLEAN, 2, TFS(&tfs_set_notset), 0x1,
2213 "JXTA Message Element Flag -- UTF16-BE Strings", HFILL}
2215 {&hf_jxta_message_flag_ucs32be,
2216 {"UCS32BE", "jxta.message.flags.UCS32BE", FT_BOOLEAN, 2, TFS(&tfs_set_notset), 0x2,
2217 "JXTA Message Flag -- UCS32-BE Strings", HFILL}
2219 {&hf_jxta_message_names_count,
2220 {"Names Count", "jxta.message.names", FT_UINT16, BASE_DEC, NULL, 0x0,
2221 "JXTA Message Names Table", HFILL}
2223 {&hf_jxta_message_names_name,
2224 {"Names Table Name", "jxta.message.names.name", FT_UINT_STRING, BASE_NONE, NULL, 0x0,
2225 "JXTA Message Names Table Name", HFILL}
2227 {&hf_jxta_message_element_count,
2228 {"Element Count", "jxta.message.elements", FT_UINT16, BASE_DEC, NULL, 0x0,
2229 "JXTA Message Element Count", HFILL}
2231 {&hf_jxta_element,
2232 {"JXTA Message Element", "jxta.message.element", FT_NONE, BASE_NONE, NULL, 0x0,
2233 NULL, HFILL}
2235 {&hf_jxta_element_sig,
2236 {"Signature", "jxta.message.element.signature", FT_STRING, BASE_NONE, NULL, 0x0,
2237 "JXTA Message Element Signature", HFILL}
2239 {&hf_jxta_element1_namespaceid,
2240 {"Namespace ID", "jxta.message.element.namespaceid", FT_UINT8, BASE_DEC, NULL, 0x0,
2241 "JXTA Message Element Namespace ID", HFILL}
2243 {&hf_jxta_element2_namespaceid,
2244 {"Namespace ID", "jxta.message.element.namespaceid", FT_UINT16, BASE_DEC, NULL, 0x0,
2245 "JXTA Message Element Namespace ID", HFILL}
2247 {&hf_jxta_element_flags,
2248 {"Flags", "jxta.message.element.flags", FT_UINT8, BASE_HEX, NULL, 0x0,
2249 "JXTA Message Element Flags", HFILL}
2251 {&hf_jxta_element1_flag_hasType,
2252 {"hasType", "jxta.message.element.flags.hasType", FT_BOOLEAN, 3, TFS(&tfs_set_notset), 0x1,
2253 "JXTA Message Element Flag -- hasType", HFILL}
2255 {&hf_jxta_element1_flag_hasEncoding,
2256 {"hasEncoding", "jxta.message.element.flags.hasEncoding", FT_BOOLEAN, 3, TFS(&tfs_set_notset), 0x2,
2257 "JXTA Message Element Flag -- hasEncoding", HFILL}
2259 {&hf_jxta_element1_flag_hasSignature,
2260 {"hasSignature", "jxta.message.element.flags.hasSignature", FT_BOOLEAN, 3, TFS(&tfs_set_notset), 0x4,
2261 "JXTA Message Element Flag -- hasSignature", HFILL}
2263 {&hf_jxta_element2_flag_64bitlens,
2264 {"uint64Lens", "jxta.message.element.flags.uint64Lens", FT_BOOLEAN, 6, TFS(&tfs_set_notset), 0x01,
2265 "JXTA Message Element Flag -- uint64Lens", HFILL}
2267 {&hf_jxta_element2_flag_nameLiteral,
2268 {"nameLiteral", "jxta.message.element.flags.nameLiteral", FT_BOOLEAN, 6, TFS(&tfs_set_notset), 0x02,
2269 "JXTA Message Element Flag -- nameLiteral", HFILL}
2271 {&hf_jxta_element2_flag_hasType,
2272 {"hasType", "jxta.message.element.flags.hasType", FT_BOOLEAN, 6, TFS(&tfs_set_notset), 0x04,
2273 "JXTA Message Element Flag -- hasType", HFILL}
2275 {&hf_jxta_element2_flag_hasSignature,
2276 {"hasSignature", "jxta.message.element.flags.hasSignature", FT_BOOLEAN, 6, TFS(&tfs_set_notset), 0x08,
2277 "JXTA Message Element Flag -- hasSignature", HFILL}
2279 {&hf_jxta_element2_flag_hasEncoding,
2280 {"hasSignature", "jxta.message.element.flags.hasEncoding", FT_BOOLEAN, 6, TFS(&tfs_set_notset), 0x10,
2281 "JXTA Message Element Flag -- hasEncoding", HFILL}
2283 {&hf_jxta_element2_flag_sigOfEncoded,
2284 {"sigOfEncoded", "jxta.message.element.flags.sigOfEncoded", FT_BOOLEAN, 6, TFS(&tfs_set_notset), 0x20,
2285 "JXTA Message Element Flag -- sigOfEncoded", HFILL}
2287 {&hf_jxta_element2_nameid,
2288 {"Name ID", "jxta.message.element.nameid", FT_UINT16, BASE_DEC, NULL, 0x0,
2289 "JXTA Message Element Name ID", HFILL}
2291 {&hf_jxta_element_name,
2292 {"Element Name", "jxta.message.element.name", FT_UINT_STRING, BASE_NONE, NULL, 0x0,
2293 "JXTA Message Element Name", HFILL}
2295 {&hf_jxta_element2_mimeid,
2296 {"MIME ID", "jxta.message.element.mimeid", FT_UINT16, BASE_DEC, NULL, 0x0,
2297 "JXTA Message Element MIME ID", HFILL}
2299 {&hf_jxta_element2_encodingid,
2300 {"Encoding ID", "jxta.message.element.encodingid", FT_UINT16, BASE_DEC, NULL, 0x0,
2301 "JXTA Message Element Encoding ID", HFILL}
2303 {&hf_jxta_element_type,
2304 {"Element Type", "jxta.message.element.type", FT_UINT_STRING, BASE_NONE, NULL, 0x0,
2305 "JXTA Message Element Name", HFILL}
2307 {&hf_jxta_element_encoding,
2308 {"Element Type", "jxta.message.element.encoding", FT_UINT_STRING, BASE_NONE, NULL, 0x0,
2309 "JXTA Message Element Encoding", HFILL}
2311 {&hf_jxta_element_content_len,
2312 {"Element Content Length", "jxta.message.element.content.length", FT_UINT32, BASE_DEC, NULL, 0x0,
2313 "JXTA Message Element Content Length", HFILL}
2315 {&hf_jxta_element_content_len64,
2316 {"Element Content Length", "jxta.message.element.content.length64", FT_UINT64, BASE_DEC, NULL, 0x0,
2317 "JXTA Message Element Content Length", HFILL}
2319 #if 0
2320 {&hf_jxta_element_content,
2321 {"Element Content", "jxta.message.element.content", FT_BYTES, BASE_NONE, NULL, 0x0,
2322 "JXTA Message Element Content", HFILL}
2324 #endif
2327 static ei_register_info ei[] = {
2328 { &ei_media_too_short, { "jxta.media_too_short", PI_PROTOCOL, PI_WARN, "Media length less than expected", EXPFILL }},
2332 * JXTA Protocol subtree array
2334 static int *ett[] = {
2335 &ett_jxta,
2336 &ett_jxta_welcome,
2337 &ett_jxta_udp,
2338 &ett_jxta_framing,
2339 &ett_jxta_framing_header,
2340 &ett_jxta_msg,
2341 &ett_jxta_msg_flags,
2342 &ett_jxta_elem,
2343 &ett_jxta_elem_1_flags,
2344 &ett_jxta_elem_2_flags
2347 proto_jxta = proto_register_protocol("JXTA P2P", "JXTA", "jxta");
2349 jxta_tap = register_tap("jxta");
2351 proto_message_jxta = proto_register_protocol("JXTA Message", "JXTA Message", "jxta.message");
2353 jxta_udp_handle = register_dissector("jxta.udp", dissect_jxta_udp, proto_jxta);
2354 stream_jxta_handle = register_dissector("jxta.stream", dissect_jxta_stream, proto_jxta);
2356 /* Register header fields */
2357 proto_register_field_array(proto_jxta, hf, array_length(hf));
2359 /* Register JXTA Sub-tree */
2360 proto_register_subtree_array(ett, array_length(ett));
2362 expert_jxta = expert_register_protocol(proto_jxta);
2363 expert_register_field_array(expert_jxta, ei, array_length(ei));
2365 uri_address_type = address_type_dissector_register("AT_URI", "URI/URL/URN", uri_to_str, uri_str_len, NULL, uri_col_filter_str, NULL, NULL, NULL);
2367 /* Register preferences */
2368 /* register re-init routine */
2369 jxta_module = prefs_register_protocol(proto_jxta, proto_reg_handoff_jxta);
2371 prefs_register_bool_preference(jxta_module, "msg.mediatype", "Register binary JXTA Message as a media type",
2372 "Enable to have correctly typed MIME media dissected as JXTA Messages.", &gMSG_MEDIA);
2374 prefs_register_bool_preference(jxta_module, "desegment",
2375 "Reassemble JXTA messages spanning multiple UDP/TCP/SCTP segments",
2376 "Whether the JXTA dissector should reassemble messages spanning multiple UDP/TCP/SCTP segments."
2377 " To use this option you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings "
2378 " and enable \"Reassemble fragmented IP datagrams\" in the IP protocol settings.",
2379 &gDESEGMENT);
2381 prefs_register_obsolete_preference(jxta_module, "udp.heuristic");
2382 prefs_register_obsolete_preference(jxta_module, "tcp.heuristic");
2383 prefs_register_obsolete_preference(jxta_module, "sctp.heuristic");
2385 register_conversation_table(proto_jxta, true, jxta_conversation_packet, jxta_endpoint_packet);
2390 * Update registrations in response to preferences changes.
2392 void proto_reg_handoff_jxta(void)
2394 static bool init_done = false;
2395 static dissector_handle_t message_jxta_handle;
2397 static bool msg_media_register_done = false;
2399 if(!init_done) {
2400 message_jxta_handle = create_dissector_handle(dissect_jxta_message, proto_message_jxta);
2402 media_type_dissector_table = find_dissector_table("media_type");
2403 tls_handle = find_dissector_add_dependency("tls", proto_jxta);
2405 media_handle = find_dissector_add_dependency("media", proto_jxta);
2407 heur_dissector_add("udp", dissect_jxta_UDP_heur, "JXTA over UDP", "jxta_udp", proto_jxta, HEURISTIC_ENABLE);
2408 heur_dissector_add("tcp", dissect_jxta_TCP_heur, "JXTA over TCP", "jxta_tcp", proto_jxta, HEURISTIC_ENABLE);
2409 heur_dissector_add("sctp", dissect_jxta_SCTP_heur, "JXTA over SCTP", "jxta_sctp", proto_jxta, HEURISTIC_ENABLE);
2411 init_done = true;
2414 if( gMSG_MEDIA ) {
2415 if( !msg_media_register_done ) {
2416 /* ws_message( "Registering JXTA Message media type" ); */
2417 dissector_add_string("media_type", "application/x-jxta-msg", message_jxta_handle);
2418 msg_media_register_done = true;
2420 } else {
2421 if( msg_media_register_done ) {
2422 /* ws_message( "Deregistering JXTA Message media type" ); */
2423 dissector_delete_string("media_type", "application/x-jxta-msg", message_jxta_handle);
2424 msg_media_register_done = false;
2430 * Editor modelines - https://www.wireshark.org/tools/modelines.html
2432 * Local variables:
2433 * c-basic-offset: 4
2434 * tab-width: 8
2435 * indent-tabs-mode: nil
2436 * End:
2438 * vi: set shiftwidth=4 tabstop=8 expandtab:
2439 * :indentSize=4:tabSize=8:noTabs=true: