Exemplo n.º 1
0
void CaptureFile::resetState() {
    /* Die if we're in the middle of reading a file. */
    //	g_assert(state != FILE_READ_IN_PROGRESS); //FIXME controllo?

    if (wth) {
        wtap_close(wth);
        wth = NULL;
    }


#if GLIB_CHECK_VERSION(2,10,0)
    if (plist != NULL)
        g_slice_free_chain(frame_data, plist, next);
#else
    if (plist_chunk != NULL) {
        frame_data *fdata = plist;
        while (fdata) {
            g_strfreev(fdata->col_expr.col_expr);
            g_strfreev(fdata->col_expr.col_expr_val);
            fdata = fdata->next;
        }
        /* memory chunks have been deprecated in favor of the slice allocator,
         * which has been added in 2.10
         */
        g_mem_chunk_destroy(plist_chunk);
        plist_chunk = NULL;
    }
#endif
    if (rfcode != NULL) {
        dfilter_free(rfcode);
        rfcode = NULL;
    }
    plist = NULL;
    plist_end = NULL;
    //	cf_unselect_packet(cf);	/* nothing to select */
    //    first_displayed = NULL;
    //    last_displayed = NULL;
    //
    //    /* No frame selected, no field in that frame selected. */
    //    current_frame = NULL;
    //    current_row = 0;
    //    finfo_selected = NULL;

    /* Clear the packet list. */
    //	packet_list_freeze();
    //	packet_list_clear();
    //	packet_list_thaw();

    f_datalen = 0;
    count = 0;
    //nstime_set_zero(&elapsed_time);

    //  reset_tap_listeners();

    /* We have no file open. */
    state = FILE_CLOSED;

    //fileset_file_closed();
}
Exemplo n.º 2
0
/*
 * Scan through and close each input file
 */
void
merge_close_in_files(int count, merge_in_file_t in_files[])
{
  int i;
  for (i = 0; i < count; i++) {
    wtap_close(in_files[i].wth);
  }
}
Exemplo n.º 3
0
/* classic wtap: close capture file */
static void
nettrace_close(wtap *wth)
{
	nettrace_3gpp_32_423_file_info_t *file_info = (nettrace_3gpp_32_423_file_info_t *)wth->priv;

	wtap_close(file_info->wth_tmp_file);

	/* delete the temp file */
	ws_unlink(file_info->tmpname);

}
Exemplo n.º 4
0
static void
cleanup_in_file(merge_in_file_t *in_file)
{
    g_assert(in_file != NULL);

    wtap_close(in_file->wth);
    in_file->wth = NULL;

    g_array_free(in_file->idb_index_map, TRUE);
    in_file->idb_index_map = NULL;
}
Exemplo n.º 5
0
/*
 * Scan through the arguments and open the input files
 */
