netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Simon Arlott <simon@fire.lp0.eu>
To: Evgeniy Polyakov <johnpol@2ka.mipt.ru>
Cc: john@screen.lv, netdev@vger.kernel.org,
	David Miller <davem@davemloft.net>
Subject: Re: strange tcp behavior
Date: Fri, 03 Aug 2007 17:51:42 +0100	[thread overview]
Message-ID: <46B35D1E.9050501@simon.arlott.org.uk> (raw)
In-Reply-To: <20070803120920.GA23166@2ka.mipt.ru>

[-- Attachment #1: Type: text/plain, Size: 3937 bytes --]

On 03/08/07 13:09, Evgeniy Polyakov wrote:
> On Fri, Aug 03, 2007 at 01:03:46PM +0100, Simon Arlott (simon@fire.lp0.eu) wrote:
>> On Fri, August 3, 2007 12:56, Evgeniy Polyakov wrote:
>> > On Fri, Aug 03, 2007 at 12:21:46PM +0100, Simon Arlott (simon@fire.lp0.eu) wrote:
>> >> Since the connection is considered closed, couldn't another socket re-use it?
>> >>
>> >> Socket A: Recv data (unread)
>> >> Socket A: Recv RST
>> >> Socket B: Reuses connection (same IPs/ports)
>> >> Socket A: Close
>> >>
>> >> Wouldn't that disrupt socket B's use of the connection?
>> >
>> > Then it will drop our data, since there were no appropriate handhsake.
>> 
>> Couldn't the sequence numbers be close enough to make the RST valid?
> 
> It does not matter - if connection is not in synchronized state all
> unrelated data is dropped, so remote side is only allowed to receive syn
> flag only, anything else must be dropped. If remote side does not do
> that, it violates RFC.

Except the remote side has a connection, because another one can be made 
before the existing connection is closed:

17:37:37.377571 IP 192.168.7.4.50550 > 192.168.7.8.2500: S 134077329:134077329(0) win 1500 (raw)
17:37:37.382352 IP 192.168.7.8.2500 > 192.168.7.4.50550: S 3460060233:3460060233(0) ack 134077330 win 14360 <mss 7180> (accept)
17:37:37.377966 IP 192.168.7.4.50550 > 192.168.7.8.2500: . ack 1 win 1500 (raw)
17:37:37.378128 IP 192.168.7.4.50550 > 192.168.7.8.2500: P 1:17(16) ack 1 win 1500 (raw)
17:37:37.378162 IP 192.168.7.8.2500 > 192.168.7.4.50550: . ack 17 win 14360
17:37:37.378131 IP 192.168.7.4.50550 > 192.168.7.8.2500: R 134077346:134077346(0) win 1500 (raw)

17:37:37.412709 IP 192.168.7.4.50550 > 192.168.7.8.2500: SWE 3257207813:3257207813(0) win 14280 <mss 7140,sackOK,timestamp 3601441543 0,nop,wscale 5> (connect)
17:37:37.412785 IP 192.168.7.8.2500 > 192.168.7.4.50550: SE 3495384256:3495384256(0) ack 3257207814 win 14336 <mss 7180,sackOK,timestamp 4294812905 3601441543,nop,wscale 6> (accept)
17:37:37.412960 IP 192.168.7.4.50550 > 192.168.7.8.2500: . ack 1 win 447 <nop,nop,timestamp 3601441543 4294812905>

17:37:38.383085 IP 192.168.7.8.2500 > 192.168.7.4.50550: R 4259643274:4259643274(0) ack 1171836829 win 14360 (close (previous connection))

17:37:47.417649 IP 192.168.7.8.2500 > 192.168.7.4.50550: F 1:1(0) ack 1 win 224 <nop,nop,timestamp 4294822910 3601441543> (close)
17:37:47.417993 IP 192.168.7.4.50550 > 192.168.7.8.2500: F 1:1(0) ack 2 win 447 <nop,nop,timestamp 3601444045 4294822910> (read returned)
17:37:47.418466 IP 192.168.7.8.2500 > 192.168.7.4.50550: . ack 2 win 224 <nop,nop,timestamp 4294822911 3601444045>


The second connection also modified the RST|ACK that was sent compared to no second connection:

17:38:03.532703 IP 192.168.7.4.50550 > 192.168.7.8.2500: S 82517575:82517575(0) win 1500 (raw)
17:38:03.532832 IP 192.168.7.8.2500 > 192.168.7.4.50550: S 3495449795:3495449795(0) ack 82517576 win 14360 <mss 7180> (accept)
17:38:03.533388 IP 192.168.7.4.50550 > 192.168.7.8.2500: . ack 1 win 1500 (raw)
17:38:03.533457 IP 192.168.7.4.50550 > 192.168.7.8.2500: P 1:17(16) ack 1 win 1500 (raw)
17:38:03.533597 IP 192.168.7.8.2500 > 192.168.7.4.50550: . ack 17 win 14360
17:38:03.533589 IP 192.168.7.4.50550 > 192.168.7.8.2500: R 82517592:82517592(0) win 1500 (raw)

17:38:04.536277 IP 192.168.7.8.2500 > 192.168.7.4.50550: R 1:1(0) ack 17 win 14360 (close)


17:38:04.536277 IP 192.168.7.8.2500 > 192.168.7.4.50550: R 1:1(0) ack 17 win 14360
vs
17:37:38.383085 IP 192.168.7.8.2500 > 192.168.7.4.50550: R 4259643274:4259643274(0) ack 1171836829 win 14360
What happened there ?


On the server, run tcptest-server.c, which waits for 1s on the first connection then 10s on the second connection.

On the client, run:
iptables -I INPUT -i eth0 -p tcp --dport 50550 -j DROP; ./client; iptables -D INPUT -i eth0 -p tcp --dport 50550 -j DROP; ./tcptest-client

(client.c from john's original email)

-- 
Simon Arlott


[-- Attachment #2: tcptest-server.c --]
[-- Type: text/x-csrc, Size: 1712 bytes --]

#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <poll.h>
#include <fcntl.h>

#define PORT 2500

#define xerror(str) do { perror(str); exit(1); } while (0)

int main(void) {
	struct sockaddr_in sa;
	int l, s, tmp;
	int t = 0;

	memset(&sa, 0, sizeof(sa));
	
	l = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
	if (!l)
		xerror("socket");
		
	sa.sin_family = AF_INET;
	sa.sin_addr.s_addr = htonl(INADDR_ANY);
	sa.sin_port = htons(PORT);

	tmp = 1;
	setsockopt(l, SOL_SOCKET, SO_REUSEADDR, (char*)&tmp, sizeof(tmp));

	if (bind(l, (struct sockaddr*)&sa, sizeof(sa)) != 0)
		xerror("bind");

	if (listen(l, 0) != 0)
		xerror("listen");

	printf("server %d ready...\n", getpid());

	for (t = 1; t <= 2; t++) {
		s = accept(l, NULL, NULL);
		switch (fork()) {
			case -1:
				xerror("fork");
				break;
			case 0:
				switch (t) {
					case 1:
						printf("server %d accepted connection\n", getpid());

#if 0
						tmp = fcntl(s, F_GETFL, 0);
						if (fcntl(s, F_SETFL, tmp | O_NONBLOCK) != 0)
							xerror("fcntl");

						if (send(s, "AAAAAAA", 7, 0) != 7)
							xerror("send");
#endif

						printf("server %d waiting for 1 second...\n", getpid());
							
						sleep(1);
						
						
						printf("server %d closing connection\n", getpid());
						
						close(s);
						
						
						return 0;
						break;

					case 2:
						printf("server %d accepted connection\n", getpid());
						printf("server %d waiting for 10 seconds...\n", getpid());

						sleep(10);


						printf("server %d closing connection\n", getpid());
						
						close(s);
						
						
						return 0;
						break;
				}
				break;
			default:
				close(s);
		}
	}

	wait(NULL);
	wait(NULL);
	return 0;
}

[-- Attachment #3: tcptest-client.c --]
[-- Type: text/x-csrc, Size: 1408 bytes --]

#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#define SERVER_IP "192.168.7.8"
#define SRC_PORT 50550
#define DST_PORT 2500

#define xerror(str) do { perror(str); exit(1); } while (0)

int main(void) {
	struct sockaddr_in sa;
	int s;
	int t = 0;
	char buf[32];
	int ret, tmp;

	memset(&sa, 0, sizeof(sa));
	
	for (t = 1; t <= 1; t++) {
		switch (fork()) {
			case -1:
				xerror("fork");
				break;
			case 0:
				printf("client %d binding port...\n", getpid());

				s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
				if (!s)
					xerror("socket");

				sa.sin_family = AF_INET;
				sa.sin_addr.s_addr = htonl(INADDR_ANY);
				sa.sin_port = htons(SRC_PORT);

				tmp = 1;
				if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char*)&tmp, sizeof(tmp)) != 0)
					xerror("setsockopt");

				if (bind(s, (struct sockaddr*)&sa, sizeof(sa)) != 0)
					xerror("bind");


				printf("client %d connecting...\n", getpid());

				sa.sin_family = AF_INET;
				sa.sin_addr.s_addr = inet_addr(SERVER_IP);
				sa.sin_port = htons(DST_PORT);

				if (connect(s, (struct sockaddr*)&sa, sizeof(sa)) != 0)
					xerror("connect");

				printf("client %d waiting in read()...\n", getpid());

				ret = read(s, buf, 32);
				printf("client %d read() returned %d\n", getpid(), ret);

				close(s);

				return 0;
		}

		wait(NULL);
	}

	return 0;
}

  reply	other threads:[~2007-08-03 16:51 UTC|newest]

Thread overview: 28+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-08-02  6:19 strange tcp behavior john
2007-08-02  9:55 ` Evgeniy Polyakov
2007-08-02 10:16   ` Evgeniy Polyakov
2007-08-02 11:38     ` Simon Arlott
2007-08-02 12:04       ` Evgeniy Polyakov
2007-08-02 12:28         ` Evgeniy Polyakov
     [not found]       ` <46860.212.93.96.73.1186055105.squirrel@mail.screen.lv>
2007-08-02 12:15         ` Simon Arlott
2007-08-02 17:15           ` Simon Arlott
2007-08-02 18:08             ` Evgeniy Polyakov
2007-08-02 18:48               ` Evgeniy Polyakov
2007-08-02 22:02                 ` David Miller
2007-08-03  2:21                 ` David Miller
2007-08-03  8:22                   ` Evgeniy Polyakov
2007-08-03 20:04                     ` David Miller
2007-08-04 16:49                       ` Evgeniy Polyakov
2007-08-03 21:17                     ` David Miller
2007-08-04 16:51                       ` Evgeniy Polyakov
2007-08-05  3:21                         ` David Miller
2007-08-02 18:58               ` Simon Arlott
2007-08-03  8:25                 ` Evgeniy Polyakov
2007-08-03 11:21                   ` Simon Arlott
2007-08-03 11:56                     ` Evgeniy Polyakov
2007-08-03 12:03                       ` Simon Arlott
2007-08-03 12:09                         ` Evgeniy Polyakov
2007-08-03 16:51                           ` Simon Arlott [this message]
2007-08-03 17:39                             ` Evgeniy Polyakov
2007-08-03 18:29                               ` Simon Arlott
2007-08-04 16:03                                 ` Evgeniy Polyakov

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=46B35D1E.9050501@simon.arlott.org.uk \
    --to=simon@fire.lp0.eu \
    --cc=davem@davemloft.net \
    --cc=john@screen.lv \
    --cc=johnpol@2ka.mipt.ru \
    --cc=netdev@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).