On Wed, Nov 28, 2018 at 10:35:37AM +0100, Claudio Jeker wrote:
> On Tue, Nov 27, 2018 at 06:55:51PM +0100, Job Snijders wrote:
> > On Tue, Nov 27, 2018 at 06:23:53PM +0100, Claudio Jeker wrote:
> > > On Tue, Nov 27, 2018 at 04:21:53PM +0100, Job Snijders wrote:
> > > > On Fri, Nov 23, 2018 at 03:55:18PM +0100, Claudio Jeker wrote:
> > > > > For origin validation I chacked the source_as in struct rde_aspath
> > > > > this is not really the right place. It should be in struct aspath
> > > > > since that holds all the ASPATH related stuff. Change this, move
> > > > > aspath_match out of util.c back into rde_attr.c and adjust code to use
> > > > > the cached value also in match from any source-as XYZ rules.
> > > > > This last bit causes a minor behavioural change since the old code
> > > > > extracted the last non AS_SET asnumber. The new code follows the ROA
> > > > > RFC and returns the rightmost AS for AS_SEQUENCE, the local AS for
> > > > > empty paths and AS_NONE (which is 0) for everything else.
> > > > > So now 'match from any source-as 0' will return all paths that do not
> > > > > have a final AS_SEQUENCE segment.
> > > > > 
> > > > > The reason for this change is that I don't want to have two different
> > > > > behaviours for what we call source-as (the one in roa-set and the one 
> > > > > on a
> > > > > filter).
> > > > 
> > > > Something is off, it seems 'source-as 0' is matching anything that has
> > > > an AS_SET attribute set:
> > > > 
> > > >     $ bgpctl show rib source-as 0 | head
> > > >     flags: * = Valid, > = Selected, I = via IBGP, A = Announced,
> > > >            S = Stale, E = Error
> > > >     origin validation state: N = not-found, V = valid, ! = invalid
> > > >     origin: i = IGP, e = EGP, ? = Incomplete
> > > > 
> > > >     flags ovs destination          gateway          lpref   med aspath 
> > > > origin
> > > >     I*>     N 5.39.176.0/21        192.147.168.1      100     0 2914 
> > > > 8530 { 198753 } ?
> > > >     I*>     N 5.101.110.0/24       192.147.168.1      100     0 2914 
> > > > 14061 { 46652 } i
> > > >     I*>     N 5.175.0.0/19         192.147.168.1      100     0 2914 
> > > > 1299 20773 { 8972 } i
> > > >     I*>     N 8.41.202.0/24        192.147.168.1      100     0 2914 
> > > > 13789 30372 { 40179 } i
> > > > 
> > > > Similarly, this should return at least 5.39.176.0/21:
> > > > 
> > > >     $ bgpctl show rib source-as 8530
> > > >     flags: * = Valid, > = Selected, I = via IBGP, A = Announced,
> > > >            S = Stale, E = Error
> > > >     origin validation state: N = not-found, V = valid, ! = invalid
> > > >     origin: i = IGP, e = EGP, ? = Incomplete
> > > > 
> > > >     flags ovs destination          gateway          lpref   med aspath 
> > > > origin
> > > >     I*>     N 80.87.16.0/20        192.147.168.1      100     0 2914 
> > > > 8530 ?
> > > >     I*>     N 87.236.128.0/21      192.147.168.1      100     0 2914 
> > > > 8530 ?
> > > >     I*>     N 88.151.152.0/21      192.147.168.1      100     0 2914 
> > > > 8530 ?
> > > >     I*>     N 89.38.120.0/21       192.147.168.1      100     0 2914 
> > > > 8530 i
> > > >     I*>     N 93.115.176.0/20      192.147.168.1      100     0 2914 
> > > > 8530 i
> > > >     I*>     N 185.52.144.0/22      192.147.168.1      100     0 2914 
> > > > 8530 ?
> > > > 
> > > 
> > > I implemented source-as the way ROA is defining it. So anything which ends
> > > with a AS_SET will return AS_NONE (which is 0). OpenBGPD has no way to
> > > have an AS_PATH that has a real 0 in the AS_PATH (those UPDATES are
> > > treated as withdraw). Because of this also the 5.39.176.0/21 is no longer
> > > matching in 'bgpctl show rib source-as 8530'.
> > 
> > I'm not sure it should behave that way.
> > 
> > 'bgpctl show rib source-as 8530' really ought to return prefixes like
> > 80.87.16.0/20 but also 5.39.176.0/21.
> 
> But isn't this different from other implementations? At least I would
> expect that the AS-path regex '8530$' would not match on the AS_SET path
> either. My issue is that we have 'source-as' in roa-set, origin-set and on
> filters in bgpd.conf plus the source-as used by bgpctl. Depending on
> context they behave differently. So if AS 8530 is in the roa-set
> and I do bgpctl show rib source-as 8530 the result will be different to
> what would match in the roa-set.
> We already had a lot of confusion about announce and that is why I decided
> to make them behave the same.
>  
> > > I'm a bit on the edge here about where to go and currently prefer to
> > > follow a RFC (which in this case is RFC6811).
> > > 
> > >  o  Route Origin ASN: The origin AS number derived from a Route as
> > >     follows:
> > > 
> > >     *  the rightmost AS in the final segment of the AS_PATH attribute
> > >          in the Route if that segment is of type AS_SEQUENCE, or
> > > 
> > >     *  the BGP speaker's own AS number if that segment is of type
> > >        AS_CONFED_SEQUENCE or AS_CONFED_SET or if the AS_PATH is empty,
> > >        or
> > > 
> > >     *  the distinguished value "NONE" if the final segment of the
> > >        AS_PATH attribute is of any other type.
> > > 
> > > As mentioned above I found it strange when behaviour is different because
> > > of where it is used.
> > 
> > RFC 6811 describes how BGP Origin Validation should be performed, but is
> > not a guideline how to treat AS_SETs in general or how CLIs should
> > function. Perhaps 'source-as 0' should just throw an error in all
> > contexts (both bgpd.conf and bgpctl), since 0 can never be in an AS_SET
> > or AS_SEQUENCE. Perhaps we shouldn't overload the number.
> 
> The overloading is done to simplify some internals. It is indeed possible
> to disallow direct use of 0 in bgpctl and replace it with 'none'. On the
> other hand it seems people are used to write belt&suspenders like configs
> where filter rules (e.g. deny form any AS 0) are added which are not needed.
>  
> > 1/ Maybe 'source-as self' or 'source-as none' can be used to match all
> > routes originated by the AS in which this bgpd instance runs.
> 
> 'source-as self' and 'source-as none' are two different things in my
> opinion. The empty AS path case is convered by 'empty-as' in the filters
> and introducing 'source-as none' with a different meaning then the one
> used by RFC6811 will not imporve anything.
>  
> > 2/ Similarly, the program could be made so that 'AS 15562' (lets use
> > 15562 as example) from the Global Configuration passed on to bgpctl and
> > used in the filter ruleset means both "what is originated by 15562" and
> > also what is originated in the own AS (and doesn't have AS_PATH yet, but
> > we know the router runs in 15562 because of the global config parameter).
> 
> This is the behaviour with this diff:
> 
> bgpctl show rib source-as 196618
> flags ovs destination          gateway          lpref   med aspath origin
> AI*>    N 10.12.12.0/24        0.0.0.0            100     0 i
> AI*>    N 10.12.13.0/24        0.0.0.0            100     0 i
> 
> 196618 is the AS of this instance.
> 
> 
> I see two different discussion points here. Or two distinct behaviour
> changes that get introduced by this diff:
> 1/ source-as behaviour for empty AS_PATH. With this diff 'source-as $myAS'
> will match for empty AS_PATH. In my opinion this makes sense but the
> interaction with empty-as should be reconsidered. (e.g. are people
> currently using both forms to achieve different behaviour in their own
> AS).
> 
> 2/ source-as handling of AS_PATH that end with an AS_SET (bgpd currently
> does not support any other segment type). Here there is two things:
>  a) should 'source-as 8530' match for the path with the AS_SET e.g:
>        2914 8530 { 198753 }
>     Should we really consider AS 8530 being the source of that prefix?
>     What about 198753?
> 
>  b) handling of 'source-as 0' ideally this should be disallowed and
>     instead 'source-as none' introduced. Which would then collect all
>     the AS_SET paths from above. b) depends on the outcome of a)
> 
> As mentioned above the idea of making source-as behave like the source-as
> in roa-set for consitency is my reason but if people think the current
> behaviour has to be preserved (with the behaviour difference between
> source-as usage) then that is fine and I will adjust the diff.
> 

