From: Claudio Jeker Subject: Re: ip sysctl atomic To: Alexander Bluhm Cc: Mark Kettenis , tech@openbsd.org Date: Fri, 17 May 2024 20:45:30 +0200 On Thu, May 16, 2024 at 09:42:01PM +0200, Alexander Bluhm wrote: > On Thu, May 16, 2024 at 02:52:29PM +0200, Mark Kettenis wrote: > > > You write it once into common memory and you read it > > > once. Thinking every time about the context whether it is safe or > > > not to rely on the compiler is too difficult for me. > > > > I feel your pain. The compilers make it pretty much impossible to > > reason about these things. But we can't wrap *every* global variables > > access in the kernel in READ_ONCE() or WRITE_ONCE. The code will > > become unreadable. > > When making code MP safe it feels better to mark every access > explicitly. But in the long run too many macros may be confusing. The problem here is that it lures you into thinking this is safe but in fact it probably isn't. > > I wonder if you should just declare all those global variables that > > you access with READ_ONCE() should be just declared volatile. > > I can live with this solution, diff is below: > - Mark integer in sysctl_int_bounded volatile. > - Declare globals volatile. > - Use consistent ip_ prefix for global variables. > - Add some locking comments. > - in IP input, forward, output use flags for consistent view > > ok? I really dislike this diff. It adds volatile to things that really don't need it and it does not fix the underlying issue that we want a consitent view of the globals during packet delivery. e.g. when a function checks ip_forwarding and then calls a 2nd function which also checks ip_forwarding then you can't ensure that both see the same value. This can be a very nasty footgun. Now if that doesn't matter then there is no need to make the globals volatile and to do anything complicated in sysctl. Just change the value. Maybe issue a memory barrier to flush out the write so other CPUs see the new value ASAP but there is no need for volatile hacks. I know you changed the ip_forwarding to use local flags / state instead which is the right approach to make this less nasty but your diff is changing too many values at once to keep track of where they are used and how. Again doing it this way does not require volatile. > bluhm > > Index: kern/kern_sysctl.c > =================================================================== > RCS file: /data/mirror/openbsd/cvs/src/sys/kern/kern_sysctl.c,v > diff -u -p -r1.427 kern_sysctl.c > --- kern/kern_sysctl.c 12 Apr 2024 16:07:09 -0000 1.427 > +++ kern/kern_sysctl.c 16 May 2024 19:22:05 -0000 > @@ -1003,21 +1003,36 @@ sysctl_securelevel_int(void *oldp, size_ > */ > int > sysctl_int_bounded(void *oldp, size_t *oldlenp, void *newp, size_t newlen, > - int *valp, int minimum, int maximum) > + volatile int *valp, int minimum, int maximum) > { > - int val = *valp; > + int oldval, newval; > int error; > > /* read only */ > - if (newp == NULL || minimum > maximum) > - return (sysctl_rdint(oldp, oldlenp, newp, val)); > + if (newp != NULL && minimum > maximum) > + return (EPERM); > > - if ((error = sysctl_int(oldp, oldlenp, newp, newlen, &val))) > - return (error); > - /* outside limits */ > - if (val < minimum || maximum < val) > + if (oldp && *oldlenp < sizeof(int)) > + return (ENOMEM); > + if (newp && newlen != sizeof(int)) > return (EINVAL); > - *valp = val; > + *oldlenp = sizeof(int); > + > + /* copyin() may sleep, call it first */ > + if (newp) { > + if ((error = copyin(newp, &newval, sizeof(int)))) > + return (error); > + /* outside limits */ > + if (newval < minimum || maximum < newval) > + return (EINVAL); > + } > + if (oldp) { > + oldval = *valp; > + if ((error = copyout(&oldval, oldp, sizeof(int)))) > + return (error); > + } > + if (newp) > + *valp = newval; > return (0); > } > > Index: net/pf.c > =================================================================== > RCS file: /data/mirror/openbsd/cvs/src/sys/net/pf.c,v > diff -u -p -r1.1196 pf.c > --- net/pf.c 14 May 2024 08:26:13 -0000 1.1196 > +++ net/pf.c 16 May 2024 19:22:05 -0000 > @@ -7958,12 +7958,17 @@ done: > switch (pd.naf) { > case AF_INET: > if (pd.dir == PF_IN) { > - if (ipforwarding == 0) { > + int flags; > + > + if (ip_forwarding == 0) { > ipstat_inc(ips_cantforward); > action = PF_DROP; > break; > } > - ip_forward(pd.m, ifp, NULL, 1); > + flags = IP_FORWARDING | IP_REDIRECT; > + if (ip_directedbcast) > + SET(flags, IP_ALLOWBROADCAST); > + ip_forward(pd.m, ifp, NULL, flags); > } else > ip_output(pd.m, NULL, NULL, 0, NULL, NULL, 0); > break; > Index: netinet/if_ether.c > =================================================================== > RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/if_ether.c,v > diff -u -p -r1.267 if_ether.c > --- netinet/if_ether.c 18 Dec 2023 13:30:44 -0000 1.267 > +++ netinet/if_ether.c 16 May 2024 19:22:05 -0000 > @@ -69,6 +69,7 @@ > * Locks used to protect struct members in this file: > * a atomic operations > * I immutable after creation > + * u unlocked integer access > * K kernel lock > * m arp mutex, needed when net lock is shared > * N net lock > @@ -86,8 +87,8 @@ struct llinfo_arp { > > /* timer values */ > int arpt_prune = (5 * 60); /* [I] walk list every 5 minutes */ > -int arpt_keep = (20 * 60); /* [a] once resolved, cache for 20 minutes */ > -int arpt_down = 20; /* [a] once declared down, don't send for 20 secs */ > +volatile int arpt_keep = (20 * 60); /* [u] once resolved, cache 20 minutes */ > +volatile int arpt_down = 20; /* [u] once declared down, don't send 20 secs */ > > struct mbuf *arppullup(struct mbuf *m); > void arpinvalidate(struct rtentry *); > Index: netinet/if_ether.h > =================================================================== > RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/if_ether.h,v > diff -u -p -r1.92 if_ether.h > --- netinet/if_ether.h 14 Feb 2024 22:41:48 -0000 1.92 > +++ netinet/if_ether.h 16 May 2024 19:22:05 -0000 > @@ -245,8 +245,8 @@ struct arpcom { > const struct ether_brport *ac_brport; > }; > > -extern int arpt_keep; /* arp resolved cache expire */ > -extern int arpt_down; /* arp down cache expire */ > +extern volatile int arpt_keep; /* arp resolved cache expire */ > +extern volatile int arpt_down; /* arp down cache expire */ > > extern u_int8_t etherbroadcastaddr[ETHER_ADDR_LEN]; > extern u_int8_t etheranyaddr[ETHER_ADDR_LEN]; > Index: netinet/in_pcb.c > =================================================================== > RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/in_pcb.c,v > diff -u -p -r1.302 in_pcb.c > --- netinet/in_pcb.c 19 Apr 2024 10:13:58 -0000 1.302 > +++ netinet/in_pcb.c 16 May 2024 19:22:05 -0000 > @@ -105,13 +105,18 @@ const struct in_addr zeroin_addr; > const union inpaddru zeroin46_addr; > > /* > + * Locks used to protect global variables in this file: > + * u unlocked integer access > + */ > + > +/* > * These configure the range of local port addresses assigned to > * "unspecified" outgoing connections/packets/whatever. > */ > -int ipport_firstauto = IPPORT_RESERVED; > -int ipport_lastauto = IPPORT_USERRESERVED; > -int ipport_hifirstauto = IPPORT_HIFIRSTAUTO; > -int ipport_hilastauto = IPPORT_HILASTAUTO; > +volatile int ipport_firstauto = IPPORT_RESERVED; /* [u] */ > +volatile int ipport_lastauto = IPPORT_USERRESERVED; /* [u] */ > +volatile int ipport_hifirstauto = IPPORT_HIFIRSTAUTO; /* [u] */ > +volatile int ipport_hilastauto = IPPORT_HILASTAUTO; /* [u] */ > > struct baddynamicports baddynamicports; > struct baddynamicports rootonlyports; > Index: netinet/ip_icmp.c > =================================================================== > RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/ip_icmp.c,v > diff -u -p -r1.192 ip_icmp.c > --- netinet/ip_icmp.c 16 Sep 2023 09:33:27 -0000 1.192 > +++ netinet/ip_icmp.c 16 May 2024 19:22:05 -0000 > @@ -589,7 +589,7 @@ reflect: > struct sockaddr_in ssrc; > struct rtentry *newrt = NULL; > > - if (icmp_rediraccept == 0 || ipforwarding == 1) > + if (icmp_rediraccept == 0 || ip_forwarding == 1) > goto freeit; > if (code > 3) > goto badcode; > Index: netinet/ip_input.c > =================================================================== > RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/ip_input.c,v > diff -u -p -r1.394 ip_input.c > --- netinet/ip_input.c 8 May 2024 13:01:30 -0000 1.394 > +++ netinet/ip_input.c 16 May 2024 19:22:05 -0000 > @@ -83,33 +83,41 @@ > #include > #endif > > +/* > + * Locks used to protect global variables in this file: > + * I immutable after creation > + * a atomic operations > + * u unlocked integer access > + * N net lock > + * F fragment reassembly ipq_mutex > + */ > + > /* values controllable via sysctl */ > -int ipforwarding = 0; > -int ipmforwarding = 0; > -int ipmultipath = 0; > -int ipsendredirects = 1; > +volatile int ip_forwarding = 0; /* [u] */ > +volatile int ip_mforwarding = 0; /* [u] */ > +int ipmultipath = 0; /* [N] */ > +volatile int ip_sendredirects = 1; /* [u] */ > int ip_dosourceroute = 0; > -int ip_defttl = IPDEFTTL; > +volatile int ip_defttl = IPDEFTTL; /* [u] */ > int ip_mtudisc = 1; > int ip_mtudisc_timeout = IPMTUDISCTIMEOUT; > -int ip_directedbcast = 0; > +volatile int ip_directedbcast = 0; /* [u] */ > > /* Protects `ipq' and `ip_frags'. */ > struct mutex ipq_mutex = MUTEX_INITIALIZER(IPL_SOFTNET); > > -/* IP reassembly queue */ > -LIST_HEAD(, ipq) ipq; > +LIST_HEAD(, ipq) ipq; /* [F] reassembly queue */ > > /* Keep track of memory used for reassembly */ > -int ip_maxqueue = 300; > -int ip_frags = 0; > +volatile int ip_maxqueue = 300; /* [u] maximum fragments in queue */ > +int ip_frags; /* [F] number of fragments */ > > const struct sysctl_bounded_args ipctl_vars[] = { > #ifdef MROUTING > { IPCTL_MRTPROTO, &ip_mrtproto, SYSCTL_INT_READONLY }, > #endif > - { IPCTL_FORWARDING, &ipforwarding, 0, 2 }, > - { IPCTL_SENDREDIRECTS, &ipsendredirects, 0, 1 }, > + { IPCTL_FORWARDING, &ip_forwarding, 0, 2 }, > + { IPCTL_SENDREDIRECTS, &ip_sendredirects, 0, 1 }, > { IPCTL_DEFTTL, &ip_defttl, 0, 255 }, > { IPCTL_DIRECTEDBCAST, &ip_directedbcast, 0, 1 }, > { IPCTL_IPPORT_FIRSTAUTO, &ipport_firstauto, 0, 65535 }, > @@ -117,7 +125,7 @@ const struct sysctl_bounded_args ipctl_v > { IPCTL_IPPORT_HIFIRSTAUTO, &ipport_hifirstauto, 0, 65535 }, > { IPCTL_IPPORT_HILASTAUTO, &ipport_hilastauto, 0, 65535 }, > { IPCTL_IPPORT_MAXQUEUE, &ip_maxqueue, 0, 10000 }, > - { IPCTL_MFORWARDING, &ipmforwarding, 0, 1 }, > + { IPCTL_MFORWARDING, &ip_mforwarding, 0, 1 }, > { IPCTL_ARPTIMEOUT, &arpt_keep, 0, INT_MAX }, > { IPCTL_ARPDOWN, &arpt_down, 0, INT_MAX }, > }; > @@ -137,8 +145,8 @@ static struct mbuf_queue ipsendraw_mq; > extern struct niqueue arpinq; > > int ip_ours(struct mbuf **, int *, int, int); > -int ip_dooptions(struct mbuf *, struct ifnet *); > -int in_ouraddr(struct mbuf *, struct ifnet *, struct route *); > +int ip_dooptions(struct mbuf *, struct ifnet *, int); > +int in_ouraddr(struct mbuf *, struct ifnet *, struct route *, int); > > int ip_fragcheck(struct mbuf **, int *); > struct mbuf * ip_reass(struct ipqent *, struct ipq *); > @@ -431,7 +439,7 @@ ip_input_if(struct mbuf **mp, int *offp, > #if NPF > 0 > struct in_addr odst; > #endif > - int pfrdr = 0; > + int flags = 0; > > KASSERT(*offp == 0); > > @@ -461,9 +469,15 @@ ip_input_if(struct mbuf **mp, int *offp, > goto bad; > > ip = mtod(m, struct ip *); > - pfrdr = odst.s_addr != ip->ip_dst.s_addr; > + if (odst.s_addr != ip->ip_dst.s_addr) > + SET(flags, IP_REDIRECT); > #endif > > + if (ip_forwarding != 0) > + SET(flags, IP_FORWARDING); > + if (ip_directedbcast) > + SET(flags, IP_ALLOWBROADCAST); > + > hlen = ip->ip_hl << 2; > > /* > @@ -472,7 +486,7 @@ ip_input_if(struct mbuf **mp, int *offp, > * error was detected (causing an icmp message > * to be sent and the original packet to be freed). > */ > - if (hlen > sizeof (struct ip) && ip_dooptions(m, ifp)) { > + if (hlen > sizeof (struct ip) && ip_dooptions(m, ifp, flags)) { > m = *mp = NULL; > goto bad; > } > @@ -483,7 +497,7 @@ ip_input_if(struct mbuf **mp, int *offp, > goto out; > } > > - switch(in_ouraddr(m, ifp, &ro)) { > + switch(in_ouraddr(m, ifp, &ro, flags)) { > case 2: > goto bad; > case 1: > @@ -500,7 +514,7 @@ ip_input_if(struct mbuf **mp, int *offp, > m->m_flags |= M_MCAST; > > #ifdef MROUTING > - if (ipmforwarding && ip_mrouter[ifp->if_rdomain]) { > + if (ip_mforwarding && ip_mrouter[ifp->if_rdomain]) { > int error; > > if (m->m_flags & M_EXT) { > @@ -565,7 +579,7 @@ ip_input_if(struct mbuf **mp, int *offp, > /* > * Not for us; forward if possible and desirable. > */ > - if (ipforwarding == 0) { > + if (!ISSET(flags, IP_FORWARDING)) { > ipstat_inc(ips_cantforward); > goto bad; > } > @@ -585,7 +599,7 @@ ip_input_if(struct mbuf **mp, int *offp, > } > #endif /* IPSEC */ > > - ip_forward(m, ifp, &ro, pfrdr); > + ip_forward(m, ifp, &ro, flags); > *mp = NULL; > rtfree(ro.ro_rt); > return IPPROTO_DONE; > @@ -807,7 +821,7 @@ ip_deliver(struct mbuf **mp, int *offp, > #undef IPSTAT_INC > > int > -in_ouraddr(struct mbuf *m, struct ifnet *ifp, struct route *ro) > +in_ouraddr(struct mbuf *m, struct ifnet *ifp, struct route *ro, int flags) > { > struct rtentry *rt; > struct ip *ip; > @@ -837,7 +851,8 @@ in_ouraddr(struct mbuf *m, struct ifnet > * if it is received on the interface with that address. > */ > if (ISSET(rt->rt_flags, RTF_BROADCAST) && > - (!ip_directedbcast || rt->rt_ifidx == ifp->if_index)) { > + (!ISSET(flags, IP_ALLOWBROADCAST) || > + rt->rt_ifidx == ifp->if_index)) { > match = 1; > > /* Make sure M_BCAST is set */ > @@ -876,7 +891,8 @@ in_ouraddr(struct mbuf *m, struct ifnet > break; > } > } > - } else if (ipforwarding == 0 && rt->rt_ifidx != ifp->if_index && > + } else if (!ISSET(flags, IP_FORWARDING) && > + rt->rt_ifidx != ifp->if_index && > !((ifp->if_flags & IFF_LOOPBACK) || (ifp->if_type == IFT_ENC) || > (m->m_pkthdr.pf.flags & PF_TAG_TRANSLATE_LOCALHOST))) { > /* received on wrong interface. */ > @@ -1132,11 +1148,13 @@ ip_slowtimo(void) > void > ip_flush(void) > { > - int max = 50; > + int limit, max = 50; > > MUTEX_ASSERT_LOCKED(&ipq_mutex); > > - while (!LIST_EMPTY(&ipq) && ip_frags > ip_maxqueue * 3 / 4 && --max) { > + limit = ip_maxqueue * 3 / 4; > + > + while (!LIST_EMPTY(&ipq) && ip_frags > limit && --max) { > ipstat_inc(ips_fragdropped); > ip_freef(LIST_FIRST(&ipq)); > } > @@ -1150,7 +1168,7 @@ ip_flush(void) > * 0 if the packet should be processed further. > */ > int > -ip_dooptions(struct mbuf *m, struct ifnet *ifp) > +ip_dooptions(struct mbuf *m, struct ifnet *ifp, int flags) > { > struct ip *ip = mtod(m, struct ip *); > unsigned int rtableid = m->m_pkthdr.ph_rtableid; > @@ -1371,8 +1389,8 @@ ip_dooptions(struct mbuf *m, struct ifne > } > } > KERNEL_UNLOCK(); > - if (forward && ipforwarding > 0) { > - ip_forward(m, ifp, NULL, 1); > + if (forward && ISSET(flags, IP_FORWARDING)) { > + ip_forward(m, ifp, NULL, flags | IP_REDIRECT); > return (1); > } > return (0); > @@ -1514,7 +1532,7 @@ const u_char inetctlerrmap[PRC_NCMDS] = > * of codes and types. > * > * If not forwarding, just drop the packet. This could be confusing > - * if ipforwarding was zero but some routing protocol was advancing > + * if ip_forwarding was zero but some routing protocol was advancing > * us as a gateway to somewhere. However, we must let the routing > * protocol deal with that. > * > @@ -1522,7 +1540,7 @@ const u_char inetctlerrmap[PRC_NCMDS] = > * via a source route. > */ > void > -ip_forward(struct mbuf *m, struct ifnet *ifp, struct route *ro, int srcrt) > +ip_forward(struct mbuf *m, struct ifnet *ifp, struct route *ro, int flags) > { > struct mbuf mfake, *mcopy; > struct ip *ip = mtod(m, struct ip *); > @@ -1588,7 +1606,7 @@ ip_forward(struct mbuf *m, struct ifnet > if ((rt->rt_ifidx == ifp->if_index) && > (rt->rt_flags & (RTF_DYNAMIC|RTF_MODIFIED)) == 0 && > satosin(rt_key(rt))->sin_addr.s_addr != 0 && > - ipsendredirects && !srcrt && > + ip_sendredirects && !ISSET(flags, IP_REDIRECT) && > !arpproxy(satosin(rt_key(rt))->sin_addr, m->m_pkthdr.ph_rtableid)) { > if ((ip->ip_src.s_addr & ifatoia(rt->rt_ifa)->ia_netmask) == > ifatoia(rt->rt_ifa)->ia_net) { > @@ -1602,9 +1620,7 @@ ip_forward(struct mbuf *m, struct ifnet > } > } > > - error = ip_output(m, NULL, ro, > - (IP_FORWARDING | (ip_directedbcast ? IP_ALLOWBROADCAST : 0)), > - NULL, NULL, 0); > + error = ip_output(m, NULL, ro, flags | IP_FORWARDING, NULL, NULL, 0); > rt = ro->ro_rt; > if (error) > ipstat_inc(ips_cantforward); > @@ -1781,10 +1797,8 @@ ip_sysctl(int *name, u_int namelen, void > NET_UNLOCK(); > return (error); > default: > - NET_LOCK(); > error = sysctl_bounded_arr(ipctl_vars, nitems(ipctl_vars), > name, namelen, oldp, oldlenp, newp, newlen); > - NET_UNLOCK(); > return (error); > } > /* NOTREACHED */ > Index: netinet/ip_ipip.c > =================================================================== > RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/ip_ipip.c,v > diff -u -p -r1.101 ip_ipip.c > --- netinet/ip_ipip.c 11 Feb 2024 01:27:45 -0000 1.101 > +++ netinet/ip_ipip.c 16 May 2024 19:22:05 -0000 > @@ -481,7 +481,7 @@ ipip_output(struct mbuf **mp, struct tdb > ip6o->ip6_vfc &= ~IPV6_VERSION_MASK; > ip6o->ip6_vfc |= IPV6_VERSION; > ip6o->ip6_plen = htons(m->m_pkthdr.len - sizeof(*ip6o)); > - ip6o->ip6_hlim = ip_defttl; > + ip6o->ip6_hlim = ip6_defhlim; > in6_embedscope(&ip6o->ip6_src, &tdb->tdb_src.sin6, NULL, NULL); > in6_embedscope(&ip6o->ip6_dst, &tdb->tdb_dst.sin6, NULL, NULL); > > Index: netinet/ip_mroute.c > =================================================================== > RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/ip_mroute.c,v > diff -u -p -r1.142 ip_mroute.c > --- netinet/ip_mroute.c 6 Apr 2024 14:23:27 -0000 1.142 > +++ netinet/ip_mroute.c 16 May 2024 19:22:05 -0000 > @@ -98,7 +98,7 @@ int mcast_debug = 1; > struct socket *ip_mrouter[RT_TABLEID_MAX + 1]; > struct rttimer_queue ip_mrouterq; > uint64_t mrt_count[RT_TABLEID_MAX + 1]; > -int ip_mrtproto = IGMP_DVMRP; /* for netstat only */ > +int ip_mrtproto = IGMP_DVMRP; /* [I] for netstat only */ > > struct mrtstat mrtstat; > > Index: netinet/ip_output.c > =================================================================== > RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/ip_output.c,v > diff -u -p -r1.399 ip_output.c > --- netinet/ip_output.c 16 May 2024 13:01:04 -0000 1.399 > +++ netinet/ip_output.c 16 May 2024 19:22:05 -0000 > @@ -326,7 +326,7 @@ reroute: > * above, will be forwarded by the ip_input() routine, > * if necessary. > */ > - if (ipmforwarding && ip_mrouter[ifp->if_rdomain] && > + if (ip_mforwarding && ip_mrouter[ifp->if_rdomain] && > (flags & IP_FORWARDING) == 0) { > int rv; > > @@ -428,7 +428,7 @@ sendit: > #endif > > #ifdef IPSEC > - if ((flags & IP_FORWARDING) && ipforwarding == 2 && > + if ((flags & IP_FORWARDING) && ip_forwarding == 2 && > (!ipsec_in_use || > m_tag_find(m, PACKET_TAG_IPSEC_IN_DONE, NULL) == NULL)) { > error = EHOSTUNREACH; > Index: netinet/ip_var.h > =================================================================== > RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/ip_var.h,v > diff -u -p -r1.117 ip_var.h > --- netinet/ip_var.h 17 Apr 2024 20:48:51 -0000 1.117 > +++ netinet/ip_var.h 16 May 2024 19:22:05 -0000 > @@ -206,26 +206,26 @@ struct ipoffnxt { > /* flags passed to ip_output */ > #define IP_FORWARDING 0x1 /* most of ip header exists */ > #define IP_RAWOUTPUT 0x2 /* raw ip header exists */ > +#define IP_REDIRECT 0x4 /* redirected by pf or source route */ > #define IP_ALLOWBROADCAST SO_BROADCAST /* can send broadcast packets */ > #define IP_MTUDISC 0x0800 /* pmtu discovery, set DF */ > > extern struct ipstat ipstat; > -extern int ip_defttl; /* default IP ttl */ > +extern volatile int ip_defttl; /* default IP ttl */ > > #define IPMTUDISCTIMEOUT (10 * 60) /* as per RFC 1191 */ > > extern int ip_mtudisc; /* mtu discovery */ > extern int ip_mtudisc_timeout; /* seconds to timeout mtu discovery */ > > -extern int ipport_firstauto; /* min port for port allocation */ > -extern int ipport_lastauto; /* max port for port allocation */ > -extern int ipport_hifirstauto; /* min dynamic/private port number */ > -extern int ipport_hilastauto; /* max dynamic/private port number */ > -extern int ipforwarding; /* enable IP forwarding */ > -#ifdef MROUTING > -extern int ipmforwarding; /* enable multicast forwarding */ > -#endif > +extern volatile int ipport_firstauto; /* min port for port allocation */ > +extern volatile int ipport_lastauto; /* max port for port allocation */ > +extern volatile int ipport_hifirstauto; /* min dynamic/private port number */ > +extern volatile int ipport_hilastauto; /* max dynamic/private port number */ > +extern volatile int ip_forwarding; /* enable IP forwarding */ > +extern volatile int ip_mforwarding; /* enable multicast forwarding */ > extern int ipmultipath; /* enable multipath routing */ > +extern volatile int ip_directedbcast; /* accept all broadcast packets */ > extern unsigned int la_hold_total; > > extern const struct pr_usrreqs rip_usrreqs; > Index: netinet6/ip6_forward.c > =================================================================== > RCS file: /data/mirror/openbsd/cvs/src/sys/netinet6/ip6_forward.c,v > diff -u -p -r1.117 ip6_forward.c > --- netinet6/ip6_forward.c 16 Apr 2024 12:56:39 -0000 1.117 > +++ netinet6/ip6_forward.c 16 May 2024 19:22:05 -0000 > @@ -75,7 +75,7 @@ > * of codes and types. > * > * If not forwarding, just drop the packet. This could be confusing > - * if ipforwarding was zero but some routing protocol was advancing > + * if ip6_forwarding was zero but some routing protocol was advancing > * us as a gateway to somewhere. However, we must let the routing > * protocol deal with that. > * > Index: sys/sysctl.h > =================================================================== > RCS file: /data/mirror/openbsd/cvs/src/sys/sys/sysctl.h,v > diff -u -p -r1.235 sysctl.h > --- sys/sysctl.h 1 Oct 2023 15:58:12 -0000 1.235 > +++ sys/sysctl.h 16 May 2024 19:22:05 -0000 > @@ -1035,7 +1035,7 @@ struct ctldebug { > */ > struct sysctl_bounded_args { > int mib; /* identifier shared with userspace as a CTL_ #define */ > - int *var; /* never NULL */ > + volatile int *var; /* never NULL */ > int minimum; /* checking is disabled if minimum == maximum */ > int maximum; /* read-only variable if minimum > maximum */ > }; > @@ -1058,7 +1058,8 @@ int sysctl_int_lower(void *, size_t *, v > int sysctl_int(void *, size_t *, void *, size_t, int *); > int sysctl_rdint(void *, size_t *, void *, int); > int sysctl_securelevel_int(void *, size_t *, void *, size_t, int *); > -int sysctl_int_bounded(void *, size_t *, void *, size_t, int *, int, int); > +int sysctl_int_bounded(void *, size_t *, void *, size_t, volatile int *, > + int, int); > int sysctl_bounded_arr(const struct sysctl_bounded_args *, u_int, > int *, u_int, void *, size_t *, void *, size_t); > int sysctl_quad(void *, size_t *, void *, size_t, int64_t *); -- :wq Claudio