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