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