From 990e03675e8122844cff9750c4025e5f48be984c Mon Sep 17 00:00:00 2001 From: etxrab Date: Wed, 8 Aug 2012 14:06:29 +0000 Subject: [PATCH] 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 --- file.c | 123 +++++++++++++++++++++++++++++++++++++++++++++++++++----- merge.h | 6 ++- 2 files changed, 116 insertions(+), 13 deletions(-) diff --git a/file.c b/file.c index 369037f70b..89677a07c0 100644 --- a/file.c +++ b/file.c @@ -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; diff --git a/merge.h b/merge.h index 08cfd85b19..a9a36f2c93 100644 --- a/merge.h +++ b/merge.h @@ -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.