From Francesco Fondelli (bug 2349):
authorStig Bjørlykke <stig@bjorlykke.org>
Tue, 11 Mar 2008 18:23:16 +0000 (18:23 -0000)
committerStig Bjørlykke <stig@bjorlykke.org>
Tue, 11 Mar 2008 18:23:16 +0000 (18:23 -0000)
Attached is a patch to export packets data as "C Arrays".  I often have
the need to [re]send data captured with wireshark using a raw/pf_packet socket.
Output format is one char[] per packet, it looks like almost the same as
the one produced by "Follow TCP stream".

svn path=/trunk/; revision=24604

AUTHORS
file.c
file.h
gtk/main.h
gtk/menu.c
gtk/print_dlg.c
gtk/win32-file-dlg.c
gtk/win32-file-dlg.h
print.c
print.h

diff --git a/AUTHORS b/AUTHORS
index 4319ec8826556f50196ab7212dd65f538b979094..e4db07988b39411407ae04352bc02330e2e24cfa 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
@@ -2293,6 +2293,7 @@ Francesco Fondelli        <francesco.fondelli [AT] gmail.com> {
        RSVP/OSPF Extensions for Support of Diffserv-aware MPLS-TE, RFC 4124
        Linux Packet Generator support
        rval_to_str() and alike
+       Export the capture file into C Arrays format
 }
 
 Bill Meier             <wmeier [AT] newsguy.com> {
diff --git a/file.c b/file.c
index fa71a63f4198aab2cddbbd2b8a06a2ae3dbbe544..cffbc033ce73df019672a7acc862e70cd282bc17 100644 (file)
--- a/file.c
+++ b/file.c
@@ -2399,6 +2399,65 @@ cf_write_csv_packets(capture_file *cf, print_args_t *print_args)
   return CF_PRINT_OK;
 }
 
+static gboolean
+write_carrays_packet(capture_file *cf _U_, frame_data *fdata,
+                    union wtap_pseudo_header *pseudo_header _U_, 
+                    const guint8 *pd, void *argsp)
+{
+  FILE *fh = argsp;
+
+  proto_tree_write_carrays(pd, fdata->cap_len, fdata->num, fh);
+  return !ferror(fh);
+}
+
+cf_print_status_t
+cf_write_carrays_packets(capture_file *cf, print_args_t *print_args)
+{
+  FILE        *fh;
+  psp_return_t ret;
+
+  fh = eth_fopen(print_args->file, "w");
+
+  if (fh == NULL)
+    return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
+
+  write_carrays_preamble(fh);
+
+  if (ferror(fh)) {
+    fclose(fh);
+    return CF_PRINT_WRITE_ERROR;
+  }
+
+  /* Iterate through the list of packets, printing the packets we were
+     told to print. */
+  ret = process_specified_packets(cf, &print_args->range, 
+                                 "Writing C Arrays",
+                                 "selected packets", TRUE,
+                                  write_carrays_packet, fh);
+  switch (ret) {
+  case PSP_FINISHED:
+    /* Completed successfully. */
+    break;
+  case PSP_STOPPED:
+    /* Well, the user decided to abort the printing. */
+    break;
+  case PSP_FAILED:
+    /* Error while printing. */
+    fclose(fh);
+    return CF_PRINT_WRITE_ERROR;
+  }
+
+  write_carrays_finale(fh);
+
+  if (ferror(fh)) {
+    fclose(fh);
+    return CF_PRINT_WRITE_ERROR;
+  }
+
+  fclose(fh);
+  return CF_PRINT_OK;
+}
+
 /* Scan through the packet list and change all columns that use the
    "command-line-specified" time stamp format to use the current
    value of that format. */
