Unlock IPv6 sysctl net.inet6.ip6.forwarding from net lock.
authorbluhm <bluhm@openbsd.org>
Sun, 14 Jul 2024 18:53:39 +0000 (18:53 +0000)
committerbluhm <bluhm@openbsd.org>
Sun, 14 Jul 2024 18:53:39 +0000 (18:53 +0000)
Use atomic operations to read ip6_forwarding while processing packets
in the network stack.
To make clear where actually the router property is needed, use the
i_am_router variable based on ip6_forwarding.  It already existed
in nd6_nbr.  Move i_am_router setting up the call stack until all
users are independent.
The forwarding decisions in pf_test, pf_refragment6, ip6_input do
also not interfere.
Use a new array ipv6ctl_vars_unlocked to make transition of all the
integer sysctls easier.  Adapt IPv4 to the new style.

OK mvs@

12 files changed:
sys/net/if.c
sys/net/pf.c
sys/net/pf_norm.c
sys/netinet/ip_carp.c
sys/netinet/ip_icmp.c
sys/netinet/ip_input.c
sys/netinet6/icmp6.c
sys/netinet6/ip6_input.c
sys/netinet6/nd6.c
sys/netinet6/nd6.h
sys/netinet6/nd6_nbr.c
sys/netinet6/nd6_rtr.c

index 46e4e8c..e0a9db5 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: if.c,v 1.719 2024/06/20 19:25:42 bluhm Exp $  */
+/*     $OpenBSD: if.c,v 1.720 2024/07/14 18:53:39 bluhm Exp $  */
 /*     $NetBSD: if.c,v 1.35 1996/05/07 05:26:04 thorpej Exp $  */
 
 /*
@@ -3353,6 +3353,7 @@ ifnewlladdr(struct ifnet *ifp)
 {
 #ifdef INET6
        struct ifaddr *ifa;
+       int i_am_router = (atomic_load_int(&ip6_forwarding) != 0);
 #endif
        struct ifreq ifrq;
        short up;
@@ -3378,7 +3379,7 @@ ifnewlladdr(struct ifnet *ifp)
         * Update the link-local address.  Don't do it if we're
         * a router to avoid confusing hosts on the network.
         */
