blob: afd6ae2250c238e9fee8b4e5753070469660803f [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 Tarreau0ccb7442013-01-07 22:54:17 +01004 * Copyright 2000-2013 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
Willy Tarreau1bc4aab2012-10-08 20:11:03 +020017#include <common/accept4.h>
Willy Tarreaudd815982007-10-16 12:25:14 +020018#include <common/config.h>
Willy Tarreaudabf2e22007-10-28 21:59:24 +010019#include <common/errors.h>
Willy Tarreaudd815982007-10-16 12:25:14 +020020#include <common/mini-clist.h>
21#include <common/standard.h>
Willy Tarreaubbebbbf2012-05-07 21:22:09 +020022#include <common/time.h>
23
24#include <types/global.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020025#include <types/protocol.h>
Willy Tarreaudd815982007-10-16 12:25:14 +020026
Willy Tarreau645513a2010-05-24 20:55:15 +020027#include <proto/acl.h>
Willy Tarreaub648d632007-10-28 22:13:50 +010028#include <proto/fd.h>
Willy Tarreaubbebbbf2012-05-07 21:22:09 +020029#include <proto/freq_ctr.h>
30#include <proto/log.h>
Willy Tarreau0ccb7442013-01-07 22:54:17 +010031#include <proto/sample.h>
Willy Tarreaubbebbbf2012-05-07 21:22:09 +020032#include <proto/task.h>
Willy Tarreaub648d632007-10-28 22:13:50 +010033
Willy Tarreau26982662012-09-12 23:17:10 +020034/* List head of all known bind keywords */
35static struct bind_kw_list bind_keywords = {
36 .list = LIST_HEAD_INIT(bind_keywords.list)
37};
38
Willy Tarreaudabf2e22007-10-28 21:59:24 +010039/* This function adds the specified listener's file descriptor to the polling
40 * lists if it is in the LI_LISTEN state. The listener enters LI_READY or
41 * LI_FULL state depending on its number of connections.
42 */
43void enable_listener(struct listener *listener)
44{
45 if (listener->state == LI_LISTEN) {
46 if (listener->nbconn < listener->maxconn) {
Willy Tarreau49b046d2012-08-09 12:11:58 +020047 fd_want_recv(listener->fd);
Willy Tarreaudabf2e22007-10-28 21:59:24 +010048 listener->state = LI_READY;
49 } else {
50 listener->state = LI_FULL;
51 }
52 }
53}
54
55/* This function removes the specified listener's file descriptor from the
56 * polling lists if it is in the LI_READY or in the LI_FULL state. The listener
57 * enters LI_LISTEN.
58 */
59void disable_listener(struct listener *listener)
60{
61 if (listener->state < LI_READY)
62 return;
63 if (listener->state == LI_READY)
Willy Tarreau49b046d2012-08-09 12:11:58 +020064 fd_stop_recv(listener->fd);
Willy Tarreaue6ca1fc2011-07-24 22:03:52 +020065 if (listener->state == LI_LIMITED)
66 LIST_DEL(&listener->wait_queue);
Willy Tarreaudabf2e22007-10-28 21:59:24 +010067 listener->state = LI_LISTEN;
68}
69
Willy Tarreaube58c382011-07-24 18:28:10 +020070/* This function tries to temporarily disable a listener, depending on the OS
71 * capabilities. Linux unbinds the listen socket after a SHUT_RD, and ignores
72 * SHUT_WR. Solaris refuses either shutdown(). OpenBSD ignores SHUT_RD but
73 * closes upon SHUT_WR and refuses to rebind. So a common validation path
74 * involves SHUT_WR && listen && SHUT_RD. In case of success, the FD's polling
75 * is disabled. It normally returns non-zero, unless an error is reported.
76 */
77int pause_listener(struct listener *l)
78{
79 if (l->state <= LI_PAUSED)
80 return 1;
81
Willy Tarreaub3fb60b2012-10-04 08:56:31 +020082 if (l->proto->sock_prot == IPPROTO_TCP) {
83 if (shutdown(l->fd, SHUT_WR) != 0)
84 return 0; /* Solaris dies here */
Willy Tarreaube58c382011-07-24 18:28:10 +020085
Willy Tarreaub3fb60b2012-10-04 08:56:31 +020086 if (listen(l->fd, l->backlog ? l->backlog : l->maxconn) != 0)
87 return 0; /* OpenBSD dies here */
Willy Tarreaube58c382011-07-24 18:28:10 +020088
Willy Tarreaub3fb60b2012-10-04 08:56:31 +020089 if (shutdown(l->fd, SHUT_RD) != 0)
90 return 0; /* should always be OK */
91 }
Willy Tarreaube58c382011-07-24 18:28:10 +020092
Willy Tarreaue6ca1fc2011-07-24 22:03:52 +020093 if (l->state == LI_LIMITED)
94 LIST_DEL(&l->wait_queue);
95
Willy Tarreau49b046d2012-08-09 12:11:58 +020096 fd_stop_recv(l->fd);
Willy Tarreaube58c382011-07-24 18:28:10 +020097 l->state = LI_PAUSED;
98 return 1;
99}
100
Willy Tarreaue6ca1fc2011-07-24 22:03:52 +0200101/* This function tries to resume a temporarily disabled listener. Paused, full,
102 * limited and disabled listeners are handled, which means that this function
103 * may replace enable_listener(). The resulting state will either be LI_READY
104 * or LI_FULL. 0 is returned in case of failure to resume (eg: dead socket).
Willy Tarreaube58c382011-07-24 18:28:10 +0200105 */
106int resume_listener(struct listener *l)
107{
108 if (l->state < LI_PAUSED)
109 return 0;
110
Willy Tarreaub3fb60b2012-10-04 08:56:31 +0200111 if (l->proto->sock_prot == IPPROTO_TCP &&
112 l->state == LI_PAUSED &&
Willy Tarreaube58c382011-07-24 18:28:10 +0200113 listen(l->fd, l->backlog ? l->backlog : l->maxconn) != 0)
114 return 0;
115
116 if (l->state == LI_READY)
117 return 1;
118
Willy Tarreaue6ca1fc2011-07-24 22:03:52 +0200119 if (l->state == LI_LIMITED)
120 LIST_DEL(&l->wait_queue);
121
Willy Tarreaube58c382011-07-24 18:28:10 +0200122 if (l->nbconn >= l->maxconn) {
123 l->state = LI_FULL;
124 return 1;
125 }
126
Willy Tarreau49b046d2012-08-09 12:11:58 +0200127 fd_want_recv(l->fd);
Willy Tarreaube58c382011-07-24 18:28:10 +0200128 l->state = LI_READY;
129 return 1;
130}
131
Willy Tarreau62793712011-07-24 19:23:38 +0200132/* Marks a ready listener as full so that the session code tries to re-enable
133 * it upon next close() using resume_listener().
134 */
135void listener_full(struct listener *l)
136{
137 if (l->state >= LI_READY) {
Willy Tarreaue6ca1fc2011-07-24 22:03:52 +0200138 if (l->state == LI_LIMITED)
139 LIST_DEL(&l->wait_queue);
140
Willy Tarreau49b046d2012-08-09 12:11:58 +0200141 fd_stop_recv(l->fd);
Willy Tarreau62793712011-07-24 19:23:38 +0200142 l->state = LI_FULL;
143 }
144}
145
Willy Tarreaue6ca1fc2011-07-24 22:03:52 +0200146/* Marks a ready listener as limited so that we only try to re-enable it when
147 * resources are free again. It will be queued into the specified queue.
148 */
149void limit_listener(struct listener *l, struct list *list)
150{
151 if (l->state == LI_READY) {
152 LIST_ADDQ(list, &l->wait_queue);
Willy Tarreau49b046d2012-08-09 12:11:58 +0200153 fd_stop_recv(l->fd);
Willy Tarreaue6ca1fc2011-07-24 22:03:52 +0200154 l->state = LI_LIMITED;
155 }
156}
157
Willy Tarreaudabf2e22007-10-28 21:59:24 +0100158/* This function adds all of the protocol's listener's file descriptors to the
159 * polling lists when they are in the LI_LISTEN state. It is intended to be
160 * used as a protocol's generic enable_all() primitive, for use after the
161 * fork(). It puts the listeners into LI_READY or LI_FULL states depending on
162 * their number of connections. It always returns ERR_NONE.
163 */
164int enable_all_listeners(struct protocol *proto)
165{
166 struct listener *listener;
167
168 list_for_each_entry(listener, &proto->listeners, proto_list)
169 enable_listener(listener);
170 return ERR_NONE;
171}
172
173/* This function removes all of the protocol's listener's file descriptors from
174 * the polling lists when they are in the LI_READY or LI_FULL states. It is
175 * intended to be used as a protocol's generic disable_all() primitive. It puts
176 * the listeners into LI_LISTEN, and always returns ERR_NONE.
177 */
178int disable_all_listeners(struct protocol *proto)
179{
180 struct listener *listener;
181
182 list_for_each_entry(listener, &proto->listeners, proto_list)
183 disable_listener(listener);
184 return ERR_NONE;
185}
186
Willy Tarreaue6ca1fc2011-07-24 22:03:52 +0200187/* Dequeues all of the listeners waiting for a resource in wait queue <queue>. */
188void dequeue_all_listeners(struct list *list)
189{
190 struct listener *listener, *l_back;
191
192 list_for_each_entry_safe(listener, l_back, list, wait_queue) {
193 /* This cannot fail because the listeners are by definition in
194 * the LI_LIMITED state. The function also removes the entry
195 * from the queue.
196 */
197 resume_listener(listener);
198 }
199}
200
Willy Tarreaub648d632007-10-28 22:13:50 +0100201/* This function closes the listening socket for the specified listener,
202 * provided that it's already in a listening state. The listener enters the
203 * LI_ASSIGNED state. It always returns ERR_NONE. This function is intended
204 * to be used as a generic function for standard protocols.
205 */
206int unbind_listener(struct listener *listener)
207{
208 if (listener->state == LI_READY)
Willy Tarreau49b046d2012-08-09 12:11:58 +0200209 fd_stop_recv(listener->fd);
Willy Tarreaub648d632007-10-28 22:13:50 +0100210
Willy Tarreaue6ca1fc2011-07-24 22:03:52 +0200211 if (listener->state == LI_LIMITED)
212 LIST_DEL(&listener->wait_queue);
213
Willy Tarreaube58c382011-07-24 18:28:10 +0200214 if (listener->state >= LI_PAUSED) {
Willy Tarreaub648d632007-10-28 22:13:50 +0100215 fd_delete(listener->fd);
216 listener->state = LI_ASSIGNED;
217 }
218 return ERR_NONE;
219}
220
Willy Tarreau3acf8c32007-10-28 22:35:41 +0100221/* This function closes all listening sockets bound to the protocol <proto>,
222 * and the listeners end in LI_ASSIGNED state if they were higher. It does not
223 * detach them from the protocol. It always returns ERR_NONE.
224 */
225int unbind_all_listeners(struct protocol *proto)
226{
227 struct listener *listener;
228
229 list_for_each_entry(listener, &proto->listeners, proto_list)
230 unbind_listener(listener);
231 return ERR_NONE;
232}
233
Willy Tarreau1a64d162007-10-28 22:26:05 +0100234/* Delete a listener from its protocol's list of listeners. The listener's
235 * state is automatically updated from LI_ASSIGNED to LI_INIT. The protocol's
236 * number of listeners is updated. Note that the listener must have previously
237 * been unbound. This is the generic function to use to remove a listener.
238 */
239void delete_listener(struct listener *listener)
240{
241 if (listener->state != LI_ASSIGNED)
242 return;
243 listener->state = LI_INIT;
244 LIST_DEL(&listener->proto_list);
245 listener->proto->nb_listeners--;
246}
247
Willy Tarreaubbebbbf2012-05-07 21:22:09 +0200248/* This function is called on a read event from a listening socket, corresponding
249 * to an accept. It tries to accept as many connections as possible, and for each
250 * calls the listener's accept handler (generally the frontend's accept handler).
251 */
Willy Tarreauafad0e02012-08-09 14:45:22 +0200252void listener_accept(int fd)
Willy Tarreaubbebbbf2012-05-07 21:22:09 +0200253{
254 struct listener *l = fdtab[fd].owner;
255 struct proxy *p = l->frontend;
Willy Tarreau50de90a2012-11-23 20:11:45 +0100256 int max_accept = l->maxaccept ? l->maxaccept : 1;
Willy Tarreaubbebbbf2012-05-07 21:22:09 +0200257 int cfd;
258 int ret;
259
260 if (unlikely(l->nbconn >= l->maxconn)) {
261 listener_full(l);
Willy Tarreauafad0e02012-08-09 14:45:22 +0200262 return;
Willy Tarreaubbebbbf2012-05-07 21:22:09 +0200263 }
264
265 if (global.cps_lim && !(l->options & LI_O_UNLIMITED)) {
266 int max = freq_ctr_remain(&global.conn_per_sec, global.cps_lim, 0);
267
268 if (unlikely(!max)) {
269 /* frontend accept rate limit was reached */
270 limit_listener(l, &global_listener_queue);
271 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 +0200272 return;
Willy Tarreaubbebbbf2012-05-07 21:22:09 +0200273 }
274
275 if (max_accept > max)
276 max_accept = max;
277 }
278
279 if (p && p->fe_sps_lim) {
280 int max = freq_ctr_remain(&p->fe_sess_per_sec, p->fe_sps_lim, 0);
281
282 if (unlikely(!max)) {
283 /* frontend accept rate limit was reached */
284 limit_listener(l, &p->listener_queue);
285 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 +0200286 return;
Willy Tarreaubbebbbf2012-05-07 21:22:09 +0200287 }
288
289 if (max_accept > max)
290 max_accept = max;
291 }
292
293 /* Note: if we fail to allocate a connection because of configured
294 * limits, we'll schedule a new attempt worst 1 second later in the
295 * worst case. If we fail due to system limits or temporary resource
296 * shortage, we try again 100ms later in the worst case.
297 */
298 while (max_accept--) {
299 struct sockaddr_storage addr;
300 socklen_t laddr = sizeof(addr);
301
302 if (unlikely(actconn >= global.maxconn) && !(l->options & LI_O_UNLIMITED)) {
303 limit_listener(l, &global_listener_queue);
304 task_schedule(global_listener_queue_task, tick_add(now_ms, 1000)); /* try again in 1 second */
Willy Tarreauafad0e02012-08-09 14:45:22 +0200305 return;
Willy Tarreaubbebbbf2012-05-07 21:22:09 +0200306 }
307
308 if (unlikely(p && p->feconn >= p->maxconn)) {
309 limit_listener(l, &p->listener_queue);
Willy Tarreauafad0e02012-08-09 14:45:22 +0200310 return;
Willy Tarreaubbebbbf2012-05-07 21:22:09 +0200311 }
312
Willy Tarreau1bc4aab2012-10-08 20:11:03 +0200313#ifdef USE_ACCEPT4
314 cfd = accept4(fd, (struct sockaddr *)&addr, &laddr, SOCK_NONBLOCK);
Willy Tarreau6b3b0d42012-10-22 19:32:55 +0200315 if (unlikely(cfd == -1 && errno == EINVAL)) {
316 /* unsupported syscall, fallback to normal accept()+fcntl() */
317 if ((cfd = accept(fd, (struct sockaddr *)&addr, &laddr)) != -1)
318 fcntl(cfd, F_SETFL, O_NONBLOCK);
319 }
Willy Tarreau1bc4aab2012-10-08 20:11:03 +0200320#else
Willy Tarreaubbebbbf2012-05-07 21:22:09 +0200321 cfd = accept(fd, (struct sockaddr *)&addr, &laddr);
Willy Tarreau1bc4aab2012-10-08 20:11:03 +0200322#endif
Willy Tarreaubbebbbf2012-05-07 21:22:09 +0200323 if (unlikely(cfd == -1)) {
324 switch (errno) {
325 case EAGAIN:
326 case EINTR:
327 case ECONNABORTED:
Willy Tarreauafad0e02012-08-09 14:45:22 +0200328 fd_poll_recv(fd);
329 return; /* nothing more to accept */
Willy Tarreaubbebbbf2012-05-07 21:22:09 +0200330 case ENFILE:
331 if (p)
332 send_log(p, LOG_EMERG,
333 "Proxy %s reached system FD limit at %d. Please check system tunables.\n",
334 p->id, maxfd);
335 limit_listener(l, &global_listener_queue);
336 task_schedule(global_listener_queue_task, tick_add(now_ms, 100)); /* try again in 100 ms */
Willy Tarreauafad0e02012-08-09 14:45:22 +0200337 return;
Willy Tarreaubbebbbf2012-05-07 21:22:09 +0200338 case EMFILE:
339 if (p)
340 send_log(p, LOG_EMERG,
341 "Proxy %s reached process FD limit at %d. Please check 'ulimit-n' and restart.\n",
342 p->id, maxfd);
343 limit_listener(l, &global_listener_queue);
344 task_schedule(global_listener_queue_task, tick_add(now_ms, 100)); /* try again in 100 ms */
Willy Tarreauafad0e02012-08-09 14:45:22 +0200345 return;
Willy Tarreaubbebbbf2012-05-07 21:22:09 +0200346 case ENOBUFS:
347 case ENOMEM:
348 if (p)
349 send_log(p, LOG_EMERG,
350 "Proxy %s reached system memory limit at %d sockets. Please check system tunables.\n",
351 p->id, maxfd);
352 limit_listener(l, &global_listener_queue);
353 task_schedule(global_listener_queue_task, tick_add(now_ms, 100)); /* try again in 100 ms */
Willy Tarreauafad0e02012-08-09 14:45:22 +0200354 return;
Willy Tarreaubbebbbf2012-05-07 21:22:09 +0200355 default:
Willy Tarreauafad0e02012-08-09 14:45:22 +0200356 /* unexpected result, let's go back to poll */
357 fd_poll_recv(fd);
358 return;
Willy Tarreaubbebbbf2012-05-07 21:22:09 +0200359 }
360 }
361
362 if (unlikely(cfd >= global.maxsock)) {
363 send_log(p, LOG_EMERG,
364 "Proxy %s reached the configured maximum connection limit. Please check the global 'maxconn' value.\n",
365 p->id);
366 close(cfd);
367 limit_listener(l, &global_listener_queue);
368 task_schedule(global_listener_queue_task, tick_add(now_ms, 1000)); /* try again in 1 second */
Willy Tarreauafad0e02012-08-09 14:45:22 +0200369 return;
Willy Tarreaubbebbbf2012-05-07 21:22:09 +0200370 }
371
372 /* increase the per-process number of cumulated connections */
373 if (!(l->options & LI_O_UNLIMITED)) {
374 update_freq_ctr(&global.conn_per_sec, 1);
375 if (global.conn_per_sec.curr_ctr > global.cps_max)
376 global.cps_max = global.conn_per_sec.curr_ctr;
377 actconn++;
378 }
379
380 jobs++;
381 totalconn++;
382 l->nbconn++;
383
384 if (l->counters) {
385 if (l->nbconn > l->counters->conn_max)
386 l->counters->conn_max = l->nbconn;
387 }
388
389 ret = l->accept(l, cfd, &addr);
390 if (unlikely(ret <= 0)) {
391 /* The connection was closed by session_accept(). Either
392 * we just have to ignore it (ret == 0) or it's a critical
393 * error due to a resource shortage, and we must stop the
394 * listener (ret < 0).
395 */
396 if (!(l->options & LI_O_UNLIMITED))
397 actconn--;
398 jobs--;
399 l->nbconn--;
400 if (ret == 0) /* successful termination */
401 continue;
402
403 limit_listener(l, &global_listener_queue);
404 task_schedule(global_listener_queue_task, tick_add(now_ms, 100)); /* try again in 100 ms */
Willy Tarreauafad0e02012-08-09 14:45:22 +0200405 return;
Willy Tarreaubbebbbf2012-05-07 21:22:09 +0200406 }
407
408 if (l->nbconn >= l->maxconn) {
409 listener_full(l);
Willy Tarreauafad0e02012-08-09 14:45:22 +0200410 return;
Willy Tarreaubbebbbf2012-05-07 21:22:09 +0200411 }
412
Willy Tarreauaece46a2012-07-06 12:25:58 +0200413 } /* end of while (max_accept--) */
Willy Tarreaubbebbbf2012-05-07 21:22:09 +0200414
Willy Tarreauaece46a2012-07-06 12:25:58 +0200415 /* we've exhausted max_accept, so there is no need to poll again */
Willy Tarreauafad0e02012-08-09 14:45:22 +0200416 return;
Willy Tarreaubbebbbf2012-05-07 21:22:09 +0200417}
418
Willy Tarreau26982662012-09-12 23:17:10 +0200419/*
420 * Registers the bind keyword list <kwl> as a list of valid keywords for next
421 * parsing sessions.
422 */
423void bind_register_keywords(struct bind_kw_list *kwl)
424{
425 LIST_ADDQ(&bind_keywords.list, &kwl->list);
426}
427
428/* Return a pointer to the bind keyword <kw>, or NULL if not found. If the
429 * keyword is found with a NULL ->parse() function, then an attempt is made to
430 * find one with a valid ->parse() function. This way it is possible to declare
431 * platform-dependant, known keywords as NULL, then only declare them as valid
432 * if some options are met. Note that if the requested keyword contains an
433 * opening parenthesis, everything from this point is ignored.
434 */
435struct bind_kw *bind_find_kw(const char *kw)
436{
437 int index;
438 const char *kwend;
439 struct bind_kw_list *kwl;
440 struct bind_kw *ret = NULL;
441
442 kwend = strchr(kw, '(');
443 if (!kwend)
444 kwend = kw + strlen(kw);
445
446 list_for_each_entry(kwl, &bind_keywords.list, list) {
447 for (index = 0; kwl->kw[index].kw != NULL; index++) {
448 if ((strncmp(kwl->kw[index].kw, kw, kwend - kw) == 0) &&
449 kwl->kw[index].kw[kwend-kw] == 0) {
450 if (kwl->kw[index].parse)
451 return &kwl->kw[index]; /* found it !*/
452 else
453 ret = &kwl->kw[index]; /* may be OK */
454 }
455 }
456 }
457 return ret;
458}
459
Willy Tarreau8638f482012-09-18 18:01:17 +0200460/* Dumps all registered "bind" keywords to the <out> string pointer. The
461 * unsupported keywords are only dumped if their supported form was not
462 * found.
463 */
464void bind_dump_kws(char **out)
465{
466 struct bind_kw_list *kwl;
467 int index;
468
469 *out = NULL;
470 list_for_each_entry(kwl, &bind_keywords.list, list) {
471 for (index = 0; kwl->kw[index].kw != NULL; index++) {
472 if (kwl->kw[index].parse ||
473 bind_find_kw(kwl->kw[index].kw) == &kwl->kw[index]) {
Willy Tarreau51fb7652012-09-18 18:24:39 +0200474 memprintf(out, "%s[%4s] %s%s%s\n", *out ? *out : "",
475 kwl->scope,
Willy Tarreau8638f482012-09-18 18:01:17 +0200476 kwl->kw[index].kw,
Willy Tarreau51fb7652012-09-18 18:24:39 +0200477 kwl->kw[index].skip ? " <arg>" : "",
478 kwl->kw[index].parse ? "" : " (not supported)");
Willy Tarreau8638f482012-09-18 18:01:17 +0200479 }
480 }
481 }
482}
483
Willy Tarreau645513a2010-05-24 20:55:15 +0200484/************************************************************************/
Willy Tarreau0ccb7442013-01-07 22:54:17 +0100485/* All supported sample and ACL keywords must be declared here. */
Willy Tarreau645513a2010-05-24 20:55:15 +0200486/************************************************************************/
487
Willy Tarreaua5e37562011-12-16 17:06:15 +0100488/* set temp integer to the number of connexions to the same listening socket */
Willy Tarreau645513a2010-05-24 20:55:15 +0200489static int
Willy Tarreau0ccb7442013-01-07 22:54:17 +0100490smp_fetch_dconn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +0200491 const struct arg *args, struct sample *smp, const char *kw)
Willy Tarreau645513a2010-05-24 20:55:15 +0200492{
Willy Tarreauf853c462012-04-23 18:53:56 +0200493 smp->type = SMP_T_UINT;
494 smp->data.uint = l4->listener->nbconn;
Willy Tarreau645513a2010-05-24 20:55:15 +0200495 return 1;
496}
497
Willy Tarreaua5e37562011-12-16 17:06:15 +0100498/* set temp integer to the id of the socket (listener) */
Willy Tarreau645513a2010-05-24 20:55:15 +0200499static int
Willy Tarreau0ccb7442013-01-07 22:54:17 +0100500smp_fetch_so_id(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +0200501 const struct arg *args, struct sample *smp, const char *kw)
Willy Tarreau37406352012-04-23 16:16:37 +0200502{
Willy Tarreauf853c462012-04-23 18:53:56 +0200503 smp->type = SMP_T_UINT;
504 smp->data.uint = l4->listener->luid;
Willy Tarreau645513a2010-05-24 20:55:15 +0200505 return 1;
506}
507
Willy Tarreau3dcc3412012-09-18 17:17:28 +0200508/* parse the "accept-proxy" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +0200509static 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 +0200510{
511 struct listener *l;
512
Willy Tarreau4348fad2012-09-20 16:48:07 +0200513 list_for_each_entry(l, &conf->listeners, by_bind)
Willy Tarreau3dcc3412012-09-18 17:17:28 +0200514 l->options |= LI_O_ACC_PROXY;
515
516 return 0;
517}
518
519/* parse the "backlog" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +0200520static 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 +0200521{
522 struct listener *l;
523 int val;
524
525 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200526 memprintf(err, "'%s' : missing value", args[cur_arg]);
Willy Tarreau3dcc3412012-09-18 17:17:28 +0200527 return ERR_ALERT | ERR_FATAL;
528 }
529
530 val = atol(args[cur_arg + 1]);
531 if (val <= 0) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200532 memprintf(err, "'%s' : invalid value %d, must be > 0", args[cur_arg], val);
Willy Tarreau3dcc3412012-09-18 17:17:28 +0200533 return ERR_ALERT | ERR_FATAL;
534 }
535
Willy Tarreau4348fad2012-09-20 16:48:07 +0200536 list_for_each_entry(l, &conf->listeners, by_bind)
Willy Tarreau3dcc3412012-09-18 17:17:28 +0200537 l->backlog = val;
538
539 return 0;
540}
541
542/* parse the "id" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +0200543static 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 +0200544{
545 struct eb32_node *node;
Willy Tarreau4348fad2012-09-20 16:48:07 +0200546 struct listener *l, *new;
Willy Tarreau3dcc3412012-09-18 17:17:28 +0200547
Willy Tarreau4348fad2012-09-20 16:48:07 +0200548 if (conf->listeners.n != conf->listeners.p) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200549 memprintf(err, "'%s' can only be used with a single socket", args[cur_arg]);
Willy Tarreau3dcc3412012-09-18 17:17:28 +0200550 return ERR_ALERT | ERR_FATAL;
551 }
552
553 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200554 memprintf(err, "'%s' : expects an integer argument", args[cur_arg]);
Willy Tarreau3dcc3412012-09-18 17:17:28 +0200555 return ERR_ALERT | ERR_FATAL;
556 }
557
Willy Tarreau4348fad2012-09-20 16:48:07 +0200558 new = LIST_NEXT(&conf->listeners, struct listener *, by_bind);
559 new->luid = atol(args[cur_arg + 1]);
560 new->conf.id.key = new->luid;
Willy Tarreau3dcc3412012-09-18 17:17:28 +0200561
Willy Tarreau4348fad2012-09-20 16:48:07 +0200562 if (new->luid <= 0) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200563 memprintf(err, "'%s' : custom id has to be > 0", args[cur_arg]);
Willy Tarreau3dcc3412012-09-18 17:17:28 +0200564 return ERR_ALERT | ERR_FATAL;
565 }
566
Willy Tarreau4348fad2012-09-20 16:48:07 +0200567 node = eb32_lookup(&px->conf.used_listener_id, new->luid);
Willy Tarreau3dcc3412012-09-18 17:17:28 +0200568 if (node) {
569 l = container_of(node, struct listener, conf.id);
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200570 memprintf(err, "'%s' : custom id %d already used at %s:%d ('bind %s')",
571 args[cur_arg], l->luid, l->bind_conf->file, l->bind_conf->line,
572 l->bind_conf->arg);
Willy Tarreau3dcc3412012-09-18 17:17:28 +0200573 return ERR_ALERT | ERR_FATAL;
574 }
575
Willy Tarreau4348fad2012-09-20 16:48:07 +0200576 eb32_insert(&px->conf.used_listener_id, &new->conf.id);
Willy Tarreau3dcc3412012-09-18 17:17:28 +0200577 return 0;
578}
579
580/* parse the "maxconn" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +0200581static 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 +0200582{
583 struct listener *l;
584 int val;
585
586 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200587 memprintf(err, "'%s' : missing value", args[cur_arg]);
Willy Tarreau3dcc3412012-09-18 17:17:28 +0200588 return ERR_ALERT | ERR_FATAL;
589 }
590
591 val = atol(args[cur_arg + 1]);
592 if (val <= 0) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200593 memprintf(err, "'%s' : invalid value %d, must be > 0", args[cur_arg], val);
Willy Tarreau3dcc3412012-09-18 17:17:28 +0200594 return ERR_ALERT | ERR_FATAL;
595 }
596
Willy Tarreau4348fad2012-09-20 16:48:07 +0200597 list_for_each_entry(l, &conf->listeners, by_bind)
Willy Tarreau3dcc3412012-09-18 17:17:28 +0200598 l->maxconn = val;
599
600 return 0;
601}
602
603/* parse the "name" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +0200604static 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 +0200605{
606 struct listener *l;
607
608 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200609 memprintf(err, "'%s' : missing name", args[cur_arg]);
Willy Tarreau3dcc3412012-09-18 17:17:28 +0200610 return ERR_ALERT | ERR_FATAL;
611 }
612
Willy Tarreau4348fad2012-09-20 16:48:07 +0200613 list_for_each_entry(l, &conf->listeners, by_bind)
Willy Tarreau3dcc3412012-09-18 17:17:28 +0200614 l->name = strdup(args[cur_arg + 1]);
615
616 return 0;
617}
618
619/* parse the "nice" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +0200620static 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 +0200621{
622 struct listener *l;
623 int val;
624
625 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200626 memprintf(err, "'%s' : missing value", args[cur_arg]);
Willy Tarreau3dcc3412012-09-18 17:17:28 +0200627 return ERR_ALERT | ERR_FATAL;
628 }
629
630 val = atol(args[cur_arg + 1]);
631 if (val < -1024 || val > 1024) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200632 memprintf(err, "'%s' : invalid value %d, allowed range is -1024..1024", args[cur_arg], val);
Willy Tarreau3dcc3412012-09-18 17:17:28 +0200633 return ERR_ALERT | ERR_FATAL;
634 }
635
Willy Tarreau4348fad2012-09-20 16:48:07 +0200636 list_for_each_entry(l, &conf->listeners, by_bind)
Willy Tarreau3dcc3412012-09-18 17:17:28 +0200637 l->nice = val;
638
639 return 0;
640}
641
642
Willy Tarreau61612d42012-04-19 18:42:05 +0200643/* Note: must not be declared <const> as its list will be overwritten.
644 * Please take care of keeping this list alphabetically sorted.
645 */
Willy Tarreaudc13c112013-06-21 23:16:39 +0200646static struct sample_fetch_kw_list smp_kws = {ILH, {
Willy Tarreau0ccb7442013-01-07 22:54:17 +0100647 { "dst_conn", smp_fetch_dconn, 0, NULL, SMP_T_UINT, SMP_USE_FTEND, },
648 { "so_id", smp_fetch_so_id, 0, NULL, SMP_T_UINT, SMP_USE_FTEND, },
649 { /* END */ },
650}};
651
652/* Note: must not be declared <const> as its list will be overwritten.
653 * Please take care of keeping this list alphabetically sorted.
654 */
Willy Tarreaudc13c112013-06-21 23:16:39 +0200655static struct acl_kw_list acl_kws = {ILH, {
Willy Tarreau0ccb7442013-01-07 22:54:17 +0100656 { /* END */ },
Willy Tarreau645513a2010-05-24 20:55:15 +0200657}};
658
Willy Tarreau3dcc3412012-09-18 17:17:28 +0200659/* Note: must not be declared <const> as its list will be overwritten.
660 * Please take care of keeping this list alphabetically sorted, doing so helps
661 * all code contributors.
662 * Optional keywords are also declared with a NULL ->parse() function so that
663 * the config parser can report an appropriate error when a known keyword was
664 * not enabled.
665 */
Willy Tarreau51fb7652012-09-18 18:24:39 +0200666static struct bind_kw_list bind_kws = { "ALL", { }, {
Willy Tarreau3dcc3412012-09-18 17:17:28 +0200667 { "accept-proxy", bind_parse_accept_proxy, 0 }, /* enable PROXY protocol */
668 { "backlog", bind_parse_backlog, 1 }, /* set backlog of listening socket */
669 { "id", bind_parse_id, 1 }, /* set id of listening socket */
670 { "maxconn", bind_parse_maxconn, 1 }, /* set maxconn of listening socket */
671 { "name", bind_parse_name, 1 }, /* set name of listening socket */
672 { "nice", bind_parse_nice, 1 }, /* set nice of listening socket */
Willy Tarreau0ccb7442013-01-07 22:54:17 +0100673 { /* END */ },
Willy Tarreau3dcc3412012-09-18 17:17:28 +0200674}};
675
Willy Tarreau645513a2010-05-24 20:55:15 +0200676__attribute__((constructor))
Willy Tarreaud1d54542012-09-12 22:58:11 +0200677static void __listener_init(void)
Willy Tarreau645513a2010-05-24 20:55:15 +0200678{
Willy Tarreau0ccb7442013-01-07 22:54:17 +0100679 sample_register_fetches(&smp_kws);
Willy Tarreau645513a2010-05-24 20:55:15 +0200680 acl_register_keywords(&acl_kws);
Willy Tarreau3dcc3412012-09-18 17:17:28 +0200681 bind_register_keywords(&bind_kws);
Willy Tarreau645513a2010-05-24 20:55:15 +0200682}
683
684/*
685 * Local variables:
686 * c-indent-level: 8
687 * c-basic-offset: 8
688 * End:
689 */