#include <epan/conversation.h>
#include <epan/epan_dissect.h>
#include <epan/tap.h>
-#include "stat_menu.h"
-#include "tap_dfilter_dlg.h"
#include <epan/dissectors/packet-data.h>
#include <epan/dissectors/packet-ber.h>
#include <epan/timestamp.h>
-#include "file_util.h"
-
-
+#include <epan/dfilter/dfilter-macro.h>
+#include <wsutil/file_util.h>
+#include <epan/column-utils.h>
+#include <epan/strutil.h>
#ifdef HAVE_LIBPCAP
gboolean auto_scroll_live;
#define FRAME_DATA_CHUNK_SIZE 1024
-/* one callback for now, we could have a list later */
-static cf_callback_t cf_cb = NULL;
-static gpointer cf_cb_user_data = NULL;
+/* this callback mechanism should possibly be replaced by the g_signal_...() stuff (if I only would know how :-) */
+typedef struct {
+ cf_callback_t cb_fct;
+ gpointer user_data;
+} cf_callback_data_t;
+
+static GList *cf_callbacks = NULL;
-void
+static void
cf_callback_invoke(int event, gpointer data)
{
- g_assert(cf_cb != NULL);
- cf_cb(event, data, cf_cb_user_data);
+ cf_callback_data_t *cb;
+ GList *cb_item = cf_callbacks;
+
+ /* 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);
+ }
}
void
cf_callback_add(cf_callback_t func, gpointer user_data)
{
- /* More than one callback listener is currently not implemented,
- but should be easy to do. */
- g_assert(cf_cb == NULL);
- cf_cb = func;
- cf_cb_user_data = user_data;
+ cf_callback_data_t *cb;
+
+ 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);
}
void
-cf_callback_remove(cf_callback_t func _U_)
+cf_callback_remove(cf_callback_t func)
{
- g_assert(cf_cb != NULL);
- cf_cb = NULL;
- cf_cb_user_data = NULL;
+ 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();
}
void
if (cf->filename != NULL) {
/* If it's a temporary file, remove it. */
if (cf->is_tempfile)
- eth_unlink(cf->filename);
+ ws_unlink(cf->filename);
g_free(cf->filename);
cf->filename = NULL;
}
/* No frame selected, no field in that frame selected. */
cf->current_frame = NULL;
+ cf->current_row = 0;
cf->finfo_selected = NULL;
/* Clear the packet list. */
const gchar *name_ptr;
const char *errmsg;
char errmsg_errno[1024+1];
- gchar err_str[2048+1];
gint64 data_offset;
progdlg_t *volatile progbar = NULL;
gboolean stop_flag;
dfilter_t *dfcode;
/* Compile the current display filter.
- * We assume this will not fail since cf->dfilter is only set in
+ * We assume this will not fail since cf->dfilter is only set in
* cf_filter IFF the filter was valid.
*/
dfcode=NULL;
cum_bytes=0;
reset_tap_listeners();
- tap_dfilter_dlg_update();
cf_callback_invoke(cf_cb_file_read_start, cf);
cf->lnk_t = wtap_file_encap(cf->wth);
cf->current_frame = cf->first_displayed;
+ cf->current_row = 0;
+
packet_list_thaw();
cf_callback_invoke(cf_cb_file_read_finished, cf);
errmsg = errmsg_errno;
break;
}
- g_snprintf(err_str, sizeof err_str, errmsg);
- simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, err_str);
+ simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", errmsg);
return CF_READ_ERROR;
} else
return CF_READ_OK;
dfilter_t *dfcode;
/* Compile the current display filter.
- * We assume this will not fail since cf->dfilter is only set in
+ * We assume this will not fail since cf->dfilter is only set in
* cf_filter IFF the filter was valid.
*/
dfcode=NULL;
*err = 0;
+ packet_list_check_end();
packet_list_freeze();
/*g_log(NULL, G_LOG_LEVEL_MESSAGE, "cf_continue_tail: %u new: %u", cf->count, to_read);*/
/* XXX - this causes "flickering" of the list */
packet_list_thaw();
- /* moving to the end of the packet list - if the user requested so and
+ /* moving to the end of the packet list - if the user requested so and
we have some new packets.
this doesn't seem to work well with a frozen GTK_Clist, so do this after
packet_list_thaw() is done, see bugzilla 1188 */
dfilter_t *dfcode;
/* Compile the current display filter.
- * We assume this will not fail since cf->dfilter is only set in
+ * We assume this will not fail since cf->dfilter is only set in
* cf_filter IFF the filter was valid.
*/
dfcode=NULL;
return CF_READ_ERROR;
}
+ packet_list_check_end();
packet_list_freeze();
while ((wtap_read(cf->wth, err, &err_info, &data_offset))) {
we have tap listeners;
+ 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()
- || num_tap_filters != 0)
+ || num_tap_filters != 0 || have_custom_cols(&cf->cinfo))
create_proto_tree = TRUE;
/* Dissect the frame. */
if (color_filters_used()) {
color_filters_prime_edt(edt);
}
+
+ col_custom_prime_edt(edt, &cf->cinfo);
+
tap_queue_init(edt);
epan_dissect_run(edt, pseudo_header, buf, fdata, &cf->cinfo);
tap_push_tapped_queue(edt);
/* 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 this was a TIME REF frame we should reset the cul bytes field */
if(edt->pi.fd->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;
+ fdata->cum_bytes = cum_bytes;
+ } else {
+ /* increase cum_bytes with this packets length */
+ cum_bytes += fdata->pkt_len;
}
- /* increase cum_bytes with this packets length */
- cum_bytes += fdata->pkt_len;
-
epan_dissect_fill_in_columns(edt);
/* If we haven't yet seen the first frame, this is it.
/* This is the last frame we've seen so far. */
cf->last_displayed = fdata;
+ fdata->col_expr.col_expr = cf->cinfo.col_expr.col_expr;
+ fdata->col_expr.col_expr_val = cf->cinfo.col_expr.col_expr_val;
+
row = packet_list_append(cf->cinfo.col_data, fdata);
- /* colorize packet: if packet is marked, use preferences,
- otherwise try to apply color filters */
+ /* 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) {
- fdata->color_filter = NULL;
packet_list_set_colors(row, &prefs.gui_marked_fg, &prefs.gui_marked_bg);
- } else {
- fdata->color_filter = color_filters_colorize_packet(row, edt);
}
/* Set the time of the previous displayed frame to the time of this
cf->count++;
cf->f_datalen = offset + phdr->caplen;
fdata->num = cf->count;
- row = add_packet_to_packet_list(fdata, cf, dfcode, pseudo_header, buf, TRUE);
+ if (!cf->redissecting) {
+ row = add_packet_to_packet_list(fdata, cf, dfcode, pseudo_header, buf, TRUE);
+ }
} else {
/* XXX - if we didn't have read filters, or if we could avoid
allocating the "frame_data" structure until we knew whether
int err_fileno;
int i;
char errmsg_errno[1024+1];
- gchar err_str[2048+1];
const char *errmsg;
gboolean got_read_error = FALSE, got_write_error = FALSE;
gint64 data_offset;
/* open the input files */
if (!merge_open_in_files(in_file_count, in_filenames, &in_files,
&open_err, &err_info, &err_fileno)) {
- free(in_files);
+ g_free(in_files);
cf_open_failure_alert_box(in_filenames[err_fileno], open_err, err_info,
FALSE, 0);
return CF_ERROR;
if (*out_filenamep != NULL) {
out_filename = *out_filenamep;
- out_fd = eth_open(out_filename, O_CREAT|O_TRUNC|O_BINARY, 0600);
+ out_fd = ws_open(out_filename, O_CREAT|O_TRUNC|O_BINARY, 0600);
if (out_fd == -1)
open_err = errno;
} else {
if (out_fd == -1) {
err_info = NULL;
merge_close_in_files(in_file_count, in_files);
- free(in_files);
+ g_free(in_files);
cf_open_failure_alert_box(out_filename, open_err, NULL, TRUE, file_type);
return CF_ERROR;
}
merge_max_snapshot_length(in_file_count, in_files),
FALSE /* compressed */, &open_err);
if (pdh == NULL) {
- eth_close(out_fd);
+ ws_close(out_fd);
merge_close_in_files(in_file_count, in_files);
- free(in_files);
+ g_free(in_files);
cf_open_failure_alert_box(out_filename, open_err, err_info, TRUE,
file_type);
return CF_ERROR;
errmsg = errmsg_errno;
break;
}
- g_snprintf(err_str, sizeof err_str, errmsg, in_files[i].filename);
- simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, err_str);
+ simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, errmsg, in_files[i].filename);
}
}
}
have to. */
return CF_ERROR;
} else
- return CF_READ_OK;
+ return CF_OK;
}
cf_status_t
dfilter_t *dfcode;
/* Compile the current display filter.
- * We assume this will not fail since cf->dfilter is only set in
+ * We assume this will not fail since cf->dfilter is only set in
* cf_filter IFF the filter was valid.
*/
dfcode=NULL;
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;
+
/* Initialize all data structures used for dissection. */
init_dissection();
}
prev_frame = fdata;
}
+ /* We are done redissecting the packet list. */
+ cf->redissecting = FALSE;
+
/* Re-sort the list using the previously selected order */
packet_list_set_sort_column();
/* 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;
+ }
packet_list_set_selected_row(selected_row);
}
do_columns ? &cf->cinfo : NULL)) {
case PSP_FINISHED:
/* Completed successfully. */
- return CF_OK;
+ return CF_READ_OK;
case PSP_STOPPED:
/* Well, the user decided to abort the refiltering.
the dissection or the hex data.
XXX - do we need it if we're just printing the hex data? */
proto_tree_needed =
- args->print_args->print_dissections != print_dissections_none || args->print_args->print_hex;
+ args->print_args->print_dissections != print_dissections_none || args->print_args->print_hex || have_custom_cols(&cf->cinfo);
edt = epan_dissect_new(proto_tree_needed, proto_tree_needed);
/* Fill in the column information if we're printing the summary
FILE *fh;
psp_return_t ret;
- fh = eth_fopen(print_args->file, "w");
+ fh = ws_fopen(print_args->file, "w");
if (fh == NULL)
return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
{
FILE *fh = argsp;
epan_dissect_t *edt;
+ gboolean proto_tree_needed;
- /* Fill in the column information, but don't create the protocol tree. */
- edt = epan_dissect_new(FALSE, FALSE);
+ /* Fill in the column information, only create the protocol tree
+ if having custom columns. */
+ proto_tree_needed = have_custom_cols(&cf->cinfo);
+ edt = epan_dissect_new(proto_tree_needed, proto_tree_needed);
epan_dissect_run(edt, pseudo_header, pd, fdata, &cf->cinfo);
epan_dissect_fill_in_columns(edt);
FILE *fh;
psp_return_t ret;
- fh = eth_fopen(print_args->file, "w");
+ fh = ws_fopen(print_args->file, "w");
if (fh == NULL)
return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
{
FILE *fh = argsp;
epan_dissect_t *edt;
+ gboolean proto_tree_needed;
- /* Fill in the column information, but don't create the protocol tree. */
- edt = epan_dissect_new(FALSE, FALSE);
+ /* Fill in the column information, only create the protocol tree
+ if having custom columns. */
+ proto_tree_needed = have_custom_cols(&cf->cinfo);
+ edt = epan_dissect_new(proto_tree_needed, proto_tree_needed);
epan_dissect_run(edt, pseudo_header, pd, fdata, &cf->cinfo);
epan_dissect_fill_in_columns(edt);
FILE *fh;
psp_return_t ret;
- fh = eth_fopen(print_args->file, "w");
+ fh = ws_fopen(print_args->file, "w");
if (fh == NULL)
return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
return CF_PRINT_OK;
}
+static gboolean
+write_carrays_packet(capture_file *cf _U_, frame_data *fdata,
+ union wtap_pseudo_header *pseudo_header _U_,
+ const guint8 *pd, void *argsp)
+{
+ FILE *fh = argsp;
+
+ proto_tree_write_carrays(pd, fdata->cap_len, fdata->num, fh);
+ return !ferror(fh);
+}
+
+cf_print_status_t
+cf_write_carrays_packets(capture_file *cf, print_args_t *print_args)
+{
+ FILE *fh;
+ psp_return_t ret;
+
+ fh = 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;
+}
+
/* 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. */
gchar status_str[100];
int progbar_nextstep;
int progbar_quantum;
- int first, last;
gboolean sorted_by_frame_column;
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)) {
+ 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;
}
- first = cf->cinfo.col_first[COL_CLS_TIME];
- g_assert(first >= 0);
- last = cf->cinfo.col_last[COL_CLS_TIME];
/* Freeze the packet list while we redo it, so we don't get any
screen updates while it happens. */
if (row != -1) {
/* This packet is in the summary list, on row "row". */
- for (i = first; i <= last; i++) {
- if (cf->cinfo.fmt_matx[i][COL_CLS_TIME]) {
+ 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_cls_time(fdata, &cf->cinfo, i);
+ col_set_fmt_time(fdata, &cf->cinfo, cf->cinfo.col_fmt[i], i);
packet_list_set_text(row, i, cf->cinfo.col_data[i]);
}
}
/* Set the column widths of those columns that show the time in
"command-line-specified" format. */
- for (i = first; i <= last; i++) {
- if (cf->cinfo.fmt_matx[i][COL_CLS_TIME]) {
- packet_list_set_cls_time_width(i);
+ 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);
}
}
match_ascii_and_unicode(capture_file *cf, frame_data *fdata, void *criterion)
{
cbs_t *info = criterion;
- const char *ascii_text = info->data;
+ const guint8 *ascii_text = info->data;
size_t textlen = info->data_len;
gboolean frame_matched;
guint32 buf_len;
match_ascii(capture_file *cf, frame_data *fdata, void *criterion)
{
cbs_t *info = criterion;
- const char *ascii_text = info->data;
+ const guint8 *ascii_text = info->data;
size_t textlen = info->data_len;
gboolean frame_matched;
guint32 buf_len;
match_unicode(capture_file *cf, frame_data *fdata, void *criterion)
{
cbs_t *info = criterion;
- const char *ascii_text = info->data;
+ const guint8 *ascii_text = info->data;
size_t textlen = info->data_len;
gboolean frame_matched;
guint32 buf_len;
i++;
if (c_match == textlen) {
frame_matched = TRUE;
- cf->search_pos = i; /* Save the position of the last character
+ cf->search_pos = i; /* Save the position of the last character
for highlighting the field. */
break;
}
c_match++;
if (c_match == datalen) {
frame_matched = TRUE;
- cf->search_pos = i; /* Save the position of the last character
+ cf->search_pos = i; /* Save the position of the last character
for highlighting the field. */
break;
}
/* Record that this frame is the current frame. */
cf->current_frame = fdata;
+ cf->current_row = row;
/* Create the logical protocol tree. */
if (cf->edt != NULL) {
epan_dissect_run(cf->edt, &cf->pseudo_header, cf->pd, cf->current_frame,
NULL);
+ dfilter_macro_build_ftv_cache(cf->edt->tree);
+
cf_callback_invoke(cf_cb_packet_selected, cf);
}
/* No packet is selected. */
cf->current_frame = NULL;
+ cf->current_row = 0;
cf_callback_invoke(cf_cb_packet_unselected, cf);
capture, so it doesn't need to stay around under that name;
first, try renaming the capture buffer file to the new name. */
#ifndef _WIN32
- if (eth_rename(cf->filename, fname) == 0) {
+ if (ws_rename(cf->filename, fname) == 0) {
/* That succeeded - there's no need to copy the source file. */
from_filename = NULL;
do_copy = FALSE;
}
char *
-cf_read_error_message(int err, const gchar *err_info)
+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),
+ 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);
- break;
+ 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:
guint8 pd[65536];
/* Copy the raw bytes of the file. */
- from_fd = eth_open(from_filename, O_RDONLY | O_BINARY, 0000 /* no creation so don't matter */);
+ from_fd = ws_open(from_filename, O_RDONLY | O_BINARY, 0000 /* no creation so don't matter */);
if (from_fd < 0) {
open_failure_alert_box(from_filename, errno, FALSE);
goto done;
may open the file in text mode, not binary mode, but we want
to copy the raw bytes of the file, so we need the output file
to be open in binary mode. */
- to_fd = eth_open(to_filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644);
+ to_fd = ws_open(to_filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644);
if (to_fd < 0) {
open_failure_alert_box(to_filename, errno, TRUE);
- eth_close(from_fd);
+ ws_close(from_fd);
goto done;
}
- while ((nread = eth_read(from_fd, pd, sizeof pd)) > 0) {
- nwritten = eth_write(to_fd, pd, nread);
+ while ((nread = ws_read(from_fd, pd, sizeof pd)) > 0) {
+ nwritten = ws_write(to_fd, pd, nread);
if (nwritten < nread) {
if (nwritten < 0)
err = errno;
else
err = WTAP_ERR_SHORT_WRITE;
write_failure_alert_box(to_filename, err);
- eth_close(from_fd);
- eth_close(to_fd);
+ ws_close(from_fd);
+ ws_close(to_fd);
goto done;
}
}
simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
"An error occurred while reading from the file \"%s\": %s.",
from_filename, strerror(err));
- eth_close(from_fd);
- eth_close(to_fd);
+ ws_close(from_fd);
+ ws_close(to_fd);
goto done;
}
- eth_close(from_fd);
- if (eth_close(to_fd) < 0) {
+ ws_close(from_fd);
+ if (ws_close(to_fd) < 0) {
write_failure_alert_box(to_filename, errno);
goto done;
}