summaryrefslogtreecommitdiff
path: root/filter
diff options
context:
space:
mode:
Diffstat (limited to 'filter')
-rw-r--r--filter/Makefile9
-rw-r--r--filter/config.Y55
-rw-r--r--filter/f-util.c9
-rw-r--r--filter/filter.c179
-rw-r--r--filter/filter.h42
-rw-r--r--filter/test.conf47
-rw-r--r--filter/trie.c71
7 files changed, 198 insertions, 214 deletions
diff --git a/filter/Makefile b/filter/Makefile
index 2de598da..f27befdf 100644
--- a/filter/Makefile
+++ b/filter/Makefile
@@ -1,5 +1,4 @@
-source=f-util.c filter.c tree.c trie.c
-root-rel=../
-dir-name=filter
-
-include ../Rules
+src := filter.c f-util.c tree.c trie.c
+obj := $(src-o-files)
+$(all-daemon)
+$(cf-local)
diff --git a/filter/config.Y b/filter/config.Y
index 5ea83f81..8af444a3 100644
--- a/filter/config.Y
+++ b/filter/config.Y
@@ -232,7 +232,6 @@ f_generate_ec(u16 kind, struct f_inst *tk, struct f_inst *tv)
cf_error("Can't operate with key of non-integer/IPv4 type in EC constructor");
}
-#ifndef IPV6
/* IP->Quad implicit conversion */
else if (tk->code == 'C') {
c1 = 1;
@@ -244,13 +243,12 @@ f_generate_ec(u16 kind, struct f_inst *tk, struct f_inst *tv)
else if (val->type == T_QUAD) {
ipv4_used = 1; key = val->val.i;
}
- else if (val->type == T_IP) {
- ipv4_used = 1; key = ipa_to_u32(val->val.px.ip);
+ else if ((val->type == T_IP) && ipa_is_ip4(val->val.ip)) {
+ ipv4_used = 1; key = ipa_to_u32(val->val.ip);
}
else
cf_error("Can't operate with key of non-integer/IPv4 type in EC constructor");
}
-#endif
if (tv->code == 'c') {
if (tv->aux != T_INT)
@@ -337,11 +335,11 @@ CF_KEYWORDS(FUNCTION, PRINT, PRINTN, UNSET, RETURN,
TRUE, FALSE, RT, RO, UNKNOWN, GENERIC,
FROM, GW, NET, MASK, PROTO, SOURCE, SCOPE, CAST, DEST, IFNAME, IFINDEX,
PREFERENCE,
+ ROA_CHECK,
LEN,
DEFINED,
ADD, DELETE, CONTAINS, RESET,
PREPEND, FIRST, LAST, LAST_NONAGGREGATED, MATCH,
- ROA_CHECK,
EMPTY,
FILTER, WHERE, EVAL)
@@ -354,7 +352,8 @@ CF_KEYWORDS(FUNCTION, PRINT, PRINTN, UNSET, RETURN,
%type <i32> cnum
%type <e> pair_item ec_item lc_item set_item switch_item set_items switch_items switch_body
%type <trie> fprefix_set
-%type <v> set_atom switch_atom fprefix fprefix_s fipa
+%type <v> set_atom switch_atom fipa
+%type <px> fprefix
%type <s> decls declsn one_decl function_params
%type <h> bgp_path bgp_path_tail1 bgp_path_tail2
@@ -380,7 +379,7 @@ type:
INT { $$ = T_INT; }
| BOOL { $$ = T_BOOL; }
| IP { $$ = T_IP; }
- | PREFIX { $$ = T_PREFIX; }
+ | PREFIX { $$ = T_NET; }
| PAIR { $$ = T_PAIR; }
| QUAD { $$ = T_QUAD; }
| EC { $$ = T_EC; }
@@ -402,7 +401,7 @@ type:
$$ = T_SET;
break;
- case T_PREFIX:
+ case T_NET:
$$ = T_PREFIX_SET;
break;
@@ -537,7 +536,8 @@ block:
* Complex types, their bison value is struct f_val
*/
fipa:
- IPA %prec PREFIX_DUMMY { $$.type = T_IP; $$.val.px.ip = $1; }
+ IP4 %prec PREFIX_DUMMY { $$.type = T_IP; $$.val.ip = ipa_from_ip4($1); }
+ | IP6 %prec PREFIX_DUMMY { $$.type = T_IP; $$.val.ip = ipa_from_ip6($1); }
;
@@ -551,7 +551,6 @@ fipa:
set_atom:
NUM { $$.type = T_INT; $$.val.i = $1; }
- | RTRID { $$.type = T_QUAD; $$.val.i = $1; }
| fipa { $$ = $1; }
| ENUM { $$.type = pair_a($1); $$.val.i = pair_b($1); }
| '(' term ')' {
@@ -568,7 +567,6 @@ set_atom:
switch_atom:
NUM { $$.type = T_INT; $$.val.i = $1; }
| '(' term ')' { $$.type = T_INT; $$.val.i = f_eval_int($2); }
- | RTRID { $$.type = T_QUAD; $$.val.i = $1; }
| fipa { $$ = $1; }
| ENUM { $$.type = pair_a($1); $$.val.i = pair_b($1); }
;
@@ -641,26 +639,20 @@ switch_items:
| switch_items ',' switch_item { $$ = f_merge_items($1, $3); }
;
-fprefix_s:
- IPA '/' NUM %prec '/' {
- if (($3 < 0) || ($3 > MAX_PREFIX_LENGTH) || !ip_is_prefix($1, $3)) cf_error("Invalid network prefix: %I/%d.", $1, $3);
- $$.type = T_PREFIX; $$.val.px.ip = $1; $$.val.px.len = $3;
- }
- ;
-
fprefix:
- fprefix_s { $$ = $1; }
- | fprefix_s '+' { $$ = $1; $$.val.px.len |= LEN_PLUS; }
- | fprefix_s '-' { $$ = $1; $$.val.px.len |= LEN_MINUS; }
- | fprefix_s '{' NUM ',' NUM '}' {
- if (! ((0 <= $3) && ($3 <= $5) && ($5 <= MAX_PREFIX_LENGTH))) cf_error("Invalid prefix pattern range: {%d, %d}.", $3, $5);
- $$ = $1; $$.val.px.len |= LEN_RANGE | ($3 << 16) | ($5 << 8);
+ net_ip_ { $$.net = $1; $$.lo = $1.pxlen; $$.hi = $1.pxlen; }
+ | net_ip_ '+' { $$.net = $1; $$.lo = $1.pxlen; $$.hi = net_max_prefix_length[$1.type]; }
+ | net_ip_ '-' { $$.net = $1; $$.lo = 0; $$.hi = $1.pxlen; }
+ | net_ip_ '{' NUM ',' NUM '}' {
+ $$.net = $1; $$.lo = $3; $$.hi = $5;
+ if ((0 > $3) || ($3 > $5) || ($5 > net_max_prefix_length[$1.type]))
+ cf_error("Invalid prefix pattern range: {%d, %d}", $3, $5);
}
;
fprefix_set:
- fprefix { $$ = f_new_trie(cfg_mem, sizeof(struct f_trie_node)); trie_add_fprefix($$, &($1.val.px)); }
- | fprefix_set ',' fprefix { $$ = $1; trie_add_fprefix($$, &($3.val.px)); }
+ fprefix { $$ = f_new_trie(cfg_mem, sizeof(struct f_trie_node)); trie_add_prefix($$, &($1.net), $1.lo, $1.hi); }
+ | fprefix_set ',' fprefix { $$ = $1; trie_add_prefix($$, &($3.net), $3.lo, $3.hi); }
;
switch_body: /* EMPTY */ { $$ = NULL; }
@@ -712,9 +704,8 @@ constant:
| TRUE { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_BOOL; $$->a2.i = 1; }
| FALSE { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_BOOL; $$->a2.i = 0; }
| TEXT { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_STRING; $$->a2.p = $1; }
- | fipa { NEW_F_VAL; $$ = f_new_inst(); $$->code = 'C'; $$->a1.p = val; *val = $1; }
- | fprefix_s {NEW_F_VAL; $$ = f_new_inst(); $$->code = 'C'; $$->a1.p = val; *val = $1; }
- | RTRID { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_QUAD; $$->a2.i = $1; }
+ | fipa { NEW_F_VAL; $$ = f_new_inst(); $$->code = 'C'; $$->a1.p = val; *val = $1; }
+ | net_ { NEW_F_VAL; $$ = f_new_inst(); $$->code = 'C'; val->type = T_NET; val->val.net = $1; $$->a1.p = val; }
| '[' set_items ']' { DBG( "We've got a set here..." ); $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_SET; $$->a2.p = build_tree($2); DBG( "ook\n" ); }
| '[' fprefix_set ']' { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_PREFIX_SET; $$->a2.p = $2; }
| ENUM { $$ = f_new_inst(); $$->code = 'c'; $$->aux = $1 >> 16; $$->a2.i = $1 & 0xffff; }
@@ -778,7 +769,7 @@ symbol:
static_attr:
FROM { $$ = f_new_inst(); $$->aux = T_IP; $$->a2.i = SA_FROM; $$->a1.i = 1; }
| GW { $$ = f_new_inst(); $$->aux = T_IP; $$->a2.i = SA_GW; $$->a1.i = 1; }
- | NET { $$ = f_new_inst(); $$->aux = T_PREFIX; $$->a2.i = SA_NET; }
+ | NET { $$ = f_new_inst(); $$->aux = T_NET; $$->a2.i = SA_NET; }
| PROTO { $$ = f_new_inst(); $$->aux = T_STRING; $$->a2.i = SA_PROTO; }
| SOURCE { $$ = f_new_inst(); $$->aux = T_ENUM_RTS; $$->a2.i = SA_SOURCE; }
| SCOPE { $$ = f_new_inst(); $$->aux = T_ENUM_SCOPE; $$->a2.i = SA_SCOPE; $$->a1.i = 1; }
@@ -841,8 +832,8 @@ term:
| DELETE '(' term ',' term ')' { $$ = f_new_inst(); $$->code = P('C','a'); $$->a1.p = $3; $$->a2.p = $5; $$->aux = 'd'; }
| FILTER '(' term ',' term ')' { $$ = f_new_inst(); $$->code = P('C','a'); $$->a1.p = $3; $$->a2.p = $5; $$->aux = 'f'; }
- | ROA_CHECK '(' SYM ')' { $$ = f_generate_roa_check($3, NULL, NULL); }
- | ROA_CHECK '(' SYM ',' term ',' term ')' { $$ = f_generate_roa_check($3, $5, $7); }
+ | ROA_CHECK '(' rtable ')' { $$ = f_generate_roa_check($3, NULL, NULL); }
+ | ROA_CHECK '(' rtable ',' term ',' term ')' { $$ = f_generate_roa_check($3, $5, $7); }
/* | term '.' LEN { $$->code = P('P','l'); } */
diff --git a/filter/f-util.c b/filter/f-util.c
index def2b248..661941ec 100644
--- a/filter/f-util.c
+++ b/filter/f-util.c
@@ -54,9 +54,8 @@ f_generate_complex(int operation, int operation_aux, struct f_inst *dyn, struct
return set_dyn;
}
-
struct f_inst *
-f_generate_roa_check(struct symbol *sym, struct f_inst *prefix, struct f_inst *asn)
+f_generate_roa_check(struct rtable_config *table, struct f_inst *prefix, struct f_inst *asn)
{
struct f_inst_roa_check *ret = cfg_allocz(sizeof(struct f_inst_roa_check));
ret->i.code = P('R','C');
@@ -65,9 +64,9 @@ f_generate_roa_check(struct symbol *sym, struct f_inst *prefix, struct f_inst *a
ret->i.arg2 = asn;
/* prefix == NULL <-> asn == NULL */
- if ((sym->class != SYM_ROA) || ! sym->def)
- cf_error("%s is not a ROA table", sym->name);
- ret->rtc = sym->def;
+ if (table->addr_type != NET_ROA4 && table->addr_type != NET_ROA6)
+ cf_error("%s is not a ROA table", table->name);
+ ret->rtc = table;
return &ret->i;
}
diff --git a/filter/filter.c b/filter/filter.c
index 85a06258..09b89401 100644
--- a/filter/filter.c
+++ b/filter/filter.c
@@ -39,6 +39,8 @@
#include "lib/socket.h"
#include "lib/string.h"
#include "lib/unaligned.h"
+#include "lib/net.h"
+#include "lib/ip.h"
#include "nest/route.h"
#include "nest/protocol.h"
#include "nest/iface.h"
@@ -94,17 +96,8 @@ pm_format(struct f_path_mask *p, buffer *buf)
buffer_puts(buf, "=]");
}
-static inline int
-uint_cmp(uint i1, uint i2)
-{
- return (int)(i1 > i2) - (int)(i1 < i2);
-}
-
-static inline int
-u64_cmp(u64 i1, u64 i2)
-{
- return (int)(i1 > i2) - (int)(i1 < i2);
-}
+static inline int val_is_ip4(const struct f_val v)
+{ return (v.type == T_IP) && ipa_is_ip4(v.val.ip); }
static inline int
lcomm_cmp(lcomm v1, lcomm v2)
@@ -130,21 +123,17 @@ lcomm_cmp(lcomm v1, lcomm v2)
int
val_compare(struct f_val v1, struct f_val v2)
{
- int rc;
-
if (v1.type != v2.type) {
if (v1.type == T_VOID) /* Hack for else */
return -1;
if (v2.type == T_VOID)
return 1;
-#ifndef IPV6
/* IP->Quad implicit conversion */
- if ((v1.type == T_QUAD) && (v2.type == T_IP))
- return uint_cmp(v1.val.i, ipa_to_u32(v2.val.px.ip));
- if ((v1.type == T_IP) && (v2.type == T_QUAD))
- return uint_cmp(ipa_to_u32(v1.val.px.ip), v2.val.i);
-#endif
+ if ((v1.type == T_QUAD) && val_is_ip4(v2))
+ return uint_cmp(v1.val.i, ipa_to_u32(v2.val.ip));
+ if (val_is_ip4(v1) && (v2.type == T_QUAD))
+ return uint_cmp(ipa_to_u32(v1.val.ip), v2.val.i);
debug( "Types do not match in val_compare\n" );
return CMP_ERROR;
@@ -164,11 +153,9 @@ val_compare(struct f_val v1, struct f_val v2)
case T_LC:
return lcomm_cmp(v1.val.lc, v2.val.lc);
case T_IP:
- return ipa_compare(v1.val.px.ip, v2.val.px.ip);
- case T_PREFIX:
- if (rc = ipa_compare(v1.val.px.ip, v2.val.px.ip))
- return rc;
- return uint_cmp(v1.val.px.len, v2.val.px.len);
+ return ipa_compare(v1.val.ip, v2.val.ip);
+ case T_NET:
+ return net_compare(v1.val.net, v2.val.net);
case T_STRING:
return strcmp(v1.val.s, v2.val.s);
default:
@@ -239,38 +226,26 @@ val_same(struct f_val v1, struct f_val v2)
}
}
-void
-fprefix_get_bounds(struct f_prefix *px, int *l, int *h)
-{
- *l = *h = px->len & LEN_MASK;
-
- if (px->len & LEN_MINUS)
- *l = 0;
-
- else if (px->len & LEN_PLUS)
- *h = MAX_PREFIX_LENGTH;
-
- else if (px->len & LEN_RANGE)
- {
- *l = 0xff & (px->len >> 16);
- *h = 0xff & (px->len >> 8);
- }
-}
-
static int
clist_set_type(struct f_tree *set, struct f_val *v)
{
- switch (set->from.type) {
+ switch (set->from.type)
+ {
case T_PAIR:
v->type = T_PAIR;
return 1;
+
case T_QUAD:
-#ifndef IPV6
- case T_IP:
-#endif
v->type = T_QUAD;
return 1;
- break;
+
+ case T_IP:
+ if (val_is_ip4(set->from) && val_is_ip4(set->to))
+ {
+ v->type = T_QUAD;
+ return 1;
+ }
+ /* Fall through */
default:
v->type = T_VOID;
return 0;
@@ -473,11 +448,10 @@ val_in_range(struct f_val v1, struct f_val v2)
if (((v1.type == T_PAIR) || (v1.type == T_QUAD)) && (v2.type == T_CLIST))
return int_set_contains(v2.val.ad, v1.val.i);
-#ifndef IPV6
+
/* IP->Quad implicit conversion */
- if ((v1.type == T_IP) && (v2.type == T_CLIST))
- return int_set_contains(v2.val.ad, ipa_to_u32(v1.val.px.ip));
-#endif
+ if (val_is_ip4(v1) && (v2.type == T_CLIST))
+ return int_set_contains(v2.val.ad, ipa_to_u32(v1.val.ip));
if ((v1.type == T_EC) && (v2.type == T_ECLIST))
return ec_set_contains(v2.val.ad, v1.val.ec);
@@ -488,21 +462,21 @@ val_in_range(struct f_val v1, struct f_val v2)
if ((v1.type == T_STRING) && (v2.type == T_STRING))
return patmatch(v2.val.s, v1.val.s);
- if ((v1.type == T_IP) && (v2.type == T_PREFIX))
- return ipa_in_net(v1.val.px.ip, v2.val.px.ip, v2.val.px.len);
+ if ((v1.type == T_IP) && (v2.type == T_NET))
+ return ipa_in_netX(v1.val.ip, v2.val.net);
- if ((v1.type == T_PREFIX) && (v2.type == T_PREFIX))
- return net_in_net(v1.val.px.ip, v1.val.px.len, v2.val.px.ip, v2.val.px.len);
+ if ((v1.type == T_NET) && (v2.type == T_NET))
+ return net_in_netX(v1.val.net, v2.val.net);
- if ((v1.type == T_PREFIX) && (v2.type == T_PREFIX_SET))
- return trie_match_fprefix(v2.val.ti, &v1.val.px);
+ if ((v1.type == T_NET) && (v2.type == T_PREFIX_SET))
+ return trie_match_net(v2.val.ti, v1.val.net);
if (v2.type != T_SET)
return CMP_ERROR;
/* With integrated Quad<->IP implicit conversion */
if ((v1.type == v2.val.t->from.type) ||
- ((IP_VERSION == 4) && (v1.type == T_QUAD) && (v2.val.t->from.type == T_IP)))
+ ((v1.type == T_QUAD) && val_is_ip4(v2.val.t->from) && val_is_ip4(v2.val.t->to)))
return !!find_tree(v2.val.t, v1);
if (v1.type == T_CLIST)
@@ -533,8 +507,8 @@ val_format(struct f_val v, buffer *buf)
case T_BOOL: buffer_puts(buf, v.val.i ? "TRUE" : "FALSE"); return;
case T_INT: buffer_print(buf, "%u", v.val.i); return;
case T_STRING: buffer_print(buf, "%s", v.val.s); return;
- case T_IP: buffer_print(buf, "%I", v.val.px.ip); return;
- case T_PREFIX: buffer_print(buf, "%I/%d", v.val.px.ip, v.val.px.len); return;
+ case T_IP: buffer_print(buf, "%I", v.val.ip); return;
+ case T_NET: buffer_print(buf, "%N", v.val.net); return;
case T_PAIR: buffer_print(buf, "(%u,%u)", v.val.i >> 16, v.val.i & 0xffff); return;
case T_QUAD: buffer_print(buf, "%R", v.val.i); return;
case T_EC: ec_format(buf2, v.val.ec); buffer_print(buf, "%s", buf2); return;
@@ -726,12 +700,10 @@ interpret(struct f_inst *what)
else if (v1.type == T_QUAD) {
ipv4_used = 1; key = v1.val.i;
}
-#ifndef IPV6
/* IP->Quad implicit conversion */
- else if (v1.type == T_IP) {
- ipv4_used = 1; key = ipa_to_u32(v1.val.px.ip);
+ else if (val_is_ip4(v1)) {
+ ipv4_used = 1; key = ipa_to_u32(v1.val.ip);
}
-#endif
else
runtime("Can't operate with key of non-integer/IPv4 type in EC constructor");
@@ -839,15 +811,15 @@ interpret(struct f_inst *what)
ARG(v2, a2.p);
sym = what->a1.p;
vp = sym->def;
- if ((sym->class != (SYM_VARIABLE | v2.type)) && (v2.type != T_VOID)) {
-#ifndef IPV6
+ if ((sym->class != (SYM_VARIABLE | v2.type)) && (v2.type != T_VOID))
+ {
/* IP->Quad implicit conversion */
- if ((sym->class == (SYM_VARIABLE | T_QUAD)) && (v2.type == T_IP)) {
+ if ((sym->class == (SYM_VARIABLE | T_QUAD)) && val_is_ip4(v2))
+ {
vp->type = T_QUAD;
- vp->val.i = ipa_to_u32(v2.val.px.ip);
+ vp->val.i = ipa_to_u32(v2.val.ip);
break;
}
-#endif
runtime( "Assigning to variable of incompatible type" );
}
*vp = v2;
@@ -917,10 +889,9 @@ interpret(struct f_inst *what)
switch (what->a2.i)
{
- case SA_FROM: res.val.px.ip = rta->from; break;
- case SA_GW: res.val.px.ip = rta->gw; break;
- case SA_NET: res.val.px.ip = (*f_rte)->net->n.prefix;
- res.val.px.len = (*f_rte)->net->n.pxlen; break;
+ case SA_FROM: res.val.ip = rta->from; break;
+ case SA_GW: res.val.ip = rta->gw; break;
+ case SA_NET: res.val.net = (*f_rte)->net->n.addr; break;
case SA_PROTO: res.val.s = rta->src->proto->name; break;
case SA_SOURCE: res.val.i = rta->source; break;
case SA_SCOPE: res.val.i = rta->scope; break;
@@ -947,12 +918,12 @@ interpret(struct f_inst *what)
switch (what->a2.i)
{
case SA_FROM:
- rta->from = v1.val.px.ip;
+ rta->from = v1.val.ip;
break;
case SA_GW:
{
- ip_addr ip = v1.val.px.ip;
+ ip_addr ip = v1.val.ip;
neighbor *n = neigh_find(rta->src->proto, &ip, 0);
if (!n || (n->scope == SCOPE_HOST))
runtime( "Invalid gw address" );
@@ -1042,7 +1013,7 @@ interpret(struct f_inst *what)
case EAF_TYPE_IP_ADDRESS:
res.type = T_IP;
struct adata * ad = e->u.ptr;
- res.val.px.ip = * (ip_addr *) ad->data;
+ res.val.ip = * (ip_addr *) ad->data;
break;
case EAF_TYPE_AS_PATH:
res.type = T_PATH;
@@ -1094,13 +1065,11 @@ interpret(struct f_inst *what)
break;
case EAF_TYPE_ROUTER_ID:
-#ifndef IPV6
/* IP->Quad implicit conversion */
- if (v1.type == T_IP) {
- l->attrs[0].u.data = ipa_to_u32(v1.val.px.ip);
+ if (val_is_ip4(v1)) {
+ l->attrs[0].u.data = ipa_to_u32(v1.val.ip);
break;
}
-#endif
/* T_INT for backward compatibility */
if ((v1.type != T_QUAD) && (v1.type != T_INT))
runtime( "Setting quad attribute to non-quad value" );
@@ -1116,7 +1085,7 @@ interpret(struct f_inst *what)
int len = sizeof(ip_addr);
struct adata *ad = lp_alloc(f_pool, sizeof(struct adata) + len);
ad->length = len;
- (* (ip_addr *) ad->data) = v1.val.px.ip;
+ (* (ip_addr *) ad->data) = v1.val.ip;
l->attrs[0].u.ptr = ad;
break;
case EAF_TYPE_AS_PATH:
@@ -1196,7 +1165,7 @@ interpret(struct f_inst *what)
ONEARG;
res.type = T_INT;
switch(v1.type) {
- case T_PREFIX: res.val.i = v1.val.px.len; break;
+ case T_NET: res.val.i = net_pxlen(v1.val.net); break;
case T_PATH: res.val.i = as_path_getlen(v1.val.ad); break;
case T_CLIST: res.val.i = int_set_get_size(v1.val.ad); break;
case T_ECLIST: res.val.i = ec_set_get_size(v1.val.ad); break;
@@ -1206,14 +1175,10 @@ interpret(struct f_inst *what)
break;
case P('c','p'): /* Convert prefix to ... */
ONEARG;
- if (v1.type != T_PREFIX)
+ if (v1.type != T_NET)
runtime( "Prefix expected" );
- res.type = what->aux;
- switch(res.type) {
- /* case T_INT: res.val.i = v1.val.px.len; break; Not needed any more */
- case T_IP: res.val.px.ip = v1.val.px.ip; break;
- default: bug( "Unknown prefix to conversion" );
- }
+ res.type = T_IP;
+ res.val.ip = net_prefix(v1.val.net);
break;
case P('a','f'): /* Get first ASN from AS PATH */
ONEARG;
@@ -1284,11 +1249,11 @@ interpret(struct f_inst *what)
runtime( "Integer expected");
if (v1.type != T_IP)
runtime( "You can mask only IP addresses" );
- {
- ip_addr mask = ipa_mkmask(v2.val.i);
- res.type = T_IP;
- res.val.px.ip = ipa_and(mask, v1.val.px.ip);
- }
+
+ res.type = T_IP;
+ res.val.ip = ipa_is_ip4(v1.val.ip) ?
+ ipa_from_ip4(ip4_and(ipa_to_ip4(v1.val.ip), ip4_mkmask(v2.val.i))) :
+ ipa_from_ip6(ip6_and(ipa_to_ip6(v1.val.ip), ip6_mkmask(v2.val.i)));
break;
case 'E': /* Create empty attribute */
@@ -1344,11 +1309,9 @@ interpret(struct f_inst *what)
if ((v2.type == T_PAIR) || (v2.type == T_QUAD))
n = v2.val.i;
-#ifndef IPV6
/* IP->Quad implicit conversion */
- else if (v2.type == T_IP)
- n = ipa_to_u32(v2.val.px.ip);
-#endif
+ else if (val_is_ip4(v2))
+ n = ipa_to_u32(v2.val.ip);
else if ((v2.type == T_SET) && clist_set_type(v2.val.t, &dummy))
arg_set = 1;
else if (v2.type == T_CLIST)
@@ -1474,11 +1437,12 @@ interpret(struct f_inst *what)
break;
+
case P('R','C'): /* ROA Check */
if (what->arg1)
{
TWOARGS;
- if ((v1.type != T_PREFIX) || (v2.type != T_INT))
+ if ((v1.type != T_NET) || (v2.type != T_INT))
runtime("Invalid argument to roa_check()");
as = v2.val.i;
@@ -1486,8 +1450,7 @@ interpret(struct f_inst *what)
else
{
ACCESS_RTE;
- v1.val.px.ip = (*f_rte)->net->n.prefix;
- v1.val.px.len = (*f_rte)->net->n.pxlen;
+ v1.val.net = (*f_rte)->net->n.addr;
/* We ignore temporary attributes, probably not a problem here */
/* 0x02 is a value of BA_AS_PATH, we don't want to include BGP headers */
@@ -1499,14 +1462,20 @@ interpret(struct f_inst *what)
as_path_get_last(e->u.ptr, &as);
}
- struct roa_table_config *rtc = ((struct f_inst_roa_check *) what)->rtc;
- if (!rtc->table)
+ struct rtable *table = ((struct f_inst_roa_check *) what)->rtc->table;
+ if (!table)
runtime("Missing ROA table");
+ /* Table type is either NET_ROA4 or NET_ROA6, checked in parser */
+ if (v1.val.net->type != ((table->addr_type == NET_ROA4) ? NET_IP4 : NET_IP6))
+ runtime("Incompatible net type");
+
res.type = T_ENUM_ROA;
- res.val.i = roa_check(rtc->table, v1.val.px.ip, v1.val.px.len, as);
+ res.val.i = net_roa_check(table, v1.val.net, as);
+
break;
+
default:
bug( "Unknown instruction %d (%c)", what->code, what->code & 0xff);
}
@@ -1640,6 +1609,7 @@ i_same(struct f_inst *f1, struct f_inst *f2)
case P('a','f'):
case P('a','l'):
case P('a','L'): ONEARG; break;
+#if 0
case P('R','C'):
TWOARGS;
/* Does not really make sense - ROA check resuls may change anyway */
@@ -1647,6 +1617,7 @@ i_same(struct f_inst *f1, struct f_inst *f2)
((struct f_inst_roa_check *) f2)->rtc->name))
return 0;
break;
+#endif
default:
bug( "Unknown instruction %d in same (%c)", f1->code, f1->code & 0xff);
}
diff --git a/filter/filter.h b/filter/filter.h
index 049ceb76..fc11b91e 100644
--- a/filter/filter.h
+++ b/filter/filter.h
@@ -35,7 +35,7 @@ struct f_inst { /* Instruction */
/* Not enough fields in f_inst for three args used by roa_check() */
struct f_inst_roa_check {
struct f_inst i;
- struct roa_table_config *rtc;
+ struct rtable_config *rtc;
};
struct f_inst3 {
@@ -50,13 +50,8 @@ struct f_inst3 {
struct f_prefix {
- ip_addr ip;
- int len;
-#define LEN_MASK 0xff
-#define LEN_PLUS 0x1000000
-#define LEN_MINUS 0x2000000
-#define LEN_RANGE 0x4000000
- /* If range then prefix must be in range (len >> 16 & 0xff, len >> 8 & 0xff) */
+ net_addr net;
+ u8 lo, hi;
};
struct f_val {
@@ -65,8 +60,8 @@ struct f_val {
uint i;
u64 ec;
lcomm lc;
- /* ip_addr ip; Folded into prefix */
- struct f_prefix px;
+ ip_addr ip;
+ const net_addr *net;
char *s;
struct f_tree *t;
struct f_trie *ti;
@@ -84,7 +79,7 @@ struct f_inst *f_new_inst(void);
struct f_inst *f_new_dynamic_attr(int type, int f_type, int code); /* Type as core knows it, type as filters know it, and code of dynamic attribute */
struct f_tree *f_new_tree(void);
struct f_inst *f_generate_complex(int operation, int operation_aux, struct f_inst *dyn, struct f_inst *argument);
-struct f_inst *f_generate_roa_check(struct symbol *sym, struct f_inst *prefix, struct f_inst *asn);
+struct f_inst *f_generate_roa_check(struct rtable_config *table, struct f_inst *prefix, struct f_inst *asn);
struct f_tree *build_tree(struct f_tree *);
@@ -93,28 +88,11 @@ int same_tree(struct f_tree *t1, struct f_tree *t2);
void tree_format(struct f_tree *t, buffer *buf);
struct f_trie *f_new_trie(linpool *lp, uint node_size);
-void *trie_add_prefix(struct f_trie *t, ip_addr px, int plen, int l, int h);
-int trie_match_prefix(struct f_trie *t, ip_addr px, int plen);
+void *trie_add_prefix(struct f_trie *t, const net_addr *n, uint l, uint h);
+int trie_match_net(struct f_trie *t, const net_addr *n);
int trie_same(struct f_trie *t1, struct f_trie *t2);
void trie_format(struct f_trie *t, buffer *buf);
-void fprefix_get_bounds(struct f_prefix *px, int *l, int *h);
-
-static inline void
-trie_add_fprefix(struct f_trie *t, struct f_prefix *px)
-{
- int l, h;
- fprefix_get_bounds(px, &l, &h);
- trie_add_prefix(t, px->ip, px->len & LEN_MASK, l, h);
-}
-
-static inline int
-trie_match_fprefix(struct f_trie *t, struct f_prefix *px)
-{
- return trie_match_prefix(t, px->ip, px->len & LEN_MASK);
-}
-
-
struct ea_list;
struct rte;
@@ -175,7 +153,7 @@ void val_format(struct f_val v, buffer *buf);
/* Bigger ones */
#define T_IP 0x20
-#define T_PREFIX 0x21
+#define T_NET 0x21
#define T_STRING 0x22
#define T_PATH_MASK 0x23 /* mask for BGP path */
#define T_PATH 0x24 /* BGP path */
@@ -211,7 +189,7 @@ struct f_tree {
struct f_trie_node
{
ip_addr addr, mask, accept;
- int plen;
+ uint plen;
struct f_trie_node *c[2];
};
diff --git a/filter/test.conf b/filter/test.conf
index 676b47d1..e65b3ebb 100644
--- a/filter/test.conf
+++ b/filter/test.conf
@@ -16,6 +16,10 @@ define ten = 10;
define p23 = (2, 3);
define ip1222 = 1.2.2.2;
+define net10 = 10.0.0.0/8;
+define netdoc = 2001:db8::/32;
+
+
function onef(int a)
{
return 1;
@@ -60,6 +64,7 @@ function fifteen()
return 15;
}
+/*
roa table rl
{
roa 10.110.0.0/16 max 16 as 1000;
@@ -85,6 +90,7 @@ function test_roa()
" ", roa_check(rl, 10.130.30.0/24, 3000) = ROA_INVALID,
" ", roa_check(rl, 10.130.130.0/24, 3000) = ROA_VALID;
}
+*/
function path_test()
bgpmask pm1;
@@ -251,28 +257,31 @@ define onetwo=1.2.3.4;
function __test1()
{
- if source ~ [ RTS_BGP, RTS_STATIC ] then {
-# ospf_metric1 = 65535;
-# ospf_metric2 = 1000;
- ospf_tag = 0x12345678;
- accept;
- } reject;
+ if source ~ [ RTS_BGP, RTS_STATIC ] then {
+# ospf_metric1 = 65535;
+# ospf_metric2 = 1000;
+ ospf_tag = 0x12345678;
+ accept;
+ }
+ reject;
}
function __test2()
{
- if source ~ [ RTS_BGP, RTS_STATIC ] then {
-# ospf_metric1 = 65535;
-# ospf_metric2 = 1000;
- ospf_tag = 0x12345678;
- accept;
- } reject;
+ if source ~ [ RTS_BGP, RTS_STATIC ] then {
+# ospf_metric1 = 65535;
+# ospf_metric2 = 1000;
+ ospf_tag = 0x12345678;
+ accept;
+ }
+ reject;
}
+
function test_pxset(prefix set pxs)
{
print pxs;
- print " must be true: ", 10.0.0.0/8 ~ pxs, ",", 10.0.0.0/10 ~ pxs, ",", 10.0.0.0/12 ~ pxs, ",",
+ print " must be true: ", net10 ~ pxs, ",", 10.0.0.0/10 ~ pxs, ",", 10.0.0.0/12 ~ pxs, ",",
20.0.0.0/24 ~ pxs, ",", 20.0.40.0/24 ~ pxs, ",", 20.0.0.0/26 ~ pxs, ",",
20.0.100.0/26 ~ pxs, ",", 20.0.0.0/28 ~ pxs, ",", 20.0.255.0/28 ~ pxs;
print " must be false: ", 10.0.0.0/7 ~ pxs, ",", 10.0.0.0/13 ~ pxs, ",", 10.0.0.0/16 ~ pxs, ",",
@@ -352,12 +361,12 @@ string st;
px = 1.2.0.0/18;
print "Testing prefixes: 1.2.0.0/18 = ", px;
- print " must be true: ", 192.168.0.0/16 ~ 192.168.0.0/16, " ", 192.168.0.0/17 ~ 192.168.0.0/16, " ", 192.168.254.0/24 ~ 192.168.0.0/16;
- print " must be false: ", 192.168.0.0/15 ~ 192.168.0.0/16, " ", 192.160.0.0/17 ~ 192.168.0.0/16;
+ print " must be true: ", 192.168.0.0/16 ~ 192.168.0.0/16, " ", 192.168.0.0/17 ~ 192.168.0.0/16, " ", 192.168.254.0/24 ~ 192.168.0.0/16, " ", netdoc ~ 2001::/16;
+ print " must be false: ", 192.168.0.0/15 ~ 192.168.0.0/16, " ", 192.160.0.0/17 ~ 192.168.0.0/16, " ", px ~ netdoc;
p = 127.1.2.3;
print "Testing mask : 127.0.0.0 = ", p.mask(8);
-
+
pp = (1, 2);
print "Testing pairs: (1,2) = ", (1,2), " = ", pp, " = ", (1,1+1), " = ", 'mkpair-a'(2);
print " must be true: ", (1,2) = (1,1+1);
@@ -401,7 +410,7 @@ string st;
b = true;
print "Testing bool: ", b, ", ", !b;
- if ( b = true ) then print "Testing bool comparison b = true: ", b;
+ if ( b = true ) then print "Testing bool comparison b = true: ", b;
else { print "*** FAIL: TRUE test failed" ; quitbird; }
ips = [ 1.1.1.0 .. 1.1.1.255, ip1222];
@@ -437,7 +446,7 @@ string st;
print "1.2.3.4 = ", onetwo;
i = 4200000000;
- print "4200000000 = ", i, " false: ", i = 4200000000, " ", i > 4100000000, " false: ", i > 4250000000;
+ print "4200000000 = ", i, " true: ", i = 4200000000, " ", i > 4100000000, " false: ", i > 4250000000;
test_undef(2);
test_undef(3);
@@ -459,7 +468,7 @@ int j;
j = 7;
j = 17;
if rip_metric > 15 then {
- reject "RIP Metric is more than infinity";
+ reject "RIP Metric is more than infinity";
}
rip_metric = 14;
unset(rip_metric);
diff --git a/filter/trie.c b/filter/trie.c
index 565ae82f..adcfcdf3 100644
--- a/filter/trie.c
+++ b/filter/trie.c
@@ -74,6 +74,19 @@
#include "conf/conf.h"
#include "filter/filter.h"
+
+/*
+ * In the trie code, the prefix length is internally treated as for the whole
+ * ip_addr, regardless whether it contains an IPv4 or IPv6 address. Therefore,
+ * remaining definitions make sense.
+ */
+
+#define ipa_mkmask(x) ip6_mkmask(x)
+#define ipa_masklen(x) ip6_masklen(&x)
+#define ipa_pxlen(x,y) ip6_pxlen(x,y)
+#define ipa_getbit(x,n) ip6_getbit(x,n)
+
+
/**
* f_new_trie - allocates and returns a new empty trie
* @lp: linear pool to allocate items from
@@ -109,12 +122,11 @@ attach_node(struct f_trie_node *parent, struct f_trie_node *child)
/**
* trie_add_prefix
* @t: trie to add to
- * @px: prefix address
- * @plen: prefix length
+ * @net: IP network prefix
* @l: prefix lower bound
* @h: prefix upper bound
*
- * Adds prefix (prefix pattern) @px/@plen to trie @t. @l and @h are lower
+ * Adds prefix (prefix pattern) @n to trie @t. @l and @h are lower
* and upper bounds on accepted prefix lengths, both inclusive.
* 0 <= l, h <= 32 (128 for IPv6).
*
@@ -124,8 +136,19 @@ attach_node(struct f_trie_node *parent, struct f_trie_node *child)
*/
void *
-trie_add_prefix(struct f_trie *t, ip_addr px, int plen, int l, int h)
+trie_add_prefix(struct f_trie *t, const net_addr *net, uint l, uint h)
{
+ ip_addr px = net_prefix(net);
+ uint plen = net_pxlen(net);
+
+ if (net->type == NET_IP4)
+ {
+ const uint delta = IP6_MAX_PREFIX_LENGTH - IP4_MAX_PREFIX_LENGTH;
+ plen += delta;
+ l += delta;
+ h += delta;
+ }
+
if (l == 0)
t->zero = 1;
else
@@ -140,7 +163,7 @@ trie_add_prefix(struct f_trie *t, ip_addr px, int plen, int l, int h)
struct f_trie_node *o = NULL;
struct f_trie_node *n = t->root;
- while(n)
+ while (n)
{
ip_addr cmask = ipa_and(n->mask, pmask);
@@ -196,18 +219,8 @@ trie_add_prefix(struct f_trie *t, ip_addr px, int plen, int l, int h)
return a;
}
-/**
- * trie_match_prefix
- * @t: trie
- * @px: prefix address
- * @plen: prefix length
- *
- * Tries to find a matching prefix pattern in the trie such that
- * prefix @px/@plen matches that prefix pattern. Returns 1 if there
- * is such prefix pattern in the trie.
- */
-int
-trie_match_prefix(struct f_trie *t, ip_addr px, int plen)
+static int
+trie_match_prefix(struct f_trie *t, ip_addr px, uint plen)
{
ip_addr pmask = ipa_mkmask(plen);
ip_addr paddr = ipa_and(px, pmask);
@@ -241,6 +254,30 @@ trie_match_prefix(struct f_trie *t, ip_addr px, int plen)
return 0;
}
+/**
+ * trie_match_net
+ * @t: trie
+ * @n: net address
+ *
+ * Tries to find a matching net in the trie such that
+ * prefix @n matches that prefix pattern. Returns 1 if there
+ * is such prefix pattern in the trie.
+ */
+int
+trie_match_net(struct f_trie *t, const net_addr *n)
+{
+ uint add = 0;
+
+ switch (n->type) {
+ case NET_IP4:
+ case NET_VPN4:
+ case NET_ROA4:
+ add = IP6_MAX_PREFIX_LENGTH - IP4_MAX_PREFIX_LENGTH;
+ }
+
+ return trie_match_prefix(t, net_prefix(n), net_pxlen(n) + add);
+}
+
static int
trie_node_same(struct f_trie_node *t1, struct f_trie_node *t2)
{