Subject: Kernel lockups in tcp code
To: None <tech-kern@NetBSD.ORG>
From: Michael Graff <explorer@cygnus.com>
List: tech-kern
Date: 11/24/1996 16:08:12
The following code will lock up your kernel but good in the -current tcp
code.  I have not had a lot of time to find out why, mostly because it locks
the machine and doesn't drop into the debugger, and does not respond to the
usual put-me-in-the-debugger key sequence.

This is on the i386, and I have not tested this on other archs.

Edit the hardcoded ip address to point to your machine in the following code,
compile it, sync, and run it for a while.

I suspect all ports 1024..5000 are in TIME_WAIT, and this causes something
to loose...

--Michael

/* $Id$ */

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

#include <netinet/in.h>

#include <arpa/inet.h>

#include <unistd.h>
#include <stdio.h>
#include <err.h>

#define PORT 8844

int
main(int argc, char **argv)
{
  pid_t pid;

  pid = fork();

  if (pid < 0)
    err(1, "fork");

  if (pid > 0) {  /* in the parent */
    fd_set ifds;
    int ifd;
    int nfd;
    int fd;
    ssize_t status;
    int fds[FD_SETSIZE];
    struct sockaddr_in isin;
    struct sockaddr_in nsin;
    int nsin_len;
    char data[1024];

    printf("In parent...\n");

    memset(&isin, 0, sizeof(isin));

    for (fd = 0 ; fd < FD_SETSIZE ; fd++)
      fds[fd] = -1;
    
    ifd = socket(AF_INET, SOCK_STREAM, 0);

    isin.sin_family = AF_INET;
    isin.sin_addr.s_addr = INADDR_ANY;
    isin.sin_port = htons(PORT);
    
    if (bind(ifd, (struct sockaddr *)&isin, sizeof(isin)) < 0)
      err(1, "bind");
    
    printf("Bound local port %d\n", ntohs(isin.sin_port));
    fds[ifd] = ifd;

    listen(ifd, 128);

    for ( ; ; ) {
      FD_ZERO(&ifds);
      for (fd = 0 ; fd < FD_SETSIZE ; fd++)
	if (fds[fd] != -1)
	  FD_SET(fd, &ifds);

      if (select(FD_SETSIZE - 1, &ifds, NULL, NULL, NULL) < 0)
	err(1, "select");
	  
      for (fd = 0 ; fd < FD_SETSIZE ; fd++)
	if (FD_ISSET(fd, &ifds))
	  if (fd == ifd) {
	    nsin_len = sizeof(nsin);
	    
	    memset(&nsin, 0, sizeof(nsin));
	    
	    if ((nfd = accept(ifd, (struct sockaddr *)&nsin, &nsin_len)) < 0)
	      err(1, "accept");
	    
	    printf("Accepted connection on port %d, fd %d... ",
		   ntohs(nsin.sin_port), nfd);
	    fflush(stdout);
	    fds[nfd] = nfd;
	  } else if (fds[fd] != -1) {
	    status = read(fd, data, sizeof(data));
	    if (status < 0)
	      err(1, "read");
	    if (status == 0) {
	      close(fd);
	      fds[fd] = -1;
	    }
	  } else {
	    errx(1, "attempted read from closed socket");
	  }
    }
  } else {  /* in the child */
    int lfd = -1;
    int ofd;
    struct sockaddr_in osin;

    sleep(1);
      
    printf("In child...\n");

    for ( ; ; ) {
      memset(&osin, 0, sizeof(osin));
      
      ofd = socket(AF_INET, SOCK_STREAM, 0);
      
      osin.sin_family = AF_INET;
      osin.sin_addr.s_addr = inet_addr("192.80.44.41");
      osin.sin_port = htons(PORT);
      
      if (connect(ofd, (struct sockaddr *)&osin, sizeof(osin)) < 0)
	err(1, "connect");
      
      usleep(10000);
      printf("Connected fd %d.  Closing %d.\n", ofd, lfd);
      fflush(stdout);

      if (lfd != -1)
	close(lfd);
      lfd = ofd;
    }
  }

}