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