Postfix3.3.1
inet_listen.c
[詳解]
1 /*++
2 /* NAME
3 /* inet_listen 3
4 /* SUMMARY
5 /* start TCP listener
6 /* SYNOPSIS
7 /* #include <listen.h>
8 /*
9 /* int inet_windowsize;
10 /*
11 /* int inet_listen(addr, backlog, block_mode)
12 /* const char *addr;
13 /* int backlog;
14 /* int block_mode;
15 /*
16 /* int inet_accept(fd)
17 /* int fd;
18 /* DESCRIPTION
19 /* The \fBinet_listen\fR routine starts a TCP listener
20 /* on the specified address, with the specified backlog, and returns
21 /* the resulting file descriptor.
22 /*
23 /* inet_accept() accepts a connection and sanitizes error results.
24 /*
25 /* Specify an inet_windowsize value > 0 to override the TCP
26 /* window size that the server advertises to the client.
27 /*
28 /* Arguments:
29 /* .IP addr
30 /* The communication endpoint to listen on. The syntax is "host:port".
31 /* Host and port may be specified in symbolic form or numerically.
32 /* A null host field means listen on all network interfaces.
33 /* .IP backlog
34 /* This argument is passed on to the \fIlisten(2)\fR routine.
35 /* .IP block_mode
36 /* Either NON_BLOCKING for a non-blocking socket, or BLOCKING for
37 /* blocking mode.
38 /* .IP fd
39 /* File descriptor returned by inet_listen().
40 /* DIAGNOSTICS
41 /* Fatal errors: inet_listen() aborts upon any system call failure.
42 /* inet_accept() leaves all error handling up to the caller.
43 /* LICENSE
44 /* .ad
45 /* .fi
46 /* The Secure Mailer license must be distributed with this software.
47 /* AUTHOR(S)
48 /* Wietse Venema
49 /* IBM T.J. Watson Research
50 /* P.O. Box 704
51 /* Yorktown Heights, NY 10598, USA
52 /*--*/
53 
54 /* System libraries. */
55 
56 #include <sys_defs.h>
57 #include <sys/socket.h>
58 #include <netinet/in.h>
59 #include <arpa/inet.h>
60 #include <netdb.h>
61 #ifndef MAXHOSTNAMELEN
62 #include <sys/param.h>
63 #endif
64 #include <errno.h>
65 #include <string.h>
66 #include <unistd.h>
67 
68 /* Utility library. */
69 
70 #include "mymalloc.h"
71 #include "msg.h"
72 #include "host_port.h"
73 #include "iostuff.h"
74 #include "listen.h"
75 #include "sane_accept.h"
76 #include "myaddrinfo.h"
77 #include "sock_addr.h"
78 #include "inet_proto.h"
79 
80 /* inet_listen - create TCP listener */
81 
82 int inet_listen(const char *addr, int backlog, int block_mode)
83 {
84  struct addrinfo *res;
85  struct addrinfo *res0;
86  int aierr;
87  int sock;
88  int on = 1;
89  char *buf;
90  char *host;
91  char *port;
92  const char *parse_err;
93  MAI_HOSTADDR_STR hostaddr;
94  MAI_SERVPORT_STR portnum;
95  INET_PROTO_INFO *proto_info;
96 
97  /*
98  * Translate address information to internal form.
99  */
100  buf = mystrdup(addr);
101  if ((parse_err = host_port(buf, &host, "", &port, (char *) 0)) != 0)
102  msg_fatal("%s: %s", addr, parse_err);
103  if (*host == 0)
104  host = 0;
105  if ((aierr = hostname_to_sockaddr(host, port, SOCK_STREAM, &res0)) != 0)
106  msg_fatal("%s: %s", addr, MAI_STRERROR(aierr));
107  myfree(buf);
108  /* No early returns or res0 leaks. */
109 
110  proto_info = inet_proto_info();
111  for (res = res0; /* see below */ ; res = res->ai_next) {
112 
113  /*
114  * No usable address found.
115  */
116  if (res == 0)
117  msg_fatal("%s: host found but no usable address", addr);
118 
119  /*
120  * Safety net.
121  */
122  if (strchr((char *) proto_info->sa_family_list, res->ai_family) != 0)
123  break;
124 
125  msg_info("skipping address family %d for %s", res->ai_family, addr);
126  }
127 
128  /*
129  * Show what address we're trying.
130  */
131  if (msg_verbose) {
132  SOCKADDR_TO_HOSTADDR(res->ai_addr, res->ai_addrlen,
133  &hostaddr, &portnum, 0);
134  msg_info("trying... [%s]:%s", hostaddr.buf, portnum.buf);
135  }
136 
137  /*
138  * Create a listener socket.
139  */
140  if ((sock = socket(res->ai_family, res->ai_socktype, 0)) < 0)
141  msg_fatal("socket: %m");
142 #ifdef HAS_IPV6
143 #if defined(IPV6_V6ONLY) && !defined(BROKEN_AI_PASSIVE_NULL_HOST)
144  if (res->ai_family == AF_INET6
145  && setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY,
146  (void *) &on, sizeof(on)) < 0)
147  msg_fatal("setsockopt(IPV6_V6ONLY): %m");
148 #endif
149 #endif
150  if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
151  (void *) &on, sizeof(on)) < 0)
152  msg_fatal("setsockopt(SO_REUSEADDR): %m");
153  if (bind(sock, res->ai_addr, res->ai_addrlen) < 0) {
154  SOCKADDR_TO_HOSTADDR(res->ai_addr, res->ai_addrlen,
155  &hostaddr, &portnum, 0);
156  msg_fatal("bind %s port %s: %m", hostaddr.buf, portnum.buf);
157  }
158  freeaddrinfo(res0);
159  non_blocking(sock, block_mode);
160  if (inet_windowsize > 0)
162  if (listen(sock, backlog) < 0)
163  msg_fatal("listen: %m");
164  return (sock);
165 }
166 
167 /* inet_accept - accept connection */
168 
169 int inet_accept(int fd)
170 {
171  struct sockaddr_storage ss;
172  SOCKADDR_SIZE ss_len = sizeof(ss);
173 
174  return (sane_accept(fd, (struct sockaddr *) &ss, &ss_len));
175 }
int msg_verbose
Definition: msg.c:177
void myfree(void *ptr)
Definition: mymalloc.c:207
void freeaddrinfo(struct addrinfo *ai)
Definition: myaddrinfo.c:742
char * mystrdup(const char *str)
Definition: mymalloc.c:225
int inet_listen(const char *addr, int backlog, int block_mode)
Definition: inet_listen.c:82
#define inet_proto_info()
Definition: inet_proto.h:29
#define hostname_to_sockaddr(host, serv, sock, res)
Definition: myaddrinfo.h:171
#define SOCKADDR_TO_HOSTADDR(sa, salen, host, port, sock)
Definition: myaddrinfo.h:197
void set_inet_windowsize(int sock, int windowsize)
int inet_accept(int fd)
Definition: inet_listen.c:169
#define SOCKADDR_SIZE
Definition: sys_defs.h:1411
char buf[MAI_HOSTADDR_STRSIZE]
Definition: myaddrinfo.h:146
int inet_windowsize
unsigned char * sa_family_list
Definition: inet_proto.h:21
int sane_accept(int sock, struct sockaddr *sa, SOCKADDR_SIZE *len)
Definition: sane_accept.c:47
NORETURN msg_fatal(const char *fmt,...)
Definition: msg.c:249
int non_blocking(int, int)
Definition: non_blocking.c:55
const char * host_port(char *buf, char **host, char *def_host, char **port, char *def_service)
Definition: host_port.c:115
#define MAI_STRERROR(e)
Definition: myaddrinfo.h:169
char buf[MAI_SERVPORT_STRSIZE]
Definition: myaddrinfo.h:154
void msg_info(const char *fmt,...)
Definition: msg.c:199