aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--file.c19
-rw-r--r--frame_tvbuff.c4
-rw-r--r--rawshark.c4
-rw-r--r--reordercap.c23
-rw-r--r--tfshark.c4
-rw-r--r--tshark.c4
-rw-r--r--ui/gtk/packet_list_store.c3
-rw-r--r--ui/proto_hier_stats.c3
-rw-r--r--wiretap/pcapng.c206
-rw-r--r--wiretap/pcapng_module.h13
-rw-r--r--wiretap/wtap.c13
-rw-r--r--wiretap/wtap.h37
12 files changed, 254 insertions, 79 deletions
diff --git a/file.c b/file.c
index ba0660efb2..78d0ad34c1 100644
--- a/file.c
+++ b/file.c
@@ -310,6 +310,9 @@ cf_open(capture_file *cf, const char *fname, unsigned int type, gboolean is_temp
and fill in the information for this file. */
cf_close(cf);
+ /* Initialize the packet header. */
+ wtap_phdr_init(&cf->phdr);
+
/* XXX - we really want to initialize this after we've read all
the packets, so we know how much we'll ultimately need. */
ws_buffer_init(&cf->buf, 1500);
@@ -436,6 +439,9 @@ cf_close(capture_file *cf)
/* no open_routine type */
cf->open_type = WTAP_TYPE_AUTO;
+ /* Clean up the packet header. */
+ wtap_phdr_cleanup(&cf->phdr);
+
/* Free up the packet buffer. */
ws_buffer_free(&cf->buf);
@@ -2192,7 +2198,7 @@ process_specified_records(capture_file *cf, packet_range_t *range,
range_process_e process_this;
struct wtap_pkthdr phdr;
- memset(&phdr, 0, sizeof(struct wtap_pkthdr));
+ wtap_phdr_init(&phdr);
ws_buffer_init(&buf, 1500);
/* Update the progress bar when it gets to this value. */
@@ -2290,6 +2296,7 @@ process_specified_records(capture_file *cf, packet_range_t *range,
if (progbar != NULL)
destroy_progress_dlg(progbar);
+ wtap_phdr_cleanup(&phdr);
ws_buffer_free(&buf);
return ret;
@@ -3942,6 +3949,8 @@ cf_get_user_packet_comment(capture_file *cf, const frame_data *fd)
char *
cf_get_comment(capture_file *cf, const frame_data *fd)
{
+ char *comment;
+
/* fetch user comment */
if (fd->flags.has_user_comment)
return g_strdup(cf_get_user_packet_comment(cf, fd));
@@ -3951,14 +3960,16 @@ cf_get_comment(capture_file *cf, const frame_data *fd)
struct wtap_pkthdr phdr; /* Packet header */
Buffer buf; /* Packet data */
- memset(&phdr, 0, sizeof(struct wtap_pkthdr));
-
+ wtap_phdr_init(&phdr);
ws_buffer_init(&buf, 1500);
+
if (!cf_read_record_r(cf, fd, &phdr, &buf))
{ /* XXX, what we can do here? */ }
+ comment = phdr.opt_comment;
+ wtap_phdr_cleanup(&phdr);
ws_buffer_free(&buf);
- return phdr.opt_comment;
+ return comment;
}
return NULL;
}
diff --git a/frame_tvbuff.c b/frame_tvbuff.c
index 71670eb23b..2e3019c7e3 100644
--- a/frame_tvbuff.c
+++ b/frame_tvbuff.c
@@ -74,7 +74,7 @@ frame_cache(struct tvb_frame *frame_tvb)
{
struct wtap_pkthdr phdr; /* Packet header */
- memset(&phdr, 0, sizeof(struct wtap_pkthdr));
+ wtap_phdr_init(&phdr);
if (frame_tvb->buf == NULL) {
frame_tvb->buf = (struct Buffer *) g_malloc(sizeof(struct Buffer));
@@ -87,6 +87,8 @@ frame_cache(struct tvb_frame *frame_tvb)
}
frame_tvb->tvb.real_data = ws_buffer_start_ptr(frame_tvb->buf) + frame_tvb->offset;
+
+ wtap_phdr_cleanup(&phdr);
}
static void
diff --git a/rawshark.c b/rawshark.c
index 8d29f34574..b1e484544b 100644
--- a/rawshark.c
+++ b/rawshark.c
@@ -990,7 +990,7 @@ load_cap_file(capture_file *cf)
struct wtap_pkthdr phdr;
epan_dissect_t edt;
- memset(&phdr, 0, sizeof(phdr));
+ wtap_phdr_init(&phdr);
epan_dissect_init(&edt, cf->epan, TRUE, FALSE);
@@ -1000,6 +1000,8 @@ load_cap_file(capture_file *cf)
epan_dissect_cleanup(&edt);
+ wtap_phdr_cleanup(&phdr);
+
if (err != 0) {
/* Print a message noting that the read failed somewhere along the line. */
switch (err) {
diff --git a/reordercap.c b/reordercap.c
index 09a8dd31b9..90fd84babf 100644
--- a/reordercap.c
+++ b/reordercap.c
@@ -104,21 +104,18 @@ typedef struct FrameRecord_t {
static void
-frame_write(FrameRecord_t *frame, wtap *wth, wtap_dumper *pdh, Buffer *buf,
- const char *infile)
+frame_write(FrameRecord_t *frame, wtap *wth, wtap_dumper *pdh,
+ struct wtap_pkthdr *phdr, Buffer *buf, const char *infile)
{
int err;
gchar *err_info;
- struct wtap_pkthdr phdr;
-
- memset(&phdr, 0, sizeof(struct wtap_pkthdr));
DEBUG_PRINT("\nDumping frame (offset=%" G_GINT64_MODIFIER "u)\n",
frame->offset);
- /* Re-read the first frame from the stored location */
- if (!wtap_seek_read(wth, frame->offset, &phdr, buf, &err, &err_info)) {
+ /* Re-read the frame from the stored location */
+ if (!wtap_seek_read(wth, frame->offset, phdr, buf, &err, &err_info)) {
if (err != 0) {
/* Print a message noting that the read failed somewhere along the line. */
fprintf(stderr,
@@ -138,11 +135,12 @@ frame_write(FrameRecord_t *frame, wtap *wth, wtap_dumper *pdh, Buffer *buf,
}
/* Copy, and set length and timestamp from item. */
- /* TODO: remove when wtap_seek_read() will read phdr */
- phdr.ts = frame->time;
+ /* TODO: remove when wtap_seek_read() fills in phdr,
+ including time stamps, for all file types */
+ phdr->ts = frame->time;
/* Dump frame to outfile */
- if (!wtap_dump(pdh, &phdr, ws_buffer_start_ptr(buf), &err)) {
+ if (!wtap_dump(pdh, phdr, ws_buffer_start_ptr(buf), &err)) {
fprintf(stderr, "reordercap: Error (%s) writing frame to outfile\n",
wtap_strerror(err));
exit(1);
@@ -202,6 +200,7 @@ main(int argc, char *argv[])
GString *runtime_info_str;
wtap *wth = NULL;
wtap_dumper *pdh = NULL;
+ struct wtap_pkthdr dump_phdr;
Buffer buf;
int err;
gchar *err_info;
@@ -360,16 +359,18 @@ main(int argc, char *argv[])
}
/* Write out each sorted frame in turn */
+ wtap_phdr_init(&dump_phdr);
ws_buffer_init(&buf, 1500);
for (i = 0; i < frames->len; i++) {
FrameRecord_t *frame = (FrameRecord_t *)frames->pdata[i];
/* Avoid writing if already sorted and configured to */
if (write_output_regardless || (wrong_order_count > 0)) {
- frame_write(frame, wth, pdh, &buf, infile);
+ frame_write(frame, wth, pdh, &dump_phdr, &buf, infile);
}
g_slice_free(FrameRecord_t, frame);
}
+ wtap_phdr_cleanup(&dump_phdr);
ws_buffer_free(&buf);
if (!write_output_regardless && (wrong_order_count == 0)) {
diff --git a/tfshark.c b/tfshark.c
index ea439d86b7..e41833a88e 100644
--- a/tfshark.c
+++ b/tfshark.c
@@ -1810,7 +1810,7 @@ load_cap_file(capture_file *cf, int max_packet_count, gint64 max_byte_count)
/* Get the union of the flags for all tap listeners. */
tap_flags = union_of_tap_listener_flags();
- memset(&file_phdr, 0, sizeof(file_phdr));
+ wtap_phdr_init(&file_phdr);
/* XXX - TEMPORARY HACK TO ELF DISSECTOR */
file_phdr.pkt_encap = 1234;
@@ -1945,6 +1945,8 @@ load_cap_file(capture_file *cf, int max_packet_count, gint64 max_byte_count)
}
}
+ wtap_phdr_cleanup(&phdr);
+
if (err != 0) {
/*
* Print a message noting that the read failed somewhere along the line.
diff --git a/tshark.c b/tshark.c
index c3218244a8..d3f31f181d 100644
--- a/tshark.c
+++ b/tshark.c
@@ -3072,7 +3072,7 @@ load_cap_file(capture_file *cf, char *save_file, int out_file_type,
Buffer buf;
epan_dissect_t *edt = NULL;
- memset(&phdr, 0, sizeof(struct wtap_pkthdr));
+ wtap_phdr_init(&phdr);
shb_hdr = wtap_file_get_shb_info(cf->wth);
idb_inf = wtap_file_get_idb_info(cf->wth);
@@ -3376,6 +3376,8 @@ load_cap_file(capture_file *cf, char *save_file, int out_file_type,
}
}
+ wtap_phdr_cleanup(&phdr);
+
if (err != 0) {
/*
* Print a message noting that the read failed somewhere along the line.
diff --git a/ui/gtk/packet_list_store.c b/ui/gtk/packet_list_store.c
index 58f9493864..230cb8fbfb 100644
--- a/ui/gtk/packet_list_store.c
+++ b/ui/gtk/packet_list_store.c
@@ -1104,7 +1104,7 @@ packet_list_dissect_and_cache_record(PacketList *packet_list, PacketListRecord *
g_return_if_fail(packet_list);
g_return_if_fail(PACKETLIST_IS_LIST(packet_list));
- memset(&phdr, 0, sizeof(struct wtap_pkthdr));
+ wtap_phdr_init(&phdr);
fdata = record->fdata;
@@ -1175,6 +1175,7 @@ packet_list_dissect_and_cache_record(PacketList *packet_list, PacketListRecord *
record->colorized = TRUE;
epan_dissect_cleanup(&edt);
+ wtap_phdr_cleanup(&phdr);
ws_buffer_free(&buf);
}
diff --git a/ui/proto_hier_stats.c b/ui/proto_hier_stats.c
index 3118003570..85d9188879 100644
--- a/ui/proto_hier_stats.c
+++ b/ui/proto_hier_stats.c
@@ -143,7 +143,7 @@ process_record(frame_data *frame, column_info *cinfo, ph_stats_t* ps)
Buffer buf;
double cur_time;
- memset(&phdr, 0, sizeof(struct wtap_pkthdr));
+ wtap_phdr_init(&phdr);
/* Load the record from the capture file */
ws_buffer_init(&buf, 1500);
@@ -170,6 +170,7 @@ process_record(frame_data *frame, column_info *cinfo, ph_stats_t* ps)
/* Free our memory. */
epan_dissect_cleanup(&edt);
+ wtap_phdr_cleanup(&phdr);
ws_buffer_free(&buf);
return TRUE; /* success */
diff --git a/wiretap/pcapng.c b/wiretap/pcapng.c
index c8d44b3592..3571ca2f74 100644
--- a/wiretap/pcapng.c
+++ b/wiretap/pcapng.c
@@ -418,6 +418,98 @@ register_pcapng_block_type_handler(guint block_type, block_reader read,
(void)g_hash_table_insert(block_handlers, GUINT_TO_POINTER(block_type),
handler);
}
+
+/*
+ * Tables for plugins to handle particular options for particular block
+ * types.
+ *
+ * An option has a handler routine, which is passed an indication of
+ * whether this section of the file is byte-swapped, the length of the
+ * option, the data of the option, a pointer to an error code, and a
+ * pointer to a pointer variable for an error string.
+ *
+ * It checks whether the length and option are valid, and, if they aren't,
+ * returns FALSE, setting the error code to the appropriate error (normally
+ * WTAP_ERR_BAD_FILE) and the error string to an appropriate string
+ * indicating the problem.
+ *
+ * Otherwise, if this section of the file is byte-swapped, it byte-swaps
+ * multi-byte numerical values, so that it's in the host byte order.
+ */
+
+/*
+ * Block types indices in the table of tables of option handlers.
+ *
+ * Block types are not guaranteed to be sequential, so we map the
+ * block types we support to a sequential set. Furthermore, all
+ * packet block types have the same set of options.
+ */
+#define BT_INDEX_SHB 0
+#define BT_INDEX_IDB 1
+#define BT_INDEX_PBS 2 /* all packet blocks */
+#define BT_INDEX_NRB 3
+#define BT_INDEX_ISB 4
+
+#define NUM_BT_INDICES 5
+
+static GHashTable *option_handlers[NUM_BT_INDICES];
+
+void
+register_pcapng_option_handler(guint block_type, guint option_code,
+ option_handler handler)
+{
+ guint bt_index;
+
+ switch (block_type) {
+
+ case BLOCK_TYPE_SHB:
+ bt_index = BT_INDEX_SHB;
+ break;
+
+ case BLOCK_TYPE_IDB:
+ bt_index = BT_INDEX_IDB;
+ break;
+
+ case BLOCK_TYPE_PB:
+ case BLOCK_TYPE_EPB:
+ case BLOCK_TYPE_SPB:
+ bt_index = BT_INDEX_PBS;
+ break;
+
+ case BLOCK_TYPE_NRB:
+ bt_index = BT_INDEX_NRB;
+ break;
+
+ case BLOCK_TYPE_ISB:
+ bt_index = BT_INDEX_ISB;
+ break;
+
+ default:
+ /*
+ * This is a block type we don't process; either we ignore it,
+ * in which case the options don't get processed, or there's
+ * a plugin routine to handle it, in which case that routine
+ * will do the option processing itself.
+ *
+ * XXX - report an error?
+ */
+ return;
+ }
+
+ if (option_handlers[bt_index] == NULL) {
+ /*
+ * Create the table of option handlers for this block type.
+ *
+ * XXX - there's no "g_uint_hash()" or "g_uint_equal()",
+ * so we use "g_direct_hash()" and "g_direct_equal()".
+ */
+ option_handlers[bt_index] = g_hash_table_new_full(g_direct_hash,
+ g_direct_equal,
+ NULL, g_free);
+ }
+ (void)g_hash_table_insert(option_handlers[bt_index],
+ GUINT_TO_POINTER(option_code), handler);
+}
#endif /* HAVE_PLUGINS */
static int
@@ -1003,10 +1095,14 @@ pcapng_read_packet_block(FILE_T fh, pcapng_block_header_t *bh, pcapng_t *pn, wta
guint32 padding;
interface_info_t iface_info;
guint64 ts;
- pcapng_option_header_t oh;
+ guint8 *opt_ptr;
+ pcapng_option_header_t *oh;
+ guint8 *option_content;
int pseudo_header_len;
- char *option_content = NULL; /* Allocate as large as the options block */
int fcslen;
+#ifdef HAVE_PLUGINS
+ option_handler handler;
+#endif
/* Don't try to allocate memory for a huge number of options, as
that might fail and, even if it succeeds, it might not leave
@@ -1232,24 +1328,24 @@ pcapng_read_packet_block(FILE_T fh, pcapng_block_header_t *bh, pcapng_t *pn, wta
/* Allocate enough memory to hold all options */
opt_cont_buf_len = to_read;
- option_content = (char *)g_try_malloc(opt_cont_buf_len);
- if (opt_cont_buf_len != 0 && option_content == NULL) {
- *err = ENOMEM; /* we assume we're out of memory */
- return FALSE;
- }
+ ws_buffer_assure_space(&wblock->packet_header->ft_specific_data, opt_cont_buf_len);
+ opt_ptr = ws_buffer_start_ptr(&wblock->packet_header->ft_specific_data);
while (to_read != 0) {
/* read option */
- bytes_read = pcapng_read_option(fh, pn, &oh, option_content, opt_cont_buf_len, to_read, err, err_info);
+ oh = (pcapng_option_header_t *)(void *)opt_ptr;
+ option_content = opt_ptr + sizeof (pcapng_option_header_t);
+ bytes_read = pcapng_read_option(fh, pn, oh, option_content, opt_cont_buf_len, to_read, err, err_info);
if (bytes_read <= 0) {
pcapng_debug0("pcapng_read_packet_block: failed to read option");
+ /* XXX - free anything? */
return FALSE;
}
block_read += bytes_read;
to_read -= bytes_read;
/* handle option content */
- switch (oh.option_code) {
+ switch (oh->option_code) {
case(OPT_EOFOPT):
if (to_read != 0) {
pcapng_debug1("pcapng_read_packet_block: %u bytes after opt_endofopt", to_read);
@@ -1258,59 +1354,81 @@ pcapng_read_packet_block(FILE_T fh, pcapng_block_header_t *bh, pcapng_t *pn, wta
to_read = 0;
break;
case(OPT_COMMENT):
- if (oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
+ if (oh->option_length > 0 && oh->option_length < opt_cont_buf_len) {
wblock->packet_header->presence_flags |= WTAP_HAS_COMMENTS;
- wblock->packet_header->opt_comment = g_strndup(option_content, oh.option_length);
- pcapng_debug2("pcapng_read_packet_block: length %u opt_comment '%s'", oh.option_length, wblock->packet_header->opt_comment);
+ wblock->packet_header->opt_comment = g_strndup(option_content, oh->option_length);
+ pcapng_debug2("pcapng_read_packet_block: length %u opt_comment '%s'", oh->option_length, wblock->packet_header->opt_comment);
} else {
- pcapng_debug1("pcapng_read_packet_block: opt_comment length %u seems strange", oh.option_length);
+ pcapng_debug1("pcapng_read_packet_block: opt_comment length %u seems strange", oh->option_length);
}
break;
case(OPT_EPB_FLAGS):
- if (oh.option_length == 4) {
- /* Don't cast a char[] into a guint32--the
- * char[] may not be aligned correctly.
- */
- wblock->packet_header->presence_flags |= WTAP_HAS_PACK_FLAGS;
- memcpy(&wblock->packet_header->pack_flags, option_content, sizeof(guint32));
- if (pn->byte_swapped)
- wblock->packet_header->pack_flags = GUINT32_SWAP_LE_BE(wblock->packet_header->pack_flags);
- if (wblock->packet_header->pack_flags & 0x000001E0) {
- /* The FCS length is present */
- fcslen = (wblock->packet_header->pack_flags & 0x000001E0) >> 5;
- }
- pcapng_debug1("pcapng_read_packet_block: pack_flags %u (ignored)", wblock->packet_header->pack_flags);
- } else {
- pcapng_debug1("pcapng_read_packet_block: pack_flags length %u not 4 as expected", oh.option_length);
+ if (oh->option_length != 4) {
+ *err = WTAP_ERR_BAD_FILE;
+ *err_info = g_strdup_printf("pcapng: packet block flags option length %u is not 4",
+ oh->option_length);
+ /* XXX - free anything? */
+ return FALSE;
+ }
+ /* Don't cast a char[] into a guint32--the
+ * char[] may not be aligned correctly.
+ */
+ wblock->packet_header->presence_flags |= WTAP_HAS_PACK_FLAGS;
+ memcpy(&wblock->packet_header->pack_flags, option_content, sizeof(guint32));
+ if (pn->byte_swapped) {
+ wblock->packet_header->pack_flags = GUINT32_SWAP_LE_BE(wblock->packet_header->pack_flags);
+ memcpy(option_content, &wblock->packet_header->pack_flags, sizeof(guint32));
+ }
+ if (wblock->packet_header->pack_flags & 0x000001E0) {
+ /* The FCS length is present */
+ fcslen = (wblock->packet_header->pack_flags & 0x000001E0) >> 5;
}
+ pcapng_debug1("pcapng_read_packet_block: pack_flags %u (ignored)", wblock->packet_header->pack_flags);
break;
case(OPT_EPB_HASH):
pcapng_debug2("pcapng_read_packet_block: epb_hash %u currently not handled - ignoring %u bytes",
- oh.option_code, oh.option_length);
+ oh->option_code, oh->option_length);
break;
case(OPT_EPB_DROPCOUNT):
- if (oh.option_length == 8) {
- /* Don't cast a char[] into a guint32--the
- * char[] may not be aligned correctly.
- */
- wblock->packet_header->presence_flags |= WTAP_HAS_DROP_COUNT;
- memcpy(&wblock->packet_header->drop_count, option_content, sizeof(guint64));
- if (pn->byte_swapped)
- wblock->packet_header->drop_count = GUINT64_SWAP_LE_BE(wblock->packet_header->drop_count);
-
- pcapng_debug1("pcapng_read_packet_block: drop_count %" G_GINT64_MODIFIER "u", wblock->packet_header->drop_count);
- } else {
- pcapng_debug1("pcapng_read_packet_block: drop_count length %u not 8 as expected", oh.option_length);
+ if (oh->option_length != 8) {
+ *err = WTAP_ERR_BAD_FILE;
+ *err_info = g_strdup_printf("pcapng: packet block drop count option length %u is not 8",
+ oh->option_length);
+ /* XXX - free anything? */
+ return FALSE;
}
+ /* Don't cast a char[] into a guint64--the
+ * char[] may not be aligned correctly.
+ */
+ wblock->packet_header->presence_flags |= WTAP_HAS_DROP_COUNT;
+ memcpy(&wblock->packet_header->drop_count, option_content, sizeof(guint64));
+ if (pn->byte_swapped) {
+ wblock->packet_header->drop_count = GUINT64_SWAP_LE_BE(wblock->packet_header->drop_count);
+ memcpy(option_content, &wblock->packet_header->drop_count, sizeof(guint64));
+ }
+
+ pcapng_debug1("pcapng_read_packet_block: drop_count %" G_GINT64_MODIFIER "u", wblock->packet_header->drop_count);
break;
default:
+#ifdef HAVE_PLUGINS
+ /*
+ * Do we have a handler for this packet block option code?
+ */
+ handler = (option_handler)g_hash_table_lookup(option_handlers[BT_INDEX_PBS],
+ GUINT_TO_POINTER(oh->option_code));
+ if (handler != NULL) {
+ /* Yes - call the handler. */
+ if (!handler(pn->byte_swapped, oh->option_length,
+ option_content, err, err_info))
+ /* XXX - free anything? */
+ return FALSE;
+ } else
+#endif
pcapng_debug2("pcapng_read_packet_block: unknown option %u - ignoring %u bytes",
- oh.option_code, oh.option_length);
+ oh->option_code, oh->option_length);
}
}
- g_free(option_content);
-
pcap_read_post_process(WTAP_FILE_TYPE_SUBTYPE_PCAPNG, iface_info.wtap_encap,
wblock->packet_header, ws_buffer_start_ptr(wblock->frame_buffer),
pn->byte_swapped, fcslen);
diff --git a/wiretap/pcapng_module.h b/wiretap/pcapng_module.h
index 226a8dd7b1..ef5701678b 100644
--- a/wiretap/pcapng_module.h
+++ b/wiretap/pcapng_module.h
@@ -36,5 +36,18 @@ WS_DLL_PUBLIC
void register_pcapng_block_type_handler(guint block_type, block_reader read,
block_writer write);
+/*
+ * Handler routine for pcap-ng option type.
+ */
+typedef gboolean (*option_handler)(gboolean, guint, guint8 *, int *, gchar **);
+
+/*
+ * Register a handler for a pcap-ng option code for a particular block
+ * type.
+ */
+WS_DLL_PUBLIC
+void register_pcapng_option_handler(guint block_type, guint option_code,
+ option_handler handle);
+
#endif /* __PCAP_MODULE_H__ */
diff --git a/wiretap/wtap.c b/wiretap/wtap.c
index 88b587e12a..e8726e280d 100644
--- a/wiretap/wtap.c
+++ b/wiretap/wtap.c
@@ -1179,6 +1179,19 @@ wtap_buf_ptr(wtap *wth)
return ws_buffer_start_ptr(wth->frame_buffer);
}
+void
+wtap_phdr_init(struct wtap_pkthdr *phdr)
+{
+ memset(phdr, 0, sizeof(struct wtap_pkthdr));
+ ws_buffer_init(&phdr->ft_specific_data, 0);
+}
+
+void
+wtap_phdr_cleanup(struct wtap_pkthdr *phdr)
+{
+ ws_buffer_free(&phdr->ft_specific_data);
+}
+
gboolean
wtap_seek_read(wtap *wth, gint64 seek_off,
struct wtap_pkthdr *phdr, Buffer *buf, int *err, gchar **err_info)
diff --git a/wiretap/wtap.h b/wiretap/wtap.h
index 26c6c9e477..55b35448c3 100644
--- a/wiretap/wtap.h
+++ b/wiretap/wtap.h
@@ -1007,20 +1007,21 @@ union wtap_pseudo_header {
#define REC_TYPE_FT_SPECIFIC_REPORT 2 /**< file-type-specific report */
struct wtap_pkthdr {
- guint rec_type; /* what type of record is this? */
- guint32 presence_flags; /* what stuff do we have? */
- nstime_t ts;
- guint32 caplen; /* data length in the file */
- guint32 len; /* data length on the wire */
- int pkt_encap; /* WTAP_ENCAP_ value for this packet */
- int pkt_tsprec; /* WTAP_TSPREC_ value for this packet */
- /* pcapng variables */
- guint32 interface_id; /* identifier of the interface. */
- /* options */
- gchar *opt_comment; /* NULL if not available */
- guint64 drop_count; /* number of packets lost (by the interface and the
- operating system) between this packet and the preceding one. */
- guint32 pack_flags; /* XXX - 0 for now (any value for "we don't have it"?) */
+ guint rec_type; /* what type of record is this? */
+ guint32 presence_flags; /* what stuff do we have? */
+ nstime_t ts; /* time stamp */
+ guint32 caplen; /* data length in the file */
+ guint32 len; /* data length on the wire */
+ int pkt_encap; /* WTAP_ENCAP_ value for this packet */
+ int pkt_tsprec; /* WTAP_TSPREC_ value for this packet */
+ /* pcapng variables */
+ guint32 interface_id; /* identifier of the interface. */
+ /* options */
+ gchar *opt_comment; /* NULL if not available */
+ guint64 drop_count; /* number of packets lost (by the interface and the
+ operating system) between this packet and the preceding one. */
+ guint32 pack_flags; /* XXX - 0 for now (any value for "we don't have it"?) */
+ Buffer ft_specific_data; /* file-type specific data */
union wtap_pseudo_header pseudo_header;
};
@@ -1464,6 +1465,14 @@ struct wtap_pkthdr *wtap_phdr(wtap *wth);
WS_DLL_PUBLIC
guint8 *wtap_buf_ptr(wtap *wth);
+/*** initialize a wtap_pkthdr structure ***/
+WS_DLL_PUBLIC
+void wtap_phdr_init(struct wtap_pkthdr *phdr);
+
+/*** clean up a wtap_pkthdr structure, freeing what wtap_phdr_init() allocated */
+WS_DLL_PUBLIC
+void wtap_phdr_cleanup(struct wtap_pkthdr *phdr);
+
/*** get various information snippets about the current file ***/
/** Return an approximation of the amount of data we've read sequentially