summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--usr.sbin/ospf6d/rde.c3
-rw-r--r--usr.sbin/ospf6d/rde.h4
-rw-r--r--usr.sbin/ospf6d/rde_spf.c77
3 files changed, 73 insertions, 11 deletions
diff --git a/usr.sbin/ospf6d/rde.c b/usr.sbin/ospf6d/rde.c
index c16e46aa1ae..bb04bb77a1e 100644
--- a/usr.sbin/ospf6d/rde.c
+++ b/usr.sbin/ospf6d/rde.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rde.c,v 1.26 2009/03/12 01:21:49 stsp Exp $ */
+/* $OpenBSD: rde.c,v 1.27 2009/03/29 21:42:30 stsp Exp $ */
/*
* Copyright (c) 2004, 2005 Claudio Jeker <claudio@openbsd.org>
@@ -49,7 +49,6 @@ void rde_send_summary(pid_t);
void rde_send_summary_area(struct area *, pid_t);
void rde_nbr_init(u_int32_t);
void rde_nbr_free(void);
-struct rde_nbr *rde_nbr_find(u_int32_t);
struct rde_nbr *rde_nbr_new(u_int32_t, struct rde_nbr *);
void rde_nbr_del(struct rde_nbr *);
diff --git a/usr.sbin/ospf6d/rde.h b/usr.sbin/ospf6d/rde.h
index d3ef2ef43ff..8d2f2820c60 100644
--- a/usr.sbin/ospf6d/rde.h
+++ b/usr.sbin/ospf6d/rde.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: rde.h,v 1.16 2009/03/29 19:28:10 stsp Exp $ */
+/* $OpenBSD: rde.h,v 1.17 2009/03/29 21:42:30 stsp Exp $ */
/*
* Copyright (c) 2004, 2005 Esben Norby <norby@openbsd.org>
@@ -30,6 +30,7 @@ struct v_nexthop {
TAILQ_ENTRY(v_nexthop) entry;
struct vertex *prev;
struct in6_addr nexthop;
+ u_int32_t ifindex;
};
TAILQ_HEAD(v_nexthead, v_nexthop);
@@ -130,6 +131,7 @@ void rde_send_delete_kroute(struct rt_node *);
void rde_nbr_del(struct rde_nbr *);
int rde_nbr_loading(struct area *);
struct rde_nbr *rde_nbr_self(struct area *);
+struct rde_nbr *rde_nbr_find(u_int32_t);
void rde_summary_update(struct rt_node *, struct area *);
/* rde_lsdb.c */
diff --git a/usr.sbin/ospf6d/rde_spf.c b/usr.sbin/ospf6d/rde_spf.c
index 2640bc093db..7e5fd431e33 100644
--- a/usr.sbin/ospf6d/rde_spf.c
+++ b/usr.sbin/ospf6d/rde_spf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rde_spf.c,v 1.10 2009/03/29 19:34:23 stsp Exp $ */
+/* $OpenBSD: rde_spf.c,v 1.11 2009/03/29 21:42:30 stsp Exp $ */
/*
* Copyright (c) 2005 Esben Norby <norby@openbsd.org>
@@ -37,7 +37,11 @@ RB_GENERATE(rt_tree, rt_node, entry, rt_compare)
struct vertex *spf_root = NULL;
void calc_nexthop_clear(struct vertex *);
-void calc_nexthop_add(struct vertex *, struct vertex *, u_int32_t);
+void calc_nexthop_add(struct vertex *, struct vertex *,
+ const struct in6_addr *, u_int32_t);
+struct in6_addr *calc_nexthop_lladdr(struct vertex *, struct lsa_rtr_link *);
+void calc_nexthop_transit_nbr(struct vertex *, struct vertex *,
+ u_int32_t ifindex);
void calc_nexthop(struct vertex *, struct vertex *);
void rt_nexthop_clear(struct rt_node *);
void rt_nexthop_add(struct rt_node *, struct v_nexthead *,
@@ -374,23 +378,80 @@ calc_nexthop_clear(struct vertex *v)
}
void
-calc_nexthop_add(struct vertex *dst, struct vertex *parent, u_int32_t nexthop)
+calc_nexthop_add(struct vertex *dst, struct vertex *parent,
+ const struct in6_addr *nexthop, u_int32_t ifindex)
{
struct v_nexthop *vn;
- if (nexthop == 0)
- /* invalid nexthop, skip it */
- return;
-
if ((vn = calloc(1, sizeof(*vn))) == NULL)
fatal("calc_nexthop_add");
vn->prev = parent;
- /* XXX vn->nexthop.s_addr = nexthop; */
+ if (nexthop)
+ vn->nexthop = *nexthop;
+ vn->ifindex = ifindex;
TAILQ_INSERT_TAIL(&dst->nexthop, vn, entry);
}
+struct in6_addr *
+calc_nexthop_lladdr(struct vertex *dst, struct lsa_rtr_link *rtr_link)
+{
+ struct iface *iface;
+ struct vertex *link;
+ struct rde_nbr *nbr;
+
+ /* Find outgoing interface, we need its LSA tree */
+ LIST_FOREACH(iface, &dst->area->iface_list, entry) {
+ if (ntohl(rtr_link->iface_id) == iface->ifindex)
+ break;
+ }
+ if (!iface) {
+ warnx("calc_nexthop_lladdr: no interface found for ifindex");
+ return (NULL);
+ }
+
+ /* Determine neighbor's link-local address.
+ * Try to get it from link LSA first. */
+ link = lsa_find_tree(&iface->lsa_tree,
+ htons(LSA_TYPE_LINK), rtr_link->nbr_iface_id,
+ htonl(dst->adv_rtr));
+ if (link)
+ return &link->lsa->data.link.lladdr;
+
+ /* Not found, so fall back to source address
+ * advertised in hello packet. */
+ if ((nbr = rde_nbr_find(dst->peerid)) == NULL)
+ fatalx("next hop is not a neighbor");
+ return &nbr->addr;
+}
+
+void
+calc_nexthop_transit_nbr(struct vertex *dst, struct vertex *parent,
+ u_int32_t ifindex)
+{
+ struct lsa_rtr_link *rtr_link;
+ unsigned int i;
+ struct in6_addr *lladdr;
+
+ if (dst->type != LSA_TYPE_ROUTER)
+ fatalx("calc_nexthop_transit_nbr: dst is not a router");
+ if (parent->type != LSA_TYPE_NETWORK)
+ fatalx("calc_nexthop_transit_nbr: parent is not a network");
+
+ /* dst is a neighbor on a directly attached transit network.
+ * Figure out dst's link local address and add it as nexthop. */
+ for (i = 0; i < lsa_num_links(dst); i++) {
+ rtr_link = get_rtr_link(dst, i);
+ if (rtr_link->type == LINK_TYPE_TRANSIT_NET &&
+ rtr_link->nbr_rtr_id == parent->lsa->hdr.adv_rtr &&
+ rtr_link->nbr_iface_id == parent->lsa->hdr.ls_id) {
+ lladdr = calc_nexthop_lladdr(dst, rtr_link);
+ calc_nexthop_add(dst, parent, lladdr, ifindex);
+ }
+ }
+}
+
void
calc_nexthop(struct vertex *dst, struct vertex *parent)
{