diff options
author | Stephen Hemminger <stephen@networkplumber.org> | 2022-08-11 13:28:03 -0700 |
---|---|---|
committer | AndersBroman <a.broman58@gmail.com> | 2022-08-20 06:12:28 +0000 |
commit | 005169491e72e22a3aa7f7035e2e3cf60b05c6f1 (patch) | |
tree | 0e47ee9d2fd862520854e57f4b3a46daaa475902 /wiretap | |
parent | 07c7ce6ad059da76d987c2dc1cc673a26a65656c (diff) |
pcapng: add support displaying hash from pcapng
Add support for displaying one or more packet hashes that
have been recorded in EPB options.
A patch to add support for EPB hash option is pending for next
DPDK release.
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
Diffstat (limited to 'wiretap')
-rw-r--r-- | wiretap/pcapng.c | 63 | ||||
-rw-r--r-- | wiretap/wtap_opttypes.c | 45 | ||||
-rw-r--r-- | wiretap/wtap_opttypes.h | 23 |
3 files changed, 127 insertions, 4 deletions
diff --git a/wiretap/pcapng.c b/wiretap/pcapng.c index 0b17413ac6..660696ce1b 100644 --- a/wiretap/pcapng.c +++ b/wiretap/pcapng.c @@ -191,6 +191,14 @@ struct pcapng_option { #define OPT_VERDICT_TYPE_TC 1 #define OPT_VERDICT_TYPE_XDP 2 +/* OPT_EPB_HASH sub-types */ +#define OPT_HASH_2COMP 0 +#define OPT_HASH_XOR 1 +#define OPT_HASH_CRC32 2 +#define OPT_HASH_MD5 3 +#define OPT_HASH_SHA1 4 +#define OPT_HASH_TOEPLITZ 5 + /* * In order to keep from trying to allocate large chunks of memory, * which could either fail or, even if it succeeds, chew up so much @@ -1644,6 +1652,7 @@ pcapng_process_packet_block_option(wtapng_block_t *wblock, { guint64 tmp64; packet_verdict_opt_t packet_verdict; + packet_hash_opt_t packet_hash; /* * Handle option content. @@ -1677,8 +1686,22 @@ pcapng_process_packet_block_option(wtapng_block_t *wblock, option_content); break; case(OPT_EPB_HASH): - ws_debug("epb_hash %u currently not handled - ignoring %u bytes", - option_code, option_length); + if (option_length < 1) { + *err = WTAP_ERR_BAD_FILE; + *err_info = ws_strdup_printf("pcapng: packet block hash option length %u is < 1", + option_length); + /* XXX - free anything? */ + return FALSE; + } + packet_hash.type = option_content[0]; + packet_hash.hash_bytes = + g_byte_array_new_take((guint8 *)g_memdup2(&option_content[1], + option_length - 1), + option_length - 1); + wtap_block_add_packet_hash_option(wblock->block, option_code, &packet_hash); + wtap_packet_hash_free(&packet_hash); + ws_debug("hash type %u, data len %u", + option_content[0], option_length - 1); break; case(OPT_EPB_DROPCOUNT): if (option_length != 8) { @@ -3907,6 +3930,39 @@ static guint32 pcapng_compute_custom_option_size(wtap_optval_t *optval) return (guint32)size; } +static guint32 pcapng_compute_packet_hash_option_size(wtap_optval_t *optval) +{ + packet_hash_opt_t* hash = &optval->packet_hash; + guint32 size; + guint32 pad; + + switch (hash->type) { + case OPT_HASH_CRC32: + size = 4; + break; + case OPT_HASH_MD5: + size = 16; + break; + case OPT_HASH_SHA1: + size = 20; + break; + case OPT_HASH_TOEPLITZ: + size = 4; + break; + default: + /* 2COMP and XOR size not defined in standard (yet) */ + size = hash->hash_bytes->len; + break; + } + if ((size % 4)) { + pad = 4 - (size % 4); + } else { + pad = 0; + } + size += pad; + return size; +} + static guint32 pcapng_compute_packet_verdict_option_size(wtap_optval_t *optval) { packet_verdict_opt_t* verdict = &optval->packet_verdictval; @@ -4757,6 +4813,9 @@ compute_epb_option_size(wtap_block_t block _U_, guint option_id, wtap_opttype_e case OPT_EPB_VERDICT: size = pcapng_compute_packet_verdict_option_size(optval); break; + case OPT_EPB_HASH: + size = pcapng_compute_packet_hash_option_size(optval); + break; default: /* Unknown options - size by datatype? */ size = 0; diff --git a/wiretap/wtap_opttypes.c b/wiretap/wtap_opttypes.c index 6a42bc3241..60b77fd636 100644 --- a/wiretap/wtap_opttypes.c +++ b/wiretap/wtap_opttypes.c @@ -194,6 +194,29 @@ void wtap_packet_verdict_free(packet_verdict_opt_t* verdict) } } +static packet_hash_opt_t +packet_hash_dup(packet_hash_opt_t* hash_src) +{ + packet_hash_opt_t hash_dest; + + memset(&hash_dest, 0, sizeof(hash_dest)); + + /* Deep copy. */ + hash_dest.type = hash_src->type; + /* array of octets */ + hash_dest.hash_bytes = + g_byte_array_new_take((guint8 *)g_memdup2(hash_src->hash_bytes->data, + hash_src->hash_bytes->len), + hash_src->hash_bytes->len); + return hash_dest; +} + +void wtap_packet_hash_free(packet_hash_opt_t* hash) +{ + /* array of bytes */ + g_byte_array_free(hash->hash_bytes, TRUE); +} + static void wtap_opttype_block_register(wtap_blocktype_t *blocktype) { wtap_block_type_t block_type; @@ -364,6 +387,10 @@ static void wtap_block_free_option(wtap_block_t block, wtap_option_t *opt) wtap_packet_verdict_free(&opt->value.packet_verdictval); break; + case WTAP_OPTTYPE_PACKET_HASH: + wtap_packet_hash_free(&opt->value.packet_hash); + break; + default: break; } @@ -508,6 +535,9 @@ wtap_block_copy(wtap_block_t dest_block, wtap_block_t src_block) case WTAP_OPTTYPE_PACKET_VERDICT: wtap_block_add_packet_verdict_option(dest_block, src_opt->option_id, &src_opt->value.packet_verdictval); break; + case WTAP_OPTTYPE_PACKET_HASH: + wtap_block_add_packet_hash_option(dest_block, src_opt->option_id, &src_opt->value.packet_hash); + break; } } } @@ -1429,6 +1459,19 @@ wtap_block_get_nth_packet_verdict_option_value(wtap_block_t block, guint option_ } wtap_opttype_return_val +wtap_block_add_packet_hash_option(wtap_block_t block, guint option_id, packet_hash_opt_t* value) +{ + wtap_opttype_return_val ret; + wtap_option_t *opt; + + ret = wtap_block_add_option_common(block, option_id, WTAP_OPTTYPE_PACKET_HASH, &opt); + if (ret != WTAP_OPTTYPE_SUCCESS) + return ret; + opt->value.packet_hash = packet_hash_dup(value); + return WTAP_OPTTYPE_SUCCESS; +} + +wtap_opttype_return_val wtap_block_remove_option(wtap_block_t block, guint option_id) { const wtap_opttype_t *opttype; @@ -1849,7 +1892,7 @@ void wtap_opttypes_initialize(void) static const wtap_opttype_t pkt_hash = { "hash", "Hash of packet data", - WTAP_OPTTYPE_BYTES, // TODO: replace with a pkt_hash_opt_t + WTAP_OPTTYPE_PACKET_HASH, WTAP_OPTTYPE_FLAG_MULTIPLE_ALLOWED }; static const wtap_opttype_t pkt_verdict = { diff --git a/wiretap/wtap_opttypes.h b/wiretap/wtap_opttypes.h index 702b51dcbc..3b20c88f1d 100644 --- a/wiretap/wtap_opttypes.h +++ b/wiretap/wtap_opttypes.h @@ -282,7 +282,8 @@ typedef enum { WTAP_OPTTYPE_IPv6, WTAP_OPTTYPE_CUSTOM, WTAP_OPTTYPE_IF_FILTER, - WTAP_OPTTYPE_PACKET_VERDICT + WTAP_OPTTYPE_PACKET_VERDICT, + WTAP_OPTTYPE_PACKET_HASH, } wtap_opttype_e; typedef enum { @@ -378,6 +379,11 @@ typedef struct packet_verdict_opt_s { } data; } packet_verdict_opt_t; +typedef struct packet_hash_opt_s { + guint8 type; + GByteArray *hash_bytes; +} packet_hash_opt_t; + /* * Structure describing a value of an option. */ @@ -392,6 +398,7 @@ typedef union { custom_opt_t custom_opt; if_filter_opt_t if_filterval; packet_verdict_opt_t packet_verdictval; + packet_hash_opt_t packet_hash; } wtap_optval_t; /* @@ -1047,6 +1054,20 @@ wtap_block_get_nth_packet_verdict_option_value(wtap_block_t block, guint option_ WS_DLL_PUBLIC void wtap_packet_verdict_free(packet_verdict_opt_t* verdict); +/** Add an packet_hash option value to a block + * + * @param[in] block Block to which to add the option + * @param[in] option_id Identifier value for option + * @param[in] value Value of option + * @return wtap_opttype_return_val - WTAP_OPTTYPE_SUCCESS if successful, + * error code otherwise + */ +WS_DLL_PUBLIC wtap_opttype_return_val +wtap_block_add_packet_hash_option(wtap_block_t block, guint option_id, packet_hash_opt_t* value); + +WS_DLL_PUBLIC void +wtap_packet_hash_free(packet_hash_opt_t* hash); + /** Remove an option from a block * * @param[in] block Block from which to remove the option |