BPv7: Add Bundle Protocol version 7 and BPSec dissectors from dtn-wireshark

This commit is contained in:
Brian Sipos 2021-10-05 21:28:12 -04:00 committed by Wireshark GitLab Utility
parent 35d09a7854
commit ce0592514c
21 changed files with 4141 additions and 747 deletions

View File

@ -65,6 +65,24 @@ libwireshark.so.0 libwireshark0 #MINVER#
bluetooth_uuid_vals@Base 1.99.2
bluetooth_uuid_vals_ext@Base 1.99.2
bluetooth_uuids@Base 2.1.0
bp_block_canonical_new@Base 3.5.1rc0-3265-gb0c69d7db316
bp_block_primary_free@Base 3.5.1rc0-3265-gb0c69d7db316
bp_block_primary_new@Base 3.5.1rc0-3265-gb0c69d7db316
bp_bundle_free@Base 3.5.1rc0-3265-gb0c69d7db316
bp_bundle_ident_equal@Base 3.5.1rc0-3265-gb0c69d7db316
bp_bundle_ident_free@Base 3.5.1rc0-3265-gb0c69d7db316
bp_bundle_ident_hash@Base 3.5.1rc0-3265-gb0c69d7db316
bp_bundle_ident_new@Base 3.5.1rc0-3265-gb0c69d7db316
bp_bundle_new@Base 3.5.1rc0-3265-gb0c69d7db316
bp_creation_ts_compare@Base 3.5.1rc0-3265-gb0c69d7db316
bp_creation_ts_free@Base 3.5.1rc0-3265-gb0c69d7db316
bp_eid_equal@Base 3.5.1rc0-3265-gb0c69d7db316
bp_eid_free@Base 3.5.1rc0-3265-gb0c69d7db316
bp_eid_new@Base 3.5.1rc0-3265-gb0c69d7db316
bpsec_id_equal@Base 3.5.1rc0-3265-gb0c69d7db316
bpsec_id_free@Base 3.5.1rc0-3265-gb0c69d7db316
bpsec_id_hash@Base 3.5.1rc0-3265-gb0c69d7db316
bpsec_id_new@Base 3.5.1rc0-3265-gb0c69d7db316
bssgp_cause_vals_ext@Base 1.9.1
bthci_cmd_authentication_enable_values@Base 2.1.2
bthci_cmd_encrypt_mode_vals@Base 2.1.2
@ -1226,6 +1244,7 @@ libwireshark.so.0 libwireshark0 #MINVER#
proto_tree_add_cbor_bstr@Base 3.5.1
proto_tree_add_cbor_container@Base 3.5.1
proto_tree_add_cbor_ctrl@Base 3.5.1
proto_tree_add_cbor_eid@Base 3.5.1rc0-3265-gb0c69d7db316
proto_tree_add_cbor_int64@Base 3.5.1
proto_tree_add_cbor_tstr@Base 3.5.1
proto_tree_add_cbor_uint64@Base 3.5.1

View File

@ -120,6 +120,8 @@ Vector Informatik Binary Log File (BLF)
[commaize]
--
Bluetooth Link Manager Protocol (BT LMP)
Bundle Protocol version 7 (BPv7)
Bundle Protocol version 7 Security (BPSec)
CBOR Object Signing and Encryption (COSE)
E2 Application Protocol (E2AP)
Event Tracing for Windows (ETW)

View File

