wireshark/epan/column-info.h
John Thacker 1b82eda9eb epan: Register dynamic column fields and make them filterable
Make the text of each registered column a FT_STRING field that can be
filtered, prefixed with _ws.col - these work in display filters, filters
in taps, coloring rules, Wireshark read filters, and in the -Y, -R, -e,
and -j options to tshark. Use them as the default "Apply as Filter" value
for the columns that aren't handled by anything else currently.

Because only the columns formats that actually correspond to columns
get filled in (invisible columns work), register and deregister the
fields when the columns change.

Use the lower case version of the rest of the COL_* define for each
column as the field name.

This adds a number of conditions to "when are the columns needed",
including when the main display filter or any filter on a tap is
using one of these fields.

Custom columns are currently not implemented. For custom columns, the
tree then has to be further primed with any fields used by the custom
columns as well. (Perhaps that should happen in epan_dissect_run() -
are there any cases where we construct the columns and don't want to
prime with any field that custom columns contains? Possibly in taps
that we know only use build in columns.)

Thus, for performance reasons, you're better off matching an ordinary
field if possible; it takes extra time to generate the columns and many
of them are numeric types. (Note that you can always convert a non-string
field to a string field if you want regex matching, consult the
*wireshark-filter(4)* man page.) It does save a bit on typing (especially
for a multifield custom column) and remembering the column title might
be easier in some cases.

The columns are set before the color filters, which means that you
can have a color filter that depends on a built-in column like Info or
Protocol.

Remove the special handling for the -e option to tshark. Note that
the behavior is a little different now, because fixed field names
are used instead of the titles (using the titles allowed illegal
filter names, because it wasn't going through the filter engine.)
For default names, this means that they're no longer capitalized,
so "_ws.col.info" instead of "_ws.col.Info" - hopefully a small
price in exchange for the filters working everywhere.

The output format for -T fields remains the same; all that special
handling is removed (except for remembering if someone asked for
a column field to know that columns should be constructed.)

They're also set before the postdissectors, so postdissectors can
have access.

Anything that depends on whether a packet and previous packets are
displayed (COL_DELTA_TIME_DIS or COL_CUMULATIVE_BYTES) doesn't work
the way most people expect, so don't register fields for those.
(The same is already true of color filters that use those, along with
color filters that use the color filter fields.)

Fix #16576. Fix #17971. Fix #4684. Fix #13491. Fix #13941.
2023-07-25 00:49:52 +00:00

130 lines
4.5 KiB
C

/* column-info.h
* Definitions for internal column structures and routines
*
* For internal Wireshark use only. Don't include this header in dissectors!
*
* Wireshark - Network traffic analyzer
* By Gerald Combs <gerald@wireshark.org>
* Copyright 1998 Gerald Combs
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#ifndef __COLUMN_INFO_H__
#define __COLUMN_INFO_H__
#include <glib.h>
#include <epan/column-utils.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/** @file
* Column info.
*/
typedef struct _proto_node proto_tree;
#define COLUMN_FIELD_FILTER "_ws.col."
/** Column expression */
typedef struct {
const gchar **col_expr; /**< Filter expression */
gchar **col_expr_val; /**< Value for filter expression */
} col_expr_t;
/** Individual column info */
typedef struct {
gint col_fmt; /**< Format of column */
gboolean *fmt_matx; /**< Specifies which formats apply to a column */
gchar *col_title; /**< Column titles */
gchar *col_custom_fields; /**< Custom column fields */
gint col_custom_occurrence;/**< Custom column field occurrence */
GSList *col_custom_fields_ids;/**< Custom column fields id */
struct epan_dfilter *col_custom_dfilter; /**< Compiled custom column field */
const gchar *col_data; /**< Column data */
gchar *col_buf; /**< Buffer into which to copy data for column */
int col_fence; /**< Stuff in column buffer before this index is immutable */
gboolean writable; /**< writable or not */
int hf_id;
} col_item_t;
/** Column info */
struct epan_column_info {
const struct epan_session *epan;
gint num_cols; /**< Number of columns */
col_item_t *columns; /**< All column data */
gint *col_first; /**< First column number with a given format */
gint *col_last; /**< Last column number with a given format */
col_expr_t col_expr; /**< Column expressions and values */
gboolean writable; /**< writable or not @todo Are we still writing to the columns? */
GRegex *prime_regex; /**< Used to prime custom columns */
};
/** Allocate all the data structures for constructing column data, given
* the number of columns.
*/
WS_DLL_PUBLIC void col_setup(column_info *cinfo, const gint num_cols);
/** Cleanup all the data structures for constructing column data;
* undoes the alocations that col_setup() does.
*/
WS_DLL_PUBLIC void col_cleanup(column_info *cinfo);
/** Initialize the data structures for constructing column data.
*/
extern void col_init(column_info *cinfo, const struct epan_session *epan);
/** Fill in all columns of the given packet which are based on values from frame_data.
*/
WS_DLL_PUBLIC void col_fill_in_frame_data(const frame_data *fd, column_info *cinfo, const gint col, gboolean const fill_col_exprs);
/** Fill in all (non-custom) columns of the given packet.
*/
WS_DLL_PUBLIC void col_fill_in(packet_info *pinfo, const gboolean fill_col_exprs, const gboolean fill_fd_colums);
/** Fill in columns if we got an error reading the packet.
* We set most columns to "???", and set the Info column to an error
* message.
*/
WS_DLL_PUBLIC void col_fill_in_error(column_info *cinfo, frame_data *fdata, const gboolean fill_col_exprs, const gboolean fill_fd_colums);
/** Check to see if our column data has changed, e.g. we have new request/response info.
*/
WS_DLL_PUBLIC gboolean col_data_changed(void);
void col_custom_set_edt(struct epan_dissect *edt, column_info *cinfo);
WS_DLL_PUBLIC
void col_custom_prime_edt(struct epan_dissect *edt, column_info *cinfo);
/** Get a filter expression for a custom column. This string must be g_free'd.
*/
WS_DLL_PUBLIC
char* col_custom_get_filter(struct epan_dissect *edt, column_info *cinfo, const gint col);
WS_DLL_PUBLIC
gboolean have_custom_cols(column_info *cinfo);
WS_DLL_PUBLIC
gboolean have_field_extractors(void);
WS_DLL_PUBLIC
gboolean col_has_time_fmt(column_info *cinfo, const gint col);
WS_DLL_PUBLIC
gboolean col_based_on_frame_data(column_info *cinfo, const gint col);
void
col_register_protocol(void);
extern
void col_dissect(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __COLUMN_INFO_H__ */