diff options
-rw-r--r-- | usr.sbin/ospf6d/rde.c | 3 | ||||
-rw-r--r-- | usr.sbin/ospf6d/rde.h | 4 | ||||
-rw-r--r-- | usr.sbin/ospf6d/rde_spf.c | 77 |
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) { |