wireshark/epan/dfilter/dfunctions.c

347 lines
8.8 KiB
C

/*
* Wireshark - Network traffic analyzer
*
* Copyright 2006 Gilbert Ramirez <gram@alumni.rice.edu>
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "config.h"
#include <glib.h>
#include "dfilter-int.h"
#include "dfunctions.h"
#include <string.h>
#include <ftypes/ftypes-int.h>
#include <ftypes/ftypes.h>
#include <epan/exceptions.h>
#include <wsutil/ws_assert.h>
/* Convert an FT_STRING using a callback function */
static gboolean
string_walk(GList* arg1list, GList **retval, gchar(*conv_func)(gchar))
{
GList *arg1;
fvalue_t *arg_fvalue;
fvalue_t *new_ft_string;
char *s, *c;
arg1 = arg1list;
while (arg1) {
arg_fvalue = (fvalue_t *)arg1->data;
/* XXX - it would be nice to handle FT_TVBUFF, too */
if (IS_FT_STRING(fvalue_type_ftenum(arg_fvalue))) {
s = (char *)wmem_strdup(NULL, (gchar *)fvalue_get(arg_fvalue));
for (c = s; *c; c++) {
*c = conv_func(*c);
}
new_ft_string = fvalue_new(FT_STRING);
fvalue_set_string(new_ft_string, s);
wmem_free(NULL, s);
*retval = g_list_append(*retval, new_ft_string);
}
arg1 = arg1->next;
}
return TRUE;
}
/* dfilter function: lower() */
static gboolean
df_func_lower(GList* arg1list, GList *arg2junk _U_, GList **retval)
{
return string_walk(arg1list, retval, g_ascii_tolower);
}
/* dfilter function: upper() */
static gboolean
df_func_upper(GList* arg1list, GList *arg2junk _U_, GList **retval)
{
return string_walk(arg1list, retval, g_ascii_toupper);
}
/* dfilter function: len() */
static gboolean
df_func_len(GList* arg1list, GList *arg2junk _U_, GList **retval)
{
GList *arg1;
fvalue_t *arg_fvalue;
fvalue_t *ft_len;
arg1 = arg1list;
while (arg1) {
arg_fvalue = (fvalue_t *)arg1->data;
ft_len = fvalue_new(FT_UINT32);
fvalue_set_uinteger(ft_len, fvalue_length(arg_fvalue));
*retval = g_list_append(*retval, ft_len);
arg1 = arg1->next;
}
return TRUE;
}
/* dfilter function: count() */
static gboolean
df_func_count(GList* arg1list, GList *arg2junk _U_, GList **retval)
{
fvalue_t *ft_ret;
guint32 num_items;
num_items = (guint32)g_list_length(arg1list);
ft_ret = fvalue_new(FT_UINT32);
fvalue_set_uinteger(ft_ret, num_items);
*retval = g_list_append(*retval, ft_ret);
return TRUE;
}
/* dfilter function: string() */
static gboolean
df_func_string(GList* arg1list, GList *arg2junk _U_, GList **retval)
{
GList *arg1 = arg1list;
fvalue_t *arg_fvalue;
fvalue_t *new_ft_string;
char *s;
while (arg1) {
arg_fvalue = (fvalue_t *)arg1->data;
switch (fvalue_type_ftenum(arg_fvalue))
{
case FT_UINT8:
case FT_UINT16:
case FT_UINT24:
case FT_UINT32:
case FT_UINT40:
case FT_UINT48:
case FT_UINT56:
case FT_UINT64:
case FT_INT8:
case FT_INT16:
case FT_INT32:
case FT_INT40:
case FT_INT48:
case FT_INT56:
case FT_INT64:
case FT_IPv4:
case FT_IPv6:
case FT_FLOAT:
case FT_DOUBLE:
case FT_ETHER:
case FT_FRAMENUM:
case FT_AX25:
case FT_IPXNET:
case FT_GUID:
case FT_OID:
case FT_EUI64:
case FT_VINES:
case FT_REL_OID:
case FT_SYSTEM_ID:
case FT_FCWWN:
case FT_IEEE_11073_SFLOAT:
case FT_IEEE_11073_FLOAT:
s = fvalue_to_string_repr(NULL, arg_fvalue, FTREPR_DFILTER, BASE_NONE);
/* Ensure we have an allocated string here */
if (!s)
s = wmem_strdup(NULL, "");
break;
default:
return TRUE;
}
new_ft_string = fvalue_new(FT_STRING);
fvalue_set_string(new_ft_string, s);
wmem_free(NULL, s);
*retval = g_list_append(*retval, new_ft_string);
arg1 = arg1->next;
}
return TRUE;
}
/* For upper() and lower() checks that the parameter passed to
* it is an FT_STRING */
static void
ul_semcheck_params(dfwork_t *dfw, int param_num, stnode_t *st_node)
{
sttype_id_t type;
ftenum_t ftype;
header_field_info *hfinfo;
type = stnode_type_id(st_node);
if (param_num == 0) {
switch(type) {
case STTYPE_FIELD:
hfinfo = (header_field_info *)stnode_data(st_node);
ftype = hfinfo->type;
if (!IS_FT_STRING(ftype)) {
dfilter_fail(dfw, "Only strings can be used in upper() or lower() or len()");
THROW(TypeError);
}
break;
default:
dfilter_fail(dfw, "Only string-type fields can be used in upper() or lower() or len()");
THROW(TypeError);
}
}
else {
ws_assert_not_reached();
}
}
/* For len() checks that the parameter passed is valid */
static void
ul_semcheck_len_params(dfwork_t *dfw, int param_num, stnode_t *st_node)
{
sttype_id_t type;
type = stnode_type_id(st_node);
if (param_num == 0) {
switch(type) {
case STTYPE_FIELD:
break;
default:
dfilter_fail(dfw, "invalid type in function len()");
THROW(TypeError);
}
}
else {
ws_assert_not_reached();
}
}
static void
ul_semcheck_field_param(dfwork_t *dfw, int param_num, stnode_t *st_node)
{
sttype_id_t type;
type = stnode_type_id(st_node);
if (param_num == 0) {
switch(type) {
case STTYPE_FIELD:
break;
default:
dfilter_fail(dfw, "Only type fields can be used as parameter for count()");
THROW(TypeError);
}
}
else {
ws_assert_not_reached();
}
}
static void
ul_semcheck_string_param(dfwork_t *dfw, int param_num, stnode_t *st_node)
{
sttype_id_t type;
ftenum_t ftype;
header_field_info *hfinfo;
const char* msg = "To string conversion for this field is not supported";
type = stnode_type_id(st_node);
if (param_num == 0) {
switch(type) {
case STTYPE_FIELD:
hfinfo = (header_field_info *)stnode_data(st_node);
ftype = hfinfo->type;
switch (ftype)
{
case FT_UINT8:
case FT_UINT16:
case FT_UINT24:
case FT_UINT32:
case FT_UINT40:
case FT_UINT48:
case FT_UINT56:
case FT_UINT64:
case FT_INT8:
case FT_INT16:
case FT_INT32:
case FT_INT40:
case FT_INT48:
case FT_INT56:
case FT_INT64:
case FT_IPv4:
case FT_IPv6:
case FT_FLOAT:
case FT_DOUBLE:
case FT_ETHER:
case FT_FRAMENUM:
case FT_AX25:
case FT_IPXNET:
case FT_GUID:
case FT_OID:
case FT_EUI64:
case FT_VINES:
case FT_REL_OID:
case FT_SYSTEM_ID:
case FT_FCWWN:
case FT_IEEE_11073_SFLOAT:
case FT_IEEE_11073_FLOAT:
break;
default:
dfilter_fail(dfw, "%s", msg);
THROW(TypeError);
break;
}
break;
default:
dfilter_fail(dfw, "%s", msg);
THROW(TypeError);
}
}
else {
ws_assert_not_reached();
}
}
/* The table of all display-filter functions */
static df_func_def_t
df_functions[] = {
{ "lower", df_func_lower, FT_STRING, 1, 1, ul_semcheck_params },
{ "upper", df_func_upper, FT_STRING, 1, 1, ul_semcheck_params },
{ "len", df_func_len, FT_UINT32, 1, 1, ul_semcheck_len_params },
{ "count", df_func_count, FT_UINT32, 1, 1, ul_semcheck_field_param },
{ "string", df_func_string, FT_STRING, 1, 1, ul_semcheck_string_param },
{ NULL, NULL, FT_NONE, 0, 0, NULL }
};
/* Lookup a display filter function record by name */
df_func_def_t*
df_func_lookup(const char *name)
{
df_func_def_t *func_def;
func_def = df_functions;
while (func_def->function != NULL) {
if (strcmp(func_def->name, name) == 0) {
return func_def;
}
func_def++;
}
return NULL;
}
/*
* Editor modelines - https://www.wireshark.org/tools/modelines.html
*
* Local variables:
* c-basic-offset: 4
* tab-width: 8
* indent-tabs-mode: nil
* End:
*
* vi: set shiftwidth=4 tabstop=8 expandtab:
* :indentSize=4:tabSize=8:noTabs=true:
*/