diff --git a/file.h b/file.h
index 03bb8a7fd7d7b573d7723a90ceba91d0dadb82b7..89e5b89ce433970f6b1e46aa043293c1216d68d8 100644 (file)
--- a/file.h
+++ b/file.h
@@ -335,6 +335,15 @@ cf_print_status_t cf_write_psml_packets(capture_file *cf, print_args_t *print_ar
  */
 cf_print_status_t cf_write_csv_packets(capture_file *cf, print_args_t *print_args);
 
+/**
+ * Print (export) the capture file into C Arrays format.
+ *
+ * @param cf the capture file
+ * @param print_args the arguments what and how to export
+ * @return one of cf_print_status_t
+ */
+cf_print_status_t cf_write_carrays_packets(capture_file *cf, print_args_t *print_args);
+
 /**
  * Find Packet in protocol tree.
  * 
index dfb8b4568c2618457acb070f61bf94f7ca6e7c06..e2268bef278f0c49f9773d87058291309d490d2e 100644 (file)
@@ -221,6 +221,13 @@ extern void export_pdml_cmd_cb(GtkWidget *widget, gpointer data);
  */
 extern void export_csv_cmd_cb(GtkWidget *widget, gpointer data);
 
+/** User requested "Export as C Arrays" by menu.
+ *
+ * @param widget parent widget (unused)
+ * @param data unused
+ */
+extern void export_carrays_cmd_cb(GtkWidget *widget, gpointer data);
+
 /** User requested "Expand Tree" by menu.
  *
  * @param widget parent widget (unused)
index 88d104196069ed2832e7e8d10a198ad713a97694..df4c57683588071fd287c5ea137974579d2f6358 100644 (file)
@@ -468,6 +468,8 @@ static GtkItemFactoryEntry menu_items[] =
                              0, NULL, NULL),
     ITEM_FACTORY_ENTRY("/File/Export/as \"_CSV\" (Comma Separated Values packet summary) file...",
                              NULL, export_csv_cmd_cb, 0, NULL, NULL),
+    ITEM_FACTORY_ENTRY("/File/Export/as \"C _Arrays\" (packet bytes) file...", NULL, export_carrays_cmd_cb,
+                             0, NULL, NULL),
     ITEM_FACTORY_ENTRY("/File/Export/<separator>", NULL, NULL, 0, "<Separator>", NULL),
     ITEM_FACTORY_ENTRY("/File/Export/as XML - \"P_SML\" (packet summary) file...", NULL, export_psml_cmd_cb,
                              0, NULL, NULL),
index 11bf7ae08d69d2871fd8829352f2c298973a86ee..6c988b39b8de6b6f0264963b35b64168273c9b7a 100644 (file)
@@ -67,7 +67,8 @@ typedef enum {
   output_action_export_ps,      /* export to postscript */
   output_action_export_psml,    /* export to packet summary markup language */
   output_action_export_pdml,    /* export to packet data markup language */
-  output_action_export_csv      /* export to csv file */
+  output_action_export_csv,     /* export to csv file */
+  output_action_export_carrays  /* export to C array file */
 } output_action_e;
 
 
@@ -95,6 +96,7 @@ static void print_destroy_cb(GtkWidget *win, gpointer user_data);
 #define PRINT_PDML_RB_KEY         "printer_pdml_radio_button"
 #define PRINT_PSML_RB_KEY         "printer_psml_radio_button"
 #define PRINT_CSV_RB_KEY          "printer_csv_radio_button"
+#define PRINT_CARRAYS_RB_KEY      "printer_carrays_radio_button"
 #define PRINT_DEST_CB_KEY         "printer_destination_check_button"
 
 #define PRINT_SUMMARY_CB_KEY      "printer_summary_check_button"
@@ -411,6 +413,54 @@ export_csv_cmd_cb(GtkWidget *widget _U_, gpointer data _U_)
   SIGNAL_CONNECT(export_csv_win, "destroy", print_destroy_cb, &export_csv_win);
 }
 
