wiretap: Generate IDBs from packets when necessary
Add a routine to generate a dummy IDB from a packet record. When pcapng is writing enhanced packet blocks and the source doesn't provide an interface id, search through the list of intereface ids for a match. If there isn't one, generate a new one and use it. This allows pcapng to write per-packet encapsulation when the source doesn't provide IDBs.
This commit is contained in:
parent
9d6b2f5d8a
commit
f4723eeb7e
@ -2337,11 +2337,13 @@ wtap_dump_init_dumper(int file_type_subtype, wtap_compression_type compression_t
|
|||||||
* means that there are no interfaces, or they will be
|
* means that there are no interfaces, or they will be
|
||||||
* provided later when reading the file in single-pass mode.)
|
* provided later when reading the file in single-pass mode.)
|
||||||
*
|
*
|
||||||
|
* For WTAP_ENCAP_PER_PACKET, we'll have to generate IDBs
|
||||||
|
* from packet records as they come in. (pcapng does this now.)
|
||||||
|
*
|
||||||
* XXX File types should provide their own IDBs (possibly
|
* XXX File types should provide their own IDBs (possibly
|
||||||
* fake ones generated by wtap_add_generated_idb()), in
|
* fake ones generated by wtap_add_generated_idb()), in
|
||||||
* order to support being used as inputs for mergecap where
|
* order to support being used as inputs for mergecap where
|
||||||
* pcapng is the output. This doesn't work for files with
|
* pcapng is the output.
|
||||||
* WTAP_ENCAP_PER_PACKET.
|
|
||||||
*/
|
*/
|
||||||
descr = wtap_dump_params_generate_idb(params);
|
descr = wtap_dump_params_generate_idb(params);
|
||||||
g_array_append_val(wdh->interface_data, descr);
|
g_array_append_val(wdh->interface_data, descr);
|
||||||
|
@ -53,6 +53,9 @@ pcapng_close(wtap *wth);
|
|||||||
static gboolean
|
static gboolean
|
||||||
pcapng_encap_is_ft_specific(int encap);
|
pcapng_encap_is_ft_specific(int encap);
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
pcapng_write_if_descr_block(wtap_dumper *wdh, wtap_block_t int_data, int *err);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Minimum block size = size of block header + size of block trailer.
|
* Minimum block size = size of block header + size of block trailer.
|
||||||
*/
|
*/
|
||||||
@ -4944,28 +4947,39 @@ pcapng_write_enhanced_packet_block(wtap_dumper *wdh, const wtap_rec *rec,
|
|||||||
options_size = compute_options_size(rec->block, compute_epb_option_size);
|
options_size = compute_options_size(rec->block, compute_epb_option_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* write (enhanced) packet block header */
|
/*
|
||||||
bh.block_type = BLOCK_TYPE_EPB;
|
* Check the interface ID. Do this before writing the header,
|
||||||
bh.block_total_length = (guint32)sizeof(bh) + (guint32)sizeof(epb) + phdr_len + rec->rec_header.packet_header.caplen + pad_len + options_total_length + options_size + 4;
|
* in case we need to add a new IDB.
|
||||||
|
*/
|
||||||
if (!wtap_dump_file_write(wdh, &bh, sizeof bh, err))
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
/* write block fixed content */
|
|
||||||
if (rec->presence_flags & WTAP_HAS_INTERFACE_ID)
|
if (rec->presence_flags & WTAP_HAS_INTERFACE_ID)
|
||||||
epb.interface_id = rec->rec_header.packet_header.interface_id;
|
epb.interface_id = rec->rec_header.packet_header.interface_id;
|
||||||
else {
|
else {
|
||||||
/*
|
/*
|
||||||
* XXX - we should support writing WTAP_ENCAP_PER_PACKET
|
* The source isn't sending us IDBs. See if we already have a
|
||||||
* data to pcapng files even if we *don't* have interface
|
* matching interface, and use it if so.
|
||||||
* IDs.
|
|
||||||
*/
|
*/
|
||||||
epb.interface_id = 0;
|
for (epb.interface_id = 0; epb.interface_id < wdh->interface_data->len; ++epb.interface_id) {
|
||||||
|
int_data = g_array_index(wdh->interface_data, wtap_block_t,
|
||||||
|
epb.interface_id);
|
||||||
|
int_data_mand = (wtapng_if_descr_mandatory_t*)wtap_block_get_mandatory_data(int_data);
|
||||||
|
if (int_data_mand->wtap_encap == rec->rec_header.packet_header.pkt_encap) {
|
||||||
|
if (int_data_mand->tsprecision == rec->tsprec || (!(rec->presence_flags & WTAP_HAS_TS))) {
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (epb.interface_id == wdh->interface_data->len) {
|
||||||
/*
|
/*
|
||||||
* Split the 64-bit timestamp into two 32-bit pieces, using
|
* We don't have a matching IDB. Generate a new one
|
||||||
* the time stamp resolution for the interface.
|
* and write it to the file.
|
||||||
*/
|
*/
|
||||||
|
int_data = wtap_rec_generate_idb(rec);
|
||||||
|
g_array_append_val(wdh->interface_data, int_data);
|
||||||
|
if (!pcapng_write_if_descr_block(wdh, int_data, err)) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
if (epb.interface_id >= wdh->interface_data->len) {
|
if (epb.interface_id >= wdh->interface_data->len) {
|
||||||
/*
|
/*
|
||||||
* Our caller is doing something bad.
|
* Our caller is doing something bad.
|
||||||
@ -4989,6 +5003,19 @@ pcapng_write_enhanced_packet_block(wtap_dumper *wdh, const wtap_rec *rec,
|
|||||||
rec->rec_header.packet_header.pkt_encap);
|
rec->rec_header.packet_header.pkt_encap);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* write (enhanced) packet block header */
|
||||||
|
bh.block_type = BLOCK_TYPE_EPB;
|
||||||
|
bh.block_total_length = (guint32)sizeof(bh) + (guint32)sizeof(epb) + phdr_len + rec->rec_header.packet_header.caplen + pad_len + options_total_length + options_size + 4;
|
||||||
|
|
||||||
|
if (!wtap_dump_file_write(wdh, &bh, sizeof bh, err))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
/* write block fixed content */
|
||||||
|
/*
|
||||||
|
* Split the 64-bit timestamp into two 32-bit pieces, using
|
||||||
|
* the time stamp resolution for the interface.
|
||||||
|
*/
|
||||||
ts = ((guint64)rec->ts.secs) * int_data_mand->time_units_per_second +
|
ts = ((guint64)rec->ts.secs) * int_data_mand->time_units_per_second +
|
||||||
(((guint64)rec->ts.nsecs) * int_data_mand->time_units_per_second) / 1000000000;
|
(((guint64)rec->ts.nsecs) * int_data_mand->time_units_per_second) / 1000000000;
|
||||||
epb.timestamp_high = (guint32)(ts >> 32);
|
epb.timestamp_high = (guint32)(ts >> 32);
|
||||||
|
@ -402,8 +402,33 @@ GArray* wtap_file_get_shb_for_new_file(wtap *wth);
|
|||||||
WS_DLL_PUBLIC
|
WS_DLL_PUBLIC
|
||||||
void wtap_add_generated_idb(wtap *wth);
|
void wtap_add_generated_idb(wtap *wth);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Generate an IDB, given a set of dump parameters, using the
|
||||||
|
* parameters' encapsulation type, snapshot length, and time stamp
|
||||||
|
* resolution. For use when a dump file has a given encapsulation type,
|
||||||
|
* and the source is not passing IDBs.
|
||||||
|
* @note This requires that the encapsulation type and time stamp
|
||||||
|
* resolution not be per-packet; it will terminate the process
|
||||||
|
* if either of them are.
|
||||||
|
*
|
||||||
|
* @param params The wtap dump parameters.
|
||||||
|
*/
|
||||||
|
|
||||||
wtap_block_t wtap_dump_params_generate_idb(const wtap_dump_params *params);
|
wtap_block_t wtap_dump_params_generate_idb(const wtap_dump_params *params);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Generate an IDB, given a packet record, using the records's
|
||||||
|
* encapsulation type and time stamp resolution, and the default
|
||||||
|
* snap length for the encapsulation type. For use when a file has
|
||||||
|
* per-packet encapsulation, and the source is not passing along IDBs.
|
||||||
|
* @note This requires that the record type be REC_TYPE_PACKET, and the
|
||||||
|
* encapsulation type and time stamp resolution not be per-packet;
|
||||||
|
* it will terminate the process if any of them are.
|
||||||
|
*
|
||||||
|
* @param rec The packet record.
|
||||||
|
*/
|
||||||
|
wtap_block_t wtap_rec_generate_idb(const wtap_rec *rec);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Gets new name resolution info for new file, based on existing info.
|
* @brief Gets new name resolution info for new file, based on existing info.
|
||||||
* @details Creates a new wtap_block_t of name resolution info and only
|
* @details Creates a new wtap_block_t of name resolution info and only
|
||||||
|
@ -1822,6 +1822,20 @@ wtap_rec_cleanup(wtap_rec *rec)
|
|||||||
ws_buffer_free(&rec->options_buf);
|
ws_buffer_free(&rec->options_buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wtap_block_t
|
||||||
|
wtap_rec_generate_idb(const wtap_rec *rec)
|
||||||
|
{
|
||||||
|
int tsprec;
|
||||||
|
ws_assert(rec->rec_type == REC_TYPE_PACKET);
|
||||||
|
if (rec->presence_flags & WTAP_HAS_TS) {
|
||||||
|
tsprec = rec->tsprec;
|
||||||
|
} else {
|
||||||
|
tsprec = WTAP_TSPREC_USEC;
|
||||||
|
/* The default */
|
||||||
|
}
|
||||||
|
return wtap_generate_idb(rec->rec_header.packet_header.pkt_encap, tsprec, 0);
|
||||||
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
wtap_seek_read(wtap *wth, gint64 seek_off, wtap_rec *rec, Buffer *buf,
|
wtap_seek_read(wtap *wth, gint64 seek_off, wtap_rec *rec, Buffer *buf,
|
||||||
int *err, gchar **err_info)
|
int *err, gchar **err_info)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user