blob: 34cb0bb76db410df9eed54b8488c6813582cb3d6 [file] [log] [blame]
willy tarreau0f7af912005-12-17 12:21:26 +01001/*
willy tarreau5cbea6f2005-12-17 12:48:26 +01002 * HA-Proxy : High Availability-enabled HTTP/TCP proxy
willy tarreau726618c2006-01-29 22:42:06 +01003 * 2000-2006 - Willy Tarreau - willy AT meta-x DOT org.
willy tarreau0f7af912005-12-17 12:21:26 +01004 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version
8 * 2 of the License, or (at your option) any later version.
9 *
willy tarreau906b2682005-12-17 13:49:52 +010010 * Please refer to RFC2068 or RFC2616 for informations about HTTP protocol, and
willy tarreau982249e2005-12-18 00:57:06 +010011 * RFC2965 for informations about cookies usage. More generally, the IETF HTTP
12 * Working Group's web site should be consulted for protocol related changes :
13 *
14 * http://ftp.ics.uci.edu/pub/ietf/http/
willy tarreau906b2682005-12-17 13:49:52 +010015 *
16 * Pending bugs (may be not fixed because never reproduced) :
willy tarreaua1598082005-12-17 13:08:06 +010017 * - solaris only : sometimes, an HTTP proxy with only a dispatch address causes
18 * the proxy to terminate (no core) if the client breaks the connection during
willy tarreauc29948c2005-12-17 13:10:27 +010019 * the response. Seen on 1.1.8pre4, but never reproduced. May not be related to
willy tarreau8337c6b2005-12-17 13:41:01 +010020 * the snprintf() bug since requests were simple (GET / HTTP/1.0), but may be
21 * related to missing setsid() (fixed in 1.1.15)
willy tarreauef900ab2005-12-17 12:52:52 +010022 * - a proxy with an invalid config will prevent the startup even if disabled.
23 *
willy tarreau036e1ce2005-12-17 13:46:33 +010024 * ChangeLog has moved to the CHANGELOG file.
willy tarreau0f7af912005-12-17 12:21:26 +010025 *
willy tarreau5cbea6f2005-12-17 12:48:26 +010026 * TODO:
27 * - handle properly intermediate incomplete server headers. Done ?
willy tarreau5cbea6f2005-12-17 12:48:26 +010028 * - handle hot-reconfiguration
willy tarreau906b2682005-12-17 13:49:52 +010029 * - fix client/server state transition when server is in connect or headers state
30 * and client suddenly disconnects. The server *should* switch to SHUT_WR, but
31 * still handle HTTP headers.
willy tarreau4302f492005-12-18 01:00:37 +010032 * - remove MAX_NEWHDR
willy tarreauc1f47532005-12-18 01:08:26 +010033 * - cut this huge file into several ones
willy tarreau0f7af912005-12-17 12:21:26 +010034 *
35 */
36
37#include <stdio.h>
38#include <stdlib.h>
39#include <unistd.h>
40#include <string.h>
41#include <ctype.h>
42#include <sys/time.h>
43#include <sys/types.h>
44#include <sys/socket.h>
45#include <netinet/tcp.h>
46#include <netinet/in.h>
47#include <arpa/inet.h>
48#include <netdb.h>
49#include <fcntl.h>
50#include <errno.h>
51#include <signal.h>
52#include <stdarg.h>
53#include <sys/resource.h>
54#include <time.h>
willy tarreau0f7af912005-12-17 12:21:26 +010055#include <syslog.h>
willy tarreau77bc8542005-12-18 01:31:43 +010056
57#ifdef USE_PCRE
58#include <pcre.h>
59#include <pcreposix.h>
60#else
61#include <regex.h>
62#endif
63
willy tarreaua1598082005-12-17 13:08:06 +010064#if defined(TPROXY) && defined(NETFILTER)
willy tarreau5cbea6f2005-12-17 12:48:26 +010065#include <linux/netfilter_ipv4.h>
66#endif
willy tarreau0f7af912005-12-17 12:21:26 +010067
willy tarreau12350152005-12-18 01:03:27 +010068#if defined(__dietlibc__)
69#include <strings.h>
70#endif
71
willy tarreau1c2ad212005-12-18 01:11:29 +010072#if defined(ENABLE_POLL)
73#include <sys/poll.h>
74#endif
75
76#if defined(ENABLE_EPOLL)
77#if !defined(USE_MY_EPOLL)
willy tarreauad90a0c2005-12-18 01:09:15 +010078#include <sys/epoll.h>
willy tarreau1c2ad212005-12-18 01:11:29 +010079#else
80#include "include/epoll.h"
81#endif
82#endif
willy tarreauad90a0c2005-12-18 01:09:15 +010083
willy tarreau779dc892006-03-19 19:32:29 +010084#ifdef DEBUG_FULL
85#include <assert.h>
86#endif
87
willy tarreau9e138862006-05-14 23:06:28 +020088#include <include/base64.h>
89#include <include/uri_auth.h>
willy tarreau598da412005-12-18 01:07:29 +010090#include "include/appsession.h"
willy tarreau18a957c2006-04-12 19:26:23 +020091#include "include/mini-clist.h"
willy tarreau12350152005-12-18 01:03:27 +010092
willy tarreaubfad5742006-03-23 14:19:11 +010093#ifndef HAPROXY_VERSION
willy tarreau7e6328d2006-05-21 23:26:20 +020094#define HAPROXY_VERSION "1.2.14"
willy tarreaubfad5742006-03-23 14:19:11 +010095#endif
96
97#ifndef HAPROXY_DATE
willy tarreau7e6328d2006-05-21 23:26:20 +020098#define HAPROXY_DATE "2006/05/21"
willy tarreaubfad5742006-03-23 14:19:11 +010099#endif
willy tarreau0f7af912005-12-17 12:21:26 +0100100
101/* this is for libc5 for example */
102#ifndef TCP_NODELAY
103#define TCP_NODELAY 1
104#endif
105
106#ifndef SHUT_RD
107#define SHUT_RD 0
108#endif
109
110#ifndef SHUT_WR
111#define SHUT_WR 1
112#endif
113
willy tarreau0174f312005-12-18 01:02:42 +0100114/*
115 * BUFSIZE defines the size of a read and write buffer. It is the maximum
116 * amount of bytes which can be stored by the proxy for each session. However,
117 * when reading HTTP headers, the proxy needs some spare space to add or rewrite
118 * headers if needed. The size of this spare is defined with MAXREWRITE. So it
119 * is not possible to process headers longer than BUFSIZE-MAXREWRITE bytes. By
120 * default, BUFSIZE=16384 bytes and MAXREWRITE=BUFSIZE/2, so the maximum length
121 * of headers accepted is 8192 bytes, which is in line with Apache's limits.
122 */
123#ifndef BUFSIZE
124#define BUFSIZE 16384
125#endif
willy tarreau0f7af912005-12-17 12:21:26 +0100126
127// reserved buffer space for header rewriting
willy tarreau0174f312005-12-18 01:02:42 +0100128#ifndef MAXREWRITE
129#define MAXREWRITE (BUFSIZE / 2)
130#endif
131
willy tarreau9fe663a2005-12-17 13:02:59 +0100132#define REQURI_LEN 1024
willy tarreau8337c6b2005-12-17 13:41:01 +0100133#define CAPTURE_LEN 64
willy tarreau0f7af912005-12-17 12:21:26 +0100134
willy tarreau5cbea6f2005-12-17 12:48:26 +0100135// max # args on a configuration line
willy tarreaue39cd132005-12-17 13:00:18 +0100136#define MAX_LINE_ARGS 40
willy tarreau5cbea6f2005-12-17 12:48:26 +0100137
willy tarreaue39cd132005-12-17 13:00:18 +0100138// max # of added headers per request
139#define MAX_NEWHDR 10
willy tarreau0f7af912005-12-17 12:21:26 +0100140
141// max # of matches per regexp
142#define MAX_MATCH 10
143
willy tarreau0174f312005-12-18 01:02:42 +0100144// cookie delimitor in "prefix" mode. This character is inserted between the
145// persistence cookie and the original value. The '~' is allowed by RFC2965,
146// and should not be too common in server names.
147#ifndef COOKIE_DELIM
148#define COOKIE_DELIM '~'
149#endif
150
willy tarreau0f7af912005-12-17 12:21:26 +0100151#define CONN_RETRIES 3
152
willy tarreau5cbea6f2005-12-17 12:48:26 +0100153#define CHK_CONNTIME 2000
willy tarreaue47c8d72005-12-17 12:55:52 +0100154#define DEF_CHKINTR 2000
155#define DEF_FALLTIME 3
156#define DEF_RISETIME 2
willy tarreau2f6ba652005-12-17 13:57:42 +0100157#define DEF_CHECK_REQ "OPTIONS / HTTP/1.0\r\n\r\n"
willy tarreau5cbea6f2005-12-17 12:48:26 +0100158
Willy TARREAU13032e72006-03-12 17:31:45 +0100159/* Default connections limit.
160 *
161 * A system limit can be enforced at build time in order to avoid using haproxy
162 * beyond reasonable system limits. For this, just define SYSTEM_MAXCONN to the
163 * absolute limit accepted by the system. If the configuration specifies a
164 * higher value, it will be capped to SYSTEM_MAXCONN and a warning will be
165 * emitted. The only way to override this limit will be to set it via the
166 * command-line '-n' argument.
167 */
168#ifndef SYSTEM_MAXCONN
willy tarreau9fe663a2005-12-17 13:02:59 +0100169#define DEFAULT_MAXCONN 2000
Willy TARREAU13032e72006-03-12 17:31:45 +0100170#else
171#define DEFAULT_MAXCONN SYSTEM_MAXCONN
172#endif
willy tarreau9fe663a2005-12-17 13:02:59 +0100173
willy tarreaue0331262006-05-15 03:02:46 +0200174#ifdef CONFIG_PRODUCT_NAME
175#define PRODUCT_NAME CONFIG_PRODUCT_NAME
176#else
177#define PRODUCT_NAME "HAProxy"
178#endif
179
willy tarreau0f7af912005-12-17 12:21:26 +0100180/* how many bits are needed to code the size of an int (eg: 32bits -> 5) */
181#define INTBITS 5
182
183/* show stats this every millisecond, 0 to disable */
184#ifndef STATTIME
185#define STATTIME 2000
186#endif
187
willy tarreau5cbea6f2005-12-17 12:48:26 +0100188/* this reduces the number of calls to select() by choosing appropriate
189 * sheduler precision in milliseconds. It should be near the minimum
190 * time that is needed by select() to collect all events. All timeouts
191 * are rounded up by adding this value prior to pass it to select().
192 */
193#define SCHEDULER_RESOLUTION 9
194
willy tarreaub952e1d2005-12-18 01:31:20 +0100195#define TIME_ETERNITY -1
196/* returns the lowest delay amongst <old> and <new>, and respects TIME_ETERNITY */
willy tarreau0f7af912005-12-17 12:21:26 +0100197#define MINTIME(old, new) (((new)<0)?(old):(((old)<0||(new)<(old))?(new):(old)))
198#define SETNOW(a) (*a=now)
199
willy tarreau9da061b2005-12-17 12:29:56 +0100200/****** string-specific macros and functions ******/
201/* if a > max, then bound <a> to <max>. The macro returns the new <a> */
202#define UBOUND(a, max) ({ typeof(a) b = (max); if ((a) > b) (a) = b; (a); })
203
204/* if a < min, then bound <a> to <min>. The macro returns the new <a> */
205#define LBOUND(a, min) ({ typeof(a) b = (min); if ((a) < b) (a) = b; (a); })
206
willy tarreau0174f312005-12-18 01:02:42 +0100207/* returns 1 only if only zero or one bit is set in X, which means that X is a
208 * power of 2, and 0 otherwise */
209#define POWEROF2(x) (((x) & ((x)-1)) == 0)
willy tarreau9da061b2005-12-17 12:29:56 +0100210/*
211 * copies at most <size-1> chars from <src> to <dst>. Last char is always
212 * set to 0, unless <size> is 0. The number of chars copied is returned
213 * (excluding the terminating zero).
214 * This code has been optimized for size and speed : on x86, it's 45 bytes
215 * long, uses only registers, and consumes only 4 cycles per char.
216 */
willy tarreau750a4722005-12-17 13:21:24 +0100217int strlcpy2(char *dst, const char *src, int size) {
willy tarreau9da061b2005-12-17 12:29:56 +0100218 char *orig = dst;
219 if (size) {
220 while (--size && (*dst = *src)) {
221 src++; dst++;
222 }
223 *dst = 0;
224 }
225 return dst - orig;
226}
willy tarreau9da061b2005-12-17 12:29:56 +0100227
willy tarreau4302f492005-12-18 01:00:37 +0100228/*
willy tarreaucb406512006-05-18 00:52:35 +0200229 * This function simply returns a statically allocated string containing
230 * the ascii representation for number 'n' in decimal.
231 */
232char *ultoa(unsigned long n) {
233 /* enough to store 2^63=18446744073709551615 */
234 static char itoa_str[21];
235 char *pos;
236
237 pos = itoa_str + sizeof(itoa_str) - 1;
238 *pos-- = '\0';
239
240 do {
241 *pos-- = '0' + n % 10;
242 n /= 10;
243 } while (n && pos >= itoa_str);
244 return pos + 1;
245}
246
247/*
willy tarreau4302f492005-12-18 01:00:37 +0100248 * Returns a pointer to an area of <__len> bytes taken from the pool <pool> or
249 * dynamically allocated. In the first case, <__pool> is updated to point to
250 * the next element in the list.
251 */
252#define pool_alloc_from(__pool, __len) ({ \
253 void *__p; \
254 if ((__p = (__pool)) == NULL) \
255 __p = malloc(((__len) >= sizeof (void *)) ? (__len) : sizeof(void *)); \
256 else { \
257 __pool = *(void **)(__pool); \
258 } \
259 __p; \
260})
261
262/*
263 * Puts a memory area back to the corresponding pool.
264 * Items are chained directly through a pointer that
265 * is written in the beginning of the memory area, so
266 * there's no need for any carrier cell. This implies
267 * that each memory area is at least as big as one
268 * pointer.
269 */
270#define pool_free_to(__pool, __ptr) ({ \
271 *(void **)(__ptr) = (void *)(__pool); \
272 __pool = (void *)(__ptr); \
273})
274
275
willy tarreau0f7af912005-12-17 12:21:26 +0100276#define MEM_OPTIM
277#ifdef MEM_OPTIM
278/*
279 * Returns a pointer to type <type> taken from the
280 * pool <pool_type> or dynamically allocated. In the
281 * first case, <pool_type> is updated to point to the
282 * next element in the list.
283 */
284#define pool_alloc(type) ({ \
willy tarreau4302f492005-12-18 01:00:37 +0100285 void *__p; \
286 if ((__p = pool_##type) == NULL) \
287 __p = malloc(sizeof_##type); \
willy tarreau0f7af912005-12-17 12:21:26 +0100288 else { \
289 pool_##type = *(void **)pool_##type; \
290 } \
willy tarreau4302f492005-12-18 01:00:37 +0100291 __p; \
willy tarreau0f7af912005-12-17 12:21:26 +0100292})
293
294/*
295 * Puts a memory area back to the corresponding pool.
296 * Items are chained directly through a pointer that
297 * is written in the beginning of the memory area, so
willy tarreau9da061b2005-12-17 12:29:56 +0100298 * there's no need for any carrier cell. This implies
willy tarreau0f7af912005-12-17 12:21:26 +0100299 * that each memory area is at least as big as one
300 * pointer.
301 */
302#define pool_free(type, ptr) ({ \
303 *(void **)ptr = (void *)pool_##type; \
304 pool_##type = (void *)ptr; \
305})
306
307#else
308#define pool_alloc(type) (calloc(1,sizeof_##type));
309#define pool_free(type, ptr) (free(ptr));
310#endif /* MEM_OPTIM */
311
willy tarreau5cbea6f2005-12-17 12:48:26 +0100312#define sizeof_task sizeof(struct task)
313#define sizeof_session sizeof(struct session)
willy tarreau18a957c2006-04-12 19:26:23 +0200314#define sizeof_pendconn sizeof(struct pendconn)
willy tarreau0f7af912005-12-17 12:21:26 +0100315#define sizeof_buffer sizeof(struct buffer)
316#define sizeof_fdtab sizeof(struct fdtab)
willy tarreau9fe663a2005-12-17 13:02:59 +0100317#define sizeof_requri REQURI_LEN
willy tarreau8337c6b2005-12-17 13:41:01 +0100318#define sizeof_capture CAPTURE_LEN
willy tarreau64a3cc32005-12-18 01:13:11 +0100319#define sizeof_curappsession CAPTURE_LEN /* current_session pool */
willy tarreau12350152005-12-18 01:03:27 +0100320#define sizeof_appsess sizeof(struct appsessions)
willy tarreau0f7af912005-12-17 12:21:26 +0100321
willy tarreau5cbea6f2005-12-17 12:48:26 +0100322/* different possible states for the sockets */
willy tarreau0f7af912005-12-17 12:21:26 +0100323#define FD_STCLOSE 0
324#define FD_STLISTEN 1
325#define FD_STCONN 2
326#define FD_STREADY 3
327#define FD_STERROR 4
328
willy tarreau5cbea6f2005-12-17 12:48:26 +0100329/* values for task->state */
willy tarreau0f7af912005-12-17 12:21:26 +0100330#define TASK_IDLE 0
331#define TASK_RUNNING 1
332
willy tarreau5cbea6f2005-12-17 12:48:26 +0100333/* values for proxy->state */
willy tarreau0f7af912005-12-17 12:21:26 +0100334#define PR_STNEW 0
335#define PR_STIDLE 1
336#define PR_STRUN 2
willy tarreaudbd3bef2006-01-20 19:35:18 +0100337#define PR_STSTOPPED 3
338#define PR_STPAUSED 4
willy tarreaufac1a862006-05-21 10:20:28 +0200339#define PR_STERROR 5
willy tarreau0f7af912005-12-17 12:21:26 +0100340
willy tarreau5cbea6f2005-12-17 12:48:26 +0100341/* values for proxy->mode */
willy tarreau0f7af912005-12-17 12:21:26 +0100342#define PR_MODE_TCP 0
343#define PR_MODE_HTTP 1
344#define PR_MODE_HEALTH 2
345
willy tarreau1c2ad212005-12-18 01:11:29 +0100346/* possible actions for the *poll() loops */
347#define POLL_LOOP_ACTION_INIT 0
348#define POLL_LOOP_ACTION_RUN 1
349#define POLL_LOOP_ACTION_CLEAN 2
350
willy tarreau64a3cc32005-12-18 01:13:11 +0100351/* poll mechanisms available */
352#define POLL_USE_SELECT (1<<0)
353#define POLL_USE_POLL (1<<1)
354#define POLL_USE_EPOLL (1<<2)
355
willy tarreau5cbea6f2005-12-17 12:48:26 +0100356/* bits for proxy->options */
willy tarreau0174f312005-12-18 01:02:42 +0100357#define PR_O_REDISP 0x00000001 /* allow reconnection to dispatch in case of errors */
358#define PR_O_TRANSP 0x00000002 /* transparent mode : use original DEST as dispatch */
359#define PR_O_COOK_RW 0x00000004 /* rewrite all direct cookies with the right serverid */
360#define PR_O_COOK_IND 0x00000008 /* keep only indirect cookies */
361#define PR_O_COOK_INS 0x00000010 /* insert cookies when not accessing a server directly */
362#define PR_O_COOK_PFX 0x00000020 /* rewrite all cookies by prefixing the right serverid */
363#define PR_O_COOK_ANY (PR_O_COOK_RW | PR_O_COOK_IND | PR_O_COOK_INS | PR_O_COOK_PFX)
364#define PR_O_BALANCE_RR 0x00000040 /* balance in round-robin mode */
willy tarreau0174f312005-12-18 01:02:42 +0100365#define PR_O_KEEPALIVE 0x00000080 /* follow keep-alive sessions */
366#define PR_O_FWDFOR 0x00000100 /* insert x-forwarded-for with client address */
367#define PR_O_BIND_SRC 0x00000200 /* bind to a specific source address when connect()ing */
368#define PR_O_NULLNOLOG 0x00000400 /* a connect without request will not be logged */
369#define PR_O_COOK_NOC 0x00000800 /* add a 'Cache-control' header with the cookie */
370#define PR_O_COOK_POST 0x00001000 /* don't insert cookies for requests other than a POST */
371#define PR_O_HTTP_CHK 0x00002000 /* use HTTP 'OPTIONS' method to check server health */
372#define PR_O_PERSIST 0x00004000 /* server persistence stays effective even when server is down */
373#define PR_O_LOGASAP 0x00008000 /* log as soon as possible, without waiting for the session to complete */
374#define PR_O_HTTP_CLOSE 0x00010000 /* force 'connection: close' in both directions */
375#define PR_O_CHK_CACHE 0x00020000 /* require examination of cacheability of the 'set-cookie' field */
willy tarreaub952e1d2005-12-18 01:31:20 +0100376#define PR_O_TCP_CLI_KA 0x00040000 /* enable TCP keep-alive on client-side sessions */
377#define PR_O_TCP_SRV_KA 0x00080000 /* enable TCP keep-alive on server-side sessions */
Willy TARREAU3481c462006-03-01 22:37:57 +0100378#define PR_O_USE_ALL_BK 0x00100000 /* load-balance between backup servers */
Willy TARREAU767ba712006-03-01 22:40:50 +0100379#define PR_O_FORCE_CLO 0x00200000 /* enforce the connection close immediately after server response */
willy tarreau1a3442d2006-03-24 21:03:20 +0100380#define PR_O_BALANCE_SH 0x00400000 /* balance on source IP hash */
381#define PR_O_BALANCE (PR_O_BALANCE_RR | PR_O_BALANCE_SH)
willy tarreau03a92de2006-05-21 18:26:53 +0200382#define PR_O_ABRT_CLOSE 0x00800000 /* immediately abort request when client closes */
willy tarreau5cbea6f2005-12-17 12:48:26 +0100383
willy tarreaua5e8c662006-04-29 10:43:46 +0200384/* various session flags, bits values 0x01 to 0x20 (shift 0) */
willy tarreau036e1ce2005-12-17 13:46:33 +0100385#define SN_DIRECT 0x00000001 /* connection made on the server matching the client cookie */
386#define SN_CLDENY 0x00000002 /* a client header matches a deny regex */
387#define SN_CLALLOW 0x00000004 /* a client header matches an allow regex */
388#define SN_SVDENY 0x00000008 /* a server header matches a deny regex */
389#define SN_SVALLOW 0x00000010 /* a server header matches an allow regex */
390#define SN_POST 0x00000020 /* the request was an HTTP POST */
391
willy tarreaua5e8c662006-04-29 10:43:46 +0200392/* session flags dedicated to cookies : bits values 0x40, 0x80 (0-3 shift 6) */
willy tarreau036e1ce2005-12-17 13:46:33 +0100393#define SN_CK_NONE 0x00000000 /* this session had no cookie */
394#define SN_CK_INVALID 0x00000040 /* this session had a cookie which matches no server */
395#define SN_CK_DOWN 0x00000080 /* this session had cookie matching a down server */
396#define SN_CK_VALID 0x000000C0 /* this session had cookie matching a valid server */
397#define SN_CK_MASK 0x000000C0 /* mask to get this session's cookie flags */
398#define SN_CK_SHIFT 6 /* bit shift */
399
willy tarreaua5e8c662006-04-29 10:43:46 +0200400/* session termination conditions, bits values 0x100 to 0x700 (0-7 shift 8) */
willy tarreaub1285d52005-12-18 01:20:14 +0100401#define SN_ERR_NONE 0x00000000
willy tarreau036e1ce2005-12-17 13:46:33 +0100402#define SN_ERR_CLITO 0x00000100 /* client time-out */
403#define SN_ERR_CLICL 0x00000200 /* client closed (read/write error) */
404#define SN_ERR_SRVTO 0x00000300 /* server time-out, connect time-out */
405#define SN_ERR_SRVCL 0x00000400 /* server closed (connect/read/write error) */
406#define SN_ERR_PRXCOND 0x00000500 /* the proxy decided to close (deny...) */
willy tarreaub1285d52005-12-18 01:20:14 +0100407#define SN_ERR_RESOURCE 0x00000600 /* the proxy encountered a lack of a local resources (fd, mem, ...) */
408#define SN_ERR_INTERNAL 0x00000700 /* the proxy encountered an internal error */
willy tarreau036e1ce2005-12-17 13:46:33 +0100409#define SN_ERR_MASK 0x00000700 /* mask to get only session error flags */
410#define SN_ERR_SHIFT 8 /* bit shift */
411
willy tarreaua5e8c662006-04-29 10:43:46 +0200412/* session state at termination, bits values 0x1000 to 0x7000 (0-7 shift 12) */
willy tarreau036e1ce2005-12-17 13:46:33 +0100413#define SN_FINST_R 0x00001000 /* session ended during client request */
414#define SN_FINST_C 0x00002000 /* session ended during server connect */
415#define SN_FINST_H 0x00003000 /* session ended during server headers */
416#define SN_FINST_D 0x00004000 /* session ended during data phase */
417#define SN_FINST_L 0x00005000 /* session ended while pushing last data to client */
willy tarreau078c79a2006-05-13 12:23:58 +0200418#define SN_FINST_Q 0x00006000 /* session ended while waiting in queue for a server slot */
willy tarreau036e1ce2005-12-17 13:46:33 +0100419#define SN_FINST_MASK 0x00007000 /* mask to get only final session state flags */
420#define SN_FINST_SHIFT 12 /* bit shift */
421
willy tarreaua5e8c662006-04-29 10:43:46 +0200422/* cookie information, bits values 0x10000 to 0x80000 (0-8 shift 16) */
willy tarreau036e1ce2005-12-17 13:46:33 +0100423#define SN_SCK_NONE 0x00000000 /* no set-cookie seen for the server cookie */
424#define SN_SCK_DELETED 0x00010000 /* existing set-cookie deleted or changed */
425#define SN_SCK_INSERTED 0x00020000 /* new set-cookie inserted or changed existing one */
426#define SN_SCK_SEEN 0x00040000 /* set-cookie seen for the server cookie */
427#define SN_SCK_MASK 0x00070000 /* mask to get the set-cookie field */
willy tarreau97f58572005-12-18 00:53:44 +0100428#define SN_SCK_ANY 0x00080000 /* at least one set-cookie seen (not to be counted) */
willy tarreau036e1ce2005-12-17 13:46:33 +0100429#define SN_SCK_SHIFT 16 /* bit shift */
430
willy tarreaua5e8c662006-04-29 10:43:46 +0200431/* cacheability management, bits values 0x100000 to 0x300000 (0-3 shift 20) */
willy tarreau97f58572005-12-18 00:53:44 +0100432#define SN_CACHEABLE 0x00100000 /* at least part of the response is cacheable */
433#define SN_CACHE_COOK 0x00200000 /* a cookie in the response is cacheable */
434#define SN_CACHE_SHIFT 20 /* bit shift */
willy tarreau5cbea6f2005-12-17 12:48:26 +0100435
willy tarreaua5e8c662006-04-29 10:43:46 +0200436/* various other session flags, bits values 0x400000 and above */
437#define SN_MONITOR 0x00400000 /* this session comes from a monitoring system */
willy tarreaudfece232006-05-02 00:19:57 +0200438#define SN_ASSIGNED 0x00800000 /* no need to assign a server to this session */
439#define SN_ADDR_SET 0x01000000 /* this session's server address has been set */
willy tarreaue0331262006-05-15 03:02:46 +0200440#define SN_SELF_GEN 0x02000000 /* the proxy generates data for the client (eg: stats) */
willy tarreaua5e8c662006-04-29 10:43:46 +0200441
willy tarreaue0331262006-05-15 03:02:46 +0200442/* various data sources for the responses */
443#define DATA_SRC_NONE 0
444#define DATA_SRC_STATS 1
willy tarreaua5e8c662006-04-29 10:43:46 +0200445
willy tarreau1f431b52006-05-21 14:46:15 +0200446/* data transmission states for the responses */
447#define DATA_ST_INIT 0
448#define DATA_ST_DATA 1
449
willy tarreau5cbea6f2005-12-17 12:48:26 +0100450/* different possible states for the client side */
willy tarreau0f7af912005-12-17 12:21:26 +0100451#define CL_STHEADERS 0
452#define CL_STDATA 1
453#define CL_STSHUTR 2
454#define CL_STSHUTW 3
455#define CL_STCLOSE 4
456
willy tarreau5cbea6f2005-12-17 12:48:26 +0100457/* different possible states for the server side */
willy tarreau0f7af912005-12-17 12:21:26 +0100458#define SV_STIDLE 0
willy tarreau9fea1942006-05-12 19:46:40 +0200459#define SV_STCONN 1
460#define SV_STHEADERS 2
461#define SV_STDATA 3
462#define SV_STSHUTR 4
463#define SV_STSHUTW 5
464#define SV_STCLOSE 6
willy tarreau0f7af912005-12-17 12:21:26 +0100465
466/* result of an I/O event */
467#define RES_SILENT 0 /* didn't happen */
468#define RES_DATA 1 /* data were sent or received */
469#define RES_NULL 2 /* result is 0 (read == 0), or connect without need for writing */
470#define RES_ERROR 3 /* result -1 or error on the socket (eg: connect()) */
471
willy tarreau9fe663a2005-12-17 13:02:59 +0100472/* modes of operation (global.mode) */
willy tarreau0f7af912005-12-17 12:21:26 +0100473#define MODE_DEBUG 1
474#define MODE_STATS 2
475#define MODE_LOG 4
476#define MODE_DAEMON 8
willy tarreau5cbea6f2005-12-17 12:48:26 +0100477#define MODE_QUIET 16
willy tarreaudd07e972005-12-18 00:48:48 +0100478#define MODE_CHECK 32
willy tarreau982249e2005-12-18 00:57:06 +0100479#define MODE_VERBOSE 64
willy tarreaud0fb4652005-12-18 01:32:04 +0100480#define MODE_STARTING 128
willy tarreaubf8ff3d2006-03-25 19:47:03 +0100481#define MODE_FOREGROUND 256
willy tarreau5cbea6f2005-12-17 12:48:26 +0100482
483/* server flags */
willy tarreaua41a8b42005-12-17 14:02:24 +0100484#define SRV_RUNNING 1 /* the server is UP */
485#define SRV_BACKUP 2 /* this server is a backup server */
486#define SRV_MAPPORTS 4 /* this server uses mapped ports */
willy tarreau0174f312005-12-18 01:02:42 +0100487#define SRV_BIND_SRC 8 /* this server uses a specific source address */
Willy TARREAU3759f982006-03-01 22:44:17 +0100488#define SRV_CHECKED 16 /* this server needs to be checked */
willy tarreau0f7af912005-12-17 12:21:26 +0100489
willy tarreaudfece232006-05-02 00:19:57 +0200490/* function which act on servers need to return various errors */
491#define SRV_STATUS_OK 0 /* everything is OK. */
492#define SRV_STATUS_INTERNAL 1 /* other unrecoverable errors. */
493#define SRV_STATUS_NOSRV 2 /* no server is available */
494#define SRV_STATUS_FULL 3 /* the/all server(s) are saturated */
495#define SRV_STATUS_QUEUED 4 /* the/all server(s) are saturated but the connection was queued */
496
willy tarreaue39cd132005-12-17 13:00:18 +0100497/* what to do when a header matches a regex */
498#define ACT_ALLOW 0 /* allow the request */
499#define ACT_REPLACE 1 /* replace the matching header */
500#define ACT_REMOVE 2 /* remove the matching header */
501#define ACT_DENY 3 /* deny the request */
willy tarreau036e1ce2005-12-17 13:46:33 +0100502#define ACT_PASS 4 /* pass this header without allowing or denying the request */
willy tarreaue39cd132005-12-17 13:00:18 +0100503
willy tarreau9fe663a2005-12-17 13:02:59 +0100504/* configuration sections */
505#define CFG_NONE 0
506#define CFG_GLOBAL 1
507#define CFG_LISTEN 2
508
willy tarreaua1598082005-12-17 13:08:06 +0100509/* fields that need to be logged. They appear as flags in session->logs.logwait */
willy tarreau9fe663a2005-12-17 13:02:59 +0100510#define LW_DATE 1 /* date */
511#define LW_CLIP 2 /* CLient IP */
512#define LW_SVIP 4 /* SerVer IP */
513#define LW_SVID 8 /* server ID */
514#define LW_REQ 16 /* http REQuest */
515#define LW_RESP 32 /* http RESPonse */
516#define LW_PXIP 64 /* proxy IP */
517#define LW_PXID 128 /* proxy ID */
willy tarreaua1598082005-12-17 13:08:06 +0100518#define LW_BYTES 256 /* bytes read from server */
willy tarreau4302f492005-12-18 01:00:37 +0100519#define LW_COOKIE 512 /* captured cookie */
520#define LW_REQHDR 1024 /* request header(s) */
521#define LW_RSPHDR 2048 /* response header(s) */
willy tarreau9fe663a2005-12-17 13:02:59 +0100522
willy tarreau41310e72006-03-25 18:17:56 +0100523#define ERR_NONE 0 /* no error */
524#define ERR_RETRYABLE 1 /* retryable error, may be cumulated */
525#define ERR_FATAL 2 /* fatal error, may be cumulated */
526
willy tarreau0f7af912005-12-17 12:21:26 +0100527/*********************************************************************/
528
529#define LIST_HEAD(a) ((void *)(&(a)))
530
531/*********************************************************************/
532
willy tarreau9e138862006-05-14 23:06:28 +0200533/* describes a chunk of string */
534struct chunk {
535 char *str; /* beginning of the string itself. Might not be 0-terminated */
536 int len; /* size of the string from first to last char. <0 = uninit. */
537};
538
willy tarreau4302f492005-12-18 01:00:37 +0100539struct cap_hdr {
540 struct cap_hdr *next;
541 char *name; /* header name, case insensitive */
542 int namelen; /* length of the header name, to speed-up lookups */
543 int len; /* capture length, not including terminal zero */
544 int index; /* index in the output array */
545 void *pool; /* pool of pre-allocated memory area of (len+1) bytes */
546};
547
willy tarreau0f7af912005-12-17 12:21:26 +0100548struct hdr_exp {
willy tarreaue39cd132005-12-17 13:00:18 +0100549 struct hdr_exp *next;
550 regex_t *preg; /* expression to look for */
551 int action; /* ACT_ALLOW, ACT_REPLACE, ACT_REMOVE, ACT_DENY */
552 char *replace; /* expression to set instead */
willy tarreau0f7af912005-12-17 12:21:26 +0100553};
554
555struct buffer {
556 unsigned int l; /* data length */
557 char *r, *w, *h, *lr; /* read ptr, write ptr, last header ptr, last read */
willy tarreauef900ab2005-12-17 12:52:52 +0100558 char *rlim; /* read limit, used for header rewriting */
willy tarreaua1598082005-12-17 13:08:06 +0100559 unsigned long long total; /* total data read */
willy tarreau0f7af912005-12-17 12:21:26 +0100560 char data[BUFSIZE];
561};
562
willy tarreau18a957c2006-04-12 19:26:23 +0200563struct pendconn {
564 struct list list; /* chaining ... */
565 struct session *sess; /* the session waiting for a connection */
566 struct server *srv; /* the server we are waiting for */
567};
568
willy tarreau0f7af912005-12-17 12:21:26 +0100569struct server {
570 struct server *next;
willy tarreau5cbea6f2005-12-17 12:48:26 +0100571 int state; /* server state (SRV_*) */
572 int cklen; /* the len of the cookie, to speed up checks */
573 char *cookie; /* the id set in the cookie */
574 char *id; /* just for identification */
willy tarreau18a957c2006-04-12 19:26:23 +0200575 struct list pendconns; /* pending connections */
willy tarreaucb406512006-05-18 00:52:35 +0200576 int nbpend, nbpend_max; /* number of pending connections */
willy tarreau59a6cc22006-05-12 01:29:08 +0200577 struct task *queue_mgt; /* the task associated to the queue processing */
willy tarreau0f7af912005-12-17 12:21:26 +0100578 struct sockaddr_in addr; /* the address to connect to */
willy tarreau0174f312005-12-18 01:02:42 +0100579 struct sockaddr_in source_addr; /* the address to which we want to bind for connect() */
willy tarreaua41a8b42005-12-17 14:02:24 +0100580 short check_port; /* the port to use for the health checks */
willy tarreau5cbea6f2005-12-17 12:48:26 +0100581 int health; /* 0->rise-1 = bad; rise->rise+fall-1 = good */
willy tarreaue47c8d72005-12-17 12:55:52 +0100582 int rise, fall; /* time in iterations */
583 int inter; /* time in milliseconds */
willy tarreau5cbea6f2005-12-17 12:48:26 +0100584 int result; /* 0 = connect OK, -1 = connect KO */
585 int curfd; /* file desc used for current test, or -1 if not in test */
willy tarreaue3f023f2006-04-08 21:52:24 +0200586 unsigned char uweight, eweight; /* user-specified weight-1, and effective weight-1 */
willy tarreaucc1e2bd2006-04-10 20:32:43 +0200587 unsigned int wscore; /* weight score, used during srv map computation */
willy tarreaucb406512006-05-18 00:52:35 +0200588 int cur_sess, cur_sess_max; /* number of currently active sessions (including syn_sent) */
willy tarreaua647c702006-04-15 22:45:52 +0200589 unsigned int cum_sess; /* cumulated number of sessions really sent to this server */
willy tarreauf76e6ca2006-05-21 21:09:55 +0200590 unsigned int maxconn, minconn; /* max # of active sessions (0 = unlimited), min# for dynamic limit. */
willy tarreaucb406512006-05-18 00:52:35 +0200591 unsigned failed_checks, down_trans; /* failed checks and up-down transitions */
willy tarreaue3b30652006-05-21 16:23:22 +0200592 unsigned failed_conns, failed_resp; /* failed connect() and responses */
593 unsigned failed_secu; /* blocked responses because of security concerns */
willy tarreau535ae7a2005-12-17 12:58:00 +0100594 struct proxy *proxy; /* the proxy this server belongs to */
willy tarreau0f7af912005-12-17 12:21:26 +0100595};
596
willy tarreau5cbea6f2005-12-17 12:48:26 +0100597/* The base for all tasks */
willy tarreau0f7af912005-12-17 12:21:26 +0100598struct task {
599 struct task *next, *prev; /* chaining ... */
600 struct task *rqnext; /* chaining in run queue ... */
willy tarreau5cbea6f2005-12-17 12:48:26 +0100601 struct task *wq; /* the wait queue this task is in */
willy tarreau0f7af912005-12-17 12:21:26 +0100602 int state; /* task state : IDLE or RUNNING */
603 struct timeval expire; /* next expiration time for this task, use only for fast sorting */
willy tarreau5cbea6f2005-12-17 12:48:26 +0100604 int (*process)(struct task *t); /* the function which processes the task */
605 void *context; /* the task's context */
606};
607
608/* WARNING: if new fields are added, they must be initialized in event_accept() */
609struct session {
610 struct task *task; /* the task associated with this session */
willy tarreau0f7af912005-12-17 12:21:26 +0100611 /* application specific below */
612 struct timeval crexpire; /* expiration date for a client read */
613 struct timeval cwexpire; /* expiration date for a client write */
614 struct timeval srexpire; /* expiration date for a server read */
615 struct timeval swexpire; /* expiration date for a server write */
616 struct timeval cnexpire; /* expiration date for a connect */
617 char res_cr, res_cw, res_sr, res_sw;/* results of some events */
618 struct proxy *proxy; /* the proxy this socket belongs to */
619 int cli_fd; /* the client side fd */
620 int srv_fd; /* the server side fd */
621 int cli_state; /* state of the client side */
622 int srv_state; /* state of the server side */
623 int conn_retries; /* number of connect retries left */
willy tarreau5cbea6f2005-12-17 12:48:26 +0100624 int flags; /* some flags describing the session */
willy tarreau0f7af912005-12-17 12:21:26 +0100625 struct buffer *req; /* request buffer */
626 struct buffer *rep; /* response buffer */
willy tarreau8a86dbf2005-12-18 00:45:59 +0100627 struct sockaddr_storage cli_addr; /* the client address */
willy tarreau0f7af912005-12-17 12:21:26 +0100628 struct sockaddr_in srv_addr; /* the address to connect to */
willy tarreau5cbea6f2005-12-17 12:48:26 +0100629 struct server *srv; /* the server being used */
willy tarreau18a957c2006-04-12 19:26:23 +0200630 struct pendconn *pend_pos; /* if not NULL, points to the position in the pending queue */
willy tarreau4302f492005-12-18 01:00:37 +0100631 char **req_cap; /* array of captured request headers (may be NULL) */
632 char **rsp_cap; /* array of captured response headers (may be NULL) */
willy tarreau9e138862006-05-14 23:06:28 +0200633 struct chunk req_line; /* points to first line */
634 struct chunk auth_hdr; /* points to 'Authorization:' header */
willy tarreaua1598082005-12-17 13:08:06 +0100635 struct {
636 int logwait; /* log fields waiting to be collected : LW_* */
637 struct timeval tv_accept; /* date of the accept() (beginning of the session) */
638 long t_request; /* delay before the end of the request arrives, -1 if never occurs */
willy tarreauf32f5242006-05-02 22:54:52 +0200639 long t_queue; /* delay before the session gets out of the connect queue, -1 if never occurs */
willy tarreaua1598082005-12-17 13:08:06 +0100640 long t_connect; /* delay before the connect() to the server succeeds, -1 if never occurs */
641 long t_data; /* delay before the first data byte from the server ... */
642 unsigned long t_close; /* total session duration */
willy tarreau5e69b162006-05-12 19:49:37 +0200643 unsigned long srv_queue_size; /* number of sessions waiting for a connect slot on this server at accept() time (in direct assignment) */
644 unsigned long prx_queue_size; /* overall number of sessions waiting for a connect slot on this instance at accept() time */
willy tarreaua1598082005-12-17 13:08:06 +0100645 char *uri; /* first line if log needed, NULL otherwise */
willy tarreau8337c6b2005-12-17 13:41:01 +0100646 char *cli_cookie; /* cookie presented by the client, in capture mode */
647 char *srv_cookie; /* cookie presented by the server, in capture mode */
willy tarreaua1598082005-12-17 13:08:06 +0100648 int status; /* HTTP status from the server, negative if from proxy */
649 long long bytes; /* number of bytes transferred from the server */
650 } logs;
willy tarreau1f431b52006-05-21 14:46:15 +0200651 short int data_source; /* where to get the data we generate ourselves */
652 short int data_state; /* where to get the data we generate ourselves */
willy tarreaue0331262006-05-15 03:02:46 +0200653 union {
654 struct {
655 struct proxy *px;
656 struct server *sv;
willy tarreau1f431b52006-05-21 14:46:15 +0200657 short px_st, sv_st; /* DATA_ST_INIT or DATA_ST_DATA */
willy tarreaue0331262006-05-15 03:02:46 +0200658 } stats;
659 } data_ctx;
willy tarreau2f6ba652005-12-17 13:57:42 +0100660 unsigned int uniq_id; /* unique ID used for the traces */
willy tarreau0f7af912005-12-17 12:21:26 +0100661};
662
willy tarreaua41a8b42005-12-17 14:02:24 +0100663struct listener {
willy tarreau8a86dbf2005-12-18 00:45:59 +0100664 int fd; /* the listen socket */
665 struct sockaddr_storage addr; /* the address we listen to */
666 struct listener *next; /* next address or NULL */
willy tarreaua41a8b42005-12-17 14:02:24 +0100667};
willy tarreauf32f5242006-05-02 22:54:52 +0200668
willy tarreau0f7af912005-12-17 12:21:26 +0100669struct proxy {
willy tarreaua41a8b42005-12-17 14:02:24 +0100670 struct listener *listen; /* the listen addresses and sockets */
willy tarreaub1285d52005-12-18 01:20:14 +0100671 struct in_addr mon_net, mon_mask; /* don't forward connections from this net (network order) FIXME: should support IPv6 */
willy tarreau0f7af912005-12-17 12:21:26 +0100672 int state; /* proxy state */
willy tarreau0f7af912005-12-17 12:21:26 +0100673 struct sockaddr_in dispatch_addr; /* the default address to connect to */
willy tarreaucc1e2bd2006-04-10 20:32:43 +0200674 struct server *srv; /* known servers */
675 int srv_act, srv_bck; /* # of running servers */
676 int tot_wact, tot_wbck; /* total weights of active and backup servers */
677 struct server **srv_map; /* the server map used to apply weights */
678 int srv_map_sz; /* the size of the effective server map */
679 int srv_rr_idx; /* next server to be elected in round robin mode */
willy tarreau0f7af912005-12-17 12:21:26 +0100680 char *cookie_name; /* name of the cookie to look for */
willy tarreau12350152005-12-18 01:03:27 +0100681 int cookie_len; /* strlen(cookie_name), computed only once */
682 char *appsession_name; /* name of the cookie to look for */
683 int appsession_name_len; /* strlen(appsession_name), computed only once */
684 int appsession_len; /* length of the appsession cookie value to be used */
685 int appsession_timeout;
686 CHTbl htbl_proxy; /* Per Proxy hashtable */
willy tarreau8337c6b2005-12-17 13:41:01 +0100687 char *capture_name; /* beginning of the name of the cookie to capture */
688 int capture_namelen; /* length of the cookie name to match */
689 int capture_len; /* length of the string to be captured */
willy tarreau9e138862006-05-14 23:06:28 +0200690 struct uri_auth *uri_auth; /* if non-NULL, the (list of) per-URI authentications */
willy tarreau0f7af912005-12-17 12:21:26 +0100691 int clitimeout; /* client I/O timeout (in milliseconds) */
692 int srvtimeout; /* server I/O timeout (in milliseconds) */
693 int contimeout; /* connect timeout (in milliseconds) */
694 char *id; /* proxy id */
willy tarreaudfece232006-05-02 00:19:57 +0200695 struct list pendconns; /* pending connections with no server assigned yet */
willy tarreaucb406512006-05-18 00:52:35 +0200696 int nbpend, nbpend_max; /* number of pending connections with no server assigned yet */
willy tarreauf32f5242006-05-02 22:54:52 +0200697 int totpend; /* total number of pending connections on this instance (for stats) */
willy tarreauf76e6ca2006-05-21 21:09:55 +0200698 unsigned int nbconn, nbconn_max; /* # of active sessions */
willy tarreau14b4d432006-04-07 18:23:29 +0200699 unsigned int cum_conn; /* cumulated number of processed sessions */
willy tarreauf76e6ca2006-05-21 21:09:55 +0200700 unsigned int maxconn; /* max # of active sessions */
willy tarreaue3b30652006-05-21 16:23:22 +0200701 unsigned failed_conns, failed_resp; /* failed connect() and responses */
702 unsigned failed_secu; /* blocked responses because of security concerns */
willy tarreau5cbea6f2005-12-17 12:48:26 +0100703 int conn_retries; /* maximum number of connect retries */
willy tarreaub952e1d2005-12-18 01:31:20 +0100704 int options; /* PR_O_REDISP, PR_O_TRANSP, ... */
willy tarreau5cbea6f2005-12-17 12:48:26 +0100705 int mode; /* mode = PR_MODE_TCP, PR_MODE_HTTP or PR_MODE_HEALTH */
willy tarreaua1598082005-12-17 13:08:06 +0100706 struct sockaddr_in source_addr; /* the address to which we want to bind for connect() */
willy tarreau0f7af912005-12-17 12:21:26 +0100707 struct proxy *next;
708 struct sockaddr_in logsrv1, logsrv2; /* 2 syslog servers */
willy tarreau5dffb602005-12-18 01:15:23 +0100709 signed char logfac1, logfac2; /* log facility for both servers. -1 = disabled */
willy tarreau8337c6b2005-12-17 13:41:01 +0100710 int loglev1, loglev2; /* log level for each server, 7 by default */
willy tarreau9fe663a2005-12-17 13:02:59 +0100711 int to_log; /* things to be logged (LW_*) */
willy tarreau0f7af912005-12-17 12:21:26 +0100712 struct timeval stop_time; /* date to stop listening, when stopping != 0 */
willy tarreaue39cd132005-12-17 13:00:18 +0100713 int nb_reqadd, nb_rspadd;
714 struct hdr_exp *req_exp; /* regular expressions for request headers */
715 struct hdr_exp *rsp_exp; /* regular expressions for response headers */
willy tarreau4302f492005-12-18 01:00:37 +0100716 int nb_req_cap, nb_rsp_cap; /* # of headers to be captured */
717 struct cap_hdr *req_cap; /* chained list of request headers to be captured */
718 struct cap_hdr *rsp_cap; /* chained list of response headers to be captured */
719 void *req_cap_pool, *rsp_cap_pool; /* pools of pre-allocated char ** used to build the sessions */
willy tarreaue39cd132005-12-17 13:00:18 +0100720 char *req_add[MAX_NEWHDR], *rsp_add[MAX_NEWHDR]; /* headers to be added */
willy tarreau0f7af912005-12-17 12:21:26 +0100721 int grace; /* grace time after stop request */
willy tarreau2f6ba652005-12-17 13:57:42 +0100722 char *check_req; /* HTTP request to use if PR_O_HTTP_CHK is set, else NULL */
723 int check_len; /* Length of the HTTP request */
willy tarreau8337c6b2005-12-17 13:41:01 +0100724 struct {
725 char *msg400; /* message for error 400 */
726 int len400; /* message length for error 400 */
727 char *msg403; /* message for error 403 */
728 int len403; /* message length for error 403 */
729 char *msg408; /* message for error 408 */
730 int len408; /* message length for error 408 */
731 char *msg500; /* message for error 500 */
732 int len500; /* message length for error 500 */
733 char *msg502; /* message for error 502 */
734 int len502; /* message length for error 502 */
735 char *msg503; /* message for error 503 */
736 int len503; /* message length for error 503 */
737 char *msg504; /* message for error 504 */
738 int len504; /* message length for error 504 */
739 } errmsg;
willy tarreau0f7af912005-12-17 12:21:26 +0100740};
741
742/* info about one given fd */
743struct fdtab {
744 int (*read)(int fd); /* read function */
745 int (*write)(int fd); /* write function */
746 struct task *owner; /* the session (or proxy) associated with this fd */
747 int state; /* the state of this fd */
748};
749
750/*********************************************************************/
751
willy tarreaub952e1d2005-12-18 01:31:20 +0100752int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy TARREAU13032e72006-03-12 17:31:45 +0100753int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
willy tarreau0f7af912005-12-17 12:21:26 +0100754char *cfg_cfgfile = NULL; /* configuration file */
755char *progname = NULL; /* program name */
756int pid; /* current process id */
willy tarreau9fe663a2005-12-17 13:02:59 +0100757
758/* global options */
759static struct {
760 int uid;
761 int gid;
762 int nbproc;
763 int maxconn;
764 int maxsock; /* max # of sockets */
willy tarreaub1285d52005-12-18 01:20:14 +0100765 int rlimit_nofile; /* default ulimit-n value : 0=unset */
willy tarreau746e26b2006-03-25 11:14:35 +0100766 int rlimit_memmax; /* default ulimit-d in megs value : 0=unset */
willy tarreau9fe663a2005-12-17 13:02:59 +0100767 int mode;
768 char *chroot;
willy tarreaufe2c5c12005-12-17 14:14:34 +0100769 char *pidfile;
willy tarreau9fe663a2005-12-17 13:02:59 +0100770 int logfac1, logfac2;
willy tarreau8337c6b2005-12-17 13:41:01 +0100771 int loglev1, loglev2;
willy tarreau9fe663a2005-12-17 13:02:59 +0100772 struct sockaddr_in logsrv1, logsrv2;
773} global = {
774 logfac1 : -1,
775 logfac2 : -1,
willy tarreau8337c6b2005-12-17 13:41:01 +0100776 loglev1 : 7, /* max syslog level : debug */
777 loglev2 : 7,
willy tarreau9fe663a2005-12-17 13:02:59 +0100778 /* others NULL OK */
779};
780
willy tarreau0f7af912005-12-17 12:21:26 +0100781/*********************************************************************/
782
willy tarreau1c2ad212005-12-18 01:11:29 +0100783fd_set *StaticReadEvent,
willy tarreau0f7af912005-12-17 12:21:26 +0100784 *StaticWriteEvent;
785
willy tarreau64a3cc32005-12-18 01:13:11 +0100786int cfg_polling_mechanism = 0; /* POLL_USE_{SELECT|POLL|EPOLL} */
willy tarreauad90a0c2005-12-18 01:09:15 +0100787
willy tarreau0f7af912005-12-17 12:21:26 +0100788void **pool_session = NULL,
willy tarreau18a957c2006-04-12 19:26:23 +0200789 **pool_pendconn = NULL,
willy tarreau0f7af912005-12-17 12:21:26 +0100790 **pool_buffer = NULL,
791 **pool_fdtab = NULL,
willy tarreau9fe663a2005-12-17 13:02:59 +0100792 **pool_requri = NULL,
willy tarreau8337c6b2005-12-17 13:41:01 +0100793 **pool_task = NULL,
willy tarreau12350152005-12-18 01:03:27 +0100794 **pool_capture = NULL,
795 **pool_appsess = NULL;
willy tarreau0f7af912005-12-17 12:21:26 +0100796
797struct proxy *proxy = NULL; /* list of all existing proxies */
798struct fdtab *fdtab = NULL; /* array of all the file descriptors */
willy tarreau5cbea6f2005-12-17 12:48:26 +0100799struct task *rq = NULL; /* global run queue */
willy tarreau5e698ef2006-05-02 14:51:00 +0200800struct task wait_queue[2] = { /* global wait queue */
801 {
802 prev:LIST_HEAD(wait_queue[0]), /* expirable tasks */
803 next:LIST_HEAD(wait_queue[0]),
804 },
805 {
806 prev:LIST_HEAD(wait_queue[1]), /* non-expirable tasks */
807 next:LIST_HEAD(wait_queue[1]),
808 },
willy tarreau5cbea6f2005-12-17 12:48:26 +0100809};
willy tarreau0f7af912005-12-17 12:21:26 +0100810
willy tarreau0f7af912005-12-17 12:21:26 +0100811static int totalconn = 0; /* total # of terminated sessions */
812static int actconn = 0; /* # of active sessions */
813static int maxfd = 0; /* # of the highest fd + 1 */
814static int listeners = 0; /* # of listeners */
815static int stopping = 0; /* non zero means stopping in progress */
816static struct timeval now = {0,0}; /* the current date at any moment */
willy tarreaue0331262006-05-15 03:02:46 +0200817static struct timeval start_date; /* the process's start date */
willy tarreaua41a8b42005-12-17 14:02:24 +0100818static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
willy tarreau0f7af912005-12-17 12:21:26 +0100819
willy tarreau53e99702006-03-25 18:53:50 +0100820/* Here we store informations about the pids of the processes we may pause
821 * or kill. We will send them a signal every 10 ms until we can bind to all
822 * our ports. With 200 retries, that's about 2 seconds.
willy tarreau41310e72006-03-25 18:17:56 +0100823 */
willy tarreau53e99702006-03-25 18:53:50 +0100824#define MAX_START_RETRIES 200
willy tarreau41310e72006-03-25 18:17:56 +0100825static int nb_oldpids = 0;
826static int *oldpids = NULL;
827static int oldpids_sig; /* use USR1 or TERM */
828
willy tarreau08dedbe2005-12-18 01:13:48 +0100829#if defined(ENABLE_EPOLL)
830/* FIXME: this is dirty, but at the moment, there's no other solution to remove
831 * the old FDs from outside the loop. Perhaps we should export a global 'poll'
832 * structure with pointers to functions such as init_fd() and close_fd(), plus
833 * a private structure with several pointers to places such as below.
834 */
835
836static fd_set *PrevReadEvent = NULL, *PrevWriteEvent = NULL;
837#endif
838
willy tarreau0f7af912005-12-17 12:21:26 +0100839static regmatch_t pmatch[MAX_MATCH]; /* rm_so, rm_eo for regular expressions */
willy tarreau750a4722005-12-17 13:21:24 +0100840/* this is used to drain data, and as a temporary buffer for sprintf()... */
willy tarreau0f7af912005-12-17 12:21:26 +0100841static char trash[BUFSIZE];
842
willy tarreaudd07e972005-12-18 00:48:48 +0100843const int zero = 0;
844const int one = 1;
845
willy tarreau0f7af912005-12-17 12:21:26 +0100846/*
willy tarreau036e1ce2005-12-17 13:46:33 +0100847 * Syslog facilities and levels. Conforming to RFC3164.
willy tarreau0f7af912005-12-17 12:21:26 +0100848 */
849
850#define MAX_SYSLOG_LEN 1024
851#define NB_LOG_FACILITIES 24
852const char *log_facilities[NB_LOG_FACILITIES] = {
853 "kern", "user", "mail", "daemon",
854 "auth", "syslog", "lpr", "news",
855 "uucp", "cron", "auth2", "ftp",
856 "ntp", "audit", "alert", "cron2",
857 "local0", "local1", "local2", "local3",
858 "local4", "local5", "local6", "local7"
859};
860
861
862#define NB_LOG_LEVELS 8
863const char *log_levels[NB_LOG_LEVELS] = {
864 "emerg", "alert", "crit", "err",
865 "warning", "notice", "info", "debug"
866};
867
868#define SYSLOG_PORT 514
869
870const char *monthname[12] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
871 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
willy tarreau036e1ce2005-12-17 13:46:33 +0100872
willy tarreaub1285d52005-12-18 01:20:14 +0100873const char sess_term_cond[8] = "-cCsSPRI"; /* normal, CliTo, CliErr, SrvTo, SrvErr, PxErr, Resource, Internal */
willy tarreau078c79a2006-05-13 12:23:58 +0200874const char sess_fin_state[8] = "-RCHDLQ7"; /* cliRequest, srvConnect, srvHeader, Data, Last, Queue, unknown */
willy tarreau036e1ce2005-12-17 13:46:33 +0100875const char sess_cookie[4] = "NIDV"; /* No cookie, Invalid cookie, cookie for a Down server, Valid cookie */
876const char sess_set_cookie[8] = "N1I3PD5R"; /* No set-cookie, unknown, Set-Cookie Inserted, unknown,
877 Set-cookie seen and left unchanged (passive), Set-cookie Deleted,
878 unknown, Set-cookie Rewritten */
879
willy tarreau0f7af912005-12-17 12:21:26 +0100880#define MAX_HOSTNAME_LEN 32
881static char hostname[MAX_HOSTNAME_LEN] = "";
882
willy tarreau8337c6b2005-12-17 13:41:01 +0100883const char *HTTP_302 =
884 "HTTP/1.0 302 Found\r\n"
885 "Cache-Control: no-cache\r\n"
886 "Connection: close\r\n"
887 "Location: "; /* not terminated since it will be concatenated with the URL */
888
willy tarreauc1f47532005-12-18 01:08:26 +0100889/* same as 302 except that the browser MUST retry with the GET method */
890const char *HTTP_303 =
891 "HTTP/1.0 303 See Other\r\n"
892 "Cache-Control: no-cache\r\n"
893 "Connection: close\r\n"
894 "Location: "; /* not terminated since it will be concatenated with the URL */
895
willy tarreaua1598082005-12-17 13:08:06 +0100896const char *HTTP_400 =
897 "HTTP/1.0 400 Bad request\r\n"
willy tarreaue39cd132005-12-17 13:00:18 +0100898 "Cache-Control: no-cache\r\n"
899 "Connection: close\r\n"
900 "\r\n"
willy tarreau750a4722005-12-17 13:21:24 +0100901 "<html><body><h1>400 Bad request</h1>\nYour browser sent an invalid request.\n</body></html>\n";
willy tarreaue39cd132005-12-17 13:00:18 +0100902
willy tarreau9e138862006-05-14 23:06:28 +0200903/* Warning: this one is an sprintf() fmt string, with <realm> as its only argument */
904const char *HTTP_401_fmt =
905 "HTTP/1.0 401 Unauthorized\r\n"
906 "Cache-Control: no-cache\r\n"
907 "Connection: close\r\n"
908 "WWW-Authenticate: Basic realm=\"%s\"\r\n"
909 "\r\n"
910 "<html><body><h1>401 Unauthorized</h1>\nYou need a valid user and password to access this content.\n</body></html>\n";
911
willy tarreaua1598082005-12-17 13:08:06 +0100912const char *HTTP_403 =
913 "HTTP/1.0 403 Forbidden\r\n"
willy tarreaue39cd132005-12-17 13:00:18 +0100914 "Cache-Control: no-cache\r\n"
915 "Connection: close\r\n"
916 "\r\n"
willy tarreau750a4722005-12-17 13:21:24 +0100917 "<html><body><h1>403 Forbidden</h1>\nRequest forbidden by administrative rules.\n</body></html>\n";
918
willy tarreau8337c6b2005-12-17 13:41:01 +0100919const char *HTTP_408 =
920 "HTTP/1.0 408 Request Time-out\r\n"
921 "Cache-Control: no-cache\r\n"
922 "Connection: close\r\n"
923 "\r\n"
924 "<html><body><h1>408 Request Time-out</h1>\nYour browser didn't send a complete request in time.\n</body></html>\n";
925
willy tarreau750a4722005-12-17 13:21:24 +0100926const char *HTTP_500 =
927 "HTTP/1.0 500 Server Error\r\n"
928 "Cache-Control: no-cache\r\n"
929 "Connection: close\r\n"
930 "\r\n"
931 "<html><body><h1>500 Server Error</h1>\nAn internal server error occured.\n</body></html>\n";
willy tarreaue39cd132005-12-17 13:00:18 +0100932
933const char *HTTP_502 =
willy tarreau8337c6b2005-12-17 13:41:01 +0100934 "HTTP/1.0 502 Bad Gateway\r\n"
willy tarreaue39cd132005-12-17 13:00:18 +0100935 "Cache-Control: no-cache\r\n"
936 "Connection: close\r\n"
937 "\r\n"
willy tarreau8337c6b2005-12-17 13:41:01 +0100938 "<html><body><h1>502 Bad Gateway</h1>\nThe server returned an invalid or incomplete response.\n</body></html>\n";
939
940const char *HTTP_503 =
941 "HTTP/1.0 503 Service Unavailable\r\n"
942 "Cache-Control: no-cache\r\n"
943 "Connection: close\r\n"
944 "\r\n"
945 "<html><body><h1>503 Service Unavailable</h1>\nNo server is available to handle this request.\n</body></html>\n";
946
947const char *HTTP_504 =
948 "HTTP/1.0 504 Gateway Time-out\r\n"
949 "Cache-Control: no-cache\r\n"
950 "Connection: close\r\n"
951 "\r\n"
952 "<html><body><h1>504 Gateway Time-out</h1>\nThe server didn't respond in time.\n</body></html>\n";
willy tarreaue39cd132005-12-17 13:00:18 +0100953
willy tarreau0f7af912005-12-17 12:21:26 +0100954/*********************************************************************/
955/* statistics ******************************************************/
956/*********************************************************************/
957
willy tarreau750a4722005-12-17 13:21:24 +0100958#if STATTIME > 0
willy tarreau0f7af912005-12-17 12:21:26 +0100959static int stats_tsk_lsrch, stats_tsk_rsrch,
960 stats_tsk_good, stats_tsk_right, stats_tsk_left,
961 stats_tsk_new, stats_tsk_nsrch;
willy tarreau750a4722005-12-17 13:21:24 +0100962#endif
willy tarreau0f7af912005-12-17 12:21:26 +0100963
964
965/*********************************************************************/
willy tarreau750a4722005-12-17 13:21:24 +0100966/* debugging *******************************************************/
967/*********************************************************************/
968#ifdef DEBUG_FULL
969static char *cli_stnames[5] = {"HDR", "DAT", "SHR", "SHW", "CLS" };
willy tarreau3504a012006-05-14 23:20:07 +0200970static char *srv_stnames[7] = {"IDL", "CON", "HDR", "DAT", "SHR", "SHW", "CLS" };
willy tarreau750a4722005-12-17 13:21:24 +0100971#endif
972
973/*********************************************************************/
willy tarreau0f7af912005-12-17 12:21:26 +0100974/* function prototypes *********************************************/
975/*********************************************************************/
976
977int event_accept(int fd);
978int event_cli_read(int fd);
979int event_cli_write(int fd);
980int event_srv_read(int fd);
981int event_srv_write(int fd);
willy tarreau5cbea6f2005-12-17 12:48:26 +0100982int process_session(struct task *t);
willy tarreau0f7af912005-12-17 12:21:26 +0100983
willy tarreau12350152005-12-18 01:03:27 +0100984static int appsession_task_init(void);
985static int appsession_init(void);
986static int appsession_refresh(struct task *t);
987
willy tarreau0f7af912005-12-17 12:21:26 +0100988/*********************************************************************/
989/* general purpose functions ***************************************/
990/*********************************************************************/
991
992void display_version() {
993 printf("HA-Proxy version " HAPROXY_VERSION " " HAPROXY_DATE"\n");
willy tarreau726618c2006-01-29 22:42:06 +0100994 printf("Copyright 2000-2006 Willy Tarreau <w@w.ods.org>\n\n");
willy tarreau0f7af912005-12-17 12:21:26 +0100995}
996
997/*
998 * This function prints the command line usage and exits
999 */
1000void usage(char *name) {
1001 display_version();
1002 fprintf(stderr,
willy tarreau982249e2005-12-18 00:57:06 +01001003 "Usage : %s -f <cfgfile> [ -vdV"
willy tarreau0f7af912005-12-17 12:21:26 +01001004#if STATTIME > 0
1005 "sl"
1006#endif
willy tarreau746e26b2006-03-25 11:14:35 +01001007 "D ] [ -n <maxconn> ] [ -N <maxpconn> ]\n"
1008 " [ -p <pidfile> ] [ -m <max megs> ]\n"
willy tarreau0f7af912005-12-17 12:21:26 +01001009 " -v displays version\n"
willy tarreaubf8ff3d2006-03-25 19:47:03 +01001010 " -d enters debug mode ; -db only disables background mode.\n"
willy tarreau982249e2005-12-18 00:57:06 +01001011 " -V enters verbose mode (disables quiet mode)\n"
willy tarreau0f7af912005-12-17 12:21:26 +01001012#if STATTIME > 0
1013 " -s enables statistics output\n"
1014 " -l enables long statistics format\n"
1015#endif
willy tarreau5cbea6f2005-12-17 12:48:26 +01001016 " -D goes daemon ; implies -q\n"
1017 " -q quiet mode : don't display messages\n"
willy tarreaudd07e972005-12-18 00:48:48 +01001018 " -c check mode : only check config file and exit\n"
willy tarreau0f7af912005-12-17 12:21:26 +01001019 " -n sets the maximum total # of connections (%d)\n"
willy tarreau746e26b2006-03-25 11:14:35 +01001020 " -m limits the usable amount of memory (in MB)\n"
willy tarreaufe2c5c12005-12-17 14:14:34 +01001021 " -N sets the default, per-proxy maximum # of connections (%d)\n"
willy tarreauad90a0c2005-12-18 01:09:15 +01001022 " -p writes pids of all children to this file\n"
willy tarreau1c2ad212005-12-18 01:11:29 +01001023#if defined(ENABLE_EPOLL)
willy tarreau64a3cc32005-12-18 01:13:11 +01001024 " -de disables epoll() usage even when available\n"
willy tarreau1c2ad212005-12-18 01:11:29 +01001025#endif
1026#if defined(ENABLE_POLL)
willy tarreau64a3cc32005-12-18 01:13:11 +01001027 " -dp disables poll() usage even when available\n"
willy tarreau1c2ad212005-12-18 01:11:29 +01001028#endif
willy tarreau53e99702006-03-25 18:53:50 +01001029 " -sf/-st [pid ]* finishes/terminates old pids. Must be last arguments.\n"
willy tarreauad90a0c2005-12-18 01:09:15 +01001030 "\n",
willy tarreau9fe663a2005-12-17 13:02:59 +01001031 name, DEFAULT_MAXCONN, cfg_maxpconn);
willy tarreau0f7af912005-12-17 12:21:26 +01001032 exit(1);
1033}
1034
1035
1036/*
willy tarreaud0fb4652005-12-18 01:32:04 +01001037 * Displays the message on stderr with the date and pid. Overrides the quiet
1038 * mode during startup.
willy tarreau0f7af912005-12-17 12:21:26 +01001039 */
1040void Alert(char *fmt, ...) {
1041 va_list argp;
1042 struct timeval tv;
1043 struct tm *tm;
1044
willy tarreaud0fb4652005-12-18 01:32:04 +01001045 if (!(global.mode & MODE_QUIET) || (global.mode & (MODE_VERBOSE | MODE_STARTING))) {
willy tarreau5cbea6f2005-12-17 12:48:26 +01001046 va_start(argp, fmt);
willy tarreau0f7af912005-12-17 12:21:26 +01001047
willy tarreau5cbea6f2005-12-17 12:48:26 +01001048 gettimeofday(&tv, NULL);
1049 tm=localtime(&tv.tv_sec);
1050 fprintf(stderr, "[ALERT] %03d/%02d%02d%02d (%d) : ",
willy tarreaua1598082005-12-17 13:08:06 +01001051 tm->tm_yday, tm->tm_hour, tm->tm_min, tm->tm_sec, (int)getpid());
willy tarreau5cbea6f2005-12-17 12:48:26 +01001052 vfprintf(stderr, fmt, argp);
1053 fflush(stderr);
1054 va_end(argp);
1055 }
willy tarreau0f7af912005-12-17 12:21:26 +01001056}
1057
1058
1059/*
1060 * Displays the message on stderr with the date and pid.
1061 */
1062void Warning(char *fmt, ...) {
1063 va_list argp;
1064 struct timeval tv;
1065 struct tm *tm;
1066
willy tarreau982249e2005-12-18 00:57:06 +01001067 if (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE)) {
willy tarreau5cbea6f2005-12-17 12:48:26 +01001068 va_start(argp, fmt);
willy tarreau0f7af912005-12-17 12:21:26 +01001069
willy tarreau5cbea6f2005-12-17 12:48:26 +01001070 gettimeofday(&tv, NULL);
1071 tm=localtime(&tv.tv_sec);
1072 fprintf(stderr, "[WARNING] %03d/%02d%02d%02d (%d) : ",
willy tarreaua1598082005-12-17 13:08:06 +01001073 tm->tm_yday, tm->tm_hour, tm->tm_min, tm->tm_sec, (int)getpid());
willy tarreau5cbea6f2005-12-17 12:48:26 +01001074 vfprintf(stderr, fmt, argp);
1075 fflush(stderr);
1076 va_end(argp);
1077 }
1078}
1079
1080/*
1081 * Displays the message on <out> only if quiet mode is not set.
1082 */
1083void qfprintf(FILE *out, char *fmt, ...) {
1084 va_list argp;
1085
willy tarreau982249e2005-12-18 00:57:06 +01001086 if (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE)) {
willy tarreau5cbea6f2005-12-17 12:48:26 +01001087 va_start(argp, fmt);
1088 vfprintf(out, fmt, argp);
1089 fflush(out);
1090 va_end(argp);
1091 }
willy tarreau0f7af912005-12-17 12:21:26 +01001092}
1093
1094
1095/*
1096 * converts <str> to a struct sockaddr_in* which is locally allocated.
1097 * The format is "addr:port", where "addr" can be empty or "*" to indicate
1098 * INADDR_ANY.
1099 */
1100struct sockaddr_in *str2sa(char *str) {
1101 static struct sockaddr_in sa;
1102 char *c;
1103 int port;
1104
willy tarreaua1598082005-12-17 13:08:06 +01001105 memset(&sa, 0, sizeof(sa));
willy tarreau0f7af912005-12-17 12:21:26 +01001106 str=strdup(str);
1107
1108 if ((c=strrchr(str,':')) != NULL) {
1109 *c++=0;
1110 port=atol(c);
1111 }
1112 else
1113 port=0;
1114
1115 if (*str == '*' || *str == '\0') { /* INADDR_ANY */
1116 sa.sin_addr.s_addr = INADDR_ANY;
1117 }
willy tarreau8a86dbf2005-12-18 00:45:59 +01001118 else if (!inet_pton(AF_INET, str, &sa.sin_addr)) {
willy tarreau0f7af912005-12-17 12:21:26 +01001119 struct hostent *he;
1120
1121 if ((he = gethostbyname(str)) == NULL) {
willy tarreau036e1ce2005-12-17 13:46:33 +01001122 Alert("Invalid server name: '%s'\n", str);
willy tarreau0f7af912005-12-17 12:21:26 +01001123 }
1124 else
1125 sa.sin_addr = *(struct in_addr *) *(he->h_addr_list);
1126 }
1127 sa.sin_port=htons(port);
1128 sa.sin_family=AF_INET;
1129
1130 free(str);
1131 return &sa;
1132}
1133
willy tarreaub1285d52005-12-18 01:20:14 +01001134/*
1135 * converts <str> to a two struct in_addr* which are locally allocated.
1136 * The format is "addr[/mask]", where "addr" cannot be empty, and mask
1137 * is optionnal and either in the dotted or CIDR notation.
1138 * Note: "addr" can also be a hostname. Returns 1 if OK, 0 if error.
1139 */
1140int str2net(char *str, struct in_addr *addr, struct in_addr *mask) {
1141 char *c;
1142 unsigned long len;
1143
1144 memset(mask, 0, sizeof(*mask));
1145 memset(addr, 0, sizeof(*addr));
1146 str=strdup(str);
1147
1148 if ((c = strrchr(str, '/')) != NULL) {
1149 *c++ = 0;
1150 /* c points to the mask */
1151 if (strchr(c, '.') != NULL) { /* dotted notation */
1152 if (!inet_pton(AF_INET, c, mask))
1153 return 0;
1154 }
1155 else { /* mask length */
1156 char *err;
1157 len = strtol(c, &err, 10);
1158 if (!*c || (err && *err) || (unsigned)len > 32)
1159 return 0;
1160 if (len)
1161 mask->s_addr = htonl(0xFFFFFFFFUL << (32 - len));
1162 else
1163 mask->s_addr = 0;
1164 }
1165 }
1166 else {
1167 mask->s_addr = 0xFFFFFFFF;
1168 }
1169 if (!inet_pton(AF_INET, str, addr)) {
1170 struct hostent *he;
1171
1172 if ((he = gethostbyname(str)) == NULL) {
1173 return 0;
1174 }
1175 else
1176 *addr = *(struct in_addr *) *(he->h_addr_list);
1177 }
1178 free(str);
1179 return 1;
1180}
1181
willy tarreau9fe663a2005-12-17 13:02:59 +01001182
1183/*
willy tarreaua41a8b42005-12-17 14:02:24 +01001184 * converts <str> to a list of listeners which are dynamically allocated.
1185 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
1186 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
1187 * - <port> is a numerical port from 1 to 65535 ;
1188 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
1189 * This can be repeated as many times as necessary, separated by a coma.
1190 * The <tail> argument is a pointer to a current list which should be appended
1191 * to the tail of the new list. The pointer to the new list is returned.
1192 */
1193struct listener *str2listener(char *str, struct listener *tail) {
1194 struct listener *l;
1195 char *c, *next, *range, *dupstr;
1196 int port, end;
1197
1198 next = dupstr = strdup(str);
willy tarreau4302f492005-12-18 01:00:37 +01001199
willy tarreaua41a8b42005-12-17 14:02:24 +01001200 while (next && *next) {
willy tarreau8a86dbf2005-12-18 00:45:59 +01001201 struct sockaddr_storage ss;
1202
willy tarreaua41a8b42005-12-17 14:02:24 +01001203 str = next;
1204 /* 1) look for the end of the first address */
1205 if ((next = strrchr(str, ',')) != NULL) {
1206 *next++ = 0;
1207 }
1208
willy tarreau8a86dbf2005-12-18 00:45:59 +01001209 /* 2) look for the addr/port delimiter, it's the last colon. */
1210 if ((range = strrchr(str, ':')) == NULL) {
1211 Alert("Missing port number: '%s'\n", str);
willy tarreaud0fb4652005-12-18 01:32:04 +01001212 goto fail;
willy tarreau8a86dbf2005-12-18 00:45:59 +01001213 }
1214
1215 *range++ = 0;
1216
1217 if (strrchr(str, ':') != NULL) {
1218 /* IPv6 address contains ':' */
1219 memset(&ss, 0, sizeof(ss));
1220 ss.ss_family = AF_INET6;
1221
1222 if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in6 *)&ss)->sin6_addr)) {
1223 Alert("Invalid server address: '%s'\n", str);
willy tarreaud0fb4652005-12-18 01:32:04 +01001224 goto fail;
willy tarreau8a86dbf2005-12-18 00:45:59 +01001225 }
willy tarreaua41a8b42005-12-17 14:02:24 +01001226 }
1227 else {
willy tarreau8a86dbf2005-12-18 00:45:59 +01001228 memset(&ss, 0, sizeof(ss));
1229 ss.ss_family = AF_INET;
1230
1231 if (*str == '*' || *str == '\0') { /* INADDR_ANY */
1232 ((struct sockaddr_in *)&ss)->sin_addr.s_addr = INADDR_ANY;
1233 }
1234 else if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in *)&ss)->sin_addr)) {
1235 struct hostent *he;
1236
1237 if ((he = gethostbyname(str)) == NULL) {
1238 Alert("Invalid server name: '%s'\n", str);
willy tarreaud0fb4652005-12-18 01:32:04 +01001239 goto fail;
willy tarreau8a86dbf2005-12-18 00:45:59 +01001240 }
1241 else
1242 ((struct sockaddr_in *)&ss)->sin_addr =
1243 *(struct in_addr *) *(he->h_addr_list);
1244 }
1245 }
willy tarreaua41a8b42005-12-17 14:02:24 +01001246
1247 /* 3) look for the port-end delimiter */
1248 if ((c = strchr(range, '-')) != NULL) {
1249 *c++ = 0;
1250 end = atol(c);
1251 }
1252 else {
1253 end = atol(range);
1254 }
1255
willy tarreaud0fb4652005-12-18 01:32:04 +01001256 port = atol(range);
1257
1258 if (port < 1 || port > 65535) {
1259 Alert("Invalid port '%d' specified for address '%s'.\n", port, str);
1260 goto fail;
1261 }
1262
1263 if (end < 1 || end > 65535) {
1264 Alert("Invalid port '%d' specified for address '%s'.\n", end, str);
1265 goto fail;
1266 }
1267
1268 for (; port <= end; port++) {
willy tarreaua41a8b42005-12-17 14:02:24 +01001269 l = (struct listener *)calloc(1, sizeof(struct listener));
1270 l->next = tail;
1271 tail = l;
1272
willy tarreau41310e72006-03-25 18:17:56 +01001273 l->fd = -1;
willy tarreau8a86dbf2005-12-18 00:45:59 +01001274 l->addr = ss;
1275 if (ss.ss_family == AF_INET6)
1276 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
1277 else
1278 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
1279
willy tarreaua41a8b42005-12-17 14:02:24 +01001280 } /* end for(port) */
1281 } /* end while(next) */
1282 free(dupstr);
1283 return tail;
willy tarreaud0fb4652005-12-18 01:32:04 +01001284 fail:
1285 free(dupstr);
1286 return NULL;
willy tarreaua41a8b42005-12-17 14:02:24 +01001287}
1288
willy tarreau4302f492005-12-18 01:00:37 +01001289
1290#define FD_SETS_ARE_BITFIELDS
1291#ifdef FD_SETS_ARE_BITFIELDS
1292/*
1293 * This map is used with all the FD_* macros to check whether a particular bit
1294 * is set or not. Each bit represents an ACSII code. FD_SET() sets those bytes
1295 * which should be encoded. When FD_ISSET() returns non-zero, it means that the
1296 * byte should be encoded. Be careful to always pass bytes from 0 to 255
1297 * exclusively to the macros.
1298 */
1299fd_set hdr_encode_map[(sizeof(fd_set) > (256/8)) ? 1 : ((256/8) / sizeof(fd_set))];
1300fd_set url_encode_map[(sizeof(fd_set) > (256/8)) ? 1 : ((256/8) / sizeof(fd_set))];
1301
1302#else
1303#error "Check if your OS uses bitfields for fd_sets"
1304#endif
1305
1306/* will try to encode the string <string> replacing all characters tagged in
1307 * <map> with the hexadecimal representation of their ASCII-code (2 digits)
1308 * prefixed by <escape>, and will store the result between <start> (included
1309 *) and <stop> (excluded), and will always terminate the string with a '\0'
1310 * before <stop>. The position of the '\0' is returned if the conversion
1311 * completes. If bytes are missing between <start> and <stop>, then the
1312 * conversion will be incomplete and truncated. If <stop> <= <start>, the '\0'
1313 * cannot even be stored so we return <start> without writing the 0.
1314 * The input string must also be zero-terminated.
1315 */
1316char hextab[16] = "0123456789ABCDEF";
1317char *encode_string(char *start, char *stop,
1318 const char escape, const fd_set *map,
1319 const char *string)
1320{
1321 if (start < stop) {
1322 stop--; /* reserve one byte for the final '\0' */
1323 while (start < stop && *string != 0) {
1324 if (!FD_ISSET((unsigned char)(*string), map))
1325 *start++ = *string;
1326 else {
1327 if (start + 3 >= stop)
1328 break;
1329 *start++ = escape;
1330 *start++ = hextab[(*string >> 4) & 15];
1331 *start++ = hextab[*string & 15];
1332 }
1333 string++;
1334 }
1335 *start = '\0';
1336 }
1337 return start;
1338}
willy tarreaua41a8b42005-12-17 14:02:24 +01001339
1340/*
willy tarreau9fe663a2005-12-17 13:02:59 +01001341 * This function sends a syslog message to both log servers of a proxy,
1342 * or to global log servers if the proxy is NULL.
1343 * It also tries not to waste too much time computing the message header.
1344 * It doesn't care about errors nor does it report them.
willy tarreau9fe663a2005-12-17 13:02:59 +01001345 */
1346void send_log(struct proxy *p, int level, char *message, ...) {
1347 static int logfd = -1; /* syslog UDP socket */
1348 static long tvsec = -1; /* to force the string to be initialized */
1349 struct timeval tv;
1350 va_list argp;
1351 static char logmsg[MAX_SYSLOG_LEN];
1352 static char *dataptr = NULL;
1353 int fac_level;
1354 int hdr_len, data_len;
1355 struct sockaddr_in *sa[2];
willy tarreau8337c6b2005-12-17 13:41:01 +01001356 int facilities[2], loglevel[2];
willy tarreau9fe663a2005-12-17 13:02:59 +01001357 int nbloggers = 0;
1358 char *log_ptr;
1359
1360 if (logfd < 0) {
1361 if ((logfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
1362 return;
1363 }
1364
1365 if (level < 0 || progname == NULL || message == NULL)
1366 return;
1367
1368 gettimeofday(&tv, NULL);
willy tarreauc29948c2005-12-17 13:10:27 +01001369 if (tv.tv_sec != tvsec || dataptr == NULL) {
willy tarreau9fe663a2005-12-17 13:02:59 +01001370 /* this string is rebuild only once a second */
1371 struct tm *tm = localtime(&tv.tv_sec);
1372 tvsec = tv.tv_sec;
1373
willy tarreauc29948c2005-12-17 13:10:27 +01001374 hdr_len = snprintf(logmsg, sizeof(logmsg),
1375 "<<<<>%s %2d %02d:%02d:%02d %s[%d]: ",
1376 monthname[tm->tm_mon],
1377 tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec,
1378 progname, pid);
1379 /* WARNING: depending upon implementations, snprintf may return
1380 * either -1 or the number of bytes that would be needed to store
1381 * the total message. In both cases, we must adjust it.
willy tarreau9fe663a2005-12-17 13:02:59 +01001382 */
willy tarreauc29948c2005-12-17 13:10:27 +01001383 if (hdr_len < 0 || hdr_len > sizeof(logmsg))
1384 hdr_len = sizeof(logmsg);
1385
1386 dataptr = logmsg + hdr_len;
willy tarreau9fe663a2005-12-17 13:02:59 +01001387 }
1388
1389 va_start(argp, message);
1390 data_len = vsnprintf(dataptr, logmsg + sizeof(logmsg) - dataptr, message, argp);
willy tarreauc29948c2005-12-17 13:10:27 +01001391 if (data_len < 0 || data_len > (logmsg + sizeof(logmsg) - dataptr))
1392 data_len = logmsg + sizeof(logmsg) - dataptr;
willy tarreau9fe663a2005-12-17 13:02:59 +01001393 va_end(argp);
willy tarreauc29948c2005-12-17 13:10:27 +01001394 dataptr[data_len - 1] = '\n'; /* force a break on ultra-long lines */
willy tarreau9fe663a2005-12-17 13:02:59 +01001395
1396 if (p == NULL) {
1397 if (global.logfac1 >= 0) {
1398 sa[nbloggers] = &global.logsrv1;
1399 facilities[nbloggers] = global.logfac1;
willy tarreau8337c6b2005-12-17 13:41:01 +01001400 loglevel[nbloggers] = global.loglev1;
willy tarreau9fe663a2005-12-17 13:02:59 +01001401 nbloggers++;
1402 }
1403 if (global.logfac2 >= 0) {
1404 sa[nbloggers] = &global.logsrv2;
1405 facilities[nbloggers] = global.logfac2;
willy tarreau8337c6b2005-12-17 13:41:01 +01001406 loglevel[nbloggers] = global.loglev2;
willy tarreau9fe663a2005-12-17 13:02:59 +01001407 nbloggers++;
1408 }
1409 } else {
1410 if (p->logfac1 >= 0) {
1411 sa[nbloggers] = &p->logsrv1;
1412 facilities[nbloggers] = p->logfac1;
willy tarreau8337c6b2005-12-17 13:41:01 +01001413 loglevel[nbloggers] = p->loglev1;
willy tarreau9fe663a2005-12-17 13:02:59 +01001414 nbloggers++;
1415 }
1416 if (p->logfac2 >= 0) {
1417 sa[nbloggers] = &p->logsrv2;
1418 facilities[nbloggers] = p->logfac2;
willy tarreau8337c6b2005-12-17 13:41:01 +01001419 loglevel[nbloggers] = p->loglev2;
willy tarreau9fe663a2005-12-17 13:02:59 +01001420 nbloggers++;
1421 }
1422 }
1423
1424 while (nbloggers-- > 0) {
willy tarreau8337c6b2005-12-17 13:41:01 +01001425 /* we can filter the level of the messages that are sent to each logger */
1426 if (level > loglevel[nbloggers])
1427 continue;
1428
willy tarreauc29948c2005-12-17 13:10:27 +01001429 /* For each target, we may have a different facility.
1430 * We can also have a different log level for each message.
1431 * This induces variations in the message header length.
1432 * Since we don't want to recompute it each time, nor copy it every
1433 * time, we only change the facility in the pre-computed header,
1434 * and we change the pointer to the header accordingly.
1435 */
willy tarreau9fe663a2005-12-17 13:02:59 +01001436 fac_level = (facilities[nbloggers] << 3) + level;
1437 log_ptr = logmsg + 3; /* last digit of the log level */
1438 do {
1439 *log_ptr = '0' + fac_level % 10;
1440 fac_level /= 10;
1441 log_ptr--;
1442 } while (fac_level && log_ptr > logmsg);
1443 *log_ptr = '<';
willy tarreau9fe663a2005-12-17 13:02:59 +01001444
willy tarreauc29948c2005-12-17 13:10:27 +01001445 /* the total syslog message now starts at logptr, for dataptr+data_len-logptr */
willy tarreau9fe663a2005-12-17 13:02:59 +01001446
1447#ifndef MSG_NOSIGNAL
willy tarreauc29948c2005-12-17 13:10:27 +01001448 sendto(logfd, log_ptr, dataptr + data_len - log_ptr, MSG_DONTWAIT,
willy tarreau9fe663a2005-12-17 13:02:59 +01001449 (struct sockaddr *)sa[nbloggers], sizeof(**sa));
1450#else
willy tarreauc29948c2005-12-17 13:10:27 +01001451 sendto(logfd, log_ptr, dataptr + data_len - log_ptr, MSG_DONTWAIT | MSG_NOSIGNAL,
willy tarreau9fe663a2005-12-17 13:02:59 +01001452 (struct sockaddr *)sa[nbloggers], sizeof(**sa));
1453#endif
1454 }
willy tarreau0f7af912005-12-17 12:21:26 +01001455}
1456
1457
1458/* sets <tv> to the current time */
1459static inline struct timeval *tv_now(struct timeval *tv) {
1460 if (tv)
1461 gettimeofday(tv, NULL);
1462 return tv;
1463}
1464
1465/*
1466 * adds <ms> ms to <from>, set the result to <tv> and returns a pointer <tv>
1467 */
willy tarreaudab722b2006-05-04 19:23:38 +02001468static struct timeval *tv_delayfrom(struct timeval *tv, struct timeval *from, int ms) {
willy tarreau0f7af912005-12-17 12:21:26 +01001469 if (!tv || !from)
1470 return NULL;
1471 tv->tv_usec = from->tv_usec + (ms%1000)*1000;
1472 tv->tv_sec = from->tv_sec + (ms/1000);
1473 while (tv->tv_usec >= 1000000) {
1474 tv->tv_usec -= 1000000;
1475 tv->tv_sec++;
1476 }
1477 return tv;
1478}
1479
1480/*
1481 * compares <tv1> and <tv2> : returns 0 if equal, -1 if tv1 < tv2, 1 if tv1 > tv2
willy tarreaub952e1d2005-12-18 01:31:20 +01001482 * Must not be used when either argument is eternity. Use tv_cmp2() for that.
willy tarreau0f7af912005-12-17 12:21:26 +01001483 */
1484static inline int tv_cmp(struct timeval *tv1, struct timeval *tv2) {
willy tarreau750a4722005-12-17 13:21:24 +01001485 if (tv1->tv_sec < tv2->tv_sec)
willy tarreau0f7af912005-12-17 12:21:26 +01001486 return -1;
willy tarreau750a4722005-12-17 13:21:24 +01001487 else if (tv1->tv_sec > tv2->tv_sec)
willy tarreau0f7af912005-12-17 12:21:26 +01001488 return 1;
1489 else if (tv1->tv_usec < tv2->tv_usec)
1490 return -1;
willy tarreau750a4722005-12-17 13:21:24 +01001491 else if (tv1->tv_usec > tv2->tv_usec)
1492 return 1;
willy tarreau0f7af912005-12-17 12:21:26 +01001493 else
1494 return 0;
1495}
1496
1497/*
1498 * returns the absolute difference, in ms, between tv1 and tv2
willy tarreaub952e1d2005-12-18 01:31:20 +01001499 * Must not be used when either argument is eternity.
willy tarreau0f7af912005-12-17 12:21:26 +01001500 */
1501unsigned long tv_delta(struct timeval *tv1, struct timeval *tv2) {
1502 int cmp;
1503 unsigned long ret;
1504
1505
willy tarreauef900ab2005-12-17 12:52:52 +01001506 cmp = tv_cmp(tv1, tv2);
willy tarreau0f7af912005-12-17 12:21:26 +01001507 if (!cmp)
1508 return 0; /* same dates, null diff */
willy tarreau750a4722005-12-17 13:21:24 +01001509 else if (cmp < 0) {
willy tarreauef900ab2005-12-17 12:52:52 +01001510 struct timeval *tmp = tv1;
1511 tv1 = tv2;
1512 tv2 = tmp;
willy tarreau0f7af912005-12-17 12:21:26 +01001513 }
willy tarreauef900ab2005-12-17 12:52:52 +01001514 ret = (tv1->tv_sec - tv2->tv_sec) * 1000;
willy tarreau0f7af912005-12-17 12:21:26 +01001515 if (tv1->tv_usec > tv2->tv_usec)
willy tarreauef900ab2005-12-17 12:52:52 +01001516 ret += (tv1->tv_usec - tv2->tv_usec) / 1000;
willy tarreau0f7af912005-12-17 12:21:26 +01001517 else
willy tarreauef900ab2005-12-17 12:52:52 +01001518 ret -= (tv2->tv_usec - tv1->tv_usec) / 1000;
willy tarreau0f7af912005-12-17 12:21:26 +01001519 return (unsigned long) ret;
1520}
1521
1522/*
willy tarreau750a4722005-12-17 13:21:24 +01001523 * returns the difference, in ms, between tv1 and tv2
willy tarreaub952e1d2005-12-18 01:31:20 +01001524 * Must not be used when either argument is eternity.
willy tarreau750a4722005-12-17 13:21:24 +01001525 */
1526static inline unsigned long tv_diff(struct timeval *tv1, struct timeval *tv2) {
1527 unsigned long ret;
1528
willy tarreau6e682ce2005-12-17 13:26:49 +01001529 ret = (tv2->tv_sec - tv1->tv_sec) * 1000;
1530 if (tv2->tv_usec > tv1->tv_usec)
1531 ret += (tv2->tv_usec - tv1->tv_usec) / 1000;
willy tarreau750a4722005-12-17 13:21:24 +01001532 else
willy tarreau6e682ce2005-12-17 13:26:49 +01001533 ret -= (tv1->tv_usec - tv2->tv_usec) / 1000;
willy tarreau750a4722005-12-17 13:21:24 +01001534 return (unsigned long) ret;
1535}
1536
1537/*
willy tarreau0f7af912005-12-17 12:21:26 +01001538 * compares <tv1> and <tv2> modulo 1ms: returns 0 if equal, -1 if tv1 < tv2, 1 if tv1 > tv2
willy tarreaub952e1d2005-12-18 01:31:20 +01001539 * Must not be used when either argument is eternity. Use tv_cmp2_ms() for that.
willy tarreau0f7af912005-12-17 12:21:26 +01001540 */
willy tarreaudab722b2006-05-04 19:23:38 +02001541static int tv_cmp_ms(struct timeval *tv1, struct timeval *tv2) {
willy tarreauefae1842005-12-17 12:51:03 +01001542 if (tv1->tv_sec == tv2->tv_sec) {
Willy TARREAUc9a64392006-03-01 22:30:20 +01001543 if (tv2->tv_usec >= tv1->tv_usec + 1000)
willy tarreauefae1842005-12-17 12:51:03 +01001544 return -1;
Willy TARREAUc9a64392006-03-01 22:30:20 +01001545 else if (tv1->tv_usec >= tv2->tv_usec + 1000)
willy tarreau750a4722005-12-17 13:21:24 +01001546 return 1;
willy tarreauefae1842005-12-17 12:51:03 +01001547 else
1548 return 0;
1549 }
willy tarreau0f7af912005-12-17 12:21:26 +01001550 else if ((tv2->tv_sec > tv1->tv_sec + 1) ||
Willy TARREAUc9a64392006-03-01 22:30:20 +01001551 ((tv2->tv_sec == tv1->tv_sec + 1) && (tv2->tv_usec + 1000000 >= tv1->tv_usec + 1000)))
willy tarreau0f7af912005-12-17 12:21:26 +01001552 return -1;
willy tarreau750a4722005-12-17 13:21:24 +01001553 else if ((tv1->tv_sec > tv2->tv_sec + 1) ||
Willy TARREAUc9a64392006-03-01 22:30:20 +01001554 ((tv1->tv_sec == tv2->tv_sec + 1) && (tv1->tv_usec + 1000000 >= tv2->tv_usec + 1000)))
willy tarreau750a4722005-12-17 13:21:24 +01001555 return 1;
willy tarreau0f7af912005-12-17 12:21:26 +01001556 else
1557 return 0;
1558}
1559
1560/*
1561 * returns the remaining time between tv1=now and event=tv2
1562 * if tv2 is passed, 0 is returned.
willy tarreaub952e1d2005-12-18 01:31:20 +01001563 * Must not be used when either argument is eternity.
willy tarreau0f7af912005-12-17 12:21:26 +01001564 */
1565static inline unsigned long tv_remain(struct timeval *tv1, struct timeval *tv2) {
1566 unsigned long ret;
1567
willy tarreau0f7af912005-12-17 12:21:26 +01001568 if (tv_cmp_ms(tv1, tv2) >= 0)
1569 return 0; /* event elapsed */
1570
willy tarreauef900ab2005-12-17 12:52:52 +01001571 ret = (tv2->tv_sec - tv1->tv_sec) * 1000;
willy tarreau0f7af912005-12-17 12:21:26 +01001572 if (tv2->tv_usec > tv1->tv_usec)
willy tarreauef900ab2005-12-17 12:52:52 +01001573 ret += (tv2->tv_usec - tv1->tv_usec) / 1000;
willy tarreau0f7af912005-12-17 12:21:26 +01001574 else
willy tarreauef900ab2005-12-17 12:52:52 +01001575 ret -= (tv1->tv_usec - tv2->tv_usec) / 1000;
willy tarreau0f7af912005-12-17 12:21:26 +01001576 return (unsigned long) ret;
1577}
1578
1579
1580/*
1581 * zeroes a struct timeval
1582 */
1583
1584static inline struct timeval *tv_eternity(struct timeval *tv) {
1585 tv->tv_sec = tv->tv_usec = 0;
1586 return tv;
1587}
1588
1589/*
1590 * returns 1 if tv is null, else 0
1591 */
1592static inline int tv_iseternity(struct timeval *tv) {
1593 if (tv->tv_sec == 0 && tv->tv_usec == 0)
1594 return 1;
1595 else
1596 return 0;
1597}
1598
1599/*
1600 * compares <tv1> and <tv2> : returns 0 if equal, -1 if tv1 < tv2, 1 if tv1 > tv2,
1601 * considering that 0 is the eternity.
1602 */
willy tarreaudab722b2006-05-04 19:23:38 +02001603static int tv_cmp2(struct timeval *tv1, struct timeval *tv2) {
willy tarreau0f7af912005-12-17 12:21:26 +01001604 if (tv_iseternity(tv1))
1605 if (tv_iseternity(tv2))
1606 return 0; /* same */
1607 else
1608 return 1; /* tv1 later than tv2 */
1609 else if (tv_iseternity(tv2))
1610 return -1; /* tv2 later than tv1 */
1611
1612 if (tv1->tv_sec > tv2->tv_sec)
1613 return 1;
1614 else if (tv1->tv_sec < tv2->tv_sec)
1615 return -1;
1616 else if (tv1->tv_usec > tv2->tv_usec)
1617 return 1;
1618 else if (tv1->tv_usec < tv2->tv_usec)
1619 return -1;
1620 else
1621 return 0;
1622}
1623
1624/*
1625 * compares <tv1> and <tv2> modulo 1 ms: returns 0 if equal, -1 if tv1 < tv2, 1 if tv1 > tv2,
1626 * considering that 0 is the eternity.
1627 */
willy tarreaudab722b2006-05-04 19:23:38 +02001628static int tv_cmp2_ms(struct timeval *tv1, struct timeval *tv2) {
willy tarreau0f7af912005-12-17 12:21:26 +01001629 if (tv_iseternity(tv1))
1630 if (tv_iseternity(tv2))
1631 return 0; /* same */
1632 else
1633 return 1; /* tv1 later than tv2 */
1634 else if (tv_iseternity(tv2))
1635 return -1; /* tv2 later than tv1 */
1636
willy tarreauefae1842005-12-17 12:51:03 +01001637 if (tv1->tv_sec == tv2->tv_sec) {
Willy TARREAUc9a64392006-03-01 22:30:20 +01001638 if (tv1->tv_usec >= tv2->tv_usec + 1000)
willy tarreauefae1842005-12-17 12:51:03 +01001639 return 1;
Willy TARREAUc9a64392006-03-01 22:30:20 +01001640 else if (tv2->tv_usec >= tv1->tv_usec + 1000)
willy tarreauefae1842005-12-17 12:51:03 +01001641 return -1;
1642 else
1643 return 0;
1644 }
1645 else if ((tv1->tv_sec > tv2->tv_sec + 1) ||
Willy TARREAUc9a64392006-03-01 22:30:20 +01001646 ((tv1->tv_sec == tv2->tv_sec + 1) && (tv1->tv_usec + 1000000 >= tv2->tv_usec + 1000)))
willy tarreau0f7af912005-12-17 12:21:26 +01001647 return 1;
1648 else if ((tv2->tv_sec > tv1->tv_sec + 1) ||
Willy TARREAUc9a64392006-03-01 22:30:20 +01001649 ((tv2->tv_sec == tv1->tv_sec + 1) && (tv2->tv_usec + 1000000 >= tv1->tv_usec + 1000)))
willy tarreau0f7af912005-12-17 12:21:26 +01001650 return -1;
1651 else
1652 return 0;
1653}
1654
1655/*
willy tarreaub952e1d2005-12-18 01:31:20 +01001656 * returns the remaining time between tv1=now and event=tv2
1657 * if tv2 is passed, 0 is returned.
1658 * Returns TIME_ETERNITY if tv2 is eternity.
1659 */
willy tarreaudab722b2006-05-04 19:23:38 +02001660static unsigned long tv_remain2(struct timeval *tv1, struct timeval *tv2) {
willy tarreaub952e1d2005-12-18 01:31:20 +01001661 unsigned long ret;
1662
1663 if (tv_iseternity(tv2))
1664 return TIME_ETERNITY;
1665
1666 if (tv_cmp_ms(tv1, tv2) >= 0)
1667 return 0; /* event elapsed */
1668
1669 ret = (tv2->tv_sec - tv1->tv_sec) * 1000;
1670 if (tv2->tv_usec > tv1->tv_usec)
1671 ret += (tv2->tv_usec - tv1->tv_usec) / 1000;
1672 else
1673 ret -= (tv1->tv_usec - tv2->tv_usec) / 1000;
1674 return (unsigned long) ret;
1675}
1676
1677/*
willy tarreau0f7af912005-12-17 12:21:26 +01001678 * returns the first event between tv1 and tv2 into tvmin.
1679 * a zero tv is ignored. tvmin is returned.
1680 */
1681static inline struct timeval *tv_min(struct timeval *tvmin,
1682 struct timeval *tv1, struct timeval *tv2) {
1683
1684 if (tv_cmp2(tv1, tv2) <= 0)
1685 *tvmin = *tv1;
1686 else
1687 *tvmin = *tv2;
1688
1689 return tvmin;
1690}
1691
1692
1693
1694/***********************************************************/
1695/* fd management ***************************************/
1696/***********************************************************/
1697
1698
1699
willy tarreau5cbea6f2005-12-17 12:48:26 +01001700/* Deletes an FD from the fdsets, and recomputes the maxfd limit.
1701 * The file descriptor is also closed.
1702 */
willy tarreaudab722b2006-05-04 19:23:38 +02001703static void fd_delete(int fd) {
willy tarreau0f7af912005-12-17 12:21:26 +01001704 FD_CLR(fd, StaticReadEvent);
1705 FD_CLR(fd, StaticWriteEvent);
willy tarreau08dedbe2005-12-18 01:13:48 +01001706#if defined(ENABLE_EPOLL)
1707 if (PrevReadEvent) {
1708 FD_CLR(fd, PrevReadEvent);
1709 FD_CLR(fd, PrevWriteEvent);
1710 }
1711#endif
1712
willy tarreau5cbea6f2005-12-17 12:48:26 +01001713 close(fd);
1714 fdtab[fd].state = FD_STCLOSE;
willy tarreau0f7af912005-12-17 12:21:26 +01001715
1716 while ((maxfd-1 >= 0) && (fdtab[maxfd-1].state == FD_STCLOSE))
1717 maxfd--;
1718}
1719
1720/* recomputes the maxfd limit from the fd */
1721static inline void fd_insert(int fd) {
1722 if (fd+1 > maxfd)
1723 maxfd = fd+1;
1724}
1725
1726/*************************************************************/
1727/* task management ***************************************/
1728/*************************************************************/
1729
willy tarreau5cbea6f2005-12-17 12:48:26 +01001730/* puts the task <t> in run queue <q>, and returns <t> */
1731static inline struct task *task_wakeup(struct task **q, struct task *t) {
1732 if (t->state == TASK_RUNNING)
1733 return t;
willy tarreau0f7af912005-12-17 12:21:26 +01001734 else {
willy tarreau5cbea6f2005-12-17 12:48:26 +01001735 t->rqnext = *q;
1736 t->state = TASK_RUNNING;
1737 return *q = t;
willy tarreau0f7af912005-12-17 12:21:26 +01001738 }
1739}
1740
willy tarreau5cbea6f2005-12-17 12:48:26 +01001741/* removes the task <t> from the queue <q>
1742 * <s> MUST be <q>'s first task.
willy tarreau0f7af912005-12-17 12:21:26 +01001743 * set the run queue to point to the next one, and return it
1744 */
willy tarreau5cbea6f2005-12-17 12:48:26 +01001745static inline struct task *task_sleep(struct task **q, struct task *t) {
1746 if (t->state == TASK_RUNNING) {
1747 *q = t->rqnext;
1748 t->state = TASK_IDLE; /* tell that s has left the run queue */
willy tarreau0f7af912005-12-17 12:21:26 +01001749 }
willy tarreau5cbea6f2005-12-17 12:48:26 +01001750 return *q; /* return next running task */
willy tarreau0f7af912005-12-17 12:21:26 +01001751}
1752
1753/*
willy tarreau5cbea6f2005-12-17 12:48:26 +01001754 * removes the task <t> from its wait queue. It must have already been removed
willy tarreau0f7af912005-12-17 12:21:26 +01001755 * from the run queue. A pointer to the task itself is returned.
1756 */
willy tarreau5cbea6f2005-12-17 12:48:26 +01001757static inline struct task *task_delete(struct task *t) {
1758 t->prev->next = t->next;
1759 t->next->prev = t->prev;
1760 return t;
willy tarreau0f7af912005-12-17 12:21:26 +01001761}
1762
1763/*
willy tarreau5cbea6f2005-12-17 12:48:26 +01001764 * frees a task. Its context must have been freed since it will be lost.
willy tarreau0f7af912005-12-17 12:21:26 +01001765 */
1766static inline void task_free(struct task *t) {
willy tarreau5cbea6f2005-12-17 12:48:26 +01001767 pool_free(task, t);
willy tarreau0f7af912005-12-17 12:21:26 +01001768}
1769
willy tarreau5cbea6f2005-12-17 12:48:26 +01001770/* inserts <task> into its assigned wait queue, where it may already be. In this case, it
willy tarreau0f7af912005-12-17 12:21:26 +01001771 * may be only moved or left where it was, depending on its timing requirements.
1772 * <task> is returned.
1773 */
willy tarreau5cbea6f2005-12-17 12:48:26 +01001774struct task *task_queue(struct task *task) {
1775 struct task *list = task->wq;
willy tarreau0f7af912005-12-17 12:21:26 +01001776 struct task *start_from;
1777
willy tarreau5e698ef2006-05-02 14:51:00 +02001778 /* This is a very dirty hack to queue non-expirable tasks in another queue
1779 * in order to avoid pulluting the tail of the standard queue. This will go
1780 * away with the new O(log(n)) scheduler anyway.
1781 */
1782 if (tv_iseternity(&task->expire)) {
1783 /* if the task was queued in the standard wait queue, we must dequeue it */
1784 if (task->prev) {
1785 if (task->wq == LIST_HEAD(wait_queue[1]))
1786 return task;
1787 else {
1788 task_delete(task);
1789 task->prev = NULL;
1790 }
1791 }
1792 list = task->wq = LIST_HEAD(wait_queue[1]);
1793 } else {
1794 /* if the task was queued in the eternity queue, we must dequeue it */
1795 if (task->prev && (task->wq == LIST_HEAD(wait_queue[1]))) {
1796 task_delete(task);
1797 task->prev = NULL;
1798 list = task->wq = LIST_HEAD(wait_queue[0]);
1799 }
1800 }
1801
1802 /* next, test if the task was already in a list */
willy tarreau0f7af912005-12-17 12:21:26 +01001803 if (task->prev == NULL) {
1804 // start_from = list;
1805 start_from = list->prev;
willy tarreau750a4722005-12-17 13:21:24 +01001806#if STATTIME > 0
willy tarreau0f7af912005-12-17 12:21:26 +01001807 stats_tsk_new++;
willy tarreau750a4722005-12-17 13:21:24 +01001808#endif
willy tarreau0f7af912005-12-17 12:21:26 +01001809 /* insert the unlinked <task> into the list, searching back from the last entry */
1810 while (start_from != list && tv_cmp2(&task->expire, &start_from->expire) < 0) {
1811 start_from = start_from->prev;
willy tarreau750a4722005-12-17 13:21:24 +01001812#if STATTIME > 0
willy tarreau0f7af912005-12-17 12:21:26 +01001813 stats_tsk_nsrch++;
willy tarreau750a4722005-12-17 13:21:24 +01001814#endif
willy tarreau0f7af912005-12-17 12:21:26 +01001815 }
1816
1817 // while (start_from->next != list && tv_cmp2(&task->expire, &start_from->next->expire) > 0) {
1818 // start_from = start_from->next;
1819 // stats_tsk_nsrch++;
1820 // }
1821 }
1822 else if (task->prev == list ||
1823 tv_cmp2(&task->expire, &task->prev->expire) >= 0) { /* walk right */
1824 start_from = task->next;
1825 if (start_from == list || tv_cmp2(&task->expire, &start_from->expire) <= 0) {
willy tarreau750a4722005-12-17 13:21:24 +01001826#if STATTIME > 0
willy tarreau0f7af912005-12-17 12:21:26 +01001827 stats_tsk_good++;
willy tarreau750a4722005-12-17 13:21:24 +01001828#endif
willy tarreau0f7af912005-12-17 12:21:26 +01001829 return task; /* it's already in the right place */
1830 }
1831
willy tarreau750a4722005-12-17 13:21:24 +01001832#if STATTIME > 0
willy tarreau0f7af912005-12-17 12:21:26 +01001833 stats_tsk_right++;
willy tarreau750a4722005-12-17 13:21:24 +01001834#endif
1835
1836 /* if the task is not at the right place, there's little chance that
1837 * it has only shifted a bit, and it will nearly always be queued
1838 * at the end of the list because of constant timeouts
1839 * (observed in real case).
1840 */
1841#ifndef WE_REALLY_THINK_THAT_THIS_TASK_MAY_HAVE_SHIFTED
1842 start_from = list->prev; /* assume we'll queue to the end of the list */
1843 while (start_from != list && tv_cmp2(&task->expire, &start_from->expire) < 0) {
1844 start_from = start_from->prev;
1845#if STATTIME > 0
1846 stats_tsk_lsrch++;
1847#endif
1848 }
1849#else /* WE_REALLY_... */
willy tarreau0f7af912005-12-17 12:21:26 +01001850 /* insert the unlinked <task> into the list, searching after position <start_from> */
1851 while (start_from->next != list && tv_cmp2(&task->expire, &start_from->next->expire) > 0) {
1852 start_from = start_from->next;
willy tarreau750a4722005-12-17 13:21:24 +01001853#if STATTIME > 0
willy tarreau0f7af912005-12-17 12:21:26 +01001854 stats_tsk_rsrch++;
willy tarreau750a4722005-12-17 13:21:24 +01001855#endif
willy tarreau0f7af912005-12-17 12:21:26 +01001856 }
willy tarreau750a4722005-12-17 13:21:24 +01001857#endif /* WE_REALLY_... */
1858
willy tarreau0f7af912005-12-17 12:21:26 +01001859 /* we need to unlink it now */
1860 task_delete(task);
1861 }
1862 else { /* walk left. */
willy tarreau750a4722005-12-17 13:21:24 +01001863#if STATTIME > 0
willy tarreau0f7af912005-12-17 12:21:26 +01001864 stats_tsk_left++;
willy tarreau750a4722005-12-17 13:21:24 +01001865#endif
willy tarreau0f7af912005-12-17 12:21:26 +01001866#ifdef LEFT_TO_TOP /* not very good */
1867 start_from = list;
1868 while (start_from->next != list && tv_cmp2(&task->expire, &start_from->next->expire) > 0) {
1869 start_from = start_from->next;
willy tarreau750a4722005-12-17 13:21:24 +01001870#if STATTIME > 0
willy tarreau0f7af912005-12-17 12:21:26 +01001871 stats_tsk_lsrch++;
willy tarreau750a4722005-12-17 13:21:24 +01001872#endif
willy tarreau0f7af912005-12-17 12:21:26 +01001873 }
1874#else
1875 start_from = task->prev->prev; /* valid because of the previous test above */
1876 while (start_from != list && tv_cmp2(&task->expire, &start_from->expire) < 0) {
1877 start_from = start_from->prev;
willy tarreau750a4722005-12-17 13:21:24 +01001878#if STATTIME > 0
willy tarreau0f7af912005-12-17 12:21:26 +01001879 stats_tsk_lsrch++;
willy tarreau750a4722005-12-17 13:21:24 +01001880#endif
willy tarreau0f7af912005-12-17 12:21:26 +01001881 }
1882#endif
1883 /* we need to unlink it now */
1884 task_delete(task);
1885 }
1886 task->prev = start_from;
1887 task->next = start_from->next;
1888 task->next->prev = task;
1889 start_from->next = task;
1890 return task;
1891}
1892
1893
1894/*********************************************************************/
willy tarreau18a957c2006-04-12 19:26:23 +02001895/* pending connections queues **************************************/
1896/*********************************************************************/
1897
1898/*
willy tarreaudfece232006-05-02 00:19:57 +02001899 * Detaches pending connection <p>, decreases the pending count, and frees
1900 * the pending connection. The connection might have been queued to a specific
1901 * server as well as to the proxy. The session also gets marked unqueued.
willy tarreau18a957c2006-04-12 19:26:23 +02001902 */
willy tarreaudfece232006-05-02 00:19:57 +02001903static void pendconn_free(struct pendconn *p) {
1904 LIST_DEL(&p->list);
1905 p->sess->pend_pos = NULL;
1906 if (p->srv)
1907 p->srv->nbpend--;
1908 else
1909 p->sess->proxy->nbpend--;
willy tarreauf32f5242006-05-02 22:54:52 +02001910 p->sess->proxy->totpend--;
willy tarreaudfece232006-05-02 00:19:57 +02001911 pool_free(pendconn, p);
1912}
1913
1914/* Returns the first pending connection for server <s>, which may be NULL if
1915 * nothing is pending.
1916 */
1917static inline struct pendconn *pendconn_from_srv(struct server *s) {
willy tarreau18a957c2006-04-12 19:26:23 +02001918 if (!s->nbpend)
1919 return NULL;
1920
1921 return LIST_ELEM(s->pendconns.n, struct pendconn *, list);
1922}
1923
willy tarreaudfece232006-05-02 00:19:57 +02001924/* Returns the first pending connection for proxy <px>, which may be NULL if
1925 * nothing is pending.
willy tarreau18a957c2006-04-12 19:26:23 +02001926 */
willy tarreaudfece232006-05-02 00:19:57 +02001927static inline struct pendconn *pendconn_from_px(struct proxy *px) {
1928 if (!px->nbpend)
1929 return NULL;
1930
1931 return LIST_ELEM(px->pendconns.n, struct pendconn *, list);
willy tarreau18a957c2006-04-12 19:26:23 +02001932}
1933
willy tarreaubc2eda62006-05-04 15:16:23 +02001934/* Detaches the next pending connection from either a server or a proxy, and
1935 * returns its associated session. If no pending connection is found, NULL is
1936 * returned. Note that neither <srv> nor <px> can be NULL.
willy tarreau18a957c2006-04-12 19:26:23 +02001937 */
willy tarreaubc2eda62006-05-04 15:16:23 +02001938static struct session *pendconn_get_next_sess(struct server *srv, struct proxy *px) {
willy tarreau18a957c2006-04-12 19:26:23 +02001939 struct pendconn *p;
1940 struct session *sess;
1941
willy tarreaubc2eda62006-05-04 15:16:23 +02001942 p = pendconn_from_srv(srv);
willy tarreaudfece232006-05-02 00:19:57 +02001943 if (!p) {
willy tarreaubc2eda62006-05-04 15:16:23 +02001944 p = pendconn_from_px(px);
willy tarreaudfece232006-05-02 00:19:57 +02001945 if (!p)
1946 return NULL;
willy tarreaubc2eda62006-05-04 15:16:23 +02001947 p->sess->srv = srv;
willy tarreaudfece232006-05-02 00:19:57 +02001948 }
willy tarreau18a957c2006-04-12 19:26:23 +02001949 sess = p->sess;
1950 pendconn_free(p);
1951 return sess;
1952}
1953
willy tarreaudfece232006-05-02 00:19:57 +02001954/* Adds the session <sess> to the pending connection list of server <sess>->srv
1955 * or to the one of <sess>->proxy if srv is NULL. All counters and back pointers
1956 * are updated accordingly. Returns NULL if no memory is available, otherwise the
1957 * pendconn itself.
willy tarreau18a957c2006-04-12 19:26:23 +02001958 */
willy tarreaudfece232006-05-02 00:19:57 +02001959static struct pendconn *pendconn_add(struct session *sess) {
willy tarreau18a957c2006-04-12 19:26:23 +02001960 struct pendconn *p;
1961
1962 p = pool_alloc(pendconn);
1963 if (!p)
1964 return NULL;
1965
willy tarreau18a957c2006-04-12 19:26:23 +02001966 sess->pend_pos = p;
willy tarreaudfece232006-05-02 00:19:57 +02001967 p->sess = sess;
1968 p->srv = sess->srv;
1969 if (sess->srv) {
1970 LIST_ADDQ(&sess->srv->pendconns, &p->list);
willy tarreau5e69b162006-05-12 19:49:37 +02001971 sess->logs.srv_queue_size += sess->srv->nbpend;
willy tarreaudfece232006-05-02 00:19:57 +02001972 sess->srv->nbpend++;
willy tarreaucb406512006-05-18 00:52:35 +02001973 if (sess->srv->nbpend > sess->srv->nbpend_max)
1974 sess->srv->nbpend_max = sess->srv->nbpend;
willy tarreaudfece232006-05-02 00:19:57 +02001975 } else {
1976 LIST_ADDQ(&sess->proxy->pendconns, &p->list);
willy tarreau5e69b162006-05-12 19:49:37 +02001977 sess->logs.prx_queue_size += sess->proxy->nbpend;
willy tarreaudfece232006-05-02 00:19:57 +02001978 sess->proxy->nbpend++;
willy tarreaucb406512006-05-18 00:52:35 +02001979 if (sess->proxy->nbpend > sess->proxy->nbpend_max)
1980 sess->proxy->nbpend_max = sess->proxy->nbpend;
willy tarreaudfece232006-05-02 00:19:57 +02001981 }
willy tarreauf32f5242006-05-02 22:54:52 +02001982 sess->proxy->totpend++;
willy tarreau18a957c2006-04-12 19:26:23 +02001983 return p;
1984}
1985
willy tarreauf76e6ca2006-05-21 21:09:55 +02001986/* returns the effective dynamic maxconn for a server, considering the minconn
1987 * and the proxy's usage relative to its saturation.
1988 */
1989static unsigned int srv_dynamic_maxconn(struct server *s) {
1990 return s->minconn ?
1991 ((s->maxconn * s->proxy->nbconn / s->proxy->maxconn) < s->minconn) ? s->minconn :
1992 (s->maxconn * s->proxy->nbconn / s->proxy->maxconn) : s->maxconn;
1993}
1994
willy tarreau59a6cc22006-05-12 01:29:08 +02001995/* returns 0 if nothing has to be done for server <s> regarding queued connections,
1996 * and non-zero otherwise. Suited for and if/else usage.
1997 */
1998static inline int may_dequeue_tasks(struct server *s, struct proxy *p) {
1999 return (s && (s->nbpend || p->nbpend) &&
willy tarreauf76e6ca2006-05-21 21:09:55 +020