aboutsummaryrefslogtreecommitdiffstats
path: root/wiretap
diff options
context:
space:
mode:
authorGuy Harris <gharris@sonic.net>2021-08-26 23:47:36 -0700
committerWireshark GitLab Utility <gerald+gitlab-utility@wireshark.org>2021-08-27 06:48:47 +0000
commit8acd0d1151c8eef2cd7c86642c2165a386955066 (patch)
tree8df1883db25ebc4836f0681817069c8f563ff208 /wiretap
parentd4de52690f7565069377aad4bdd32c272dc576cc (diff)
pcapng: export routines to do the option-section processing.
That way, add-on modules to handle block types not handled by the core pcapng code can use pcap_process_options() to process a block's options and can use the routines to handle the "standard" option value types to handle particular options. Also, allow both everything-is-little-endian and everything-is-big-endian Custom Block types in pcap_process_options().
Diffstat (limited to 'wiretap')
-rw-r--r--wiretap/pcapng.c221
-rw-r--r--wiretap/pcapng_module.h90
2 files changed, 254 insertions, 57 deletions
diff --git a/wiretap/pcapng.c b/wiretap/pcapng.c
index e443b47764..5aaf3bea06 100644
--- a/wiretap/pcapng.c
+++ b/wiretap/pcapng.c
@@ -231,18 +231,6 @@ typedef struct wtapng_simple_packet_s {
/* XXX - put the packet data / pseudo_header here as well? */
} wtapng_simple_packet_t;
-/* Section data in private struct */
-typedef struct section_info_t {
- gboolean byte_swapped; /**< TRUE if this section is not in our byte order */
- guint16 version_major; /**< Major version number of this section */
- guint16 version_minor; /**< Minor version number of this section */
- GArray *interfaces; /**< Interfaces found in this section */
- gint64 shb_off; /**< File offset of the SHB for this section */
- guint32 bblog_version; /**< BBLog: version used */
- guint64 bblog_offset_tv_sec; /**< BBLog: UTC offset */
- guint64 bblog_offset_tv_usec;
-} section_info_t;
-
/* Interface data in private struct */
typedef struct interface_info_s {
int wtap_encap;
@@ -514,7 +502,7 @@ register_pcapng_option_handler(guint block_type, guint option_code,
GUINT_TO_POINTER(option_code), handler);
}
-static void
+void
pcapng_process_uint8_option(wtapng_block_t *wblock,
guint16 option_code, guint16 option_length,
const guint8 *option_content)
@@ -529,7 +517,7 @@ pcapng_process_uint8_option(wtapng_block_t *wblock,
}
}
-static void
+void
pcapng_process_uint32_option(wtapng_block_t *wblock,
guint16 option_code, guint16 option_length,
guint32 option_content)
@@ -544,9 +532,10 @@ pcapng_process_uint32_option(wtapng_block_t *wblock,
}
}
-static void
+void
pcapng_process_timestamp_option(wtapng_block_t *wblock,
const section_info_t *section_info,
+ pcapng_opt_byte_order_e byte_order,
guint16 option_code, guint16 option_length,
const guint8 *option_content)
{
@@ -560,9 +549,35 @@ pcapng_process_timestamp_option(wtapng_block_t *wblock,
*/
memcpy(&high, option_content, sizeof(guint32));
memcpy(&low, option_content + sizeof(guint32), sizeof(guint32));
- if (section_info->byte_swapped) {
- high = GUINT32_SWAP_LE_BE(high);
- low = GUINT32_SWAP_LE_BE(low);
+ switch (byte_order) {
+
+ case OPT_SECTION_BYTE_ORDER:
+ if (section_info->byte_swapped) {
+ high = GUINT32_SWAP_LE_BE(high);
+ low = GUINT32_SWAP_LE_BE(low);
+ }
+ break;
+
+ case OPT_BIG_ENDIAN:
+ high = GUINT32_FROM_BE(high);
+ low = GUINT32_FROM_BE(low);
+ break;
+
+ case OPT_LITTLE_ENDIAN:
+ high = GUINT32_FROM_LE(high);
+ low = GUINT32_FROM_LE(low);
+ break;
+
+ default:
+ /*
+ * This should not happen - this is called by pcapng_process_options(),
+ * which returns an error for an invalid byte_order argument, and
+ * otherwise passes the known-to-be-valid byte_order argument to
+ * us.
+ *
+ * Just ignore the option.
+ */
+ return;
}
timestamp = (guint64)high;
timestamp <<= 32;
@@ -576,9 +591,10 @@ pcapng_process_timestamp_option(wtapng_block_t *wblock,
}
}
-static void
+void
pcapng_process_uint64_option(wtapng_block_t *wblock,
const section_info_t *section_info,
+ pcapng_opt_byte_order_e byte_order,
guint16 option_code, guint16 option_length,
const guint8 *option_content)
{
@@ -590,6 +606,33 @@ pcapng_process_uint64_option(wtapng_block_t *wblock,
* aligned correctly.
*/
memcpy(&uint64, option_content, sizeof(guint64));
+ switch (byte_order) {
+
+ case OPT_SECTION_BYTE_ORDER:
+ if (section_info->byte_swapped) {
+ uint64 = GUINT64_SWAP_LE_BE(uint64);
+ }
+ break;
+
+ case OPT_BIG_ENDIAN:
+ uint64 = GUINT64_FROM_BE(uint64);
+ break;
+
+ case OPT_LITTLE_ENDIAN:
+ uint64 = GUINT64_FROM_LE(uint64);
+ break;
+
+ default:
+ /*
+ * This should not happen - this is called by pcapng_process_options(),
+ * which returns an error for an invalid byte_order argument, and
+ * otherwise passes the known-to-be-valid byte_order argument to
+ * us.
+ *
+ * Just ignore the option.
+ */
+ return;
+ }
if (section_info->byte_swapped)
uint64 = GUINT64_SWAP_LE_BE(uint64);
/*
@@ -601,16 +644,16 @@ pcapng_process_uint64_option(wtapng_block_t *wblock,
}
}
-static void
+void
pcapng_process_string_option(wtapng_block_t *wblock, guint16 option_code,
guint16 option_length, const guint8 *option_content)
{
wtap_block_add_string_option(wblock->block, option_code, (const char *)option_content, option_length);
}
-static void
+void
pcapng_process_bytes_option(wtapng_block_t *wblock, guint16 option_code,
- guint16 option_length, const guint8 *option_content)
+ guint16 option_length, const guint8 *option_content)
{
wtap_block_add_bytes_option(wblock->block, option_code, (const char *)option_content, option_length);
}
@@ -702,7 +745,7 @@ pcapng_process_custom_option(wtapng_block_t *wblock,
section_info_t *section_info,
guint16 option_code, guint16 option_length,
const guint8 *option_content,
- gboolean little_endian,
+ pcapng_opt_byte_order_e byte_order,
int *err, gchar **err_info)
{
guint32 pen;
@@ -715,10 +758,33 @@ pcapng_process_custom_option(wtapng_block_t *wblock,
return FALSE;
}
memcpy(&pen, option_content, sizeof(guint32));
- if (little_endian) {
+ switch (byte_order) {
+
+ case OPT_SECTION_BYTE_ORDER:
+ if (section_info->byte_swapped) {
+ pen = GUINT32_SWAP_LE_BE(pen);
+ }
+ break;
+
+ case OPT_BIG_ENDIAN:
+ pen = GUINT32_FROM_BE(pen);
+ break;
+
+ case OPT_LITTLE_ENDIAN:
pen = GUINT32_FROM_LE(pen);
- } else if (section_info->byte_swapped) {
- pen = GUINT32_SWAP_LE_BE(pen);
+ break;
+
+ default:
+ /*
+ * This should not happen - this is called by pcapng_process_options(),
+ * which returns an error for an invalid byte_order argument, and
+ * otherwise passes the known-to-be-valid byte_order argument to
+ * us.
+ */
+ *err = WTAP_ERR_INTERNAL;
+ *err_info = g_strdup_printf("pcapng: invalid byte order %d passed to pcapng_process_custom_option()",
+ byte_order);
+ return FALSE;
}
switch (pen) {
case PEN_NFLX:
@@ -771,7 +837,7 @@ pcapng_process_unhandled_option(wtapng_block_t *wblock _U_,
}
#endif
-static gboolean
+gboolean
pcapng_process_options(FILE_T fh, wtapng_block_t *wblock,
section_info_t *section_info,
guint opt_cont_buf_len,
@@ -780,7 +846,7 @@ pcapng_process_options(FILE_T fh, wtapng_block_t *wblock,
guint16, guint16,
const guint8 *,
int *, gchar **),
- gboolean little_endian,
+ pcapng_opt_byte_order_e byte_order,
int *err, gchar **err_info)
{
guint8 *option_content; /* Allocate as large as the options block */
@@ -830,12 +896,31 @@ pcapng_process_options(FILE_T fh, wtapng_block_t *wblock,
}
option_code = oh->option_code;
option_length = oh->option_length;
- if (little_endian) {
+ switch (byte_order) {
+
+ case OPT_SECTION_BYTE_ORDER:
+ if (section_info->byte_swapped) {
+ option_code = GUINT16_SWAP_LE_BE(option_code);
+ option_length = GUINT16_SWAP_LE_BE(option_length);
+ }
+ break;
+
+ case OPT_BIG_ENDIAN:
+ option_code = GUINT16_FROM_BE(option_code);
+ option_length = GUINT16_FROM_BE(option_length);
+ break;
+
+ case OPT_LITTLE_ENDIAN:
option_code = GUINT16_FROM_LE(option_code);
option_length = GUINT16_FROM_LE(option_length);
- } else if (section_info->byte_swapped) {
- option_code = GUINT16_SWAP_LE_BE(option_code);
- option_length = GUINT16_SWAP_LE_BE(option_length);
+ break;
+
+ default:
+ /* Don't do that. */
+ *err = WTAP_ERR_INTERNAL;
+ *err_info = g_strdup_printf("pcapng: invalid byte order %d passed to pcapng_process_options()",
+ byte_order);
+ return FALSE;
}
option_ptr += sizeof (*oh); /* 4 bytes, so it remains aligned */
opt_bytes_remaining -= sizeof (*oh);
@@ -871,7 +956,7 @@ pcapng_process_options(FILE_T fh, wtapng_block_t *wblock,
if (!pcapng_process_custom_option(wblock, section_info,
option_code, option_length,
option_ptr,
- little_endian,
+ byte_order,
err, err_info)) {
g_free(option_content);
return FALSE;
@@ -1092,7 +1177,7 @@ pcapng_read_section_header_block(FILE_T fh, pcapng_block_header_t *bh,
opt_cont_buf_len = bh->block_total_length - MIN_SHB_SIZE;
if (!pcapng_process_options(fh, wblock, section_info, opt_cont_buf_len,
pcapng_process_section_header_block_option,
- FALSE, err, err_info))
+ OPT_SECTION_BYTE_ORDER, err, err_info))
return PCAPNG_BLOCK_ERROR;
/*
@@ -1140,8 +1225,10 @@ pcapng_process_if_descr_block_option(wtapng_block_t *wblock,
option_content);
break;
case(OPT_IDB_SPEED): /* if_speed */
- pcapng_process_uint64_option(wblock, section_info, option_code,
- option_length, option_content);
+ pcapng_process_uint64_option(wblock, section_info,
+ OPT_SECTION_BYTE_ORDER,
+ option_code, option_length,
+ option_content);
break;
case(OPT_IDB_TSRESOL): /* if_tsresol */
pcapng_process_uint8_option(wblock, option_code, option_length,
@@ -1355,7 +1442,7 @@ pcapng_read_if_descr_block(wtap *wth, FILE_T fh, pcapng_block_header_t *bh,
opt_cont_buf_len = bh->block_total_length - MIN_IDB_SIZE;
if (!pcapng_process_options(fh, wblock, section_info, opt_cont_buf_len,
pcapng_process_if_descr_block_option,
- FALSE, err, err_info))
+ OPT_SECTION_BYTE_ORDER, err, err_info))
return FALSE;
/*
@@ -1562,7 +1649,10 @@ pcapng_process_packet_block_option(wtapng_block_t *wblock,
/* XXX - free anything? */
return FALSE;
}
- pcapng_process_uint64_option(wblock, section_info, option_code, option_length, option_content);
+ pcapng_process_uint64_option(wblock, section_info,
+ OPT_SECTION_BYTE_ORDER,
+ option_code, option_length,
+ option_content);
break;
case(OPT_EPB_PACKETID):
if (option_length != 8) {
@@ -1572,7 +1662,10 @@ pcapng_process_packet_block_option(wtapng_block_t *wblock,
/* XXX - free anything? */
return FALSE;
}
- pcapng_process_uint64_option(wblock, section_info, option_code, option_length, option_content);
+ pcapng_process_uint64_option(wblock, section_info,
+ OPT_SECTION_BYTE_ORDER,
+ option_code, option_length,
+ option_content);
break;
case(OPT_EPB_QUEUE):
if (option_length != 4) {
@@ -1860,7 +1953,7 @@ pcapng_read_packet_block(FILE_T fh, pcapng_block_header_t *bh,
(int)sizeof(bh->block_total_length);
if (!pcapng_process_options(fh, wblock, section_info, opt_cont_buf_len,
pcapng_process_packet_block_option,
- FALSE, err, err_info))
+ OPT_SECTION_BYTE_ORDER, err, err_info))
return FALSE;
/*
@@ -2351,7 +2444,7 @@ read_options:
opt_cont_buf_len = to_read;
if (!pcapng_process_options(fh, wblock, section_info, opt_cont_buf_len,
pcapng_process_name_resolution_block_option,
- FALSE, err, err_info))
+ OPT_SECTION_BYTE_ORDER, err, err_info))
return FALSE;
ws_buffer_free(&nrb_rec);
@@ -2391,32 +2484,46 @@ pcapng_process_interface_statistics_block_option(wtapng_block_t *wblock,
*/
switch (option_code) {
case(OPT_ISB_STARTTIME): /* isb_starttime */
- pcapng_process_timestamp_option(wblock, section_info, option_code,
- option_length, option_content);
+ pcapng_process_timestamp_option(wblock, section_info,
+ OPT_SECTION_BYTE_ORDER,
+ option_code, option_length,
+ option_content);
break;
case(OPT_ISB_ENDTIME): /* isb_endtime */
- pcapng_process_timestamp_option(wblock, section_info, option_code,
- option_length, option_content);
+ pcapng_process_timestamp_option(wblock, section_info,
+ OPT_SECTION_BYTE_ORDER,
+ option_code, option_length,
+ option_content);
break;
case(OPT_ISB_IFRECV): /* isb_ifrecv */
- pcapng_process_uint64_option(wblock, section_info, option_code,
- option_length, option_content);
+ pcapng_process_uint64_option(wblock, section_info,
+ OPT_SECTION_BYTE_ORDER,
+ option_code, option_length,
+ option_content);
break;
case(OPT_ISB_IFDROP): /* isb_ifdrop */
- pcapng_process_uint64_option(wblock, section_info, option_code,
- option_length, option_content);
+ pcapng_process_uint64_option(wblock, section_info,
+ OPT_SECTION_BYTE_ORDER,
+ option_code, option_length,
+ option_content);
break;
case(OPT_ISB_FILTERACCEPT): /* isb_filteraccept 6 */
- pcapng_process_uint64_option(wblock, section_info, option_code,
- option_length, option_content);
+ pcapng_process_uint64_option(wblock, section_info,
+ OPT_SECTION_BYTE_ORDER,
+ option_code, option_length,
+ option_content);
break;
case(OPT_ISB_OSDROP): /* isb_osdrop 7 */
- pcapng_process_uint64_option(wblock, section_info, option_code,
- option_length, option_content);
+ pcapng_process_uint64_option(wblock, section_info,
+ OPT_SECTION_BYTE_ORDER,
+ option_code, option_length,
+ option_content);
break;
case(OPT_ISB_USRDELIV): /* isb_usrdeliv 8 */
- pcapng_process_uint64_option(wblock, section_info, option_code,
- option_length, option_content);
+ pcapng_process_uint64_option(wblock, section_info,
+ OPT_SECTION_BYTE_ORDER,
+ option_code, option_length,
+ option_content);
break;
default:
if (!pcapng_process_unhandled_option(wblock, BT_INDEX_ISB,
@@ -2483,7 +2590,7 @@ pcapng_read_interface_statistics_block(FILE_T fh, pcapng_block_header_t *bh,
(MIN_BLOCK_SIZE + (guint)sizeof isb); /* fixed and variable part, including padding */
if (!pcapng_process_options(fh, wblock, section_info, opt_cont_buf_len,
pcapng_process_interface_statistics_block_option,
- FALSE, err, err_info))
+ OPT_SECTION_BYTE_ORDER, err, err_info))
return FALSE;
/*
@@ -2553,7 +2660,7 @@ pcapng_read_nflx_custom_block(FILE_T fh, pcapng_block_header_t *bh,
/* Options */
if (!pcapng_process_options(fh, wblock, section_info, opt_cont_buf_len,
- NULL, TRUE, err, err_info))
+ NULL, OPT_LITTLE_ENDIAN, err, err_info))
return FALSE;
return TRUE;
diff --git a/wiretap/pcapng_module.h b/wiretap/pcapng_module.h
index 8ff8c618ca..5be1e40976 100644
--- a/wiretap/pcapng_module.h
+++ b/wiretap/pcapng_module.h
@@ -52,6 +52,22 @@ typedef struct wtapng_block_s {
Buffer *frame_buffer;
} wtapng_block_t;
+/* Section data in private struct */
+/*
+ * XXX - there needs to be a more general way to implement the Netflix
+ * BBLog blocks and options.
+ */
+typedef struct section_info_t {
+ gboolean byte_swapped; /**< TRUE if this section is not in our byte order */
+ guint16 version_major; /**< Major version number of this section */
+ guint16 version_minor; /**< Minor version number of this section */
+ GArray *interfaces; /**< Interfaces found in this section */
+ gint64 shb_off; /**< File offset of the SHB for this section */
+ guint32 bblog_version; /**< BBLog: version used */
+ guint64 bblog_offset_tv_sec; /**< BBLog: UTC offset */
+ guint64 bblog_offset_tv_usec;
+} section_info_t;
+
/*
* Reader and writer routines for pcapng block types.
*/
@@ -91,4 +107,78 @@ void register_pcapng_option_handler(guint block_type, guint option_code,
option_sizer sizer,
option_writer writer);
+/*
+ * Byte order of the options within a block.
+ *
+ * This is usually the byte order of the section, but, for options
+ * within a Custom Block, it needs to be a specified byte order,
+ * or a byte order indicated by data in the Custom Data (stored in
+ * a fashion that doesn't require knowing the byte order of the
+ * Custom Data, as it's also the byte order of the Custom Data
+ * itself), so that programs ignorant of the format of a given
+ * type of Custom Block can still read a block from one file and
+ * write it to another, even if the host doing the writing has
+ * a byte order different from the host that previously wrote
+ * the file.
+ */
+typedef enum {
+ OPT_SECTION_BYTE_ORDER, /* byte order of this section */
+ OPT_BIG_ENDIAN, /* as it says */
+ OPT_LITTLE_ENDIAN /* ditto */
+} pcapng_opt_byte_order_e;
+
+/*
+ * Process the options section of a block. process_option points to
+ * a routine that processes all the block-specific options, i.e.
+ * options other than the end-of-options, comment, and custom
+ * options.
+ */
+WS_DLL_PUBLIC
+gboolean pcapng_process_options(FILE_T fh, wtapng_block_t *wblock,
+ section_info_t *section_info,
+ guint opt_cont_buf_len,
+ gboolean (*process_option)(wtapng_block_t *,
+ const section_info_t *,
+ guint16, guint16,
+ const guint8 *,
+ int *, gchar **),
+ pcapng_opt_byte_order_e byte_order,
+ int *err, gchar **err_info);
+
+/*
+ * Helper routines to process options with types used in more than one
+ * block type.
+ */
+WS_DLL_PUBLIC
+void pcapng_process_uint8_option(wtapng_block_t *wblock,
+ guint16 option_code, guint16 option_length,
+ const guint8 *option_content);
+
+WS_DLL_PUBLIC
+void pcapng_process_uint32_option(wtapng_block_t *wblock,
+ guint16 option_code, guint16 option_length,
+ guint32 option_content);
+
+WS_DLL_PUBLIC
+void pcapng_process_timestamp_option(wtapng_block_t *wblock,
+ const section_info_t *section_info,
+ pcapng_opt_byte_order_e byte_order,
+ guint16 option_code, guint16 option_length,
+ const guint8 *option_content);
+
+WS_DLL_PUBLIC
+void pcapng_process_uint64_option(wtapng_block_t *wblock,
+ const section_info_t *section_info,
+ pcapng_opt_byte_order_e byte_order,
+ guint16 option_code, guint16 option_length,
+ const guint8 *option_content);
+
+WS_DLL_PUBLIC
+void pcapng_process_string_option(wtapng_block_t *wblock, guint16 option_code,
+ guint16 option_length, const guint8 *option_content);
+
+WS_DLL_PUBLIC
+void pcapng_process_bytes_option(wtapng_block_t *wblock, guint16 option_code,
+ guint16 option_length, const guint8 *option_content);
+
#endif /* __PCAP_MODULE_H__ */