blob: 78d936746d5ba4ee11eb0704ff921f89f724ca24 [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
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100157#ifdef CONFIG_HAP_LINUX_TPROXY
158 if ((listener->options & LI_O_FOREIGN)
159 && (setsockopt(fd, SOL_IP, IP_TRANSPARENT, (char *) &one, sizeof(one)) == -1)) {
160 msg = "cannot make listening socket transparent";
161 err |= ERR_ALERT;
162 }
163#endif
Willy Tarreaue6b98942007-10-29 01:09:36 +0100164 if (bind(fd, (struct sockaddr *)&listener->addr, listener->proto->sock_addrlen) == -1) {
165 err |= ERR_RETRYABLE | ERR_ALERT;
166 msg = "cannot bind socket";
167 goto tcp_close_return;
168 }
169
Willy Tarreauc73ce2b2008-01-06 10:55:10 +0100170 if (listen(fd, listener->backlog ? listener->backlog : listener->maxconn) == -1) {
Willy Tarreaue6b98942007-10-29 01:09:36 +0100171 err |= ERR_RETRYABLE | ERR_ALERT;
172 msg = "cannot listen to socket";
173 goto tcp_close_return;
174 }
175
176 /* the socket is ready */
177 listener->fd = fd;
178 listener->state = LI_LISTEN;
179
180 /* the function for the accept() event */
181 fd_insert(fd);
182 fdtab[fd].cb[DIR_RD].f = listener->accept;
183 fdtab[fd].cb[DIR_WR].f = NULL; /* never called */
184 fdtab[fd].cb[DIR_RD].b = fdtab[fd].cb[DIR_WR].b = NULL;
185 fdtab[fd].owner = (struct task *)listener; /* reference the listener instead of a task */
186 fdtab[fd].state = FD_STLISTEN;
187 fdtab[fd].peeraddr = NULL;
188 fdtab[fd].peerlen = 0;
189 fdtab[fd].listener = NULL;
190 fdtab[fd].ev = 0;
191 tcp_return:
192 if (msg && errlen)
193 strlcpy2(errmsg, msg, errlen);
194 return err;
195
196 tcp_close_return:
197 close(fd);
198 goto tcp_return;
199}
200
201/* This function creates all TCP sockets bound to the protocol entry <proto>.
202 * It is intended to be used as the protocol's bind_all() function.
203 * The sockets will be registered but not added to any fd_set, in order not to
204 * loose them across the fork(). A call to enable_all_listeners() is needed
205 * to complete initialization. The return value is composed from ERR_*.
206 */
207static int tcp_bind_listeners(struct protocol *proto)
208{
209 struct listener *listener;
210 int err = ERR_NONE;
211
212 list_for_each_entry(listener, &proto->listeners, proto_list) {
213 err |= tcp_bind_listener(listener, NULL, 0);
214 if ((err & ERR_CODE) == ERR_ABORT)
215 break;
216 }
217
218 return err;
219}
220
221/* Add listener to the list of tcpv4 listeners. The listener's state
222 * is automatically updated from LI_INIT to LI_ASSIGNED. The number of
223 * listeners is updated. This is the function to use to add a new listener.
224 */
225void tcpv4_add_listener(struct listener *listener)
226{
227 if (listener->state != LI_INIT)
228 return;
229 listener->state = LI_ASSIGNED;
230 listener->proto = &proto_tcpv4;
231 LIST_ADDQ(&proto_tcpv4.listeners, &listener->proto_list);
232 proto_tcpv4.nb_listeners++;
233}
234
235/* Add listener to the list of tcpv4 listeners. The listener's state
236 * is automatically updated from LI_INIT to LI_ASSIGNED. The number of
237 * listeners is updated. This is the function to use to add a new listener.
238 */
239void tcpv6_add_listener(struct listener *listener)
240{
241 if (listener->state != LI_INIT)
242 return;
243 listener->state = LI_ASSIGNED;
244 listener->proto = &proto_tcpv6;
245 LIST_ADDQ(&proto_tcpv6.listeners, &listener->proto_list);
246 proto_tcpv6.nb_listeners++;
247}
248
249__attribute__((constructor))
250static void __tcp_protocol_init(void)
251{
252 protocol_register(&proto_tcpv4);
253 protocol_register(&proto_tcpv6);
254}
255
256
257/*
258 * Local variables:
259 * c-indent-level: 8
260 * c-basic-offset: 8
261 * End:
262 */