X-Git-Url: http://git.samba.org/samba.git/?p=obnox%2Fwireshark%2Fwip.git;a=blobdiff_plain;f=file.c;h=075d688f042e96024b3c36567349674a387c21ed;hp=46143eefe4da384c8eea4111289b68d0a5b890fe;hb=b54591c66d25873a99914669738387d1434d3dd1;hpb=2b8b69caac7b67da1e3b7af4309ea405bb942f62 diff --git a/file.c b/file.c index 46143eefe4..075d688f04 100644 --- a/file.c +++ b/file.c @@ -60,6 +60,7 @@ #include "merge.h" #include "alert_box.h" #include "simple_dialog.h" +#include "main_statusbar.h" #include "progress_dlg.h" #include "ui_util.h" #include @@ -72,14 +73,17 @@ #include #include #include +#include #ifdef HAVE_LIBPCAP gboolean auto_scroll_live; #endif +static guint32 cum_bytes; static nstime_t first_ts; static nstime_t prev_dis_ts; -static guint32 cum_bytes; +static nstime_t prev_cap_ts; + static gulong computed_elapsed; static void cf_reset_state(capture_file *cf); @@ -90,24 +94,33 @@ static int read_packet(capture_file *cf, dfilter_t *dfcode, static void rescan_packets(capture_file *cf, const char *action, const char *action_item, gboolean refilter, gboolean redissect); -static gboolean match_protocol_tree(capture_file *cf, frame_data *fdata, +typedef enum { + MR_NOTMATCHED, + MR_MATCHED, + MR_ERROR +} match_result; +static match_result match_protocol_tree(capture_file *cf, frame_data *fdata, void *criterion); static void match_subtree_text(proto_node *node, gpointer data); -static gboolean match_summary_line(capture_file *cf, frame_data *fdata, +static match_result match_summary_line(capture_file *cf, frame_data *fdata, void *criterion); -static gboolean match_ascii_and_unicode(capture_file *cf, frame_data *fdata, +static match_result match_ascii_and_unicode(capture_file *cf, frame_data *fdata, void *criterion); -static gboolean match_ascii(capture_file *cf, frame_data *fdata, +static match_result match_ascii(capture_file *cf, frame_data *fdata, void *criterion); -static gboolean match_unicode(capture_file *cf, frame_data *fdata, +static match_result match_unicode(capture_file *cf, frame_data *fdata, void *criterion); -static gboolean match_binary(capture_file *cf, frame_data *fdata, +static match_result match_binary(capture_file *cf, frame_data *fdata, void *criterion); -static gboolean match_dfilter(capture_file *cf, frame_data *fdata, +static match_result match_dfilter(capture_file *cf, frame_data *fdata, void *criterion); -static gboolean find_packet(capture_file *cf, - gboolean (*match_function)(capture_file *, frame_data *, void *), +static match_result match_marked(capture_file *cf, frame_data *fdata, + void *criterion); +static match_result match_time_reference(capture_file *cf, frame_data *fdata, void *criterion); +static gboolean find_packet(capture_file *cf, + match_result (*match_function)(capture_file *, frame_data *, void *), + void *criterion, search_direction dir); static void cf_open_failure_alert_box(const char *filename, int err, gchar *err_info, gboolean for_writing, @@ -115,12 +128,10 @@ static void cf_open_failure_alert_box(const char *filename, int err, static const char *file_rename_error_message(int err); static void cf_write_failure_alert_box(const char *filename, int err); static void cf_close_failure_alert_box(const char *filename, int err); -#ifdef NEW_PACKET_LIST static void ref_time_packets(capture_file *cf); -#endif /* Update the progress bar this many times when reading a file. */ #define N_PROGBAR_UPDATES 100 -/* We read around 200k/100ms domt update the progress bar more often than that */ +/* We read around 200k/100ms don't update the progress bar more often than that */ #define MIN_QUANTUM 200000 #define MIN_NUMBER_OF_PACKET 1500 @@ -129,10 +140,14 @@ static void ref_time_packets(capture_file *cf); #define FRAME_DATA_CHUNK_SIZE 1024 -/* this callback mechanism should possibly be replaced by the g_signal_...() stuff (if I only would know how :-) */ +/* + * We could probably use g_signal_...() instead of the callbacks below but that + * would require linking our CLI programs to libgobject and creating an object + * instance for the signals. + */ typedef struct { - cf_callback_t cb_fct; - gpointer user_data; + cf_callback_t cb_fct; + gpointer user_data; } cf_callback_data_t; static GList *cf_callbacks = NULL; @@ -140,98 +155,95 @@ static GList *cf_callbacks = NULL; static void cf_callback_invoke(int event, gpointer data) { - cf_callback_data_t *cb; - GList *cb_item = cf_callbacks; + cf_callback_data_t *cb; + GList *cb_item = cf_callbacks; - /* there should be at least one interested */ - g_assert(cb_item != NULL); + /* there should be at least one interested */ + g_assert(cb_item != NULL); - while(cb_item != NULL) { - cb = cb_item->data; - cb->cb_fct(event, data, cb->user_data); - cb_item = g_list_next(cb_item); - } + while(cb_item != NULL) { + cb = cb_item->data; + cb->cb_fct(event, data, cb->user_data); + cb_item = g_list_next(cb_item); + } } void cf_callback_add(cf_callback_t func, gpointer user_data) { - cf_callback_data_t *cb; + cf_callback_data_t *cb; - cb = g_malloc(sizeof(cf_callback_data_t)); - cb->cb_fct = func; - cb->user_data = user_data; + cb = g_malloc(sizeof(cf_callback_data_t)); + cb->cb_fct = func; + cb->user_data = user_data; - cf_callbacks = g_list_append(cf_callbacks, cb); + cf_callbacks = g_list_append(cf_callbacks, cb); } void cf_callback_remove(cf_callback_t func) { - cf_callback_data_t *cb; - GList *cb_item = cf_callbacks; - - while(cb_item != NULL) { - cb = cb_item->data; - if(cb->cb_fct == func) { - cf_callbacks = g_list_remove(cf_callbacks, cb); - g_free(cb); - return; - } - cb_item = g_list_next(cb_item); + cf_callback_data_t *cb; + GList *cb_item = cf_callbacks; + + while(cb_item != NULL) { + cb = cb_item->data; + if(cb->cb_fct == func) { + cf_callbacks = g_list_remove(cf_callbacks, cb); + g_free(cb); + return; } + cb_item = g_list_next(cb_item); + } - g_assert_not_reached(); + g_assert_not_reached(); } void cf_timestamp_auto_precision(capture_file *cf) { -#ifdef NEW_PACKET_LIST - int i; -#endif - int prec = timestamp_get_precision(); + int i; + int prec = timestamp_get_precision(); - /* don't try to get the file's precision if none is opened */ - if(cf->state == FILE_CLOSED) { - return; - } + /* don't try to get the file's precision if none is opened */ + if(cf->state == FILE_CLOSED) { + return; + } - /* if we are in auto mode, set precision of current file */ - if(prec == TS_PREC_AUTO || - prec == TS_PREC_AUTO_SEC || - prec == TS_PREC_AUTO_DSEC || - prec == TS_PREC_AUTO_CSEC || - prec == TS_PREC_AUTO_MSEC || - prec == TS_PREC_AUTO_USEC || - prec == TS_PREC_AUTO_NSEC) - { - switch(wtap_file_tsprecision(cf->wth)) { - case(WTAP_FILE_TSPREC_SEC): - timestamp_set_precision(TS_PREC_AUTO_SEC); - break; - case(WTAP_FILE_TSPREC_DSEC): - timestamp_set_precision(TS_PREC_AUTO_DSEC); - break; - case(WTAP_FILE_TSPREC_CSEC): - timestamp_set_precision(TS_PREC_AUTO_CSEC); - break; - case(WTAP_FILE_TSPREC_MSEC): - timestamp_set_precision(TS_PREC_AUTO_MSEC); - break; - case(WTAP_FILE_TSPREC_USEC): - timestamp_set_precision(TS_PREC_AUTO_USEC); - break; - case(WTAP_FILE_TSPREC_NSEC): - timestamp_set_precision(TS_PREC_AUTO_NSEC); - break; - default: - g_assert_not_reached(); - } + /* if we are in auto mode, set precision of current file */ + if(prec == TS_PREC_AUTO || + prec == TS_PREC_AUTO_SEC || + prec == TS_PREC_AUTO_DSEC || + prec == TS_PREC_AUTO_CSEC || + prec == TS_PREC_AUTO_MSEC || + prec == TS_PREC_AUTO_USEC || + prec == TS_PREC_AUTO_NSEC) + { + switch(wtap_file_tsprecision(cf->wth)) { + case(WTAP_FILE_TSPREC_SEC): + timestamp_set_precision(TS_PREC_AUTO_SEC); + break; + case(WTAP_FILE_TSPREC_DSEC): + timestamp_set_precision(TS_PREC_AUTO_DSEC); + break; + case(WTAP_FILE_TSPREC_CSEC): + timestamp_set_precision(TS_PREC_AUTO_CSEC); + break; + case(WTAP_FILE_TSPREC_MSEC): + timestamp_set_precision(TS_PREC_AUTO_MSEC); + break; + case(WTAP_FILE_TSPREC_USEC): + timestamp_set_precision(TS_PREC_AUTO_USEC); + break; + case(WTAP_FILE_TSPREC_NSEC): + timestamp_set_precision(TS_PREC_AUTO_NSEC); + break; + default: + g_assert_not_reached(); } -#ifdef NEW_PACKET_LIST + } /* Set the column widths of those columns that show the time in "command-line-specified" format. */ for (i = 0; i < cf->cinfo.num_cols; i++) { @@ -239,31 +251,30 @@ cf_timestamp_auto_precision(capture_file *cf) new_packet_list_resize_column(i); } } -#endif } gulong cf_get_computed_elapsed(void) { - return computed_elapsed; + return computed_elapsed; } static void reset_elapsed(void) { - computed_elapsed = 0; + computed_elapsed = 0; } static void compute_elapsed(GTimeVal *start_time) { - gdouble delta_time; - GTimeVal time_now; + gdouble delta_time; + GTimeVal time_now; - g_get_current_time(&time_now); + g_get_current_time(&time_now); - delta_time = (time_now.tv_sec - start_time->tv_sec) * 1e6 + + delta_time = (time_now.tv_sec - start_time->tv_sec) * 1e6 + time_now.tv_usec - start_time->tv_usec; - computed_elapsed = (gulong) (delta_time / 1000); /* ms*/ + computed_elapsed = (gulong) (delta_time / 1000); /* ms*/ } cf_status_t @@ -308,6 +319,8 @@ cf_open(capture_file *cf, const char *fname, gboolean is_tempfile, int *err) cf->count = 0; cf->displayed_count = 0; cf->marked_count = 0; + cf->ignored_count = 0; + cf->ref_time_count = 0; cf->drops_known = FALSE; cf->drops = 0; cf->snap = wtap_snapshot_length(cf->wth); @@ -321,6 +334,7 @@ cf_open(capture_file *cf, const char *fname, gboolean is_tempfile, int *err) nstime_set_zero(&cf->elapsed_time); nstime_set_unset(&first_ts); nstime_set_unset(&prev_dis_ts); + nstime_set_unset(&prev_cap_ts); cum_bytes = 0; #if GLIB_CHECK_VERSION(2,10,0) @@ -335,15 +349,10 @@ cf_open(capture_file *cf, const char *fname, gboolean is_tempfile, int *err) g_assert(cf->plist_chunk); #endif -#ifdef NEW_PACKET_LIST /* Adjust timestamp precision if auto is selected, col width will be adjusted */ cf_timestamp_auto_precision(cf); /* XXX needed ? */ new_packet_list_queue_draw(); -#else - /* change the time formats now, as we might have a new precision */ - cf_change_time_formats(cf); -#endif fileset_file_opened(fname); if(cf->cd_t == WTAP_FILE_BER) { @@ -351,6 +360,9 @@ cf_open(capture_file *cf, const char *fname, gboolean is_tempfile, int *err) ber_set_filename(cf->filename); } + wtap_set_cb_new_ipv4(cf->wth, add_ipv4_name); + wtap_set_cb_new_ipv6(cf->wth, (wtap_new_ipv6_callback_t) add_ipv6_name); + return CF_OK; fail: @@ -388,8 +400,8 @@ cf_reset_state(capture_file *cf) cf->user_saved = FALSE; #if GLIB_CHECK_VERSION(2,10,0) - if (cf->plist != NULL) - g_slice_free_chain(frame_data, cf->plist, next); + if (cf->plist_start != NULL) + g_slice_free_chain(frame_data, cf->plist_start, next); #else /* memory chunks have been deprecated in favor of the slice allocator, * which has been added in 2.10 @@ -399,11 +411,9 @@ cf_reset_state(capture_file *cf) cf->plist_chunk = NULL; } #endif - if (cf->rfcode != NULL) { - dfilter_free(cf->rfcode); - cf->rfcode = NULL; - } - cf->plist = NULL; + dfilter_free(cf->rfcode); + cf->rfcode = NULL; + cf->plist_start = NULL; cf->plist_end = NULL; cf_unselect_packet(cf); /* nothing to select */ cf->first_displayed = NULL; @@ -415,15 +425,9 @@ cf_reset_state(capture_file *cf) cf->finfo_selected = NULL; /* Clear the packet list. */ -#ifdef NEW_PACKET_LIST new_packet_list_freeze(); new_packet_list_clear(); new_packet_list_thaw(); -#else - packet_list_freeze(); - packet_list_clear(); - packet_list_thaw(); -#endif cf->f_datalen = 0; cf->count = 0; @@ -456,34 +460,56 @@ cf_close(capture_file *cf) } /* an out of memory exception occured, wait for a user button press to exit */ -void outofmemory_cb(gpointer dialog _U_, gint btn _U_, gpointer data _U_) +static void outofmemory_cb(gpointer dialog _U_, gint btn _U_, gpointer data _U_) { main_window_exit(); } -static float calc_progbar_val(capture_file *cf, gint64 size, gint64 file_pos){ - - float progbar_val; - - progbar_val = (gfloat) file_pos / (gfloat) size; - if (progbar_val > 1.0) { - /* The file probably grew while we were reading it. - Update file size, and try again. */ - size = wtap_file_size(cf->wth, NULL); - if (size >= 0) - progbar_val = (gfloat) file_pos / (gfloat) size; - /* If it's still > 1, either "wtap_file_size()" failed (in which - case there's not much we can do about it), or the file - *shrank* (in which case there's not much we can do about - it); just clip the progress value at 1.0. */ - if (progbar_val > 1.0f) - progbar_val = 1.0f; - } - return progbar_val; +static float +calc_progbar_val(capture_file *cf, gint64 size, gint64 file_pos, gchar *status_str, gulong status_size) +{ + float progbar_val; + + progbar_val = (gfloat) file_pos / (gfloat) size; + if (progbar_val > 1.0) { + + /* The file probably grew while we were reading it. + * Update file size, and try again. + */ + size = wtap_file_size(cf->wth, NULL); + + /* Another possibility is that we're reading a compressed file and we've + * read more (uncompressed) data from the file than exists in the + * (compressed) file. So check how much data we've actually read. + * + * This is inside this "if val > 1.0" check to avoid the lseek() when + * reading uncompressed files. Testing has (thus far) shown no progress + * bar weirdness resulting from switching from the data offset (when + * reading the first part of the file) to the real file position. + */ + file_pos = wtap_read_so_far(cf->wth, NULL); + + if (size >= 0) + progbar_val = (gfloat) file_pos / (gfloat) size; + + /* If it's still > 1, either "wtap_file_size()" failed (in which + * case there's not much we can do about it), or the file + * *shrank* (in which case there's not much we can do about + * it); just clip the progress value at 1.0. + */ + if (progbar_val > 1.0f) + progbar_val = 1.0f; + } + + g_snprintf(status_str, status_size, + "%" G_GINT64_MODIFIER "dKB of %" G_GINT64_MODIFIER "dKB", + file_pos / 1024, size / 1024); + + return progbar_val; } cf_read_status_t -cf_read(capture_file *cf) +cf_read(capture_file *cf, gboolean from_save) { int err; gchar *err_info; @@ -523,10 +549,13 @@ cf_read(capture_file *cf) reset_tap_listeners(); - cf_callback_invoke(cf_cb_file_read_start, cf); - name_ptr = get_basename(cf->filename); + if (from_save == FALSE) + cf_callback_invoke(cf_cb_file_read_started, cf); + else + cf_callback_invoke(cf_cb_file_save_started, (gpointer)name_ptr); + /* Find the size of the file. */ size = wtap_file_size(cf->wth, NULL); @@ -537,31 +566,31 @@ cf_read(capture_file *cf) if (size >= 0){ progbar_quantum = size/N_PROGBAR_UPDATES; if (progbar_quantum < MIN_QUANTUM) - progbar_quantum = MIN_QUANTUM; + progbar_quantum = MIN_QUANTUM; }else progbar_quantum = 0; /* Progress so far. */ progbar_val = 0.0f; -#ifdef NEW_PACKET_LIST new_packet_list_freeze(); -#else - packet_list_freeze(); -#endif stop_flag = FALSE; g_get_current_time(&start_time); while ((wtap_read(cf->wth, &err, &err_info, &data_offset))) { if (size >= 0) { - count++; + count++; /* Create the progress bar if necessary. - * Check wether it should be created or not every MIN_NUMBER_OF_PACKET + * Check whether it should be created or not every MIN_NUMBER_OF_PACKET */ if ((progbar == NULL) && !(count % MIN_NUMBER_OF_PACKET)){ - progbar_val = calc_progbar_val( cf, size, data_offset); - progbar = delayed_create_progress_dlg("Loading", name_ptr, - TRUE, &stop_flag, &start_time, progbar_val); + progbar_val = calc_progbar_val(cf, size, data_offset, status_str, sizeof(status_str)); + if (from_save == FALSE) + progbar = delayed_create_progress_dlg("Loading", name_ptr, + TRUE, &stop_flag, &start_time, progbar_val); + else + progbar = delayed_create_progress_dlg("Saving", name_ptr, + TRUE, &stop_flag, &start_time, progbar_val); } /* Update the progress bar, but do it only N_PROGBAR_UPDATES times; @@ -570,34 +599,24 @@ cf_read(capture_file *cf) 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 (data_offset >= progbar_nextstep) { - if (progbar != NULL) { - progbar_val = calc_progbar_val( cf, size, data_offset); - /* update the packet lists content on the first run or frequently on very large files */ - /* (on smaller files the display update takes longer than reading the file) */ + if (progbar != NULL) { + progbar_val = calc_progbar_val(cf, size, data_offset, status_str, sizeof(status_str)); + /* update the packet lists content on the first run or frequently on very large files */ + /* (on smaller files the display update takes longer than reading the file) */ #ifdef HAVE_LIBPCAP - if (progbar_quantum > 500000 || displayed_once == 0) { - if ((auto_scroll_live || displayed_once == 0 || cf->displayed_count < 1000) && cf->plist_end != NULL) { - displayed_once = 1; -#ifdef NEW_PACKET_LIST - new_packet_list_thaw(); - if (auto_scroll_live) - new_packet_list_moveto_end(); - new_packet_list_freeze(); -#else - packet_list_thaw(); - if (auto_scroll_live) - packet_list_moveto_end(); - packet_list_freeze(); -#endif /* NEW_PACKET_LIST */ - } + if (progbar_quantum > 500000 || displayed_once == 0) { + if ((auto_scroll_live || displayed_once == 0 || cf->displayed_count < 1000) && cf->plist_end != NULL) { + displayed_once = 1; + new_packet_list_thaw(); + if (auto_scroll_live) + new_packet_list_moveto_end(); + new_packet_list_freeze(); + } } #endif /* HAVE_LIBPCAP */ - g_snprintf(status_str, sizeof(status_str), - "%" G_GINT64_MODIFIER "dKB of %" G_GINT64_MODIFIER "dKB", - data_offset / 1024, size / 1024); - update_progress_dlg(progbar, progbar_val, status_str); - } - progbar_nextstep += progbar_quantum; + update_progress_dlg(progbar, progbar_val, status_str); + } + progbar_nextstep += progbar_quantum; } } @@ -611,27 +630,27 @@ cf_read(capture_file *cf) break; } TRY { - read_packet(cf, dfcode, filtering_tap_listeners, tap_flags, data_offset); + read_packet(cf, dfcode, filtering_tap_listeners, tap_flags, data_offset); } CATCH(OutOfMemoryError) { - gpointer dialog; - - dialog = simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, - "%sOut Of Memory!%s\n" - "\n" - "Sorry, but Wireshark has to terminate now!\n" - "\n" - "Some infos / workarounds can be found at:\n" - "http://wiki.wireshark.org/KnownBugs/OutOfMemory", - simple_dialog_primary_start(), simple_dialog_primary_end()); - /* we have to terminate, as we cannot recover from the memory error */ - simple_dialog_set_cb(dialog, outofmemory_cb, NULL); - while(1) { - main_window_update(); - /* XXX - how to avoid a busy wait? */ - /* Sleep(100); */ - }; - break; + gpointer dialog; + + dialog = simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, + "%sOut Of Memory!%s\n" + "\n" + "Sorry, but Wireshark has to terminate now!\n" + "\n" + "Some infos / workarounds can be found at:\n" + "http://wiki.wireshark.org/KnownBugs/OutOfMemory", + simple_dialog_primary_start(), simple_dialog_primary_end()); + /* we have to terminate, as we cannot recover from the memory error */ + simple_dialog_set_cb(dialog, outofmemory_cb, NULL); + while(1) { + main_window_update(); + /* XXX - how to avoid a busy wait? */ + /* Sleep(100); */ + }; + break; } ENDTRY; } @@ -667,33 +686,27 @@ cf_read(capture_file *cf) cf->current_frame = cf->first_displayed; cf->current_row = 0; -#ifdef NEW_PACKET_LIST new_packet_list_thaw(); -#else - packet_list_thaw(); -#endif - - cf_callback_invoke(cf_cb_file_read_finished, cf); + if (from_save == FALSE) + cf_callback_invoke(cf_cb_file_read_finished, cf); + else + cf_callback_invoke(cf_cb_file_save_finished, cf); /* If we have any displayed packets to select, select the first of those packets by making the first row the selected row. */ if (cf->first_displayed != NULL){ -#ifdef NEW_PACKET_LIST new_packet_list_select_first_row(); -#else - packet_list_select_row(0); -#endif /* NEW_PACKET_LIST */ } if(stop_flag) { simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK, - "%sFile loading was cancelled!%s\n" - "\n" - "The remaining packets in the file were discarded.\n" - "\n" - "As a lot of packets from the original file will be missing,\n" - "remember to be careful when saving the current content to a file.\n", - simple_dialog_primary_start(), simple_dialog_primary_end()); + "%sFile loading was cancelled!%s\n" + "\n" + "The remaining packets in the file were discarded.\n" + "\n" + "As a lot of packets from the original file will be missing,\n" + "remember to be careful when saving the current content to a file.\n", + simple_dialog_primary_start(), simple_dialog_primary_end()); return CF_READ_ERROR; } @@ -705,34 +718,34 @@ cf_read(capture_file *cf) case WTAP_ERR_UNSUPPORTED_ENCAP: g_snprintf(errmsg_errno, sizeof(errmsg_errno), - "The capture file has a packet with a network type that Wireshark doesn't support.\n(%s)", - err_info); + "The capture file has a packet with a network type that Wireshark doesn't support.\n(%s)", + err_info); g_free(err_info); errmsg = errmsg_errno; break; case WTAP_ERR_CANT_READ: errmsg = "An attempt to read from the capture file failed for" - " some unknown reason."; + " some unknown reason."; break; case WTAP_ERR_SHORT_READ: errmsg = "The capture file appears to have been cut short" - " in the middle of a packet."; + " in the middle of a packet."; break; case WTAP_ERR_BAD_RECORD: g_snprintf(errmsg_errno, sizeof(errmsg_errno), - "The capture file appears to be damaged or corrupt.\n(%s)", - err_info); + "The capture file appears to be damaged or corrupt.\n(%s)", + err_info); g_free(err_info); errmsg = errmsg_errno; break; default: g_snprintf(errmsg_errno, sizeof(errmsg_errno), - "An error occurred while reading the" - " capture file: %s.", wtap_strerror(err)); + "An error occurred while reading the" + " capture file: %s.", wtap_strerror(err)); errmsg = errmsg_errno; break; } @@ -761,7 +774,6 @@ cf_continue_tail(capture_file *cf, volatile int to_read, int *err) dfilter_t *dfcode; gboolean filtering_tap_listeners; guint tap_flags; - volatile gboolean visible = FALSE; gboolean compiled; /* Compile the current display filter. @@ -779,59 +791,53 @@ cf_continue_tail(capture_file *cf, volatile int to_read, int *err) *err = 0; -#ifdef NEW_PACKET_LIST new_packet_list_check_end(); - new_packet_list_freeze(); -#else - packet_list_check_end(); - packet_list_freeze(); -#endif + /* Don't freeze/thaw the list when doing live capture */ + /*new_packet_list_freeze();*/ /*g_log(NULL, G_LOG_LEVEL_MESSAGE, "cf_continue_tail: %u new: %u", cf->count, to_read);*/ - while (to_read != 0 && (wtap_read(cf->wth, err, &err_info, &data_offset))) { + while (to_read != 0) { + wtap_cleareof(cf->wth); + if (!wtap_read(cf->wth, err, &err_info, &data_offset)) { + break; + } if (cf->state == FILE_READ_ABORTED) { /* Well, the user decided to exit Wireshark. Break out of the loop, and let the code below (which is called even if there - aren't any packets left to read) exit. */ + aren't any packets left to read) exit. */ break; } TRY{ - if (read_packet(cf, dfcode, filtering_tap_listeners, tap_flags, - data_offset) != -1) { - visible = TRUE; - newly_displayed_packets++; - }else{ - visible = FALSE; - } + if (read_packet(cf, dfcode, filtering_tap_listeners, tap_flags, + data_offset) != -1) { + newly_displayed_packets++; + } } CATCH(OutOfMemoryError) { - gpointer dialog; - - dialog = simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, - "%sOut Of Memory!%s\n" - "\n" - "Sorry, but Wireshark has to terminate now!\n" - "\n" - "The capture file is not lost, it can be found at:\n" - "%s\n" - "\n" - "Some infos / workarounds can be found at:\n" - "http://wiki.wireshark.org/KnownBugs/OutOfMemory", - simple_dialog_primary_start(), simple_dialog_primary_end(), cf->filename); - /* we have to terminate, as we cannot recover from the memory error */ - simple_dialog_set_cb(dialog, outofmemory_cb, NULL); - while(1) { - main_window_update(); - /* XXX - how to avoid a busy wait? */ - /* Sleep(100); */ - }; -#ifdef NEW_PACKET_LIST - new_packet_list_thaw(); -#else - packet_list_thaw(); -#endif - return CF_READ_ABORTED; + gpointer dialog; + + dialog = simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, + "%sOut Of Memory!%s\n" + "\n" + "Sorry, but Wireshark has to terminate now!\n" + "\n" + "The capture file is not lost, it can be found at:\n" + "%s\n" + "\n" + "Some infos / workarounds can be found at:\n" + "http://wiki.wireshark.org/KnownBugs/OutOfMemory", + simple_dialog_primary_start(), simple_dialog_primary_end(), cf->filename); + /* we have to terminate, as we cannot recover from the memory error */ + simple_dialog_set_cb(dialog, outofmemory_cb, NULL); + while(1) { + main_window_update(); + /* XXX - how to avoid a busy wait? */ + /* Sleep(100); */ + }; + /* Don't freeze/thaw the list when doing live capture */ + /*new_packet_list_thaw();*/ + return CF_READ_ABORTED; } ENDTRY; to_read--; @@ -843,28 +849,20 @@ cf_continue_tail(capture_file *cf, volatile int to_read, int *err) } /*g_log(NULL, G_LOG_LEVEL_MESSAGE, "cf_continue_tail: count %u state: %u err: %u", - cf->count, cf->state, *err);*/ + cf->count, cf->state, *err);*/ -#ifdef NEW_PACKET_LIST - new_packet_list_thaw(); -#else - /* XXX - this causes "flickering" of the list */ - packet_list_thaw(); -#endif + /* Don't freeze/thaw the list when doing live capture */ + /*new_packet_list_thaw();*/ + /* With the new packet list the first packet + * isn't automatically selected. + */ + if(!cf->current_frame) + new_packet_list_select_first_row(); /* moving to the end of the packet list - if the user requested so and we have some new packets. */ if (newly_displayed_packets && auto_scroll_live && cf->plist_end != NULL) -#ifdef NEW_PACKET_LIST - if(visible) new_packet_list_moveto_end(); -#else - /* this doesn't seem to work well with a frozen GTK_Clist, so do this after - packet_list_thaw() is done, see bugzilla 1188 */ - /* XXX - this cheats and looks inside the packet list to find the final - row number. */ - packet_list_moveto_end(); -#endif /* NEW_PACKET_LIST */ if (cf->state == FILE_READ_ABORTED) { /* Well, the user decided to exit Wireshark. Return CF_READ_ABORTED @@ -884,6 +882,11 @@ cf_continue_tail(capture_file *cf, volatile int to_read, int *err) return CF_READ_OK; } +void +cf_fake_continue_tail(capture_file *cf) { + cf->state = FILE_READ_DONE; +} + cf_read_status_t cf_finish_tail(capture_file *cf, int *err) { @@ -912,13 +915,9 @@ cf_finish_tail(capture_file *cf, int *err) return CF_READ_ERROR; } -#ifdef NEW_PACKET_LIST new_packet_list_check_end(); - new_packet_list_freeze(); -#else - packet_list_check_end(); - packet_list_freeze(); -#endif + /* Don't freeze/thaw the list when doing live capture */ + /*new_packet_list_freeze();*/ while ((wtap_read(cf->wth, err, &err_info, &data_offset))) { if (cf->state == FILE_READ_ABORTED) { @@ -935,11 +934,8 @@ cf_finish_tail(capture_file *cf, int *err) dfilter_free(dfcode); } -#ifdef NEW_PACKET_LIST - new_packet_list_thaw(); -#else - packet_list_thaw(); -#endif + /* Don't freeze/thaw the list when doing live capture */ + /*new_packet_list_thaw();*/ if (cf->state == FILE_READ_ABORTED) { /* Well, the user decided to abort the read. We're only called @@ -952,13 +948,7 @@ cf_finish_tail(capture_file *cf, int *err) } if (auto_scroll_live && cf->plist_end != NULL) -#ifdef NEW_PACKET_LIST new_packet_list_moveto_end(); -#else - /* XXX - this cheats and looks inside the packet list to find the final - row number. */ - packet_list_moveto_end(); -#endif /* We're done reading sequentially through the file. */ cf->state = FILE_READ_DONE; @@ -1003,68 +993,91 @@ cf_get_display_name(capture_file *cf) } else { /* The file we read is a temporary file from a live capture; we don't mention its name. */ - displayname = "(Untitled)"; + if (cf->source) { + displayname = cf->source; + } else { + displayname = "(Untitled)"; + } } return displayname; } +void cf_set_tempfile_source(capture_file *cf, gchar *source) { + if (cf->source) { + g_free(cf->source); + } + + if (source) { + cf->source = g_strdup(source); + } else { + cf->source = g_strdup(""); + } +} + +const gchar *cf_get_tempfile_source(capture_file *cf) { + if (!cf->source) { + return ""; + } + + return cf->source; +} + /* XXX - use a macro instead? */ int cf_get_packet_count(capture_file *cf) { - return cf->count; + return cf->count; } /* XXX - use a macro instead? */ void cf_set_packet_count(capture_file *cf, int packet_count) { - cf->count = packet_count; + cf->count = packet_count; } /* XXX - use a macro instead? */ gboolean cf_is_tempfile(capture_file *cf) { - return cf->is_tempfile; + return cf->is_tempfile; } void cf_set_tempfile(capture_file *cf, gboolean is_tempfile) { - cf->is_tempfile = is_tempfile; + cf->is_tempfile = is_tempfile; } /* XXX - use a macro instead? */ void cf_set_drops_known(capture_file *cf, gboolean drops_known) { - cf->drops_known = drops_known; + cf->drops_known = drops_known; } /* XXX - use a macro instead? */ void cf_set_drops(capture_file *cf, guint32 drops) { - cf->drops = drops; + cf->drops = drops; } /* XXX - use a macro instead? */ gboolean cf_get_drops_known(capture_file *cf) { - return cf->drops_known; + return cf->drops_known; } /* XXX - use a macro instead? */ guint32 cf_get_drops(capture_file *cf) { - return cf->drops; + return cf->drops; } void cf_set_rfcode(capture_file *cf, dfilter_t *rfcode) { - cf->rfcode = rfcode; + cf->rfcode = rfcode; } -#ifdef NEW_PACKET_LIST static int add_packet_to_packet_list(frame_data *fdata, capture_file *cf, dfilter_t *dfcode, gboolean filtering_tap_listeners, @@ -1080,43 +1093,8 @@ add_packet_to_packet_list(frame_data *fdata, capture_file *cf, cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL; - /* just add some value here until we know if it is being displayed or not */ - fdata->cum_bytes = cum_bytes + fdata->pkt_len; - - /* If we don't have the time stamp of the first packet in the - capture, it's because this is the first packet. Save the time - stamp of this packet as the time stamp of the first packet. */ - if (nstime_is_unset(&first_ts)) { - first_ts = fdata->abs_ts; - } - /* if this frames is marked as a reference time frame, reset - firstsec and firstusec to this frame */ - if(fdata->flags.ref_time){ - first_ts = fdata->abs_ts; - } - - /* If we don't have the time stamp of the previous displayed packet, - it's because this is the first displayed packet. Save the time - stamp of this packet as the time stamp of the previous displayed - packet. */ - if (nstime_is_unset(&prev_dis_ts)) { - prev_dis_ts = fdata->abs_ts; - } - - /* Get the time elapsed between the first packet and this packet. */ - nstime_delta(&fdata->rel_ts, &fdata->abs_ts, &first_ts); - - /* If it's greater than the current elapsed time, set the elapsed time - to it (we check for "greater than" so as not to be confused by - time moving backwards). */ - if ((gint32)cf->elapsed_time.secs < fdata->rel_ts.secs - || ((gint32)cf->elapsed_time.secs == fdata->rel_ts.secs && (gint32)cf->elapsed_time.nsecs < fdata->rel_ts.nsecs)) { - cf->elapsed_time = fdata->rel_ts; - } - - /* Get the time elapsed between the previous displayed packet and - this packet. */ - nstime_delta(&fdata->del_dis_ts, &fdata->abs_ts, &prev_dis_ts); + frame_data_set_before_dissect(fdata, &cf->elapsed_time, + &first_ts, &prev_dis_ts, &prev_cap_ts); /* If either + we have a display filter and are re-applying it; @@ -1152,24 +1130,17 @@ add_packet_to_packet_list(frame_data *fdata, capture_file *cf, } else fdata->flags.passed_dfilter = 1; + if(fdata->flags.passed_dfilter || fdata->flags.ref_time) + cf->displayed_count++; + if (add_to_packet_list) { /* We fill the needed columns from new_packet_list */ row = new_packet_list_append(cinfo, fdata, &edt.pi); } - if( (fdata->flags.passed_dfilter) || (fdata->flags.ref_time) ) + if(fdata->flags.passed_dfilter || fdata->flags.ref_time) { - /* This frame either passed the display filter list or is marked as - a time reference frame. All time reference frames are displayed - even if they dont pass the display filter */ - if(fdata->flags.ref_time){ - /* if this was a TIME REF frame we should reset the cul bytes field */ - cum_bytes = fdata->pkt_len; - fdata->cum_bytes = cum_bytes; - } else { - /* increase cum_bytes with this packets length */ - cum_bytes += fdata->pkt_len; - } + frame_data_set_after_dissect(fdata, &cum_bytes, &prev_dis_ts); /* If we haven't yet seen the first frame, this is it. @@ -1189,178 +1160,21 @@ add_packet_to_packet_list(frame_data *fdata, capture_file *cf, /* This is the last frame we've seen so far. */ cf->last_displayed = fdata; - - /* Set the time of the previous displayed frame to the time of this - frame. */ - prev_dis_ts = fdata->abs_ts; - - cf->displayed_count++; } epan_dissect_cleanup(&edt); return row; } -#else - -static int -add_packet_to_packet_list(frame_data *fdata, capture_file *cf, - dfilter_t *dfcode, gboolean filtering_tap_listeners, - guint tap_flags, - union wtap_pseudo_header *pseudo_header, const guchar *buf, - gboolean refilter, - gboolean add_to_packet_list _U_) +/* + * Initialize the col_text and col_text_len arrays. + */ +static void +init_col_text(frame_data *fdata, gint num_cols) { - gboolean create_proto_tree = FALSE; - epan_dissect_t edt; - column_info *cinfo; - gint row = -1; - - cinfo = &cf->cinfo; - - /* just add some value here until we know if it is being displayed or not */ - fdata->cum_bytes = cum_bytes + fdata->pkt_len; - - /* If we don't have the time stamp of the first packet in the - capture, it's because this is the first packet. Save the time - stamp of this packet as the time stamp of the first packet. */ - if (nstime_is_unset(&first_ts)) { - first_ts = fdata->abs_ts; - } - /* if this frames is marked as a reference time frame, reset - firstsec and firstusec to this frame */ - if(fdata->flags.ref_time){ - first_ts = fdata->abs_ts; - } - - /* If we don't have the time stamp of the previous displayed packet, - it's because this is the first displayed packet. Save the time - stamp of this packet as the time stamp of the previous displayed - packet. */ - if (nstime_is_unset(&prev_dis_ts)) { - prev_dis_ts = fdata->abs_ts; - } - - /* Get the time elapsed between the first packet and this packet. */ - nstime_delta(&fdata->rel_ts, &fdata->abs_ts, &first_ts); - - /* If it's greater than the current elapsed time, set the elapsed time - to it (we check for "greater than" so as not to be confused by - time moving backwards). */ - if ((gint32)cf->elapsed_time.secs < fdata->rel_ts.secs - || ((gint32)cf->elapsed_time.secs == fdata->rel_ts.secs && (gint32)cf->elapsed_time.nsecs < fdata->rel_ts.nsecs)) { - cf->elapsed_time = fdata->rel_ts; - } - - /* Get the time elapsed between the previous displayed packet and - this packet. */ - nstime_delta(&fdata->del_dis_ts, &fdata->abs_ts, &prev_dis_ts); - - /* If either - - we have a display filter and are re-applying it; - - we have a list of color filters; - - we have tap listeners with filters; - - we have tap listeners that require a protocol tree; - - we have custom columns; - - allocate a protocol tree root node, so that we'll construct - a protocol tree against which a filter expression can be - evaluated. */ - if ((dfcode != NULL && refilter) || - color_filters_used() || - have_custom_cols(cinfo) || - filtering_tap_listeners || (tap_flags & TL_REQUIRES_PROTO_TREE)) - create_proto_tree = TRUE; - - /* Dissect the frame. */ - epan_dissect_init(&edt, create_proto_tree, FALSE); - - if (dfcode != NULL && refilter) { - epan_dissect_prime_dfilter(&edt, dfcode); - } - - /* prepare color filters */ - color_filters_prime_edt(&edt); - col_custom_prime_edt(&edt, cinfo); - - tap_queue_init(&edt); - epan_dissect_run(&edt, pseudo_header, buf, fdata, cinfo); - tap_push_tapped_queue(&edt); - - /* If we have a display filter, apply it if we're refiltering, otherwise - leave the "passed_dfilter" flag alone. - - If we don't have a display filter, set "passed_dfilter" to 1. */ - if (dfcode != NULL) { - if (refilter) { - fdata->flags.passed_dfilter = dfilter_apply_edt(dfcode, &edt) ? 1 : 0; - } - } else - fdata->flags.passed_dfilter = 1; - - if( (fdata->flags.passed_dfilter) || (fdata->flags.ref_time) ) - { - /* This frame either passed the display filter list or is marked as - a time reference frame. All time reference frames are displayed - even if they dont pass the display filter */ - if(fdata->flags.ref_time){ - /* if this was a TIME REF frame we should reset the cul bytes field */ - cum_bytes = fdata->pkt_len; - fdata->cum_bytes = cum_bytes; - } else { - /* increase cum_bytes with this packets length */ - cum_bytes += fdata->pkt_len; - } - - epan_dissect_fill_in_columns(&edt, FALSE, TRUE); - - /* If we haven't yet seen the first frame, this is it. - - XXX - we must do this before we add the row to the display, - as, if the display's GtkCList's selection mode is - GTK_SELECTION_BROWSE, when the first entry is added to it, - "cf_select_packet()" will be called, and it will fetch the row - data for the 0th row, and will get a null pointer rather than - "fdata", as "gtk_clist_append()" won't yet have returned and - thus "gtk_clist_set_row_data()" won't yet have been called. - - We thus need to leave behind bread crumbs so that - "cf_select_packet()" can find this frame. See the comment - in "cf_select_packet()". */ - if (cf->first_displayed == NULL) - cf->first_displayed = fdata; - - /* This is the last frame we've seen so far. */ - cf->last_displayed = fdata; - - row = packet_list_append(cinfo->col_data, fdata); - - /* colorize packet: first apply color filters - * then if packet is marked, use preferences to overwrite color - * we do both to make sure that when a packet gets un-marked, the - * color will be correctly set (fixes bug 2038) - */ - fdata->color_filter = color_filters_colorize_packet(row, &edt); - if (fdata->flags.marked) { - packet_list_set_colors(row, &prefs.gui_marked_fg, &prefs.gui_marked_bg); - } - - /* Set the time of the previous displayed frame to the time of this - frame. */ - prev_dis_ts = fdata->abs_ts; - - cf->displayed_count++; - } - - epan_dissect_cleanup(&edt); - return row; + fdata->col_text_len = se_alloc0(sizeof(*fdata->col_text_len) * num_cols); + fdata->col_text = se_alloc0(sizeof(*fdata->col_text) * num_cols); } -#endif /* read in a new packet */ /* returns the row of the new packet in the packet list or -1 if not displayed */ @@ -1373,8 +1187,7 @@ read_packet(capture_file *cf, dfilter_t *dfcode, const guchar *buf = wtap_buf_ptr(cf->wth); frame_data *fdata; int passed; - frame_data *plist_end; - int row = -1; + int row = -1; cf->count++; @@ -1387,32 +1200,9 @@ read_packet(capture_file *cf, dfilter_t *dfcode, #else fdata = g_mem_chunk_alloc(cf->plist_chunk); #endif - fdata->num = cf->count; - fdata->next = NULL; - fdata->prev = NULL; - fdata->pfd = NULL; - fdata->pkt_len = phdr->len; - fdata->cap_len = phdr->caplen; - fdata->file_off = offset; - /* To save some memory, we coarcese it into a gint8 */ - g_assert(phdr->pkt_encap <= G_MAXINT8); - fdata->lnk_t = (gint8) phdr->pkt_encap; - fdata->abs_ts.secs = phdr->ts.secs; - fdata->abs_ts.nsecs = phdr->ts.nsecs; - fdata->flags.encoding = CHAR_ASCII; - fdata->flags.visited = 0; - fdata->flags.marked = 0; - fdata->flags.ref_time = 0; - fdata->color_filter = NULL; -#ifdef NEW_PACKET_LIST - fdata->col_text_len = se_alloc0(sizeof(fdata->col_text_len) * (cf->cinfo.num_cols)); - fdata->col_text = se_alloc0(sizeof(fdata->col_text) * (cf->cinfo.num_cols)); -#endif - if (cf->plist_end != NULL) - nstime_delta(&fdata->del_cap_ts, &fdata->abs_ts, &cf->plist_end->abs_ts); - else - nstime_set_zero(&fdata->del_cap_ts); + frame_data_init(fdata, cf->count, phdr, offset, cum_bytes); + init_col_text(fdata, cf->cinfo.num_cols); passed = TRUE; if (cf->rfcode) { @@ -1425,15 +1215,9 @@ read_packet(capture_file *cf, dfilter_t *dfcode, } if (passed) { - plist_end = cf->plist_end; - fdata->prev = plist_end; - if (plist_end != NULL) - plist_end->next = fdata; - else - cf->plist = fdata; - cf->plist_end = fdata; + cap_file_add_fdata(cf, fdata); - cf->f_datalen = offset + phdr->caplen; + cf->f_datalen = offset + fdata->cap_len; if (!cf->redissecting) { row = add_packet_to_packet_list(fdata, cf, dfcode, @@ -1696,6 +1480,7 @@ cf_filter_packets(capture_file *cf, gchar *dftext, gboolean force) const char *filter_new = dftext ? dftext : ""; const char *filter_old = cf->dfilter ? cf->dfilter : ""; dfilter_t *dfcode; + GTimeVal start_time; /* if new filter equals old one, do nothing unless told to do so */ if (!force && strcmp(filter_new, filter_old) == 0) { @@ -1743,355 +1528,94 @@ cf_filter_packets(capture_file *cf, gchar *dftext, gboolean force) /* We have a valid filter. Replace the current filter. */ g_free(cf->dfilter); cf->dfilter = dftext; - - /* Now rescan the packet list, applying the new filter, but not - throwing away information constructed on a previous pass. */ - if (dftext == NULL) { - rescan_packets(cf, "Resetting", "Filter", TRUE, FALSE); - } else { - rescan_packets(cf, "Filtering", dftext, TRUE, FALSE); - } - - /* Cleanup and release all dfilter resources */ - if (dfcode != NULL){ - dfilter_free(dfcode); - } - return CF_OK; -} - -void -cf_colorize_packets(capture_file *cf) -{ - rescan_packets(cf, "Colorizing", "all packets", FALSE, FALSE); -} - -void -cf_reftime_packets(capture_file *cf) -{ - -#ifdef NEW_PACKET_LIST - ref_time_packets(cf); -#else - rescan_packets(cf, "Reprocessing", "all packets", TRUE, TRUE); -#endif -} - -void -cf_redissect_packets(capture_file *cf) -{ - rescan_packets(cf, "Reprocessing", "all packets", TRUE, TRUE); -} - -/* Rescan the list of packets, reconstructing the CList. - - "action" describes why we're doing this; it's used in the progress - dialog box. - - "action_item" describes what we're doing; it's used in the progress - dialog box. - - "refilter" is TRUE if we need to re-evaluate the filter expression. - - "redissect" is TRUE if we need to make the dissectors reconstruct - any state information they have (because a preference that affects - some dissector has changed, meaning some dissector might construct - its state differently from the way it was constructed the last time). */ - -/* Rescan packets with "old" packet list */ -#ifndef NEW_PACKET_LIST -static void -rescan_packets(capture_file *cf, const char *action, const char *action_item, - gboolean refilter, gboolean redissect) -{ - frame_data *fdata; - progdlg_t *progbar = NULL; - gboolean stop_flag; - int count; - int err; - gchar *err_info; - frame_data *selected_frame, *preceding_frame, *following_frame, *prev_frame; - int selected_row, prev_row, preceding_row, following_row; - gboolean selected_frame_seen; - int row; - float progbar_val; - GTimeVal start_time; - gchar status_str[100]; - int progbar_nextstep; - int progbar_quantum; - dfilter_t *dfcode; - gboolean filtering_tap_listeners; - guint tap_flags; - gboolean add_to_packet_list = TRUE; - gboolean compiled; - - /* Compile the current display filter. - * We assume this will not fail since cf->dfilter is only set in - * cf_filter IFF the filter was valid. - */ - compiled = dfilter_compile(cf->dfilter, &dfcode); - g_assert(!cf->dfilter || (compiled && dfcode)); - - /* Do we have any tap listeners with filters? */ - filtering_tap_listeners = have_filtering_tap_listeners(); - - /* Get the union of the flags for all tap listeners. */ - tap_flags = union_of_tap_listener_flags(); - - reset_tap_listeners(); - /* Which frame, if any, is the currently selected frame? - XXX - should the selected frame or the focus frame be the "current" - frame, that frame being the one from which "Find Frame" searches - start? */ - selected_frame = cf->current_frame; - - /* We don't yet know what row that frame will be on, if any, after we - rebuild the clist, however. */ - selected_row = -1; - - /* Freeze the packet list while we redo it, so we don't get any - screen updates while it happens. */ - packet_list_freeze(); - - /* Clear it out. */ - packet_list_clear(); - - if (redissect) { - /* We need to re-initialize all the state information that protocols - keep, because some preference that controls a dissector has changed, - which might cause the state information to be constructed differently - by that dissector. */ - - /* We might receive new packets while redissecting, and we don't - want to dissect those before their time. */ - cf->redissecting = TRUE; - - /* Cleanup all data structures used for dissection. */ - cleanup_dissection(); - /* Initialize all data structures used for dissection. */ - init_dissection(); - - } - - /* We don't yet know which will be the first and last frames displayed. */ - cf->first_displayed = NULL; - cf->last_displayed = NULL; - - reset_elapsed(); - - /* We currently don't display any packets */ - cf->displayed_count = 0; - - /* Iterate through the list of frames. Call a routine for each frame - to check whether it should be displayed and, if so, add it to - the display list. */ - nstime_set_unset(&first_ts); - nstime_set_unset(&prev_dis_ts); - cum_bytes = 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); - row = -1; /* no previous row yet */ - prev_row = -1; - prev_frame = NULL; - - preceding_row = -1; - preceding_frame = NULL; - following_row = -1; - following_frame = NULL; - - selected_frame_seen = FALSE; - for (fdata = cf->plist; fdata != NULL; fdata = fdata->next) { - /* 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(action, action_item, 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 filtering. Just stop. - - XXX - go back to the previous filter? Users probably just - want not to wait for a filtering operation to finish; - unless we cancel by having no filter, reverting to the - previous filter will probably be even more expensive than - continuing the filtering, as it involves going back to the - beginning and filtering, and even with no filter we currently - have to re-generate the entire clist, which is also expensive. - - I'm not sure what Network Monitor does, but it doesn't appear - to give you an unfiltered display if you cancel. */ - break; - } - - count++; - - if (redissect) { - /* Since all state for the frame was destroyed, mark the frame - * as not visited, free the GSList referring to the state - * data (the per-frame data itself was freed by - * "init_dissection()"), and null out the GSList pointer. - */ - fdata->flags.visited = 0; - frame_data_cleanup(fdata); - } - - if (!wtap_seek_read (cf->wth, fdata->file_off, &cf->pseudo_header, - cf->pd, fdata->cap_len, &err, &err_info)) { - simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, - cf_read_error_message(err, err_info), cf->filename); - break; - } - - /* If the previous frame is displayed, and we haven't yet seen the - selected frame, remember that frame - it's the closest one we've - yet seen before the selected frame. */ - if (prev_row != -1 && !selected_frame_seen) { - preceding_row = prev_row; - preceding_frame = prev_frame; - } - row = add_packet_to_packet_list(fdata, cf, dfcode, filtering_tap_listeners, - tap_flags, &cf->pseudo_header, cf->pd, - refilter, - add_to_packet_list); - - /* If this frame is displayed, and this is the first frame we've - seen displayed after the selected frame, remember this frame - - it's the closest one we've yet seen at or after the selected - frame. */ - if (row != -1 && selected_frame_seen && following_row == -1) { - following_row = row; - following_frame = fdata; - } - if (fdata == selected_frame) { - selected_row = row; - selected_frame_seen = TRUE; - } - - /* Remember this row/frame - it'll be the previous row/frame - on the next pass through the loop. */ - prev_row = row; - prev_frame = fdata; + /* Now rescan the packet list, applying the new filter, but not + throwing away information constructed on a previous pass. */ + if (dftext == NULL) { + rescan_packets(cf, "Resetting", "Filter", TRUE, FALSE); + } else { + rescan_packets(cf, "Filtering", dftext, TRUE, FALSE); } - /* We are done redissecting the packet list. */ - cf->redissecting = FALSE; + /* Cleanup and release all dfilter resources */ + dfilter_free(dfcode); - if (redissect) { - /* Clear out what remains of the visited flags and per-frame data - pointers. + return CF_OK; +} - XXX - that may cause various forms of bogosity when dissecting - these frames, as they won't have been seen by this sequential - pass, but the only alternative I see is to keep scanning them - even though the user requested that the scan stop, and that - would leave the user stuck with an Wireshark grinding on - until it finishes. Should we just stick them with that? */ - for (; fdata != NULL; fdata = fdata->next) { - fdata->flags.visited = 0; - frame_data_cleanup(fdata); - } - } +void +cf_reftime_packets(capture_file *cf) +{ - /* We're done filtering the packets; destroy the progress bar if it - was created. */ - if (progbar != NULL) - destroy_progress_dlg(progbar); + ref_time_packets(cf); +} - /* Unfreeze the packet list. */ - packet_list_thaw(); +void +cf_redissect_packets(capture_file *cf) +{ + rescan_packets(cf, "Reprocessing", "all packets", TRUE, TRUE); +} - if (selected_row == -1) { - /* The selected frame didn't pass the filter. */ - if (selected_frame == NULL) { - /* That's because there *was* no selected frame. Make the first - displayed frame the current frame. */ - selected_row = 0; - } else { - /* Find the nearest displayed frame to the selected frame (whether - it's before or after that frame) and make that the current frame. - If the next and previous displayed frames are equidistant from the - selected frame, choose the next one. */ - g_assert(following_frame == NULL || - following_frame->num >= selected_frame->num); - g_assert(preceding_frame == NULL || - preceding_frame->num <= selected_frame->num); - if (following_frame == NULL) { - /* No frame after the selected frame passed the filter, so we - have to select the last displayed frame before the selected - frame. */ - selected_row = preceding_row; - } else if (preceding_frame == NULL) { - /* No frame before the selected frame passed the filter, so we - have to select the first displayed frame after the selected - frame. */ - selected_row = following_row; - } else { - /* Frames before and after the selected frame passed the filter, so - we'll select the previous frame */ - selected_row = preceding_row; - } - } - } +gboolean +cf_read_frame_r(capture_file *cf, frame_data *fdata, + union wtap_pseudo_header *pseudo_header, guint8 *pd) +{ + int err; + gchar *err_info; + char errmsg_errno[1024+1]; - if (selected_row == -1) { - /* There are no frames displayed at all. */ - cf_unselect_packet(cf); - } else { - /* Either the frame that was selected passed the filter, or we've - found the nearest displayed frame to that frame. Select it, make - it the focus row, and make it visible. */ - if (selected_row == 0) { - /* Set to invalid to force update of packet list and packet details */ - cf->current_row = -1; + if (!wtap_seek_read(cf->wth, fdata->file_off, pseudo_header, pd, + fdata->cap_len, &err, &err_info)) { + switch (err) { + + case WTAP_ERR_UNSUPPORTED_ENCAP: + g_snprintf(errmsg_errno, sizeof(errmsg_errno), + "The file \"%%s\" has a packet with a network type that Wireshark doesn't support.\n(%s)", + err_info); + g_free(err_info); + break; + + case WTAP_ERR_BAD_RECORD: + g_snprintf(errmsg_errno, sizeof(errmsg_errno), + "An error occurred while reading from the file \"%%s\": %s.\n(%s)", + wtap_strerror(err), err_info); + g_free(err_info); + break; + + default: + g_snprintf(errmsg_errno, sizeof(errmsg_errno), + "An error occurred while reading from the file \"%%s\": %s.", + wtap_strerror(err)); + break; } - packet_list_set_selected_row(selected_row); + simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, errmsg_errno, cf->filename); + return FALSE; } + return TRUE; +} - /* Cleanup and release all dfilter resources */ - if (dfcode != NULL){ - dfilter_free(dfcode); - } +gboolean +cf_read_frame(capture_file *cf, frame_data *fdata) +{ + return cf_read_frame_r(cf, fdata, &cf->pseudo_header, cf->pd); } -#else +/* Rescan the list of packets, reconstructing the CList. + + "action" describes why we're doing this; it's used in the progress + dialog box. + + "action_item" describes what we're doing; it's used in the progress + dialog box. + "refilter" is TRUE if we need to re-evaluate the filter expression. + + "redissect" is TRUE if we need to make the dissectors reconstruct + any state information they have (because a preference that affects + some dissector has changed, meaning some dissector might construct + its state differently from the way it was constructed the last time). */ static void rescan_packets(capture_file *cf, const char *action, const char *action_item, gboolean refilter, gboolean redissect) @@ -2101,12 +1625,9 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item, progdlg_t *progbar = NULL; gboolean stop_flag; int count; - int err; - gchar *err_info; frame_data *selected_frame, *preceding_frame, *following_frame, *prev_frame; int selected_frame_num, preceding_frame_num, following_frame_num, prev_frame_num; gboolean selected_frame_seen; - int frame_num; float progbar_val; GTimeVal start_time; gchar status_str[100]; @@ -2138,7 +1659,7 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item, start? */ selected_frame = cf->current_frame; - /* Mark frane num as not found */ + /* Mark frame num as not found */ selected_frame_num = -1; /* Freeze the packet list while we redo it, so we don't get any @@ -2170,8 +1691,6 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item, cf->first_displayed = NULL; cf->last_displayed = NULL; - reset_elapsed(); - /* We currently don't display any packets */ cf->displayed_count = 0; @@ -2180,6 +1699,7 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item, the display list. */ nstime_set_unset(&first_ts); nstime_set_unset(&prev_dis_ts); + nstime_set_unset(&prev_cap_ts); cum_bytes = 0; /* Update the progress bar when it gets to this value. */ @@ -2196,7 +1716,6 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item, g_get_current_time(&start_time); /* no previous row yet */ - frame_num = -1; prev_frame_num = -1; prev_frame = NULL; @@ -2207,7 +1726,7 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item, selected_frame_seen = FALSE; - for (fdata = cf->plist; fdata != NULL; fdata = fdata->next) { + for (fdata = cf->plist_start; fdata != NULL; fdata = fdata->next) { /* 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 @@ -2243,15 +1762,15 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item, /* Well, the user decided to abort the filtering. Just stop. XXX - go back to the previous filter? Users probably just - want not to wait for a filtering operation to finish; - unless we cancel by having no filter, reverting to the - previous filter will probably be even more expensive than - continuing the filtering, as it involves going back to the - beginning and filtering, and even with no filter we currently - have to re-generate the entire clist, which is also expensive. - - I'm not sure what Network Monitor does, but it doesn't appear - to give you an unfiltered display if you cancel. */ + want not to wait for a filtering operation to finish; + unless we cancel by having no filter, reverting to the + previous filter will probably be even more expensive than + continuing the filtering, as it involves going back to the + beginning and filtering, and even with no filter we currently + have to re-generate the entire clist, which is also expensive. + + I'm not sure what Network Monitor does, but it doesn't appear + to give you an unfiltered display if you cancel. */ break; } @@ -2269,16 +1788,11 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item, * And after that fdata->col_text (which is allocated using se_alloc0()) * no longer points to valid memory. */ - fdata->col_text_len = se_alloc0(sizeof(fdata->col_text_len) * (cf->cinfo.num_cols)); - fdata->col_text = se_alloc0(sizeof(fdata->col_text) * (cf->cinfo.num_cols)); + init_col_text(fdata, cf->cinfo.num_cols); } - if (!wtap_seek_read (cf->wth, fdata->file_off, &cf->pseudo_header, - cf->pd, fdata->cap_len, &err, &err_info)) { - simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, - cf_read_error_message(err, err_info), cf->filename); - break; - } + if (!cf_read_frame(cf, fdata)) + break; /* error reading the frame */ /* If the previous frame is displayed, and we haven't yet seen the selected frame, remember that frame - it's the closest one we've @@ -2340,6 +1854,9 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item, if (!add_to_packet_list) new_packet_list_recreate_visible_rows(); + /* Compute the time it took to filter the file */ + compute_elapsed(&start_time); + new_packet_list_thaw(); if (selected_frame_num == -1) { @@ -2385,6 +1902,8 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item, /* Either the frame that was selected passed the filter, or we've found the nearest displayed frame to that frame. Select it, make it the focus row, and make it visible. */ + /* Set to invalid to force update of packet list and packet details */ + cf->current_row = -1; if (selected_frame_num == 0) { new_packet_list_select_first_row(); }else{ @@ -2393,18 +1912,15 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item, } /* Cleanup and release all dfilter resources */ - if (dfcode != NULL){ - dfilter_free(dfcode); - } + dfilter_free(dfcode); } -#endif /* NEW_PACKET_LIST */ + /* * Scan trough all frame data and recalculate the ref time * without rereading the file. * XXX - do we need a progres bar or is this fast enough? */ -#ifdef NEW_PACKET_LIST static void ref_time_packets(capture_file *cf) { @@ -2414,11 +1930,13 @@ ref_time_packets(capture_file *cf) nstime_set_unset(&prev_dis_ts); cum_bytes = 0; - for (fdata = cf->plist; fdata != NULL; fdata = fdata->next) { - - fdata->cum_bytes = cum_bytes + fdata->pkt_len; + for (fdata = cf->plist_start; fdata != NULL; fdata = fdata->next) { /* just add some value here until we know if it is being displayed or not */ - fdata->cum_bytes = cum_bytes + fdata->pkt_len; + fdata->cum_bytes = cum_bytes + fdata->pkt_len; + + /* + *Timestamps + */ /* If we don't have the time stamp of the first packet in the capture, it's because this is the first packet. Save the time @@ -2429,7 +1947,7 @@ ref_time_packets(capture_file *cf) /* if this frames is marked as a reference time frame, reset firstsec and firstusec to this frame */ if(fdata->flags.ref_time){ - first_ts = fdata->abs_ts; + first_ts = fdata->abs_ts; } /* If we don't have the time stamp of the previous displayed packet, @@ -2455,12 +1973,17 @@ ref_time_packets(capture_file *cf) this packet. */ nstime_delta(&fdata->del_dis_ts, &fdata->abs_ts, &prev_dis_ts); + prev_dis_ts = fdata->abs_ts; + + /* + * Byte counts + */ if( (fdata->flags.passed_dfilter) || (fdata->flags.ref_time) ){ /* This frame either passed the display filter list or is marked as a time reference frame. All time reference frames are displayed even if they dont pass the display filter */ if(fdata->flags.ref_time){ - /* if this was a TIME REF frame we should reset the cul bytes field */ + /* if this was a TIME REF frame we should reset the cum_bytes field */ cum_bytes = fdata->pkt_len; fdata->cum_bytes = cum_bytes; } else { @@ -2470,7 +1993,6 @@ ref_time_packets(capture_file *cf) } } } -#endif typedef enum { PSP_FINISHED, @@ -2486,8 +2008,6 @@ process_specified_packets(capture_file *cf, packet_range_t *range, void *callback_args) { frame_data *fdata; - int err; - gchar *err_info; union wtap_pseudo_header pseudo_header; guint8 pd[WTAP_MAX_PACKET_SIZE+1]; psp_return_t ret = PSP_FINISHED; @@ -2519,7 +2039,7 @@ process_specified_packets(capture_file *cf, packet_range_t *range, /* Iterate through the list of packets, printing the packets that were selected by the current display filter. */ - for (fdata = cf->plist; fdata != NULL; fdata = fdata->next) { + for (fdata = cf->plist_start; fdata != NULL; fdata = fdata->next) { /* 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 @@ -2574,11 +2094,8 @@ process_specified_packets(capture_file *cf, packet_range_t *range, } /* Get the packet */ - if (!wtap_seek_read(cf->wth, fdata->file_off, &pseudo_header, - pd, fdata->cap_len, &err, &err_info)) { + if (!cf_read_frame_r(cf, fdata, &pseudo_header, pd)) { /* Attempt to get the packet failed. */ - simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, - cf_read_error_message(err, err_info), cf->filename); ret = PSP_FAILED; break; } @@ -2707,6 +2224,7 @@ print_packet(capture_file *cf, frame_data *fdata, /* Fill in the column information if we're printing the summary information. */ if (args->print_args->print_summary) { + col_custom_prime_edt(&edt, &cf->cinfo); epan_dissect_run(&edt, pseudo_header, pd, fdata, &cf->cinfo); epan_dissect_fill_in_columns(&edt, FALSE, TRUE); } else @@ -3039,6 +2557,7 @@ write_psml_packet(capture_file *cf, frame_data *fdata, if having custom columns. */ proto_tree_needed = have_custom_cols(&cf->cinfo); epan_dissect_init(&edt, proto_tree_needed, proto_tree_needed); + col_custom_prime_edt(&edt, &cf->cinfo); epan_dissect_run(&edt, pseudo_header, pd, fdata, &cf->cinfo); epan_dissect_fill_in_columns(&edt, FALSE, TRUE); @@ -3113,6 +2632,7 @@ write_csv_packet(capture_file *cf, frame_data *fdata, if having custom columns. */ proto_tree_needed = have_custom_cols(&cf->cinfo); epan_dissect_init(&edt, proto_tree_needed, proto_tree_needed); + col_custom_prime_edt(&edt, &cf->cinfo); epan_dissect_run(&edt, pseudo_header, pd, fdata, &cf->cinfo); epan_dissect_fill_in_columns(&edt, FALSE, TRUE); @@ -3181,257 +2701,93 @@ write_carrays_packet(capture_file *cf _U_, frame_data *fdata, { 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 = ws_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; -} - -#ifndef NEW_PACKET_LIST /* This function is not needed with the new packet list */ - -/* 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. */ -void -cf_change_time_formats(capture_file *cf) -{ - int i; - frame_data *fdata; - progdlg_t *progbar = NULL; - gboolean stop_flag; - int count; - int row; - float progbar_val; - GTimeVal start_time; - gchar status_str[100]; - int progbar_nextstep; - int progbar_quantum; - gboolean sorted_by_frame_column; - - /* Adjust timestamp precision if auto is selected */ - cf_timestamp_auto_precision(cf); - - /* Are there any columns with time stamps in the "command-line-specified" - format? - - XXX - we have to force the "column is writable" flag on, as it - might be off from the last frame that was dissected. */ - col_set_writable(&cf->cinfo, TRUE); - if (!check_col(&cf->cinfo, COL_CLS_TIME) && - !check_col(&cf->cinfo, COL_ABS_TIME) && - !check_col(&cf->cinfo, COL_ABS_DATE_TIME) && - !check_col(&cf->cinfo, COL_REL_TIME) && - !check_col(&cf->cinfo, COL_DELTA_TIME) && - !check_col(&cf->cinfo, COL_DELTA_TIME_DIS)) { - /* No, there aren't any columns in that format, so we have no work - to do. */ - return; - } - - /* Freeze the packet list while we redo it, so we don't get any - screen updates while it happens. */ - packet_list_freeze(); - - /* 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; - - /* If the rows are currently sorted by the frame column then we know - * the row number of each packet: it's the row number of the previously - * displayed packet + 1. - * - * Otherwise, if the display is sorted by a different column then we have - * to use the O(N) packet_list_find_row_from_data() (thus making the job - * of changing the time display format O(N**2)). - * - * (XXX - In fact it's still O(N**2) because gtk_clist_set_text() takes - * the row number and walks that many elements down the clist to find - * the appropriate element.) - */ - sorted_by_frame_column = FALSE; - for (i = 0; i < cf->cinfo.num_cols; i++) { - if (cf->cinfo.col_fmt[i] == COL_NUMBER) - { - sorted_by_frame_column = (i == packet_list_get_sort_column()); - break; - } - } - - stop_flag = FALSE; - g_get_current_time(&start_time); - - /* Iterate through the list of packets, checking whether the packet - is in a row of the summary list and, if so, whether there are - any columns that show the time in the "command-line-specified" - format and, if so, update that row. */ - for (fdata = cf->plist, row = -1; fdata != NULL; fdata = fdata->next) { - /* 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("Changing", "time display", - 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 packets", count, cf->count); - update_progress_dlg(progbar, progbar_val, status_str); - } - - progbar_nextstep += progbar_quantum; - } + proto_tree_write_carrays(pd, fdata->cap_len, fdata->num, fh); + return !ferror(fh); +} - if (stop_flag) { - /* Well, the user decided to abort the redisplay. Just stop. +cf_print_status_t +cf_write_carrays_packets(capture_file *cf, print_args_t *print_args) +{ + FILE *fh; + psp_return_t ret; - XXX - this leaves the time field in the old format in - frames we haven't yet processed. So it goes; should we - simply not offer them the option of stopping? */ - break; - } + fh = ws_fopen(print_args->file, "w"); - count++; + if (fh == NULL) + return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */ - /* Find what row this packet is in. */ - if (!sorted_by_frame_column) { - /* This function is O(N), so we try to avoid using it... */ - row = packet_list_find_row_from_data(fdata); - } else { - /* ...which we do by maintaining a count of packets that are - being displayed (i.e., that have passed the display filter), - and using the current value of that count as the row number - (which is why we can only do it when the display is sorted - by the frame number). */ - if (fdata->flags.passed_dfilter) - row++; - else - continue; - } + write_carrays_preamble(fh); - if (row != -1) { - /* This packet is in the summary list, on row "row". */ + if (ferror(fh)) { + fclose(fh); + return CF_PRINT_WRITE_ERROR; + } - for (i = 0; i < cf->cinfo.num_cols; i++) { - if (col_has_time_fmt(&cf->cinfo, i)) { - /* This is one of the columns that shows the time in - "command-line-specified" format; update it. */ - cf->cinfo.col_buf[i][0] = '\0'; - col_set_fmt_time(fdata, &cf->cinfo, cf->cinfo.col_fmt[i], i); - packet_list_set_text(row, i, cf->cinfo.col_data[i]); - } - } - } + /* 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; } - /* We're done redisplaying the packets; destroy the progress bar if it - was created. */ - if (progbar != NULL) - destroy_progress_dlg(progbar); + write_carrays_finale(fh); - /* Set the column widths of those columns that show the time in - "command-line-specified" format. */ - for (i = 0; i < cf->cinfo.num_cols; i++) { - if (col_has_time_fmt(&cf->cinfo, i)) { - packet_list_set_time_width(cf->cinfo.col_fmt[i], i); - } + if (ferror(fh)) { + fclose(fh); + return CF_PRINT_WRITE_ERROR; } - /* Unfreeze the packet list. */ - packet_list_thaw(); + fclose(fh); + return CF_PRINT_OK; } -#endif /* NEW_PACKET_LIST */ - - -typedef struct { - const char *string; - size_t string_len; - capture_file *cf; - gboolean frame_matched; -} match_data; gboolean -cf_find_packet_protocol_tree(capture_file *cf, const char *string) +cf_find_packet_protocol_tree(capture_file *cf, const char *string, + search_direction dir) { match_data mdata; mdata.string = string; mdata.string_len = strlen(string); - return find_packet(cf, match_protocol_tree, &mdata); + return find_packet(cf, match_protocol_tree, &mdata, dir); } -static gboolean +gboolean +cf_find_string_protocol_tree(capture_file *cf, proto_tree *tree, match_data *mdata) +{ + mdata->frame_matched = FALSE; + mdata->string = convert_string_case(cf->sfilter, cf->case_type); + mdata->string_len = strlen(mdata->string); + mdata->cf = cf; + /* Iterate through all the nodes looking for matching text */ + proto_tree_children_foreach(tree, match_subtree_text, mdata); + return mdata->frame_matched ? MR_MATCHED : MR_NOTMATCHED; +} + +static match_result match_protocol_tree(capture_file *cf, frame_data *fdata, void *criterion) { match_data *mdata = criterion; epan_dissect_t edt; + /* Load the frame's data. */ + if (!cf_read_frame(cf, fdata)) { + /* Attempt to get the packet failed. */ + return MR_ERROR; + } + /* Construct the protocol tree, including the displayed text */ epan_dissect_init(&edt, TRUE, TRUE); /* We don't need the column information */ @@ -3442,7 +2798,7 @@ match_protocol_tree(capture_file *cf, frame_data *fdata, void *criterion) mdata->frame_matched = FALSE; proto_tree_children_foreach(edt.tree, match_subtree_text, mdata); epan_dissect_cleanup(&edt); - return mdata->frame_matched; + return mdata->frame_matched ? MR_MATCHED : MR_NOTMATCHED; } static void @@ -3450,15 +2806,15 @@ match_subtree_text(proto_node *node, gpointer data) { match_data *mdata = (match_data*) data; const gchar *string = mdata->string; - size_t string_len = mdata->string_len; + size_t string_len = mdata->string_len; capture_file *cf = mdata->cf; field_info *fi = PNODE_FINFO(node); - gchar label_str[ITEM_LABEL_LENGTH]; - gchar *label_ptr; - size_t label_len; - guint32 i; - guint8 c_char; - size_t c_match = 0; + gchar label_str[ITEM_LABEL_LENGTH]; + gchar *label_ptr; + size_t label_len; + guint32 i; + guint8 c_char; + size_t c_match = 0; g_assert(fi && "dissection with an invisible proto tree?"); @@ -3489,9 +2845,10 @@ match_subtree_text(proto_node *node, gpointer data) if (c_char == string[c_match]) { c_match++; if (c_match == string_len) { - /* No need to look further; we have a match */ - mdata->frame_matched = TRUE; - return; + /* No need to look further; we have a match */ + mdata->frame_matched = TRUE; + mdata->finfo = fi; + return; } } else c_match = 0; @@ -3503,29 +2860,36 @@ match_subtree_text(proto_node *node, gpointer data) } gboolean -cf_find_packet_summary_line(capture_file *cf, const char *string) +cf_find_packet_summary_line(capture_file *cf, const char *string, + search_direction dir) { match_data mdata; mdata.string = string; mdata.string_len = strlen(string); - return find_packet(cf, match_summary_line, &mdata); + return find_packet(cf, match_summary_line, &mdata, dir); } -static gboolean +static match_result match_summary_line(capture_file *cf, frame_data *fdata, void *criterion) { match_data *mdata = criterion; const gchar *string = mdata->string; - size_t string_len = mdata->string_len; + size_t string_len = mdata->string_len; epan_dissect_t edt; const char *info_column; - size_t info_column_len; - gboolean frame_matched = FALSE; - gint colx; - guint32 i; - guint8 c_char; - size_t c_match = 0; + size_t info_column_len; + match_result result = MR_NOTMATCHED; + gint colx; + guint32 i; + guint8 c_char; + size_t c_match = 0; + + /* Load the frame's data. */ + if (!cf_read_frame(cf, fdata)) { + /* Attempt to get the packet failed. */ + return MR_ERROR; + } /* Don't bother constructing the protocol tree */ epan_dissect_init(&edt, FALSE, FALSE); @@ -3539,23 +2903,23 @@ match_summary_line(capture_file *cf, frame_data *fdata, void *criterion) info_column = edt.pi.cinfo->col_data[colx]; info_column_len = strlen(info_column); for (i = 0; i < info_column_len; i++) { - c_char = info_column[i]; - if (cf->case_type) - c_char = toupper(c_char); - if (c_char == string[c_match]) { - c_match++; - if (c_match == string_len) { - frame_matched = TRUE; - break; - } - } else - c_match = 0; + c_char = info_column[i]; + if (cf->case_type) + c_char = toupper(c_char); + if (c_char == string[c_match]) { + c_match++; + if (c_match == string_len) { + result = MR_MATCHED; + break; + } + } else + c_match = 0; } break; } } epan_dissect_cleanup(&edt); - return frame_matched; + return result; } typedef struct { @@ -3564,7 +2928,8 @@ typedef struct { } cbs_t; /* "Counted byte string" */ gboolean -cf_find_packet_data(capture_file *cf, const guint8 *string, size_t string_size) +cf_find_packet_data(capture_file *cf, const guint8 *string, size_t string_size, + search_direction dir) { cbs_t info; @@ -3577,35 +2942,41 @@ cf_find_packet_data(capture_file *cf, const guint8 *string, size_t string_size) switch (cf->scs_type) { case SCS_ASCII_AND_UNICODE: - return find_packet(cf, match_ascii_and_unicode, &info); + return find_packet(cf, match_ascii_and_unicode, &info, dir); case SCS_ASCII: - return find_packet(cf, match_ascii, &info); + return find_packet(cf, match_ascii, &info, dir); case SCS_UNICODE: - return find_packet(cf, match_unicode, &info); + return find_packet(cf, match_unicode, &info, dir); default: g_assert_not_reached(); return FALSE; } } else - return find_packet(cf, match_binary, &info); + return find_packet(cf, match_binary, &info, dir); } -static gboolean +static match_result match_ascii_and_unicode(capture_file *cf, frame_data *fdata, void *criterion) { - cbs_t *info = criterion; - const guint8 *ascii_text = info->data; - size_t textlen = info->data_len; - gboolean frame_matched; - guint32 buf_len; - guint32 i; - guint8 c_char; - size_t c_match = 0; - - frame_matched = FALSE; + cbs_t *info = criterion; + const guint8 *ascii_text = info->data; + size_t textlen = info->data_len; + match_result result; + guint32 buf_len; + guint32 i; + guint8 c_char; + size_t c_match = 0; + + /* Load the frame's data. */ + if (!cf_read_frame(cf, fdata)) { + /* Attempt to get the packet failed. */ + return MR_ERROR; + } + + result = MR_NOTMATCHED; buf_len = fdata->pkt_len; for (i = 0; i < buf_len; i++) { c_char = cf->pd[i]; @@ -3613,33 +2984,39 @@ match_ascii_and_unicode(capture_file *cf, frame_data *fdata, void *criterion) c_char = toupper(c_char); if (c_char != 0) { if (c_char == ascii_text[c_match]) { - c_match++; - if (c_match == textlen) { - frame_matched = TRUE; - cf->search_pos = i; /* Save the position of the last character - for highlighting the field. */ - break; - } + c_match++; + if (c_match == textlen) { + result = MR_MATCHED; + cf->search_pos = i; /* Save the position of the last character + for highlighting the field. */ + break; + } } else - c_match = 0; + c_match = 0; } } - return frame_matched; + return result; } -static gboolean +static match_result match_ascii(capture_file *cf, frame_data *fdata, void *criterion) { - cbs_t *info = criterion; - const guint8 *ascii_text = info->data; - size_t textlen = info->data_len; - gboolean frame_matched; - guint32 buf_len; - guint32 i; - guint8 c_char; - size_t c_match = 0; - - frame_matched = FALSE; + cbs_t *info = criterion; + const guint8 *ascii_text = info->data; + size_t textlen = info->data_len; + match_result result; + guint32 buf_len; + guint32 i; + guint8 c_char; + size_t c_match = 0; + + /* Load the frame's data. */ + if (!cf_read_frame(cf, fdata)) { + /* Attempt to get the packet failed. */ + return MR_ERROR; + } + + result = MR_NOTMATCHED; buf_len = fdata->pkt_len; for (i = 0; i < buf_len; i++) { c_char = cf->pd[i]; @@ -3648,30 +3025,36 @@ match_ascii(capture_file *cf, frame_data *fdata, void *criterion) if (c_char == ascii_text[c_match]) { c_match++; if (c_match == textlen) { - frame_matched = TRUE; - cf->search_pos = i; /* Save the position of the last character - for highlighting the field. */ - break; + result = MR_MATCHED; + cf->search_pos = i; /* Save the position of the last character + for highlighting the field. */ + break; } } else c_match = 0; } - return frame_matched; + return result; } -static gboolean +static match_result match_unicode(capture_file *cf, frame_data *fdata, void *criterion) { - cbs_t *info = criterion; - const guint8 *ascii_text = info->data; - size_t textlen = info->data_len; - gboolean frame_matched; - guint32 buf_len; - guint32 i; - guint8 c_char; - size_t c_match = 0; - - frame_matched = FALSE; + cbs_t *info = criterion; + const guint8 *ascii_text = info->data; + size_t textlen = info->data_len; + match_result result; + guint32 buf_len; + guint32 i; + guint8 c_char; + size_t c_match = 0; + + /* Load the frame's data. */ + if (!cf_read_frame(cf, fdata)) { + /* Attempt to get the packet failed. */ + return MR_ERROR; + } + + result = MR_NOTMATCHED; buf_len = fdata->pkt_len; for (i = 0; i < buf_len; i++) { c_char = cf->pd[i]; @@ -3681,86 +3064,148 @@ match_unicode(capture_file *cf, frame_data *fdata, void *criterion) c_match++; i++; if (c_match == textlen) { - frame_matched = TRUE; - cf->search_pos = i; /* Save the position of the last character - for highlighting the field. */ - break; + result = MR_MATCHED; + cf->search_pos = i; /* Save the position of the last character + for highlighting the field. */ + break; } } else c_match = 0; } - return frame_matched; + return result; } -static gboolean +static match_result match_binary(capture_file *cf, frame_data *fdata, void *criterion) { - cbs_t *info = criterion; - const guint8 *binary_data = info->data; - size_t datalen = info->data_len; - gboolean frame_matched; - guint32 buf_len; - guint32 i; - size_t c_match = 0; - - frame_matched = FALSE; + cbs_t *info = criterion; + const guint8 *binary_data = info->data; + size_t datalen = info->data_len; + match_result result; + guint32 buf_len; + guint32 i; + size_t c_match = 0; + + /* Load the frame's data. */ + if (!cf_read_frame(cf, fdata)) { + /* Attempt to get the packet failed. */ + return MR_ERROR; + } + + result = MR_NOTMATCHED; buf_len = fdata->pkt_len; for (i = 0; i < buf_len; i++) { if (cf->pd[i] == binary_data[c_match]) { c_match++; if (c_match == datalen) { - frame_matched = TRUE; - cf->search_pos = i; /* Save the position of the last character - for highlighting the field. */ - break; + result = MR_MATCHED; + cf->search_pos = i; /* Save the position of the last character + for highlighting the field. */ + break; } } else c_match = 0; } - return frame_matched; + return result; } gboolean -cf_find_packet_dfilter(capture_file *cf, dfilter_t *sfcode) +cf_find_packet_dfilter(capture_file *cf, dfilter_t *sfcode, + search_direction dir) { - return find_packet(cf, match_dfilter, sfcode); + return find_packet(cf, match_dfilter, sfcode, dir); } -static gboolean +gboolean +cf_find_packet_dfilter_string(capture_file *cf, const char *filter, + search_direction dir) +{ + dfilter_t *sfcode; + gboolean result; + + if (!dfilter_compile(filter, &sfcode)) { + /* + * XXX - this shouldn't happen, as the filter string is machine + * generated + */ + return FALSE; + } + if (sfcode == NULL) { + /* + * XXX - this shouldn't happen, as the filter string is machine + * generated. + */ + return FALSE; + } + result = find_packet(cf, match_dfilter, sfcode, dir); + dfilter_free(sfcode); + return result; +} + +static match_result match_dfilter(capture_file *cf, frame_data *fdata, void *criterion) { - dfilter_t *sfcode = criterion; - epan_dissect_t edt; - gboolean frame_matched; + dfilter_t *sfcode = criterion; + epan_dissect_t edt; + match_result result; + + /* Load the frame's data. */ + if (!cf_read_frame(cf, fdata)) { + /* Attempt to get the packet failed. */ + return MR_ERROR; + } epan_dissect_init(&edt, TRUE, FALSE); epan_dissect_prime_dfilter(&edt, sfcode); epan_dissect_run(&edt, &cf->pseudo_header, cf->pd, fdata, NULL); - frame_matched = dfilter_apply_edt(sfcode, &edt); + result = dfilter_apply_edt(sfcode, &edt) ? MR_MATCHED : MR_NOTMATCHED; epan_dissect_cleanup(&edt); - return frame_matched; + return result; +} + +gboolean +cf_find_packet_marked(capture_file *cf, search_direction dir) +{ + return find_packet(cf, match_marked, NULL, dir); +} + +static match_result +match_marked(capture_file *cf _U_, frame_data *fdata, void *criterion _U_) +{ + return fdata->flags.marked ? MR_MATCHED : MR_NOTMATCHED; +} + +gboolean +cf_find_packet_time_reference(capture_file *cf, search_direction dir) +{ + return find_packet(cf, match_time_reference, NULL, dir); +} + +static match_result +match_time_reference(capture_file *cf _U_, frame_data *fdata, void *criterion _U_) +{ + return fdata->flags.ref_time ? MR_MATCHED : MR_NOTMATCHED; } static gboolean find_packet(capture_file *cf, - gboolean (*match_function)(capture_file *, frame_data *, void *), - void *criterion) + match_result (*match_function)(capture_file *, frame_data *, void *), + void *criterion, search_direction dir) { - frame_data *start_fd; - frame_data *fdata; - frame_data *new_fd = NULL; - progdlg_t *progbar = NULL; - gboolean stop_flag; - int count; - int err; - gchar *err_info; - int row; - float progbar_val; - GTimeVal start_time; - gchar status_str[100]; - int progbar_nextstep; - int progbar_quantum; - char *title; + frame_data *start_fd; + frame_data *fdata; + frame_data *new_fd = NULL; + progdlg_t *progbar = NULL; + gboolean stop_flag; + int count; + int row; + float progbar_val; + GTimeVal start_time; + gchar status_str[100]; + int progbar_nextstep; + int progbar_quantum; + const char *title; + match_result result; start_fd = cf->current_frame; if (start_fd != NULL) { @@ -3781,7 +3226,6 @@ find_packet(capture_file *cf, stop_flag = FALSE; g_get_current_time(&start_time); - fdata = start_fd; title = cf->sfilter?cf->sfilter:""; for (;;) { /* Create the progress bar if necessary. @@ -3823,7 +3267,7 @@ find_packet(capture_file *cf, } /* Go past the current frame. */ - if (cf->sbackward) { + if (dir == SD_BACKWARD) { /* Go on to the previous frame. */ fdata = fdata->prev; if (fdata == NULL) { @@ -3837,18 +3281,12 @@ find_packet(capture_file *cf, if (prefs.gui_find_wrap) { - simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK, - "%sBeginning of capture exceeded!%s\n\n" - "Search is continued from the end of the capture.", - simple_dialog_primary_start(), simple_dialog_primary_end()); + statusbar_push_temporary_msg("Search reached the beginning. Continuing at end."); fdata = cf->plist_end; /* wrap around */ } else { - simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK, - "%sBeginning of capture exceeded!%s\n\n" - "Try searching forwards.", - simple_dialog_primary_start(), simple_dialog_primary_end()); + statusbar_push_temporary_msg("Search reached the beginning."); fdata = start_fd; /* stay on previous packet */ } } @@ -3858,18 +3296,12 @@ find_packet(capture_file *cf, if (fdata == NULL) { if (prefs.gui_find_wrap) { - simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK, - "%sEnd of capture exceeded!%s\n\n" - "Search is continued from the start of the capture.", - simple_dialog_primary_start(), simple_dialog_primary_end()); - fdata = cf->plist; /* wrap around */ + statusbar_push_temporary_msg("Search reached the end. Continuing at beginning."); + fdata = cf->plist_start; /* wrap around */ } else { - simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK, - "%sEnd of capture exceeded!%s\n\n" - "Try searching backwards.", - simple_dialog_primary_start(), simple_dialog_primary_end()); + statusbar_push_temporary_msg("Search reached the end."); fdata = start_fd; /* stay on previous packet */ } } @@ -3879,27 +3311,23 @@ find_packet(capture_file *cf, /* Is this packet in the display? */ if (fdata->flags.passed_dfilter) { - /* Yes. Load its data. */ - if (!wtap_seek_read(cf->wth, fdata->file_off, &cf->pseudo_header, - cf->pd, fdata->cap_len, &err, &err_info)) { - /* Read error. Report the error, and go back to the frame + /* Yes. Does it match the search criterion? */ + result = (*match_function)(cf, fdata, criterion); + if (result == MR_ERROR) { + /* Error; our caller has reported the error. Go back to the frame where we started. */ - simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, - cf_read_error_message(err, err_info), cf->filename); new_fd = start_fd; break; - } - - /* Does it match the search criterion? */ - if ((*match_function)(cf, fdata, criterion)) { + } else if (result == MR_MATCHED) { + /* Yes. Go to the new frame. */ new_fd = fdata; - break; /* found it! */ + break; } } if (fdata == start_fd) { /* We're back to the frame we were on originally, and that frame - doesn't match the search filter. The search failed. */ + doesn't match the search filter. The search failed. */ break; } } @@ -3911,28 +3339,21 @@ find_packet(capture_file *cf, } if (new_fd != NULL) { -#ifdef NEW_PACKET_LIST - /* Find and select */ - row = new_packet_list_find_row_from_data(fdata, TRUE); -#else - /* We found a frame. Find what row it's in. */ - row = packet_list_find_row_from_data(new_fd); -#endif /* NEW_PACKET_LIST */ + /* Find and select */ + cf->search_in_progress = TRUE; + row = new_packet_list_find_row_from_data(fdata, TRUE); + cf->search_in_progress = FALSE; + cf->search_pos = 0; /* Reset the position */ if (row == -1) { - /* We didn't find a row even though we know that a frame - * exists that satifies the search criteria. This means that the - * frame isn't being displayed currently so we can't select it. */ - simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK, - "%sEnd of capture exceeded!%s\n\n" - "The capture file is probably not fully loaded.", - simple_dialog_primary_start(), simple_dialog_primary_end()); - return FALSE; + /* We didn't find a row even though we know that a frame + * exists that satifies the search criteria. This means that the + * frame isn't being displayed currently so we can't select it. */ + simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK, + "%sEnd of capture exceeded!%s\n\n" + "The capture file is probably not fully loaded.", + simple_dialog_primary_start(), simple_dialog_primary_end()); + return FALSE; } - -#ifndef NEW_PACKET_LIST - /* Select that row, make it the focus row, and make it visible. */ - packet_list_set_selected_row(row); -#endif /* NEW_PACKET_LIST */ return TRUE; /* success */ } else return FALSE; /* failure */ @@ -3942,101 +3363,39 @@ gboolean cf_goto_frame(capture_file *cf, guint fnumber) { frame_data *fdata; - int row; - for (fdata = cf->plist; fdata != NULL && fdata->num < fnumber; fdata = fdata->next) + for (fdata = cf->plist_start; fdata != NULL && fdata->num < fnumber; fdata = fdata->next) ; if (fdata == NULL) { /* we didn't find a packet with that packet number */ - simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, - "There is no packet with the packet number %u.", fnumber); + statusbar_push_temporary_msg("There is no packet number %u.", fnumber); return FALSE; /* we failed to go to that packet */ } if (!fdata->flags.passed_dfilter) { /* that packet currently isn't displayed */ /* XXX - add it to the set of displayed packets? */ - simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, - "The packet number %u isn't currently being displayed.", fnumber); + statusbar_push_temporary_msg("Packet number %u isn't displayed.", fnumber); return FALSE; /* we failed to go to that packet */ } -#ifdef NEW_PACKET_LIST - row = new_packet_list_find_row_from_data(fdata, TRUE); -#else - /* We found that packet, and it's currently being displayed. - Find what row it's in. */ - row = packet_list_find_row_from_data(fdata); - g_assert(row != -1); - - /* Select that row, make it the focus row, and make it visible. */ - packet_list_set_selected_row(row); -#endif /* NEW_PACKET_LIST */ + new_packet_list_find_row_from_data(fdata, TRUE); return TRUE; /* we got to that packet */ } gboolean -cf_goto_top_frame(capture_file *cf _U_) +cf_goto_top_frame() { -#ifdef NEW_PACKET_LIST /* Find and select */ new_packet_list_select_first_row(); -#else - frame_data *fdata; - int row; - frame_data *lowest_fdata = NULL; - - for (fdata = cf->plist; fdata != NULL; fdata = fdata->next) { - if (fdata->flags.passed_dfilter) { - lowest_fdata = fdata; - break; - } - } - - if (lowest_fdata == NULL) { - return FALSE; - } - - /* We found that packet, and it's currently being displayed. - Find what row it's in. */ - row = packet_list_find_row_from_data(lowest_fdata); - g_assert(row != -1); - - /* Select that row, make it the focus row, and make it visible. */ - packet_list_set_selected_row(row); -#endif /* NEW_PACKET_LIST */ return TRUE; /* we got to that packet */ } gboolean -cf_goto_bottom_frame(capture_file *cf _U_) /* cf is unused w/ NEW_PACKET_LIST */ +cf_goto_bottom_frame() { -#ifdef NEW_PACKET_LIST /* Find and select */ new_packet_list_select_last_row(); -#else - frame_data *fdata; - int row; - frame_data *highest_fdata = NULL; - - for (fdata = cf->plist; fdata != NULL; fdata = fdata->next) { - if (fdata->flags.passed_dfilter) { - highest_fdata = fdata; - } - } - - if (highest_fdata == NULL) { - return FALSE; - } - - /* We found that packet, and it's currently being displayed. - Find what row it's in. */ - row = packet_list_find_row_from_data(highest_fdata); - g_assert(row != -1); - - /* Select that row, make it the focus row, and make it visible. */ - packet_list_set_selected_row(row); -#endif /* NEW_PACKET_LIST */ return TRUE; /* we got to that packet */ } @@ -4067,15 +3426,9 @@ void cf_select_packet(capture_file *cf, int row) { frame_data *fdata; - int err; - gchar *err_info; /* Get the frame data struct pointer for this frame */ -#ifdef NEW_PACKET_LIST fdata = new_packet_list_get_row_data(row); -#else - fdata = (frame_data *)packet_list_get_row_data(row); -#endif if (fdata == NULL) { /* XXX - if a GtkCList's selection mode is GTK_SELECTION_BROWSE, when @@ -4114,10 +3467,7 @@ cf_select_packet(capture_file *cf, int row) } /* Get the data in that frame. */ - if (!wtap_seek_read (cf->wth, fdata->file_off, &cf->pseudo_header, - cf->pd, fdata->cap_len, &err, &err_info)) { - simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, - cf_read_error_message(err, err_info), cf->filename); + if (!cf_read_frame (cf, fdata)) { return; } @@ -4132,6 +3482,7 @@ cf_select_packet(capture_file *cf, int row) /* We don't need the columns here. */ cf->edt = epan_dissect_new(TRUE, TRUE); + tap_build_interesting(cf->edt); epan_dissect_run(cf->edt, &cf->pseudo_header, cf->pd, cf->current_frame, NULL); @@ -4195,6 +3546,32 @@ cf_unmark_frame(capture_file *cf, frame_data *frame) } } +/* + * Ignore a particular frame. + */ +void +cf_ignore_frame(capture_file *cf, frame_data *frame) +{ + if (! frame->flags.ignored) { + frame->flags.ignored = TRUE; + if (cf->count > cf->ignored_count) + cf->ignored_count++; + } +} + +/* + * Un-ignore a particular frame. + */ +void +cf_unignore_frame(capture_file *cf, frame_data *frame) +{ + if (frame->flags.ignored) { + frame->flags.ignored = FALSE; + if (cf->ignored_count > 0) + cf->ignored_count--; + } +} + typedef struct { wtap_dumper *pdh; const char *fname; @@ -4262,7 +3639,7 @@ cf_save(capture_file *cf, const char *fname, packet_range_t *range, guint save_f wtap_dumper *pdh; save_callback_args_t callback_args; - cf_callback_invoke(cf_cb_file_safe_started, (gpointer) fname); + cf_callback_invoke(cf_cb_file_save_started, (gpointer)fname); /* don't write over an existing file. */ /* this should've been already checked by our caller, just to be sure... */ @@ -4276,7 +3653,6 @@ cf_save(capture_file *cf, const char *fname, packet_range_t *range, guint save_f packet_range_process_init(range); - if (packet_range_process_all(range) && save_format == cf->cd_t) { /* We're not filtering packets, and we're saving it in the format it's already in, so we can just move or copy the raw data. */ @@ -4284,7 +3660,7 @@ cf_save(capture_file *cf, const char *fname, packet_range_t *range, guint save_f if (cf->is_tempfile) { /* The file being saved is a temporary file from a live capture, so it doesn't need to stay around under that name; - first, try renaming the capture buffer file to the new name. */ + first, try renaming the capture buffer file to the new name. */ #ifndef _WIN32 if (ws_rename(cf->filename, fname) == 0) { /* That succeeded - there's no need to copy the source file. */ @@ -4292,22 +3668,22 @@ cf_save(capture_file *cf, const char *fname, packet_range_t *range, guint save_f do_copy = FALSE; } else { if (errno == EXDEV) { - /* They're on different file systems, so we have to copy the - file. */ - do_copy = TRUE; + /* They're on different file systems, so we have to copy the + file. */ + do_copy = TRUE; from_filename = cf->filename; - } else { - /* The rename failed, but not because they're on different - file systems - put up an error message. (Or should we - just punt and try to copy? The only reason why I'd - expect the rename to fail and the copy to succeed would - be if we didn't have permission to remove the file from - the temporary directory, and that might be fixable - but - is it worth requiring the user to go off and fix it?) */ - simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, - file_rename_error_message(errno), fname); - goto fail; - } + } else { + /* The rename failed, but not because they're on different + file systems - put up an error message. (Or should we + just punt and try to copy? The only reason why I'd + expect the rename to fail and the copy to succeed would + be if we didn't have permission to remove the file from + the temporary directory, and that might be fixable - but + is it worth requiring the user to go off and fix it?) */ + simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, + file_rename_error_message(errno), fname); + goto fail; + } } #else do_copy = TRUE; @@ -4375,7 +3751,7 @@ cf_save(capture_file *cf, const char *fname, packet_range_t *range, guint save_f } } - cf_callback_invoke(cf_cb_file_safe_finished, NULL); + cf_callback_invoke(cf_cb_file_save_finished, NULL); if (packet_range_process_all(range)) { /* We saved the entire capture, not just some packets from it. @@ -4393,7 +3769,8 @@ cf_save(capture_file *cf, const char *fname, packet_range_t *range, guint save_f if ((cf_open(cf, fname, FALSE, &err)) == CF_OK) { /* XXX - report errors if this fails? What should we return if it fails or is aborted? */ - switch (cf_read(cf)) { + + switch (cf_read(cf, TRUE)) { case CF_READ_OK: case CF_READ_ERROR: @@ -4409,13 +3786,13 @@ cf_save(capture_file *cf, const char *fname, packet_range_t *range, guint save_f correctly for the "no capture file open" state). */ break; } - cf_callback_invoke(cf_cb_file_safe_reload_finished, NULL); + cf_callback_invoke(cf_cb_file_save_reload_finished, cf); } } return CF_OK; fail: - cf_callback_invoke(cf_cb_file_safe_failed, NULL); + cf_callback_invoke(cf_cb_file_save_failed, NULL); return CF_ERROR; } @@ -4472,10 +3849,10 @@ cf_open_failure_alert_box(const char *filename, int err, gchar *err_info, case WTAP_ERR_UNSUPPORTED_ENCAP: if (for_writing) { - simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, + simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Wireshark can't save this capture in that format."); } else { - simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, + simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "The file \"%s\" is a capture for a network type that Wireshark doesn't support.\n" "(%s)", filename, err_info); @@ -4485,10 +3862,10 @@ cf_open_failure_alert_box(const char *filename, int err, gchar *err_info, case WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED: if (for_writing) { - simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, + simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Wireshark can't save this capture in that format."); } else { - simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, + simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "The file \"%s\" is a capture for a network type that Wireshark doesn't support.", filename); } @@ -4505,11 +3882,11 @@ cf_open_failure_alert_box(const char *filename, int err, gchar *err_info, case WTAP_ERR_CANT_OPEN: if (for_writing) { - simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, + simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "The file \"%s\" could not be created for some unknown reason.", filename); } else { - simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, + simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "The file \"%s\" could not be opened for some unknown reason.", filename); } @@ -4573,36 +3950,6 @@ file_rename_error_message(int err) return errmsg; } -char * -cf_read_error_message(int err, gchar *err_info) -{ - static char errmsg_errno[1024+1]; - - switch (err) { - - case WTAP_ERR_UNSUPPORTED_ENCAP: - g_snprintf(errmsg_errno, sizeof(errmsg_errno), - "The file \"%%s\" has a packet with a network type that Wireshark doesn't support.\n(%s)", - err_info); - g_free(err_info); - break; - - case WTAP_ERR_BAD_RECORD: - g_snprintf(errmsg_errno, sizeof(errmsg_errno), - "An error occurred while reading from the file \"%%s\": %s.\n(%s)", - wtap_strerror(err), err_info); - g_free(err_info); - break; - - default: - g_snprintf(errmsg_errno, sizeof(errmsg_errno), - "An error occurred while reading from the file \"%%s\": %s.", - wtap_strerror(err)); - break; - } - return errmsg_errno; -} - static void cf_write_failure_alert_box(const char *filename, int err) { @@ -4674,7 +4021,7 @@ cf_reload(capture_file *cf) { is_tempfile = cf->is_tempfile; cf->is_tempfile = FALSE; if (cf_open(cf, filename, is_tempfile, &err) == CF_OK) { - switch (cf_read(cf)) { + switch (cf_read(cf, FALSE)) { case CF_READ_OK: case CF_READ_ERROR: @@ -4704,3 +4051,16 @@ cf_reload(capture_file *cf) { we should free up our copy. */ g_free(filename); } + +/* + * Editor modelines + * + * Local Variables: + * c-basic-offset: 2 + * tab-width: 8 + * indent-tabs-mode: nil + * End: + * + * ex: set shiftwidth=2 tabstop=8 expandtab + * :indentSize=2:tabSize=8:noTabs=true: + */