gboolean
merge_open_in_files(int in_file_count, char *const *in_file_names,
                    merge_in_file_t **in_files, int *err, gchar **err_info,
                    int *err_fileno)
{
  gint i;
  gint j;
  size_t files_size = in_file_count * sizeof(merge_in_file_t);
  merge_in_file_t *files;
  gint64 size;

  files = (merge_in_file_t *)g_malloc(files_size);
  *in_files = files;

  for (i = 0; i < in_file_count; i++) {
    files[i].filename    = in_file_names[i];
    files[i].wth         = wtap_open_offline(in_file_names[i], WTAP_TYPE_AUTO, err, err_info, FALSE);
    files[i].data_offset = 0;
    files[i].state       = PACKET_NOT_PRESENT;
    files[i].packet_num  = 0;
    if (!files[i].wth) {
      /* Close the files we've already opened. */
      for (j = 0; j < i; j++)
        wtap_close(files[j].wth);
      *err_fileno = i;
      return FALSE;
    }
    size = wtap_file_size(files[i].wth, err);
    if (size == -1) {
      for (j = 0; j + 1 > j && j <= i; j++)
        wtap_close(files[j].wth);
      *err_fileno = i;
      return FALSE;
    }
    files[i].size = size;
  }
  return TRUE;
}
Exemplo n.º 6
0
/* classic wtap: close capture file */
static void
nettrace_close(wtap *wth)
{
	nettrace_3gpp_32_423_file_info_t *file_info = (nettrace_3gpp_32_423_file_info_t *)wth->priv;

	wtap_close(file_info->wth_tmp_file);

	/*Clear the shb info, it's been freed by wtap_close*/
	wth->shb_hdr.opt_comment = NULL;
	wth->shb_hdr.shb_hardware = NULL;
	wth->shb_hdr.shb_os = NULL;
	wth->shb_hdr.shb_user_appl = NULL;

	/* delete the temp file */
	ws_unlink(file_info->tmpname);

}
Exemplo n.º 7
0
/* new file arrived */
gboolean capture_info_new_file(const char *new_filename)
{
    int err;
    gchar *err_info;
    gchar *err_msg;


    if(info_data.wtap != NULL) {
        wtap_close(info_data.wtap);
    }

    info_data.wtap = wtap_open_offline(new_filename, &err, &err_info, FALSE);
    if (!info_data.wtap) {
        err_msg = g_strdup_printf(cf_open_error_message(err, err_info, FALSE, WTAP_FILE_PCAP),
                                  new_filename);
        g_warning("capture_info_new_file: %d (%s)", err, err_msg);
        g_free (err_msg);
        return FALSE;
    } else
        return TRUE;
}
Exemplo n.º 8
0
/* new file arrived */
gboolean capture_info_new_file(const char *new_filename, info_data_t* cap_info)
{
    int err;
    gchar *err_info;
    gchar *err_msg;


    if(cap_info->wtap != NULL) {
        wtap_close(cap_info->wtap);
    }

    cap_info->wtap = wtap_open_offline(new_filename, WTAP_TYPE_AUTO, &err, &err_info, FALSE);
    if (!cap_info->wtap) {
        err_msg = g_strdup_printf(cf_open_error_message(err, err_info, FALSE, WTAP_FILE_TYPE_SUBTYPE_UNKNOWN),
                                  new_filename);
        g_warning("capture_info_new_file: %d (%s)", err, err_msg);
        g_free (err_msg);
        return FALSE;
    } else
        return TRUE;
}
Exemplo n.º 9
0
int CaptureFile::close() {
    wtap_close(wth);
    cleanup_dissection();
    return 0;
}
Exemplo n.º 10
0
/**
 * This function processes a specified capture file with the specified fields of interest
 * and display filter.  This function calls the appropriate language-specific callback
 * function in <cb> to manipulate data structures in the caller's scope.
 * 
 * @param filename valid pcap file
 * @param nfields a positive integer describing the number of fields
 * @param fields an array of strings
 * @return 0 on success, else error.
 */
