Postfix3.3.1
sane_accept.c
[詳解]
1 /*++
2 /* NAME
3 /* sane_accept 3
4 /* SUMMARY
5 /* sanitize accept() error returns
6 /* SYNOPSIS
7 /* #include <sane_accept.h>
8 /*
9 /* int sane_accept(sock, buf, len)
10 /* int sock;
11 /* struct sockaddr *buf;
12 /* SOCKADDR_SIZE *len;
13 /* DESCRIPTION
14 /* sane_accept() implements the accept(2) socket call, and maps
15 /* known harmless error results to EAGAIN.
16 /*
17 /* If the buf and len arguments are not null, then additional
18 /* workarounds may be enabled that depend on the socket type.
19 /* BUGS
20 /* Bizarre systems may have other harmless error results. Such
21 /* systems encourage programmers to ignore error results, and
22 /* penalize programmers who code defensively.
23 /* LICENSE
24 /* .ad
25 /* .fi
26 /* The Secure Mailer license must be distributed with this software.
27 /* AUTHOR(S)
28 /* Wietse Venema
29 /* IBM T.J. Watson Research
30 /* P.O. Box 704
31 /* Yorktown Heights, NY 10598, USA
32 /*--*/
33 
34 /* System library. */
35 
36 #include "sys_defs.h"
37 #include <sys/socket.h>
38 #include <errno.h>
39 
40 /* Utility library. */
41 
42 #include "msg.h"
43 #include "sane_accept.h"
44 
45 /* sane_accept - sanitize accept() error returns */
46 
47 int sane_accept(int sock, struct sockaddr *sa, SOCKADDR_SIZE *len)
48 {
49  static int accept_ok_errors[] = {
50  EAGAIN,
51  ECONNREFUSED,
52  ECONNRESET,
53  EHOSTDOWN,
54  EHOSTUNREACH,
55  EINTR,
56  ENETDOWN,
57  ENETUNREACH,
58  ENOTCONN,
59  EWOULDBLOCK,
60  ENOBUFS, /* HPUX11 */
61  ECONNABORTED,
62 #ifdef EPROTO
63  EPROTO, /* SunOS 5.5.1 */
64 #endif
65  0,
66  };
67  int count;
68  int err;
69  int fd;
70 
71  /*
72  * XXX Solaris 2.4 accept() returns EPIPE when a UNIX-domain client has
73  * disconnected in the mean time. From then on, UNIX-domain sockets are
74  * hosed beyond recovery. There is no point treating this as a beneficial
75  * error result because the program would go into a tight loop.
76  *
77  * XXX Solaris 2.5.1 accept() returns EPROTO when a TCP client has
78  * disconnected in the mean time. Since there is no connection, it is
79  * safe to map the error code onto EAGAIN.
80  *
81  * XXX LINUX < 2.1 accept() wakes up before the three-way handshake is
82  * complete, so it can fail with ECONNRESET and other "false alarm"
83  * indications.
84  *
85  * XXX FreeBSD 4.2-STABLE accept() returns ECONNABORTED when a UNIX-domain
86  * client has disconnected in the mean time. The data that was sent with
87  * connect() write() close() is lost, even though the write() and close()
88  * reported successful completion. This was fixed shortly before FreeBSD
89  * 4.3.
90  *
91  * XXX HP-UX 11 returns ENOBUFS when the client has disconnected in the mean
92  * time.
93  */
94  if ((fd = accept(sock, sa, len)) < 0) {
95  for (count = 0; (err = accept_ok_errors[count]) != 0; count++) {
96  if (errno == err) {
97  errno = EAGAIN;
98  break;
99  }
100  }
101  }
102 
103  /*
104  * XXX Solaris select() produces false read events, so that read() blocks
105  * forever on a blocking socket, and fails with EAGAIN on a non-blocking
106  * socket. Turning on keepalives will fix a blocking socket provided that
107  * the kernel's keepalive timer expires before the Postfix watchdog
108  * timer.
109  *
110  * XXX Work around NAT induced damage by sending a keepalive before an idle
111  * connection is expired. This requires that the kernel keepalive timer
112  * is set to a short time, like 100s.
113  */
114  else if (sa && (sa->sa_family == AF_INET
115 #ifdef HAS_IPV6
116  || sa->sa_family == AF_INET6
117 #endif
118  )) {
119  int on = 1;
120 
121  (void) setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE,
122  (void *) &on, sizeof(on));
123  }
124  return (fd);
125 }
#define SOCKADDR_SIZE
Definition: sys_defs.h:1411
int sane_accept(int sock, struct sockaddr *sa, SOCKADDR_SIZE *len)
Definition: sane_accept.c:47