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
This commit is contained in:
Alexander V. Chernikov 2022-09-27 13:39:34 +00:00
parent a42206a7ca
commit f66968564d
5 changed files with 24 additions and 20 deletions

View file

@ -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);

View file

@ -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)) {

View file

@ -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:

View file

@ -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*/

View file

@ -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);