glong sharktools_get_cb(gchar *filename, gulong nfields, const gchar **fields,
                       gchar *dfilterorig, sharktools_callbacks *cb)
{
  gsize i;
  capture_file cfile;
  gchar *cf_name = NULL;
  char *dfilter;
  dfilter_t *rfcode = NULL;

  // Create an stdata struct on the stack
  st_data_t stdata;

  dprintf("%s: entering...\n", __FUNCTION__);

  dprintf("%s: dfilterorig: %s\n", __FUNCTION__, dfilterorig);

  dfilter = strdup(dfilterorig);

  dprintf("%s: dfilter: %s\n", __FUNCTION__, dfilter);

  if(!dfilter_compile(dfilter, &rfcode))
    {
      sprintf(errmsg, "%s", dfilter_error_msg);
      printf("errmsg");
      if(rfcode)
        dfilter_free(rfcode);
      return -1;
    }

  // Defined in cfile.c, looks easy enough to use
  cap_file_init(&cfile);

  cf_name = filename;

  // Open pcap file
  int err;
  if(cf_open(&cfile, cf_name, FALSE, &err) != CF_OK)
    {
      //sprintf(errmsg, "%s", dfilter_error_msg);
      if(rfcode)
        dfilter_free(rfcode);
      return -1;
    }

  dprintf("nfields = %ld\n", nfields);

  stdata_init(&stdata, nfields);

  stdata_add_fields(&stdata, fields, nfields);

  dprintf("stdata.fields->len = %d\n", stdata.fields->len);

  dprintf("stdata.field_values_str = %lX\n", (glong)stdata.field_values_str);
  dprintf("stdata.field_types = %lX\n", (glong)stdata.field_types);
  
  dprintf("%s: opened file\n", __FUNCTION__);

  cfile.rfcode = rfcode;

  gchar        *err_info;
  gint64       data_offset;

  // Read and process each packet one at a time
  while(wtap_read(cfile.wth, &err, &err_info, &data_offset))
    {
      dprintf("*******************************\n");

      // (Re)-set all the stdata.field_{values,types} fields
      for(i = 0; i < nfields; i++)
        {
          stdata.field_values_str[i] = 0;
          stdata.field_types[i] = FT_NONE;
        }

      gboolean passed = FALSE;
      
      passed = process_packet(&cfile, data_offset, &stdata);

      if(passed)
	{
          gpointer row = cb->row_new(cb);

	  for(i = 0; i < nfields; i++)
	    {
              gpointer key;
              key = cb->keys[i];

              dprintf("key = %p\n", key);

	      dprintf("values[%ld] = %p\n", i, stdata.field_values_str[i]);
	      dprintf("types[%ld] = %ld\n", i, stdata.field_types[i]);

              cb->row_set(cb, row, key,
                          stdata.field_types[i],
                          stdata.field_values_native[i],
                          stdata.field_values_str[i]
                          );
            }

          cb->row_add(cb, row);
        }
    }

  if(rfcode)
    dfilter_free(rfcode);
  wtap_close(cfile.wth);
  cfile.wth = NULL;

  stdata_cleanup(&stdata);

  dprintf("%s: ...leaving.\n", __FUNCTION__);

  return 0;
}
Exemplo n.º 11
0
/**
 * This function returns the number of packets in <filename> that would
 * pass through the filter <dfilter>.  This was necessary to mitigate memory
 * usage in Matlab, where dynamically-growing or shrinking data structures
 * (apparently) don't exist.  If it looks hacky, it is :-)
 *
 * NB: there is a race condition between running sharktools_count() and
 * sharktools_get_cb(), since we close and reopen the pcap file in between.
 */
