diff options
-rw-r--r-- | file.c | 19 | ||||
-rw-r--r-- | frame_tvbuff.c | 4 | ||||
-rw-r--r-- | rawshark.c | 4 | ||||
-rw-r--r-- | reordercap.c | 23 | ||||
-rw-r--r-- | tfshark.c | 4 | ||||
-rw-r--r-- | tshark.c | 4 | ||||
-rw-r--r-- | ui/gtk/packet_list_store.c | 3 | ||||
-rw-r--r-- | ui/proto_hier_stats.c | 3 | ||||
-rw-r--r-- | wiretap/pcapng.c | 206 | ||||
-rw-r--r-- | wiretap/pcapng_module.h | 13 | ||||
-rw-r--r-- | wiretap/wtap.c | 13 | ||||
-rw-r--r-- | wiretap/wtap.h | 37 |
12 files changed, 254 insertions, 79 deletions
@@ -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)) { @@ -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. @@ -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 |