Make it possible to merge libpcap files with different encapsulation types by making...
authorAnders Broman <anders.broman@ericsson.com>
Wed, 8 Aug 2012 14:06:29 +0000 (14:06 -0000)
committerAnders Broman <anders.broman@ericsson.com>
Wed, 8 Aug 2012 14:06:29 +0000 (14:06 -0000)
svn path=/trunk/; revision=44338

file.c
merge.h

diff --git a/file.c b/file.c
index 369037f70b068bda71f487071b020e3f21a1e879..89677a07c03bcf8f5018afe28010f14348bda1dc 100644 (file)
--- 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 08cfd85b19de6dd48a6eaf383dcf9a852e8a9b93..a9a36f2c9308d416ae2b550dd6e9d6397e32ee25 100644 (file)
--- 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.