From 5e173e9f631913f68cf38d57a69c3ce6faf60d1e Mon Sep 17 00:00:00 2001 From: Jan Moskyto Matejka Date: Wed, 16 Dec 2015 10:25:12 +0100 Subject: [PATCH] Stop perusing f_prefix for non-prefix-set uses Multiple changes by Ondrej Santiago Zajicek --- conf/confbase.Y | 4 +- filter/config.Y | 53 ++++++++++----------- filter/filter.c | 121 +++++++++++++++++------------------------------- filter/filter.h | 48 ++++++------------- filter/trie.c | 53 ++++++++++++++------- lib/birdlib.h | 6 +++ lib/ip.h | 6 --- lib/net.c | 27 +++++++---- lib/net.h | 31 ++++++++++++- nest/config.Y | 6 +-- nest/rt-table.c | 3 +- 11 files changed, 176 insertions(+), 182 deletions(-) diff --git a/conf/confbase.Y b/conf/confbase.Y index 4bf9599b..467ce5a4 100644 --- a/conf/confbase.Y +++ b/conf/confbase.Y @@ -61,7 +61,7 @@ CF_DECLS struct roa_table *rot; void *g; bird_clock_t time; - struct prefix px; + struct f_prefix px; struct proto_spec ps; struct timeformat *tf; } @@ -162,7 +162,7 @@ ipa: ipa_raw | SYM { if ($1->class != (SYM_CONSTANT | T_IP)) cf_error("IP address expected"); - $$ = SYM_VAL($1).px.ip; + $$ = SYM_VAL($1).ip; } ; diff --git a/filter/config.Y b/filter/config.Y index d6844751..9411b7aa 100644 --- a/filter/config.Y +++ b/filter/config.Y @@ -134,7 +134,7 @@ f_new_ec_item(u32 kind, u32 ipv4_used, u32 key, u32 vf, u32 vt) static inline struct f_inst * f_generate_empty(struct f_inst *dyn) -{ +{ struct f_inst *e = f_new_inst(); e->code = 'E'; @@ -217,8 +217,8 @@ 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"); @@ -234,7 +234,7 @@ f_generate_ec(u16 kind, struct f_inst *tk, struct f_inst *tv) if (c1 && c2) { u64 ec; - + if (kind == EC_GENERIC) { ec = ec_generic(key, val2); } @@ -253,7 +253,7 @@ f_generate_ec(u16 kind, struct f_inst *tk, struct f_inst *tv) NEW_F_VAL; rv = f_new_inst(); rv->code = 'C'; - rv->a1.p = val; + rv->a1.p = val; val->type = T_EC; val->val.ec = ec; } @@ -297,8 +297,9 @@ CF_KEYWORDS(FUNCTION, PRINT, PRINTN, UNSET, RETURN, %type pair_atom ec_expr %type pair_item ec_item set_item switch_item set_items switch_items switch_body %type fprefix_set -%type set_atom switch_atom fprefix fprefix_s fipa -%type decls declsn one_decl function_params +%type set_atom switch_atom fipa +%type fprefix +%type decls declsn one_decl function_params %type bgp_path bgp_path_tail1 bgp_path_tail2 CF_GRAMMAR @@ -323,7 +324,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; } @@ -342,7 +343,7 @@ type: $$ = T_SET; break; - case T_PREFIX: + case T_NET: $$ = T_PREFIX_SET; break; @@ -477,7 +478,7 @@ block: * Complex types, their bison value is struct f_val */ fipa: - ipa_raw %prec PREFIX_DUMMY { $$.type = T_IP; $$.val.px.ip = $1; } + ipa_raw %prec PREFIX_DUMMY { $$.type = T_IP; $$.val.ip = $1; } ; @@ -572,26 +573,20 @@ switch_items: | switch_items ',' switch_item { $$ = f_merge_items($1, $3); } ; -fprefix_s: - ipa_raw '/' NUM %prec '/' { - if (($3 < 0) || ($3 > (ipa_is_ip4($1) ? IP4_MAX_PREFIX_LENGTH : IP6_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 <= (ipa_is_ip4($1.val.px.ip) ? IP4_MAX_PREFIX_LENGTH : IP6_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.n.pxlen; $$.hi = $1.n.pxlen; } + | net_ip '+' { $$.net = $1; $$.lo = $1.n.pxlen; $$.hi = net_max_prefix_length[$1.n.type]; } + | net_ip '-' { $$.net = $1; $$.lo = 0; $$.hi = $1.n.pxlen; } + | net_ip '{' NUM ',' NUM '}' { + $$.net = $1; $$.lo = $3; $$.hi = $5; + if ((0 > $3) || ($3 > $5) || ($5 > net_max_prefix_length[$1.n.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.n), $1.lo, $1.hi); } + | fprefix_set ',' fprefix { $$ = $1; trie_add_prefix($$, &($3.net.n), $3.lo, $3.hi); } ; switch_body: /* EMPTY */ { $$ = NULL; } @@ -602,7 +597,7 @@ switch_body: /* EMPTY */ { $$ = NULL; } t->data = $4; $$ = f_merge_items($1, $2); } - | switch_body ELSECOL cmds { + | switch_body ELSECOL cmds { struct f_tree *t = f_new_tree(); t->from.type = t->to.type = T_VOID; t->right = t; @@ -642,8 +637,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; } + | fipa { NEW_F_VAL; $$ = f_new_inst(); $$->code = 'C'; $$->a1.p = val; *val = $1; } + | net_any { 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; } @@ -706,7 +701,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; } diff --git a/filter/filter.c b/filter/filter.c index 0e17a8e5..3859a185 100644 --- a/filter/filter.c +++ b/filter/filter.c @@ -90,17 +90,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); } /** * val_compare - compare two values @@ -114,8 +105,6 @@ u64_cmp(u64 i1, u64 i2) 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; @@ -124,10 +113,10 @@ val_compare(struct f_val v1, struct f_val v2) #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); + 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); #endif debug( "Types do not match in val_compare\n" ); @@ -146,11 +135,9 @@ val_compare(struct f_val v1, struct f_val v2) case T_EC: return u64_cmp(v1.val.ec, v2.val.ec); 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: @@ -209,24 +196,6 @@ 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 = ipa_is_ip4(px->ip) ? IP4_MAX_PREFIX_LENGTH : IP6_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) { @@ -385,8 +354,8 @@ val_in_range(struct f_val v1, struct f_val v2) 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)); + if (val_is_ip4(v1) && (v2.type == T_CLIST)) + return int_set_contains(v2.val.ad, ipa_to_u32(v1.val.ip)); #endif if ((v1.type == T_EC) && (v2.type == T_ECLIST)) @@ -395,14 +364,14 @@ 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; @@ -437,8 +406,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; @@ -630,8 +599,8 @@ interpret(struct f_inst *what) } #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 @@ -715,9 +684,10 @@ interpret(struct f_inst *what) if ((sym->class != (SYM_VARIABLE | v2.type)) && (v2.type != T_VOID)) { #ifndef IPV6 /* 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 @@ -790,10 +760,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 = net_prefix((*f_rte)->net->n.addr); - res.val.px.len = net_pxlen((*f_rte)->net->n.addr); 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; @@ -820,12 +789,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" ); @@ -908,7 +877,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; @@ -958,8 +927,8 @@ interpret(struct f_inst *what) 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 @@ -978,7 +947,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: @@ -1053,7 +1022,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; @@ -1062,14 +1031,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; @@ -1135,7 +1100,7 @@ interpret(struct f_inst *what) { ip_addr mask = ipa_mkmask(v2.val.i); res.type = T_IP; - res.val.px.ip = ipa_and(mask, v1.val.px.ip); + res.val.ip = ipa_and(mask, v1.val.ip); } break; @@ -1195,7 +1160,7 @@ interpret(struct f_inst *what) #ifndef IPV6 /* IP->Quad implicit conversion */ else if (v2.type == T_IP) - n = ipa_to_u32(v2.val.px.ip); + n = ipa_to_u32(v2.val.ip); #endif else if ((v2.type == T_SET) && clist_set_type(v2.val.t, &dummy)) arg_set = 1; @@ -1284,7 +1249,7 @@ interpret(struct f_inst *what) 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; @@ -1292,8 +1257,7 @@ interpret(struct f_inst *what) else { ACCESS_RTE; - v1.val.px.ip = net_prefix((*f_rte)->net->n.addr); - v1.val.px.len = net_pxlen((*f_rte)->net->n.addr); + 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 */ @@ -1310,7 +1274,8 @@ interpret(struct f_inst *what) runtime("Missing ROA table"); res.type = T_ENUM_ROA; - res.val.i = roa_check(rtc->table, v1.val.px.ip, v1.val.px.len, as); + res.val.i = ROA_UNKNOWN; + // XXXX res.val.i = roa_check_net(rtc->table, &v1.val.net, as); break; default: diff --git a/filter/filter.h b/filter/filter.h index e59c8226..4e8293c5 100644 --- a/filter/filter.h +++ b/filter/filter.h @@ -39,13 +39,8 @@ struct f_inst_roa_check { }; 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_union net; + u8 lo, hi; }; struct f_val { @@ -53,8 +48,8 @@ struct f_val { union { uint i; u64 ec; - /* 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; @@ -81,28 +76,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, 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; @@ -163,7 +141,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 */ @@ -176,12 +154,12 @@ void val_format(struct f_val v, buffer *buf); #define T_PREFIX_SET 0x81 -#define SA_FROM 1 -#define SA_GW 2 -#define SA_NET 3 -#define SA_PROTO 4 -#define SA_SOURCE 5 -#define SA_SCOPE 6 +#define SA_FROM 1 +#define SA_GW 2 +#define SA_NET 3 +#define SA_PROTO 4 +#define SA_SOURCE 5 +#define SA_SCOPE 6 #define SA_CAST 7 #define SA_DEST 8 #define SA_IFNAME 9 diff --git a/filter/trie.c b/filter/trie.c index 8af9015e..9fdaac6d 100644 --- a/filter/trie.c +++ b/filter/trie.c @@ -109,12 +109,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 +123,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, 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 +150,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,17 +206,7 @@ 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 +static int trie_match_prefix(struct f_trie *t, ip_addr px, int plen) { ip_addr pmask = ipa_mkmask(plen); @@ -241,6 +241,27 @@ 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) +{ + int add = 0; + switch (n->type) { + case NET_IP4: + case NET_VPN4: 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) { diff --git a/lib/birdlib.h b/lib/birdlib.h index 16f437ef..5fec6c7a 100644 --- a/lib/birdlib.h +++ b/lib/birdlib.h @@ -35,6 +35,12 @@ #define DELTA(a,b) (((a)>=(b))?(a)-(b):(b)-(a)) #define ARRAY_SIZE(a) (sizeof(a)/sizeof(*(a))) +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); } + /* Bitfield macros */ diff --git a/lib/ip.h b/lib/ip.h index 9706b397..1834db4f 100644 --- a/lib/ip.h +++ b/lib/ip.h @@ -492,10 +492,4 @@ int ip6_pton(const char *a, ip6_addr *o); char *ip_scope_text(uint); -struct prefix { - ip_addr addr; - uint len; -}; - - #endif diff --git a/lib/net.c b/lib/net.c index 21486a9b..e2765995 100644 --- a/lib/net.c +++ b/lib/net.c @@ -58,23 +58,30 @@ net_pxmask(const net_addr *a) } } - -static inline int net_validate_ip4(const net_addr_ip4 *n) +int +net_compare(const net_addr *a, const net_addr *b) { - return (n->pxlen <= IP4_MAX_PREFIX_LENGTH) && - ip4_zero(ip4_and(n->prefix, ip4_not(ip4_mkmask(n->pxlen)))); -} + if (a->type != b->type) + return uint_cmp(a->type, b->type); -static inline int net_validate_ip6(const net_addr_ip6 *n) -{ - return (n->pxlen <= IP6_MAX_PREFIX_LENGTH) && - ip6_zero(ip6_and(n->prefix, ip6_not(ip6_mkmask(n->pxlen)))); + switch (a->type) + { + case NET_IP4: + return net_compare_ip4((const net_addr_ip4 *) a, (const net_addr_ip4 *) b); + case NET_IP6: + return net_compare_ip6((const net_addr_ip6 *) a, (const net_addr_ip6 *) b); + case NET_VPN4: + return net_compare_vpn4((const net_addr_vpn4 *) a, (const net_addr_vpn4 *) b); + case NET_VPN6: + return net_compare_vpn6((const net_addr_vpn6 *) a, (const net_addr_vpn6 *) b); + } + return 0; } int net_validate(const net_addr *N) { - switch (a->type) + switch (N->type) { case NET_IP4: case NET_VPN4: diff --git a/lib/net.h b/lib/net.h index bc1233bf..c9ca349f 100644 --- a/lib/net.h +++ b/lib/net.h @@ -162,6 +162,21 @@ static inline int net_zero_vpn6(const net_addr_vpn6 *a) { return !a->pxlen && ip6_zero(a->prefix) && !a->rd; } +static inline int net_compare_ip4(const net_addr_ip4 *a, const net_addr_ip4 *b) +{ return ip4_compare(a->prefix, b->prefix) ?: uint_cmp(a->pxlen, b->pxlen); } + +static inline int net_compare_ip6(const net_addr_ip6 *a, const net_addr_ip6 *b) +{ return ip6_compare(a->prefix, b->prefix) ?: uint_cmp(a->pxlen, b->pxlen); } + +static inline int net_compare_vpn4(const net_addr_vpn4 *a, const net_addr_vpn4 *b) +{ return u64_cmp(a->rd, b->rd) ?: ip4_compare(a->prefix, b->prefix) ?: uint_cmp(a->pxlen, b->pxlen); } + +static inline int net_compare_vpn6(const net_addr_vpn6 *a, const net_addr_vpn6 *b) +{ return u64_cmp(a->rd, b->rd) ?: ip6_compare(a->prefix, b->prefix) ?: uint_cmp(a->pxlen, b->pxlen); } + +int net_compare(const net_addr *a, const net_addr *b); + + static inline void net_copy(net_addr *dst, const net_addr *src) { memcpy(dst, src, src->length); } @@ -195,6 +210,21 @@ static inline u32 net_hash_vpn6(const net_addr_vpn6 *n) { return ip6_hash(n->prefix) ^ ((u32) n->pxlen << 26) ^ u64_hash(n->rd); } +static inline int net_validate_ip4(const net_addr_ip4 *n) +{ + return (n->pxlen <= IP4_MAX_PREFIX_LENGTH) && + ip4_zero(ip4_and(n->prefix, ip4_not(ip4_mkmask(n->pxlen)))); +} + +static inline int net_validate_ip6(const net_addr_ip6 *n) +{ + return (n->pxlen <= IP6_MAX_PREFIX_LENGTH) && + ip6_zero(ip6_and(n->prefix, ip6_not(ip6_mkmask(n->pxlen)))); +} + +int net_validate(const net_addr *N); + + static inline void net_normalize_ip4(net_addr_ip4 *n) { n->prefix = ip4_and(n->prefix, ip4_mkmask(n->pxlen)); } @@ -203,7 +233,6 @@ static inline void net_normalize_ip6(net_addr_ip6 *n) void net_normalize(net_addr *N); -int net_validate(const net_addr *N); int net_classify(const net_addr *N); int net_format(const net_addr *N, char *buf, int buflen); diff --git a/nest/config.Y b/nest/config.Y index e5a6e0bb..612e4d40 100644 --- a/nest/config.Y +++ b/nest/config.Y @@ -98,10 +98,8 @@ idval: | SYM { if ($1->class == (SYM_CONSTANT | T_INT) || $1->class == (SYM_CONSTANT | T_QUAD)) $$ = SYM_VAL($1).i; -#ifndef IPV6 - else if ($1->class == (SYM_CONSTANT | T_IP)) - $$ = ipa_to_u32(SYM_VAL($1).px.ip); -#endif + else if (($1->class == (SYM_CONSTANT | T_IP)) && ipa_is_ip4(SYM_VAL($1).ip)) + $$ = ipa_to_u32(SYM_VAL($1).ip); else cf_error("Number of IPv4 address constant expected"); } diff --git a/nest/rt-table.c b/nest/rt-table.c index 05073ce0..6ac659a8 100644 --- a/nest/rt-table.c +++ b/nest/rt-table.c @@ -2293,13 +2293,14 @@ rt_update_hostentry(rtable *tab, struct hostentry *he) he->igp_metric = rt_get_igp_metric(e); } - /* XXXX */ done: /* Add a prefix range to the trie */ + /* XXXX if (ipa_is_ip4(he->addr)) trie_add_prefix(tab->hostcache->trie, he->addr, IP4_MAX_PREFIX_LENGTH, pxlen, IP4_MAX_PREFIX_LENGTH); else trie_add_prefix(tab->hostcache->trie, he->addr, IP6_MAX_PREFIX_LENGTH, pxlen, IP6_MAX_PREFIX_LENGTH); + */ rta_free(old_src); return old_src != he->src;