summaryrefslogtreecommitdiff
path: root/sys/netinet6
diff options
context:
space:
mode:
authorMartin Pieuchot <mpi@cvs.openbsd.org>2015-08-24 23:26:44 +0000
committerMartin Pieuchot <mpi@cvs.openbsd.org>2015-08-24 23:26:44 +0000
commitd7e72a5c0bf93847cd4d8fd757df1c8e96c29414 (patch)
tree12fb535d0de47f2b9f01e84ab6b6cef8a8b256bf /sys/netinet6
parenta63b802c24c934fb925fa4e67a549edc680f0c73 (diff)
Start moving away from the global prefix list by limiting its usage to
AUTOCONF'd addresses. This prevent the kernel from removing connected (/64) routes as soon as it configures an AUTOCONF'd address based on a RA. Tested by sebastia@, ok sthen@
Diffstat (limited to 'sys/netinet6')
-rw-r--r--sys/netinet6/in6.c52
-rw-r--r--sys/netinet6/in6_ifattach.c26
-rw-r--r--sys/netinet6/nd6.c20
-rw-r--r--sys/netinet6/nd6.h4
-rw-r--r--sys/netinet6/nd6_rtr.c15
5 files changed, 47 insertions, 70 deletions
diff --git a/sys/netinet6/in6.c b/sys/netinet6/in6.c
index b3085cbf219..761ed807cd2 100644
--- a/sys/netinet6/in6.c
+++ b/sys/netinet6/in6.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: in6.c,v 1.167 2015/08/24 15:58:35 mpi Exp $ */
+/* $OpenBSD: in6.c,v 1.168 2015/08/24 23:26:43 mpi Exp $ */
/* $KAME: in6.c,v 1.372 2004/06/14 08:14:21 itojun Exp $ */
/*
@@ -462,7 +462,6 @@ in6_control(struct socket *so, u_long cmd, caddr_t data, struct ifnet *ifp)
case SIOCAIFADDR_IN6:
{
- struct nd_prefix *pr;
int plen, error = 0;
/* reject read-only flags */
@@ -509,40 +508,20 @@ in6_control(struct socket *so, u_long cmd, caddr_t data, struct ifnet *ifp)
if (ia6->ia6_flags & IN6_IFF_TENTATIVE)
nd6_dad_start(&ia6->ia_ifa);
-
plen = in6_mask2len(&ifra->ifra_prefixmask.sin6_addr, NULL);
if (plen == 128) {
dohooks(ifp->if_addrhooks, 0);
break; /* we don't need to install a host route. */
}
- /*
- * then, make the prefix on-link on the interface.
- * XXX: we'd rather create the prefix before the address, but
- * we need at least one address to install the corresponding
- * interface route, so we configure the address first.
- */
- pr = nd6_prefix_add(ifp, &ifra->ifra_addr,
- &ifra->ifra_prefixmask, &ifra->ifra_lifetime,
- ((ifra->ifra_flags & IN6_IFF_AUTOCONF) != 0));
- if (pr == NULL) {
- log(LOG_ERR, "cannot add prefix\n");
- return (EINVAL); /* XXX panic here? */
- }
-
- /* relate the address to the prefix */
- if (ia6->ia6_ndpr == NULL) {
- ia6->ia6_ndpr = pr;
- pr->ndpr_refcnt++;
- }
-
s = splsoftnet();
- /*
- * this might affect the status of autoconfigured addresses,
- * that is, this address might make other addresses detached.
- */
- pfxlist_onlink_check();
-
+ error = rt_ifa_add(&ia6->ia_ifa,
+ RTF_UP|RTF_CLONING|RTF_CONNECTED, ia6->ia_ifa.ifa_addr);
+ if (error) {
+ in6_purgeaddr(&ia6->ia_ifa);
+ splx(s);
+ return (error);
+ }
dohooks(ifp->if_addrhooks, 0);
splx(s);
break;
@@ -977,24 +956,19 @@ in6_purgeaddr(struct ifaddr *ifa)
void
in6_unlink_ifa(struct in6_ifaddr *ia6, struct ifnet *ifp)
{
+ struct ifaddr *ifa = &ia6->ia_ifa;
+
splsoftassert(IPL_SOFTNET);
- ifa_del(ifp, &ia6->ia_ifa);
+ ifa_del(ifp, ifa);
TAILQ_REMOVE(&in6_ifaddr, ia6, ia_list);
/* Release the reference to the base prefix. */
if (ia6->ia6_ndpr == NULL) {
- char addr[INET6_ADDRSTRLEN];
-
- if (!IN6_IS_ADDR_LINKLOCAL(IA6_IN6(ia6)) &&
- !IN6_IS_ADDR_LOOPBACK(IA6_IN6(ia6)) &&
- !IN6_ARE_ADDR_EQUAL(IA6_MASKIN6(ia6), &in6mask128))
- log(LOG_NOTICE, "in6_unlink_ifa: interface address "
- "%s has no prefix\n",
- inet_ntop(AF_INET6, IA6_IN6(ia6), addr,
- sizeof(addr)));
+ rt_ifa_del(ifa, RTF_CLONING | RTF_CONNECTED, ifa->ifa_addr);
} else {
+ KASSERT(ia6->ia6_flags & IN6_IFF_AUTOCONF);
ia6->ia6_flags &= ~IN6_IFF_AUTOCONF;
if (--ia6->ia6_ndpr->ndpr_refcnt == 0)
prelist_remove(ia6->ia6_ndpr);
diff --git a/sys/netinet6/in6_ifattach.c b/sys/netinet6/in6_ifattach.c
index 6c6a65af67a..b83e5b48dda 100644
--- a/sys/netinet6/in6_ifattach.c
+++ b/sys/netinet6/in6_ifattach.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: in6_ifattach.c,v 1.92 2015/08/24 15:58:35 mpi Exp $ */
+/* $OpenBSD: in6_ifattach.c,v 1.93 2015/08/24 23:26:43 mpi Exp $ */
/* $KAME: in6_ifattach.c,v 1.124 2001/07/18 08:32:51 jinmei Exp $ */
/*
@@ -293,7 +293,8 @@ int
in6_ifattach_linklocal(struct ifnet *ifp, struct in6_addr *ifid)
{
struct in6_aliasreq ifra;
- int s, error;
+ struct in6_ifaddr *ia6;
+ int s, error;
/*
* configure link-local address.
@@ -355,32 +356,23 @@ in6_ifattach_linklocal(struct ifnet *ifp, struct in6_addr *ifid)
return (-1);
}
+ ia6 = in6ifa_ifpforlinklocal(ifp, 0);
+
/*
* Perform DAD.
*
* XXX: Some P2P interfaces seem not to send packets just after
* becoming up, so we skip p2p interfaces for safety.
*/
- if (in6if_do_dad(ifp) && ((ifp->if_flags & IFF_POINTOPOINT) ||
- (ifp->if_type == IFT_CARP)) == 0) {
- struct in6_ifaddr *ia6;
- ia6 = in6ifa_ifpforlinklocal(ifp, 0);
+ if (in6if_do_dad(ifp) && ((ifp->if_flags & IFF_POINTOPOINT) == 0)) {
ia6->ia6_flags |= IN6_IFF_TENTATIVE;
nd6_dad_start(&ia6->ia_ifa);
}
- /*
- * Make the link-local prefix (fe80::/64%link) as on-link.
- * Since we'd like to manage prefixes separately from addresses,
- * we make an ND6 prefix structure for the link-local prefix,
- * and add it to the prefix list as a never-expire prefix.
- * XXX: this change might affect some existing code base...
- */
- if (nd6_prefix_add(ifp, &ifra.ifra_addr, &ifra.ifra_prefixmask,
- &ifra.ifra_lifetime, 1) == NULL)
- return (EINVAL);
+ error = rt_ifa_add(&ia6->ia_ifa, RTF_UP|RTF_CLONING|RTF_CONNECTED,
+ ia6->ia_ifa.ifa_addr);
- return (0);
+ return (error);
}
int
diff --git a/sys/netinet6/nd6.c b/sys/netinet6/nd6.c
index b10dfb51563..3fb56fe4835 100644
--- a/sys/netinet6/nd6.c
+++ b/sys/netinet6/nd6.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: nd6.c,v 1.147 2015/08/24 14:00:29 bluhm Exp $ */
+/* $OpenBSD: nd6.c,v 1.148 2015/08/24 23:26:43 mpi Exp $ */
/* $KAME: nd6.c,v 1.280 2002/06/08 19:52:07 itojun Exp $ */
/*
@@ -719,6 +719,8 @@ int
nd6_is_addr_neighbor(struct sockaddr_in6 *addr, struct ifnet *ifp)
{
struct nd_prefix *pr;
+ struct in6_ifaddr *ia6;
+ struct ifaddr *ifa;
struct rtentry *rt;
/*
@@ -731,6 +733,22 @@ nd6_is_addr_neighbor(struct sockaddr_in6 *addr, struct ifnet *ifp)
ntohs(*(u_int16_t *)&addr->sin6_addr.s6_addr[2]) == ifp->if_index)
return (1);
+ TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
+ if (ifa->ifa_addr->sa_family != AF_INET6)
+ continue;
+
+ ia6 = ifatoia6(ifa);
+
+ /* Prefix check down below. */
+ if (ia6->ia6_flags & IN6_IFF_AUTOCONF)
+ continue;
+
+ if (IN6_ARE_MASKED_ADDR_EQUAL(&addr->sin6_addr,
+ &ia6->ia_addr.sin6_addr,
+ &ia6->ia_prefixmask.sin6_addr))
+ return (1);
+ }
+
/*
* If the address matches one of our on-link prefixes, it should be a
* neighbor.
diff --git a/sys/netinet6/nd6.h b/sys/netinet6/nd6.h
index 543d94d7cd9..5761109a161 100644
--- a/sys/netinet6/nd6.h
+++ b/sys/netinet6/nd6.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: nd6.h,v 1.46 2015/08/24 15:58:35 mpi Exp $ */
+/* $OpenBSD: nd6.h,v 1.47 2015/08/24 23:26:43 mpi Exp $ */
/* $KAME: nd6.h,v 1.95 2002/06/08 11:31:06 itojun Exp $ */
/*
@@ -313,7 +313,7 @@ void pfxlist_onlink_check(void);
struct nd_defrouter *defrouter_lookup(struct in6_addr *, struct ifnet *);
struct nd_prefix *nd6_prefix_add(struct ifnet *, struct sockaddr_in6 *,
- struct sockaddr_in6 *, struct in6_addrlifetime *, int);
+ struct sockaddr_in6 *, struct in6_addrlifetime *);
struct nd_prefix *nd6_prefix_lookup(struct nd_prefix *);
int in6_ifdel(struct ifnet *, struct in6_addr *);
int in6_init_prefix_ltimes(struct nd_prefix *ndpr);
diff --git a/sys/netinet6/nd6_rtr.c b/sys/netinet6/nd6_rtr.c
index 9c4a8df3683..bcc93dd8e56 100644
--- a/sys/netinet6/nd6_rtr.c
+++ b/sys/netinet6/nd6_rtr.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: nd6_rtr.c,v 1.118 2015/08/24 22:11:34 mpi Exp $ */
+/* $OpenBSD: nd6_rtr.c,v 1.119 2015/08/24 23:26:43 mpi Exp $ */
/* $KAME: nd6_rtr.c,v 1.97 2001/02/07 11:09:13 itojun Exp $ */
/*
@@ -1071,7 +1071,7 @@ purge_detached(struct ifnet *ifp)
struct nd_prefix *
nd6_prefix_add(struct ifnet *ifp, struct sockaddr_in6 *addr,
- struct sockaddr_in6 *mask, struct in6_addrlifetime *lt, int autoconf)
+ struct sockaddr_in6 *mask, struct in6_addrlifetime *lt)
{
struct nd_prefix pr0, *pr;
int i;
@@ -1098,7 +1098,7 @@ nd6_prefix_add(struct ifnet *ifp, struct sockaddr_in6 *addr,
* an intended behavior.
*/
pr0.ndpr_raf_onlink = 1; /* should be configurable? */
- pr0.ndpr_raf_auto = autoconf;
+ pr0.ndpr_raf_auto = 1;
pr0.ndpr_vltime = lt->ia6t_vltime;
pr0.ndpr_pltime = lt->ia6t_pltime;
@@ -1188,14 +1188,7 @@ prelist_remove(struct nd_prefix *pr)
/* make sure to invalidate the prefix until it is really freed. */
pr->ndpr_vltime = 0;
pr->ndpr_pltime = 0;
-#if 0
- /*
- * Though these flags are now meaningless, we'd rather keep the value
- * not to confuse users when executing "ndp -p".
- */
- pr->ndpr_raf_onlink = 0;
- pr->ndpr_raf_auto = 0;
-#endif
+
if ((pr->ndpr_stateflags & NDPRF_ONLINK) != 0 &&
(e = nd6_prefix_offlink(pr)) != 0) {
char addr[INET6_ADDRSTRLEN];