Re: 2.2 generating odd TCP resets?

From: Brian Craft (bcboy@thecraftstudio.com)
Date: Wed Oct 18 2000 - 23:20:40 EST


> Looks like the application on the Linux system is issuing a close() on
> the socket before reading all of the available data. That always
> causes a RST to be sent.

Here's some stripped down code to generate bogus (I think) TCP
resets on 2.2.14-17.

The RST is generated when the server closes the socket, but there
is NO data pending on the socket.

On linux run
    ./st

on windows run
    ./st 10.0.70.5

(or whatever).

The windows box should return an error on read after linux
generates the RST. The code can be compiled with cygwin.

Is there any reason this should fail? It does not fail when
talking to a linux host. The only obvious difference is windows
generates two ACK's of the server's FIN.

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <netinet/in.h>

#define LEN 1000000
int main(int argc, char *argv[])
{
    struct sockaddr_in sin;
    int len, fd;
    char buff[LEN];

    len = sizeof (sin);
    sin.sin_family = AF_INET;
    sin.sin_port = htons (5000);

    if (argc > 1) { /* client side */
        int n, count = 0;
                printf("client\n");
        sin.sin_addr.s_addr = inet_addr(argv[1]);
        fd = socket (AF_INET, SOCK_STREAM, 0);
        if (fd < 1) { perror("socket"); exit(0); }
        while (connect (fd, (struct sockaddr *) &sin, len)) {
            usleep(10000);
            perror("connect");
        }
        printf("connected to server\n");
        shutdown(fd, 1);
        usleep(2000000);
        while (count < LEN) {
            n = read(fd, buff, 100);
            if (n < 0) {
                printf("error on read\n");
                break;
            }
            count += n;
        }

        if (count == LEN) printf("read ok\n");
        /*printf("read %s\n", buff); */
        close(fd);
    } else { /* server side */
        int i, new_fd;
        int on = 1;
                printf("server\n");
                sin.sin_addr.s_addr = INADDR_ANY;
        fd = socket (AF_INET, SOCK_STREAM, 0);
        setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on));

        if (fd < 1) {
            perror("serv socket");
            exit(0);
        }
        if (bind (fd, (struct sockaddr *)&sin, len) < 0
            ||listen (fd, 1) < 0) {
            perror("bind/listen");
            close(fd);
            exit(0);
        }
        new_fd = accept (fd, 0, 0);
        if (new_fd < 0) { perror("accept"); exit(0); }
        close(fd);
        usleep(1000000);
        shutdown (new_fd, 0);
        fcntl (new_fd, F_SETFL, 1);
        for (i = 0; i < LEN; ++i) buff[i] = i%256;
        write(new_fd, buff, LEN);
        close(new_fd);
        printf("socket closed\n");
        usleep(10000000);
        printf("server exiting\n");
    }

    return 0;
}
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Mon Oct 23 2000 - 21:00:14 EST