Example #1
0
    ph_stats_t*
ph_stats_new(capture_file *cf)
{
    ph_stats_t	*ps;
    guint32	framenum;
    frame_data	*frame;
    guint	tot_packets, tot_bytes;
    progdlg_t	*progbar = NULL;
    gboolean	stop_flag;
    int		count;
    wtap_rec	rec;
    Buffer	buf;
    float	progbar_val;
    GTimeVal	start_time;
    gchar	status_str[100];
    int		progbar_nextstep;
    int		progbar_quantum;

    if (!cf) return NULL;

    pc_proto_id = proto_registrar_get_id_byname("pkt_comment");

    /* Initialize the data */
    ps = g_new(ph_stats_t, 1);
    ps->tot_packets = 0;
    ps->tot_bytes = 0;
    ps->stats_tree = g_node_new(NULL);
    ps->first_time = 0.0;
    ps->last_time = 0.0;

    /* Update the progress bar when it gets to this value. */
    progbar_nextstep = 0;
    /* When we reach the value that triggers a progress bar update,
       bump that value by this amount. */
    progbar_quantum = cf->count/N_PROGBAR_UPDATES;
    /* Count of packets at which we've looked. */
    count = 0;
    /* Progress so far. */
    progbar_val = 0.0f;

    stop_flag = FALSE;
    g_get_current_time(&start_time);

    tot_packets = 0;
    tot_bytes = 0;

    wtap_rec_init(&rec);
    ws_buffer_init(&buf, 1514);

    for (framenum = 1; framenum <= cf->count; framenum++) {
        frame = frame_data_sequence_find(cf->provider.frames, framenum);

        /* Create the progress bar if necessary.
           We check on every iteration of the loop, so that
           it takes no longer than the standard time to create
           it (otherwise, for a large file, we might take
           considerably longer than that standard time in order
           to get to the next progress bar step). */
        if (progbar == NULL)
            progbar = delayed_create_progress_dlg(
                    cf->window, "Computing",
                    "protocol hierarchy statistics",
                    TRUE, &stop_flag, &start_time, progbar_val);

        /* Update the progress bar, but do it only N_PROGBAR_UPDATES
           times; when we update it, we have to run the GTK+ main
           loop to get it to repaint what's pending, and doing so
           may involve an "ioctl()" to see if there's any pending
           input from an X server, and doing that for every packet
           can be costly, especially on a big file. */
        if (count >= progbar_nextstep) {
            /* let's not divide by zero. I should never be started
             * with count == 0, so let's assert that
             */
            g_assert(cf->count > 0);

            progbar_val = (gfloat) count / cf->count;

            if (progbar != NULL) {
                g_snprintf(status_str, sizeof(status_str),
                        "%4u of %u frames", count, cf->count);
                update_progress_dlg(progbar, progbar_val, status_str);
            }

            progbar_nextstep += progbar_quantum;
        }

        if (stop_flag) {
            /* Well, the user decided to abort the statistics.
               computation process  Just stop. */
            break;
        }

        /* Skip frames that are hidden due to the display filter.
           XXX - should the progress bar count only packets that
           passed the display filter?  If so, it should
           probably do so for other loops (see "file.c") that
           look only at those packets. */
        if (frame->passed_dfilter) {

            if (frame->has_ts) {
                if (tot_packets == 0) {
                    double cur_time = nstime_to_sec(&frame->abs_ts);
                    ps->first_time = cur_time;
                    ps->last_time = cur_time;
                }
            }

            /* we don't care about colinfo */
            if (!process_record(cf, frame, NULL, &rec, &buf, ps)) {
                /*
                 * Give up, and set "stop_flag" so we
                 * just abort rather than popping up
                 * the statistics window.
                 */
                stop_flag = TRUE;
                break;
            }

            tot_packets++;
            tot_bytes += frame->pkt_len;
        }

        count++;
    }

    wtap_rec_cleanup(&rec);
    ws_buffer_free(&buf);

    /* We're done calculating the statistics; destroy the progress bar
       if it was created. */
    if (progbar != NULL)
        destroy_progress_dlg(progbar);

    if (stop_flag) {
        /*
         * We quit in the middle; throw away the statistics
         * and return NULL, so our caller doesn't pop up a
         * window with the incomplete statistics.
         */
        ph_stats_free(ps);
        return NULL;
    }

    ps->tot_packets = tot_packets;
    ps->tot_bytes = tot_bytes;

    return ps;
}
Example #2
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;
}