patch-2.1.53 linux/net/ipv4/tcp.c
Next file: linux/net/ipv4/tcp_input.c
Previous file: linux/net/ipv4/sysctl_net_ipv4.c
Back to the patch index
Back to the overall index
- Lines: 210
- Date:
Thu Sep 4 13:25:28 1997
- Orig file:
v2.1.52/linux/net/ipv4/tcp.c
- Orig date:
Mon Aug 4 16:25:41 1997
diff -u --recursive --new-file v2.1.52/linux/net/ipv4/tcp.c linux/net/ipv4/tcp.c
@@ -5,7 +5,7 @@
*
* Implementation of the Transmission Control Protocol(TCP).
*
- * Version: $Id: tcp.c,v 1.67 1997/07/20 12:46:07 freitag Exp $
+ * Version: $Id: tcp.c,v 1.70 1997/09/01 03:14:28 davem Exp $
*
* Authors: Ross Biro, <bir7@leland.Stanford.Edu>
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -268,7 +268,8 @@
*
* Urgent Pointer (4.2.2.4)
* **MUST point urgent pointer to last byte of urgent data (not right
- * after). (doesn't, to be like BSD)
+ * after). (doesn't, to be like BSD. That's configurable, but defaults
+ * to off)
* MUST inform application layer asynchronously of incoming urgent
* data. (does)
* MUST provide application with means of determining the amount of
@@ -282,7 +283,8 @@
* MUST ignore unsupported options (does)
*
* Maximum Segment Size Option (4.2.2.6)
- * MUST implement both sending and receiving MSS. (does)
+ * MUST implement both sending and receiving MSS. (does, but currently
+ * only uses the smaller of both of them)
* SHOULD send an MSS with every SYN where receive MSS != 536 (MAY send
* it always). (does, even when MSS == 536, which is legal)
* MUST assume MSS == 536 if no MSS received at connection setup (does)
@@ -296,7 +298,8 @@
* Initial Sequence Number Selection (4.2.2.8)
* MUST use the RFC 793 clock selection mechanism. (doesn't, but it's
* OK: RFC 793 specifies a 250KHz clock, while we use 1MHz, which is
- * necessary for 10Mbps networks - and harder than BSD to spoof!)
+ * necessary for 10Mbps networks - and harder than BSD to spoof!
+ * With syncookies we doesn't)
*
* Simultaneous Open Attempts (4.2.2.10)
* MUST support simultaneous open attempts (does)
@@ -359,8 +362,8 @@
* MAY provide keep-alives. (does)
* MUST make keep-alives configurable on a per-connection basis. (does)
* MUST default to no keep-alives. (does)
- * **MUST make keep-alive interval configurable. (doesn't)
- * **MUST make default keep-alive interval > 2 hours. (doesn't)
+ * MUST make keep-alive interval configurable. (does)
+ * MUST make default keep-alive interval > 2 hours. (does)
* MUST NOT interpret failure to ACK keep-alive packet as dead
* connection. (doesn't)
* SHOULD send keep-alive with no data. (does)
@@ -384,15 +387,16 @@
* Unreachables (0, 1, 5), Time Exceededs and Parameter
* Problems. (doesn't)
* SHOULD report soft Destination Unreachables etc. to the
- * application. (does)
+ * application. (does, but may drop them in the ICMP error handler
+ * during an accept())
* SHOULD abort connection upon receipt of hard Destination Unreachable
- * messages (2, 3, 4). (does)
+ * messages (2, 3, 4). (does, but see above)
*
* Remote Address Validation (4.2.3.10)
* MUST reject as an error OPEN for invalid remote IP address. (does)
* MUST ignore SYN with invalid source address. (does)
* MUST silently discard incoming SYN for broadcast/multicast
- * address. (does)
+ * address. (I'm not sure if it does. Someone should check this.)
*
* Asynchronous Reports (4.2.4.1)
* MUST provide mechanism for reporting soft errors to application
@@ -402,6 +406,7 @@
* MUST allow application layer to set Type of Service. (does IP_TOS)
*
* (Whew. -- MS 950903)
+ * (Updated by AK, but not complete yet.)
**/
#include <linux/types.h>
@@ -416,7 +421,6 @@
int sysctl_tcp_fin_timeout = TCP_FIN_TIMEOUT;
-unsigned long seq_offset;
struct tcp_mib tcp_statistics;
kmem_cache_t *tcp_openreq_cachep;
@@ -426,17 +430,20 @@
* the socket locked or with interrupts disabled
*/
-static struct open_request *tcp_find_established(struct tcp_opt *tp)
+static struct open_request *tcp_find_established(struct tcp_opt *tp,
+ struct open_request **prevp)
{
struct open_request *req = tp->syn_wait_queue;
-
+ struct open_request *prev = (struct open_request *)&tp->syn_wait_queue;
while(req) {
if (req->sk &&
(req->sk->state == TCP_ESTABLISHED ||
req->sk->state >= TCP_FIN_WAIT1))
break;
+ prev = req;
req = req->dl_next;
}
+ *prevp = prev;
return req;
}
@@ -466,8 +473,7 @@
tcp_openreq_free(iter);
}
- tp->syn_wait_queue = NULL;
- tp->syn_wait_last = &tp->syn_wait_queue;
+ tcp_synq_init(tp);
}
/*
@@ -566,10 +572,10 @@
*/
static unsigned int tcp_listen_poll(struct sock *sk, poll_table *wait)
{
- struct open_request *req;
+ struct open_request *req, *dummy;
lock_sock(sk);
- req = tcp_find_established(&sk->tp_pinfo.af_tcp);
+ req = tcp_find_established(&sk->tp_pinfo.af_tcp, &dummy);
release_sock(sk);
if (req)
return POLLIN | POLLRDNORM;
@@ -1021,7 +1027,10 @@
sk->urg_data = URG_READ;
if(len>0)
+ {
err = memcpy_toiovec(msg->msg_iov, &c, 1);
+ msg->msg_flags|=MSG_OOB;
+ }
else
msg->msg_flags|=MSG_TRUNC;
@@ -1415,13 +1424,9 @@
static inline int closing(struct sock * sk)
{
- switch (sk->state) {
- case TCP_FIN_WAIT1:
- case TCP_CLOSING:
- case TCP_LAST_ACK:
- return 1;
- };
- return 0;
+ return ((1 << sk->state) & ((1 << TCP_FIN_WAIT1)|
+ (1 << TCP_CLOSING)|
+ (1 << TCP_LAST_ACK)));
}
@@ -1501,7 +1506,7 @@
static struct open_request * wait_for_connect(struct sock * sk)
{
struct wait_queue wait = { current, NULL };
- struct open_request *req = NULL;
+ struct open_request *req = NULL, *dummy;
add_wait_queue(sk->sleep, &wait);
for (;;) {
@@ -1509,8 +1514,8 @@
release_sock(sk);
schedule();
lock_sock(sk);
- req = tcp_find_established(&(sk->tp_pinfo.af_tcp));
- if (req)
+ req = tcp_find_established(&(sk->tp_pinfo.af_tcp), &dummy);
+ if (req)
break;
if (current->signal & ~current->blocked)
break;
@@ -1528,7 +1533,7 @@
struct sock *tcp_accept(struct sock *sk, int flags)
{
struct tcp_opt *tp = &sk->tp_pinfo.af_tcp;
- struct open_request *req;
+ struct open_request *req, *prev;
struct sock *newsk = NULL;
int error;
@@ -1541,13 +1546,18 @@
lock_sock(sk);
- req = tcp_find_established(tp);
+ req = tcp_find_established(tp, &prev);
if (req) {
got_new_connect:
- tcp_synq_unlink(tp, req);
+ tcp_synq_unlink(tp, req, prev);
newsk = req->sk;
tcp_openreq_free(req);
sk->ack_backlog--;
+ /* FIXME: need to check here if socket has already
+ * an soft_err or err set.
+ * We have two options here then: reply (this behaviour matches
+ * Solaris) or return the error to the application (old Linux)
+ */
error = 0;
out:
release_sock(sk);
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov