ACK_hole01.c


/* ACK_hole01.c - Sun Aug 11 13:00:54 PDT 2002
 * John Sage - jsage@finchhaven.com
 *
 * A first attempt at a TCP/IP network data sink
 *   along the lines of trafficrcv.c - see:
 *   http://www.psc.edu/~web100/pathprobe/
 *
 * Now based upon WR Stevens tcpserv04.c
 *   "UNIX Network Programming", p.128
 *   modified to do nothing with packets received
 *
 * Version 0.0.4 - add EINTR error handling - Sun Aug 11 13:00:54 PDT 2002
 * Version 0.0.3 - add syslog logging - Sun Aug 11 07:13:38 PDT 2002
 * Version 0.0.2
 *   It works; not sure what all of it does :-/
 *   but it works: no zombies, no local ports
 *   left hanging in CLOSE_WAIT as with trafficrcv.c
 *
 */

#include "unp.h"
#include "error.c"

#ifndef RCVBUFF
#define RCVBUFF (1024 * 1024)
#endif

/* USAGE */

static void
usage(char name[])
{
  fprintf(stdout, "Usage: %s [-p port]\n",name);
}

/* SIGCHLD zombie killer, from UNP p.128 */

void
sig_chld(int signo)
{
  pid_t pid;
  int   stat;
  while ( (pid = waitpid(-1, &stat, WNOHANG)) > 0 )
    fprintf(stdout, "Child %d terminated in sig_chld, zombie killed!\n", pid);
  return;
}

/* MAIN */

int
main(int argc, char **argv)
{
  char      c;
  char      *databuf;
  char      message[256];
  int       bytes;
  int       errflg = 0;
  int       i;
  int       listenfd, connfd;
  int       port;
  long      connaddr;
  pid_t     childpid;
  socklen_t clilen;
  struct    sockaddr_in cliaddr, servaddr;

  while ((c = getopt (argc, argv, "?p:")) != -1) {
    switch (c) {
    case '?':
      errflg++;
    case 'p':
      port = atoi(optarg);
      break;
    default:
      errflg++;
      break;
    }
  }

  if (errflg) {
    usage(argv[0]);
    exit (2);
  }

  fprintf(stdout, "\nACK_hole is listening on port %d!\n", port);

/* SOCKET */

  listenfd = socket(AF_INET, SOCK_STREAM, 0);

  bzero(&servaddr, sizeof(servaddr));
  servaddr.sin_family = AF_INET;
  servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
  servaddr.sin_port = htons(port);

/* BIND */

  if (bind(listenfd, (SA *) &servaddr, sizeof(servaddr)) == -1) {
    perror("BIND failed");
    exit(-1);
  }

/* Allocate receive data buffer */

  if ((databuf = malloc(RCVBUFF)) == NULL) {
      fprintf(stdout, "malloc of data buffer failed!\n");
      exit(-1);
  }

/* LISTEN */

  listen(listenfd, LISTENQ);

  for ( ; ; ) {
    clilen = sizeof(cliaddr);

/* ACCEPT with EINTR handling */

    if ( (connfd = accept(listenfd, (SA *) &cliaddr, &clilen)) < 0) {
      if (errno ==EINTR)
	continue; /* back to for ( ; ; ) */
      else
	err_sys("accept error");
    }

    printf("CONNECT received from: ");
    connaddr = cliaddr.sin_addr.s_addr;
    for (i = 0; i < 4; i++) {
      printf("%d.", connaddr & 0xff);
      connaddr = connaddr >> 8;
    }
    printf("%d,", ntohs(cliaddr.sin_port));
    printf(" to local port %d!\n", ntohs(servaddr.sin_port));

    /* log to syslog, too.. */

    sprintf(message, "Connection from remote host %s:%d to local port %d",
	    inet_ntoa(cliaddr.sin_addr),
	    ntohs(cliaddr.sin_port),
	    ntohs(servaddr.sin_port));
    syslog(LOG_INFO, message);

/* SIGCHLD */

    signal(SIGCHLD, sig_chld);

/* FORK */

    if ( (childpid = fork()) == 0 ) {
      close(listenfd);

/* READ */

      read(connfd, databuf, bytes);
      /* do nothing */
      exit(0);
    }

/* CLOSE */

    close(connfd);

  } /* end for ( ; ; ) */

} /* end main */


This page last preened by Webmaster jsage@finchhaven.com on:
Last modified: Thu Feb 13 22:34:14 2003