aboutsummaryrefslogtreecommitdiffstats
path: root/wiretap
diff options
context:
space:
mode:
authorStephen Hemminger <stephen@networkplumber.org>2022-08-11 13:28:03 -0700
committerAndersBroman <a.broman58@gmail.com>2022-08-20 06:12:28 +0000
commit005169491e72e22a3aa7f7035e2e3cf60b05c6f1 (patch)
tree0e47ee9d2fd862520854e57f4b3a46daaa475902 /wiretap
parent07c7ce6ad059da76d987c2dc1cc673a26a65656c (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.c63
-rw-r--r--wiretap/wtap_opttypes.c45
-rw-r--r--wiretap/wtap_opttypes.h23
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