summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--usr.sbin/ospf6d/rde.c105
1 files changed, 65 insertions, 40 deletions
diff --git a/usr.sbin/ospf6d/rde.c b/usr.sbin/ospf6d/rde.c
index 9d7e2d228c5..a5392547c37 100644
--- a/usr.sbin/ospf6d/rde.c
+++ b/usr.sbin/ospf6d/rde.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rde.c,v 1.36 2010/01/24 12:21:05 stsp Exp $ */
+/* $OpenBSD: rde.c,v 1.37 2010/03/01 08:58:48 claudio Exp $ */
/*
* Copyright (c) 2004, 2005 Claudio Jeker <claudio@openbsd.org>
@@ -60,6 +60,7 @@ void rde_req_list_free(struct rde_nbr *);
struct lsa *rde_asext_get(struct rroute *);
struct lsa *rde_asext_put(struct rroute *);
+int comp_asext(struct lsa *, struct lsa *);
struct lsa *orig_asext_lsa(struct rroute *, u_int16_t);
struct lsa *orig_sum_lsa(struct rt_node *, struct area *, u_int8_t, int);
struct lsa *orig_intra_lsa_net(struct iface *, struct vertex *);
@@ -1110,22 +1111,31 @@ rde_req_list_free(struct rde_nbr *nbr)
struct lsa *
rde_asext_get(struct rroute *rr)
{
-#if 0
- struct area *area;
- struct iface *iface;
-XXX
+ struct area *area;
+ struct iface *iface;
+ struct iface_addr *ia;
+ struct in6_addr addr;
+
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);
+ LIST_FOREACH(iface, &area->iface_list, entry)
+ TAILQ_FOREACH(ia, &iface->ifa_list, entry) {
+ if (IN6_IS_ADDR_LINKLOCAL(&ia->addr))
+ continue;
+
+ inet6applymask(&addr, &ia->addr,
+ rr->kr.prefixlen);
+ if (!memcmp(&addr, &rr->kr.prefix,
+ sizeof(addr)) && rr->kr.prefixlen ==
+ ia->prefixlen) {
+ /* already announced as Prefix LSA */
+ log_debug("rde_asext_get: %s/%d is "
+ "part of prefix LSA",
+ log_in6addr(&rr->kr.prefix),
+ rr->kr.prefixlen);
+ return (NULL);
+ }
}
- }
-#endif
+
/* update of seqnum is done by lsa_merge */
return (orig_asext_lsa(rr, DEFAULT_AGE));
}
@@ -1514,14 +1524,39 @@ orig_intra_area_prefix_lsas(struct area *area)
lsa_merge(rde_nbr_self(area), lsa, old);
}
+int
+comp_asext(struct lsa *a, struct lsa *b)
+{
+ /* compare prefixes, if they are equal or not */
+ if (a->data.asext.prefix.prefixlen != b->data.asext.prefix.prefixlen)
+ return (-1);
+ return (memcmp(
+ (char *)a + sizeof(struct lsa_hdr) + sizeof(struct lsa_asext),
+ (char *)b + sizeof(struct lsa_hdr) + sizeof(struct lsa_asext),
+ LSA_PREFIXSIZE(a->data.asext.prefix.prefixlen)));
+}
+
struct lsa *
orig_asext_lsa(struct rroute *rr, u_int16_t age)
{
-#if 0 /* XXX a lot todo */
struct lsa *lsa;
- u_int16_t len;
+ u_int32_t ext_tag;
+ u_int16_t len, ext_off = 0;
- len = sizeof(struct lsa_hdr) + sizeof(struct lsa_asext);
+ len = sizeof(struct lsa_hdr) + sizeof(struct lsa_asext) +
+ LSA_PREFIXSIZE(rr->kr.prefixlen);
+
+ /*
+ * nexthop -- on connected routes we are the nexthop,
+ * on all other cases we should announce the true nexthop
+ * unless that nexthop is outside of the ospf cloud.
+ * XXX for now we don't do this.
+ */
+
+ if (rr->kr.ext_tag) {
+ ext_off = len;
+ len += sizeof(ext_tag);
+ }
if ((lsa = calloc(1, len)) == NULL)
fatal("orig_asext_lsa");
@@ -1530,39 +1565,29 @@ orig_asext_lsa(struct rroute *rr, u_int16_t age)
/* LSA header */
lsa->hdr.age = htons(age);
- lsa->hdr.type = LSA_TYPE_EXTERNAL;
+ lsa->hdr.type = htons(LSA_TYPE_EXTERNAL);
lsa->hdr.adv_rtr = rdeconf->rtr_id.s_addr;
lsa->hdr.seq_num = htonl(INIT_SEQ_NUM);
lsa->hdr.len = htons(len);
- /* prefix and mask */
- /*
- * TODO ls_id must be unique, for overlapping routes this may
- * not be true. In this case a hack needs to be done to
- * make the ls_id unique.
- */
- lsa->hdr.ls_id = rr->kr.prefix.s_addr;
- lsa->data.asext.mask = prefixlen2mask(rr->kr.prefixlen);
-
- /*
- * 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.
- */
- lsa->data.asext.fw_addr = 0;
-
lsa->data.asext.metric = htonl(rr->metric);
- lsa->data.asext.ext_tag = htonl(rr->kr.ext_tag);
+ lsa->data.asext.prefix.prefixlen = rr->kr.prefixlen;
+ memcpy((char *)lsa + sizeof(struct lsa_hdr) + sizeof(struct lsa_asext),
+ &rr->kr.prefix, LSA_PREFIXSIZE(rr->kr.prefixlen));
+
+ if (rr->kr.ext_tag) {
+ lsa->data.asext.prefix.options |= LSA_ASEXT_T_FLAG;
+ ext_tag = htonl(rr->kr.ext_tag);
+ memcpy((char *)lsa + ext_off, &ext_tag, sizeof(ext_tag));
+ }
+ lsa->hdr.ls_id = lsa_find_lsid(&asext_tree, lsa->hdr.type,
+ lsa->hdr.adv_rtr, comp_asext, lsa);
lsa->hdr.ls_chksum = 0;
lsa->hdr.ls_chksum =
htons(iso_cksum(lsa, len, LS_CKSUM_OFFSET));
return (lsa);
-#endif
- return NULL;
}
struct lsa *