glong sharktools_count(char *filename, char *dfilter)
{
  capture_file cfile;
  gchar *cf_name = NULL;
  dfilter_t *rfcode = NULL;
  glong count = 0;

  dprintf("%s: entering...\n", __FUNCTION__);

  dprintf("%s: dfilter: %s\n", __FUNCTION__, dfilter);
  if(!dfilter_compile(dfilter, &rfcode))
    {
      sprintf(errmsg, "%s", dfilter_error_msg);
      printf("errmsg");
      if(rfcode)
        dfilter_free(rfcode);
      return -1;
    }

  // Defined in cfile.c, looks easy enough to use
  cap_file_init(&cfile);

  cf_name = filename;

  // Open pcap file
  int err;
  if(cf_open(&cfile, cf_name, FALSE, &err) != CF_OK)
    {
      //sprintf(errmsg, "%s", dfilter_error_msg);
      if(rfcode)
        dfilter_free(rfcode);
      return -1;
    }

  dprintf("%s: opened file\n", __FUNCTION__);

  cfile.rfcode = rfcode;

  gchar        *err_info;
  gint64       data_offset;

  // Read and process each packet one at a time
  while(wtap_read(cfile.wth, &err, &err_info, &data_offset))
    {
      gboolean passed = TRUE;
      
      // Only process packets if there's a display filter specified
      if(dfilter != NULL && *dfilter != '\0')
        {
          // Passing in NULL for st_data_t means we're just counting
          passed = process_packet(&cfile, data_offset, NULL);
        }

      if(passed)
	{
          count++;
          //dprintf("count! %d\n", count);
        }
    }

  if(rfcode)
    dfilter_free(rfcode);
  wtap_close(cfile.wth);
  cfile.wth = NULL;

  return count;
}
Exemplo n.º 12
0
/* close the info */
void capture_info_close(void)
{
    capture_info_ui_destroy(&info_data.ui);
    if(info_data.wtap)
        wtap_close(info_data.wtap);
}
Exemplo n.º 13
0
int
main(int argc, char *argv[])
{
  GString *comp_info_str;
  GString *runtime_info_str;
  wtap  *wth;
  int    err;
  gchar *err_info;
  int    i;
  int    opt;
  int    overall_error_status;
  static const struct option long_options[] = {
      {"help", no_argument, NULL, 'h'},
      {"version", no_argument, NULL, 'v'},
      {0, 0, 0, 0 }
  };

#ifdef HAVE_PLUGINS
  char  *init_progfile_dir_error;
#endif

  /* Set the C-language locale to the native environment. */
  setlocale(LC_ALL, "");

  /* Get the compile-time version information string */
  comp_info_str = get_compiled_version_info(NULL, NULL);

  /* Get the run-time version information string */
  runtime_info_str = get_runtime_version_info(NULL);

  /* Add it to the information to be reported on a crash. */
  ws_add_crash_info("Captype (Wireshark) %s\n"
         "\n"
         "%s"
         "\n"
         "%s",
      get_ws_vcs_version_info(), comp_info_str->str, runtime_info_str->str);
  g_string_free(comp_info_str, TRUE);
  g_string_free(runtime_info_str, TRUE);

#ifdef _WIN32
  arg_list_utf_16to8(argc, argv);
  create_app_running_mutex();
#endif /* _WIN32 */

  /*
   * Get credential information for later use.
   */
  init_process_policies();
  init_open_routines();

#ifdef HAVE_PLUGINS
  if ((init_progfile_dir_error = init_progfile_dir(argv[0], main))) {
    g_warning("captype: init_progfile_dir(): %s", init_progfile_dir_error);
    g_free(init_progfile_dir_error);
  } else {
    /* Register all the plugin types we have. */
    wtap_register_plugin_types(); /* Types known to libwiretap */

    init_report_err(failure_message,NULL,NULL,NULL);

    /* Scan for plugins.  This does *not* call their registration routines;
       that's done later.

       Don't report failures to load plugins because most (non-wiretap)
       plugins *should* fail to load (because we're not linked against
       libwireshark and dissector plugins need libwireshark). */
    scan_plugins(DONT_REPORT_LOAD_FAILURE);

    /* Register all libwiretap plugin modules. */
    register_all_wiretap_modules();
  }
#endif

  /* Process the options */
  while ((opt = getopt_long(argc, argv, "hv", long_options, NULL)) !=-1) {

    switch (opt) {

      case 'h':
        printf("Captype (Wireshark) %s\n"
               "Print the file types of capture files.\n"
               "See https://www.wireshark.org for more information.\n",
               get_ws_vcs_version_info());
        print_usage(stdout);
        exit(0);
        break;

      case 'v':
        comp_info_str = get_compiled_version_info(NULL, NULL);
        runtime_info_str = get_runtime_version_info(NULL);
        show_version("Captype (Wireshark)", comp_info_str, runtime_info_str);
        g_string_free(comp_info_str, TRUE);
        g_string_free(runtime_info_str, TRUE);
        exit(0);
        break;

      case '?':              /* Bad flag - print usage message */
        print_usage(stderr);
        exit(1);
        break;
    }
  }

  if (argc < 2) {
    print_usage(stderr);
    return 1;
  }

  overall_error_status = 0;

  for (i = 1; i < argc; i++) {
    wth = wtap_open_offline(argv[i], WTAP_TYPE_AUTO, &err, &err_info, FALSE);

    if(wth) {
      printf("%s: %s\n", argv[i], wtap_file_type_subtype_short_string(wtap_file_type_subtype(wth)));
      wtap_close(wth);
    } else {
      if (err == WTAP_ERR_FILE_UNKNOWN_FORMAT)
        printf("%s: unknown\n", argv[i]);
      else {
        fprintf(stderr, "captype: Can't open %s: %s\n", argv[i],
                wtap_strerror(err));
        if (err_info != NULL) {
          fprintf(stderr, "(%s)\n", err_info);
          g_free(err_info);
        }
        overall_error_status = 1; /* remember that an error has occurred */
      }
    }

  }

  return overall_error_status;
}
Exemplo n.º 14
0
int
main(int argc, char *argv[])
{
  int ser_fd;
  GError *err = NULL;
  int werr;
  gchar *err_info;
  gint64 data_offset;
  wtap *w;
  GOptionContext *opt_ctxt;
  gint64 ts_start_us = 0;
  gint64 time_start_us = 0;
  opt_ctxt = g_option_context_new ("FILE");
  g_option_context_add_main_entries(opt_ctxt, app_options, NULL);
  if (!g_option_context_parse(opt_ctxt, &argc, &argv, &err)) {
    g_printerr("Failed to parse options: %s\n", err->message);
    return EXIT_FAILURE;
  }
  g_option_context_free(opt_ctxt);
  
  w = wtap_open_offline(argv[1], WTAP_TYPE_AUTO, &werr, &err_info, FALSE);
  if (!w) {
    g_printerr("Failed to open packet file: %d\n", werr);
    return EXIT_FAILURE;
  }

  if (pseudo) {
    ser_fd = open_pseudo_terminal(&err);
    if (ser_fd < 0) {
      g_printerr("Failed open pseudo terminal: %s\n", err->message);
      return EXIT_FAILURE;
    }
  } else {
    ser_fd = profibus_serial_open(device, speed, &err);
    if (ser_fd < 0) {
      g_printerr("Failed open serial port: %s\n", err->message);
      return EXIT_FAILURE;
    }
  }
  
  while(TRUE) {
    guint8 *data;
    struct wtap_pkthdr *hdr;
    if (!wtap_read(w, &werr, &err_info, &data_offset)) {
      if (err == 0) break;
      g_printerr("Failed to read packet file: %d\n", werr);
      return EXIT_FAILURE;
    }
    hdr = wtap_phdr(w);
    data = wtap_buf_ptr(w);
    if (timing) {
      if (time_start_us == 0) {
	ts_start_us = hdr->ts.secs * 1000000LL +  hdr->ts.nsecs / 1000;
	time_start_us = g_get_monotonic_time();
      } else {
	gint64 ts = hdr->ts.secs * 1000000LL +  hdr->ts.nsecs / 1000;
	gint64 next = time_start_us + (ts - ts_start_us);
	gint64 now = g_get_monotonic_time();
	gint64 delay = next - now;
	if (delay > 0) {
	  poll(NULL, 0, delay / 1000);
	}
      }
    }
    if (write(ser_fd, data, hdr->len) != hdr->len) {
      g_printerr("Failed to write to serial device: %s\n", strerror(errno));
      break;
    }
    /* g_debug("Write %d", hdr->len); */
  }
  wtap_close(w);
  g_message("EOF");
  close(ser_fd);
  return EXIT_SUCCESS;
}
Exemplo n.º 15
0
/* close the info */
void capture_info_close(info_data_t* cap_info)
{
    capture_info_ui_destroy(&cap_info->ui);
    if(cap_info->wtap)
        wtap_close(cap_info->wtap);
}
Exemplo n.º 16
0
int
main(int argc, char *argv[])
{
    GString *comp_info_str;
    GString *runtime_info_str;
    char *init_progfile_dir_error;
    wtap *wth = NULL;
    wtap_dumper *pdh = NULL;
    wtap_rec dump_rec;
    Buffer buf;
    int err;
    gchar *err_info;
    gint64 data_offset;
    const wtap_rec *rec;
    guint wrong_order_count = 0;
    gboolean write_output_regardless = TRUE;
    guint i;
    GArray                      *shb_hdrs = NULL;
    wtapng_iface_descriptions_t *idb_inf = NULL;
    GArray                      *nrb_hdrs = NULL;
    int                          ret = EXIT_SUCCESS;

    GPtrArray *frames;
    FrameRecord_t *prevFrame = NULL;

    int opt;
    static const struct option long_options[] = {
        {"help", no_argument, NULL, 'h'},
        {"version", no_argument, NULL, 'v'},
        {0, 0, 0, 0 }
    };
    int file_count;
    char *infile;
    const char *outfile;

    cmdarg_err_init(failure_warning_message, failure_message_cont);

    /* Get the compile-time version information string */
    comp_info_str = get_compiled_version_info(NULL, NULL);

    /* Get the run-time version information string */
    runtime_info_str = get_runtime_version_info(NULL);

    /* Add it to the information to be reported on a crash. */
    ws_add_crash_info("Reordercap (Wireshark) %s\n"
         "\n"
         "%s"
         "\n"
         "%s",
      get_ws_vcs_version_info(), comp_info_str->str, runtime_info_str->str);
    g_string_free(comp_info_str, TRUE);
    g_string_free(runtime_info_str, TRUE);

    /*
     * Get credential information for later use.
     */
    init_process_policies();

    /*
     * Attempt to get the pathname of the directory containing the
     * executable file.
     */
    init_progfile_dir_error = init_progfile_dir(argv[0]);
    if (init_progfile_dir_error != NULL) {
        fprintf(stderr,
                "reordercap: Can't get pathname of directory containing the reordercap program: %s.\n",
                init_progfile_dir_error);
        g_free(init_progfile_dir_error);
    }

    init_report_message(failure_warning_message, failure_warning_message,
                        NULL, NULL, NULL);

    wtap_init(TRUE);

    /* Process the options first */
    while ((opt = getopt_long(argc, argv, "hnv", long_options, NULL)) != -1) {
        switch (opt) {
            case 'n':
                write_output_regardless = FALSE;
                break;
            case 'h':
                printf("Reordercap (Wireshark) %s\n"
                       "Reorder timestamps of input file frames into output file.\n"
                       "See https://www.wireshark.org for more information.\n",
                       get_ws_vcs_version_info());
                print_usage(stdout);
                goto clean_exit;
            case 'v':
                comp_info_str = get_compiled_version_info(NULL, NULL);
                runtime_info_str = get_runtime_version_info(NULL);
                show_version("Reordercap (Wireshark)", comp_info_str, runtime_info_str);
                g_string_free(comp_info_str, TRUE);
                g_string_free(runtime_info_str, TRUE);
                goto clean_exit;
            case '?':
                print_usage(stderr);
                ret = INVALID_OPTION;
                goto clean_exit;
        }
    }

    /* Remaining args are file names */
    file_count = argc - optind;
    if (file_count == 2) {
        infile  = argv[optind];
        outfile = argv[optind+1];
    }
    else {
        print_usage(stderr);
        ret = INVALID_OPTION;
        goto clean_exit;
    }

    /* Open infile */
    /* TODO: if reordercap is ever changed to give the user a choice of which
       open_routine reader to use, then the following needs to change. */
    wth = wtap_open_offline(infile, WTAP_TYPE_AUTO, &err, &err_info, TRUE);
    if (wth == NULL) {
        cfile_open_failure_message("reordercap", infile, err, err_info);
        ret = OPEN_ERROR;
        goto clean_exit;
    }
    DEBUG_PRINT("file_type_subtype is %d\n", wtap_file_type_subtype(wth));

    shb_hdrs = wtap_file_get_shb_for_new_file(wth);
    idb_inf = wtap_file_get_idb_info(wth);
    nrb_hdrs = wtap_file_get_nrb_for_new_file(wth);

    /* Open outfile (same filetype/encap as input file) */
    if (strcmp(outfile, "-") == 0) {
      pdh = wtap_dump_open_stdout_ng(wtap_file_type_subtype(wth), wtap_file_encap(wth),
                                     wtap_snapshot_length(wth), FALSE, shb_hdrs, idb_inf, nrb_hdrs, &err);
    } else {
      pdh = wtap_dump_open_ng(outfile, wtap_file_type_subtype(wth), wtap_file_encap(wth),
                              wtap_snapshot_length(wth), FALSE, shb_hdrs, idb_inf, nrb_hdrs, &err);
    }
    g_free(idb_inf);
    idb_inf = NULL;

    if (pdh == NULL) {
        cfile_dump_open_failure_message("reordercap", outfile, err,
                                        wtap_file_type_subtype(wth));
        wtap_block_array_free(shb_hdrs);
        wtap_block_array_free(nrb_hdrs);
        ret = OUTPUT_FILE_ERROR;
        goto clean_exit;
    }

    /* Allocate the array of frame pointers. */
    frames = g_ptr_array_new();

    /* Read each frame from infile */
    while (wtap_read(wth, &err, &err_info, &data_offset)) {
        FrameRecord_t *newFrameRecord;

        rec = wtap_get_rec(wth);

        newFrameRecord = g_slice_new(FrameRecord_t);
        newFrameRecord->num = frames->len + 1;
        newFrameRecord->offset = data_offset;
        if (rec->presence_flags & WTAP_HAS_TS) {
            newFrameRecord->frame_time = rec->ts;
        } else {
            nstime_set_unset(&newFrameRecord->frame_time);
        }

        if (prevFrame && frames_compare(&newFrameRecord, &prevFrame) < 0) {
           wrong_order_count++;
        }

        g_ptr_array_add(frames, newFrameRecord);
        prevFrame = newFrameRecord;
    }
    if (err != 0) {
      /* Print a message noting that the read failed somewhere along the line. */
      cfile_read_failure_message("reordercap", infile, err, err_info);
    }

    printf("%u frames, %u out of order\n", frames->len, wrong_order_count);

    /* Sort the frames */
    if (wrong_order_count > 0) {
        g_ptr_array_sort(frames, frames_compare);
    }

    /* Write out each sorted frame in turn */
    wtap_rec_init(&dump_rec);
    ws_buffer_init(&buf, 1500);
    for (i = 0; i < frames->len; i++) {
        FrameRecord_t *frame = (FrameRecord_t *)frames->pdata[i];

        /* Avoid writing if already sorted and configured to */
        if (write_output_regardless || (wrong_order_count > 0)) {
            frame_write(frame, wth, pdh, &dump_rec, &buf, infile, outfile);
        }
        g_slice_free(FrameRecord_t, frame);
    }
    wtap_rec_cleanup(&dump_rec);
    ws_buffer_free(&buf);

    if (!write_output_regardless && (wrong_order_count == 0)) {
        printf("Not writing output file because input file is already in order.\n");
    }

    /* Free the whole array */
    g_ptr_array_free(frames, TRUE);

    /* Close outfile */
    if (!wtap_dump_close(pdh, &err)) {
        cfile_close_failure_message(outfile, err);
        wtap_block_array_free(shb_hdrs);
        wtap_block_array_free(nrb_hdrs);
        ret = OUTPUT_FILE_ERROR;
        goto clean_exit;
    }
    wtap_block_array_free(shb_hdrs);
    wtap_block_array_free(nrb_hdrs);

    /* Finally, close infile and release resources. */
    wtap_close(wth);

clean_exit:
    wtap_cleanup();
    free_progdirs();
    return ret;
}