summaryrefslogtreecommitdiff
path: root/proto/bgp/attrs.c
diff options
context:
space:
mode:
authorOndrej Zajicek (work) <santiago@crfreenet.org>2019-11-10 02:06:07 +0100
committerOndrej Zajicek (work) <santiago@crfreenet.org>2019-11-10 02:06:07 +0100
commit0b228fca04c8a9a81af6a4973877ceba9aede3f0 (patch)
treeae5a7e9a1c8d4c6adc86db1d543a2befbcfa3a63 /proto/bgp/attrs.c
parentbecda5638a8ff8b056ec04b5e156e86b168cb9ef (diff)
BGP: Add option to enforce first AS in AS_PATH
This is optional check described in RFC 4271. Although this can be also done by filters, it is widely implemented option in BGP implementations. Thanks to Eugene Bogomazov for the original patch.
Diffstat (limited to 'proto/bgp/attrs.c')
-rw-r--r--proto/bgp/attrs.c24
1 files changed, 19 insertions, 5 deletions
diff --git a/proto/bgp/attrs.c b/proto/bgp/attrs.c
index 9b243763..39297dd7 100644
--- a/proto/bgp/attrs.c
+++ b/proto/bgp/attrs.c
@@ -404,6 +404,15 @@ bgp_format_origin(eattr *a, byte *buf, uint size UNUSED)
}
+static inline int
+bgp_as_path_first_as_equal(const byte *data, uint len, u32 asn)
+{
+ return (len >= 6) &&
+ ((data[0] == AS_PATH_SEQUENCE) || (data[0] == AS_PATH_CONFED_SEQUENCE)) &&
+ (data[1] > 0) &&
+ (get_u32(data+2) == asn);
+}
+
static int
bgp_encode_as_path(struct bgp_write_state *s, eattr *a, byte *buf, uint size)
{
@@ -433,11 +442,6 @@ bgp_decode_as_path(struct bgp_parse_state *s, uint code UNUSED, uint flags, byte
if (!as_path_valid(data, len, as_length, as_sets, as_confed, err, sizeof(err)))
WITHDRAW("Malformed AS_PATH attribute - %s", err);
- /* In some circumstances check for initial AS_CONFED_SEQUENCE; RFC 5065 5.0 */
- if (p->is_interior && !p->is_internal &&
- ((len < 2) || (data[0] != AS_PATH_CONFED_SEQUENCE)))
- WITHDRAW("Malformed AS_PATH attribute - %s", "missing initial AS_CONFED_SEQUENCE");
-
if (!s->as4_session)
{
/* Prepare 32-bit AS_PATH (from 16-bit one) in a temporary buffer */
@@ -446,6 +450,16 @@ bgp_decode_as_path(struct bgp_parse_state *s, uint code UNUSED, uint flags, byte
len = as_path_16to32(data, src, len);
}
+ /* In some circumstances check for initial AS_CONFED_SEQUENCE; RFC 5065 5.0 */
+ if (p->is_interior && !p->is_internal &&
+ ((len < 2) || (data[0] != AS_PATH_CONFED_SEQUENCE)))
+ WITHDRAW("Malformed AS_PATH attribute - %s", "missing initial AS_CONFED_SEQUENCE");
+
+ /* Reject routes with first AS in AS_PATH not matching neighbor AS; RFC 4271 6.3 */
+ if (!p->is_internal && p->cf->enforce_first_as &&
+ !bgp_as_path_first_as_equal(data, len, p->remote_as))
+ WITHDRAW("Malformed AS_PATH attribute - %s", "First AS differs from neigbor AS");
+
bgp_set_attr_data(to, s->pool, BA_AS_PATH, flags, data, len);
}