summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClaudio Jeker <claudio@cvs.openbsd.org>2009-10-05 08:20:27 +0000
committerClaudio Jeker <claudio@cvs.openbsd.org>2009-10-05 08:20:27 +0000
commit5e6ca13d17bb06f788768f818835f6420eff8a3d (patch)
tree3d46b77442efafab72cf3926b17e8938ca707076
parent3dc1de0fadffb0117f49dc36fd559c9051df5ec5 (diff)
Until now AS-ext LSA were always announced with the router as nexthop.
Change this so that the real nexthop is announced if the following conditions are met: - the nexthop is reachable via an OSPF enabled interface - the interface is a broadcast or NBMA interface It does not make sense to announce the nexthop of a point-to-point link since the traffic has to go through this box anyway. This is closer to what other systems implement.
-rw-r--r--usr.sbin/ospfd/rde.c52
1 files changed, 36 insertions, 16 deletions
diff --git a/usr.sbin/ospfd/rde.c b/usr.sbin/ospfd/rde.c
index 4848b820076..88c1d7a4350 100644
--- a/usr.sbin/ospfd/rde.c
+++ b/usr.sbin/ospfd/rde.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rde.c,v 1.81 2009/06/06 07:31:26 eric Exp $ */
+/* $OpenBSD: rde.c,v 1.82 2009/10/05 08:20:26 claudio Exp $ */
/*
* Copyright (c) 2004, 2005 Claudio Jeker <claudio@openbsd.org>
@@ -56,6 +56,7 @@ int rde_req_list_exists(struct rde_nbr *, struct lsa_hdr *);
void rde_req_list_del(struct rde_nbr *, struct lsa_hdr *);
void rde_req_list_free(struct rde_nbr *);
+struct iface *rde_asext_lookup(u_int32_t, int);
struct lsa *rde_asext_get(struct rroute *);
struct lsa *rde_asext_put(struct rroute *);
@@ -1033,24 +1034,32 @@ rde_req_list_free(struct rde_nbr *nbr)
/*
* as-external LSA handling
*/
-struct lsa *
-rde_asext_get(struct rroute *rr)
+struct iface *
+rde_asext_lookup(u_int32_t prefix, int plen)
{
struct area *area;
struct iface *iface;
- LIST_FOREACH(area, &rdeconf->area_list, entry)
+ LIST_FOREACH(area, &rdeconf->area_list, entry) {
LIST_FOREACH(iface, &area->iface_list, entry) {
if ((iface->addr.s_addr & iface->mask.s_addr) ==
- rr->kr.prefix.s_addr && iface->mask.s_addr ==
- prefixlen2mask(rr->kr.prefixlen)) {
- /* already announced as (stub) net LSA */
- log_debug("rde_asext_get: %s/%d is net LSA",
- inet_ntoa(rr->kr.prefix), rr->kr.prefixlen);
- return (NULL);
- }
+ (prefix & iface->mask.s_addr) && (plen == -1 ||
+ iface->mask.s_addr == prefixlen2mask(plen)))
+ return (iface);
}
+ }
+ return (NULL);
+}
+struct lsa *
+rde_asext_get(struct rroute *rr)
+{
+ if (rde_asext_lookup(rr->kr.prefix.s_addr, rr->kr.prefixlen)) {
+ /* already announced as (stub) net LSA */
+ log_debug("rde_asext_get: %s/%d is net LSA",
+ inet_ntoa(rr->kr.prefix), rr->kr.prefixlen);
+ return (NULL);
+ }
/* update of seqnum is done by lsa_merge */
return (orig_asext_lsa(rr, DEFAULT_AGE));
}
@@ -1138,6 +1147,7 @@ struct lsa *
orig_asext_lsa(struct rroute *rr, u_int16_t age)
{
struct lsa *lsa;
+ struct iface *iface;
u_int16_t len;
len = sizeof(struct lsa_hdr) + sizeof(struct lsa_asext);
@@ -1166,12 +1176,22 @@ orig_asext_lsa(struct rroute *rr, u_int16_t age)
/*
* nexthop -- on connected routes we are the nexthop,
- * on all other cases we announce the true nexthop.
- * XXX this is wrong as the true nexthop may be outside
- * of the ospf cloud and so unreachable. For now we force
- * all traffic to be directed to us.
+ * in other cases we may announce the true nexthop if the
+ * nexthop is reachable via an OSPF enabled interface but only
+ * broadcast & NBMA interfaces are considered in that case.
+ * It does not make sense to announce the nexthop of a point-to-point
+ * link since the traffic has to go through this box anyway.
+ * Some implementations actually check that there are multiple
+ * neighbors on the particular segment, we skip that check.
*/
- lsa->data.asext.fw_addr = 0;
+ iface = rde_asext_lookup(rr->kr.nexthop.s_addr, -1);
+ if (rr->kr.flags & F_CONNECTED)
+ lsa->data.asext.fw_addr = 0;
+ else if (iface && (iface->type == IF_TYPE_BROADCAST ||
+ iface->type == IF_TYPE_NBMA))
+ lsa->data.asext.fw_addr = rr->kr.nexthop.s_addr;
+ else
+ lsa->data.asext.fw_addr = 0;
lsa->data.asext.metric = htonl(rr->metric);
lsa->data.asext.ext_tag = htonl(rr->kr.ext_tag);