@ -252,6 +252,7 @@ set(DISSECTOR_PUBLIC_HEADERS
packet-adb_service.h
packet-afp.h
packet-alcap.h
packet-amp.h
packet-ansi_a.h
packet-ansi_map.h
packet-ansi_tcap.h
@ -267,6 +268,9 @@ set(DISSECTOR_PUBLIC_HEADERS
packet-bgp.h
packet-bicc_mst.h
packet-bluetooth.h
packet-bpv6.h
packet-bpv7.h
packet-bpsec.h
packet-bssap.h
packet-bssgp.h
packet-btatt.h
@ -330,7 +334,6 @@ set(DISSECTOR_PUBLIC_HEADERS
packet-dop.h
packet-dsp.h
packet-dtls.h
packet-dtn.h
packet-dvbci.h
packet-e1ap.h
packet-enip.h
@ -581,6 +584,7 @@ set(DISSECTOR_PUBLIC_HEADERS
packet-tacacs.h
packet-tcap.h
packet-tcp.h
packet-tcpclv3.h
packet-tetra.h
packet-thrift.h
packet-tls-utils.h
@ -694,6 +698,7 @@ set(DISSECTOR_SRC
${CMAKE_CURRENT_SOURCE_DIR}/packet-ansi_637.c
${CMAKE_CURRENT_SOURCE_DIR}/packet-ansi_683.c
${CMAKE_CURRENT_SOURCE_DIR}/packet-ansi_801.c
${CMAKE_CURRENT_SOURCE_DIR}/packet-amp.h
${CMAKE_CURRENT_SOURCE_DIR}/packet-ansi_a.c
${CMAKE_CURRENT_SOURCE_DIR}/packet-aodv.c
${CMAKE_CURRENT_SOURCE_DIR}/packet-aoe.c
@ -764,6 +769,9 @@ set(DISSECTOR_SRC
${CMAKE_CURRENT_SOURCE_DIR}/packet-brcm-tag.c
${CMAKE_CURRENT_SOURCE_DIR}/packet-brdwlk.c
${CMAKE_CURRENT_SOURCE_DIR}/packet-brp.c
${CMAKE_CURRENT_SOURCE_DIR}/packet-bpv6.c
${CMAKE_CURRENT_SOURCE_DIR}/packet-bpv7.c
${CMAKE_CURRENT_SOURCE_DIR}/packet-bpsec.c
${CMAKE_CURRENT_SOURCE_DIR}/packet-bssap.c
${CMAKE_CURRENT_SOURCE_DIR}/packet-bssgp.c
${CMAKE_CURRENT_SOURCE_DIR}/packet-bt-dht.c
@ -983,7 +991,6 @@ set(DISSECTOR_SRC
${CMAKE_CURRENT_SOURCE_DIR}/packet-dsr.c
${CMAKE_CURRENT_SOURCE_DIR}/packet-dtcp-ip.c
${CMAKE_CURRENT_SOURCE_DIR}/packet-dtls.c
${CMAKE_CURRENT_SOURCE_DIR}/packet-dtn.c
${CMAKE_CURRENT_SOURCE_DIR}/packet-dtp.c
${CMAKE_CURRENT_SOURCE_DIR}/packet-dtpt.c
${CMAKE_CURRENT_SOURCE_DIR}/packet-dua.c
@ -1831,6 +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-tcpros.c
${CMAKE_CURRENT_SOURCE_DIR}/packet-tdmoe.c
${CMAKE_CURRENT_SOURCE_DIR}/packet-tdmop.c

View File

@ -14,6 +14,7 @@
#include <epan/exceptions.h>
#include <epan/packet.h>
#include "packet-amp.h"
/* The AMP standard can be found here:
* https://tools.ietf.org/html/draft-birrane-dtn-amp-04
@ -25,8 +26,6 @@
data-payload as AMP. Later in the future, when a dedicated field is given to
this, this should be filled. */
void dissect_amp_as_subtree(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset);
/*
*/
static void

View File

@ -0,0 +1,42 @@
/* packet-amp.h
* Routines for Asynchronous management Protocol dissection
* Copyright 2018, Krishnamurthy Mayya (krishnamurthymayya@gmail.com)
* Updated to CBOR encoding: Keith Scott, 2019 (kscott@mitre.org)
*
* Wireshark - Network traffic analyzer
* By Gerald Combs <gerald@wireshark.org>
* Copyright 1998 Gerald Combs
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#ifndef PACKET_AMP_H
#define PACKET_AMP_H
#include <ws_symbol_export.h>
#include <epan/tvbuff.h>
#include <epan/proto.h>
#ifdef __cplusplus
extern "C" {
#endif
void dissect_amp_as_subtree(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset);
#ifdef __cplusplus
}
#endif
#endif /* PACKET_AMP_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

@ -0,0 +1,576 @@
/* packet-sec.c
* Routines for Bundle Protocol Version 7 Security (BPSec) dissection
* References:
* BPSec: https://datatracker.ietf.org/doc/html/draft-ietf-dtn-bpsec-27
*
* Copyright 2019-2021, Brian Sipos <brian.sipos@gmail.com>
*
* Wireshark - Network traffic analyzer
* By Gerald Combs <gerald@wireshark.org>
* Copyright 1998 Gerald Combs
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*/
#include "packet-bpsec.h"
#include "packet-bpv7.h"
#include <epan/packet.h>
#include <epan/prefs.h>
#include <epan/proto.h>
#include <epan/expert.h>
#include <epan/to_str.h>
#include <wsutil/crc16.h>
#include <wsutil/crc32.h>
#include <stdio.h>
#include <inttypes.h>
#include "epan/wscbor.h"
/// Glib logging "domain" name
//static const char *LOG_DOMAIN = "bpsec";
/// Protocol handles
static int proto_bpsec = -1;
/// Dissect opaque CBOR data
static dissector_handle_t handle_cbor = NULL;
/// Extension sub-dissectors
static dissector_table_t param_dissectors = NULL;
static dissector_table_t result_dissectors = NULL;
static const val64_string shavar_vals[] = {
{5, "HMAC 256/256"},
{6, "HMAC 384/384"},
{7, "HMAC 512/512"},
{0, NULL},
};
static const val64_string aesvar_vals[] = {
{1, "A128GCM"},
{3, "A256GCM"},
{0, NULL},
};
static int hf_bib = -1;
static int hf_bcb = -1;
static int hf_asb_target_list = -1;
static int hf_asb_target = -1;
static int hf_asb_ctxid = -1;
static int hf_asb_flags = -1;
static int hf_asb_flags_has_params = -1;
static int hf_asb_secsrc_nodeid = -1;
static int hf_asb_secsrc_uri = -1;
static int hf_asb_param_list = -1;
static int hf_asb_param_pair = -1;
static int hf_asb_param_id = -1;
static int hf_asb_result_all_list = -1;
static int hf_asb_result_tgt_list = -1;
static int hf_asb_result_tgt_ref = -1;
static int hf_asb_result_pair = -1;
static int hf_asb_result_id = -1;
static int hf_defaultsc_shavar = -1;
static int hf_defaultsc_wrapedkey = -1;
static int hf_defaultsc_scope = -1;
static int hf_defaultsc_scope_pri_block = -1;
static int hf_defaultsc_scope_tgt_head = -1;
static int hf_defaultsc_scope_sec_head = -1;
static int hf_defaultsc_hmac = -1;
static int hf_defaultsc_iv = -1;
static int hf_defaultsc_aesvar = -1;
static int hf_defaultsc_authtag = -1;
/// Field definitions
static hf_register_info fields[] = {
{&hf_bib, {"BPSec Block Integrity Block", "bpsec.bib", FT_PROTOCOL, BASE_NONE, NULL, 0x0, NULL, HFILL}},
{&hf_bcb, {"BPSec Block Confidentiality Block", "bpsec.bcb", FT_PROTOCOL, BASE_NONE, NULL, 0x0, NULL, HFILL}},
{&hf_asb_target_list, {"Security Targets, Count", "bpsec.asb.target_count", FT_UINT64, BASE_DEC, NULL, 0x0, NULL, HFILL}},
{&hf_asb_target, {"Target Block Number", "bpsec.asb.target", FT_UINT64, BASE_DEC, NULL, 0x0, NULL, HFILL}},
{&hf_asb_ctxid, {"Context ID", "bpsec.asb.ctxid", FT_INT64, BASE_DEC, NULL, 0x0, NULL, HFILL}},
{&hf_asb_flags, {"Flags", "bpsec.asb.flags", FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL}},
{&hf_asb_flags_has_params, {"Parameters Present", "bpsec.asb.flags.has_params", FT_BOOLEAN, 8, TFS(&tfs_set_notset), BPSEC_ASB_HAS_PARAMS, NULL, HFILL}},
{&hf_asb_secsrc_nodeid, {"Security Source", "bpsec.asb.secsrc.nodeid", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL}},
{&hf_asb_secsrc_uri, {"Security Source URI", "bpsec.asb.secsrc.uri", FT_STRING, STR_UNICODE, NULL, 0x0, NULL, HFILL}},
{&hf_asb_param_list, {"Security Parameters, Count", "bpsec.asb.param_count", FT_UINT64, BASE_DEC, NULL, 0x0, NULL, HFILL}},
{&hf_asb_param_pair, {"Parameter", "bpsec.asb.param", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL}},
{&hf_asb_param_id, {"Type ID", "bpsec.asb.param.id", FT_INT64, BASE_DEC, NULL, 0x0, NULL, HFILL}},
{&hf_asb_result_all_list, {"Security Result Targets, Count", "bpsec.asb.result_count", FT_UINT64, BASE_DEC, NULL, 0x0, NULL, HFILL}},
{&hf_asb_result_tgt_ref, {"Associated Target Block Number", "bpsec.asb.result_tgt_ref", FT_UINT64, BASE_DEC, NULL, 0x0, NULL, HFILL}},
{&hf_asb_result_tgt_list, {"Security Results, Count", "bpsec.asb.result_count", FT_UINT64, BASE_DEC, NULL, 0x0, NULL, HFILL}},
{&hf_asb_result_pair, {"Result", "bpsec.asb.result", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL}},
{&hf_asb_result_id, {"Type ID", "bpsec.asb.result.id", FT_INT64, BASE_DEC, NULL, 0x0, NULL, HFILL}},
{&hf_defaultsc_shavar, {"SHA Variant", "bpsec.defaultsc.shavar", FT_UINT64, BASE_DEC | BASE_VAL64_STRING, VALS64(shavar_vals), 0x0, NULL, HFILL}},
{&hf_defaultsc_wrapedkey, {"Wrapped Key", "bpsec.defaultsc.wrappedkey", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL}},
{&hf_defaultsc_scope, {"BIB Scope", "bpsec.defaultsc.scope", FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL}},
{&hf_defaultsc_scope_pri_block, {"Primary Block", "bpsec.defaultsc.scope.pri_block", FT_BOOLEAN, 16, TFS(&tfs_set_notset), 0x0001, NULL, HFILL}},
{&hf_defaultsc_scope_tgt_head, {"Target Header", "bpsec.defaultsc.scope.tgt_head", FT_BOOLEAN, 16, TFS(&tfs_set_notset), 0x0002, NULL, HFILL}},
{&hf_defaultsc_scope_sec_head, {"Security Header", "bpsec.defaultsc.scope.sec_head", FT_BOOLEAN, 16, TFS(&tfs_set_notset), 0x0004, NULL, HFILL}},
{&hf_defaultsc_hmac, {"Expected HMAC", "bpsec.defaultsc.hmac", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL}},
{&hf_defaultsc_iv, {"IV", "bpsec.defaultsc.iv", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL}},
{&hf_defaultsc_aesvar, {"AES Variant", "bpsec.defaultsc.aesvar", FT_UINT64, BASE_DEC | BASE_VAL64_STRING, VALS64(aesvar_vals), 0x0, NULL, HFILL}},
{&hf_defaultsc_authtag, {"Authentication Tag", "bpsec.defaultsc.authtag", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL}},
};
static int *const asb_flags[] = {
&hf_asb_flags_has_params,
NULL
};
static int *const defaultsc_scope[] = {
&hf_defaultsc_scope_pri_block,
&hf_defaultsc_scope_tgt_head,
&hf_defaultsc_scope_sec_head,
NULL
};
static int ett_asb = -1;
static int ett_asb_flags = -1;
static int ett_tgt_list = -1;
static int ett_param_list = -1;
static int ett_param_pair = -1;
static int ett_result_all_list = -1;
static int ett_result_tgt_list = -1;
static int ett_result_pair = -1;
static int ett_defaultsc_scope = -1;
/// Tree structures
static int *ett[] = {
&ett_asb,
&ett_asb_flags,
&ett_tgt_list,
&ett_param_list,
&ett_param_pair,
&ett_result_all_list,
&ett_result_tgt_list,
&ett_result_pair,
&ett_defaultsc_scope,
};
static expert_field ei_secsrc_diff = EI_INIT;
static expert_field ei_ctxid_zero = EI_INIT;
static expert_field ei_ctxid_priv = EI_INIT;
static expert_field ei_target_invalid = EI_INIT;
static expert_field ei_value_partial_decode = EI_INIT;
static ei_register_info expertitems[] = {
{&ei_secsrc_diff, {"bpsec.secsrc_diff", PI_SECURITY, PI_CHAT, "BPSec Security Source different from bundle Source", EXPFILL}},
{&ei_ctxid_zero, {"bpsec.ctxid_zero", PI_SECURITY, PI_WARN, "BPSec Security Context ID zero is reserved", EXPFILL}},
{&ei_ctxid_priv, {"bpsec.ctxid_priv", PI_SECURITY, PI_NOTE, "BPSec Security Context ID from private/experimental block", EXPFILL}},
{&ei_target_invalid, {"bpsec.target_invalid", PI_PROTOCOL, PI_WARN, "Target block number not present", EXPFILL}},
{&ei_value_partial_decode, {"bpsec.value_partial_decode", PI_UNDECODED, PI_WARN, "Value data not fully dissected", EXPFILL}},
};
bpsec_id_t * bpsec_id_new(wmem_allocator_t *alloc, gint64 context_id, gint64 type_id) {
bpsec_id_t *obj;
if (alloc) {
obj = wmem_new(alloc, bpsec_id_t);
}
else {
obj = g_new(bpsec_id_t, 1);
}
obj->context_id = context_id;
obj->type_id = type_id;
return obj;
}
void bpsec_id_free(wmem_allocator_t *alloc, gpointer ptr) {
//bpsec_id_t *obj = (bpsec_id_t *)ptr;
wmem_free(alloc, ptr);
}
gboolean bpsec_id_equal(gconstpointer a, gconstpointer b) {
const bpsec_id_t *aobj = a;
const bpsec_id_t *bobj = b;
return (
aobj && bobj
&& (aobj->context_id == bobj->context_id)
&& (aobj->type_id == bobj->type_id)
);
}
guint bpsec_id_hash(gconstpointer key) {
const bpsec_id_t *obj = key;
return (
g_int64_hash(&(obj->context_id))
^ g_int64_hash(&(obj->type_id))
);
}
/** Dissect an ID-value pair within a context.
*
* @param dissector
* @param typeid
* @param tvb
* @param pinfo
* @param tree
*/
static gint dissect_value(dissector_handle_t dissector, gint64 *typeid, tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
gint sublen = 0;
if (dissector) {
sublen = call_dissector_with_data(dissector, tvb, pinfo, tree, typeid);
if ((sublen < 0) || ((guint)sublen < tvb_captured_length(tvb))) {
expert_add_info(pinfo, proto_tree_get_parent(tree), &ei_value_partial_decode);
}
}
if (sublen == 0) {
sublen = call_dissector(handle_cbor, tvb, pinfo, tree);
}
return sublen;
}
/** Dissector for abstract security block structure.
*/
static int dissect_block_asb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, const bp_dissector_data_t *const data, int root_hfindex) {
proto_item *item_asb = proto_tree_add_item(tree, root_hfindex, tvb, 0, -1, ENC_NA);
proto_tree *tree_asb = proto_item_add_subtree(item_asb, ett_asb);
gint offset = 0;
wmem_array_t *targets;
targets = wmem_array_new(wmem_packet_scope(), sizeof(guint64));
wscbor_chunk_t *chunk_tgt_list = wscbor_chunk_read(wmem_packet_scope(), tvb, &offset);
wscbor_require_array(chunk_tgt_list);
proto_item *item_tgt_list = proto_tree_add_cbor_container(tree_asb, hf_asb_target_list, pinfo, tvb, chunk_tgt_list);
if (!wscbor_skip_if_errors(wmem_packet_scope(), tvb, &offset, chunk_tgt_list)) {
proto_tree *tree_tgt_list = proto_item_add_subtree(item_tgt_list, ett_tgt_list);
wscbor_chunk_t *chunk_tgt = wscbor_chunk_read(wmem_packet_scope(), tvb, &offset);
guint64 *tgt_blknum = wscbor_require_uint64(wmem_packet_scope(), chunk_tgt);
proto_item *item_tgt = proto_tree_add_cbor_uint64(tree_tgt_list, hf_asb_target, pinfo, tvb, chunk_tgt, tgt_blknum);
if (tgt_blknum) {
wmem_array_append(targets, tgt_blknum, 1);
wmem_map_t *map = NULL;
if (*tgt_blknum == 0) {
map = (root_hfindex == hf_bib)
? data->bundle->primary->sec.data_i
: data->bundle->primary->sec.data_c;
}
else {
bp_block_canonical_t *found = wmem_map_lookup(data->bundle->block_nums, tgt_blknum);
if (found) {
map = (root_hfindex == hf_bib)
? found->sec.data_i
: found->sec.data_c;
}
else {
expert_add_info(pinfo, item_tgt, &ei_target_invalid);
}
}
if (map) {
wmem_map_insert(
map,
data->block->block_number,
NULL
);
}
}
proto_item_set_len(item_tgt_list, offset - chunk_tgt_list->start);
}
wscbor_chunk_t *chunk_ctxid = wscbor_chunk_read(wmem_packet_scope(), tvb, &offset);
gint64 *ctxid = wscbor_require_int64(wmem_packet_scope(), chunk_ctxid);
proto_item *item_ctxid = proto_tree_add_cbor_int64(tree_asb, hf_asb_ctxid, pinfo, tvb, chunk_ctxid, ctxid);
if (ctxid) {
if (*ctxid == 0) {
expert_add_info(pinfo, item_ctxid, &ei_ctxid_zero);
}
else if (*ctxid < 0) {
expert_add_info(pinfo, item_ctxid, &ei_ctxid_priv);
}
}
wscbor_chunk_t *chunk_flags = wscbor_chunk_read(wmem_packet_scope(), tvb, &offset);
guint64 *flags = wscbor_require_uint64(wmem_packet_scope(), chunk_flags);
proto_tree_add_cbor_bitmask(tree_asb, hf_asb_flags, ett_asb_flags, asb_flags, pinfo, tvb, chunk_flags, flags);
{
bp_eid_t *secsrc = bp_eid_new(wmem_packet_scope());
proto_item *item_secsrc = proto_tree_add_cbor_eid(tree_asb, hf_asb_secsrc_nodeid, hf_asb_secsrc_uri, pinfo, tvb, &offset, secsrc);
if (!bp_eid_equal(data->bundle->primary->src_nodeid, secsrc)) {
expert_add_info(pinfo, item_secsrc, &ei_secsrc_diff);
}
}
if (flags && (*flags & BPSEC_ASB_HAS_PARAMS)) {
wscbor_chunk_t *chunk_param_list = wscbor_chunk_read(wmem_packet_scope(), tvb, &offset);
wscbor_require_array(chunk_param_list);
proto_item *item_param_list = proto_tree_add_cbor_container(tree_asb, hf_asb_param_list, pinfo, tvb, chunk_param_list);
if (!wscbor_skip_if_errors(wmem_packet_scope(), tvb, &offset, chunk_param_list)) {
proto_tree *tree_param_list = proto_item_add_subtree(item_param_list, ett_param_list);
// iterate all parameters
for (guint64 param_ix = 0; param_ix < chunk_param_list->head_value; ++param_ix) {
wscbor_chunk_t *chunk_param_pair = wscbor_chunk_read(wmem_packet_scope(), tvb, &offset);
wscbor_require_array_size(chunk_param_pair, 2, 2);
proto_item *item_param_pair = proto_tree_add_cbor_container(tree_param_list, hf_asb_param_pair, pinfo, tvb, chunk_param_pair);
if (!wscbor_skip_if_errors(wmem_packet_scope(), tvb, &offset, chunk_param_pair)) {
proto_tree *tree_param_pair = proto_item_add_subtree(item_param_pair, ett_param_pair);
wscbor_chunk_t *chunk_paramid = wscbor_chunk_read(wmem_packet_scope(), tvb, &offset);
gint64 *paramid = wscbor_require_int64(wmem_packet_scope(), chunk_paramid);
proto_tree_add_cbor_int64(tree_param_pair, hf_asb_param_id, pinfo, tvb, chunk_paramid, paramid);
if (paramid) {
proto_item_append_text(item_param_pair, ", ID: %" PRIi64, *paramid);
}
const gint offset_value = offset;
wscbor_skip_next_item(wmem_packet_scope(), tvb, &offset);
tvbuff_t *tvb_value = tvb_new_subset_length(tvb, offset_value, offset - offset_value);
dissector_handle_t value_dissect = NULL;
if (ctxid && paramid) {
bpsec_id_t *key = bpsec_id_new(wmem_packet_scope(), *ctxid, *paramid);
value_dissect = dissector_get_custom_table_handle(param_dissectors, key);
bpsec_id_free(wmem_packet_scope(), key);
}
dissect_value(value_dissect, paramid, tvb_value, pinfo, tree_param_pair);
proto_item_set_len(item_param_pair, offset - chunk_param_pair->start);
}
}
proto_item_set_len(item_param_list, offset - chunk_param_list->start);
}
}
// array sizes should agree
const guint tgt_size = wmem_array_get_count(targets);
wscbor_chunk_t *chunk_result_all_list = wscbor_chunk_read(wmem_packet_scope(), tvb, &offset);
wscbor_require_array_size(chunk_result_all_list, tgt_size, tgt_size);
proto_item *item_result_all_list = proto_tree_add_cbor_container(tree_asb, hf_asb_result_all_list, pinfo, tvb, chunk_result_all_list);
if (!wscbor_skip_if_errors(wmem_packet_scope(), tvb, &offset, chunk_result_all_list)) {
proto_tree *tree_result_all_list = proto_item_add_subtree(item_result_all_list, ett_result_all_list);
// iterate each target's results
for (guint tgt_ix = 0; tgt_ix < tgt_size; ++tgt_ix) {
wscbor_chunk_t *chunk_result_tgt_list = wscbor_chunk_read(wmem_packet_scope(), tvb, &offset);
wscbor_require_array(chunk_result_tgt_list);
proto_item *item_result_tgt_list = proto_tree_add_cbor_container(tree_result_all_list, hf_asb_result_tgt_list, pinfo, tvb, chunk_result_tgt_list);
if (!wscbor_skip_if_errors(wmem_packet_scope(), tvb, &offset, chunk_result_tgt_list)) {
proto_tree *tree_result_tgt_list = proto_item_add_subtree(item_result_tgt_list, ett_result_tgt_list);
// Hint at the associated target number
if (tgt_ix < tgt_size) {
const guint64 *tgt_blknum = wmem_array_index(targets, tgt_ix);
proto_item *item_tgt_blknum = proto_tree_add_uint64(tree_result_tgt_list, hf_asb_result_tgt_ref, tvb, 0, 0, *tgt_blknum);
PROTO_ITEM_SET_GENERATED(item_tgt_blknum);
}
// iterate all results for this target
for (guint64 result_ix = 0; result_ix < chunk_result_tgt_list->head_value; ++result_ix) {
wscbor_chunk_t *chunk_result_pair = wscbor_chunk_read(wmem_packet_scope(), tvb, &offset);
wscbor_require_array_size(chunk_result_pair, 2, 2);
proto_item *item_result_pair = proto_tree_add_cbor_container(tree_result_tgt_list, hf_asb_result_pair, pinfo, tvb, chunk_result_pair);
if (!wscbor_skip_if_errors(wmem_packet_scope(), tvb, &offset, chunk_result_pair)) {
proto_tree *tree_result_pair = proto_item_add_subtree(item_result_pair, ett_result_pair);
wscbor_chunk_t *chunk_resultid = wscbor_chunk_read(wmem_packet_scope(), tvb, &offset);
gint64 *resultid = wscbor_require_int64(wmem_packet_scope(), chunk_resultid);
proto_tree_add_cbor_int64(tree_result_pair, hf_asb_result_id, pinfo, tvb, chunk_resultid, resultid);
if (resultid) {
proto_item_append_text(item_result_pair, ", ID: %" PRIi64, *resultid);
}
const gint offset_value = offset;
wscbor_skip_next_item(wmem_packet_scope(), tvb, &offset);
tvbuff_t *tvb_value = tvb_new_subset_length(tvb, offset_value, offset - offset_value);
dissector_handle_t value_dissect = NULL;
if (ctxid && resultid) {
bpsec_id_t *key = bpsec_id_new(wmem_packet_scope(), *ctxid, *resultid);
value_dissect = dissector_get_custom_table_handle(result_dissectors, key);
bpsec_id_free(wmem_packet_scope(), key);
}
dissect_value(value_dissect, resultid, tvb_value, pinfo, tree_result_pair);
proto_item_set_len(item_result_pair, offset - chunk_result_pair->start);
}
}
proto_item_set_len(item_result_tgt_list, offset - chunk_result_tgt_list->start);
}
}
proto_item_set_len(item_result_all_list, offset - chunk_result_all_list->start);
}
proto_item_set_len(item_asb, offset);
return offset;
}
/** Dissector for Bundle Integrity block.
*/
static int dissect_block_bib(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) {
return dissect_block_asb(tvb, pinfo, tree, (bp_dissector_data_t *)data, hf_bib);
}
/** Dissector for Bundle Confidentiality block.
*/
static int dissect_block_bcb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) {
return dissect_block_asb(tvb, pinfo, tree, (bp_dissector_data_t *)data, hf_bcb);
}
static int dissect_defaultsc_param_shavar(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) {
gint offset = 0;
wscbor_chunk_t *chunk = wscbor_chunk_read(wmem_packet_scope(), tvb, &offset);
guint64 *val = wscbor_require_uint64(wmem_packet_scope(), chunk);
proto_tree_add_cbor_uint64(tree, hf_defaultsc_shavar, pinfo, tvb, chunk, val);
return offset;
}
static int dissect_defaultsc_param_wrappedkey(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) {
gint offset = 0;
wscbor_chunk_t *chunk = wscbor_chunk_read(wmem_packet_scope(), tvb, &offset);
wscbor_require_bstr(wmem_packet_scope(), chunk);
proto_tree_add_cbor_bstr(tree, hf_defaultsc_wrapedkey, pinfo, tvb, chunk);
return offset;
}
static int dissect_defaultsc_param_scope(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) {
gint offset = 0;
wscbor_chunk_t *chunk = wscbor_chunk_read(wmem_packet_scope(), tvb, &offset);
guint64 *flags = wscbor_require_uint64(wmem_packet_scope(), chunk);
proto_tree_add_cbor_bitmask(tree, hf_defaultsc_scope, ett_defaultsc_scope, defaultsc_scope, pinfo, tvb, chunk, flags);
return offset;
}
static int dissect_defaultsc_result_hmac(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) {
gint offset = 0;
wscbor_chunk_t *chunk = wscbor_chunk_read(wmem_packet_scope(), tvb, &offset);
wscbor_require_bstr(wmem_packet_scope(), chunk);
proto_tree_add_cbor_bstr(tree, hf_defaultsc_hmac, pinfo, tvb, chunk);
return offset;
}
static int dissect_defaultsc_param_iv(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) {
gint offset = 0;
wscbor_chunk_t *chunk = wscbor_chunk_read(wmem_packet_scope(), tvb, &offset);
wscbor_require_bstr(wmem_packet_scope(), chunk);
proto_tree_add_cbor_bstr(tree, hf_defaultsc_iv, pinfo, tvb, chunk);
return offset;
}
static int dissect_defaultsc_param_aesvar(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) {
gint offset = 0;
wscbor_chunk_t *chunk = wscbor_chunk_read(wmem_packet_scope(), tvb, &offset);
guint64 *val = wscbor_require_uint64(wmem_packet_scope(), chunk);
proto_tree_add_cbor_uint64(tree, hf_defaultsc_aesvar, pinfo, tvb, chunk, val);
return offset;
}
static int dissect_defaultsc_result_authtag(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) {
gint offset = 0;
wscbor_chunk_t *chunk = wscbor_chunk_read(wmem_packet_scope(), tvb, &offset);
wscbor_require_bstr(wmem_packet_scope(), chunk);
proto_tree_add_cbor_bstr(tree, hf_defaultsc_authtag, pinfo, tvb, chunk);
return offset;
}
/// Re-initialize after a configuration change
static void reinit_bpsec(void) {
}
/// Overall registration of the protocol
void proto_register_bpsec(void) {
proto_bpsec = proto_register_protocol(
"DTN Bundle Protocol Security", /* name */
"BPSec", /* short name */
"bpsec" /* abbrev */
);
proto_register_field_array(proto_bpsec, fields, array_length(fields));
proto_register_subtree_array(ett, array_length(ett));
expert_module_t *expert = expert_register_protocol(proto_bpsec);
expert_register_field_array(expert, expertitems, array_length(expertitems));
param_dissectors = register_custom_dissector_table("bpsec.param", "BPSec Parameter", proto_bpsec, bpsec_id_hash, bpsec_id_equal);
result_dissectors = register_custom_dissector_table("bpsec.result", "BPSec Result", proto_bpsec, bpsec_id_hash, bpsec_id_equal);
prefs_register_protocol(proto_bpsec, reinit_bpsec);
}
void proto_reg_handoff_bpsec(void) {
handle_cbor = find_dissector("cbor");
/* Packaged extensions */
{
guint64 *key = g_new(guint64, 1);
*key = 11;
dissector_handle_t hdl = create_dissector_handle(dissect_block_bib, proto_bpsec);
dissector_add_custom_table_handle("bpv7.block_type", key, hdl);
}
{
guint64 *key = g_new(guint64, 1);
*key = 12;
dissector_handle_t hdl = create_dissector_handle(dissect_block_bcb, proto_bpsec);
dissector_add_custom_table_handle("bpv7.block_type", key, hdl);
}
// Context 1: BIB-HMAC-SHA2
{
bpsec_id_t *key = g_new(bpsec_id_t, 1);
key->context_id = 1;
key->type_id = 1;
dissector_handle_t hdl = create_dissector_handle(dissect_defaultsc_param_shavar, proto_bpsec);
dissector_add_custom_table_handle("bpsec.param", key, hdl);
}
{
bpsec_id_t *key = g_new(bpsec_id_t, 1);
key->context_id = 1;
key->type_id = 2;
dissector_handle_t hdl = create_dissector_handle(dissect_defaultsc_param_wrappedkey, proto_bpsec);
dissector_add_custom_table_handle("bpsec.param", key, hdl);
}
{
bpsec_id_t *key = g_new(bpsec_id_t, 1);
key->context_id = 1;
key->type_id = 3;
dissector_handle_t hdl = create_dissector_handle(dissect_defaultsc_param_scope, proto_bpsec);
dissector_add_custom_table_handle("bpsec.param", key, hdl);
}
{
bpsec_id_t *key = g_new(bpsec_id_t, 1);
key->context_id = 1;
key->type_id = 1;
dissector_handle_t hdl = create_dissector_handle(dissect_defaultsc_result_hmac, proto_bpsec);
dissector_add_custom_table_handle("bpsec.result", key, hdl);
}
// Context 2: BCB-AES-GCM
{
bpsec_id_t *key = g_new(bpsec_id_t, 1);
key->context_id = 2;
key->type_id = 1;
dissector_handle_t hdl = create_dissector_handle(dissect_defaultsc_param_iv, proto_bpsec);
dissector_add_custom_table_handle("bpsec.param", key, hdl);
}
{
bpsec_id_t *key = g_new(bpsec_id_t, 1);
key->context_id = 2;
key->type_id = 2;
dissector_handle_t hdl = create_dissector_handle(dissect_defaultsc_param_aesvar, proto_bpsec);
dissector_add_custom_table_handle("bpsec.param", key, hdl);
}
{
bpsec_id_t *key = g_new(bpsec_id_t, 1);
key->context_id = 2;
key->type_id = 3;
dissector_handle_t hdl = create_dissector_handle(dissect_defaultsc_param_wrappedkey, proto_bpsec);
dissector_add_custom_table_handle("bpsec.param", key, hdl);
}
{
bpsec_id_t *key = g_new(bpsec_id_t, 1);
key->context_id = 2;
key->type_id = 4;
dissector_handle_t hdl = create_dissector_handle(dissect_defaultsc_param_scope, proto_bpsec);
dissector_add_custom_table_handle("bpsec.param", key, hdl);
}
{
bpsec_id_t *key = g_new(bpsec_id_t, 1);
key->context_id = 2;
key->type_id = 1;
dissector_handle_t hdl = create_dissector_handle(dissect_defaultsc_result_authtag, proto_bpsec);
dissector_add_custom_table_handle("bpsec.result", key, hdl);
}
reinit_bpsec();
}

View File

@ -0,0 +1,74 @@
/* packet-bpv7.h
* Definitions for Bundle Protocol Version 7 Security (BPSec) dissection
* References:
* BPSec: https://datatracker.ietf.org/doc/html/draft-ietf-dtn-bpsec-27
*
* Copyright 2019-2021, Brian Sipos <brian.sipos@gmail.com>
*
* Wireshark - Network traffic analyzer
* By Gerald Combs <gerald@wireshark.org>
* Copyright 1998 Gerald Combs
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*/
#ifndef PACKET_BPSEC_H
#define PACKET_BPSEC_H
#include <ws_symbol_export.h>
#include <epan/tvbuff.h>
#include <epan/proto.h>
#include <epan/expert.h>
#include <glib.h>
#ifdef __cplusplus
extern "C" {
#endif
/*
* BPSec per-context parameter types and result types are registered with the
* dissector table "bpsec.param" and "bpsec.result" respectively.
* Both use bpsec_id_t* table keys, to identify both the context and the type
* code points.
*/
/** Abstract Security Block Security Context Flags.
* Section 3.6.
*/
typedef enum {
/// Security Parameters present
BPSEC_ASB_HAS_PARAMS = 0x01,
} BpsecAsbFlag;
/// Parameter/Result dissector lookup
typedef struct {
/// Security context ID
gint64 context_id;
/// Parameter/Result ID
gint64 type_id;
} bpsec_id_t;
/** Construct a new ID.
*/
WS_DLL_PUBLIC
bpsec_id_t * bpsec_id_new(wmem_allocator_t *alloc, gint64 context_id, gint64 type_id);
/** Function to match the GDestroyNotify signature.
*/
WS_DLL_PUBLIC
void bpsec_id_free(wmem_allocator_t *alloc, gpointer ptr);
/** Function to match the GCompareFunc signature.
*/
WS_DLL_PUBLIC
gboolean bpsec_id_equal(gconstpointer a, gconstpointer b);
/** Function to match the GHashFunc signature.
*/
WS_DLL_PUBLIC
guint bpsec_id_hash(gconstpointer key);
#ifdef __cplusplus
}
#endif
#endif /* PACKET_BPSEC_H */

View File

@ -1,4 +1,7 @@
/* packet-dtn.c
/* packet-bpv6.c
* References:
* RFC 5050: https://tools.ietf.org/html/rfc5050
*
* Copyright 2006-2007 The MITRE Corporation.
* All Rights Reserved.
* Approved for Public Release; Distribution Unlimited.
@ -41,8 +44,9 @@
#include <epan/packet.h>
#include <epan/reassemble.h>
#include <epan/expert.h>
#include "packet-dtn.h"
#include "packet-tcp.h"
#include <epan/wscbor.h>
#include "packet-bpv6.h"
#include "packet-cfdp.h"
static int dissect_admin_record(proto_tree *primary_tree, tvbuff_t *tvb, packet_info *pinfo,
int offset, int payload_length, gboolean* success);
@ -53,59 +57,13 @@ dissect_amp_as_subtree(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int
static int add_sdnv_time_to_tree(proto_tree *tree, tvbuff_t *tvb, int offset, int hf_sdnv_time);
/* For Reassembling TCP Convergence Layer segments */
static reassembly_table msg_reassembly_table;
static const char magic[] = {'d', 't', 'n', '!'};
static int proto_bundle = -1;
static int proto_tcp_conv = -1;
static dissector_handle_t bundle_handle = NULL;
static dissector_handle_t bpv6_handle = NULL;
static dissector_handle_t bpv7_handle = NULL;
static int hf_bundle_pdu_version = -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;
/* Primary Header Processing Flag Variables */
static int hf_bundle_procflags = -1;
static int hf_bundle_procflags_fragment = -1;
@ -267,8 +225,6 @@ static int hf_block_ciphersuite_range_length = -1;
/* Tree Node Variables */
static gint ett_bundle = -1;
static gint ett_conv_flags = -1;
static gint ett_shutdown_flags = -1;
static gint ett_bundle_hdr = -1;
static gint ett_primary_hdr = -1;
static gint ett_proc_flags = -1;
@ -279,17 +235,11 @@ static gint ett_dictionary = -1;
static gint ett_payload_hdr = -1;
static gint ett_payload_flags = -1;
static gint ett_block_flags = -1;
static gint ett_contact_hdr_flags = -1;
static gint ett_admin_record = -1;
static gint ett_admin_rec_status = -1;
static gint ett_metadata_hdr = -1;
static gint ett_sec_block_param_data = -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_bundle_payload_length = EI_INIT;
static expert_field ei_bundle_control_flags_length = EI_INIT;
static expert_field ei_bundle_block_control_flags = EI_INIT;
@ -299,14 +249,6 @@ static expert_field ei_bundle_offset_error = EI_INIT;
static expert_field ei_block_control_block_cteb_invalid = EI_INIT;
static expert_field ei_block_control_block_cteb_valid = EI_INIT;
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;
#define BUNDLE_PORT 4556
typedef struct dictionary_data {
int bundle_header_dict_length;
@ -335,25 +277,6 @@ typedef struct dictionary_data {
} 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 value_string admin_record_type_vals[] = {
{ADMIN_REC_TYPE_STATUS_REPORT, "Bundle Status Report"},
{ADMIN_REC_TYPE_CUSTODY_SIGNAL, "Custody Signal"},
@ -430,39 +353,6 @@ static const value_string res_params_types[] = {
{0, NULL}
};
/*
* SDNV has a zero in high-order bit position of last byte. The high-order
* bit of all preceding bytes is set to one. This returns the numeric value
* in an integer and sets the value of the second argument to the number of
* bytes used to code the SDNV. A -1 is returned if the evaluation fails
* (value exceeds maximum for signed integer). 0 is an acceptable value.
*/
#define SDNV_MASK 0x7f
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"
};
/*
* Adds the result of 2 SDNVs to tree: First SDNV is seconds, next is nanoseconds.
* Returns bytes in both SDNVs or 0 if something goes wrong.
@ -1958,6 +1848,12 @@ evaluate_sdnv(tvbuff_t *tvb, int offset, int *bytecount)
return value;
}
int evaluate_sdnv_ei(tvbuff_t *tvb, int offset, int *bytecount, expert_field **error) {
int value = evaluate_sdnv(tvb, offset, bytecount);
*error = (value < 0) ? &ei_bundle_sdnv_length : NULL;
return value;
}
/* Special Function to evaluate 64 bit SDNVs */
/*3rd arg is number of bytes in field (returned)*/
gint64
@ -2153,404 +2049,8 @@ evaluate_sdnv64(tvbuff_t *tvb, int offset, int *bytecount, guint64 *value)
}
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, "TCPCL");
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.
*/
eid_length = evaluate_sdnv(tvb, offset, &sdnv_length);
ti = proto_tree_add_int(tree, hf_contact_hdr_local_eid_length, tvb, offset, sdnv_length, eid_length);
if (eid_length < 0) {
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;
sub_item = proto_tree_add_item(tree, proto_bundle, tvb, offset, -1, ENC_NA);
sub_tree = proto_item_add_subtree(sub_item, ett_bundle);
new_tvb = process_reassembled_data(tvb, offset + convergence_hdr_size,
pinfo, "Reassembled DTN", frag_msg,
&msg_frag_items, NULL, sub_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;
}
static int
dissect_bundle(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
dissect_bpv6(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
{
proto_item *ti, *ti_bundle_protocol;
proto_tree *bundle_tree, *primary_tree;
@ -2620,12 +2120,40 @@ dissect_bundle(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _
return(offset);
}
/// Introspect the data to choose a dissector version
static int
dissect_bundle(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
{
gint offset = 0;
{
// Primary Header Version octet
guint8 version = tvb_get_guint8(tvb, offset);
if ((version == 4) || (version == 5) || (version == 6)) {
return call_dissector(bpv6_handle, tvb, pinfo, tree);
}
}
wscbor_chunk_t *frame = wscbor_chunk_read(wmem_packet_scope(), tvb, &offset);
if (frame->type_major == CBOR_TYPE_ARRAY) {
wscbor_chunk_t *primary = wscbor_chunk_read(wmem_packet_scope(), tvb, &offset);
if (primary->type_major == CBOR_TYPE_ARRAY) {
wscbor_chunk_t *version = wscbor_chunk_read(wmem_packet_scope(), tvb, &offset);
if (version->type_major == CBOR_TYPE_UINT) {
guint64 vers_val = version->head_value;
if (vers_val == 7) {
return call_dissector(bpv7_handle, tvb, pinfo, tree);
}
}
}
}
return 0;
}
void proto_reg_handoff_bundle(void);
void proto_register_bundle(void);
void
proto_register_bundle(void)
proto_register_bpv6(void)
{
static hf_register_info hf[] = {
@ -2633,47 +2161,6 @@ proto_register_bundle(void)
{"Bundle Version", "bundle.version",
FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL}
},
{&hf_msg_fragments,
{"Message Fragments", "bundle.msg.fragments",
FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL}
},
{&hf_msg_fragment,
{"Message Fragment", "bundle.msg.fragment",
FT_FRAMENUM, BASE_NONE, NULL, 0x0, NULL, HFILL}
},
{&hf_msg_fragment_overlap,
{"Message fragment overlap", "bundle.msg.fragment.overlap",
FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL}
},
{&hf_msg_fragment_overlap_conflicts,
{"Message fragment overlapping with conflicting data",
"bundle.msg.fragment.overlap.conflicts",
FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL}
},
{&hf_msg_fragment_multiple_tails,
{"Message has multiple tails", "bundle.msg.fragment.multiple_tails",
FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL}
},
{&hf_msg_fragment_too_long_fragment,
{"Message fragment too long", "bundle.msg.fragment.too_long_fragment",
FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL}
},
{&hf_msg_fragment_error,
{"Message defragmentation error", "bundle.msg.fragment.error",
FT_FRAMENUM, BASE_NONE, NULL, 0x0, NULL, HFILL}
},
{&hf_msg_fragment_count,
{"Message fragment count", "bundle.msg.fragment.count",
FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL}
},
{&hf_msg_reassembled_in,
{"Reassembled in", "bundle.msg.reassembled.in",
FT_FRAMENUM, BASE_NONE, NULL, 0x0, NULL, HFILL}
},
{&hf_msg_reassembled_length,
{"Reassembled DTN length", "bundle.msg.reassembled.length",
FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL}
},
{&hf_bundle_procflags,
{"Primary Header Processing Flags", "bundle.primary.proc.flag",
FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL}
@ -3192,93 +2679,6 @@ proto_register_bundle(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}
},
};
static gint *ett[] = {
&ett_bundle,
&ett_bundle_hdr,
@ -3291,22 +2691,12 @@ proto_register_bundle(void)
&ett_payload_hdr,
&ett_payload_flags,
&ett_block_flags,
&ett_contact_hdr_flags,
&ett_conv_flags,
&ett_shutdown_flags,
&ett_admin_record,
&ett_admin_rec_status,
&ett_metadata_hdr,
&ett_sec_block_param_data
};
static gint *ett_tcpcl[] = {
&ett_tcp_conv,
&ett_tcp_conv_hdr,
&ett_msg_fragment,
&ett_msg_fragments,
};
static ei_register_info ei[] = {
{ &ei_bundle_control_flags_length,
{ "bundle.block.control.flags.length", PI_UNDECODED, PI_WARN, "Wrong bundle control flag length", EXPFILL }
@ -3334,47 +2724,23 @@ proto_register_bundle(void)
},
};
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_bundle;
expert_module_t *expert_bundle, *expert_tcpcl;
proto_bundle = proto_register_protocol("Bundle Protocol", "Bundle", "bundle");
proto_bundle = proto_register_protocol("Bundle Protocol", "BP", "bundle");
bpv6_handle = register_dissector("bpv6", dissect_bpv6, proto_bundle);
bundle_handle = register_dissector("bundle", dissect_bundle, proto_bundle);
proto_tcp_conv = proto_register_protocol ("DTN TCP Convergence Layer Protocol", "TCPCL", "tcpcl");
proto_register_field_array(proto_bundle, hf, array_length(hf));
proto_register_subtree_array(ett, array_length(ett));
expert_bundle = expert_register_protocol(proto_bundle);
expert_register_field_array(expert_bundle, ei, array_length(ei));
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_bundle(void)
proto_reg_handoff_bpv6(void)
{
dissector_handle_t tcpcl_handle;
bpv7_handle = find_dissector("bpv7");
tcpcl_handle = create_dissector_handle(dissect_tcpcl, proto_bundle);
dissector_add_uint_with_preference("tcp.port", BUNDLE_PORT, tcpcl_handle);
dissector_add_uint_with_preference("udp.port", BUNDLE_PORT, bundle_handle);
}

View File

@ -1,4 +1,7 @@
/*
/* packet-bpv6.h
* References:
* RFC 5050: https://tools.ietf.org/html/rfc5050
*
* Copyright 2006-2007 The MITRE Corporation.
* All Rights Reserved.
* Approved for Public Release; Distribution Unlimited.
@ -15,53 +18,18 @@
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#ifndef PACKET_BPV6_H
#define PACKET_BPV6_H
/* 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
#include <ws_symbol_export.h>
#include <epan/tvbuff.h>
#include <epan/proto.h>
/* 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
#ifdef __cplusplus
extern "C" {
#endif
#define BUNDLE_PORT 4556
#define BUNDLE_PROCFLAGS_FRAG_MASK 0x01
#define BUNDLE_PROCFLAGS_ADMIN_MASK 0x02
@ -106,12 +74,6 @@
#define PAYLOAD_PROCFLAGS_DISCARD_FAILURE 0x04
#define PAYLOAD_PROCFLAGS_LAST_HEADER 0x08
/* 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
/* Administrative Record Definitions */
#define ADMIN_REC_TYPE_STATUS_REPORT 0x01
#define ADMIN_REC_TYPE_CUSTODY_SIGNAL 0x02
@ -150,7 +112,20 @@
#define DTN_SCHEME_STR "dtn"
#define IPN_SCHEME_STR "ipn"
/*
* SDNV has a zero in high-order bit position of last byte. The high-order
* bit of all preceding bytes is set to one. This returns the numeric value
* in an integer and sets the value of the second argument to the number of
* bytes used to code the SDNV. A -1 is returned if the evaluation fails
* (value exceeds maximum for signed integer). 0 is an acceptable value.
*/
#define SDNV_MASK 0x7f
int evaluate_sdnv(tvbuff_t *tvb, int offset, int *bytecount);
/// Return an error_info index if not valid
int evaluate_sdnv_ei(tvbuff_t *tvb, int offset, int *bytecount, expert_field **error);
gint64 evaluate_sdnv_64(tvbuff_t *tvb, int offset, int *bytecount);
@ -161,10 +136,14 @@ gint64 evaluate_sdnv_64(tvbuff_t *tvb, int offset, int *bytecount);
* result is TRUE (1) on success else FALSE (0)
*/
int evaluate_sdnv32(tvbuff_t *tvb, int offset, int *bytecount, guint32 *value);
int evaluate_sdnv64(tvbuff_t *tvb, int offset, int *bytecount, guint64 *value);
void
dissect_cfdp_as_subtree(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset);
#ifdef __cplusplus
}
#endif
#endif /* PACKET_AMP_H */
/*
* Editor modelines - https://www.wireshark.org/tools/modelines.html

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,357 @@
/* packet-bpv7.h
* Definitions for Bundle Protocol Version 7 dissection.
* References:
* BPv7: https://datatracker.ietf.org/doc/html/draft-ietf-dtn-bpbis-31
*
* Copyright 2019-2021, Brian Sipos <brian.sipos@gmail.com>
*
* Wireshark - Network traffic analyzer
* By Gerald Combs <gerald@wireshark.org>
* Copyright 1998 Gerald Combs
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*/
#ifndef PACKET_BPV7_H
#define PACKET_BPV7_H
#include <ws_symbol_export.h>
#include <epan/tvbuff.h>
#include <epan/proto.h>
#include <epan/expert.h>
#ifdef __cplusplus
extern "C" {
#endif
/*
* BPv7 block-type-specific data dissectors are registered with the
* dissector table "bpv7.block_type" and Administrative Record dissectors
* with the table "bpv7.admin_record_type". Both use guint64* table keys.
*/
/** Bundle CRC types.
* Section 4.1.1.
*/
typedef enum {
/// no CRC is present.
BP_CRC_NONE = 0,
/// a standard X-25 CRC-16 is present.
BP_CRC_16 = 1,
/// a standard CRC32C (Castagnoli) CRC-32 is present.
BP_CRC_32 = 2,
} BundleCrcType;
/** Bundle processing control flags.
* Section 4.1.3.
*/
typedef enum {
/// bundle deletion status reports are requested.
BP_BUNDLE_REQ_DELETION_REPORT = 0x040000,
/// bundle delivery status reports are requested.
BP_BUNDLE_REQ_DELIVERY_REPORT = 0x020000,
/// bundle forwarding status reports are requested.
BP_BUNDLE_REQ_FORWARDING_REPORT = 0x010000,
/// bundle reception status reports are requested.
BP_BUNDLE_REQ_RECEPTION_REPORT = 0x004000,
/// status time is requested in all status reports.
BP_BUNDLE_REQ_STATUS_TIME = 0x000040,
/// user application acknowledgement is requested.
BP_BUNDLE_USER_APP_ACK = 0x000020,
/// bundle must not be fragmented.
BP_BUNDLE_NO_FRAGMENT = 0x000004,
/// payload is an administrative record.
BP_BUNDLE_PAYLOAD_ADMIN = 0x000002,
/// bundle is a fragment.
BP_BUNDLE_IS_FRAGMENT = 0x000001,
} BundleProcessingFlag;
/** Block processing control flags.
* Section 4.1.4.
*/
typedef enum {
/// block must be removed from bundle if it can't be processed.
BP_BLOCK_REMOVE_IF_NO_PROCESS = 0x10,
/// bundle must be deleted if block can't be processed.
BP_BLOCK_DELETE_IF_NO_PROCESS = 0x04,
/// transmission of a status report is requested if block can't be processed.
BP_BLOCK_STATUS_IF_NO_PROCESS = 0x02,
/// block must be replicated in every fragment.
BP_BLOCK_REPLICATE_IN_FRAGMENT = 0x01,
} BlockProcessingFlag;
/** Standard block type codes.
* Section 4.2.3 and Section 4.3.
*/
typedef enum {
BP_BLOCKTYPE_INVALID = 0,
/// Payload (data)
BP_BLOCKTYPE_PAYLOAD = 1,
/// Previous Node
BP_BLOCKTYPE_PREV_NODE = 6,
/// Bundle Age
BP_BLOCKTYPE_BUNDLE_AGE = 7,
/// Hop Count
BP_BLOCKTYPE_HOP_COUNT = 10,
/// Block Integrity Block
BP_BLOCKTYPE_BIB = 11,
/// Block Confidentiality Block
BP_BLOCKTYPE_BCB = 12,
} BlockTypeCode;
/** Administrative record type codes.
* Section 6.1.
*/
typedef enum {
/// Bundle status report
BP_ADMINTYPE_BUNDLE_STATUS = 1,
} AdminRecordTypeCode;
/// DTN time with derived UTC time
typedef struct {
/// DTN time
guint64 dtntime;
/// Converted to UTC
nstime_t utctime;
} bp_dtn_time_t;
/// Creation Timestamp used to correlate bundles
typedef struct {
/// Absolute time
bp_dtn_time_t abstime;
/// Sequence number
guint64 seqno;
} bp_creation_ts_t;
/** Construct a new timestamp.
*/
WS_DLL_PUBLIC
bp_creation_ts_t * bp_creation_ts_alloc(wmem_allocator_t *alloc);
/** Function to match the GDestroyNotify signature.
*/
WS_DLL_PUBLIC
void bp_creation_ts_free(wmem_allocator_t *alloc, bp_creation_ts_t *obj);
/** Function to match the GCompareDataFunc signature.
*/
WS_DLL_PUBLIC
gint bp_creation_ts_compare(gconstpointer a, gconstpointer b, gpointer user_data);
/** Endpoint ID scheme encodings.
*/
typedef enum {
EID_SCHEME_DTN = 1,
EID_SCHEME_IPN = 2,
} EidScheme;
/// Metadata from a Endpoint ID
typedef struct {
/// Scheme ID number
gint64 scheme;
/// Derived URI text
const char *uri;
/// Optional DTN well-known SSP
const char *dtn_wkssp;
/// Optional URI authority part
// const char *node_name;
/// Optional DTN service name
const char *dtn_serv;
} bp_eid_t;
/** Construct a new timestamp.
*/
WS_DLL_PUBLIC
bp_eid_t * bp_eid_new(wmem_allocator_t *alloc);
/** Function to match the GDestroyNotify signature.
*/
WS_DLL_PUBLIC
void bp_eid_free(wmem_allocator_t *alloc, bp_eid_t *obj);
/** Function to match the GCompareFunc signature.
*/
WS_DLL_PUBLIC
gboolean bp_eid_equal(gconstpointer a, gconstpointer b);
/// Security marking metadata
typedef struct {
/// Block numbers marking the data as security integrity protected
wmem_map_t *data_i;
/// Block numbers marking the data as security-modified and not decodable
wmem_map_t *data_c;
} security_mark_t;
/// Metadata extracted from the primary block
typedef struct {
/// Display item for the whole block
proto_item *item_block;
/// Bundle flags (assumed zero).
/// Values are BundleProcessingFlag.
guint64 flags;
/// Destination EID
bp_eid_t *dst_eid;
/// Source NID
bp_eid_t *src_nodeid;
/// Report-to NID
bp_eid_t *rep_nodeid;
/// Creation Timestamp
bp_creation_ts_t ts;
/// Optional fragment start offset
guint64 *frag_offset;
/// Optional bundle total length
guint64 *total_len;
/// CRC type code (assumed zero)
BundleCrcType crc_type;
/// Raw bytes of CRC field
tvbuff_t *crc_field;
security_mark_t sec;
} bp_block_primary_t;
/** Construct a new object on the file allocator.
*/
WS_DLL_PUBLIC
bp_block_primary_t * bp_block_primary_new(wmem_allocator_t *alloc);
/** Function to match the GDestroyNotify signature.
*/
WS_DLL_PUBLIC
void bp_block_primary_free(wmem_allocator_t *alloc, bp_block_primary_t *obj);
typedef struct {
/// The index of the block within the bundle.
/// This is for internal bookkeeping, *not* the block number.
guint64 blk_ix;
/// Display item for the whole block
proto_item *item_block;
/// Type of this block
guint64 *type_code;
/// Unique identifier for this block
guint64 *block_number;
/// All flags on this block
guint64 flags;
/// CRC type code (assumed zero)
BundleCrcType crc_type;
/// Raw bytes of CRC field
tvbuff_t *crc_field;
/// Type-specific data, unencoded
tvbuff_t *data;
/// Type-specific data tree
proto_tree *tree_data;
security_mark_t sec;
} bp_block_canonical_t;
/** Construct a new object on the file allocator.
* @param blk_ix The index of the block within the bundle.
* The canonical index is always greater than zero.
*/
WS_DLL_PUBLIC
bp_block_canonical_t * bp_block_canonical_new(wmem_allocator_t *alloc, guint64 blk_ix);
WS_DLL_PUBLIC
void bp_block_canonical_delete(wmem_allocator_t *alloc, bp_block_canonical_t *obj);
/// Identification of an individual bundle
typedef struct {
/// Normalized EID URI for the Source Node ID
const char *src;
/// Pointer to an external Creation Timestamp
bp_creation_ts_t *ts;
/// Pointer to external optional fragment start offset
guint64 *frag_offset;
/// Pointer to external optional bundle total length
guint64 *total_len;
} bp_bundle_ident_t;
/** Construct a new object on the file allocator.
*/
WS_DLL_PUBLIC
bp_bundle_ident_t * bp_bundle_ident_new(wmem_allocator_t *alloc, bp_eid_t *src, bp_creation_ts_t *ts, guint64 *off, guint64 *len);
WS_DLL_PUBLIC
void bp_bundle_ident_free(wmem_allocator_t *alloc, bp_bundle_ident_t *obj);
/** Function to match the GCompareFunc signature.
*/
WS_DLL_PUBLIC
gboolean bp_bundle_ident_equal(gconstpointer a, gconstpointer b);
/** Function to match the GHashFunc signature.
*/
WS_DLL_PUBLIC
guint bp_bundle_ident_hash(gconstpointer key);
/// Metadata extracted per-bundle
typedef struct {
/// Index of the frame
guint32 frame_num;
/// Timestamp on the frame (end time if reassembled)
nstime_t frame_time;
/// Bundle identity derived from #primary data
bp_bundle_ident_t *ident;
/// Required primary block
bp_block_primary_t *primary;
/// Additional blocks in order (type bp_block_canonical_t)
wmem_list_t *blocks;
/// Map from block number (guint64) to pointer to block of that number
/// (bp_block_canonical_t owned by #blocks)
wmem_map_t *block_nums;
/// Map from block type code (guint64) to sequence (wmem_list_t) of
/// pointers to block of that type (bp_block_canonical_t owned by #blocks)
wmem_map_t *block_types;
} bp_bundle_t;
/** Construct a new object on the file allocator.
*/
WS_DLL_PUBLIC
bp_bundle_t * bp_bundle_new(wmem_allocator_t *alloc);
/** Function to match the GDestroyNotify signature.
*/
WS_DLL_PUBLIC
void bp_bundle_free(wmem_allocator_t *alloc, bp_bundle_t *obj);
/** Extract an Endpoint ID.
* All EID fields are allocated with wmem_file_scope().
*
* @param tree The tree to write items under.
* @param hfindex The root item field.
* @param hfindex_uri The reassembled URI item field.
* @param pinfo Packet info to update.
* @param tvb Buffer to read from.
* @param[in,out] offset Starting offset within @c tvb.
* @param[out] eid If non-null, the EID to write to.
* @return The new tree item.
*/
WS_DLL_PUBLIC
proto_item * proto_tree_add_cbor_eid(proto_tree *tree, int hfindex, int hfindex_uri, packet_info *pinfo, tvbuff_t *tvb, gint *offset, bp_eid_t *eid);
/// Metadata for an entire file
typedef struct {
/// Map from a bundle ID (bp_bundle_ident_t) to bundle (bp_bundle_t)
wmem_map_t *bundles;
/// Map from subject bundle ID (bp_bundle_ident_t) to
/// map from references (bp_bundle_ident_t) of status bundles to NULL
/// i.e. a set
wmem_map_t *admin_status;
} bp_history_t;
/** Data supplied to each block sub-dissector.
*/
typedef struct {
/// The overall bundle being decoded (so far)
bp_bundle_t *bundle;
/// This block being decoded
bp_block_canonical_t *block;
} bp_dissector_data_t;
#ifdef __cplusplus
}
#endif
#endif /* PACKET_BPV7_H */

View File

@ -19,7 +19,7 @@
#include <epan/packet.h>
#include <epan/expert.h>
#include "packet-dtn.h"
#include "packet-cfdp.h"
/* The CFDP standard can be found here:
* http://public.ccsds.org/publications/archive/727x0b4.pdf

View File

@ -0,0 +1,46 @@
/* packet-cfdp.c
* Routines for CCSDS File Delivery Protocol (CFDP) dissection
* Copyright 2013, Juan Antonio Montesinos juan.mondl@gmail.com
*
* Wireshark - Network traffic analyzer
* By Gerald Combs <gerald@wireshark.org>
* Copyright 1998 Gerald Combs
*
* Slightly updated to allow more in-depth decoding when called
* with the 'dissect_as_subtree' method and to leverage some
* of the bitfield display operations: Keith Scott
* <kscott@mitre.org>.
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#ifndef PACKET_CFDP_H
#define PACKET_CFDP_H
#include <ws_symbol_export.h>
#include <epan/tvbuff.h>
#include <epan/proto.h>
#ifdef __cplusplus
extern "C" {
#endif
void dissect_cfdp_as_subtree(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset);
#ifdef __cplusplus
}
#endif
#endif /* PACKET_CFDP_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

@ -36,7 +36,7 @@
#include <epan/expert.h>
#include <epan/reassemble.h>
#include "packet-dtn.h"
#include "packet-bpv6.h"
void proto_register_ltp(void);
void proto_reg_handoff_ltp(void);

View File

@ -0,0 +1,775 @@
/* 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

@ -0,0 +1,101 @@
/* 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:
*/

View File

@ -0,0 +1,7 @@
[_
[7, 11094, 1, [2, [26622, 12070]], [2, [5279, 7390]], [2, [4785, 1111]], [81089243, 993], 52532350140, 1646, 2047, h'55E4'],
[7, 7, 175, 0, 24(h'1B000000013075CD37')],
[10, 5, 89, 0, 24(h'820007')],
[12, 25, 162, 0, 63(h'8101 02 01 82028219149f191cde 84 8201426869 820205 8203426869 820407 8181 8201457468657265')],
[1, 1, 3, 0, 24(h'8201848482F41B000000018BA3F02382F41A3027AC8782F41B000000018DFAF97381F503820282185D18B9821A533D733D190119')]
]

Binary file not shown.

View File

@ -0,0 +1,7 @@
[_
[7, 11094, 1, [2, [26622, 12070]], [2, [5279, 7390]], [2, [4785, 1111]], [81089243, 993], 52532350140, 1646, 2047, h'55E4'],
[7, 7, 175, 0, 24(h'1B000000013075CD37')],
[10, 5, 89, 0, 24(h'820007')],
[11, 25, 162, 0, 63(h'8101 01 01 82028219149f191cde 83 820105 8202426869 820307 8181 8201457468657265')],
[1, 1, 3, 0, 24(h'8201848482F41B000000018BA3F02382F41A3027AC8782F41B000000018DFAF97381F503820282185D18B9821A533D733D190119')]
]

Binary file not shown.

View File

@ -14,6 +14,49 @@ import unittest
import fixtures
import sys
@fixtures.mark_usefixtures('test_env')
@fixtures.uses_fixtures
class case_dissect_bpv7(subprocesstest.SubprocessTestCase):
def test_bpv7_admin_status(self, cmd_tshark, features, dirs, capture_file):
self.assertRun((cmd_tshark,
'-r', capture_file('dtn_udpcl_bpv7_bpsec_bib_admin.pcapng'),
'-Tfields', '-ebpv7.status_rep.identity',
))
self.assertTrue(self.grepOutput(r'Source: ipn:93.185, DTN Time: 1396536125, Seq: 281'))
def test_bpv7_bpsec_bib(self, cmd_tshark, features, dirs, capture_file):
self.assertRun((cmd_tshark,
'-r', capture_file('dtn_udpcl_bpv7_bpsec_bib_admin.pcapng'),
'-Tfields', '-ebpsec.asb.ctxid',
))
self.assertEqual(self.countOutput(r'1'), 1)
def test_bpv7_bpsec_bib_admin_type(self, cmd_tshark, features, dirs, capture_file):
# BIB doesn't alter payload
self.assertRun((cmd_tshark,
'-r', capture_file('dtn_udpcl_bpv7_bpsec_bib_admin.pcapng'),
'-Tfields', '-ebpv7.admin_rec.type_code',
))
self.assertEqual(self.countOutput(r'1'), 1)
def test_bpv7_bpsec_bcb(self, cmd_tshark, features, dirs, capture_file):
self.assertRun((cmd_tshark,
'-r', capture_file('dtn_udpcl_bpv7_bpsec_bcb_admin.pcapng'),
'-Tfields', '-ebpsec.asb.ctxid',
))
self.assertEqual(self.countOutput(r'2'), 1)
def test_bpv7_bpsec_bcb_admin_type(self, cmd_tshark, features, dirs, capture_file):
# BCB inhibits payload dissection
self.assertRun((cmd_tshark,
'-r', capture_file('dtn_udpcl_bpv7_bpsec_bcb_admin.pcapng'),
'-Tfields', '-ebpv7.admin_rec.type_code',
))
self.assertEqual(self.countOutput(r'1'), 0)
@fixtures.mark_usefixtures('test_env')
@fixtures.uses_fixtures
class case_dissect_cose(subprocesstest.SubprocessTestCase):