9866cf3bad
This adds BPv7 source and destination as first-class text addresses for the packet. This fixes proto-data used for decode-as table editing outside of a layer.
382 lines
11 KiB
C
382 lines
11 KiB
C
/* packet-bpv7.h
|
|
* Definitions for Bundle Protocol Version 7 dissection.
|
|
* References:
|
|
* RFC 9171: https://www.rfc-editor.org/rfc/rfc9171.html
|
|
*
|
|
* 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
|
|
|
|
/* This dissector defines two layers of protocol:
|
|
* - The BPv7 bundle format and its block types.
|
|
* - The BPv7 Administrative Record which is a bundle payload as indicated by
|
|
* a primary block flag.
|
|
*
|
|
* BPv7 block-type-specific data (BTSD) 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.
|
|
* Both use bp_dissector_data_t* as dissector user data.
|
|
*
|
|
* There is a BTSD heuristic dissector table "bpv7.btsd" which uses
|
|
* bp_dissector_data_t* as dissector user data.
|
|
*
|
|
* Payload block (block type 1) dissection is additionally handled based on
|
|
* bundle flags and destination EID as:
|
|
* - If the bundle flags mark it as administrative, it is dissected as such.
|
|
* - If the destination is a well-known SSP, the dissector table
|
|
* "bpv7.payload.dtn_wkssp" is used with the scheme-specific part.
|
|
* - If the destination is "dtn" scheme, the dissector table
|
|
* "bpv7.payload.dtn_serv" is used with the service demux (text string).
|
|
* There is also Decode As behavior for dtn service demux.
|
|
* - If the destination is "ipn" scheme, the dissector table
|
|
* "bpv7.payload.ipn_serv" is used with the service number (uint value).
|
|
* There is also Decode As behavior for ipn service number.
|
|
* - Finally, fall through to BTSD heuristic dissection.
|
|
* All payload dissection uses bp_dissector_data_t* as dissector user data.
|
|
*/
|
|
|
|
/** Bundle CRC types.
|
|
* RFC 9171 Section 4.2.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.
|
|
* RFC 9171 Section 4.2.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.
|
|
* RFC 9171 Section 4.2.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.
|
|
* RFC 9171 Section 4.3.2 and Section 4.4.
|
|
*/
|
|
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.
|
|
* RFC 9171 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;
|
|
|
|
/** 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 as address
|
|
address uri;
|
|
|
|
/// Optional DTN-scheme well-known SSP
|
|
const char *dtn_wkssp;
|
|
/// Optional DTN-scheme service name
|
|
const char *dtn_serv;
|
|
/// Optional IPN-scheme service name
|
|
guint64 *ipn_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)
|
|
guint64 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)
|
|
guint64 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
|
|
address src;
|
|
/// Creation Timestamp
|
|
bp_creation_ts_t ts;
|
|
/// Pointer to external optional fragment start offset
|
|
const guint64 *frag_offset;
|
|
/// Pointer to external optional bundle total length
|
|
const guint64 *total_len;
|
|
} bp_bundle_ident_t;
|
|
|
|
/** Construct a new object on the file allocator.
|
|
* @param alloc The allocator to use.
|
|
* @param src The non-null pointer to source EID.
|
|
* @param ts The non-null pointer to Timestamp.
|
|
* @param off Optional fragment offset value.
|
|
* @param len Optional fragment length value.
|
|
*/
|
|
WS_DLL_PUBLIC
|
|
bp_bundle_ident_t * bp_bundle_ident_new(wmem_allocator_t *alloc, const bp_eid_t *src, const bp_creation_ts_t *ts, const guint64 *off, const guint64 *len);
|
|
|
|
WS_DLL_PUBLIC
|
|
void bp_bundle_ident_free(wmem_allocator_t *alloc, bp_bundle_ident_t *obj);
|
|
|
|
/** Function to match the GEqualFunc 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;
|
|
/// Layer within the frame
|
|
guint8 layer_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;
|
|
|
|
/// Payload BTSD start offset in bundle TVB
|
|
guint *pyld_start;
|
|
/// Payload BTSD length
|
|
guint *pyld_len;
|
|
} 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 wmem_list_t of 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 */
|