blob: a5431c2b3f19ef85d7c44bf00d49b80f0f530990 [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Proxy variables and functions.
3 *
4 * Copyright 2000-2006 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 <fcntl.h>
14#include <unistd.h>
15#include <sys/types.h>
16#include <sys/socket.h>
17#include <sys/stat.h>
18
Willy Tarreau2dd0d472006-06-29 17:53:05 +020019#include <common/defaults.h>
20#include <common/compat.h>
Willy Tarreaue3ba5f02006-06-29 18:54:54 +020021#include <common/config.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020022#include <common/time.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020023
24#include <types/global.h>
25#include <types/polling.h>
26
27#include <proto/client.h>
28#include <proto/fd.h>
29#include <proto/log.h>
30#include <proto/proxy.h>
31
32
33int listeners; /* # of listeners */
34struct proxy *proxy = NULL; /* list of all existing proxies */
35
Willy Tarreau977b8e42006-12-29 14:19:17 +010036/*
37 * This function returns a string containing the type of the proxy in a format
38 * suitable for error messages, from its capabilities.
39 */
Willy Tarreau2b5652f2006-12-31 17:46:05 +010040const char *proxy_type_str(struct proxy *proxy)
Willy Tarreau977b8e42006-12-29 14:19:17 +010041{
Willy Tarreau2b5652f2006-12-31 17:46:05 +010042 int cap = proxy->cap;
Willy Tarreau977b8e42006-12-29 14:19:17 +010043 if ((cap & PR_CAP_LISTEN) == PR_CAP_LISTEN)
44 return "listener";
45 else if (cap & PR_CAP_FE)
46 return "frontend";
47 else if (cap & PR_CAP_BE)
48 return "backend";
49 else if (cap & PR_CAP_RS)
50 return "ruleset";
51 else
52 return "proxy";
53}
54
Willy Tarreaubaaee002006-06-26 02:48:02 +020055
56/*
Willy Tarreau2ff76222007-04-09 19:29:56 +020057 * This function creates all proxy sockets. It should be done very early,
58 * typically before privileges are dropped. The sockets will be registered
59 * but not added to any fd_set, in order not to loose them across the fork().
60 * The proxies also start in IDLE state, meaning that it will be
61 * maintain_proxies that will finally complete their loading.
62 *
63 * Its return value is composed from ERR_NONE, ERR_RETRYABLE and ERR_FATAL.
64 * Retryable errors will only be printed if <verbose> is not zero.
Willy Tarreaubaaee002006-06-26 02:48:02 +020065 */
66int start_proxies(int verbose)
67{
68 struct proxy *curproxy;
69 struct listener *listener;
70 int err = ERR_NONE;
71 int fd, pxerr;
72
73 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
74 if (curproxy->state != PR_STNEW)
75 continue; /* already initialized */
76
77 pxerr = 0;
78 for (listener = curproxy->listen; listener != NULL; listener = listener->next) {
79 if (listener->fd != -1)
80 continue; /* already initialized */
81
82 if ((fd = socket(listener->addr.ss_family, SOCK_STREAM, IPPROTO_TCP)) == -1) {
83 if (verbose)
84 Alert("cannot create listening socket for proxy %s. Aborting.\n",
85 curproxy->id);
86 err |= ERR_RETRYABLE;
87 pxerr |= 1;
88 continue;
89 }
90
91 if (fd >= global.maxsock) {
92 Alert("socket(): not enough free sockets for proxy %s. Raise -n argument. Aborting.\n",
93 curproxy->id);
94 close(fd);
95 err |= ERR_FATAL;
96 pxerr |= 1;
97 break;
98 }
99
100 if ((fcntl(fd, F_SETFL, O_NONBLOCK) == -1) ||
101 (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY,
102 (char *) &one, sizeof(one)) == -1)) {
103 Alert("cannot make socket non-blocking for proxy %s. Aborting.\n",
104 curproxy->id);
105 close(fd);
106 err |= ERR_FATAL;
107 pxerr |= 1;
108 break;
109 }
110
111 if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *) &one, sizeof(one)) == -1) {
112 Alert("cannot do so_reuseaddr for proxy %s. Continuing.\n",
113 curproxy->id);
114 }
115
116#ifdef SO_REUSEPORT
117 /* OpenBSD supports this. As it's present in old libc versions of Linux,
118 * it might return an error that we will silently ignore.
119 */
120 setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, (char *) &one, sizeof(one));
121#endif
122 if (bind(fd,
123 (struct sockaddr *)&listener->addr,
124 listener->addr.ss_family == AF_INET6 ?
125 sizeof(struct sockaddr_in6) :
126 sizeof(struct sockaddr_in)) == -1) {
127 if (verbose)
128 Alert("cannot bind socket for proxy %s. Aborting.\n",
129 curproxy->id);
130 close(fd);
131 err |= ERR_RETRYABLE;
132 pxerr |= 1;
133 continue;
134 }
135
136 if (listen(fd, curproxy->maxconn) == -1) {
137 if (verbose)
138 Alert("cannot listen to socket for proxy %s. Aborting.\n",
139 curproxy->id);
140 close(fd);
141 err |= ERR_RETRYABLE;
142 pxerr |= 1;
143 continue;
144 }
145
146 /* the socket is ready */
147 listener->fd = fd;
148
149 /* the function for the accept() event */
Willy Tarreau54469402006-07-29 16:59:06 +0200150 fdtab[fd].cb[DIR_RD].f = &event_accept;
151 fdtab[fd].cb[DIR_WR].f = NULL; /* never called */
152 fdtab[fd].cb[DIR_RD].b = fdtab[fd].cb[DIR_WR].b = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200153 fdtab[fd].owner = (struct task *)curproxy; /* reference the proxy instead of a task */
154 fdtab[fd].state = FD_STLISTEN;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200155 fd_insert(fd);
156 listeners++;
157 }
158
159 if (!pxerr) {
Willy Tarreau2ff76222007-04-09 19:29:56 +0200160 curproxy->state = PR_STIDLE;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200161 send_log(curproxy, LOG_NOTICE, "Proxy %s started.\n", curproxy->id);
162 }
163 }
164
165 return err;
166}
167
168
169/*
170 * this function enables proxies when there are enough free sessions,
171 * or stops them when the table is full. It is designed to be called from the
172 * select_loop(). It returns the time left before next expiration event
173 * during stop time, TIME_ETERNITY otherwise.
174 */
175int maintain_proxies(void)
176{
177 struct proxy *p;
178 struct listener *l;
179 int tleft; /* time left */
180
181 p = proxy;
182 tleft = TIME_ETERNITY; /* infinite time */
183
184 /* if there are enough free sessions, we'll activate proxies */
185 if (actconn < global.maxconn) {
186 while (p) {
Willy Tarreauf1221aa2006-12-17 22:14:12 +0100187 if (p->feconn < p->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200188 if (p->state == PR_STIDLE) {
189 for (l = p->listen; l != NULL; l = l->next) {
Willy Tarreauf161a342007-04-08 16:59:42 +0200190 EV_FD_SET(l->fd, DIR_RD);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200191 }
192 p->state = PR_STRUN;
193 }
194 }
195 else {
196 if (p->state == PR_STRUN) {
197 for (l = p->listen; l != NULL; l = l->next) {
Willy Tarreauf161a342007-04-08 16:59:42 +0200198 EV_FD_CLR(l->fd, DIR_RD);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200199 }
200 p->state = PR_STIDLE;
201 }
202 }
203 p = p->next;
204 }
205 }
206 else { /* block all proxies */
207 while (p) {
208 if (p->state == PR_STRUN) {
209 for (l = p->listen; l != NULL; l = l->next) {
Willy Tarreauf161a342007-04-08 16:59:42 +0200210 EV_FD_CLR(l->fd, DIR_RD);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200211 }
212 p->state = PR_STIDLE;
213 }
214 p = p->next;
215 }
216 }
217
218 if (stopping) {
219 p = proxy;
220 while (p) {
221 if (p->state != PR_STSTOPPED) {
222 int t;
223 t = tv_remain2(&now, &p->stop_time);
224 if (t == 0) {
225 Warning("Proxy %s stopped.\n", p->id);
226 send_log(p, LOG_WARNING, "Proxy %s stopped.\n", p->id);
227
228 for (l = p->listen; l != NULL; l = l->next) {
229 fd_delete(l->fd);
230 listeners--;
231 }
232 p->state = PR_STSTOPPED;
233 }
234 else {
235 tleft = MINTIME(t, tleft);
236 }
237 }
238 p = p->next;
239 }
240 }
241 return tleft;
242}
243
244
245/*
246 * this function disables health-check servers so that the process will quickly be ignored
247 * by load balancers. Note that if a proxy was already in the PAUSED state, then its grace
248 * time will not be used since it would already not listen anymore to the socket.
249 */
250void soft_stop(void)
251{
252 struct proxy *p;
253
254 stopping = 1;
255 p = proxy;
256 tv_now(&now); /* else, the old time before select will be used */
257 while (p) {
258 if (p->state != PR_STSTOPPED) {
259 Warning("Stopping proxy %s in %d ms.\n", p->id, p->grace);
260 send_log(p, LOG_WARNING, "Stopping proxy %s in %d ms.\n", p->id, p->grace);
261 tv_delayfrom(&p->stop_time, &now, p->grace);
262 }
263 p = p->next;
264 }
265}
266
267
268/*
269 * Linux unbinds the listen socket after a SHUT_RD, and ignores SHUT_WR.
270 * Solaris refuses either shutdown().
271 * OpenBSD ignores SHUT_RD but closes upon SHUT_WR and refuses to rebind.
272 * So a common validation path involves SHUT_WR && listen && SHUT_RD.
273 * If disabling at least one listener returns an error, then the proxy
274 * state is set to PR_STERROR because we don't know how to resume from this.
275 */
276void pause_proxy(struct proxy *p)
277{
278 struct listener *l;
279 for (l = p->listen; l != NULL; l = l->next) {
280 if (shutdown(l->fd, SHUT_WR) == 0 &&
281 listen(l->fd, p->maxconn) == 0 &&
282 shutdown(l->fd, SHUT_RD) == 0) {
Willy Tarreauf161a342007-04-08 16:59:42 +0200283 EV_FD_CLR(l->fd, DIR_RD);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200284 if (p->state != PR_STERROR)
285 p->state = PR_STPAUSED;
286 }
287 else
288 p->state = PR_STERROR;
289 }
290}
291
292/*
293 * This function temporarily disables listening so that another new instance
294 * can start listening. It is designed to be called upon reception of a
295 * SIGTTOU, after which either a SIGUSR1 can be sent to completely stop
296 * the proxy, or a SIGTTIN can be sent to listen again.
297 */
298void pause_proxies(void)
299{
300 int err;
301 struct proxy *p;
302
303 err = 0;
304 p = proxy;
305 tv_now(&now); /* else, the old time before select will be used */
306 while (p) {
307 if (p->state != PR_STERROR &&
308 p->state != PR_STSTOPPED &&
309 p->state != PR_STPAUSED) {
310 Warning("Pausing proxy %s.\n", p->id);
311 send_log(p, LOG_WARNING, "Pausing proxy %s.\n", p->id);
312 pause_proxy(p);
313 if (p->state != PR_STPAUSED) {
314 err |= 1;
315 Warning("Proxy %s failed to enter pause mode.\n", p->id);
316 send_log(p, LOG_WARNING, "Proxy %s failed to enter pause mode.\n", p->id);
317 }
318 }
319 p = p->next;
320 }
321 if (err) {
322 Warning("Some proxies refused to pause, performing soft stop now.\n");
323 send_log(p, LOG_WARNING, "Some proxies refused to pause, performing soft stop now.\n");
324 soft_stop();
325 }
326}
327
328
329/*
330 * This function reactivates listening. This can be used after a call to
331 * sig_pause(), for example when a new instance has failed starting up.
332 * It is designed to be called upon reception of a SIGTTIN.
333 */
334void listen_proxies(void)
335{
336 struct proxy *p;
337 struct listener *l;
338
339 p = proxy;
340 tv_now(&now); /* else, the old time before select will be used */
341 while (p) {
342 if (p->state == PR_STPAUSED) {
343 Warning("Enabling proxy %s.\n", p->id);
344 send_log(p, LOG_WARNING, "Enabling proxy %s.\n", p->id);
345
346 for (l = p->listen; l != NULL; l = l->next) {
347 if (listen(l->fd, p->maxconn) == 0) {
Willy Tarreauf1221aa2006-12-17 22:14:12 +0100348 if (actconn < global.maxconn && p->feconn < p->maxconn) {
Willy Tarreauf161a342007-04-08 16:59:42 +0200349 EV_FD_SET(l->fd, DIR_RD);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200350 p->state = PR_STRUN;
351 }
352 else
353 p->state = PR_STIDLE;
354 } else {
355 int port;
356
357 if (l->addr.ss_family == AF_INET6)
358 port = ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port);
359 else
360 port = ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
361
362 Warning("Port %d busy while trying to enable proxy %s.\n",
363 port, p->id);
364 send_log(p, LOG_WARNING, "Port %d busy while trying to enable proxy %s.\n",
365 port, p->id);
366 /* Another port might have been enabled. Let's stop everything. */
367 pause_proxy(p);
368 break;
369 }
370 }
371 }
372 p = p->next;
373 }
374}
375
376
377/*
378 * Local variables:
379 * c-indent-level: 8
380 * c-basic-offset: 8
381 * End:
382 */