blob: 4303ef9875a68b5aa735273be044521bb703e6e9 [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]);
209 if (global.tune.bufsize <= 0) {
210 ha_alert("parsing [%s:%d] : '%s' expects a positive integer argument.\n", file, linenum, args[0]);
211 err_code |= ERR_ALERT | ERR_FATAL;
212 goto out;
213 }
214 }
215 else if (!strcmp(args[0], "tune.maxrewrite")) {
216 if (alertif_too_many_args(1, file, linenum, args, &err_code))
217 goto out;
218 if (*(args[1]) == 0) {
219 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
220 err_code |= ERR_ALERT | ERR_FATAL;
221 goto out;
222 }
223 global.tune.maxrewrite = atol(args[1]);
224 if (global.tune.maxrewrite < 0) {
225 ha_alert("parsing [%s:%d] : '%s' expects a positive integer argument.\n", file, linenum, args[0]);
226 err_code |= ERR_ALERT | ERR_FATAL;
227 goto out;
228 }
229 }
230 else if (!strcmp(args[0], "tune.idletimer")) {
231 unsigned int idle;
232 const char *res;
233
234 if (alertif_too_many_args(1, file, linenum, args, &err_code))
235 goto out;
236 if (*(args[1]) == 0) {
237 ha_alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
238 err_code |= ERR_ALERT | ERR_FATAL;
239 goto out;
240 }
241
242 res = parse_time_err(args[1], &idle, TIME_UNIT_MS);
243 if (res) {
244 ha_alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
245 file, linenum, *res, args[0]);
246 err_code |= ERR_ALERT | ERR_FATAL;
247 goto out;
248 }
249
250 if (idle > 65535) {
251 ha_alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
252 err_code |= ERR_ALERT | ERR_FATAL;
253 goto out;
254 }
255 global.tune.idle_timer = idle;
256 }
257 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
258 if (alertif_too_many_args(1, file, linenum, args, &err_code))
259 goto out;
260 if (global.tune.client_rcvbuf != 0) {
261 ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
262 err_code |= ERR_ALERT;
263 goto out;
264 }
265 if (*(args[1]) == 0) {
266 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
267 err_code |= ERR_ALERT | ERR_FATAL;
268 goto out;
269 }
270 global.tune.client_rcvbuf = atol(args[1]);
271 }
272 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
273 if (alertif_too_many_args(1, file, linenum, args, &err_code))
274 goto out;
275 if (global.tune.server_rcvbuf != 0) {
276 ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
277 err_code |= ERR_ALERT;
278 goto out;
279 }
280 if (*(args[1]) == 0) {
281 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
282 err_code |= ERR_ALERT | ERR_FATAL;
283 goto out;
284 }
285 global.tune.server_rcvbuf = atol(args[1]);
286 }
287 else if (!strcmp(args[0], "tune.sndbuf.client")) {
288 if (alertif_too_many_args(1, file, linenum, args, &err_code))
289 goto out;
290 if (global.tune.client_sndbuf != 0) {
291 ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
292 err_code |= ERR_ALERT;
293 goto out;
294 }
295 if (*(args[1]) == 0) {
296 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
297 err_code |= ERR_ALERT | ERR_FATAL;
298 goto out;
299 }
300 global.tune.client_sndbuf = atol(args[1]);
301 }
302 else if (!strcmp(args[0], "tune.sndbuf.server")) {
303 if (alertif_too_many_args(1, file, linenum, args, &err_code))
304 goto out;
305 if (global.tune.server_sndbuf != 0) {
306 ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
307 err_code |= ERR_ALERT;
308 goto out;
309 }
310 if (*(args[1]) == 0) {
311 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
312 err_code |= ERR_ALERT | ERR_FATAL;
313 goto out;
314 }
315 global.tune.server_sndbuf = atol(args[1]);
316 }
317 else if (!strcmp(args[0], "tune.pipesize")) {
318 if (alertif_too_many_args(1, file, linenum, args, &err_code))
319 goto out;
320 if (*(args[1]) == 0) {
321 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
322 err_code |= ERR_ALERT | ERR_FATAL;
323 goto out;
324 }
325 global.tune.pipesize = atol(args[1]);
326 }
327 else if (!strcmp(args[0], "tune.http.cookielen")) {
328 if (alertif_too_many_args(1, file, linenum, args, &err_code))
329 goto out;
330 if (*(args[1]) == 0) {
331 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
332 err_code |= ERR_ALERT | ERR_FATAL;
333 goto out;
334 }
335 global.tune.cookie_len = atol(args[1]) + 1;
336 }
337 else if (!strcmp(args[0], "tune.http.logurilen")) {
338 if (alertif_too_many_args(1, file, linenum, args, &err_code))
339 goto out;
340 if (*(args[1]) == 0) {
341 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
342 err_code |= ERR_ALERT | ERR_FATAL;
343 goto out;
344 }
345 global.tune.requri_len = atol(args[1]) + 1;
346 }
347 else if (!strcmp(args[0], "tune.http.maxhdr")) {
348 if (alertif_too_many_args(1, file, linenum, args, &err_code))
349 goto out;
350 if (*(args[1]) == 0) {
351 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
352 err_code |= ERR_ALERT | ERR_FATAL;
353 goto out;
354 }
355 global.tune.max_http_hdr = atoi(args[1]);
356 if (global.tune.max_http_hdr < 1 || global.tune.max_http_hdr > 32767) {
357 ha_alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 32767\n",
358 file, linenum, args[0]);
359 err_code |= ERR_ALERT | ERR_FATAL;
360 goto out;
361 }
362 }
363 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
364 if (alertif_too_many_args(1, file, linenum, args, &err_code))
365 goto out;
366 if (*args[1]) {
367 global.tune.comp_maxlevel = atoi(args[1]);
368 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
369 ha_alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
370 file, linenum, args[0]);
371 err_code |= ERR_ALERT | ERR_FATAL;
372 goto out;
373 }
374 } else {
375 ha_alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
376 file, linenum, args[0]);
377 err_code |= ERR_ALERT | ERR_FATAL;
378 goto out;
379 }
380 }
381 else if (!strcmp(args[0], "tune.pattern.cache-size")) {
382 if (*args[1]) {
383 global.tune.pattern_cache = atoi(args[1]);
384 if (global.tune.pattern_cache < 0) {
385 ha_alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
386 file, linenum, args[0]);
387 err_code |= ERR_ALERT | ERR_FATAL;
388 goto out;
389 }
390 } else {
391 ha_alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
392 file, linenum, args[0]);
393 err_code |= ERR_ALERT | ERR_FATAL;
394 goto out;
395 }
396 }
397 else if (!strcmp(args[0], "uid")) {
398 if (alertif_too_many_args(1, file, linenum, args, &err_code))
399 goto out;
400 if (global.uid != 0) {
401 ha_alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
402 err_code |= ERR_ALERT;
403 goto out;
404 }
405 if (*(args[1]) == 0) {
406 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
407 err_code |= ERR_ALERT | ERR_FATAL;
408 goto out;
409 }
410 if (strl2irc(args[1], strlen(args[1]), &global.uid) != 0) {
411 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]);
412 err_code |= ERR_WARN;
413 goto out;
414 }
415
416 }
417 else if (!strcmp(args[0], "gid")) {
418 if (alertif_too_many_args(1, file, linenum, args, &err_code))
419 goto out;
420 if (global.gid != 0) {
421 ha_alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
422 err_code |= ERR_ALERT;
423 goto out;
424 }
425 if (*(args[1]) == 0) {
426 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
427 err_code |= ERR_ALERT | ERR_FATAL;
428 goto out;
429 }
430 if (strl2irc(args[1], strlen(args[1]), &global.gid) != 0) {
431 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]);
432 err_code |= ERR_WARN;
433 goto out;
434 }
435 }
436 else if (!strcmp(args[0], "external-check")) {
437 if (alertif_too_many_args(0, file, linenum, args, &err_code))
438 goto out;
439 global.external_check = 1;
440 }
441 /* user/group name handling */
442 else if (!strcmp(args[0], "user")) {
443 struct passwd *ha_user;
444 if (alertif_too_many_args(1, file, linenum, args, &err_code))
445 goto out;
446 if (global.uid != 0) {
447 ha_alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
448 err_code |= ERR_ALERT;
449 goto out;
450 }
451 errno = 0;
452 ha_user = getpwnam(args[1]);
453 if (ha_user != NULL) {
454 global.uid = (int)ha_user->pw_uid;
455 }
456 else {
457 ha_alert("parsing [%s:%d] : cannot find user id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
458 err_code |= ERR_ALERT | ERR_FATAL;
459 }
460 }
461 else if (!strcmp(args[0], "group")) {
462 struct group *ha_group;
463 if (alertif_too_many_args(1, file, linenum, args, &err_code))
464 goto out;
465 if (global.gid != 0) {
466 ha_alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
467 err_code |= ERR_ALERT;
468 goto out;
469 }
470 errno = 0;
471 ha_group = getgrnam(args[1]);
472 if (ha_group != NULL) {
473 global.gid = (int)ha_group->gr_gid;
474 }
475 else {
476 ha_alert("parsing [%s:%d] : cannot find group id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
477 err_code |= ERR_ALERT | ERR_FATAL;
478 }
479 }
480 /* end of user/group name handling*/
481 else if (!strcmp(args[0], "nbproc")) {
482 if (alertif_too_many_args(1, file, linenum, args, &err_code))
483 goto out;
484 if (*(args[1]) == 0) {
485 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
486 err_code |= ERR_ALERT | ERR_FATAL;
487 goto out;
488 }
489 global.nbproc = atol(args[1]);
490 if (global.nbproc < 1 || global.nbproc > LONGBITS) {
491 ha_alert("parsing [%s:%d] : '%s' must be between 1 and %d (was %d).\n",
492 file, linenum, args[0], LONGBITS, global.nbproc);
493 err_code |= ERR_ALERT | ERR_FATAL;
494 goto out;
495 }
496 }
497 else if (!strcmp(args[0], "nbthread")) {
498 if (alertif_too_many_args(1, file, linenum, args, &err_code))
499 goto out;
500 if (*(args[1]) == 0) {
501 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
502 err_code |= ERR_ALERT | ERR_FATAL;
503 goto out;
504 }
505 global.nbthread = parse_nbthread(args[1], &errmsg);
506 if (!global.nbthread) {
507 ha_alert("parsing [%s:%d] : '%s' %s.\n",
508 file, linenum, args[0], errmsg);
509 err_code |= ERR_ALERT | ERR_FATAL;
510 goto out;
511 }
512 }
513 else if (!strcmp(args[0], "maxconn")) {
514 if (alertif_too_many_args(1, file, linenum, args, &err_code))
515 goto out;
516 if (global.maxconn != 0) {
517 ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
518 err_code |= ERR_ALERT;
519 goto out;
520 }
521 if (*(args[1]) == 0) {
522 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
523 err_code |= ERR_ALERT | ERR_FATAL;
524 goto out;
525 }
526 global.maxconn = atol(args[1]);
527#ifdef SYSTEM_MAXCONN
528 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
529 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);
530 global.maxconn = DEFAULT_MAXCONN;
531 err_code |= ERR_ALERT;
532 }
533#endif /* SYSTEM_MAXCONN */
534 }
535 else if (!strcmp(args[0], "ssl-server-verify")) {
536 if (alertif_too_many_args(1, file, linenum, args, &err_code))
537 goto out;
538 if (*(args[1]) == 0) {
539 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
540 err_code |= ERR_ALERT | ERR_FATAL;
541 goto out;
542 }
543 if (strcmp(args[1],"none") == 0)
544 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
545 else if (strcmp(args[1],"required") == 0)
546 global.ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED;
547 else {
548 ha_alert("parsing [%s:%d] : '%s' expects 'none' or 'required' as argument.\n", file, linenum, args[0]);
549 err_code |= ERR_ALERT | ERR_FATAL;
550 goto out;
551 }
552 }
553 else if (!strcmp(args[0], "maxconnrate")) {
554 if (alertif_too_many_args(1, file, linenum, args, &err_code))
555 goto out;
556 if (global.cps_lim != 0) {
557 ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
558 err_code |= ERR_ALERT;
559 goto out;
560 }
561 if (*(args[1]) == 0) {
562 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
563 err_code |= ERR_ALERT | ERR_FATAL;
564 goto out;
565 }
566 global.cps_lim = atol(args[1]);
567 }
568 else if (!strcmp(args[0], "maxsessrate")) {
569 if (alertif_too_many_args(1, file, linenum, args, &err_code))
570 goto out;
571 if (global.sps_lim != 0) {
572 ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
573 err_code |= ERR_ALERT;
574 goto out;
575 }
576 if (*(args[1]) == 0) {
577 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
578 err_code |= ERR_ALERT | ERR_FATAL;
579 goto out;
580 }
581 global.sps_lim = atol(args[1]);
582 }
583 else if (!strcmp(args[0], "maxsslrate")) {
584 if (alertif_too_many_args(1, file, linenum, args, &err_code))
585 goto out;
586 if (global.ssl_lim != 0) {
587 ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
588 err_code |= ERR_ALERT;
589 goto out;
590 }
591 if (*(args[1]) == 0) {
592 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
593 err_code |= ERR_ALERT | ERR_FATAL;
594 goto out;
595 }
596 global.ssl_lim = atol(args[1]);
597 }
598 else if (!strcmp(args[0], "maxcomprate")) {
599 if (alertif_too_many_args(1, file, linenum, args, &err_code))
600 goto out;
601 if (*(args[1]) == 0) {
602 ha_alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
603 err_code |= ERR_ALERT | ERR_FATAL;
604 goto out;
605 }
606 global.comp_rate_lim = atoi(args[1]) * 1024;
607 }
608 else if (!strcmp(args[0], "maxpipes")) {
609 if (alertif_too_many_args(1, file, linenum, args, &err_code))
610 goto out;
611 if (global.maxpipes != 0) {
612 ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
613 err_code |= ERR_ALERT;
614 goto out;
615 }
616 if (*(args[1]) == 0) {
617 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
618 err_code |= ERR_ALERT | ERR_FATAL;
619 goto out;
620 }
621 global.maxpipes = atol(args[1]);
622 }
623 else if (!strcmp(args[0], "maxzlibmem")) {
624 if (alertif_too_many_args(1, file, linenum, args, &err_code))
625 goto out;
626 if (*(args[1]) == 0) {
627 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
628 err_code |= ERR_ALERT | ERR_FATAL;
629 goto out;
630 }
631 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
632 }
633 else if (!strcmp(args[0], "maxcompcpuusage")) {
634 if (alertif_too_many_args(1, file, linenum, args, &err_code))
635 goto out;
636 if (*(args[1]) == 0) {
637 ha_alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
638 err_code |= ERR_ALERT | ERR_FATAL;
639 goto out;
640 }
641 compress_min_idle = 100 - atoi(args[1]);
642 if (compress_min_idle > 100) {
643 ha_alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
644 err_code |= ERR_ALERT | ERR_FATAL;
645 goto out;
646 }
647 }
648
649 else if (!strcmp(args[0], "ulimit-n")) {
650 if (alertif_too_many_args(1, file, linenum, args, &err_code))
651 goto out;
652 if (global.rlimit_nofile != 0) {
653 ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
654 err_code |= ERR_ALERT;
655 goto out;
656 }
657 if (*(args[1]) == 0) {
658 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
659 err_code |= ERR_ALERT | ERR_FATAL;
660 goto out;
661 }
662 global.rlimit_nofile = atol(args[1]);
663 }
664 else if (!strcmp(args[0], "chroot")) {
665 if (alertif_too_many_args(1, file, linenum, args, &err_code))
666 goto out;
667 if (global.chroot != NULL) {
668 ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
669 err_code |= ERR_ALERT;
670 goto out;
671 }
672 if (*(args[1]) == 0) {
673 ha_alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
674 err_code |= ERR_ALERT | ERR_FATAL;
675 goto out;
676 }
677 global.chroot = strdup(args[1]);
678 }
679 else if (!strcmp(args[0], "description")) {
680 int i, len=0;
681 char *d;
682
683 if (!*args[1]) {
684 ha_alert("parsing [%s:%d]: '%s' expects a string argument.\n",
685 file, linenum, args[0]);
686 err_code |= ERR_ALERT | ERR_FATAL;
687 goto out;
688 }
689
690 for (i = 1; *args[i]; i++)
691 len += strlen(args[i]) + 1;
692
693 if (global.desc)
694 free(global.desc);
695
696 global.desc = d = calloc(1, len);
697
698 d += snprintf(d, global.desc + len - d, "%s", args[1]);
699 for (i = 2; *args[i]; i++)
700 d += snprintf(d, global.desc + len - d, " %s", args[i]);
701 }
702 else if (!strcmp(args[0], "node")) {
703 int i;
704 char c;
705
706 if (alertif_too_many_args(1, file, linenum, args, &err_code))
707 goto out;
708
709 for (i=0; args[1][i]; i++) {
710 c = args[1][i];
711 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
712 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
713 break;
714 }
715
716 if (!i || args[1][i]) {
717 ha_alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
718 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
719 file, linenum, args[0]);
720 err_code |= ERR_ALERT | ERR_FATAL;
721 goto out;
722 }
723
724 if (global.node)
725 free(global.node);
726
727 global.node = strdup(args[1]);
728 }
729 else if (!strcmp(args[0], "pidfile")) {
730 if (alertif_too_many_args(1, file, linenum, args, &err_code))
731 goto out;
732 if (global.pidfile != NULL) {
733 ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
734 err_code |= ERR_ALERT;
735 goto out;
736 }
737 if (*(args[1]) == 0) {
738 ha_alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
739 err_code |= ERR_ALERT | ERR_FATAL;
740 goto out;
741 }
742 global.pidfile = strdup(args[1]);
743 }
744 else if (!strcmp(args[0], "unix-bind")) {
745 int cur_arg = 1;
746 while (*(args[cur_arg])) {
747 if (!strcmp(args[cur_arg], "prefix")) {
748 if (global.unix_bind.prefix != NULL) {
749 ha_alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
750 err_code |= ERR_ALERT;
751 cur_arg += 2;
752 continue;
753 }
754
755 if (*(args[cur_arg+1]) == 0) {
756 ha_alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
757 err_code |= ERR_ALERT | ERR_FATAL;
758 goto out;
759 }
760 global.unix_bind.prefix = strdup(args[cur_arg+1]);
761 cur_arg += 2;
762 continue;
763 }
764
765 if (!strcmp(args[cur_arg], "mode")) {
766
767 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
768 cur_arg += 2;
769 continue;
770 }
771
772 if (!strcmp(args[cur_arg], "uid")) {
773
774 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
775 cur_arg += 2;
776 continue;
777 }
778
779 if (!strcmp(args[cur_arg], "gid")) {
780
781 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
782 cur_arg += 2;
783 continue;
784 }
785
786 if (!strcmp(args[cur_arg], "user")) {
787 struct passwd *user;
788
789 user = getpwnam(args[cur_arg + 1]);
790 if (!user) {
791 ha_alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
792 file, linenum, args[0], args[cur_arg + 1 ]);
793 err_code |= ERR_ALERT | ERR_FATAL;
794 goto out;
795 }
796
797 global.unix_bind.ux.uid = user->pw_uid;
798 cur_arg += 2;
799 continue;
800 }
801
802 if (!strcmp(args[cur_arg], "group")) {
803 struct group *group;
804
805 group = getgrnam(args[cur_arg + 1]);
806 if (!group) {
807 ha_alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
808 file, linenum, args[0], args[cur_arg + 1 ]);
809 err_code |= ERR_ALERT | ERR_FATAL;
810 goto out;
811 }
812
813 global.unix_bind.ux.gid = group->gr_gid;
814 cur_arg += 2;
815 continue;
816 }
817
818 ha_alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
819 file, linenum, args[0]);
820 err_code |= ERR_ALERT | ERR_FATAL;
821 goto out;
822 }
823 }
824 else if (!strcmp(args[0], "log")) { /* "no log" or "log ..." */
825 if (!parse_logsrv(args, &global.logsrvs, (kwm == KWM_NO), &errmsg)) {
826 ha_alert("parsing [%s:%d] : %s : %s\n", file, linenum, args[0], errmsg);
827 err_code |= ERR_ALERT | ERR_FATAL;
828 goto out;
829 }
830 }
831 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
832 char *name;
833
834 if (global.log_send_hostname != NULL) {
835 ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
836 err_code |= ERR_ALERT;
837 goto out;
838 }
839
840 if (*(args[1]))
841 name = args[1];
842 else
843 name = hostname;
844
845 free(global.log_send_hostname);
846 global.log_send_hostname = strdup(name);
847 }
848 else if (!strcmp(args[0], "server-state-base")) { /* path base where HAProxy can find server state files */
849 if (global.server_state_base != NULL) {
850 ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
851 err_code |= ERR_ALERT;
852 goto out;
853 }
854
855 if (!*(args[1])) {
856 ha_alert("parsing [%s:%d] : '%s' expects one argument: a directory path.\n", file, linenum, args[0]);
857 err_code |= ERR_FATAL;
858 goto out;
859 }
860
861 global.server_state_base = strdup(args[1]);
862 }
863 else if (!strcmp(args[0], "server-state-file")) { /* path to the file where HAProxy can load the server states */
864 if (global.server_state_file != NULL) {
865 ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
866 err_code |= ERR_ALERT;
867 goto out;
868 }
869
870 if (!*(args[1])) {
871 ha_alert("parsing [%s:%d] : '%s' expect one argument: a file path.\n", file, linenum, args[0]);
872 err_code |= ERR_FATAL;
873 goto out;
874 }
875
876 global.server_state_file = strdup(args[1]);
877 }
878 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
879 if (alertif_too_many_args(1, file, linenum, args, &err_code))
880 goto out;
881 if (*(args[1]) == 0) {
882 ha_alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
883 err_code |= ERR_ALERT | ERR_FATAL;
884 goto out;
885 }
886 chunk_destroy(&global.log_tag);
887 chunk_initstr(&global.log_tag, strdup(args[1]));
888 }
889 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
890 if (alertif_too_many_args(1, file, linenum, args, &err_code))
891 goto out;
892 if (global.spread_checks != 0) {
893 ha_alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
894 err_code |= ERR_ALERT;
895 goto out;
896 }
897 if (*(args[1]) == 0) {
898 ha_alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
899 err_code |= ERR_ALERT | ERR_FATAL;
900 goto out;
901 }
902 global.spread_checks = atol(args[1]);
903 if (global.spread_checks < 0 || global.spread_checks > 50) {
904 ha_alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
905 err_code |= ERR_ALERT | ERR_FATAL;
906 }
907 }
908 else if (!strcmp(args[0], "max-spread-checks")) { /* maximum time between first and last check */
909 const char *err;
910 unsigned int val;
911
912 if (alertif_too_many_args(1, file, linenum, args, &err_code))
913 goto out;
914 if (*(args[1]) == 0) {
915 ha_alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
916 err_code |= ERR_ALERT | ERR_FATAL;
917 goto out;
918 }
919
920 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
921 if (err) {
922 ha_alert("parsing [%s:%d]: unsupported character '%c' in '%s' (wants an integer delay).\n", file, linenum, *err, args[0]);
923 err_code |= ERR_ALERT | ERR_FATAL;
924 }
925 global.max_spread_checks = val;
926 if (global.max_spread_checks < 0) {
927 ha_alert("parsing [%s:%d]: '%s' needs a positive delay in milliseconds.\n",file, linenum, args[0]);
928 err_code |= ERR_ALERT | ERR_FATAL;
929 }
930 }
931 else if (strcmp(args[0], "cpu-map") == 0) {
932 /* map a process list to a CPU set */
933#ifdef USE_CPU_AFFINITY
934 char *slash;
935 unsigned long proc = 0, thread = 0, cpus;
936 int i, j, n, autoinc;
937
938 if (!*args[1] || !*args[2]) {
939 ha_alert("parsing [%s:%d] : %s expects a process number "
940 " ('all', 'odd', 'even', a number from 1 to %d or a range), "
941 " followed by a list of CPU ranges with numbers from 0 to %d.\n",
942 file, linenum, args[0], LONGBITS, LONGBITS - 1);
943 err_code |= ERR_ALERT | ERR_FATAL;
944 goto out;
945 }
946
947 if ((slash = strchr(args[1], '/')) != NULL)
948 *slash = 0;
949
950 if (parse_process_number(args[1], &proc, &autoinc, &errmsg)) {
951 ha_alert("parsing [%s:%d] : %s : %s\n", file, linenum, args[0], errmsg);
952 err_code |= ERR_ALERT | ERR_FATAL;
953 goto out;
954 }
955
956 if (slash) {
957 if (parse_process_number(slash+1, &thread, NULL, &errmsg)) {
958 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 *slash = '/';
963
964 if (autoinc && atleast2(proc) && atleast2(thread)) {
965 ha_alert("parsing [%s:%d] : %s : '%s' : unable to automatically bind "
966 "a process range _AND_ a thread range\n",
967 file, linenum, args[0], args[1]);
968 err_code |= ERR_ALERT | ERR_FATAL;
969 goto out;
970 }
971 }
972
973 if (parse_cpu_set((const char **)args+2, &cpus, &errmsg)) {
974 ha_alert("parsing [%s:%d] : %s : %s\n", file, linenum, args[0], errmsg);
975 err_code |= ERR_ALERT | ERR_FATAL;
976 goto out;
977 }
978
979 if (autoinc &&
980 my_popcountl(proc) != my_popcountl(cpus) &&
981 my_popcountl(thread) != my_popcountl(cpus)) {
982 ha_alert("parsing [%s:%d] : %s : PROC/THREAD range and CPU sets "
983 "must have the same size to be automatically bound\n",
984 file, linenum, args[0]);
985 err_code |= ERR_ALERT | ERR_FATAL;
986 goto out;
987 }
988
989 for (i = n = 0; i < LONGBITS; i++) {
990 /* No mapping for this process */
991 if (!(proc & (1UL << i)))
992 continue;
993
994 /* Mapping at the process level */
995 if (!thread) {
996 if (!autoinc)
997 global.cpu_map.proc[i] = cpus;
998 else {
999 n += my_ffsl(cpus >> n);
1000 global.cpu_map.proc[i] = (1UL << (n-1));
1001 }
1002 continue;
1003 }
1004
1005 /* Mapping at the thread level */
1006 for (j = 0; j < MAX_THREADS; j++) {
1007 /* Np mapping for this thread */
1008 if (!(thread & (1UL << j)))
1009 continue;
1010
1011 if (!autoinc)
1012 global.cpu_map.thread[i][j] = cpus;
1013 else {
1014 n += my_ffsl(cpus >> n);
1015 global.cpu_map.thread[i][j] = (1UL << (n-1));
1016 }
1017 }
1018 }
1019#else
1020 ha_alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n",
1021 file, linenum, args[0]);
1022 err_code |= ERR_ALERT | ERR_FATAL;
1023 goto out;
1024#endif /* ! USE_CPU_AFFINITY */
1025 }
1026 else if (strcmp(args[0], "setenv") == 0 || strcmp(args[0], "presetenv") == 0) {
1027 if (alertif_too_many_args(3, file, linenum, args, &err_code))
1028 goto out;
1029
1030 if (*(args[2]) == 0) {
1031 ha_alert("parsing [%s:%d]: '%s' expects a name and a value.\n", file, linenum, args[0]);
1032 err_code |= ERR_ALERT | ERR_FATAL;
1033 goto out;
1034 }
1035
1036 /* "setenv" overwrites, "presetenv" only sets if not yet set */
1037 if (setenv(args[1], args[2], (args[0][0] == 's')) != 0) {
1038 ha_alert("parsing [%s:%d]: '%s' failed on variable '%s' : %s.\n", file, linenum, args[0], args[1], strerror(errno));
1039 err_code |= ERR_ALERT | ERR_FATAL;
1040 goto out;
1041 }
1042 }
1043 else if (!strcmp(args[0], "unsetenv")) {
1044 int arg;
1045
1046 if (*(args[1]) == 0) {
1047 ha_alert("parsing [%s:%d]: '%s' expects at least one variable name.\n", file, linenum, args[0]);
1048 err_code |= ERR_ALERT | ERR_FATAL;
1049 goto out;
1050 }
1051
1052 for (arg = 1; *args[arg]; arg++) {
1053 if (unsetenv(args[arg]) != 0) {
1054 ha_alert("parsing [%s:%d]: '%s' failed on variable '%s' : %s.\n", file, linenum, args[0], args[arg], strerror(errno));
1055 err_code |= ERR_ALERT | ERR_FATAL;
1056 goto out;
1057 }
1058 }
1059 }
1060 else if (!strcmp(args[0], "resetenv")) {
1061 extern char **environ;
1062 char **env = environ;
1063
1064 /* args contain variable names to keep, one per argument */
1065 while (*env) {
1066 int arg;
1067
1068 /* look for current variable in among all those we want to keep */
1069 for (arg = 1; *args[arg]; arg++) {
1070 if (strncmp(*env, args[arg], strlen(args[arg])) == 0 &&
1071 (*env)[strlen(args[arg])] == '=')
1072 break;
1073 }
1074
1075 /* delete this variable */
1076 if (!*args[arg]) {
1077 char *delim = strchr(*env, '=');
1078
1079 if (!delim || delim - *env >= trash.size) {
1080 ha_alert("parsing [%s:%d]: '%s' failed to unset invalid variable '%s'.\n", file, linenum, args[0], *env);
1081 err_code |= ERR_ALERT | ERR_FATAL;
1082 goto out;
1083 }
1084
1085 memcpy(trash.area, *env, delim - *env);
1086 trash.area[delim - *env] = 0;
1087
1088 if (unsetenv(trash.area) != 0) {
1089 ha_alert("parsing [%s:%d]: '%s' failed to unset variable '%s' : %s.\n", file, linenum, args[0], *env, strerror(errno));
1090 err_code |= ERR_ALERT | ERR_FATAL;
1091 goto out;
1092 }
1093 }
1094 else
1095 env++;
1096 }
1097 }
1098 else {
1099 struct cfg_kw_list *kwl;
1100 int index;
1101 int rc;
1102
1103 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1104 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1105 if (kwl->kw[index].section != CFG_GLOBAL)
1106 continue;
1107 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
1108 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
1109 if (rc < 0) {
1110 ha_alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
1111 err_code |= ERR_ALERT | ERR_FATAL;
1112 }
1113 else if (rc > 0) {
1114 ha_warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
1115 err_code |= ERR_WARN;
1116 goto out;
1117 }
1118 goto out;
1119 }
1120 }
1121 }
1122
1123 ha_alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
1124 err_code |= ERR_ALERT | ERR_FATAL;
1125 }
1126
1127 out:
1128 free(errmsg);
1129 return err_code;
1130}
1131