docs/54995: Error in accept(2) man page

William Sloan wsloan at ectogenic.com
Mon Jul 28 22:00:26 UTC 2003


>Number:         54995
>Category:       docs
>Synopsis:       Error in accept(2) man page
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    freebsd-doc
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          doc-bug
>Submitter-Id:   current-users
>Arrival-Date:   Mon Jul 28 15:00:24 PDT 2003
>Closed-Date:
>Last-Modified:
>Originator:     William Sloan
>Release:        FreeBSD 5.1-RELEASE i386
>Organization:
ectogenic.com
>Environment:
System: FreeBSD pox.ectogenic.com 5.1-RELEASE FreeBSD 5.1-RELEASE #0: Thu Jun 26 15:47:13 PDT 2003 root at yenlowang.wooferstar.net:/usr/src/sys/i386/compile/SMP i386


	
>Description:
	The accept(2) man pages states that the new
socket has the same properties as the orginal socket.  This appears not to be the case as the output from
attached C program shows.
Server Info: Status of socket 3
Server Info: Socket send timeout is 5
Server Info: Socket recv timeout is 5
Server Info: REUSEADDR flag is 4
Server Info: Linger options are 128 and 5
Server Info: Nonblocking IO is 4
Server Info: Async IO is 64
Server Info: close-on-exec flag is 1
Server Info: Pid owner is 59559
Server Info: 
After accept
Server Info: Orignal socket
Server Info: Status of socket 3
Server Info: Socket send timeout is 5
Server Info: Socket recv timeout is 5
Server Info: REUSEADDR flag is 4
Server Info: Linger options are 128 and 5
Server Info: Nonblocking IO is 4
Server Info: Async IO is 64
Server Info: close-on-exec flag is 1
Server Info: Pid owner is 59559
Server Info: 
Accepted socket
Server Info: Status of socket 4
Server Info: Socket send timeout is 0
Server Info: Socket recv timeout is 0
Server Info: REUSEADDR flag is 4
Server Info: Linger options are 128 and 5
Server Info: Nonblocking IO is 4
Server Info: Async IO is 64
Server Info: close-on-exec flag is 0
Server Info: Pid owner is 59559

>How-To-Repeat:
	
Compile and run the attached program and make a TCP connection to port 64000.  Output like that
of the previous section should show some properties changing across exec calls.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#define SYSLOG_NAMES
#include <syslog.h>

#define WILDCARD_ADDRESS "*"

void logger (int level, char *s, ...)
{
  int i = 0;
  va_list args;

  fprintf(stderr, "Server ");
  while (prioritynames[i].c_name != NULL) {
    if (level == prioritynames[i].c_val) {
      fprintf(stderr, "%c", toupper(prioritynames[i].c_name[0]));
      fprintf(stderr, "%s: ", &(prioritynames[i].c_name[1]));
      break;
    }
    i++;
  }
  va_start(args, s);
  vfprintf(stderr, s, args);
  va_end(args);
  return;
}

void set_socket_options(int socket)
{
  int enable = 1, val;
  struct timeval timeout;
  struct linger linger_opts;

  bzero (&timeout, sizeof(timeout));
  timeout.tv_sec = 5;

  if (setsockopt (socket, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout))) {
    logger(LOG_CRIT, "Could not set send timeout option\n");
    exit(EXIT_FAILURE);
  }

  if (setsockopt (socket, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout))) {
    logger(LOG_CRIT, "Could not set recv timeout option\n");
    exit(EXIT_FAILURE);
  }

  if (setsockopt(socket, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(enable))) {
    logger (LOG_CRIT, "Could not set reuse addr flag\n");
    exit (EXIT_FAILURE);
  }

  linger_opts.l_onoff = 1;
  linger_opts.l_linger = 5;
  if (setsockopt(socket, SOL_SOCKET, SO_LINGER, &linger_opts, sizeof(linger_opts))) {
    logger (LOG_CRIT, "Could not set linger options\n");
    exit(EXIT_FAILURE);
  }

  val = fcntl(socket, F_GETFL);
  val |= O_NONBLOCK;
  if (fcntl (socket, F_SETFL, val) == -1) {
    logger (LOG_CRIT, "Could not set nonblocking I/O because %s\n", strerror(errno));
    exit (EXIT_FAILURE);
  }

  if (fcntl (socket, F_SETFD, FD_CLOEXEC) == -1) {
    logger (LOG_CRIT, "Could not set close on exec flag because %s\n", strerror(errno));
    exit (EXIT_FAILURE);
  }

  if (fcntl (socket, F_SETOWN, getpid()) == -1) {
    logger (LOG_CRIT, "Could not set owner because %s\n", strerror(errno));
  }

  val = fcntl(socket, F_GETFL);
  val |= O_ASYNC;
  if (fcntl (socket, F_SETFL, val) == -1) {
    logger (LOG_CRIT, "Could not set ASYNC because %s\n", strerror(errno));
    exit (EXIT_FAILURE);
  }
  return;
}

