Download raw body.
sysctl(2): push locking down to icmp_sysctl()
Keep locking only for ICMPCTL_REDIRTIMEOUT case. It is complicated, so
left it as is.
ICMPCTL_STATS loads per-CPU counters into local data, so no locking
required.
`icmpctl_vars' are atomically accessed integers. Except `icmperrppslim'
they are simply booleans, so nothing special required. I used the local
`icmperrppslim_local' variable to load `icmperrppslim' value because it
it could have negative values. claudio@ proposed to always load such
values to local variables, so I want to try this notation with this
diff.
Index: sys/netinet/in_proto.c
===================================================================
RCS file: /cvs/src/sys/netinet/in_proto.c,v
diff -u -p -r1.113 in_proto.c
--- sys/netinet/in_proto.c 22 Aug 2024 10:58:31 -0000 1.113
+++ sys/netinet/in_proto.c 4 Dec 2024 18:55:34 -0000
@@ -219,7 +219,7 @@ const struct protosw inetsw[] = {
.pr_type = SOCK_RAW,
.pr_domain = &inetdomain,
.pr_protocol = IPPROTO_ICMP,
- .pr_flags = PR_ATOMIC|PR_ADDR|PR_MPSOCKET,
+ .pr_flags = PR_ATOMIC|PR_ADDR|PR_MPSOCKET|PR_MPSYSCTL,
.pr_input = icmp_input,
.pr_ctloutput = rip_ctloutput,
.pr_usrreqs = &rip_usrreqs,
Index: sys/netinet/ip_icmp.c
===================================================================
RCS file: /cvs/src/sys/netinet/ip_icmp.c,v
diff -u -p -r1.196 ip_icmp.c
--- sys/netinet/ip_icmp.c 14 Jul 2024 18:53:39 -0000 1.196
+++ sys/netinet/ip_icmp.c 4 Dec 2024 18:55:34 -0000
@@ -105,16 +105,21 @@
* host table maintenance routines.
*/
+/*
+ * Locks used to protect data:
+ * a atomic
+ */
+
#ifdef ICMPPRINTFS
int icmpprintfs = 0; /* Settable from ddb */
#endif
/* values controllable via sysctl */
-int icmpmaskrepl = 0;
-int icmpbmcastecho = 0;
-int icmptstamprepl = 1;
-int icmperrppslim = 100;
-int icmp_rediraccept = 0;
+int icmpmaskrepl = 0; /* [a] */
+int icmpbmcastecho = 0; /* [a] */
+int icmptstamprepl = 1; /* [a] */
+int icmperrppslim = 100; /* [a] */
+int icmp_rediraccept = 0; /* [a] */
int icmp_redirtimeout = 10 * 60;
static int icmperrpps_count = 0;
@@ -506,7 +511,7 @@ icmp_input_if(struct ifnet *ifp, struct
break;
case ICMP_ECHO:
- if (!icmpbmcastecho &&
+ if (atomic_load_int(&icmpbmcastecho) == 0 &&
(m->m_flags & (M_MCAST | M_BCAST)) != 0) {
icmpstat_inc(icps_bmcastecho);
break;
@@ -515,10 +520,10 @@ icmp_input_if(struct ifnet *ifp, struct
goto reflect;
case ICMP_TSTAMP:
- if (icmptstamprepl == 0)
+ if (atomic_load_int(&icmptstamprepl) == 0)
break;
- if (!icmpbmcastecho &&
+ if (atomic_load_int(&icmpbmcastecho) == 0 &&
(m->m_flags & (M_MCAST | M_BCAST)) != 0) {
icmpstat_inc(icps_bmcastecho);
break;
@@ -533,7 +538,7 @@ icmp_input_if(struct ifnet *ifp, struct
goto reflect;
case ICMP_MASKREQ:
- if (icmpmaskrepl == 0)
+ if (atomic_load_int(&icmpmaskrepl) == 0)
break;
if (icmplen < ICMP_MASKLEN) {
icmpstat_inc(icps_badlen);
@@ -590,7 +595,7 @@ reflect:
struct rtentry *newrt = NULL;
int i_am_router = (atomic_load_int(&ip_forwarding) != 0);
- if (icmp_rediraccept == 0 || i_am_router)
+ if (atomic_load_int(&icmp_rediraccept) == 0 || i_am_router)
goto freeit;
if (code > 3)
goto badcode;
@@ -884,24 +889,27 @@ icmp_sysctl(int *name, u_int namelen, vo
return (ENOTDIR);
switch (name[0]) {
- case ICMPCTL_REDIRTIMEOUT:
+ case ICMPCTL_REDIRTIMEOUT: {
+ size_t savelen = *oldlenp;
+
+ if ((error = sysctl_vslock(oldp, savelen)))
+ break;
NET_LOCK();
error = sysctl_int_bounded(oldp, oldlenp, newp, newlen,
&icmp_redirtimeout, 0, INT_MAX);
rt_timer_queue_change(&icmp_redirect_timeout_q,
icmp_redirtimeout);
NET_UNLOCK();
+ sysctl_vsunlock(oldp, savelen);
break;
-
+ }
case ICMPCTL_STATS:
error = icmp_sysctl_icmpstat(oldp, oldlenp, newp);
break;
default:
- NET_LOCK();
error = sysctl_bounded_arr(icmpctl_vars, nitems(icmpctl_vars),
name, namelen, oldp, oldlenp, newp, newlen);
- NET_UNLOCK();
break;
}
@@ -1098,9 +1106,10 @@ icmp_mtudisc_timeout(struct rtentry *rt,
int
icmp_ratelimit(const struct in_addr *dst, const int type, const int code)
{
+ int icmperrppslim_local = atomic_load_int(&icmperrppslim);
/* PPS limit */
if (!ppsratecheck(&icmperrppslim_last, &icmperrpps_count,
- icmperrppslim))
+ icmperrppslim_local))
return 1; /* The packet is subject to rate limit */
return 0; /* okay to send */
}
sysctl(2): push locking down to icmp_sysctl()