Claudio Jeker(cje...@diehard.n-r-g.com) on 2018.07.18 21:59:44 +0200:
> This is the next small bit of rde rebuilding.
> 
> Move nexthop into struct filterstate (including nexthop flags) and use
> them whereever possible. In some places (path_update, softreconfig_out
> handler) the nexthop state are folded back into the rde_aspath.
> This also fixes a possible crash when it comes to nexthop filtering.
> 
> -- 
> :wq Claudio


reads good, also tested.

ok benno@

> 
> 
> ? obj
> Index: rde.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/bgpd/rde.c,v
> retrieving revision 1.394
> diff -u -p -r1.394 rde.c
> --- rde.c     16 Jul 2018 09:09:20 -0000      1.394
> +++ rde.c     18 Jul 2018 19:52:26 -0000
> @@ -998,7 +998,7 @@ rde_update_dispatch(struct imsg *imsg)
>           imsg->hdr.len - IMSG_HEADER_SIZE - 4 - withdrawn_len - attrpath_len;
>       bzero(&mpa, sizeof(mpa));
>  
> -     rde_filterstate_prep(&state, NULL);
> +     rde_filterstate_prep(&state, NULL, NULL);
>       if (attrpath_len != 0) { /* 0 = no NLRI information in this message */
>               /* parse path attributes */
>               while (len > 0) {
> @@ -1221,14 +1221,9 @@ rde_update_dispatch(struct imsg *imsg)
>                       goto done;
>               }
>  
> -             /*
> -              * this works because asp is not linked.
> -              * But first unlock the previously locked nexthop.
> -              */
> -             if (state.aspath.nexthop) {
> -                     (void)nexthop_put(state.aspath.nexthop);
> -                     state.aspath.nexthop = NULL;
> -             }
> +             /* unlock the previously locked nexthop, it is no longer used */
> +             (void)nexthop_put(state.nexthop);
> +             state.nexthop = NULL;
>               if ((pos = rde_get_mp_nexthop(mpp, mplen, aid, &state)) == -1) {
>                       log_peer_warnx(&peer->conf, "bad nlri prefix");
>                       rde_update_err(peer, ERR_UPDATE, ERR_UPD_OPTATTR,
> @@ -1318,13 +1313,13 @@ rde_update_update(struct rde_peer *peer,
>       for (i = RIB_LOC_START; i < rib_size; i++) {
>               if (*ribs[i].name == '\0')
>                       break;
> -             rde_filterstate_prep(&state, &in->aspath);
> +             rde_filterstate_prep(&state, &in->aspath, in->nexthop);
>               /* input filter */
>               action = rde_filter(ribs[i].in_rules, peer, p, &state);
>  
>               if (action == ACTION_ALLOW) {
>                       rde_update_log("update", i, peer,
> -                         &state.aspath.nexthop->exit_nexthop, prefix,
> +                         &state.nexthop->exit_nexthop, prefix,
>                           prefixlen);
>                       path_update(&ribs[i].rib, peer, &state, prefix,
>                           prefixlen, 0);
> @@ -1499,7 +1494,8 @@ bad_flags:
>                           op, len);
>                       return (-1);
>               }
> -             a->nexthop = nexthop_get(&nexthop);
> +             nexthop_put(state->nexthop);    /* just to be sure */
> +             state->nexthop = nexthop_get(&nexthop);
>               break;
>       case ATTR_MED:
>               if (attr_len != 4)
> @@ -1832,7 +1828,8 @@ rde_get_mp_nexthop(u_char *data, u_int16
>               return (-1);
>       }
>  
> -     state->aspath.nexthop = nexthop_get(&nexthop);
> +     nexthop_put(state->nexthop);    /* just to be sure */
> +     state->nexthop = nexthop_get(&nexthop);
>  
>       /* ignore reserved (old SNPA) field as per RFC4760 */
>       totlen += nhlen + 1;
> @@ -2251,7 +2248,7 @@ rde_dump_filterout(struct rde_peer *peer
>       if (up_test_update(peer, p) != 1)
>               return;
>  
> -     rde_filterstate_prep(&state, prefix_aspath(p));
> +     rde_filterstate_prep(&state, prefix_aspath(p), prefix_nexthop(p));
>       a = rde_filter(out_rules, peer, p, &state);
>  
>       if (a == ACTION_ALLOW)
> @@ -3006,7 +3003,7 @@ rde_softreconfig_in(struct rib_entry *re
>               asp = prefix_aspath(p);
>               peer = asp->peer;
>  
> -             rde_filterstate_prep(&state, asp);
> +             rde_filterstate_prep(&state, asp, prefix_nexthop(p));
>               action = rde_filter(rib->in_rules, peer, p, &state);
>  
>               if (action == ACTION_ALLOW) {
> @@ -3044,8 +3041,8 @@ rde_softreconfig_out(struct rib_entry *r
>       if (up_test_update(peer, p) != 1)
>               return;
>  
> -     rde_filterstate_prep(&ostate, prefix_aspath(p));
> -     rde_filterstate_prep(&nstate, prefix_aspath(p));
> +     rde_filterstate_prep(&ostate, prefix_aspath(p), prefix_nexthop(p));
> +     rde_filterstate_prep(&nstate, prefix_aspath(p), prefix_nexthop(p));
>       oa = rde_filter(out_rules_tmp, peer, p, &ostate);
>       na = rde_filter(out_rules, peer, p, &nstate);
>  
> @@ -3054,14 +3051,23 @@ rde_softreconfig_out(struct rib_entry *r
>               /* nothing todo */
>       if (oa == ACTION_DENY && na == ACTION_ALLOW) {
>               /* send update */
> -             up_generate(peer, &nstate.aspath, &addr, pt->prefixlen);
> +             up_generate(peer, &nstate, &addr, pt->prefixlen);
>       } else if (oa == ACTION_ALLOW && na == ACTION_DENY) {
>               /* send withdraw */
>               up_generate(peer, NULL, &addr, pt->prefixlen);
>       } else if (oa == ACTION_ALLOW && na == ACTION_ALLOW) {
> +             /* XXX update nexthop for now, ugly but will go away */
> +             nexthop_put(nstate.aspath.nexthop);
> +             nstate.aspath.nexthop = nexthop_ref(nstate.nexthop);
> +             nstate.aspath.flags = (nstate.aspath.flags & ~F_NEXTHOP_MASK) |
> +                 (nstate.nhflags & F_NEXTHOP_MASK);
> +             nexthop_put(ostate.aspath.nexthop);
> +             ostate.aspath.nexthop = nexthop_ref(ostate.nexthop);
> +             ostate.aspath.flags = (ostate.aspath.flags & ~F_NEXTHOP_MASK) |
> +                 (ostate.nhflags & F_NEXTHOP_MASK);
>               /* send update if path attributes changed */
>               if (path_compare(&nstate.aspath, &ostate.aspath) != 0)
> -                     up_generate(peer, &nstate.aspath, &addr, pt->prefixlen);
> +                     up_generate(peer, &nstate, &addr, pt->prefixlen);
>       }
>  
>       rde_filterstate_clean(&ostate);
> @@ -3084,7 +3090,7 @@ rde_softreconfig_unload_peer(struct rib_
>       if (up_test_update(peer, p) != 1)
>               return;
>  
> -     rde_filterstate_prep(&ostate, prefix_aspath(p));
> +     rde_filterstate_prep(&ostate, prefix_aspath(p), prefix_nexthop(p));
>       if (rde_filter(out_rules_tmp, peer, p, &ostate) != ACTION_DENY) {
>               /* send withdraw */
>               up_generate(peer, NULL, &addr, pt->prefixlen);
> @@ -3559,7 +3565,7 @@ network_add(struct network_config *nc, i
>       }
>       if (!flagstatic)
>               asp->flags |= F_ANN_DYNAMIC;
> -     rde_filterstate_prep(&state, asp);
> +     rde_filterstate_prep(&state, asp, NULL); /* nexthop is not set */
>       rde_apply_set(&nc->attrset, &state, nc->prefix.aid, peerself, peerself);
>       if (vpnset)
>               rde_apply_set(vpnset, &state, nc->prefix.aid, peerself,
> Index: rde.h
> ===================================================================
> RCS file: /cvs/src/usr.sbin/bgpd/rde.h,v
> retrieving revision 1.179
> diff -u -p -r1.179 rde.h
> --- rde.h     16 Jul 2018 09:09:20 -0000      1.179
> +++ rde.h     18 Jul 2018 19:52:26 -0000
> @@ -316,6 +316,8 @@ struct prefix {
>  
>  struct filterstate {
>       struct rde_aspath       aspath;
> +     struct nexthop          *nexthop;
> +     unsigned int            nhflags;
>  };
>  
>  extern struct rde_memstats rdemem;
> @@ -405,7 +407,7 @@ u_char            *community_ext_delete_non_trans(
>  void          prefix_evaluate(struct prefix *, struct rib_entry *);
>  
>  /* rde_filter.c */
> -void          rde_filterstate_prep(struct filterstate *, struct rde_aspath 
> *);
> +void          rde_filterstate_prep(struct filterstate *, struct rde_aspath 
> *,                    struct nexthop *);
>  void          rde_filterstate_clean(struct filterstate *);
>  enum filter_actions rde_filter(struct filter_head *, struct rde_peer *,
>                    struct prefix *, struct filterstate *);
> @@ -506,6 +508,12 @@ prefix_aspath(struct prefix *p)
>       return (p->aspath);
>  }
>  
> +static inline struct nexthop *
> +prefix_nexthop(struct prefix *p)
> +{
> +     return (p->aspath->nexthop);
> +}
> +
>  static inline struct rde_peer *
>  prefix_peer(struct prefix *p)
>  {
> @@ -528,7 +536,7 @@ int                nexthop_compare(struct nexthop *, 
>  void          up_init(struct rde_peer *);
>  void          up_down(struct rde_peer *);
>  int           up_test_update(struct rde_peer *, struct prefix *);
> -int           up_generate(struct rde_peer *, struct rde_aspath *,
> +int           up_generate(struct rde_peer *, struct filterstate *,
>                    struct bgpd_addr *, u_int8_t);
>  void          up_generate_updates(struct filter_head *, struct rde_peer *,
>                    struct prefix *, struct prefix *);
> Index: rde_filter.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/bgpd/rde_filter.c,v
> retrieving revision 1.96
> diff -u -p -r1.96 rde_filter.c
> --- rde_filter.c      16 Jul 2018 09:09:20 -0000      1.96
> +++ rde_filter.c      18 Jul 2018 19:52:26 -0000
> @@ -30,7 +30,7 @@
>  #include "log.h"
>  
>  int  rde_filter_match(struct filter_rule *, struct rde_peer *,
> -         struct rde_aspath *, struct prefix *);
> +         struct filterstate *, struct prefix *);
>  int  rde_prefix_match(struct filter_prefix *, struct prefix *);
>  int  filterset_equal(struct filter_set_head *, struct filter_set_head *);
>  
> @@ -139,7 +139,7 @@ rde_apply_set(struct filter_set_head *sh
>               case ACTION_SET_NEXTHOP_NOMODIFY:
>               case ACTION_SET_NEXTHOP_SELF:
>                       nexthop_modify(set->action.nh, set->type, aid,
> -                         &state->aspath.nexthop, &state->aspath.flags);
> +                         &state->nexthop, &state->nhflags);
>                       break;
>               case ACTION_SET_COMMUNITY:
>                       switch (set->action.community.as) {
> @@ -338,12 +338,16 @@ rde_apply_set(struct filter_set_head *sh
>  
>  int
>  rde_filter_match(struct filter_rule *f, struct rde_peer *peer,
> -    struct rde_aspath *asp, struct prefix *p)
> +    struct filterstate *state, struct prefix *p)
>  {
>       u_int32_t       pas;
>       int             cas, type;
>       int64_t         las, ld1, ld2;
> -     struct prefixset_item *psi;
> +     struct prefixset_item   *psi;
> +     struct rde_aspath       *asp = NULL;
> +
> +     if (state != NULL)
> +             asp = &state->aspath;
>  
>       if (asp != NULL && f->match.as.type != AS_NONE) {
>               if (f->match.as.flags & AS_FLAG_NEIGHBORAS)
> @@ -355,10 +359,10 @@ rde_filter_match(struct filter_rule *f, 
>                       return (0);
>       }
>  
> -     if (asp != NULL && f->peer.ebgp && !peer->conf.ebgp)
> -                     return (0);
> -     if (asp != NULL && f->peer.ibgp && peer->conf.ebgp)
> -                     return (0);
> +     if (f->peer.ebgp && !peer->conf.ebgp)
> +             return (0);
> +     if (f->peer.ibgp && peer->conf.ebgp)
> +             return (0);
>  
>       if (asp != NULL && f->match.aslen.type != ASLEN_NONE)
>               if (aspath_lenmatch(asp->aspath, f->match.aslen.type,
> @@ -450,12 +454,12 @@ rde_filter_match(struct filter_rule *f, 
>                       return (0);
>       }
>  
> -     if (f->match.nexthop.flags != 0) {
> +     if (state != NULL && f->match.nexthop.flags != 0) {
>               struct bgpd_addr *nexthop, *cmpaddr;
> -             if (asp != NULL && asp->nexthop == NULL)
> +             if (state->nexthop == NULL)
>                       /* no nexthop, skip */
>                       return (0);
> -             nexthop = &asp->nexthop->exit_nexthop;
> +             nexthop = &state->nexthop->exit_nexthop;
>               if (f->match.nexthop.flags == FILTER_NEXTHOP_ADDR)
>                       cmpaddr = &f->match.nexthop.addr;
>               else
> @@ -635,19 +639,26 @@ rde_filter_equal(struct filter_head *a, 
>  }
>  
>  void
> -rde_filterstate_prep(struct filterstate *state, struct rde_aspath *asp)
> +rde_filterstate_prep(struct filterstate *state, struct rde_aspath *asp,
> +    struct nexthop *nh)
>  {
>       memset(state, 0, sizeof(*state));
>  
>       path_prep(&state->aspath);
>       if (asp)
>               path_copy(&state->aspath, asp);
> +     state->nexthop = nexthop_ref(nh);
> +     /* XXX the flag handling needs improvement */
> +     if (asp)
> +             state->nhflags |= asp->flags & F_NEXTHOP_MASK;
>  }
>  
>  void
>  rde_filterstate_clean(struct filterstate *state)
>  {
>       path_clean(&state->aspath);
> +     nexthop_put(state->nexthop);
> +     state->nexthop = NULL;
>  }
>  
>  void
> @@ -1007,10 +1018,9 @@ rde_filter(struct filter_head *rules, st
>      struct prefix *p, struct filterstate *state)
>  {
>       struct filter_rule      *f;
> -     struct rde_aspath       *asp = prefix_aspath(p);
>       enum filter_actions      action = ACTION_DENY; /* default deny */
>  
> -     if (asp->flags & F_ATTR_PARSE_ERR)
> +     if (state && state->aspath.flags & F_ATTR_PARSE_ERR)
>               /*
>                * don't try to filter bad updates just deny them
>                * so they act as implicit withdraws
> @@ -1035,7 +1045,7 @@ rde_filter(struct filter_head *rules, st
>                    f->peer.peerid != peer->conf.id),
>                    f->skip[RDE_FILTER_SKIP_PEERID].ptr);
>  
> -             if (rde_filter_match(f, peer, asp, p)) {
> +             if (rde_filter_match(f, peer, state, p)) {
>                       if (state != NULL) {
>                               rde_apply_set(&f->set, state,
>                                   p->re->prefix->aid, prefix_peer(p), peer);
> Index: rde_rib.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/bgpd/rde_rib.c,v
> retrieving revision 1.171
> diff -u -p -r1.171 rde_rib.c
> --- rde_rib.c 16 Jul 2018 09:09:20 -0000      1.171
> +++ rde_rib.c 18 Jul 2018 19:52:27 -0000
> @@ -423,6 +423,11 @@ path_update(struct rib *rib, struct rde_
>       struct prefix           *p;
>       int                      pflag = 0;
>  
> +     nexthop_put(nasp->nexthop);
> +     nasp->nexthop = nexthop_ref(state->nexthop);
> +     nasp->flags = (nasp->flags & ~F_NEXTHOP_MASK) |
> +         (state->nhflags & F_NEXTHOP_MASK);
> +
>       if (nasp->pftableid) {
>               rde_send_pftable(nasp->pftableid, prefix, prefixlen, 0);
>               rde_send_pftable_commit();
> @@ -1467,4 +1472,3 @@ nexthop_hash(struct bgpd_addr *nexthop)
>       }
>       return (&nexthoptable.nexthop_hashtbl[h & 
> nexthoptable.nexthop_hashmask]);
>  }
> -
> Index: rde_update.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/bgpd/rde_update.c,v
> retrieving revision 1.94
> diff -u -p -r1.94 rde_update.c
> --- rde_update.c      9 Jul 2018 14:08:48 -0000       1.94
> +++ rde_update.c      18 Jul 2018 19:52:27 -0000
> @@ -27,11 +27,11 @@
>  #include "rde.h"
>  #include "log.h"
>  
> -in_addr_t    up_get_nexthop(struct rde_peer *, struct rde_aspath *);
> +in_addr_t    up_get_nexthop(struct rde_peer *, struct filterstate *);
>  int          up_generate_mp_reach(struct rde_peer *, struct update_attr *,
> -                 struct rde_aspath *, u_int8_t);
> +                 struct filterstate *, u_int8_t);
>  int          up_generate_attr(struct rde_peer *, struct update_attr *,
> -                 struct rde_aspath *, u_int8_t);
> +                 struct filterstate *, u_int8_t);
>  
>  /* update stuff. */
>  struct update_prefix {
> @@ -354,19 +354,19 @@ up_test_update(struct rde_peer *peer, st
>  }
>  
>  int
> -up_generate(struct rde_peer *peer, struct rde_aspath *asp,
> +up_generate(struct rde_peer *peer, struct filterstate *state,
>      struct bgpd_addr *addr, u_int8_t prefixlen)
>  {
>       struct update_attr              *ua = NULL;
>       struct update_prefix            *up;
>       SIPHASH_CTX                     ctx;
>  
> -     if (asp) {
> +     if (state) {
>               ua = calloc(1, sizeof(struct update_attr));
>               if (ua == NULL)
>                       fatal("up_generate");
>  
> -             if (up_generate_attr(peer, ua, asp, addr->aid) == -1) {
> +             if (up_generate_attr(peer, ua, state, addr->aid) == -1) {
>                       log_warnx("generation of bgp path attributes failed");
>                       free(ua);
>                       return (-1);
> @@ -425,14 +425,15 @@ withdraw:
>                       return;
>               }
>  
> -             rde_filterstate_prep(&state, prefix_aspath(new));
> +             rde_filterstate_prep(&state, prefix_aspath(new),
> +                 prefix_nexthop(new));
>               if (rde_filter(rules, peer, new, &state) == ACTION_DENY) {
>                       rde_filterstate_clean(&state);
>                       goto withdraw;
>               }
>  
>               pt_getaddr(new->re->prefix, &addr);
> -             up_generate(peer, &state.aspath, &addr,
> +             up_generate(peer, &state, &addr,
>                   new->re->prefix->prefixlen);
>  
>               rde_filterstate_clean(&state);
> @@ -484,13 +485,13 @@ up_generate_default(struct filter_head *
>       p.flags = 0;
>  
>       /* filter as usual */
> -     rde_filterstate_prep(&state, asp);
> +     rde_filterstate_prep(&state, asp, NULL);
>       if (rde_filter(rules, peer, &p, &state) == ACTION_DENY) {
>               rde_filterstate_clean(&state);
>               return;
>       }
>  
> -     up_generate(peer, &state.aspath, &addr, 0);
> +     up_generate(peer, &state, &addr, 0);
>  
>       /* no longer needed */
>       rde_filterstate_clean(&state);
> @@ -541,27 +542,27 @@ u_char  up_attr_buf[4096];
>  
>  /* only for IPv4 */
>  in_addr_t
> -up_get_nexthop(struct rde_peer *peer, struct rde_aspath *a)
> +up_get_nexthop(struct rde_peer *peer, struct filterstate *state)
>  {
>       in_addr_t       mask;
>  
>       /* nexthop, already network byte order */
> -     if (a->flags & F_NEXTHOP_NOMODIFY) {
> +     if (state->nhflags & F_NEXTHOP_NOMODIFY) {
>               /* no modify flag set */
> -             if (a->nexthop == NULL)
> +             if (state->nexthop == NULL)
>                       return (peer->local_v4_addr.v4.s_addr);
>               else
> -                     return (a->nexthop->exit_nexthop.v4.s_addr);
> -     } else if (a->flags & F_NEXTHOP_SELF)
> +                     return (state->nexthop->exit_nexthop.v4.s_addr);
> +     } else if (state->nhflags & F_NEXTHOP_SELF)
>               return (peer->local_v4_addr.v4.s_addr);
>       else if (!peer->conf.ebgp) {
>               /*
>                * If directly connected use peer->local_v4_addr
>                * this is only true for announced networks.
>                */
> -             if (a->nexthop == NULL)
> +             if (state->nexthop == NULL)
>                       return (peer->local_v4_addr.v4.s_addr);
> -             else if (a->nexthop->exit_nexthop.v4.s_addr ==
> +             else if (state->nexthop->exit_nexthop.v4.s_addr ==
>                   peer->remote_addr.v4.s_addr)
>                       /*
>                        * per RFC: if remote peer address is equal to
> @@ -570,17 +571,17 @@ up_get_nexthop(struct rde_peer *peer, st
>                        */
>                       return (peer->local_v4_addr.v4.s_addr);
>               else
> -                     return (a->nexthop->exit_nexthop.v4.s_addr);
> +                     return (state->nexthop->exit_nexthop.v4.s_addr);
>       } else if (peer->conf.distance == 1) {
>               /* ebgp directly connected */
> -             if (a->nexthop != NULL &&
> -                 a->nexthop->flags & NEXTHOP_CONNECTED) {
> +             if (state->nexthop != NULL &&
> +                 state->nexthop->flags & NEXTHOP_CONNECTED) {
>                       mask = htonl(
> -                         prefixlen2mask(a->nexthop->nexthop_netlen));
> +                         prefixlen2mask(state->nexthop->nexthop_netlen));
>                       if ((peer->remote_addr.v4.s_addr & mask) ==
> -                         (a->nexthop->nexthop_net.v4.s_addr & mask))
> +                         (state->nexthop->nexthop_net.v4.s_addr & mask))
>                               /* nexthop and peer are in the same net */
> -                             return (a->nexthop->exit_nexthop.v4.s_addr);
> +                             return (state->nexthop->exit_nexthop.v4.s_addr);
>                       else
>                               return (peer->local_v4_addr.v4.s_addr);
>               } else
> @@ -597,7 +598,7 @@ up_get_nexthop(struct rde_peer *peer, st
>  
>  int
>  up_generate_mp_reach(struct rde_peer *peer, struct update_attr *upa,
> -    struct rde_aspath *a, u_int8_t aid)
> +    struct filterstate *state, u_int8_t aid)
>  {
>       u_int16_t       tmp;
>  
> @@ -615,43 +616,43 @@ up_generate_mp_reach(struct rde_peer *pe
>               upa->mpattr[20] = 0; /* Reserved must be 0 */
>  
>               /* nexthop dance see also up_get_nexthop() */
> -             if (a->flags & F_NEXTHOP_NOMODIFY) {
> +             if (state->nhflags & F_NEXTHOP_NOMODIFY) {
>                       /* no modify flag set */
> -                     if (a->nexthop == NULL)
> +                     if (state->nexthop == NULL)
>                               memcpy(&upa->mpattr[4], &peer->local_v6_addr.v6,
>                                   sizeof(struct in6_addr));
>                       else
>                               memcpy(&upa->mpattr[4],
> -                                 &a->nexthop->exit_nexthop.v6,
> +                                 &state->nexthop->exit_nexthop.v6,
>                                   sizeof(struct in6_addr));
> -             } else if (a->flags & F_NEXTHOP_SELF)
> +             } else if (state->nhflags & F_NEXTHOP_SELF)
>                       memcpy(&upa->mpattr[4], &peer->local_v6_addr.v6,
>                           sizeof(struct in6_addr));
>               else if (!peer->conf.ebgp) {
>                       /* ibgp */
> -                     if (a->nexthop == NULL ||
> -                         (a->nexthop->exit_nexthop.aid == AID_INET6 &&
> -                         !memcmp(&a->nexthop->exit_nexthop.v6,
> +                     if (state->nexthop == NULL ||
> +                         (state->nexthop->exit_nexthop.aid == AID_INET6 &&
> +                         !memcmp(&state->nexthop->exit_nexthop.v6,
>                           &peer->remote_addr.v6, sizeof(struct in6_addr))))
>                               memcpy(&upa->mpattr[4], &peer->local_v6_addr.v6,
>                                   sizeof(struct in6_addr));
>                       else
>                               memcpy(&upa->mpattr[4],
> -                                 &a->nexthop->exit_nexthop.v6,
> +                                 &state->nexthop->exit_nexthop.v6,
>                                   sizeof(struct in6_addr));
>               } else if (peer->conf.distance == 1) {
>                       /* ebgp directly connected */
> -                     if (a->nexthop != NULL &&
> -                         a->nexthop->flags & NEXTHOP_CONNECTED)
> +                     if (state->nexthop != NULL &&
> +                         state->nexthop->flags & NEXTHOP_CONNECTED)
>                               if (prefix_compare(&peer->remote_addr,
> -                                 &a->nexthop->nexthop_net,
> -                                 a->nexthop->nexthop_netlen) == 0) {
> +                                 &state->nexthop->nexthop_net,
> +                                 state->nexthop->nexthop_netlen) == 0) {
>                                       /*
>                                        * nexthop and peer are in the same
>                                        * subnet
>                                        */
>                                       memcpy(&upa->mpattr[4],
> -                                         &a->nexthop->exit_nexthop.v6,
> +                                         &state->nexthop->exit_nexthop.v6,
>                                           sizeof(struct in6_addr));
>                                       return (0);
>                               }
> @@ -674,46 +675,46 @@ up_generate_mp_reach(struct rde_peer *pe
>               upa->mpattr[3] = sizeof(u_int64_t) + sizeof(struct in_addr);
>  
>               /* nexthop dance see also up_get_nexthop() */
> -             if (a->flags & F_NEXTHOP_NOMODIFY) {
> +             if (state->nhflags & F_NEXTHOP_NOMODIFY) {
>                       /* no modify flag set */
> -                     if (a->nexthop == NULL)
> +                     if (state->nexthop == NULL)
>                               memcpy(&upa->mpattr[12],
>                                   &peer->local_v4_addr.v4,
>                                   sizeof(struct in_addr));
>                       else
>                               /* nexthops are stored as IPv4 addrs */
>                               memcpy(&upa->mpattr[12],
> -                                 &a->nexthop->exit_nexthop.v4,
> +                                 &state->nexthop->exit_nexthop.v4,
>                                   sizeof(struct in_addr));
> -             } else if (a->flags & F_NEXTHOP_SELF)
> +             } else if (state->nhflags & F_NEXTHOP_SELF)
>                       memcpy(&upa->mpattr[12], &peer->local_v4_addr.v4,
>                           sizeof(struct in_addr));
>               else if (!peer->conf.ebgp) {
>                       /* ibgp */
> -                     if (a->nexthop == NULL ||
> -                         (a->nexthop->exit_nexthop.aid == AID_INET &&
> -                         !memcmp(&a->nexthop->exit_nexthop.v4,
> +                     if (state->nexthop == NULL ||
> +                         (state->nexthop->exit_nexthop.aid == AID_INET &&
> +                         !memcmp(&state->nexthop->exit_nexthop.v4,
>                           &peer->remote_addr.v4, sizeof(struct in_addr))))
>                               memcpy(&upa->mpattr[12],
>                                   &peer->local_v4_addr.v4,
>                                   sizeof(struct in_addr));
>                       else
>                               memcpy(&upa->mpattr[12],
> -                                 &a->nexthop->exit_nexthop.v4,
> +                                 &state->nexthop->exit_nexthop.v4,
>                                   sizeof(struct in_addr));
>               } else if (peer->conf.distance == 1) {
>                       /* ebgp directly connected */
> -                     if (a->nexthop != NULL &&
> -                         a->nexthop->flags & NEXTHOP_CONNECTED)
> +                     if (state->nexthop != NULL &&
> +                         state->nexthop->flags & NEXTHOP_CONNECTED)
>                               if (prefix_compare(&peer->remote_addr,
> -                                 &a->nexthop->nexthop_net,
> -                                 a->nexthop->nexthop_netlen) == 0) {
> +                                 &state->nexthop->nexthop_net,
> +                                 state->nexthop->nexthop_netlen) == 0) {
>                                       /*
>                                        * nexthop and peer are in the same
>                                        * subnet
>                                        */
>                                       memcpy(&upa->mpattr[12],
> -                                         &a->nexthop->exit_nexthop.v4,
> +                                         &state->nexthop->exit_nexthop.v4,
>                                           sizeof(struct in_addr));
>                                       return (0);
>                               }
> @@ -732,8 +733,9 @@ up_generate_mp_reach(struct rde_peer *pe
>  
>  int
>  up_generate_attr(struct rde_peer *peer, struct update_attr *upa,
> -    struct rde_aspath *a, u_int8_t aid)
> +    struct filterstate *state, u_int8_t aid)
>  {
> +     struct rde_aspath *asp = &state->aspath;
>       struct attr     *oa, *newaggr = NULL;
>       u_char          *pdata;
>       u_int32_t        tmp32;
> @@ -746,17 +748,17 @@ up_generate_attr(struct rde_peer *peer, 
>  
>       /* origin */
>       if ((r = attr_write(up_attr_buf + wlen, len, ATTR_WELL_KNOWN,
> -         ATTR_ORIGIN, &a->origin, 1)) == -1)
> +         ATTR_ORIGIN, &asp->origin, 1)) == -1)
>               return (-1);
>       wlen += r; len -= r;
>  
>       /* aspath */
>       if (!peer->conf.ebgp ||
>           peer->conf.flags & PEERFLAG_TRANS_AS)
> -             pdata = aspath_prepend(a->aspath, peer->conf.local_as, 0,
> +             pdata = aspath_prepend(asp->aspath, peer->conf.local_as, 0,
>                   &plen);
>       else
> -             pdata = aspath_prepend(a->aspath, peer->conf.local_as, 1,
> +             pdata = aspath_prepend(asp->aspath, peer->conf.local_as, 1,
>                   &plen);
>  
>       if (!rde_as4byte(peer))
> @@ -770,7 +772,7 @@ up_generate_attr(struct rde_peer *peer, 
>  
>       switch (aid) {
>       case AID_INET:
> -             nexthop = up_get_nexthop(peer, a);
> +             nexthop = up_get_nexthop(peer, state);
>               if ((r = attr_write(up_attr_buf + wlen, len, ATTR_WELL_KNOWN,
>                   ATTR_NEXTHOP, &nexthop, 4)) == -1)
>                       return (-1);
> @@ -786,10 +788,10 @@ up_generate_attr(struct rde_peer *peer, 
>        * unless the MED is originating from us or the peer is an IBGP one.
>        * Only exception are routers with "transparent-as yes" set.
>        */
> -     if (a->flags & F_ATTR_MED && (!peer->conf.ebgp ||
> -         a->flags & F_ATTR_MED_ANNOUNCE ||
> +     if (asp->flags & F_ATTR_MED && (!peer->conf.ebgp ||
> +         asp->flags & F_ATTR_MED_ANNOUNCE ||
>           peer->conf.flags & PEERFLAG_TRANS_AS)) {
> -             tmp32 = htonl(a->med);
> +             tmp32 = htonl(asp->med);
>               if ((r = attr_write(up_attr_buf + wlen, len, ATTR_OPTIONAL,
>                   ATTR_MED, &tmp32, 4)) == -1)
>                       return (-1);
> @@ -798,7 +800,7 @@ up_generate_attr(struct rde_peer *peer, 
>  
>       if (!peer->conf.ebgp) {
>               /* local preference, only valid for ibgp */
> -             tmp32 = htonl(a->lpref);
> +             tmp32 = htonl(asp->lpref);
>               if ((r = attr_write(up_attr_buf + wlen, len, ATTR_WELL_KNOWN,
>                   ATTR_LOCALPREF, &tmp32, 4)) == -1)
>                       return (-1);
> @@ -814,8 +816,8 @@ up_generate_attr(struct rde_peer *peer, 
>        *  3. transitive known attrs: announce unmodified
>        *  4. transitive unknown attrs: set partial bit and re-announce
>        */
> -     for (l = 0; l < a->others_len; l++) {
> -             if ((oa = a->others[l]) == NULL)
> +     for (l = 0; l < asp->others_len; l++) {
> +             if ((oa = asp->others[l]) == NULL)
>                       break;
>               switch (oa->type) {
>               case ATTR_ATOMIC_AGGREGATE:
> @@ -912,13 +914,13 @@ up_generate_attr(struct rde_peer *peer, 
>       if (neednewpath) {
>               if (!peer->conf.ebgp ||
>                   peer->conf.flags & PEERFLAG_TRANS_AS)
> -                     pdata = aspath_prepend(a->aspath, peer->conf.local_as,
> +                     pdata = aspath_prepend(asp->aspath, peer->conf.local_as,
>                           0, &plen);
>               else
> -                     pdata = aspath_prepend(a->aspath, peer->conf.local_as,
> +                     pdata = aspath_prepend(asp->aspath, peer->conf.local_as,
>                           1, &plen);
>               flags = ATTR_OPTIONAL|ATTR_TRANSITIVE;
> -             if (!(a->flags & F_PREFIX_ANNOUNCED))
> +             if (!(asp->flags & F_PREFIX_ANNOUNCED))
>                       flags |= ATTR_PARTIAL;
>               if (plen == 0)
>                       r = 0;
> @@ -930,7 +932,7 @@ up_generate_attr(struct rde_peer *peer, 
>       }
>       if (newaggr) {
>               flags = ATTR_OPTIONAL|ATTR_TRANSITIVE;
> -             if (!(a->flags & F_PREFIX_ANNOUNCED))
> +             if (!(asp->flags & F_PREFIX_ANNOUNCED))
>                       flags |= ATTR_PARTIAL;
>               if ((r = attr_write(up_attr_buf + wlen, len, flags,
>                   ATTR_AS4_AGGREGATOR, newaggr->data, newaggr->len)) == -1)
> @@ -940,7 +942,7 @@ up_generate_attr(struct rde_peer *peer, 
>  
>       /* write mp attribute to different buffer */
>       if (ismp)
> -             if (up_generate_mp_reach(peer, upa, a, aid) == -1)
> +             if (up_generate_mp_reach(peer, upa, state, aid) == -1)
>                       return (-1);
>  
>       /* the bgp path attributes are now stored in the global buf */
> 

Reply via email to