This is the same diff as before minus the behaviour change of source-as.
Lets get this in and then we can figure out if we want to change
something.

-- 
:wq Claudio

Index: usr.sbin/bgpctl/bgpctl.c
===================================================================
RCS file: /cvs/src/usr.sbin/bgpctl/bgpctl.c,v
retrieving revision 1.225
diff -u -p -r1.225 bgpctl.c
--- usr.sbin/bgpctl/bgpctl.c    5 Dec 2018 06:53:52 -0000       1.225
+++ usr.sbin/bgpctl/bgpctl.c    6 Dec 2018 09:14:17 -0000
@@ -97,6 +97,7 @@ void           mrt_to_bgpd_addr(union mrt_addr *
 const char     *msg_type(u_int8_t);
 void            network_bulk(struct parse_result *);
 const char     *print_auth_method(enum auth_method);
+int             match_aspath(void *, u_int16_t, struct filter_as *);
 
 struct imsgbuf *ibuf;
 struct mrt_parser show_mrt = { show_mrt_dump, show_mrt_state, show_mrt_msg };
@@ -2056,8 +2057,7 @@ show_mrt_dump(struct mrt_rib *mr, struct
                }
                /* filter by AS */
                if (req->as.type != AS_UNDEF &&
-                  !aspath_match(mre->aspath, mre->aspath_len,
-                  &req->as, 0))
+                  !match_aspath(mre->aspath, mre->aspath_len, &req->as))
                        continue;
 
                if (req->flags & F_CTL_DETAIL) {
@@ -2122,8 +2122,7 @@ network_mrt_dump(struct mrt_rib *mr, str
                }
                /* filter by AS */
                if (req->as.type != AS_UNDEF &&
-                  !aspath_match(mre->aspath, mre->aspath_len,
-                  &req->as, 0))
+                  !match_aspath(mre->aspath, mre->aspath_len, &req->as))
                        continue;
 
                bzero(&net, sizeof(net));
@@ -2661,7 +2660,67 @@ msg_type(u_int8_t type)
 }
 
 int
-as_set_match(const struct as_set *a, u_int32_t asnum)
+match_aspath(void *data, u_int16_t len, struct filter_as *f)
 {
+       u_int8_t        *seg;
+       int              final;
+       u_int16_t        seg_size;
+       u_int8_t         i, seg_len;
+       u_int32_t        as = 0;
+
+       if (f->type == AS_EMPTY) {
+               if (len == 0)
+                       return (1);
+               else
+                       return (0);
+       }
+
+       seg = data;
+
+       /* just check the leftmost AS */
+       if (f->type == AS_PEER && len >= 6) {
+               as = aspath_extract(seg, 0);
+               if (f->as_min == as)
+                       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);
+
+               if (f->type == AS_SOURCE) {
+                       /*
+                        * Just extract the rightmost AS
+                        * but if that segment is an AS_SET then the rightmost
+                        * AS of a previous AS_SEQUENCE segment should be used.
+                        * Because of that just look at AS_SEQUENCE segments.
+                        */
+                       if (seg[0] == AS_SEQUENCE)
+                               as = aspath_extract(seg, seg_len - 1);
+                       /* not yet in the final segment */
+                       if (!final)
+                               continue;
+                       if (f->as_min == as)
+                               return (1);
+                       else
+                               return (0);
+               }
+               /* AS_TRANSIT or AS_ALL */
+               for (i = 0; i < seg_len; i++) {
+                       /*
+                        * the source (rightmost) AS is excluded from
+                        * AS_TRANSIT matches.
+                        */
+                       if (final && i == seg_len - 1 && f->type == AS_TRANSIT)
+                               return (0);
+                       as = aspath_extract(seg, i);
+                       if (f->as_min == as)
+                               return (1);
+               }
+       }
        return (0);
 }
