wiretap: eliminate the pcap/nspcap/pcapng WTAP_FILE_TYPE_SUBTYPE_ values.

Register the pcap and pcapng file types/subtypes rather than hardwiring
them into the table.

Call the registration routines for them directly, rather than through a
generated table; they're always supposed to be there, as some code in
Wireshark either writes only one of those formats or defaults to writing
one of those formats.  Don't run their source code through the
registration-routine-finder script.

Have the file type/subtype codes for them be directly exported to the
libwiretap core, and provide routines to return each of them, to be used
by the aforementioned code.

When reporting errors with cfile_write_failure_message(), use
wtap_dump_file_type_subtype() to get the file type/subtype value for the
wtap_dumper to which we're writing, rather than hardcoding it.

Have the "export PDU" code capable of supporting arbitrary file
types/subtypes, although we currently only use pcapng.

Get rid of declarations of now-static can_write_encap and
dump_open routines in various headers.
This commit is contained in:
Guy Harris 2021-02-23 01:18:31 -08:00
parent 3742f921b2
commit 166159f15d
30 changed files with 856 additions and 482 deletions

View File

@ -130,6 +130,9 @@ libwiretap.so.0 libwiretap0 #MINVER#
wtap_opttypes_initialize@Base 2.1.2
wtap_opttypes_cleanup@Base 2.3.0
wtap_pcap_encap_to_wtap_encap@Base 1.9.1
wtap_pcap_file_type_subtype@Base 3.5.0
wtap_pcap_nsec_file_type_subtype@Base 3.5.0
wtap_pcapng_file_type_subtype@Base 3.5.0
wtap_plugins_supported@Base 3.5.0
wtap_read@Base 1.9.1
wtap_read_bytes@Base 1.99.1

View File

@ -161,7 +161,7 @@ GPtrArray *capture_comments = NULL;
static struct select_item selectfrm[MAX_SELECTIONS];
static guint max_selected = 0;
static gboolean keep_em = FALSE;
static int out_file_type_subtype = WTAP_FILE_TYPE_SUBTYPE_PCAPNG; /* default to pcapng */
static int out_file_type_subtype = WTAP_FILE_TYPE_SUBTYPE_UNKNOWN;
static int out_frame_type = -2; /* Leave frame type alone */
static gboolean verbose = FALSE; /* Not so verbose */
static struct time_adjustment time_adj = {NSTIME_INIT_ZERO, 0}; /* no adjustment */
@ -1512,7 +1512,11 @@ main(int argc, char *argv[])
print_usage(stderr);
ret = INVALID_OPTION;
goto clean_exit;
}
if (out_file_type_subtype == WTAP_FILE_TYPE_SUBTYPE_UNKNOWN) {
/* default to pcapng */
out_file_type_subtype = wtap_pcapng_file_type_subtype();
}
if (err_prob >= 0.0) {

View File

@ -57,7 +57,7 @@ proto_reg_handoff_pcapng_block(void)
pcapng_block_handle = create_dissector_handle(dissect_pcapng_block,
proto_pcapng_block);
dissector_add_uint("wtap_fts_rec", WTAP_FILE_TYPE_SUBTYPE_PCAPNG,
dissector_add_uint("wtap_fts_rec", wtap_pcapng_file_type_subtype(),
pcapng_block_handle);
}

View File

@ -1165,7 +1165,7 @@ snort_dissector(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data
params.encap = pinfo->rec->rec_header.packet_header.pkt_encap;
params.snaplen = WTAP_MAX_PACKET_SIZE_STANDARD;
current_session.pdh = wtap_dump_fdopen(current_session.in,
WTAP_FILE_TYPE_SUBTYPE_PCAP,
wtap_pcap_file_type_subtype(),
WTAP_UNCOMPRESSED,
&params,
&open_err,

View File

@ -210,7 +210,7 @@ WSLUA_CONSTRUCTOR Dumper_new(lua_State* L) {
#define WSLUA_OPTARG_Dumper_new_ENCAP 3 /* The encapsulation to be used in the file to be created - a number entry from the `wtap_encaps` table in `init.lua`. */
Dumper d;
const char* fname = luaL_checkstring(L,WSLUA_ARG_Dumper_new_FILENAME);
int filetype = (int)luaL_optinteger(L,WSLUA_OPTARG_Dumper_new_FILETYPE,WTAP_FILE_TYPE_SUBTYPE_PCAP);
int filetype = (int)luaL_optinteger(L,WSLUA_OPTARG_Dumper_new_FILETYPE,wtap_pcap_file_type_subtype());
int encap = (int)luaL_optinteger(L,WSLUA_OPTARG_Dumper_new_ENCAP,WTAP_ENCAP_ETHERNET);
int err = 0;
gchar *err_info = NULL;
@ -414,7 +414,7 @@ WSLUA_METHOD Dumper_new_for_current(lua_State* L) {
#define WSLUA_OPTARG_Dumper_new_for_current_FILETYPE 2 /* The file type. Defaults to pcap. */
Dumper d;
const char* fname = luaL_checkstring(L,1);
int filetype = (int)luaL_optinteger(L,WSLUA_OPTARG_Dumper_new_for_current_FILETYPE,WTAP_FILE_TYPE_SUBTYPE_PCAP);
int filetype = (int)luaL_optinteger(L,WSLUA_OPTARG_Dumper_new_for_current_FILETYPE,wtap_pcap_file_type_subtype());
int encap;
int err = 0;
gchar *err_info = NULL;

View File

@ -95,7 +95,7 @@ WSLUA_FUNCTION wslua_wtap_pcap_file_type_subtype(lua_State* LS) {
@since 3.2.12, 3.4.4
*/
lua_Number filetype = WTAP_FILE_TYPE_SUBTYPE_PCAP;
lua_Number filetype = wtap_pcap_file_type_subtype();
lua_pushnumber(LS,filetype);
WSLUA_RETURN(1); /* The filetype value for pcap files. */
}
@ -106,7 +106,7 @@ WSLUA_FUNCTION wslua_wtap_pcap_nsec_file_type_subtype(lua_State* LS) {
@since 3.2.12, 3.4.4
*/
lua_Number filetype = WTAP_FILE_TYPE_SUBTYPE_PCAP_NSEC;
lua_Number filetype = wtap_pcap_nsec_file_type_subtype();
lua_pushnumber(LS,filetype);
WSLUA_RETURN(1); /* The filetype value for nanosecond-resolution pcap files. */
}
@ -117,7 +117,7 @@ WSLUA_FUNCTION wslua_wtap_pcapng_file_type_subtype(lua_State* LS) {
@since 3.2.12, 3.4.4
*/
lua_Number filetype = WTAP_FILE_TYPE_SUBTYPE_PCAPNG;
lua_Number filetype = wtap_pcapng_file_type_subtype();
lua_pushnumber(LS,filetype);
WSLUA_RETURN(1); /* The filetype value for pcapng files. */
}

View File

@ -448,6 +448,7 @@ static struct extcap_dumper extcap_dumper_open(char *fifo, int encap) {
}
#else
wtap_dump_params params = WTAP_DUMP_PARAMS_INIT;
int file_type_subtype;
int err = 0;
gchar *err_info = NULL;
@ -455,14 +456,15 @@ static struct extcap_dumper extcap_dumper_open(char *fifo, int encap) {
params.encap = encap;
params.snaplen = PACKET_LENGTH;
extcap_dumper.dumper.wtap = wtap_dump_open(fifo, WTAP_FILE_TYPE_SUBTYPE_PCAP_NSEC, WTAP_UNCOMPRESSED, &params, &err, &err_info);
file_type_subtype = wtap_pcap_nsec_file_type_subtype();
extcap_dumper.dumper.wtap = wtap_dump_open(fifo, file_type_subtype, WTAP_UNCOMPRESSED, &params, &err, &err_info);
if (!extcap_dumper.dumper.wtap) {
cfile_dump_open_failure_message("androiddump", fifo, err, err_info, WTAP_FILE_TYPE_SUBTYPE_PCAP_NSEC);
cfile_dump_open_failure_message("androiddump", fifo, err, err_info, file_type_subtype);
exit(EXIT_CODE_CANNOT_SAVE_WIRETAP_DUMP);
}
extcap_dumper.encap = encap;
if (!wtap_dump_flush(extcap_dumper.dumper.wtap, &err)) {
cfile_dump_open_failure_message("androiddump", fifo, err, NULL, WTAP_FILE_TYPE_SUBTYPE_PCAP_NSEC);
cfile_dump_open_failure_message("androiddump", fifo, err, NULL, file_type_subtype);
exit(EXIT_CODE_CANNOT_SAVE_WIRETAP_DUMP);
}
#endif
@ -520,14 +522,14 @@ static gboolean extcap_dumper_dump(struct extcap_dumper extcap_dumper,
rec.rec_header.packet_header.pkt_encap = extcap_dumper.encap;
if (!wtap_dump(extcap_dumper.dumper.wtap, &rec, (const guint8 *) buffer, &err, &err_info)) {
cfile_write_failure_message("androiddump", NULL, fifo, err, err_info,
0, WTAP_FILE_TYPE_SUBTYPE_PCAP_NSEC);
cfile_write_failure_message("androiddump", NULL, fifo, err, err_info, 0,
wtap_dump_file_type_subtype(extcap_dumper.dumper.wtap));
return FALSE;
}
if (!wtap_dump_flush(extcap_dumper.dumper.wtap, &err)) {
cfile_write_failure_message("androiddump", NULL, fifo, err, NULL,
0, WTAP_FILE_TYPE_SUBTYPE_PCAP_NSEC);
cfile_write_failure_message("androiddump", NULL, fifo, err, NULL, 0,
wtap_dump_file_type_subtype(extcap_dumper.dumper.wtap));
return FALSE;
}
#endif

View File

@ -192,7 +192,7 @@ wtap_dumper* etw_dump_open(const char* pcapng_filename, int* err, gchar** err_in
params.shb_hdrs = shb_hdrs;
params.idb_inf = idb_info;
pdh = wtap_dump_open(pcapng_filename, WTAP_FILE_TYPE_SUBTYPE_PCAPNG, WTAP_UNCOMPRESSED, &params, err, err_info);
pdh = wtap_dump_open(pcapng_filename, wtap_pcapng_file_type_subtype(), WTAP_UNCOMPRESSED, &params, err, err_info);
if (shb_hdrs)
{

View File

@ -216,7 +216,7 @@ main(int argc, char *argv[])
gboolean verbose = FALSE;
int in_file_count = 0;
guint32 snaplen = 0;
int file_type = WTAP_FILE_TYPE_SUBTYPE_PCAPNG; /* default to pcapng format */
int file_type = WTAP_FILE_TYPE_SUBTYPE_UNKNOWN;
int err = 0;
gchar *err_info = NULL;
int err_fileno;
@ -327,6 +327,10 @@ main(int argc, char *argv[])
}
}
/* Default to pcapng when writing. */
if (file_type == WTAP_FILE_TYPE_SUBTYPE_UNKNOWN)
file_type = wtap_pcapng_file_type_subtype();
cb.callback_func = merge_callback;
cb.data = NULL;
@ -345,9 +349,13 @@ main(int argc, char *argv[])
return 1;
}
/* setting IDB merge mode must use PCAPNG output */
if (mode != IDB_MERGE_MODE_MAX && file_type != WTAP_FILE_TYPE_SUBTYPE_PCAPNG) {
fprintf(stderr, "The IDB merge mode can only be used with PCAPNG output format\n");
/*
* Setting IDB merge mode must use a file format that supports
* (and thus requires) interface ID and information blocks.
*/
if (mode != IDB_MERGE_MODE_MAX &&
wtap_file_type_subtype_supports_block(file_type, WTAP_BLOCK_IF_ID_AND_INFO) == BLOCK_NOT_SUPPORTED) {
fprintf(stderr, "The IDB merge mode can only be used with an output format that identifies interfaces\n");
status = MERGE_ERR_INVALID_OPTION;
goto clean_exit;
}

View File

@ -622,14 +622,14 @@ void randpkt_loop(randpkt_example* example, guint64 produce_count, guint64 packe
if (!wtap_dump(example->dump, rec, buffer, &err, &err_info)) {
cfile_write_failure_message("randpkt", NULL,
example->filename, err, err_info, 0,
WTAP_FILE_TYPE_SUBTYPE_PCAP);
wtap_dump_file_type_subtype(example->dump));
}
if (packet_delay_ms) {
g_usleep(1000 * (gulong)packet_delay_ms);
if (!wtap_dump_flush(example->dump, &err)) {
cfile_write_failure_message("randpkt", NULL,
example->filename, err, NULL, 0,
WTAP_FILE_TYPE_SUBTYPE_PCAP);
wtap_dump_file_type_subtype(example->dump));
}
}
}
@ -661,6 +661,7 @@ int randpkt_example_init(randpkt_example* example, char* produce_filename, int p
{
int err;
gchar *err_info;
int file_type_subtype;
if (pkt_rand == NULL) {
pkt_rand = g_rand_new();
@ -670,19 +671,20 @@ int randpkt_example_init(randpkt_example* example, char* produce_filename, int p
.encap = example->sample_wtap_encap,
.snaplen = produce_max_bytes,
};
file_type_subtype = wtap_pcap_file_type_subtype();
if (strcmp(produce_filename, "-") == 0) {
/* Write to the standard output. */
example->dump = wtap_dump_open_stdout(WTAP_FILE_TYPE_SUBTYPE_PCAP,
example->dump = wtap_dump_open_stdout(file_type_subtype,
WTAP_UNCOMPRESSED, &params, &err, &err_info);
example->filename = "the standard output";
} else {
example->dump = wtap_dump_open(produce_filename, WTAP_FILE_TYPE_SUBTYPE_PCAP,
example->dump = wtap_dump_open(produce_filename, file_type_subtype,
WTAP_UNCOMPRESSED, &params, &err, &err_info);
example->filename = produce_filename;
}
if (!example->dump) {
cfile_dump_open_failure_message("randpkt", produce_filename,
err, err_info, WTAP_FILE_TYPE_SUBTYPE_PCAP);
err, err_info, file_type_subtype);
return WRITE_ERROR;
}

View File

@ -733,7 +733,7 @@ main(int argc, char *argv[])
gboolean capture_option_specified = FALSE;
volatile int max_packet_count = 0;
#endif
volatile int out_file_type = WTAP_FILE_TYPE_SUBTYPE_PCAPNG;
volatile int out_file_type = WTAP_FILE_TYPE_SUBTYPE_UNKNOWN;
volatile gboolean out_file_name_res = FALSE;
volatile int in_file_type = WTAP_TYPE_AUTO;
gchar *volatile cf_name = NULL;
@ -746,6 +746,7 @@ main(int argc, char *argv[])
gchar *output_only = NULL;
gchar *volatile pdu_export_arg = NULL;
char *volatile exp_pdu_filename = NULL;
int exp_pdu_file_type_subtype;
exp_pdu_t exp_pdu_tap_data;
const gchar* elastic_mapping_filter = NULL;
@ -1528,6 +1529,10 @@ main(int argc, char *argv[])
if (output_action == WRITE_NONE)
output_action = WRITE_TEXT;
/* set the default file type to pcapng */
if (out_file_type == WTAP_FILE_TYPE_SUBTYPE_UNKNOWN)
out_file_type = wtap_pcapng_file_type_subtype();
/*
* Print packet summary information is the default if neither -V or -x
* were specified. Note that this is new behavior, which allows for the
@ -1766,16 +1771,19 @@ main(int argc, char *argv[])
if (global_capture_opts.saving_to_file) {
/* They specified a "-w" flag, so we'll be saving to a capture file. */
gboolean use_pcapng;
/* When capturing, we only support writing pcap or pcapng format. */
if (out_file_type != WTAP_FILE_TYPE_SUBTYPE_PCAP &&
out_file_type != WTAP_FILE_TYPE_SUBTYPE_PCAPNG) {
if (out_file_type == wtap_pcapng_file_type_subtype()) {
use_pcapng = TRUE;
} else if (out_file_type == wtap_pcap_file_type_subtype()) {
use_pcapng = FALSE;
} else {
cmdarg_err("Live captures can only be saved in pcap or pcapng format.");
exit_status = INVALID_OPTION;
goto clean_exit;
}
if (global_capture_opts.capture_comment &&
out_file_type != WTAP_FILE_TYPE_SUBTYPE_PCAPNG) {
if (global_capture_opts.capture_comment && !use_pcapng) {
cmdarg_err("A capture comment can only be written to a pcapng file.");
exit_status = INVALID_OPTION;
goto clean_exit;
@ -1818,7 +1826,7 @@ main(int argc, char *argv[])
exit_status = INVALID_OPTION;
goto clean_exit;
}
global_capture_opts.use_pcapng = (out_file_type == WTAP_FILE_TYPE_SUBTYPE_PCAPNG) ? TRUE : FALSE;
global_capture_opts.use_pcapng = use_pcapng;
} else {
/* They didn't specify a "-w" flag, so we won't be saving to a
capture file. Check for options that only make sense if
@ -2051,14 +2059,18 @@ main(int argc, char *argv[])
}
/* Activate the export PDU tap */
/* Write a pcapng file... */
exp_pdu_file_type_subtype = wtap_pcapng_file_type_subtype();
/* ...with this comment */
comment = g_strdup_printf("Dump of PDUs from %s", cf_name);
exp_pdu_status = exp_pdu_open(&exp_pdu_tap_data, exp_fd, comment,
exp_pdu_status = exp_pdu_open(&exp_pdu_tap_data,
exp_pdu_file_type_subtype, exp_fd, comment,
&err, &err_info);
g_free(comment);
if (!exp_pdu_status) {
cfile_dump_open_failure_message("TShark", exp_pdu_filename,
err, err_info,
WTAP_FILE_TYPE_SUBTYPE_PCAPNG);
exp_pdu_file_type_subtype);
exit_status = INVALID_EXPORT;
goto clean_exit;
}

View File

@ -34,6 +34,7 @@ static void
exp_pdu_file_open(exp_pdu_t *exp_pdu_tap_data)
{
int import_file_fd;
int file_type_subtype;
char *capfile_name, *comment;
gboolean status;
int err;
@ -48,14 +49,16 @@ exp_pdu_file_open(exp_pdu_t *exp_pdu_tap_data)
goto end;
}
/* Write a pcapng file... */
file_type_subtype = wtap_pcapng_file_type_subtype();
/* ...with this comment */
comment = g_strdup_printf("Dump of PDUs from %s", cfile.filename);
status = exp_pdu_open(exp_pdu_tap_data, import_file_fd, comment, &err,
&err_info);
status = exp_pdu_open(exp_pdu_tap_data, file_type_subtype, import_file_fd,
comment, &err, &err_info);
g_free(comment);
if (!status) {
cfile_dump_open_failure_alert_box(capfile_name ? capfile_name : "temporary file",
err, err_info,
WTAP_FILE_TYPE_SUBTYPE_PCAPNG);
err, err_info, file_type_subtype);
goto end;
}

View File

@ -124,19 +124,22 @@ void ImportTextDialog::convertTextFile() {
int err;
gchar *err_info;
wtap_dump_params params;
int file_type_subtype;
capfile_name_.clear();
wtap_dump_params_init(&params, NULL);
params.encap = import_info_.encapsulation;
params.snaplen = import_info_.max_frame_length;
params.tsprec = WTAP_TSPREC_USEC; /* XXX - support other precisions? */
/* Write a pcapng temporary file */
file_type_subtype = wtap_pcapng_file_type_subtype();
/* Use a random name for the temporary import buffer */
import_info_.wdh = wtap_dump_open_tempfile(&tmpname, "import", WTAP_FILE_TYPE_SUBTYPE_PCAPNG, WTAP_UNCOMPRESSED, &params, &err, &err_info);
import_info_.wdh = wtap_dump_open_tempfile(&tmpname, "import", file_type_subtype, WTAP_UNCOMPRESSED, &params, &err, &err_info);
capfile_name_.append(tmpname ? tmpname : "temporary file");
g_free(tmpname);
qDebug() << capfile_name_ << ":" << import_info_.wdh << import_info_.encapsulation << import_info_.max_frame_length;
if (import_info_.wdh == NULL) {
cfile_dump_open_failure_alert_box(capfile_name_.toUtf8().constData(), err, err_info, WTAP_FILE_TYPE_SUBTYPE_PCAP);
cfile_dump_open_failure_alert_box(capfile_name_.toUtf8().constData(), err, err_info, file_type_subtype);
fclose(import_info_.import_text_file);
setResult(QDialog::Rejected);
return;

View File

@ -1041,7 +1041,8 @@ void MainWindow::dropEvent(QDropEvent *event)
/* merge the files in chronological order */
if (cf_merge_files_to_tempfile(this, &tmpname, local_files.size(),
in_filenames, WTAP_FILE_TYPE_SUBTYPE_PCAPNG,
in_filenames,
wtap_pcapng_file_type_subtype(),
FALSE) == CF_OK) {
/* Merge succeeded; close the currently-open file and try
to open the merged capture file. */

View File

@ -85,8 +85,8 @@ export_pdu_packet(void *tapdata, packet_info *pinfo, epan_dissect_t *edt, const
}
gboolean
exp_pdu_open(exp_pdu_t *exp_pdu_tap_data, int fd, const char *comment, int *err,
gchar **err_info)
exp_pdu_open(exp_pdu_t *exp_pdu_tap_data, int fd, int file_type_subtype,
const char *comment, int *err, gchar **err_info)
{
/* pcapng defs */
wtap_block_t shb_hdr;
@ -96,49 +96,69 @@ exp_pdu_open(exp_pdu_t *exp_pdu_tap_data, int fd, const char *comment, int *err,
gsize opt_len;
gchar *opt_str;
/* Create data for SHB */
os_info_str = g_string_new("");
get_os_version_info(os_info_str);
shb_hdr = wtap_block_create(WTAP_BLOCK_SECTION);
/* options */
wtap_block_add_string_option(shb_hdr, OPT_COMMENT, comment, strlen(comment));
/*
* UTF-8 string containing the name of the operating system used to create
* this section.
* If the file format supports a section block, and the section
* block supports comments, create data for it.
*/
opt_len = os_info_str->len;
opt_str = g_string_free(os_info_str, FALSE);
if (opt_str) {
wtap_block_add_string_option(shb_hdr, OPT_SHB_OS, opt_str, opt_len);
g_free(opt_str);
if (wtap_file_type_subtype_supports_block(file_type_subtype,
WTAP_BLOCK_SECTION) != BLOCK_NOT_SUPPORTED &&
wtap_file_type_subtype_supports_option(file_type_subtype,
WTAP_BLOCK_SECTION,
OPT_COMMENT) != OPTION_NOT_SUPPORTED) {
os_info_str = g_string_new("");
get_os_version_info(os_info_str);
shb_hdr = wtap_block_create(WTAP_BLOCK_SECTION);
/* options */
wtap_block_add_string_option(shb_hdr, OPT_COMMENT, comment, strlen(comment));
/*
* UTF-8 string containing the name of the operating system used to
* create this section.
*/
opt_len = os_info_str->len;
opt_str = g_string_free(os_info_str, FALSE);
if (opt_str) {
wtap_block_add_string_option(shb_hdr, OPT_SHB_OS, opt_str, opt_len);
g_free(opt_str);
}
/*
* UTF-8 string containing the name of the application used to create
* this section.
*/
wtap_block_add_string_option_format(shb_hdr, OPT_SHB_USERAPPL, "%s",
get_appname_and_version());
exp_pdu_tap_data->shb_hdrs = g_array_new(FALSE, FALSE, sizeof(wtap_block_t));
g_array_append_val(exp_pdu_tap_data->shb_hdrs, shb_hdr);
} else {
exp_pdu_tap_data->shb_hdrs = NULL;
}
/*
* UTF-8 string containing the name of the application used to create
* this section.
* Create a fake IDB even if it's not supported; that provides a
* link-layer type
*/
wtap_block_add_string_option_format(shb_hdr, OPT_SHB_USERAPPL, "%s", get_appname_and_version());
if (wtap_file_type_subtype_supports_block(file_type_subtype,
WTAP_BLOCK_IF_ID_AND_INFO) != BLOCK_NOT_SUPPORTED) {
exp_pdu_tap_data->idb_inf = g_new(wtapng_iface_descriptions_t,1);
exp_pdu_tap_data->idb_inf->interface_data = g_array_new(FALSE, FALSE, sizeof(wtap_block_t));
/* Create fake IDB info */
exp_pdu_tap_data->idb_inf = g_new(wtapng_iface_descriptions_t,1);
exp_pdu_tap_data->idb_inf->interface_data = g_array_new(FALSE, FALSE, sizeof(wtap_block_t));
/* create the fake interface data */
int_data = wtap_block_create(WTAP_BLOCK_IF_ID_AND_INFO);
int_data_mand = (wtapng_if_descr_mandatory_t*)wtap_block_get_mandatory_data(int_data);
int_data_mand->wtap_encap = WTAP_ENCAP_WIRESHARK_UPPER_PDU;
int_data_mand->time_units_per_second = 1000000000; /* default nanosecond resolution */
int_data_mand->snap_len = WTAP_MAX_PACKET_SIZE_STANDARD;
/* create the fake interface data */
int_data = wtap_block_create(WTAP_BLOCK_IF_ID_AND_INFO);
int_data_mand = (wtapng_if_descr_mandatory_t*)wtap_block_get_mandatory_data(int_data);
int_data_mand->wtap_encap = WTAP_ENCAP_WIRESHARK_UPPER_PDU;
int_data_mand->time_units_per_second = 1000000000; /* default nanosecond resolution */
int_data_mand->snap_len = WTAP_MAX_PACKET_SIZE_STANDARD;
wtap_block_add_string_option(int_data, OPT_IDB_NAME, "Fake IF, PDU->Export", strlen("Fake IF, PDU->Export"));
wtap_block_add_uint8_option(int_data, OPT_IDB_TSRESOL, 9);
wtap_block_add_string_option(int_data, OPT_IDB_NAME, "Fake IF, PDU->Export", strlen("Fake IF, PDU->Export"));
wtap_block_add_uint8_option(int_data, OPT_IDB_TSRESOL, 9);
g_array_append_val(exp_pdu_tap_data->idb_inf->interface_data, int_data);
exp_pdu_tap_data->shb_hdrs = g_array_new(FALSE, FALSE, sizeof(wtap_block_t));
g_array_append_val(exp_pdu_tap_data->shb_hdrs, shb_hdr);
g_array_append_val(exp_pdu_tap_data->idb_inf->interface_data, int_data);
} else {
exp_pdu_tap_data->idb_inf = NULL;
}
const wtap_dump_params params = {
.encap = WTAP_ENCAP_WIRESHARK_UPPER_PDU,
@ -147,10 +167,10 @@ exp_pdu_open(exp_pdu_t *exp_pdu_tap_data, int fd, const char *comment, int *err,
.idb_inf = exp_pdu_tap_data->idb_inf,
};
if (fd == 1) {
exp_pdu_tap_data->wdh = wtap_dump_open_stdout(WTAP_FILE_TYPE_SUBTYPE_PCAPNG,
exp_pdu_tap_data->wdh = wtap_dump_open_stdout(file_type_subtype,
WTAP_UNCOMPRESSED, &params, err, err_info);
} else {
exp_pdu_tap_data->wdh = wtap_dump_fdopen(fd, WTAP_FILE_TYPE_SUBTYPE_PCAPNG,
exp_pdu_tap_data->wdh = wtap_dump_fdopen(fd, file_type_subtype,
WTAP_UNCOMPRESSED, &params, err, err_info);
}
if (exp_pdu_tap_data->wdh == NULL)

View File

@ -44,8 +44,8 @@ char *exp_pdu_pre_open(const char *tap_name, const char *filter,
* the error
* @return TRUE on success or FALSE on failure.
*/
gboolean exp_pdu_open(exp_pdu_t *data, int fd, const char *comment, int *err,
gchar **err_info);
gboolean exp_pdu_open(exp_pdu_t *data, int file_type_subtype, int fd,
const char *comment, int *err, gchar **err_info);
/* Stops the PDUs export. */
gboolean exp_pdu_close(exp_pdu_t *exp_pdu_tap_data, int *err, gchar **err_info);

View File

@ -23,6 +23,11 @@ set(WIRETAP_PUBLIC_HEADERS
# file types. (For cases where more than one source file is
# used, this should be the one that contains a registration routine.)
#
# This does not include libpcap.c and pcapng.c; those are listed below,
# and we don't scan them to see whether they have registration
# routines, we *require* them to have registration routines named
# register_pcap() and register_pcapng(), and directly call those routines.
#
set(WIRETAP_C_MODULE_FILES
${CMAKE_CURRENT_SOURCE_DIR}/5views.c
${CMAKE_CURRENT_SOURCE_DIR}/aethra.c
@ -52,7 +57,6 @@ set(WIRETAP_C_MODULE_FILES
${CMAKE_CURRENT_SOURCE_DIR}/json.c
${CMAKE_CURRENT_SOURCE_DIR}/k12.c
${CMAKE_CURRENT_SOURCE_DIR}/lanalyzer.c
${CMAKE_CURRENT_SOURCE_DIR}/libpcap.c
${CMAKE_CURRENT_SOURCE_DIR}/log3gpp.c
${CMAKE_CURRENT_SOURCE_DIR}/logcat.c
${CMAKE_CURRENT_SOURCE_DIR}/logcat_text.c
@ -71,7 +75,6 @@ set(WIRETAP_C_MODULE_FILES
${CMAKE_CURRENT_SOURCE_DIR}/ngsniffer.c
${CMAKE_CURRENT_SOURCE_DIR}/packetlogger.c
${CMAKE_CURRENT_SOURCE_DIR}/pcap-common.c
${CMAKE_CURRENT_SOURCE_DIR}/pcapng.c
${CMAKE_CURRENT_SOURCE_DIR}/peekclassic.c
${CMAKE_CURRENT_SOURCE_DIR}/peektagged.c
${CMAKE_CURRENT_SOURCE_DIR}/rfc7468.c
@ -105,6 +108,8 @@ set(WIRETAP_MODULE_FILES
#
set(WIRETAP_NONGENERATED_C_FILES
${WIRETAP_C_MODULE_FILES}
${CMAKE_CURRENT_SOURCE_DIR}/pcapng.c
${CMAKE_CURRENT_SOURCE_DIR}/libpcap.c
${CMAKE_CURRENT_SOURCE_DIR}/file_access.c
${CMAKE_CURRENT_SOURCE_DIR}/file_wrappers.c
${CMAKE_CURRENT_SOURCE_DIR}/merge.c

View File

@ -13,8 +13,6 @@
#include "ws_symbol_export.h"
wtap_open_return_val commview_open(wtap *wth, int *err, gchar **err_info);
int commview_dump_can_write_encap(int encap);
gboolean commview_dump_open(wtap_dumper *wdh, int *err, gchar **err_info);
#endif /* __COMMVIEW_H__ */

View File

@ -41,8 +41,6 @@ struct erf_private {
#define ERF_WS_DEFAULT_HOST_ID 0
wtap_open_return_val erf_open(wtap *wth, int *err, gchar **err_info);
int erf_dump_can_write_encap(int encap);
int erf_dump_open(wtap_dumper *wdh, int *err, gchar **err_info);
#endif /* __W_ERF_H__ */

View File

@ -22,7 +22,9 @@
#include "wtap-int.h"
#include "wtap_modules.h"
#include "file_wrappers.h"
#include "required_file_handlers.h"
#include <wsutil/buffer.h>
#include "lanalyzer.h"
#include "ngsniffer.h"
#include "radcom.h"
@ -1214,114 +1216,6 @@ wtap_fdreopen(wtap *wth, const char *filename, int *err)
return TRUE;
}
static const struct supported_block_type pcap_blocks_supported[] = {
/*
* We support packet blocks, with no comments or other options.
*/
{ WTAP_BLOCK_PACKET, MULTIPLE_BLOCKS_SUPPORTED, NO_OPTIONS_SUPPORTED }
};
/*
* pcapng supports several block types, and supports more than one
* of them.
*
* It also supports comments for many block types, as well as other
* option types.
*/
/* Options for section blocks. */
static const struct supported_option_type section_block_options_supported[] = {
{ OPT_COMMENT, MULTIPLE_OPTIONS_SUPPORTED },
{ OPT_SHB_HARDWARE, ONE_OPTION_SUPPORTED },
{ OPT_SHB_USERAPPL, ONE_OPTION_SUPPORTED }
};
/* Options for interface blocks. */
static const struct supported_option_type interface_block_options_supported[] = {
{ OPT_COMMENT, MULTIPLE_OPTIONS_SUPPORTED },
{ OPT_IDB_NAME, ONE_OPTION_SUPPORTED },
{ OPT_IDB_DESCR, ONE_OPTION_SUPPORTED },
{ OPT_IDB_IP4ADDR, MULTIPLE_OPTIONS_SUPPORTED },
{ OPT_IDB_IP6ADDR, MULTIPLE_OPTIONS_SUPPORTED },
{ OPT_IDB_MACADDR, ONE_OPTION_SUPPORTED },
{ OPT_IDB_EUIADDR, ONE_OPTION_SUPPORTED },
{ OPT_IDB_SPEED, ONE_OPTION_SUPPORTED },
{ OPT_IDB_TSRESOL, ONE_OPTION_SUPPORTED },
{ OPT_IDB_TZONE, ONE_OPTION_SUPPORTED },
{ OPT_IDB_FILTER, ONE_OPTION_SUPPORTED },
{ OPT_IDB_OS, ONE_OPTION_SUPPORTED },
{ OPT_IDB_FCSLEN, ONE_OPTION_SUPPORTED },
{ OPT_IDB_TSOFFSET, ONE_OPTION_SUPPORTED },
{ OPT_IDB_HARDWARE, ONE_OPTION_SUPPORTED }
};
/* Options for name resolution blocks. */
static const struct supported_option_type name_resolution_block_options_supported[] = {
{ OPT_COMMENT, MULTIPLE_OPTIONS_SUPPORTED },
{ OPT_NS_DNSNAME, ONE_OPTION_SUPPORTED },
{ OPT_NS_DNSIP4ADDR, ONE_OPTION_SUPPORTED },
{ OPT_NS_DNSIP6ADDR, ONE_OPTION_SUPPORTED }
};
/* Options for interface statistics blocks. */
static const struct supported_option_type interface_statistics_block_options_supported[] = {
{ OPT_COMMENT, MULTIPLE_OPTIONS_SUPPORTED },
{ OPT_ISB_STARTTIME, ONE_OPTION_SUPPORTED },
{ OPT_ISB_ENDTIME, ONE_OPTION_SUPPORTED },
{ OPT_ISB_IFRECV, ONE_OPTION_SUPPORTED },
{ OPT_ISB_IFDROP, ONE_OPTION_SUPPORTED },
{ OPT_ISB_FILTERACCEPT, ONE_OPTION_SUPPORTED },
{ OPT_ISB_OSDROP, ONE_OPTION_SUPPORTED },
{ OPT_ISB_USRDELIV, ONE_OPTION_SUPPORTED }
};
/* Options for decryption secrets blocks. */
static const struct supported_option_type decryption_secrets_block_options_supported[] = {
{ OPT_COMMENT, MULTIPLE_OPTIONS_SUPPORTED }
};
/* Options for packet blocks. */
static const struct supported_option_type packet_block_options_supported[] = {
/* XXX - pending use of wtap_block_t's for packets */
{ OPT_COMMENT, MULTIPLE_OPTIONS_SUPPORTED }
};
/* Options for file-type-sepcific reports. */
static const struct supported_option_type ft_specific_report_block_options_supported[] = {
{ OPT_COMMENT, MULTIPLE_OPTIONS_SUPPORTED }
};
/* Options for file-type-sepcific event. */
static const struct supported_option_type ft_specific_event_block_options_supported[] = {
{ OPT_COMMENT, MULTIPLE_OPTIONS_SUPPORTED }
};
static const struct supported_block_type pcapng_blocks_supported[] = {
/* Multiple sections. */
{ WTAP_BLOCK_SECTION, MULTIPLE_BLOCKS_SUPPORTED, OPTION_TYPES_SUPPORTED(section_block_options_supported) },
/* Multiple interfaces. */
{ WTAP_BLOCK_IF_ID_AND_INFO, MULTIPLE_BLOCKS_SUPPORTED, OPTION_TYPES_SUPPORTED(interface_block_options_supported) },
/* Multiple blocks of name resolution information */
{ WTAP_BLOCK_NAME_RESOLUTION, MULTIPLE_BLOCKS_SUPPORTED, OPTION_TYPES_SUPPORTED(name_resolution_block_options_supported) },
/* Multiple blocks of interface statistics. */
{ WTAP_BLOCK_IF_STATISTICS, MULTIPLE_BLOCKS_SUPPORTED, OPTION_TYPES_SUPPORTED(interface_statistics_block_options_supported) },
/* Multiple blocks of decryption secrets. */
{ WTAP_BLOCK_DECRYPTION_SECRETS, MULTIPLE_BLOCKS_SUPPORTED, OPTION_TYPES_SUPPORTED(decryption_secrets_block_options_supported) },
/* And, obviously, multiple packets. */
{ WTAP_BLOCK_PACKET, MULTIPLE_BLOCKS_SUPPORTED, OPTION_TYPES_SUPPORTED(packet_block_options_supported) },
/* Multiple file-type specific reports (including local ones). */
{ WTAP_BLOCK_FT_SPECIFIC_REPORT, MULTIPLE_BLOCKS_SUPPORTED, OPTION_TYPES_SUPPORTED(ft_specific_report_block_options_supported) },
/* Multiple file-type specific events (including local ones). */
{ WTAP_BLOCK_FT_SPECIFIC_EVENT, MULTIPLE_BLOCKS_SUPPORTED, OPTION_TYPES_SUPPORTED(ft_specific_event_block_options_supported) }
};
/* Table of the file types and subtypes for which we have built-in support.
Entries must be sorted by WTAP_FILE_TYPE_SUBTYPE_xxx values in ascending
order.
@ -1337,48 +1231,7 @@ static const struct file_type_subtype_info file_type_subtype_table_base[] = {
/* WTAP_FILE_TYPE_SUBTYPE_UNKNOWN (only used internally for initialization) */
{ NULL, NULL, NULL, NULL,
FALSE, NO_OPTIONS_SUPPORTED,
NULL, NULL, NULL },
/* WTAP_FILE_TYPE_SUBTYPE_PCAP */
/* Gianluca Varenni suggests that we add "deprecated" to the description. */
{ "Wireshark/tcpdump/... - pcap", "pcap", "pcap", "cap;dmp",
FALSE, BLOCKS_SUPPORTED(pcap_blocks_supported),
libpcap_dump_can_write_encap, libpcap_dump_open, NULL },
/* WTAP_FILE_TYPE_SUBTYPE_PCAPNG */
{ "Wireshark/... - pcapng", "pcapng", "pcapng", "ntar",
FALSE, BLOCKS_SUPPORTED(pcapng_blocks_supported),
pcapng_dump_can_write_encap, pcapng_dump_open, NULL },
/* WTAP_FILE_TYPE_SUBTYPE_PCAP_NSEC */
{ "Wireshark/tcpdump/... - nanosecond pcap", "nsecpcap", "pcap", "cap;dmp",
FALSE, BLOCKS_SUPPORTED(pcap_blocks_supported),
libpcap_dump_can_write_encap, libpcap_dump_open, NULL },
/* WTAP_FILE_TYPE_SUBTYPE_PCAP_AIX */
{ "AIX tcpdump - pcap", "aixpcap", "pcap", "cap;dmp",
FALSE, BLOCKS_SUPPORTED(pcap_blocks_supported),
NULL, NULL, NULL },
/* WTAP_FILE_TYPE_SUBTYPE_PCAP_SS991029 */
{ "Modified tcpdump - pcap", "modpcap", "pcap", "cap;dmp",
FALSE, BLOCKS_SUPPORTED(pcap_blocks_supported),
libpcap_dump_can_write_encap, libpcap_dump_open, NULL },
/* WTAP_FILE_TYPE_SUBTYPE_PCAP_NOKIA */
{ "Nokia tcpdump - pcap", "nokiapcap", "pcap", "cap;dmp",
FALSE, BLOCKS_SUPPORTED(pcap_blocks_supported),
libpcap_dump_can_write_encap, libpcap_dump_open, NULL },
/* WTAP_FILE_TYPE_SUBTYPE_PCAP_SS990417 */
{ "RedHat 6.1 tcpdump - pcap", "rh6_1pcap", "pcap", "cap;dmp",
FALSE, BLOCKS_SUPPORTED(pcap_blocks_supported),
libpcap_dump_can_write_encap, libpcap_dump_open, NULL },
/* WTAP_FILE_TYPE_SUBTYPE_PCAP_SS990915 */
{ "SuSE 6.3 tcpdump - pcap", "suse6_3pcap", "pcap", "cap;dmp",
FALSE, BLOCKS_SUPPORTED(pcap_blocks_supported),
libpcap_dump_can_write_encap, libpcap_dump_open, NULL }
NULL, NULL, NULL }
};
#define N_DUMP_OPEN_TABLE_BASE_ENTRIES (sizeof(file_type_subtype_table_base) / sizeof(struct file_type_subtype_info))
@ -1398,6 +1251,13 @@ static const struct file_type_subtype_info* file_type_subtype_table;
*/
static guint wtap_num_builtin_file_types_subtypes;
/*
* Required builtin types.
*/
int pcap_file_type_subtype = -1;
int pcap_nsec_file_type_subtype = -1;
int pcapng_file_type_subtype = -1;
/*
* Initialize the table of file types/subtypes with all the builtin
* types/subtypes.
@ -1414,9 +1274,12 @@ wtap_init_file_type_subtypes(void)
* the average number of file types/subtypes registered by
* a module is > 1 but probably < 2, but that shouldn't
* waste too much memory.
*
* Add on 7 more for pcapng, pcap, nanosecond pcap, and the
* extra modified flavors of pcap.
*/
file_type_subtype_table_arr = g_array_sized_new(FALSE, TRUE,
sizeof(struct file_type_subtype_info), wtap_module_count*2);
sizeof(struct file_type_subtype_info), wtap_module_count*2 + 7);
/* Copy over the fixed builtin entries. */
g_array_append_vals(file_type_subtype_table_arr, file_type_subtype_table_base,
@ -1427,7 +1290,18 @@ wtap_init_file_type_subtypes(void)
/* Remember which entries are builtin. */
wtap_num_builtin_file_types_subtypes = file_type_subtype_table_arr->len;
/* Register the builtin entries that aren't in the table. */
/*
* Register the builtin entries that aren't in the table.
* First, do the required ones; register pcapng first, then
* pcap, so, at the beginning of the table, we have pcapng,
* pcap, nanosecond pcap, and the weird modified pcaps, so
* searches for file types that can write a file format
* start with pcapng, pcap, and nanosecond pcap.
*/
register_pcapng();
register_pcap();
/* Now register the ones found by the build process */
for (guint i = 0; i < wtap_module_count; i++)
wtap_module_reg[i].cb_func();
@ -1720,8 +1594,6 @@ wtap_get_savable_file_types_subtypes_for_file(int file_type_subtype,
ft_sort_order sort_order)
{
GArray *savable_file_types_subtypes;
int pcap_file_type_subtype = wtap_name_to_file_type_subtype("pcap");
int pcapng_file_type_subtype = wtap_name_to_file_type_subtype("pcapng");
int ft;
int default_file_type_subtype = -1;
int other_file_type_subtype = -1;
@ -1731,6 +1603,22 @@ wtap_get_savable_file_types_subtypes_for_file(int file_type_subtype,
required_comment_types)) {
/* Yes - make that the default file type/subtype. */
default_file_type_subtype = file_type_subtype;
} else if (wtap_dump_can_write_format(pcap_file_type_subtype,
file_encaps,
required_comment_types)) {
/*
* No, but we can write it as a pcap file; make that
* the default file type/subtype.
*/
default_file_type_subtype = pcap_file_type_subtype;
} else if (wtap_dump_can_write_format(pcapng_file_type_subtype,
file_encaps,
required_comment_types)) {
/*
* No, but we can write it as a pcapng file; make that
* the default file type/subtype.
*/
default_file_type_subtype = pcapng_file_type_subtype;
} else {
/* OK, find the first file type/subtype we *can* save it as. */
default_file_type_subtype = -1;
@ -1818,8 +1706,6 @@ GArray *
wtap_get_writable_file_types_subtypes(ft_sort_order sort_order)
{
GArray *writable_file_types_subtypes;
int pcap_file_type_subtype = wtap_name_to_file_type_subtype("pcap");
int pcapng_file_type_subtype = wtap_name_to_file_type_subtype("pcapng");
int ft;
/*
@ -1944,6 +1830,48 @@ wtap_name_to_file_type_subtype(const char *name)
return -1; /* no such file type, or we can't write it */
}
/*
* Provide the file type/subtype for pcap.
*/
int
wtap_pcap_file_type_subtype(void)
{
/*
* Make sure pcap was registered as a file type/subtype;
* it's one of our "native" formats.
*/
g_assert(pcap_file_type_subtype != -1);
return pcap_file_type_subtype;
}
/*
* Provide the file type/subtype for nanosecond-resolution pcap.
*/
int
wtap_pcap_nsec_file_type_subtype(void)
{
/*
* Make sure nanosecond-resolution pcap was registered
* as a file type/subtype; it's one of our "native" formats.
*/
g_assert(pcap_nsec_file_type_subtype != -1);
return pcap_nsec_file_type_subtype;
}
/*
* Provide the file type/subtype for pcapng.
*/
int
wtap_pcapng_file_type_subtype(void)
{
/*
* Make sure pcapng was registered as a file type/subtype;
* it's one of our "native" formats.
*/
g_assert(pcapng_file_type_subtype != -1);
return pcapng_file_type_subtype;
}
block_support_t
wtap_file_type_subtype_supports_block(int filetype, wtap_block_type_t type)
{
@ -2949,22 +2877,6 @@ wtap_register_backwards_compatibility_lua_name(const char *name, int ft)
WTAP_TSPREC_NSEC);
wtap_register_backwards_compatibility_lua_name("UNKNOWN",
WTAP_FILE_TYPE_SUBTYPE_UNKNOWN);
wtap_register_backwards_compatibility_lua_name("PCAP",
WTAP_FILE_TYPE_SUBTYPE_PCAP);
wtap_register_backwards_compatibility_lua_name("PCAPNG",
WTAP_FILE_TYPE_SUBTYPE_PCAPNG);
wtap_register_backwards_compatibility_lua_name("PCAP_NSEC",
WTAP_FILE_TYPE_SUBTYPE_PCAP_NSEC);
wtap_register_backwards_compatibility_lua_name("PCAP_AIX",
WTAP_FILE_TYPE_SUBTYPE_PCAP_AIX);
wtap_register_backwards_compatibility_lua_name("PCAP_SS991029",
WTAP_FILE_TYPE_SUBTYPE_PCAP_SS991029);
wtap_register_backwards_compatibility_lua_name("PCAP_NOKIA",
WTAP_FILE_TYPE_SUBTYPE_PCAP_NOKIA);
wtap_register_backwards_compatibility_lua_name("PCAP_SS990417",
WTAP_FILE_TYPE_SUBTYPE_PCAP_SS990417);
wtap_register_backwards_compatibility_lua_name("PCAP_SS990915",
WTAP_FILE_TYPE_SUBTYPE_PCAP_SS990915);
}
entry.name = name;
entry.ft = ft;

View File

@ -13,7 +13,5 @@
#include "wtap.h"
wtap_open_return_val lanalyzer_open(wtap *wth, int *err, gchar **err_info);
gboolean lanalyzer_dump_open(wtap_dumper *wdh, int *err, gchar **err_info);
int lanalyzer_dump_can_write_encap(int encap);
#endif

View File

@ -13,6 +13,7 @@
#include <errno.h>
#include "wtap-int.h"
#include "file_wrappers.h"
#include "required_file_handlers.h"
#include "pcap-common.h"
#include "pcap-encap.h"
#include "libpcap.h"
@ -30,11 +31,29 @@ typedef enum {
MAYBE_SWAPPED
} swapped_type_t;
/*
* Variants of pcap, some distinguished by the magic number and some,
* alas, not.
*
* (Don't do that. Srsly.)
*/
typedef enum {
PCAP, /* OG pcap */
PCAP_NSEC, /* PCAP with nanosecond resolution */
PCAP_AIX, /* AIX pcap */
PCAP_SS990417, /* Modified, from 1999-04-17 patch */
PCAP_SS990915, /* Modified, from 1999-09-15 patch */
PCAP_SS991029, /* Modified, from 1999-10-29 patch */
PCAP_NOKIA, /* Nokia pcap */
PCAP_UNKNOWN /* Unknown as yet */
} pcap_variant_t;
typedef struct {
gboolean byte_swapped;
swapped_type_t lengths_swapped;
guint16 version_major;
guint16 version_minor;
pcap_variant_t variant;
void *encap_priv;
} libpcap_t;
@ -48,12 +67,33 @@ static gboolean libpcap_seek_read(wtap *wth, gint64 seek_off,
wtap_rec *rec, Buffer *buf, int *err, gchar **err_info);
static gboolean libpcap_read_packet(wtap *wth, FILE_T fh,
wtap_rec *rec, Buffer *buf, int *err, gchar **err_info);
static gboolean libpcap_dump(wtap_dumper *wdh, const wtap_rec *rec,
const guint8 *pd, int *err, gchar **err_info);
static int libpcap_read_header(wtap *wth, FILE_T fh, int *err, gchar **err_info,
struct pcaprec_ss990915_hdr *hdr);
static void libpcap_close(wtap *wth);
static gboolean libpcap_dump_pcap(wtap_dumper *wdh, const wtap_rec *rec,
const guint8 *pd, int *err, gchar **err_info);
static gboolean libpcap_dump_pcap_nsec(wtap_dumper *wdh, const wtap_rec *rec,
const guint8 *pd, int *err, gchar **err_info);
static gboolean libpcap_dump_pcap_ss990417(wtap_dumper *wdh,
const wtap_rec *rec, const guint8 *pd, int *err, gchar **err_info);
static gboolean libpcap_dump_pcap_ss990915(wtap_dumper *wdh,
const wtap_rec *rec, const guint8 *pd, int *err, gchar **err_info);
static gboolean libpcap_dump_pcap_ss991029(wtap_dumper *wdh,
const wtap_rec *rec, const guint8 *pd, int *err, gchar **err_info);
static gboolean libpcap_dump_pcap_nokia(wtap_dumper *wdh, const wtap_rec *rec,
const guint8 *pd, int *err, gchar **err_info);
/*
* Private file type/subtype values; pcap and nanosecond-resolution
* pcap are imported from wiretap/file_access.c.
*/
static int pcap_aix_file_type_subtype = -1;
static int pcap_ss990417_file_type_subtype = -1;
static int pcap_ss990915_file_type_subtype = -1;
static int pcap_ss991029_file_type_subtype = -1;
static int pcap_nokia_file_type_subtype = -1;
wtap_open_return_val libpcap_open(wtap *wth, int *err, gchar **err_info)
{
guint32 magic;
@ -64,23 +104,23 @@ wtap_open_return_val libpcap_open(wtap *wth, int *err, gchar **err_info)
int file_encap;
gint64 first_packet_offset;
libpcap_t *libpcap;
static const int subtypes_modified[] = {
WTAP_FILE_TYPE_SUBTYPE_PCAP_SS991029,
WTAP_FILE_TYPE_SUBTYPE_PCAP_SS990915
static const pcap_variant_t variants_modified[] = {
PCAP_SS991029,
PCAP_SS990915
};
#define N_SUBTYPES_MODIFIED G_N_ELEMENTS(subtypes_modified)
static const int subtypes_standard[] = {
WTAP_FILE_TYPE_SUBTYPE_PCAP,
WTAP_FILE_TYPE_SUBTYPE_PCAP_SS990417,
WTAP_FILE_TYPE_SUBTYPE_PCAP_NOKIA
#define N_VARIANTS_MODIFIED G_N_ELEMENTS(variants_modified)
static const pcap_variant_t variants_standard[] = {
PCAP,
PCAP_SS990417,
PCAP_NOKIA
};
#define N_SUBTYPES_STANDARD G_N_ELEMENTS(subtypes_standard)
#define N_VARIANTS_STANDARD G_N_ELEMENTS(variants_standard)
#define MAX_FIGURES_OF_MERIT \
MAX(N_SUBTYPES_MODIFIED, N_SUBTYPES_STANDARD)
MAX(N_VARIANTS_MODIFIED, N_VARIANTS_STANDARD)
int figures_of_merit[MAX_FIGURES_OF_MERIT];
const int *subtypes;
int n_subtypes;
int best_subtype;
const pcap_variant_t *variants;
int n_variants;
int best_variant;
int i;
int skip_size = 0;
int sizebytes;
@ -351,7 +391,8 @@ wtap_open_return_val libpcap_open(wtap *wth, int *err, gchar **err_info)
* and for the ERF link-layer header type, and set the
* precision to nanosecond precision.
*/
wth->file_type_subtype = WTAP_FILE_TYPE_SUBTYPE_PCAP_AIX;
libpcap->variant = PCAP_AIX;
wth->file_type_subtype = pcap_aix_file_type_subtype;
wth->file_tsprec = WTAP_TSPREC_NSEC;
/*
@ -407,12 +448,12 @@ wtap_open_return_val libpcap_open(wtap *wth, int *err, gchar **err_info)
if (modified) {
/*
* Well, we have the magic number from Alexey's
* later two patches. Try the subtypes for that,
* later two patches. Try the variants for that,
* and fail if we're reading from a pipe.
*/
wth->file_type_subtype = WTAP_FILE_TYPE_SUBTYPE_UNKNOWN;
subtypes = subtypes_modified;
n_subtypes = N_SUBTYPES_MODIFIED;
libpcap->variant = PCAP_UNKNOWN;
variants = variants_modified;
n_variants = N_VARIANTS_MODIFIED;
} else {
if (wth->file_tsprec == WTAP_TSPREC_NSEC) {
/*
@ -423,26 +464,26 @@ wtap_open_return_val libpcap_open(wtap *wth, int *err, gchar **err_info)
* it and tell them to ask The Tcpdump Group
* for another magic number).
*/
wth->file_type_subtype = WTAP_FILE_TYPE_SUBTYPE_PCAP_NSEC;
subtypes = NULL;
n_subtypes = 0;
libpcap->variant = PCAP_NSEC;
variants = NULL;
n_variants = 0;
} else {
/*
* We have the regular libpcap magic number.
* Try the subtypes for that, unless we're
* Try the variants for that, unless we're
* reading from a pipe, in which case we
* just assume it's a regular libpcap file.
*/
wth->file_type_subtype = WTAP_FILE_TYPE_SUBTYPE_PCAP;
subtypes = subtypes_standard;
n_subtypes = N_SUBTYPES_STANDARD;
libpcap->variant = PCAP;
variants = variants_standard;
n_variants = N_VARIANTS_STANDARD;
}
}
/*
* Do we have any subtypes to try?
* Do we have any variants to try?
*/
if (n_subtypes == 0) {
if (n_variants == 0) {
/*
* No, so just use what we picked.
*/
@ -450,9 +491,9 @@ wtap_open_return_val libpcap_open(wtap *wth, int *err, gchar **err_info)
} else if (wth->ispipe) {
/*
* It's a pipe, so use what we picked, unless we picked
* WTAP_FILE_TYPE_SUBTYPE_UNKNOWN, in which case we fail.
* PCAP_UNKNOWN, in which case we fail.
*/
if (wth->file_type_subtype == WTAP_FILE_TYPE_SUBTYPE_UNKNOWN) {
if (libpcap->variant == PCAP_UNKNOWN) {;
*err = WTAP_ERR_UNSUPPORTED;
*err_info = g_strdup("pcap: that type of pcap file can't be read from a pipe");
return WTAP_OPEN_ERROR;
@ -460,8 +501,8 @@ wtap_open_return_val libpcap_open(wtap *wth, int *err, gchar **err_info)
goto done;
} else {
first_packet_offset = file_tell(wth->fh);
for (i = 0; i < n_subtypes; i++) {
wth->file_type_subtype = subtypes[i];
for (i = 0; i < n_variants; i++) {
libpcap->variant = variants[i];
figures_of_merit[i] = libpcap_try(wth, err, err_info);
if (figures_of_merit[i] == -1) {
/*
@ -497,22 +538,55 @@ wtap_open_return_val libpcap_open(wtap *wth, int *err, gchar **err_info)
/*
* OK, none are perfect; let's see which one is least bad.
*/
best_subtype = INT_MAX;
for (i = 0; i < n_subtypes; i++) {
best_variant = INT_MAX;
for (i = 0; i < n_variants; i++) {
/*
* Is this subtype better than the last one we saw?
*/
if (figures_of_merit[i] < best_subtype) {
if (figures_of_merit[i] < best_variant) {
/*
* Yes. Choose it until we find a better one.
*/
wth->file_type_subtype = subtypes[i];
best_subtype = figures_of_merit[i];
libpcap->variant = variants[i];
best_variant = figures_of_merit[i];
}
}
}
done:
/*
* Set the file type and subtype.
*/
switch (libpcap->variant) {
case PCAP:
wth->file_type_subtype = pcap_file_type_subtype;
break;
case PCAP_NSEC:
wth->file_type_subtype = pcap_nsec_file_type_subtype;
break;
case PCAP_SS990417:
wth->file_type_subtype = pcap_ss990417_file_type_subtype;
break;
case PCAP_SS990915:
wth->file_type_subtype = pcap_ss990915_file_type_subtype;
break;
case PCAP_SS991029:
wth->file_type_subtype = pcap_ss991029_file_type_subtype;
break;
case PCAP_NOKIA:
wth->file_type_subtype = pcap_nokia_file_type_subtype;
break;
default:
g_assert_not_reached();
}
/*
* We treat a DLT_ value of 13 specially - it appears that in
* Nokia libpcap format, it's some form of ATM with what I
@ -522,8 +596,7 @@ done:
* If this is a Nokia capture, treat 13 as WTAP_ENCAP_ATM_PDUS,
* rather than as what we normally treat it.
*/
if (wth->file_type_subtype == WTAP_FILE_TYPE_SUBTYPE_PCAP_NOKIA &&
hdr.network == 13)
if (libpcap->variant == PCAP_NOKIA && hdr.network == 13)
wth->file_encap = WTAP_ENCAP_ATM_PDUS;
if (wth->file_encap == WTAP_ENCAP_ERF) {
@ -607,6 +680,8 @@ static int libpcap_try(wtap *wth, int *err, gchar **err_info)
being chosen. */
static int libpcap_try_record(wtap *wth, FILE_T fh, int *err, gchar **err_info)
{
libpcap_t *libpcap = (libpcap_t *)wth->priv;
/*
* pcaprec_ss990915_hdr is the largest header type.
*/
@ -636,10 +711,9 @@ static int libpcap_try_record(wtap *wth, FILE_T fh, int *err, gchar **err_info)
}
ret = 0; /* start out presuming everything's OK */
switch (wth->file_type_subtype) {
case WTAP_FILE_TYPE_SUBTYPE_PCAP_NSEC:
case WTAP_FILE_TYPE_SUBTYPE_PCAP_AIX:
switch (libpcap->variant) {
case PCAP_NSEC:
case PCAP_AIX:
/*
* Nanosecond resolution; treat fractions-of-a-second
* values >= 1 000 000 000 as an indication that
@ -773,9 +847,8 @@ libpcap_read_packet(wtap *wth, FILE_T fh, wtap_rec *rec,
guint packet_size;
guint orig_size;
int phdr_len;
libpcap_t *libpcap;
libpcap = (libpcap_t *)wth->priv;
libpcap_t *libpcap = (libpcap_t *)wth->priv;
gboolean is_nokia;
if (!libpcap_read_header(wth, fh, err, err_info, &hdr))
return FALSE;
@ -802,7 +875,7 @@ libpcap_read_packet(wtap *wth, FILE_T fh, wtap_rec *rec,
* AIX appears to put 3 bytes of padding in front of FDDI
* frames; strip that crap off.
*/
if (wth->file_type_subtype == WTAP_FILE_TYPE_SUBTYPE_PCAP_AIX &&
if (libpcap->variant == PCAP_AIX &&
(wth->file_encap == WTAP_ENCAP_FDDI ||
wth->file_encap == WTAP_ENCAP_FDDI_BITSWAPPED)) {
/*
@ -819,7 +892,8 @@ libpcap_read_packet(wtap *wth, FILE_T fh, wtap_rec *rec,
return FALSE;
}
phdr_len = pcap_process_pseudo_header(fh, wth->file_type_subtype,
is_nokia = (libpcap->variant == PCAP_NOKIA);
phdr_len = pcap_process_pseudo_header(fh, is_nokia,
wth->file_encap, packet_size, rec, err, err_info);
if (phdr_len < 0)
return FALSE; /* error */
@ -858,8 +932,8 @@ libpcap_read_packet(wtap *wth, FILE_T fh, wtap_rec *rec,
if (!wtap_read_packet_bytes(fh, buf, packet_size, err, err_info))
return FALSE; /* failed */
pcap_read_post_process(wth->file_type_subtype, wth->file_encap,
rec, ws_buffer_start_ptr(buf), libpcap->byte_swapped, -1);
pcap_read_post_process(is_nokia, wth->file_encap, rec,
ws_buffer_start_ptr(buf), libpcap->byte_swapped, -1);
return TRUE;
}
@ -871,26 +945,26 @@ static int libpcap_read_header(wtap *wth, FILE_T fh, int *err, gchar **err_info,
{
int bytes_to_read;
guint32 temp;
libpcap_t *libpcap;
libpcap_t *libpcap = (libpcap_t *)wth->priv;
switch (wth->file_type_subtype) {
switch (libpcap->variant) {
case WTAP_FILE_TYPE_SUBTYPE_PCAP:
case WTAP_FILE_TYPE_SUBTYPE_PCAP_AIX:
case WTAP_FILE_TYPE_SUBTYPE_PCAP_NSEC:
case PCAP:
case PCAP_AIX:
case PCAP_NSEC:
bytes_to_read = sizeof (struct pcaprec_hdr);
break;
case WTAP_FILE_TYPE_SUBTYPE_PCAP_SS990417:
case WTAP_FILE_TYPE_SUBTYPE_PCAP_SS991029:
case PCAP_SS990417:
case PCAP_SS991029:
bytes_to_read = sizeof (struct pcaprec_modified_hdr);
break;
case WTAP_FILE_TYPE_SUBTYPE_PCAP_SS990915:
case PCAP_SS990915:
bytes_to_read = sizeof (struct pcaprec_ss990915_hdr);
break;
case WTAP_FILE_TYPE_SUBTYPE_PCAP_NOKIA:
case PCAP_NOKIA:
bytes_to_read = sizeof (struct pcaprec_nokia_hdr);
break;
@ -901,7 +975,6 @@ static int libpcap_read_header(wtap *wth, FILE_T fh, int *err, gchar **err_info,
if (!wtap_read_bytes_or_eof(fh, hdr, bytes_to_read, err, err_info))
return FALSE;
libpcap = (libpcap_t *)wth->priv;
if (libpcap->byte_swapped) {
/* Byte-swap the record header fields. */
hdr->hdr.ts_sec = GUINT32_SWAP_LE_BE(hdr->hdr.ts_sec);
@ -936,6 +1009,10 @@ static int libpcap_read_header(wtap *wth, FILE_T fh, int *err, gchar **err_info,
return TRUE;
}
typedef struct {
pcap_variant_t variant;
} libpcap_dump_t;
/* Returns 0 if we could write the specified encapsulation type,
an error indication otherwise. */
int libpcap_dump_can_write_encap(int encap)
@ -950,43 +1027,11 @@ int libpcap_dump_can_write_encap(int encap)
return 0;
}
/* Returns TRUE on success, FALSE on failure; sets "*err" to an error code on
failure */
gboolean libpcap_dump_open(wtap_dumper *wdh, int *err, gchar **err_info)
static gboolean libpcap_dump_write_file_header(wtap_dumper *wdh, guint32 magic,
int *err)
{
guint32 magic;
struct pcap_hdr file_hdr;
/* This is a libpcap file */
wdh->subtype_write = libpcap_dump;
/* Write the file header. */
switch (wdh->file_type_subtype) {
case WTAP_FILE_TYPE_SUBTYPE_PCAP:
case WTAP_FILE_TYPE_SUBTYPE_PCAP_SS990417: /* modified, but with the old magic, sigh */
case WTAP_FILE_TYPE_SUBTYPE_PCAP_NOKIA: /* Nokia libpcap of some sort */
magic = PCAP_MAGIC;
break;
case WTAP_FILE_TYPE_SUBTYPE_PCAP_SS990915: /* new magic, extra crap */
case WTAP_FILE_TYPE_SUBTYPE_PCAP_SS991029:
magic = PCAP_MODIFIED_MAGIC;
break;
case WTAP_FILE_TYPE_SUBTYPE_PCAP_NSEC: /* same as WTAP_FILE_TYPE_SUBTYPE_PCAP, but nsec precision */
magic = PCAP_NSEC_MAGIC;
break;
default:
/* We should never get here - our open routine
should only get called for the types above. */
*err = WTAP_ERR_INTERNAL;
*err_info = g_strdup_printf("libpcap: invalid file type/subtype %u",
wdh->file_type_subtype);
return FALSE;
}
if (!wtap_dump_file_write(wdh, &magic, sizeof magic, err))
return FALSE;
wdh->bytes_dumped += sizeof magic;
@ -1018,15 +1063,110 @@ gboolean libpcap_dump_open(wtap_dumper *wdh, int *err, gchar **err_info)
return TRUE;
}
/* Write a record for a packet to a dump file.
Returns TRUE on success, FALSE on failure. */
static gboolean libpcap_dump(wtap_dumper *wdh,
const wtap_rec *rec,
const guint8 *pd, int *err, gchar **err_info _U_)
/* Good old fashioned pcap.
Returns TRUE on success, FALSE on failure; sets "*err" to an error code on
failure */
static gboolean
libpcap_dump_open_pcap(wtap_dumper *wdh, int *err, gchar **err_info _U_)
{
/* This is a libpcap file */
wdh->subtype_write = libpcap_dump_pcap;
/* Write the file header. */
return libpcap_dump_write_file_header(wdh, PCAP_MAGIC, err);
}
/* Like classic pcap, but with nanosecond resolution.
Returns TRUE on success, FALSE on failure; sets "*err" to an error code on
failure */
static gboolean
libpcap_dump_open_pcap_nsec(wtap_dumper *wdh, int *err, gchar **err_info _U_)
{
/* This is a nanosecond-resolution libpcap file */
wdh->subtype_write = libpcap_dump_pcap_nsec;
/* Write the file header. */
return libpcap_dump_write_file_header(wdh, PCAP_NSEC_MAGIC, err);
}
/* Modified, but with the old magic, sigh.
Returns TRUE on success, FALSE on failure; sets "*err" to an error code on
failure */
static gboolean
libpcap_dump_open_pcap_ss990417(wtap_dumper *wdh, int *err,
gchar **err_info _U_)
{
/* This is a modified-by-patch-SS990417 libpcap file */
wdh->subtype_write = libpcap_dump_pcap_ss990417;
/* Write the file header. */
return libpcap_dump_write_file_header(wdh, PCAP_MAGIC, err);
}
/* New magic, extra crap.
Returns TRUE on success, FALSE on failure; sets "*err" to an error code on
failure */
static gboolean
libpcap_dump_open_pcap_ss990915(wtap_dumper *wdh, int *err,
gchar **err_info _U_)
{
/* This is a modified-by-patch-SS990915 libpcap file */
wdh->subtype_write = libpcap_dump_pcap_ss990915;
/* Write the file header. */
return libpcap_dump_write_file_header(wdh, PCAP_MODIFIED_MAGIC, err);
}
/* Same magic as SS990915, *different* extra crap, sigh.
Returns TRUE on success, FALSE on failure; sets "*err" to an error code on
failure */
static gboolean
libpcap_dump_open_pcap_ss991029(wtap_dumper *wdh, int *err,
gchar **err_info _U_)
{
/* This is a modified-by-patch-SS991029 libpcap file */
wdh->subtype_write = libpcap_dump_pcap_ss991029;
/* Write the file header. */
return libpcap_dump_write_file_header(wdh, PCAP_MODIFIED_MAGIC, err);
}
static void libpcap_close(wtap *wth)
{
libpcap_t *libpcap = (libpcap_t *)wth->priv;
if (libpcap->encap_priv) {
switch (wth->file_encap) {
case WTAP_ENCAP_ERF:
erf_priv_free((erf_t*) libpcap->encap_priv);
break;
default:
g_free(libpcap->encap_priv);
break;
}
}
}
/* Nokia libpcap of some sort.
Returns TRUE on success, FALSE on failure; sets "*err" to an error code on
failure */
static gboolean
libpcap_dump_open_pcap_nokia(wtap_dumper *wdh, int *err, gchar **err_info _U_)
{
/* This is a Nokia libpcap file */
wdh->subtype_write = libpcap_dump_pcap_nokia;
/* Write the file header. */
return libpcap_dump_write_file_header(wdh, PCAP_MAGIC, err);
}
static gboolean
libpcap_dump_write_packet(wtap_dumper *wdh, const wtap_rec *rec,
struct pcaprec_hdr *hdr, size_t hdr_size, const guint8 *pd, int *err)
{
const union wtap_pseudo_header *pseudo_header = &rec->rec_header.packet_header.pseudo_header;
struct pcaprec_ss990915_hdr rec_hdr;
size_t hdr_size;
int phdrsize;
phdrsize = pcap_get_phdr_size(wdh->encap, pseudo_header);
@ -1055,85 +1195,10 @@ static gboolean libpcap_dump(wtap_dumper *wdh,
return FALSE;
}
rec_hdr.hdr.incl_len = rec->rec_header.packet_header.caplen + phdrsize;
rec_hdr.hdr.orig_len = rec->rec_header.packet_header.len + phdrsize;
hdr->incl_len = rec->rec_header.packet_header.caplen + phdrsize;
hdr->orig_len = rec->rec_header.packet_header.len + phdrsize;
switch (wdh->file_type_subtype) {
case WTAP_FILE_TYPE_SUBTYPE_PCAP:
rec_hdr.hdr.ts_sec = (guint32) rec->ts.secs;
rec_hdr.hdr.ts_usec = rec->ts.nsecs / 1000;
hdr_size = sizeof (struct pcaprec_hdr);
break;
case WTAP_FILE_TYPE_SUBTYPE_PCAP_NSEC:
rec_hdr.hdr.ts_sec = (guint32) rec->ts.secs;
rec_hdr.hdr.ts_usec = rec->ts.nsecs;
hdr_size = sizeof (struct pcaprec_hdr);
break;
case WTAP_FILE_TYPE_SUBTYPE_PCAP_SS990417: /* modified, but with the old magic, sigh */
case WTAP_FILE_TYPE_SUBTYPE_PCAP_SS991029:
rec_hdr.hdr.ts_sec = (guint32) rec->ts.secs;
rec_hdr.hdr.ts_usec = rec->ts.nsecs / 1000;
/* XXX - what should we supply here?
Alexey's "libpcap" looks up the interface in the system's
interface list if "ifindex" is non-zero, and prints
the interface name. It ignores "protocol", and uses
"pkt_type" to tag the packet as "host", "broadcast",
"multicast", "other host", "outgoing", or "none of the
above", but that's it.
If the capture we're writing isn't a modified or
RH 6.1 capture, we'd have to do some work to
generate the packet type and interface index - and
we can't generate the interface index unless we
just did the capture ourselves in any case.
I'm inclined to continue to punt; systems other than
those with the older patch can read standard "libpcap"
files, and systems with the older patch, e.g. RH 6.1,
will just have to live with this. */
rec_hdr.ifindex = 0;
rec_hdr.protocol = 0;
rec_hdr.pkt_type = 0;
hdr_size = sizeof (struct pcaprec_modified_hdr);
break;
case WTAP_FILE_TYPE_SUBTYPE_PCAP_SS990915: /* new magic, extra crap at the end */
rec_hdr.hdr.ts_sec = (guint32) rec->ts.secs;
rec_hdr.hdr.ts_usec = rec->ts.nsecs / 1000;
rec_hdr.ifindex = 0;
rec_hdr.protocol = 0;
rec_hdr.pkt_type = 0;
rec_hdr.cpu1 = 0;
rec_hdr.cpu2 = 0;
hdr_size = sizeof (struct pcaprec_ss990915_hdr);
break;
case WTAP_FILE_TYPE_SUBTYPE_PCAP_NOKIA: /* old magic, extra crap at the end */
rec_hdr.hdr.ts_sec = (guint32) rec->ts.secs;
rec_hdr.hdr.ts_usec = rec->ts.nsecs / 1000;
/* restore the "mysterious stuff" that came with the packet */
memcpy(&rec_hdr.ifindex, pseudo_header->nokia.stuff, 4);
/* not written */
rec_hdr.protocol = 0;
rec_hdr.pkt_type = 0;
rec_hdr.cpu1 = 0;
rec_hdr.cpu2 = 0;
hdr_size = sizeof (struct pcaprec_nokia_hdr);
break;
default:
/* We should never get here - our open routine
should only get called for the types above. */
g_assert_not_reached();
*err = WTAP_ERR_UNWRITABLE_FILE_TYPE;
return FALSE;
}
if (!wtap_dump_file_write(wdh, &rec_hdr, hdr_size, err))
if (!wtap_dump_file_write(wdh, hdr, hdr_size, err))
return FALSE;
wdh->bytes_dumped += hdr_size;
@ -1146,22 +1211,226 @@ static gboolean libpcap_dump(wtap_dumper *wdh,
return TRUE;
}
static void libpcap_close(wtap *wth)
/* Good old fashioned pcap.
Write a record for a packet to a dump file.
Returns TRUE on success, FALSE on failure. */
static gboolean
libpcap_dump_pcap(wtap_dumper *wdh, const wtap_rec *rec, const guint8 *pd,
int *err, gchar **err_info _U_)
{
libpcap_t *libpcap = (libpcap_t *)wth->priv;
struct pcaprec_hdr rec_hdr;
if (libpcap->encap_priv) {
switch (wth->file_encap) {
rec_hdr.ts_sec = (guint32) rec->ts.secs;
rec_hdr.ts_usec = rec->ts.nsecs / 1000;
return libpcap_dump_write_packet(wdh, rec, &rec_hdr, sizeof rec_hdr,
pd, err);
}
case WTAP_ENCAP_ERF:
erf_priv_free((erf_t*) libpcap->encap_priv);
break;
/* Like classic pcap, but with nanosecond resolution.
Write a record for a packet to a dump file.
Returns TRUE on success, FALSE on failure. */
static gboolean
libpcap_dump_pcap_nsec(wtap_dumper *wdh, const wtap_rec *rec, const guint8 *pd,
int *err, gchar **err_info _U_)
{
struct pcaprec_hdr rec_hdr;
default:
g_free(libpcap->encap_priv);
break;
}
}
rec_hdr.ts_sec = (guint32) rec->ts.secs;
rec_hdr.ts_usec = rec->ts.nsecs;
return libpcap_dump_write_packet(wdh, rec, &rec_hdr, sizeof rec_hdr,
pd, err);
}
/* Modified, but with the old magic, sigh.
Write a record for a packet to a dump file.
Returns TRUE on success, FALSE on failure. */
static gboolean
libpcap_dump_pcap_ss990417(wtap_dumper *wdh, const wtap_rec *rec,
const guint8 *pd, int *err, gchar **err_info _U_)
{
struct pcaprec_modified_hdr rec_hdr;
rec_hdr.hdr.ts_sec = (guint32) rec->ts.secs;
rec_hdr.hdr.ts_usec = rec->ts.nsecs / 1000;
/* XXX - what should we supply here?
Alexey's "libpcap" looks up the interface in the system's
interface list if "ifindex" is non-zero, and prints
the interface name. It ignores "protocol", and uses
"pkt_type" to tag the packet as "host", "broadcast",
"multicast", "other host", "outgoing", or "none of the
above", but that's it.
If the capture we're writing isn't a modified or
RH 6.1 capture, we'd have to do some work to
generate the packet type and interface index - and
we can't generate the interface index unless we
just did the capture ourselves in any case.
I'm inclined to continue to punt; systems other than
those with the older patch can read standard "libpcap"
files, and systems with the older patch, e.g. RH 6.1,
will just have to live with this. */
rec_hdr.ifindex = 0;
rec_hdr.protocol = 0;
rec_hdr.pkt_type = 0;
return libpcap_dump_write_packet(wdh, rec, &rec_hdr.hdr, sizeof rec_hdr,
pd, err);
}
/* New magic, extra crap.
Write a record for a packet to a dump file.
Returns TRUE on success, FALSE on failure. */
static gboolean
libpcap_dump_pcap_ss990915(wtap_dumper *wdh, const wtap_rec *rec,
const guint8 *pd, int *err, gchar **err_info _U_)
{
struct pcaprec_ss990915_hdr rec_hdr;
rec_hdr.hdr.ts_sec = (guint32) rec->ts.secs;
rec_hdr.hdr.ts_usec = rec->ts.nsecs / 1000;
rec_hdr.ifindex = 0;
rec_hdr.protocol = 0;
rec_hdr.pkt_type = 0;
rec_hdr.cpu1 = 0;
rec_hdr.cpu2 = 0;
return libpcap_dump_write_packet(wdh, rec, &rec_hdr.hdr, sizeof rec_hdr,
pd, err);
}
/* Same magic as SS990915, *different* extra crap, sigh.
Write a record for a packet to a dump file.
Returns TRUE on success, FALSE on failure. */
static gboolean
libpcap_dump_pcap_ss991029(wtap_dumper *wdh, const wtap_rec *rec,
const guint8 *pd, int *err, gchar **err_info _U_)
{
struct pcaprec_modified_hdr rec_hdr;
rec_hdr.hdr.ts_sec = (guint32) rec->ts.secs;
rec_hdr.hdr.ts_usec = rec->ts.nsecs / 1000;
/* XXX - what should we supply here?
Alexey's "libpcap" looks up the interface in the system's
interface list if "ifindex" is non-zero, and prints
the interface name. It ignores "protocol", and uses
"pkt_type" to tag the packet as "host", "broadcast",
"multicast", "other host", "outgoing", or "none of the
above", but that's it.
If the capture we're writing isn't a modified or
RH 6.1 capture, we'd have to do some work to
generate the packet type and interface index - and
we can't generate the interface index unless we
just did the capture ourselves in any case.
I'm inclined to continue to punt; systems other than
those with the older patch can read standard "libpcap"
files, and systems with the older patch, e.g. RH 6.1,
will just have to live with this. */
rec_hdr.ifindex = 0;
rec_hdr.protocol = 0;
rec_hdr.pkt_type = 0;
return libpcap_dump_write_packet(wdh, rec, &rec_hdr.hdr, sizeof rec_hdr,
pd, err);
}
/* Nokia libpcap of some sort.
Write a record for a packet to a dump file.
Returns TRUE on success, FALSE on failure. */
static gboolean
libpcap_dump_pcap_nokia(wtap_dumper *wdh, const wtap_rec *rec,
const guint8 *pd, int *err, gchar **err_info _U_)
{
struct pcaprec_nokia_hdr rec_hdr;
const union wtap_pseudo_header *pseudo_header = &rec->rec_header.packet_header.pseudo_header;
rec_hdr.hdr.ts_sec = (guint32) rec->ts.secs;
rec_hdr.hdr.ts_usec = rec->ts.nsecs / 1000;
/* restore the "mysterious stuff" that came with the packet */
memcpy(rec_hdr.stuff, pseudo_header->nokia.stuff, 4);
return libpcap_dump_write_packet(wdh, rec, &rec_hdr.hdr, sizeof rec_hdr,
pd, err);
}
static const struct supported_block_type pcap_blocks_supported[] = {
/*
* We support packet blocks, with no comments or other options.
*/
{ WTAP_BLOCK_PACKET, MULTIPLE_BLOCKS_SUPPORTED, NO_OPTIONS_SUPPORTED }
};
static const struct file_type_subtype_info pcap_info = {
/* Gianluca Varenni suggests that we add "deprecated" to the description. */
"Wireshark/tcpdump/... - pcap", "pcap", "pcap", "cap;dmp",
FALSE, BLOCKS_SUPPORTED(pcap_blocks_supported),
libpcap_dump_can_write_encap, libpcap_dump_open_pcap, NULL
};
static const struct file_type_subtype_info pcap_nsec_info = {
"Wireshark/tcpdump/... - nanosecond pcap", "nsecpcap", "pcap", "cap;dmp",
FALSE, BLOCKS_SUPPORTED(pcap_blocks_supported),
libpcap_dump_can_write_encap, libpcap_dump_open_pcap_nsec, NULL
};
static const struct file_type_subtype_info pcap_aix_info = {
"AIX tcpdump - pcap", "aixpcap", "pcap", "cap;dmp",
FALSE, BLOCKS_SUPPORTED(pcap_blocks_supported),
NULL, NULL, NULL
};
static const struct file_type_subtype_info pcap_ss990417_info = {
"RedHat 6.1 tcpdump - pcap", "rh6_1pcap", "pcap", "cap;dmp",
FALSE, BLOCKS_SUPPORTED(pcap_blocks_supported),
libpcap_dump_can_write_encap, libpcap_dump_open_pcap_ss990417, NULL
};
static const struct file_type_subtype_info pcap_ss990915_info = {
"SuSE 6.3 tcpdump - pcap", "suse6_3pcap", "pcap", "cap;dmp",
FALSE, BLOCKS_SUPPORTED(pcap_blocks_supported),
libpcap_dump_can_write_encap, libpcap_dump_open_pcap_ss990915, NULL
};
static const struct file_type_subtype_info pcap_ss991029_info = {
"Modified tcpdump - pcap", "modpcap", "pcap", "cap;dmp",
FALSE, BLOCKS_SUPPORTED(pcap_blocks_supported),
libpcap_dump_can_write_encap, libpcap_dump_open_pcap_ss991029, NULL
};
static const struct file_type_subtype_info pcap_nokia_info = {
"Nokia tcpdump - pcap", "nokiapcap", "pcap", "cap;dmp",
FALSE, BLOCKS_SUPPORTED(pcap_blocks_supported),
libpcap_dump_can_write_encap, libpcap_dump_open_pcap_nokia, NULL
};
void register_pcap(void)
{
pcap_file_type_subtype = wtap_register_file_type_subtypes(&pcap_info);
pcap_nsec_file_type_subtype = wtap_register_file_type_subtypes(&pcap_nsec_info);
pcap_aix_file_type_subtype = wtap_register_file_type_subtypes(&pcap_aix_info);
pcap_ss990417_file_type_subtype = wtap_register_file_type_subtypes(&pcap_ss990417_info);
pcap_ss990915_file_type_subtype = wtap_register_file_type_subtypes(&pcap_ss990915_info);
pcap_ss991029_file_type_subtype = wtap_register_file_type_subtypes(&pcap_ss991029_info);
pcap_nokia_file_type_subtype = wtap_register_file_type_subtypes(&pcap_nokia_info);
/*
* Register name for backwards compatibility with the
* wtap_filetypes table in Lua.
*/
wtap_register_backwards_compatibility_lua_name("PCAP",
pcap_file_type_subtype);
wtap_register_backwards_compatibility_lua_name("PCAP_NSEC",
pcap_nsec_file_type_subtype);
wtap_register_backwards_compatibility_lua_name("PCAP_AIX",
pcap_aix_file_type_subtype);
wtap_register_backwards_compatibility_lua_name("PCAP_SS990417",
pcap_ss990417_file_type_subtype);
wtap_register_backwards_compatibility_lua_name("PCAP_SS990915",
pcap_ss990915_file_type_subtype);
wtap_register_backwards_compatibility_lua_name("PCAP_SS991029",
pcap_ss991029_file_type_subtype);
wtap_register_backwards_compatibility_lua_name("PCAP_NOKIA",
pcap_nokia_file_type_subtype);
}
/*

View File

@ -97,7 +97,5 @@ struct pcaprec_nokia_hdr {
};
wtap_open_return_val libpcap_open(wtap *wth, int *err, gchar **err_info);
gboolean libpcap_dump_open(wtap_dumper *wdh, int *err, gchar **err_info);
int libpcap_dump_can_write_encap(int encap);
#endif

View File

@ -2114,7 +2114,7 @@ pcap_byteswap_nflog_pseudoheader(wtap_rec *rec, guint8 *pd)
}
int
pcap_process_pseudo_header(FILE_T fh, int file_type, int wtap_encap,
pcap_process_pseudo_header(FILE_T fh, gboolean is_nokia, int wtap_encap,
guint packet_size, wtap_rec *rec, int *err, gchar **err_info)
{
int phdr_len = 0;
@ -2122,7 +2122,7 @@ pcap_process_pseudo_header(FILE_T fh, int file_type, int wtap_encap,
switch (wtap_encap) {
case WTAP_ENCAP_ATM_PDUS:
if (file_type == WTAP_FILE_TYPE_SUBTYPE_PCAP_NOKIA) {
if (is_nokia) {
/*
* Nokia IPSO ATM.
*/
@ -2144,7 +2144,7 @@ pcap_process_pseudo_header(FILE_T fh, int file_type, int wtap_encap,
break;
case WTAP_ENCAP_ETHERNET:
if (file_type == WTAP_FILE_TYPE_SUBTYPE_PCAP_NOKIA) {
if (is_nokia) {
/*
* Nokia IPSO. Pseudo header has already been read, but it's not considered
* part of the packet size, so reread it to store the data for later (when saving)
@ -2267,13 +2267,13 @@ pcap_process_pseudo_header(FILE_T fh, int file_type, int wtap_encap,
}
void
pcap_read_post_process(int file_type, int wtap_encap,
pcap_read_post_process(gboolean is_nokia, int wtap_encap,
wtap_rec *rec, guint8 *pd, gboolean bytes_swapped, int fcs_len)
{
switch (wtap_encap) {
case WTAP_ENCAP_ATM_PDUS:
if (file_type == WTAP_FILE_TYPE_SUBTYPE_PCAP_NOKIA) {
if (is_nokia) {
/*
* Nokia IPSO ATM.
*

View File

@ -19,10 +19,11 @@
extern guint wtap_max_snaplen_for_encap(int wtap_encap);
extern int pcap_process_pseudo_header(FILE_T fh, int file_type, int wtap_encap,
guint packet_size, wtap_rec *rec, int *err, gchar **err_info);
extern int pcap_process_pseudo_header(FILE_T fh, gboolean is_nokia,
int wtap_encap, guint packet_size, wtap_rec *rec,
int *err, gchar **err_info);
extern void pcap_read_post_process(int file_type, int wtap_encap,
extern void pcap_read_post_process(gboolean is_nokia, int wtap_encap,
wtap_rec *rec, guint8 *pd, gboolean bytes_swapped, int fcs_len);
extern int pcap_get_phdr_size(int encap,

View File

@ -26,6 +26,7 @@
#include "wtap-int.h"
#include "file_wrappers.h"
#include "required_file_handlers.h"
#include "pcap-common.h"
#include "pcap-encap.h"
#include "pcapng.h"
@ -52,8 +53,6 @@ pcapng_close(wtap *wth);
static gboolean
pcapng_encap_is_ft_specific(int encap);
void register_pcapng(void);
/*
* Minimum block size = size of block header + size of block trailer.
*/
@ -1409,7 +1408,7 @@ pcapng_read_packet_block(FILE_T fh, pcapng_block_header_t *bh,
memset((void *)&wblock->rec->rec_header.packet_header.pseudo_header, 0, sizeof(union wtap_pseudo_header));
pseudo_header_len = pcap_process_pseudo_header(fh,
WTAP_FILE_TYPE_SUBTYPE_PCAPNG,
FALSE, /* not a Nokia pcap - not a pcap at all */
iface_info.wtap_encap,
packet.cap_len,
wblock->rec,
@ -1650,7 +1649,7 @@ pcapng_read_packet_block(FILE_T fh, pcapng_block_header_t *bh,
}
}
pcap_read_post_process(WTAP_FILE_TYPE_SUBTYPE_PCAPNG, iface_info.wtap_encap,
pcap_read_post_process(FALSE, iface_info.wtap_encap,
wblock->rec, ws_buffer_start_ptr(wblock->frame_buffer),
section_info->byte_swapped, fcslen);
@ -1786,7 +1785,7 @@ pcapng_read_simple_packet_block(FILE_T fh, pcapng_block_header_t *bh,
memset((void *)&wblock->rec->rec_header.packet_header.pseudo_header, 0, sizeof(union wtap_pseudo_header));
pseudo_header_len = pcap_process_pseudo_header(fh,
WTAP_FILE_TYPE_SUBTYPE_PCAPNG,
FALSE,
iface_info.wtap_encap,
simple_packet.cap_len,
wblock->rec,
@ -1811,7 +1810,7 @@ pcapng_read_simple_packet_block(FILE_T fh, pcapng_block_header_t *bh,
return FALSE;
}
pcap_read_post_process(WTAP_FILE_TYPE_SUBTYPE_PCAPNG, iface_info.wtap_encap,
pcap_read_post_process(FALSE, iface_info.wtap_encap,
wblock->rec, ws_buffer_start_ptr(wblock->frame_buffer),
section_info->byte_swapped, iface_info.fcslen);
@ -2848,7 +2847,7 @@ pcapng_open(wtap *wth, int *err, gchar **err_info)
wth->subtype_read = pcapng_read;
wth->subtype_seek_read = pcapng_seek_read;
wth->subtype_close = pcapng_close;
wth->file_type_subtype = WTAP_FILE_TYPE_SUBTYPE_PCAPNG;
wth->file_type_subtype = pcapng_file_type_subtype;
/* Always initialize the list of Decryption Secret Blocks such that a
* wtap_dumper can refer to it right after opening the capture file. */
@ -4984,8 +4983,119 @@ gboolean pcapng_encap_is_ft_specific(int encap)
return FALSE;
}
/*
* pcapng supports several block types, and supports more than one
* of them.
*
* It also supports comments for many block types, as well as other
* option types.
*/
/* Options for section blocks. */
static const struct supported_option_type section_block_options_supported[] = {
{ OPT_COMMENT, MULTIPLE_OPTIONS_SUPPORTED },
{ OPT_SHB_HARDWARE, ONE_OPTION_SUPPORTED },
{ OPT_SHB_USERAPPL, ONE_OPTION_SUPPORTED }
};
/* Options for interface blocks. */
static const struct supported_option_type interface_block_options_supported[] = {
{ OPT_COMMENT, MULTIPLE_OPTIONS_SUPPORTED },
{ OPT_IDB_NAME, ONE_OPTION_SUPPORTED },
{ OPT_IDB_DESCR, ONE_OPTION_SUPPORTED },
{ OPT_IDB_IP4ADDR, MULTIPLE_OPTIONS_SUPPORTED },
{ OPT_IDB_IP6ADDR, MULTIPLE_OPTIONS_SUPPORTED },
{ OPT_IDB_MACADDR, ONE_OPTION_SUPPORTED },
{ OPT_IDB_EUIADDR, ONE_OPTION_SUPPORTED },
{ OPT_IDB_SPEED, ONE_OPTION_SUPPORTED },
{ OPT_IDB_TSRESOL, ONE_OPTION_SUPPORTED },
{ OPT_IDB_TZONE, ONE_OPTION_SUPPORTED },
{ OPT_IDB_FILTER, ONE_OPTION_SUPPORTED },
{ OPT_IDB_OS, ONE_OPTION_SUPPORTED },
{ OPT_IDB_FCSLEN, ONE_OPTION_SUPPORTED },
{ OPT_IDB_TSOFFSET, ONE_OPTION_SUPPORTED },
{ OPT_IDB_HARDWARE, ONE_OPTION_SUPPORTED }
};
/* Options for name resolution blocks. */
static const struct supported_option_type name_resolution_block_options_supported[] = {
{ OPT_COMMENT, MULTIPLE_OPTIONS_SUPPORTED },
{ OPT_NS_DNSNAME, ONE_OPTION_SUPPORTED },
{ OPT_NS_DNSIP4ADDR, ONE_OPTION_SUPPORTED },
{ OPT_NS_DNSIP6ADDR, ONE_OPTION_SUPPORTED }
};
/* Options for interface statistics blocks. */
static const struct supported_option_type interface_statistics_block_options_supported[] = {
{ OPT_COMMENT, MULTIPLE_OPTIONS_SUPPORTED },
{ OPT_ISB_STARTTIME, ONE_OPTION_SUPPORTED },
{ OPT_ISB_ENDTIME, ONE_OPTION_SUPPORTED },
{ OPT_ISB_IFRECV, ONE_OPTION_SUPPORTED },
{ OPT_ISB_IFDROP, ONE_OPTION_SUPPORTED },
{ OPT_ISB_FILTERACCEPT, ONE_OPTION_SUPPORTED },
{ OPT_ISB_OSDROP, ONE_OPTION_SUPPORTED },
{ OPT_ISB_USRDELIV, ONE_OPTION_SUPPORTED }
};
/* Options for decryption secrets blocks. */
static const struct supported_option_type decryption_secrets_block_options_supported[] = {
{ OPT_COMMENT, MULTIPLE_OPTIONS_SUPPORTED }
};
/* Options for packet blocks. */
static const struct supported_option_type packet_block_options_supported[] = {
/* XXX - pending use of wtap_block_t's for packets */
{ OPT_COMMENT, MULTIPLE_OPTIONS_SUPPORTED }
};
/* Options for file-type-sepcific reports. */
static const struct supported_option_type ft_specific_report_block_options_supported[] = {
{ OPT_COMMENT, MULTIPLE_OPTIONS_SUPPORTED }
};
/* Options for file-type-sepcific event. */
static const struct supported_option_type ft_specific_event_block_options_supported[] = {
{ OPT_COMMENT, MULTIPLE_OPTIONS_SUPPORTED }
};
static const struct supported_block_type pcapng_blocks_supported[] = {
/* Multiple sections. */
{ WTAP_BLOCK_SECTION, MULTIPLE_BLOCKS_SUPPORTED, OPTION_TYPES_SUPPORTED(section_block_options_supported) },
/* Multiple interfaces. */
{ WTAP_BLOCK_IF_ID_AND_INFO, MULTIPLE_BLOCKS_SUPPORTED, OPTION_TYPES_SUPPORTED(interface_block_options_supported) },
/* Multiple blocks of name resolution information */
{ WTAP_BLOCK_NAME_RESOLUTION, MULTIPLE_BLOCKS_SUPPORTED, OPTION_TYPES_SUPPORTED(name_resolution_block_options_supported) },
/* Multiple blocks of interface statistics. */
{ WTAP_BLOCK_IF_STATISTICS, MULTIPLE_BLOCKS_SUPPORTED, OPTION_TYPES_SUPPORTED(interface_statistics_block_options_supported) },
/* Multiple blocks of decryption secrets. */
{ WTAP_BLOCK_DECRYPTION_SECRETS, MULTIPLE_BLOCKS_SUPPORTED, OPTION_TYPES_SUPPORTED(decryption_secrets_block_options_supported) },
/* And, obviously, multiple packets. */
{ WTAP_BLOCK_PACKET, MULTIPLE_BLOCKS_SUPPORTED, OPTION_TYPES_SUPPORTED(packet_block_options_supported) },
/* Multiple file-type specific reports (including local ones). */
{ WTAP_BLOCK_FT_SPECIFIC_REPORT, MULTIPLE_BLOCKS_SUPPORTED, OPTION_TYPES_SUPPORTED(ft_specific_report_block_options_supported) },
/* Multiple file-type specific events (including local ones). */
{ WTAP_BLOCK_FT_SPECIFIC_EVENT, MULTIPLE_BLOCKS_SUPPORTED, OPTION_TYPES_SUPPORTED(ft_specific_event_block_options_supported) }
};
static const struct file_type_subtype_info pcapng_info = {
"Wireshark/... - pcapng", "pcapng", "pcapng", "ntar",
FALSE, BLOCKS_SUPPORTED(pcapng_blocks_supported),
pcapng_dump_can_write_encap, pcapng_dump_open, NULL
};
void register_pcapng(void)
{
pcapng_file_type_subtype = wtap_register_file_type_subtypes(&pcapng_info);
wtap_register_backwards_compatibility_lua_name("PCAPNG",
pcapng_file_type_subtype);
}
/*

View File

@ -73,7 +73,5 @@ struct pcapng_option_header {
#define MIN_DSB_SIZE ((guint32)(MIN_BLOCK_SIZE + sizeof(pcapng_decryption_secrets_block_t)))
wtap_open_return_val pcapng_open(wtap *wth, int *err, gchar **err_info);
gboolean pcapng_dump_open(wtap_dumper *wdh, int *err, gchar **err_info);
int pcapng_dump_can_write_encap(int encap);
#endif

View File

@ -0,0 +1,33 @@
/* required_file_handlers.h
* Functions and variables defined by required file handlers (pcap,
* nanosecond pcap, pcapng).
*
* Wireshark - Network traffic analyzer
* By Gerald Combs <gerald@wireshark.org>
* Copyright 1998 Gerald Combs
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#ifndef __REQUIRED_FILE_HANDLERS_H__
#define __REQUIRED_FILE_HANDLERS_H__
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/*
* These are for use within libwiretap only; they are not exported.
*/
extern void register_pcap(void);
extern void register_pcapng(void);
extern int pcap_file_type_subtype; /* regular pcap */
extern int pcap_nsec_file_type_subtype; /* pcap with nanosecond resolution */
extern int pcapng_file_type_subtype; /* pcapng */
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __REQUIRED_FILE_HANDLERS_H__ */

View File

@ -14,7 +14,5 @@
#include "ws_symbol_export.h"
wtap_open_return_val snoop_open(wtap *wth, int *err, gchar **err_info);
gboolean snoop_dump_open(wtap_dumper *wdh, int *err, gchar **err_info);
int snoop_dump_can_write_encap(int encap);
#endif

View File

@ -301,14 +301,6 @@ extern "C" {
different subtypes need to be written in a different
fashion. */
#define WTAP_FILE_TYPE_SUBTYPE_UNKNOWN 0
#define WTAP_FILE_TYPE_SUBTYPE_PCAP 1
#define WTAP_FILE_TYPE_SUBTYPE_PCAPNG 2
#define WTAP_FILE_TYPE_SUBTYPE_PCAP_NSEC 3
#define WTAP_FILE_TYPE_SUBTYPE_PCAP_AIX 4
#define WTAP_FILE_TYPE_SUBTYPE_PCAP_SS991029 5
#define WTAP_FILE_TYPE_SUBTYPE_PCAP_NOKIA 6
#define WTAP_FILE_TYPE_SUBTYPE_PCAP_SS990417 7
#define WTAP_FILE_TYPE_SUBTYPE_PCAP_SS990915 8
/* timestamp precision (currently only these values are supported) */
#define WTAP_TSPREC_UNKNOWN -2
@ -2197,6 +2189,12 @@ WS_DLL_PUBLIC
const char *wtap_file_type_subtype_name(int file_type_subtype);
WS_DLL_PUBLIC
int wtap_name_to_file_type_subtype(const char *name);
WS_DLL_PUBLIC
int wtap_pcap_file_type_subtype(void);
WS_DLL_PUBLIC
int wtap_pcap_nsec_file_type_subtype(void);
WS_DLL_PUBLIC
int wtap_pcapng_file_type_subtype(void);
/**
* Return an indication of whether this capture file format supports