The aspath_neighbor function returns the first AS of a path. Now if the
first element is an AS_SET then this does not really make sense.
RFC4271 has this bit in section 9.1.2.2
Similarly, neighborAS(n) is a function that returns the
neighbor AS from which the route was received. If the route is
learned via IBGP, and the other IBGP speaker didn't originate
the route, it is the neighbor AS from which the other IBGP
speaker learned the route. If the route is learned via IBGP,
and the other IBGP speaker either (a) originated the route, or
(b) created the route by aggregation and the AS_PATH attribute
of the aggregate route is either empty or begins with an
AS_SET, it is the local AS.
bgpd uses aspath_neighbor() in a few spots:
- in the decision process to decide if MED should be compared or not
- in filters using 'peer-as'
- in the enforce neighbor-as check
I think the above mentioned behaviour is valid for all these cases and so
here is a diff that adjust aspath_neighbor().
--
:wq Claudio
Index: rde_attr.c
===================================================================
RCS file: /cvs/src/usr.sbin/bgpd/rde_attr.c,v
retrieving revision 1.123
diff -u -p -r1.123 rde_attr.c
--- rde_attr.c 24 Jun 2019 06:39:49 -0000 1.123
+++ rde_attr.c 14 Jan 2021 13:13:15 -0000
@@ -673,8 +673,13 @@ aspath_length(struct aspath *aspath)
u_int32_t
aspath_neighbor(struct aspath *aspath)
{
- /* Empty aspath is OK -- internal AS route. */
- if (aspath->len == 0)
+ /*
+ * Empty aspath is OK -- internal AS route.
+ * Additionally the RFC specifies that if the path starts with an
+ * AS_SET the neighbor AS is also the local AS.
+ */
+ if (aspath->len == 0 ||
+ aspath->data[0] != AS_SEQUENCE)
return (rde_local_as());
return (aspath_extract(aspath->data, 0));
}