Index: usr.sbin/bgpd/bgpd.h
===================================================================
RCS file: /cvs/src/usr.sbin/bgpd/bgpd.h,v
retrieving revision 1.355
diff -u -p -r1.355 bgpd.h
--- usr.sbin/bgpd/bgpd.h        28 Nov 2018 08:32:26 -0000      1.355
+++ usr.sbin/bgpd/bgpd.h        28 Nov 2018 09:10:01 -0000
@@ -1258,7 +1258,6 @@ const char        *log_shutcomm(const char *);
 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);
 u_int32_t       aspath_extract(const void *, int);
 int             aspath_verify(void *, u_int16_t, int);
 #define                 AS_ERR_LEN     -1
Index: usr.sbin/bgpd/rde.c
===================================================================
RCS file: /cvs/src/usr.sbin/bgpd/rde.c,v
retrieving revision 1.451
diff -u -p -r1.451 rde.c
--- usr.sbin/bgpd/rde.c 29 Nov 2018 15:11:27 -0000      1.451
+++ usr.sbin/bgpd/rde.c 3 Dec 2018 15:09:46 -0000
@@ -482,7 +482,6 @@ rde_dispatch_imsg_session(struct imsgbuf
                        asp->origin = csr.origin;
                        asp->flags |= F_PREFIX_ANNOUNCED | F_ANN_DYNAMIC;
                        asp->aspath = aspath_get(asdata, csr.aspath_len);
-                       asp->source_as = aspath_origin(asp->aspath);
                        netconf_s.asp = asp;
                        break;
                case IMSG_NETWORK_ATTR:
@@ -1121,10 +1120,6 @@ rde_update_dispatch(struct imsg *imsg)
                        }
                }
 
-               if (state.aspath.flags & F_ATTR_ASPATH)
-                       state.aspath.source_as =
-                           aspath_origin(state.aspath.aspath);
-
                rde_reflector(peer, &state.aspath);
        }
 
