blob: 117347aba45d5e18d79c8f5d9e23e4daa1fa757a [file] [log] [blame]
Willy Tarreau36b9e222018-11-11 15:19:52 +01001#include <stdio.h>
2#include <stdlib.h>
3#include <string.h>
4#include <netdb.h>
5#include <ctype.h>
6#include <pwd.h>
7#include <grp.h>
8#include <errno.h>
9#include <sys/types.h>
10#include <sys/stat.h>
11#include <fcntl.h>
12#include <unistd.h>
13
14#include <common/cfgparse.h>
15#include <proto/compression.h>
16
17/*
18 * parse a line in a <global> section. Returns the error code, 0 if OK, or
19 * any combination of :
20 * - ERR_ABORT: must abort ASAP
21 * - ERR_FATAL: we can continue parsing but not start the service
22 * - ERR_WARN: a warning has been emitted
23 * - ERR_ALERT: an alert has been emitted
24 * Only the two first ones can stop processing, the two others are just
25 * indicators.
26 */
27int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
28{
29 int err_code = 0;
30 char *errmsg = NULL;
31
32 if (!strcmp(args[0], "global")) { /* new section */
33 /* no option, nothing special to do */
34 alertif_too_many_args(0, file, linenum, args, &err_code);
35 goto out;
36 }
37 else if (!strcmp(args[0], "daemon")) {
38 if (alertif_too_many_args(0, file, linenum, args, &err_code))
39 goto out;
40 global.mode |= MODE_DAEMON;
41 }
42 else if (!strcmp(args[0], "master-worker")) {
43 if (alertif_too_many_args(1, file, linenum, args, &err_code))
44 goto out;
45 if (*args[1]) {
46 if (!strcmp(args[1], "no-exit-on-failure")) {
47 global.tune.options |= GTUNE_NOEXIT_ONFAILURE;
48 } else {
49 ha_alert("parsing [%s:%d] : '%s' only supports 'no-exit-on-failure' option.\n", file, linenum, args[0]);
50 err_code |= ERR_ALERT | ERR_FATAL;
51 goto out;
52 }
53 }
54 global.mode |= MODE_MWORKER;
55 }
56 else if (!strcmp(args[0], "debug")) {
57 if (alertif_too_many_args(0, file, linenum, args, &err_code))
58 goto out;
59 global.mode |= MODE_DEBUG;
60 }
61 else if (!strcmp(args[0], "noepoll")) {
62 if (alertif_too_many_args(0, file, linenum, args, &err_code))
63 goto out;
64 global.tune.options &= ~GTUNE_USE_EPOLL;
65 }
66 else if (!strcmp(args[0], "nokqueue")) {
67 if (alertif_too_many_args(0, file, linenum, args, &err_code))
68 goto out;
69 global.tune.options &= ~GTUNE_USE_KQUEUE;
70 }
71 else if (!strcmp(args[0], "nopoll")) {
72 if (alertif_too_many_args(0, file, linenum, args, &err_code))
73 goto out;
74 global.tune.options &= ~GTUNE_USE_POLL;
75 }
Willy Tarreaubeb859a2018-11-22 18:07:59 +010076 else if (!strcmp(args[0], "busy-polling")) { /* "no busy-polling" or "busy-polling" */
77 if (alertif_too_many_args(0, file, linenum, args, &err_code))
78 goto out;
79 if (kwm == KWM_NO)
80 global.tune.options &= ~GTUNE_BUSY_POLLING;
81 else
82 global.tune.options |= GTUNE_BUSY_POLLING;
83 }
Willy Tarreau36b9e222018-11-11 15:19:52 +010084 else if (!strcmp(args[0], "nosplice")) {
85 if (alertif_too_many_args(0, file, linenum, args, &err_code))
86 goto out;
87 global.tune.options &= ~GTUNE_USE_SPLICE;
88 }
89 else if (!strcmp(args[0], "nogetaddrinfo")) {
90 if (alertif_too_many_args(0, file, linenum, args, &err_code))
91 goto out;
92 global.tune.options &= ~GTUNE_USE_GAI;
93 }
94 else if (!strcmp(args[0], "noreuseport")) {
95 if (alertif_too_many_args(0, file, linenum, args, &err_code))
96 goto out;
97 global.tune.options &= ~GTUNE_USE_REUSEPORT;
98 }
99 else if (!strcmp(args[0], "quiet")) {
100 if (alertif_too_many_args(0, file, linenum, args, &err_code))
101 goto out;
102 global.mode |= MODE_QUIET;
103 }
104 else if (!strcmp(args[0], "tune.runqueue-depth")) {
105 if (alertif_too_many_args(1, file, linenum, args, &err_code))
106 goto out;
107 if (global.tune.runqueue_depth != 0) {
108 ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
109 err_code |= ERR_ALERT;
110 goto out;
111 }
112 if (*(args[1]) == 0) {
113 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
114 err_code |= ERR_ALERT | ERR_FATAL;
115 goto out;
116 }
117 global.tune.runqueue_depth = atol(args[1]);
118
119 }
120 else if (!strcmp(args[0], "tune.maxpollevents")) {
121 if (alertif_too_many_args(1, file, linenum, args, &err_code))
122 goto out;
123 if (global.tune.maxpollevents != 0) {
124 ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
125 err_code |= ERR_ALERT;
126 goto out;
127 }
128 if (*(args[1]) == 0) {
129 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
130 err_code |= ERR_ALERT | ERR_FATAL;
131 goto out;
132 }
133 global.tune.maxpollevents = atol(args[1]);
134 }
135 else if (!strcmp(args[0], "tune.maxaccept")) {
136 if (alertif_too_many_args(1, file, linenum, args, &err_code))
137 goto out;
138 if (global.tune.maxaccept != 0) {
139 ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
140 err_code |= ERR_ALERT;
141 goto out;
142 }
143 if (*(args[1]) == 0) {
144 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
145 err_code |= ERR_ALERT | ERR_FATAL;
146 goto out;
147 }
148 global.tune.maxaccept = atol(args[1]);
149 }
150 else if (!strcmp(args[0], "tune.chksize")) {
151 if (alertif_too_many_args(1, file, linenum, args, &err_code))
152 goto out;
153 if (*(args[1]) == 0) {
154 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
155 err_code |= ERR_ALERT | ERR_FATAL;
156 goto out;
157 }
158 global.tune.chksize = atol(args[1]);
159 }
160 else if (!strcmp(args[0], "tune.recv_enough")) {
161 if (alertif_too_many_args(1, file, linenum, args, &err_code))
162 goto out;
163 if (*(args[1]) == 0) {
164 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
165 err_code |= ERR_ALERT | ERR_FATAL;
166 goto out;
167 }
168 global.tune.recv_enough = atol(args[1]);
169 }
170 else if (!strcmp(args[0], "tune.buffers.limit")) {
171 if (alertif_too_many_args(1, file, linenum, args, &err_code))
172 goto out;
173 if (*(args[1]) == 0) {
174 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
175 err_code |= ERR_ALERT | ERR_FATAL;
176 goto out;
177 }
178 global.tune.buf_limit = atol(args[1]);
179 if (global.tune.buf_limit) {
180 if (global.tune.buf_limit < 3)
181 global.tune.buf_limit = 3;
182 if (global.tune.buf_limit <= global.tune.reserved_bufs)
183 global.tune.buf_limit = global.tune.reserved_bufs + 1;
184 }
185 }
186 else if (!strcmp(args[0], "tune.buffers.reserve")) {
187 if (alertif_too_many_args(1, file, linenum, args, &err_code))
188 goto out;
189 if (*(args[1]) == 0) {
190 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
191 err_code |= ERR_ALERT | ERR_FATAL;
192 goto out;
193 }
194 global.tune.reserved_bufs = atol(args[1]);
195 if (global.tune.reserved_bufs < 2)
196 global.tune.reserved_bufs = 2;
197 if (global.tune.buf_limit && global.tune.buf_limit <= global.tune.reserved_bufs)
198 global.tune.buf_limit = global.tune.reserved_bufs + 1;
199 }
200 else if (!strcmp(args[0], "tune.bufsize")) {
201 if (alertif_too_many_args(1, file, linenum, args, &err_code))
202 goto out;
203 if (*(args[1]) == 0) {
204 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
205 err_code |= ERR_ALERT | ERR_FATAL;
206 goto out;
207 }
208 global.tune.bufsize = atol(args[1]);
Willy Tarreauc77d3642018-12-12 06:19:42 +0100209 /* round it up to support a two-pointer alignment at the end */
210 global.tune.bufsize = (global.tune.bufsize + 2 * sizeof(void *) - 1) & -(2 * sizeof(void *));
Willy Tarreau36b9e222018-11-11 15:19:52 +0100211 if (global.tune.bufsize <= 0) {
212 ha_alert("parsing [%s:%d] : '%s' expects a positive integer argument.\n", file, linenum, args[0]);
213 err_code |= ERR_ALERT | ERR_FATAL;
214 goto out;
215 }
216 }
217 else if (!strcmp(args[0], "tune.maxrewrite")) {
218 if (alertif_too_many_args(1, file, linenum, args, &err_code))
219 goto out;
220 if (*(args[1]) == 0) {
221 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
222 err_code |= ERR_ALERT | ERR_FATAL;
223 goto out;
224 }
225 global.tune.maxrewrite = atol(args[1]);
226 if (global.tune.maxrewrite < 0) {
227 ha_alert("parsing [%s:%d] : '%s' expects a positive integer argument.\n", file, linenum, args[0]);
228 err_code |= ERR_ALERT | ERR_FATAL;
229 goto out;
230 }
231 }
232 else if (!strcmp(args[0], "tune.idletimer")) {
233 unsigned int idle;
234 const char *res;
235
236 if (alertif_too_many_args(1, file, linenum, args, &err_code))
237 goto out;
238 if (*(args[1]) == 0) {
239 ha_alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
240 err_code |= ERR_ALERT | ERR_FATAL;
241 goto out;
242 }
243
244 res = parse_time_err(args[1], &idle, TIME_UNIT_MS);
245 if (res) {
246 ha_alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
247 file, linenum, *res, args[0]);
248 err_code |= ERR_ALERT | ERR_FATAL;
249 goto out;
250 }
251
252 if (idle > 65535) {
253 ha_alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
254 err_code |= ERR_ALERT | ERR_FATAL;
255 goto out;
256 }
257 global.tune.idle_timer = idle;
258 }
259 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
260 if (alertif_too_many_args(1, file, linenum, args, &err_code))
261 goto out;
262 if (global.tune.client_rcvbuf != 0) {
263 ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
264 err_code |= ERR_ALERT;
265 goto out;
266 }
267 if (*(args[1]) == 0) {
268 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
269 err_code |= ERR_ALERT | ERR_FATAL;
270 goto out;
271 }
272 global.tune.client_rcvbuf = atol(args[1]);
273 }
274 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
275 if (alertif_too_many_args(1, file, linenum, args, &err_code))
276 goto out;
277 if (global.tune.server_rcvbuf != 0) {
278 ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
279 err_code |= ERR_ALERT;
280 goto out;
281 }
282 if (*(args[1]) == 0) {
283 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
284 err_code |= ERR_ALERT | ERR_FATAL;
285 goto out;
286 }
287 global.tune.server_rcvbuf = atol(args[1]);
288 }
289 else if (!strcmp(args[0], "tune.sndbuf.client")) {
290 if (alertif_too_many_args(1, file, linenum, args, &err_code))
291 goto out;
292 if (global.tune.client_sndbuf != 0) {
293 ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
294 err_code |= ERR_ALERT;
295 goto out;
296 }
297 if (*(args[1]) == 0) {
298 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
299 err_code |= ERR_ALERT | ERR_FATAL;
300 goto out;
301 }
302 global.tune.client_sndbuf = atol(args[1]);
303 }
304 else if (!strcmp(args[0], "tune.sndbuf.server")) {
305 if (alertif_too_many_args(1, file, linenum, args, &err_code))
306 goto out;
307 if (global.tune.server_sndbuf != 0) {
308 ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
309 err_code |= ERR_ALERT;
310 goto out;
311 }
312 if (*(args[1]) == 0) {
313 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
314 err_code |= ERR_ALERT | ERR_FATAL;
315 goto out;
316 }
317 global.tune.server_sndbuf = atol(args[1]);
318 }
319 else if (!strcmp(args[0], "tune.pipesize")) {
320 if (alertif_too_many_args(1, file, linenum, args, &err_code))
321 goto out;
322 if (*(args[1]) == 0) {
323 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
324 err_code |= ERR_ALERT | ERR_FATAL;
325 goto out;
326 }
327 global.tune.pipesize = atol(args[1]);
328 }
329 else if (!strcmp(args[0], "tune.http.cookielen")) {
330 if (alertif_too_many_args(1, file, linenum, args, &err_code))
331 goto out;
332 if (*(args[1]) == 0) {
333 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
334 err_code |= ERR_ALERT | ERR_FATAL;
335 goto out;
336 }
337 global.tune.cookie_len = atol(args[1]) + 1;
338 }
339 else if (!strcmp(args[0], "tune.http.logurilen")) {
340 if (alertif_too_many_args(1, file, linenum, args, &err_code))
341 goto out;
342 if (*(args[1]) == 0) {
343 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
344 err_code |= ERR_ALERT | ERR_FATAL;
345 goto out;
346 }
347 global.tune.requri_len = atol(args[1]) + 1;
348 }
349 else if (!strcmp(args[0], "tune.http.maxhdr")) {
350 if (alertif_too_many_args(1, file, linenum, args, &err_code))
351 goto out;
352 if (*(args[1]) == 0) {
353 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
354 err_code |= ERR_ALERT | ERR_FATAL;
355 goto out;
356 }
357 global.tune.max_http_hdr = atoi(args[1]);
358 if (global.tune.max_http_hdr < 1 || global.tune.max_http_hdr > 32767) {
359 ha_alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 32767\n",
360 file, linenum, args[0]);
361 err_code |= ERR_ALERT | ERR_FATAL;
362 goto out;
363 }
364 }
365 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
366 if (alertif_too_many_args(1, file, linenum, args, &err_code))
367 goto out;
368 if (*args[1]) {
369 global.tune.comp_maxlevel = atoi(args[1]);
370 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
371 ha_alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
372 file, linenum, args[0]);
373 err_code |= ERR_ALERT | ERR_FATAL;
374 goto out;
375 }
376 } else {
377 ha_alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
378 file, linenum, args[0]);
379 err_code |= ERR_ALERT | ERR_FATAL;
380 goto out;
381 }
382 }
383 else if (!strcmp(args[0], "tune.pattern.cache-size")) {
384 if (*args[1]) {
385 global.tune.pattern_cache = atoi(args[1]);
386 if (global.tune.pattern_cache < 0) {
387 ha_alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
388 file, linenum, args[0]);
389 err_code |= ERR_ALERT | ERR_FATAL;
390 goto out;
391 }
392 } else {
393 ha_alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
394 file, linenum, args[0]);
395 err_code |= ERR_ALERT | ERR_FATAL;
396 goto out;
397 }
398 }
399 else if (!strcmp(args[0], "uid")) {
400 if (alertif_too_many_args(1, file, linenum, args, &err_code))
401 goto out;
402 if (global.uid != 0) {
403 ha_alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
404 err_code |= ERR_ALERT;
405 goto out;
406 }
407 if (*(args[1]) == 0) {
408 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
409 err_code |= ERR_ALERT | ERR_FATAL;
410 goto out;
411 }
412 if (strl2irc(args[1], strlen(args[1]), &global.uid) != 0) {
413 ha_warning("parsing [%s:%d] : uid: string '%s' is not a number.\n | You might want to use the 'user' parameter to use a system user name.\n", file, linenum, args[1]);
414 err_code |= ERR_WARN;
415 goto out;
416 }
417
418 }
419 else if (!strcmp(args[0], "gid")) {
420 if (alertif_too_many_args(1, file, linenum, args, &err_code))
421 goto out;
422 if (global.gid != 0) {
423 ha_alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
424 err_code |= ERR_ALERT;
425 goto out;
426 }
427 if (*(args[1]) == 0) {
428 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
429 err_code |= ERR_ALERT | ERR_FATAL;
430 goto out;
431 }
432 if (strl2irc(args[1], strlen(args[1]), &global.gid) != 0) {
433 ha_warning("parsing [%s:%d] : gid: string '%s' is not a number.\n | You might want to use the 'group' parameter to use a system group name.\n", file, linenum, args[1]);
434 err_code |= ERR_WARN;
435 goto out;
436 }
437 }
438 else if (!strcmp(args[0], "external-check")) {
439 if (alertif_too_many_args(0, file, linenum, args, &err_code))
440 goto out;
441 global.external_check = 1;
442 }
443 /* user/group name handling */
444 else if (!strcmp(args[0], "user")) {
445 struct passwd *ha_user;
446 if (alertif_too_many_args(1, file, linenum, args, &err_code))
447 goto out;
448 if (global.uid != 0) {
449 ha_alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
450 err_code |= ERR_ALERT;
451 goto out;
452 }
453 errno = 0;
454 ha_user = getpwnam(args[1]);
455 if (ha_user != NULL) {
456 global.uid = (int)ha_user->pw_uid;
457 }
458 else {
459 ha_alert("parsing [%s:%d] : cannot find user id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
460 err_code |= ERR_ALERT | ERR_FATAL;
461 }
462 }
463 else if (!strcmp(args[0], "group")) {
464 struct group *ha_group;
465 if (alertif_too_many_args(1, file, linenum, args, &err_code))
466 goto out;
467 if (global.gid != 0) {
468 ha_alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
469 err_code |= ERR_ALERT;
470 goto out;
471 }
472 errno = 0;
473 ha_group = getgrnam(args[1]);
474 if (ha_group != NULL) {
475 global.gid = (int)ha_group->gr_gid;
476 }
477 else {
478 ha_alert("parsing [%s:%d] : cannot find group id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
479 err_code |= ERR_ALERT | ERR_FATAL;
480 }
481 }
482 /* end of user/group name handling*/
483 else if (!strcmp(args[0], "nbproc")) {
484 if (alertif_too_many_args(1, file, linenum, args, &err_code))
485 goto out;
486 if (*(args[1]) == 0) {
487 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
488 err_code |= ERR_ALERT | ERR_FATAL;
489 goto out;
490 }
491 global.nbproc = atol(args[1]);
Willy Tarreaua38a7172019-02-02 17:11:28 +0100492 all_proc_mask = nbits(global.nbproc);
Willy Tarreauff9c9142019-02-07 10:39:36 +0100493 if (global.nbproc < 1 || global.nbproc > MAX_PROCS) {
Willy Tarreau36b9e222018-11-11 15:19:52 +0100494 ha_alert("parsing [%s:%d] : '%s' must be between 1 and %d (was %d).\n",
Willy Tarreauff9c9142019-02-07 10:39:36 +0100495 file, linenum, args[0], MAX_PROCS, global.nbproc);
Willy Tarreau36b9e222018-11-11 15:19:52 +0100496 err_code |= ERR_ALERT | ERR_FATAL;
497 goto out;
498 }
499 }
500 else if (!strcmp(args[0], "nbthread")) {
501 if (alertif_too_many_args(1, file, linenum, args, &err_code))
502 goto out;
503 if (*(args[1]) == 0) {
504 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
505 err_code |= ERR_ALERT | ERR_FATAL;
506 goto out;
507 }
508 global.nbthread = parse_nbthread(args[1], &errmsg);
509 if (!global.nbthread) {
510 ha_alert("parsing [%s:%d] : '%s' %s.\n",
511 file, linenum, args[0], errmsg);
512 err_code |= ERR_ALERT | ERR_FATAL;
513 goto out;
514 }
515 }
516 else if (!strcmp(args[0], "maxconn")) {
517 if (alertif_too_many_args(1, file, linenum, args, &err_code))
518 goto out;
519 if (global.maxconn != 0) {
520 ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
521 err_code |= ERR_ALERT;
522 goto out;
523 }
524 if (*(args[1]) == 0) {
525 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
526 err_code |= ERR_ALERT | ERR_FATAL;
527 goto out;
528 }
529 global.maxconn = atol(args[1]);
530#ifdef SYSTEM_MAXCONN
531 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
532 ha_alert("parsing [%s:%d] : maxconn value %d too high for this system.\nLimiting to %d. Please use '-n' to force the value.\n", file, linenum, global.maxconn, DEFAULT_MAXCONN);
533 global.maxconn = DEFAULT_MAXCONN;
534 err_code |= ERR_ALERT;
535 }
536#endif /* SYSTEM_MAXCONN */
537 }
538 else if (!strcmp(args[0], "ssl-server-verify")) {
539 if (alertif_too_many_args(1, file, linenum, args, &err_code))
540 goto out;
541 if (*(args[1]) == 0) {
542 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
543 err_code |= ERR_ALERT | ERR_FATAL;
544 goto out;
545 }
546 if (strcmp(args[1],"none") == 0)
547 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
548 else if (strcmp(args[1],"required") == 0)
549 global.ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED;
550 else {
551 ha_alert("parsing [%s:%d] : '%s' expects 'none' or 'required' as argument.\n", file, linenum, args[0]);
552 err_code |= ERR_ALERT | ERR_FATAL;
553 goto out;
554 }
555 }
556 else if (!strcmp(args[0], "maxconnrate")) {
557 if (alertif_too_many_args(1, file, linenum, args, &err_code))
558 goto out;
559 if (global.cps_lim != 0) {
560 ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
561 err_code |= ERR_ALERT;
562 goto out;
563 }
564 if (*(args[1]) == 0) {
565 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
566 err_code |= ERR_ALERT | ERR_FATAL;
567 goto out;
568 }
569 global.cps_lim = atol(args[1]);
570 }
571 else if (!strcmp(args[0], "maxsessrate")) {
572 if (alertif_too_many_args(1, file, linenum, args, &err_code))
573 goto out;
574 if (global.sps_lim != 0) {
575 ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
576 err_code |= ERR_ALERT;
577 goto out;
578 }
579 if (*(args[1]) == 0) {
580 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
581 err_code |= ERR_ALERT | ERR_FATAL;
582 goto out;
583 }
584 global.sps_lim = atol(args[1]);
585 }
586 else if (!strcmp(args[0], "maxsslrate")) {
587 if (alertif_too_many_args(1, file, linenum, args, &err_code))
588 goto out;
589 if (global.ssl_lim != 0) {
590 ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
591 err_code |= ERR_ALERT;
592 goto out;
593 }
594 if (*(args[1]) == 0) {
595 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
596 err_code |= ERR_ALERT | ERR_FATAL;
597 goto out;
598 }
599 global.ssl_lim = atol(args[1]);
600 }
601 else if (!strcmp(args[0], "maxcomprate")) {
602 if (alertif_too_many_args(1, file, linenum, args, &err_code))
603 goto out;
604 if (*(args[1]) == 0) {
605 ha_alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
606 err_code |= ERR_ALERT | ERR_FATAL;
607 goto out;
608 }
609 global.comp_rate_lim = atoi(args[1]) * 1024;
610 }
611 else if (!strcmp(args[0], "maxpipes")) {
612 if (alertif_too_many_args(1, file, linenum, args, &err_code))
613 goto out;
614 if (global.maxpipes != 0) {
615 ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
616 err_code |= ERR_ALERT;
617 goto out;
618 }
619 if (*(args[1]) == 0) {
620 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
621 err_code |= ERR_ALERT | ERR_FATAL;
622 goto out;
623 }
624 global.maxpipes = atol(args[1]);
625 }
626 else if (!strcmp(args[0], "maxzlibmem")) {
627 if (alertif_too_many_args(1, file, linenum, args, &err_code))
628 goto out;
629 if (*(args[1]) == 0) {
630 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
631 err_code |= ERR_ALERT | ERR_FATAL;
632 goto out;
633 }
634 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
635 }
636 else if (!strcmp(args[0], "maxcompcpuusage")) {
637 if (alertif_too_many_args(1, file, linenum, args, &err_code))
638 goto out;
639 if (*(args[1]) == 0) {
640 ha_alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
641 err_code |= ERR_ALERT | ERR_FATAL;
642 goto out;
643 }
644 compress_min_idle = 100 - atoi(args[1]);
645 if (compress_min_idle > 100) {
646 ha_alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
647 err_code |= ERR_ALERT | ERR_FATAL;
648 goto out;
649 }
650 }
651
652 else if (!strcmp(args[0], "ulimit-n")) {
653 if (alertif_too_many_args(1, file, linenum, args, &err_code))
654 goto out;
655 if (global.rlimit_nofile != 0) {
656 ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
657 err_code |= ERR_ALERT;
658 goto out;
659 }
660 if (*(args[1]) == 0) {
661 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
662 err_code |= ERR_ALERT | ERR_FATAL;
663 goto out;
664 }
665 global.rlimit_nofile = atol(args[1]);
666 }
667 else if (!strcmp(args[0], "chroot")) {
668 if (alertif_too_many_args(1, file, linenum, args, &err_code))
669 goto out;
670 if (global.chroot != NULL) {
671 ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
672 err_code |= ERR_ALERT;
673 goto out;
674 }
675 if (*(args[1]) == 0) {
676 ha_alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
677 err_code |= ERR_ALERT | ERR_FATAL;
678 goto out;
679 }
680 global.chroot = strdup(args[1]);
681 }
682 else if (!strcmp(args[0], "description")) {
683 int i, len=0;
684 char *d;
685
686 if (!*args[1]) {
687 ha_alert("parsing [%s:%d]: '%s' expects a string argument.\n",
688 file, linenum, args[0]);
689 err_code |= ERR_ALERT | ERR_FATAL;
690 goto out;
691 }
692
693 for (i = 1; *args[i]; i++)
694 len += strlen(args[i]) + 1;
695
696 if (global.desc)
697 free(global.desc);
698
699 global.desc = d = calloc(1, len);
700
701 d += snprintf(d, global.desc + len - d, "%s", args[1]);
702 for (i = 2; *args[i]; i++)
703 d += snprintf(d, global.desc + len - d, " %s", args[i]);
704 }
705 else if (!strcmp(args[0], "node")) {
706 int i;
707 char c;
708
709 if (alertif_too_many_args(1, file, linenum, args, &err_code))
710 goto out;
711
712 for (i=0; args[1][i]; i++) {
713 c = args[1][i];
714 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
715 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
716 break;
717 }
718
719 if (!i || args[1][i]) {
720 ha_alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
721 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
722 file, linenum, args[0]);
723 err_code |= ERR_ALERT | ERR_FATAL;
724 goto out;
725 }
726
727 if (global.node)
728 free(global.node);
729
730 global.node = strdup(args[1]);
731 }
732 else if (!strcmp(args[0], "pidfile")) {
733 if (alertif_too_many_args(1, file, linenum, args, &err_code))
734 goto out;
735 if (global.pidfile != NULL) {
736 ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
737 err_code |= ERR_ALERT;
738 goto out;
739 }
740 if (*(args[1]) == 0) {
741 ha_alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
742 err_code |= ERR_ALERT | ERR_FATAL;
743 goto out;
744 }
745 global.pidfile = strdup(args[1]);
746 }
747 else if (!strcmp(args[0], "unix-bind")) {
748 int cur_arg = 1;
749 while (*(args[cur_arg])) {
750 if (!strcmp(args[cur_arg], "prefix")) {
751 if (global.unix_bind.prefix != NULL) {
752 ha_alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
753 err_code |= ERR_ALERT;
754 cur_arg += 2;
755 continue;
756 }
757
758 if (*(args[cur_arg+1]) == 0) {
759 ha_alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
760 err_code |= ERR_ALERT | ERR_FATAL;
761 goto out;
762 }
763 global.unix_bind.prefix = strdup(args[cur_arg+1]);
764 cur_arg += 2;
765 continue;
766 }
767
768 if (!strcmp(args[cur_arg], "mode")) {
769
770 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
771 cur_arg += 2;
772 continue;
773 }
774
775 if (!strcmp(args[cur_arg], "uid")) {
776
777 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
778 cur_arg += 2;
779 continue;
780 }
781
782 if (!strcmp(args[cur_arg], "gid")) {
783
784 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
785 cur_arg += 2;
786 continue;
787 }
788
789 if (!strcmp(args[cur_arg], "user")) {
790 struct passwd *user;
791
792 user = getpwnam(args[cur_arg + 1]);
793 if (!user) {
794 ha_alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
795 file, linenum, args[0], args[cur_arg + 1 ]);
796 err_code |= ERR_ALERT | ERR_FATAL;
797 goto out;
798 }
799
800 global.unix_bind.ux.uid = user->pw_uid;
801 cur_arg += 2;
802 continue;
803 }
804
805 if (!strcmp(args[cur_arg], "group")) {
806 struct group *group;
807
808 group = getgrnam(args[cur_arg + 1]);
809 if (!group) {
810 ha_alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
811 file, linenum, args[0], args[cur_arg + 1 ]);
812 err_code |= ERR_ALERT | ERR_FATAL;
813 goto out;
814 }
815
816 global.unix_bind.ux.gid = group->gr_gid;
817 cur_arg += 2;
818 continue;
819 }
820
821 ha_alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
822 file, linenum, args[0]);
823 err_code |= ERR_ALERT | ERR_FATAL;
824 goto out;
825 }
826 }
827 else if (!strcmp(args[0], "log")) { /* "no log" or "log ..." */
828 if (!parse_logsrv(args, &global.logsrvs, (kwm == KWM_NO), &errmsg)) {
829 ha_alert("parsing [%s:%d] : %s : %s\n", file, linenum, args[0], errmsg);
830 err_code |= ERR_ALERT | ERR_FATAL;
831 goto out;
832 }
833 }
834 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
835 char *name;
836
837 if (global.log_send_hostname != NULL) {
838 ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
839 err_code |= ERR_ALERT;
840 goto out;
841 }
842
843 if (*(args[1]))
844 name = args[1];
845 else
846 name = hostname;
847
848 free(global.log_send_hostname);
849 global.log_send_hostname = strdup(name);
850 }
851 else if (!strcmp(args[0], "server-state-base")) { /* path base where HAProxy can find server state files */
852 if (global.server_state_base != NULL) {
853 ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
854 err_code |= ERR_ALERT;
855 goto out;
856 }
857
858 if (!*(args[1])) {
859 ha_alert("parsing [%s:%d] : '%s' expects one argument: a directory path.\n", file, linenum, args[0]);
860 err_code |= ERR_FATAL;
861 goto out;
862 }
863
864 global.server_state_base = strdup(args[1]);
865 }
866 else if (!strcmp(args[0], "server-state-file")) { /* path to the file where HAProxy can load the server states */
867 if (global.server_state_file != NULL) {
868 ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
869 err_code |= ERR_ALERT;
870 goto out;
871 }
872
873 if (!*(args[1])) {
874 ha_alert("parsing [%s:%d] : '%s' expect one argument: a file path.\n", file, linenum, args[0]);
875 err_code |= ERR_FATAL;
876 goto out;
877 }
878
879 global.server_state_file = strdup(args[1]);
880 }
881 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
882 if (alertif_too_many_args(1, file, linenum, args, &err_code))
883 goto out;
884 if (*(args[1]) == 0) {
885 ha_alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
886 err_code |= ERR_ALERT | ERR_FATAL;
887 goto out;
888 }
889 chunk_destroy(&global.log_tag);
890 chunk_initstr(&global.log_tag, strdup(args[1]));
891 }
892 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
893 if (alertif_too_many_args(1, file, linenum, args, &err_code))
894 goto out;
895 if (global.spread_checks != 0) {
896 ha_alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
897 err_code |= ERR_ALERT;
898 goto out;
899 }
900 if (*(args[1]) == 0) {
901 ha_alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
902 err_code |= ERR_ALERT | ERR_FATAL;
903 goto out;
904 }
905 global.spread_checks = atol(args[1]);
906 if (global.spread_checks < 0 || global.spread_checks > 50) {
907 ha_alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
908 err_code |= ERR_ALERT | ERR_FATAL;
909 }
910 }
911 else if (!strcmp(args[0], "max-spread-checks")) { /* maximum time between first and last check */
912 const char *err;
913 unsigned int val;
914
915 if (alertif_too_many_args(1, file, linenum, args, &err_code))
916 goto out;
917 if (*(args[1]) == 0) {
918 ha_alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
919 err_code |= ERR_ALERT | ERR_FATAL;
920 goto out;
921 }
922
923 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
924 if (err) {
925 ha_alert("parsing [%s:%d]: unsupported character '%c' in '%s' (wants an integer delay).\n", file, linenum, *err, args[0]);
926 err_code |= ERR_ALERT | ERR_FATAL;
927 }
928 global.max_spread_checks = val;
929 if (global.max_spread_checks < 0) {
930 ha_alert("parsing [%s:%d]: '%s' needs a positive delay in milliseconds.\n",file, linenum, args[0]);
931 err_code |= ERR_ALERT | ERR_FATAL;
932 }
933 }
934 else if (strcmp(args[0], "cpu-map") == 0) {
935 /* map a process list to a CPU set */
936#ifdef USE_CPU_AFFINITY
937 char *slash;
938 unsigned long proc = 0, thread = 0, cpus;
939 int i, j, n, autoinc;
940
941 if (!*args[1] || !*args[2]) {
942 ha_alert("parsing [%s:%d] : %s expects a process number "
943 " ('all', 'odd', 'even', a number from 1 to %d or a range), "
944 " followed by a list of CPU ranges with numbers from 0 to %d.\n",
Willy Tarreau5799e9c2019-03-05 18:14:03 +0100945 file, linenum, args[0], LONGBITS, LONGBITS - 1);
Willy Tarreau36b9e222018-11-11 15:19:52 +0100946 err_code |= ERR_ALERT | ERR_FATAL;
947 goto out;
948 }
949
950 if ((slash = strchr(args[1], '/')) != NULL)
951 *slash = 0;
952
Willy Tarreau5799e9c2019-03-05 18:14:03 +0100953 /* note: we silently ignore processes over MAX_PROCS and
954 * threads over MAX_THREADS so as not to make configurations a
955 * pain to maintain.
956 */
957 if (parse_process_number(args[1], &proc, LONGBITS, &autoinc, &errmsg)) {
Willy Tarreau36b9e222018-11-11 15:19:52 +0100958 ha_alert("parsing [%s:%d] : %s : %s\n", file, linenum, args[0], errmsg);
959 err_code |= ERR_ALERT | ERR_FATAL;
960 goto out;
961 }
962
963 if (slash) {
Willy Tarreau5799e9c2019-03-05 18:14:03 +0100964 if (parse_process_number(slash+1, &thread, LONGBITS, NULL, &errmsg)) {
Willy Tarreau36b9e222018-11-11 15:19:52 +0100965 ha_alert("parsing [%s:%d] : %s : %s\n", file, linenum, args[0], errmsg);
966 err_code |= ERR_ALERT | ERR_FATAL;
967 goto out;
968 }
969 *slash = '/';
970
971 if (autoinc && atleast2(proc) && atleast2(thread)) {
972 ha_alert("parsing [%s:%d] : %s : '%s' : unable to automatically bind "
973 "a process range _AND_ a thread range\n",
974 file, linenum, args[0], args[1]);
975 err_code |= ERR_ALERT | ERR_FATAL;
976 goto out;
977 }
978 }
979
980 if (parse_cpu_set((const char **)args+2, &cpus, &errmsg)) {
981 ha_alert("parsing [%s:%d] : %s : %s\n", file, linenum, args[0], errmsg);
982 err_code |= ERR_ALERT | ERR_FATAL;
983 goto out;
984 }
985
986 if (autoinc &&
987 my_popcountl(proc) != my_popcountl(cpus) &&
988 my_popcountl(thread) != my_popcountl(cpus)) {
989 ha_alert("parsing [%s:%d] : %s : PROC/THREAD range and CPU sets "
990 "must have the same size to be automatically bound\n",
991 file, linenum, args[0]);
992 err_code |= ERR_ALERT | ERR_FATAL;
993 goto out;
994 }
995
Willy Tarreauff9c9142019-02-07 10:39:36 +0100996 for (i = n = 0; i < MAX_PROCS; i++) {
Willy Tarreau36b9e222018-11-11 15:19:52 +0100997 /* No mapping for this process */
998 if (!(proc & (1UL << i)))
999 continue;
1000
1001 /* Mapping at the process level */
1002 if (!thread) {
1003 if (!autoinc)
1004 global.cpu_map.proc[i] = cpus;
1005 else {
1006 n += my_ffsl(cpus >> n);
1007 global.cpu_map.proc[i] = (1UL << (n-1));
1008 }
1009 continue;
1010 }
1011
1012 /* Mapping at the thread level */
1013 for (j = 0; j < MAX_THREADS; j++) {
1014 /* Np mapping for this thread */
1015 if (!(thread & (1UL << j)))
1016 continue;
1017
1018 if (!autoinc)
1019 global.cpu_map.thread[i][j] = cpus;
1020 else {
1021 n += my_ffsl(cpus >> n);
1022 global.cpu_map.thread[i][j] = (1UL << (n-1));
1023 }
1024 }
1025 }
1026#else
1027 ha_alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n",
1028 file, linenum, args[0]);
1029 err_code |= ERR_ALERT | ERR_FATAL;
1030 goto out;
1031#endif /* ! USE_CPU_AFFINITY */
1032 }
1033 else if (strcmp(args[0], "setenv") == 0 || strcmp(args[0], "presetenv") == 0) {
1034 if (alertif_too_many_args(3, file, linenum, args, &err_code))
1035 goto out;
1036
1037 if (*(args[2]) == 0) {
1038 ha_alert("parsing [%s:%d]: '%s' expects a name and a value.\n", file, linenum, args[0]);
1039 err_code |= ERR_ALERT | ERR_FATAL;
1040 goto out;
1041 }
1042
1043 /* "setenv" overwrites, "presetenv" only sets if not yet set */
1044 if (setenv(args[1], args[2], (args[0][0] == 's')) != 0) {
1045 ha_alert("parsing [%s:%d]: '%s' failed on variable '%s' : %s.\n", file, linenum, args[0], args[1], strerror(errno));
1046 err_code |= ERR_ALERT | ERR_FATAL;
1047 goto out;
1048 }
1049 }
1050 else if (!strcmp(args[0], "unsetenv")) {
1051 int arg;
1052
1053 if (*(args[1]) == 0) {
1054 ha_alert("parsing [%s:%d]: '%s' expects at least one variable name.\n", file, linenum, args[0]);
1055 err_code |= ERR_ALERT | ERR_FATAL;
1056 goto out;
1057 }
1058
1059 for (arg = 1; *args[arg]; arg++) {
1060 if (unsetenv(args[arg]) != 0) {
1061 ha_alert("parsing [%s:%d]: '%s' failed on variable '%s' : %s.\n", file, linenum, args[0], args[arg], strerror(errno));
1062 err_code |= ERR_ALERT | ERR_FATAL;
1063 goto out;
1064 }
1065 }
1066 }
1067 else if (!strcmp(args[0], "resetenv")) {
1068 extern char **environ;
1069 char **env = environ;
1070
1071 /* args contain variable names to keep, one per argument */
1072 while (*env) {
1073 int arg;
1074
1075 /* look for current variable in among all those we want to keep */
1076 for (arg = 1; *args[arg]; arg++) {
1077 if (strncmp(*env, args[arg], strlen(args[arg])) == 0 &&
1078 (*env)[strlen(args[arg])] == '=')
1079 break;
1080 }
1081
1082 /* delete this variable */
1083 if (!*args[arg]) {
1084 char *delim = strchr(*env, '=');
1085
1086 if (!delim || delim - *env >= trash.size) {
1087 ha_alert("parsing [%s:%d]: '%s' failed to unset invalid variable '%s'.\n", file, linenum, args[0], *env);
1088 err_code |= ERR_ALERT | ERR_FATAL;
1089 goto out;
1090 }
1091
1092 memcpy(trash.area, *env, delim - *env);
1093 trash.area[delim - *env] = 0;
1094
1095 if (unsetenv(trash.area) != 0) {
1096 ha_alert("parsing [%s:%d]: '%s' failed to unset variable '%s' : %s.\n", file, linenum, args[0], *env, strerror(errno));
1097 err_code |= ERR_ALERT | ERR_FATAL;
1098 goto out;
1099 }
1100 }
1101 else
1102 env++;
1103 }
1104 }
1105 else {
1106 struct cfg_kw_list *kwl;
1107 int index;
1108 int rc;
1109
1110 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1111 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1112 if (kwl->kw[index].section != CFG_GLOBAL)
1113 continue;
1114 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
1115 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
1116 if (rc < 0) {
1117 ha_alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
1118 err_code |= ERR_ALERT | ERR_FATAL;
1119 }
1120 else if (rc > 0) {
1121 ha_warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
1122 err_code |= ERR_WARN;
1123 goto out;
1124 }
1125 goto out;
1126 }
1127 }
1128 }
1129
1130 ha_alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
1131 err_code |= ERR_ALERT | ERR_FATAL;
1132 }
1133
1134 out:
1135 free(errmsg);
1136 return err_code;
1137}
1138