summaryrefslogtreecommitdiff
path: root/usr.sbin/bgpd
diff options
context:
space:
mode:
authorClaudio Jeker <claudio@cvs.openbsd.org>2018-08-09 21:12:34 +0000
committerClaudio Jeker <claudio@cvs.openbsd.org>2018-08-09 21:12:34 +0000
commitf36e4f26f3fea10c627b9fbbe2aafc758180d0da (patch)
tree2f207746cc1aacdaad822b5f750a8f2fa72d7217 /usr.sbin/bgpd
parent2ab237ebf6e8a5b5420010ec49d985236443a284 (diff)
Improve handling of source-as when an AS_SET is rightmost. In that case
use the rightmost AS from the previous AS path segment. As suggested in rfc6472. Also fix a long standing bug of AS 42 >< 4242 matching 43 - 4241 instead of 1-41 and 4243 and upwards. Last but not least pass the filter_as struct to as_compare since that will make it easier to implement as-sets. OK benno@, OK job@ on a previous version
Diffstat (limited to 'usr.sbin/bgpd')
-rw-r--r--usr.sbin/bgpd/bgpd.h4
-rw-r--r--usr.sbin/bgpd/util.c67
2 files changed, 38 insertions, 33 deletions
diff --git a/usr.sbin/bgpd/bgpd.h b/usr.sbin/bgpd/bgpd.h
index 92ffec8bd16..a36b3667429 100644
--- a/usr.sbin/bgpd/bgpd.h
+++ b/usr.sbin/bgpd/bgpd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: bgpd.h,v 1.329 2018/08/08 14:29:05 claudio Exp $ */
+/* $OpenBSD: bgpd.h,v 1.330 2018/08/09 21:12:33 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -1156,8 +1156,6 @@ int aspath_snprint(char *, size_t, void *, u_int16_t);
int aspath_asprint(char **, void *, u_int16_t);
size_t aspath_strlen(void *, u_int16_t);
int aspath_match(void *, u_int16_t, struct filter_as *, u_int32_t);
-int as_compare(u_int8_t, u_int32_t, u_int32_t, u_int32_t,
- u_int32_t);
u_int32_t aspath_extract(const void *, int);
int aspath_verify(void *, u_int16_t, int);
#define AS_ERR_LEN -1
diff --git a/usr.sbin/bgpd/util.c b/usr.sbin/bgpd/util.c
index 8ae8272371d..c62e7e15af2 100644
--- a/usr.sbin/bgpd/util.c
+++ b/usr.sbin/bgpd/util.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: util.c,v 1.28 2018/07/22 16:52:27 claudio Exp $ */
+/* $OpenBSD: util.c,v 1.29 2018/08/09 21:12:33 claudio Exp $ */
/*
* Copyright (c) 2006 Claudio Jeker <claudio@openbsd.org>
@@ -312,6 +312,20 @@ aspath_strlen(void *data, u_int16_t len)
return (total_size);
}
+static int
+as_compare(struct filter_as *f, u_int32_t as, u_int32_t match)
+{
+ if ((f->op == OP_NONE || f->op == OP_EQ) && as == match)
+ return (1);
+ else if (f->op == OP_NE && as != match)
+ return (1);
+ else if (f->op == OP_RANGE && as >= f->as_min && as <= f->as_max)
+ return (1);
+ else if (f->op == OP_XRANGE && (as < f->as_min || as > f->as_max))
+ return (1);
+ return (0);
+}
+
/* we need to be able to search more than one as */
int
aspath_match(void *data, u_int16_t len, struct filter_as *f, u_int32_t match)
@@ -320,7 +334,7 @@ aspath_match(void *data, u_int16_t len, struct filter_as *f, u_int32_t match)
int final;
u_int16_t seg_size;
u_int8_t i, seg_len;
- u_int32_t as;
+ u_int32_t as = 0, preas;
if (f->type == AS_EMPTY) {
if (len == 0)
@@ -330,27 +344,35 @@ aspath_match(void *data, u_int16_t len, struct filter_as *f, u_int32_t match)
}
seg = data;
- for (; len > 0; len -= seg_size, seg += seg_size) {
+
+ /* just check the leftmost AS */
+ if (f->type == AS_PEER && len >= 6) {
+ as = aspath_extract(seg, 0);
+ if (as_compare(f, as, match))
+ return (1);
+ else
+ return (0);
+ }
+
+ for (; len >= 6; len -= seg_size, seg += seg_size) {
seg_len = seg[1];
seg_size = 2 + sizeof(u_int32_t) * seg_len;
final = (len == seg_size);
- /* just check the first (leftmost) AS */
- if (f->type == AS_PEER) {
- as = aspath_extract(seg, 0);
- if (as_compare(f->op, as, match, f->as_min, f->as_max))
- return (1);
- else
- return (0);
- }
- /* just check the final (rightmost) AS */
+ /* just check the rightmost AS */
if (f->type == AS_SOURCE) {
+ /* keep previous AS in case an AS_SET is rightmost */
+ preas = as;
+ as = aspath_extract(seg, seg_len - 1);
/* not yet in the final segment */
if (!final)
continue;
- as = aspath_extract(seg, seg_len - 1);
- if (as_compare(f->op, as, match, f->as_min, f->as_max))
+ if (seg[0] == AS_SET)
+ /* use aggregator AS per rfc6472 */
+ if (preas)
+ as = preas;
+ if (as_compare(f, as, match))
return (1);
else
return (0);
@@ -364,28 +386,13 @@ aspath_match(void *data, u_int16_t len, struct filter_as *f, u_int32_t match)
if (final && i == seg_len - 1 && f->type == AS_TRANSIT)
return (0);
as = aspath_extract(seg, i);
- if (as_compare(f->op, as, match, f->as_min, f->as_max))
+ if (as_compare(f, as, match))
return (1);
}
}
return (0);
}
-int
-as_compare(u_int8_t op, u_int32_t as, u_int32_t match, u_int32_t as_min,
- u_int32_t as_max)
-{
- if ((op == OP_NONE || op == OP_EQ) && as == match)
- return (1);
- else if (op == OP_NE && as != match)
- return (1);
- else if (op == OP_RANGE && as >= as_min && as <= as_max)
- return (1);
- else if (op == OP_XRANGE && as > as_min && as < as_max)
- return (1);
- return (0);
-}
-
/*
* Extract the asnum out of the as segment at the specified position.
* Direct access is not possible because of non-aligned reads.