blob: 593096d7f387f1bf137e6129f29ba0e02dfaa79f [file] [log] [blame]
Willy Tarreaue6b98942007-10-29 01:09:36 +01001/*
2 * AF_INET/AF_INET6 SOCK_STREAM protocol layer (tcp)
3 *
4 * Copyright 2000-2007 Willy Tarreau <w@1wt.eu>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
13#include <ctype.h>
14#include <errno.h>
15#include <fcntl.h>
16#include <stdio.h>
17#include <stdlib.h>
18#include <string.h>
19#include <time.h>
20
21#include <sys/param.h>
22#include <sys/socket.h>
23#include <sys/stat.h>
24#include <sys/types.h>
25#include <sys/un.h>
26
27#include <common/compat.h>
28#include <common/config.h>
29#include <common/debug.h>
30#include <common/errors.h>
31#include <common/memory.h>
32#include <common/mini-clist.h>
33#include <common/standard.h>
34#include <common/time.h>
35#include <common/version.h>
36
37#include <types/acl.h>
38#include <types/client.h>
39#include <types/global.h>
40#include <types/polling.h>
41#include <types/proxy.h>
42#include <types/server.h>
43
44#include <proto/acl.h>
45#include <proto/backend.h>
46#include <proto/buffers.h>
47#include <proto/fd.h>
48#include <proto/protocols.h>
49#include <proto/proto_tcp.h>
50#include <proto/queue.h>
51#include <proto/senddata.h>
52#include <proto/session.h>
53#include <proto/stream_sock.h>
54#include <proto/task.h>
55
56static int tcp_bind_listeners(struct protocol *proto);
57
58/* Note: must not be declared <const> as its list will be overwritten */
59static struct protocol proto_tcpv4 = {
60 .name = "tcpv4",
61 .sock_domain = AF_INET,
62 .sock_type = SOCK_STREAM,
63 .sock_prot = IPPROTO_TCP,
64 .sock_family = AF_INET,
65 .sock_addrlen = sizeof(struct sockaddr_in),
66 .l3_addrlen = 32/8,
67 .read = &stream_sock_read,
68 .write = &stream_sock_write,
69 .bind_all = tcp_bind_listeners,
70 .unbind_all = unbind_all_listeners,
71 .enable_all = enable_all_listeners,
72 .listeners = LIST_HEAD_INIT(proto_tcpv4.listeners),
73 .nb_listeners = 0,
74};
75
76/* Note: must not be declared <const> as its list will be overwritten */
77static struct protocol proto_tcpv6 = {
78 .name = "tcpv6",
79 .sock_domain = AF_INET6,
80 .sock_type = SOCK_STREAM,
81 .sock_prot = IPPROTO_TCP,
82 .sock_family = AF_INET6,
83 .sock_addrlen = sizeof(struct sockaddr_in6),
84 .l3_addrlen = 128/8,
85 .read = &stream_sock_read,
86 .write = &stream_sock_write,
87 .bind_all = tcp_bind_listeners,
88 .unbind_all = unbind_all_listeners,
89 .enable_all = enable_all_listeners,
90 .listeners = LIST_HEAD_INIT(proto_tcpv6.listeners),
91 .nb_listeners = 0,
92};
93
94
95/* This function tries to bind a TCPv4/v6 listener. It may return a warning or
96 * an error message in <err> if the message is at most <errlen> bytes long
97 * (including '\0'). The return value is composed from ERR_ABORT, ERR_WARN,
98 * ERR_ALERT, ERR_RETRYABLE and ERR_FATAL. ERR_NONE indicates that everything
99 * was alright and that no message was returned. ERR_RETRYABLE means that an
100 * error occurred but that it may vanish after a retry (eg: port in use), and
101 * ERR_FATAL indicates a non-fixable error.ERR_WARN and ERR_ALERT do not alter
102 * the meaning of the error, but just indicate that a message is present which
103 * should be displayed with the respective level. Last, ERR_ABORT indicates
104 * that it's pointless to try to start other listeners. No error message is
105 * returned if errlen is NULL.
106 */
107int tcp_bind_listener(struct listener *listener, char *errmsg, int errlen)
108{
109 __label__ tcp_return, tcp_close_return;
110 int fd, err;
111 const char *msg = NULL;
112
113 /* ensure we never return garbage */
114 if (errmsg && errlen)
115 *errmsg = 0;
116
117 if (listener->state != LI_ASSIGNED)
118 return ERR_NONE; /* already bound */
119
120 err = ERR_NONE;
121
122 if ((fd = socket(listener->addr.ss_family, SOCK_STREAM, IPPROTO_TCP)) == -1) {
123 err |= ERR_RETRYABLE | ERR_ALERT;
124 msg = "cannot create listening socket";
125 goto tcp_return;
126 }
127
128 if (fd >= global.maxsock) {
129 err |= ERR_FATAL | ERR_ABORT | ERR_ALERT;
130 msg = "not enough free sockets (raise '-n' parameter)";
131 goto tcp_close_return;
132 }
133
134 if ((fcntl(fd, F_SETFL, O_NONBLOCK) == -1) ||
135 (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY,
136 (char *) &one, sizeof(one)) == -1)) {
137 err |= ERR_FATAL | ERR_ALERT;
138 msg = "cannot make socket non-blocking";
139 goto tcp_close_return;
140 }
141
142 if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *) &one, sizeof(one)) == -1) {
143 /* not fatal but should be reported */
144 msg = "cannot do so_reuseaddr";
145 err |= ERR_ALERT;
146 }
147
148 if (listener->options & LI_O_NOLINGER)
149 setsockopt(fd, SOL_SOCKET, SO_LINGER, (struct linger *) &nolinger, sizeof(struct linger));
150
151#ifdef SO_REUSEPORT
152 /* OpenBSD supports this. As it's present in old libc versions of Linux,
153 * it might return an error that we will silently ignore.
154 */
155 setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, (char *) &one, sizeof(one));
156#endif
157 if (bind(fd, (struct sockaddr *)&listener->addr, listener->proto->sock_addrlen) == -1) {
158 err |= ERR_RETRYABLE | ERR_ALERT;
159 msg = "cannot bind socket";
160 goto tcp_close_return;
161 }
162
163 if (listen(fd, listener->maxconn) == -1) {
164 err |= ERR_RETRYABLE | ERR_ALERT;
165 msg = "cannot listen to socket";
166 goto tcp_close_return;
167 }
168
169 /* the socket is ready */
170 listener->fd = fd;
171 listener->state = LI_LISTEN;
172
173 /* the function for the accept() event */
174 fd_insert(fd);
175 fdtab[fd].cb[DIR_RD].f = listener->accept;
176 fdtab[fd].cb[DIR_WR].f = NULL; /* never called */
177 fdtab[fd].cb[DIR_RD].b = fdtab[fd].cb[DIR_WR].b = NULL;
178 fdtab[fd].owner = (struct task *)listener; /* reference the listener instead of a task */
179 fdtab[fd].state = FD_STLISTEN;
180 fdtab[fd].peeraddr = NULL;
181 fdtab[fd].peerlen = 0;
182 fdtab[fd].listener = NULL;
183 fdtab[fd].ev = 0;
184 tcp_return:
185 if (msg && errlen)
186 strlcpy2(errmsg, msg, errlen);
187 return err;
188
189 tcp_close_return:
190 close(fd);
191 goto tcp_return;
192}
193
194/* This function creates all TCP sockets bound to the protocol entry <proto>.
195 * It is intended to be used as the protocol's bind_all() function.
196 * The sockets will be registered but not added to any fd_set, in order not to
197 * loose them across the fork(). A call to enable_all_listeners() is needed
198 * to complete initialization. The return value is composed from ERR_*.
199 */
200static int tcp_bind_listeners(struct protocol *proto)
201{
202 struct listener *listener;
203 int err = ERR_NONE;
204
205 list_for_each_entry(listener, &proto->listeners, proto_list) {
206 err |= tcp_bind_listener(listener, NULL, 0);
207 if ((err & ERR_CODE) == ERR_ABORT)
208 break;
209 }
210
211 return err;
212}
213
214/* Add listener to the list of tcpv4 listeners. The listener's state
215 * is automatically updated from LI_INIT to LI_ASSIGNED. The number of
216 * listeners is updated. This is the function to use to add a new listener.
217 */
218void tcpv4_add_listener(struct listener *listener)
219{
220 if (listener->state != LI_INIT)
221 return;
222 listener->state = LI_ASSIGNED;
223 listener->proto = &proto_tcpv4;
224 LIST_ADDQ(&proto_tcpv4.listeners, &listener->proto_list);
225 proto_tcpv4.nb_listeners++;
226}
227
228/* Add listener to the list of tcpv4 listeners. The listener's state
229 * is automatically updated from LI_INIT to LI_ASSIGNED. The number of
230 * listeners is updated. This is the function to use to add a new listener.
231 */
232void tcpv6_add_listener(struct listener *listener)
233{
234 if (listener->state != LI_INIT)
235 return;
236 listener->state = LI_ASSIGNED;
237 listener->proto = &proto_tcpv6;
238 LIST_ADDQ(&proto_tcpv6.listeners, &listener->proto_list);
239 proto_tcpv6.nb_listeners++;
240}
241
242__attribute__((constructor))
243static void __tcp_protocol_init(void)
244{
245 protocol_register(&proto_tcpv4);
246 protocol_register(&proto_tcpv6);
247}
248
249
250/*
251 * Local variables:
252 * c-indent-level: 8
253 * c-basic-offset: 8
254 * End:
255 */