TCPCLv4: Update TCPCL dissector to include version 4 from dtn-wireshark

Some enhancements and visual fixes to version 3 dissector are also included.
This commit is contained in:
Brian Sipos 2021-10-11 01:03:50 -04:00 committed by Wireshark GitLab Utility
parent 0e667117b4
commit c36ce0b01b
10 changed files with 2419 additions and 878 deletions

View File

@ -1617,6 +1617,7 @@ libwireshark.so.0 libwireshark0 #MINVER#
tap_register_plugin@Base 2.5.0
tcp_dissect_pdus@Base 1.9.1
tcp_port_to_display@Base 1.99.2
tcpcl_dissect_ctx_get@Base 3.7.0
tfs_accept_reject@Base 1.9.1
tfs_accepted_not_accepted@Base 1.9.1
tfs_ack_nack@Base 1.9.1

View File

@ -130,6 +130,7 @@ Bluetooth Link Manager Protocol (BT LMP)
Bundle Protocol version 7 (BPv7)
Bundle Protocol version 7 Security (BPSec)
CBOR Object Signing and Encryption (COSE)
DTN TCP Convergence Layer version 4 (TCPCLv4)
E2 Application Protocol (E2AP)
Event Tracing for Windows (ETW)
High-Performance Connectivity Tracer (HiPerConTracer)

View File

@ -584,7 +584,7 @@ set(DISSECTOR_PUBLIC_HEADERS
packet-tacacs.h
packet-tcap.h
packet-tcp.h
packet-tcpclv3.h
packet-tcpcl.h
packet-tetra.h
packet-thrift.h
packet-tls-utils.h
@ -1838,7 +1838,7 @@ set(DISSECTOR_SRC
${CMAKE_CURRENT_SOURCE_DIR}/packet-tapa.c
${CMAKE_CURRENT_SOURCE_DIR}/packet-tcg-cp-oids.c
${CMAKE_CURRENT_SOURCE_DIR}/packet-tcp.c
${CMAKE_CURRENT_SOURCE_DIR}/packet-tcpclv3.c
${CMAKE_CURRENT_SOURCE_DIR}/packet-tcpcl.c
${CMAKE_CURRENT_SOURCE_DIR}/packet-tcpros.c
${CMAKE_CURRENT_SOURCE_DIR}/packet-tdmoe.c
${CMAKE_CURRENT_SOURCE_DIR}/packet-tdmop.c

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,242 @@
/* packet-tcpcl.h
* References:
* RFC 7242: https://tools.ietf.org/html/rfc7242
* TCPCLv4: https://www.ietf.org/archive/id/draft-ietf-dtn-tcpclv4-28.html
*
* TCPCLv4 portions copyright 2019-2021, Brian Sipos <brian.sipos@gmail.com>
* Copyright 2006-2007 The MITRE Corporation.
* All Rights Reserved.
* Approved for Public Release; Distribution Unlimited.
* Tracking Number 07-0090.
*
* The US Government will not be charged any license fee and/or royalties
* related to this software. Neither name of The MITRE Corporation; nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* Wireshark - Network traffic analyzer
* By Gerald Combs <gerald@wireshark.org>
* Copyright 1998 Gerald Combs
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#ifndef PACKET_TCPCL_H
#define PACKET_TCPCL_H
#include <ws_symbol_export.h>
#include <epan/tvbuff.h>
#include <epan/proto.h>
#ifdef __cplusplus
extern "C" {
#endif
/** Extension points for TCPCLv4 are available as:
* For session extension item dissectors, the dissector table
* "tcpcl.v4.sess_ext" has a FT_UINT16 key for registering.
* For transfer extension item dissectors, the dissector table
* "tcpcl.v4.xfer_ext" has a FT_UINT16 key for registering.
* Both have user data dissection context which is obtained with the
* tcpcl_dissect_ctx_get() function.
*/
/* TCP Convergence Layer v3 - Message Types */
typedef enum {
TCPCLV3_TYPE_MASK = 0xf0,
TCPCLV3_DATA_SEGMENT = 0x10,
TCPCLV3_ACK_SEGMENT = 0x20,
TCPCLV3_REFUSE_BUNDLE = 0x30,
TCPCLV3_KEEP_ALIVE = 0x40,
TCPCLV3_SHUTDOWN = 0x50,
TCPCLV3_LENGTH = 0x60,
} Tcpclv3MessageType;
/* TCP Convergence Layer - Contact Header Flags */
typedef enum {
TCPCLV3_BUNDLE_ACK_FLAG = 0x01,
TCPCLV3_REACTIVE_FRAG_FLAG = 0x02,
TCPCLV3_CONNECTOR_RCVR_FLAG = 0x04,
} Tcpclv3ContactFlag;
/* TCP Convergence Layer - Data Segment Flags */
typedef enum {
TCPCLV3_DATA_FLAGS = 0x03,
TCPCLV3_DATA_END_FLAG = 0x01,
TCPCLV3_DATA_START_FLAG = 0x02,
} Tcpclv3DataSegmentFlag;
/* TCP Convergence Layer - Shutdown Segment Flags */
typedef enum {
TCPCLV3_SHUTDOWN_FLAGS = 0x03,
TCPCLV3_SHUTDOWN_REASON = 0x02,
TCPCLV3_SHUTDOWN_DELAY = 0x01,
} Tcpclv3ShutdownFlag;
/* REFUSE-BUNDLE Reason-Codes */
typedef enum {
TCPCLV3_REFUSE_REASON_UNKNOWN = 0x00,
TCPCLV3_REFUSE_REASON_RX_COMPLETE = 0x01,
TCPCLV3_REFUSE_REASON_RX_EXHAUSTED = 0x02,
TCPCLV3_REFUSE_REASON_RX_RETRANSMIT = 0x03,
/* 0x4-0x7 - Unassigned
* 0x8-0xf - Reserved for future Use */
} Tcpclv3RefuseType;
typedef enum {
TCPCLV4_MSGTYPE_INVALID = 0x00,
TCPCLV4_MSGTYPE_XFER_SEGMENT = 0x01,
TCPCLV4_MSGTYPE_XFER_ACK = 0x02,
TCPCLV4_MSGTYPE_XFER_REFUSE = 0x03,
TCPCLV4_MSGTYPE_KEEPALIVE = 0x04,
TCPCLV4_MSGTYPE_SESS_TERM = 0x05,
TCPCLV4_MSGTYPE_MSG_REJECT = 0x06,
TCPCLV4_MSGTYPE_SESS_INIT = 0x07,
} Tcpclv4MessageType;
typedef enum {
TCPCLV4_SESSEXT_INVALID = 0x00,
} Tcpclv4SessExtenionType;
typedef enum {
TCPCLV4_XFEREXT_INVALID = 0x00,
TCPCLV4_XFEREXT_TRANSFER_LEN = 0x01,
} Tcpclv4XferExtenionType;
typedef enum {
TCPCLV4_CONTACT_FLAG_CANTLS = 0x01,
} Tcpclv4ContactFlag;
typedef enum {
TCPCLV4_SESS_TERM_FLAG_REPLY = 0x01,
} Tcpclv4SessTermFlag;
typedef enum {
TCPCLV4_TRANSFER_FLAG_START = 0x02,
TCPCLV4_TRANSFER_FLAG_END = 0x01,
} Tcpclv4TransferFlag;
typedef enum {
TCPCLV4_EXTENSION_FLAG_CRITICAL = 0x01,
} Tcpclv4ExtensionFlag;
/// Finer grained locating than just the frame number
typedef struct {
/// Index of the frame
guint32 frame_num;
/// Source index within the frame
gint src_ix;
/// Offset within the source TVB
gint raw_offset;
} tcpcl_frame_loc_t;
typedef struct {
/// Ordered list of seg_meta_t* for XFER_SEGMENT as seen in the first scan.
wmem_list_t *seg_list;
/// Ordered list of ack_meta_t* for XFER_ACK as seen in the first scan.
wmem_list_t *ack_list;
/// Optional Transfer Length extension
guint64 *total_length;
} tcpcl_transfer_t;
typedef struct {
/// Address for this peer
address addr;
/// Port for the this peer
guint32 port;
/// Frame number in which the contact header starts
tcpcl_frame_loc_t *chdr_seen;
/// TCPCL version seen from this peer
guint8 version;
/// CAN_TLS flag from the contact header
gboolean can_tls;
/// Frame number in which the v4 SESS_INIT message starts
tcpcl_frame_loc_t *sess_init_seen;
/// Keepalive duration (s) from v4 SESS_INIT
guint16 keepalive;
/// Segment MRU
guint64 segment_mru;
/// Transfer MRU
guint64 transfer_mru;
/// Frame number in which the SESS_TERM message starts
tcpcl_frame_loc_t *sess_term_seen;
/// SESS_TERM reason
guint8 sess_term_reason;
/// Map from tcpcl_frame_loc_t* to possible associated transfer ID guint64*
wmem_map_t *frame_loc_to_transfer;
/// Map from transfer ID guint64* to tcpcl_transfer_t* sent from this peer
wmem_map_t *transfers;
} tcpcl_peer_t;
/// Persistent state associated with a TCP conversation
typedef struct {
/// Information for the active side of the session
tcpcl_peer_t *active;
/// Information for the passive side of the session
tcpcl_peer_t *passive;
/// Set to the first TCPCL version seen.
/// Used later for validity check.
guint8 *version;
/// True when contact negotiation is finished
gboolean contact_negotiated;
/// Negotiated use of TLS from @c can_tls of the peers
gboolean session_use_tls;
/// The last frame before TLS handshake
tcpcl_frame_loc_t *session_tls_start;
/// True when session negotiation is finished
gboolean sess_negotiated;
/// Negotiated session keepalive
guint16 sess_keepalive;
} tcpcl_conversation_t;
/// Context for a single packet dissection
typedef struct {
tcpcl_conversation_t *convo;
/// Dissection cursor
tcpcl_frame_loc_t *cur_loc;
/// True if the dissection is on a contact header
gboolean is_contact;
/// The sending peer
tcpcl_peer_t *tx_peer;
/// The receiving peer
tcpcl_peer_t *rx_peer;
/// Possible transfer payload
tvbuff_t *xferload;
} tcpcl_dissect_ctx_t;
/** Initialize members of the dissection context.
*
* @param pinfo Packet info for the frame.
* @param tvb The buffer dissected.
* @param offset The start offset.
* @return ctx The new packet context.
*/
WS_DLL_PUBLIC
tcpcl_dissect_ctx_t * tcpcl_dissect_ctx_get(tvbuff_t *tvb, packet_info *pinfo, const gint offset);
#ifdef __cplusplus
}
#endif
#endif /* PACKET_TCPCL_H */
/*
* Editor modelines - https://www.wireshark.org/tools/modelines.html
*
* Local variables:
* c-basic-offset: 4
* tab-width: 8
* indent-tabs-mode: nil
* End:
*
* vi: set shiftwidth=4 tabstop=8 expandtab:
* :indentSize=4:tabSize=8:noTabs=true:
*/

View File

@ -1,775 +0,0 @@
/* packet-tcpclv3.c
* References:
* RFC 7242: https://tools.ietf.org/html/rfc7242
*
* Copyright 2006-2007 The MITRE Corporation.
* All Rights Reserved.
* Approved for Public Release; Distribution Unlimited.
* Tracking Number 07-0090.
*
* The US Government will not be charged any license fee and/or royalties
* related to this software. Neither name of The MITRE Corporation; nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* Wireshark - Network traffic analyzer
* By Gerald Combs <gerald@wireshark.org>
* Copyright 1998 Gerald Combs
*
* SPDX-License-Identifier: GPL-2.0-or-later
*
* Specification reference:
* RFC 5050
* https://tools.ietf.org/html/rfc5050
*/
/*
* Modifications were made to this file under designation MFS-33289-1 and
* are Copyright 2015 United States Government as represented by NASA
* Marshall Space Flight Center. All Rights Reserved.
*
* Released under the GNU GPL with NASA legal approval granted 2016-06-10.
*
* The subject software is provided "AS IS" WITHOUT ANY WARRANTY of any kind,
* either expressed, implied or statutory and this agreement does not,
* in any manner, constitute an endorsement by government agency of any
* results, designs or products resulting from use of the subject software.
* See the Agreement for the specific language governing permissions and
* limitations.
*/
#include "config.h"
#include <stdio.h>
#include <epan/packet.h>
#include <epan/reassemble.h>
#include <epan/expert.h>
#include "packet-tcpclv3.h"
#include "packet-bpv6.h"
#include "packet-tcp.h"
/* For Reassembling TCP Convergence Layer segments */
static reassembly_table msg_reassembly_table;
static const char magic[] = {'d', 't', 'n', '!'};
static int proto_tcp_conv = -1;
/* TCP Convergence Header Variables */
static int hf_tcp_convergence_pkt_type = -1;
/* Refuse-Bundle reason code */
static int hf_dtn_refuse_bundle_reason_code = -1;
static int hf_contact_hdr_version = -1;
static int hf_contact_hdr_flags = -1;
static int hf_contact_hdr_keep_alive = -1;
static int hf_contact_hdr_flags_ack_req = -1;
static int hf_contact_hdr_flags_frag_enable = -1;
static int hf_contact_hdr_flags_nak = -1;
static int hf_contact_hdr_magic = -1;
static int hf_contact_hdr_local_eid_length = -1;
static int hf_contact_hdr_local_eid = -1;
/* TCP Convergence Data Header Variables */
static int hf_tcp_convergence_data_procflags = -1;
static int hf_tcp_convergence_data_procflags_start = -1;
static int hf_tcp_convergence_data_procflags_end = -1;
static int hf_tcp_convergence_data_segment_length = -1;
/* TCP Convergence Ack Variables */
static int hf_tcp_convergence_ack_length = -1;
/* TCP Convergence Shutdown Header Variables */
static int hf_tcp_convergence_shutdown_flags = -1;
static int hf_tcp_convergence_shutdown_flags_reason = -1;
static int hf_tcp_convergence_shutdown_flags_delay = -1;
static int hf_tcp_convergence_shutdown_reason = -1;
static int hf_tcp_convergence_shutdown_delay = -1;
/*TCP Convergence Layer Reassembly boilerplate*/
static int hf_msg_fragments = -1;
static int hf_msg_fragment = -1;
static int hf_msg_fragment_overlap = -1;
static int hf_msg_fragment_overlap_conflicts = -1;
static int hf_msg_fragment_multiple_tails = -1;
static int hf_msg_fragment_too_long_fragment = -1;
static int hf_msg_fragment_error = -1;
static int hf_msg_fragment_count = -1;
static int hf_msg_reassembled_in = -1;
static int hf_msg_reassembled_length = -1;
/* Tree Node Variables */
static gint ett_conv_flags = -1;
static gint ett_shutdown_flags = -1;
static gint ett_contact_hdr_flags = -1;
static gint ett_tcp_conv = -1;
static gint ett_tcp_conv_hdr = -1;
static gint ett_msg_fragment = -1;
static gint ett_msg_fragments = -1;
static expert_field ei_tcp_convergence_data_flags = EI_INIT;
static expert_field ei_tcp_convergence_segment_length = EI_INIT;
static expert_field ei_tcp_convergence_ack_length = EI_INIT;
static dissector_handle_t bundle_handle;
typedef struct dictionary_data {
int bundle_header_dict_length;
int dest_scheme_offset;
int dst_scheme_pos;
int dst_scheme_len;
int source_scheme_offset;
int src_scheme_pos;
int src_scheme_len;
int report_scheme_offset;
int rpt_scheme_pos;
int rpt_scheme_len;
int cust_scheme_offset;
int cust_scheme_pos;
int cust_scheme_len;
int dest_ssp_offset;
int dst_ssp_len;
int source_ssp_offset;
int src_ssp_len;
int report_ssp_offset;
int rpt_ssp_len;
int cust_ssp_offset;
int cust_ssp_len;
} dictionary_data_t;
static const value_string packet_type_vals[] = {
{((TCP_CONVERGENCE_DATA_SEGMENT>>4) & 0x0F), "Data"},
{((TCP_CONVERGENCE_ACK_SEGMENT>>4) & 0x0F), "Ack"},
{((TCP_CONVERGENCE_REFUSE_BUNDLE>>4) & 0x0F), "Refuse Bundle"},
{((TCP_CONVERGENCE_KEEP_ALIVE>>4) & 0x0F), "Keep Alive"},
{((TCP_CONVERGENCE_SHUTDOWN>>4) & 0x0F), "Shutdown"},
{((TCP_CONVERGENCE_LENGTH>>4) & 0x0F), "Length"},
{0, NULL}
};
/* Refuse-Bundle Reason-Code Flags as per RFC-7242: Section-5.4 */
static const value_string refuse_bundle_reason_code[] = {
{TCP_REFUSE_BUNDLE_REASON_UNKNOWN, "Reason for refusal is unknown"},
{TCP_REFUSE_BUNDLE_REASON_RX_COMPLETE, "Complete Bundle Received"},
{TCP_REFUSE_BUNDLE_REASON_RX_EXHAUSTED, "Receiver's resources exhausted"},
{TCP_REFUSE_BUNDLE_REASON_RX_RETRANSMIT, "Receiver expects re-transmission of bundle"},
{0, NULL}
};
static const fragment_items msg_frag_items = {
/*Fragment subtrees*/
&ett_msg_fragment,
&ett_msg_fragments,
/*Fragment Fields*/
&hf_msg_fragments,
&hf_msg_fragment,
&hf_msg_fragment_overlap,
&hf_msg_fragment_overlap_conflicts,
&hf_msg_fragment_multiple_tails,
&hf_msg_fragment_too_long_fragment,
&hf_msg_fragment_error,
&hf_msg_fragment_count,
/*Reassembled in field*/
&hf_msg_reassembled_in,
/*Reassembled length field*/
&hf_msg_reassembled_length,
/* Reassembled data field */
NULL,
/*Tag*/
"Message fragments"
};
static guint
get_dtn_contact_header_len(packet_info *pinfo _U_, tvbuff_t *tvb,
int offset, void *data _U_)
{
int len, bytecount;
/* get length from sdnv */
len = evaluate_sdnv(tvb, offset+8, &bytecount);
if (len < 0)
return 0;
return len+bytecount+8;
}
static int
dissect_dtn_contact_header(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
{
proto_item *ti;
proto_tree *conv_proto_tree, *conv_tree, *conv_flag_tree;
int eid_length, sdnv_length;
int offset = 0;
col_set_str(pinfo->cinfo, COL_PROTOCOL, "TCPCLv3");
col_clear(pinfo->cinfo,COL_INFO); /* Clear out stuff in the info column */
col_add_str(pinfo->cinfo, COL_INFO, "Contact Header");
ti = proto_tree_add_item(tree, proto_tcp_conv, tvb, offset, -1, ENC_NA);
conv_proto_tree = proto_item_add_subtree(ti, ett_tcp_conv);
conv_tree = proto_tree_add_subtree(conv_proto_tree, tvb, offset, -1, ett_tcp_conv, NULL, "Contact Header");
proto_tree_add_item(conv_tree, hf_contact_hdr_magic, tvb, offset, 4, ENC_NA|ENC_ASCII);
offset += 4;
proto_tree_add_item(conv_tree, hf_contact_hdr_version, tvb, offset, 1, ENC_BIG_ENDIAN);
offset++;
/* Subtree to expand the bits in the Contact Header Flags */
ti = proto_tree_add_item(conv_tree, hf_contact_hdr_flags, tvb, offset, 1, ENC_BIG_ENDIAN);
conv_flag_tree = proto_item_add_subtree(ti, ett_contact_hdr_flags);
proto_tree_add_item(conv_flag_tree, hf_contact_hdr_flags_ack_req, tvb, offset, 1, ENC_BIG_ENDIAN);
proto_tree_add_item(conv_flag_tree, hf_contact_hdr_flags_frag_enable, tvb, offset, 1, ENC_BIG_ENDIAN);
proto_tree_add_item(conv_flag_tree, hf_contact_hdr_flags_nak, tvb, offset, 1, ENC_BIG_ENDIAN);
offset++;
proto_tree_add_item(conv_tree, hf_contact_hdr_keep_alive, tvb, offset, 2, ENC_BIG_ENDIAN);
offset += 2;
/*
* New format Contact header has length field followed by Bundle Header.
*/
expert_field *ei_bundle_sdnv_length;
eid_length = evaluate_sdnv_ei(tvb, offset, &sdnv_length, &ei_bundle_sdnv_length);
ti = proto_tree_add_int(tree, hf_contact_hdr_local_eid_length, tvb, offset, sdnv_length, eid_length);
if (ei_bundle_sdnv_length) {
expert_add_info(pinfo, ti, ei_bundle_sdnv_length);
return offset;
}
proto_tree_add_item(conv_tree, hf_contact_hdr_local_eid, tvb, sdnv_length + offset, eid_length, ENC_NA|ENC_ASCII);
return tvb_captured_length(tvb);
}
static guint
get_tcpcl_pdu_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset, void *data _U_)
{
int len, bytecount;
guint8 conv_hdr = tvb_get_guint8(tvb, offset);
switch (conv_hdr & TCP_CONVERGENCE_TYPE_MASK)
{
case TCP_CONVERGENCE_DATA_SEGMENT:
/* get length from sdnv */
len = evaluate_sdnv(tvb, offset+1, &bytecount);
if (len < 0)
return 0;
return len+bytecount+1;
case TCP_CONVERGENCE_ACK_SEGMENT:
/* get length from sdnv */
len = evaluate_sdnv(tvb, offset+1, &bytecount);
if (len < 0)
return 0;
return bytecount+1;
case TCP_CONVERGENCE_KEEP_ALIVE:
case TCP_CONVERGENCE_REFUSE_BUNDLE:
/* always 1 byte */
return 1;
case TCP_CONVERGENCE_SHUTDOWN:
len = 1;
if (conv_hdr & TCP_CONVERGENCE_SHUTDOWN_REASON) {
len += 1;
}
if (conv_hdr & TCP_CONVERGENCE_SHUTDOWN_DELAY) {
len += 2;
}
return len;
case TCP_CONVERGENCE_LENGTH:
/* get length from sdnv */
len = evaluate_sdnv(tvb, offset+1, &bytecount);
if (len < 0)
return 0;
return bytecount+1;
}
/* This probably isn't a TCPCL/Bundle packet, so just stop dissection */
return -1;
}
static int
dissect_tcpcl_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
{
guint8 conv_hdr;
guint8 refuse_bundle_hdr;
int offset = 0;
int sdnv_length, segment_length, convergence_hdr_size;
proto_item *ci, *sub_item;
proto_tree *conv_proto_tree, *conv_tree, *sub_tree;
fragment_head *frag_msg;
tvbuff_t *new_tvb;
gboolean more_frags;
int processed_length = 0;
const gchar* col_text;
gboolean bundle_in_col_info;
static guint32 frag_id = 0;
static guint32 last_frame = 0;
static int last_raw_offset = 0;
if (last_frame != pinfo->fd->num || tvb_raw_offset(tvb) < last_raw_offset)
frag_id = 0;
last_frame = pinfo->fd->num;
last_raw_offset = tvb_raw_offset(tvb);
col_set_str(pinfo->cinfo, COL_PROTOCOL, "TCPCL");
col_clear(pinfo->cinfo,COL_INFO); /* Clear out stuff in the info column */
col_text = col_get_text(pinfo->cinfo, COL_INFO);
bundle_in_col_info = (col_text && strstr(col_text, " > "));
ci = proto_tree_add_item(tree, proto_tcp_conv, tvb, offset, -1, ENC_NA);
conv_proto_tree = proto_item_add_subtree(ci, ett_tcp_conv);
conv_tree = proto_tree_add_subtree(conv_proto_tree, tvb, 0, -1, ett_tcp_conv_hdr, NULL, "TCP Convergence Header");
conv_hdr = tvb_get_guint8(tvb, offset);
proto_tree_add_item(conv_tree, hf_tcp_convergence_pkt_type, tvb, offset, 1, ENC_BIG_ENDIAN);
col_add_str(pinfo->cinfo, COL_INFO, val_to_str_const((conv_hdr>>4)&0xF, packet_type_vals, "Unknown"));
switch (conv_hdr & TCP_CONVERGENCE_TYPE_MASK)
{
case TCP_CONVERGENCE_DATA_SEGMENT:
sub_item = proto_tree_add_item(conv_tree, hf_tcp_convergence_data_procflags, tvb,
offset, 1, ENC_BIG_ENDIAN);
sub_tree = proto_item_add_subtree(sub_item, ett_conv_flags);
proto_tree_add_item(sub_tree, hf_tcp_convergence_data_procflags_start,
tvb, offset, 1, ENC_BIG_ENDIAN);
proto_tree_add_item(sub_tree, hf_tcp_convergence_data_procflags_end,
tvb, offset, 1, ENC_BIG_ENDIAN);
/* Only Start and End flags (bits 0 & 1) are valid in Data Segment */
if ((conv_hdr & ~(TCP_CONVERGENCE_TYPE_MASK | TCP_CONVERGENCE_DATA_FLAGS)) != 0) {
expert_add_info(pinfo, sub_item, &ei_tcp_convergence_data_flags);
}
segment_length = evaluate_sdnv(tvb, 1, &sdnv_length);
sub_item = proto_tree_add_int(conv_tree, hf_tcp_convergence_data_segment_length, tvb, 1, sdnv_length, segment_length);
if (segment_length < 0) {
expert_add_info(pinfo, sub_item, &ei_tcp_convergence_segment_length);
return 1;
}
convergence_hdr_size = sdnv_length + 1;
/*
* 1/11/2006 - If I got here, I should have a complete convergence layer
* "segment" beginning at frame_offset. However that might not be a
* complete bundle. Or there might be a complete bundle plus one or more
* additional convergence layer headers.
*/
new_tvb = NULL;
sub_tree = NULL;
if ((conv_hdr & TCP_CONVERGENCE_DATA_END_FLAG) == TCP_CONVERGENCE_DATA_END_FLAG) {
more_frags = FALSE;
}
else {
more_frags = TRUE;
}
frag_msg = fragment_add_seq_next(&msg_reassembly_table,
tvb, offset + convergence_hdr_size,
pinfo, frag_id, data,
segment_length, more_frags);
if (!more_frags) ++frag_id;
processed_length = convergence_hdr_size + segment_length;
if (frag_msg && !more_frags) {
int save_fd_head_layer = frag_msg->reas_in_layer_num;
frag_msg->reas_in_layer_num = pinfo->curr_layer_num;
new_tvb = process_reassembled_data(tvb, offset + convergence_hdr_size,
pinfo, "Reassembled DTN", frag_msg,
&msg_frag_items, NULL,
proto_tree_get_parent_tree(tree)
);
frag_msg->reas_in_layer_num = save_fd_head_layer;
}
if (new_tvb) {
if (0 == call_dissector_with_data(bundle_handle, new_tvb, pinfo, sub_tree, data)) {
/*Couldn't parse bundle, treat as raw data */
call_data_dissector(new_tvb, pinfo, sub_tree);
return tvb_captured_length(tvb);
}
}
else {
/*
* If there are 2 segments, the second of which is very short, this
* gets displayed instead of the usual Source EID/Destination EID in
* the Bundle Dissection frame. If these statements are left out entirely,
* nothing is displayed, i.e., there seems to be no way to get the
* Source/Destination in the 2-segment case. I'll leave it in because I
* think it is informative in the multi-segment case although confusing in the
* 2-segment case.
*/
col_add_str(pinfo->cinfo, COL_INFO, "[Bundle TCPCL Segment]");
}
break;
case TCP_CONVERGENCE_ACK_SEGMENT:
if (bundle_in_col_info) {
if (!strstr(col_text, ", TCPL ACK")) {
col_add_str(pinfo->cinfo, COL_INFO, ", TCPL ACK Segment(s)");
}
} else {
col_set_str(pinfo->cinfo, COL_INFO, "TCPL ACK Segment(s)");
}
segment_length = evaluate_sdnv(tvb, offset+1, &sdnv_length);
sub_item = proto_tree_add_int(conv_tree, hf_tcp_convergence_ack_length, tvb, offset+1, sdnv_length, segment_length);
if (segment_length < 0) {
expert_add_info(pinfo, sub_item, &ei_tcp_convergence_ack_length);
processed_length = tvb_captured_length(tvb);
} else {
processed_length = sdnv_length + 1;
}
break;
case TCP_CONVERGENCE_KEEP_ALIVE:
if (bundle_in_col_info) {
if (!strstr(col_text, ", TCPL KEEPALIVE")) {
col_add_str(pinfo->cinfo, COL_INFO, ", TCPL KEEPALIVE Segment");
}
} else {
col_set_str(pinfo->cinfo, COL_INFO, "TCPL KEEPALIVE Segment");
}
/*No valid flags in Keep Alive*/
processed_length = 1;
break;
case TCP_CONVERGENCE_SHUTDOWN:
if (bundle_in_col_info) {
if (!strstr(col_text, ", TCPL SHUTDOWN")) {
col_add_str(pinfo->cinfo, COL_INFO, ", TCPL SHUTDOWN Segment");
}
} else {
col_set_str(pinfo->cinfo, COL_INFO, "TCPL SHUTDOWN Segment");
}
/* Add tree for Shutdown Flags */
sub_item = proto_tree_add_item(conv_tree, hf_tcp_convergence_shutdown_flags, tvb,
offset, 1, ENC_BIG_ENDIAN);
sub_tree = proto_item_add_subtree(sub_item, ett_shutdown_flags);
proto_tree_add_item(sub_tree, hf_tcp_convergence_shutdown_flags_reason,
tvb, offset, 1, ENC_BIG_ENDIAN);
proto_tree_add_item(sub_tree, hf_tcp_convergence_shutdown_flags_delay,
tvb, offset, 1, ENC_BIG_ENDIAN);
offset += 1;
if (conv_hdr & TCP_CONVERGENCE_SHUTDOWN_REASON) {
proto_tree_add_item(conv_tree,
hf_tcp_convergence_shutdown_reason, tvb,
offset, 1, ENC_BIG_ENDIAN);
offset += 1;
}
if (conv_hdr & TCP_CONVERGENCE_SHUTDOWN_DELAY) {
proto_tree_add_item(conv_tree,
hf_tcp_convergence_shutdown_delay, tvb,
offset, 2, ENC_BIG_ENDIAN);
}
break;
case TCP_CONVERGENCE_REFUSE_BUNDLE:
if (bundle_in_col_info) {
if (!strstr(col_text, ", TCPL REFUSE")) {
col_add_str(pinfo->cinfo, COL_INFO, ", TCPL REFUSE_BUNDLE Segment");
}
} else {
col_set_str(pinfo->cinfo, COL_INFO, "TCPL REFUSE_BUNDLE Segment");
}
refuse_bundle_hdr = tvb_get_guint8(tvb, offset);
proto_tree_add_item(conv_tree, hf_dtn_refuse_bundle_reason_code, tvb, offset, 1, ENC_BIG_ENDIAN);
col_add_str(pinfo->cinfo, COL_INFO, val_to_str_const((refuse_bundle_hdr>>4)&0xF, refuse_bundle_reason_code, "Unknown"));
/*No valid flags*/
processed_length = tvb_captured_length(tvb);
break;
}
return processed_length;
}
static int
dissect_tcpcl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
{
guint8 conv_hdr;
int offset, bytecount;
int processed_length;
/* Make sure we have a convergence header byte */
if (!tvb_bytes_exist(tvb, 0, 1))
return 0;
conv_hdr = tvb_get_guint8(tvb, 0);
switch (conv_hdr & TCP_CONVERGENCE_TYPE_MASK)
{
case TCP_CONVERGENCE_DATA_SEGMENT:
case TCP_CONVERGENCE_ACK_SEGMENT:
/* ensure sdnv */
offset = 1;
bytecount = 1;
if (!tvb_bytes_exist(tvb, offset, 1)) {
pinfo->desegment_offset = 0;
pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT;
return 0;
}
while (tvb_get_guint8(tvb, offset) & ~SDNV_MASK) {
if (bytecount > (int)sizeof(int)) {
/* invalid length field */
return 0;
}
bytecount++;
offset++;
if (!tvb_bytes_exist(tvb, offset, 1)) {
pinfo->desegment_offset = 0;
pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT;
return 0;
}
}
break;
case TCP_CONVERGENCE_KEEP_ALIVE:
case TCP_CONVERGENCE_REFUSE_BUNDLE:
/* always 1 byte */
break;
case TCP_CONVERGENCE_SHUTDOWN:
if ((conv_hdr &
~(TCP_CONVERGENCE_TYPE_MASK | TCP_CONVERGENCE_SHUTDOWN_FLAGS)) != 0) {
/* Not for us */
return 0;
}
break;
default:
if (conv_hdr == (guint8)magic[0]) {
if (!tvb_bytes_exist(tvb, 0, 4) || tvb_memeql(tvb, 0, magic, 4)) {
/* Not for us */
return 0;
}
tcp_dissect_pdus(tvb, pinfo, tree, TRUE, 8, get_dtn_contact_header_len, dissect_dtn_contact_header, data);
return tvb_captured_length(tvb);
}
/* Not for us */
return 0;
};
processed_length = get_tcpcl_pdu_len(pinfo, tvb, 0, data);
tcp_dissect_pdus(tvb, pinfo, tree, TRUE, 1, get_tcpcl_pdu_len, dissect_tcpcl_pdu, data);
return processed_length;
}
void
proto_register_tcpclv3(void)
{
static hf_register_info hf_tcpcl[] = {
{&hf_tcp_convergence_pkt_type,
{"Pkt Type", "tcpcl.pkt_type",
FT_UINT8, BASE_DEC, VALS(packet_type_vals), 0xF0, NULL, HFILL}
},
{&hf_dtn_refuse_bundle_reason_code,
{"Reason-Code", "tcpcl.refuse.reason_code",
FT_UINT8, BASE_DEC, VALS(refuse_bundle_reason_code), 0x0F, NULL, HFILL}
},
{&hf_tcp_convergence_data_procflags,
{"TCP Convergence Data Flags", "tcpcl.data.proc.flag",
FT_UINT8, BASE_HEX, NULL, TCP_CONVERGENCE_DATA_FLAGS, NULL, HFILL}
},
{&hf_tcp_convergence_data_procflags_start,
{"Segment contains start of bundle", "tcpcl.data.proc.start",
FT_BOOLEAN, 8, NULL, TCP_CONVERGENCE_DATA_START_FLAG, NULL, HFILL}
},
{&hf_tcp_convergence_data_procflags_end,
{"Segment contains end of Bundle", "tcpcl.data.proc.end",
FT_BOOLEAN, 8, NULL, TCP_CONVERGENCE_DATA_END_FLAG, NULL, HFILL}
},
{&hf_tcp_convergence_data_segment_length,
{"Segment Length", "tcpcl.data.length",
FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL}
},
{&hf_tcp_convergence_shutdown_flags,
{"TCP Convergence Shutdown Flags", "tcpcl.shutdown.flags",
FT_UINT8, BASE_HEX, NULL, TCP_CONVERGENCE_SHUTDOWN_FLAGS, NULL, HFILL}
},
{&hf_tcp_convergence_shutdown_flags_reason,
{"Shutdown includes Reason Code", "tcpcl.shutdown.reason.flag",
FT_BOOLEAN, 8, NULL, TCP_CONVERGENCE_SHUTDOWN_REASON, NULL, HFILL}
},
{&hf_tcp_convergence_shutdown_flags_delay,
{"Shutdown includes Reconnection Delay", "tcpcl.shutdown.delay.flag",
FT_BOOLEAN, 8, NULL, TCP_CONVERGENCE_SHUTDOWN_DELAY, NULL, HFILL}
},
{&hf_tcp_convergence_shutdown_reason,
{"Shutdown Reason Code", "tcpcl.shutdown.reason",
FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL}
},
{&hf_tcp_convergence_shutdown_delay,
{"Shutdown Reconnection Delay", "tcpcl.shutdown.delay",
FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}
},
{&hf_tcp_convergence_ack_length,
{"Ack Length", "tcpcl.ack.length",
FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL}
},
{&hf_contact_hdr_version,
{"Version", "tcpcl.contact_hdr.version",
FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL}
},
{&hf_contact_hdr_flags,
{"Flags", "tcpcl.contact_hdr.flags",
FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL}
},
{&hf_contact_hdr_flags_ack_req,
{"Bundle Acks Requested", "tcpcl.contact_hdr.flags.ackreq",
FT_BOOLEAN, 8, NULL, TCP_CONV_BUNDLE_ACK_FLAG, NULL, HFILL}
},
{&hf_contact_hdr_flags_frag_enable,
{"Reactive Fragmentation Enabled", "tcpcl.contact_hdr.flags.fragen",
FT_BOOLEAN, 8, NULL, TCP_CONV_REACTIVE_FRAG_FLAG, NULL, HFILL}
},
{&hf_contact_hdr_flags_nak,
{"Support Negative Acknowledgements", "tcpcl.contact_hdr.flags.nak",
FT_BOOLEAN, 8, NULL, TCP_CONV_CONNECTOR_RCVR_FLAG, NULL, HFILL}
},
{&hf_contact_hdr_keep_alive,
{"Keep Alive", "tcpcl.contact_hdr.keep_alive",
FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}
},
{&hf_contact_hdr_magic,
{"Magic", "tcpcl.contact_hdr.magic",
FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL}
},
{&hf_contact_hdr_local_eid,
{"Local EID", "tcpcl.contact_hdr.local_eid",
FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL}
},
{&hf_contact_hdr_local_eid_length,
{"Local EID Length", "tcpcl.contact_hdr.local_eid_length",
FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL}
},
{&hf_msg_fragments,
{"Message Fragments", "tcpcl.msg.fragments",
FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL}
},
{&hf_msg_fragment,
{"Message Fragment", "tcpcl.msg.fragment",
FT_FRAMENUM, BASE_NONE, NULL, 0x0, NULL, HFILL}
},
{&hf_msg_fragment_overlap,
{"Message fragment overlap", "tcpcl.msg.fragment.overlap",
FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL}
},
{&hf_msg_fragment_overlap_conflicts,
{"Message fragment overlapping with conflicting data",
"tcpcl.msg.fragment.overlap.conflicts",
FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL}
},
{&hf_msg_fragment_multiple_tails,
{"Message has multiple tails", "tcpcl.msg.fragment.multiple_tails",
FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL}
},
{&hf_msg_fragment_too_long_fragment,
{"Message fragment too long", "tcpcl.msg.fragment.too_long_fragment",
FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL}
},
{&hf_msg_fragment_error,
{"Message defragmentation error", "tcpcl.msg.fragment.error",
FT_FRAMENUM, BASE_NONE, NULL, 0x0, NULL, HFILL}
},
{&hf_msg_fragment_count,
{"Message fragment count", "tcpcl.msg.fragment.count",
FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL}
},
{&hf_msg_reassembled_in,
{"Reassembled in", "tcpcl.msg.reassembled.in",
FT_FRAMENUM, BASE_NONE, NULL, 0x0, NULL, HFILL}
},
{&hf_msg_reassembled_length,
{"Reassembled DTN length", "tcpcl.msg.reassembled.length",
FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL}
},
};
static gint *ett_tcpcl[] = {
&ett_tcp_conv,
&ett_tcp_conv_hdr,
&ett_conv_flags,
&ett_contact_hdr_flags,
&ett_shutdown_flags,
&ett_msg_fragment,
&ett_msg_fragments,
};
static ei_register_info ei_tcpcl[] = {
{ &ei_tcp_convergence_data_flags,
{ "tcpcl.data.flags.invalid", PI_PROTOCOL, PI_WARN, "Invalid TCP CL Data Segment Flags", EXPFILL }
},
{ &ei_tcp_convergence_segment_length,
{ "tcpcl.data.length.invalid", PI_PROTOCOL, PI_ERROR, "Invalid Data Length", EXPFILL }
},
{ &ei_tcp_convergence_ack_length,
{ "tcpcl.ack.length.error", PI_PROTOCOL, PI_WARN, "Ack Length: Error", EXPFILL }
},
};
expert_module_t *expert_tcpcl;
proto_tcp_conv = proto_register_protocol ("DTN TCP Convergence Layer Protocol", "TCPCL", "tcpcl");
proto_register_field_array(proto_tcp_conv, hf_tcpcl, array_length(hf_tcpcl));
proto_register_subtree_array(ett_tcpcl, array_length(ett_tcpcl));
expert_tcpcl = expert_register_protocol(proto_tcp_conv);
expert_register_field_array(expert_tcpcl, ei_tcpcl, array_length(ei_tcpcl));
reassembly_table_register(&msg_reassembly_table,
&addresses_reassembly_table_functions);
}
void
proto_reg_handoff_tcpclv3(void)
{
dissector_handle_t tcpcl_handle;
bundle_handle = find_dissector("bundle");
tcpcl_handle = create_dissector_handle(dissect_tcpcl, proto_tcp_conv);
dissector_add_uint_with_preference("tcp.port", BUNDLE_PORT, tcpcl_handle);
}
/*
* Editor modelines - https://www.wireshark.org/tools/modelines.html
*
* Local variables:
* c-basic-offset: 4
* tab-width: 8
* indent-tabs-mode: nil
* End:
*
* vi: set shiftwidth=4 tabstop=8 expandtab:
* :indentSize=4:tabSize=8:noTabs=true:
*/

View File

@ -1,101 +0,0 @@
/* packet-tcpclv3.h
* References:
* RFC 7242: https://tools.ietf.org/html/rfc7242
*
* Copyright 2006-2007 The MITRE Corporation.
* All Rights Reserved.
* Approved for Public Release; Distribution Unlimited.
* Tracking Number 07-0090.
*
* The US Government will not be charged any license fee and/or royalties
* related to this software. Neither name of The MITRE Corporation; nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* Wireshark - Network traffic analyzer
* By Gerald Combs <gerald@wireshark.org>
* Copyright 1998 Gerald Combs
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#ifndef PACKET_TCPCLV3_H
#define PACKET_TCPCLV3_H
#include <ws_symbol_export.h>
#include <epan/tvbuff.h>
#include <epan/proto.h>
#ifdef __cplusplus
extern "C" {
#endif
/* TCP Convergence Layer - Message Types */
#define TCP_CONV_MSG_TYPE_DATA 0x01
#define TCP_CONV_MSG_TYPE_ACK 0x02
#define TCP_CONV_MSG_TYPE_KEEP_ALIVE 0x03
#define TCP_CONV_MSG_TYPE_SHUTDOWN 0x04
/* TCP Convergence Layer (3) - Message Types */
#define TCP_CONVERGENCE_TYPE_MASK 0xf0
#define TCP_CONVERGENCE_DATA_SEGMENT 0x10
#define TCP_CONVERGENCE_ACK_SEGMENT 0x20
#define TCP_CONVERGENCE_REFUSE_BUNDLE 0x30
#define TCP_CONVERGENCE_KEEP_ALIVE 0x40
#define TCP_CONVERGENCE_SHUTDOWN 0x50
#define TCP_CONVERGENCE_LENGTH 0x60
/* TCP Convergence Layer - Contact Header Flags */
#define TCP_CONV_BUNDLE_ACK_FLAG 0x01
#define TCP_CONV_REACTIVE_FRAG_FLAG 0x02
#define TCP_CONV_CONNECTOR_RCVR_FLAG 0x04
/* TCP Convergence Layer - Data Segment Flags */
#define TCP_CONVERGENCE_DATA_FLAGS 0x03
#define TCP_CONVERGENCE_DATA_END_FLAG 0x01
#define TCP_CONVERGENCE_DATA_START_FLAG 0x02
/* TCP Convergence Layer - Shutdown Segment Flags */
#define TCP_CONVERGENCE_SHUTDOWN_FLAGS 0x03
#define TCP_CONVERGENCE_SHUTDOWN_REASON 0x02
#define TCP_CONVERGENCE_SHUTDOWN_DELAY 0x01
/* REFUSE-BUNDLE Reason-Codes */
#define TCP_REFUSE_BUNDLE_REASON_UNKNOWN 0x00
#define TCP_REFUSE_BUNDLE_REASON_RX_COMPLETE 0x01
#define TCP_REFUSE_BUNDLE_REASON_RX_EXHAUSTED 0x02
#define TCP_REFUSE_BUNDLE_REASON_RX_RETRANSMIT 0x03
/* 0x4-0x7 - Unassigned
* 0x8-0xf - Reserved for future Use */
/*
* TCP Convergence Layer - Minimum buffer sizes
* For Data Packet require 5 bytes fixed plus
* up to 4 additional for length SDV
*/
#define TCP_CONV_MIN_DATA_BUFFER 9
/* Header Fixed Sizes */
#define TCP_CONV_HDR_DATA_FIXED_LENGTH 5
#define TCP_CONV_HDR_ACK_LENGTH 9
#define TCP_CONV_HDR_KEEP_ALIVE_LENGTH 1
#define TCP_CONV_HDR_SHUTDOWN_LENGTH 1
#ifdef __cplusplus
}
#endif
#endif /* PACKET_TCPCLV3_H */
/*
* Editor modelines - https://www.wireshark.org/tools/modelines.html
*
* Local variables:
* c-basic-offset: 4
* tab-width: 8
* indent-tabs-mode: nil
* End:
*
* vi: set shiftwidth=4 tabstop=8 expandtab:
* :indentSize=4:tabSize=8:noTabs=true:
*/

Binary file not shown.

Binary file not shown.

View File

@ -15,6 +15,25 @@ import fixtures
import sys
@fixtures.mark_usefixtures('test_env')
@fixtures.uses_fixtures
class case_dissect_dtn_tcpcl(subprocesstest.SubprocessTestCase):
def test_tcpclv3_xfer(self, cmd_tshark, features, dirs, capture_file):
self.assertRun((cmd_tshark,
'-r', capture_file('dtn_tcpclv3_bpv6_transfer.pcapng'),
'-Tfields', '-etcpcl.ack.length',
))
self.assertEqual(self.countOutput(r'1064'), 2)
def test_tcpclv4_xfer(self, cmd_tshark, features, dirs, capture_file):
self.assertRun((cmd_tshark,
'-r', capture_file('dtn_tcpclv4_bpv7_transfer.pcapng'),
'-Tfields', '-etcpcl.v4.xfer_ack.ack_len',
))
self.assertEqual(self.countOutput(r'199'), 2)
@fixtures.mark_usefixtures('test_env')
@fixtures.uses_fixtures
class case_dissect_bpv7(subprocesstest.SubprocessTestCase):