void print_socket_options(int socket)
{
  int val, enable;
  struct timeval timeout;
  struct linger linger_opts;

  logger (LOG_INFO, "Status of socket %d\n", socket);

  val = sizeof(timeout);
  if (getsockopt (socket, SOL_SOCKET, SO_SNDTIMEO, &timeout, &val)) {
    logger(LOG_CRIT, "Could not get send timeout option\n");
    exit(EXIT_FAILURE);
  }
  logger (LOG_INFO, "Socket send timeout is %d\n", timeout.tv_sec);

  val = sizeof(timeout);
  if (getsockopt (socket, SOL_SOCKET, SO_RCVTIMEO, &timeout, &val)) {
    logger(LOG_CRIT, "Could not get recv timeout option\n");
    exit(EXIT_FAILURE);
  }
  logger (LOG_INFO, "Socket recv timeout is %d\n", timeout.tv_sec);

  val = sizeof(enable);
  if (getsockopt(socket, SOL_SOCKET, SO_REUSEADDR, &enable, &val)) {
    logger (LOG_CRIT, "Could not get reuse addr flag\n");
    exit (EXIT_FAILURE);
  }
  logger (LOG_INFO, "REUSEADDR flag is %d\n", enable);

  val = sizeof(linger_opts);
  if (getsockopt(socket, SOL_SOCKET, SO_LINGER, &linger_opts, &val)) {
    logger (LOG_CRIT, "Could not set linger options\n");
    exit(EXIT_FAILURE);
  }
  logger (LOG_INFO, "Linger options are %d and %d\n", linger_opts.l_onoff, linger_opts.l_linger);

  val = fcntl(socket, F_GETFL);
  logger (LOG_INFO, "Nonblocking IO is %d\n", val & O_NONBLOCK);
  logger (LOG_INFO, "Async IO is %d\n", val & O_ASYNC);

  val = fcntl (socket, F_GETFD);
  logger (LOG_INFO, "close-on-exec flag is %d\n", val);

  val = fcntl (socket, F_GETOWN);
  logger (LOG_INFO, "Pid owner is %d\n", val);

  return;
}

int opensocket(char *address, int port, int timeout_sec, int linger_sec)
{
  int s, enable;
  struct sockaddr_in name;

  if ((s = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
    logger(LOG_CRIT, "Could not open socket: %s\n", strerror(errno));
    return s;
  }

  bzero (&name, sizeof(name));

  set_socket_options(s);

  name.sin_family = AF_INET;
  if (strcmp(address, WILDCARD_ADDRESS) == 0) {
    name.sin_addr.s_addr = htonl(INADDR_ANY);
  } else {
    if ((name.sin_addr.s_addr = inet_addr(address)) == INADDR_NONE) {
      logger(LOG_CRIT, "Inet_addr failed: %s\n", strerror(errno));
      exit (EXIT_FAILURE);
    }
  }
  name.sin_port = htons(port);

  if (bind(s, (struct sockaddr *)&name, sizeof(name)) == -1) {
    logger(LOG_CRIT, "Could not bind socket: %s\n", strerror(errno));
    close(s);
    return -1;
  }

  if (listen(s, 4) == -1) {
    logger(LOG_CRIT, "Could not listen on socket: %s\n", strerror(errno));
    close(s);
    return -1;
  }

  return s;
}
  
int main (void)
{
  int s, ns, len;
  struct sockaddr addr;

  s = opensocket("*", 64000, 3, 5);
  print_socket_options(s);

  do {
    len = sizeof (addr);
    ns = accept(s, &addr, &len);
  } while ((ns == -1) && (errno == EWOULDBLOCK));
  logger (LOG_INFO, "\nAfter accept\n");
  logger (LOG_INFO, "Orignal socket\n");
  print_socket_options(s);
  logger (LOG_INFO, "\nAccepted socket\n");
  print_socket_options(ns);
  close (s);
  close(ns);
}

>Fix:

	
	Detail in the accept(2) man page which socket properties are changed durning
	an accept call.


>Release-Note:
>Audit-Trail:
>Unformatted:



More information about the freebsd-doc mailing list