diff options
author | Claudio Jeker <claudio@cvs.openbsd.org> | 2004-01-12 13:33:17 +0000 |
---|---|---|
committer | Claudio Jeker <claudio@cvs.openbsd.org> | 2004-01-12 13:33:17 +0000 |
commit | 1b90e602977493019983f46c9113241a59e7cc59 (patch) | |
tree | 5c28236b9fbe95fda774009953a4903b4ab68a90 | |
parent | 9963d85edc566970b02ecb6373709ed448799d06 (diff) |
Nexthop announcement fixup. There are different rules for ibgp and ebgp.
For ibgp the nexthop is normally passed unmodified unless the nexthop is
equal to the remote peer ip. To ebgp peers the nexthop is changed to the
local session ip unless the remote peer ip and the nexthop are on the same
subnet. OK henning@
-rw-r--r-- | usr.sbin/bgpd/rde.h | 4 | ||||
-rw-r--r-- | usr.sbin/bgpd/rde_decide.c | 60 | ||||
-rw-r--r-- | usr.sbin/bgpd/rde_rib.c | 6 |
3 files changed, 57 insertions, 13 deletions
diff --git a/usr.sbin/bgpd/rde.h b/usr.sbin/bgpd/rde.h index d14b4ac5def..0848897d4b4 100644 --- a/usr.sbin/bgpd/rde.h +++ b/usr.sbin/bgpd/rde.h @@ -1,4 +1,4 @@ -/* $OpenBSD: rde.h,v 1.15 2004/01/11 21:47:20 claudio Exp $ */ +/* $OpenBSD: rde.h,v 1.16 2004/01/12 13:33:16 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org> and @@ -155,6 +155,8 @@ struct nexthop { struct aspath_head path_h; struct bgpd_addr exit_nexthop; struct bgpd_addr true_nexthop; + struct bgpd_addr nexthop_net; + u_int8_t nexthop_netlen; u_int8_t connected; }; diff --git a/usr.sbin/bgpd/rde_decide.c b/usr.sbin/bgpd/rde_decide.c index a3d8e389fd2..791201c8ee1 100644 --- a/usr.sbin/bgpd/rde_decide.c +++ b/usr.sbin/bgpd/rde_decide.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rde_decide.c,v 1.15 2004/01/11 21:47:20 claudio Exp $ */ +/* $OpenBSD: rde_decide.c,v 1.16 2004/01/12 13:33:16 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org> @@ -31,7 +31,7 @@ int prefix_cmp(struct prefix *, struct prefix *); void up_generate_updates(struct prefix *, struct prefix *); int up_generate_attr(struct rde_peer *, struct update_attr *, - struct attr_flags *); + struct attr_flags *, struct nexthop *); int up_set_prefix(u_char *, int, struct bgpd_addr *, u_int8_t); /* @@ -220,12 +220,12 @@ prefix_evaluate(struct prefix *p, struct pt_entry *pte) } /* - * XXX send update with remove for pte->active and add for xp + * Send update with remove for pte->active and add for xp * but remember that xp may be ineligible or NULL. - * do not send an update if the only available path - * has an unreachable nexthop + * Do not send an update if the only available path + * has an unreachable nexthop. This decision has to be made + * by the called functions. */ - up_generate_updates(xp, pte->active); rde_send_kroute(xp, pte->active); @@ -449,8 +449,8 @@ up_generate_updates(struct prefix *new, struct prefix *old) if (a == NULL) fatal("up_queue_update"); - if (up_generate_attr(peer, a, &new->aspath->flags) == - -1) + if (up_generate_attr(peer, a, &new->aspath->flags, + new->aspath->nexthop) == -1) logit(LOG_CRIT, "generation of bgp path attributes failed"); @@ -472,10 +472,11 @@ u_char up_attr_buf[4096]; int up_generate_attr(struct rde_peer *peer, struct update_attr *upa, - struct attr_flags *a) + struct attr_flags *a, struct nexthop *nh) { struct attr *oa; u_int32_t tmp32; + in_addr_t nexthop, mask; int r; u_int16_t len = sizeof(up_attr_buf), wlen = 0; @@ -492,9 +493,46 @@ up_generate_attr(struct rde_peer *peer, struct update_attr *upa, wlen += r; len -= r; /* nexthop, already network byte order */ - /* XXX XXX nexthop fixup */ + if (peer->conf.ebgp == 0) { + /* + * if directly connected use peer->local_addr + * This is only the case for announcements, which we + * currenlty don't handle. It is currently unclear how + * to recognize those routes. The connected flag is not + * enough. + */ + if (a->nexthop == peer->remote_addr.v4.s_addr) + /* + * per rfc: if remote peer address is equal to + * the nexthop set the nexthop to our local address. + * This reduces the risk of routing loops. + */ + nexthop = peer->local_addr.v4.s_addr; + else + nexthop = nh->exit_nexthop.v4.s_addr; + } else if (peer->conf.distance == 1) { + /* ebgp directly connected */ + if (nh->connected) { + mask = 0xffffffff << (32 - nh->nexthop_netlen); + mask = htonl(mask); + if ((peer->remote_addr.v4.s_addr & mask) == + (nh->nexthop_net.v4.s_addr & mask)) + /* nexthop and peer are in the same net */ + nexthop = nh->exit_nexthop.v4.s_addr; + else + nexthop = peer->local_addr.v4.s_addr; + } else + nexthop = peer->local_addr.v4.s_addr; + } else + /* ebgp multihop */ + /* + * XXX for ebgp multihop nh->connected should always be false + * so it should be possible to unify the two ebgp cases. + */ + nexthop = peer->local_addr.v4.s_addr; + if ((r = attr_write(up_attr_buf + wlen, len, ATTR_WELL_KNOWN, - ATTR_NEXTHOP, &a->nexthop, 4)) == -1) + ATTR_NEXTHOP, &nexthop, 4)) == -1) return (-1); wlen += r; len -= r; diff --git a/usr.sbin/bgpd/rde_rib.c b/usr.sbin/bgpd/rde_rib.c index 21d593f1ee7..e9c71336283 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.21 2004/01/11 22:08:04 henning Exp $ */ +/* $OpenBSD: rde_rib.c,v 1.22 2004/01/12 13:33:16 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org> @@ -1111,6 +1111,10 @@ nexthop_update(struct kroute_nexthop *msg) memcpy(&nh->true_nexthop, &msg->gateway, sizeof(nh->true_nexthop)); + nh->nexthop_netlen = msg->kr.prefixlen; + nh->nexthop_net.af = AF_INET; + nh->nexthop_net.v4.s_addr = msg->kr.prefix; + nh->connected = msg->connected; LIST_FOREACH(asp, &nh->path_h, nexthop_l) { |