+/*
+ * Keep a static pointer to the current "Export carrays" window, if any, so that if
+ * somebody tries to do "File:Export to carrays" while there's already a "Export carrays" window
+ * up, we just pop up the existing one, rather than creating a new one.
+ */
+static GtkWidget *export_carrays_win = NULL;
+
+static print_args_t export_carrays_args;
+
+static gboolean export_carrays_prefs_init = FALSE;
+
+void
+export_carrays_cmd_cb(GtkWidget *widget _U_, gpointer data _U_)
+{
+  print_args_t *args = &export_carrays_args;
+
+#if GTK_MAJOR_VERSION >= 2 && _WIN32
+  win32_export_file(GDK_WINDOW_HWND(top_level->window), export_type_carrays);
+  return;
+#endif
+
+  if (export_carrays_win != NULL) {
+    /* There's already a "Export carrays" dialog box; reactivate it. */
+    reactivate_window(export_carrays_win);
+    return;
+  }
+
+  /* get settings from preferences (and other initial values) only once */
+  if(export_carrays_prefs_init == FALSE) {
+      export_carrays_prefs_init = TRUE;
+      args->format              = PR_FMT_TEXT;
+      args->to_file             = TRUE;
+      args->file                = g_strdup("");
+      args->cmd                 = g_strdup("");
+      args->print_summary       = FALSE;
+      args->print_dissections   = print_dissections_none;
+      args->print_hex           = FALSE;
+      args->print_formfeed      = FALSE;
+  }
+
+  /* init the printing range */
+  packet_range_init(&args->range);
+
+  export_carrays_win = open_print_dialog("Wireshark: Export as \"C Arrays\" File", 
+                                        output_action_export_carrays, args);
+  SIGNAL_CONNECT(export_carrays_win, "destroy", print_destroy_cb, &export_carrays_win);
+}
+
 static void
 print_browse_file_cb(GtkWidget *file_bt, GtkWidget *file_te)
 {
@@ -432,7 +482,7 @@ open_print_dialog(const char *title, output_action_e action, print_args_t *args)
   GtkWidget     *main_vb;
 
   GtkWidget     *printer_fr, *printer_vb, *export_format_lb;
-  GtkWidget     *text_rb, *ps_rb, *pdml_rb, *psml_rb, *csv_rb;
+  GtkWidget     *text_rb, *ps_rb, *pdml_rb, *psml_rb, *csv_rb, *carrays_rb;
   GtkWidget     *printer_tb, *dest_cb;
 #ifndef _WIN32
   GtkWidget     *cmd_lb, *cmd_te;
@@ -535,6 +585,16 @@ open_print_dialog(const char *title, output_action_e action, print_args_t *args)
   gtk_box_pack_start(GTK_BOX(printer_vb), csv_rb, FALSE, FALSE, 0);
   /* gtk_widget_show(csv_rb); */
 
+  carrays_rb = RADIO_BUTTON_NEW_WITH_MNEMONIC(text_rb, "C Arrays", accel_group);
+  if (action == output_action_export_carrays)
+    gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(carrays_rb), TRUE);
+  gtk_tooltips_set_tip (tooltips, carrays_rb,
+      "Print output in C Arrays format, "
+      "a text file suitable for use in C/C++ programs. "
+      "One char[] for each packet.", NULL);
+  gtk_box_pack_start(GTK_BOX(printer_vb), carrays_rb, FALSE, FALSE, 0);
+  /* gtk_widget_show(carrays_rb); */
+
   /* printer table */
 #ifndef _WIN32
   printer_tb = gtk_table_new(2, 3, FALSE);
@@ -741,6 +801,7 @@ open_print_dialog(const char *title, output_action_e action, print_args_t *args)
   OBJECT_SET_DATA(ok_bt, PRINT_PDML_RB_KEY, pdml_rb);
   OBJECT_SET_DATA(ok_bt, PRINT_PSML_RB_KEY, psml_rb);
   OBJECT_SET_DATA(ok_bt, PRINT_CSV_RB_KEY, csv_rb);
+  OBJECT_SET_DATA(ok_bt, PRINT_CARRAYS_RB_KEY, carrays_rb);
   OBJECT_SET_DATA(ok_bt, PRINT_DEST_CB_KEY, dest_cb);
 #ifndef _WIN32
   OBJECT_SET_DATA(ok_bt, PRINT_CMD_TE_KEY, cmd_te);
@@ -869,6 +930,7 @@ print_ok_cb(GtkWidget *ok_bt, gpointer parent_w)
   gchar             *dirname;
   gboolean          export_as_pdml = FALSE, export_as_psml = FALSE;
   gboolean          export_as_csv = FALSE;
+  gboolean          export_as_carrays = FALSE;
 #ifdef _WIN32
   gboolean          win_printer = FALSE;
   int               tmp_fd;
@@ -946,6 +1008,9 @@ print_ok_cb(GtkWidget *ok_bt, gpointer parent_w)
   button = (GtkWidget *)OBJECT_GET_DATA(ok_bt, PRINT_CSV_RB_KEY);
   if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (button)))
     export_as_csv = TRUE;
