patch-1.3.87 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: 1723
- Date:
Fri Apr 12 15:01:02 1996
- Orig file:
v1.3.86/linux/net/ipv4/tcp.c
- Orig date:
Wed Apr 10 17:02:28 1996
diff -u --recursive --new-file v1.3.86/linux/net/ipv4/tcp.c linux/net/ipv4/tcp.c
@@ -19,63 +19,63 @@
* Arnt Gulbrandsen, <agulbra@nvg.unit.no>
* Jorge Cwik, <jorge@laser.satlink.net>
*
- * Fixes:
+ * Fixes:
* Alan Cox : Numerous verify_area() calls
* Alan Cox : Set the ACK bit on a reset
* Alan Cox : Stopped it crashing if it closed while
- * sk->inuse=1 and was trying to connect
+ * sk->inuse=1 and was trying to connect
* (tcp_err()).
* Alan Cox : All icmp error handling was broken
* pointers passed where wrong and the
* socket was looked up backwards. Nobody
* tested any icmp error code obviously.
- * Alan Cox : tcp_err() now handled properly. It
- * wakes people on errors. select
+ * Alan Cox : tcp_err() now handled properly. It
+ * wakes people on errors. select
* behaves and the icmp error race
* has gone by moving it into sock.c
- * Alan Cox : tcp_send_reset() fixed to work for
- * everything not just packets for
+ * Alan Cox : tcp_send_reset() fixed to work for
+ * everything not just packets for
* unknown sockets.
* Alan Cox : tcp option processing.
- * Alan Cox : Reset tweaked (still not 100%) [Had
+ * Alan Cox : Reset tweaked (still not 100%) [Had
* syn rule wrong]
* Herp Rosmanith : More reset fixes
- * Alan Cox : No longer acks invalid rst frames.
+ * Alan Cox : No longer acks invalid rst frames.
* Acking any kind of RST is right out.
- * Alan Cox : Sets an ignore me flag on an rst
- * receive otherwise odd bits of prattle
+ * Alan Cox : Sets an ignore me flag on an rst
+ * receive otherwise odd bits of prattle
* escape still
- * Alan Cox : Fixed another acking RST frame bug.
+ * Alan Cox : Fixed another acking RST frame bug.
* Should stop LAN workplace lockups.
- * Alan Cox : Some tidyups using the new skb list
+ * Alan Cox : Some tidyups using the new skb list
* facilities
* Alan Cox : sk->keepopen now seems to work
* Alan Cox : Pulls options out correctly on accepts
* Alan Cox : Fixed assorted sk->rqueue->next errors
* Alan Cox : PSH doesn't end a TCP read. Switched a
* bit to skb ops.
- * Alan Cox : Tidied tcp_data to avoid a potential
+ * Alan Cox : Tidied tcp_data to avoid a potential
* nasty.
- * Alan Cox : Added some better commenting, as the
+ * Alan Cox : Added some better commenting, as the
* tcp is hard to follow
* Alan Cox : Removed incorrect check for 20 * psh
* Michael O'Reilly : ack < copied bug fix.
* Johannes Stille : Misc tcp fixes (not all in yet).
* Alan Cox : FIN with no memory -> CRASH
- * Alan Cox : Added socket option proto entries.
+ * Alan Cox : Added socket option proto entries.
* Also added awareness of them to accept.
* Alan Cox : Added TCP options (SOL_TCP)
- * Alan Cox : Switched wakeup calls to callbacks,
- * so the kernel can layer network
+ * Alan Cox : Switched wakeup calls to callbacks,
+ * so the kernel can layer network
* sockets.
* Alan Cox : Use ip_tos/ip_ttl settings.
* Alan Cox : Handle FIN (more) properly (we hope).
- * Alan Cox : RST frames sent on unsynchronised
+ * Alan Cox : RST frames sent on unsynchronised
* state ack error.
* Alan Cox : Put in missing check for SYN bit.
- * Alan Cox : Added tcp_select_window() aka NET2E
+ * Alan Cox : Added tcp_select_window() aka NET2E
* window non shrink trick.
- * Alan Cox : Added a couple of small NET2E timer
+ * Alan Cox : Added a couple of small NET2E timer
* fixes
* Charles Hedrick : TCP fixes
* Toomas Tamm : TCP window fixes
@@ -89,7 +89,7 @@
* Adam Caldwell : Assorted timer/timing errors
* Matthew Dillon : Fixed another RST bug
* Alan Cox : Move to kernel side addressing changes.
- * Alan Cox : Beginning work on TCP fastpathing
+ * Alan Cox : Beginning work on TCP fastpathing
* (not yet usable)
* Arnt Gulbrandsen: Turbocharged tcp_check() routine.
* Alan Cox : TCP fast path debugging
@@ -97,21 +97,21 @@
* Michael Riepe : Bug in tcp_check()
* Matt Dillon : More TCP improvements and RST bug fixes
* Matt Dillon : Yet more small nasties remove from the
- * TCP code (Be very nice to this man if
+ * TCP code (Be very nice to this man if
* tcp finally works 100%) 8)
- * Alan Cox : BSD accept semantics.
+ * Alan Cox : BSD accept semantics.
* Alan Cox : Reset on closedown bug.
* Peter De Schrijver : ENOTCONN check missing in tcp_sendto().
- * Michael Pall : Handle select() after URG properly in
+ * Michael Pall : Handle select() after URG properly in
* all cases.
- * Michael Pall : Undo the last fix in tcp_read_urg()
+ * Michael Pall : Undo the last fix in tcp_read_urg()
* (multi URG PUSH broke rlogin).
- * Michael Pall : Fix the multi URG PUSH problem in
- * tcp_readable(), select() after URG
+ * Michael Pall : Fix the multi URG PUSH problem in
+ * tcp_readable(), select() after URG
* works now.
- * Michael Pall : recv(...,MSG_OOB) never blocks in the
+ * Michael Pall : recv(...,MSG_OOB) never blocks in the
* BSD api.
- * Alan Cox : Changed the semantics of sk->socket to
+ * Alan Cox : Changed the semantics of sk->socket to
* fix a race and a signal problem with
* accept() and async I/O.
* Alan Cox : Relaxed the rules on tcp_sendto().
@@ -128,23 +128,23 @@
* Alan Cox : Reset tracing code.
* Alan Cox : Spurious resets on shutdown.
* Alan Cox : Giant 15 minute/60 second timer error
- * Alan Cox : Small whoops in selecting before an
+ * Alan Cox : Small whoops in selecting before an
* accept.
- * Alan Cox : Kept the state trace facility since
+ * Alan Cox : Kept the state trace facility since
* it's handy for debugging.
* Alan Cox : More reset handler fixes.
- * Alan Cox : Started rewriting the code based on
- * the RFC's for other useful protocol
- * references see: Comer, KA9Q NOS, and
- * for a reference on the difference
+ * Alan Cox : Started rewriting the code based on
+ * the RFC's for other useful protocol
+ * references see: Comer, KA9Q NOS, and
+ * for a reference on the difference
* between specifications and how BSD
* works see the 4.4lite source.
- * A.N.Kuznetsov : Don't time wait on completion of tidy
+ * A.N.Kuznetsov : Don't time wait on completion of tidy
* close.
* Linus Torvalds : Fin/Shutdown & copied_seq changes.
* Linus Torvalds : Fixed BSD port reuse to work first syn
- * Alan Cox : Reimplemented timers as per the RFC
- * and using multiple timers for sanity.
+ * Alan Cox : Reimplemented timers as per the RFC
+ * and using multiple timers for sanity.
* Alan Cox : Small bug fixes, and a lot of new
* comments.
* Alan Cox : Fixed dual reader crash by locking
@@ -164,7 +164,7 @@
* Alan Cox : Per route irtt.
* Matt Day : Select() match BSD precisely on error
* Alan Cox : New buffers
- * Marc Tamsky : Various sk->prot->retransmits and
+ * Marc Tamsky : Various sk->prot->retransmits and
* sk->retransmits misupdating fixed.
* Fixed tcp_write_timeout: stuck close,
* and TCP syn retries gets used now.
@@ -180,14 +180,26 @@
* Alan Cox : Small hooks for enSKIP.
* Alexey Kuznetsov: Path MTU discovery.
* Alan Cox : Support soft errors.
- * Alan Cox : Fix MTU discovery pathalogical case
+ * Alan Cox : Fix MTU discovery pathological case
* when the remote claims no mtu!
* Marc Tamsky : TCP_CLOSE fix.
- * Colin (G3TNE) : Send a reset on syn ack replies in
+ * Colin (G3TNE) : Send a reset on syn ack replies in
* window but wrong (fixes NT lpd problems)
* Pedro Roque : Better TCP window handling, delayed ack.
- * Joerg Reuter : No modification of locked buffers in
+ * Joerg Reuter : No modification of locked buffers in
* tcp_do_retransmit()
+ * Eric Schenk : Changed receiver side silly window
+ * avoidance algorithm to BSD style
+ * algorithm. This doubles throughput
+ * against machines running Solaris,
+ * and seems to result in general
+ * improvement.
+ * Eric Schenk : Changed receiver side silly window
+ * avoidance algorithm to BSD style
+ * algorithm. This doubles throughput
+ * against machines running Solaris,
+ * and seems to result in general
+ * improvement.
*
* To Fix:
* Fast path the code. Two things here - fix the window calculation
@@ -209,7 +221,7 @@
* tcp_data/tcp_read as well as the window shrink crud.
* Separate out duplicated code - tcp_alloc_skb, tcp_build_ack
* tcp_queue_skb seem obvious routines to extract.
- *
+ *
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
@@ -246,7 +258,7 @@
* TCP_LAST_ACK out side has shutdown after remote has
* shutdown. There may still be data in our
* buffer that we have to finish sending
- *
+ *
* TCP_CLOSE socket is finished
*/
@@ -256,7 +268,7 @@
* for violations and the like. tcp.c is just too big... If I say something
* "does?" or "doesn't?", it means I'm not sure, and will have to hash it out
* with Alan. -- MS 950903
- *
+ *
* Use of PSH (4.2.2.2)
* MAY aggregate data sent without the PSH flag. (does)
* MAY queue data received without the PSH flag. (does)
@@ -266,12 +278,12 @@
* MUST set PSH on last segment (does)
* MAY pass received PSH to application layer (doesn't)
* SHOULD send maximum-sized segment whenever possible. (almost always does)
- *
+ *
* Window Size (4.2.2.3, 4.2.2.16)
* MUST treat window size as an unsigned number (does)
* SHOULD treat window size as a 32-bit number (does not)
* MUST NOT shrink window once it is offered (does not normally)
- *
+ *
* 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)
@@ -282,11 +294,11 @@
* **MUST support urgent data sequence of arbitrary length. (doesn't, but
* it's sort of tricky to fix, as urg_ptr is a 16-bit quantity)
* [Follows BSD 1 byte of urgent data]
- *
+ *
* TCP Options (4.2.2.5)
* MUST be able to receive TCP options in any segment. (does)
* MUST ignore unsupported options (does)
- *
+ *
* Maximum Segment Size Option (4.2.2.6)
* MUST implement both sending and receiving MSS. (does)
* SHOULD send an MSS with every SYN where receive MSS != 536 (MAY send
@@ -295,72 +307,72 @@
* MUST calculate "effective send MSS" correctly:
* min(physical_MTU, remote_MSS+20) - sizeof(tcphdr) - sizeof(ipopts)
* (does - but allows operator override)
- *
+ *
* TCP Checksum (4.2.2.7)
* MUST generate and check TCP checksum. (does)
- *
+ *
* 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!)
- *
+ *
* Simultaneous Open Attempts (4.2.2.10)
* MUST support simultaneous open attempts (does)
- *
+ *
* Recovery from Old Duplicate SYN (4.2.2.11)
* MUST keep track of active vs. passive open (does)
- *
+ *
* RST segment (4.2.2.12)
* SHOULD allow an RST segment to contain data (does, but doesn't do
* anything with it, which is standard)
- *
+ *
* Closing a Connection (4.2.2.13)
- * MUST inform application of whether connectin was closed by RST or
+ * MUST inform application of whether connection was closed by RST or
* normal close. (does)
* MAY allow "half-duplex" close (treat connection as closed for the
* local app, even before handshake is done). (does)
* MUST linger in TIME_WAIT for 2 * MSL (does)
- *
+ *
* Retransmission Timeout (4.2.2.15)
* MUST implement Jacobson's slow start and congestion avoidance
- * stuff. (does)
- *
+ * stuff. (does)
+ *
* Probing Zero Windows (4.2.2.17)
* MUST support probing of zero windows. (does)
* MAY keep offered window closed indefinitely. (does)
* MUST allow remote window to stay closed indefinitely. (does)
- *
+ *
* Passive Open Calls (4.2.2.18)
* MUST NOT let new passive open affect other connections. (doesn't)
* MUST support passive opens (LISTENs) concurrently. (does)
- *
+ *
* Time to Live (4.2.2.19)
* MUST make TCP TTL configurable. (does - IP_TTL option)
- *
+ *
* Event Processing (4.2.2.20)
* SHOULD queue out-of-order segments. (does)
* MUST aggregate ACK segments whenever possible. (does but badly)
- *
+ *
* Retransmission Timeout Calculation (4.2.3.1)
* MUST implement Karn's algorithm and Jacobson's algorithm for RTO
* calculation. (does, or at least explains them in the comments 8*b)
* SHOULD initialize RTO to 0 and RTT to 3. (does)
- *
+ *
* When to Send an ACK Segment (4.2.3.2)
* SHOULD implement delayed ACK. (does)
* MUST keep ACK delay < 0.5 sec. (does)
- *
+ *
* When to Send a Window Update (4.2.3.3)
* MUST implement receiver-side SWS. (does)
- *
+ *
* When to Send Data (4.2.3.4)
* MUST implement sender-side SWS. (does)
* SHOULD implement Nagle algorithm. (does)
- *
+ *
* TCP Connection Failures (4.2.3.5)
* MUST handle excessive retransmissions "properly" (see the RFC). (does)
* SHOULD inform application layer of soft errors. (does)
- *
+ *
* TCP Keep-Alives (4.2.3.6)
* MAY provide keep-alives. (does)
* MUST make keep-alives configurable on a per-connection basis. (does)
@@ -370,19 +382,19 @@
* MUST NOT interpret failure to ACK keep-alive packet as dead
* connection. (doesn't)
* SHOULD send keep-alive with no data. (does)
- *
+ *
* TCP Multihoming (4.2.3.7)
* MUST get source address from IP layer before sending first
* SYN. (does)
* MUST use same local address for all segments of a connection. (does)
- *
+ *
* IP Options (4.2.3.8)
* MUST ignore unsupported IP options. (does)
* MAY support Time Stamp and Record Route. (does)
* MUST allow application to specify a source route. (does)
- * MUST allow receieved Source Route option to set route for all future
+ * MUST allow received Source Route option to set route for all future
* segments on this connection. (does not (security issues))
- *
+ *
* ICMP messages (4.2.3.9)
* MUST act on ICMP errors. (does)
* MUST slow transmission upon receipt of a Source Quench. (does)
@@ -393,20 +405,20 @@
* application. (does)
* SHOULD abort connection upon receipt of hard Destination Unreachable
* messages (2, 3, 4). (does)
- *
+ *
* 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. (does)
+ *
* Asynchronous Reports (4.2.4.1)
* MUST provide mechanism for reporting soft errors to application
* layer. (does)
- *
+ *
* Type of Service (4.2.4.2)
* MUST allow application layer to set Type of Service. (does IP_TOS)
- *
+ *
* (Whew. -- MS 950903)
**/
@@ -433,7 +445,7 @@
/*
* Find someone to 'accept'. Must be called with
* the socket locked or with interrupts disabled
- */
+ */
static struct sk_buff *tcp_find_established(struct sock *s)
{
@@ -460,7 +472,7 @@
struct sk_buff *skb;
unsigned long flags;
save_flags(flags);
- cli();
+ cli();
skb=tcp_find_established(s);
if(skb!=NULL)
skb_unlink(skb); /* Take it off the queue */
@@ -468,17 +480,17 @@
return skb;
}
-/*
+/*
* This routine closes sockets which have been at least partially
* opened, but not yet accepted. Currently it is only called by
- * tcp_close, and timeout mirrors the value there.
+ * tcp_close, and timeout mirrors the value there.
*/
-static void tcp_close_pending (struct sock *sk)
+static void tcp_close_pending (struct sock *sk)
{
struct sk_buff *skb;
- while ((skb = skb_dequeue(&sk->receive_queue)) != NULL)
+ while ((skb = skb_dequeue(&sk->receive_queue)) != NULL)
{
tcp_close(skb->sk, 0);
kfree_skb(skb, FREE_READ);
@@ -487,7 +499,7 @@
}
/*
- * Enter the time wait state.
+ * Enter the time wait state.
*/
void tcp_time_wait(struct sock *sk)
@@ -514,20 +526,20 @@
{
struct tcphdr *th = (struct tcphdr *)header;
struct sock *sk;
-
+
/*
* This one is _WRONG_. FIXME urgently.
*/
-#ifndef CONFIG_NO_PATH_MTU_DISCOVERY
+#ifndef CONFIG_NO_PATH_MTU_DISCOVERY
struct iphdr *iph=(struct iphdr *)(header-sizeof(struct iphdr));
-#endif
+#endif
th =(struct tcphdr *)header;
sk = get_sock(&tcp_prot, th->source, daddr, th->dest, saddr);
- if (sk == NULL)
+ if (sk == NULL)
return;
-
- if (type == ICMP_SOURCE_QUENCH)
+
+ if (type == ICMP_SOURCE_QUENCH)
{
/*
* FIXME:
@@ -538,7 +550,7 @@
sk->cong_window--;
return;
}
-
+
if (type == ICMP_PARAMETERPROB)
{
sk->err=EPROTO;
@@ -573,11 +585,11 @@
*/
if (code < 13)
- {
+ {
if(icmp_err_convert[code].fatal || sk->state == TCP_SYN_SENT || sk->state == TCP_SYN_RECV)
{
sk->err = icmp_err_convert[code].errno;
- if (sk->state == TCP_SYN_SENT || sk->state == TCP_SYN_RECV)
+ if (sk->state == TCP_SYN_SENT || sk->state == TCP_SYN_RECV)
{
tcp_statistics.TcpAttemptFails++;
tcp_set_state(sk,TCP_CLOSE);
@@ -612,29 +624,29 @@
if (sk == NULL || (skb = skb_peek(&sk->receive_queue)) == NULL)
{
restore_flags(flags);
- if(sk && sk->debug)
+ if(sk && sk->debug)
printk("empty\n");
return(0);
}
-
+
counted = sk->copied_seq; /* Where we are at the moment */
amount = 0;
-
- /*
- * Do until a push or until we are out of data.
+
+ /*
+ * Do until a push or until we are out of data.
*/
-
- do
+
+ do
{
if (before(counted, skb->seq)) /* Found a hole so stops here */
break;
sum = skb->len - (counted - skb->seq); /* Length - header but start from where we are up to (avoid overlaps) */
if (skb->h.th->syn)
sum++;
- if (sum > 0)
+ if (sum > 0)
{ /* Add it up, move on */
amount += sum;
- if (skb->h.th->syn)
+ if (skb->h.th->syn)
amount--;
counted += sum;
}
@@ -707,7 +719,7 @@
if (sk->shutdown & RCV_SHUTDOWN)
return 1;
-
+
if (sk->acked_seq == sk->copied_seq)
break;
@@ -720,7 +732,7 @@
case SEL_OUT:
if (sk->err)
return 1;
- if (sk->shutdown & SEND_SHUTDOWN)
+ if (sk->shutdown & SEND_SHUTDOWN)
return 0;
if (sk->state == TCP_SYN_SENT || sk->state == TCP_SYN_RECV)
break;
@@ -745,7 +757,7 @@
int tcp_ioctl(struct sock *sk, int cmd, unsigned long arg)
{
int err;
- switch(cmd)
+ switch(cmd)
{
case TIOCINQ:
@@ -755,7 +767,7 @@
{
unsigned long amount;
- if (sk->state == TCP_LISTEN)
+ if (sk->state == TCP_LISTEN)
return(-EINVAL);
lock_sock(sk);
@@ -796,13 +808,13 @@
/*
- * This routine computes a TCP checksum.
+ * This routine computes a TCP checksum.
*
* Modified January 1995 from a go-faster DOS routine by
* Jorge Cwik <jorge@laser.satlink.net>
*/
#undef DEBUG_TCP_CHECK
-void tcp_send_check(struct tcphdr *th, unsigned long saddr,
+void tcp_send_check(struct tcphdr *th, unsigned long saddr,
unsigned long daddr, int len, struct sk_buff *skb)
{
#ifdef DEBUG_TCP_CHECK
@@ -829,22 +841,17 @@
}
-/*
- * This routine builds a generic TCP header.
+/*
+ * This routine builds a generic TCP header.
*/
-
-extern __inline int tcp_build_header(struct tcphdr *th, struct sock *sk, int push)
-{
+static inline int tcp_build_header(struct tcphdr *th, struct sock *sk, int push)
+{
memcpy(th,(void *) &(sk->dummy_th), sizeof(*th));
+ th->psh = (push == 0) ? 1 : 0;
th->seq = htonl(sk->write_seq);
- th->psh =(push == 0) ? 1 : 0;
- sk->ack_backlog = 0;
- sk->bytes_rcv = 0;
- sk->ack_timed = 0;
th->ack_seq = htonl(sk->acked_seq);
- sk->window = tcp_select_window(sk);
- th->window = htons(sk->window);
+ th->window = htons(tcp_select_window(sk));
return(sizeof(*th));
}
@@ -855,10 +862,10 @@
static void wait_for_tcp_connect(struct sock * sk)
{
release_sock(sk);
- cli();
- if (sk->state != TCP_ESTABLISHED && sk->state != TCP_CLOSE_WAIT && sk->err == 0)
+ cli();
+ if (sk->state != TCP_ESTABLISHED && sk->state != TCP_CLOSE_WAIT && sk->err == 0)
{
- interruptible_sleep_on(sk->sleep);
+ interruptible_sleep_on(sk->sleep);
}
sti();
lock_sock(sk);
@@ -873,7 +880,7 @@
cli();
if (sk->wmem_alloc*2 > sk->sndbuf &&
(sk->state == TCP_ESTABLISHED||sk->state == TCP_CLOSE_WAIT)
- && sk->err == 0)
+ && sk->err == 0)
{
sk->socket->flags &= ~SO_NOSPACE;
interruptible_sleep_on(sk->sleep);
@@ -901,65 +908,65 @@
struct proto *prot;
struct device *dev = NULL;
unsigned char *from;
-
+
/*
* Ok commence sending
*/
-
+
while(iovct<msg->msg_iovlen)
{
seglen=msg->msg_iov[iovct].iov_len;
from=msg->msg_iov[iovct++].iov_base;
prot = sk->prot;
- while(seglen > 0)
+ while(seglen > 0)
{
/*
* Stop on errors
*/
- if (sk->err)
+ if (sk->err)
{
- if (copied)
+ if (copied)
return copied;
return sock_error(sk);
}
/*
- * Make sure that we are established.
+ * Make sure that we are established.
*/
- if (sk->shutdown & SEND_SHUTDOWN)
+ if (sk->shutdown & SEND_SHUTDOWN)
{
if (copied)
return copied;
return -EPIPE;
}
- /*
+ /*
* Wait for a connection to finish.
*/
- while (sk->state != TCP_ESTABLISHED && sk->state != TCP_CLOSE_WAIT)
+ while (sk->state != TCP_ESTABLISHED && sk->state != TCP_CLOSE_WAIT)
{
if (copied)
return copied;
- if (sk->err)
+ if (sk->err)
return sock_error(sk);
-
+
if (sk->state != TCP_SYN_SENT && sk->state != TCP_SYN_RECV)
{
if (sk->keepopen)
send_sig(SIGPIPE, current, 0);
return -EPIPE;
}
-
+
if (nonblock)
return -EAGAIN;
if (current->signal & ~current->blocked)
return -ERESTARTSYS;
-
+
wait_for_tcp_connect(sk);
}
-
+
/*
* The following code can result in copy <= if sk->mss is ever
* decreased. It shouldn't be. sk->mss is min(sk->mtu, sk->max_window).
@@ -971,9 +978,9 @@
* before the exchange of SYN's. If the initial ack from the other
* end has a window of 0, max_window and thus mss will both be 0.
*/
-
- /*
- * Now we need to check if we have a half built packet.
+
+ /*
+ * Now we need to check if we have a half built packet.
*/
#ifndef CONFIG_NO_PATH_MTU_DISCOVERY
/*
@@ -981,7 +988,7 @@
* but it works... I do not know why 8) --ANK
*
* Really, we should rebuild all the queues...
- * It's difficult. Temprorary hack is to send all
+ * It's difficult. Temporary hack is to send all
* queued segments with allowed fragmentation.
*/
{
@@ -993,18 +1000,18 @@
}
}
#endif
-
- if ((skb = tcp_dequeue_partial(sk)) != NULL)
+
+ if ((skb = tcp_dequeue_partial(sk)) != NULL)
{
int tcp_size;
tcp_size = skb->tail - (unsigned char *)(skb->h.th + 1);
-
+
/* Add more stuff to the end of skb->len */
- if (!(flags & MSG_OOB))
+ if (!(flags & MSG_OOB))
{
copy = min(sk->mss - tcp_size, seglen);
- if (copy <= 0)
+ if (copy <= 0)
{
printk("TCP: **bug**: \"copy\" <= 0\n");
return -EFAULT;
@@ -1031,7 +1038,7 @@
* host, don't use it. This is sender side
* silly window prevention, as specified in RFC1122.
* (Note that this is different than earlier versions of
- * SWS prevention, e.g. RFC813.). What we actually do is
+ * SWS prevention, e.g. RFC813.). What we actually do is
* use the whole MSS. Since the results in the right
* edge of the packet being outside the window, it will
* be queued for later rather than sent.
@@ -1042,37 +1049,37 @@
copy = sk->mss;
if (copy > seglen)
copy = seglen;
- if (copy <= 0)
+ if (copy <= 0)
{
printk("TCP: **bug**: copy=%d, sk->mss=%d\n", copy, sk->mss);
return -EFAULT;
}
/*
- * We should really check the window here also.
+ * We should really check the window here also.
*/
-
+
send_tmp = NULL;
- if (copy < sk->mss && !(flags & MSG_OOB) && sk->packets_out)
+ if (copy < sk->mss && !(flags & MSG_OOB) && sk->packets_out)
{
skb = sock_wmalloc(sk, sk->mtu + 128 + prot->max_header + 15, 0, GFP_KERNEL);
send_tmp = skb;
- }
- else
+ }
+ else
{
skb = sock_wmalloc(sk, copy + prot->max_header + 15 , 0, GFP_KERNEL);
}
-
+
/*
- * If we didn't get any memory, we need to sleep.
+ * If we didn't get any memory, we need to sleep.
*/
-
- if (skb == NULL)
+
+ if (skb == NULL)
{
sk->socket->flags |= SO_NOSPACE;
- if (nonblock)
+ if (nonblock)
{
- if (copied)
+ if (copied)
return copied;
return -EAGAIN;
}
@@ -1091,18 +1098,18 @@
skb->sk = sk;
skb->free = 0;
skb->localroute = sk->localroute|(flags&MSG_DONTROUTE);
-
+
/*
* FIXME: we need to optimize this.
* Perhaps some hints here would be good.
*/
-
+
tmp = prot->build_header(skb, sk->saddr, sk->daddr, &dev,
IPPROTO_TCP, sk->opt, skb->truesize,sk->ip_tos,sk->ip_ttl,&sk->ip_route_cache);
- if (tmp < 0 )
+ if (tmp < 0 )
{
sock_wfree(sk, skb);
- if (copied)
+ if (copied)
return(copied);
return(tmp);
}
@@ -1112,15 +1119,15 @@
skb->dev = dev;
skb->h.th =(struct tcphdr *)skb_put(skb,sizeof(struct tcphdr));
tmp = tcp_build_header(skb->h.th, sk, seglen-copy);
- if (tmp < 0)
+ if (tmp < 0)
{
sock_wfree(sk, skb);
- if (copied)
+ if (copied)
return(copied);
return(tmp);
}
-
- if (flags & MSG_OOB)
+
+ if (flags & MSG_OOB)
{
skb->h.th->urg = 1;
skb->h.th->urg_ptr = ntohs(copy);
@@ -1128,15 +1135,15 @@
skb->csum = csum_partial_copy_fromuser(from,
skb_put(skb,copy), copy, 0);
-
+
from += copy;
copied += copy;
len -= copy;
seglen -= copy;
skb->free = 0;
sk->write_seq += copy;
-
- if (send_tmp != NULL)
+
+ if (send_tmp != NULL)
{
tcp_enqueue_partial(send_tmp, sk);
continue;
@@ -1158,7 +1165,7 @@
/*
* Do sanity checking for sendmsg/sendto/send
*/
-
+
if (flags & ~(MSG_OOB|MSG_DONTROUTE))
goto out;
if (msg->msg_name) {
@@ -1166,15 +1173,15 @@
if (msg->msg_namelen < sizeof(*addr))
goto out;
- if (addr->sin_family && addr->sin_family != AF_INET)
+ if (addr->sin_family && addr->sin_family != AF_INET)
goto out;
retval = -ENOTCONN;
if(sk->state == TCP_CLOSE)
goto out;
retval = -EISCONN;
- if (addr->sin_port != sk->dummy_th.dest)
+ if (addr->sin_port != sk->dummy_th.dest)
goto out;
- if (addr->sin_addr.s_addr != sk->daddr)
+ if (addr->sin_addr.s_addr != sk->daddr)
goto out;
}
@@ -1202,17 +1209,17 @@
out:
return retval;
}
-
+
/*
- * Send an ack if one is backlogged at this point.
+ * Send an ack if one is backlogged at this point.
*
- * This is called for delayed acks also.
+ * This is called for delayed acks also.
*/
-
+
void tcp_read_wakeup(struct sock *sk)
{
- if (!sk->ack_backlog)
+ if (!sk->ack_backlog)
return;
/*
@@ -1220,7 +1227,7 @@
* from the closed destination.
*/
if ((sk->state == TCP_CLOSE) || (sk->state == TCP_TIME_WAIT))
- return;
+ return;
tcp_send_ack(sk);
}
@@ -1230,7 +1237,7 @@
* Handle reading urgent data. BSD has very simple semantics for
* this, no blocking and very strange errors 8)
*/
-
+
static int tcp_recv_urg(struct sock * sk, int nonblock,
struct msghdr *msg, int len, int flags, int *addr_len)
{
@@ -1239,13 +1246,13 @@
*/
if (sk->urginline || !sk->urg_data || sk->urg_data == URG_READ)
return -EINVAL; /* Yes this is right ! */
-
- if (sk->err)
+
+ if (sk->err)
return sock_error(sk);
-
- if (sk->state == TCP_CLOSE || sk->done)
+
+ if (sk->state == TCP_CLOSE || sk->done)
{
- if (!sk->done)
+ if (!sk->done)
{
sk->done = 1;
return 0;
@@ -1253,13 +1260,13 @@
return -ENOTCONN;
}
- if (sk->shutdown & RCV_SHUTDOWN)
+ if (sk->shutdown & RCV_SHUTDOWN)
{
sk->done = 1;
return 0;
}
lock_sock(sk);
- if (sk->urg_data & URG_VALID)
+ if (sk->urg_data & URG_VALID)
{
char c = sk->urg_data;
if (!(flags & MSG_PEEK))
@@ -1278,7 +1285,7 @@
return 1;
}
release_sock(sk);
-
+
/*
* Fixed the recv(..., MSG_OOB) behaviour. BSD docs and
* the available implementations agree in this case:
@@ -1294,7 +1301,7 @@
* must be called with interrupts disabled or with the
* socket locked so that the sk_buff queue operation is ok.
*/
-
+
static inline void tcp_eat_skb(struct sock *sk, struct sk_buff * skb)
{
skb->sk = sk;
@@ -1303,38 +1310,37 @@
}
/*
- * FIXME:
- * This routine frees used buffers.
- * It should consider sending an ACK to let the
- * other end know we now have a bigger window.
+ * FIXME:
+ * This routine frees used buffers.
+ * It should consider sending an ACK to let the
+ * other end know we now have a bigger window.
*/
static void cleanup_rbuf(struct sock *sk)
{
- struct sk_buff *skb;
-
/*
* NOTE! The socket must be locked, so that we don't get
* a messed-up receive queue.
*/
- while ((skb=skb_peek(&sk->receive_queue)) != NULL) {
+ while (!skb_queue_empty(&sk->receive_queue)) {
+ struct sk_buff *skb = sk->receive_queue.next;
if (!skb->used || skb->users)
break;
tcp_eat_skb(sk, skb);
}
- /* If we raised the window due to cleaning up, tell the world.. */
- if (tcp_raise_window(sk)) {
- sk->ack_backlog++;
- tcp_read_wakeup(sk);
- }
-}
+ /*
+ * Tell the world if we raised the window.
+ */
+ if (tcp_raise_window(sk))
+ tcp_send_ack(sk);
+}
/*
- * This routine copies from a sock struct into the user buffer.
+ * This routine copies from a sock struct into the user buffer.
*/
-
+
static int tcp_recvmsg(struct sock *sk, struct msghdr *msg,
int len, int nonblock, int flags, int *addr_len)
{
@@ -1344,26 +1350,26 @@
volatile u32 *seq; /* So gcc doesn't overoptimise */
unsigned long used;
- /*
- * This error should be checked.
+ /*
+ * This error should be checked.
*/
-
+
if (sk->state == TCP_LISTEN)
return -ENOTCONN;
/*
- * Urgent data needs to be handled specially.
+ * Urgent data needs to be handled specially.
*/
-
+
if (flags & MSG_OOB)
return tcp_recv_urg(sk, nonblock, msg, len, flags, addr_len);
/*
* Copying sequence to update. This is volatile to handle
- * the multi-reader case neatly (memcpy_to/fromfs might be
+ * the multi-reader case neatly (memcpy_to/fromfs might be
* inline and thus not flush cached variables otherwise).
*/
-
+
peek_seq = sk->copied_seq;
seq = &sk->copied_seq;
if (flags & MSG_PEEK)
@@ -1371,15 +1377,15 @@
add_wait_queue(sk->sleep, &wait);
lock_sock(sk);
- while (len > 0)
+ while (len > 0)
{
struct sk_buff * skb;
u32 offset;
-
+
/*
* Are we at urgent data? Stop if we have read anything.
*/
-
+
if (copied && sk->urg_data && sk->urg_seq == *seq)
break;
@@ -1397,11 +1403,11 @@
/*
* Next get a buffer.
*/
-
+
current->state = TASK_INTERRUPTIBLE;
skb = skb_peek(&sk->receive_queue);
- do
+ do
{
if (!skb)
break;
@@ -1423,15 +1429,15 @@
if (copied)
break;
- if (sk->err)
+ if (sk->err)
{
copied = sock_error(sk);
break;
}
- if (sk->state == TCP_CLOSE)
+ if (sk->state == TCP_CLOSE)
{
- if (!sk->done)
+ if (!sk->done)
{
sk->done = 1;
break;
@@ -1440,13 +1446,13 @@
break;
}
- if (sk->shutdown & RCV_SHUTDOWN)
+ if (sk->shutdown & RCV_SHUTDOWN)
{
sk->done = 1;
break;
}
-
- if (nonblock)
+
+ if (nonblock)
{
copied = -EAGAIN;
break;
@@ -1463,32 +1469,32 @@
found_ok_skb:
/*
* Lock the buffer. We can be fairly relaxed as
- * an interrupt will never steal a buffer we are
+ * an interrupt will never steal a buffer we are
* using unless I've missed something serious in
* tcp_data.
*/
-
+
skb->users++;
-
+
/*
- * Ok so how much can we use ?
+ * Ok so how much can we use ?
*/
-
+
used = skb->len - offset;
if (len < used)
used = len;
/*
- * Do we have urgent data here?
+ * Do we have urgent data here?
*/
-
- if (sk->urg_data)
+
+ if (sk->urg_data)
{
u32 urg_offset = sk->urg_seq - *seq;
- if (urg_offset < used)
+ if (urg_offset < used)
{
- if (!urg_offset)
+ if (!urg_offset)
{
- if (!sk->urginline)
+ if (!sk->urginline)
{
++*seq;
offset++;
@@ -1499,12 +1505,12 @@
used = urg_offset;
}
}
-
+
/*
* Copy it - We _MUST_ update *seq first so that we
* don't ever double read when we have dual readers
*/
-
+
*seq += used;
/*
@@ -1512,25 +1518,25 @@
* 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);
copied += used;
len -= used;
-
+
/*
* We now will not sleep again until we are finished
* with skb. Sorry if you are doing the SMP port
* but you'll just have to fix it neatly ;)
*/
-
+
skb->users --;
-
+
if (after(sk->copied_seq,sk->urg_seq))
sk->urg_data = 0;
if (used + offset < skb->len)
continue;
-
+
/*
* Process the FIN.
*/
@@ -1541,24 +1547,24 @@
continue;
skb->used = 1;
if (!skb->users)
- tcp_eat_skb(sk, skb);
+ tcp_eat_skb(sk, skb);
continue;
found_fin_ok:
++*seq;
if (flags & MSG_PEEK)
break;
-
+
/*
* All is done
*/
-
+
skb->used = 1;
sk->shutdown |= RCV_SHUTDOWN;
break;
}
-
+
if(copied>0 && msg->msg_name)
{
struct sockaddr_in *sin=(struct sockaddr_in *)msg->msg_name;
@@ -1568,7 +1574,7 @@
}
if(addr_len)
*addr_len=sizeof(struct sockaddr_in);
-
+
remove_wait_queue(sk->sleep, &wait);
current->state = TASK_RUNNING;
@@ -1582,11 +1588,11 @@
/*
* State processing on a close. This implements the state shift for
- * sending our FIN frame. Note that we only send a FIN for some
+ * sending our FIN frame. Note that we only send a FIN for some
* states. A shutdown() may have already sent the FIN, or we may be
* closed.
*/
-
+
static int tcp_close_state(struct sock *sk, int dead)
{
int ns=TCP_CLOSE;
@@ -1613,9 +1619,9 @@
ns=TCP_LAST_ACK;
send_fin=1;
}
-
+
tcp_set_state(sk,ns);
-
+
/*
* This is a (useful) BSD violating of the RFC. There is a
* problem with TCP as specified in that the other end could
@@ -1633,7 +1639,7 @@
else
tcp_reset_msl_timer(sk, TIME_CLOSE, TCP_FIN_TIMEOUT);
}
-
+
return send_fin;
}
@@ -1650,18 +1656,18 @@
* Tim MacKenzie(tym@dibbler.cs.monash.edu.au) 4 Dec '92.
*/
- if (!(how & SEND_SHUTDOWN))
+ if (!(how & SEND_SHUTDOWN))
return;
-
+
/*
* If we've already sent a FIN, or it's a closed state
*/
-
+
if (sk->state == TCP_FIN_WAIT1 ||
sk->state == TCP_FIN_WAIT2 ||
sk->state == TCP_CLOSING ||
sk->state == TCP_LAST_ACK ||
- sk->state == TCP_TIME_WAIT ||
+ sk->state == TCP_TIME_WAIT ||
sk->state == TCP_CLOSE ||
sk->state == TCP_LISTEN
)
@@ -1677,19 +1683,19 @@
sk->shutdown |= SEND_SHUTDOWN;
/*
- * Clear out any half completed packets.
+ * Clear out any half completed packets.
*/
if (sk->partial)
tcp_send_partial(sk);
-
+
/*
* FIN if needed
*/
-
+
if (tcp_close_state(sk,0))
tcp_send_fin(sk);
-
+
release_sock(sk);
}
@@ -1697,7 +1703,7 @@
/*
* Return 1 if we still have things to send in our buffers.
*/
-
+
static inline int closing(struct sock * sk)
{
switch (sk->state) {
@@ -1715,12 +1721,12 @@
struct sk_buff *skb;
/*
- * We need to grab some memory, and put together a FIN,
+ * We need to grab some memory, and put together a FIN,
* and then put it into the queue to be sent.
*/
-
+
lock_sock(sk);
-
+
tcp_cache_zap();
if(sk->state == TCP_LISTEN)
{
@@ -1731,11 +1737,11 @@
sk->dead = 1;
return;
}
-
+
sk->keepopen = 1;
sk->shutdown = SHUTDOWN_MASK;
- if (!sk->dead)
+ if (!sk->dead)
sk->state_change(sk);
/*
@@ -1743,22 +1749,22 @@
* descriptor close, not protocol-sourced closes, because the
* reader process may not have drained the data yet!
*/
-
+
while((skb=skb_dequeue(&sk->receive_queue))!=NULL)
kfree_skb(skb, FREE_READ);
/*
- * Get rid off any half-completed packets.
+ * Get rid off any half-completed packets.
*/
- if (sk->partial)
+ if (sk->partial)
tcp_send_partial(sk);
-
+
/*
* Timeout is not the same thing - however the code likes
* to send both the same way (sigh).
*/
-
+
if (tcp_close_state(sk,1)==1)
{
tcp_send_fin(sk);
@@ -1771,7 +1777,7 @@
while(closing(sk) && current->timeout)
{
interruptible_sleep_on(sk->sleep);
- if (current->signal & ~current->blocked)
+ if (current->signal & ~current->blocked)
{
break;
}
@@ -1792,32 +1798,32 @@
/*
- * This will accept the next outstanding connection.
+ * This will accept the next outstanding connection.
*/
-
+
static struct sock *tcp_accept(struct sock *sk, int flags)
{
struct sock *newsk;
struct sk_buff *skb;
-
+
/*
* We need to make sure that this socket is listening,
* and that it has something pending.
*/
- if (sk->state != TCP_LISTEN)
+ if (sk->state != TCP_LISTEN)
{
sk->err = EINVAL;
- return(NULL);
+ return(NULL);
}
/* Avoid the race. */
cli();
lock_sock(sk);
- while((skb = tcp_dequeue_established(sk)) == NULL)
+ while((skb = tcp_dequeue_established(sk)) == NULL)
{
- if (flags & O_NONBLOCK)
+ if (flags & O_NONBLOCK)
{
sti();
release_sock(sk);
@@ -1827,7 +1833,7 @@
release_sock(sk);
interruptible_sleep_on(sk->sleep);
- if (current->signal & ~current->blocked)
+ if (current->signal & ~current->blocked)
{
sti();
sk->err = ERESTARTSYS;
@@ -1838,7 +1844,7 @@
sti();
/*
- * Now all we need to do is return skb->sk.
+ * Now all we need to do is return skb->sk.
*/
newsk = skb->sk;
@@ -1850,9 +1856,9 @@
}
/*
- * This will initiate an outgoing connection.
+ * This will initiate an outgoing connection.
*/
-
+
static int tcp_connect(struct sock *sk, struct sockaddr_in *usin, int addr_len)
{
struct sk_buff *buff;
@@ -1863,47 +1869,48 @@
struct tcphdr *t1;
struct rtable *rt;
- if (sk->state != TCP_CLOSE)
+ if (sk->state != TCP_CLOSE)
return(-EISCONN);
/*
* Don't allow a double connect.
*/
-
+
if(sk->daddr)
return -EINVAL;
-
- if (addr_len < 8)
+
+ if (addr_len < 8)
return(-EINVAL);
- if (usin->sin_family && usin->sin_family != AF_INET)
+ if (usin->sin_family && usin->sin_family != AF_INET)
return(-EAFNOSUPPORT);
/*
* connect() to INADDR_ANY means loopback (BSD'ism).
*/
-
+
if(usin->sin_addr.s_addr==INADDR_ANY)
usin->sin_addr.s_addr=ip_my_addr();
-
+
/*
- * Don't want a TCP connection going to a broadcast address
+ * Don't want a TCP connection going to a broadcast address
*/
- if ((atype=ip_chk_addr(usin->sin_addr.s_addr)) == IS_BROADCAST || atype==IS_MULTICAST)
+ if ((atype=ip_chk_addr(usin->sin_addr.s_addr)) == IS_BROADCAST || atype==IS_MULTICAST)
return -ENETUNREACH;
-
+
lock_sock(sk);
sk->daddr = usin->sin_addr.s_addr;
sk->write_seq = tcp_init_seq();
sk->window_seq = sk->write_seq;
sk->rcv_ack_seq = sk->write_seq -1;
+ sk->rcv_ack_cnt = 1;
sk->err = 0;
sk->dummy_th.dest = usin->sin_port;
release_sock(sk);
buff = sock_wmalloc(sk,MAX_SYN_SIZE,0, GFP_KERNEL);
- if (buff == NULL)
+ if (buff == NULL)
{
return(-ENOMEM);
}
@@ -1911,15 +1918,15 @@
buff->sk = sk;
buff->free = 0;
buff->localroute = sk->localroute;
-
+
/*
* Put in the IP header and routing stuff.
*/
-
+
tmp = sk->prot->build_header(buff, sk->saddr, sk->daddr, &dev,
IPPROTO_TCP, NULL, MAX_SYN_SIZE,sk->ip_tos,sk->ip_ttl,&sk->ip_route_cache);
- if (tmp < 0)
+ if (tmp < 0)
{
sock_wfree(sk, buff);
release_sock(sk);
@@ -1941,7 +1948,7 @@
t1->syn = 1;
t1->doff = 6;
/* use 512 or whatever user asked for */
-
+
if(rt!=NULL && (rt->rt_flags&RTF_WINDOW))
sk->window_clamp=rt->rt_window;
else
@@ -1951,20 +1958,20 @@
sk->mtu = sk->user_mss;
else if (rt)
sk->mtu = rt->rt_mtu - sizeof(struct iphdr) - sizeof(struct tcphdr);
- else
+ else
sk->mtu = 576 - sizeof(struct iphdr) - sizeof(struct tcphdr);
/*
- * but not bigger than device MTU
+ * but not bigger than device MTU
*/
if(sk->mtu <32)
sk->mtu = 32; /* Sanity limit */
-
+
sk->mtu = min(sk->mtu, dev->mtu - sizeof(struct iphdr) - sizeof(struct tcphdr));
#ifdef CONFIG_SKIP
-
+
/*
* SKIP devices set their MTU to 65535. This is so they can take packets
* unfragmented to security process then fragment. They could lie to the
@@ -1973,13 +1980,13 @@
*
* [IPHDR][IPSP][Security data][Modified TCP data][Security data]
*/
-
+
if(skip_pick_mtu!=NULL) /* If SKIP is loaded.. */
sk->mtu=skip_pick_mtu(sk->mtu,dev);
#endif
-
+
/*
- * Put in the TCP options to say MTU.
+ * Put in the TCP options to say MTU.
*/
ptr = skb_put(buff,4);
@@ -1992,7 +1999,7 @@
sizeof(struct tcphdr) + 4, buff);
/*
- * This must go first otherwise a really quick response will get reset.
+ * This must go first otherwise a really quick response will get reset.
*/
tcp_cache_zap();
@@ -2001,25 +2008,27 @@
sk->rto = rt->rt_irtt;
else
sk->rto = TCP_TIMEOUT_INIT;
- sk->retransmit_timer.function=&tcp_retransmit_timer;
+ sk->delack_timer.function = tcp_delack_timer;
+ sk->delack_timer.data = (unsigned long) sk;
+ sk->retransmit_timer.function = tcp_retransmit_timer;
sk->retransmit_timer.data = (unsigned long)sk;
tcp_reset_xmit_timer(sk, TIME_WRITE, sk->rto); /* Timer for repeating the SYN until an answer */
- sk->retransmits = 0; /* Now works the right way instead of a hacked
+ sk->retransmits = 0; /* Now works the right way instead of a hacked
initial setting */
- sk->prot->queue_xmit(sk, dev, buff, 0);
+ sk->prot->queue_xmit(sk, dev, buff, 0);
tcp_reset_xmit_timer(sk, TIME_WRITE, sk->rto);
tcp_statistics.TcpActiveOpens++;
tcp_statistics.TcpOutSegs++;
-
+
release_sock(sk);
return(0);
}
/*
- * Socket option code for TCP.
+ * Socket option code for TCP.
*/
-
+
int tcp_setsockopt(struct sock *sk, int level, int optname, char *optval, int optlen)
{
int val,err;
@@ -2027,13 +2036,13 @@
if(level!=SOL_TCP)
return ip_setsockopt(sk,level,optname,optval,optlen);
- if (optval == NULL)
+ if (optval == NULL)
return(-EINVAL);
err=verify_area(VERIFY_READ, optval, sizeof(int));
if(err)
return err;
-
+
val = get_user((int *)optval);
switch(optname)
@@ -2062,7 +2071,7 @@
if(level!=SOL_TCP)
return ip_getsockopt(sk,level,optname,optval,optlen);
-
+
switch(optname)
{
case TCP_MAXSEG:
@@ -2085,7 +2094,7 @@
put_user(val,(int *)optval);
return(0);
-}
+}
struct proto tcp_prot = {
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov
with Sam's (original) version of this