git: f66968564dd7 - main - protocols: make socket buffers ioctl handler changeable

From: Alexander V. Chernikov <melifaro_at_FreeBSD.org>
Date: Wed, 28 Sep 2022 10:20:20 UTC
The branch main has been updated by melifaro:

URL: https://cgit.FreeBSD.org/src/commit/?id=f66968564dd7e87a02f3a4d4bfa5e73c84e5e772

commit f66968564dd7e87a02f3a4d4bfa5e73c84e5e772
Author:     Alexander V. Chernikov <melifaro@FreeBSD.org>
AuthorDate: 2022-09-27 13:39:34 +0000
Commit:     Alexander V. Chernikov <melifaro@FreeBSD.org>
CommitDate: 2022-09-28 10:20:09 +0000

    protocols: make socket buffers ioctl handler changeable
    
    Allow to set custom per-protocol handlers for the socket buffers
     ioctls by introducing pr_setsbopt callback with the default value
     set to the currently-used sbsetopt().
    
    Reviewed by:    glebius
    Differential Revision: https://reviews.freebsd.org/D36746
---
 sys/kern/uipc_domain.c  |  1 +
 sys/kern/uipc_sockbuf.c | 24 ++++++++++++++++++------
 sys/kern/uipc_socket.c  | 14 +-------------
 sys/sys/protosw.h       |  2 ++
 sys/sys/sockbuf.h       |  3 ++-
 5 files changed, 24 insertions(+), 20 deletions(-)

diff --git a/sys/kern/uipc_domain.c b/sys/kern/uipc_domain.c
index f1b2c616c662..0c92ff699171 100644
--- a/sys/kern/uipc_domain.c
+++ b/sys/kern/uipc_domain.c
@@ -201,6 +201,7 @@ pr_init(struct domain *dom, struct protosw *pr)
 	DEFAULT(pr_sosend, sosend_generic);
 	DEFAULT(pr_soreceive, soreceive_generic);
 	DEFAULT(pr_sopoll, sopoll_generic);
+	DEFAULT(pr_setsbopt, sbsetopt);
 
 #define NOTSUPP(foo)	if (pr->foo == NULL)  pr->foo = foo ## _notsupp
 	NOTSUPP(pr_accept);
diff --git a/sys/kern/uipc_sockbuf.c b/sys/kern/uipc_sockbuf.c
index da02de3e3301..a2d3fc28bbec 100644
--- a/sys/kern/uipc_sockbuf.c
+++ b/sys/kern/uipc_sockbuf.c
@@ -651,18 +651,30 @@ sbreserve_locked(struct socket *so, sb_which which, u_long cc,
 }
 
 int
-sbsetopt(struct socket *so, int cmd, u_long cc)
+sbsetopt(struct socket *so, struct sockopt *sopt)
 {
 	struct sockbuf *sb;
 	sb_which wh;
 	short *flags;
-	u_int *hiwat, *lowat;
-	int error;
+	u_int cc, *hiwat, *lowat;
+	int error, optval;
+
+	error = sooptcopyin(sopt, &optval, sizeof optval, sizeof optval);
+	if (error != 0)
+		return (error);
+
+	/*
+	 * Values < 1 make no sense for any of these options,
+	 * so disallow them.
+	 */
+	if (optval < 1)
+		return (EINVAL);
+	cc = optval;
 
 	sb = NULL;
 	SOCK_LOCK(so);
 	if (SOLISTENING(so)) {
-		switch (cmd) {
+		switch (sopt->sopt_name) {
 			case SO_SNDLOWAT:
 			case SO_SNDBUF:
 				lowat = &so->sol_sbsnd_lowat;
@@ -677,7 +689,7 @@ sbsetopt(struct socket *so, int cmd, u_long cc)
 				break;
 		}
 	} else {
-		switch (cmd) {
+		switch (sopt->sopt_name) {
 			case SO_SNDLOWAT:
 			case SO_SNDBUF:
 				sb = &so->so_snd;
@@ -696,7 +708,7 @@ sbsetopt(struct socket *so, int cmd, u_long cc)
 	}
 
 	error = 0;
-	switch (cmd) {
+	switch (sopt->sopt_name) {
 	case SO_SNDBUF:
 	case SO_RCVBUF:
 		if (SOLISTENING(so)) {
diff --git a/sys/kern/uipc_socket.c b/sys/kern/uipc_socket.c
index 7f5e70d14e91..7e1d2c910dbd 100644
--- a/sys/kern/uipc_socket.c
+++ b/sys/kern/uipc_socket.c
@@ -3109,21 +3109,9 @@ sosetopt(struct socket *so, struct sockopt *sopt)
 		case SO_RCVBUF:
 		case SO_SNDLOWAT:
 		case SO_RCVLOWAT:
-			error = sooptcopyin(sopt, &optval, sizeof optval,
-			    sizeof optval);
+			error = so->so_proto->pr_setsbopt(so, sopt);
 			if (error)
 				goto bad;
-
-			/*
-			 * Values < 1 make no sense for any of these options,
-			 * so disallow them.
-			 */
-			if (optval < 1) {
-				error = EINVAL;
-				goto bad;
-			}
-
-			error = sbsetopt(so, sopt->sopt_name, optval);
 			break;
 
 		case SO_SNDTIMEO:
diff --git a/sys/sys/protosw.h b/sys/sys/protosw.h
index 3b89c6f78caf..c0d1ae3761d8 100644
--- a/sys/sys/protosw.h
+++ b/sys/sys/protosw.h
@@ -62,6 +62,7 @@ struct uio;
 
 /* USE THESE FOR YOUR PROTOTYPES ! */
 typedef int	pr_ctloutput_t(struct socket *, struct sockopt *);
+typedef int	pr_setsbopt_t(struct socket *, struct sockopt *);
 typedef void	pr_abort_t(struct socket *);
 typedef int	pr_accept_t(struct socket *, struct sockaddr **);
 typedef int	pr_attach_t(struct socket *, int, struct thread *);
@@ -143,6 +144,7 @@ struct protosw {
 	pr_sense_t	*pr_sense;	/* stat(2) */
 	pr_flush_t	*pr_flush;	/* XXXGL: merge with pr_shutdown_t! */
 	pr_sosetlabel_t	*pr_sosetlabel;	/* MAC, XXXGL: remove */
+	pr_setsbopt_t	*pr_setsbopt;	/* Socket buffer ioctls */
 };
 /*#endif*/
 
diff --git a/sys/sys/sockbuf.h b/sys/sys/sockbuf.h
index 7075cab650da..a0c6fd10116a 100644
--- a/sys/sys/sockbuf.h
+++ b/sys/sys/sockbuf.h
@@ -71,6 +71,7 @@ struct ktls_session;
 struct mbuf;
 struct sockaddr;
 struct socket;
+struct sockopt;
 struct thread;
 struct selinfo;
 
@@ -227,7 +228,7 @@ void	sbflush(struct sockbuf *sb);
 void	sbflush_locked(struct sockbuf *sb);
 void	sbrelease(struct socket *, sb_which);
 void	sbrelease_locked(struct socket *, sb_which);
-int	sbsetopt(struct socket *so, int cmd, u_long cc);
+int	sbsetopt(struct socket *so, struct sockopt *);
 bool	sbreserve_locked(struct socket *so, sb_which which, u_long cc,
 	    struct thread *td);
 void	sbsndptr_adv(struct sockbuf *sb, struct mbuf *mb, u_int len);