-       if (ip6_forwarding == 0) {
+       if (!i_am_router) {
                ifa = &in6ifa_ifpforlinklocal(ifp, 0)->ia_ifa;
                if (ifa) {
                        in6_purgeaddr(ifa);
index fb278db..378bafc 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: pf.c,v 1.1202 2024/07/12 09:25:27 bluhm Exp $ */
+/*     $OpenBSD: pf.c,v 1.1203 2024/07/14 18:53:39 bluhm Exp $ */
 
 /*
  * Copyright (c) 2001 Daniel Hartmeier
@@ -7988,7 +7988,7 @@ done:
                        if (pd.dir == PF_IN) {
                                int flags = IPV6_REDIRECT;
 
-                               switch (ip6_forwarding) {
+                               switch (atomic_load_int(&ip6_forwarding)) {
                                case 2:
                                        SET(flags, IPV6_FORWARDING_IPSEC);
                                        /* FALLTHROUGH */
index 4178fe7..2bfad78 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: pf_norm.c,v 1.232 2024/07/04 12:50:08 bluhm Exp $ */
+/*     $OpenBSD: pf_norm.c,v 1.233 2024/07/14 18:53:39 bluhm Exp $ */
 
 /*
  * Copyright 2001 Niels Provos <provos@citi.umich.edu>
@@ -1013,7 +1013,7 @@ pf_refragment6(struct mbuf **m0, struct m_tag *mtag, struct sockaddr_in6 *dst,
                if (ifp == NULL) {
                        int flags = 0;
 
-                       switch (ip6_forwarding) {
+                       switch (atomic_load_int(&ip6_forwarding)) {
                        case 2:
                                SET(flags, IPV6_FORWARDING_IPSEC);
                                /* FALLTHROUGH */
index c6e882f..2613931 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ip_carp.c,v 1.362 2024/06/20 19:25:42 bluhm Exp $     */
+/*     $OpenBSD: ip_carp.c,v 1.363 2024/07/14 18:53:39 bluhm Exp $     */
 
 /*
  * Copyright (c) 2002 Michael Shalayeff. All rights reserved.
@@ -1287,9 +1287,10 @@ carp_send_na(struct carp_softc *sc)
        struct ifaddr *ifa;
        struct in6_addr *in6;
        static struct in6_addr mcast = IN6ADDR_LINKLOCAL_ALLNODES_INIT;
+       int i_am_router = (atomic_load_int(&ip6_forwarding) != 0);
        int flags = ND_NA_FLAG_OVERRIDE;
 
-       if (ip6_forwarding != 0)
+       if (i_am_router)
                flags |= ND_NA_FLAG_ROUTER;
 
        TAILQ_FOREACH(ifa, &sc->sc_if.if_addrlist, ifa_list) {
index baaa9a2..5c5ccde 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ip_icmp.c,v 1.195 2024/07/12 09:25:27 bluhm Exp $     */
+/*     $OpenBSD: ip_icmp.c,v 1.196 2024/07/14 18:53:39 bluhm Exp $     */
 /*     $NetBSD: ip_icmp.c,v 1.19 1996/02/13 23:42:22 christos Exp $    */
 
 /*
@@ -588,9 +588,9 @@ reflect:
                struct sockaddr_in sgw;
                struct sockaddr_in ssrc;
                struct rtentry *newrt = NULL;
+               int i_am_router = (atomic_load_int(&ip_forwarding) != 0);
 
-               if (icmp_rediraccept == 0 ||
-                   atomic_load_int(&ip_forwarding) != 0)
+               if (icmp_rediraccept == 0 || i_am_router)
                        goto freeit;
                if (code > 3)
                        goto badcode;
index 8797a26..1d68e0f 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ip_input.c,v 1.398 2024/07/12 09:25:27 bluhm Exp $    */
+/*     $OpenBSD: ip_input.c,v 1.399 2024/07/14 18:53:39 bluhm Exp $    */
 /*     $NetBSD: ip_input.c,v 1.30 1996/03/16 23:53:58 christos Exp $   */
 
 /*
@@ -111,6 +111,10 @@ LIST_HEAD(, ipq) ipq;
 int    ip_maxqueue = 300;
 int    ip_frags = 0;
 
+const struct sysctl_bounded_args ipctl_vars_unlocked[] = {
+       { IPCTL_FORWARDING, &ip_forwarding, 0, 2 },
+};
+
 const struct sysctl_bounded_args ipctl_vars[] = {
 #ifdef MROUTING
        { IPCTL_MRTPROTO, &ip_mrtproto, SYSCTL_INT_READONLY },
@@ -1799,8 +1803,9 @@ ip_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
                NET_UNLOCK();
                return (error);
        case IPCTL_FORWARDING:
-               return (sysctl_int_bounded(oldp, oldlenp, newp, newlen,
-                   &ip_forwarding, 0, 2));
+               return (sysctl_bounded_arr(
+                   ipctl_vars_unlocked, nitems(ipctl_vars_unlocked),
+                   name, namelen, oldp, oldlenp, newp, newlen));
        default:
                NET_LOCK();
                error = sysctl_bounded_arr(ipctl_vars, nitems(ipctl_vars),
index 2a8950d..04ad1b3 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: icmp6.c,v 1.253 2024/06/20 19:25:42 bluhm Exp $       */
+/*     $OpenBSD: icmp6.c,v 1.254 2024/07/14 18:53:39 bluhm Exp $       */
 /*     $KAME: icmp6.c,v 1.217 2001/06/20 15:03:29 jinmei Exp $ */
 
 /*
@@ -1228,6 +1228,7 @@ icmp6_redirect_input(struct mbuf *m, int off)
        char *lladdr = NULL;
        int lladdrlen = 0;
        struct rtentry *rt = NULL;
+       int i_am_router = (atomic_load_int(&ip6_forwarding) != 0);
        int is_router;
        int is_onlink;
        struct in6_addr src6 = ip6->ip6_src;
@@ -1241,7 +1242,7 @@ icmp6_redirect_input(struct mbuf *m, int off)
                return;
 
        /* if we are router, we don't update route by icmp6 redirect */
-       if (ip6_forwarding != 0)
+       if (i_am_router)
                goto freeit;
        if (!(ifp->if_xflags & IFXF_AUTOCONF6))
                goto freeit;
@@ -1366,7 +1367,7 @@ icmp6_redirect_input(struct mbuf *m, int off)
 
        /* RFC 2461 8.3 */
        nd6_cache_lladdr(ifp, &redtgt6, lladdr, lladdrlen, ND_REDIRECT,
-                        is_onlink ? ND_REDIRECT_ONLINK : ND_REDIRECT_ROUTER);
+           is_onlink ? ND_REDIRECT_ONLINK : ND_REDIRECT_ROUTER, i_am_router);
 
        if (!is_onlink) {       /* better router case.  perform rtredirect. */
                /* perform rtredirect */
@@ -1438,11 +1439,12 @@ icmp6_redirect_output(struct mbuf *m0, struct rtentry *rt)
        size_t maxlen;
        u_char *p;
        struct sockaddr_in6 src_sa;
+       int i_am_router = (atomic_load_int(&ip6_forwarding) != 0);
 
        icmp6_errcount(ND_REDIRECT, 0);
 
        /* if we are not router, we don't send icmp6 redirect */
-       if (ip6_forwarding == 0)
+       if (!i_am_router)
                goto fail;
 
        /* sanity check */
index 6952cf6..4ab7d8c 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ip6_input.c,v 1.264 2024/07/04 12:50:08 bluhm Exp $   */
+/*     $OpenBSD: ip6_input.c,v 1.265 2024/07/14 18:53:39 bluhm Exp $   */
 /*     $KAME: ip6_input.c,v 1.188 2001/03/29 05:34:31 itojun Exp $     */
 
 /*
@@ -416,7 +416,7 @@ ip6_input_if(struct mbuf **mp, int *offp, int nxt, int af, struct ifnet *ifp)
                SET(flags, IPV6_REDIRECT);
 #endif
 
-       switch (ip6_forwarding) {
+       switch (atomic_load_int(&ip6_forwarding)) {
        case 2:
                SET(flags, IPV6_FORWARDING_IPSEC);
                /* FALLTHROUGH */
@@ -1443,12 +1443,15 @@ const u_char inet6ctlerrmap[PRC_NCMDS] = {
 extern int ip6_mrtproto;
 #endif
 
+const struct sysctl_bounded_args ipv6ctl_vars_unlocked[] = {
+       { IPV6CTL_FORWARDING, &ip6_forwarding, 0, 2 },
+};
+
 const struct sysctl_bounded_args ipv6ctl_vars[] = {
        { IPV6CTL_DAD_PENDING, &ip6_dad_pending, SYSCTL_INT_READONLY },
 #ifdef MROUTING
        { IPV6CTL_MRTPROTO, &ip6_mrtproto, SYSCTL_INT_READONLY },
 #endif
-       { IPV6CTL_FORWARDING, &ip6_forwarding, 0, 2 },
        { IPV6CTL_SENDREDIRECTS, &ip6_sendredirects, 0, 1 },
        { IPV6CTL_DEFHLIM, &ip6_defhlim, 0, 255 },
        { IPV6CTL_MAXFRAGPACKETS, &ip6_maxfragpackets, 0, 1000 },
@@ -1568,6 +1571,10 @@ ip6_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp,
                        atomic_inc_long(&rtgeneration);
                NET_UNLOCK();
                return (error);
+       case IPV6CTL_FORWARDING:
+               return (sysctl_bounded_arr(
+                   ipv6ctl_vars_unlocked, nitems(ipv6ctl_vars_unlocked),
+                   name, namelen, oldp, oldlenp, newp, newlen));
        default:
                NET_LOCK();
                error = sysctl_bounded_arr(ipv6ctl_vars, nitems(ipv6ctl_vars),
index 28bc1b9..fce85be 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: nd6.c,v 1.281 2024/06/20 19:25:42 bluhm Exp $ */
+/*     $OpenBSD: nd6.c,v 1.282 2024/07/14 18:53:39 bluhm Exp $ */
 /*     $KAME: nd6.c,v 1.280 2002/06/08 19:52:07 itojun Exp $   */
 
 /*
@@ -107,8 +107,8 @@ void nd6_slowtimo(void *);
 void nd6_expire(void *);
 void nd6_expire_timer(void *);
 void nd6_invalidate(struct rtentry *);
-void nd6_free(struct rtentry *);
-int nd6_llinfo_timer(struct rtentry *);
+void nd6_free(struct rtentry *, int);
+int nd6_llinfo_timer(struct rtentry *, int);
 
 struct timeout nd6_timer_to;
 struct timeout nd6_slowtimo_ch;
@@ -264,6 +264,7 @@ nd6_timer(void *unused)
 {
        struct llinfo_nd6 *ln, *nln;
        time_t uptime, expire;
+       int i_am_router = (atomic_load_int(&ip6_forwarding) != 0);
        int secs;
 
        NET_LOCK();
@@ -276,7 +277,7 @@ nd6_timer(void *unused)
                struct rtentry *rt = ln->ln_rt;
 
                if (rt->rt_expire && rt->rt_expire <= uptime)
-                       if (nd6_llinfo_timer(rt))
+                       if (nd6_llinfo_timer(rt, i_am_router))
                                continue;
 
                if (rt->rt_expire && rt->rt_expire < expire)
@@ -300,7 +301,7 @@ nd6_timer(void *unused)
  * Returns 1 if `rt' should no longer be used, 0 otherwise.
  */
 int
-nd6_llinfo_timer(struct rtentry *rt)
+nd6_llinfo_timer(struct rtentry *rt, int i_am_router)
 {
        struct llinfo_nd6 *ln = (struct llinfo_nd6 *)rt->rt_llinfo;
        struct sockaddr_in6 *dst = satosin6(rt_key(rt));
@@ -346,7 +347,7 @@ nd6_llinfo_timer(struct rtentry *rt)
                        } else
                                atomic_sub_int(&ln_hold_total, len);
 
-                       nd6_free(rt);
+                       nd6_free(rt, i_am_router);
                        ln = NULL;
                }
                break;
@@ -362,7 +363,7 @@ nd6_llinfo_timer(struct rtentry *rt)
        case ND6_LLINFO_PURGE:
                /* Garbage Collection(RFC 2461 5.3) */
                if (!ND6_LLINFO_PERMANENT(ln)) {
-                       nd6_free(rt);
+                       nd6_free(rt, i_am_router);
                        ln = NULL;
                }
                break;
@@ -383,7 +384,7 @@ nd6_llinfo_timer(struct rtentry *rt)
                        nd6_ns_output(ifp, &dst->sin6_addr, &dst->sin6_addr,
                            &ln->ln_saddr6, 0);
                } else {
-                       nd6_free(rt);
+                       nd6_free(rt, i_am_router);
                        ln = NULL;
                }
                break;
@@ -477,6 +478,7 @@ void
 nd6_purge(struct ifnet *ifp)
 {
        struct llinfo_nd6 *ln, *nln;
+       int i_am_router = (atomic_load_int(&ip6_forwarding) != 0);
 
        NET_ASSERT_LOCKED_EXCLUSIVE();
 
@@ -492,7 +494,7 @@ nd6_purge(struct ifnet *ifp)
                    rt->rt_gateway->sa_family == AF_LINK) {
                        sdl = satosdl(rt->rt_gateway);
                        if (sdl->sdl_index == ifp->if_index)
-                               nd6_free(rt);
+                               nd6_free(rt, i_am_router);
                }
        }
 }
@@ -661,7 +663,7 @@ nd6_invalidate(struct rtentry *rt)
  * Free an nd6 llinfo entry.
  */
 void
-nd6_free(struct rtentry *rt)
+nd6_free(struct rtentry *rt, int i_am_router)
 {
        struct llinfo_nd6 *ln = (struct llinfo_nd6 *)rt->rt_llinfo;
        struct in6_addr in6 = satosin6(rt_key(rt))->sin6_addr;
@@ -671,7 +673,7 @@ nd6_free(struct rtentry *rt)
 
        ifp = if_get(rt->rt_ifidx);
 
-       if (ip6_forwarding == 0) {
+       if (!i_am_router) {
                if (ln->ln_router) {
                        /*
                         * rt6_flush must be called whether or not the neighbor
@@ -1031,7 +1033,7 @@ nd6_ioctl(u_long cmd, caddr_t data, struct ifnet *ifp)
  */
 void
 nd6_cache_lladdr(struct ifnet *ifp, const struct in6_addr *from, char *lladdr,
-    int lladdrlen, int type, int code)
+    int lladdrlen, int type, int code, int i_am_router)
 {
        struct rtentry *rt;
        struct llinfo_nd6 *ln;
@@ -1080,7 +1082,7 @@ nd6_cache_lladdr(struct ifnet *ifp, const struct in6_addr *from, char *lladdr,
                return;
        if ((rt->rt_flags & (RTF_GATEWAY | RTF_LLINFO)) != RTF_LLINFO) {
 fail:
-               nd6_free(rt);
+               nd6_free(rt, i_am_router);
                rtfree(rt);
                return;
        }
index 293ccbf..b65fad0 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: nd6.h,v 1.99 2023/05/04 06:56:56 bluhm Exp $  */
+/*     $OpenBSD: nd6.h,v 1.100 2024/07/14 18:53:39 bluhm Exp $ */
 /*     $KAME: nd6.h,v 1.95 2002/06/08 11:31:06 itojun Exp $    */
 
 /*
@@ -134,7 +134,7 @@ void nd6_nud_hint(struct rtentry *);
 void nd6_rtrequest(struct ifnet *, int, struct rtentry *);
 int nd6_ioctl(u_long, caddr_t, struct ifnet *);
 void nd6_cache_lladdr(struct ifnet *, const struct in6_addr *, char *,
-    int, int, int);
+    int, int, int, int);
 int nd6_resolve(struct ifnet *, struct rtentry *, struct mbuf *,
         struct sockaddr *, u_char *);
 int nd6_need_cache(struct ifnet *);
index b674731..2e49133 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: nd6_nbr.c,v 1.152 2024/06/20 19:25:42 bluhm Exp $     */
+/*     $OpenBSD: nd6_nbr.c,v 1.153 2024/07/14 18:53:39 bluhm Exp $     */
 /*     $KAME: nd6_nbr.c,v 1.61 2001/02/10 16:06:14 jinmei Exp $        */
 
 /*
@@ -108,7 +108,7 @@ nd6_ns_input(struct mbuf *m, int off, int icmp6len)
        struct ifaddr *ifa = NULL;
        int lladdrlen = 0;
        int anycast = 0, proxy = 0, tentative = 0;
-       int i_am_router = (ip6_forwarding != 0);
+       int i_am_router = (atomic_load_int(&ip6_forwarding) != 0);
        int tlladdr;
        struct nd_opts ndopts;
        struct sockaddr_dl *proxydl = NULL;
@@ -323,7 +323,7 @@ nd6_ns_input(struct mbuf *m, int off, int icmp6len)
        }
 
        nd6_cache_lladdr(ifp, &saddr6, lladdr, lladdrlen, ND_NEIGHBOR_SOLICIT,
-           0);
+           0, i_am_router);
 
        nd6_na_output(ifp, &saddr6, &taddr6,
            ((anycast || proxy || !tlladdr) ? 0 : ND_NA_FLAG_OVERRIDE) |
@@ -559,7 +559,7 @@ nd6_na_input(struct mbuf *m, int off, int icmp6len)
        int is_override;
        char *lladdr = NULL;
        int lladdrlen = 0;
-       int i_am_router = (ip6_forwarding != 0);
+       int i_am_router = (atomic_load_int(&ip6_forwarding) != 0);
        struct ifaddr *ifa;
        struct in6_ifaddr *ifa6;
        struct llinfo_nd6 *ln;
index d68b7a8..1d4ec43 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: nd6_rtr.c,v 1.170 2023/03/31 19:43:33 bluhm Exp $     */
+/*     $OpenBSD: nd6_rtr.c,v 1.171 2024/07/14 18:53:39 bluhm Exp $     */
 /*     $KAME: nd6_rtr.c,v 1.97 2001/02/07 11:09:13 itojun Exp $        */
 
 /*
@@ -73,6 +73,7 @@ nd6_rtr_cache(struct mbuf *m, int off, int icmp6len, int icmp6_type)
        struct in6_addr saddr6 = ip6->ip6_src;
        char *lladdr = NULL;
        int lladdrlen = 0;
+       int i_am_router = (atomic_load_int(&ip6_forwarding) != 0);
        struct nd_opts ndopts;
        char src[INET6_ADDRSTRLEN], dst[INET6_ADDRSTRLEN];
 
@@ -157,7 +158,8 @@ nd6_rtr_cache(struct mbuf *m, int off, int icmp6len, int icmp6_type)
                goto bad;
        }
 
-       nd6_cache_lladdr(ifp, &saddr6, lladdr, lladdrlen, icmp6_type, 0);
+       nd6_cache_lladdr(ifp, &saddr6, lladdr, lladdrlen, icmp6_type, 0,
+           i_am_router);
        if_put(ifp);
 
  freeit: