summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorclaudio <claudio@openbsd.org>2010-05-17 16:08:20 +0000
committerclaudio <claudio@openbsd.org>2010-05-17 16:08:20 +0000
commit4a044d31dbbf1d311275263eb1c0fb4c19abdd2e (patch)
treefb0b6750b5705334962a7c42b068fcb175fbe756
parentLast bits of MPLS VPN support. Hook kernel routing tables and RIB together. (diff)
downloadwireguard-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.520
-rw-r--r--usr.sbin/bgpd/bgpd.h18
-rw-r--r--usr.sbin/bgpd/parse.y30
-rw-r--r--usr.sbin/bgpd/printconf.c7
-rw-r--r--usr.sbin/bgpd/rde.h3
-rw-r--r--usr.sbin/bgpd/rde_attr.c39
-rw-r--r--usr.sbin/bgpd/rde_filter.c7
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: