summaryrefslogtreecommitdiff
path: root/usr.sbin/bgpd
diff options
context:
space:
mode:
authorClaudio Jeker <claudio@cvs.openbsd.org>2004-02-24 15:43:04 +0000
committerClaudio Jeker <claudio@cvs.openbsd.org>2004-02-24 15:43:04 +0000
commit46cc2fafccf26883df44da801f91310a2d04d829 (patch)
treec5b2e41e1328f8b92aaa77978c9271df45456b85 /usr.sbin/bgpd
parente0fc228d8ac39bc46d67758d7b3c5f5118b0ac72 (diff)
Enhance filters. prefixlen knows now 8-24 and 8><24. It is possible to use
prefix 10.0.0.0/8 prefixlen >= 8 and set localpref 100 can be set on a per neighbor basis. OK henning@
Diffstat (limited to 'usr.sbin/bgpd')
-rw-r--r--usr.sbin/bgpd/bgpd.h23
-rw-r--r--usr.sbin/bgpd/parse.y82
-rw-r--r--usr.sbin/bgpd/printconf.c32
-rw-r--r--usr.sbin/bgpd/rde.c9
-rw-r--r--usr.sbin/bgpd/rde_filter.c17
5 files changed, 127 insertions, 36 deletions
diff --git a/usr.sbin/bgpd/bgpd.h b/usr.sbin/bgpd/bgpd.h
index b43c5ec12cf..9a43575cc1c 100644
--- a/usr.sbin/bgpd/bgpd.h
+++ b/usr.sbin/bgpd/bgpd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: bgpd.h,v 1.97 2004/02/16 17:24:04 henning Exp $ */
+/* $OpenBSD: bgpd.h,v 1.98 2004/02/24 15:43:03 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -125,6 +125,15 @@ enum announce_type {
ANNOUNCE_ALL
};
+struct filter_set {
+ u_int8_t flags;
+ u_int32_t localpref;
+ u_int32_t med;
+ struct in_addr nexthop;
+ struct in6_addr nexthop6;
+ u_int8_t prepend;
+};
+
struct peer_config {
u_int32_t id;
u_int32_t groupid;
@@ -139,6 +148,7 @@ struct peer_config {
u_int8_t passive;
u_int16_t holdtime;
u_int16_t min_holdtime;
+ struct filter_set attrset;
enum announce_type announce_type;
char tcp_md5_key[TCP_MD5_KEY_LEN];
enum reconf_action reconf_action;
@@ -316,6 +326,7 @@ enum as_spec {
enum comp_ops {
OP_NONE,
OP_RANGE,
+ OP_XRANGE,
OP_EQ,
OP_NE,
OP_LE,
@@ -342,6 +353,7 @@ struct filter_match {
u_int8_t len;
} prefix;
struct {
+ sa_family_t af;
enum comp_ops op;
u_int8_t len_min;
u_int8_t len_max;
@@ -352,15 +364,6 @@ struct filter_match {
} as;
};
-struct filter_set {
- u_int8_t flags;
- u_int32_t localpref;
- u_int32_t med;
- struct in_addr nexthop;
- struct in6_addr nexthop6;
- u_int8_t prepend;
-};
-
TAILQ_HEAD(filter_head, filter_rule);
struct filter_rule {
diff --git a/usr.sbin/bgpd/parse.y b/usr.sbin/bgpd/parse.y
index cecddb5258a..cb77f09434d 100644
--- a/usr.sbin/bgpd/parse.y
+++ b/usr.sbin/bgpd/parse.y
@@ -1,4 +1,4 @@
-/* $OpenBSD: parse.y,v 1.57 2004/02/19 13:54:58 claudio Exp $ */
+/* $OpenBSD: parse.y,v 1.58 2004/02/24 15:43:03 claudio Exp $ */
/*
* Copyright (c) 2002, 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -115,9 +115,9 @@ typedef struct {
%type <v.addr> address
%type <v.u8> action quick direction
%type <v.filter_peers> filter_peer
-%type <v.filter_match> filter_match
+%type <v.filter_match> filter_match prefixlenop
%type <v.filter_set> filter_set filter_set_l filter_set_opt
-%type <v.u8> unaryop filter_as
+%type <v.u8> unaryop binaryop filter_as
%%
grammar : /* empty */
@@ -419,6 +419,10 @@ peeropts : REMOTEAS number {
strtoul(s, NULL, 16);
}
}
+ | filter_set {
+ memcpy(&curpeer->conf.attrset, &$1,
+ sizeof(curpeer->conf.attrset));
+ }
;
filterrule : action quick direction filter_peer filter_match filter_set
@@ -433,6 +437,20 @@ filterrule : action quick direction filter_peer filter_match filter_set
if (expand_rule(&r, &$4, &$5, &$6) == -1)
YYERROR;
}
+ | action quick direction filter_peer filter_match
+ {
+ struct filter_rule r;
+ struct filter_set set;
+
+ bzero(&r, sizeof(r));
+ bzero(&set, sizeof(set));
+ r.action = $1;
+ r.quick = $2;
+ r.dir = $3;
+
+ if (expand_rule(&r, &$4, &$5, &set) == -1)
+ YYERROR;
+ }
;
action : ALLOW { $$ = ACTION_ALLOW; }
@@ -490,14 +508,26 @@ filter_match : /* empty */ { bzero(&$$, sizeof($$)); }
}
$$.prefix.len = $4;
}
- | PREFIXLEN unaryop number {
+ | PREFIX address '/' number PREFIXLEN prefixlenop {
bzero(&$$, sizeof($$));
- if ($3 > 128) {
- yyerror("prefixlen must be < 128");
+ memcpy(&$$.prefix.addr, &$2, sizeof($$.prefix.addr));
+ if ($4 > 32) {
+ yyerror("prefixlength must be <= 32");
+ YYERROR;
+ }
+ $$.prefix.len = $4;
+ $$.prefixlen = $6.prefixlen;
+ $$.prefixlen.af = AF_INET;
+ if ($$.prefixlen.len_max > 32 ||
+ $$.prefixlen.len_min > 32) {
+ yyerror("prefixlength must be <= 32");
YYERROR;
}
- $$.prefixlen.op = $2;
- $$.prefixlen.len_min = $3;
+ }
+ | PREFIXLEN prefixlenop {
+ bzero(&$$, sizeof($$));
+ $$.prefixlen = $2.prefixlen;
+ $$.prefixlen.af = AF_INET;
}
| filter_as number {
bzero(&$$, sizeof($$));
@@ -510,16 +540,38 @@ filter_match : /* empty */ { bzero(&$$, sizeof($$)); }
}
;
+prefixlenop : unaryop number {
+ bzero(&$$, sizeof($$));
+ if ($2 > 128) {
+ yyerror("prefixlen must be < 128");
+ YYERROR;
+ }
+ $$.prefixlen.op = $1;
+ $$.prefixlen.len_min = $2;
+ }
+ | number binaryop number {
+ bzero(&$$, sizeof($$));
+ if ($1 > 128 || $3 > 128) {
+ yyerror("prefixlen must be < 128");
+ YYERROR;
+ }
+ if ($1 >= $3) {
+ yyerror("start prefixlen is bigger that end");
+ YYERROR;
+ }
+ $$.prefixlen.op = $2;
+ $$.prefixlen.len_min = $1;
+ $$.prefixlen.len_max = $3;
+ }
+ ;
+
filter_as : AS { $$ = AS_ALL; }
| SOURCEAS { $$ = AS_SOURCE; }
| TRANSITAS { $$ = AS_TRANSIT; }
;
-filter_set : /* empty */ {
- bzero(&$$, sizeof($$));
- }
- | SET filter_set_opt { $$ = $2; }
- | SET "{" filter_set_l "}" { $$ = $3; }
+filter_set : SET filter_set_opt { $$ = $2; }
+ | SET optnl "{" optnl filter_set_l optnl "}" { $$ = $5; }
;
filter_set_l : filter_set_l comma filter_set_opt {
@@ -577,6 +629,10 @@ unaryop : '=' { $$ = OP_EQ; }
| '>' { $$ = OP_GT; }
;
+binaryop : '-' { $$ = OP_RANGE; }
+ | '>' '<' { $$ = OP_XRANGE; }
+ ;
+
%%
struct keywords {
diff --git a/usr.sbin/bgpd/printconf.c b/usr.sbin/bgpd/printconf.c
index 281c88e0243..8caa4611c6c 100644
--- a/usr.sbin/bgpd/printconf.c
+++ b/usr.sbin/bgpd/printconf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: printconf.c,v 1.4 2004/02/09 23:16:46 henning Exp $ */
+/* $OpenBSD: printconf.c,v 1.5 2004/02/24 15:43:03 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -31,6 +31,12 @@ void
print_op(enum comp_ops op)
{
switch (op) {
+ case OP_RANGE:
+ printf("-");
+ break;
+ case OP_XRANGE:
+ printf("><");
+ break;
case OP_EQ:
printf("=");
break;
@@ -124,6 +130,20 @@ print_peer(struct peer_config *p)
printf("%s\tannounce ???\n", c);
if (p->tcp_md5_key[0])
printf("%s\ttcp md5sig\n", c);
+ if (p->attrset.flags) {
+ printf("%s\tset {\n", c);
+ if (p->attrset.flags & SET_LOCALPREF)
+ printf("%s\t\tlocalpref %u\n", c, p->attrset.localpref);
+ if (p->attrset.flags & SET_MED)
+ printf("%s\t\tmed %u\n", c, p->attrset.med);
+ if (p->attrset.flags & SET_NEXTHOP)
+ printf("%s\t\tnexthop %s\n",
+ c, inet_ntoa(p->attrset.nexthop));
+ if (p->attrset.flags & SET_PREPEND)
+ printf("%s\t\tprepend-self %u\n",
+ c, p->attrset.prepend);
+ printf("%s\t}\n", c);
+ }
printf("%s}\n", c);
if (p->group[0])
printf("}\n");
@@ -175,10 +195,12 @@ print_rule(struct peer *peer_l, struct filter_rule *r)
r->match.prefix.len);
if (r->match.prefixlen.op) {
- if (r->match.prefixlen.op == OP_RANGE)
- printf("prefixlen %u - %u ", r->match.prefixlen.len_min,
- r->match.prefixlen.len_max);
- else {
+ if (r->match.prefixlen.op == OP_RANGE ||
+ r->match.prefixlen.op == OP_XRANGE) {
+ printf("prefixlen %u ", r->match.prefixlen.len_min);
+ print_op(r->match.prefixlen.op);
+ printf(" %u ", r->match.prefixlen.len_max);
+ } else {
printf("prefixlen ");
print_op(r->match.prefixlen.op);
printf(" %u ", r->match.prefixlen.len_min);
diff --git a/usr.sbin/bgpd/rde.c b/usr.sbin/bgpd/rde.c
index 3f6194bfebf..36f65314729 100644
--- a/usr.sbin/bgpd/rde.c
+++ b/usr.sbin/bgpd/rde.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rde.c,v 1.84 2004/02/23 17:19:26 claudio Exp $ */
+/* $OpenBSD: rde.c,v 1.85 2004/02/24 15:43:03 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -455,7 +455,10 @@ rde_update_dispatch(struct imsg *imsg)
attr_optfree(&attrs);
return (0);
}
-
+
+ /* apply default overrides */
+ rde_apply_set(&attrs, &peer->conf.attrset);
+
/* parse nlri prefix */
while (nlri_len > 0) {
if ((pos = rde_update_get_prefix(p, nlri_len, &prefix,
@@ -476,7 +479,7 @@ rde_update_dispatch(struct imsg *imsg)
p += pos;
nlri_len -= pos;
-
+
/* input filter */
/*
* XXX we need to copy attrs befor calling the filter
diff --git a/usr.sbin/bgpd/rde_filter.c b/usr.sbin/bgpd/rde_filter.c
index b6e10347188..7423fbf63e2 100644
--- a/usr.sbin/bgpd/rde_filter.c
+++ b/usr.sbin/bgpd/rde_filter.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rde_filter.c,v 1.1 2004/02/19 23:07:00 claudio Exp $ */
+/* $OpenBSD: rde_filter.c,v 1.2 2004/02/24 15:43:03 claudio Exp $ */
/*
* Copyright (c) 2004 Claudio Jeker <claudio@openbsd.org>
@@ -110,6 +110,9 @@ rde_filter_match(struct filter_rule *f, struct attr_flags *attrs,
case OP_RANGE:
return ((plen >= f->match.prefixlen.len_min) &&
(plen <= f->match.prefixlen.len_max));
+ case OP_XRANGE:
+ return ((plen < f->match.prefixlen.len_min) ||
+ (plen > f->match.prefixlen.len_max));
case OP_EQ:
return (plen == f->match.prefixlen.len_min);
case OP_NE:
@@ -126,16 +129,20 @@ rde_filter_match(struct filter_rule *f, struct attr_flags *attrs,
/* NOTREACHED */
} else if (f->match.prefixlen.op != OP_NONE) {
/* only prefixlen without a prefix */
- /*
- * XXX IPv4 and IPv6 will cause trouble here.
- * XXX need to store the af.
- */
+
+ if (f->match.prefixlen.af != prefix->af)
+ /* don't use IPv4 rules for IPv6 and vice versa */
+ return (0);
+
switch (f->match.prefixlen.op) {
case OP_NONE:
fatalx("internal filter bug");
case OP_RANGE:
return ((plen >= f->match.prefixlen.len_min) &&
(plen <= f->match.prefixlen.len_max));
+ case OP_XRANGE:
+ return ((plen < f->match.prefixlen.len_min) ||
+ (plen > f->match.prefixlen.len_max));
case OP_EQ:
return (plen == f->match.prefixlen.len_min);
case OP_NE: