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 */ >