diff options
author | 2010-05-17 16:08:20 +0000 | |
---|---|---|
committer | 2010-05-17 16:08:20 +0000 | |
commit | 4a044d31dbbf1d311275263eb1c0fb4c19abdd2e (patch) | |
tree | fb0b6750b5705334962a7c42b068fcb175fbe756 | |
parent | Last bits of MPLS VPN support. Hook kernel routing tables and RIB together. (diff) | |
download | wireguard-openbsd-4a044d31dbbf1d311275263eb1c0fb4c19abdd2e.tar.xz wireguard-openbsd-4a044d31dbbf1d311275263eb1c0fb4c19abdd2e.zip |
Implement two new filters, max-as-len and max-as-seq. The first is limiting
the length of an AS path (matches if the path is longer then the specified
lenght) the second matches when a sequence of the same AS number is longer
then the specified length).
max-as-len is good to protect crappy comercial bgp boxes from other crappy
comercial bgp boxes. max-as-seq was a feature request from SwissIX and maybe
EuroIX to find and filter prepends.
Additinal testing and OK sthen@
-rw-r--r-- | usr.sbin/bgpd/bgpd.conf.5 | 20 | ||||
-rw-r--r-- | usr.sbin/bgpd/bgpd.h | 18 | ||||
-rw-r--r-- | usr.sbin/bgpd/parse.y | 30 | ||||
-rw-r--r-- | usr.sbin/bgpd/printconf.c | 7 | ||||
-rw-r--r-- | usr.sbin/bgpd/rde.h | 3 | ||||
-rw-r--r-- | usr.sbin/bgpd/rde_attr.c | 39 | ||||
-rw-r--r-- | usr.sbin/bgpd/rde_filter.c | 7 |
7 files changed, 114 insertions, 10 deletions
diff --git a/usr.sbin/bgpd/bgpd.conf.5 b/usr.sbin/bgpd/bgpd.conf.5 index 5ae88b70442..7dc729c72df 100644 --- a/usr.sbin/bgpd/bgpd.conf.5 +++ b/usr.sbin/bgpd/bgpd.conf.5 @@ -1,4 +1,4 @@ -.\" $OpenBSD: bgpd.conf.5,v 1.107 2010/05/17 15:49:29 claudio Exp $ +.\" $OpenBSD: bgpd.conf.5,v 1.108 2010/05/17 16:08:20 claudio Exp $ .\" .\" Copyright (c) 2004 Claudio Jeker <claudio@openbsd.org> .\" Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -1140,6 +1140,24 @@ without specifying a .Ic prefix beforehand. .Pp +.It Ic max-as-len Ar len +This rule applies only to +.Em UPDATES +where the +.Em AS path +has more then +.Ar len +elements. +.Pp +.It Ic max-as-seq Ar len +This rule applies only to +.Em UPDATES +where a single +.Em AS number +is repeated more then +.Ar len +times. +.Pp .It Xo .Ic prefix .Ar address Ns Li / Ns Ar len diff --git a/usr.sbin/bgpd/bgpd.h b/usr.sbin/bgpd/bgpd.h index 1fb519acfef..9e4ccd8b80f 100644 --- a/usr.sbin/bgpd/bgpd.h +++ b/usr.sbin/bgpd/bgpd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: bgpd.h,v 1.259 2010/05/17 15:49:29 claudio Exp $ */ +/* $OpenBSD: bgpd.h,v 1.260 2010/05/17 16:08:20 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -580,17 +580,28 @@ enum as_spec { AS_EMPTY }; +enum aslen_spec { + ASLEN_NONE, + ASLEN_MAX, + ASLEN_SEQ +}; + struct filter_as { u_int32_t as; u_int16_t flags; enum as_spec type; }; +struct filter_aslen { + u_int aslen; + enum aslen_spec type; +}; + #define AS_FLAG_NEIGHBORAS 0x01 struct filter_community { - int as; - int type; + int as; + int type; }; struct filter_extcommunity { @@ -732,6 +743,7 @@ struct filter_match { struct filter_prefix prefix; struct filter_prefixlen prefixlen; struct filter_as as; + struct filter_aslen aslen; struct filter_community community; struct filter_extcommunity ext_community; }; diff --git a/usr.sbin/bgpd/parse.y b/usr.sbin/bgpd/parse.y index 2d426aa4140..6660ae92149 100644 --- a/usr.sbin/bgpd/parse.y +++ b/usr.sbin/bgpd/parse.y @@ -1,4 +1,4 @@ -/* $OpenBSD: parse.y,v 1.254 2010/05/17 15:49:29 claudio Exp $ */ +/* $OpenBSD: parse.y,v 1.255 2010/05/17 16:08:20 claudio Exp $ */ /* * Copyright (c) 2002, 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -180,7 +180,7 @@ typedef struct { %token FROM TO ANY %token CONNECTED STATIC %token COMMUNITY EXTCOMMUNITY -%token PREFIX PREFIXLEN SOURCEAS TRANSITAS PEERAS DELETE +%token PREFIX PREFIXLEN SOURCEAS TRANSITAS PEERAS DELETE MAXASLEN MAXASSEQ %token SET LOCALPREF MED METRIC NEXTHOP REJECT BLACKHOLE NOMODIFY SELF %token PREPEND_SELF PREPEND_PEER PFTABLE WEIGHT RTLABEL ORIGIN %token ERROR INCLUDE @@ -1616,6 +1616,30 @@ filter_elm : filter_prefix_h { } fmopts.as_l = $1; } + | MAXASLEN NUMBER { + if (fmopts.m.aslen.type != ASLEN_NONE) { + yyerror("AS length filters already specified"); + YYERROR; + } + if ($2 < 0 || $2 > UINT_MAX) { + yyerror("bad max-as-len %lld", $2); + YYERROR; + } + fmopts.m.aslen.type = ASLEN_MAX; + fmopts.m.aslen.aslen = $2; + } + | MAXASSEQ NUMBER { + if (fmopts.m.aslen.type != ASLEN_NONE) { + yyerror("AS length filters already specified"); + YYERROR; + } + if ($2 < 0 || $2 > UINT_MAX) { + yyerror("bad max-as-seq %lld", $2); + YYERROR; + } + fmopts.m.aslen.type = ASLEN_SEQ; + fmopts.m.aslen.aslen = $2; + } | COMMUNITY STRING { if (fmopts.m.community.as != COMMUNITY_UNSET) { yyerror("\"community\" already specified"); @@ -2107,6 +2131,8 @@ lookup(char *s) { "localpref", LOCALPREF}, { "log", LOG}, { "match", MATCH}, + { "max-as-len", MAXASLEN}, + { "max-as-seq", MAXASSEQ}, { "max-prefix", MAXPREFIX}, { "md5sig", MD5SIG}, { "med", MED}, diff --git a/usr.sbin/bgpd/printconf.c b/usr.sbin/bgpd/printconf.c index 860aebd1913..dbf03bdbae4 100644 --- a/usr.sbin/bgpd/printconf.c +++ b/usr.sbin/bgpd/printconf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: printconf.c,v 1.81 2010/05/17 15:49:29 claudio Exp $ */ +/* $OpenBSD: printconf.c,v 1.82 2010/05/17 16:08:20 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -569,6 +569,11 @@ print_rule(struct peer *peer_l, struct filter_rule *r) printf("unfluffy-as %s ", log_as(r->match.as.as)); } + if (r->match.aslen.type) { + printf("%s %u ", r->match.aslen.type == ASLEN_MAX ? + "max-as-len" : "max-as-seq", r->match.aslen.aslen); + } + if (r->match.community.as != COMMUNITY_UNSET) { printf("community "); print_community(r->match.community.as, diff --git a/usr.sbin/bgpd/rde.h b/usr.sbin/bgpd/rde.h index bf3f3a8a9f6..21e98c90f5c 100644 --- a/usr.sbin/bgpd/rde.h +++ b/usr.sbin/bgpd/rde.h @@ -1,4 +1,4 @@ -/* $OpenBSD: rde.h,v 1.134 2010/05/03 13:09:38 claudio Exp $ */ +/* $OpenBSD: rde.h,v 1.135 2010/05/17 16:08:20 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org> and @@ -345,6 +345,7 @@ int aspath_loopfree(struct aspath *, u_int32_t); int aspath_compare(struct aspath *, struct aspath *); u_char *aspath_prepend(struct aspath *, u_int32_t, int, u_int16_t *); int aspath_match(struct aspath *, enum as_spec, u_int32_t); +int aspath_lenmatch(struct aspath *, enum aslen_spec, u_int); int community_match(struct rde_aspath *, int, int); int community_set(struct rde_aspath *, int, int); void community_delete(struct rde_aspath *, int, int); diff --git a/usr.sbin/bgpd/rde_attr.c b/usr.sbin/bgpd/rde_attr.c index 6b1dc839d8a..e38473ff8d8 100644 --- a/usr.sbin/bgpd/rde_attr.c +++ b/usr.sbin/bgpd/rde_attr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rde_attr.c,v 1.83 2010/03/29 09:24:07 claudio Exp $ */ +/* $OpenBSD: rde_attr.c,v 1.84 2010/05/17 16:08:20 claudio Exp $ */ /* * Copyright (c) 2004 Claudio Jeker <claudio@openbsd.org> @@ -971,6 +971,43 @@ aspath_match(struct aspath *a, enum as_spec type, u_int32_t as) return (0); } +int +aspath_lenmatch(struct aspath *a, enum aslen_spec type, u_int aslen) +{ + u_int8_t *seg; + u_int32_t as, lastas = 0; + u_int count = 0; + u_int16_t len, seg_size; + u_int8_t i, seg_type, seg_len; + + if (type == ASLEN_MAX) { + if (aslen < aspath_count(a->data, a->len)) + return (1); + else + return (0); + } + + /* type == ASLEN_SEQ */ + seg = a->data; + for (len = a->len; len > 0; len -= seg_size, seg += seg_size) { + seg_type = seg[0]; + seg_len = seg[1]; + seg_size = 2 + sizeof(u_int32_t) * seg_len; + + for (i = 0; i < seg_len; i++) { + /* what should we do with AS_SET? */ + as = aspath_extract(seg, i); + if (as == lastas) { + if (aslen < ++count) + return (1); + } else + count = 1; + lastas = as; + } + } + return (0); +} + /* * Functions handling communities and extended communities. */ diff --git a/usr.sbin/bgpd/rde_filter.c b/usr.sbin/bgpd/rde_filter.c index 7ce990812a3..436526cf471 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.63 2010/04/28 13:07:48 claudio Exp $ */ +/* $OpenBSD: rde_filter.c,v 1.64 2010/05/17 16:08:20 claudio Exp $ */ /* * Copyright (c) 2004 Claudio Jeker <claudio@openbsd.org> @@ -281,6 +281,11 @@ rde_filter_match(struct filter_rule *f, struct rde_aspath *asp, return (0); } + if (asp != NULL && f->match.aslen.type != ASLEN_NONE) + if (aspath_lenmatch(asp->aspath, f->match.aslen.type, + f->match.aslen.aslen) == 0) + return (0); + if (asp != NULL && f->match.community.as != COMMUNITY_UNSET) { switch (f->match.community.as) { case COMMUNITY_ERROR: |