mirror of
https://gitlab.nic.cz/labs/bird.git
synced 2024-12-22 09:41:54 +00:00
Filters: Also sender protocol and channel name available
Introducing the object member dereference framework.
This commit is contained in:
parent
064b59d1c7
commit
598cebd19f
@ -1,4 +1,4 @@
|
|||||||
src := filter.c data.c f-util.c tree.c trie.c inst-gen.c
|
src := filter.c data.c deref.c f-util.c tree.c trie.c inst-gen.c
|
||||||
obj := $(src-o-files)
|
obj := $(src-o-files)
|
||||||
$(all-daemon)
|
$(all-daemon)
|
||||||
$(cf-local)
|
$(cf-local)
|
||||||
|
@ -431,7 +431,7 @@ CF_KEYWORDS(FUNCTION, PRINT, PRINTN, UNSET, RETURN,
|
|||||||
SET, STRING, BGPMASK, BGPPATH, CLIST, ECLIST, LCLIST,
|
SET, STRING, BGPMASK, BGPPATH, CLIST, ECLIST, LCLIST,
|
||||||
IF, THEN, ELSE, CASE,
|
IF, THEN, ELSE, CASE,
|
||||||
TRUE, FALSE, RT, RO, UNKNOWN, GENERIC,
|
TRUE, FALSE, RT, RO, UNKNOWN, GENERIC,
|
||||||
FROM, GW, NET, MASK, PROTO, SOURCE, SCOPE, DEST, IFNAME, IFINDEX,
|
FROM, GW, NET, MASK, PROTO, AUTHOR, SENDER, SOURCE, SCOPE, DEST, IFNAME, IFINDEX,
|
||||||
PREFERENCE,
|
PREFERENCE,
|
||||||
ROA_CHECK, ASN, SRC, DST,
|
ROA_CHECK, ASN, SRC, DST,
|
||||||
IS_V4, IS_V6,
|
IS_V4, IS_V6,
|
||||||
@ -902,6 +902,8 @@ static_attr:
|
|||||||
| GW { $$ = f_new_static_attr(T_IP, SA_GW, 0); }
|
| GW { $$ = f_new_static_attr(T_IP, SA_GW, 0); }
|
||||||
| NET { $$ = f_new_static_attr(T_NET, SA_NET, 1); }
|
| NET { $$ = f_new_static_attr(T_NET, SA_NET, 1); }
|
||||||
| PROTO { $$ = f_new_static_attr(T_STRING, SA_PROTO, 1); }
|
| PROTO { $$ = f_new_static_attr(T_STRING, SA_PROTO, 1); }
|
||||||
|
| SENDER { $$ = f_new_static_attr(T_CHANNEL, SA_SENDER, 1); }
|
||||||
|
| AUTHOR { $$ = f_new_static_attr(T_PROTO, SA_AUTHOR, 1); }
|
||||||
| SOURCE { $$ = f_new_static_attr(T_ENUM_RTS, SA_SOURCE, 1); }
|
| SOURCE { $$ = f_new_static_attr(T_ENUM_RTS, SA_SOURCE, 1); }
|
||||||
| SCOPE { $$ = f_new_static_attr(T_ENUM_SCOPE, SA_SCOPE, 0); }
|
| SCOPE { $$ = f_new_static_attr(T_ENUM_SCOPE, SA_SCOPE, 0); }
|
||||||
| DEST { $$ = f_new_static_attr(T_ENUM_RTD, SA_DEST, 0); }
|
| DEST { $$ = f_new_static_attr(T_ENUM_RTD, SA_DEST, 0); }
|
||||||
@ -938,19 +940,24 @@ term:
|
|||||||
|
|
||||||
| dynamic_attr { $$ = f_new_inst(FI_EA_GET, $1); }
|
| dynamic_attr { $$ = f_new_inst(FI_EA_GET, $1); }
|
||||||
|
|
||||||
| term '.' IS_V4 { $$ = f_new_inst(FI_IS_V4, $1); }
|
|
||||||
| term '.' TYPE { $$ = f_new_inst(FI_TYPE, $1); }
|
|
||||||
| term '.' IP { $$ = f_new_inst(FI_IP, $1); }
|
|
||||||
| term '.' RD { $$ = f_new_inst(FI_ROUTE_DISTINGUISHER, $1); }
|
|
||||||
| term '.' LEN { $$ = f_new_inst(FI_LENGTH, $1); }
|
|
||||||
| term '.' MAXLEN { $$ = f_new_inst(FI_ROA_MAXLEN, $1); }
|
|
||||||
| term '.' ASN { $$ = f_new_inst(FI_ROA_ASN, $1); }
|
|
||||||
| term '.' SRC { $$ = f_new_inst(FI_NET_SRC, $1); }
|
|
||||||
| term '.' DST { $$ = f_new_inst(FI_NET_DST, $1); }
|
|
||||||
| term '.' MASK '(' term ')' { $$ = f_new_inst(FI_IP_MASK, $1, $5); }
|
| term '.' MASK '(' term ')' { $$ = f_new_inst(FI_IP_MASK, $1, $5); }
|
||||||
| term '.' FIRST { $$ = f_new_inst(FI_AS_PATH_FIRST, $1); }
|
| term '.' token {
|
||||||
| term '.' LAST { $$ = f_new_inst(FI_AS_PATH_LAST, $1); }
|
switch ($3.value) {
|
||||||
| term '.' LAST_NONAGGREGATED { $$ = f_new_inst(FI_AS_PATH_LAST_NAG, $1); }
|
case IS_V4: $$ = f_new_inst(FI_IS_V4, $1); break;
|
||||||
|
case TYPE: $$ = f_new_inst(FI_TYPE, $1); break;
|
||||||
|
case IP: $$ = f_new_inst(FI_IP, $1); break;
|
||||||
|
case RD: $$ = f_new_inst(FI_ROUTE_DISTINGUISHER, $1); break;
|
||||||
|
case LEN: $$ = f_new_inst(FI_LENGTH, $1); break;
|
||||||
|
case MAXLEN: $$ = f_new_inst(FI_ROA_MAXLEN, $1); break;
|
||||||
|
case ASN: $$ = f_new_inst(FI_ROA_ASN, $1); break;
|
||||||
|
case SRC: $$ = f_new_inst(FI_NET_SRC, $1); break;
|
||||||
|
case DST: $$ = f_new_inst(FI_NET_DST, $1); break;
|
||||||
|
case FIRST: $$ = f_new_inst(FI_AS_PATH_FIRST, $1); break;
|
||||||
|
case LAST: $$ = f_new_inst(FI_AS_PATH_LAST, $1); break;
|
||||||
|
case LAST_NONAGGREGATED: $$ = f_new_inst(FI_AS_PATH_LAST_NAG, $1); break;
|
||||||
|
default: $$ = f_new_inst(FI_DEREF, $1, f_get_deref($1->type, &$3)); break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Communities */
|
/* Communities */
|
||||||
/* This causes one shift/reduce conflict
|
/* This causes one shift/reduce conflict
|
||||||
|
@ -61,6 +61,9 @@ enum f_type {
|
|||||||
|
|
||||||
T_SET = 0x80,
|
T_SET = 0x80,
|
||||||
T_PREFIX_SET = 0x81,
|
T_PREFIX_SET = 0x81,
|
||||||
|
|
||||||
|
T_PROTO = 0xa0, /* Protocol instance */
|
||||||
|
T_CHANNEL = 0xa1, /* Channel */
|
||||||
} PACKED;
|
} PACKED;
|
||||||
|
|
||||||
/* Filter value; size of this affects filter memory consumption */
|
/* Filter value; size of this affects filter memory consumption */
|
||||||
@ -78,6 +81,8 @@ struct f_val {
|
|||||||
const struct adata *ad;
|
const struct adata *ad;
|
||||||
const struct f_path_mask *path_mask;
|
const struct f_path_mask *path_mask;
|
||||||
struct f_path_mask_item pmi;
|
struct f_path_mask_item pmi;
|
||||||
|
struct proto *proto;
|
||||||
|
struct channel *channel;
|
||||||
} val;
|
} val;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -94,6 +99,8 @@ enum f_sa_code {
|
|||||||
SA_GW,
|
SA_GW,
|
||||||
SA_NET,
|
SA_NET,
|
||||||
SA_PROTO,
|
SA_PROTO,
|
||||||
|
SA_SENDER,
|
||||||
|
SA_AUTHOR,
|
||||||
SA_SOURCE,
|
SA_SOURCE,
|
||||||
SA_SCOPE,
|
SA_SCOPE,
|
||||||
SA_DEST,
|
SA_DEST,
|
||||||
@ -126,6 +133,16 @@ struct f_lval {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Member dereference (in filter/deref.c) */
|
||||||
|
struct f_deref {
|
||||||
|
struct f_val (*deref)(struct f_val *);
|
||||||
|
const char *name;
|
||||||
|
enum f_type source_type, result_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct keyword;
|
||||||
|
const struct f_deref *f_get_deref(enum f_type, const struct keyword *);
|
||||||
|
|
||||||
/* IP prefix range structure */
|
/* IP prefix range structure */
|
||||||
struct f_prefix {
|
struct f_prefix {
|
||||||
net_addr net; /* The matching prefix must match this net */
|
net_addr net; /* The matching prefix must match this net */
|
||||||
|
@ -90,7 +90,7 @@ FID_DUMP_BODY()m4_dnl
|
|||||||
debug("%s" $4 "\n", INDENT, $5);
|
debug("%s" $4 "\n", INDENT, $5);
|
||||||
]])
|
]])
|
||||||
FID_INTERPRET_EXEC()m4_dnl
|
FID_INTERPRET_EXEC()m4_dnl
|
||||||
const $1 $2 = whati->$2
|
$1 const $2 = whati->$2
|
||||||
FID_INTERPRET_BODY')
|
FID_INTERPRET_BODY')
|
||||||
|
|
||||||
# Instruction arguments are needed only until linearization is done.
|
# Instruction arguments are needed only until linearization is done.
|
||||||
|
68
filter/deref.c
Normal file
68
filter/deref.c
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
/*
|
||||||
|
* Filters: dereferencing metaobjects
|
||||||
|
*
|
||||||
|
* (c) 2020 Maria Matejka <mq@jmq.cz>
|
||||||
|
*
|
||||||
|
* Can be freely distributed and used under the terms of the GNU GPL.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define PARSER 1
|
||||||
|
|
||||||
|
#include "nest/bird.h"
|
||||||
|
#include "nest/route.h"
|
||||||
|
#include "nest/protocol.h"
|
||||||
|
#include "filter/filter.h"
|
||||||
|
#include "filter/f-inst.h"
|
||||||
|
#include "filter/data.h"
|
||||||
|
#include "conf/conf.h"
|
||||||
|
#include "conf/cf-parse.tab.h"
|
||||||
|
|
||||||
|
static struct f_val deref_proto__name__deref(struct f_val *val)
|
||||||
|
{ return (struct f_val) { .type = T_STRING, .val.s = val->val.proto->name }; }
|
||||||
|
|
||||||
|
static const struct f_deref deref_proto__name = {
|
||||||
|
.deref = deref_proto__name__deref,
|
||||||
|
.name = "name",
|
||||||
|
.source_type = T_PROTO,
|
||||||
|
.result_type = T_STRING,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct f_val deref_channel__name__deref(struct f_val *val)
|
||||||
|
{ return (struct f_val) { .type = T_STRING, .val.s = val->val.channel->name }; }
|
||||||
|
|
||||||
|
static const struct f_deref deref_channel__name = {
|
||||||
|
.deref = deref_channel__name__deref,
|
||||||
|
.name = "name",
|
||||||
|
.source_type = T_CHANNEL,
|
||||||
|
.result_type = T_STRING,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct f_val deref_channel__proto__deref(struct f_val *val)
|
||||||
|
{ return (struct f_val) { .type = T_PROTO, .val.proto = val->val.channel->proto }; }
|
||||||
|
|
||||||
|
static const struct f_deref deref_channel__proto = {
|
||||||
|
.deref = deref_channel__proto__deref,
|
||||||
|
.name = "proto",
|
||||||
|
.source_type = T_CHANNEL,
|
||||||
|
.result_type = T_PROTO,
|
||||||
|
};
|
||||||
|
|
||||||
|
const struct f_deref *f_get_deref(enum f_type type, const struct keyword *kw)
|
||||||
|
{
|
||||||
|
if (!type)
|
||||||
|
cf_error("Can't dereference an object with unsure type");
|
||||||
|
|
||||||
|
#define CX(t, v) ((u64) (t) | ((v) << (8 * sizeof (enum f_type))))
|
||||||
|
switch (CX(type, kw->value))
|
||||||
|
{
|
||||||
|
case CX(T_PROTO, NAME):
|
||||||
|
return &deref_proto__name;
|
||||||
|
case CX(T_CHANNEL, NAME):
|
||||||
|
return &deref_channel__name;
|
||||||
|
case CX(T_CHANNEL, PROTO):
|
||||||
|
return &deref_channel__proto;
|
||||||
|
}
|
||||||
|
|
||||||
|
cf_error("Can't call (%s).%s: Undefined operation", f_type_name(type), kw->name);
|
||||||
|
}
|
@ -404,6 +404,21 @@
|
|||||||
RESULT(T_BOOL, i, (v1.type != T_VOID) && !undef_value(v1));
|
RESULT(T_BOOL, i, (v1.type != T_VOID) && !undef_value(v1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
INST(FI_DEREF, 1, 1) {
|
||||||
|
NEVER_CONSTANT;
|
||||||
|
ARG_ANY(1);
|
||||||
|
FID_MEMBER(
|
||||||
|
const struct f_deref *,
|
||||||
|
deref,
|
||||||
|
[[ f1->deref != f2->deref ]],
|
||||||
|
"dereference %s from %s",
|
||||||
|
[[ item->deref->name, f_type_name(item->deref->source_type) ]]
|
||||||
|
);
|
||||||
|
|
||||||
|
RESULT_TYPE(deref->result_type);
|
||||||
|
RESULT_VAL(deref->deref(&v1));
|
||||||
|
}
|
||||||
|
|
||||||
INST(FI_TYPE, 1, 1) {
|
INST(FI_TYPE, 1, 1) {
|
||||||
ARG_ANY(1); /* There may be more types supporting this operation */
|
ARG_ANY(1); /* There may be more types supporting this operation */
|
||||||
switch (v1.type)
|
switch (v1.type)
|
||||||
@ -503,6 +518,8 @@
|
|||||||
case SA_GW: RESULT(sa.f_type, ip, rta->nh.gw); break;
|
case SA_GW: RESULT(sa.f_type, ip, rta->nh.gw); break;
|
||||||
case SA_NET: RESULT(sa.f_type, net, (*fs->rte)->net->n.addr); break;
|
case SA_NET: RESULT(sa.f_type, net, (*fs->rte)->net->n.addr); break;
|
||||||
case SA_PROTO: RESULT(sa.f_type, s, rta->src->proto->name); break;
|
case SA_PROTO: RESULT(sa.f_type, s, rta->src->proto->name); break;
|
||||||
|
case SA_SENDER: RESULT(sa.f_type, channel, (*fs->rte)->sender); break;
|
||||||
|
case SA_AUTHOR: RESULT(sa.f_type, proto, rta->src->proto); break;
|
||||||
case SA_SOURCE: RESULT(sa.f_type, i, rta->source); break;
|
case SA_SOURCE: RESULT(sa.f_type, i, rta->source); break;
|
||||||
case SA_SCOPE: RESULT(sa.f_type, i, rta->scope); break;
|
case SA_SCOPE: RESULT(sa.f_type, i, rta->scope); break;
|
||||||
case SA_DEST: RESULT(sa.f_type, i, rta->dest); break;
|
case SA_DEST: RESULT(sa.f_type, i, rta->dest); break;
|
||||||
|
Loading…
Reference in New Issue
Block a user