/src/wireshark/epan/dissectors/packet-jxta.c
Line | Count | Source |
1 | | /* packet-jxta.c |
2 | | * |
3 | | * Routines for JXTA packet dissection |
4 | | * JXTA specification from https://jxta-spec.dev.java.net (now at https://github.com/chaupal/jxta-spec ?) |
5 | | * |
6 | | * Copyright 2004-08, Mike Duigou <bondolo@dev.java.net> |
7 | | * |
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 |
12 | | * |
13 | | * Wireshark - Network traffic analyzer |
14 | | * By Gerald Combs <gerald@wireshark.org> |
15 | | * Copyright 2000 Gerald Combs |
16 | | * |
17 | | * SPDX-License-Identifier: GPL-2.0-or-later |
18 | | */ |
19 | | |
20 | | #include "config.h" |
21 | | |
22 | 0 | #define WS_LOG_DOMAIN "jxta" |
23 | | |
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> |
34 | | |
35 | | #include "packet-jxta.h" |
36 | | #include "packet-media-type.h" |
37 | | |
38 | | void proto_register_jxta(void); |
39 | | void proto_reg_handoff_jxta(void); |
40 | | |
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' }; |
44 | | |
45 | | static const char JXTA_WELCOME_MSG_SIG[] = { 'J', 'X', 'T', 'A', 'H', 'E', 'L', 'L', 'O', ' ' }; |
46 | | |
47 | | static const char* JXTA_WELCOME_MSG_VERSION_1_1 = "1.1"; |
48 | | static const char* JXTA_WELCOME_MSG_VERSION_3_0 = "3.0"; |
49 | | |
50 | | static const int JXTA_MSG_VERSION_1; |
51 | | static const int JXTA_MSG_VERSION_2 = 1; |
52 | | |
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; |
56 | | |
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; |
62 | | |
63 | | static int proto_jxta; |
64 | | static int proto_message_jxta; |
65 | | static int jxta_tap; |
66 | | |
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; |
71 | | |
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; */ |
126 | | |
127 | | /** |
128 | | * JXTA Protocol subtree handles |
129 | | **/ |
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; |
140 | | |
141 | | static expert_field ei_media_too_short; |
142 | | |
143 | | static int uri_address_type = -1; |
144 | | |
145 | | /** |
146 | | * global preferences |
147 | | **/ |
148 | | static bool gDESEGMENT = true; |
149 | | static bool gMSG_MEDIA = true; |
150 | | |
151 | | static dissector_handle_t jxta_udp_handle; |
152 | | |
153 | | /** |
154 | | * Stream Conversation data |
155 | | **/ |
156 | | struct jxta_stream_conversation_data { |
157 | | port_type tpt_ptype; |
158 | | |
159 | | address initiator_tpt_address; |
160 | | uint32_t initiator_tpt_port; |
161 | | uint32_t initiator_welcome_frame; |
162 | | address initiator_address; |
163 | | |
164 | | address receiver_tpt_address; |
165 | | uint32_t receiver_tpt_port; |
166 | | uint32_t receiver_welcome_frame; |
167 | | address receiver_address; |
168 | | }; |
169 | | |
170 | | typedef struct jxta_stream_conversation_data jxta_stream_conversation_data; |
171 | | |
172 | | static const char* jxta_conv_get_filter_type(conv_item_t* conv, conv_filter_type_e filter) |
173 | 0 | { |
174 | 0 | if ((filter == CONV_FT_SRC_ADDRESS) && (conv->src_address.type == uri_address_type)) |
175 | 0 | return "jxta.message.src"; |
176 | | |
177 | 0 | if ((filter == CONV_FT_DST_ADDRESS) && (conv->dst_address.type == uri_address_type)) |
178 | 0 | return "jxta.message.dst"; |
179 | | |
180 | 0 | if ((filter == CONV_FT_ANY_ADDRESS) && (conv->src_address.type == uri_address_type)) |
181 | 0 | return "jxta.message.address"; |
182 | | |
183 | 0 | return CONV_FILTER_INVALID; |
184 | 0 | } |
185 | | |
186 | | static ct_dissector_info_t jxta_ct_dissector_info = {&jxta_conv_get_filter_type}; |
187 | | |
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) |
190 | 0 | { |
191 | 0 | conv_hash_t *hash = (conv_hash_t*) pct; |
192 | 0 | hash->flags = flags; |
193 | |
|
194 | 0 | const jxta_tap_header *jxtahdr = (const jxta_tap_header *) vip; |
195 | |
|
196 | 0 | add_conversation_table_data(hash, &jxtahdr->src_address, &jxtahdr->dest_address, |
197 | 0 | 0, 0, 1, jxtahdr->size, NULL, NULL, &jxta_ct_dissector_info, CONVERSATION_NONE); |
198 | |
|
199 | 0 | return TAP_PACKET_REDRAW; |
200 | 0 | } |
201 | | |
202 | | static const char* jxta_endpoint_get_filter_type(endpoint_item_t* endpoint, conv_filter_type_e filter) |
203 | 0 | { |
204 | 0 | if ((filter == CONV_FT_ANY_ADDRESS) && (endpoint->myaddress.type == uri_address_type)) |
205 | 0 | return "jxta.message.address"; |
206 | | |
207 | 0 | return CONV_FILTER_INVALID; |
208 | 0 | } |
209 | | |
210 | | static et_dissector_info_t jxta_endpoint_dissector_info = {&jxta_endpoint_get_filter_type}; |
211 | | |
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) |
214 | 0 | { |
215 | 0 | conv_hash_t *hash = (conv_hash_t*) pit; |
216 | 0 | hash->flags = flags; |
217 | |
|
218 | 0 | const jxta_tap_header *jxtahdr = (const jxta_tap_header *)vip; |
219 | | |
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 | 0 | add_endpoint_table_data(hash, &jxtahdr->src_address, 0, true, 1, jxtahdr->size, &jxta_endpoint_dissector_info, ENDPOINT_NONE); |
224 | 0 | add_endpoint_table_data(hash, &jxtahdr->dest_address, 0, false, 1, jxtahdr->size, &jxta_endpoint_dissector_info, ENDPOINT_NONE); |
225 | 0 | return TAP_PACKET_REDRAW; |
226 | 0 | } |
227 | | |
228 | | static int uri_to_str(const address* addr, char *buf, int buf_len) |
229 | 0 | { |
230 | 0 | int copy_len = addr->len < (buf_len - 1) ? addr->len : (buf_len - 1); |
231 | 0 | memcpy(buf, addr->data, copy_len ); |
232 | 0 | buf[copy_len] = '\0'; |
233 | 0 | return copy_len+1; |
234 | 0 | } |
235 | | |
236 | | static int uri_str_len(const address* addr) |
237 | 0 | { |
238 | 0 | return addr->len+1; |
239 | 0 | } |
240 | | |
241 | | static const char* uri_col_filter_str(const address* addr _U_, bool is_src) |
242 | 0 | { |
243 | 0 | if (is_src) |
244 | 0 | return "uri.src"; |
245 | | |
246 | 0 | return "uri.dst"; |
247 | 0 | } |
248 | | |
249 | | /** |
250 | | * Prototypes |
251 | | **/ |
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); |
256 | | |
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); |
266 | | |
267 | | /** |
268 | | * Heuristically dissect a tvbuff containing a JXTA UDP Message |
269 | | * |
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 |
274 | | **/ |
275 | | static bool dissect_jxta_UDP_heur(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, void * data _U_) |
276 | 1.34k | { |
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! |
280 | | */ |
281 | 1.34k | int save_desegment_offset; |
282 | 1.34k | uint32_t save_desegment_len; |
283 | 1.34k | int ret; |
284 | | |
285 | 1.34k | 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 | 1.33k | return false; |
288 | 1.33k | } |
289 | | |
290 | 11 | save_desegment_offset = pinfo->desegment_offset; |
291 | 11 | save_desegment_len = pinfo->desegment_len; |
292 | 11 | ret = dissect_jxta_udp(tvb, pinfo, tree, NULL); |
293 | | |
294 | | /* ws_message( "%d Heuristic UDP Dissection : %d", pinfo->num, ret ); */ |
295 | | |
296 | 11 | if (ret < 0) { |
297 | | /* |
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. |
303 | | */ |
304 | 0 | pinfo->desegment_offset = save_desegment_offset; |
305 | 0 | pinfo->desegment_len = save_desegment_len; |
306 | 0 | return false; |
307 | 11 | } else if (ret == 0) { |
308 | | /* |
309 | | * A clear rejection. |
310 | | */ |
311 | 11 | pinfo->desegment_offset = save_desegment_offset; |
312 | 11 | pinfo->desegment_len = save_desegment_len; |
313 | 11 | return false; |
314 | 11 | } else { |
315 | | /* |
316 | | * A clear acceptance. |
317 | | */ |
318 | 0 | return true; |
319 | 0 | } |
320 | 11 | } |
321 | | |
322 | | /** |
323 | | * Heuristically dissect a tvbuff containing a JXTA TCP Stream |
324 | | * |
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 |
329 | | **/ |
330 | | static bool dissect_jxta_TCP_heur(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, void * data _U_) |
331 | 3.12k | { |
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! |
335 | | */ |
336 | 3.12k | int save_desegment_offset; |
337 | 3.12k | uint32_t save_desegment_len; |
338 | 3.12k | int ret; |
339 | | |
340 | 3.12k | save_desegment_offset = pinfo->desegment_offset; |
341 | 3.12k | save_desegment_len = pinfo->desegment_len; |
342 | 3.12k | ret = dissect_jxta_stream(tvb, pinfo, tree, NULL); |
343 | | |
344 | | /* ws_message( "%d Heuristic TCP Dissection : %d", pinfo->num, ret ); */ |
345 | | |
346 | 3.12k | if (ret < 0) { |
347 | | /* |
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. |
354 | | * |
355 | | * Therefore, we treat a negative return from |
356 | | * dissect_jxta_stream() as a rejection. |
357 | | * |
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. |
363 | | */ |
364 | 0 | pinfo->desegment_offset = save_desegment_offset; |
365 | 0 | pinfo->desegment_len = save_desegment_len; |
366 | 0 | return false; |
367 | 3.12k | } else if (ret == 0) { |
368 | | /* |
369 | | * A clear rejection. |
370 | | */ |
371 | 3.11k | pinfo->desegment_offset = save_desegment_offset; |
372 | 3.11k | pinfo->desegment_len = save_desegment_len; |
373 | 3.11k | return false; |
374 | 3.11k | } else { |
375 | | /* |
376 | | * A clear acceptance. |
377 | | */ |
378 | 10 | return true; |
379 | 10 | } |
380 | 3.12k | } |
381 | | |
382 | | /** |
383 | | * Heuristically dissect a tvbuff containing a JXTA SCTP Stream |
384 | | * |
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 |
389 | | **/ |
390 | | static bool dissect_jxta_SCTP_heur(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, void * data _U_) |
391 | 100 | { |
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! |
395 | | */ |
396 | 100 | int save_desegment_offset; |
397 | 100 | uint32_t save_desegment_len; |
398 | 100 | int ret; |
399 | | |
400 | 100 | save_desegment_offset = pinfo->desegment_offset; |
401 | 100 | save_desegment_len = pinfo->desegment_len; |
402 | 100 | ret = dissect_jxta_stream(tvb, pinfo, tree, NULL); |
403 | | |
404 | | /* ws_message( "%d Heuristic SCTP Dissection : %d", pinfo->num, ret ); */ |
405 | | |
406 | 100 | if (ret < 0) { |
407 | | /* |
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. |
413 | | * |
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. |
419 | | */ |
420 | 0 | pinfo->desegment_offset = save_desegment_offset; |
421 | 0 | pinfo->desegment_len = save_desegment_len; |
422 | 0 | return false; |
423 | 100 | } else if (ret == 0) { |
424 | | /* |
425 | | * A clear rejection. |
426 | | */ |
427 | 98 | pinfo->desegment_offset = save_desegment_offset; |
428 | 98 | pinfo->desegment_len = save_desegment_len; |
429 | 98 | return false; |
430 | 98 | } else { |
431 | | /* |
432 | | * A clear acceptance. |
433 | | */ |
434 | 2 | return true; |
435 | 2 | } |
436 | 100 | } |
437 | | |
438 | | /** |
439 | | * Dissect a tvbuff containing a JXTA UDP header, JXTA Message framing and a JXTA Message |
440 | | * |
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. |
447 | | **/ |
448 | | static int dissect_jxta_udp(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, void * data _U_) |
449 | 16 | { |
450 | 16 | unsigned offset = 0; |
451 | 16 | unsigned available; |
452 | 16 | int needed = 0; |
453 | | |
454 | 16 | conversation_t *conversation = find_or_create_conversation(pinfo); |
455 | | |
456 | 16 | conversation_set_dissector(conversation, jxta_udp_handle); |
457 | | |
458 | 16 | while (true) { |
459 | 16 | tvbuff_t *jxta_message_framing_tvb; |
460 | 16 | int processed = 0; |
461 | 16 | uint64_t content_length = -1; |
462 | 16 | char *content_type = NULL; |
463 | | |
464 | 16 | available = tvb_reported_length_remaining(tvb, offset); |
465 | 16 | if (available < sizeof(JXTA_UDP_SIG)) { |
466 | 0 | needed = (int) (sizeof(JXTA_UDP_SIG) - available); |
467 | 0 | break; |
468 | 0 | } |
469 | | |
470 | 16 | if (tvb_memeql(tvb, offset, (const uint8_t*)JXTA_UDP_SIG, sizeof(JXTA_UDP_SIG)) != 0) { |
471 | | /* not ours */ |
472 | 2 | return 0; |
473 | 2 | } |
474 | | |
475 | 14 | offset += (int)sizeof(JXTA_UDP_SIG); |
476 | | |
477 | 14 | jxta_message_framing_tvb = tvb_new_subset_remaining(tvb, offset); |
478 | 14 | processed = dissect_jxta_message_framing(jxta_message_framing_tvb, pinfo, NULL, &content_length, &content_type); |
479 | | |
480 | 14 | if ((0 == processed) || (NULL == content_type) || (content_length <= 0) || (content_length > UINT_MAX)) { |
481 | | /** Buffer did not begin with valid framing headers */ |
482 | 14 | return 0; |
483 | 14 | } |
484 | | |
485 | 0 | if (processed < 0) { |
486 | 0 | needed = -processed; |
487 | 0 | break; |
488 | 0 | } |
489 | | |
490 | 0 | offset += processed; |
491 | |
|
492 | 0 | available = tvb_reported_length_remaining(tvb, offset); |
493 | 0 | if (available < content_length) { |
494 | 0 | needed = (int) (content_length - available); |
495 | 0 | break; |
496 | 0 | } |
497 | | |
498 | 0 | offset += (unsigned) content_length; |
499 | |
|
500 | 0 | break; |
501 | 0 | } |
502 | | |
503 | 0 | if ((needed > 0) && gDESEGMENT && pinfo->can_desegment) { |
504 | | /* ws_message( "UDP requesting %d more bytes", needed ); */ |
505 | 0 | pinfo->desegment_offset = 0; |
506 | 0 | pinfo->desegment_len = needed; |
507 | 0 | return -needed; |
508 | 0 | } |
509 | | |
510 | 0 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "JXTA"); |
511 | |
|
512 | 0 | unsigned tree_offset = 0; |
513 | 0 | proto_item *jxta_tree_item = |
514 | 0 | proto_tree_add_protocol_format(tree, proto_jxta, tvb, tree_offset, -1, "JXTA" ); |
515 | 0 | proto_tree *jxta_tree = proto_item_add_subtree(jxta_tree_item, ett_jxta); |
516 | 0 | proto_item *jxta_udp_tree_item = |
517 | 0 | proto_tree_add_none_format(jxta_tree, hf_jxta_udp, tvb, tree_offset, -1, "JXTA UDP Message"); |
518 | 0 | proto_tree *jxta_udp_tree = proto_item_add_subtree(jxta_udp_tree_item, ett_jxta_udp); |
519 | 0 | tvbuff_t *jxta_message_framing_tvb; |
520 | 0 | uint64_t content_length = -1; |
521 | 0 | char *content_type = NULL; |
522 | 0 | tvbuff_t *jxta_message_tvb; |
523 | |
|
524 | 0 | proto_tree_add_item(jxta_udp_tree, hf_jxta_udpsig, tvb, tree_offset, (int)sizeof(JXTA_UDP_SIG), ENC_ASCII); |
525 | 0 | tree_offset += (int)sizeof(JXTA_UDP_SIG); |
526 | |
|
527 | 0 | jxta_message_framing_tvb = tvb_new_subset_remaining(tvb, tree_offset); |
528 | |
|
529 | 0 | tree_offset += dissect_jxta_message_framing(jxta_message_framing_tvb, pinfo, jxta_tree, &content_length, &content_type); |
530 | |
|
531 | 0 | jxta_message_tvb = tvb_new_subset_length(tvb, tree_offset, (int) content_length); |
532 | |
|
533 | 0 | tree_offset += dissect_media(content_type, jxta_message_tvb, pinfo, tree); |
534 | |
|
535 | 0 | proto_item_set_end(jxta_udp_tree_item, tvb, tree_offset); |
536 | | |
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); |
540 | |
|
541 | 0 | return offset; |
542 | 0 | } |
543 | | |
544 | | /** |
545 | | * Dissect a tvbuff containing JXTA stream PDUs. This commonly includes |
546 | | * connections over TCP sockets. |
547 | | * |
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. |
551 | | * |
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. |
558 | | **/ |
559 | | static int dissect_jxta_stream(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, void * data _U_) |
560 | 3.25k | { |
561 | 3.25k | unsigned offset = 0; |
562 | 3.25k | unsigned available = tvb_reported_length_remaining(tvb, offset); |
563 | 3.25k | int processed = 0; |
564 | 3.25k | int needed = 0; |
565 | 3.25k | jxta_stream_conversation_data *tpt_conv_data = NULL; |
566 | 3.25k | proto_item *jxta_tree_item = NULL; |
567 | 3.25k | proto_tree *jxta_tree = NULL; |
568 | | |
569 | | /* ws_message("Dissecting%s : %d", (NULL != tree) ? " for display" : "", pinfo->num ); */ |
570 | | |
571 | 3.25k | if (available < sizeof(JXTA_WELCOME_MSG_SIG)) { |
572 | 467 | needed = (int) (sizeof(JXTA_WELCOME_MSG_SIG) - available); |
573 | 467 | goto Common_Exit; |
574 | 467 | } |
575 | | |
576 | 2.78k | 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 | 32 | address *welcome_addr; |
579 | 32 | bool initiator = false; |
580 | | |
581 | 32 | tpt_conv_data = get_tpt_conversation(pinfo); |
582 | | |
583 | 32 | if (0 == tpt_conv_data->initiator_welcome_frame) { |
584 | | /* The initiator welcome frame */ |
585 | 19 | tpt_conv_data->tpt_ptype = pinfo->ptype; |
586 | 19 | tpt_conv_data->initiator_welcome_frame = pinfo->num; |
587 | 19 | copy_address_wmem(wmem_file_scope(), &tpt_conv_data->initiator_tpt_address, &pinfo->src); |
588 | 19 | tpt_conv_data->initiator_tpt_port = pinfo->srcport; |
589 | | |
590 | 19 | welcome_addr = &tpt_conv_data->initiator_address; |
591 | 19 | initiator = true; |
592 | 19 | } else { |
593 | 13 | if (tpt_conv_data->initiator_welcome_frame >= pinfo->num) { |
594 | | /* what we saw previously was the receiver welcome message */ |
595 | 3 | tpt_conv_data->receiver_welcome_frame = tpt_conv_data->initiator_welcome_frame; |
596 | 3 | tpt_conv_data->receiver_tpt_address = tpt_conv_data->initiator_tpt_address; |
597 | 3 | tpt_conv_data->receiver_tpt_port = tpt_conv_data->initiator_tpt_port; |
598 | 3 | tpt_conv_data->receiver_address = tpt_conv_data->initiator_address; |
599 | 3 | tpt_conv_data->initiator_welcome_frame = pinfo->num; |
600 | 3 | copy_address_wmem(wmem_file_scope(), &tpt_conv_data->initiator_tpt_address, &pinfo->src); |
601 | 3 | tpt_conv_data->initiator_tpt_port = pinfo->srcport; |
602 | | |
603 | 3 | welcome_addr = &tpt_conv_data->initiator_address; |
604 | 3 | initiator = true; |
605 | 10 | } else { |
606 | | /* The receiver welcome frame */ |
607 | 10 | tpt_conv_data->tpt_ptype = pinfo->ptype; |
608 | 10 | tpt_conv_data->receiver_welcome_frame = pinfo->num; |
609 | 10 | copy_address_wmem(wmem_file_scope(), &tpt_conv_data->receiver_tpt_address, &pinfo->src); |
610 | 10 | tpt_conv_data->receiver_tpt_port = pinfo->srcport; |
611 | | |
612 | 10 | welcome_addr = &tpt_conv_data->receiver_address; |
613 | 10 | initiator = false; |
614 | 10 | } |
615 | 13 | } |
616 | | |
617 | 32 | processed = dissect_jxta_welcome(tvb, pinfo, NULL, welcome_addr, initiator); |
618 | | |
619 | 32 | if( processed < 0 ) { |
620 | 0 | needed = -processed; |
621 | 0 | goto Common_Exit; |
622 | 0 | } |
623 | | |
624 | | /* redo, this time creating the display tree. */ |
625 | 32 | jxta_tree_item = proto_tree_add_protocol_format(tree, proto_jxta, tvb, offset, -1, "JXTA" ); |
626 | 32 | jxta_tree = proto_item_add_subtree(jxta_tree_item, ett_jxta); |
627 | | |
628 | 32 | processed = dissect_jxta_welcome(tvb, pinfo, jxta_tree, welcome_addr, initiator); |
629 | 2.75k | } else { |
630 | | /* Somewhere in the middle of a JXTA stream connection */ |
631 | 2.75k | uint64_t content_length = UINT64_MAX; |
632 | 2.75k | char *content_type = NULL; |
633 | 2.75k | int headers_len = dissect_jxta_message_framing(tvb, pinfo, NULL, &content_length, &content_type); |
634 | | |
635 | 2.75k | if ((0 == headers_len) || (NULL == content_type) || (content_length <= 0) || (content_length > UINT_MAX)) { |
636 | | /** Buffer did not begin with valid framing headers */ |
637 | 2.75k | return 0; |
638 | 2.75k | } |
639 | | |
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); */ |
645 | | |
646 | 0 | if (headers_len < 0) { |
647 | | /* negative headers_len means we need more bytes */ |
648 | 0 | needed = -headers_len; |
649 | 0 | goto Common_Exit; |
650 | 0 | } |
651 | | |
652 | 0 | available = tvb_reported_length_remaining(tvb, offset + headers_len); |
653 | 0 | if (available >= content_length) { |
654 | 0 | tvbuff_t *jxta_message_tvb = tvb_new_subset_length(tvb, offset + headers_len, (int) content_length); |
655 | 0 | conversation_t *peer_conversation = NULL; |
656 | |
|
657 | 0 | jxta_tree_item = proto_tree_add_protocol_format(tree, proto_jxta, tvb, offset, -1, "JXTA" ); |
658 | 0 | jxta_tree = proto_item_add_subtree(jxta_tree_item, ett_jxta); |
659 | | |
660 | | /* Redo header processing, this time populating the tree. */ |
661 | 0 | headers_len = dissect_jxta_message_framing(tvb, pinfo, jxta_tree, &content_length, &content_type); |
662 | |
|
663 | 0 | tpt_conv_data = get_tpt_conversation(pinfo); |
664 | 0 | peer_conversation = get_peer_conversation(pinfo, tpt_conv_data, true); |
665 | | |
666 | | /* Use our source and destination addresses if we have them */ |
667 | 0 | 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); */ |
671 | |
|
672 | 0 | if (addresses_equal(&pinfo->src, &tpt_conv_data->initiator_tpt_address) |
673 | 0 | && 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 | 0 | copy_address_shallow(&pinfo->src, &tpt_conv_data->initiator_address); |
678 | 0 | pinfo->srcport = 0; |
679 | 0 | copy_address_shallow(&pinfo->dst, &tpt_conv_data->receiver_address); |
680 | 0 | pinfo->destport = 0; |
681 | 0 | pinfo->ptype = PT_NONE; |
682 | 0 | } else if (addresses_equal(&pinfo->src, &tpt_conv_data->receiver_tpt_address) && |
683 | 0 | 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 | 0 | copy_address_shallow(&pinfo->src, &tpt_conv_data->receiver_address); |
688 | 0 | pinfo->srcport = 0; |
689 | 0 | copy_address_shallow(&pinfo->dst, &tpt_conv_data->initiator_address); |
690 | 0 | pinfo->destport = 0; |
691 | 0 | pinfo->ptype = PT_NONE; |
692 | 0 | } 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); */ |
696 | 0 | } |
697 | 0 | } |
698 | |
|
699 | 0 | processed = headers_len; |
700 | |
|
701 | 0 | processed += dissect_media(content_type, jxta_message_tvb, pinfo, tree); |
702 | 0 | } else { |
703 | | /* we need more bytes before we can process message body. */ |
704 | 0 | needed = (int) ((unsigned) content_length - available); |
705 | 0 | goto Common_Exit; |
706 | 0 | } |
707 | 0 | } |
708 | | |
709 | 32 | offset += processed; |
710 | | |
711 | 485 | Common_Exit: |
712 | 485 | if ((needed > 0) && gDESEGMENT && pinfo->can_desegment) { |
713 | | /* ws_message( "Stream requesting %d more bytes", needed ); */ |
714 | 0 | pinfo->desegment_offset = offset; |
715 | 0 | pinfo->desegment_len = needed; |
716 | 0 | return -needed; |
717 | 0 | } |
718 | | |
719 | 485 | return offset; |
720 | 485 | } |
721 | | |
722 | | /** |
723 | | * Find or possibly create a transport conversation object for the connection |
724 | | * which is associated with the packet info. |
725 | | * |
726 | | * @param pinfo The packet info from the underlying transport. |
727 | | **/ |
728 | | static jxta_stream_conversation_data *get_tpt_conversation(packet_info * pinfo) |
729 | 32 | { |
730 | 32 | conversation_t *tpt_conversation = find_or_create_conversation(pinfo); |
731 | 32 | jxta_stream_conversation_data *tpt_conv_data; |
732 | | |
733 | 32 | conversation_set_dissector(tpt_conversation, stream_jxta_handle); |
734 | | |
735 | 32 | tpt_conv_data = (jxta_stream_conversation_data *) conversation_get_proto_data(tpt_conversation, proto_jxta); |
736 | | |
737 | 32 | if (NULL == tpt_conv_data) { |
738 | 19 | tpt_conv_data = wmem_new(wmem_file_scope(), jxta_stream_conversation_data); |
739 | 19 | tpt_conv_data->tpt_ptype = pinfo->ptype; |
740 | | |
741 | 19 | copy_address_wmem(wmem_file_scope(), &tpt_conv_data->initiator_tpt_address, &pinfo->src); |
742 | 19 | tpt_conv_data->initiator_tpt_port = pinfo->srcport; |
743 | 19 | tpt_conv_data->initiator_welcome_frame = 0; |
744 | 19 | clear_address(&tpt_conv_data->initiator_address); |
745 | | |
746 | 19 | copy_address_wmem(wmem_file_scope(), &tpt_conv_data->receiver_tpt_address, &pinfo->dst); |
747 | 19 | tpt_conv_data->receiver_tpt_port = pinfo->destport; |
748 | 19 | tpt_conv_data->receiver_welcome_frame = 0; |
749 | 19 | clear_address(&tpt_conv_data->receiver_address); |
750 | | |
751 | 19 | conversation_add_proto_data(tpt_conversation, proto_jxta, tpt_conv_data); |
752 | 19 | } |
753 | | |
754 | 32 | return tpt_conv_data; |
755 | 32 | } |
756 | | |
757 | | /** |
758 | | * Find or possibly create a peer conversation object for the connection |
759 | | * which is associated with the packet info. |
760 | | * |
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. |
763 | | **/ |
764 | | static conversation_t *get_peer_conversation(packet_info * pinfo, jxta_stream_conversation_data* tpt_conv_data, bool create) |
765 | 0 | { |
766 | 0 | conversation_t * peer_conversation = NULL; |
767 | |
|
768 | 0 | if ((AT_NONE != tpt_conv_data->initiator_address.type) && (AT_NONE != tpt_conv_data->receiver_address.type)) { |
769 | 0 | peer_conversation = find_conversation(pinfo->num, &tpt_conv_data->initiator_address, &tpt_conv_data->receiver_address, |
770 | 0 | CONVERSATION_NONE, 0, 0, NO_PORT_B); |
771 | |
|
772 | 0 | if (create && (NULL == peer_conversation)) { |
773 | 0 | peer_conversation = conversation_new(pinfo->num, &tpt_conv_data->initiator_address, |
774 | 0 | &tpt_conv_data->receiver_address, CONVERSATION_NONE, 0, 0, NO_PORT2); |
775 | 0 | conversation_set_dissector(peer_conversation, stream_jxta_handle); |
776 | 0 | } |
777 | |
|
778 | 0 | } |
779 | |
|
780 | 0 | return peer_conversation; |
781 | 0 | } |
782 | | |
783 | | /** |
784 | | * Dissect a tvbuff containing a JXTA Welcome Message |
785 | | * |
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. |
794 | | **/ |
795 | | static int dissect_jxta_welcome(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, address * found_addr, bool initiator) |
796 | 64 | { |
797 | 64 | unsigned offset = 0; |
798 | 64 | int afterwelcome; |
799 | 64 | int first_linelen; |
800 | 64 | unsigned available = tvb_reported_length_remaining(tvb, offset); |
801 | 64 | char **tokens = NULL; |
802 | | |
803 | 64 | if (available < sizeof(JXTA_WELCOME_MSG_SIG)) { |
804 | 0 | return (int) (available - sizeof(JXTA_WELCOME_MSG_SIG)); |
805 | 0 | } |
806 | | |
807 | 64 | if (0 != tvb_memeql(tvb, 0, (const uint8_t*)JXTA_WELCOME_MSG_SIG, sizeof(JXTA_WELCOME_MSG_SIG))) { |
808 | | /* not ours! */ |
809 | 0 | return 0; |
810 | 0 | } |
811 | | |
812 | 64 | first_linelen = tvb_find_line_end(tvb, offset, -1, &afterwelcome, gDESEGMENT && pinfo->can_desegment); |
813 | | |
814 | 64 | if (-1 == first_linelen) { |
815 | 0 | if (available > 4096) { |
816 | | /* it's too far too be reasonable */ |
817 | 0 | return 0; |
818 | 0 | } else { |
819 | | /* ask for more bytes */ |
820 | 0 | return -DESEGMENT_ONE_MORE_SEGMENT; |
821 | 0 | } |
822 | 0 | } |
823 | | |
824 | | /* Dissect the Welcome Message */ |
825 | | |
826 | 64 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "JXTA"); |
827 | | |
828 | 64 | col_set_str(pinfo->cinfo, COL_INFO, "Welcome"); |
829 | | |
830 | 64 | { |
831 | 64 | char *welcomeline = (char*)tvb_get_string_enc(pinfo->pool, tvb, offset, first_linelen, ENC_ASCII); |
832 | 64 | char **current_token; |
833 | 64 | unsigned token_offset = offset; |
834 | 64 | proto_item *jxta_welcome_tree_item = NULL; |
835 | 64 | proto_tree *jxta_welcome_tree = NULL; |
836 | | |
837 | 64 | tokens = wmem_strsplit(pinfo->pool, welcomeline, " ", 255); |
838 | 64 | current_token = tokens; |
839 | | |
840 | 64 | if (tree) { |
841 | 32 | jxta_welcome_tree_item = |
842 | 32 | proto_tree_add_none_format(tree, hf_jxta_welcome, tvb, offset, afterwelcome, |
843 | 32 | "JXTA Connection Welcome Message, %s", welcomeline); |
844 | 32 | jxta_welcome_tree = proto_item_add_subtree(jxta_welcome_tree_item, ett_jxta_welcome); |
845 | 32 | } |
846 | | |
847 | 64 | if (jxta_welcome_tree) { |
848 | 32 | proto_item *jxta_welcome_initiator_item = |
849 | 32 | proto_tree_add_boolean(jxta_welcome_tree, hf_jxta_welcome_initiator, tvb, 0, 0, initiator); |
850 | 32 | proto_item_set_generated(jxta_welcome_initiator_item); |
851 | 32 | } |
852 | | |
853 | 64 | if (NULL != *current_token) { |
854 | 64 | proto_tree_add_item(jxta_welcome_tree, hf_jxta_welcome_sig, tvb, token_offset, (int) strlen(*current_token), ENC_ASCII); |
855 | | |
856 | 64 | token_offset += (unsigned) strlen(*current_token) + 1; |
857 | 64 | current_token++; |
858 | 64 | } else { |
859 | | /* invalid welcome message */ |
860 | 0 | afterwelcome = 0; |
861 | 0 | goto Common_Exit; |
862 | 0 | } |
863 | | |
864 | 64 | if (NULL != *current_token) { |
865 | 64 | if (jxta_welcome_tree) { |
866 | 32 | proto_tree_add_item(jxta_welcome_tree, hf_jxta_welcome_destAddr, tvb, token_offset, (int) strlen(*current_token), |
867 | 32 | ENC_ASCII); |
868 | 32 | } |
869 | | |
870 | 64 | token_offset += (unsigned) strlen(*current_token) + 1; |
871 | 64 | current_token++; |
872 | 64 | } else { |
873 | | /* invalid welcome message */ |
874 | 0 | afterwelcome = 0; |
875 | 0 | goto Common_Exit; |
876 | 0 | } |
877 | | |
878 | 64 | if (NULL != *current_token) { |
879 | 40 | if (jxta_welcome_tree) { |
880 | 19 | proto_tree_add_item(jxta_welcome_tree, hf_jxta_welcome_pubAddr, tvb, token_offset, (int) strlen(*current_token), ENC_ASCII); |
881 | 19 | } |
882 | | |
883 | 40 | token_offset += (unsigned) strlen(*current_token) + 1; |
884 | 40 | current_token++; |
885 | 40 | } else { |
886 | | /* invalid welcome message */ |
887 | 24 | afterwelcome = 0; |
888 | 24 | goto Common_Exit; |
889 | 24 | } |
890 | | |
891 | 40 | if (NULL != *current_token) { |
892 | 29 | if (jxta_welcome_tree) { |
893 | 13 | proto_tree_add_item(jxta_welcome_tree, hf_jxta_welcome_peerid, tvb, token_offset, (int) strlen(*current_token), ENC_ASCII); |
894 | 13 | } |
895 | | |
896 | 29 | col_append_str(pinfo->cinfo, COL_INFO, (initiator ? " -> " : " <- ") ); |
897 | 29 | col_append_str(pinfo->cinfo, COL_INFO, *current_token); |
898 | | |
899 | 29 | if (NULL != found_addr) { |
900 | 28 | set_address(found_addr, uri_address_type, (int)strlen(*current_token) + 1, wmem_strdup(wmem_file_scope(), *current_token)); |
901 | 28 | } |
902 | | |
903 | 29 | token_offset += (unsigned) strlen(*current_token) + 1; |
904 | 29 | current_token++; |
905 | 29 | } else { |
906 | | /* invalid welcome message */ |
907 | 11 | afterwelcome = 0; |
908 | 11 | goto Common_Exit; |
909 | 11 | } |
910 | | |
911 | 29 | if (NULL != *current_token) { |
912 | 25 | int variable_tokens = 0; |
913 | 25 | char **variable_token = current_token; |
914 | | |
915 | 127 | while(NULL != *variable_token) { |
916 | 102 | variable_tokens++; |
917 | 102 | variable_token++; |
918 | 102 | } |
919 | | |
920 | 25 | if( variable_tokens < 1 ) { |
921 | | /* invalid welcome message */ |
922 | 0 | afterwelcome = 0; |
923 | 0 | goto Common_Exit; |
924 | 0 | } |
925 | | |
926 | 25 | if( (2 == variable_tokens) && (0 == strcmp(JXTA_WELCOME_MSG_VERSION_1_1, current_token[variable_tokens -1])) ) { |
927 | 0 | if (jxta_welcome_tree) { |
928 | 0 | proto_tree_add_item(jxta_welcome_tree, hf_jxta_welcome_noProp, tvb, token_offset, (int) strlen(*current_token), ENC_ASCII); |
929 | 0 | } |
930 | |
|
931 | 0 | token_offset += (unsigned) strlen(*current_token) + 1; |
932 | 0 | current_token++; |
933 | |
|
934 | 0 | if (jxta_welcome_tree) { |
935 | 0 | proto_tree_add_item(jxta_welcome_tree, hf_jxta_welcome_version, tvb, token_offset, (int) strlen(*current_token), ENC_ASCII); |
936 | 0 | } |
937 | 25 | } else if( (3 == variable_tokens) && (0 == strcmp(JXTA_WELCOME_MSG_VERSION_3_0, current_token[variable_tokens -1])) ) { |
938 | 0 | if (jxta_welcome_tree) { |
939 | 0 | proto_tree_add_item(jxta_welcome_tree, hf_jxta_welcome_noProp, tvb, token_offset, (int) strlen(*current_token), ENC_ASCII); |
940 | 0 | } |
941 | |
|
942 | 0 | token_offset += (unsigned) strlen(*current_token) + 1; |
943 | 0 | current_token++; |
944 | |
|
945 | 0 | if (jxta_welcome_tree) { |
946 | 0 | proto_tree_add_item(jxta_welcome_tree, hf_jxta_welcome_msgVers, tvb, token_offset, (int) strlen(*current_token), ENC_ASCII); |
947 | 0 | } |
948 | |
|
949 | 0 | token_offset += (unsigned) strlen(*current_token) + 1; |
950 | 0 | current_token++; |
951 | |
|
952 | 0 | if (jxta_welcome_tree) { |
953 | 0 | proto_tree_add_item(jxta_welcome_tree, hf_jxta_welcome_version, tvb, token_offset, (int) strlen(*current_token), ENC_ASCII); |
954 | 0 | } |
955 | 25 | } else { |
956 | | /* Unrecognized Welcome Version */ |
957 | 25 | int each_variable_token; |
958 | | |
959 | 126 | for( each_variable_token = 0; each_variable_token < variable_tokens; each_variable_token++ ) { |
960 | 101 | if (jxta_welcome_tree) { |
961 | 47 | jxta_welcome_tree_item = proto_tree_add_item(jxta_welcome_tree, |
962 | 47 | (each_variable_token < (variable_tokens -1) ? hf_jxta_welcome_variable : hf_jxta_welcome_version), |
963 | 47 | tvb, token_offset, (int) strlen(*current_token), ENC_ASCII|ENC_NA); |
964 | | |
965 | 47 | proto_item_append_text(jxta_welcome_tree_item, " (UNRECOGNIZED)"); |
966 | 47 | } |
967 | | |
968 | 101 | token_offset += (unsigned) strlen(*current_token) + 1; |
969 | 101 | current_token++; |
970 | 101 | } |
971 | 25 | } |
972 | 25 | } else { |
973 | | /* invalid welcome message */ |
974 | 4 | afterwelcome = 0; |
975 | 4 | goto Common_Exit; |
976 | 4 | } |
977 | 29 | } |
978 | | |
979 | 50 | Common_Exit: |
980 | 50 | col_set_writable(pinfo->cinfo, -1, false); |
981 | | |
982 | 50 | return afterwelcome; |
983 | 29 | } |
984 | | |
985 | | /** |
986 | | * Dissect a tvbuff containing JXTA Message framing. |
987 | | * |
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. |
998 | | **/ |
999 | | static int dissect_jxta_message_framing(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, uint64_t * content_length, |
1000 | | char ** content_type) |
1001 | 2.76k | { |
1002 | 2.76k | unsigned offset = 0; |
1003 | 2.76k | unsigned available; |
1004 | 2.76k | int needed = 0; |
1005 | | |
1006 | | /* |
1007 | | * First go around. Make sure all of the bytes are there. |
1008 | | */ |
1009 | 3.03k | do { |
1010 | 3.03k | uint8_t headername_len; |
1011 | 3.03k | uint8_t headername_offset; |
1012 | 3.03k | uint16_t headervalue_len; |
1013 | 3.03k | uint16_t headervalue_offset; |
1014 | | |
1015 | 3.03k | available = tvb_reported_length_remaining(tvb, offset); |
1016 | 3.03k | if (available < 1) { |
1017 | 6 | needed = 1; |
1018 | 6 | break; |
1019 | 3.03k | } else { |
1020 | 3.03k | headername_len = tvb_get_uint8(tvb, offset); |
1021 | 3.03k | offset++; |
1022 | 3.03k | headername_offset = offset; |
1023 | | |
1024 | 3.03k | available = tvb_reported_length_remaining(tvb, offset); |
1025 | 3.03k | if (available < headername_len) { |
1026 | 1.25k | needed = (int) (headername_len - available); |
1027 | 1.25k | break; |
1028 | 1.25k | } |
1029 | | |
1030 | 1.77k | if (0 == headername_len) { |
1031 | 674 | break; |
1032 | 674 | } |
1033 | 1.10k | offset += headername_len; |
1034 | 1.10k | } |
1035 | | |
1036 | 1.10k | available = tvb_reported_length_remaining(tvb, offset); |
1037 | 1.10k | if (available < 2) { |
1038 | 20 | needed = (int) (2 - available); |
1039 | 20 | break; |
1040 | 1.08k | } else { |
1041 | 1.08k | headervalue_len = tvb_get_ntohs(tvb, offset); |
1042 | 1.08k | offset += 2; |
1043 | 1.08k | headervalue_offset = offset; |
1044 | | |
1045 | 1.08k | available = tvb_reported_length_remaining(tvb, offset); |
1046 | 1.08k | if (available < headervalue_len) { |
1047 | 809 | needed = (int) (headervalue_len - available); |
1048 | 809 | break; |
1049 | 809 | } |
1050 | | |
1051 | 272 | offset += headervalue_len; |
1052 | 272 | } |
1053 | | |
1054 | 272 | if (content_type && (sizeof("content-type") - 1) == headername_len) { |
1055 | 8 | if (0 == tvb_strncaseeql(tvb, headername_offset, "content-type", sizeof("content-type") - 1)) { |
1056 | 0 | *content_type = (char*)tvb_get_string_enc(pinfo->pool, tvb, headervalue_offset, headervalue_len, ENC_ASCII); |
1057 | 0 | } |
1058 | 8 | } |
1059 | | |
1060 | | |
1061 | 272 | if (content_length && (sizeof(uint64_t) == headervalue_len) && ((sizeof("content-length") - 1) == headername_len)) { |
1062 | 1 | if (0 == tvb_strncaseeql(tvb, headername_offset, "content-length", sizeof("content-length") - 1)) { |
1063 | 0 | *content_length = tvb_get_ntoh64(tvb, headervalue_offset); |
1064 | 0 | } |
1065 | 1 | } |
1066 | 2.76k | } while (true); |
1067 | | |
1068 | 2.76k | if ((needed > 0) && gDESEGMENT && pinfo->can_desegment) { |
1069 | | /* ws_message( "Framing requesting %d more bytes", needed ); */ |
1070 | 0 | pinfo->desegment_offset = 0; |
1071 | 0 | pinfo->desegment_len = needed; |
1072 | 0 | return -needed; |
1073 | 0 | } |
1074 | | |
1075 | | /* |
1076 | | * Second (optional pass) Now that we are sure that all the bytes are there we update the protocol tree. |
1077 | | */ |
1078 | 2.76k | if (tree) { |
1079 | 0 | unsigned tree_offset = 0; |
1080 | 0 | proto_item *framing_tree_item; |
1081 | 0 | proto_tree *framing_tree; |
1082 | |
|
1083 | 0 | framing_tree_item = |
1084 | 0 | proto_tree_add_none_format(tree, hf_jxta_framing, tvb, tree_offset, -1, "JXTA Message Framing Headers"); |
1085 | 0 | framing_tree = proto_item_add_subtree(framing_tree_item, ett_jxta_framing); |
1086 | | |
1087 | | /* parse framing headers */ |
1088 | 0 | do { |
1089 | 0 | uint8_t headernamelen = tvb_get_uint8(tvb, tree_offset); |
1090 | 0 | proto_item *framing_header_tree_item = |
1091 | 0 | proto_tree_add_item(framing_tree, hf_jxta_framing_header, tvb, tree_offset, -1, ENC_NA); |
1092 | 0 | proto_tree *framing_header_tree = proto_item_add_subtree(framing_header_tree_item, ett_jxta_framing_header); |
1093 | | |
1094 | | /* |
1095 | | * Put header name into the protocol tree |
1096 | | */ |
1097 | 0 | proto_tree_add_item(framing_header_tree, hf_jxta_framing_header_name, tvb, tree_offset, (int)sizeof(int8_t), ENC_ASCII|ENC_BIG_ENDIAN); |
1098 | | |
1099 | | /* |
1100 | | * Append header name into the header protocol item. It's a nice hint so you don't have to reveal all headers. |
1101 | | */ |
1102 | 0 | if (headernamelen > 0) { |
1103 | 0 | proto_item_append_text(framing_header_tree_item, " \"%s\"", |
1104 | 0 | tvb_format_text(pinfo->pool, tvb, tree_offset + 1, headernamelen)); |
1105 | 0 | } |
1106 | |
|
1107 | 0 | tree_offset += 1 + headernamelen; |
1108 | |
|
1109 | 0 | if (headernamelen > 0) { |
1110 | 0 | uint16_t headervaluelen = tvb_get_ntohs(tvb, tree_offset); |
1111 | |
|
1112 | 0 | if (tree) { |
1113 | 0 | proto_tree_add_uint(framing_header_tree, hf_jxta_framing_header_value_length, tvb, tree_offset, |
1114 | 0 | 2, headervaluelen); |
1115 | | |
1116 | | /** TODO bondolo Add specific handling for known header types */ |
1117 | | |
1118 | | /* |
1119 | | * Put header value into protocol tree. |
1120 | | */ |
1121 | 0 | proto_tree_add_item(framing_header_tree, hf_jxta_framing_header_value, tvb, tree_offset + 2, |
1122 | 0 | headervaluelen, ENC_NA); |
1123 | 0 | } |
1124 | |
|
1125 | 0 | tree_offset += 2 + headervaluelen; |
1126 | 0 | } |
1127 | |
|
1128 | 0 | proto_item_set_end(framing_header_tree_item, tvb, tree_offset); |
1129 | |
|
1130 | 0 | if (0 == headernamelen) { |
1131 | 0 | break; |
1132 | 0 | } |
1133 | 0 | } while (true); |
1134 | |
|
1135 | 0 | proto_item_set_end(framing_tree_item, tvb, tree_offset); |
1136 | |
|
1137 | 0 | DISSECTOR_ASSERT(offset == tree_offset); |
1138 | 0 | } |
1139 | | |
1140 | | /* return how many bytes we used up. */ |
1141 | 2.76k | return offset; |
1142 | 2.76k | } |
1143 | | |
1144 | | /** |
1145 | | * Dissect a tvbuff containing one or more JXTA Messages. |
1146 | | * |
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. |
1153 | | **/ |
1154 | | static int dissect_jxta_message(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, void * data _U_) |
1155 | 0 | { |
1156 | 0 | int complete_messages = 0; |
1157 | 0 | unsigned offset = 0; |
1158 | 0 | unsigned tree_offset = 0; |
1159 | 0 | unsigned available; |
1160 | 0 | int needed = 0; |
1161 | 0 | wmem_strbuf_t* src_addr; |
1162 | 0 | wmem_strbuf_t* dst_addr; |
1163 | |
|
1164 | 0 | while (true) { |
1165 | 0 | uint8_t message_version; |
1166 | 0 | unsigned message_start_offset = offset; |
1167 | | |
1168 | | /* First pass. Make sure all of the bytes we need are available */ |
1169 | 0 | available = tvb_reported_length_remaining(tvb, offset); |
1170 | |
|
1171 | 0 | if((0 == available) && (0 != complete_messages)) { |
1172 | | /* We have discovered all of the complete messages in the tvbuff. */ |
1173 | 0 | break; |
1174 | 0 | } |
1175 | | |
1176 | 0 | if (available < sizeof(JXTA_MSG_SIG)) { |
1177 | 0 | needed = (int) (sizeof(JXTA_MSG_SIG) - available); |
1178 | 0 | break; |
1179 | 0 | } |
1180 | | |
1181 | 0 | if (tvb_memeql(tvb, offset, (const uint8_t*)JXTA_MSG_SIG, sizeof(JXTA_MSG_SIG)) != 0) { |
1182 | | /* It is not one of ours */ |
1183 | 0 | return 0; |
1184 | 0 | } |
1185 | | |
1186 | 0 | offset += (int)sizeof(JXTA_MSG_SIG); |
1187 | |
|
1188 | 0 | available = tvb_reported_length_remaining(tvb, offset); |
1189 | 0 | if (available < 1) { |
1190 | 0 | needed = 1; |
1191 | 0 | break; |
1192 | 0 | } else { |
1193 | 0 | message_version = tvb_get_uint8(tvb, offset); |
1194 | |
|
1195 | 0 | offset++; |
1196 | |
|
1197 | 0 | 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 | 0 | return 0; |
1200 | 0 | } |
1201 | 0 | } |
1202 | | |
1203 | | /* Read the flags (Version 2 and later) */ |
1204 | 0 | if(message_version > 0) { |
1205 | 0 | available = tvb_reported_length_remaining(tvb, offset); |
1206 | 0 | if (available < 1) { |
1207 | 0 | needed = 1; |
1208 | 0 | break; |
1209 | 0 | } else { |
1210 | 0 | offset++; |
1211 | 0 | } |
1212 | 0 | } |
1213 | | |
1214 | | /* Read names table */ |
1215 | 0 | available = tvb_reported_length_remaining(tvb, offset); |
1216 | 0 | if (available < 2) { |
1217 | 0 | needed = (int) (2 - available); |
1218 | 0 | break; |
1219 | 0 | } else { |
1220 | 0 | uint16_t msg_names_count = tvb_get_ntohs(tvb, offset); |
1221 | 0 | unsigned each_name; |
1222 | |
|
1223 | 0 | offset += 2; |
1224 | |
|
1225 | 0 | for (each_name = 0; each_name < msg_names_count; each_name++) { |
1226 | 0 | uint16_t name_len; |
1227 | |
|
1228 | 0 | available = tvb_reported_length_remaining(tvb, offset); |
1229 | 0 | if (available < sizeof(name_len)) { |
1230 | 0 | needed = (int) (sizeof(name_len) - available); |
1231 | 0 | break; |
1232 | 0 | } |
1233 | | |
1234 | 0 | name_len = tvb_get_ntohs(tvb, offset); |
1235 | |
|
1236 | 0 | available = tvb_reported_length_remaining(tvb, offset + (int)sizeof(name_len)); |
1237 | 0 | if (available < name_len) { |
1238 | 0 | needed = (int) (name_len - available); |
1239 | 0 | break; |
1240 | 0 | } |
1241 | | |
1242 | 0 | offset += (int)sizeof(name_len) + name_len; |
1243 | 0 | } |
1244 | 0 | } |
1245 | | |
1246 | | /* parse element count */ |
1247 | 0 | available = tvb_reported_length_remaining(tvb, offset); |
1248 | 0 | if (available < 2) { |
1249 | 0 | needed = (int) (2 - available); |
1250 | 0 | break; |
1251 | 0 | } else { |
1252 | 0 | uint16_t elem_count = tvb_get_ntohs(tvb, offset); |
1253 | 0 | unsigned each_elem; |
1254 | |
|
1255 | 0 | offset += 2; |
1256 | | |
1257 | | /* parse elements */ |
1258 | 0 | for (each_elem = 0; each_elem < elem_count; each_elem++) { |
1259 | 0 | tvbuff_t *jxta_message_element_tvb = tvb_new_subset_remaining(tvb, offset); |
1260 | 0 | int processed; |
1261 | |
|
1262 | 0 | if (JXTA_MSG_VERSION_1 == message_version) { |
1263 | 0 | processed = dissect_jxta_message_element_1(jxta_message_element_tvb, pinfo, NULL, 0, NULL); |
1264 | 0 | } else { /* JXTA_MSG_VERSION_2 */ |
1265 | 0 | processed = dissect_jxta_message_element_2(jxta_message_element_tvb, pinfo, NULL, 0, NULL); |
1266 | 0 | } |
1267 | |
|
1268 | 0 | if (processed < 0) { |
1269 | 0 | needed = -processed; |
1270 | 0 | break; |
1271 | 0 | } |
1272 | | |
1273 | 0 | 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 ); |
1283 | | */ |
1284 | 0 | return 0; |
1285 | 0 | } |
1286 | | |
1287 | 0 | offset += processed; |
1288 | 0 | } |
1289 | 0 | } |
1290 | | |
1291 | 0 | if ((uri_address_type == pinfo->src.type) && (uri_address_type == pinfo->dst.type)) { |
1292 | 0 | jxta_tap_header *tap_header = wmem_new(wmem_file_scope(), jxta_tap_header); |
1293 | |
|
1294 | 0 | copy_address_shallow(&tap_header->src_address, &pinfo->src); |
1295 | 0 | copy_address_shallow(&tap_header->dest_address, &pinfo->dst); |
1296 | 0 | tap_header->size = offset - message_start_offset ; |
1297 | |
|
1298 | 0 | tap_queue_packet(jxta_tap, pinfo, tap_header); |
1299 | 0 | } |
1300 | |
|
1301 | 0 | complete_messages++; |
1302 | | |
1303 | | /* ws_message( "%d Scanned message #%d: ", pinfo->num, complete_messages ); */ |
1304 | 0 | } |
1305 | | |
1306 | 0 | if ((needed > 0) && gDESEGMENT && pinfo->can_desegment) { |
1307 | | /* ws_message("Frame %d: Message requesting %d more bytes", pinfo->num, needed); */ |
1308 | 0 | pinfo->desegment_offset = 0; |
1309 | 0 | pinfo->desegment_len = needed; |
1310 | 0 | return -needed; |
1311 | 0 | } |
1312 | | |
1313 | 0 | src_addr = wmem_strbuf_create(pinfo->pool); |
1314 | 0 | wmem_strbuf_append(src_addr, address_to_str(pinfo->pool, &pinfo->src)); |
1315 | 0 | dst_addr = wmem_strbuf_create(pinfo->pool); |
1316 | 0 | wmem_strbuf_append(dst_addr, address_to_str(pinfo->pool, &pinfo->dst)); |
1317 | | |
1318 | | /* append the port if appropriate */ |
1319 | 0 | if (PT_NONE != pinfo->ptype) { |
1320 | 0 | wmem_strbuf_append_printf(src_addr, ":%d", pinfo->srcport); |
1321 | 0 | wmem_strbuf_append_printf(dst_addr, ":%d", pinfo->destport); |
1322 | 0 | } |
1323 | |
|
1324 | 0 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "JXTA"); |
1325 | |
|
1326 | 0 | if( complete_messages > 1 ) { |
1327 | 0 | col_add_fstr(pinfo->cinfo, COL_INFO, "%d Messages, %s -> %s", complete_messages, |
1328 | 0 | wmem_strbuf_get_str(src_addr), wmem_strbuf_get_str(dst_addr)); |
1329 | 0 | } else { |
1330 | 0 | col_add_fstr(pinfo->cinfo, COL_INFO, "Message, %s -> %s", |
1331 | 0 | wmem_strbuf_get_str(src_addr), wmem_strbuf_get_str(dst_addr)); |
1332 | 0 | } |
1333 | |
|
1334 | 0 | col_set_writable(pinfo->cinfo, -1, false); |
1335 | |
|
1336 | 0 | while( tree && (complete_messages > 0) ) { |
1337 | 0 | proto_item *jxta_msg_tree_item = NULL; |
1338 | 0 | proto_tree *jxta_msg_tree = NULL; |
1339 | 0 | uint8_t message_version; |
1340 | 0 | const char **names_table = NULL; |
1341 | 0 | uint16_t msg_names_count; |
1342 | 0 | unsigned each_name; |
1343 | 0 | uint16_t elem_count; |
1344 | 0 | unsigned each_elem; |
1345 | 0 | proto_item *tree_item; |
1346 | |
|
1347 | 0 | jxta_msg_tree_item = proto_tree_add_protocol_format(tree, proto_message_jxta, tvb, tree_offset, -1, |
1348 | 0 | "JXTA Message, %s -> %s", wmem_strbuf_get_str(src_addr), |
1349 | 0 | wmem_strbuf_get_str(dst_addr)); |
1350 | |
|
1351 | 0 | jxta_msg_tree = proto_item_add_subtree(jxta_msg_tree_item, ett_jxta_msg); |
1352 | |
|
1353 | 0 | proto_tree_add_item(jxta_msg_tree, hf_jxta_message_sig, tvb, tree_offset, (int)sizeof(JXTA_MSG_SIG), ENC_ASCII); |
1354 | 0 | tree_offset += (int)sizeof(JXTA_MSG_SIG); |
1355 | |
|
1356 | 0 | tree_item = proto_tree_add_string(jxta_msg_tree, hf_jxta_message_src, tvb, 0, 0, wmem_strbuf_get_str(src_addr)); |
1357 | 0 | proto_item_set_generated(tree_item); |
1358 | |
|
1359 | 0 | tree_item = proto_tree_add_string(jxta_msg_tree, hf_jxta_message_address, tvb, 0, 0, wmem_strbuf_get_str(src_addr)); |
1360 | 0 | proto_item_set_hidden(tree_item); |
1361 | 0 | proto_item_set_generated(tree_item); |
1362 | |
|
1363 | 0 | if(uri_address_type == pinfo->src.type) { |
1364 | 0 | tree_item = proto_tree_add_string(jxta_msg_tree, hf_uri_src, tvb, 0, 0, wmem_strbuf_get_str(src_addr)); |
1365 | 0 | proto_item_set_hidden(tree_item); |
1366 | 0 | proto_item_set_generated(tree_item); |
1367 | 0 | tree_item = proto_tree_add_string(jxta_msg_tree, hf_uri_addr, tvb, 0, 0, wmem_strbuf_get_str(src_addr)); |
1368 | 0 | proto_item_set_hidden(tree_item); |
1369 | 0 | proto_item_set_generated(tree_item); |
1370 | 0 | } |
1371 | |
|
1372 | 0 | tree_item = proto_tree_add_string(jxta_msg_tree, hf_jxta_message_dst, tvb, 0, 0, wmem_strbuf_get_str(dst_addr)); |
1373 | 0 | proto_item_set_generated(tree_item); |
1374 | |
|
1375 | 0 | tree_item = proto_tree_add_string(jxta_msg_tree, hf_jxta_message_address, tvb, 0, 0, wmem_strbuf_get_str(dst_addr)); |
1376 | 0 | proto_item_set_hidden(tree_item); |
1377 | 0 | proto_item_set_generated(tree_item); |
1378 | |
|
1379 | 0 | if(uri_address_type == pinfo->dst.type) { |
1380 | 0 | tree_item = proto_tree_add_string(jxta_msg_tree, hf_uri_dst, tvb, 0, 0, wmem_strbuf_get_str(dst_addr)); |
1381 | 0 | proto_item_set_hidden(tree_item); |
1382 | 0 | proto_item_set_generated(tree_item); |
1383 | 0 | tree_item = proto_tree_add_string(jxta_msg_tree, hf_uri_addr, tvb, 0, 0, wmem_strbuf_get_str(dst_addr)); |
1384 | 0 | proto_item_set_hidden(tree_item); |
1385 | 0 | proto_item_set_generated(tree_item); |
1386 | 0 | } |
1387 | |
|
1388 | 0 | message_version = tvb_get_uint8(tvb, tree_offset); |
1389 | 0 | proto_tree_add_uint(jxta_msg_tree, hf_jxta_message_version, tvb, tree_offset, 1, message_version); |
1390 | 0 | tree_offset += 1; |
1391 | |
|
1392 | 0 | if( message_version > 0 ) { |
1393 | 0 | static int * const flags[] = { |
1394 | 0 | &hf_jxta_message_flag_utf16be, |
1395 | 0 | &hf_jxta_message_flag_ucs32be, |
1396 | 0 | NULL |
1397 | 0 | }; |
1398 | |
|
1399 | 0 | proto_tree_add_bitmask(jxta_msg_tree, tvb, tree_offset, hf_jxta_message_flags, ett_jxta_msg_flags, flags, ENC_NA); |
1400 | 0 | tree_offset += 1; |
1401 | 0 | } |
1402 | |
|
1403 | 0 | msg_names_count = tvb_get_ntohs(tvb, tree_offset); |
1404 | 0 | proto_tree_add_uint(jxta_msg_tree, hf_jxta_message_names_count, tvb, tree_offset, 2, msg_names_count); |
1405 | 0 | tree_offset += 2; |
1406 | |
|
1407 | 0 | names_table = (const char **)wmem_alloc(pinfo->pool, (msg_names_count + 2) * sizeof(const char *)); |
1408 | 0 | names_table[0] = ""; |
1409 | 0 | names_table[1] = "jxta"; |
1410 | | |
1411 | | /* parse names */ |
1412 | 0 | for (each_name = 0; each_name < msg_names_count; each_name++) { |
1413 | 0 | uint16_t name_len = tvb_get_ntohs(tvb, tree_offset); |
1414 | |
|
1415 | 0 | names_table[2 + each_name] = (char*)tvb_get_string_enc(pinfo->pool, tvb, tree_offset + 2, name_len, ENC_ASCII); |
1416 | 0 | proto_tree_add_item(jxta_msg_tree, hf_jxta_message_names_name, tvb, tree_offset, 2, ENC_ASCII|ENC_BIG_ENDIAN); |
1417 | 0 | tree_offset += 2 + name_len; |
1418 | 0 | } |
1419 | | |
1420 | | /* parse element count */ |
1421 | 0 | elem_count = tvb_get_ntohs(tvb, tree_offset); |
1422 | 0 | proto_tree_add_item(jxta_msg_tree, hf_jxta_message_element_count, tvb, tree_offset, 2, ENC_BIG_ENDIAN); |
1423 | 0 | tree_offset += 2; |
1424 | | |
1425 | | /* FIXME bondolo Element count 0 (Process elements until FIN) should be supported. */ |
1426 | | |
1427 | | /* parse elements */ |
1428 | 0 | for (each_elem = 0; each_elem < elem_count; each_elem++) { |
1429 | 0 | tvbuff_t *jxta_message_element_tvb = tvb_new_subset_remaining(tvb, tree_offset); |
1430 | |
|
1431 | 0 | if(JXTA_MSG_VERSION_1 == message_version) { |
1432 | 0 | tree_offset += |
1433 | 0 | dissect_jxta_message_element_1(jxta_message_element_tvb, pinfo, jxta_msg_tree, msg_names_count + 2, names_table); |
1434 | 0 | } else if(JXTA_MSG_VERSION_2 == message_version) { |
1435 | 0 | tree_offset += |
1436 | 0 | dissect_jxta_message_element_2(jxta_message_element_tvb, pinfo, jxta_msg_tree, msg_names_count + 2, names_table); |
1437 | 0 | } else { |
1438 | | /* Sort of a lie, we say that we don't recognize it at all. */ |
1439 | 0 | return 0; |
1440 | 0 | } |
1441 | 0 | } |
1442 | | |
1443 | 0 | proto_item_set_end(jxta_msg_tree_item, tvb, tree_offset); |
1444 | |
|
1445 | 0 | complete_messages--; |
1446 | 0 | } |
1447 | | |
1448 | 0 | if( tree ) { |
1449 | | /* ws_message( "%d tvb offset : %d tree offset : %d", pinfo->num, offset, tree_offset ); */ |
1450 | 0 | DISSECTOR_ASSERT(tree_offset == offset); |
1451 | 0 | } |
1452 | |
|
1453 | 0 | return offset; |
1454 | 0 | } |
1455 | | |
1456 | | /** |
1457 | | * Dissect a tvbuff containing a JXTA Message Element (Version 1). |
1458 | | * |
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. |
1465 | | **/ |
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) |
1469 | 0 | { |
1470 | 0 | unsigned offset = 0; |
1471 | 0 | unsigned available; |
1472 | 0 | int needed = 0; |
1473 | 0 | uint8_t flags; |
1474 | | |
1475 | | /* First pass. Make sure all of the bytes we need are available */ |
1476 | |
|
1477 | 0 | while (true) { |
1478 | | /* signature field */ |
1479 | 0 | available = tvb_reported_length_remaining(tvb, offset); |
1480 | 0 | if (available < sizeof(JXTA_MSGELEM_SIG)) { |
1481 | 0 | needed = (int) (sizeof(JXTA_MSGELEM_SIG) - available); |
1482 | 0 | } |
1483 | |
|
1484 | 0 | if (tvb_memeql(tvb, offset, (const uint8_t*)JXTA_MSGELEM_SIG, sizeof(JXTA_MSGELEM_SIG)) != 0) { |
1485 | | /* It is not one of ours */ |
1486 | 0 | return 0; |
1487 | 0 | } |
1488 | | |
1489 | 0 | offset += (int)sizeof(JXTA_MSGELEM_SIG); |
1490 | | |
1491 | | /* namespace id field */ |
1492 | 0 | available = tvb_reported_length_remaining(tvb, offset); |
1493 | 0 | if (available < 1) { |
1494 | 0 | needed = 1; |
1495 | 0 | break; |
1496 | 0 | } |
1497 | | |
1498 | 0 | offset++; |
1499 | | |
1500 | | /* flags field */ |
1501 | 0 | available = tvb_reported_length_remaining(tvb, offset); |
1502 | 0 | if (available < 1) { |
1503 | 0 | needed = 1; |
1504 | 0 | break; |
1505 | 0 | } else { |
1506 | 0 | flags = tvb_get_uint8(tvb, offset); |
1507 | 0 | offset++; |
1508 | 0 | } |
1509 | | |
1510 | | /* name field */ |
1511 | 0 | available = tvb_reported_length_remaining(tvb, offset); |
1512 | 0 | if (available < 2) { |
1513 | 0 | needed = (int) (2 - available); |
1514 | 0 | break; |
1515 | 0 | } else { |
1516 | 0 | uint16_t name_len = tvb_get_ntohs(tvb, offset); |
1517 | 0 | offset += 2; |
1518 | |
|
1519 | 0 | available = tvb_reported_length_remaining(tvb, offset); |
1520 | 0 | if (available < name_len) { |
1521 | 0 | needed = (int) (name_len - available); |
1522 | 0 | break; |
1523 | 0 | } |
1524 | | |
1525 | 0 | offset += name_len; |
1526 | 0 | } |
1527 | | |
1528 | | /* type field */ |
1529 | 0 | if ((flags & JXTAMSG1_ELMFLAG_TYPE) != 0) { |
1530 | 0 | uint16_t type_len; |
1531 | |
|
1532 | 0 | available = tvb_reported_length_remaining(tvb, offset); |
1533 | 0 | if (available < 2) { |
1534 | 0 | needed = (int) (2 - available); |
1535 | 0 | break; |
1536 | 0 | } |
1537 | | |
1538 | 0 | type_len = tvb_get_ntohs(tvb, offset); |
1539 | 0 | offset += 2; |
1540 | |
|
1541 | 0 | available = tvb_reported_length_remaining(tvb, offset); |
1542 | 0 | if (available < type_len) { |
1543 | 0 | needed = (int) (type_len - available); |
1544 | 0 | break; |
1545 | 0 | } |
1546 | | |
1547 | 0 | offset += type_len; |
1548 | 0 | } |
1549 | | |
1550 | | /* encoding field */ |
1551 | 0 | if ((flags & JXTAMSG1_ELMFLAG_ENCODING) != 0) { |
1552 | 0 | uint16_t encoding_len; |
1553 | |
|
1554 | 0 | available = tvb_reported_length_remaining(tvb, offset); |
1555 | 0 | if (available < 2) { |
1556 | 0 | needed = (int) (2 - available); |
1557 | 0 | break; |
1558 | 0 | } |
1559 | | |
1560 | 0 | encoding_len = tvb_get_ntohs(tvb, offset); |
1561 | 0 | offset += 2; |
1562 | |
|
1563 | 0 | available = tvb_reported_length_remaining(tvb, offset); |
1564 | 0 | if (available < encoding_len) { |
1565 | 0 | needed = (int) (encoding_len - available); |
1566 | 0 | break; |
1567 | 0 | } |
1568 | | |
1569 | 0 | offset += encoding_len; |
1570 | 0 | } |
1571 | | |
1572 | | /* content field */ |
1573 | 0 | available = tvb_reported_length_remaining(tvb, offset); |
1574 | 0 | if (available < 2) { |
1575 | 0 | needed = (int) (2 - available); |
1576 | 0 | break; |
1577 | 0 | } else { |
1578 | 0 | uint32_t content_len = tvb_get_ntohl(tvb, offset); |
1579 | 0 | offset += 4; |
1580 | |
|
1581 | 0 | available = tvb_reported_length_remaining(tvb, offset); |
1582 | 0 | if (available < content_len) { |
1583 | 0 | needed = (int) (content_len - available); |
1584 | 0 | break; |
1585 | 0 | } |
1586 | | |
1587 | 0 | offset += content_len; |
1588 | 0 | } |
1589 | | |
1590 | | /* signature element field */ |
1591 | 0 | if ((flags & JXTAMSG1_ELMFLAG_SIGNATURE) != 0) { |
1592 | 0 | tvbuff_t *jxta_signature_element_tvb; |
1593 | 0 | int processed; |
1594 | |
|
1595 | 0 | jxta_signature_element_tvb = tvb_new_subset_remaining(tvb, offset); |
1596 | |
|
1597 | 0 | increment_dissection_depth(pinfo); |
1598 | 0 | processed = dissect_jxta_message_element_1(jxta_signature_element_tvb, pinfo, NULL, 0, NULL); |
1599 | 0 | decrement_dissection_depth(pinfo); |
1600 | |
|
1601 | 0 | if (processed == 0) { |
1602 | 0 | return offset; |
1603 | 0 | } |
1604 | | |
1605 | 0 | if (processed < 0) { |
1606 | 0 | needed = -processed; |
1607 | 0 | break; |
1608 | 0 | } |
1609 | | |
1610 | 0 | offset += processed; |
1611 | 0 | } |
1612 | | |
1613 | 0 | break; |
1614 | 0 | } |
1615 | | |
1616 | 0 | if ((needed > 0) && gDESEGMENT && pinfo->can_desegment) { |
1617 | | /* ws_message( "Element1 requesting %d more bytes", needed ); */ |
1618 | 0 | pinfo->desegment_offset = 0; |
1619 | 0 | pinfo->desegment_len = needed; |
1620 | 0 | return -needed; |
1621 | 0 | } |
1622 | | |
1623 | | /* Second pass : build the proto tree */ |
1624 | 0 | unsigned tree_offset = 0; |
1625 | 0 | proto_item *jxta_elem_tree_item = proto_tree_add_item(tree, hf_jxta_element, tvb, tree_offset, -1, ENC_NA); |
1626 | 0 | proto_tree *jxta_elem_tree = proto_item_add_subtree(jxta_elem_tree_item, ett_jxta_elem); |
1627 | 0 | uint8_t namespaceID; |
1628 | 0 | proto_item *namespace_ti; |
1629 | 0 | uint16_t name_len; |
1630 | 0 | uint32_t content_len; |
1631 | 0 | char *mediatype = NULL; |
1632 | 0 | tvbuff_t *element_content_tvb; |
1633 | 0 | static int * const element_flags[] = { |
1634 | 0 | &hf_jxta_element1_flag_hasType, |
1635 | 0 | &hf_jxta_element1_flag_hasEncoding, |
1636 | 0 | &hf_jxta_element1_flag_hasSignature, |
1637 | 0 | NULL |
1638 | 0 | }; |
1639 | |
|
1640 | 0 | proto_tree_add_item(jxta_elem_tree, hf_jxta_element_sig, tvb, tree_offset, (int)sizeof(JXTA_MSGELEM_SIG), ENC_ASCII); |
1641 | 0 | tree_offset += (int)sizeof(JXTA_MSGELEM_SIG); |
1642 | |
|
1643 | 0 | namespaceID = tvb_get_uint8(tvb, tree_offset); |
1644 | 0 | namespace_ti = |
1645 | 0 | proto_tree_add_uint(jxta_elem_tree, hf_jxta_element1_namespaceid, tvb, tree_offset, 1, namespaceID); |
1646 | 0 | if (namespaceID < ns_count) { |
1647 | 0 | proto_item_append_text(namespace_ti, " (%s)", names_table[namespaceID]); |
1648 | 0 | } else { |
1649 | 0 | proto_item_append_text(namespace_ti, " * BAD *"); |
1650 | 0 | } |
1651 | 0 | tree_offset += 1; |
1652 | |
|
1653 | 0 | flags = tvb_get_uint8(tvb, tree_offset); |
1654 | 0 | proto_tree_add_bitmask(jxta_elem_tree, tvb, tree_offset, hf_jxta_element_flags, ett_jxta_elem_1_flags, element_flags, ENC_NA); |
1655 | 0 | tree_offset += 1; |
1656 | |
|
1657 | 0 | name_len = tvb_get_ntohs(tvb, tree_offset); |
1658 | 0 | proto_item_append_text(jxta_elem_tree_item, " \"%s\"", tvb_format_text(pinfo->pool, tvb, tree_offset + 2, name_len)); |
1659 | 0 | proto_tree_add_item(jxta_elem_tree, hf_jxta_element_name, tvb, tree_offset, 2, ENC_ASCII|ENC_BIG_ENDIAN); |
1660 | 0 | tree_offset += 2 + name_len; |
1661 | | |
1662 | | /* process type */ |
1663 | 0 | if ((flags & JXTAMSG1_ELMFLAG_TYPE) != 0) { |
1664 | 0 | uint16_t type_len = tvb_get_ntohs(tvb, tree_offset); |
1665 | 0 | proto_tree_add_item(jxta_elem_tree, hf_jxta_element_type, tvb, tree_offset, 2, ENC_ASCII|ENC_BIG_ENDIAN); |
1666 | 0 | tree_offset += 2; |
1667 | |
|
1668 | 0 | mediatype = (char*)tvb_get_string_enc(pinfo->pool, tvb, tree_offset, type_len, ENC_ASCII); |
1669 | |
|
1670 | 0 | tree_offset += type_len; |
1671 | 0 | } |
1672 | | |
1673 | | /* process encoding */ |
1674 | 0 | if ((flags & JXTAMSG1_ELMFLAG_ENCODING) != 0) { |
1675 | 0 | uint16_t encoding_len = tvb_get_ntohs(tvb, tree_offset); |
1676 | 0 | proto_tree_add_item(jxta_elem_tree, hf_jxta_element_encoding, tvb, tree_offset, 2, ENC_ASCII|ENC_BIG_ENDIAN); |
1677 | 0 | tree_offset += 2 + encoding_len; |
1678 | 0 | } |
1679 | | |
1680 | | /* content */ |
1681 | 0 | content_len = tvb_get_ntohl(tvb, tree_offset); |
1682 | 0 | proto_tree_add_item(jxta_elem_tree, hf_jxta_element_content_len, tvb, tree_offset, 4, ENC_BIG_ENDIAN); |
1683 | 0 | tree_offset += 4; |
1684 | |
|
1685 | 0 | element_content_tvb = tvb_new_subset_length(tvb, tree_offset, content_len); |
1686 | |
|
1687 | 0 | tree_offset += dissect_media(mediatype, element_content_tvb, pinfo, jxta_elem_tree); |
1688 | | |
1689 | | /* process the signature element */ |
1690 | 0 | if ((flags & JXTAMSG1_ELMFLAG_SIGNATURE) != 0) { |
1691 | 0 | tvbuff_t *jxta_message_element_tvb = tvb_new_subset_remaining(tvb, tree_offset); |
1692 | |
|
1693 | 0 | increment_dissection_depth(pinfo); |
1694 | 0 | tree_offset += dissect_jxta_message_element_1(jxta_message_element_tvb, pinfo, jxta_elem_tree, ns_count, names_table); |
1695 | 0 | decrement_dissection_depth(pinfo); |
1696 | 0 | } |
1697 | |
|
1698 | 0 | proto_item_set_end(jxta_elem_tree_item, tvb, tree_offset); |
1699 | | |
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); |
1703 | |
|
1704 | 0 | return offset; |
1705 | 0 | } |
1706 | | |
1707 | | /** |
1708 | | * Dissect a tvbuff containing a JXTA Message Element (Version 2). |
1709 | | * |
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. |
1718 | | **/ |
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) |
1722 | 0 | { |
1723 | 0 | unsigned offset = 0; |
1724 | 0 | unsigned available; |
1725 | 0 | int needed = 0; |
1726 | 0 | uint8_t flags; |
1727 | | |
1728 | | /* First pass. Make sure all of the bytes we need are available */ |
1729 | |
|
1730 | 0 | while (true) { |
1731 | | /* signature field */ |
1732 | 0 | available = tvb_reported_length_remaining(tvb, offset); |
1733 | 0 | if (available < sizeof(JXTA_MSGELEM_SIG)) { |
1734 | 0 | needed = (int) (sizeof(JXTA_MSGELEM_SIG) - available); |
1735 | 0 | } |
1736 | |
|
1737 | 0 | if (tvb_memeql(tvb, offset, (const uint8_t*)JXTA_MSGELEM_SIG, sizeof(JXTA_MSGELEM_SIG)) != 0) { |
1738 | | /* It is not one of ours */ |
1739 | 0 | return 0; |
1740 | 0 | } |
1741 | | |
1742 | 0 | offset += (int)sizeof(JXTA_MSGELEM_SIG); |
1743 | | |
1744 | | /* flags field */ |
1745 | 0 | available = tvb_reported_length_remaining(tvb, offset); |
1746 | 0 | if (available < 1) { |
1747 | 0 | needed = 1; |
1748 | 0 | break; |
1749 | 0 | } else { |
1750 | 0 | flags = tvb_get_uint8(tvb, offset); |
1751 | 0 | offset++; |
1752 | 0 | } |
1753 | | |
1754 | | /* namespace id field */ |
1755 | 0 | available = tvb_reported_length_remaining(tvb, offset); |
1756 | 0 | if (available < 2) { |
1757 | 0 | needed = (int) (2 - available); |
1758 | 0 | break; |
1759 | 0 | } |
1760 | | |
1761 | 0 | offset += 2; |
1762 | | |
1763 | | /* name field */ |
1764 | 0 | if ((flags & JXTAMSG2_ELMFLAG_NAME_LITERAL) == 0) { |
1765 | 0 | available = tvb_reported_length_remaining(tvb, offset); |
1766 | 0 | if (available < 2) { |
1767 | 0 | needed = (int) (2 - available); |
1768 | 0 | break; |
1769 | 0 | } |
1770 | | |
1771 | 0 | offset += 2; |
1772 | 0 | } else { |
1773 | | /* literal name field */ |
1774 | 0 | available = tvb_reported_length_remaining(tvb, offset); |
1775 | 0 | if (available < 2) { |
1776 | 0 | needed = (int) (2 - available); |
1777 | 0 | break; |
1778 | 0 | } else { |
1779 | 0 | uint16_t name_len = tvb_get_ntohs(tvb, offset); |
1780 | 0 | offset += 2; |
1781 | |
|
1782 | 0 | available = tvb_reported_length_remaining(tvb, offset); |
1783 | 0 | if (available < name_len) { |
1784 | 0 | needed = (int) (name_len - available); |
1785 | 0 | break; |
1786 | 0 | } |
1787 | | |
1788 | 0 | offset += name_len; |
1789 | 0 | } |
1790 | 0 | } |
1791 | | |
1792 | | /* type field */ |
1793 | 0 | if ((flags & JXTAMSG2_ELMFLAG_TYPE) != 0) { |
1794 | 0 | available = tvb_reported_length_remaining(tvb, offset); |
1795 | 0 | if (available < 2) { |
1796 | 0 | needed = (int) (2 - available); |
1797 | 0 | break; |
1798 | 0 | } |
1799 | | |
1800 | 0 | offset += 2; |
1801 | 0 | } |
1802 | | |
1803 | | /* encoding field */ |
1804 | 0 | if ((flags & JXTAMSG2_ELMFLAG_ENCODINGS) != 0) { |
1805 | 0 | available = tvb_reported_length_remaining(tvb, offset); |
1806 | 0 | if (available < 2) { |
1807 | 0 | needed = (int) (2 - available); |
1808 | 0 | break; |
1809 | 0 | } |
1810 | | |
1811 | 0 | offset += 2; |
1812 | 0 | } |
1813 | | |
1814 | | |
1815 | | /* content field */ |
1816 | 0 | if ((flags & JXTAMSG2_ELMFLAG_UINT64_LENS) != 0) { |
1817 | 0 | available = tvb_reported_length_remaining(tvb, offset); |
1818 | 0 | if (available < sizeof(uint64_t)) { |
1819 | 0 | needed = (int) (sizeof(uint64_t) - available); |
1820 | 0 | break; |
1821 | 0 | } else { |
1822 | 0 | uint64_t content_len = tvb_get_ntoh64(tvb, offset); |
1823 | 0 | offset += (int)sizeof(uint64_t); |
1824 | |
|
1825 | 0 | available = tvb_reported_length_remaining(tvb, offset); |
1826 | 0 | if (available < content_len) { |
1827 | 0 | needed = (int) (content_len - available); |
1828 | 0 | break; |
1829 | 0 | } |
1830 | | |
1831 | 0 | offset += (unsigned) content_len; |
1832 | 0 | } |
1833 | 0 | } else { |
1834 | 0 | available = tvb_reported_length_remaining(tvb, offset); |
1835 | 0 | if (available < 4) { |
1836 | 0 | needed = (int) (4 - available); |
1837 | 0 | break; |
1838 | 0 | } else { |
1839 | 0 | uint64_t content_len = tvb_get_ntohl(tvb, offset); |
1840 | 0 | offset += 4; |
1841 | |
|
1842 | 0 | available = tvb_reported_length_remaining(tvb, offset); |
1843 | 0 | if (available < content_len) { |
1844 | 0 | needed = (int) (content_len - available); |
1845 | 0 | break; |
1846 | 0 | } |
1847 | | |
1848 | 0 | offset += (unsigned) content_len; |
1849 | 0 | } |
1850 | 0 | } |
1851 | | |
1852 | | /* signature element field */ |
1853 | 0 | if ((flags & JXTAMSG2_ELMFLAG_SIGNATURE) != 0) { |
1854 | 0 | tvbuff_t *jxta_signature_element_tvb; |
1855 | 0 | int processed; |
1856 | |
|
1857 | 0 | jxta_signature_element_tvb = tvb_new_subset_remaining(tvb, offset); |
1858 | |
|
1859 | 0 | increment_dissection_depth(pinfo); |
1860 | 0 | processed = dissect_jxta_message_element_2(jxta_signature_element_tvb, pinfo, NULL, 0, NULL); |
1861 | 0 | decrement_dissection_depth(pinfo); |
1862 | |
|
1863 | 0 | if (processed == 0) { |
1864 | 0 | return offset; |
1865 | 0 | } |
1866 | | |
1867 | 0 | if (processed < 0) { |
1868 | 0 | needed = -processed; |
1869 | 0 | break; |
1870 | 0 | } |
1871 | | |
1872 | 0 | offset += processed; |
1873 | 0 | } |
1874 | | |
1875 | 0 | break; |
1876 | 0 | } |
1877 | | |
1878 | 0 | if ((needed > 0) && gDESEGMENT && pinfo->can_desegment) { |
1879 | | /* ws_message( "Element2 requesting %d more bytes", needed ); */ |
1880 | 0 | pinfo->desegment_offset = 0; |
1881 | 0 | pinfo->desegment_len = needed; |
1882 | 0 | return -needed; |
1883 | 0 | } |
1884 | | |
1885 | | /* Second (optional) pass : build the proto tree */ |
1886 | 0 | unsigned tree_offset = 0; |
1887 | 0 | proto_item *jxta_elem_tree_item = proto_tree_add_item(tree, hf_jxta_element, tvb, tree_offset, -1, ENC_NA); |
1888 | 0 | proto_tree *jxta_elem_tree = proto_item_add_subtree(jxta_elem_tree_item, ett_jxta_elem); |
1889 | 0 | uint16_t namespaceID; |
1890 | 0 | proto_item *namespace_ti; |
1891 | 0 | uint16_t nameID; |
1892 | 0 | proto_item *name_ti; |
1893 | 0 | uint64_t content_len; |
1894 | 0 | const char *mediatype = NULL; |
1895 | 0 | tvbuff_t *element_content_tvb; |
1896 | 0 | static int * const element_flags[] = { |
1897 | 0 | &hf_jxta_element2_flag_64bitlens, |
1898 | 0 | &hf_jxta_element2_flag_nameLiteral, |
1899 | 0 | &hf_jxta_element2_flag_hasType, |
1900 | 0 | &hf_jxta_element2_flag_hasSignature, |
1901 | 0 | &hf_jxta_element2_flag_hasEncoding, |
1902 | 0 | &hf_jxta_element2_flag_sigOfEncoded, |
1903 | 0 | NULL |
1904 | 0 | }; |
1905 | |
|
1906 | 0 | proto_tree_add_item(jxta_elem_tree, hf_jxta_element_sig, tvb, tree_offset, (int)sizeof(JXTA_MSGELEM_SIG), ENC_ASCII); |
1907 | 0 | tree_offset += (int)sizeof(JXTA_MSGELEM_SIG); |
1908 | |
|
1909 | 0 | flags = tvb_get_uint8(tvb, tree_offset); |
1910 | 0 | proto_tree_add_bitmask(jxta_elem_tree, tvb, tree_offset, hf_jxta_element_flags, ett_jxta_elem_2_flags, element_flags, ENC_NA); |
1911 | 0 | tree_offset += 1; |
1912 | | |
1913 | | /* Namespace */ |
1914 | 0 | namespaceID = tvb_get_ntohs(tvb, tree_offset); |
1915 | 0 | namespace_ti = |
1916 | 0 | proto_tree_add_uint(jxta_elem_tree, hf_jxta_element2_namespaceid, tvb, tree_offset, 2, namespaceID); |
1917 | 0 | if (namespaceID < names_count) { |
1918 | 0 | proto_item_append_text(namespace_ti, " (%s)", names_table[namespaceID]); |
1919 | 0 | } else { |
1920 | 0 | proto_item_append_text(namespace_ti, " * BAD *"); |
1921 | 0 | } |
1922 | 0 | tree_offset += 2; |
1923 | | |
1924 | | /* Name */ |
1925 | 0 | if ((flags & JXTAMSG2_ELMFLAG_NAME_LITERAL) == 0) { |
1926 | 0 | nameID = tvb_get_ntohs(tvb, tree_offset); |
1927 | 0 | name_ti = |
1928 | 0 | proto_tree_add_uint(jxta_elem_tree, hf_jxta_element2_nameid, tvb, tree_offset, 2, nameID); |
1929 | 0 | if (nameID < names_count) { |
1930 | 0 | proto_item_append_text(name_ti, " (%s)", names_table[nameID]); |
1931 | 0 | } else { |
1932 | 0 | proto_item_append_text(name_ti, " * BAD *"); |
1933 | 0 | } |
1934 | 0 | tree_offset += 2; |
1935 | 0 | } else { |
1936 | | /* literal name */ |
1937 | 0 | uint16_t name_len = tvb_get_ntohs(tvb, tree_offset); |
1938 | 0 | proto_item_append_text(jxta_elem_tree_item, " \"%s\"", tvb_format_text(pinfo->pool, tvb, tree_offset + 2, name_len)); |
1939 | 0 | proto_tree_add_item(jxta_elem_tree, hf_jxta_element_name, tvb, tree_offset, 2, ENC_ASCII|ENC_BIG_ENDIAN); |
1940 | 0 | tree_offset += 2 + name_len; |
1941 | 0 | } |
1942 | | |
1943 | | /* process type */ |
1944 | 0 | if ((flags & JXTAMSG2_ELMFLAG_TYPE) != 0) { |
1945 | 0 | uint16_t mimeID = tvb_get_ntohs(tvb, tree_offset); |
1946 | 0 | proto_item *mime_ti = |
1947 | 0 | proto_tree_add_uint(jxta_elem_tree, hf_jxta_element2_mimeid, tvb, tree_offset, 2, mimeID); |
1948 | |
|
1949 | 0 | if (mimeID < names_count) { |
1950 | 0 | proto_item_append_text(mime_ti, " (%s)", names_table[mimeID]); |
1951 | 0 | mediatype = wmem_strdup( pinfo->pool, names_table[mimeID] ); |
1952 | 0 | } else { |
1953 | 0 | proto_item_append_text(mime_ti, " * BAD *"); |
1954 | 0 | } |
1955 | |
|
1956 | 0 | tree_offset += 2; |
1957 | 0 | } else { |
1958 | 0 | mediatype = "application/octet-stream"; |
1959 | 0 | } |
1960 | | |
1961 | | /* process encoding */ |
1962 | 0 | if ((flags & JXTAMSG2_ELMFLAG_ENCODINGS) != 0) { |
1963 | 0 | uint16_t encodingID = tvb_get_ntohs(tvb, tree_offset); |
1964 | 0 | proto_item *encoding_ti = |
1965 | 0 | proto_tree_add_uint(jxta_elem_tree, hf_jxta_element2_encodingid, tvb, tree_offset, 2, encodingID); |
1966 | |
|
1967 | 0 | if (encodingID < names_count) { |
1968 | 0 | proto_item_append_text(encoding_ti, " (%s)", names_table[encodingID]); |
1969 | 0 | } else { |
1970 | 0 | proto_item_append_text(encoding_ti, " * BAD *"); |
1971 | 0 | } |
1972 | |
|
1973 | 0 | tree_offset += 2; |
1974 | 0 | } |
1975 | | |
1976 | |
|
1977 | 0 | if ((flags & JXTAMSG2_ELMFLAG_UINT64_LENS) != 0) { |
1978 | 0 | content_len = tvb_get_ntoh64(tvb, tree_offset); |
1979 | 0 | proto_tree_add_item(jxta_elem_tree, hf_jxta_element_content_len64, tvb, tree_offset, 8, ENC_BIG_ENDIAN); |
1980 | 0 | tree_offset += 8; |
1981 | 0 | } else { |
1982 | 0 | content_len = tvb_get_ntohl(tvb, tree_offset); |
1983 | 0 | proto_tree_add_item(jxta_elem_tree, hf_jxta_element_content_len, tvb, tree_offset, 4, ENC_BIG_ENDIAN); |
1984 | 0 | tree_offset += 4; |
1985 | 0 | } |
1986 | | |
1987 | | /* content */ |
1988 | 0 | element_content_tvb = tvb_new_subset_length(tvb, tree_offset, (int)content_len); |
1989 | |
|
1990 | 0 | tree_offset += dissect_media(mediatype, element_content_tvb, pinfo, jxta_elem_tree); |
1991 | | |
1992 | | /* process the signature element */ |
1993 | 0 | if ((flags & JXTAMSG2_ELMFLAG_SIGNATURE) != 0) { |
1994 | 0 | tvbuff_t *jxta_message_element_tvb = tvb_new_subset_remaining(tvb, tree_offset); |
1995 | |
|
1996 | 0 | tree_offset += dissect_jxta_message_element_1(jxta_message_element_tvb, pinfo, jxta_elem_tree, names_count, names_table); |
1997 | 0 | } |
1998 | |
|
1999 | 0 | proto_item_set_end(jxta_elem_tree_item, tvb, tree_offset); |
2000 | | |
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); |
2004 | |
|
2005 | 0 | return offset; |
2006 | 0 | } |
2007 | | |
2008 | | /** |
2009 | | * Dissect a tvbuff containing arbitrary typed data. |
2010 | | * |
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> |
2018 | | * |
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. |
2026 | | **/ |
2027 | | // NOLINTNEXTLINE(misc-no-recursion) |
2028 | 0 | static int dissect_media( const char* fullmediatype, tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree) { |
2029 | 0 | int dissected = 0; |
2030 | |
|
2031 | 0 | if (fullmediatype) { |
2032 | 0 | char *mediatype = wmem_strdup(pinfo->pool, fullmediatype); |
2033 | 0 | char *parms_at = strchr(mediatype, ';'); |
2034 | 0 | const char *save_match_string = pinfo->match_string; |
2035 | 0 | media_content_info_t content_info = { MEDIA_CONTAINER_OTHER, NULL, NULL, NULL }; |
2036 | | |
2037 | | /* Based upon what is done in packet-media.c we set up type and params */ |
2038 | 0 | if (NULL != parms_at) { |
2039 | 0 | content_info.media_str = wmem_strdup( pinfo->pool, parms_at + 1 ); |
2040 | 0 | *parms_at = '\0'; |
2041 | 0 | } |
2042 | | |
2043 | | /* Set the version that goes to packet-media.c before converting case */ |
2044 | 0 | pinfo->match_string = wmem_strdup(pinfo->pool, mediatype); |
2045 | | |
2046 | | /* force to lower case */ |
2047 | 0 | ascii_strdown_inplace(mediatype); |
2048 | |
|
2049 | 0 | 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 | 0 | if (NULL != tls_handle) { |
2052 | 0 | dissected = call_dissector(tls_handle, tvb, pinfo, tree); |
2053 | 0 | } |
2054 | 0 | } else if (0 == strcmp("application/gzip", mediatype)) { |
2055 | 0 | tvbuff_t *uncomp_tvb = tvb_child_uncompress_zlib(tvb, tvb, 0, tvb_captured_length(tvb)); |
2056 | |
|
2057 | 0 | if( NULL != uncomp_tvb ) { |
2058 | 0 | add_new_data_source(pinfo, uncomp_tvb, "Uncompressed Element Content"); |
2059 | | |
2060 | | /* XXX bondolo 20060201 Force XML for uncompressed data. */ |
2061 | 0 | increment_dissection_depth(pinfo); |
2062 | 0 | dissected = dissect_media("text/xml;charset=\"UTF-8\"", uncomp_tvb, pinfo, tree); |
2063 | 0 | decrement_dissection_depth(pinfo); |
2064 | |
|
2065 | 0 | if( dissected > 0 ) { |
2066 | | /* report back the uncompressed length. */ |
2067 | 0 | dissected = tvb_captured_length(tvb); |
2068 | 0 | } |
2069 | 0 | } |
2070 | 0 | } else { |
2071 | 0 | dissected = dissector_try_string_with_data(media_type_dissector_table, mediatype, tvb, pinfo, tree, true, &content_info) ? tvb_captured_length(tvb) : 0; |
2072 | |
|
2073 | 0 | if( dissected != (int) tvb_captured_length(tvb) ) { |
2074 | | /* ws_message( "%s : %d expected, %d dissected", mediatype, tvb_captured_length(tvb), dissected ); */ |
2075 | 0 | } |
2076 | 0 | } |
2077 | |
|
2078 | 0 | if (0 == dissected) { |
2079 | 0 | dissected = call_dissector_with_data(media_handle, tvb, pinfo, tree, &content_info); |
2080 | 0 | } |
2081 | |
|
2082 | 0 | pinfo->match_string = save_match_string; |
2083 | 0 | } |
2084 | |
|
2085 | 0 | if(0 == dissected) { |
2086 | | /* display it as raw data */ |
2087 | 0 | dissected = call_data_dissector(tvb, pinfo, tree); |
2088 | 0 | } |
2089 | |
|
2090 | 0 | if (dissected < (int) tvb_reported_length(tvb)) { |
2091 | 0 | proto_item *item = proto_tree_add_expert(tree, pinfo, &ei_media_too_short, tvb, 0, dissected); |
2092 | 0 | proto_item_set_generated(item); |
2093 | 0 | } |
2094 | 0 | return dissected; |
2095 | 0 | } |
2096 | | |
2097 | | /** |
2098 | | * Register jxta protocol and jxta message protocol, header fields, subtree types, preferences. |
2099 | | **/ |
2100 | | void proto_register_jxta(void) |
2101 | 14 | { |
2102 | 14 | module_t *jxta_module; |
2103 | 14 | expert_module_t *expert_jxta; |
2104 | | |
2105 | | /** our header fields */ |
2106 | 14 | static hf_register_info hf[] = { |
2107 | 14 | {&hf_uri_addr, |
2108 | 14 | {"Address", "jxta.uri.addr", FT_STRING, BASE_NONE, NULL, 0x0, |
2109 | 14 | "URI Address (source or destination)", HFILL} |
2110 | 14 | }, |
2111 | 14 | {&hf_uri_src, |
2112 | 14 | {"Source", "jxta.uri.src", FT_STRING, BASE_NONE, NULL, 0x0, |
2113 | 14 | "URI Source", HFILL} |
2114 | 14 | }, |
2115 | 14 | {&hf_uri_dst, |
2116 | 14 | {"Destination", "jxta.uri.dst", FT_STRING, BASE_NONE, NULL, 0x0, |
2117 | 14 | "URI Destination", HFILL} |
2118 | 14 | }, |
2119 | 14 | {&hf_jxta_udp, |
2120 | 14 | {"JXTA UDP", "jxta.udp", FT_NONE, BASE_NONE, NULL, 0x0, |
2121 | 14 | NULL, HFILL} |
2122 | 14 | }, |
2123 | 14 | {&hf_jxta_udpsig, |
2124 | 14 | {"Signature", "jxta.udpsig", FT_STRING, BASE_NONE, NULL, 0x0, |
2125 | 14 | "JXTA UDP Signature", HFILL} |
2126 | 14 | }, |
2127 | 14 | {&hf_jxta_welcome, |
2128 | 14 | {"Welcome", "jxta.welcome", FT_NONE, BASE_NONE, NULL, 0x00, |
2129 | 14 | "JXTA Connection Welcome Message", HFILL} |
2130 | 14 | }, |
2131 | 14 | {&hf_jxta_welcome_initiator, |
2132 | 14 | {"Initiator", "jxta.welcome.initiator", FT_BOOLEAN, BASE_NONE, NULL, 0x00, |
2133 | 14 | "JXTA Connection Welcome Message Initiator", HFILL} |
2134 | 14 | }, |
2135 | 14 | {&hf_jxta_welcome_sig, |
2136 | 14 | {"Signature", "jxta.welcome.signature", FT_STRING, BASE_NONE, NULL, 0x0, |
2137 | 14 | "JXTA Connection Welcome Message Signature", HFILL} |
2138 | 14 | }, |
2139 | 14 | {&hf_jxta_welcome_destAddr, |
2140 | 14 | {"Destination Address", "jxta.welcome.destAddr", FT_STRING, BASE_NONE, NULL, 0x0, |
2141 | 14 | "JXTA Connection Welcome Message Destination Address", HFILL} |
2142 | 14 | }, |
2143 | 14 | {&hf_jxta_welcome_pubAddr, |
2144 | 14 | {"Public Address", "jxta.welcome.pubAddr", FT_STRING, BASE_NONE, NULL, 0x0, |
2145 | 14 | "JXTA Connection Welcome Message Public Address", HFILL} |
2146 | 14 | }, |
2147 | 14 | {&hf_jxta_welcome_peerid, |
2148 | 14 | {"PeerID", "jxta.welcome.peerid", FT_STRING, BASE_NONE, NULL, 0x0, |
2149 | 14 | "JXTA Connection Welcome Message PeerID", HFILL} |
2150 | 14 | }, |
2151 | 14 | {&hf_jxta_welcome_noProp, |
2152 | 14 | {"No Propagate Flag", "jxta.welcome.noPropFlag", FT_STRING, BASE_NONE, NULL, 0x0, |
2153 | 14 | "JXTA Connection Welcome Message No Propagate Flag", HFILL} |
2154 | 14 | }, |
2155 | 14 | {&hf_jxta_welcome_msgVers, |
2156 | 14 | {"Preferred Message Version", "jxta.welcome.msgVersion", FT_STRING, BASE_NONE, NULL, 0x0, |
2157 | 14 | "JXTA Connection Welcome Message Preferred Message Version", HFILL} |
2158 | 14 | }, |
2159 | 14 | {&hf_jxta_welcome_variable, |
2160 | 14 | {"Variable Parameter", "jxta.welcome.variable", FT_STRING, BASE_NONE, NULL, 0x0, |
2161 | 14 | "JXTA Connection Welcome Message Variable Parameter", HFILL} |
2162 | 14 | }, |
2163 | 14 | {&hf_jxta_welcome_version, |
2164 | 14 | {"Version", "jxta.welcome.version", FT_STRING, BASE_NONE, NULL, 0x0, |
2165 | 14 | "JXTA Connection Welcome Message Version", HFILL} |
2166 | 14 | }, |
2167 | 14 | {&hf_jxta_framing, |
2168 | 14 | {"Framing", "jxta.framing", FT_NONE, BASE_NONE, NULL, 0x0, |
2169 | 14 | "JXTA Message Framing", HFILL} |
2170 | 14 | }, |
2171 | 14 | {&hf_jxta_framing_header, |
2172 | 14 | {"Header", "jxta.framing.header", FT_NONE, BASE_NONE, NULL, 0x0, |
2173 | 14 | "JXTA Message Framing Header", HFILL} |
2174 | 14 | }, |
2175 | 14 | {&hf_jxta_framing_header_name, |
2176 | 14 | {"Name", "jxta.framing.header.name", FT_UINT_STRING, BASE_NONE, NULL, 0x0, |
2177 | 14 | "JXTA Message Framing Header Name", HFILL} |
2178 | 14 | }, |
2179 | 14 | {&hf_jxta_framing_header_value_length, |
2180 | 14 | {"Value Length", "jxta.framing.header.valuelen", FT_UINT16, BASE_DEC, NULL, 0x0, |
2181 | 14 | "JXTA Message Framing Header Value Length", HFILL} |
2182 | 14 | }, |
2183 | 14 | {&hf_jxta_framing_header_value, |
2184 | 14 | {"Value", "jxta.framing.header.value", FT_BYTES, BASE_NONE, NULL, 0x0, |
2185 | 14 | "JXTA Message Framing Header Value", HFILL} |
2186 | 14 | }, |
2187 | 14 | {&hf_jxta_message_address, |
2188 | 14 | {"Address", "jxta.message.address", FT_STRING, BASE_NONE, NULL, 0x0, |
2189 | 14 | "JXTA Message Address (source or destination)", HFILL} |
2190 | 14 | }, |
2191 | 14 | {&hf_jxta_message_src, |
2192 | 14 | {"Source", "jxta.message.source", FT_STRING, BASE_NONE, NULL, 0x0, |
2193 | 14 | "JXTA Message Source", HFILL} |
2194 | 14 | }, |
2195 | 14 | {&hf_jxta_message_dst, |
2196 | 14 | {"Destination", "jxta.message.destination", FT_STRING, BASE_NONE, NULL, 0x0, |
2197 | 14 | "JXTA Message Destination", HFILL} |
2198 | 14 | }, |
2199 | 14 | {&hf_jxta_message_sig, |
2200 | 14 | {"Signature", "jxta.message.signature", FT_STRING, BASE_NONE, NULL, 0x0, |
2201 | 14 | "JXTA Message Signature", HFILL} |
2202 | 14 | }, |
2203 | 14 | {&hf_jxta_message_version, |
2204 | 14 | {"Version", "jxta.message.version", FT_UINT8, BASE_DEC, NULL, 0x0, |
2205 | 14 | "JXTA Message Version", HFILL} |
2206 | 14 | }, |
2207 | 14 | {&hf_jxta_message_flags, |
2208 | 14 | {"Flags", "jxta.message.flags", FT_UINT8, BASE_HEX, NULL, 0x0, |
2209 | 14 | "JXTA Message Flags", HFILL} |
2210 | 14 | }, |
2211 | 14 | {&hf_jxta_message_flag_utf16be, |
2212 | 14 | {"UTF16BE", "jxta.message.flags.UTF-16BE", FT_BOOLEAN, 2, TFS(&tfs_set_notset), 0x1, |
2213 | 14 | "JXTA Message Element Flag -- UTF16-BE Strings", HFILL} |
2214 | 14 | }, |
2215 | 14 | {&hf_jxta_message_flag_ucs32be, |
2216 | 14 | {"UCS32BE", "jxta.message.flags.UCS32BE", FT_BOOLEAN, 2, TFS(&tfs_set_notset), 0x2, |
2217 | 14 | "JXTA Message Flag -- UCS32-BE Strings", HFILL} |
2218 | 14 | }, |
2219 | 14 | {&hf_jxta_message_names_count, |
2220 | 14 | {"Names Count", "jxta.message.names", FT_UINT16, BASE_DEC, NULL, 0x0, |
2221 | 14 | "JXTA Message Names Table", HFILL} |
2222 | 14 | }, |
2223 | 14 | {&hf_jxta_message_names_name, |
2224 | 14 | {"Names Table Name", "jxta.message.names.name", FT_UINT_STRING, BASE_NONE, NULL, 0x0, |
2225 | 14 | "JXTA Message Names Table Name", HFILL} |
2226 | 14 | }, |
2227 | 14 | {&hf_jxta_message_element_count, |
2228 | 14 | {"Element Count", "jxta.message.elements", FT_UINT16, BASE_DEC, NULL, 0x0, |
2229 | 14 | "JXTA Message Element Count", HFILL} |
2230 | 14 | }, |
2231 | 14 | {&hf_jxta_element, |
2232 | 14 | {"JXTA Message Element", "jxta.message.element", FT_NONE, BASE_NONE, NULL, 0x0, |
2233 | 14 | NULL, HFILL} |
2234 | 14 | }, |
2235 | 14 | {&hf_jxta_element_sig, |
2236 | 14 | {"Signature", "jxta.message.element.signature", FT_STRING, BASE_NONE, NULL, 0x0, |
2237 | 14 | "JXTA Message Element Signature", HFILL} |
2238 | 14 | }, |
2239 | 14 | {&hf_jxta_element1_namespaceid, |
2240 | 14 | {"Namespace ID", "jxta.message.element.namespaceid", FT_UINT8, BASE_DEC, NULL, 0x0, |
2241 | 14 | "JXTA Message Element Namespace ID", HFILL} |
2242 | 14 | }, |
2243 | 14 | {&hf_jxta_element2_namespaceid, |
2244 | 14 | {"Namespace ID", "jxta.message.element.namespaceid", FT_UINT16, BASE_DEC, NULL, 0x0, |
2245 | 14 | "JXTA Message Element Namespace ID", HFILL} |
2246 | 14 | }, |
2247 | 14 | {&hf_jxta_element_flags, |
2248 | 14 | {"Flags", "jxta.message.element.flags", FT_UINT8, BASE_HEX, NULL, 0x0, |
2249 | 14 | "JXTA Message Element Flags", HFILL} |
2250 | 14 | }, |
2251 | 14 | {&hf_jxta_element1_flag_hasType, |
2252 | 14 | {"hasType", "jxta.message.element.flags.hasType", FT_BOOLEAN, 3, TFS(&tfs_set_notset), 0x1, |
2253 | 14 | "JXTA Message Element Flag -- hasType", HFILL} |
2254 | 14 | }, |
2255 | 14 | {&hf_jxta_element1_flag_hasEncoding, |
2256 | 14 | {"hasEncoding", "jxta.message.element.flags.hasEncoding", FT_BOOLEAN, 3, TFS(&tfs_set_notset), 0x2, |
2257 | 14 | "JXTA Message Element Flag -- hasEncoding", HFILL} |
2258 | 14 | }, |
2259 | 14 | {&hf_jxta_element1_flag_hasSignature, |
2260 | 14 | {"hasSignature", "jxta.message.element.flags.hasSignature", FT_BOOLEAN, 3, TFS(&tfs_set_notset), 0x4, |
2261 | 14 | "JXTA Message Element Flag -- hasSignature", HFILL} |
2262 | 14 | }, |
2263 | 14 | {&hf_jxta_element2_flag_64bitlens, |
2264 | 14 | {"uint64Lens", "jxta.message.element.flags.uint64Lens", FT_BOOLEAN, 6, TFS(&tfs_set_notset), 0x01, |
2265 | 14 | "JXTA Message Element Flag -- uint64Lens", HFILL} |
2266 | 14 | }, |
2267 | 14 | {&hf_jxta_element2_flag_nameLiteral, |
2268 | 14 | {"nameLiteral", "jxta.message.element.flags.nameLiteral", FT_BOOLEAN, 6, TFS(&tfs_set_notset), 0x02, |
2269 | 14 | "JXTA Message Element Flag -- nameLiteral", HFILL} |
2270 | 14 | }, |
2271 | 14 | {&hf_jxta_element2_flag_hasType, |
2272 | 14 | {"hasType", "jxta.message.element.flags.hasType", FT_BOOLEAN, 6, TFS(&tfs_set_notset), 0x04, |
2273 | 14 | "JXTA Message Element Flag -- hasType", HFILL} |
2274 | 14 | }, |
2275 | 14 | {&hf_jxta_element2_flag_hasSignature, |
2276 | 14 | {"hasSignature", "jxta.message.element.flags.hasSignature", FT_BOOLEAN, 6, TFS(&tfs_set_notset), 0x08, |
2277 | 14 | "JXTA Message Element Flag -- hasSignature", HFILL} |
2278 | 14 | }, |
2279 | 14 | {&hf_jxta_element2_flag_hasEncoding, |
2280 | 14 | {"hasSignature", "jxta.message.element.flags.hasEncoding", FT_BOOLEAN, 6, TFS(&tfs_set_notset), 0x10, |
2281 | 14 | "JXTA Message Element Flag -- hasEncoding", HFILL} |
2282 | 14 | }, |
2283 | 14 | {&hf_jxta_element2_flag_sigOfEncoded, |
2284 | 14 | {"sigOfEncoded", "jxta.message.element.flags.sigOfEncoded", FT_BOOLEAN, 6, TFS(&tfs_set_notset), 0x20, |
2285 | 14 | "JXTA Message Element Flag -- sigOfEncoded", HFILL} |
2286 | 14 | }, |
2287 | 14 | {&hf_jxta_element2_nameid, |
2288 | 14 | {"Name ID", "jxta.message.element.nameid", FT_UINT16, BASE_DEC, NULL, 0x0, |
2289 | 14 | "JXTA Message Element Name ID", HFILL} |
2290 | 14 | }, |
2291 | 14 | {&hf_jxta_element_name, |
2292 | 14 | {"Element Name", "jxta.message.element.name", FT_UINT_STRING, BASE_NONE, NULL, 0x0, |
2293 | 14 | "JXTA Message Element Name", HFILL} |
2294 | 14 | }, |
2295 | 14 | {&hf_jxta_element2_mimeid, |
2296 | 14 | {"MIME ID", "jxta.message.element.mimeid", FT_UINT16, BASE_DEC, NULL, 0x0, |
2297 | 14 | "JXTA Message Element MIME ID", HFILL} |
2298 | 14 | }, |
2299 | 14 | {&hf_jxta_element2_encodingid, |
2300 | 14 | {"Encoding ID", "jxta.message.element.encodingid", FT_UINT16, BASE_DEC, NULL, 0x0, |
2301 | 14 | "JXTA Message Element Encoding ID", HFILL} |
2302 | 14 | }, |
2303 | 14 | {&hf_jxta_element_type, |
2304 | 14 | {"Element Type", "jxta.message.element.type", FT_UINT_STRING, BASE_NONE, NULL, 0x0, |
2305 | 14 | "JXTA Message Element Name", HFILL} |
2306 | 14 | }, |
2307 | 14 | {&hf_jxta_element_encoding, |
2308 | 14 | {"Element Type", "jxta.message.element.encoding", FT_UINT_STRING, BASE_NONE, NULL, 0x0, |
2309 | 14 | "JXTA Message Element Encoding", HFILL} |
2310 | 14 | }, |
2311 | 14 | {&hf_jxta_element_content_len, |
2312 | 14 | {"Element Content Length", "jxta.message.element.content.length", FT_UINT32, BASE_DEC, NULL, 0x0, |
2313 | 14 | "JXTA Message Element Content Length", HFILL} |
2314 | 14 | }, |
2315 | 14 | {&hf_jxta_element_content_len64, |
2316 | 14 | {"Element Content Length", "jxta.message.element.content.length64", FT_UINT64, BASE_DEC, NULL, 0x0, |
2317 | 14 | "JXTA Message Element Content Length", HFILL} |
2318 | 14 | }, |
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} |
2323 | | }, |
2324 | | #endif |
2325 | 14 | }; |
2326 | | |
2327 | 14 | static ei_register_info ei[] = { |
2328 | 14 | { &ei_media_too_short, { "jxta.media_too_short", PI_PROTOCOL, PI_WARN, "Media length less than expected", EXPFILL }}, |
2329 | 14 | }; |
2330 | | |
2331 | | /** |
2332 | | * JXTA Protocol subtree array |
2333 | | **/ |
2334 | 14 | static int *ett[] = { |
2335 | 14 | &ett_jxta, |
2336 | 14 | &ett_jxta_welcome, |
2337 | 14 | &ett_jxta_udp, |
2338 | 14 | &ett_jxta_framing, |
2339 | 14 | &ett_jxta_framing_header, |
2340 | 14 | &ett_jxta_msg, |
2341 | 14 | &ett_jxta_msg_flags, |
2342 | 14 | &ett_jxta_elem, |
2343 | 14 | &ett_jxta_elem_1_flags, |
2344 | 14 | &ett_jxta_elem_2_flags |
2345 | 14 | }; |
2346 | | |
2347 | 14 | proto_jxta = proto_register_protocol("JXTA P2P", "JXTA", "jxta"); |
2348 | | |
2349 | 14 | jxta_tap = register_tap("jxta"); |
2350 | | |
2351 | 14 | proto_message_jxta = proto_register_protocol("JXTA Message", "JXTA Message", "jxta.message"); |
2352 | | |
2353 | 14 | jxta_udp_handle = register_dissector("jxta.udp", dissect_jxta_udp, proto_jxta); |
2354 | 14 | stream_jxta_handle = register_dissector("jxta.stream", dissect_jxta_stream, proto_jxta); |
2355 | | |
2356 | | /* Register header fields */ |
2357 | 14 | proto_register_field_array(proto_jxta, hf, array_length(hf)); |
2358 | | |
2359 | | /* Register JXTA Sub-tree */ |
2360 | 14 | proto_register_subtree_array(ett, array_length(ett)); |
2361 | | |
2362 | 14 | expert_jxta = expert_register_protocol(proto_jxta); |
2363 | 14 | expert_register_field_array(expert_jxta, ei, array_length(ei)); |
2364 | | |
2365 | 14 | 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); |
2366 | | |
2367 | | /* Register preferences */ |
2368 | | /* register re-init routine */ |
2369 | 14 | jxta_module = prefs_register_protocol(proto_jxta, proto_reg_handoff_jxta); |
2370 | | |
2371 | 14 | prefs_register_bool_preference(jxta_module, "msg.mediatype", "Register binary JXTA Message as a media type", |
2372 | 14 | "Enable to have correctly typed MIME media dissected as JXTA Messages.", &gMSG_MEDIA); |
2373 | | |
2374 | 14 | prefs_register_bool_preference(jxta_module, "desegment", |
2375 | 14 | "Reassemble JXTA messages spanning multiple UDP/TCP/SCTP segments", |
2376 | 14 | "Whether the JXTA dissector should reassemble messages spanning multiple UDP/TCP/SCTP segments." |
2377 | 14 | " To use this option you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings " |
2378 | 14 | " and enable \"Reassemble fragmented IP datagrams\" in the IP protocol settings.", |
2379 | 14 | &gDESEGMENT); |
2380 | | |
2381 | 14 | prefs_register_obsolete_preference(jxta_module, "udp.heuristic"); |
2382 | 14 | prefs_register_obsolete_preference(jxta_module, "tcp.heuristic"); |
2383 | 14 | prefs_register_obsolete_preference(jxta_module, "sctp.heuristic"); |
2384 | | |
2385 | 14 | register_conversation_table(proto_jxta, true, jxta_conversation_packet, jxta_endpoint_packet); |
2386 | 14 | } |
2387 | | |
2388 | | |
2389 | | /** |
2390 | | * Update registrations in response to preferences changes. |
2391 | | **/ |
2392 | | void proto_reg_handoff_jxta(void) |
2393 | 14 | { |
2394 | 14 | static bool init_done = false; |
2395 | 14 | static dissector_handle_t message_jxta_handle; |
2396 | | |
2397 | 14 | static bool msg_media_register_done = false; |
2398 | | |
2399 | 14 | if(!init_done) { |
2400 | 14 | message_jxta_handle = create_dissector_handle(dissect_jxta_message, proto_message_jxta); |
2401 | | |
2402 | 14 | media_type_dissector_table = find_dissector_table("media_type"); |
2403 | 14 | tls_handle = find_dissector_add_dependency("tls", proto_jxta); |
2404 | | |
2405 | 14 | media_handle = find_dissector_add_dependency("media", proto_jxta); |
2406 | | |
2407 | 14 | heur_dissector_add("udp", dissect_jxta_UDP_heur, "JXTA over UDP", "jxta_udp", proto_jxta, HEURISTIC_ENABLE); |
2408 | 14 | heur_dissector_add("tcp", dissect_jxta_TCP_heur, "JXTA over TCP", "jxta_tcp", proto_jxta, HEURISTIC_ENABLE); |
2409 | 14 | heur_dissector_add("sctp", dissect_jxta_SCTP_heur, "JXTA over SCTP", "jxta_sctp", proto_jxta, HEURISTIC_ENABLE); |
2410 | | |
2411 | 14 | init_done = true; |
2412 | 14 | } |
2413 | | |
2414 | 14 | if( gMSG_MEDIA ) { |
2415 | 14 | if( !msg_media_register_done ) { |
2416 | | /* ws_message( "Registering JXTA Message media type" ); */ |
2417 | 14 | dissector_add_string("media_type", "application/x-jxta-msg", message_jxta_handle); |
2418 | 14 | msg_media_register_done = true; |
2419 | 14 | } |
2420 | 14 | } else { |
2421 | 0 | if( msg_media_register_done ) { |
2422 | | /* ws_message( "Deregistering JXTA Message media type" ); */ |
2423 | 0 | dissector_delete_string("media_type", "application/x-jxta-msg", message_jxta_handle); |
2424 | | msg_media_register_done = false; |
2425 | 0 | } |
2426 | 0 | } |
2427 | 14 | } |
2428 | | |
2429 | | /* |
2430 | | * Editor modelines - https://www.wireshark.org/tools/modelines.html |
2431 | | * |
2432 | | * Local variables: |
2433 | | * c-basic-offset: 4 |
2434 | | * tab-width: 8 |
2435 | | * indent-tabs-mode: nil |
2436 | | * End: |
2437 | | * |
2438 | | * vi: set shiftwidth=4 tabstop=8 expandtab: |
2439 | | * :indentSize=4:tabSize=8:noTabs=true: |
2440 | | */ |