@@ -1389,7 +1384,7 @@ rde_update_update(struct rde_peer *peer,
 
        peer->prefix_rcvd_update++;
        vstate = rde_roa_validity(&conf->rde_roa, prefix, prefixlen,
-           in->aspath.source_as);
+           aspath_origin(in->aspath.aspath));
 
        /* add original path to the Adj-RIB-In */
        if (path_update(&ribs[RIB_ADJ_IN].rib, peer, in, prefix, prefixlen,
@@ -2220,8 +2215,8 @@ rde_dump_filter(struct prefix *p, struct
        if ((req->flags & F_CTL_INVALID) &&
            (asp->flags & F_ATTR_PARSE_ERR) == 0)
                return;
-       if (req->as.type != AS_UNDEF && !aspath_match(asp->aspath->data,
-           asp->aspath->len, &req->as, 0))
+       if (req->as.type != AS_UNDEF &&
+           !aspath_match(asp->aspath, &req->as, 0))
                return;
        switch (req->community.type) {
        case COMMUNITY_TYPE_NONE:
@@ -3085,7 +3080,7 @@ rde_softreconfig_in(struct rib_entry *re
                if (conf->rde_roa.dirty) {
                        /* ROA validation state update */
                        vstate = rde_roa_validity(&conf->rde_roa,
-                           &prefix, pt->prefixlen, asp->source_as);
+                           &prefix, pt->prefixlen, aspath_origin(asp->aspath));
                        if (vstate != p->validation_state) {
                                force_eval = 1;
                                p->validation_state = vstate;
@@ -3660,7 +3655,6 @@ network_add(struct network_config *nc, i
                asp = path_get();
                asp->aspath = aspath_get(NULL, 0);
                asp->origin = ORIGIN_IGP;
-               asp->source_as = aspath_origin(asp->aspath);
                asp->flags = F_ATTR_ORIGIN | F_ATTR_ASPATH |
                    F_ATTR_LOCALPREF | F_PREFIX_ANNOUNCED;
                /* the nexthop is unset unless a default set overrides it */
@@ -3674,7 +3668,7 @@ network_add(struct network_config *nc, i
                    peerself);
 
        vstate = rde_roa_validity(&conf->rde_roa, &nc->prefix,
-           nc->prefixlen, asp->source_as);
+           nc->prefixlen, aspath_origin(asp->aspath));
        if (path_update(&ribs[RIB_ADJ_IN].rib, peerself, &state, &nc->prefix,
            nc->prefixlen, vstate) == 1)
                peerself->prefix_cnt++;
Index: usr.sbin/bgpd/rde.h
===================================================================
RCS file: /cvs/src/usr.sbin/bgpd/rde.h,v
retrieving revision 1.203
diff -u -p -r1.203 rde.h
--- usr.sbin/bgpd/rde.h 28 Nov 2018 08:32:27 -0000      1.203
+++ usr.sbin/bgpd/rde.h 28 Nov 2018 09:10:02 -0000
@@ -125,6 +125,7 @@ struct rde_peer {
 
 struct aspath {
        LIST_ENTRY(aspath)      entry;
+       u_int32_t               source_as;      /* cached source_as */
        int                     refcnt; /* reference count */
        u_int16_t               len;    /* total length of aspath in octets */
        u_int16_t               ascnt;  /* number of AS hops in data */
@@ -208,7 +209,6 @@ struct rde_aspath {
        struct aspath                   *aspath;
        u_int64_t                        hash;
        u_int32_t                        flags;         /* internally used */
-       u_int32_t                        source_as;     /* cached source_as */
        u_int32_t                        med;           /* multi exit disc */
        u_int32_t                        lpref;         /* local pref */
        u_int32_t                        weight;        /* low prio lpref */
@@ -354,11 +354,11 @@ u_char            *aspath_deflate(u_char *, u_int1
 void            aspath_merge(struct rde_aspath *, struct attr *);
 u_char         *aspath_dump(struct aspath *);
 u_int16_t       aspath_length(struct aspath *);
-u_int16_t       aspath_count(const void *, u_int16_t);
 u_int32_t       aspath_neighbor(struct aspath *);
 u_int32_t       aspath_origin(struct aspath *);
 int             aspath_loopfree(struct aspath *, u_int32_t);
 int             aspath_compare(struct aspath *, struct aspath *);
+int             aspath_match(struct aspath *, struct filter_as *, u_int32_t);
 u_char         *aspath_prepend(struct aspath *, u_int32_t, int, u_int16_t *);
 int             aspath_lenmatch(struct aspath *, enum aslen_spec, u_int);
 
Index: usr.sbin/bgpd/rde_attr.c
===================================================================
RCS file: /cvs/src/usr.sbin/bgpd/rde_attr.c,v
retrieving revision 1.113
diff -u -p -r1.113 rde_attr.c
--- usr.sbin/bgpd/rde_attr.c    28 Nov 2018 08:32:27 -0000      1.113
+++ usr.sbin/bgpd/rde_attr.c    6 Dec 2018 11:13:57 -0000
@@ -441,6 +441,8 @@ attr_put(struct attr *a)
 
 /* aspath specific functions */
 
+static u_int16_t aspath_count(const void *, u_int16_t);
+static u_int32_t aspath_extract_origin(const void *, u_int16_t);
 static u_int16_t aspath_countlength(struct aspath *, u_int16_t, int);
 static void     aspath_countcopy(struct aspath *, u_int16_t, u_int8_t *,
                     u_int16_t, int);
@@ -530,6 +532,7 @@ aspath_get(void *data, u_int16_t len)
                aspath->refcnt = 0;
                aspath->len = len;
                aspath->ascnt = aspath_count(data, len);
+               aspath->source_as = aspath_extract_origin(data, len);
                memcpy(aspath->data, data, len);
 
                /* link */
@@ -667,7 +670,22 @@ aspath_length(struct aspath *aspath)
        return (aspath->len);
 }
 
-u_int16_t
+u_int32_t
+aspath_neighbor(struct aspath *aspath)
+{
+       /* Empty aspath is OK -- internal AS route. */
+       if (aspath->len == 0)
+               return (rde_local_as());
+       return (aspath_extract(aspath->data, 0));
+}
+
+u_int32_t
+aspath_origin(struct aspath *aspath)
+{
+       return aspath->source_as;
+}
+
+static u_int16_t
 aspath_count(const void *data, u_int16_t len)
 {
        const u_int8_t  *seg;
@@ -692,6 +710,41 @@ aspath_count(const void *data, u_int16_t
        return (cnt);
 }
 
+/*
+ * The origin AS number derived from a Route as follows:
+ * o  the rightmost AS in the final segment of the AS_PATH attribute
+ *    in the Route if that segment is of type AS_SEQUENCE, or
+ * o  the BGP speaker's own AS number if that segment is of type
+ *    AS_CONFED_SEQUENCE or AS_CONFED_SET or if the AS_PATH is empty,
+ * o  the distinguished value "NONE" if the final segment of the
+ *    AS_PATH attribute is of any other type.
+ */
+static u_int32_t
+aspath_extract_origin(const void *data, u_int16_t len)
+{
+       const u_int8_t  *seg;
+       u_int32_t        as = AS_NONE;
+       u_int16_t        seg_size;
+       u_int8_t         seg_len;
+
+       /* AS_PATH is empty */
+       if (len == 0)
+               return (rde_local_as());
+
+       seg = data;
+       for (; len > 0; len -= seg_size, seg += seg_size) {
+               seg_len = seg[1];
+               seg_size = 2 + sizeof(u_int32_t) * seg_len;
+
+               if (len == seg_size && seg[0] == AS_SEQUENCE) {
+                       as = aspath_extract(seg, seg_len - 1);
+               }
+               if (seg_size > len)
+                       fatalx("%s: would overflow", __func__);
+       }
+       return (as);
+}
+
 static u_int16_t
 aspath_countlength(struct aspath *aspath, u_int16_t cnt, int headcnt)
 {
@@ -771,50 +824,6 @@ aspath_countcopy(struct aspath *aspath, 
        }
 }
 
-u_int32_t
-aspath_neighbor(struct aspath *aspath)
-{
-       /* Empty aspath is OK -- internal AS route. */
-       if (aspath->len == 0)
-               return (rde_local_as());
-       return (aspath_extract(aspath->data, 0));
-}
-
-/*
- * The origin AS number derived from a Route as follows:
- * o  the rightmost AS in the final segment of the AS_PATH attribute
- *    in the Route if that segment is of type AS_SEQUENCE, or
- * o  the BGP speaker's own AS number if that segment is of type
- *    AS_CONFED_SEQUENCE or AS_CONFED_SET or if the AS_PATH is empty,
- * o  the distinguished value "NONE" if the final segment of the
- *   AS_PATH attribute is of any other type.
- */
-u_int32_t
-aspath_origin(struct aspath *aspath)
-{
-       u_int8_t        *seg;
-       u_int32_t        as = AS_NONE;
-       u_int16_t        len, seg_size;
-       u_int8_t         seg_len;
-
-       /* AS_PATH is empty */
-       if (aspath->len == 0)
-               return (rde_local_as());
-
-       seg = aspath->data;
-       for (len = aspath->len; len > 0; len -= seg_size, seg += seg_size) {
-               seg_len = seg[1];
-               seg_size = 2 + sizeof(u_int32_t) * seg_len;
-
-               if (len == seg_size && seg[0] == AS_SEQUENCE) {
-                       as = aspath_extract(seg, seg_len - 1);
-               }
-               if (seg_size > len)
-                       fatalx("%s: would overflow", __func__);
-       }
-       return (as);
-}
-
 int
 aspath_loopfree(struct aspath *aspath, u_int32_t myAS)
 {
@@ -872,6 +881,110 @@ aspath_lookup(const void *data, u_int16_
        return (NULL);
 }
 
+
+static int
+as_compare(struct filter_as *f, u_int32_t as, u_int32_t neighas)
+{
+       u_int32_t match;
+
+       if (f->flags & AS_FLAG_AS_SET_NAME)     /* should not happen */
+               return (0);
+       if (f->flags & AS_FLAG_AS_SET)
+               return (as_set_match(f->aset, as));
+
+       if (f->flags & AS_FLAG_NEIGHBORAS)
+               match = neighas;
+       else
+               match = f->as_min;
+
+       switch (f->op) {
+       case OP_NONE:
+       case OP_EQ:
+               if (as == match)
+                       return (1);
+               break;
+       case OP_NE:
+               if (as != match)
+                       return (1);
+               break;
+       case OP_RANGE:
+               if (as >= f->as_min && as <= f->as_max)
+                       return (1);
+               break;
+       case OP_XRANGE:
+               if (as < f->as_min || as > f->as_max)
+                       return (1);
+               break;
+       }
+       return (0);
+}
+
+/* we need to be able to search more than one as */
+int
+aspath_match(struct aspath *aspath, struct filter_as *f, u_int32_t neighas)
+{
+       const u_int8_t  *seg;
+       int              final;
+       u_int16_t        len, seg_size;
+       u_int8_t         i, seg_len;
+       u_int32_t        as = AS_NONE;
+
+       if (f->type == AS_EMPTY) {
+               if (aspath_length(aspath) == 0)
+                       return (1);
+               else
+                       return (0);
+       }
+
+       /* just check the leftmost AS */
+       if (f->type == AS_PEER) {
+               as = aspath_neighbor(aspath);
+               if (as_compare(f, as, neighas))
+                       return (1);
+               else
+                       return (0);
+       }
+
+       seg = aspath->data;
+       len = aspath->len;
+       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);
+
+               if (f->type == AS_SOURCE) {
+                       /*
+                        * Just extract the rightmost AS
+                        * but if that segment is an AS_SET then the rightmost
+                        * AS of a previous AS_SEQUENCE segment should be used.
+                        * Because of that just look at AS_SEQUENCE segments.
+                        */
+                       if (seg[0] == AS_SEQUENCE)
+                               as = aspath_extract(seg, seg_len - 1);
+                       /* not yet in the final segment */
+                       if (!final)
+                               continue;
+                       if (as_compare(f, as, neighas))
+                               return (1);
+                       else
+                               return (0);
+               }
+               /* AS_TRANSIT or AS_ALL */
+               for (i = 0; i < seg_len; i++) {
+                       /*
+                        * the source (rightmost) AS is excluded from
+                        * AS_TRANSIT matches.
+                        */
+                       if (final && i == seg_len - 1 && f->type == AS_TRANSIT)
+                               return (0);
+                       as = aspath_extract(seg, i);
+                       if (as_compare(f, as, neighas))
+                               return (1);
+               }
+       }
+       return (0);
+}
 
 /*
  * Returns a new prepended aspath. Old needs to be freed by caller.
Index: usr.sbin/bgpd/rde_filter.c
===================================================================
RCS file: /cvs/src/usr.sbin/bgpd/rde_filter.c,v
retrieving revision 1.114
diff -u -p -r1.114 rde_filter.c
--- usr.sbin/bgpd/rde_filter.c  28 Nov 2018 08:32:27 -0000      1.114
+++ usr.sbin/bgpd/rde_filter.c  28 Nov 2018 09:10:02 -0000
@@ -219,8 +219,8 @@ rde_filter_match(struct filter_rule *f, 
        }
 
        if (asp != NULL && f->match.as.type != AS_UNDEF) {
-               if (aspath_match(asp->aspath->data, asp->aspath->len,
-                   &f->match.as, peer->conf.remote_as) == 0)
+               if (aspath_match(asp->aspath, &f->match.as,
+                   peer->conf.remote_as) == 0)
                        return (0);
        }
 
@@ -289,7 +289,7 @@ rde_filter_match(struct filter_rule *f, 
                pt_getaddr(p->re->prefix, prefix);
                plen = p->re->prefix->prefixlen;
                if (trie_roa_check(&f->match.originset.ps->th, prefix, plen,
-                   asp->source_as) != ROA_VALID)
+                   aspath_origin(asp->aspath)) != ROA_VALID)
                        return (0);
        }
 
Index: usr.sbin/bgpd/rde_rib.c
===================================================================
RCS file: /cvs/src/usr.sbin/bgpd/rde_rib.c,v
retrieving revision 1.186
diff -u -p -r1.186 rde_rib.c
--- usr.sbin/bgpd/rde_rib.c     14 Nov 2018 12:14:41 -0000      1.186
+++ usr.sbin/bgpd/rde_rib.c     23 Nov 2018 14:41:47 -0000
@@ -657,10 +657,6 @@ path_compare(struct rde_aspath *a, struc
                return (1);
        if (a->pftableid < b->pftableid)
                return (-1);
-       if (a->source_as > b->source_as)
-               return (1);
-       if (a->source_as < b->source_as)
-               return (-1);
 
        r = aspath_compare(a->aspath, b->aspath);
        if (r > 0)
@@ -761,7 +757,6 @@ path_copy(struct rde_aspath *dst, const 
        dst->lpref = src->lpref;
        dst->weight = src->weight;
        dst->origin = src->origin;
-       dst->source_as = src->source_as;
        dst->rtlabelid = rtlabel_ref(src->rtlabelid);
        dst->pftableid = pftable_ref(src->pftableid);
 
Index: usr.sbin/bgpd/util.c
===================================================================
RCS file: /cvs/src/usr.sbin/bgpd/util.c,v
retrieving revision 1.40
diff -u -p -r1.40 util.c
--- usr.sbin/bgpd/util.c        26 Sep 2018 14:38:19 -0000      1.40
+++ usr.sbin/bgpd/util.c        23 Nov 2018 14:41:47 -0000
@@ -312,110 +312,6 @@ 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 neighas)
-{
-       u_int32_t match;
-
-       if (f->flags & AS_FLAG_AS_SET_NAME)     /* should not happen */
-               return (0);
-       if (f->flags & AS_FLAG_AS_SET)
-               return (as_set_match(f->aset, as));
-
-       if (f->flags & AS_FLAG_NEIGHBORAS)
-               match = neighas;
-       else
-               match = f->as_min;
-
-       switch (f->op) {
-       case OP_NONE:
-       case OP_EQ:
-               if (as == match)
-                       return (1);
-               break;
-       case OP_NE:
-               if (as != match)
-                       return (1);
-               break;
-       case OP_RANGE:
-               if (as >= f->as_min && as <= f->as_max)
-                       return (1);
-               break;
-       case OP_XRANGE:
-               if (as < f->as_min || as > f->as_max)
-                       return (1);
-               break;
-       }
-       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 neighas)
-{
-       u_int8_t        *seg;
-       int              final;
-       u_int16_t        seg_size;
-       u_int8_t         i, seg_len;
-       u_int32_t        as = 0;
-
-       if (f->type == AS_EMPTY) {
-               if (len == 0)
-                       return (1);
-               else
-                       return (0);
-       }
-
-       seg = data;
-
-       /* just check the leftmost AS */
-       if (f->type == AS_PEER && len >= 6) {
-               as = aspath_extract(seg, 0);
-               if (as_compare(f, as, neighas))
-                       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);
-
-               if (f->type == AS_SOURCE) {
-                       /*
-                        * Just extract the rightmost AS
-                        * but if that segment is an AS_SET then the rightmost
-                        * AS of a previous AS_SEQUENCE segment should be used.
-                        * Because of that just look at AS_SEQUENCE segments.
-                        */
-                       if (seg[0] == AS_SEQUENCE)
-                               as = aspath_extract(seg, seg_len - 1);
-                       /* not yet in the final segment */
-                       if (!final)
-                               continue;
-                       if (as_compare(f, as, neighas))
-                               return (1);
-                       else
-                               return (0);
-               }
-               /* AS_TRANSIT or AS_ALL */
-               for (i = 0; i < seg_len; i++) {
-                       /*
-                        * the source (rightmost) AS is excluded from
-                        * AS_TRANSIT matches.
-                        */
-                       if (final && i == seg_len - 1 && f->type == AS_TRANSIT)
-                               return (0);
-                       as = aspath_extract(seg, i);
-                       if (as_compare(f, as, neighas))
-                               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.

Reply via email to