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@Base 1.99.2
bluetooth_uuid_vals_ext@Base 1.99.2 bluetooth_uuid_vals_ext@Base 1.99.2
bluetooth_uuids@Base 2.1.0 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 bssgp_cause_vals_ext@Base 1.9.1
bthci_cmd_authentication_enable_values@Base 2.1.2 bthci_cmd_authentication_enable_values@Base 2.1.2
bthci_cmd_encrypt_mode_vals@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_bstr@Base 3.5.1
proto_tree_add_cbor_container@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_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_int64@Base 3.5.1
proto_tree_add_cbor_tstr@Base 3.5.1 proto_tree_add_cbor_tstr@Base 3.5.1
proto_tree_add_cbor_uint64@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] [commaize]
-- --
Bluetooth Link Manager Protocol (BT LMP) Bluetooth Link Manager Protocol (BT LMP)
Bundle Protocol version 7 (BPv7)
Bundle Protocol version 7 Security (BPSec)
CBOR Object Signing and Encryption (COSE) CBOR Object Signing and Encryption (COSE)
E2 Application Protocol (E2AP) E2 Application Protocol (E2AP)
Event Tracing for Windows (ETW) Event Tracing for Windows (ETW)

View File

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

View File

@ -14,6 +14,7 @@
#include <epan/exceptions.h> #include <epan/exceptions.h>
#include <epan/packet.h> #include <epan/packet.h>
#include "packet-amp.h"
/* The AMP standard can be found here: /* The AMP standard can be found here:
* https://tools.ietf.org/html/draft-birrane-dtn-amp-04 * 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 data-payload as AMP. Later in the future, when a dedicated field is given to
this, this should be filled. */ this, this should be filled. */
void dissect_amp_as_subtree(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset);
/* /*
*/ */
static void 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. * Copyright 2006-2007 The MITRE Corporation.
* All Rights Reserved. * All Rights Reserved.
* Approved for Public Release; Distribution Unlimited. * Approved for Public Release; Distribution Unlimited.
@ -41,8 +44,9 @@
#include <epan/packet.h> #include <epan/packet.h>
#include <epan/reassemble.h> #include <epan/reassemble.h>
#include <epan/expert.h> #include <epan/expert.h>
#include "packet-dtn.h" #include <epan/wscbor.h>
#include "packet-tcp.h" #include "packet-bpv6.h"
#include "packet-cfdp.h"
static int dissect_admin_record(proto_tree *primary_tree, tvbuff_t *tvb, packet_info *pinfo, static int dissect_admin_record(proto_tree *primary_tree, tvbuff_t *tvb, packet_info *pinfo,
int offset, int payload_length, gboolean* success); 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); 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_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; 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 */ /* Primary Header Processing Flag Variables */
static int hf_bundle_procflags = -1; static int hf_bundle_procflags = -1;
static int hf_bundle_procflags_fragment = -1; static int hf_bundle_procflags_fragment = -1;
@ -267,8 +225,6 @@ static int hf_block_ciphersuite_range_length = -1;
/* Tree Node Variables */ /* Tree Node Variables */
static gint ett_bundle = -1; 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_bundle_hdr = -1;
static gint ett_primary_hdr = -1; static gint ett_primary_hdr = -1;
static gint ett_proc_flags = -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_hdr = -1;
static gint ett_payload_flags = -1; static gint ett_payload_flags = -1;
static gint ett_block_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_record = -1;
static gint ett_admin_rec_status = -1; static gint ett_admin_rec_status = -1;
static gint ett_metadata_hdr = -1; static gint ett_metadata_hdr = -1;
static gint ett_sec_block_param_data = -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_payload_length = EI_INIT;
static expert_field ei_bundle_control_flags_length = EI_INIT; static expert_field ei_bundle_control_flags_length = EI_INIT;
static expert_field ei_bundle_block_control_flags = 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_invalid = EI_INIT;
static expert_field ei_block_control_block_cteb_valid = 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 { typedef struct dictionary_data {
int bundle_header_dict_length; int bundle_header_dict_length;
@ -335,25 +277,6 @@ typedef struct dictionary_data {
} dictionary_data_t; } 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[] = { static const value_string admin_record_type_vals[] = {
{ADMIN_REC_TYPE_STATUS_REPORT, "Bundle Status Report"}, {ADMIN_REC_TYPE_STATUS_REPORT, "Bundle Status Report"},
{ADMIN_REC_TYPE_CUSTODY_SIGNAL, "Custody Signal"}, {ADMIN_REC_TYPE_CUSTODY_SIGNAL, "Custody Signal"},
@ -430,39 +353,6 @@ static const value_string res_params_types[] = {
{0, NULL} {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. * 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. * 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; 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 */ /* Special Function to evaluate 64 bit SDNVs */
/*3rd arg is number of bytes in field (returned)*/ /*3rd arg is number of bytes in field (returned)*/
gint64 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 static int
dissect_dtn_contact_header(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;
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_)
{ {
proto_item *ti, *ti_bundle_protocol; proto_item *ti, *ti_bundle_protocol;
proto_tree *bundle_tree, *primary_tree; 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); 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 void
proto_register_bundle(void) proto_register_bpv6(void)
{ {
static hf_register_info hf[] = { static hf_register_info hf[] = {
@ -2633,47 +2161,6 @@ proto_register_bundle(void)
{"Bundle Version", "bundle.version", {"Bundle Version", "bundle.version",
FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL} 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, {&hf_bundle_procflags,
{"Primary Header Processing Flags", "bundle.primary.proc.flag", {"Primary Header Processing Flags", "bundle.primary.proc.flag",
FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL} 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[] = { static gint *ett[] = {
&ett_bundle, &ett_bundle,
&ett_bundle_hdr, &ett_bundle_hdr,
@ -3291,22 +2691,12 @@ proto_register_bundle(void)
&ett_payload_hdr, &ett_payload_hdr,
&ett_payload_flags, &ett_payload_flags,
&ett_block_flags, &ett_block_flags,
&ett_contact_hdr_flags,
&ett_conv_flags,
&ett_shutdown_flags,
&ett_admin_record, &ett_admin_record,
&ett_admin_rec_status, &ett_admin_rec_status,
&ett_metadata_hdr, &ett_metadata_hdr,
&ett_sec_block_param_data &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[] = { static ei_register_info ei[] = {
{ &ei_bundle_control_flags_length, { &ei_bundle_control_flags_length,
{ "bundle.block.control.flags.length", PI_UNDECODED, PI_WARN, "Wrong bundle control flag length", EXPFILL } { "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[] = { expert_module_t *expert_bundle;
{ &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_tcpcl; proto_bundle = proto_register_protocol("Bundle Protocol", "BP", "bundle");
bpv6_handle = register_dissector("bpv6", dissect_bpv6, proto_bundle);
proto_bundle = proto_register_protocol("Bundle Protocol", "Bundle", "bundle");
bundle_handle = register_dissector("bundle", dissect_bundle, 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_field_array(proto_bundle, hf, array_length(hf));
proto_register_subtree_array(ett, array_length(ett)); proto_register_subtree_array(ett, array_length(ett));
expert_bundle = expert_register_protocol(proto_bundle); expert_bundle = expert_register_protocol(proto_bundle);
expert_register_field_array(expert_bundle, ei, array_length(ei)); 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 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); 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. * Copyright 2006-2007 The MITRE Corporation.
* All Rights Reserved. * All Rights Reserved.
* Approved for Public Release; Distribution Unlimited. * Approved for Public Release; Distribution Unlimited.
@ -15,53 +18,18 @@
* *
* SPDX-License-Identifier: GPL-2.0-or-later * SPDX-License-Identifier: GPL-2.0-or-later
*/ */
#ifndef PACKET_BPV6_H
#define PACKET_BPV6_H
/* TCP Convergence Layer - Message Types */ #include <ws_symbol_export.h>
#define TCP_CONV_MSG_TYPE_DATA 0x01 #include <epan/tvbuff.h>
#define TCP_CONV_MSG_TYPE_ACK 0x02 #include <epan/proto.h>
#define TCP_CONV_MSG_TYPE_KEEP_ALIVE 0x03
#define TCP_CONV_MSG_TYPE_SHUTDOWN 0x04
/* TCP Convergence Layer (3) - Message Types */ #ifdef __cplusplus
#define TCP_CONVERGENCE_TYPE_MASK 0xf0 extern "C" {
#define TCP_CONVERGENCE_DATA_SEGMENT 0x10 #endif
#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
#define BUNDLE_PORT 4556
#define BUNDLE_PROCFLAGS_FRAG_MASK 0x01 #define BUNDLE_PROCFLAGS_FRAG_MASK 0x01
#define BUNDLE_PROCFLAGS_ADMIN_MASK 0x02 #define BUNDLE_PROCFLAGS_ADMIN_MASK 0x02
@ -106,12 +74,6 @@
#define PAYLOAD_PROCFLAGS_DISCARD_FAILURE 0x04 #define PAYLOAD_PROCFLAGS_DISCARD_FAILURE 0x04
#define PAYLOAD_PROCFLAGS_LAST_HEADER 0x08 #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 */ /* Administrative Record Definitions */
#define ADMIN_REC_TYPE_STATUS_REPORT 0x01 #define ADMIN_REC_TYPE_STATUS_REPORT 0x01
#define ADMIN_REC_TYPE_CUSTODY_SIGNAL 0x02 #define ADMIN_REC_TYPE_CUSTODY_SIGNAL 0x02
@ -150,7 +112,20 @@
#define DTN_SCHEME_STR "dtn" #define DTN_SCHEME_STR "dtn"
#define IPN_SCHEME_STR "ipn" #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); 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); 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) * result is TRUE (1) on success else FALSE (0)
*/ */
int evaluate_sdnv32(tvbuff_t *tvb, int offset, int *bytecount, guint32 *value); int evaluate_sdnv32(tvbuff_t *tvb, int offset, int *bytecount, guint32 *value);
int evaluate_sdnv64(tvbuff_t *tvb, int offset, int *bytecount, guint64 *value); int evaluate_sdnv64(tvbuff_t *tvb, int offset, int *bytecount, guint64 *value);
void #ifdef __cplusplus
dissect_cfdp_as_subtree(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset); }
#endif
#endif /* PACKET_AMP_H */
/* /*
* Editor modelines - https://www.wireshark.org/tools/modelines.html * 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/packet.h>
#include <epan/expert.h> #include <epan/expert.h>
#include "packet-dtn.h" #include "packet-cfdp.h"
/* The CFDP standard can be found here: /* The CFDP standard can be found here:
* http://public.ccsds.org/publications/archive/727x0b4.pdf * 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/expert.h>
#include <epan/reassemble.h> #include <epan/reassemble.h>
#include "packet-dtn.h" #include "packet-bpv6.h"
void proto_register_ltp(void); void proto_register_ltp(void);
void proto_reg_handoff_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 fixtures
import sys 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.mark_usefixtures('test_env')
@fixtures.uses_fixtures @fixtures.uses_fixtures
class case_dissect_cose(subprocesstest.SubprocessTestCase): class case_dissect_cose(subprocesstest.SubprocessTestCase):