summaryrefslogtreecommitdiffstats
path: root/sys/netinet/tcp_usrreq.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/netinet/tcp_usrreq.c')
-rw-r--r--sys/netinet/tcp_usrreq.c117
1 files changed, 60 insertions, 57 deletions
diff --git a/sys/netinet/tcp_usrreq.c b/sys/netinet/tcp_usrreq.c
index cc94bbb..ba0c012 100644
--- a/sys/netinet/tcp_usrreq.c
+++ b/sys/netinet/tcp_usrreq.c
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* From: @(#)tcp_usrreq.c 8.2 (Berkeley) 1/3/94
- * $Id: tcp_usrreq.c,v 1.36 1997/12/18 09:50:38 davidg Exp $
+ * $Id: tcp_usrreq.c,v 1.37 1998/01/27 09:15:11 davidg Exp $
*/
#include "opt_tcpdebug.h"
@@ -560,104 +560,107 @@ tcp_connect(tp, nam, p)
return 0;
}
+/*
+ * The new sockopt interface makes it possible for us to block in the
+ * copyin/out step (if we take a page fault). Taking a page fault at
+ * splnet() is probably a Bad Thing. (Since sockets and pcbs both now
+ * use TSM, there probably isn't any need for this function to run at
+ * splnet() any more. This needs more examination.)
+ */
int
-tcp_ctloutput(op, so, level, optname, mp, p)
- int op;
+tcp_ctloutput(so, sopt)
struct socket *so;
- int level, optname;
- struct mbuf **mp;
- struct proc *p;
+ struct sockopt *sopt;
{
- int error = 0, s;
- struct inpcb *inp;
- register struct tcpcb *tp;
- register struct mbuf *m;
- register int i;
+ int error, opt, optval, s;
+ struct inpcb *inp;
+ struct tcpcb *tp;
+ struct mbuf *m;
- s = splnet();
+ error = 0;
+ s = splnet(); /* XXX */
inp = sotoinpcb(so);
if (inp == NULL) {
splx(s);
- if (op == PRCO_SETOPT && *mp)
- (void) m_free(*mp);
return (ECONNRESET);
}
- if (level != IPPROTO_TCP) {
- error = ip_ctloutput(op, so, level, optname, mp, p);
+ if (sopt->sopt_level != IPPROTO_TCP) {
+ error = ip_ctloutput(so, sopt);
splx(s);
return (error);
}
tp = intotcpcb(inp);
- switch (op) {
-
- case PRCO_SETOPT:
- m = *mp;
- switch (optname) {
-
+ switch (sopt->sopt_dir) {
+ case SOPT_SET:
+ switch (sopt->sopt_name) {
case TCP_NODELAY:
- if (m == NULL || m->m_len < sizeof (int))
- error = EINVAL;
- else if (*mtod(m, int *))
- tp->t_flags |= TF_NODELAY;
+ case TCP_NOOPT:
+ case TCP_NOPUSH:
+ error = sooptcopyin(sopt, &optval, sizeof optval,
+ sizeof optval);
+ if (error)
+ break;
+
+ switch (sopt->sopt_name) {
+ case TCP_NODELAY:
+ opt = TF_NODELAY;
+ break;
+ case TCP_NOOPT:
+ opt = TF_NOOPT;
+ break;
+ case TCP_NOPUSH:
+ opt = TF_NOPUSH;
+ break;
+ default:
+ opt = 0; /* dead code to fool gcc */
+ break;
+ }
+
+ if (optval)
+ tp->t_flags |= opt;
else
- tp->t_flags &= ~TF_NODELAY;
+ tp->t_flags &= ~opt;
break;
case TCP_MAXSEG:
- if (m && (i = *mtod(m, int *)) > 0 && i <= tp->t_maxseg)
- tp->t_maxseg = i;
- else
- error = EINVAL;
- break;
+ error = sooptcopyin(sopt, &optval, sizeof optval,
+ sizeof optval);
+ if (error)
+ break;
- case TCP_NOOPT:
- if (m == NULL || m->m_len < sizeof (int))
- error = EINVAL;
- else if (*mtod(m, int *))
- tp->t_flags |= TF_NOOPT;
+ if (optval > 0 && optval <= tp->t_maxseg)
+ tp->t_maxseg = optval;
else
- tp->t_flags &= ~TF_NOOPT;
- break;
-
- case TCP_NOPUSH:
- if (m == NULL || m->m_len < sizeof (int))
error = EINVAL;
- else if (*mtod(m, int *))
- tp->t_flags |= TF_NOPUSH;
- else
- tp->t_flags &= ~TF_NOPUSH;
break;
default:
error = ENOPROTOOPT;
break;
}
- if (m)
- (void) m_free(m);
break;
- case PRCO_GETOPT:
- *mp = m = m_get(M_WAIT, MT_SOOPTS);
- m->m_len = sizeof(int);
-
- switch (optname) {
+ case SOPT_GET:
+ switch (sopt->sopt_name) {
case TCP_NODELAY:
- *mtod(m, int *) = tp->t_flags & TF_NODELAY;
+ optval = tp->t_flags & TF_NODELAY;
break;
case TCP_MAXSEG:
- *mtod(m, int *) = tp->t_maxseg;
+ optval = tp->t_maxseg;
break;
case TCP_NOOPT:
- *mtod(m, int *) = tp->t_flags & TF_NOOPT;
+ optval = tp->t_flags & TF_NOOPT;
break;
case TCP_NOPUSH:
- *mtod(m, int *) = tp->t_flags & TF_NOPUSH;
+ optval = tp->t_flags & TF_NOPUSH;
break;
default:
error = ENOPROTOOPT;
break;
}
+ if (error == 0)
+ error = sooptcopyout(sopt, &optval, sizeof optval);
break;
}
splx(s);
OpenPOWER on IntegriCloud