blob: 7c21b9db2ff26efb13f5045a270d9ba66747b5d3 [file] [log] [blame]
Willy Tarreaudd815982007-10-16 12:25:14 +02001/*
Willy Tarreaud1d54542012-09-12 22:58:11 +02002 * Listener management functions.
Willy Tarreaudd815982007-10-16 12:25:14 +02003 *
Willy Tarreaud1d54542012-09-12 22:58:11 +02004 * Copyright 2000-2012 Willy Tarreau <w@1wt.eu>
Willy Tarreaudd815982007-10-16 12:25:14 +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
Willy Tarreaubbebbbf2012-05-07 21:22:09 +020013#include <errno.h>
Willy Tarreaudd815982007-10-16 12:25:14 +020014#include <stdio.h>
15#include <string.h>
16
17#include <common/config.h>
Willy Tarreaudabf2e22007-10-28 21:59:24 +010018#include <common/errors.h>
Willy Tarreaudd815982007-10-16 12:25:14 +020019#include <common/mini-clist.h>
20#include <common/standard.h>
Willy Tarreaubbebbbf2012-05-07 21:22:09 +020021#include <common/time.h>
22
23#include <types/global.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020024#include <types/protocol.h>
Willy Tarreaudd815982007-10-16 12:25:14 +020025
Willy Tarreau645513a2010-05-24 20:55:15 +020026#include <proto/acl.h>
Willy Tarreaub648d632007-10-28 22:13:50 +010027#include <proto/fd.h>
Willy Tarreaubbebbbf2012-05-07 21:22:09 +020028#include <proto/freq_ctr.h>
29#include <proto/log.h>
30#include <proto/task.h>
Willy Tarreaub648d632007-10-28 22:13:50 +010031
Willy Tarreau26982662012-09-12 23:17:10 +020032/* List head of all known bind keywords */
33static struct bind_kw_list bind_keywords = {
34 .list = LIST_HEAD_INIT(bind_keywords.list)
35};
36
Willy Tarreaudabf2e22007-10-28 21:59:24 +010037/* This function adds the specified listener's file descriptor to the polling
38 * lists if it is in the LI_LISTEN state. The listener enters LI_READY or
39 * LI_FULL state depending on its number of connections.
40 */
41void enable_listener(struct listener *listener)
42{
43 if (listener->state == LI_LISTEN) {
44 if (listener->nbconn < listener->maxconn) {
Willy Tarreau49b046d2012-08-09 12:11:58 +020045 fd_want_recv(listener->fd);
Willy Tarreaudabf2e22007-10-28 21:59:24 +010046 listener->state = LI_READY;
47 } else {
48 listener->state = LI_FULL;
49 }
50 }
51}
52
53/* This function removes the specified listener's file descriptor from the
54 * polling lists if it is in the LI_READY or in the LI_FULL state. The listener
55 * enters LI_LISTEN.
56 */
57void disable_listener(struct listener *listener)
58{
59 if (listener->state < LI_READY)
60 return;
61 if (listener->state == LI_READY)
Willy Tarreau49b046d2012-08-09 12:11:58 +020062 fd_stop_recv(listener->fd);
Willy Tarreaue6ca1fc2011-07-24 22:03:52 +020063 if (listener->state == LI_LIMITED)
64 LIST_DEL(&listener->wait_queue);
Willy Tarreaudabf2e22007-10-28 21:59:24 +010065 listener->state = LI_LISTEN;
66}
67
Willy Tarreaube58c382011-07-24 18:28:10 +020068/* This function tries to temporarily disable a listener, depending on the OS
69 * capabilities. Linux unbinds the listen socket after a SHUT_RD, and ignores
70 * SHUT_WR. Solaris refuses either shutdown(). OpenBSD ignores SHUT_RD but
71 * closes upon SHUT_WR and refuses to rebind. So a common validation path
72 * involves SHUT_WR && listen && SHUT_RD. In case of success, the FD's polling
73 * is disabled. It normally returns non-zero, unless an error is reported.
74 */
75int pause_listener(struct listener *l)
76{
77 if (l->state <= LI_PAUSED)
78 return 1;
79
Willy Tarreaub3fb60b2012-10-04 08:56:31 +020080 if (l->proto->sock_prot == IPPROTO_TCP) {
81 if (shutdown(l->fd, SHUT_WR) != 0)
82 return 0; /* Solaris dies here */
Willy Tarreaube58c382011-07-24 18:28:10 +020083
Willy Tarreaub3fb60b2012-10-04 08:56:31 +020084 if (listen(l->fd, l->backlog ? l->backlog : l->maxconn) != 0)
85 return 0; /* OpenBSD dies here */
Willy Tarreaube58c382011-07-24 18:28:10 +020086
Willy Tarreaub3fb60b2012-10-04 08:56:31 +020087 if (shutdown(l->fd, SHUT_RD) != 0)
88 return 0; /* should always be OK */
89 }
Willy Tarreaube58c382011-07-24 18:28:10 +020090
Willy Tarreaue6ca1fc2011-07-24 22:03:52 +020091 if (l->state == LI_LIMITED)
92 LIST_DEL(&l->wait_queue);
93
Willy Tarreau49b046d2012-08-09 12:11:58 +020094 fd_stop_recv(l->fd);
Willy Tarreaube58c382011-07-24 18:28:10 +020095 l->state = LI_PAUSED;
96 return 1;
97}
98
Willy Tarreaue6ca1fc2011-07-24 22:03:52 +020099/* This function tries to resume a temporarily disabled listener. Paused, full,
100 * limited and disabled listeners are handled, which means that this function
101 * may replace enable_listener(). The resulting state will either be LI_READY
102 * or LI_FULL. 0 is returned in case of failure to resume (eg: dead socket).
Willy Tarreaube58c382011-07-24 18:28:10 +0200103 */
104int resume_listener(struct listener *l)
105{
106 if (l->state < LI_PAUSED)
107 return 0;
108
Willy Tarreaub3fb60b2012-10-04 08:56:31 +0200109 if (l->proto->sock_prot == IPPROTO_TCP &&
110 l->state == LI_PAUSED &&
Willy Tarreaube58c382011-07-24 18:28:10 +0200111 listen(l->fd, l->backlog ? l->backlog : l->maxconn) != 0)
112 return 0;
113
114 if (l->state == LI_READY)
115 return 1;
116
Willy Tarreaue6ca1fc2011-07-24 22:03:52 +0200117 if (l->state == LI_LIMITED)
118 LIST_DEL(&l->wait_queue);
119
Willy Tarreaube58c382011-07-24 18:28:10 +0200120 if (l->nbconn >= l->maxconn) {
121 l->state = LI_FULL;
122 return 1;
123 }
124
Willy Tarreau49b046d2012-08-09 12:11:58 +0200125 fd_want_recv(l->fd);
Willy Tarreaube58c382011-07-24 18:28:10 +0200126 l->state = LI_READY;
127 return 1;
128}
129
Willy Tarreau62793712011-07-24 19:23:38 +0200130/* Marks a ready listener as full so that the session code tries to re-enable
131 * it upon next close() using resume_listener().
132 */
133void listener_full(struct listener *l)
134{
135 if (l->state >= LI_READY) {
Willy Tarreaue6ca1fc2011-07-24 22:03:52 +0200136 if (l->state == LI_LIMITED)
137 LIST_DEL(&l->wait_queue);
138
Willy Tarreau49b046d2012-08-09 12:11:58 +0200139 fd_stop_recv(l->fd);
Willy Tarreau62793712011-07-24 19:23:38 +0200140 l->state = LI_FULL;
141 }
142}
143
Willy Tarreaue6ca1fc2011-07-24 22:03:52 +0200144/* Marks a ready listener as limited so that we only try to re-enable it when
145 * resources are free again. It will be queued into the specified queue.
146 */
147void limit_listener(struct listener *l, struct list *list)
148{
149 if (l->state == LI_READY) {
150 LIST_ADDQ(list, &l->wait_queue);
Willy Tarreau49b046d2012-08-09 12:11:58 +0200151 fd_stop_recv(l->fd);
Willy Tarreaue6ca1fc2011-07-24 22:03:52 +0200152 l->state = LI_LIMITED;
153 }
154}
155
Willy Tarreaudabf2e22007-10-28 21:59:24 +0100156/* This function adds all of the protocol's listener's file descriptors to the
157 * polling lists when they are in the LI_LISTEN state. It is intended to be
158 * used as a protocol's generic enable_all() primitive, for use after the
159 * fork(). It puts the listeners into LI_READY or LI_FULL states depending on
160 * their number of connections. It always returns ERR_NONE.
161 */
162int enable_all_listeners(struct protocol *proto)
163{
164 struct listener *listener;
165
166 list_for_each_entry(listener, &proto->listeners, proto_list)
167 enable_listener(listener);
168 return ERR_NONE;
169}
170
171/* This function removes all of the protocol's listener's file descriptors from
172 * the polling lists when they are in the LI_READY or LI_FULL states. It is
173 * intended to be used as a protocol's generic disable_all() primitive. It puts
174 * the listeners into LI_LISTEN, and always returns ERR_NONE.
175 */
176int disable_all_listeners(struct protocol *proto)
177{
178 struct listener *listener;
179
180 list_for_each_entry(listener, &proto->listeners, proto_list)
181 disable_listener(listener);
182 return ERR_NONE;
183}
184
Willy Tarreaue6ca1fc2011-07-24 22:03:52 +0200185/* Dequeues all of the listeners waiting for a resource in wait queue <queue>. */
186void dequeue_all_listeners(struct list *list)
187{
188 struct listener *listener, *l_back;
189
190 list_for_each_entry_safe(listener, l_back, list, wait_queue) {
191 /* This cannot fail because the listeners are by definition in
192 * the LI_LIMITED state. The function also removes the entry
193 * from the queue.
194 */
195 resume_listener(listener);
196 }
197}
198
Willy Tarreaub648d632007-10-28 22:13:50 +0100199/* This function closes the listening socket for the specified listener,
200 * provided that it's already in a listening state. The listener enters the
201 * LI_ASSIGNED state. It always returns ERR_NONE. This function is intended
202 * to be used as a generic function for standard protocols.
203 */
204int unbind_listener(struct listener *listener)
205{
206 if (listener->state == LI_READY)
Willy Tarreau49b046d2012-08-09 12:11:58 +0200207 fd_stop_recv(listener->fd);
Willy Tarreaub648d632007-10-28 22:13:50 +0100208
Willy Tarreaue6ca1fc2011-07-24 22:03:52 +0200209 if (listener->state == LI_LIMITED)
210 LIST_DEL(&listener->wait_queue);
211
Willy Tarreaube58c382011-07-24 18:28:10 +0200212 if (listener->state >= LI_PAUSED) {
Willy Tarreaub648d632007-10-28 22:13:50 +0100213 fd_delete(listener->fd);
214 listener->state = LI_ASSIGNED;
215 }
216 return ERR_NONE;
217}
218
Willy Tarreau3acf8c32007-10-28 22:35:41 +0100219/* This function closes all listening sockets bound to the protocol <proto>,
220 * and the listeners end in LI_ASSIGNED state if they were higher. It does not
221 * detach them from the protocol. It always returns ERR_NONE.
222 */
223int unbind_all_listeners(struct protocol *proto)
224{
225 struct listener *listener;
226
227 list_for_each_entry(listener, &proto->listeners, proto_list)
228 unbind_listener(listener);
229 return ERR_NONE;
230}
231
Willy Tarreau1a64d162007-10-28 22:26:05 +0100232/* Delete a listener from its protocol's list of listeners. The listener's
233 * state is automatically updated from LI_ASSIGNED to LI_INIT. The protocol's
234 * number of listeners is updated. Note that the listener must have previously
235 * been unbound. This is the generic function to use to remove a listener.
236 */
237void delete_listener(struct listener *listener)
238{
239 if (listener->state != LI_ASSIGNED)
240 return;
241 listener->state = LI_INIT;
242 LIST_DEL(&listener->proto_list);
243 listener->proto->nb_listeners--;
244}
245
Willy Tarreaubbebbbf2012-05-07 21:22:09 +0200246/* This function is called on a read event from a listening socket, corresponding
247 * to an accept. It tries to accept as many connections as possible, and for each
248 * calls the listener's accept handler (generally the frontend's accept handler).
249 */
Willy Tarreauafad0e02012-08-09 14:45:22 +0200250void listener_accept(int fd)
Willy Tarreaubbebbbf2012-05-07 21:22:09 +0200251{
252 struct listener *l = fdtab[fd].owner;
253 struct proxy *p = l->frontend;
254 int max_accept = global.tune.maxaccept;
255 int cfd;
256 int ret;
257
258 if (unlikely(l->nbconn >= l->maxconn)) {
259 listener_full(l);
Willy Tarreauafad0e02012-08-09 14:45:22 +0200260 return;
Willy Tarreaubbebbbf2012-05-07 21:22:09 +0200261 }
262
263 if (global.cps_lim && !(l->options & LI_O_UNLIMITED)) {
264 int max = freq_ctr_remain(&global.conn_per_sec, global.cps_lim, 0);
265
266 if (unlikely(!max)) {
267 /* frontend accept rate limit was reached */
268 limit_listener(l, &global_listener_queue);
269 task_schedule(global_listener_queue_task, tick_add(now_ms, next_event_delay(&global.conn_per_sec, global.cps_lim, 0)));
Willy Tarreauafad0e02012-08-09 14:45:22 +0200270 return;
Willy Tarreaubbebbbf2012-05-07 21:22:09 +0200271 }
272
273 if (max_accept > max)
274 max_accept = max;
275 }
276
277 if (p && p->fe_sps_lim) {
278 int max = freq_ctr_remain(&p->fe_sess_per_sec, p->fe_sps_lim, 0);
279
280 if (unlikely(!max)) {
281 /* frontend accept rate limit was reached */
282 limit_listener(l, &p->listener_queue);
283 task_schedule(p->task, tick_add(now_ms, next_event_delay(&p->fe_sess_per_sec, p->fe_sps_lim, 0)));
Willy Tarreauafad0e02012-08-09 14:45:22 +0200284 return;
Willy Tarreaubbebbbf2012-05-07 21:22:09 +0200285 }
286
287 if (max_accept > max)
288 max_accept = max;
289 }
290
291 /* Note: if we fail to allocate a connection because of configured
292 * limits, we'll schedule a new attempt worst 1 second later in the
293 * worst case. If we fail due to system limits or temporary resource
294 * shortage, we try again 100ms later in the worst case.
295 */
296 while (max_accept--) {
297 struct sockaddr_storage addr;
298 socklen_t laddr = sizeof(addr);
299
300 if (unlikely(actconn >= global.maxconn) && !(l->options & LI_O_UNLIMITED)) {
301 limit_listener(l, &global_listener_queue);
302 task_schedule(global_listener_queue_task, tick_add(now_ms, 1000)); /* try again in 1 second */
Willy Tarreauafad0e02012-08-09 14:45:22 +0200303 return;
Willy Tarreaubbebbbf2012-05-07 21:22:09 +0200304 }
305
306 if (unlikely(p && p->feconn >= p->maxconn)) {
307 limit_listener(l, &p->listener_queue);
Willy Tarreauafad0e02012-08-09 14:45:22 +0200308 return;
Willy Tarreaubbebbbf2012-05-07 21:22:09 +0200309 }
310
311 cfd = accept(fd, (struct sockaddr *)&addr, &laddr);
312 if (unlikely(cfd == -1)) {
313 switch (errno) {
314 case EAGAIN:
315 case EINTR:
316 case ECONNABORTED:
Willy Tarreauafad0e02012-08-09 14:45:22 +0200317 fd_poll_recv(fd);
318 return; /* nothing more to accept */
Willy Tarreaubbebbbf2012-05-07 21:22:09 +0200319 case ENFILE:
320 if (p)
321 send_log(p, LOG_EMERG,
322 "Proxy %s reached system FD limit at %d. Please check system tunables.\n",
323 p->id, maxfd);
324 limit_listener(l, &global_listener_queue);
325 task_schedule(global_listener_queue_task, tick_add(now_ms, 100)); /* try again in 100 ms */
Willy Tarreauafad0e02012-08-09 14:45:22 +0200326 return;
Willy Tarreaubbebbbf2012-05-07 21:22:09 +0200327 case EMFILE:
328 if (p)
329 send_log(p, LOG_EMERG,
330 "Proxy %s reached process FD limit at %d. Please check 'ulimit-n' and restart.\n",
331 p->id, maxfd);
332 limit_listener(l, &global_listener_queue);
333 task_schedule(global_listener_queue_task, tick_add(now_ms, 100)); /* try again in 100 ms */
Willy Tarreauafad0e02012-08-09 14:45:22 +0200334 return;
Willy Tarreaubbebbbf2012-05-07 21:22:09 +0200335 case ENOBUFS:
336 case ENOMEM:
337 if (p)
338 send_log(p, LOG_EMERG,
339 "Proxy %s reached system memory limit at %d sockets. Please check system tunables.\n",
340 p->id, maxfd);
341 limit_listener(l, &global_listener_queue);
342 task_schedule(global_listener_queue_task, tick_add(now_ms, 100)); /* try again in 100 ms */
Willy Tarreauafad0e02012-08-09 14:45:22 +0200343 return;
Willy Tarreaubbebbbf2012-05-07 21:22:09 +0200344 default:
Willy Tarreauafad0e02012-08-09 14:45:22 +0200345 /* unexpected result, let's go back to poll */
346 fd_poll_recv(fd);
347 return;
Willy Tarreaubbebbbf2012-05-07 21:22:09 +0200348 }
349 }
350
351 if (unlikely(cfd >= global.maxsock)) {
352 send_log(p, LOG_EMERG,
353 "Proxy %s reached the configured maximum connection limit. Please check the global 'maxconn' value.\n",
354 p->id);
355 close(cfd);
356 limit_listener(l, &global_listener_queue);
357 task_schedule(global_listener_queue_task, tick_add(now_ms, 1000)); /* try again in 1 second */
Willy Tarreauafad0e02012-08-09 14:45:22 +0200358 return;
Willy Tarreaubbebbbf2012-05-07 21:22:09 +0200359 }
360
361 /* increase the per-process number of cumulated connections */
362 if (!(l->options & LI_O_UNLIMITED)) {
363 update_freq_ctr(&global.conn_per_sec, 1);
364 if (global.conn_per_sec.curr_ctr > global.cps_max)
365 global.cps_max = global.conn_per_sec.curr_ctr;
366 actconn++;
367 }
368
369 jobs++;
370 totalconn++;
371 l->nbconn++;
372
373 if (l->counters) {
374 if (l->nbconn > l->counters->conn_max)
375 l->counters->conn_max = l->nbconn;
376 }
377
378 ret = l->accept(l, cfd, &addr);
379 if (unlikely(ret <= 0)) {
380 /* The connection was closed by session_accept(). Either
381 * we just have to ignore it (ret == 0) or it's a critical
382 * error due to a resource shortage, and we must stop the
383 * listener (ret < 0).
384 */
385 if (!(l->options & LI_O_UNLIMITED))
386 actconn--;
387 jobs--;
388 l->nbconn--;
389 if (ret == 0) /* successful termination */
390 continue;
391
392 limit_listener(l, &global_listener_queue);
393 task_schedule(global_listener_queue_task, tick_add(now_ms, 100)); /* try again in 100 ms */
Willy Tarreauafad0e02012-08-09 14:45:22 +0200394 return;
Willy Tarreaubbebbbf2012-05-07 21:22:09 +0200395 }
396
397 if (l->nbconn >= l->maxconn) {
398 listener_full(l);
Willy Tarreauafad0e02012-08-09 14:45:22 +0200399 return;
Willy Tarreaubbebbbf2012-05-07 21:22:09 +0200400 }
401
Willy Tarreauaece46a2012-07-06 12:25:58 +0200402 } /* end of while (max_accept--) */
Willy Tarreaubbebbbf2012-05-07 21:22:09 +0200403
Willy Tarreauaece46a2012-07-06 12:25:58 +0200404 /* we've exhausted max_accept, so there is no need to poll again */
Willy Tarreauafad0e02012-08-09 14:45:22 +0200405 return;
Willy Tarreaubbebbbf2012-05-07 21:22:09 +0200406}
407
Willy Tarreau26982662012-09-12 23:17:10 +0200408/*
409 * Registers the bind keyword list <kwl> as a list of valid keywords for next
410 * parsing sessions.
411 */
412void bind_register_keywords(struct bind_kw_list *kwl)
413{
414 LIST_ADDQ(&bind_keywords.list, &kwl->list);
415}
416
417/* Return a pointer to the bind keyword <kw>, or NULL if not found. If the
418 * keyword is found with a NULL ->parse() function, then an attempt is made to
419 * find one with a valid ->parse() function. This way it is possible to declare
420 * platform-dependant, known keywords as NULL, then only declare them as valid
421 * if some options are met. Note that if the requested keyword contains an
422 * opening parenthesis, everything from this point is ignored.
423 */
424struct bind_kw *bind_find_kw(const char *kw)
425{
426 int index;
427 const char *kwend;
428 struct bind_kw_list *kwl;
429 struct bind_kw *ret = NULL;
430
431 kwend = strchr(kw, '(');
432 if (!kwend)
433 kwend = kw + strlen(kw);
434
435 list_for_each_entry(kwl, &bind_keywords.list, list) {
436 for (index = 0; kwl->kw[index].kw != NULL; index++) {
437 if ((strncmp(kwl->kw[index].kw, kw, kwend - kw) == 0) &&
438 kwl->kw[index].kw[kwend-kw] == 0) {
439 if (kwl->kw[index].parse)
440 return &kwl->kw[index]; /* found it !*/
441 else
442 ret = &kwl->kw[index]; /* may be OK */
443 }
444 }
445 }
446 return ret;
447}
448
Willy Tarreau8638f482012-09-18 18:01:17 +0200449/* Dumps all registered "bind" keywords to the <out> string pointer. The
450 * unsupported keywords are only dumped if their supported form was not
451 * found.
452 */
453void bind_dump_kws(char **out)
454{
455 struct bind_kw_list *kwl;
456 int index;
457
458 *out = NULL;
459 list_for_each_entry(kwl, &bind_keywords.list, list) {
460 for (index = 0; kwl->kw[index].kw != NULL; index++) {
461 if (kwl->kw[index].parse ||
462 bind_find_kw(kwl->kw[index].kw) == &kwl->kw[index]) {
Willy Tarreau51fb7652012-09-18 18:24:39 +0200463 memprintf(out, "%s[%4s] %s%s%s\n", *out ? *out : "",
464 kwl->scope,
Willy Tarreau8638f482012-09-18 18:01:17 +0200465 kwl->kw[index].kw,
Willy Tarreau51fb7652012-09-18 18:24:39 +0200466 kwl->kw[index].skip ? " <arg>" : "",
467 kwl->kw[index].parse ? "" : " (not supported)");
Willy Tarreau8638f482012-09-18 18:01:17 +0200468 }
469 }
470 }
471}
472
Willy Tarreau645513a2010-05-24 20:55:15 +0200473/************************************************************************/
474/* All supported ACL keywords must be declared here. */
475/************************************************************************/
476
Willy Tarreaua5e37562011-12-16 17:06:15 +0100477/* set temp integer to the number of connexions to the same listening socket */
Willy Tarreau645513a2010-05-24 20:55:15 +0200478static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +0200479acl_fetch_dconn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +0200480 const struct arg *args, struct sample *smp)
Willy Tarreau645513a2010-05-24 20:55:15 +0200481{
Willy Tarreauf853c462012-04-23 18:53:56 +0200482 smp->type = SMP_T_UINT;
483 smp->data.uint = l4->listener->nbconn;
Willy Tarreau645513a2010-05-24 20:55:15 +0200484 return 1;
485}
486
Willy Tarreaua5e37562011-12-16 17:06:15 +0100487/* set temp integer to the id of the socket (listener) */
Willy Tarreau645513a2010-05-24 20:55:15 +0200488static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +0200489acl_fetch_so_id(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +0200490 const struct arg *args, struct sample *smp)
Willy Tarreau37406352012-04-23 16:16:37 +0200491{
Willy Tarreauf853c462012-04-23 18:53:56 +0200492 smp->type = SMP_T_UINT;
493 smp->data.uint = l4->listener->luid;
Willy Tarreau645513a2010-05-24 20:55:15 +0200494 return 1;
495}
496
Willy Tarreau3dcc3412012-09-18 17:17:28 +0200497/* parse the "accept-proxy" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +0200498static int bind_parse_accept_proxy(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
Willy Tarreau3dcc3412012-09-18 17:17:28 +0200499{
500 struct listener *l;
501
Willy Tarreau4348fad2012-09-20 16:48:07 +0200502 list_for_each_entry(l, &conf->listeners, by_bind)
Willy Tarreau3dcc3412012-09-18 17:17:28 +0200503 l->options |= LI_O_ACC_PROXY;
504
505 return 0;
506}
507
508/* parse the "backlog" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +0200509static int bind_parse_backlog(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
Willy Tarreau3dcc3412012-09-18 17:17:28 +0200510{
511 struct listener *l;
512 int val;
513
514 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200515 memprintf(err, "'%s' : missing value", args[cur_arg]);
Willy Tarreau3dcc3412012-09-18 17:17:28 +0200516 return ERR_ALERT | ERR_FATAL;
517 }
518
519 val = atol(args[cur_arg + 1]);
520 if (val <= 0) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200521 memprintf(err, "'%s' : invalid value %d, must be > 0", args[cur_arg], val);
Willy Tarreau3dcc3412012-09-18 17:17:28 +0200522 return ERR_ALERT | ERR_FATAL;
523 }
524
Willy Tarreau4348fad2012-09-20 16:48:07 +0200525 list_for_each_entry(l, &conf->listeners, by_bind)
Willy Tarreau3dcc3412012-09-18 17:17:28 +0200526 l->backlog = val;
527
528 return 0;
529}
530
531/* parse the "id" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +0200532static int bind_parse_id(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
Willy Tarreau3dcc3412012-09-18 17:17:28 +0200533{
534 struct eb32_node *node;
Willy Tarreau4348fad2012-09-20 16:48:07 +0200535 struct listener *l, *new;
Willy Tarreau3dcc3412012-09-18 17:17:28 +0200536
Willy Tarreau4348fad2012-09-20 16:48:07 +0200537 if (conf->listeners.n != conf->listeners.p) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200538 memprintf(err, "'%s' can only be used with a single socket", args[cur_arg]);
Willy Tarreau3dcc3412012-09-18 17:17:28 +0200539 return ERR_ALERT | ERR_FATAL;
540 }
541
542 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200543 memprintf(err, "'%s' : expects an integer argument", args[cur_arg]);
Willy Tarreau3dcc3412012-09-18 17:17:28 +0200544 return ERR_ALERT | ERR_FATAL;
545 }
546
Willy Tarreau4348fad2012-09-20 16:48:07 +0200547 new = LIST_NEXT(&conf->listeners, struct listener *, by_bind);
548 new->luid = atol(args[cur_arg + 1]);
549 new->conf.id.key = new->luid;
Willy Tarreau3dcc3412012-09-18 17:17:28 +0200550
Willy Tarreau4348fad2012-09-20 16:48:07 +0200551 if (new->luid <= 0) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200552 memprintf(err, "'%s' : custom id has to be > 0", args[cur_arg]);
Willy Tarreau3dcc3412012-09-18 17:17:28 +0200553 return ERR_ALERT | ERR_FATAL;
554 }
555
Willy Tarreau4348fad2012-09-20 16:48:07 +0200556 node = eb32_lookup(&px->conf.used_listener_id, new->luid);
Willy Tarreau3dcc3412012-09-18 17:17:28 +0200557 if (node) {
558 l = container_of(node, struct listener, conf.id);
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200559 memprintf(err, "'%s' : custom id %d already used at %s:%d ('bind %s')",
560 args[cur_arg], l->luid, l->bind_conf->file, l->bind_conf->line,
561 l->bind_conf->arg);
Willy Tarreau3dcc3412012-09-18 17:17:28 +0200562 return ERR_ALERT | ERR_FATAL;
563 }
564
Willy Tarreau4348fad2012-09-20 16:48:07 +0200565 eb32_insert(&px->conf.used_listener_id, &new->conf.id);
Willy Tarreau3dcc3412012-09-18 17:17:28 +0200566 return 0;
567}
568
569/* parse the "maxconn" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +0200570static int bind_parse_maxconn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
Willy Tarreau3dcc3412012-09-18 17:17:28 +0200571{
572 struct listener *l;
573 int val;
574
575 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200576 memprintf(err, "'%s' : missing value", args[cur_arg]);
Willy Tarreau3dcc3412012-09-18 17:17:28 +0200577 return ERR_ALERT | ERR_FATAL;
578 }
579
580 val = atol(args[cur_arg + 1]);
581 if (val <= 0) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200582 memprintf(err, "'%s' : invalid value %d, must be > 0", args[cur_arg], val);
Willy Tarreau3dcc3412012-09-18 17:17:28 +0200583 return ERR_ALERT | ERR_FATAL;
584 }
585
Willy Tarreau4348fad2012-09-20 16:48:07 +0200586 list_for_each_entry(l, &conf->listeners, by_bind)
Willy Tarreau3dcc3412012-09-18 17:17:28 +0200587 l->maxconn = val;
588
589 return 0;
590}
591
592/* parse the "name" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +0200593static int bind_parse_name(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
Willy Tarreau3dcc3412012-09-18 17:17:28 +0200594{
595 struct listener *l;
596
597 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200598 memprintf(err, "'%s' : missing name", args[cur_arg]);
Willy Tarreau3dcc3412012-09-18 17:17:28 +0200599 return ERR_ALERT | ERR_FATAL;
600 }
601
Willy Tarreau4348fad2012-09-20 16:48:07 +0200602 list_for_each_entry(l, &conf->listeners, by_bind)
Willy Tarreau3dcc3412012-09-18 17:17:28 +0200603 l->name = strdup(args[cur_arg + 1]);
604
605 return 0;
606}
607
608/* parse the "nice" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +0200609static int bind_parse_nice(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
Willy Tarreau3dcc3412012-09-18 17:17:28 +0200610{
611 struct listener *l;
612 int val;
613
614 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200615 memprintf(err, "'%s' : missing value", args[cur_arg]);
Willy Tarreau3dcc3412012-09-18 17:17:28 +0200616 return ERR_ALERT | ERR_FATAL;
617 }
618
619 val = atol(args[cur_arg + 1]);
620 if (val < -1024 || val > 1024) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200621 memprintf(err, "'%s' : invalid value %d, allowed range is -1024..1024", args[cur_arg], val);
Willy Tarreau3dcc3412012-09-18 17:17:28 +0200622 return ERR_ALERT | ERR_FATAL;
623 }
624
Willy Tarreau4348fad2012-09-20 16:48:07 +0200625 list_for_each_entry(l, &conf->listeners, by_bind)
Willy Tarreau3dcc3412012-09-18 17:17:28 +0200626 l->nice = val;
627
628 return 0;
629}
630
631
Willy Tarreau61612d42012-04-19 18:42:05 +0200632/* Note: must not be declared <const> as its list will be overwritten.
633 * Please take care of keeping this list alphabetically sorted.
634 */
Willy Tarreau645513a2010-05-24 20:55:15 +0200635static struct acl_kw_list acl_kws = {{ },{
Willy Tarreau61612d42012-04-19 18:42:05 +0200636 { "dst_conn", acl_parse_int, acl_fetch_dconn, acl_match_int, ACL_USE_NOTHING, 0 },
637 { "so_id", acl_parse_int, acl_fetch_so_id, acl_match_int, ACL_USE_NOTHING, 0 },
Willy Tarreau645513a2010-05-24 20:55:15 +0200638 { NULL, NULL, NULL, NULL },
639}};
640
Willy Tarreau3dcc3412012-09-18 17:17:28 +0200641/* Note: must not be declared <const> as its list will be overwritten.
642 * Please take care of keeping this list alphabetically sorted, doing so helps
643 * all code contributors.
644 * Optional keywords are also declared with a NULL ->parse() function so that
645 * the config parser can report an appropriate error when a known keyword was
646 * not enabled.
647 */
Willy Tarreau51fb7652012-09-18 18:24:39 +0200648static struct bind_kw_list bind_kws = { "ALL", { }, {
Willy Tarreau3dcc3412012-09-18 17:17:28 +0200649 { "accept-proxy", bind_parse_accept_proxy, 0 }, /* enable PROXY protocol */
650 { "backlog", bind_parse_backlog, 1 }, /* set backlog of listening socket */
651 { "id", bind_parse_id, 1 }, /* set id of listening socket */
652 { "maxconn", bind_parse_maxconn, 1 }, /* set maxconn of listening socket */
653 { "name", bind_parse_name, 1 }, /* set name of listening socket */
654 { "nice", bind_parse_nice, 1 }, /* set nice of listening socket */
655 { NULL, NULL, 0 },
656}};
657
Willy Tarreau645513a2010-05-24 20:55:15 +0200658__attribute__((constructor))
Willy Tarreaud1d54542012-09-12 22:58:11 +0200659static void __listener_init(void)
Willy Tarreau645513a2010-05-24 20:55:15 +0200660{
661 acl_register_keywords(&acl_kws);
Willy Tarreau3dcc3412012-09-18 17:17:28 +0200662 bind_register_keywords(&bind_kws);
Willy Tarreau645513a2010-05-24 20:55:15 +0200663}
664
665/*
666 * Local variables:
667 * c-indent-level: 8
668 * c-basic-offset: 8
669 * End:
670 */