Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
labs
BIRD Internet Routing Daemon
Commits
ead7b8f4
Commit
ead7b8f4
authored
Mar 22, 2017
by
Jan Moskyto Matejka
Browse files
Merge branch 'nexthop-merged' into int-new
parents
da3cf9ea
61e501da
Changes
41
Hide whitespace changes
Inline
Side-by-side
conf/cf-lex.l
View file @
ead7b8f4
...
...
@@ -123,6 +123,60 @@ include ^{WHITE}*include{WHITE}*\".*\"{WHITE}*;
cf_include(start, end-start);
}
[02]:{DIGIT}+:{DIGIT}+ {
unsigned long int l, len1, len2;
char *e;
if (yytext[0] == '0')
{
cf_lval.i64 = 0;
len1 = 16;
len2 = 32;
}
else
{
cf_lval.i64 = 2ULL << 48;
len1 = 32;
len2 = 16;
}
errno = 0;
l = strtoul(yytext+2, &e, 10);
if (e && (*e != ':') || (errno == ERANGE) || (l >> len1))
cf_error("ASN out of range");
cf_lval.i64 |= ((u64) l) << len2;
errno = 0;
l = strtoul(e+1, &e, 10);
if (e && *e || (errno == ERANGE) || (l >> len2))
cf_error("Number out of range");
cf_lval.i64 |= l;
return VPN_RD;
}
1:{DIGIT}+\.{DIGIT}+\.{DIGIT}+\.{DIGIT}+:{DIGIT}+ {
unsigned long int l;
ip4_addr ip4;
char *e;
cf_lval.i64 = 1ULL << 48;
e = strchr(yytext+2, ':');
*e++ = '\0';
if (!ip4_pton(yytext+2, &ip4))
cf_error("Invalid IPv4 address %s in Route Distinguisher", yytext+2);
cf_lval.i64 |= ((u64) ip4_to_u32(ip4)) << 16;
errno = 0;
l = strtoul(e, &e, 10);
if (e && *e || (errno == ERANGE) || (l >> 16))
cf_error("Number out of range");
cf_lval.i64 |= l;
return VPN_RD;
}
{DIGIT}+\.{DIGIT}+\.{DIGIT}+\.{DIGIT}+ {
if (!ip4_pton(yytext, &cf_lval.ip4))
cf_error("Invalid IPv4 address %s", yytext);
...
...
conf/confbase.Y
View file @
ead7b8f4
...
...
@@ -38,6 +38,7 @@ CF_DECLS
%union {
int i;
u32 i32;
u64 i64;
ip_addr a;
ip4_addr ip4;
ip6_addr ip6;
...
...
@@ -64,6 +65,7 @@ CF_DECLS
struct proto_spec ps;
struct channel_limit cl;
struct timeformat *tf;
mpls_label_stack *mls;
}
%token END CLI_MARKER INVALID_TOKEN ELSECOL DDOT
...
...
@@ -72,6 +74,7 @@ CF_DECLS
%token <i> NUM ENUM
%token <ip4> IP4
%token <ip6> IP6
%token <i64> VPN_RD
%token <s> SYM
%token <t> TEXT
%type <iface> ipa_scope
...
...
@@ -81,7 +84,8 @@ CF_DECLS
%type <time> datetime
%type <a> ipa
%type <net> net_ip4_ net_ip6_ net_ip6 net_ip_ net_ip net_or_ipa
%type <net_ptr> net_ net_any net_roa4_ net_roa6_ net_roa_
%type <net_ptr> net_ net_any net_vpn4_ net_vpn6_ net_vpn_ net_roa4_ net_roa6_ net_roa_
%type <mls> label_stack_start label_stack
%type <t> text opttext
...
...
@@ -93,7 +97,7 @@ CF_DECLS
%left '!'
%nonassoc '.'
CF_KEYWORDS(DEFINE, ON, OFF, YES, NO, S, MS, US, PORT)
CF_KEYWORDS(DEFINE, ON, OFF, YES, NO, S, MS, US, PORT
, VPN
)
CF_GRAMMAR
...
...
@@ -196,6 +200,18 @@ net_ip6_: IP6 '/' NUM
cf_error("Invalid IPv6 prefix");
};
net_vpn4_: VPN_RD net_ip4_
{
$$ = cfg_alloc(sizeof(net_addr_vpn4));
net_fill_vpn4($$, net4_prefix(&$2), net4_pxlen(&$2), $1);
}
net_vpn6_: VPN_RD net_ip6_
{
$$ = cfg_alloc(sizeof(net_addr_vpn6));
net_fill_vpn6($$, net6_prefix(&$2), net6_pxlen(&$2), $1);
}
net_roa4_: net_ip4_ MAX NUM AS NUM
{
$$ = cfg_alloc(sizeof(net_addr_roa4));
...
...
@@ -213,10 +229,12 @@ net_roa6_: net_ip6_ MAX NUM AS NUM
};
net_ip_: net_ip4_ | net_ip6_ ;
net_vpn_: net_vpn4_ | net_vpn6_ ;
net_roa_: net_roa4_ | net_roa6_ ;
net_:
net_ip_ { $$ = cfg_alloc($1.length); net_copy($$, &($1)); }
| net_vpn_
| net_roa_
| net_flow_
;
...
...
@@ -254,6 +272,8 @@ net_any:
net_or_ipa:
net_ip4_
| net_ip6_
| net_vpn4_ { $$ = *$1; }
| net_vpn6_ { $$ = *$1; }
| IP4 { net_fill_ip4(&($$), $1, IP4_MAX_PREFIX_LENGTH); }
| IP6 { net_fill_ip6(&($$), $1, IP6_MAX_PREFIX_LENGTH); }
| SYM {
...
...
@@ -266,6 +286,22 @@ net_or_ipa:
}
;
label_stack_start: NUM
{
$$ = cfg_allocz(sizeof(mpls_label_stack));
$$->len = 1;
$$->stack[0] = $1;
};
label_stack:
label_stack_start
| label_stack '/' NUM {
if ($1->len >= MPLS_MAX_LABEL_STACK)
cf_error("Too many labels in stack");
$1->stack[$1->len++] = $3;
$$ = $1;
}
;
datetime:
TEXT {
...
...
configure.in
View file @
ead7b8f4
...
...
@@ -57,6 +57,7 @@ if test "$ac_test_CFLAGS" != set ; then
bird_cflags_default=yes
fi
AC_PROG_CC
AC_PROG_CC_C99
if test -z "$GCC" ; then
AC_MSG_ERROR([This program requires the GNU C Compiler.])
...
...
doc/Makefile
View file @
ead7b8f4
...
...
@@ -36,8 +36,8 @@ $(o)%.ps: $(o)%.dvi
dvips
-D600
-ta4
-o
$@
$<
$(o)%.pdf
:
$(o)%.tex
pdflatex
-output-directory
=
$(
dir
$@
)
$<
pdflatex
-output-directory
=
$(
dir
$@
)
$<
TEXINPUTS
=
$(TEXINPUTS)
:
$
(
doc-srcdir
)
/tex
pdflatex
-output-directory
=
$(
dir
$@
)
$<
TEXINPUTS
=
$(TEXINPUTS)
:
$
(
doc-srcdir
)
/tex
pdflatex
-output-directory
=
$(
dir
$@
)
$<
$(o)%.txt
:
$(o)%.sgml
cd
$(
dir
$@
)
&&
$(sgml2)
txt
$(
notdir
$<
)
...
...
doc/bird.sgml
View file @
ead7b8f4
...
...
@@ -1186,20 +1186,41 @@ foot).
<tag><label id="type-ip">ip</tag>
This type can hold a single IP address. Depending on the compile-time
configuration of BIRD you are using, it is either an IPv4 or IPv6
address. IP addresses are written in the standard notation
address; this may be checked by <cf>.is_ip4</cf> which returns <cf/bool/.
IP addresses are written in the standard notation
(<cf/10.20.30.40/ or <cf/fec0:3:4::1/). You can apply special operator
<cf>.mask(<M>num</M>)</cf> on values of type ip. It masks out all but
first <cf><M>num</M></cf> bits from the IP address. So
<cf/1.2.3.4.mask(8) = 1.0.0.0/ is true.
<tag><label id="type-prefix">prefix</tag>
This type can hold a network prefix consisting of IP address and prefix
length. Prefix literals are written as <cf><m/ipaddress//<m/pxlen/</cf>,
This type can hold a network prefix consisting of IP address, prefix
length and several other values. This is the key in route tables.
Prefixes may be of several types, which can be determined by the special
operator <cf/.type/. The type may be:
<cf/NET_IP4/ and <cf/NET_IP6/ prefixes hold an IP prefix. The literals
are written as <cf><m/ipaddress//<m/pxlen/</cf>,
or <cf><m>ipaddress</m>/<m>netmask</m></cf>. There are two special
operators on prefixes: <cf/.ip/ which extracts the IP address from
the
pair, and <cf/.len/, which separates prefix length from the pair.
operators on
IP
prefixes: <cf/.ip/ which extracts the IP address from
the
pair, and <cf/.len/, which separates prefix length from the pair.
So <cf>1.2.0.0/16.len = 16</cf> is true.
<cf/NET_VPN4/ and <cf/NET_VPN6/ prefixes hold an IP prefix with VPN
Route Distinguisher (<rfc id="4364">). They support the same special
operators as IP prefixes, and also <cf/.rd/ which extracts the Route
Distinguisher. Their literals are written
as <cf><m/vpnrd/ <m/ipprefix/</cf>
<cf/NET_ROA4/ and <cf/NET_ROA6/ prefixes hold an IP prefix range
together with an ASN. They support the same special operators as IP
prefixes, and also <cf/.maxlen/ which extracts maximal prefix length,
and <cf/.asn/ which extracts the ASN.
<cf/NET_FLOW4/ and <cf/NET_FLOW6/ hold an IP prefix together with a
flowspec rule. Filters currently don't support flowspec parsing.
<tag><label id="type-ec">ec</tag>
This is a specialized type used to represent BGP extended community
values. It is essentially a 64bit value, literals of this type are
...
...
@@ -4160,12 +4181,12 @@ return packets as undeliverable if they are in your IP block, you don't have any
specific destination for them and you don't want to send them out through the
default route to prevent routing loops).
<p>There are f
ive
types of static routes: `classical' routes telling to forward
packets to a neighboring router
, multipath routes specifying several (possibly
weighted) neighboring routers,
device routes specifying forwarding to hosts on a
directly connected network,
recursive routes computing their nexthops by doing
route table lookups for a
given IP, and special routes (sink, blackhole etc.)
which specify a special
action to be done instead of forwarding the packet.
<p>There are f
our
types of static routes: `classical' routes telling to forward
packets to a neighboring router
(single path or multipath, possibly weighted),
device routes specifying forwarding to hosts on a
directly connected network,
recursive routes computing their nexthops by doing
route table lookups for a
given IP, and special routes (sink, blackhole etc.)
which specify a special
action to be done instead of forwarding the packet.
<p>When the particular destination is not available (the interface is down or
the next hop of the route is not a neighbor at the moment), Static just
...
...
@@ -4194,14 +4215,14 @@ definition of the protocol contains mainly a list of static routes.
<p>Route definitions (each may also contain a block of per-route options):
<descrip>
<tag><label id="static-route-via-ip">route <m/prefix/ via <m/ip/</tag>
Static route through a neighboring router. For link-local next hops,
<tag><label id="static-route-via-ip">route <m/prefix/ via <m/ip/
[mpls <m/num/[/<m/num/[/<m/num/[...]]]]
</tag>
Static
single path
route through a neighboring router. For link-local next hops,
interface can be specified as a part of the address (e.g.,
<cf/via fe80::1234%eth0/).
<cf/via fe80::1234%eth0/).
MPLS labels should be specified in outer-first order.
<tag><label id="static-route-via-mpath">route <m/prefix/
multipath
via <m/ip/ [weight <m/num/] [bfd <m/switch/] [via
<m/
...
/
]</tag>
<tag><label id="static-route-via-mpath">route <m/prefix/ via <m/ip/
[mpls <m/num/[/<m/num/[/<m/num/[...]]]]
[weight <m/num/] [bfd <m/switch/] [via ...]</tag>
Static multipath route. Contains several nexthops (gateways), possibly
with their weights.
with their weights
and MPLS labels
.
<tag><label id="static-route-via-iface">route <m/prefix/ via <m/"interface"/</tag>
Static device route through an interface to hosts on a directly
...
...
filter/config.Y
View file @
ead7b8f4
...
...
@@ -393,13 +393,14 @@ CF_DECLS
CF_KEYWORDS(FUNCTION, PRINT, PRINTN, UNSET, RETURN,
ACCEPT, REJECT, ERROR, QUITBIRD,
INT, BOOL, IP, PREFIX, PAIR, QUAD, EC, LC,
INT, BOOL, IP,
TYPE,
PREFIX,
RD,
PAIR, QUAD, EC, LC,
SET, STRING, BGPMASK, BGPPATH, CLIST, ECLIST, LCLIST,
IF, THEN, ELSE, CASE,
TRUE, FALSE, RT, RO, UNKNOWN, GENERIC,
FROM, GW, NET, MASK, PROTO, SOURCE, SCOPE,
CAST,
DEST, IFNAME, IFINDEX,
FROM, GW, NET, MASK, PROTO, SOURCE, SCOPE, DEST, IFNAME, IFINDEX,
PREFERENCE,
ROA_CHECK, ASN,
IS_V4, IS_V6,
LEN, MAXLEN,
DEFINED,
ADD, DELETE, CONTAINS, RESET,
...
...
@@ -460,6 +461,7 @@ type:
INT { $$ = T_INT; }
| BOOL { $$ = T_BOOL; }
| IP { $$ = T_IP; }
| RD { $$ = T_RD; }
| PREFIX { $$ = T_NET; }
| PAIR { $$ = T_PAIR; }
| QUAD { $$ = T_QUAD; }
...
...
@@ -786,6 +788,7 @@ constant:
| 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; }
| VPN_RD { NEW_F_VAL; $$ = f_new_inst(); $$->code = 'C'; val->type = T_RD; val->val.ec = $1; $$->a1.p = val; }
| 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; }
...
...
@@ -854,7 +857,6 @@ static_attr:
| 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; }
| CAST { $$ = f_new_inst(); $$->aux = T_ENUM_RTC; $$->a2.i = SA_CAST; }
| DEST { $$ = f_new_inst(); $$->aux = T_ENUM_RTD; $$->a2.i = SA_DEST; $$->a1.i = 1; }
| IFNAME { $$ = f_new_inst(); $$->aux = T_STRING; $$->a2.i = SA_IFNAME; }
| IFINDEX { $$ = f_new_inst(); $$->aux = T_INT; $$->a2.i = SA_IFINDEX; }
...
...
@@ -889,7 +891,10 @@ term:
| rtadot dynamic_attr { $$ = $2; $$->code = P('e','a'); }
| term '.' IS_V4 { $$ = f_new_inst(); $$->code = P('I','i'); $$->a1.p = $1; }
| term '.' TYPE { $$ = f_new_inst(); $$->code = 'T'; $$->a1.p = $1; }
| term '.' IP { $$ = f_new_inst(); $$->code = P('c','p'); $$->a1.p = $1; $$->aux = T_IP; }
| term '.' RD { $$ = f_new_inst(); $$->code = P('R','D'); $$->a1.p = $1; $$->aux = T_RD; }
| term '.' LEN { $$ = f_new_inst(); $$->code = 'L'; $$->a1.p = $1; }
| term '.' MAXLEN { $$ = f_new_inst(); $$->code = P('R','m'); $$->a1.p = $1; }
| term '.' ASN { $$ = f_new_inst(); $$->code = P('R','a'); $$->a1.p = $1; }
...
...
filter/filter.c
View file @
ead7b8f4
...
...
@@ -151,6 +151,7 @@ val_compare(struct f_val v1, struct f_val v2)
case
T_QUAD
:
return
uint_cmp
(
v1
.
val
.
i
,
v2
.
val
.
i
);
case
T_EC
:
case
T_RD
:
return
u64_cmp
(
v1
.
val
.
ec
,
v2
.
val
.
ec
);
case
T_LC
:
return
lcomm_cmp
(
v1
.
val
.
lc
,
v2
.
val
.
lc
);
...
...
@@ -515,6 +516,7 @@ val_format(struct f_val v, buffer *buf)
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
;
case
T_LC
:
lc_format
(
buf2
,
v
.
val
.
lc
);
buffer_print
(
buf
,
"%s"
,
buf2
);
return
;
case
T_RD
:
rd_format
(
v
.
val
.
ec
,
buf2
,
1024
);
buffer_print
(
buf
,
"%s"
,
buf2
);
return
;
case
T_PREFIX_SET
:
trie_format
(
v
.
val
.
ti
,
buf
);
return
;
case
T_SET
:
tree_format
(
v
.
val
.
t
,
buf
);
return
;
case
T_ENUM
:
buffer_print
(
buf
,
"(enum %x)%u"
,
v
.
type
,
v
.
val
.
i
);
return
;
...
...
@@ -815,6 +817,25 @@ interpret(struct f_inst *what)
res
.
type
=
T_BOOL
;
res
.
val
.
i
=
(
v1
.
type
!=
T_VOID
);
break
;
case
'T'
:
ONEARG
;
switch
(
v1
.
type
)
{
case
T_NET
:
res
.
type
=
T_ENUM_NETTYPE
;
res
.
val
.
i
=
v1
.
val
.
net
->
type
;
break
;
default:
runtime
(
"Can't determine type of this item"
);
}
break
;
case
P
(
'I'
,
'i'
):
ONEARG
;
if
(
v1
.
type
!=
T_IP
)
runtime
(
"IP version check needs an IP address"
);
res
.
type
=
T_BOOL
;
res
.
val
.
i
=
ipa_is_ip4
(
v1
.
val
.
ip
);
break
;
/* Set to indirect value, a1 = variable, a2 = value */
case
's'
:
...
...
@@ -900,15 +921,14 @@ interpret(struct f_inst *what)
switch
(
what
->
a2
.
i
)
{
case
SA_FROM
:
res
.
val
.
ip
=
rta
->
from
;
break
;
case
SA_GW
:
res
.
val
.
ip
=
rta
->
gw
;
break
;
case
SA_GW
:
res
.
val
.
ip
=
rta
->
nh
.
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
;
case
SA_CAST
:
res
.
val
.
i
=
rta
->
cast
;
break
;
case
SA_DEST
:
res
.
val
.
i
=
rta
->
dest
;
break
;
case
SA_IFNAME
:
res
.
val
.
s
=
rta
->
iface
?
rta
->
iface
->
name
:
""
;
break
;
case
SA_IFINDEX
:
res
.
val
.
i
=
rta
->
iface
?
rta
->
iface
->
index
:
0
;
break
;
case
SA_IFNAME
:
res
.
val
.
s
=
rta
->
nh
.
iface
?
rta
->
nh
.
iface
->
name
:
""
;
break
;
case
SA_IFINDEX
:
res
.
val
.
i
=
rta
->
nh
.
iface
?
rta
->
nh
.
iface
->
index
:
0
;
break
;
default:
bug
(
"Invalid static attribute access (%x)"
,
res
.
type
);
...
...
@@ -938,10 +958,10 @@ interpret(struct f_inst *what)
if
(
!
n
||
(
n
->
scope
==
SCOPE_HOST
))
runtime
(
"Invalid gw address"
);
rta
->
dest
=
RTD_
ROUTER
;
rta
->
gw
=
ip
;
rta
->
iface
=
n
->
iface
;
rta
->
next
hops
=
NULL
;
rta
->
dest
=
RTD_
UNICAST
;
rta
->
nh
.
gw
=
ip
;
rta
->
nh
.
iface
=
n
->
iface
;
rta
->
n
h
.
n
ext
=
NULL
;
rta
->
hostentry
=
NULL
;
}
break
;
...
...
@@ -956,9 +976,9 @@ interpret(struct f_inst *what)
runtime
(
"Destination can be changed only to blackhole, unreachable or prohibit"
);
rta
->
dest
=
i
;
rta
->
gw
=
IPA_NONE
;
rta
->
iface
=
NULL
;
rta
->
next
hops
=
NULL
;
rta
->
nh
.
gw
=
IPA_NONE
;
rta
->
nh
.
iface
=
NULL
;
rta
->
n
h
.
n
ext
=
NULL
;
rta
->
hostentry
=
NULL
;
break
;
...
...
@@ -1210,6 +1230,15 @@ interpret(struct f_inst *what)
res
.
type
=
T_IP
;
res
.
val
.
ip
=
net_prefix
(
v1
.
val
.
net
);
break
;
case
P
(
'R'
,
'D'
):
ONEARG
;
if
(
v1
.
type
!=
T_NET
)
runtime
(
"Prefix expected"
);
if
(
!
net_is_vpn
(
v1
.
val
.
net
))
runtime
(
"VPN address expected"
);
res
.
type
=
T_RD
;
res
.
val
.
ec
=
net_rd
(
v1
.
val
.
net
);
break
;
case
P
(
'a'
,
'f'
):
/* Get first ASN from AS PATH */
ONEARG
;
if
(
v1
.
type
!=
T_PATH
)
...
...
@@ -1582,6 +1611,8 @@ i_same(struct f_inst *f1, struct f_inst *f2)
case
P
(
'!'
,
'~'
):
case
'~'
:
TWOARGS
;
break
;
case
P
(
'd'
,
'e'
):
ONEARG
;
break
;
case
'T'
:
ONEARG
;
break
;
case
P
(
'n'
,
'T'
):
break
;
case
P
(
'm'
,
'l'
):
TWOARGS
;
...
...
@@ -1647,6 +1678,7 @@ i_same(struct f_inst *f1, struct f_inst *f2)
case
'r'
:
ONEARG
;
break
;
case
P
(
'c'
,
'p'
):
ONEARG
;
break
;
case
P
(
'R'
,
'D'
):
ONEARG
;
break
;
case
P
(
'c'
,
'a'
):
/* Call rewriting trickery to avoid exponential behaviour */
ONEARG
;
if
(
!
i_same
(
f1
->
a2
.
p
,
f2
->
a2
.
p
))
...
...
filter/filter.h
View file @
ead7b8f4
...
...
@@ -146,6 +146,8 @@ void val_format(struct f_val v, buffer *buf);
#define T_ENUM_RTC 0x33
#define T_ENUM_RTD 0x34
#define T_ENUM_ROA 0x35
#define T_ENUM_NETTYPE 0x36
/* new enums go here */
#define T_ENUM_EMPTY 0x3f
/* Special hack for atomic_aggr */
...
...
@@ -162,6 +164,7 @@ void val_format(struct f_val v, buffer *buf);
#define T_ECLIST 0x27
/* Extended community list */
#define T_LC 0x28
/* Large community value, lcomm */
#define T_LCLIST 0x29
/* Large community list */
#define T_RD 0x2a
/* Route distinguisher for VPN addresses */
#define T_RETURN 0x40
#define T_SET 0x80
...
...
@@ -174,10 +177,9 @@ void val_format(struct f_val v, buffer *buf);
#define SA_PROTO 4
#define SA_SOURCE 5
#define SA_SCOPE 6
#define SA_CAST 7
#define SA_DEST 8
#define SA_IFNAME 9
#define SA_IFINDEX 10
#define SA_DEST 7
#define SA_IFNAME 8
#define SA_IFINDEX 9
struct
f_tree
{
...
...
filter/test.conf
View file @
ead7b8f4
...
...
@@ -312,15 +312,18 @@ function t_ip()
ip
p
;
{
p
=
127
.
1
.
2
.
3
;
bt_assert
(
p
.
is_v4
);
bt_assert
(
p
.
mask
(
8
) =
127
.
0
.
0
.
0
);
bt_assert
(
1
.
2
.
3
.
4
=
1
.
2
.
3
.
4
);
bt_assert
(
1
.
2
.
3
.
4
=
onetwo
);
bt_assert
(
format
(
p
) =
"127.1.2.3"
);
p
= ::
fffe
:
6
:
c0c
:
936
d
:
88
c7
:
35
d3
;
bt_assert
(!
p
.
is_v4
);
bt_assert
(
format
(
p
) =
"::fffe:6:c0c:936d:88c7:35d3"
);
p
=
1234
:
5678
::;
bt_assert
(!
p
.
is_v4
);
bt_assert
(
p
.
mask
(
24
) =
1234
:
5600
::);
}
...
...
@@ -444,8 +447,8 @@ function test_pxset(prefix set pxs)
function
t_prefix_set
()
prefix
set
pxs
;
{
pxs
= [
1
.
2
.
0
.
0
/
16
,
1
.
4
.
0
.
0
/
16
+];
bt_assert
(
format
(
pxs
) =
"[1.2.0.0/112{::0.1.0.0}, 1.4.0.0/112{::0.1.255.255}]"
);
pxs
= [
1
.
2
.
0
.
0
/
16
,
1
.
4
.
0
.
0
/
16
+
,
44
.
66
.
88
.
64
/
30
{
24
,
28
},
12
.
34
.
56
.
0
/
24
{
8
,
16
}
];
bt_assert
(
format
(
pxs
) =
"[1.2.0.0/112{::0.1.0.0}, 1.4.0.0/112{::0.1.255.255}
, 12.34.0.0/112{::1.255.0.0}, 44.66.88.64/124{::1f0}
]"
);
bt_assert
(
1
.
2
.
0
.
0
/
16
~
pxs
);
bt_assert
(
1
.
4
.
0
.
0
/
16
~
pxs
);
bt_assert
(
1
.
4
.
0
.
0
/
18
~
pxs
);
...
...
@@ -1165,12 +1168,20 @@ int j;
accept
"ok I take that"
;
}
filter
roa_filter
{
if
net
~ [
10
.
0
.
0
.
0
/
8
{
16
,
24
},
2000
::/
3
{
16
,
96
} ]
then
{
accept
;
}
reject
;
}
roa4
table
r4
;
roa6
table
r6
;
protocol
static
{
roa4
{
table
r4
; };
roa4
{
table
r4
;
import
filter
roa_filter
;
};
route
10
.
110
.
0
.
0
/
16
max
16
as
1000
blackhole
;
route
10
.
120
.
0
.
0
/
16
max
24
as
1000
blackhole
;
route
10
.
130
.
0
.
0
/
16
max
24
as
2000
blackhole
;
...
...
@@ -1179,66 +1190,124 @@ protocol static
protocol
static
{
roa6
{
table
r6
; };
roa6
{
table
r6
;
import
filter
roa_filter
;
};
route
2001
:
0
db8
:
85
a3
:
8
a2e
::/
64
max
96
as
1000
blackhole
;
}
function
test_roa_check
()
prefix
pfx
;
{
# cannot be tested in __startup(), sorry
print
"Should be true: "
,
roa_check
(
r4
,
10
.
10
.
0
.
0
/
16
,
1000
) =
ROA_UNKNOWN
,
" "
,
roa_check
(
r4
,
10
.
0
.
0
.
0
/
8
,
1000
) =
ROA_UNKNOWN
,
" "
,
roa_check
(
r4
,
10
.
110
.
0
.
0
/
16
,
1000
) =
ROA_VALID
,
" "
,
roa_check
(
r4
,
10
.
110
.
0
.
0
/
16
,
2000
) =
ROA_INVALID
,
" "
,
roa_check
(
r4
,
10
.
110
.
32
.
0
/
20
,
1000
) =
ROA_INVALID
,
" "
,
roa_check
(
r4
,
10
.
120
.
32
.
0
/
20
,
1000
) =
ROA_VALID
;
print
"Should be true: "
,
roa_check
(
r4
,
10
.
120
.
32
.
0
/
20
,
2000
) =
ROA_INVALID
,
" "
,
roa_check
(
r4
,
10
.
120
.
32
.
32
/
28
,
1000
) =
ROA_INVALID
,
" "
,
roa_check
(
r4
,
10
.
130
.
130
.
0
/
24
,
1000
) =
ROA_INVALID
,
" "
,
roa_check
(
r4
,
10
.
130
.
130
.
0
/
24
,
2000
) =
ROA_VALID
,
" "
,
roa_check
(
r4
,
10
.
130
.
30
.
0
/
24
,
3000
) =
ROA_INVALID
,
" "
,
roa_check
(
r4
,
10
.
130
.
130
.
0
/
24
,
3000
) =
ROA_VALID
;
print
"Should be true: "
,
roa_check
(
r6
,
2001
:
0
db8
:
85
a3
:
8
a2e
:
1234
::/
80
,
1000
) =
ROA_VALID
,
" "
,
roa_check
(
r6
,
2001
:
0
db8
:
85
a3
:
8
a2e
:
1234
::/
97
,
1000
) =
ROA_INVALID
,
" "
,
roa_check
(
r6
,
2001
:
0
db8
:
85
a3
:
8
a2e
::/
64
,
1000
) =
ROA_VALID
,
" "
,
roa_check
(
r6
,
2001
:
0
db8
:
85
a3
::/
48
,
1000
) =
ROA_UNKNOWN
;
print
"Should be true: "
,
roa_check
(
r4
,
10
.
10
.
0
.
0
/
16
,
1000
) =
ROA_UNKNOWN
,
" "
,
roa_check
(
r4
,
10
.
0
.
0
.
0
/
8
,
1000
) =
ROA_UNKNOWN
,
" "
,
roa_check
(
r4
,
10
.
110
.
0
.
0
/
16
,
1000
) =
ROA_VALID
,
" "
,
roa_check
(
r4
,
10
.
110
.
0
.
0
/
16
,
2000
) =
ROA_INVALID
,
" "
,
roa_check
(
r4
,
10
.
110
.
32
.
0
/
20
,
1000
) =
ROA_INVALID
,
" "
,
roa_check
(
r4
,
10
.
120
.
32
.
0
/
20
,
1000
) =
ROA_VALID
;
print
"Should be true: "
,
roa_check
(
r6
,
2001
:
0
db8
:
85
a3
:
8
a2e
:
1234
::/
80
,
1000
) =
ROA_VALID
,
" "
,
roa_check
(
r6
,
2001
:
0
db8
:
85
a3
:
8
a2e
:
1234
::/
97
,
1000
) =
ROA_INVALID
,
" "
,
roa_check
(
r6
,
2001
:
0
db8
:
85
a3
:
8
a2e
::/
64
,
1000
) =
ROA_VALID
,
" "
,
roa_check
(
r6
,
2001
:
0
db8
:
85
a3
::/
48
,
1000
) =
ROA_UNKNOWN
;
print
"Should be true: "
,
roa_check
(
r4
,
2001
:
0
db8
:
85
a3
:
8
a2e
:
1234
::/
97
,
1000
) =
ROA_INVALID
||
roa_check
(
r6
,
2001
:
0
db8
:
85
a3
:
8
a2e
:
1234
::/
97
,
1000
) =
ROA_INVALID
;
print
"Should be false: "
,
roa_check
(
r4
,
2001
:
0
db8
:
85
a3
:
8
a2e
:
1234
::/
80
,
1000
) =
ROA_INVALID
||
roa_check
(
r6
,
2001
:
0
db8
:
85
a3
:
8
a2e
:
1234
::/
80
,
1000
) =
ROA_INVALID
,
" "
,
roa_check
(
r4
,
2001
:
0
db8
:
85
a3
::/
48
,
1000
) =
ROA_INVALID
||
roa_check
(
r6
,
2001
:
0
db8
:
85
a3
::/
48
,
1000
) =
ROA_INVALID
;
print
"Should be true: "
,
10
.
130
.
130
.
0
/
24
~
0
.
0
.
0
.
0
/
0
,
" "
,
2001
:
0
db8
:
85
a3
:
8
a2e
::/
64
~ ::/
0
;
print
"Should be false: "
,
10
.
130
.
130
.
0
/
24
~ ::/
0
,
" "
,
2001
:
0
db8
:
85
a3
:
8
a2e
::/
64
~
0
.
0
.
0
.
0
/
0
;
bt_assert
(
roa_check
(
r4
,
10
.
10
.
0
.
0
/
16
,
1000
) =
ROA_UNKNOWN
);
bt_assert
(
roa_check
(
r4
,
10
.
0
.
0
.
0
/
8
,
1000
) =
ROA_UNKNOWN
);
bt_assert
(
roa_check
(
r4
,
10
.
110
.
0
.
0
/
16
,
1000
) =
ROA_VALID
);
bt_assert
(
roa_check
(
r4
,
10
.
110
.
0
.
0
/
16
,
2000
) =
ROA_INVALID
);
bt_assert
(
roa_check
(
r4
,
10
.
110
.
32
.
0
/
20
,
1000
) =
ROA_INVALID
);
bt_assert
(
roa_check
(
r4
,
10
.
120
.
32
.
0
/
20
,
1000
) =
ROA_VALID
);
bt_assert
(
roa_check
(
r4
,
10
.
120
.
32
.
0
/
20
,
2000
) =
ROA_INVALID
);
bt_assert
(
roa_check
(
r4
,
10
.
120
.
32
.
32
/
28
,
1000
) =
ROA_INVALID
);
bt_assert
(
roa_check
(
r4
,
10
.
130
.
130
.
0
/
24
,
1000
) =
ROA_INVALID
);
bt_assert
(
roa_check
(
r4
,
10
.
130
.
130
.
0
/
24
,
2000
) =
ROA_VALID
);
bt_assert
(
roa_check
(
r4
,
10
.
130
.
30
.
0
/
24
,
3000
) =
ROA_INVALID
);
bt_assert
(
roa_check
(
r4
,
10
.
130
.
130
.
0
/
24
,
3000
) =
ROA_VALID
);
bt_assert
(
roa_check
(
r6
,
2001
:
0
db8
:
85
a3
:
8
a2e
:
1234
::/
80
,
1000
) =
ROA_VALID
);
bt_assert
(
roa_check
(
r6
,
2001
:
0
db8
:
85
a3
:
8
a2e
:
1234
::/
97
,
1000
) =
ROA_INVALID
);
bt_assert
(
roa_check
(
r6
,
2001
:
0
db8
:
85
a3
:
8
a2e
::/
64
,
1000
) =
ROA_VALID
);
bt_assert
(
roa_check
(
r6
,
2001
:
0
db8
:
85
a3
::/
48
,
1000
) =
ROA_UNKNOWN
);
bt_assert
(
roa_check
(
r4
,
10
.
10
.
0
.
0
/
16
,
1000
) =
ROA_UNKNOWN
);
bt_assert
(
roa_check
(
r4
,
10
.
0
.
0
.
0
/
8
,
1000
) =
ROA_UNKNOWN
);
bt_assert
(
roa_check
(
r4
,
10
.
110
.
0
.
0
/
16
,
1000
) =
ROA_VALID
);
bt_assert
(
roa_check
(
r4
,
10
.
110
.
0
.
0
/
16
,
2000
) =
ROA_INVALID
);
bt_assert
(
roa_check
(
r4
,
10
.
110
.
32
.
0
/
20
,
1000
) =
ROA_INVALID
);
bt_assert
(
roa_check
(
r4
,
10
.
120
.
32
.
0
/
20
,
1000
) =
ROA_VALID
);
bt_assert
(
roa_check
(
r6
,
2001
:
0
db8
:
85
a3
:
8
a2e
:
1234
::/
80
,
1000
) =
ROA_VALID
);
bt_assert
(
roa_check
(
r6
,
2001
:
0
db8
:
85
a3
:
8
a2e
:
1234
::/
97
,
1000
) =
ROA_INVALID
);
bt_assert
(
roa_check
(
r6
,
2001
:
0
db8
:
85
a3
:
8
a2e
::/
64
,
1000
) =
ROA_VALID
);
bt_assert
(
roa_check
(
r6
,
2001
:
0
db8
:
85
a3
::/
48
,
1000
) =
ROA_UNKNOWN
);
bt_assert
(
roa_check
(
r4
,
2001
:
0
db8
:
85
a3
:
8
a2e
:
1234
::/
97
,
1000
) =
ROA_UNKNOWN
);
bt_assert
(
roa_check
(
r6
,
2001
:
0
db8
:
85
a3
:
8
a2e
:
1234
::/
97
,
1000
) =
ROA_INVALID
);
bt_assert
(
roa_check
(
r4
,
2001
:
0
db8
:
85
a3
:
8
a2e
:
1234
::/
80
,
1000
) =
ROA_UNKNOWN
);
bt_assert
(
roa_check
(
r6
,
2001
:
0
db8
:
85
a3
:
8
a2e
:
1234
::/
80
,
1000
) =
ROA_VALID
);
bt_assert
(
roa_check
(
r4
,
2001
:
0
db8
:
85
a3
::/
48
,
1000
) =
ROA_UNKNOWN
);
bt_assert
(
roa_check
(
r6
,
2001
:
0
db8
:
85
a3
::/
48
,
1000
) =
ROA_UNKNOWN
);
bt_assert
(
10
.
130
.
130
.
0
/
24
~
0
.
0
.
0
.
0
/
0
);
bt_assert
(
2001
:
0
db8
:
85
a3
:
8
a2e
::/
64
~ ::/
0
);
bt_assert
(
10
.
130
.
130
.
0
/
24
!~ ::/
0
);
bt_assert
(
2001
:
0
db8
:
85
a3
:
8
a2e
::/
64
!~
0
.
0
.
0
.
0
/
0
);
pfx
=
12
.
13
.
0
.
0
/
16
max
24
as
1234
;
bt_assert
(
pfx
.
len
=
16
);
bt_assert
(
pfx
.
maxlen
=
24
);
bt_assert
(
pfx
.
asn
=
1234
);
pfx
=
1000
::/
8
max
32
as
1234
;
bt_assert
(
pfx
.
len
=
8
);
bt_assert
(
pfx
.
maxlen
=
32
);
bt_assert
(
pfx
.
asn
=
1234
);
}