diff --git a/sys/kern/uipc_domain.c b/sys/kern/uipc_domain.c --- a/sys/kern/uipc_domain.c +++ b/sys/kern/uipc_domain.c @@ -201,6 +201,7 @@ 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 --- a/sys/kern/uipc_sockbuf.c +++ b/sys/kern/uipc_sockbuf.c @@ -651,18 +651,30 @@ } 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 @@ break; } } else { - switch (cmd) { + switch (sopt->sopt_name) { case SO_SNDLOWAT: case SO_SNDBUF: sb = &so->so_snd; @@ -696,7 +708,7 @@ } 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 --- a/sys/kern/uipc_socket.c +++ b/sys/kern/uipc_socket.c @@ -3109,21 +3109,9 @@ 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 --- a/sys/sys/protosw.h +++ b/sys/sys/protosw.h @@ -62,6 +62,7 @@ /* 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 @@ 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 --- a/sys/sys/sockbuf.h +++ b/sys/sys/sockbuf.h @@ -71,6 +71,7 @@ struct mbuf; struct sockaddr; struct socket; +struct sockopt; struct thread; struct selinfo; @@ -227,7 +228,7 @@ 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);