1
0
mirror of https://github.com/openbsd/src.git synced 2025-01-10 06:47:55 -08:00

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@
This commit is contained in:
claudio 2004-02-24 15:43:03 +00:00
parent 6ffac9ef4b
commit d77f116553
5 changed files with 127 additions and 36 deletions

View File

@ -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 {

View File

@ -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;
}
$$.prefixlen.op = $2;
$$.prefixlen.len_min = $3;
$$.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 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 {

View File

@ -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);

View File

@ -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

View File

@ -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: