diff options
author | Martin Pieuchot <mpi@cvs.openbsd.org> | 2015-08-24 23:26:44 +0000 |
---|---|---|
committer | Martin Pieuchot <mpi@cvs.openbsd.org> | 2015-08-24 23:26:44 +0000 |
commit | d7e72a5c0bf93847cd4d8fd757df1c8e96c29414 (patch) | |
tree | 12fb535d0de47f2b9f01e84ab6b6cef8a8b256bf /sys/netinet6 | |
parent | a63b802c24c934fb925fa4e67a549edc680f0c73 (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.c | 52 | ||||
-rw-r--r-- | sys/netinet6/in6_ifattach.c | 26 | ||||
-rw-r--r-- | sys/netinet6/nd6.c | 20 | ||||
-rw-r--r-- | sys/netinet6/nd6.h | 4 | ||||
-rw-r--r-- | sys/netinet6/nd6_rtr.c | 15 |
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]; |