mirror of
https://github.com/zeek/zeek.git
synced 2025-10-03 15:18:20 +00:00
New BiF record_field_vals() that returns the fields of a record in a
table with meta-information. Example: type r: record { a: count; b: string &default="Foo"; c: double &optional; d: string &log; }; event bro_init() { local x: r = [$a=42, $d="Bar"]; print record_fields(x); } This prints: { [a] = [type_name=record, log=F, value=42, default_val=<uninitialized>] [b] = [type_name=record, log=F, value=<uninitialized>, default_val=Foo], [c] = [type_name=record, log=F, value=<uninitialized>, default_val=<uninitialized>], [d] = [type_name=record, log=T, value=Bar, default_val=<uninitialized>], } This is one more step in Seth's quest for full inspection support. :-)
This commit is contained in:
parent
cdd8827cc4
commit
8bacb6eb3d
9 changed files with 99 additions and 9 deletions
|
@ -183,6 +183,17 @@ type script_id: record {
|
||||||
value: any &optional;
|
value: any &optional;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
type id_table: table[string] of script_id;
|
||||||
|
|
||||||
|
type record_field: record {
|
||||||
|
type_name: string;
|
||||||
|
log: bool;
|
||||||
|
value: any &optional;
|
||||||
|
default_val: any &optional;
|
||||||
|
};
|
||||||
|
|
||||||
|
type record_field_table: table[string] of record_field;
|
||||||
|
|
||||||
# The following two variables are defined here until the core is not
|
# The following two variables are defined here until the core is not
|
||||||
# dependent on the names remaining as they are now.
|
# dependent on the names remaining as they are now.
|
||||||
## This is the list of capture filters indexed by some user-definable ID.
|
## This is the list of capture filters indexed by some user-definable ID.
|
||||||
|
@ -190,8 +201,6 @@ global capture_filters: table[string] of string &redef;
|
||||||
## This is the list of restriction filters indexed by some user-definable ID.
|
## This is the list of restriction filters indexed by some user-definable ID.
|
||||||
global restrict_filters: table[string] of string &redef;
|
global restrict_filters: table[string] of string &redef;
|
||||||
|
|
||||||
type id_table: table[string] of script_id;
|
|
||||||
|
|
||||||
# {precompile,install}_pcap_filter identify the filter by IDs
|
# {precompile,install}_pcap_filter identify the filter by IDs
|
||||||
type PcapFilterID: enum { None };
|
type PcapFilterID: enum { None };
|
||||||
|
|
||||||
|
|
|
@ -248,6 +248,8 @@ int record_all_packets;
|
||||||
|
|
||||||
RecordType* script_id;
|
RecordType* script_id;
|
||||||
TableType* id_table;
|
TableType* id_table;
|
||||||
|
RecordType* record_field;
|
||||||
|
TableType* record_field_table;
|
||||||
|
|
||||||
StringVal* cmd_line_bpf_filter;
|
StringVal* cmd_line_bpf_filter;
|
||||||
|
|
||||||
|
@ -550,4 +552,6 @@ void init_net_var()
|
||||||
|
|
||||||
script_id = internal_type("script_id")->AsRecordType();
|
script_id = internal_type("script_id")->AsRecordType();
|
||||||
id_table = internal_type("id_table")->AsTableType();
|
id_table = internal_type("id_table")->AsTableType();
|
||||||
|
record_field = internal_type("record_field")->AsRecordType();
|
||||||
|
record_field_table = internal_type("record_field_table")->AsTableType();
|
||||||
}
|
}
|
||||||
|
|
|
@ -251,6 +251,8 @@ extern int record_all_packets;
|
||||||
|
|
||||||
extern RecordType* script_id;
|
extern RecordType* script_id;
|
||||||
extern TableType* id_table;
|
extern TableType* id_table;
|
||||||
|
extern RecordType* record_field;
|
||||||
|
extern TableType* record_field_table;
|
||||||
|
|
||||||
extern StringVal* cmd_line_bpf_filter;
|
extern StringVal* cmd_line_bpf_filter;
|
||||||
|
|
||||||
|
|
12
src/Type.cc
12
src/Type.cc
|
@ -987,6 +987,18 @@ BroType* RecordType::FieldType(int field) const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Val* RecordType::FieldDefault(int field) const
|
||||||
|
{
|
||||||
|
const TypeDecl* td = FieldDecl(field);
|
||||||
|
|
||||||
|
if ( ! td->attrs )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const Attr* def_attr = td->attrs->FindAttr(ATTR_DEFAULT);
|
||||||
|
|
||||||
|
return def_attr ? def_attr->AttrExpr()->Eval(0) : 0;
|
||||||
|
}
|
||||||
|
|
||||||
int RecordType::FieldOffset(const char* field) const
|
int RecordType::FieldOffset(const char* field) const
|
||||||
{
|
{
|
||||||
if ( types )
|
if ( types )
|
||||||
|
|
|
@ -448,6 +448,7 @@ public:
|
||||||
int HasField(const char* field) const;
|
int HasField(const char* field) const;
|
||||||
BroType* FieldType(const char* field) const;
|
BroType* FieldType(const char* field) const;
|
||||||
BroType* FieldType(int field) const;
|
BroType* FieldType(int field) const;
|
||||||
|
Val* FieldDefault(int field) const; // Ref's the returned value; 0 if none.
|
||||||
|
|
||||||
// A field's offset is its position in the type_decl_list,
|
// A field's offset is its position in the type_decl_list,
|
||||||
// starting at 0. Returns negative if the field doesn't exist.
|
// starting at 0. Returns negative if the field doesn't exist.
|
||||||
|
|
|
@ -2935,11 +2935,7 @@ Val* RecordVal::LookupWithDefault(int field) const
|
||||||
if ( val )
|
if ( val )
|
||||||
return val->Ref();
|
return val->Ref();
|
||||||
|
|
||||||
// Check for &default.
|
return record_type->FieldDefault(field);
|
||||||
const Attr* def_attr =
|
|
||||||
record_type->FieldDecl(field)->attrs->FindAttr(ATTR_DEFAULT);
|
|
||||||
|
|
||||||
return def_attr ? def_attr->AttrExpr()->Eval(0) : 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RecordVal* RecordVal::CoerceTo(const RecordType* t, Val* aggr) const
|
RecordVal* RecordVal::CoerceTo(const RecordType* t, Val* aggr) const
|
||||||
|
|
38
src/bro.bif
38
src/bro.bif
|
@ -1657,6 +1657,44 @@ function global_ids%(%): id_table
|
||||||
return ids;
|
return ids;
|
||||||
%}
|
%}
|
||||||
|
|
||||||
|
function record_fields%(rec: any%): record_field_table
|
||||||
|
%{
|
||||||
|
TableVal* fields = new TableVal(record_field_table);
|
||||||
|
|
||||||
|
RecordVal* rv = rec->AsRecordVal();
|
||||||
|
RecordType* rt = rv->Type()->AsRecordType();
|
||||||
|
|
||||||
|
if ( rt->Tag() != TYPE_RECORD )
|
||||||
|
{
|
||||||
|
reporter->Error("non-record passed to record_fields");
|
||||||
|
return fields;
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( int i = 0; i < rt->NumFields(); ++i )
|
||||||
|
{
|
||||||
|
BroType* ft = rt->FieldType(i);
|
||||||
|
TypeDecl* fd = rt->FieldDecl(i);
|
||||||
|
Val* fv = rv->Lookup(i);
|
||||||
|
|
||||||
|
if ( fv )
|
||||||
|
Ref(fv);
|
||||||
|
|
||||||
|
bool logged = (fd->attrs && fd->FindAttr(ATTR_LOG) != 0);
|
||||||
|
|
||||||
|
RecordVal* nr = new RecordVal(record_field);
|
||||||
|
nr->Assign(0, new StringVal(type_name(rt->Tag())));
|
||||||
|
nr->Assign(1, new Val(logged, TYPE_BOOL));
|
||||||
|
nr->Assign(2, fv);
|
||||||
|
nr->Assign(3, rt->FieldDefault(i));
|
||||||
|
|
||||||
|
Val* field_name = new StringVal(rt->FieldName(i));
|
||||||
|
fields->Assign(field_name, nr);
|
||||||
|
Unref(field_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
return fields;
|
||||||
|
%}
|
||||||
|
|
||||||
%%{
|
%%{
|
||||||
#include "Anon.h"
|
#include "Anon.h"
|
||||||
%%}
|
%%}
|
||||||
|
|
8
testing/btest/Baseline/bifs.records_fields/out
Normal file
8
testing/btest/Baseline/bifs.records_fields/out
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
[a=42, b=<uninitialized>, c=<uninitialized>, d=Bar]
|
||||||
|
{
|
||||||
|
[b] = [type_name=record, log=F, value=<uninitialized>, default_val=Foo],
|
||||||
|
[d] = [type_name=record, log=T, value=Bar, default_val=<uninitialized>],
|
||||||
|
[c] = [type_name=record, log=F, value=<uninitialized>, default_val=<uninitialized>],
|
||||||
|
[a] = [type_name=record, log=F, value=42, default_val=<uninitialized>]
|
||||||
|
}
|
||||||
|
F
|
20
testing/btest/bifs/records_fields.bro
Normal file
20
testing/btest/bifs/records_fields.bro
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
#
|
||||||
|
# @TEST-EXEC: bro %INPUT >out
|
||||||
|
# @TEST-EXEC: btest-diff out
|
||||||
|
|
||||||
|
type r: record {
|
||||||
|
a: count;
|
||||||
|
b: string &default="Foo";
|
||||||
|
c: double &optional;
|
||||||
|
d: string &log;
|
||||||
|
};
|
||||||
|
|
||||||
|
event bro_init()
|
||||||
|
{
|
||||||
|
local x: r = [$a=42, $d="Bar"];
|
||||||
|
print x;
|
||||||
|
local t: record_field_table;
|
||||||
|
t = record_fields(x);
|
||||||
|
print t;
|
||||||
|
print t["c"]?$value;
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue