1 /* packet-tcpclv3.c
2 * References:
3 * RFC 7242: https://tools.ietf.org/html/rfc7242
4 *
5 * Copyright 2006-2007 The MITRE Corporation.
6 * All Rights Reserved.
7 * Approved for Public Release; Distribution Unlimited.
8 * Tracking Number 07-0090.
9 *
10 * The US Government will not be charged any license fee and/or royalties
11 * related to this software. Neither name of The MITRE Corporation; nor the
12 * names of its contributors may be used to endorse or promote products
13 * derived from this software without specific prior written permission.
14 *
15 * Wireshark - Network traffic analyzer
16 * By Gerald Combs <gerald@wireshark.org>
17 * Copyright 1998 Gerald Combs
18 *
19 * SPDX-License-Identifier: GPL-2.0-or-later
20 *
21 * Specification reference:
22 * RFC 5050
23 * https://tools.ietf.org/html/rfc5050
24 */
25
26 /*
27 * Modifications were made to this file under designation MFS-33289-1 and
28 * are Copyright 2015 United States Government as represented by NASA
29 * Marshall Space Flight Center. All Rights Reserved.
30 *
31 * Released under the GNU GPL with NASA legal approval granted 2016-06-10.
32 *
33 * The subject software is provided "AS IS" WITHOUT ANY WARRANTY of any kind,
34 * either expressed, implied or statutory and this agreement does not,
35 * in any manner, constitute an endorsement by government agency of any
36 * results, designs or products resulting from use of the subject software.
37 * See the Agreement for the specific language governing permissions and
38 * limitations.
39 */
40
41 #include "config.h"
42
43 #include <stdio.h>
44 #include <epan/packet.h>
45 #include <epan/reassemble.h>
46 #include <epan/expert.h>
47 #include "packet-tcpclv3.h"
48 #include "packet-bpv6.h"
49 #include "packet-tcp.h"
50
51 /* For Reassembling TCP Convergence Layer segments */
52 static reassembly_table msg_reassembly_table;
53
54 static const char magic[] = {'d', 't', 'n', '!'};
55
56 static int proto_tcp_conv = -1;
57
58 /* TCP Convergence Header Variables */
59 static int hf_tcp_convergence_pkt_type = -1;
60
61 /* Refuse-Bundle reason code */
62 static int hf_dtn_refuse_bundle_reason_code = -1;
63
64 static int hf_contact_hdr_version = -1;
65 static int hf_contact_hdr_flags = -1;
66 static int hf_contact_hdr_keep_alive = -1;
67 static int hf_contact_hdr_flags_ack_req = -1;
68 static int hf_contact_hdr_flags_frag_enable = -1;
69 static int hf_contact_hdr_flags_nak = -1;
70 static int hf_contact_hdr_magic = -1;
71 static int hf_contact_hdr_local_eid_length = -1;
72 static int hf_contact_hdr_local_eid = -1;
73
74 /* TCP Convergence Data Header Variables */
75 static int hf_tcp_convergence_data_procflags = -1;
76 static int hf_tcp_convergence_data_procflags_start = -1;
77 static int hf_tcp_convergence_data_procflags_end = -1;
78 static int hf_tcp_convergence_data_segment_length = -1;
79
80 /* TCP Convergence Ack Variables */
81 static int hf_tcp_convergence_ack_length = -1;
82
83 /* TCP Convergence Shutdown Header Variables */
84 static int hf_tcp_convergence_shutdown_flags = -1;
85 static int hf_tcp_convergence_shutdown_flags_reason = -1;
86 static int hf_tcp_convergence_shutdown_flags_delay = -1;
87 static int hf_tcp_convergence_shutdown_reason = -1;
88 static int hf_tcp_convergence_shutdown_delay = -1;
89
90 /*TCP Convergence Layer Reassembly boilerplate*/
91 static int hf_msg_fragments = -1;
92 static int hf_msg_fragment = -1;
93 static int hf_msg_fragment_overlap = -1;
94 static int hf_msg_fragment_overlap_conflicts = -1;
95 static int hf_msg_fragment_multiple_tails = -1;
96 static int hf_msg_fragment_too_long_fragment = -1;
97 static int hf_msg_fragment_error = -1;
98 static int hf_msg_fragment_count = -1;
99 static int hf_msg_reassembled_in = -1;
100 static int hf_msg_reassembled_length = -1;
101
102 /* Tree Node Variables */
103 static gint ett_conv_flags = -1;
104 static gint ett_shutdown_flags = -1;
105 static gint ett_contact_hdr_flags = -1;
106 static gint ett_tcp_conv = -1;
107 static gint ett_tcp_conv_hdr = -1;
108 static gint ett_msg_fragment = -1;
109 static gint ett_msg_fragments = -1;
110
111 static expert_field ei_tcp_convergence_data_flags = EI_INIT;
112 static expert_field ei_tcp_convergence_segment_length = EI_INIT;
113 static expert_field ei_tcp_convergence_ack_length = EI_INIT;
114
115
116 static dissector_handle_t bundle_handle;
117
118 typedef struct dictionary_data {
119 int bundle_header_dict_length;
120
121 int dest_scheme_offset;
122 int dst_scheme_pos;
123 int dst_scheme_len;
124 int source_scheme_offset;
125 int src_scheme_pos;
126 int src_scheme_len;
127 int report_scheme_offset;
128 int rpt_scheme_pos;
129 int rpt_scheme_len;
130 int cust_scheme_offset;
131 int cust_scheme_pos;
132 int cust_scheme_len;
133 int dest_ssp_offset;
134 int dst_ssp_len;
135 int source_ssp_offset;
136 int src_ssp_len;
137 int report_ssp_offset;
138 int rpt_ssp_len;
139 int cust_ssp_offset;
140 int cust_ssp_len;
141
142 } dictionary_data_t;
143
144
145 static const value_string packet_type_vals[] = {
146 {((TCP_CONVERGENCE_DATA_SEGMENT>>4) & 0x0F), "Data"},
147 {((TCP_CONVERGENCE_ACK_SEGMENT>>4) & 0x0F), "Ack"},
148 {((TCP_CONVERGENCE_REFUSE_BUNDLE>>4) & 0x0F), "Refuse Bundle"},
149 {((TCP_CONVERGENCE_KEEP_ALIVE>>4) & 0x0F), "Keep Alive"},
150 {((TCP_CONVERGENCE_SHUTDOWN>>4) & 0x0F), "Shutdown"},
151 {((TCP_CONVERGENCE_LENGTH>>4) & 0x0F), "Length"},
152 {0, NULL}
153 };
154
155 /* Refuse-Bundle Reason-Code Flags as per RFC-7242: Section-5.4 */
156 static const value_string refuse_bundle_reason_code[] = {
157 {TCP_REFUSE_BUNDLE_REASON_UNKNOWN, "Reason for refusal is unknown"},
158 {TCP_REFUSE_BUNDLE_REASON_RX_COMPLETE, "Complete Bundle Received"},
159 {TCP_REFUSE_BUNDLE_REASON_RX_EXHAUSTED, "Receiver's resources exhausted"},
160 {TCP_REFUSE_BUNDLE_REASON_RX_RETRANSMIT, "Receiver expects re-transmission of bundle"},
161 {0, NULL}
162 };
163
164 static const fragment_items msg_frag_items = {
165 /*Fragment subtrees*/
166 &ett_msg_fragment,
167 &ett_msg_fragments,
168 /*Fragment Fields*/
169 &hf_msg_fragments,
170 &hf_msg_fragment,
171 &hf_msg_fragment_overlap,
172 &hf_msg_fragment_overlap_conflicts,
173 &hf_msg_fragment_multiple_tails,
174 &hf_msg_fragment_too_long_fragment,
175 &hf_msg_fragment_error,
176 &hf_msg_fragment_count,
177 /*Reassembled in field*/
178 &hf_msg_reassembled_in,
179 /*Reassembled length field*/
180 &hf_msg_reassembled_length,
181 /* Reassembled data field */
182 NULL,
183 /*Tag*/
184 "Message fragments"
185 };
186
187 static guint
get_dtn_contact_header_len(packet_info * pinfo _U_,tvbuff_t * tvb,int offset,void * data _U_)188 get_dtn_contact_header_len(packet_info *pinfo _U_, tvbuff_t *tvb,
189 int offset, void *data _U_)
190 {
191 int len, bytecount;
192
193 /* get length from sdnv */
194 len = evaluate_sdnv(tvb, offset+8, &bytecount);
195 if (len < 0)
196 return 0;
197
198 return len+bytecount+8;
199 }
200
201 static int
dissect_dtn_contact_header(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)202 dissect_dtn_contact_header(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
203 {
204 proto_item *ti;
205 proto_tree *conv_proto_tree, *conv_tree, *conv_flag_tree;
206 int eid_length, sdnv_length;
207 int offset = 0;
208
209 col_set_str(pinfo->cinfo, COL_PROTOCOL, "TCPCLv3");
210 col_clear(pinfo->cinfo,COL_INFO); /* Clear out stuff in the info column */
211 col_add_str(pinfo->cinfo, COL_INFO, "Contact Header");
212
213 ti = proto_tree_add_item(tree, proto_tcp_conv, tvb, offset, -1, ENC_NA);
214 conv_proto_tree = proto_item_add_subtree(ti, ett_tcp_conv);
215
216 conv_tree = proto_tree_add_subtree(conv_proto_tree, tvb, offset, -1, ett_tcp_conv, NULL, "Contact Header");
217
218 proto_tree_add_item(conv_tree, hf_contact_hdr_magic, tvb, offset, 4, ENC_NA|ENC_ASCII);
219 offset += 4;
220 proto_tree_add_item(conv_tree, hf_contact_hdr_version, tvb, offset, 1, ENC_BIG_ENDIAN);
221 offset++;
222
223 /* Subtree to expand the bits in the Contact Header Flags */
224 ti = proto_tree_add_item(conv_tree, hf_contact_hdr_flags, tvb, offset, 1, ENC_BIG_ENDIAN);
225 conv_flag_tree = proto_item_add_subtree(ti, ett_contact_hdr_flags);
226 proto_tree_add_item(conv_flag_tree, hf_contact_hdr_flags_ack_req, tvb, offset, 1, ENC_BIG_ENDIAN);
227 proto_tree_add_item(conv_flag_tree, hf_contact_hdr_flags_frag_enable, tvb, offset, 1, ENC_BIG_ENDIAN);
228 proto_tree_add_item(conv_flag_tree, hf_contact_hdr_flags_nak, tvb, offset, 1, ENC_BIG_ENDIAN);
229 offset++;
230
231 proto_tree_add_item(conv_tree, hf_contact_hdr_keep_alive, tvb, offset, 2, ENC_BIG_ENDIAN);
232 offset += 2;
233
234 /*
235 * New format Contact header has length field followed by Bundle Header.
236 */
237 expert_field *ei_bundle_sdnv_length;
238 eid_length = evaluate_sdnv_ei(tvb, offset, &sdnv_length, &ei_bundle_sdnv_length);
239 ti = proto_tree_add_int(tree, hf_contact_hdr_local_eid_length, tvb, offset, sdnv_length, eid_length);
240 if (ei_bundle_sdnv_length) {
241 expert_add_info(pinfo, ti, ei_bundle_sdnv_length);
242 return offset;
243 }
244
245 proto_tree_add_item(conv_tree, hf_contact_hdr_local_eid, tvb, sdnv_length + offset, eid_length, ENC_NA|ENC_ASCII);
246 return tvb_captured_length(tvb);
247 }
248
249 static guint
get_tcpcl_pdu_len(packet_info * pinfo _U_,tvbuff_t * tvb,int offset,void * data _U_)250 get_tcpcl_pdu_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset, void *data _U_)
251 {
252 int len, bytecount;
253 guint8 conv_hdr = tvb_get_guint8(tvb, offset);
254
255 switch (conv_hdr & TCP_CONVERGENCE_TYPE_MASK)
256 {
257 case TCP_CONVERGENCE_DATA_SEGMENT:
258 /* get length from sdnv */
259 len = evaluate_sdnv(tvb, offset+1, &bytecount);
260 if (len < 0)
261 return 0;
262
263 return len+bytecount+1;
264
265 case TCP_CONVERGENCE_ACK_SEGMENT:
266 /* get length from sdnv */
267 len = evaluate_sdnv(tvb, offset+1, &bytecount);
268 if (len < 0)
269 return 0;
270
271 return bytecount+1;
272
273 case TCP_CONVERGENCE_KEEP_ALIVE:
274 case TCP_CONVERGENCE_REFUSE_BUNDLE:
275 /* always 1 byte */
276 return 1;
277 case TCP_CONVERGENCE_SHUTDOWN:
278 len = 1;
279
280 if (conv_hdr & TCP_CONVERGENCE_SHUTDOWN_REASON) {
281 len += 1;
282 }
283 if (conv_hdr & TCP_CONVERGENCE_SHUTDOWN_DELAY) {
284 len += 2;
285 }
286
287 return len;
288
289 case TCP_CONVERGENCE_LENGTH:
290 /* get length from sdnv */
291 len = evaluate_sdnv(tvb, offset+1, &bytecount);
292 if (len < 0)
293 return 0;
294 return bytecount+1;
295
296 }
297
298 /* This probably isn't a TCPCL/Bundle packet, so just stop dissection */
299 return -1;
300 }
301
302 static int
dissect_tcpcl_pdu(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data)303 dissect_tcpcl_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
304 {
305 guint8 conv_hdr;
306 guint8 refuse_bundle_hdr;
307 int offset = 0;
308 int sdnv_length, segment_length, convergence_hdr_size;
309 proto_item *ci, *sub_item;
310 proto_tree *conv_proto_tree, *conv_tree, *sub_tree;
311 fragment_head *frag_msg;
312 tvbuff_t *new_tvb;
313 gboolean more_frags;
314 int processed_length = 0;
315 const gchar* col_text;
316 gboolean bundle_in_col_info;
317
318 static guint32 frag_id = 0;
319 static guint32 last_frame = 0;
320 static int last_raw_offset = 0;
321
322 if (last_frame != pinfo->fd->num || tvb_raw_offset(tvb) < last_raw_offset)
323 frag_id = 0;
324 last_frame = pinfo->fd->num;
325 last_raw_offset = tvb_raw_offset(tvb);
326
327 col_set_str(pinfo->cinfo, COL_PROTOCOL, "TCPCL");
328 col_clear(pinfo->cinfo,COL_INFO); /* Clear out stuff in the info column */
329
330 col_text = col_get_text(pinfo->cinfo, COL_INFO);
331 bundle_in_col_info = (col_text && strstr(col_text, " > "));
332
333 ci = proto_tree_add_item(tree, proto_tcp_conv, tvb, offset, -1, ENC_NA);
334 conv_proto_tree = proto_item_add_subtree(ci, ett_tcp_conv);
335
336 conv_tree = proto_tree_add_subtree(conv_proto_tree, tvb, 0, -1, ett_tcp_conv_hdr, NULL, "TCP Convergence Header");
337
338 conv_hdr = tvb_get_guint8(tvb, offset);
339 proto_tree_add_item(conv_tree, hf_tcp_convergence_pkt_type, tvb, offset, 1, ENC_BIG_ENDIAN);
340 col_add_str(pinfo->cinfo, COL_INFO, val_to_str_const((conv_hdr>>4)&0xF, packet_type_vals, "Unknown"));
341
342 switch (conv_hdr & TCP_CONVERGENCE_TYPE_MASK)
343 {
344 case TCP_CONVERGENCE_DATA_SEGMENT:
345 sub_item = proto_tree_add_item(conv_tree, hf_tcp_convergence_data_procflags, tvb,
346 offset, 1, ENC_BIG_ENDIAN);
347 sub_tree = proto_item_add_subtree(sub_item, ett_conv_flags);
348 proto_tree_add_item(sub_tree, hf_tcp_convergence_data_procflags_start,
349 tvb, offset, 1, ENC_BIG_ENDIAN);
350 proto_tree_add_item(sub_tree, hf_tcp_convergence_data_procflags_end,
351 tvb, offset, 1, ENC_BIG_ENDIAN);
352
353 /* Only Start and End flags (bits 0 & 1) are valid in Data Segment */
354 if ((conv_hdr & ~(TCP_CONVERGENCE_TYPE_MASK | TCP_CONVERGENCE_DATA_FLAGS)) != 0) {
355 expert_add_info(pinfo, sub_item, &ei_tcp_convergence_data_flags);
356 }
357
358 segment_length = evaluate_sdnv(tvb, 1, &sdnv_length);
359 sub_item = proto_tree_add_int(conv_tree, hf_tcp_convergence_data_segment_length, tvb, 1, sdnv_length, segment_length);
360 if (segment_length < 0) {
361 expert_add_info(pinfo, sub_item, &ei_tcp_convergence_segment_length);
362 return 1;
363 }
364
365 convergence_hdr_size = sdnv_length + 1;
366
367 /*
368 * 1/11/2006 - If I got here, I should have a complete convergence layer
369 * "segment" beginning at frame_offset. However that might not be a
370 * complete bundle. Or there might be a complete bundle plus one or more
371 * additional convergence layer headers.
372 */
373
374 new_tvb = NULL;
375 sub_tree = NULL;
376 if ((conv_hdr & TCP_CONVERGENCE_DATA_END_FLAG) == TCP_CONVERGENCE_DATA_END_FLAG) {
377 more_frags = FALSE;
378 }
379 else {
380 more_frags = TRUE;
381 }
382
383 frag_msg = fragment_add_seq_next(&msg_reassembly_table,
384 tvb, offset + convergence_hdr_size,
385 pinfo, frag_id, data,
386 segment_length, more_frags);
387
388 if (!more_frags) ++frag_id;
389
390 processed_length = convergence_hdr_size + segment_length;
391
392 if (frag_msg && !more_frags) {
393
394 int save_fd_head_layer = frag_msg->reas_in_layer_num;
395 frag_msg->reas_in_layer_num = pinfo->curr_layer_num;
396
397 new_tvb = process_reassembled_data(tvb, offset + convergence_hdr_size,
398 pinfo, "Reassembled DTN", frag_msg,
399 &msg_frag_items, NULL,
400 proto_tree_get_parent_tree(tree)
401 );
402
403 frag_msg->reas_in_layer_num = save_fd_head_layer;
404 }
405
406 if (new_tvb) {
407 if (0 == call_dissector_with_data(bundle_handle, new_tvb, pinfo, sub_tree, data)) {
408 /*Couldn't parse bundle, treat as raw data */
409 call_data_dissector(new_tvb, pinfo, sub_tree);
410 return tvb_captured_length(tvb);
411 }
412 }
413 else {
414
415 /*
416 * If there are 2 segments, the second of which is very short, this
417 * gets displayed instead of the usual Source EID/Destination EID in
418 * the Bundle Dissection frame. If these statements are left out entirely,
419 * nothing is displayed, i.e., there seems to be no way to get the
420 * Source/Destination in the 2-segment case. I'll leave it in because I
421 * think it is informative in the multi-segment case although confusing in the
422 * 2-segment case.
423 */
424 col_add_str(pinfo->cinfo, COL_INFO, "[Bundle TCPCL Segment]");
425 }
426 break;
427 case TCP_CONVERGENCE_ACK_SEGMENT:
428 if (bundle_in_col_info) {
429 if (!strstr(col_text, ", TCPL ACK")) {
430 col_add_str(pinfo->cinfo, COL_INFO, ", TCPL ACK Segment(s)");
431 }
432 } else {
433 col_set_str(pinfo->cinfo, COL_INFO, "TCPL ACK Segment(s)");
434 }
435 segment_length = evaluate_sdnv(tvb, offset+1, &sdnv_length);
436 sub_item = proto_tree_add_int(conv_tree, hf_tcp_convergence_ack_length, tvb, offset+1, sdnv_length, segment_length);
437 if (segment_length < 0) {
438 expert_add_info(pinfo, sub_item, &ei_tcp_convergence_ack_length);
439 processed_length = tvb_captured_length(tvb);
440 } else {
441 processed_length = sdnv_length + 1;
442 }
443 break;
444 case TCP_CONVERGENCE_KEEP_ALIVE:
445 if (bundle_in_col_info) {
446 if (!strstr(col_text, ", TCPL KEEPALIVE")) {
447 col_add_str(pinfo->cinfo, COL_INFO, ", TCPL KEEPALIVE Segment");
448 }
449 } else {
450 col_set_str(pinfo->cinfo, COL_INFO, "TCPL KEEPALIVE Segment");
451 }
452 /*No valid flags in Keep Alive*/
453 processed_length = 1;
454 break;
455
456 case TCP_CONVERGENCE_SHUTDOWN:
457 if (bundle_in_col_info) {
458 if (!strstr(col_text, ", TCPL SHUTDOWN")) {
459 col_add_str(pinfo->cinfo, COL_INFO, ", TCPL SHUTDOWN Segment");
460 }
461 } else {
462 col_set_str(pinfo->cinfo, COL_INFO, "TCPL SHUTDOWN Segment");
463 }
464 /* Add tree for Shutdown Flags */
465 sub_item = proto_tree_add_item(conv_tree, hf_tcp_convergence_shutdown_flags, tvb,
466 offset, 1, ENC_BIG_ENDIAN);
467 sub_tree = proto_item_add_subtree(sub_item, ett_shutdown_flags);
468
469 proto_tree_add_item(sub_tree, hf_tcp_convergence_shutdown_flags_reason,
470 tvb, offset, 1, ENC_BIG_ENDIAN);
471 proto_tree_add_item(sub_tree, hf_tcp_convergence_shutdown_flags_delay,
472 tvb, offset, 1, ENC_BIG_ENDIAN);
473
474 offset += 1;
475 if (conv_hdr & TCP_CONVERGENCE_SHUTDOWN_REASON) {
476 proto_tree_add_item(conv_tree,
477 hf_tcp_convergence_shutdown_reason, tvb,
478 offset, 1, ENC_BIG_ENDIAN);
479 offset += 1;
480 }
481 if (conv_hdr & TCP_CONVERGENCE_SHUTDOWN_DELAY) {
482 proto_tree_add_item(conv_tree,
483 hf_tcp_convergence_shutdown_delay, tvb,
484 offset, 2, ENC_BIG_ENDIAN);
485 }
486 break;
487 case TCP_CONVERGENCE_REFUSE_BUNDLE:
488 if (bundle_in_col_info) {
489 if (!strstr(col_text, ", TCPL REFUSE")) {
490 col_add_str(pinfo->cinfo, COL_INFO, ", TCPL REFUSE_BUNDLE Segment");
491 }
492 } else {
493 col_set_str(pinfo->cinfo, COL_INFO, "TCPL REFUSE_BUNDLE Segment");
494 }
495
496 refuse_bundle_hdr = tvb_get_guint8(tvb, offset);
497 proto_tree_add_item(conv_tree, hf_dtn_refuse_bundle_reason_code, tvb, offset, 1, ENC_BIG_ENDIAN);
498 col_add_str(pinfo->cinfo, COL_INFO, val_to_str_const((refuse_bundle_hdr>>4)&0xF, refuse_bundle_reason_code, "Unknown"));
499
500 /*No valid flags*/
501 processed_length = tvb_captured_length(tvb);
502 break;
503 }
504
505 return processed_length;
506 }
507
508 static int
dissect_tcpcl(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data)509 dissect_tcpcl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
510 {
511 guint8 conv_hdr;
512 int offset, bytecount;
513 int processed_length;
514
515 /* Make sure we have a convergence header byte */
516 if (!tvb_bytes_exist(tvb, 0, 1))
517 return 0;
518
519 conv_hdr = tvb_get_guint8(tvb, 0);
520 switch (conv_hdr & TCP_CONVERGENCE_TYPE_MASK)
521 {
522 case TCP_CONVERGENCE_DATA_SEGMENT:
523 case TCP_CONVERGENCE_ACK_SEGMENT:
524 /* ensure sdnv */
525 offset = 1;
526 bytecount = 1;
527
528 if (!tvb_bytes_exist(tvb, offset, 1)) {
529 pinfo->desegment_offset = 0;
530 pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT;
531 return 0;
532 }
533
534 while (tvb_get_guint8(tvb, offset) & ~SDNV_MASK) {
535 if (bytecount > (int)sizeof(int)) {
536 /* invalid length field */
537 return 0;
538 }
539
540 bytecount++;
541 offset++;
542
543 if (!tvb_bytes_exist(tvb, offset, 1)) {
544 pinfo->desegment_offset = 0;
545 pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT;
546 return 0;
547 }
548 }
549 break;
550 case TCP_CONVERGENCE_KEEP_ALIVE:
551 case TCP_CONVERGENCE_REFUSE_BUNDLE:
552 /* always 1 byte */
553 break;
554 case TCP_CONVERGENCE_SHUTDOWN:
555 if ((conv_hdr &
556 ~(TCP_CONVERGENCE_TYPE_MASK | TCP_CONVERGENCE_SHUTDOWN_FLAGS)) != 0) {
557 /* Not for us */
558 return 0;
559 }
560 break;
561 default:
562 if (conv_hdr == (guint8)magic[0]) {
563 if (!tvb_bytes_exist(tvb, 0, 4) || tvb_memeql(tvb, 0, magic, 4)) {
564 /* Not for us */
565 return 0;
566 }
567
568 tcp_dissect_pdus(tvb, pinfo, tree, TRUE, 8, get_dtn_contact_header_len, dissect_dtn_contact_header, data);
569 return tvb_captured_length(tvb);
570 }
571
572 /* Not for us */
573 return 0;
574 };
575
576 processed_length = get_tcpcl_pdu_len(pinfo, tvb, 0, data);
577
578 tcp_dissect_pdus(tvb, pinfo, tree, TRUE, 1, get_tcpcl_pdu_len, dissect_tcpcl_pdu, data);
579
580 return processed_length;
581 }
582
583
584 void
proto_register_tcpclv3(void)585 proto_register_tcpclv3(void)
586 {
587
588 static hf_register_info hf_tcpcl[] = {
589 {&hf_tcp_convergence_pkt_type,
590 {"Pkt Type", "tcpcl.pkt_type",
591 FT_UINT8, BASE_DEC, VALS(packet_type_vals), 0xF0, NULL, HFILL}
592 },
593 {&hf_dtn_refuse_bundle_reason_code,
594 {"Reason-Code", "tcpcl.refuse.reason_code",
595 FT_UINT8, BASE_DEC, VALS(refuse_bundle_reason_code), 0x0F, NULL, HFILL}
596 },
597 {&hf_tcp_convergence_data_procflags,
598 {"TCP Convergence Data Flags", "tcpcl.data.proc.flag",
599 FT_UINT8, BASE_HEX, NULL, TCP_CONVERGENCE_DATA_FLAGS, NULL, HFILL}
600 },
601 {&hf_tcp_convergence_data_procflags_start,
602 {"Segment contains start of bundle", "tcpcl.data.proc.start",
603 FT_BOOLEAN, 8, NULL, TCP_CONVERGENCE_DATA_START_FLAG, NULL, HFILL}
604 },
605 {&hf_tcp_convergence_data_procflags_end,
606 {"Segment contains end of Bundle", "tcpcl.data.proc.end",
607 FT_BOOLEAN, 8, NULL, TCP_CONVERGENCE_DATA_END_FLAG, NULL, HFILL}
608 },
609 {&hf_tcp_convergence_data_segment_length,
610 {"Segment Length", "tcpcl.data.length",
611 FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL}
612 },
613 {&hf_tcp_convergence_shutdown_flags,
614 {"TCP Convergence Shutdown Flags", "tcpcl.shutdown.flags",
615 FT_UINT8, BASE_HEX, NULL, TCP_CONVERGENCE_SHUTDOWN_FLAGS, NULL, HFILL}
616 },
617 {&hf_tcp_convergence_shutdown_flags_reason,
618 {"Shutdown includes Reason Code", "tcpcl.shutdown.reason.flag",
619 FT_BOOLEAN, 8, NULL, TCP_CONVERGENCE_SHUTDOWN_REASON, NULL, HFILL}
620 },
621 {&hf_tcp_convergence_shutdown_flags_delay,
622 {"Shutdown includes Reconnection Delay", "tcpcl.shutdown.delay.flag",
623 FT_BOOLEAN, 8, NULL, TCP_CONVERGENCE_SHUTDOWN_DELAY, NULL, HFILL}
624 },
625 {&hf_tcp_convergence_shutdown_reason,
626 {"Shutdown Reason Code", "tcpcl.shutdown.reason",
627 FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL}
628 },
629 {&hf_tcp_convergence_shutdown_delay,
630 {"Shutdown Reconnection Delay", "tcpcl.shutdown.delay",
631 FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}
632 },
633 {&hf_tcp_convergence_ack_length,
634 {"Ack Length", "tcpcl.ack.length",
635 FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL}
636 },
637 {&hf_contact_hdr_version,
638 {"Version", "tcpcl.contact_hdr.version",
639 FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL}
640 },
641 {&hf_contact_hdr_flags,
642 {"Flags", "tcpcl.contact_hdr.flags",
643 FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL}
644 },
645 {&hf_contact_hdr_flags_ack_req,
646 {"Bundle Acks Requested", "tcpcl.contact_hdr.flags.ackreq",
647 FT_BOOLEAN, 8, NULL, TCP_CONV_BUNDLE_ACK_FLAG, NULL, HFILL}
648 },
649 {&hf_contact_hdr_flags_frag_enable,
650 {"Reactive Fragmentation Enabled", "tcpcl.contact_hdr.flags.fragen",
651 FT_BOOLEAN, 8, NULL, TCP_CONV_REACTIVE_FRAG_FLAG, NULL, HFILL}
652 },
653 {&hf_contact_hdr_flags_nak,
654 {"Support Negative Acknowledgements", "tcpcl.contact_hdr.flags.nak",
655 FT_BOOLEAN, 8, NULL, TCP_CONV_CONNECTOR_RCVR_FLAG, NULL, HFILL}
656 },
657 {&hf_contact_hdr_keep_alive,
658 {"Keep Alive", "tcpcl.contact_hdr.keep_alive",
659 FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}
660 },
661 {&hf_contact_hdr_magic,
662 {"Magic", "tcpcl.contact_hdr.magic",
663 FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL}
664 },
665 {&hf_contact_hdr_local_eid,
666 {"Local EID", "tcpcl.contact_hdr.local_eid",
667 FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL}
668 },
669 {&hf_contact_hdr_local_eid_length,
670 {"Local EID Length", "tcpcl.contact_hdr.local_eid_length",
671 FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL}
672 },
673
674 {&hf_msg_fragments,
675 {"Message Fragments", "tcpcl.msg.fragments",
676 FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL}
677 },
678 {&hf_msg_fragment,
679 {"Message Fragment", "tcpcl.msg.fragment",
680 FT_FRAMENUM, BASE_NONE, NULL, 0x0, NULL, HFILL}
681 },
682 {&hf_msg_fragment_overlap,
683 {"Message fragment overlap", "tcpcl.msg.fragment.overlap",
684 FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL}
685 },
686 {&hf_msg_fragment_overlap_conflicts,
687 {"Message fragment overlapping with conflicting data",
688 "tcpcl.msg.fragment.overlap.conflicts",
689 FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL}
690 },
691 {&hf_msg_fragment_multiple_tails,
692 {"Message has multiple tails", "tcpcl.msg.fragment.multiple_tails",
693 FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL}
694 },
695 {&hf_msg_fragment_too_long_fragment,
696 {"Message fragment too long", "tcpcl.msg.fragment.too_long_fragment",
697 FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL}
698 },
699 {&hf_msg_fragment_error,
700 {"Message defragmentation error", "tcpcl.msg.fragment.error",
701 FT_FRAMENUM, BASE_NONE, NULL, 0x0, NULL, HFILL}
702 },
703 {&hf_msg_fragment_count,
704 {"Message fragment count", "tcpcl.msg.fragment.count",
705 FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL}
706 },
707 {&hf_msg_reassembled_in,
708 {"Reassembled in", "tcpcl.msg.reassembled.in",
709 FT_FRAMENUM, BASE_NONE, NULL, 0x0, NULL, HFILL}
710 },
711 {&hf_msg_reassembled_length,
712 {"Reassembled DTN length", "tcpcl.msg.reassembled.length",
713 FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL}
714 },
715 };
716
717 static gint *ett_tcpcl[] = {
718 &ett_tcp_conv,
719 &ett_tcp_conv_hdr,
720 &ett_conv_flags,
721 &ett_contact_hdr_flags,
722 &ett_shutdown_flags,
723 &ett_msg_fragment,
724 &ett_msg_fragments,
725 };
726
727 static ei_register_info ei_tcpcl[] = {
728 { &ei_tcp_convergence_data_flags,
729 { "tcpcl.data.flags.invalid", PI_PROTOCOL, PI_WARN, "Invalid TCP CL Data Segment Flags", EXPFILL }
730 },
731 { &ei_tcp_convergence_segment_length,
732 { "tcpcl.data.length.invalid", PI_PROTOCOL, PI_ERROR, "Invalid Data Length", EXPFILL }
733 },
734 { &ei_tcp_convergence_ack_length,
735 { "tcpcl.ack.length.error", PI_PROTOCOL, PI_WARN, "Ack Length: Error", EXPFILL }
736 },
737 };
738
739 expert_module_t *expert_tcpcl;
740
741 proto_tcp_conv = proto_register_protocol ("DTN TCP Convergence Layer Protocol", "TCPCL", "tcpcl");
742
743 proto_register_field_array(proto_tcp_conv, hf_tcpcl, array_length(hf_tcpcl));
744 proto_register_subtree_array(ett_tcpcl, array_length(ett_tcpcl));
745 expert_tcpcl = expert_register_protocol(proto_tcp_conv);
746 expert_register_field_array(expert_tcpcl, ei_tcpcl, array_length(ei_tcpcl));
747
748 reassembly_table_register(&msg_reassembly_table,
749 &addresses_reassembly_table_functions);
750
751 }
752
753 void
proto_reg_handoff_tcpclv3(void)754 proto_reg_handoff_tcpclv3(void)
755 {
756 dissector_handle_t tcpcl_handle;
757
758 bundle_handle = find_dissector("bundle");
759
760 tcpcl_handle = create_dissector_handle(dissect_tcpcl, proto_tcp_conv);
761 dissector_add_uint_with_preference("tcp.port", BUNDLE_PORT, tcpcl_handle);
762 }
763
764 /*
765 * Editor modelines - https://www.wireshark.org/tools/modelines.html
766 *
767 * Local variables:
768 * c-basic-offset: 4
769 * tab-width: 8
770 * indent-tabs-mode: nil
771 * End:
772 *
773 * vi: set shiftwidth=4 tabstop=8 expandtab:
774 * :indentSize=4:tabSize=8:noTabs=true:
775 */
776