summaryrefslogtreecommitdiff
path: root/usr.sbin
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin')
-rw-r--r--usr.sbin/bgpd/rde.c50
-rw-r--r--usr.sbin/bgpd/rde.h14
-rw-r--r--usr.sbin/bgpd/rde_filter.c42
-rw-r--r--usr.sbin/bgpd/rde_rib.c8
-rw-r--r--usr.sbin/bgpd/rde_update.c136
5 files changed, 140 insertions, 110 deletions
diff --git a/usr.sbin/bgpd/rde.c b/usr.sbin/bgpd/rde.c
index 686c1befcda..899e45defde 100644
--- a/usr.sbin/bgpd/rde.c
+++ b/usr.sbin/bgpd/rde.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rde.c,v 1.398 2018/07/22 06:03:17 claudio Exp $ */
+/* $OpenBSD: rde.c,v 1.399 2018/07/22 16:59:08 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -990,7 +990,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) {
@@ -1213,14 +1213,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 nexthop");
rde_update_err(peer, ERR_UPDATE, ERR_UPD_OPTATTR,
@@ -1310,13 +1305,13 @@ rde_update_update(struct rde_peer *peer, struct filterstate *in,
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);
@@ -1491,7 +1486,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)
@@ -1824,7 +1820,8 @@ rde_get_mp_nexthop(u_char *data, u_int16_t len, u_int8_t aid,
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;
@@ -2102,7 +2099,7 @@ rde_dump_filterout(struct rde_peer *peer, struct prefix *p,
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)
@@ -2857,7 +2854,7 @@ rde_softreconfig_in(struct rib_entry *re, void *ptr)
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) {
@@ -2895,8 +2892,8 @@ rde_softreconfig_out(struct rib_entry *re, void *ptr)
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);
@@ -2905,14 +2902,23 @@ rde_softreconfig_out(struct rib_entry *re, void *ptr)
/* 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);
@@ -2935,7 +2941,7 @@ rde_softreconfig_unload_peer(struct rib_entry *re, void *ptr)
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);
@@ -3410,7 +3416,7 @@ network_add(struct network_config *nc, int flagstatic)
}
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,
diff --git a/usr.sbin/bgpd/rde.h b/usr.sbin/bgpd/rde.h
index fbcdb944d27..5d933b4047d 100644
--- a/usr.sbin/bgpd/rde.h
+++ b/usr.sbin/bgpd/rde.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: rde.h,v 1.180 2018/07/20 14:58:20 claudio Exp $ */
+/* $OpenBSD: rde.h,v 1.181 2018/07/22 16:59:08 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org> and
@@ -316,6 +316,8 @@ struct prefix {
struct filterstate {
struct rde_aspath aspath;
+ struct nexthop *nexthop;
+ unsigned int nhflags;
};
extern struct rde_memstats rdemem;
@@ -399,7 +401,7 @@ u_char *community_ext_delete_non_trans(u_char *, u_int16_t,
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 *);
@@ -500,6 +502,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)
{
@@ -522,7 +530,7 @@ int nexthop_compare(struct nexthop *, 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 *);
diff --git a/usr.sbin/bgpd/rde_filter.c b/usr.sbin/bgpd/rde_filter.c
index 53bf0b0257b..4ba3129d5d7 100644
--- a/usr.sbin/bgpd/rde_filter.c
+++ b/usr.sbin/bgpd/rde_filter.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rde_filter.c,v 1.96 2018/07/16 09:09:20 claudio Exp $ */
+/* $OpenBSD: rde_filter.c,v 1.97 2018/07/22 16:59:08 claudio Exp $ */
/*
* Copyright (c) 2004 Claudio Jeker <claudio@openbsd.org>
@@ -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, struct filterstate *state,
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, struct filterstate *state,
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, struct rde_peer *peer,
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, struct rde_peer *peer,
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, struct filter_head *b,
}
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, struct rde_peer *peer,
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, struct rde_peer *peer,
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);
diff --git a/usr.sbin/bgpd/rde_rib.c b/usr.sbin/bgpd/rde_rib.c
index 10757a3d11b..f566017575a 100644
--- a/usr.sbin/bgpd/rde_rib.c
+++ b/usr.sbin/bgpd/rde_rib.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rde_rib.c,v 1.171 2018/07/16 09:09:20 claudio Exp $ */
+/* $OpenBSD: rde_rib.c,v 1.172 2018/07/22 16:59:08 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org>
@@ -423,6 +423,11 @@ path_update(struct rib *rib, struct rde_peer *peer, struct filterstate *state,
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]);
}
-
diff --git a/usr.sbin/bgpd/rde_update.c b/usr.sbin/bgpd/rde_update.c
index c30d1db1d0a..c4af0dd75b4 100644
--- a/usr.sbin/bgpd/rde_update.c
+++ b/usr.sbin/bgpd/rde_update.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rde_update.c,v 1.94 2018/07/09 14:08:48 claudio Exp $ */
+/* $OpenBSD: rde_update.c,v 1.95 2018/07/22 16:59:08 claudio Exp $ */
/*
* Copyright (c) 2004 Claudio Jeker <claudio@openbsd.org>
@@ -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, struct prefix *p)
}
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 *rules, struct rde_peer *peer,
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, struct rde_aspath *a)
*/
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, struct rde_aspath *a)
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 *peer, struct update_attr *upa,
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 *peer, struct update_attr *upa,
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 *peer, struct update_attr *upa,
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, struct update_attr *upa,
/* 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, struct update_attr *upa,
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, struct update_attr *upa,
* 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, struct update_attr *upa,
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, struct update_attr *upa,
* 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, struct update_attr *upa,
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, struct update_attr *upa,
}
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, struct update_attr *upa,
/* 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 */