patch-2.1.10 linux/net/ipv4/tcp.c
Next file: linux/net/ipv4/tcp_input.c
Previous file: linux/net/ipv4/route.c
Back to the patch index
Back to the overall index
- Lines: 278
- Date:
Fri Nov 15 14:04:01 1996
- Orig file:
v2.1.9/linux/net/ipv4/tcp.c
- Orig date:
Tue Nov 12 15:56:16 1996
diff -u --recursive --new-file v2.1.9/linux/net/ipv4/tcp.c linux/net/ipv4/tcp.c
@@ -658,7 +658,6 @@
int tcp_ioctl(struct sock *sk, int cmd, unsigned long arg)
{
- int err;
switch(cmd)
{
@@ -675,21 +674,12 @@
lock_sock(sk);
amount = tcp_readable(sk);
release_sock(sk);
- err=verify_area(VERIFY_WRITE,(void *)arg, sizeof(int));
- if(err)
- return err;
- put_user(amount, (int *)arg);
- return(0);
+ return put_user(amount, (int *)arg);
}
case SIOCATMARK:
{
int answ = sk->urg_data && sk->urg_seq == sk->copied_seq;
-
- err = verify_area(VERIFY_WRITE,(void *) arg, sizeof(int));
- if (err)
- return err;
- put_user(answ,(int *) arg);
- return(0);
+ return put_user(answ,(int *) arg);
}
case TIOCOUTQ:
{
@@ -697,11 +687,7 @@
if (sk->state == TCP_LISTEN) return(-EINVAL);
amount = sock_wspace(sk);
- err=verify_area(VERIFY_WRITE,(void *)arg, sizeof(int));
- if(err)
- return err;
- put_user(amount, (int *)arg);
- return(0);
+ return put_user(amount, (int *)arg);
}
default:
return(-EINVAL);
@@ -718,9 +704,9 @@
struct tcp_opt *tp=&(sk->tp_pinfo.af_tcp);
memcpy(th,(void *) &(sk->dummy_th), sizeof(*th));
th->seq = htonl(sk->write_seq);
-#if 0
+
th->psh =(push == 0) ? 1 : 0;
-#endif
+
sk->bytes_rcv = 0;
sk->ack_timed = 0;
th->ack_seq = htonl(tp->rcv_nxt);
@@ -986,7 +972,7 @@
{
tmp += copy;
}
-
+
skb = sock_wmalloc(sk, tmp, 0, GFP_KERNEL);
/*
@@ -1106,6 +1092,7 @@
struct msghdr *msg, int len, int flags,
int *addr_len)
{
+ int err;
struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
/*
@@ -1138,7 +1125,7 @@
char c = sk->urg_data;
if (!(flags & MSG_PEEK))
sk->urg_data = URG_READ;
- memcpy_toiovec(msg->msg_iov, &c, 1);
+ err = memcpy_toiovec(msg->msg_iov, &c, 1);
if(msg->msg_name)
{
tp->af_specific->addr2sockaddr(sk, (struct sockaddr *)
@@ -1148,7 +1135,7 @@
*addr_len= tp->af_specific->sockaddr_len;
release_sock(sk);
- return 1;
+ return err ? -EFAULT : 1;
}
release_sock(sk);
@@ -1226,6 +1213,7 @@
u32 peek_seq;
volatile u32 *seq; /* So gcc doesn't overoptimise */
unsigned long used;
+ int err = 0;
/*
* This error should be checked.
@@ -1274,6 +1262,8 @@
if (copied)
break;
copied = -ERESTARTSYS;
+ if (nonblock)
+ copied = -EAGAIN;
break;
}
@@ -1398,13 +1388,28 @@
*seq += used;
/*
- * This memcpy_tofs can sleep. If it sleeps and we
+ * This memcpy_toiovec can sleep. If it sleeps and we
* do a second read it relies on the skb->users to avoid
* a crash when cleanup_rbuf() gets called.
*/
- memcpy_toiovec(msg->msg_iov,((unsigned char *)skb->h.th) +
- skb->h.th->doff*4 + offset, used);
+ /*
+ * FIXME: should break out of the loop early when an
+ * error occurs
+ */
+
+ err = memcpy_toiovec(msg->msg_iov, ((unsigned char *)skb->h.th) + skb->h.th->doff*4 + offset, used);
+
+ if (err)
+ {
+ /*
+ * exception. bailout!
+ */
+ *seq -= err;
+ skb->users--;
+ return -EFAULT;
+ }
+
copied += used;
len -= used;
@@ -1414,7 +1419,7 @@
* but you'll just have to fix it neatly ;)
*/
- skb->users --;
+ skb->users--;
if (after(sk->copied_seq,sk->urg_seq))
sk->urg_data = 0;
@@ -1824,17 +1829,12 @@
default:
return(-ENOPROTOOPT);
}
- err=verify_area(VERIFY_WRITE, optlen, sizeof(int));
- if(err)
- return err;
- put_user(sizeof(int),(int *) optlen);
-
- err=verify_area(VERIFY_WRITE, optval, sizeof(int));
- if(err)
- return err;
- put_user(val,(int *)optval);
- return(0);
+ err = put_user(sizeof(int),(int *) optlen);
+ if (!err)
+ err = put_user(val,(int *)optval);
+
+ return err;
}
void tcp_set_keepalive(struct sock *sk, int val)
@@ -1847,6 +1847,104 @@
{
tcp_dec_slow_timer(TCP_SLT_KEEPALIVE);
}
+}
+
+
+/*
+ * This function returns the amount that we can raise the
+ * usable window based on the following constraints
+ *
+ * 1. The window can never be shrunk once it is offered (RFC 793)
+ * 2. We limit memory per socket
+ */
+
+
+unsigned short tcp_select_window(struct sock *sk)
+{
+ struct tcp_opt *tp = &sk->tp_pinfo.af_tcp;
+ long free_space = sock_rspace(sk);
+ long window;
+ long cur_win;
+ long usable;
+ int mss = sk->mss;
+
+ if (sk->window_clamp)
+ {
+ free_space = min(sk->window_clamp, free_space);
+ mss = min(sk->window_clamp, mss);
+ }
+
+ /*
+ * compute the actual window i.e.
+ * old_window - received_bytes_on_that_win
+ */
+
+ cur_win = tp->rcv_wup - (tp->rcv_nxt - tp->rcv_wnd);
+ window = tp->rcv_wnd;
+
+ if ( cur_win < 0 )
+ {
+ cur_win = 0;
+ printk(KERN_DEBUG "TSW: win < 0 w=%d 1=%u 2=%u\n",
+ tp->rcv_wnd, tp->rcv_nxt, tp->rcv_wup);
+ }
+
+ /*
+ * RFC 1122:
+ * "the suggested [SWS] avoidance algoritm for the receiver is to keep
+ * RECV.NEXT + RCV.WIN fixed until:
+ * RCV.BUFF - RCV.USER - RCV.WINDOW >= min(1/2 RCV.BUFF, MSS)"
+ *
+ * i.e. don't raise the right edge of the window until you can't raise
+ * it MSS bytes
+ */
+
+ /*
+ * It would be a good idea if it didn't break header prediction.
+ * and BSD made the header predition standard...
+ * It expects the same value in the header i.e. th->window to be
+ * constant
+ */
+
+ usable = free_space - cur_win;
+ if (usable < 0)
+ {
+ usable = 0;
+ }
+
+ if ( window < usable )
+ {
+ /*
+ * Window is not blocking the sender
+ * and we have enought free space for it
+ */
+
+ if (cur_win > (sk->mss << 1))
+ goto out;
+ }
+
+
+ if (window >= usable)
+ {
+ /*
+ * We are offering too much, cut it down...
+ * but don't shrink the window
+ */
+
+ window = max(usable, cur_win);
+ }
+ else
+ {
+ if ((usable - window) >= mss)
+ {
+ window += mss;
+ }
+ }
+
+ out:
+ tp->rcv_wnd = window;
+ tp->rcv_wup = tp->rcv_nxt;
+ return window;
}
/*
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov