dfilter: Add layer support for references
This adds support for using the layers filter with field references. Before: $ dftest 'ip.src != ${ip.src#2}' dftest: invalid character in macro name After: $ dftest 'ip.src != ${ip.src#2}' Filter: ip.src != ${ip.src#2} Syntax tree: 0 TEST_ALL_NE: 1 FIELD(ip.src <FT_IPv4>) 1 REFERENCE(ip.src#[2:1] <FT_IPv4>) Instructions: 00000 READ_TREE ip.src <FT_IPv4> -> reg#0 00001 IF_FALSE_GOTO 5 00002 READ_REFERENCE_R ${ip.src <FT_IPv4>} #[2:1] -> reg#1 00003 IF_FALSE_GOTO 5 00004 ALL_NE reg#0 != reg#1 00005 RETURN This requires adding another level of complexity to references. When loading references we need to copy the 'proto_layer_num' and add the logic to filter on that. The "layer" sttype is removed and replace by a new field sttype with support for a range. This is a nice cleanup for the semantic check and general simplification. The grammar is better too with this design. Range sttype is renamed to slice for clarity.
This commit is contained in:
parent
e9e6431d7b
commit
aaff0d21ae
|
@ -96,7 +96,8 @@ They previously shipped with Qt 5.12.2.
|
|||
For example the expression "all tcp.port > 1024" is true if and only if all tcp.port fields match the condition.
|
||||
Previously only the default behaviour to return true if any one field matches was supported.
|
||||
** Field references, of the form ${some.field}, are now part of the syntax of display filters. Previously they were implemented as macros.
|
||||
The new implementation is more efficient and allows matching multiple values, like any other protocol field.
|
||||
The new implementation is more efficient and has the same properties as protocol fields, like matching on multiple values
|
||||
using quantifiers and support for layer filtering.
|
||||
** Arithmetic is supported for numeric fields with the usual operators “+”, “-”, “*”, “/”, and “%”.
|
||||
Arithmetic expressions must be grouped using curly brackets (not parenthesis).
|
||||
** New display filter functions max(), min() and abs() have been added.
|
||||
|
|
|
@ -22,10 +22,11 @@ set(DFILTER_HEADER_FILES
|
|||
drange.h
|
||||
gencode.h
|
||||
semcheck.h
|
||||
sttype-field.h
|
||||
sttype-function.h
|
||||
sttype-pointer.h
|
||||
sttype-range.h
|
||||
sttype-set.h
|
||||
sttype-slice.h
|
||||
sttype-test.h
|
||||
syntax-tree.h
|
||||
)
|
||||
|
@ -38,10 +39,11 @@ set(DFILTER_NONGENERATED_FILES
|
|||
drange.c
|
||||
gencode.c
|
||||
semcheck.c
|
||||
sttype-field.c
|
||||
sttype-function.c
|
||||
sttype-pointer.c
|
||||
sttype-range.c
|
||||
sttype-set.c
|
||||
sttype-slice.c
|
||||
sttype-string.c
|
||||
sttype-test.c
|
||||
syntax-tree.c
|
||||
|
|
|
@ -16,6 +16,12 @@
|
|||
#include <epan/proto.h>
|
||||
#include <stdio.h>
|
||||
|
||||
typedef struct {
|
||||
const header_field_info *hfinfo;
|
||||
fvalue_t *value;
|
||||
int proto_layer_num;
|
||||
} df_reference_t;
|
||||
|
||||
/* Passed back to user */
|
||||
struct epan_dfilter {
|
||||
GPtrArray *insns;
|
||||
|
@ -44,7 +50,7 @@ typedef struct {
|
|||
int next_insn_id;
|
||||
int next_register;
|
||||
GPtrArray *deprecated;
|
||||
GHashTable *references; /* hfinfo -> pointer to GSList of fvalues */
|
||||
GHashTable *references; /* hfinfo -> pointer to array of references */
|
||||
GHashTable *loaded_references;
|
||||
char *expanded_text;
|
||||
stloc_t err_loc;
|
||||
|
@ -119,4 +125,10 @@ dfilter_fvalue_from_charconst(dfwork_t *dfw, ftenum_t ftype, stnode_t *st);
|
|||
|
||||
const char *tokenstr(int token);
|
||||
|
||||
df_reference_t *
|
||||
reference_new(const field_info *finfo);
|
||||
|
||||
void
|
||||
reference_free(df_reference_t *ref);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -101,7 +101,9 @@ static gboolean start_is_field_reference(const char *start)
|
|||
char saved_c;
|
||||
const header_field_info *hfinfo;
|
||||
|
||||
end = strchr(start, '}');
|
||||
end = strchr(start, '#');
|
||||
if (end == NULL)
|
||||
end = strchr(start, '}');
|
||||
if (end == NULL)
|
||||
return FALSE;
|
||||
|
||||
|
|
|
@ -238,13 +238,10 @@ dfilter_free(dfilter_t *df)
|
|||
g_free(df);
|
||||
}
|
||||
|
||||
static void free_reference(gpointer data)
|
||||
static void free_refs_array(gpointer data)
|
||||
{
|
||||
/* List data must be freed. */
|
||||
GSList **fvalues_ptr = data;
|
||||
if (*fvalues_ptr)
|
||||
g_slist_free_full(*fvalues_ptr, (GDestroyNotify)fvalue_free);
|
||||
g_free(fvalues_ptr);
|
||||
/* Array data must be freed. */
|
||||
(void)g_ptr_array_free(data, TRUE);
|
||||
}
|
||||
|
||||
|
||||
|
@ -255,7 +252,7 @@ dfwork_new(void)
|
|||
|
||||
dfw->references =
|
||||
g_hash_table_new_full(g_direct_hash, g_direct_equal,
|
||||
NULL, free_reference);
|
||||
NULL, (GDestroyNotify)free_refs_array);
|
||||
|
||||
dfw->loaded_references =
|
||||
g_hash_table_new_full(g_direct_hash, g_direct_equal,
|
||||
|
@ -340,7 +337,7 @@ const char *tokenstr(int token)
|
|||
case TOKEN_DOTDOT: return "DOTDOT";
|
||||
case TOKEN_LPAREN: return "LPAREN";
|
||||
case TOKEN_RPAREN: return "RPAREN";
|
||||
case TOKEN_REFERENCE: return "REFERENCE";
|
||||
case TOKEN_DOLLAR: return "DOLLAR";
|
||||
}
|
||||
return "<unknown>";
|
||||
}
|
||||
|
@ -675,6 +672,14 @@ dfilter_log_full(const char *domain, enum ws_log_level level,
|
|||
g_free(str);
|
||||
}
|
||||
|
||||
static int
|
||||
compare_ref_layer(gconstpointer _a, gconstpointer _b)
|
||||
{
|
||||
const df_reference_t *a = *(const df_reference_t **)_a;
|
||||
const df_reference_t *b = *(const df_reference_t **)_b;
|
||||
return a->proto_layer_num - b->proto_layer_num;
|
||||
}
|
||||
|
||||
void
|
||||
dfilter_load_field_references(const dfilter_t *df, proto_tree *tree)
|
||||
{
|
||||
|
@ -682,7 +687,7 @@ dfilter_load_field_references(const dfilter_t *df, proto_tree *tree)
|
|||
GPtrArray *finfos;
|
||||
field_info *finfo;
|
||||
header_field_info *hfinfo;
|
||||
GSList **fvalues_ptr;
|
||||
GPtrArray *refs;
|
||||
int i, len;
|
||||
|
||||
if (g_hash_table_size(df->references) == 0) {
|
||||
|
@ -691,10 +696,9 @@ dfilter_load_field_references(const dfilter_t *df, proto_tree *tree)
|
|||
}
|
||||
|
||||
g_hash_table_iter_init( &iter, df->references);
|
||||
while (g_hash_table_iter_next (&iter, (void **)&hfinfo, (void **)&fvalues_ptr)) {
|
||||
/* If we have a previous list free it and the data too */
|
||||
g_slist_free_full(*fvalues_ptr, (GDestroyNotify)fvalue_free);
|
||||
*fvalues_ptr = NULL;
|
||||
while (g_hash_table_iter_next (&iter, (void **)&hfinfo, (void **)&refs)) {
|
||||
/* If we have a previous array free the data */
|
||||
g_ptr_array_set_size(refs, 0);
|
||||
|
||||
while (hfinfo) {
|
||||
finfos = proto_find_finfo(tree, hfinfo->id);
|
||||
|
@ -706,15 +710,33 @@ dfilter_load_field_references(const dfilter_t *df, proto_tree *tree)
|
|||
len = finfos->len;
|
||||
for (i = 0; i < len; i++) {
|
||||
finfo = g_ptr_array_index(finfos, i);
|
||||
*fvalues_ptr = g_slist_prepend(*fvalues_ptr,
|
||||
fvalue_dup(&finfo->value));
|
||||
g_ptr_array_add(refs, reference_new(finfo));
|
||||
}
|
||||
|
||||
hfinfo = hfinfo->same_name_next;
|
||||
}
|
||||
|
||||
g_ptr_array_sort(refs, compare_ref_layer);
|
||||
}
|
||||
}
|
||||
|
||||
df_reference_t *
|
||||
reference_new(const field_info *finfo)
|
||||
{
|
||||
df_reference_t *ref = g_new(df_reference_t, 1);
|
||||
ref->hfinfo = finfo->hfinfo;
|
||||
ref->value = fvalue_dup(&finfo->value);
|
||||
ref->proto_layer_num = finfo->proto_layer_num;
|
||||
return ref;
|
||||
}
|
||||
|
||||
void
|
||||
reference_free(df_reference_t *ref)
|
||||
{
|
||||
fvalue_free(ref->value);
|
||||
g_free(ref);
|
||||
}
|
||||
|
||||
/*
|
||||
* Editor modelines - https://www.wireshark.org/tools/modelines.html
|
||||
*
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
|
||||
#include "dfilter-int.h"
|
||||
#include "dfunctions.h"
|
||||
#include "sttype-pointer.h"
|
||||
#include "sttype-field.h"
|
||||
#include "semcheck.h"
|
||||
|
||||
#include <string.h>
|
||||
|
@ -277,7 +277,7 @@ ul_semcheck_is_field_string(dfwork_t *dfw, const char *func_name, ftenum_t lhs_f
|
|||
dfw_resolve_unparsed(dfw, st_node);
|
||||
|
||||
if (stnode_type_id(st_node) == STTYPE_FIELD) {
|
||||
hfinfo = stnode_data(st_node);
|
||||
hfinfo = sttype_field_hfinfo(st_node);
|
||||
if (IS_FT_STRING(hfinfo->type)) {
|
||||
return FT_STRING;
|
||||
}
|
||||
|
@ -312,7 +312,7 @@ ul_semcheck_string_param(dfwork_t *dfw, const char *func_name, ftenum_t lhs_ftyp
|
|||
dfw_resolve_unparsed(dfw, st_node);
|
||||
|
||||
if (stnode_type_id(st_node) == STTYPE_FIELD) {
|
||||
hfinfo = stnode_data(st_node);
|
||||
hfinfo = sttype_field_hfinfo(st_node);
|
||||
switch (hfinfo->type) {
|
||||
case FT_UINT8:
|
||||
case FT_UINT16:
|
||||
|
@ -380,7 +380,7 @@ ul_semcheck_compare(dfwork_t *dfw, const char *func_name, ftenum_t lhs_ftype,
|
|||
ftype = check_function(dfw, arg, lhs_ftype);
|
||||
}
|
||||
else {
|
||||
ftype = sttype_pointer_ftenum(arg);
|
||||
ftype = sttype_field_ftenum(arg);
|
||||
}
|
||||
|
||||
if (ftype == FT_NONE) {
|
||||
|
@ -404,7 +404,7 @@ ul_semcheck_compare(dfwork_t *dfw, const char *func_name, ftenum_t lhs_ftype,
|
|||
ft_arg = check_function(dfw, arg, ftype);
|
||||
}
|
||||
else {
|
||||
ft_arg = sttype_pointer_ftenum(arg);
|
||||
ft_arg = sttype_field_ftenum(arg);
|
||||
}
|
||||
|
||||
if (ft_arg == FT_NONE) {
|
||||
|
@ -450,7 +450,7 @@ ul_semcheck_absolute_value(dfwork_t *dfw, const char *func_name, ftenum_t lhs_ft
|
|||
ftype = check_function(dfw, st_node, lhs_ftype);
|
||||
}
|
||||
else {
|
||||
ftype = sttype_pointer_ftenum(st_node);
|
||||
ftype = sttype_field_ftenum(st_node);
|
||||
}
|
||||
|
||||
if (ftype == FT_NONE) {
|
||||
|
|
|
@ -30,6 +30,7 @@ dfvm_opcode_tostr(dfvm_opcode_t code)
|
|||
case READ_TREE: return "READ_TREE";
|
||||
case READ_TREE_R: return "READ_TREE_R";
|
||||
case READ_REFERENCE: return "READ_REFERENCE";
|
||||
case READ_REFERENCE_R: return "READ_REFERENCE_R";
|
||||
case PUT_FVALUE: return "PUT_FVALUE";
|
||||
case ALL_EQ: return "ALL_EQ";
|
||||
case ANY_EQ: return "ANY_EQ";
|
||||
|
@ -299,7 +300,7 @@ dfvm_dump_str(wmem_allocator_t *alloc, dfilter_t *df, gboolean print_references)
|
|||
break;
|
||||
|
||||
case CHECK_EXISTS_R:
|
||||
wmem_strbuf_append_printf(buf, "%05d CHECK_EXISTS\t%s#[%s]\n",
|
||||
wmem_strbuf_append_printf(buf, "%05d CHECK_EXISTS_R\t%s #[%s]\n",
|
||||
id, arg1_str, arg2_str);
|
||||
break;
|
||||
|
||||
|
@ -309,7 +310,7 @@ dfvm_dump_str(wmem_allocator_t *alloc, dfilter_t *df, gboolean print_references)
|
|||
break;
|
||||
|
||||
case READ_TREE_R:
|
||||
wmem_strbuf_append_printf(buf, "%05d READ_TREE\t\t%s#[%s] -> %s\n",
|
||||
wmem_strbuf_append_printf(buf, "%05d READ_TREE_R\t%s #[%s] -> %s\n",
|
||||
id, arg1_str, arg3_str, arg2_str);
|
||||
break;
|
||||
|
||||
|
@ -318,6 +319,11 @@ dfvm_dump_str(wmem_allocator_t *alloc, dfilter_t *df, gboolean print_references)
|
|||
id, arg1_str, arg2_str);
|
||||
break;
|
||||
|
||||
case READ_REFERENCE_R:
|
||||
wmem_strbuf_append_printf(buf, "%05d READ_REFERENCE_R\t${%s} #[%s] -> %s\n",
|
||||
id, arg1_str, arg3_str, arg2_str);
|
||||
break;
|
||||
|
||||
case PUT_FVALUE:
|
||||
wmem_strbuf_append_printf(buf, "%05d PUT_FVALUE\t%s -> %s\n",
|
||||
id, arg1_str, arg2_str);
|
||||
|
@ -485,20 +491,18 @@ dfvm_dump_str(wmem_allocator_t *alloc, dfilter_t *df, gboolean print_references)
|
|||
g_hash_table_iter_init(&ref_iter, df->references);
|
||||
while (g_hash_table_iter_next(&ref_iter, &key, &value)) {
|
||||
const char *abbrev = ((header_field_info *)key)->abbrev;
|
||||
GSList *fvalues = *(GSList **)value;
|
||||
GPtrArray *refs_array = value;
|
||||
df_reference_t *ref;
|
||||
|
||||
wmem_strbuf_append_printf(buf, "${%s} = {", abbrev);
|
||||
|
||||
if (fvalues != NULL) {
|
||||
str = fvalue_to_debug_repr(NULL, fvalues->data);
|
||||
wmem_strbuf_append_printf(buf, "%s <%s>", str, fvalue_type_name(fvalues->data));
|
||||
g_free(str);
|
||||
|
||||
for (fvalues = fvalues->next; fvalues != NULL; fvalues = fvalues->next) {
|
||||
str = fvalue_to_debug_repr(NULL, fvalues->data);
|
||||
wmem_strbuf_append_printf(buf, ", %s <%s>", str, fvalue_type_name(fvalues->data));
|
||||
g_free(str);
|
||||
for (i = 0; i < refs_array->len; i++) {
|
||||
if (i != 0) {
|
||||
wmem_strbuf_append(buf, ", ");
|
||||
}
|
||||
ref = refs_array->pdata[i];
|
||||
str = fvalue_to_debug_repr(NULL, ref->value);
|
||||
wmem_strbuf_append_printf(buf, "%s <%s>", str, fvalue_type_name(ref->value));
|
||||
g_free(str);
|
||||
}
|
||||
wmem_strbuf_append(buf, "}\n");
|
||||
}
|
||||
|
@ -653,14 +657,58 @@ read_tree(dfilter_t *df, proto_tree *tree,
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
read_reference(dfilter_t *df, dfvm_value_t *arg1, dfvm_value_t *arg2)
|
||||
GSList *
|
||||
filter_refs_fvalues(GPtrArray *refs_array, drange_t *range)
|
||||
{
|
||||
GSList **fvalues_ptr;
|
||||
int length; /* maximum proto layer number. The numbers are sequential. */
|
||||
df_reference_t *last_ref, *ref;
|
||||
int cookie = -1;
|
||||
gboolean cookie_matches = false;
|
||||
int layer;
|
||||
GSList *fvalues = NULL;
|
||||
|
||||
/* refs array is sorted. */
|
||||
last_ref = refs_array->pdata[refs_array->len - 1];
|
||||
length = last_ref->proto_layer_num;
|
||||
|
||||
for (guint i = 0; i < refs_array->len; i++) {
|
||||
if (range == NULL) {
|
||||
fvalues = g_slist_prepend(fvalues, fvalue_dup(ref->value));
|
||||
continue;
|
||||
}
|
||||
|
||||
ref = refs_array->pdata[i];
|
||||
layer = ref->proto_layer_num;
|
||||
if (cookie == layer) {
|
||||
if (cookie_matches) {
|
||||
fvalues = g_slist_prepend(fvalues, fvalue_dup(ref->value));
|
||||
}
|
||||
}
|
||||
else {
|
||||
cookie = layer;
|
||||
cookie_matches = drange_contains_layer(range, layer, length);
|
||||
if (cookie_matches) {
|
||||
fvalues = g_slist_prepend(fvalues, fvalue_dup(ref->value));
|
||||
}
|
||||
}
|
||||
}
|
||||
return fvalues;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
read_reference(dfilter_t *df, dfvm_value_t *arg1, dfvm_value_t *arg2,
|
||||
dfvm_value_t *arg3)
|
||||
{
|
||||
GPtrArray *refs;
|
||||
drange_t *range = NULL;
|
||||
|
||||
header_field_info *hfinfo = arg1->value.hfinfo;
|
||||
int reg = arg2->value.numeric;
|
||||
|
||||
if (arg3) {
|
||||
range = arg3->value.drange;
|
||||
}
|
||||
|
||||
/* Already loaded in this run of the dfilter? */
|
||||
if (df->attempted_load[reg]) {
|
||||
if (df->registers[reg]) {
|
||||
|
@ -673,16 +721,16 @@ read_reference(dfilter_t *df, dfvm_value_t *arg1, dfvm_value_t *arg2)
|
|||
|
||||
df->attempted_load[reg] = TRUE;
|
||||
|
||||
fvalues_ptr = g_hash_table_lookup(df->references, hfinfo);
|
||||
if (*fvalues_ptr == NULL) {
|
||||
refs = g_hash_table_lookup(df->references, hfinfo);
|
||||
if (refs == NULL || refs->len == 0) {
|
||||
df->registers[reg] = NULL;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Shallow copy */
|
||||
df->registers[reg] = g_slist_copy(*fvalues_ptr);
|
||||
/* These values are referenced only, do not try to free it later. */
|
||||
df->free_registers[reg] = NULL;
|
||||
df->registers[reg] = filter_refs_fvalues(refs, range);
|
||||
/* Creates new value so own it. */
|
||||
df->free_registers[reg] = (GDestroyNotify)fvalue_free;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -1011,9 +1059,11 @@ debug_register(GSList *reg, guint32 num)
|
|||
wmem_strbuf_append_printf(buf, "Reg#%"G_GUINT32_FORMAT" = { ", num);
|
||||
for (l = reg; l != NULL; l = l->next) {
|
||||
s = fvalue_to_debug_repr(NULL, l->data);
|
||||
wmem_strbuf_append(buf, s);
|
||||
wmem_strbuf_append_printf(buf, "%s <%s>", s, fvalue_type_name(l->data));
|
||||
g_free(s);
|
||||
wmem_strbuf_append_c(buf, ' ');
|
||||
if (l->next != NULL) {
|
||||
wmem_strbuf_append(buf, ", ");
|
||||
}
|
||||
}
|
||||
wmem_strbuf_append_c(buf, '}');
|
||||
WS_DEBUG_HERE("%s", wmem_strbuf_get_str(buf));
|
||||
|
@ -1257,7 +1307,11 @@ dfvm_apply(dfilter_t *df, proto_tree *tree)
|
|||
break;
|
||||
|
||||
case READ_REFERENCE:
|
||||
accum = read_reference(df, arg1, arg2);
|
||||
accum = read_reference(df, arg1, arg2, NULL);
|
||||
break;
|
||||
|
||||
case READ_REFERENCE_R:
|
||||
accum = read_reference(df, arg1, arg2, arg3);
|
||||
break;
|
||||
|
||||
case PUT_FVALUE:
|
||||
|
|
|
@ -56,6 +56,7 @@ typedef enum {
|
|||
READ_TREE,
|
||||
READ_TREE_R,
|
||||
READ_REFERENCE,
|
||||
READ_REFERENCE_R,
|
||||
PUT_FVALUE,
|
||||
ALL_EQ,
|
||||
ANY_EQ,
|
||||
|
|
|
@ -243,7 +243,7 @@ drange_node_set_to_the_end(drange_node* drnode)
|
|||
|
||||
/* drange constructor */
|
||||
drange_t *
|
||||
drange_new(void)
|
||||
drange_new(drange_node* drnode)
|
||||
{
|
||||
drange_t * new_drange;
|
||||
new_drange = g_new(drange_t,1);
|
||||
|
@ -252,6 +252,10 @@ drange_new(void)
|
|||
new_drange->total_length = 0;
|
||||
new_drange->min_start_offset = G_MAXINT;
|
||||
new_drange->max_start_offset = G_MININT;
|
||||
|
||||
if (drnode)
|
||||
drange_append_drange_node(new_drange, drnode);
|
||||
|
||||
return new_drange;
|
||||
}
|
||||
|
||||
|
@ -269,7 +273,7 @@ drange_new_from_list(GSList *list)
|
|||
{
|
||||
drange_t *new_drange;
|
||||
|
||||
new_drange = drange_new();
|
||||
new_drange = drange_new(NULL);
|
||||
g_slist_foreach(list, drange_append_wrapper, new_drange);
|
||||
return new_drange;
|
||||
}
|
||||
|
@ -283,7 +287,7 @@ drange_dup(drange_t *org)
|
|||
if (!org)
|
||||
return NULL;
|
||||
|
||||
new_drange = drange_new();
|
||||
new_drange = drange_new(NULL);
|
||||
for (p = org->range_list; p; p = p->next) {
|
||||
drange_node *drnode = (drange_node *)p->data;
|
||||
drange_append_drange_node(new_drange, drange_node_dup(drnode));
|
||||
|
|
|
@ -70,7 +70,7 @@ void drange_node_set_end_offset(drange_node* drnode, gint offset);
|
|||
void drange_node_set_to_the_end(drange_node* drnode);
|
||||
|
||||
/* drange constructor */
|
||||
drange_t * drange_new(void);
|
||||
drange_t * drange_new(drange_node* drnode);
|
||||
drange_t * drange_new_from_list(GSList *list);
|
||||
drange_t * drange_dup(drange_t *org);
|
||||
|
||||
|
|
|
@ -12,7 +12,8 @@
|
|||
#include "gencode.h"
|
||||
#include "dfvm.h"
|
||||
#include "syntax-tree.h"
|
||||
#include "sttype-range.h"
|
||||
#include "sttype-field.h"
|
||||
#include "sttype-slice.h"
|
||||
#include "sttype-test.h"
|
||||
#include "sttype-set.h"
|
||||
#include "sttype-function.h"
|
||||
|
@ -66,6 +67,7 @@ select_opcode(dfvm_opcode_t op, test_match_t how)
|
|||
case READ_TREE:
|
||||
case READ_TREE_R:
|
||||
case READ_REFERENCE:
|
||||
case READ_REFERENCE_R:
|
||||
case PUT_FVALUE:
|
||||
case MK_SLICE:
|
||||
case MK_BITWISE_AND:
|
||||
|
@ -187,9 +189,7 @@ dfw_append_read_tree(dfwork_t *dfw, header_field_info *hfinfo,
|
|||
if (added_new_hfinfo) {
|
||||
while (hfinfo) {
|
||||
/* Record the FIELD_ID in hash of interesting fields. */
|
||||
g_hash_table_insert(dfw->interesting_fields,
|
||||
GINT_TO_POINTER(hfinfo->id),
|
||||
GUINT_TO_POINTER(TRUE));
|
||||
g_hash_table_add(dfw->interesting_fields, &hfinfo->id);
|
||||
hfinfo = hfinfo->same_name_next;
|
||||
}
|
||||
}
|
||||
|
@ -199,46 +199,43 @@ dfw_append_read_tree(dfwork_t *dfw, header_field_info *hfinfo,
|
|||
|
||||
/* returns register number */
|
||||
static dfvm_value_t *
|
||||
dfw_append_read_reference(dfwork_t *dfw, header_field_info *hfinfo)
|
||||
dfw_append_read_reference(dfwork_t *dfw, header_field_info *hfinfo,
|
||||
drange_t *range)
|
||||
{
|
||||
dfvm_insn_t *insn;
|
||||
dfvm_value_t *reg_val, *val1;
|
||||
GSList **fvalues_ptr;
|
||||
gboolean added_new_hfinfo = FALSE;
|
||||
dfvm_value_t *reg_val, *val1, *val3;
|
||||
GPtrArray *refs_array;
|
||||
|
||||
/* Rewind to find the first field of this name. */
|
||||
while (hfinfo->same_name_prev_id != -1) {
|
||||
hfinfo = proto_registrar_get_nth(hfinfo->same_name_prev_id);
|
||||
}
|
||||
|
||||
/* Keep track of which registers
|
||||
* were used for which hfinfo's so that we
|
||||
* can re-use registers. */
|
||||
reg_val = g_hash_table_lookup(dfw->loaded_references, hfinfo);
|
||||
if (!reg_val) {
|
||||
reg_val = dfvm_value_new_register(dfw->next_register++);
|
||||
g_hash_table_insert(dfw->loaded_references, hfinfo, dfvm_value_ref(reg_val));
|
||||
added_new_hfinfo = TRUE;
|
||||
}
|
||||
|
||||
insn = dfvm_insn_new(READ_REFERENCE);
|
||||
/* We can't reuse registers with a filter so just skip
|
||||
* that optimization and don't reuse them at all. */
|
||||
val1 = dfvm_value_new_hfinfo(hfinfo);
|
||||
reg_val = dfvm_value_new_register(dfw->next_register++);
|
||||
if (range) {
|
||||
val3 = dfvm_value_new_drange(range);
|
||||
insn = dfvm_insn_new(READ_REFERENCE_R);
|
||||
}
|
||||
else {
|
||||
val3 = NULL;
|
||||
insn = dfvm_insn_new(READ_REFERENCE);
|
||||
}
|
||||
insn->arg1 = dfvm_value_ref(val1);
|
||||
insn->arg2 = dfvm_value_ref(reg_val);
|
||||
insn->arg3 = dfvm_value_ref(val3);
|
||||
dfw_append_insn(dfw, insn);
|
||||
|
||||
fvalues_ptr = g_new(GSList *, 1);
|
||||
*fvalues_ptr = NULL;
|
||||
g_hash_table_insert(dfw->references, hfinfo, fvalues_ptr);
|
||||
refs_array = g_ptr_array_new_with_free_func((GDestroyNotify)reference_free);
|
||||
g_hash_table_insert(dfw->references, hfinfo, refs_array);
|
||||
|
||||
if (added_new_hfinfo) {
|
||||
while (hfinfo) {
|
||||
/* Record the FIELD_ID in hash of interesting fields. */
|
||||
g_hash_table_insert(dfw->interesting_fields,
|
||||
GINT_TO_POINTER(hfinfo->id),
|
||||
GUINT_TO_POINTER(TRUE));
|
||||
hfinfo = hfinfo->same_name_next;
|
||||
}
|
||||
/* Record the FIELD_ID in hash of interesting fields. */
|
||||
while (hfinfo) {
|
||||
/* Record the FIELD_ID in hash of interesting fields. */
|
||||
g_hash_table_add(dfw->interesting_fields, &hfinfo->id);
|
||||
hfinfo = hfinfo->same_name_next;
|
||||
}
|
||||
|
||||
return reg_val;
|
||||
|
@ -252,16 +249,16 @@ dfw_append_mk_slice(dfwork_t *dfw, stnode_t *node, GSList **jumps_ptr)
|
|||
dfvm_insn_t *insn;
|
||||
dfvm_value_t *reg_val, *val1, *val3;
|
||||
|
||||
entity = sttype_range_entity(node);
|
||||
entity = sttype_slice_entity(node);
|
||||
|
||||
insn = dfvm_insn_new(MK_SLICE);
|
||||
val1 = gen_entity(dfw, entity, jumps_ptr);
|
||||
insn->arg1 = dfvm_value_ref(val1);
|
||||
reg_val = dfvm_value_new_register(dfw->next_register++);
|
||||
insn->arg2 = dfvm_value_ref(reg_val);
|
||||
val3 = dfvm_value_new_drange(sttype_range_drange_steal(node));
|
||||
val3 = dfvm_value_new_drange(sttype_slice_drange_steal(node));
|
||||
insn->arg3 = dfvm_value_ref(val3);
|
||||
sttype_range_remove_drange(node);
|
||||
sttype_slice_remove_drange(node);
|
||||
dfw_append_insn(dfw, insn);
|
||||
|
||||
return reg_val;
|
||||
|
@ -510,22 +507,19 @@ gen_entity(dfwork_t *dfw, stnode_t *st_arg, GSList **jumps_ptr)
|
|||
sttype_id_t e_type;
|
||||
dfvm_value_t *val;
|
||||
header_field_info *hfinfo;
|
||||
drange_t *range = NULL;
|
||||
e_type = stnode_type_id(st_arg);
|
||||
|
||||
if (e_type == STTYPE_FIELD) {
|
||||
hfinfo = stnode_data(st_arg);
|
||||
val = dfw_append_read_tree(dfw, hfinfo, NULL);
|
||||
hfinfo = sttype_field_hfinfo(st_arg);
|
||||
range = sttype_field_drange_steal(st_arg);
|
||||
val = dfw_append_read_tree(dfw, hfinfo, range);
|
||||
*jumps_ptr = g_slist_prepend(*jumps_ptr, dfw_append_jump(dfw));
|
||||
}
|
||||
else if (e_type == STTYPE_REFERENCE) {
|
||||
hfinfo = stnode_data(st_arg);
|
||||
val = dfw_append_read_reference(dfw, hfinfo);
|
||||
*jumps_ptr = g_slist_prepend(*jumps_ptr, dfw_append_jump(dfw));
|
||||
}
|
||||
else if (e_type == STTYPE_LAYER) {
|
||||
stnode_t *entity = sttype_range_entity(st_arg);
|
||||
drange_t *range = sttype_range_drange_steal(st_arg);
|
||||
val = dfw_append_read_tree(dfw, stnode_data(entity), range);
|
||||
hfinfo = sttype_field_hfinfo(st_arg);
|
||||
range = sttype_field_drange_steal(st_arg);
|
||||
val = dfw_append_read_reference(dfw, hfinfo, range);
|
||||
*jumps_ptr = g_slist_prepend(*jumps_ptr, dfw_append_jump(dfw));
|
||||
}
|
||||
else if (e_type == STTYPE_FVALUE) {
|
||||
|
@ -556,18 +550,10 @@ gen_exists(dfwork_t *dfw, stnode_t *st_node)
|
|||
dfvm_insn_t *insn;
|
||||
dfvm_value_t *val1, *val2 = NULL;
|
||||
header_field_info *hfinfo;
|
||||
stnode_t *st_arg;
|
||||
drange_t *range;
|
||||
drange_t *range = NULL;
|
||||
|
||||
if (stnode_type_id(st_node) == STTYPE_LAYER) {
|
||||
st_arg = sttype_range_entity(st_node);
|
||||
range = sttype_range_drange_steal(st_node);
|
||||
}
|
||||
else {
|
||||
st_arg = st_node;
|
||||
range = NULL;
|
||||
}
|
||||
hfinfo = stnode_data(st_arg);
|
||||
hfinfo = sttype_field_hfinfo(st_node);
|
||||
range = sttype_field_drange_steal(st_node);
|
||||
|
||||
/* Rewind to find the first field of this name. */
|
||||
while (hfinfo->same_name_prev_id != -1) {
|
||||
|
@ -592,9 +578,7 @@ gen_exists(dfwork_t *dfw, stnode_t *st_node)
|
|||
|
||||
/* Record the FIELD_ID in hash of interesting fields. */
|
||||
while (hfinfo) {
|
||||
g_hash_table_insert(dfw->interesting_fields,
|
||||
GINT_TO_POINTER(hfinfo->id),
|
||||
GUINT_TO_POINTER(TRUE));
|
||||
g_hash_table_add(dfw->interesting_fields, &hfinfo->id);
|
||||
hfinfo = hfinfo->same_name_next;
|
||||
}
|
||||
}
|
||||
|
@ -728,7 +712,6 @@ gencode(dfwork_t *dfw, stnode_t *st_node)
|
|||
gen_test(dfw, st_node);
|
||||
break;
|
||||
case STTYPE_FIELD:
|
||||
case STTYPE_LAYER:
|
||||
gen_exists(dfw, st_node);
|
||||
break;
|
||||
case STTYPE_ARITHMETIC:
|
||||
|
@ -791,7 +774,7 @@ dfw_gencode(dfwork_t *dfw)
|
|||
{
|
||||
dfw->insns = g_ptr_array_new();
|
||||
dfw->loaded_fields = g_hash_table_new(g_direct_hash, g_direct_equal);
|
||||
dfw->interesting_fields = g_hash_table_new(g_direct_hash, g_direct_equal);
|
||||
dfw->interesting_fields = g_hash_table_new(g_int_hash, g_int_equal);
|
||||
gencode(dfw, dfw->st_root);
|
||||
dfw_append_insn(dfw, dfvm_insn_new(RETURN));
|
||||
optimize(dfw);
|
||||
|
@ -806,7 +789,7 @@ typedef struct {
|
|||
static void
|
||||
get_hash_key(gpointer key, gpointer value _U_, gpointer user_data)
|
||||
{
|
||||
int field_id = GPOINTER_TO_INT(key);
|
||||
int field_id = *(int *)key;
|
||||
hash_key_iterator *hki = (hash_key_iterator *)user_data;
|
||||
|
||||
hki->fields[hki->i] = field_id;
|
||||
|
|
|
@ -6,7 +6,8 @@
|
|||
|
||||
#include "dfilter-int.h"
|
||||
#include "syntax-tree.h"
|
||||
#include "sttype-range.h"
|
||||
#include "sttype-field.h"
|
||||
#include "sttype-slice.h"
|
||||
#include "sttype-test.h"
|
||||
#include "sttype-function.h"
|
||||
#include "sttype-set.h"
|
||||
|
@ -44,6 +45,9 @@ new_function(dfwork_t *dfw, stnode_t *node);
|
|||
%type range_node_list {GSList*}
|
||||
%destructor range_node_list {drange_node_free_list($$);}
|
||||
|
||||
%type layer {GSList*}
|
||||
%destructor layer {drange_node_free_list($$);}
|
||||
|
||||
%type function_params {GSList*}
|
||||
%destructor function_params {st_funcparams_free($$);}
|
||||
|
||||
|
@ -118,31 +122,71 @@ atom(A) ::= STRING(S). { A = S; }
|
|||
atom(A) ::= CHARCONST(N). { A = N; }
|
||||
atom(A) ::= UNPARSED(S). { A = S; }
|
||||
atom(A) ::= LITERAL(S). { A = S; }
|
||||
atom(A) ::= FIELD(F). { A = F; }
|
||||
atom(A) ::= REFERENCE(F). { A = F; }
|
||||
|
||||
layer(R) ::= atom(F) HASH LBRACKET range_node_list(L) RBRACKET.
|
||||
layer(R) ::= HASH LBRACKET range_node_list(L) RBRACKET.
|
||||
{
|
||||
R = stnode_new(STTYPE_LAYER, NULL, NULL, NULL);
|
||||
sttype_range_set(R, F, L);
|
||||
g_slist_free(L);
|
||||
R = L;
|
||||
}
|
||||
|
||||
layer(R) ::= atom(F) HASH INTEGER(N).
|
||||
layer(R) ::= HASH INTEGER(N).
|
||||
{
|
||||
R = stnode_new(STTYPE_LAYER, NULL, NULL, stnode_location(F));
|
||||
char *err_msg = sttype_range_set_number(R, F, stnode_token(N));
|
||||
char *err_msg = NULL;
|
||||
drange_node *range = drange_node_from_str(stnode_token(N), &err_msg);
|
||||
if (err_msg != NULL) {
|
||||
FAIL(dfw, N, "%s", err_msg);
|
||||
g_free(err_msg);
|
||||
}
|
||||
stnode_free(N);
|
||||
R = g_slist_append(NULL, range);
|
||||
}
|
||||
|
||||
field(R) ::= FIELD(F).
|
||||
{
|
||||
R = F;
|
||||
}
|
||||
|
||||
field(R) ::= FIELD(F) layer(L).
|
||||
{
|
||||
R = F;
|
||||
sttype_field_set_range(R, L);
|
||||
g_slist_free(L);
|
||||
}
|
||||
|
||||
field(R) ::= UNPARSED(U) layer(L).
|
||||
{
|
||||
header_field_info *hfinfo = dfilter_resolve_unparsed(dfw, stnode_data(U));
|
||||
if (hfinfo == NULL) {
|
||||
FAIL(dfw, U, "%s is not a valid field", stnode_token(U));
|
||||
}
|
||||
R = stnode_new(STTYPE_FIELD, hfinfo, NULL, stnode_location(U));
|
||||
stnode_free(U);
|
||||
sttype_field_set_range(R, L);
|
||||
g_slist_free(L);
|
||||
}
|
||||
|
||||
reference(R) ::= DOLLAR LBRACE field(F) RBRACE.
|
||||
{
|
||||
/* convert field to reference */
|
||||
R = stnode_new(STTYPE_REFERENCE, sttype_field_hfinfo(F), NULL, stnode_location(F));
|
||||
sttype_field_set_drange(R, sttype_field_drange_steal(F));
|
||||
stnode_free(F);
|
||||
}
|
||||
|
||||
reference(R) ::= DOLLAR LBRACE UNPARSED(U) RBRACE.
|
||||
{
|
||||
header_field_info *hfinfo = dfilter_resolve_unparsed(dfw, stnode_data(U));
|
||||
if (hfinfo == NULL) {
|
||||
FAIL(dfw, U, "%s is not a valid field", stnode_token(U));
|
||||
}
|
||||
R = stnode_new(STTYPE_REFERENCE, hfinfo, NULL, stnode_location(U));
|
||||
stnode_free(U);
|
||||
}
|
||||
|
||||
entity(E) ::= atom(A). { E = A; }
|
||||
entity(E) ::= slice(R). { E = R; }
|
||||
entity(E) ::= function(F). { E = F; }
|
||||
entity(E) ::= layer(L). { E = L; }
|
||||
entity(E) ::= field(F). { E = F; }
|
||||
entity(E) ::= reference(R). { E = R; }
|
||||
|
||||
arithmetic_expr(T) ::= entity(N).
|
||||
{
|
||||
|
@ -327,7 +371,7 @@ set_element(N) ::= set_entity(X) DOTDOT set_entity(Y).
|
|||
slice(R) ::= entity(E) LBRACKET range_node_list(L) RBRACKET.
|
||||
{
|
||||
R = stnode_new(STTYPE_SLICE, NULL, NULL, NULL);
|
||||
sttype_range_set(R, E, L);
|
||||
sttype_slice_set(R, E, L);
|
||||
|
||||
/* Delete the list, but not the drange_nodes that
|
||||
* the list contains. */
|
||||
|
|
|
@ -154,6 +154,7 @@ hyphen-bytes {hex2}(-{hex2})+
|
|||
"{" return simple(TOKEN_LBRACE);
|
||||
".." return simple(TOKEN_DOTDOT);
|
||||
"}" return simple(TOKEN_RBRACE);
|
||||
"$" return simple(TOKEN_DOLLAR);
|
||||
"any" return simple(TOKEN_ANY);
|
||||
"all" return simple(TOKEN_ALL);
|
||||
|
||||
|
@ -467,12 +468,6 @@ hyphen-bytes {hex2}(-{hex2})+
|
|||
return set_lval_str(yyextra, TOKEN_UNPARSED, yytext);
|
||||
}
|
||||
|
||||
"${"{Identifier}"}" {
|
||||
char *end = strchr(yytext, '}');
|
||||
*end = '\0';
|
||||
return set_lval_field(yyextra, TOKEN_REFERENCE, yytext + 2);
|
||||
}
|
||||
|
||||
. {
|
||||
/* Default */
|
||||
update_location(yyextra, yytext);
|
||||
|
@ -575,9 +570,6 @@ set_lval_field(df_scanner_state_t *state, int token, const char *token_value)
|
|||
case TOKEN_FIELD:
|
||||
type_id = STTYPE_FIELD;
|
||||
break;
|
||||
case TOKEN_REFERENCE:
|
||||
type_id = STTYPE_REFERENCE;
|
||||
break;
|
||||
default:
|
||||
ws_assert_not_reached();
|
||||
}
|
||||
|
|
|
@ -15,7 +15,8 @@
|
|||
#include "dfilter-int.h"
|
||||
#include "semcheck.h"
|
||||
#include "syntax-tree.h"
|
||||
#include "sttype-range.h"
|
||||
#include "sttype-field.h"
|
||||
#include "sttype-slice.h"
|
||||
#include "sttype-test.h"
|
||||
#include "sttype-set.h"
|
||||
#include "sttype-function.h"
|
||||
|
@ -507,7 +508,6 @@ check_exists(dfwork_t *dfw, stnode_t *st_arg1)
|
|||
switch (stnode_type_id(st_arg1)) {
|
||||
case STTYPE_FIELD:
|
||||
case STTYPE_ARITHMETIC:
|
||||
case STTYPE_LAYER:
|
||||
/* This is OK */
|
||||
break;
|
||||
case STTYPE_REFERENCE:
|
||||
|
@ -546,17 +546,6 @@ check_exists(dfwork_t *dfw, stnode_t *st_arg1)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
check_exists_layer(dfwork_t *dfw, stnode_t *st_arg1)
|
||||
{
|
||||
stnode_t *entity;
|
||||
|
||||
entity = sttype_range_entity(st_arg1);
|
||||
dfw_resolve_unparsed(dfw, entity);
|
||||
check_exists(dfw, entity);
|
||||
/* Nothing to do here? */
|
||||
}
|
||||
|
||||
static void
|
||||
check_slice_sanity(dfwork_t *dfw, stnode_t *st, ftenum_t lhs_ftype)
|
||||
{
|
||||
|
@ -566,12 +555,12 @@ check_slice_sanity(dfwork_t *dfw, stnode_t *st, ftenum_t lhs_ftype)
|
|||
|
||||
LOG_NODE(st);
|
||||
|
||||
entity1 = sttype_range_entity(st);
|
||||
entity1 = sttype_slice_entity(st);
|
||||
ws_assert(entity1);
|
||||
dfw_resolve_unparsed(dfw, entity1);
|
||||
|
||||
if (stnode_type_id(entity1) == STTYPE_FIELD) {
|
||||
hfinfo1 = stnode_data(entity1);
|
||||
hfinfo1 = sttype_field_hfinfo(entity1);
|
||||
ftype1 = hfinfo1->type;
|
||||
|
||||
if (!ftype_can_slice(ftype1)) {
|
||||
|
@ -594,51 +583,9 @@ check_slice_sanity(dfwork_t *dfw, stnode_t *st, ftenum_t lhs_ftype)
|
|||
}
|
||||
}
|
||||
|
||||
static ftenum_t
|
||||
check_layer_sanity(dfwork_t *dfw, stnode_t *st)
|
||||
{
|
||||
stnode_t *entity1;
|
||||
sttype_id_t e_type;
|
||||
|
||||
LOG_NODE(st);
|
||||
|
||||
entity1 = sttype_range_entity(st);
|
||||
ws_assert(entity1);
|
||||
dfw_resolve_unparsed(dfw, entity1);
|
||||
e_type = stnode_type_id(entity1);
|
||||
|
||||
if (e_type == STTYPE_FIELD) {
|
||||
return sttype_pointer_ftenum(entity1);
|
||||
}
|
||||
else if (e_type == STTYPE_REFERENCE) {
|
||||
/* TODO: Implement layers with references. */
|
||||
FAIL(dfw, entity1, "The # operator is not valid with a reference");
|
||||
}
|
||||
else {
|
||||
FAIL(dfw, entity1, "%s is not a valid field value", stnode_todisplay(entity1));
|
||||
}
|
||||
}
|
||||
|
||||
#define IS_FIELD_ENTITY(ft) \
|
||||
((ft) == STTYPE_FIELD || \
|
||||
(ft) == STTYPE_REFERENCE || \
|
||||
(ft) == STTYPE_LAYER)
|
||||
|
||||
static ftenum_t
|
||||
field_ftenum(stnode_t *st)
|
||||
{
|
||||
sttype_id_t e_type;
|
||||
|
||||
e_type = stnode_type_id(st);
|
||||
if (e_type == STTYPE_FIELD || e_type == STTYPE_REFERENCE)
|
||||
return sttype_pointer_ftenum(st);
|
||||
else if (e_type == STTYPE_LAYER) {
|
||||
return sttype_pointer_ftenum(sttype_range_entity(st));
|
||||
}
|
||||
else {
|
||||
ws_assert_not_reached();
|
||||
}
|
||||
}
|
||||
(ft) == STTYPE_REFERENCE)
|
||||
|
||||
static void
|
||||
convert_to_bytes(stnode_t *arg)
|
||||
|
@ -652,7 +599,7 @@ convert_to_bytes(stnode_t *arg)
|
|||
drange_node_set_to_the_end(rn);
|
||||
|
||||
stnode_replace(arg, STTYPE_SLICE, NULL);
|
||||
sttype_range_set1(arg, entity1, rn);
|
||||
sttype_slice_set1(arg, entity1, rn);
|
||||
}
|
||||
|
||||
ftenum_t
|
||||
|
@ -718,7 +665,7 @@ again:
|
|||
|
||||
ws_assert(stnode_type_id(st_arg1) == STTYPE_FIELD ||
|
||||
stnode_type_id(st_arg1) == STTYPE_REFERENCE);
|
||||
hfinfo1 = stnode_data(st_arg1);
|
||||
hfinfo1 = sttype_field_hfinfo(st_arg1);
|
||||
ftype1 = hfinfo1->type;
|
||||
|
||||
if (!can_func(ftype1)) {
|
||||
|
@ -728,7 +675,7 @@ again:
|
|||
}
|
||||
|
||||
if (IS_FIELD_ENTITY(type2)) {
|
||||
ftype2 = field_ftenum(st_arg2);
|
||||
ftype2 = sttype_field_ftenum(st_arg2);
|
||||
|
||||
if (!compatible_ftypes(ftype1, ftype2)) {
|
||||
FAIL(dfw, st_arg2, "%s and %s are not of compatible types.",
|
||||
|
@ -817,21 +764,6 @@ again:
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
check_relation_LHS_LAYER(dfwork_t *dfw, test_op_t st_op,
|
||||
FtypeCanFunc can_func,
|
||||
gboolean allow_partial_value,
|
||||
stnode_t *st_node,
|
||||
stnode_t *st_arg1, stnode_t *st_arg2)
|
||||
{
|
||||
stnode_t *entity;
|
||||
|
||||
check_layer_sanity(dfw, st_arg1);
|
||||
entity = sttype_range_entity(st_arg1);
|
||||
ws_assert(stnode_type_id(entity) == STTYPE_FIELD);
|
||||
check_relation_LHS_FIELD(dfw, st_op, can_func, allow_partial_value, st_node, entity, st_arg2);
|
||||
}
|
||||
|
||||
static void
|
||||
check_relation_LHS_SLICE(dfwork_t *dfw, test_op_t st_op,
|
||||
FtypeCanFunc can_func _U_,
|
||||
|
@ -851,7 +783,7 @@ again:
|
|||
type2 = stnode_type_id(st_arg2);
|
||||
|
||||
if (IS_FIELD_ENTITY(type2)) {
|
||||
ftype2 = field_ftenum(st_arg2);
|
||||
ftype2 = sttype_field_ftenum(st_arg2);
|
||||
|
||||
if (!is_bytes_type(ftype2)) {
|
||||
if (!ftype_can_slice(ftype2)) {
|
||||
|
@ -948,7 +880,7 @@ again:
|
|||
type2 = stnode_type_id(st_arg2);
|
||||
|
||||
if (IS_FIELD_ENTITY(type2)) {
|
||||
ftype2 = field_ftenum(st_arg2);
|
||||
ftype2 = sttype_field_ftenum(st_arg2);
|
||||
|
||||
if (!compatible_ftypes(ftype1, ftype2)) {
|
||||
FAIL(dfw, st_arg2, "Function %s and %s are not of compatible types.",
|
||||
|
@ -1078,10 +1010,6 @@ check_relation(dfwork_t *dfw, test_op_t st_op,
|
|||
check_relation_LHS_FIELD(dfw, st_op, can_func,
|
||||
allow_partial_value, st_node, st_arg1, st_arg2);
|
||||
break;
|
||||
case STTYPE_LAYER:
|
||||
check_relation_LHS_LAYER(dfw, st_op, can_func,
|
||||
allow_partial_value, st_node, st_arg1, st_arg2);
|
||||
break;
|
||||
case STTYPE_SLICE:
|
||||
check_relation_LHS_SLICE(dfw, st_op, can_func,
|
||||
allow_partial_value, st_node, st_arg1, st_arg2);
|
||||
|
@ -1300,7 +1228,7 @@ check_arithmetic_entity(dfwork_t *dfw, stnode_t *st_arg, ftenum_t lhs_ftype)
|
|||
ftype = fvalue_type_ftenum(fvalue);
|
||||
}
|
||||
else if (type == STTYPE_FIELD || type == STTYPE_REFERENCE) {
|
||||
header_field_info *hfinfo = stnode_data(st_arg);
|
||||
header_field_info *hfinfo = sttype_field_hfinfo(st_arg);
|
||||
ftype = hfinfo->type;
|
||||
}
|
||||
else if (type == STTYPE_FUNCTION) {
|
||||
|
@ -1419,9 +1347,6 @@ semcheck(dfwork_t *dfw, stnode_t *st_node)
|
|||
case STTYPE_ARITHMETIC:
|
||||
check_arithmetic_expr(dfw, st_node, FT_NONE);
|
||||
break;
|
||||
case STTYPE_LAYER:
|
||||
check_exists_layer(dfw, st_node);
|
||||
break;
|
||||
default:
|
||||
check_exists(dfw, st_node);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,202 @@
|
|||
/*
|
||||
* Wireshark - Network traffic analyzer
|
||||
* By Gerald Combs <gerald@wireshark.org>
|
||||
* Copyright 2001 Gerald Combs
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
/* The ideas in this code came from Ed Warnicke's original implementation
|
||||
* of dranges for the old display filter code (Ethereal 0.8.15 and before).
|
||||
* The code is different, but definitely inspired by his code.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
#include <epan/proto.h>
|
||||
#include "sttype-field.h"
|
||||
#include <wsutil/ws_assert.h>
|
||||
|
||||
typedef struct {
|
||||
guint32 magic;
|
||||
header_field_info *hfinfo;
|
||||
drange_t *drange;
|
||||
} field_t;
|
||||
|
||||
#define FIELD_MAGIC 0xfc2002cf
|
||||
|
||||
static gpointer
|
||||
field_new(gpointer hfinfo)
|
||||
{
|
||||
field_t *field;
|
||||
|
||||
field = g_new(field_t, 1);
|
||||
field->magic = FIELD_MAGIC;
|
||||
field->hfinfo = hfinfo;
|
||||
field->drange = NULL;
|
||||
|
||||
return field;
|
||||
}
|
||||
|
||||
static gpointer
|
||||
field_dup(gconstpointer data)
|
||||
{
|
||||
const field_t *org = data;
|
||||
field_t *field;
|
||||
|
||||
ws_assert_magic(org, FIELD_MAGIC);
|
||||
field = field_new(NULL);
|
||||
field->hfinfo = org->hfinfo;
|
||||
field->drange = drange_dup(org->drange);
|
||||
|
||||
return field;
|
||||
}
|
||||
|
||||
static void
|
||||
field_free(gpointer data)
|
||||
{
|
||||
field_t *field = data;
|
||||
ws_assert_magic(field, FIELD_MAGIC);
|
||||
|
||||
if (field->drange)
|
||||
drange_free(field->drange);
|
||||
g_free(field);
|
||||
}
|
||||
|
||||
static char *
|
||||
field_tostr(const void *data, gboolean pretty _U_)
|
||||
{
|
||||
const field_t *field = data;
|
||||
ws_assert_magic(field, FIELD_MAGIC);
|
||||
char *repr, *drange_str;
|
||||
|
||||
if (field->drange && (drange_str = drange_tostr(field->drange))) {
|
||||
repr = ws_strdup_printf("%s#[%s] <%s>",
|
||||
field->hfinfo->abbrev,
|
||||
drange_str,
|
||||
ftype_name(field->hfinfo->type));
|
||||
g_free(drange_str);
|
||||
}
|
||||
else {
|
||||
repr = ws_strdup_printf("%s <%s>", field->hfinfo->abbrev,
|
||||
ftype_name(field->hfinfo->type));
|
||||
}
|
||||
|
||||
return repr;
|
||||
}
|
||||
|
||||
header_field_info *
|
||||
sttype_field_hfinfo(stnode_t *node)
|
||||
{
|
||||
field_t *field = node->data;
|
||||
ws_assert_magic(field, FIELD_MAGIC);
|
||||
return field->hfinfo;
|
||||
}
|
||||
|
||||
ftenum_t
|
||||
sttype_field_ftenum(stnode_t *node)
|
||||
{
|
||||
field_t *field = node->data;
|
||||
ws_assert_magic(field, FIELD_MAGIC);
|
||||
return field->hfinfo->type;
|
||||
}
|
||||
|
||||
drange_t *
|
||||
sttype_field_drange(stnode_t *node)
|
||||
{
|
||||
field_t *field = node->data;
|
||||
ws_assert_magic(field, FIELD_MAGIC);
|
||||
return field->drange;
|
||||
}
|
||||
|
||||
drange_t *
|
||||
sttype_field_drange_steal(stnode_t *node)
|
||||
{
|
||||
field_t *field;
|
||||
drange_t *dr;
|
||||
|
||||
field = stnode_data(node);
|
||||
ws_assert_magic(field, FIELD_MAGIC);
|
||||
dr = field->drange;
|
||||
field->drange = NULL;
|
||||
return dr;
|
||||
}
|
||||
|
||||
/* Set a field */
|
||||
void
|
||||
sttype_field_set_range(stnode_t *node, GSList* drange_list)
|
||||
{
|
||||
field_t *field = stnode_data(node);
|
||||
ws_assert_magic(field, FIELD_MAGIC);
|
||||
ws_assert(field->drange == NULL);
|
||||
field->drange = drange_new_from_list(drange_list);
|
||||
}
|
||||
|
||||
void
|
||||
sttype_field_set_range1(stnode_t *node, drange_node *rn)
|
||||
{
|
||||
field_t *field = stnode_data(node);
|
||||
ws_assert_magic(field, FIELD_MAGIC);
|
||||
ws_assert(field->drange == NULL);
|
||||
field->drange = drange_new(rn);
|
||||
}
|
||||
|
||||
void
|
||||
sttype_field_set_drange(stnode_t *node, drange_t *dr)
|
||||
{
|
||||
field_t *field = stnode_data(node);
|
||||
ws_assert_magic(field, FIELD_MAGIC);
|
||||
ws_assert(field->drange == NULL);
|
||||
field->drange = dr;
|
||||
}
|
||||
|
||||
char *
|
||||
sttype_field_set_number(stnode_t *node, const char *number_str)
|
||||
{
|
||||
char *err_msg = NULL;
|
||||
drange_node *rn = drange_node_from_str(number_str, &err_msg);
|
||||
if (err_msg != NULL)
|
||||
return err_msg;
|
||||
|
||||
sttype_field_set_range1(node, rn);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
sttype_register_field(void)
|
||||
{
|
||||
static sttype_t field_type = {
|
||||
STTYPE_FIELD,
|
||||
"FIELD",
|
||||
field_new,
|
||||
field_free,
|
||||
field_dup,
|
||||
field_tostr
|
||||
};
|
||||
static sttype_t reference_type = {
|
||||
STTYPE_REFERENCE,
|
||||
"REFERENCE",
|
||||
field_new,
|
||||
field_free,
|
||||
field_dup,
|
||||
field_tostr
|
||||
};
|
||||
|
||||
sttype_register(&field_type);
|
||||
sttype_register(&reference_type);
|
||||
}
|
||||
|
||||
/*
|
||||
* Editor modelines - https://www.wireshark.org/tools/modelines.html
|
||||
*
|
||||
* Local variables:
|
||||
* c-basic-offset: 8
|
||||
* tab-width: 8
|
||||
* indent-tabs-mode: t
|
||||
* End:
|
||||
*
|
||||
* vi: set shiftwidth=8 tabstop=8 noexpandtab:
|
||||
* :indentSize=8:tabSize=8:noTabs=false:
|
||||
*/
|
|
@ -0,0 +1,48 @@
|
|||
/** @file
|
||||
*
|
||||
* Wireshark - Network traffic analyzer
|
||||
* By Gerald Combs <gerald@wireshark.org>
|
||||
* Copyright 2001 Gerald Combs
|
||||
*
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef STTYPE_FIELD_H
|
||||
#define STTYPE_FIELD_H
|
||||
|
||||
#include "syntax-tree.h"
|
||||
#include "drange.h"
|
||||
|
||||
|
||||
header_field_info *
|
||||
sttype_field_hfinfo(stnode_t *node);
|
||||
|
||||
ftenum_t
|
||||
sttype_field_ftenum(stnode_t *node);
|
||||
|
||||
drange_t *
|
||||
sttype_field_drange(stnode_t *node);
|
||||
|
||||
drange_t *
|
||||
sttype_field_drange_steal(stnode_t *node);
|
||||
|
||||
/* Set a range */
|
||||
void
|
||||
sttype_field_set_range(stnode_t *node, GSList* drange_list);
|
||||
|
||||
void
|
||||
sttype_field_set_range1(stnode_t *node, drange_node *rn);
|
||||
|
||||
void
|
||||
sttype_field_set_drange(stnode_t *node, drange_t *dr);
|
||||
|
||||
char *
|
||||
sttype_field_set_number(stnode_t *node, const char *number_str);
|
||||
|
||||
/* Clear the 'drange' variable to remove responsibility for
|
||||
* freeing it. */
|
||||
void
|
||||
sttype_field_remove_drange(stnode_t *node);
|
||||
|
||||
#endif
|
|
@ -52,14 +52,6 @@ sttype_fvalue_tostr(const void *data, gboolean pretty)
|
|||
return repr;
|
||||
}
|
||||
|
||||
static char *
|
||||
field_tostr(const void *data, gboolean pretty _U_)
|
||||
{
|
||||
const header_field_info *hfinfo = data;
|
||||
|
||||
return ws_strdup_printf("%s <%s>", hfinfo->abbrev, ftype_name(hfinfo->type));
|
||||
}
|
||||
|
||||
static char *
|
||||
pcre_tostr(const void *data, gboolean pretty _U_)
|
||||
{
|
||||
|
@ -128,25 +120,6 @@ sttype_pointer_ftenum(stnode_t *node)
|
|||
void
|
||||
sttype_register_pointer(void)
|
||||
{
|
||||
static sttype_t field_type = {
|
||||
STTYPE_FIELD,
|
||||
"FIELD",
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
field_tostr
|
||||
};
|
||||
/* A field reference is a *constant* prototocol field value read directly
|
||||
* from the currently selected frame in the protocol tree when a filter is
|
||||
* applied to it. */
|
||||
static sttype_t reference_type = {
|
||||
STTYPE_REFERENCE,
|
||||
"REFERENCE",
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
field_tostr
|
||||
};
|
||||
static sttype_t fvalue_type = {
|
||||
STTYPE_FVALUE,
|
||||
"FVALUE",
|
||||
|
@ -180,8 +153,6 @@ sttype_register_pointer(void)
|
|||
range_node_tostr
|
||||
};
|
||||
|
||||
sttype_register(&field_type);
|
||||
sttype_register(&reference_type);
|
||||
sttype_register(&fvalue_type);
|
||||
sttype_register(&pcre_type);
|
||||
sttype_register(&charconst_type);
|
||||
|
|
|
@ -1,215 +0,0 @@
|
|||
/*
|
||||
* Wireshark - Network traffic analyzer
|
||||
* By Gerald Combs <gerald@wireshark.org>
|
||||
* Copyright 2001 Gerald Combs
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
/* The ideas in this code came from Ed Warnicke's original implementation
|
||||
* of dranges for the old display filter code (Ethereal 0.8.15 and before).
|
||||
* The code is different, but definitely inspired by his code.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
#include <epan/proto.h>
|
||||
#include "drange.h"
|
||||
#include "sttype-range.h"
|
||||
#include <wsutil/ws_assert.h>
|
||||
|
||||
typedef struct {
|
||||
guint32 magic;
|
||||
stnode_t *entity;
|
||||
drange_t *drange;
|
||||
} range_t;
|
||||
|
||||
#define RANGE_MAGIC 0xec0990ce
|
||||
|
||||
static gpointer
|
||||
range_new(gpointer junk _U_)
|
||||
{
|
||||
range_t *range;
|
||||
|
||||
ws_assert(junk == NULL);
|
||||
|
||||
range = g_new(range_t, 1);
|
||||
|
||||
range->magic = RANGE_MAGIC;
|
||||
range->entity = NULL;
|
||||
range->drange = NULL;
|
||||
|
||||
return range;
|
||||
}
|
||||
|
||||
static gpointer
|
||||
range_dup(gconstpointer data)
|
||||
{
|
||||
const range_t *org = data;
|
||||
range_t *range;
|
||||
|
||||
range = range_new(NULL);
|
||||
range->entity = stnode_dup(org->entity);
|
||||
range->drange = drange_dup(org->drange);
|
||||
|
||||
return range;
|
||||
}
|
||||
|
||||
static void
|
||||
range_free(gpointer value)
|
||||
{
|
||||
range_t *range = value;
|
||||
ws_assert_magic(range, RANGE_MAGIC);
|
||||
|
||||
if (range->drange)
|
||||
drange_free(range->drange);
|
||||
|
||||
if (range->entity)
|
||||
stnode_free(range->entity);
|
||||
|
||||
g_free(range);
|
||||
}
|
||||
|
||||
static char *
|
||||
slice_tostr(const void *data, gboolean pretty)
|
||||
{
|
||||
const range_t *range = data;
|
||||
ws_assert_magic(range, RANGE_MAGIC);
|
||||
|
||||
char *repr, *drange_str;
|
||||
|
||||
drange_str = drange_tostr(range->drange);
|
||||
repr = ws_strdup_printf("%s[%s]",
|
||||
stnode_tostr(range->entity, pretty),
|
||||
drange_str);
|
||||
g_free(drange_str);
|
||||
|
||||
return repr;
|
||||
}
|
||||
|
||||
static char *
|
||||
layer_tostr(const void *data, gboolean pretty)
|
||||
{
|
||||
const range_t *range = data;
|
||||
ws_assert_magic(range, RANGE_MAGIC);
|
||||
|
||||
char *repr, *drange_str;
|
||||
|
||||
drange_str = drange_tostr(range->drange);
|
||||
repr = ws_strdup_printf("%s#[%s]",
|
||||
stnode_tostr(range->entity, pretty),
|
||||
drange_str);
|
||||
g_free(drange_str);
|
||||
|
||||
return repr;
|
||||
}
|
||||
|
||||
void
|
||||
sttype_range_remove_drange(stnode_t *node)
|
||||
{
|
||||
range_t *range;
|
||||
|
||||
range = stnode_data(node);
|
||||
ws_assert_magic(range, RANGE_MAGIC);
|
||||
|
||||
range->drange = NULL;
|
||||
}
|
||||
|
||||
drange_t *
|
||||
sttype_range_drange_steal(stnode_t *node)
|
||||
{
|
||||
range_t *range;
|
||||
drange_t *dr;
|
||||
|
||||
range = stnode_data(node);
|
||||
ws_assert_magic(range, RANGE_MAGIC);
|
||||
dr = range->drange;
|
||||
range->drange = NULL;
|
||||
return dr;
|
||||
}
|
||||
|
||||
/* Set a range */
|
||||
void
|
||||
sttype_range_set(stnode_t *node, stnode_t *entity, GSList* drange_list)
|
||||
{
|
||||
range_t *range;
|
||||
|
||||
range = stnode_data(node);
|
||||
ws_assert_magic(range, RANGE_MAGIC);
|
||||
|
||||
range->entity = entity;
|
||||
|
||||
range->drange = drange_new_from_list(drange_list);
|
||||
}
|
||||
|
||||
void
|
||||
sttype_range_set1(stnode_t *node, stnode_t *entity, drange_node *rn)
|
||||
{
|
||||
sttype_range_set(node, entity, g_slist_append(NULL, rn));
|
||||
}
|
||||
|
||||
char *
|
||||
sttype_range_set_number(stnode_t *node, stnode_t *entity, const char *number_str)
|
||||
{
|
||||
char *err_msg = NULL;
|
||||
drange_node *rn = drange_node_from_str(number_str, &err_msg);
|
||||
if (err_msg != NULL)
|
||||
return err_msg;
|
||||
sttype_range_set1(node, entity, rn);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
stnode_t *
|
||||
sttype_range_entity(stnode_t *node)
|
||||
{
|
||||
range_t *range = node->data;
|
||||
ws_assert_magic(range, RANGE_MAGIC);
|
||||
return range->entity;
|
||||
}
|
||||
|
||||
drange_t *
|
||||
sttype_range_drange(stnode_t *node)
|
||||
{
|
||||
range_t *range = node->data;
|
||||
ws_assert_magic(range, RANGE_MAGIC);
|
||||
return range->drange;
|
||||
}
|
||||
|
||||
void
|
||||
sttype_register_range(void)
|
||||
{
|
||||
static sttype_t slice_type = {
|
||||
STTYPE_SLICE,
|
||||
"SLICE",
|
||||
range_new,
|
||||
range_free,
|
||||
range_dup,
|
||||
slice_tostr
|
||||
};
|
||||
static sttype_t layer_type = {
|
||||
STTYPE_LAYER,
|
||||
"LAYER",
|
||||
range_new,
|
||||
range_free,
|
||||
range_dup,
|
||||
layer_tostr
|
||||
};
|
||||
|
||||
sttype_register(&slice_type);
|
||||
sttype_register(&layer_type);
|
||||
}
|
||||
|
||||
/*
|
||||
* Editor modelines - https://www.wireshark.org/tools/modelines.html
|
||||
*
|
||||
* Local variables:
|
||||
* c-basic-offset: 8
|
||||
* tab-width: 8
|
||||
* indent-tabs-mode: t
|
||||
* End:
|
||||
*
|
||||
* vi: set shiftwidth=8 tabstop=8 noexpandtab:
|
||||
* :indentSize=8:tabSize=8:noTabs=false:
|
||||
*/
|
|
@ -1,42 +0,0 @@
|
|||
/** @file
|
||||
*
|
||||
* Wireshark - Network traffic analyzer
|
||||
* By Gerald Combs <gerald@wireshark.org>
|
||||
* Copyright 2001 Gerald Combs
|
||||
*
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef STTYPE_RANGE_H
|
||||
#define STTYPE_RANGE_H
|
||||
|
||||
#include "syntax-tree.h"
|
||||
#include "drange.h"
|
||||
|
||||
|
||||
stnode_t *
|
||||
sttype_range_entity(stnode_t *node);
|
||||
|
||||
drange_t *
|
||||
sttype_range_drange(stnode_t *node);
|
||||
|
||||
drange_t *
|
||||
sttype_range_drange_steal(stnode_t *node);
|
||||
|
||||
/* Set a range */
|
||||
void
|
||||
sttype_range_set(stnode_t *node, stnode_t *field, GSList* drange_list);
|
||||
|
||||
void
|
||||
sttype_range_set1(stnode_t *node, stnode_t *field, drange_node *rn);
|
||||
|
||||
char *
|
||||
sttype_range_set_number(stnode_t *node, stnode_t *entity, const char *number_str);
|
||||
|
||||
/* Clear the 'drange' variable to remove responsibility for
|
||||
* freeing it. */
|
||||
void
|
||||
sttype_range_remove_drange(stnode_t *node);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,191 @@
|
|||
/*
|
||||
* Wireshark - Network traffic analyzer
|
||||
* By Gerald Combs <gerald@wireshark.org>
|
||||
* Copyright 2001 Gerald Combs
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
/* The ideas in this code came from Ed Warnicke's original implementation
|
||||
* of dranges for the old display filter code (Ethereal 0.8.15 and before).
|
||||
* The code is different, but definitely inspired by his code.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
#include <epan/proto.h>
|
||||
#include "drange.h"
|
||||
#include "sttype-slice.h"
|
||||
#include <wsutil/ws_assert.h>
|
||||
|
||||
typedef struct {
|
||||
guint32 magic;
|
||||
stnode_t *entity;
|
||||
drange_t *drange;
|
||||
} slice_t;
|
||||
|
||||
#define SLICE_MAGIC 0xec0990ce
|
||||
|
||||
static gpointer
|
||||
slice_new(gpointer junk _U_)
|
||||
{
|
||||
slice_t *slice;
|
||||
|
||||
ws_assert(junk == NULL);
|
||||
|
||||
slice = g_new(slice_t, 1);
|
||||
|
||||
slice->magic = SLICE_MAGIC;
|
||||
slice->entity = NULL;
|
||||
slice->drange = NULL;
|
||||
|
||||
return slice;
|
||||
}
|
||||
|
||||
static gpointer
|
||||
slice_dup(gconstpointer data)
|
||||
{
|
||||
const slice_t *org = data;
|
||||
slice_t *slice;
|
||||
|
||||
slice = slice_new(NULL);
|
||||
slice->entity = stnode_dup(org->entity);
|
||||
slice->drange = drange_dup(org->drange);
|
||||
|
||||
return slice;
|
||||
}
|
||||
|
||||
static void
|
||||
slice_free(gpointer value)
|
||||
{
|
||||
slice_t *slice = value;
|
||||
ws_assert_magic(slice, SLICE_MAGIC);
|
||||
|
||||
if (slice->drange)
|
||||
drange_free(slice->drange);
|
||||
|
||||
if (slice->entity)
|
||||
stnode_free(slice->entity);
|
||||
|
||||
g_free(slice);
|
||||
}
|
||||
|
||||
static char *
|
||||
slice_tostr(const void *data, gboolean pretty)
|
||||
{
|
||||
const slice_t *slice = data;
|
||||
ws_assert_magic(slice, SLICE_MAGIC);
|
||||
|
||||
char *repr, *drange_str;
|
||||
|
||||
drange_str = drange_tostr(slice->drange);
|
||||
repr = ws_strdup_printf("%s[%s]",
|
||||
stnode_tostr(slice->entity, pretty),
|
||||
drange_str);
|
||||
g_free(drange_str);
|
||||
|
||||
return repr;
|
||||
}
|
||||
|
||||
void
|
||||
sttype_slice_remove_drange(stnode_t *node)
|
||||
{
|
||||
slice_t *slice;
|
||||
|
||||
slice = stnode_data(node);
|
||||
ws_assert_magic(slice, SLICE_MAGIC);
|
||||
|
||||
slice->drange = NULL;
|
||||
}
|
||||
|
||||
drange_t *
|
||||
sttype_slice_drange_steal(stnode_t *node)
|
||||
{
|
||||
slice_t *slice;
|
||||
drange_t *dr;
|
||||
|
||||
slice = stnode_data(node);
|
||||
ws_assert_magic(slice, SLICE_MAGIC);
|
||||
dr = slice->drange;
|
||||
slice->drange = NULL;
|
||||
return dr;
|
||||
}
|
||||
|
||||
/* Set a slice */
|
||||
void
|
||||
sttype_slice_set(stnode_t *node, stnode_t *entity, GSList* drange_list)
|
||||
{
|
||||
slice_t *slice;
|
||||
|
||||
slice = stnode_data(node);
|
||||
ws_assert_magic(slice, SLICE_MAGIC);
|
||||
|
||||
slice->entity = entity;
|
||||
|
||||
slice->drange = drange_new_from_list(drange_list);
|
||||
}
|
||||
|
||||
void
|
||||
sttype_slice_set1(stnode_t *node, stnode_t *entity, drange_node *rn)
|
||||
{
|
||||
sttype_slice_set(node, entity, g_slist_append(NULL, rn));
|
||||
}
|
||||
|
||||
void
|
||||
sttype_slice_set_drange(stnode_t *node, stnode_t *field, drange_t *dr)
|
||||
{
|
||||
slice_t *slice;
|
||||
|
||||
slice = stnode_data(node);
|
||||
ws_assert_magic(slice, SLICE_MAGIC);
|
||||
|
||||
slice->entity = field;
|
||||
|
||||
slice->drange = dr;
|
||||
}
|
||||
|
||||
stnode_t *
|
||||
sttype_slice_entity(stnode_t *node)
|
||||
{
|
||||
slice_t *slice = node->data;
|
||||
ws_assert_magic(slice, SLICE_MAGIC);
|
||||
return slice->entity;
|
||||
}
|
||||
|
||||
drange_t *
|
||||
sttype_slice_drange(stnode_t *node)
|
||||
{
|
||||
slice_t *slice = node->data;
|
||||
ws_assert_magic(slice, SLICE_MAGIC);
|
||||
return slice->drange;
|
||||
}
|
||||
|
||||
void
|
||||
sttype_register_slice(void)
|
||||
{
|
||||
static sttype_t slice_type = {
|
||||
STTYPE_SLICE,
|
||||
"SLICE",
|
||||
slice_new,
|
||||
slice_free,
|
||||
slice_dup,
|
||||
slice_tostr
|
||||
};
|
||||
|
||||
sttype_register(&slice_type);
|
||||
}
|
||||
|
||||
/*
|
||||
* Editor modelines - https://www.wireshark.org/tools/modelines.html
|
||||
*
|
||||
* Local variables:
|
||||
* c-basic-offset: 8
|
||||
* tab-width: 8
|
||||
* indent-tabs-mode: t
|
||||
* End:
|
||||
*
|
||||
* vi: set shiftwidth=8 tabstop=8 noexpandtab:
|
||||
* :indentSize=8:tabSize=8:noTabs=false:
|
||||
*/
|
|
@ -0,0 +1,42 @@
|
|||
/** @file
|
||||
*
|
||||
* Wireshark - Network traffic analyzer
|
||||
* By Gerald Combs <gerald@wireshark.org>
|
||||
* Copyright 2001 Gerald Combs
|
||||
*
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef STTYPE_SLICE_H
|
||||
#define STTYPE_SLICE_H
|
||||
|
||||
#include "syntax-tree.h"
|
||||
#include "drange.h"
|
||||
|
||||
|
||||
stnode_t *
|
||||
sttype_slice_entity(stnode_t *node);
|
||||
|
||||
drange_t *
|
||||
sttype_slice_drange(stnode_t *node);
|
||||
|
||||
drange_t *
|
||||
sttype_slice_drange_steal(stnode_t *node);
|
||||
|
||||
/* Set a range */
|
||||
void
|
||||
sttype_slice_set(stnode_t *node, stnode_t *field, GSList* drange_list);
|
||||
|
||||
void
|
||||
sttype_slice_set1(stnode_t *node, stnode_t *field, drange_node *rn);
|
||||
|
||||
void
|
||||
sttype_slice_set_drange(stnode_t *node, stnode_t *field, drange_t *dr);
|
||||
|
||||
/* Clear the 'drange' variable to remove responsibility for
|
||||
* freeing it. */
|
||||
void
|
||||
sttype_slice_remove_drange(stnode_t *node);
|
||||
|
||||
#endif
|
|
@ -28,10 +28,11 @@ static sttype_t* type_list[STTYPE_NUM_TYPES];
|
|||
void
|
||||
sttype_init(void)
|
||||
{
|
||||
sttype_register_field();
|
||||
sttype_register_function();
|
||||
sttype_register_pointer();
|
||||
sttype_register_range();
|
||||
sttype_register_set();
|
||||
sttype_register_slice();
|
||||
sttype_register_string();
|
||||
sttype_register_test();
|
||||
}
|
||||
|
|
|
@ -31,7 +31,6 @@ typedef enum {
|
|||
STTYPE_FIELD,
|
||||
STTYPE_FVALUE,
|
||||
STTYPE_SLICE,
|
||||
STTYPE_LAYER,
|
||||
STTYPE_RANGE_NODE,
|
||||
STTYPE_FUNCTION,
|
||||
STTYPE_SET,
|
||||
|
@ -104,11 +103,11 @@ typedef struct {
|
|||
} stnode_t;
|
||||
|
||||
/* These are the sttype_t registration function prototypes. */
|
||||
void sttype_register_field(void);
|
||||
void sttype_register_function(void);
|
||||
void sttype_register_integer(void);
|
||||
void sttype_register_pointer(void);
|
||||
void sttype_register_range(void);
|
||||
void sttype_register_set(void);
|
||||
void sttype_register_slice(void);
|
||||
void sttype_register_string(void);
|
||||
void sttype_register_test(void);
|
||||
|
||||
|
|
|
@ -282,12 +282,17 @@ class case_arithmetic(unittest.TestCase):
|
|||
|
||||
@fixtures.uses_fixtures
|
||||
class case_field_reference(unittest.TestCase):
|
||||
trace_file = "dhcp.pcap"
|
||||
trace_file = "ipoipoip.pcap"
|
||||
|
||||
def test_ref_1(self, checkDFilterCountWithSelectedFrame):
|
||||
dfilter = 'frame.number < ${frame.number}'
|
||||
# select frame 3, expect 2 frames out of 4.
|
||||
checkDFilterCountWithSelectedFrame(dfilter, 2, 3)
|
||||
# select frame 2, expect 1 frames out of 2.
|
||||
checkDFilterCountWithSelectedFrame(dfilter, 1, 2)
|
||||
|
||||
def test_ref_2(self, checkDFilterCountWithSelectedFrame):
|
||||
dfilter = 'ip.src#3 == ${ip.src#4}'
|
||||
# select frame 1, expect 1 frames out of 2.
|
||||
checkDFilterCountWithSelectedFrame(dfilter, 1, 1)
|
||||
|
||||
@fixtures.uses_fixtures
|
||||
class case_field_reference(unittest.TestCase):
|
||||
|
|
Loading…
Reference in New Issue