diff options
author | 2010-07-01 18:57:21 +0000 | |
---|---|---|
committer | 2010-07-01 18:57:21 +0000 | |
commit | 8e1674f3617de22e76249f1f7cada09a002f46f5 (patch) | |
tree | c84556fecad50efbe6d498aa373e449ed32217f0 | |
parent | SO_PEERCRED should return ENOTCONN when the sockets are not connected (diff) | |
download | wireguard-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.c | 72 | ||||
-rw-r--r-- | usr.sbin/ospf6d/ospf6d.c | 4 | ||||
-rw-r--r-- | usr.sbin/ospf6d/ospf6d.h | 11 | ||||
-rw-r--r-- | usr.sbin/ospf6d/ospfe.c | 48 | ||||
-rw-r--r-- | usr.sbin/ospf6d/rde.c | 3 | ||||
-rw-r--r-- | usr.sbin/ospf6d/rde.h | 3 | ||||
-rw-r--r-- | usr.sbin/ospf6d/rde_lsdb.c | 22 |
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); |