diff options
Diffstat (limited to 'wiretap/pcapng.c')
-rw-r--r-- | wiretap/pcapng.c | 112 |
1 files changed, 102 insertions, 10 deletions
diff --git a/wiretap/pcapng.c b/wiretap/pcapng.c index 85c635fc..f5c3b320 100644 --- a/wiretap/pcapng.c +++ b/wiretap/pcapng.c @@ -16,10 +16,10 @@ */ #include "config.h" -#include "wtap_opttypes.h" - #define WS_LOG_DOMAIN LOG_DOMAIN_WIRETAP +#include "wtap_opttypes.h" + #include <stdlib.h> #include <string.h> #include <errno.h> @@ -4368,7 +4368,6 @@ 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: @@ -4388,12 +4387,25 @@ static guint32 pcapng_compute_packet_hash_option_size(wtap_optval_t *optval) size = hash->hash_bytes->len; break; } + /* XXX - What if the size of the hash bytes doesn't match the + * expected size? We can: + * 1) Return 0, and omit it when writing + * 2) Return hash_bytes->len, and write it out exactly as we have it + * 3) Return the correct size here, and when writing err or possibly + * truncate. + */ + /* Account for the size of the algorithm type field. */ + size += 1; +#if 0 + /* compute_block_option_size() handles padding. */ + uint32_t pad; if ((size % 4)) { pad = 4 - (size % 4); } else { pad = 0; } size += pad; +#endif return size; } @@ -4401,7 +4413,6 @@ static guint32 pcapng_compute_packet_verdict_option_size(wtap_optval_t *optval) { packet_verdict_opt_t* verdict = &optval->packet_verdictval; guint32 size; - guint32 pad; switch (verdict->type) { @@ -4410,23 +4421,31 @@ static guint32 pcapng_compute_packet_verdict_option_size(wtap_optval_t *optval) break; case packet_verdict_linux_ebpf_tc: - size = 9; + size = 8; break; case packet_verdict_linux_ebpf_xdp: - size = 9; + size = 8; break; default: size = 0; break; } + /* Account for the type octet */ + if (size) { + size += 1; + } +#if 0 + /* compute_block_option_size() handles padding. */ + uint32_t pad; if ((size % 4)) { pad = 4 - (size % 4); } else { pad = 0; } size += pad; +#endif return size; } @@ -4468,6 +4487,15 @@ compute_block_option_size(wtap_block_t block _U_, guint option_id, wtap_opttype_ /* * Are we writing this option? */ + /* + * XXX: The option length field is 16 bits. If size > 65535 (how? + * was the block was obtained from some format other than pcapng?), + * are we going to silently omit the option (in which case we shouldn't + * add the size here), or err out when writing it (in which case + * it's probably fine to add the size or not?) Adding it here and + * then omitting it when writing, as some of the routines do, means + * creating a corrupt file. + */ if (size != 0) { /* * Yes. Add the size of the option header to the size of the @@ -4922,7 +4950,8 @@ static gboolean pcapng_write_packet_verdict_option(wtap_dumper *wdh, guint optio switch (verdict->type) { case packet_verdict_hardware: - size = verdict->data.verdict_bytes->len; + /* Include type octet */ + size = verdict->data.verdict_bytes->len + 1; if (size > 65535) { /* * Too big to fit in the option. @@ -4941,8 +4970,8 @@ static gboolean pcapng_write_packet_verdict_option(wtap_dumper *wdh, guint optio if (!wtap_dump_file_write(wdh, &type, sizeof(guint8), err)) return FALSE; - if (!wtap_dump_file_write(wdh, verdict->data.verdict_bytes->data, size, - err)) + if (!wtap_dump_file_write(wdh, verdict->data.verdict_bytes->data, + verdict->data.verdict_bytes->len, err)) return FALSE; break; @@ -4992,6 +5021,63 @@ static gboolean pcapng_write_packet_verdict_option(wtap_dumper *wdh, guint optio return TRUE; } +static gboolean pcapng_write_packet_hash_option(wtap_dumper *wdh, unsigned option_id, wtap_optval_t *optval, int *err) +{ + packet_hash_opt_t* hash = &optval->packet_hash; + struct pcapng_option_header option_hdr; + uint8_t type; + size_t size; + const uint32_t zero_pad = 0; + uint32_t pad; + + size = pcapng_compute_packet_hash_option_size(optval); + + if (size > 65535) { + /* + * Too big to fit in the option. + * Don't write anything. + * + * XXX - truncate it? Report an error? + */ + return TRUE; + } + + if (size > hash->hash_bytes->len + 1) { + /* + * We don't have enough bytes to write. + * pcapng_compute_packet_hash_option_size() should return 0 if + * we want to silently omit the option instead, or should return + * the length if we want to blindly copy it. + * XXX - Is this the best error type? + */ + *err = WTAP_ERR_UNWRITABLE_REC_DATA; + return FALSE; + } + + type = hash->type; + + option_hdr.type = option_id; + /* Include type byte */ + option_hdr.value_length = (uint16_t)size; + if (!wtap_dump_file_write(wdh, &option_hdr, 4, err)) + return FALSE; + + if (!wtap_dump_file_write(wdh, &type, sizeof(uint8_t), err)) + return FALSE; + + if (!wtap_dump_file_write(wdh, hash->hash_bytes->data, size - 1, + err)) + return FALSE; + + /* write padding (if any) */ + if ((size % 4)) { + pad = 4 - (size % 4); + if (!wtap_dump_file_write(wdh, &zero_pad, pad, err)) + return FALSE; + } + return TRUE; +} + static gboolean write_block_option(wtap_block_t block, guint option_id, wtap_opttype_e option_type _U_, wtap_optval_t *optval, void* user_data) { write_options_t* options = (write_options_t*)user_data; @@ -5231,8 +5317,14 @@ static gboolean write_wtap_epb_option(wtap_dumper *wdh, wtap_block_t block _U_, return FALSE; break; case OPT_PKT_VERDICT: - if (!pcapng_write_packet_verdict_option(wdh, OPT_EPB_QUEUE, optval, + if (!pcapng_write_packet_verdict_option(wdh, OPT_EPB_VERDICT, optval, err)) + return false; + break; + case OPT_PKT_HASH: + if (!pcapng_write_packet_hash_option(wdh, OPT_EPB_HASH, optval, + err)) + return false; break; default: /* Unknown options - write by datatype? */ |