+  button = (GtkWidget *)OBJECT_GET_DATA(ok_bt, PRINT_CARRAYS_RB_KEY);
+  if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (button)))
+    export_as_carrays = TRUE;
 
   button = (GtkWidget *)OBJECT_GET_DATA(ok_bt, PRINT_SUMMARY_CB_KEY);
   args->print_summary = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (button));
@@ -985,6 +1050,8 @@ print_ok_cb(GtkWidget *ok_bt, gpointer parent_w)
     status = cf_write_psml_packets(&cfile, args);
   else if (export_as_csv)
     status = cf_write_csv_packets(&cfile, args);
+  else if (export_as_carrays)
+    status = cf_write_carrays_packets(&cfile, args);
   else {
     switch (args->format) {
 
index 950c851a85da572b60157c2b806ba148563d6b8f..0aa819a0f65334788e734b49706cae9640bb45c7 100644 (file)
@@ -505,9 +505,12 @@ win32_export_file(HWND h_wnd, export_type_e export_type) {
                }
                status = cf_print_packets(&cfile, &print_args);
                break;
-            case export_type_csv:     /* CSV */
+            case export_type_csv:       /* CSV */
                 status = cf_write_csv_packets(&cfile, &print_args);
                 break;
+            case export_type_carrays:   /* C Arrays */
+                status = cf_write_carrays_packets(&cfile, &print_args);
+                break;
            case export_type_psml:      /* PSML */
                status = cf_write_psml_packets(&cfile, &print_args);
                break;
index edce057cab05db636a144cbd966071ae907acce8..15f9260d91bafc3138574881dcd96668a2663987 100644 (file)
@@ -30,7 +30,8 @@ typedef enum {
     export_type_ps,
     export_type_csv,
     export_type_psml,
-    export_type_pdml
+    export_type_pdml,
+    export_type_carrays
 } export_type_e;
 
 /** Open the "Open" dialog box.
diff --git a/print.c b/print.c
index a4fca368de850c51a6f4b43eb80990ffc1cc1f9f..4a24b8023ffd105b0a171706b5915ef29dee765f 100644 (file)
--- a/print.c
+++ b/print.c
@@ -628,6 +628,45 @@ write_csv_finale(FILE *fh _U_)
 
 }
 
+void
+write_carrays_preamble(FILE *fh _U_)
+{
+
+}
+
+void
+proto_tree_write_carrays(const guint8 *pd, guint32 len, guint32 num, FILE *fh)
+{
+        guint32 i = 0;
+
+       if (!len)
+               return;
+
+       fprintf(fh, "char pkt%u[] = {\n", num);
+
+        for (i = 0; i < len; i++) {
+
+               fprintf(fh, "0x%02x", *(pd + i));
+
+               if (i == (len - 1)) {
+                       fprintf(fh, " };\n\n");
+                       break;
+               }
+
+               if (!((i + 1) % 8)) {
+                       fprintf(fh, ", \n");
+               } else {
+                       fprintf(fh, ", ");
+               }
+       }
+}
+
+void
+write_carrays_finale(FILE *fh _U_)
+{
+
+}
+
 /*
  * Find the data source for a specified field, and return a pointer
  * to the data in it. Returns NULL if the data is out of bounds.
diff --git a/print.h b/print.h
index 1187651ff09740f5aa16044ec85009402f0c9e5f..cf81d7d79e637e8181cf820f07bd780c728dab16 100644 (file)
--- a/print.h
+++ b/print.h
@@ -137,6 +137,10 @@ extern void write_csv_preamble(FILE *fh);
 extern void proto_tree_write_csv(epan_dissect_t *edt, FILE *fh);
 extern void write_csv_finale(FILE *fh);
 
+extern void write_carrays_preamble(FILE *fh);
+extern void proto_tree_write_carrays(const guint8 *pd, guint32 len, guint32 num, FILE *fh);
+extern void write_carrays_finale(FILE *fh);
+
 extern void write_fields_preamble(output_fields_t* fields, FILE *fh);
 extern void proto_tree_write_fields(output_fields_t* fields, epan_dissect_t *edt, FILE *fh);
 extern void write_fields_finale(output_fields_t* fields, FILE *fh);