Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 25 Jun 1997 04:09:20 -0400 (EDT)
From:      Brian Mitchell <brian@firehouse.net>
To:        FreeBSD-gnats-submit@FreeBSD.ORG
Subject:   kern/3948: nonworking t/tcp server side
Message-ID:  <199706250809.EAA01275@apocalypse.saturn.net>
Resent-Message-ID: <199706250820.BAA09750@hub.freebsd.org>

next in thread | raw e-mail | index | archive | help

>Number:         3948
>Category:       kern
>Synopsis:       nonworking t/tcp server side
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Wed Jun 25 01:20:01 PDT 1997
>Last-Modified:
>Originator:     Brian Mitchell
>Organization:
firehouse.net
>Release:        FreeBSD 2.2.1-RELEASE i386
>Environment:

486 running 2.2.1-RELEASE

>Description:

t/tcp seems not to work on server side. To test, I wrote a
simple t/tcp server and sniffed with tcpdump. The packet
traces do not match the description in the manpage. Client
side appears to work, server side does not.


>How-To-Repeat:
(this is somewhat long, but I believe most of it is relevant)

TRANSACTION MODEL
     The expected model of a ``transaction'' as used by T/TCP is a fairly sim-
     ple one:

     1.   A client program generates a request to be sent to the server, which
          is small enough to fit in a single TCP segment, and sends a SYN PUSH
          FIN segment with options and data to the server.

     2.   The server program accepts the request in the same manner as for
          regular TCP connections, interprets it, and generates a reply which
          may be small enough to fit in a single segment.  If it is, the reply
          is sent in a single SYN PUSH FIN ACK segment with (different) op-
          tions and data back to the client.  If not, then the connection de-
          generates into (almost) the usual case for TCP. The server then
          closes its socket.

     3.   The client reads the reply and closes its socket.


My understanding of this is the server gets a SPF segment (as it does) and 
replies with a SPFA segment if it is small enough to fit in a single
packet. This is where things appear to fall apart, as is shown in the 
following tcpdump log.


03:48:31.553801 localhost.1056 > localhost.finger: SFP 319123411:319123420(9) 
win 57344 <mss 16344,nop,wscale 0,nop,nop,timestamp 48396 
0,nop,nop,cc[|tcp]> (DF)

03:48:31.555366 localhost.finger > localhost.1056: S 319212645:319212645(0) 
ack 319123422 win 57344 <mss 16344,nop,wscale 0,nop,nop,timestamp 48396
48396,nop,nop,cc[|tcp]> (DF)

03:48:31.555998 localhost.1056 > localhost.finger: . ack 1 win 57344 
<nop,nop,timestamp 48396 48396,nop,nop,cc 42> (DF)

03:48:31.560896 localhost.finger > localhost.1056: FP 1:7(6) ack 1 win 57344 
<nop,nop,timestamp 48396 48396,nop,nop,cc 43> (DF)

03:48:31.561525 localhost.1056 > localhost.finger: . ack 8 win 57338 
<nop,nop,timestamp 48396 48396,nop,nop,cc 42> (DF)


Here is the execution of the server program. I'm using port 79 since
finger already has t/tcp support.
# ./ttcp1 79
test123
 

Here is execution of finger, and the response.
> finger test123@localhost
[localhost]
REPLY


Here I make sure t/tcp is indeed enabled (although there was little doubt
judging from the initial segment from the client).
> /usr/sbin/sysctl net.inet.tcp.rfc1644
net.inet.tcp.rfc1644: 1

Here is the output of uname -r
> uname -r
2.2.1-RELEASE




Here is the code. Perhaps my interpretation of the manpage was incorrect?

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
main(int argc, char **argv)
{
	u_short port = 79;
	struct sockaddr_in sin;
	int s;
	int i;
	char buffer[1024];

	if(argc > 1)
		port = atoi(argv[1]);
	if(port < 1)
		port = 79;
	s = socket(PF_INET, SOCK_STREAM, 0);
	if(s < 0)
	{
		perror("socket");
		exit(1);
	}
	if(setsockopt(s, IPPROTO_TCP, TCP_NOPUSH, &s, sizeof(s)) < 0)
	{
		perror("setsockopt");
		exit(1);
	}
	sin.sin_family = PF_INET;
	sin.sin_port = htons(port);
	sin.sin_addr.s_addr = INADDR_ANY;
	if(bind(s, (struct sockaddr *)&sin, sizeof(sin)) < 0)
	{
		perror("bind");
		exit(1);
	}
	if(listen(s, 5) < 0)
	{
		perror("listen");
		exit(1);
	}
	i = sizeof(sin);
	s = accept(s, (struct sockaddr *)&sin, &i);
	if(s < 0)
	{
		perror("accept");
		exit(1);
	}
	i = read(s, buffer, 1024);
	if(i < 0)
	{
		perror("read");
		exit(1);
	}
	else if(!i)
	{
		fprintf(stderr, "peer closed connection\n");
		exit(1);
	}
	else
	{
		write(1, buffer, i);
		write(s, "REPLY\n", 6);
		exit(0);
	}
}

>Fix:
	

>Audit-Trail:
>Unformatted:



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199706250809.EAA01275>