Make it possible to merge libpcap files with different encapsulation types by making the output file a pcapng file and construkting SHB and IDB

git-svn-id: http://anonsvn.wireshark.org/wireshark/trunk@44338 f5534014-38df-0310-8fa8-9805f1628bb7
This commit is contained in:
etxrab 2012-08-08 14:06:29 +00:00
parent 1dbd5cb48e
commit 990e03675e
2 changed files with 116 additions and 13 deletions

123
file.c
View File

@ -1258,6 +1258,8 @@ cf_merge_files(char **out_filenamep, int in_file_count,
gint64 progbar_nextstep;
gint64 progbar_quantum;
gchar *display_basename;
int selected_frame_type;
gboolean fake_interface_ids = FALSE;
/* open the input files */
if (!merge_open_in_files(in_file_count, in_filenames, &in_files,
@ -1288,17 +1290,105 @@ cf_merge_files(char **out_filenamep, int in_file_count,
return CF_ERROR;
}
pdh = wtap_dump_fdopen(out_fd, file_type,
merge_select_frame_type(in_file_count, in_files),
merge_max_snapshot_length(in_file_count, in_files),
FALSE /* compressed */, &open_err);
if (pdh == NULL) {
ws_close(out_fd);
merge_close_in_files(in_file_count, in_files);
g_free(in_files);
cf_open_failure_alert_box(out_filename, open_err, err_info, TRUE,
file_type);
return CF_ERROR;
selected_frame_type = merge_select_frame_type(in_file_count, in_files);
/* If we are trying to merge a number of libpcap files with different encapsulation types
* change the output file type to pcapng and create SHB and IDB:s for the new file use the
* interface index stored in in_files per file to change the phdr before writing the datablock.
* XXX should it be an option to convert to pcapng?
*
* We need something similar when merging pcapng files possibly with an option to say
* the same interface(s) used in all in files. SHBs comments should be merged together.
*/
if((selected_frame_type == WTAP_ENCAP_PER_PACKET)&&(file_type == WTAP_FILE_PCAP)){
/* Write output in pcapng format */
wtapng_section_t *shb_hdr;
wtapng_iface_descriptions_t *idb_inf, *idb_inf_merge_file;
wtapng_if_descr_t int_data, *file_int_data;
GString *comment_gstr;
int i;
fake_interface_ids = TRUE;
/* Create SHB info */
shb_hdr = wtap_file_get_shb_info(in_files[0].wth);
comment_gstr = g_string_new("");
g_string_append_printf(comment_gstr, "%s \n",shb_hdr->opt_comment);
g_string_append_printf(comment_gstr, "File created by merging: \n");
file_type = WTAP_FILE_PCAPNG;
for (i = 0; i < in_file_count; i++) {
g_string_append_printf(comment_gstr, "File%d: %s \n",i+1,in_files[i].filename);
}
shb_hdr->section_length = -1;
/* options */
shb_hdr->opt_comment = g_string_free(comment_gstr, FALSE); /* NULL if not available */
shb_hdr->shb_hardware = NULL; /* NULL if not available, UTF-8 string containing the description of the hardware used to create this section. */
shb_hdr->shb_os = NULL; /* NULL if not available, UTF-8 string containing the name of the operating system used to create this section. */
shb_hdr->shb_user_appl = "Wireshark"; /* NULL if not available, UTF-8 string containing the name of the application used to create this section. */
/* create fake IDB info */
idb_inf = g_new(wtapng_iface_descriptions_t,1);
idb_inf->number_of_interfaces = in_file_count; /* TODO make this the number of DIFFERENT encapsulation types
* check that snaplength is the same too?
*/
idb_inf->interface_data = g_array_new(FALSE, FALSE, sizeof(wtapng_if_descr_t));
for (i = 0; i < in_file_count; i++) {
idb_inf_merge_file = wtap_file_get_idb_info(in_files[i].wth);
/* read the interface data from the in file to our combined interfca data */
file_int_data = &g_array_index (idb_inf_merge_file->interface_data, wtapng_if_descr_t, 0);
int_data.wtap_encap = file_int_data->wtap_encap;
int_data.time_units_per_second = file_int_data->time_units_per_second;
int_data.link_type = file_int_data->link_type;
int_data.snap_len = file_int_data->snap_len;
int_data.if_name = g_strdup(file_int_data->if_name);
int_data.opt_comment = NULL;
int_data.if_description = NULL;
int_data.if_speed = 0;
int_data.if_tsresol = 6;
int_data.if_filter_str = NULL;
int_data.bpf_filter_len = 0;
int_data.if_filter_bpf_bytes = NULL;
int_data.if_os = NULL;
int_data.if_fcslen = -1;
int_data.num_stat_entries = 0; /* Number of ISB:s */
int_data.interface_statistics = NULL;
g_array_append_val(idb_inf->interface_data, int_data);
g_free(idb_inf_merge_file);
/* Set fake interface Id in per file data */
in_files[i].interface_id = i;
}
pdh = wtap_dump_fdopen_ng(out_fd, file_type,
selected_frame_type,
merge_max_snapshot_length(in_file_count, in_files),
FALSE /* compressed */, shb_hdr, idb_inf /* wtapng_iface_descriptions_t *idb_inf */, &open_err);
if (pdh == NULL) {
ws_close(out_fd);
merge_close_in_files(in_file_count, in_files);
g_free(in_files);
cf_open_failure_alert_box(out_filename, open_err, err_info, TRUE,
file_type);
return CF_ERROR;
}
}else{
pdh = wtap_dump_fdopen(out_fd, file_type,
selected_frame_type,
merge_max_snapshot_length(in_file_count, in_files),
FALSE /* compressed */, &open_err);
if (pdh == NULL) {
ws_close(out_fd);
merge_close_in_files(in_file_count, in_files);
g_free(in_files);
cf_open_failure_alert_box(out_filename, open_err, err_info, TRUE,
file_type);
return CF_ERROR;
}
}
/* Get the sum of the sizes of all the files. */
@ -1382,6 +1472,17 @@ cf_merge_files(char **out_filenamep, int in_file_count,
break;
}
/* If we have WTAP_ENCAP_PER_PACKETend the infiles are of type WTAP_FILE_PCAP
* we need to set the interface id in the paket header = the interface index we used
* in the IDBs interface description for this file(encapsulation type).
*/
if(fake_interface_ids){
struct wtap_pkthdr *phdr;
phdr = wtap_phdr(in_file->wth);
phdr->interface_id = in_file->interface_id;
phdr->presence_flags = phdr->presence_flags | WTAP_HAS_INTERFACE_ID;
}
if (!wtap_dump(pdh, wtap_phdr(in_file->wth), wtap_pseudoheader(in_file->wth),
wtap_buf_ptr(in_file->wth), &write_err)) {
got_write_error = TRUE;

View File

@ -44,8 +44,10 @@ typedef struct merge_in_file_s {
wtap *wth;
gint64 data_offset;
in_file_state_e state;
guint32 packet_num; /* current packet number */
gint64 size; /* file size */
guint32 packet_num; /* current packet number */
gint64 size; /* file size */
guint32 interface_id; /* identifier of the interface.
* Used for fake interfaces when writing WTAP_ENCAP_PER_PACKET */
} merge_in_file_t;
/** Open a number of input files to merge.