summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbluhm <bluhm@openbsd.org>2010-07-01 18:57:21 +0000
committerbluhm <bluhm@openbsd.org>2010-07-01 18:57:21 +0000
commit8e1674f3617de22e76249f1f7cada09a002f46f5 (patch)
treec84556fecad50efbe6d498aa373e449ed32217f0
parentSO_PEERCRED should return ENOTCONN when the sockets are not connected (diff)
downloadwireguard-openbsd-8e1674f3617de22e76249f1f7cada09a002f46f5.tar.xz
wireguard-openbsd-8e1674f3617de22e76249f1f7cada09a002f46f5.zip
The prefixes of interface addresses of an ospf link have to be
advertised as link-lsa and intra-area-prefix-lsa when they change dynamically. Handle RTM_NEWADDR and RTM_DELADDR in kroute by sending an imsg to ospfe. Upon this event, originate a new link-lsa in ospfe. In rde a new intra-area-prefix-lsa is generated when a link-lsa appears or goes away. ok claudio@; ok and test stsp@
-rw-r--r--usr.sbin/ospf6d/kroute.c72
-rw-r--r--usr.sbin/ospf6d/ospf6d.c4
-rw-r--r--usr.sbin/ospf6d/ospf6d.h11
-rw-r--r--usr.sbin/ospf6d/ospfe.c48
-rw-r--r--usr.sbin/ospf6d/rde.c3
-rw-r--r--usr.sbin/ospf6d/rde.h3
-rw-r--r--usr.sbin/ospf6d/rde_lsdb.c22
7 files changed, 148 insertions, 15 deletions
diff --git a/usr.sbin/ospf6d/kroute.c b/usr.sbin/ospf6d/kroute.c
index f5021848e51..5dd53996cdf 100644
--- a/usr.sbin/ospf6d/kroute.c
+++ b/usr.sbin/ospf6d/kroute.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kroute.c,v 1.22 2010/06/28 15:06:00 bluhm Exp $ */
+/* $OpenBSD: kroute.c,v 1.23 2010/07/01 18:57:21 bluhm Exp $ */
/*
* Copyright (c) 2004 Esben Norby <norby@openbsd.org>
@@ -78,6 +78,8 @@ void get_rtaddrs(int, struct sockaddr *, struct sockaddr **);
void if_change(u_short, int, struct if_data *);
void if_newaddr(u_short, struct sockaddr_in6 *,
struct sockaddr_in6 *, struct sockaddr_in6 *);
+void if_deladdr(u_short, struct sockaddr_in6 *,
+ struct sockaddr_in6 *, struct sockaddr_in6 *);
void if_announce(void *);
int send_rtmsg(int, int, struct kroute *);
@@ -838,6 +840,7 @@ if_newaddr(u_short ifindex, struct sockaddr_in6 *ifa, struct sockaddr_in6 *mask,
{
struct iface *iface;
struct iface_addr *ia;
+ struct ifaddrchange ifc;
if (ifa == NULL || ifa->sin6_family != AF_INET6)
return;
@@ -898,6 +901,60 @@ if_newaddr(u_short ifindex, struct sockaddr_in6 *ifa, struct sockaddr_in6 *mask,
}
TAILQ_INSERT_TAIL(&iface->ifa_list, ia, entry);
+ ifc.addr = ia->addr;
+ ifc.dstbrd = ia->dstbrd;
+ ifc.prefixlen = ia->prefixlen;
+ ifc.ifindex = ifindex;
+ main_imsg_compose_ospfe(IMSG_IFADDRNEW, 0, &ifc, sizeof(ifc));
+}
+
+void
+if_deladdr(u_short ifindex, struct sockaddr_in6 *ifa, struct sockaddr_in6 *mask,
+ struct sockaddr_in6 *brd)
+{
+ struct iface *iface;
+ struct iface_addr *ia, *nia;
+ struct ifaddrchange ifc;
+
+ if (ifa == NULL || ifa->sin6_family != AF_INET6)
+ return;
+ if ((iface = if_find(ifindex)) == NULL) {
+ log_warnx("if_deladdr: corresponding if %i not found", ifindex);
+ return;
+ }
+
+ /* We only care about link-local and global-scope. */
+ if (IN6_IS_ADDR_UNSPECIFIED(&ifa->sin6_addr) ||
+ IN6_IS_ADDR_LOOPBACK(&ifa->sin6_addr) ||
+ IN6_IS_ADDR_MULTICAST(&ifa->sin6_addr) ||
+ IN6_IS_ADDR_SITELOCAL(&ifa->sin6_addr) ||
+ IN6_IS_ADDR_V4MAPPED(&ifa->sin6_addr) ||
+ IN6_IS_ADDR_V4COMPAT(&ifa->sin6_addr))
+ return;
+
+ /* XXX thanks, KAME, for this ugliness... adopted from route/show.c */
+ if (IN6_IS_ADDR_LINKLOCAL(&ifa->sin6_addr)) {
+ ifa->sin6_addr.s6_addr[2] = 0;
+ ifa->sin6_addr.s6_addr[3] = 0;
+ }
+
+ for (ia = TAILQ_FIRST(&iface->ifa_list); ia != NULL; ia = nia) {
+ nia = TAILQ_NEXT(ia, entry);
+
+ if (IN6_ARE_ADDR_EQUAL(&ia->addr, &ifa->sin6_addr)) {
+ log_debug("if_deladdr: ifindex %u, addr %s/%d",
+ ifindex, log_in6addr(&ia->addr), ia->prefixlen);
+ TAILQ_REMOVE(&iface->ifa_list, ia, entry);
+ ifc.addr = ia->addr;
+ ifc.dstbrd = ia->dstbrd;
+ ifc.prefixlen = ia->prefixlen;
+ ifc.ifindex = ifindex;
+ main_imsg_compose_ospfe(IMSG_IFADDRDEL, 0, &ifc,
+ sizeof(ifc));
+ free(ia);
+ return;
+ }
+ }
}
void
@@ -1495,6 +1552,19 @@ add:
(struct sockaddr_in6 *)rti_info[RTAX_NETMASK],
(struct sockaddr_in6 *)rti_info[RTAX_BRD]);
break;
+ case RTM_DELADDR:
+ ifam = (struct ifa_msghdr *)rtm;
+ if ((ifam->ifam_addrs & (RTA_NETMASK | RTA_IFA |
+ RTA_BRD)) == 0)
+ break;
+ sa = (struct sockaddr *)(ifam + 1);
+ get_rtaddrs(ifam->ifam_addrs, sa, rti_info);
+
+ if_deladdr(ifam->ifam_index,
+ (struct sockaddr_in6 *)rti_info[RTAX_IFA],
+ (struct sockaddr_in6 *)rti_info[RTAX_NETMASK],
+ (struct sockaddr_in6 *)rti_info[RTAX_BRD]);
+ break;
case RTM_IFANNOUNCE:
if_announce(next);
break;
diff --git a/usr.sbin/ospf6d/ospf6d.c b/usr.sbin/ospf6d/ospf6d.c
index d1e0d9862cb..7848eb36e8c 100644
--- a/usr.sbin/ospf6d/ospf6d.c
+++ b/usr.sbin/ospf6d/ospf6d.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ospf6d.c,v 1.18 2009/12/22 19:47:05 claudio Exp $ */
+/* $OpenBSD: ospf6d.c,v 1.19 2010/07/01 18:57:21 bluhm Exp $ */
/*
* Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org>
@@ -475,6 +475,8 @@ main_dispatch_rde(int fd, short event, void *bula)
void
main_imsg_compose_ospfe(int type, pid_t pid, void *data, u_int16_t datalen)
{
+ if (iev_ospfe == NULL)
+ return;
imsg_compose_event(iev_ospfe, type, 0, pid, -1, data, datalen);
}
diff --git a/usr.sbin/ospf6d/ospf6d.h b/usr.sbin/ospf6d/ospf6d.h
index 9cba1885eeb..6b6937a2357 100644
--- a/usr.sbin/ospf6d/ospf6d.h
+++ b/usr.sbin/ospf6d/ospf6d.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ospf6d.h,v 1.20 2010/06/03 10:00:34 bluhm Exp $ */
+/* $OpenBSD: ospf6d.h,v 1.21 2010/07/01 18:57:21 bluhm Exp $ */
/*
* Copyright (c) 2004, 2007 Esben Norby <norby@openbsd.org>
@@ -100,6 +100,8 @@ enum imsg_type {
IMSG_IFINFO,
IMSG_IFADD,
IMSG_IFDELETE,
+ IMSG_IFADDRNEW,
+ IMSG_IFADDRDEL,
IMSG_NEIGHBOR_UP,
IMSG_NEIGHBOR_DOWN,
IMSG_NEIGHBOR_CHANGE,
@@ -324,6 +326,13 @@ struct iface {
#define F_IFACE_AVAIL 0x04
};
+struct ifaddrchange {
+ struct in6_addr addr;
+ struct in6_addr dstbrd;
+ unsigned int ifindex;
+ u_int8_t prefixlen;
+};
+
/* ospf_conf */
enum {
PROC_MAIN,
diff --git a/usr.sbin/ospf6d/ospfe.c b/usr.sbin/ospf6d/ospfe.c
index b87de73540c..6f1b1dceb8d 100644
--- a/usr.sbin/ospf6d/ospfe.c
+++ b/usr.sbin/ospf6d/ospfe.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ospfe.c,v 1.29 2010/05/26 13:56:08 nicm Exp $ */
+/* $OpenBSD: ospfe.c,v 1.30 2010/07/01 18:57:21 bluhm Exp $ */
/*
* Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org>
@@ -250,6 +250,8 @@ ospfe_dispatch_main(int fd, short event, void *bula)
{
static struct area *narea;
static struct iface *niface;
+ struct ifaddrchange *ifc;
+ struct iface_addr *ia, *nia;
struct imsg imsg;
struct imsgev *iev = bula;
struct imsgbuf *ibuf = &iev->ibuf;
@@ -321,6 +323,50 @@ ospfe_dispatch_main(int fd, short event, void *bula)
LIST_REMOVE(iface, entry);
if_del(iface);
break;
+ case IMSG_IFADDRNEW:
+ if (imsg.hdr.len != IMSG_HEADER_SIZE +
+ sizeof(struct ifaddrchange))
+ fatalx("IFADDRNEW imsg with wrong len");
+ ifc = imsg.data;
+
+ iface = if_find(ifc->ifindex);
+ if (iface == NULL)
+ fatalx("IFADDRNEW interface lost in ospfe");
+
+ if ((ia = calloc(1, sizeof(struct iface_addr))) ==
+ NULL)
+ fatal("ospfe_dispatch_main IFADDRNEW");
+ ia->addr = ifc->addr;
+ ia->dstbrd = ifc->dstbrd;
+ ia->prefixlen = ifc->prefixlen;
+
+ TAILQ_INSERT_TAIL(&iface->ifa_list, ia, entry);
+ orig_link_lsa(iface);
+ break;
+ case IMSG_IFADDRDEL:
+ if (imsg.hdr.len != IMSG_HEADER_SIZE +
+ sizeof(struct ifaddrchange))
+ fatalx("IFADDRDEL imsg with wrong len");
+ ifc = imsg.data;
+
+ iface = if_find(ifc->ifindex);
+ if (iface == NULL)
+ fatalx("IFADDRDEL interface lost in ospfe");
+
+ for (ia = TAILQ_FIRST(&iface->ifa_list); ia != NULL;
+ ia = nia) {
+ nia = TAILQ_NEXT(ia, entry);
+
+ if (IN6_ARE_ADDR_EQUAL(&ia->addr,
+ &ifc->addr)) {
+ TAILQ_REMOVE(&iface->ifa_list, ia,
+ entry);
+ free(ia);
+ break;
+ }
+ }
+ orig_link_lsa(iface);
+ break;
case IMSG_RECONF_CONF:
if ((nconf = malloc(sizeof(struct ospfd_conf))) ==
NULL)
diff --git a/usr.sbin/ospf6d/rde.c b/usr.sbin/ospf6d/rde.c
index 287cbc9eccc..dca25f36ba5 100644
--- a/usr.sbin/ospf6d/rde.c
+++ b/usr.sbin/ospf6d/rde.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rde.c,v 1.42 2010/06/28 15:05:01 bluhm Exp $ */
+/* $OpenBSD: rde.c,v 1.43 2010/07/01 18:57:21 bluhm Exp $ */
/*
* Copyright (c) 2004, 2005 Claudio Jeker <claudio@openbsd.org>
@@ -65,7 +65,6 @@ 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 *);
struct lsa *orig_intra_lsa_rtr(struct area *, struct vertex *);
-void orig_intra_area_prefix_lsas(struct area *);
void append_prefix_lsa(struct lsa **, u_int16_t *,
struct lsa_prefix *);
int link_lsa_from_full_nbr(struct lsa *, struct iface *);
diff --git a/usr.sbin/ospf6d/rde.h b/usr.sbin/ospf6d/rde.h
index ada301c4281..ec0459f8404 100644
--- a/usr.sbin/ospf6d/rde.h
+++ b/usr.sbin/ospf6d/rde.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: rde.h,v 1.20 2010/03/01 08:55:45 claudio Exp $ */
+/* $OpenBSD: rde.h,v 1.21 2010/07/01 18:57:21 bluhm Exp $ */
/*
* Copyright (c) 2004, 2005 Esben Norby <norby@openbsd.org>
@@ -134,6 +134,7 @@ 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 *);
+void orig_intra_area_prefix_lsas(struct area *);
/* rde_lsdb.c */
void lsa_init(struct lsa_tree *);
diff --git a/usr.sbin/ospf6d/rde_lsdb.c b/usr.sbin/ospf6d/rde_lsdb.c
index 1c9601a7e7e..cf65ae42536 100644
--- a/usr.sbin/ospf6d/rde_lsdb.c
+++ b/usr.sbin/ospf6d/rde_lsdb.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rde_lsdb.c,v 1.32 2010/06/12 10:12:41 bluhm Exp $ */
+/* $OpenBSD: rde_lsdb.c,v 1.33 2010/07/01 18:57:21 bluhm Exp $ */
/*
* Copyright (c) 2004, 2005 Claudio Jeker <claudio@openbsd.org>
@@ -432,6 +432,7 @@ lsa_add(struct rde_nbr *nbr, struct lsa *lsa)
struct lsa_tree *tree;
struct vertex *new, *old;
struct timeval tv, now, res;
+ int update = 1;
if (LSA_IS_SCOPE_AS(ntohs(lsa->hdr.type)))
tree = &asext_tree;
@@ -460,14 +461,15 @@ lsa_add(struct rde_nbr *nbr, struct lsa *lsa)
fatal("lsa_add");
return (1);
}
- if (!lsa_equal(new->lsa, old->lsa)) {
- if (ntohs(lsa->hdr.type) != LSA_TYPE_EXTERNAL)
- nbr->area->dirty = 1;
- start_spf_timer();
- }
+ if (lsa_equal(new->lsa, old->lsa))
+ update = 0;
vertex_free(old);
RB_INSERT(lsa_tree, tree, new);
- } else {
+ }
+
+ if (update) {
+ if (ntohs(lsa->hdr.type) == LSA_TYPE_LINK)
+ orig_intra_area_prefix_lsas(nbr->area);
if (ntohs(lsa->hdr.type) != LSA_TYPE_EXTERNAL)
nbr->area->dirty = 1;
start_spf_timer();
@@ -787,6 +789,8 @@ lsa_timeout(int fd, short event, void *bula)
v->deleted = 0;
/* schedule recalculation of the RIB */
+ if (ntohs(v->lsa->hdr.type) == LSA_TYPE_LINK)
+ orig_intra_area_prefix_lsas(v->area);
if (ntohs(v->lsa->hdr.type) != LSA_TYPE_EXTERNAL)
v->area->dirty = 1;
start_spf_timer();
@@ -877,9 +881,11 @@ lsa_merge(struct rde_nbr *nbr, struct lsa *lsa, struct vertex *v)
/* overwrite the lsa all other fields are unaffected */
free(v->lsa);
v->lsa = lsa;
- start_spf_timer();
+ if (v->type == LSA_TYPE_LINK)
+ orig_intra_area_prefix_lsas(nbr->area);
if (v->type != LSA_TYPE_EXTERNAL)
nbr->area->dirty = 1;
+ start_spf_timer();
/* set correct timeout for reflooding the LSA */
clock_gettime(CLOCK_MONOTONIC, &tp);