blob: 46078ceb1bf832bc3cb162a68ce4715b4693f7fb [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Backend variables and functions.
3 *
Willy Tarreaud825eef2007-05-12 22:35:00 +02004 * Copyright 2000-2007 Willy Tarreau <w@1wt.eu>
Willy Tarreaubaaee002006-06-26 02:48:02 +02005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
13#include <errno.h>
14#include <fcntl.h>
15#include <stdio.h>
16#include <stdlib.h>
17#include <syslog.h>
Willy Tarreauf19cf372006-11-14 15:40:51 +010018#include <string.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020019
Willy Tarreau2dd0d472006-06-29 17:53:05 +020020#include <common/compat.h>
Willy Tarreaue3ba5f02006-06-29 18:54:54 +020021#include <common/config.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020022#include <common/time.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020023
24#include <types/buffers.h>
25#include <types/global.h>
26#include <types/polling.h>
27#include <types/proxy.h>
28#include <types/server.h>
29#include <types/session.h>
30
31#include <proto/backend.h>
Willy Tarreau14c8aac2007-05-08 19:46:30 +020032#include <proto/client.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020033#include <proto/fd.h>
Willy Tarreau80587432006-12-24 17:47:20 +010034#include <proto/httperr.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020035#include <proto/log.h>
36#include <proto/proto_http.h>
37#include <proto/queue.h>
38#include <proto/stream_sock.h>
39#include <proto/task.h>
40
Willy Tarreau77074d52006-11-12 23:57:19 +010041#ifdef CONFIG_HAP_CTTPROXY
42#include <import/ip_tproxy.h>
43#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +020044
Willy Tarreau6d1a9882007-01-07 02:03:04 +010045#ifdef CONFIG_HAP_TCPSPLICE
46#include <libtcpsplice.h>
47#endif
48
Willy Tarreaubaaee002006-06-26 02:48:02 +020049/*
50 * This function recounts the number of usable active and backup servers for
51 * proxy <p>. These numbers are returned into the p->srv_act and p->srv_bck.
52 * This function also recomputes the total active and backup weights.
53 */
54void recount_servers(struct proxy *px)
55{
56 struct server *srv;
Willy Tarreau20697042007-11-15 23:26:18 +010057 int first_bkw = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +020058
Willy Tarreau20697042007-11-15 23:26:18 +010059 px->srv_act = px->srv_bck = 0;
60 px->lbprm.tot_wact = px->lbprm.tot_wbck = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +020061 for (srv = px->srv; srv != NULL; srv = srv->next) {
62 if (srv->state & SRV_RUNNING) {
63 if (srv->state & SRV_BACKUP) {
64 px->srv_bck++;
Willy Tarreau20697042007-11-15 23:26:18 +010065 px->lbprm.tot_wbck += srv->eweight;
66 if (px->srv_bck == 1)
67 first_bkw = srv->eweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +020068 } else {
69 px->srv_act++;
Willy Tarreau20697042007-11-15 23:26:18 +010070 px->lbprm.tot_wact += srv->eweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +020071 }
72 }
73 }
Willy Tarreau20697042007-11-15 23:26:18 +010074
75 if (px->srv_act) {
76 px->lbprm.tot_weight = px->lbprm.tot_wact;
77 px->lbprm.tot_used = px->srv_act;
78 }
79 else if (px->srv_bck) {
80 if (px->options & PR_O_USE_ALL_BK) {
81 px->lbprm.tot_weight = px->lbprm.tot_wbck;
82 px->lbprm.tot_used = px->srv_bck;
83 }
84 else { /* the first backup server is enough */
85 px->lbprm.tot_weight = first_bkw;
86 px->lbprm.tot_used = 1;
87 }
88 }
89 else {
90 px->lbprm.tot_weight = 0;
91 px->lbprm.tot_used = 0;
92 }
93
Willy Tarreaubaaee002006-06-26 02:48:02 +020094}
95
Willy Tarreau20697042007-11-15 23:26:18 +010096/* This function recomputes the server map for proxy px. It relies on
97 * px->lbprm.tot_wact, tot_wbck, tot_used, tot_weight, so it must be
98 * called after recount_servers(). It also expects px->lbprm.map.srv
99 * to be allocated with the largest size needed. It updates tot_weight.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200100 */
101void recalc_server_map(struct proxy *px)
102{
103 int o, tot, flag;
104 struct server *cur, *best;
105
Willy Tarreau20697042007-11-15 23:26:18 +0100106 switch (px->lbprm.tot_used) {
107 case 0: /* no server */
108 px->lbprm.map.state &= ~PR_MAP_RECALC;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200109 return;
Willy Tarreau20697042007-11-15 23:26:18 +0100110 case 1: /* only one server, just fill first entry */
111 tot = 1;
112 break;
113 default:
114 tot = px->lbprm.tot_weight;
115 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200116 }
117
Willy Tarreau20697042007-11-15 23:26:18 +0100118 /* here we *know* that we have some servers */
119 if (px->srv_act)
120 flag = SRV_RUNNING;
121 else
122 flag = SRV_RUNNING | SRV_BACKUP;
123
Willy Tarreaubaaee002006-06-26 02:48:02 +0200124 /* this algorithm gives priority to the first server, which means that
125 * it will respect the declaration order for equivalent weights, and
126 * that whatever the weights, the first server called will always be
Willy Tarreau20697042007-11-15 23:26:18 +0100127 * the first declared. This is an important asumption for the backup
Willy Tarreaubaaee002006-06-26 02:48:02 +0200128 * case, where we want the first server only.
129 */
130 for (cur = px->srv; cur; cur = cur->next)
131 cur->wscore = 0;
132
133 for (o = 0; o < tot; o++) {
134 int max = 0;
135 best = NULL;
136 for (cur = px->srv; cur; cur = cur->next) {
137 if ((cur->state & (SRV_RUNNING | SRV_BACKUP)) == flag) {
138 int v;
139
140 /* If we are forced to return only one server, we don't want to
141 * go further, because we would return the wrong one due to
142 * divide overflow.
143 */
144 if (tot == 1) {
145 best = cur;
Willy Tarreau20697042007-11-15 23:26:18 +0100146 /* note that best->wscore will be wrong but we don't care */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200147 break;
148 }
149
Willy Tarreau417fae02007-03-25 21:16:40 +0200150 cur->wscore += cur->eweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200151 v = (cur->wscore + tot) / tot; /* result between 0 and 3 */
152 if (best == NULL || v > max) {
153 max = v;
154 best = cur;
155 }
156 }
157 }
Willy Tarreau20697042007-11-15 23:26:18 +0100158 px->lbprm.map.srv[o] = best;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200159 best->wscore -= tot;
160 }
Willy Tarreau20697042007-11-15 23:26:18 +0100161 px->lbprm.map.state &= ~PR_MAP_RECALC;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200162}
163
Willy Tarreau5dc2fa62007-11-19 19:10:18 +0100164/* This function is responsible of building the server MAP for map-based LB
165 * algorithms, allocating the map, and setting p->lbprm.wmult to the GCD of the
166 * weights if applicable. It should be called only once per proxy, at config
167 * time.
168 */
169void init_server_map(struct proxy *p)
170{
171 struct server *srv;
172 int pgcd;
173 int act, bck;
174
175 if (!p->srv)
176 return;
177
178 /* We will factor the weights to reduce the table,
179 * using Euclide's largest common divisor algorithm
180 */
181 pgcd = p->srv->uweight;
182 for (srv = p->srv->next; srv && pgcd > 1; srv = srv->next) {
183 int w = srv->uweight;
184 while (w) {
185 int t = pgcd % w;
186 pgcd = w;
187 w = t;
188 }
189 }
190
191 /* It is sometimes useful to know what factor to apply
192 * to the backend's effective weight to know its real
193 * weight.
194 */
195 p->lbprm.wmult = pgcd;
196
197 act = bck = 0;
198 for (srv = p->srv; srv; srv = srv->next) {
199 srv->eweight = srv->uweight / pgcd;
200 if (srv->state & SRV_BACKUP)
201 bck += srv->eweight;
202 else
203 act += srv->eweight;
204 }
205
206 /* this is the largest map we will ever need for this servers list */
207 if (act < bck)
208 act = bck;
209
210 p->lbprm.map.srv = (struct server **)calloc(act, sizeof(struct server *));
211 /* recounts servers and their weights */
212 p->lbprm.map.state = PR_MAP_RECALC;
213 recount_servers(p);
214 recalc_server_map(p);
215}
216
Willy Tarreau01732802007-11-01 22:48:15 +0100217/*
218 * This function tries to find a running server for the proxy <px> following
219 * the URL parameter hash method. It looks for a specific parameter in the
220 * URL and hashes it to compute the server ID. This is useful to optimize
221 * performance by avoiding bounces between servers in contexts where sessions
222 * are shared but cookies are not usable. If the parameter is not found, NULL
223 * is returned. If any server is found, it will be returned. If no valid server
224 * is found, NULL is returned.
225 *
226 */
227struct server *get_server_ph(struct proxy *px, const char *uri, int uri_len)
228{
229 unsigned long hash = 0;
230 char *p;
231 int plen;
232
Willy Tarreau20697042007-11-15 23:26:18 +0100233 if (px->lbprm.tot_weight == 0)
Willy Tarreau01732802007-11-01 22:48:15 +0100234 return NULL;
235
Willy Tarreau20697042007-11-15 23:26:18 +0100236 if (px->lbprm.map.state & PR_MAP_RECALC)
237 recalc_server_map(px);
238
Willy Tarreau01732802007-11-01 22:48:15 +0100239 p = memchr(uri, '?', uri_len);
240 if (!p)
241 return NULL;
242 p++;
243
244 uri_len -= (p - uri);
245 plen = px->url_param_len;
246
247 if (uri_len <= plen)
248 return NULL;
249
250 while (uri_len > plen) {
251 /* Look for the parameter name followed by an equal symbol */
252 if (p[plen] == '=') {
253 /* skip the equal symbol */
254 uri = p;
255 p += plen + 1;
256 uri_len -= plen + 1;
257 if (memcmp(uri, px->url_param_name, plen) == 0) {
258 /* OK, we have the parameter here at <uri>, and
259 * the value after the equal sign, at <p>
260 */
261 while (uri_len && *p != '&') {
262 hash = *p + (hash << 6) + (hash << 16) - hash;
263 uri_len--;
264 p++;
265 }
Willy Tarreau20697042007-11-15 23:26:18 +0100266 return px->lbprm.map.srv[hash % px->lbprm.tot_weight];
Willy Tarreau01732802007-11-01 22:48:15 +0100267 }
268 }
269
270 /* skip to next parameter */
271 uri = p;
272 p = memchr(uri, '&', uri_len);
273 if (!p)
274 return NULL;
275 p++;
276 uri_len -= (p - uri);
277 }
278 return NULL;
279}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200280
281/*
282 * This function marks the session as 'assigned' in direct or dispatch modes,
283 * or tries to assign one in balance mode, according to the algorithm. It does
284 * nothing if the session had already been assigned a server.
285 *
286 * It may return :
287 * SRV_STATUS_OK if everything is OK. s->srv will be valid.
288 * SRV_STATUS_NOSRV if no server is available. s->srv = NULL.
289 * SRV_STATUS_FULL if all servers are saturated. s->srv = NULL.
290 * SRV_STATUS_INTERNAL for other unrecoverable errors.
291 *
292 * Upon successful return, the session flag SN_ASSIGNED to indicate that it does
293 * not need to be called anymore. This usually means that s->srv can be trusted
294 * in balance and direct modes. This flag is not cleared, so it's to the caller
295 * to clear it if required (eg: redispatch).
296 *
297 */
298
299int assign_server(struct session *s)
300{
301#ifdef DEBUG_FULL
302 fprintf(stderr,"assign_server : s=%p\n",s);
303#endif
304
305 if (s->pend_pos)
306 return SRV_STATUS_INTERNAL;
307
308 if (!(s->flags & SN_ASSIGNED)) {
Willy Tarreaue2e27a52007-04-01 00:01:37 +0200309 if (s->be->options & PR_O_BALANCE) {
Willy Tarreau1a20a5d2007-11-01 21:08:19 +0100310 int len;
311
Willy Tarreau5d65bbb2007-01-21 12:47:26 +0100312 if (s->flags & SN_DIRECT) {
313 s->flags |= SN_ASSIGNED;
314 return SRV_STATUS_OK;
315 }
Willy Tarreau1a20a5d2007-11-01 21:08:19 +0100316
Willy Tarreaue2e27a52007-04-01 00:01:37 +0200317 if (!s->be->srv_act && !s->be->srv_bck)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200318 return SRV_STATUS_NOSRV;
319
Willy Tarreau1a20a5d2007-11-01 21:08:19 +0100320 switch (s->be->options & PR_O_BALANCE) {
321 case PR_O_BALANCE_RR:
Willy Tarreaue2e27a52007-04-01 00:01:37 +0200322 s->srv = get_server_rr_with_conns(s->be);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200323 if (!s->srv)
324 return SRV_STATUS_FULL;
Willy Tarreau1a20a5d2007-11-01 21:08:19 +0100325 break;
326 case PR_O_BALANCE_SH:
Willy Tarreaubaaee002006-06-26 02:48:02 +0200327 if (s->cli_addr.ss_family == AF_INET)
328 len = 4;
329 else if (s->cli_addr.ss_family == AF_INET6)
330 len = 16;
331 else /* unknown IP family */
332 return SRV_STATUS_INTERNAL;
333
Willy Tarreaue2e27a52007-04-01 00:01:37 +0200334 s->srv = get_server_sh(s->be,
Willy Tarreaubaaee002006-06-26 02:48:02 +0200335 (void *)&((struct sockaddr_in *)&s->cli_addr)->sin_addr,
336 len);
Willy Tarreau1a20a5d2007-11-01 21:08:19 +0100337 break;
338 case PR_O_BALANCE_UH:
Willy Tarreau2fcb5002007-05-08 13:35:26 +0200339 /* URI hashing */
340 s->srv = get_server_uh(s->be,
341 s->txn.req.sol + s->txn.req.sl.rq.u,
342 s->txn.req.sl.rq.u_l);
Willy Tarreau01732802007-11-01 22:48:15 +0100343 break;
344 case PR_O_BALANCE_PH:
345 /* URL Parameter hashing */
346 s->srv = get_server_ph(s->be,
347 s->txn.req.sol + s->txn.req.sl.rq.u,
348 s->txn.req.sl.rq.u_l);
349 if (!s->srv) {
350 /* parameter not found, fall back to round robin */
351 s->srv = get_server_rr_with_conns(s->be);
352 if (!s->srv)
353 return SRV_STATUS_FULL;
354 }
Willy Tarreau1a20a5d2007-11-01 21:08:19 +0100355 break;
356 default:
357 /* unknown balancing algorithm */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200358 return SRV_STATUS_INTERNAL;
Willy Tarreau1a20a5d2007-11-01 21:08:19 +0100359 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200360 }
Willy Tarreaue2e27a52007-04-01 00:01:37 +0200361 else if (!*(int *)&s->be->dispatch_addr.sin_addr &&
Willy Tarreau5d65bbb2007-01-21 12:47:26 +0100362 !(s->fe->options & PR_O_TRANSP)) {
Willy Tarreau1a1158b2007-01-20 11:07:46 +0100363 return SRV_STATUS_NOSRV;
Willy Tarreau5d65bbb2007-01-21 12:47:26 +0100364 }
365 s->flags |= SN_ASSIGNED;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200366 }
367 return SRV_STATUS_OK;
368}
369
370
371/*
372 * This function assigns a server address to a session, and sets SN_ADDR_SET.
373 * The address is taken from the currently assigned server, or from the
374 * dispatch or transparent address.
375 *
376 * It may return :
377 * SRV_STATUS_OK if everything is OK.
378 * SRV_STATUS_INTERNAL for other unrecoverable errors.
379 *
380 * Upon successful return, the session flag SN_ADDR_SET is set. This flag is
381 * not cleared, so it's to the caller to clear it if required.
382 *
383 */
384int assign_server_address(struct session *s)
385{
386#ifdef DEBUG_FULL
387 fprintf(stderr,"assign_server_address : s=%p\n",s);
388#endif
389
Willy Tarreaue2e27a52007-04-01 00:01:37 +0200390 if ((s->flags & SN_DIRECT) || (s->be->options & PR_O_BALANCE)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200391 /* A server is necessarily known for this session */
392 if (!(s->flags & SN_ASSIGNED))
393 return SRV_STATUS_INTERNAL;
394
395 s->srv_addr = s->srv->addr;
396
397 /* if this server remaps proxied ports, we'll use
398 * the port the client connected to with an offset. */
399 if (s->srv->state & SRV_MAPPORTS) {
Willy Tarreau14c8aac2007-05-08 19:46:30 +0200400 if (!(s->fe->options & PR_O_TRANSP) && !(s->flags & SN_FRT_ADDR_SET))
401 get_frt_addr(s);
402 if (s->frt_addr.ss_family == AF_INET) {
403 s->srv_addr.sin_port = htons(ntohs(s->srv_addr.sin_port) +
404 ntohs(((struct sockaddr_in *)&s->frt_addr)->sin_port));
405 } else {
406 s->srv_addr.sin_port = htons(ntohs(s->srv_addr.sin_port) +
407 ntohs(((struct sockaddr_in6 *)&s->frt_addr)->sin6_port));
408 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200409 }
410 }
Willy Tarreaue2e27a52007-04-01 00:01:37 +0200411 else if (*(int *)&s->be->dispatch_addr.sin_addr) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200412 /* connect to the defined dispatch addr */
Willy Tarreaue2e27a52007-04-01 00:01:37 +0200413 s->srv_addr = s->be->dispatch_addr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200414 }
Willy Tarreau73de9892006-11-30 11:40:23 +0100415 else if (s->fe->options & PR_O_TRANSP) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200416 /* in transparent mode, use the original dest addr if no dispatch specified */
417 socklen_t salen = sizeof(s->srv_addr);
418
419 if (get_original_dst(s->cli_fd, &s->srv_addr, &salen) == -1) {
420 qfprintf(stderr, "Cannot get original server address.\n");
421 return SRV_STATUS_INTERNAL;
422 }
423 }
Willy Tarreau1a1158b2007-01-20 11:07:46 +0100424 else {
425 /* no server and no LB algorithm ! */
426 return SRV_STATUS_INTERNAL;
427 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200428
429 s->flags |= SN_ADDR_SET;
430 return SRV_STATUS_OK;
431}
432
433
434/* This function assigns a server to session <s> if required, and can add the
435 * connection to either the assigned server's queue or to the proxy's queue.
436 *
437 * Returns :
438 *
439 * SRV_STATUS_OK if everything is OK.
440 * SRV_STATUS_NOSRV if no server is available. s->srv = NULL.
441 * SRV_STATUS_QUEUED if the connection has been queued.
442 * SRV_STATUS_FULL if the server(s) is/are saturated and the
443 * connection could not be queued.
444 * SRV_STATUS_INTERNAL for other unrecoverable errors.
445 *
446 */
447int assign_server_and_queue(struct session *s)
448{
449 struct pendconn *p;
450 int err;
451
452 if (s->pend_pos)
453 return SRV_STATUS_INTERNAL;
454
455 if (s->flags & SN_ASSIGNED) {
Elijah Epifanovacafc5f2007-10-25 20:15:38 +0200456 if (s->srv && s->srv->maxqueue > 0 && s->srv->nbpend >= s->srv->maxqueue) {
457 s->flags &= ~(SN_DIRECT | SN_ASSIGNED | SN_ADDR_SET);
458 s->srv = NULL;
459 http_flush_cookie_flags(&s->txn);
460 } else {
461 /* a server does not need to be assigned, perhaps because we're in
462 * direct mode, or in dispatch or transparent modes where the server
463 * is not needed.
464 */
465 if (s->srv &&
466 s->srv->maxconn && s->srv->cur_sess >= srv_dynamic_maxconn(s->srv)) {
467 p = pendconn_add(s);
468 if (p)
469 return SRV_STATUS_QUEUED;
470 else
471 return SRV_STATUS_FULL;
472 }
473 return SRV_STATUS_OK;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200474 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200475 }
476
477 /* a server needs to be assigned */
478 err = assign_server(s);
479 switch (err) {
480 case SRV_STATUS_OK:
481 /* in balance mode, we might have servers with connection limits */
482 if (s->srv &&
483 s->srv->maxconn && s->srv->cur_sess >= srv_dynamic_maxconn(s->srv)) {
484 p = pendconn_add(s);
485 if (p)
486 return SRV_STATUS_QUEUED;
487 else
488 return SRV_STATUS_FULL;
489 }
490 return SRV_STATUS_OK;
491
492 case SRV_STATUS_FULL:
493 /* queue this session into the proxy's queue */
494 p = pendconn_add(s);
495 if (p)
496 return SRV_STATUS_QUEUED;
497 else
498 return SRV_STATUS_FULL;
499
500 case SRV_STATUS_NOSRV:
501 case SRV_STATUS_INTERNAL:
502 return err;
503 default:
504 return SRV_STATUS_INTERNAL;
505 }
506}
507
508
509/*
510 * This function initiates a connection to the server assigned to this session
511 * (s->srv, s->srv_addr). It will assign a server if none is assigned yet.
512 * It can return one of :
513 * - SN_ERR_NONE if everything's OK
514 * - SN_ERR_SRVTO if there are no more servers
515 * - SN_ERR_SRVCL if the connection was refused by the server
516 * - SN_ERR_PRXCOND if the connection has been limited by the proxy (maxconn)
517 * - SN_ERR_RESOURCE if a system resource is lacking (eg: fd limits, ports, ...)
518 * - SN_ERR_INTERNAL for any other purely internal errors
519 * Additionnally, in the case of SN_ERR_RESOURCE, an emergency log will be emitted.
520 */
521int connect_server(struct session *s)
522{
523 int fd, err;
524
525 if (!(s->flags & SN_ADDR_SET)) {
526 err = assign_server_address(s);
527 if (err != SRV_STATUS_OK)
528 return SN_ERR_INTERNAL;
529 }
530
531 if ((fd = s->srv_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) {
532 qfprintf(stderr, "Cannot get a server socket.\n");
533
534 if (errno == ENFILE)
Willy Tarreaue2e27a52007-04-01 00:01:37 +0200535 send_log(s->be, LOG_EMERG,
Willy Tarreaubaaee002006-06-26 02:48:02 +0200536 "Proxy %s reached system FD limit at %d. Please check system tunables.\n",
Willy Tarreaue2e27a52007-04-01 00:01:37 +0200537 s->be->id, maxfd);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200538 else if (errno == EMFILE)
Willy Tarreaue2e27a52007-04-01 00:01:37 +0200539 send_log(s->be, LOG_EMERG,
Willy Tarreaubaaee002006-06-26 02:48:02 +0200540 "Proxy %s reached process FD limit at %d. Please check 'ulimit-n' and restart.\n",
Willy Tarreaue2e27a52007-04-01 00:01:37 +0200541 s->be->id, maxfd);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200542 else if (errno == ENOBUFS || errno == ENOMEM)
Willy Tarreaue2e27a52007-04-01 00:01:37 +0200543 send_log(s->be, LOG_EMERG,
Willy Tarreaubaaee002006-06-26 02:48:02 +0200544 "Proxy %s reached system memory limit at %d sockets. Please check system tunables.\n",
Willy Tarreaue2e27a52007-04-01 00:01:37 +0200545 s->be->id, maxfd);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200546 /* this is a resource error */
547 return SN_ERR_RESOURCE;
548 }
549
550 if (fd >= global.maxsock) {
551 /* do not log anything there, it's a normal condition when this option
552 * is used to serialize connections to a server !
553 */
554 Alert("socket(): not enough free sockets. Raise -n argument. Giving up.\n");
555 close(fd);
556 return SN_ERR_PRXCOND; /* it is a configuration limit */
557 }
558
Willy Tarreau6d1a9882007-01-07 02:03:04 +0100559#ifdef CONFIG_HAP_TCPSPLICE
Willy Tarreaue2e27a52007-04-01 00:01:37 +0200560 if ((s->fe->options & s->be->options) & PR_O_TCPSPLICE) {
Willy Tarreau6d1a9882007-01-07 02:03:04 +0100561 /* TCP splicing supported by both FE and BE */
562 tcp_splice_initfd(s->cli_fd, fd);
563 }
564#endif
565
Willy Tarreaubaaee002006-06-26 02:48:02 +0200566 if ((fcntl(fd, F_SETFL, O_NONBLOCK)==-1) ||
567 (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *) &one, sizeof(one)) == -1)) {
568 qfprintf(stderr,"Cannot set client socket to non blocking mode.\n");
569 close(fd);
570 return SN_ERR_INTERNAL;
571 }
572
Willy Tarreaue2e27a52007-04-01 00:01:37 +0200573 if (s->be->options & PR_O_TCP_SRV_KA)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200574 setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (char *) &one, sizeof(one));
575
Alexandre Cassen87ea5482007-10-11 20:48:58 +0200576 if (s->be->options & PR_O_TCP_NOLING)
577 setsockopt(fd, SOL_SOCKET, SO_LINGER, (struct linger *) &nolinger, sizeof(struct linger));
578
Willy Tarreaubaaee002006-06-26 02:48:02 +0200579 /* allow specific binding :
580 * - server-specific at first
581 * - proxy-specific next
582 */
583 if (s->srv != NULL && s->srv->state & SRV_BIND_SRC) {
584 setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *) &one, sizeof(one));
585 if (bind(fd, (struct sockaddr *)&s->srv->source_addr, sizeof(s->srv->source_addr)) == -1) {
586 Alert("Cannot bind to source address before connect() for server %s/%s. Aborting.\n",
Willy Tarreaue2e27a52007-04-01 00:01:37 +0200587 s->be->id, s->srv->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200588 close(fd);
Willy Tarreaue2e27a52007-04-01 00:01:37 +0200589 send_log(s->be, LOG_EMERG,
Willy Tarreaubaaee002006-06-26 02:48:02 +0200590 "Cannot bind to source address before connect() for server %s/%s.\n",
Willy Tarreaue2e27a52007-04-01 00:01:37 +0200591 s->be->id, s->srv->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200592 return SN_ERR_RESOURCE;
593 }
Willy Tarreau77074d52006-11-12 23:57:19 +0100594#ifdef CONFIG_HAP_CTTPROXY
595 if (s->srv->state & SRV_TPROXY_MASK) {
596 struct in_tproxy itp1, itp2;
597 memset(&itp1, 0, sizeof(itp1));
598
599 itp1.op = TPROXY_ASSIGN;
600 switch (s->srv->state & SRV_TPROXY_MASK) {
601 case SRV_TPROXY_ADDR:
602 itp1.v.addr.faddr = s->srv->tproxy_addr.sin_addr;
603 itp1.v.addr.fport = s->srv->tproxy_addr.sin_port;
604 break;
605 case SRV_TPROXY_CLI:
606 itp1.v.addr.fport = ((struct sockaddr_in *)&s->cli_addr)->sin_port;
607 /* fall through */
608 case SRV_TPROXY_CIP:
609 /* FIXME: what can we do if the client connects in IPv6 ? */
610 itp1.v.addr.faddr = ((struct sockaddr_in *)&s->cli_addr)->sin_addr;
611 break;
612 }
613
614 /* set connect flag on socket */
615 itp2.op = TPROXY_FLAGS;
616 itp2.v.flags = ITP_CONNECT | ITP_ONCE;
617
618 if (setsockopt(fd, SOL_IP, IP_TPROXY, &itp1, sizeof(itp1)) == -1 ||
619 setsockopt(fd, SOL_IP, IP_TPROXY, &itp2, sizeof(itp2)) == -1) {
620 Alert("Cannot bind to tproxy source address before connect() for server %s/%s. Aborting.\n",
Willy Tarreaue2e27a52007-04-01 00:01:37 +0200621 s->be->id, s->srv->id);
Willy Tarreau77074d52006-11-12 23:57:19 +0100622 close(fd);
Willy Tarreaue2e27a52007-04-01 00:01:37 +0200623 send_log(s->be, LOG_EMERG,
Willy Tarreau77074d52006-11-12 23:57:19 +0100624 "Cannot bind to tproxy source address before connect() for server %s/%s.\n",
Willy Tarreaue2e27a52007-04-01 00:01:37 +0200625 s->be->id, s->srv->id);
Willy Tarreau77074d52006-11-12 23:57:19 +0100626 return SN_ERR_RESOURCE;
627 }
628 }
629#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +0200630 }
Willy Tarreaue2e27a52007-04-01 00:01:37 +0200631 else if (s->be->options & PR_O_BIND_SRC) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200632 setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *) &one, sizeof(one));
Willy Tarreaue2e27a52007-04-01 00:01:37 +0200633 if (bind(fd, (struct sockaddr *)&s->be->source_addr, sizeof(s->be->source_addr)) == -1) {
634 Alert("Cannot bind to source address before connect() for proxy %s. Aborting.\n", s->be->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200635 close(fd);
Willy Tarreaue2e27a52007-04-01 00:01:37 +0200636 send_log(s->be, LOG_EMERG,
Willy Tarreaubaaee002006-06-26 02:48:02 +0200637 "Cannot bind to source address before connect() for server %s/%s.\n",
Willy Tarreaue2e27a52007-04-01 00:01:37 +0200638 s->be->id, s->srv->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200639 return SN_ERR_RESOURCE;
640 }
Willy Tarreau77074d52006-11-12 23:57:19 +0100641#ifdef CONFIG_HAP_CTTPROXY
Willy Tarreaue2e27a52007-04-01 00:01:37 +0200642 if (s->be->options & PR_O_TPXY_MASK) {
Willy Tarreau77074d52006-11-12 23:57:19 +0100643 struct in_tproxy itp1, itp2;
644 memset(&itp1, 0, sizeof(itp1));
645
646 itp1.op = TPROXY_ASSIGN;
Willy Tarreaue2e27a52007-04-01 00:01:37 +0200647 switch (s->be->options & PR_O_TPXY_MASK) {
Willy Tarreau77074d52006-11-12 23:57:19 +0100648 case PR_O_TPXY_ADDR:
649 itp1.v.addr.faddr = s->srv->tproxy_addr.sin_addr;
650 itp1.v.addr.fport = s->srv->tproxy_addr.sin_port;
651 break;
652 case PR_O_TPXY_CLI:
653 itp1.v.addr.fport = ((struct sockaddr_in *)&s->cli_addr)->sin_port;
654 /* fall through */
655 case PR_O_TPXY_CIP:
656 /* FIXME: what can we do if the client connects in IPv6 ? */
657 itp1.v.addr.faddr = ((struct sockaddr_in *)&s->cli_addr)->sin_addr;
658 break;
659 }
660
661 /* set connect flag on socket */
662 itp2.op = TPROXY_FLAGS;
663 itp2.v.flags = ITP_CONNECT | ITP_ONCE;
664
665 if (setsockopt(fd, SOL_IP, IP_TPROXY, &itp1, sizeof(itp1)) == -1 ||
666 setsockopt(fd, SOL_IP, IP_TPROXY, &itp2, sizeof(itp2)) == -1) {
667 Alert("Cannot bind to tproxy source address before connect() for proxy %s. Aborting.\n",
Willy Tarreaue2e27a52007-04-01 00:01:37 +0200668 s->be->id);
Willy Tarreau77074d52006-11-12 23:57:19 +0100669 close(fd);
Willy Tarreaue2e27a52007-04-01 00:01:37 +0200670 send_log(s->be, LOG_EMERG,
Willy Tarreau77074d52006-11-12 23:57:19 +0100671 "Cannot bind to tproxy source address before connect() for server %s/%s.\n",
Willy Tarreaue2e27a52007-04-01 00:01:37 +0200672 s->be->id, s->srv->id);
Willy Tarreau77074d52006-11-12 23:57:19 +0100673 return SN_ERR_RESOURCE;
674 }
675 }
676#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +0200677 }
678
679 if ((connect(fd, (struct sockaddr *)&s->srv_addr, sizeof(s->srv_addr)) == -1) &&
680 (errno != EINPROGRESS) && (errno != EALREADY) && (errno != EISCONN)) {
681
682 if (errno == EAGAIN || errno == EADDRINUSE) {
683 char *msg;
684 if (errno == EAGAIN) /* no free ports left, try again later */
685 msg = "no free ports";
686 else
687 msg = "local address already in use";
688
689 qfprintf(stderr,"Cannot connect: %s.\n",msg);
690 close(fd);
Willy Tarreaue2e27a52007-04-01 00:01:37 +0200691 send_log(s->be, LOG_EMERG,
Willy Tarreaubaaee002006-06-26 02:48:02 +0200692 "Connect() failed for server %s/%s: %s.\n",
Willy Tarreaue2e27a52007-04-01 00:01:37 +0200693 s->be->id, s->srv->id, msg);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200694 return SN_ERR_RESOURCE;
695 } else if (errno == ETIMEDOUT) {
696 //qfprintf(stderr,"Connect(): ETIMEDOUT");
697 close(fd);
698 return SN_ERR_SRVTO;
699 } else {
700 // (errno == ECONNREFUSED || errno == ENETUNREACH || errno == EACCES || errno == EPERM)
701 //qfprintf(stderr,"Connect(): %d", errno);
702 close(fd);
703 return SN_ERR_SRVCL;
704 }
705 }
706
707 fdtab[fd].owner = s->task;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200708 fdtab[fd].state = FD_STCONN; /* connection in progress */
Willy Tarreaud7971282006-07-29 18:36:34 +0200709 fdtab[fd].cb[DIR_RD].f = &stream_sock_read;
Willy Tarreau54469402006-07-29 16:59:06 +0200710 fdtab[fd].cb[DIR_RD].b = s->rep;
Willy Tarreauf8306d52006-07-29 19:01:31 +0200711 fdtab[fd].cb[DIR_WR].f = &stream_sock_write;
Willy Tarreau54469402006-07-29 16:59:06 +0200712 fdtab[fd].cb[DIR_WR].b = s->req;
Willy Tarreaue94ebd02007-10-09 17:14:37 +0200713
714 fdtab[fd].peeraddr = (struct sockaddr *)&s->srv_addr;
715 fdtab[fd].peerlen = sizeof(s->srv_addr);
716
Willy Tarreauf161a342007-04-08 16:59:42 +0200717 EV_FD_SET(fd, DIR_WR); /* for connect status */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200718
719 fd_insert(fd);
720 if (s->srv) {
721 s->srv->cur_sess++;
722 if (s->srv->cur_sess > s->srv->cur_sess_max)
723 s->srv->cur_sess_max = s->srv->cur_sess;
724 }
725
Willy Tarreaua8b55e32007-05-13 16:08:19 +0200726 if (!tv_add_ifset(&s->req->cex, &now, &s->be->contimeout))
Willy Tarreaud7971282006-07-29 18:36:34 +0200727 tv_eternity(&s->req->cex);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200728 return SN_ERR_NONE; /* connection is OK */
729}
730
731
732/*
733 * This function checks the retry count during the connect() job.
734 * It updates the session's srv_state and retries, so that the caller knows
735 * what it has to do. It uses the last connection error to set the log when
736 * it expires. It returns 1 when it has expired, and 0 otherwise.
737 */
738int srv_count_retry_down(struct session *t, int conn_err)
739{
740 /* we are in front of a retryable error */
741 t->conn_retries--;
Krzysztof Oledzki1cf36ba2007-10-18 19:12:30 +0200742 if (t->srv)
743 t->srv->retries++;
744 t->be->retries++;
745
Willy Tarreaubaaee002006-06-26 02:48:02 +0200746 if (t->conn_retries < 0) {
747 /* if not retryable anymore, let's abort */
Willy Tarreaud7971282006-07-29 18:36:34 +0200748 tv_eternity(&t->req->cex);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200749 srv_close_with_err(t, conn_err, SN_FINST_C,
Willy Tarreau80587432006-12-24 17:47:20 +0100750 503, error_message(t, HTTP_ERR_503));
Willy Tarreaubaaee002006-06-26 02:48:02 +0200751 if (t->srv)
752 t->srv->failed_conns++;
Willy Tarreaue2e27a52007-04-01 00:01:37 +0200753 t->be->failed_conns++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200754
755 /* We used to have a free connection slot. Since we'll never use it,
756 * we have to inform the server that it may be used by another session.
757 */
Willy Tarreaue2e27a52007-04-01 00:01:37 +0200758 if (may_dequeue_tasks(t->srv, t->be))
Willy Tarreau96bcfd72007-04-29 10:41:56 +0200759 task_wakeup(t->srv->queue_mgt);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200760 return 1;
761 }
762 return 0;
763}
764
765
766/*
767 * This function performs the retryable part of the connect() job.
768 * It updates the session's srv_state and retries, so that the caller knows
769 * what it has to do. It returns 1 when it breaks out of the loop, or 0 if
770 * it needs to redispatch.
771 */
772int srv_retryable_connect(struct session *t)
773{
774 int conn_err;
775
776 /* This loop ensures that we stop before the last retry in case of a
777 * redispatchable server.
778 */
779 do {
780 /* initiate a connection to the server */
781 conn_err = connect_server(t);
782 switch (conn_err) {
783
784 case SN_ERR_NONE:
785 //fprintf(stderr,"0: c=%d, s=%d\n", c, s);
786 t->srv_state = SV_STCONN;
787 return 1;
788
789 case SN_ERR_INTERNAL:
Willy Tarreaud7971282006-07-29 18:36:34 +0200790 tv_eternity(&t->req->cex);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200791 srv_close_with_err(t, SN_ERR_INTERNAL, SN_FINST_C,
Willy Tarreau80587432006-12-24 17:47:20 +0100792 500, error_message(t, HTTP_ERR_500));
Willy Tarreaubaaee002006-06-26 02:48:02 +0200793 if (t->srv)
794 t->srv->failed_conns++;
Willy Tarreaue2e27a52007-04-01 00:01:37 +0200795 t->be->failed_conns++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200796 /* release other sessions waiting for this server */
Willy Tarreaue2e27a52007-04-01 00:01:37 +0200797 if (may_dequeue_tasks(t->srv, t->be))
Willy Tarreau96bcfd72007-04-29 10:41:56 +0200798 task_wakeup(t->srv->queue_mgt);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200799 return 1;
800 }
801 /* ensure that we have enough retries left */
802 if (srv_count_retry_down(t, conn_err)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200803 return 1;
804 }
Willy Tarreaue2e27a52007-04-01 00:01:37 +0200805 } while (t->srv == NULL || t->conn_retries > 0 || !(t->be->options & PR_O_REDISP));
Willy Tarreaubaaee002006-06-26 02:48:02 +0200806
807 /* We're on our last chance, and the REDISP option was specified.
808 * We will ignore cookie and force to balance or use the dispatcher.
809 */
810 /* let's try to offer this slot to anybody */
Willy Tarreaue2e27a52007-04-01 00:01:37 +0200811 if (may_dequeue_tasks(t->srv, t->be))
Willy Tarreau96bcfd72007-04-29 10:41:56 +0200812 task_wakeup(t->srv->queue_mgt);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200813
814 if (t->srv)
815 t->srv->failed_conns++;
Krzysztof Oledzki1cf36ba2007-10-18 19:12:30 +0200816 t->be->redispatches++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200817
818 t->flags &= ~(SN_DIRECT | SN_ASSIGNED | SN_ADDR_SET);
819 t->srv = NULL; /* it's left to the dispatcher to choose a server */
Willy Tarreau3d300592007-03-18 18:34:41 +0100820 http_flush_cookie_flags(&t->txn);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200821 return 0;
822}
823
824
825/* This function performs the "redispatch" part of a connection attempt. It
826 * will assign a server if required, queue the connection if required, and
827 * handle errors that might arise at this level. It can change the server
828 * state. It will return 1 if it encounters an error, switches the server
829 * state, or has to queue a connection. Otherwise, it will return 0 indicating
830 * that the connection is ready to use.
831 */
832
833int srv_redispatch_connect(struct session *t)
834{
835 int conn_err;
836
837 /* We know that we don't have any connection pending, so we will
838 * try to get a new one, and wait in this state if it's queued
839 */
840 conn_err = assign_server_and_queue(t);
841 switch (conn_err) {
842 case SRV_STATUS_OK:
843 break;
844
845 case SRV_STATUS_NOSRV:
846 /* note: it is guaranteed that t->srv == NULL here */
Willy Tarreaud7971282006-07-29 18:36:34 +0200847 tv_eternity(&t->req->cex);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200848 srv_close_with_err(t, SN_ERR_SRVTO, SN_FINST_C,
Willy Tarreau80587432006-12-24 17:47:20 +0100849 503, error_message(t, HTTP_ERR_503));
Willy Tarreaubaaee002006-06-26 02:48:02 +0200850 if (t->srv)
851 t->srv->failed_conns++;
Willy Tarreaue2e27a52007-04-01 00:01:37 +0200852 t->be->failed_conns++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200853
854 return 1;
855
856 case SRV_STATUS_QUEUED:
857 /* FIXME-20060503 : we should use the queue timeout instead */
Willy Tarreaua8b55e32007-05-13 16:08:19 +0200858 if (!tv_add_ifset(&t->req->cex, &now, &t->be->contimeout))
Willy Tarreaud7971282006-07-29 18:36:34 +0200859 tv_eternity(&t->req->cex);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200860 t->srv_state = SV_STIDLE;
861 /* do nothing else and do not wake any other session up */
862 return 1;
863
864 case SRV_STATUS_FULL:
865 case SRV_STATUS_INTERNAL:
866 default:
Willy Tarreaud7971282006-07-29 18:36:34 +0200867 tv_eternity(&t->req->cex);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200868 srv_close_with_err(t, SN_ERR_INTERNAL, SN_FINST_C,
Willy Tarreau80587432006-12-24 17:47:20 +0100869 500, error_message(t, HTTP_ERR_500));
Willy Tarreaubaaee002006-06-26 02:48:02 +0200870 if (t->srv)
871 t->srv->failed_conns++;
Willy Tarreaue2e27a52007-04-01 00:01:37 +0200872 t->be->failed_conns++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200873
874 /* release other sessions waiting for this server */
Willy Tarreaue2e27a52007-04-01 00:01:37 +0200875 if (may_dequeue_tasks(t->srv, t->be))
Willy Tarreau96bcfd72007-04-29 10:41:56 +0200876 task_wakeup(t->srv->queue_mgt);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200877 return 1;
878 }
879 /* if we get here, it's because we got SRV_STATUS_OK, which also
880 * means that the connection has not been queued.
881 */
882 return 0;
883}
884
Krzysztof Oledzki85130942007-10-22 16:21:10 +0200885int be_downtime(struct proxy *px) {
Krzysztof Oledzki85130942007-10-22 16:21:10 +0200886 if ((px->srv_act || px->srv_bck) && px->last_change < now.tv_sec) // ignore negative time
887 return px->down_time;
888
889 return now.tv_sec - px->last_change + px->down_time;
890}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200891
Willy Tarreaua0cbda62007-11-01 21:39:54 +0100892/* This function parses a "balance" statement in a backend section describing
893 * <curproxy>. It returns -1 if there is any error, otherwise zero. If it
894 * returns -1, it may write an error message into ther <err> buffer, for at
895 * most <errlen> bytes, trailing zero included. The trailing '\n' will not be
896 * written. The function must be called with <args> pointing to the first word
897 * after "balance".
898 */
899int backend_parse_balance(const char **args, char *err, int errlen, struct proxy *curproxy)
900{
901 if (!*(args[0])) {
902 /* if no option is set, use round-robin by default */
903 curproxy->options &= ~PR_O_BALANCE;
904 curproxy->options |= PR_O_BALANCE_RR;
905 return 0;
906 }
907
908 if (!strcmp(args[0], "roundrobin")) {
909 curproxy->options &= ~PR_O_BALANCE;
910 curproxy->options |= PR_O_BALANCE_RR;
911 }
912 else if (!strcmp(args[0], "source")) {
913 curproxy->options &= ~PR_O_BALANCE;
914 curproxy->options |= PR_O_BALANCE_SH;
915 }
916 else if (!strcmp(args[0], "uri")) {
917 curproxy->options &= ~PR_O_BALANCE;
918 curproxy->options |= PR_O_BALANCE_UH;
919 }
Willy Tarreau01732802007-11-01 22:48:15 +0100920 else if (!strcmp(args[0], "url_param")) {
921 if (!*args[1]) {
922 snprintf(err, errlen, "'balance url_param' requires an URL parameter name.");
923 return -1;
924 }
925 curproxy->options &= ~PR_O_BALANCE;
926 curproxy->options |= PR_O_BALANCE_PH;
927 if (curproxy->url_param_name)
928 free(curproxy->url_param_name);
929 curproxy->url_param_name = strdup(args[1]);
930 curproxy->url_param_len = strlen(args[1]);
931 }
Willy Tarreaua0cbda62007-11-01 21:39:54 +0100932 else {
Willy Tarreau01732802007-11-01 22:48:15 +0100933 snprintf(err, errlen, "'balance' only supports 'roundrobin', 'source', 'uri' and 'url_param' options.");
Willy Tarreaua0cbda62007-11-01 21:39:54 +0100934 return -1;
935 }
936 return 0;
937}
938
Willy Tarreaubaaee002006-06-26 02:48:02 +0200939/*
940 * Local variables:
941 * c-indent-level: 8
942 * c-basic-offset: 8
943 * End:
944 */