blob: 2b3249758e8ddcc7a1a30fab0b8eaaab8b8fcb07 [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;
Willy Tarreau1b857852020-02-25 11:27:22 +010060 ha_warning("parsing [%s:%d] : '%s' must never be used and will be removed in 2.3. If you need debug mode, please use '-d' on the command line.\n", file, linenum, args[0]);
61 err_code |= ERR_WARN;
62 goto out;
Willy Tarreau36b9e222018-11-11 15:19:52 +010063 }
64 else if (!strcmp(args[0], "noepoll")) {
65 if (alertif_too_many_args(0, file, linenum, args, &err_code))
66 goto out;
67 global.tune.options &= ~GTUNE_USE_EPOLL;
68 }
69 else if (!strcmp(args[0], "nokqueue")) {
70 if (alertif_too_many_args(0, file, linenum, args, &err_code))
71 goto out;
72 global.tune.options &= ~GTUNE_USE_KQUEUE;
73 }
Emmanuel Hocdet0ba4f482019-04-08 16:53:32 +000074 else if (!strcmp(args[0], "noevports")) {
75 if (alertif_too_many_args(0, file, linenum, args, &err_code))
76 goto out;
77 global.tune.options &= ~GTUNE_USE_EVPORTS;
78 }
Willy Tarreau36b9e222018-11-11 15:19:52 +010079 else if (!strcmp(args[0], "nopoll")) {
80 if (alertif_too_many_args(0, file, linenum, args, &err_code))
81 goto out;
82 global.tune.options &= ~GTUNE_USE_POLL;
83 }
Willy Tarreaubeb859a2018-11-22 18:07:59 +010084 else if (!strcmp(args[0], "busy-polling")) { /* "no busy-polling" or "busy-polling" */
85 if (alertif_too_many_args(0, file, linenum, args, &err_code))
86 goto out;
87 if (kwm == KWM_NO)
88 global.tune.options &= ~GTUNE_BUSY_POLLING;
89 else
90 global.tune.options |= GTUNE_BUSY_POLLING;
91 }
Willy Tarreau636848a2019-04-15 19:38:50 +020092 else if (!strcmp(args[0], "set-dumpable")) { /* "no set-dumpable" or "set-dumpable" */
93 if (alertif_too_many_args(0, file, linenum, args, &err_code))
94 goto out;
95 if (kwm == KWM_NO)
96 global.tune.options &= ~GTUNE_SET_DUMPABLE;
97 else
98 global.tune.options |= GTUNE_SET_DUMPABLE;
99 }
Willy Tarreaud96f1122019-12-03 07:07:36 +0100100 else if (!strcmp(args[0], "insecure-fork-wanted")) { /* "no insecure-fork-wanted" or "insecure-fork-wanted" */
101 if (alertif_too_many_args(0, file, linenum, args, &err_code))
102 goto out;
103 if (kwm == KWM_NO)
104 global.tune.options &= ~GTUNE_INSECURE_FORK;
105 else
106 global.tune.options |= GTUNE_INSECURE_FORK;
107 }
Willy Tarreaua45a8b52019-12-06 16:31:45 +0100108 else if (!strcmp(args[0], "insecure-setuid-wanted")) { /* "no insecure-setuid-wanted" or "insecure-setuid-wanted" */
109 if (alertif_too_many_args(0, file, linenum, args, &err_code))
110 goto out;
111 if (kwm == KWM_NO)
112 global.tune.options &= ~GTUNE_INSECURE_SETUID;
113 else
114 global.tune.options |= GTUNE_INSECURE_SETUID;
115 }
Willy Tarreau36b9e222018-11-11 15:19:52 +0100116 else if (!strcmp(args[0], "nosplice")) {
117 if (alertif_too_many_args(0, file, linenum, args, &err_code))
118 goto out;
119 global.tune.options &= ~GTUNE_USE_SPLICE;
120 }
121 else if (!strcmp(args[0], "nogetaddrinfo")) {
122 if (alertif_too_many_args(0, file, linenum, args, &err_code))
123 goto out;
124 global.tune.options &= ~GTUNE_USE_GAI;
125 }
126 else if (!strcmp(args[0], "noreuseport")) {
127 if (alertif_too_many_args(0, file, linenum, args, &err_code))
128 goto out;
129 global.tune.options &= ~GTUNE_USE_REUSEPORT;
130 }
131 else if (!strcmp(args[0], "quiet")) {
132 if (alertif_too_many_args(0, file, linenum, args, &err_code))
133 goto out;
134 global.mode |= MODE_QUIET;
135 }
Willy Tarreau3eb10b82020-04-15 16:42:39 +0200136 else if (!strcmp(args[0], "zero-warning")) {
137 if (alertif_too_many_args(0, file, linenum, args, &err_code))
138 goto out;
139 global.mode |= MODE_ZERO_WARNING;
140 }
Willy Tarreau36b9e222018-11-11 15:19:52 +0100141 else if (!strcmp(args[0], "tune.runqueue-depth")) {
142 if (alertif_too_many_args(1, file, linenum, args, &err_code))
143 goto out;
144 if (global.tune.runqueue_depth != 0) {
145 ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
146 err_code |= ERR_ALERT;
147 goto out;
148 }
149 if (*(args[1]) == 0) {
150 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
151 err_code |= ERR_ALERT | ERR_FATAL;
152 goto out;
153 }
154 global.tune.runqueue_depth = atol(args[1]);
155
156 }
157 else if (!strcmp(args[0], "tune.maxpollevents")) {
158 if (alertif_too_many_args(1, file, linenum, args, &err_code))
159 goto out;
160 if (global.tune.maxpollevents != 0) {
161 ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
162 err_code |= ERR_ALERT;
163 goto out;
164 }
165 if (*(args[1]) == 0) {
166 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
167 err_code |= ERR_ALERT | ERR_FATAL;
168 goto out;
169 }
170 global.tune.maxpollevents = atol(args[1]);
171 }
172 else if (!strcmp(args[0], "tune.maxaccept")) {
Christopher Faulet6b02ab82019-04-30 14:03:56 +0200173 long max;
174
Willy Tarreau36b9e222018-11-11 15:19:52 +0100175 if (alertif_too_many_args(1, file, linenum, args, &err_code))
176 goto out;
177 if (global.tune.maxaccept != 0) {
178 ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
179 err_code |= ERR_ALERT;
180 goto out;
181 }
182 if (*(args[1]) == 0) {
183 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
184 err_code |= ERR_ALERT | ERR_FATAL;
185 goto out;
186 }
Christopher Faulet6b02ab82019-04-30 14:03:56 +0200187 max = atol(args[1]);
188 if (/*max < -1 || */max > INT_MAX) {
189 ha_alert("parsing [%s:%d] : '%s' expects -1 or an integer from 0 to INT_MAX.\n", file, linenum, args[0]);
190 err_code |= ERR_ALERT | ERR_FATAL;
191 goto out;
192 }
193 global.tune.maxaccept = max;
Willy Tarreau36b9e222018-11-11 15:19:52 +0100194 }
195 else if (!strcmp(args[0], "tune.chksize")) {
196 if (alertif_too_many_args(1, file, linenum, args, &err_code))
197 goto out;
198 if (*(args[1]) == 0) {
199 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
200 err_code |= ERR_ALERT | ERR_FATAL;
201 goto out;
202 }
203 global.tune.chksize = atol(args[1]);
204 }
205 else if (!strcmp(args[0], "tune.recv_enough")) {
206 if (alertif_too_many_args(1, file, linenum, args, &err_code))
207 goto out;
208 if (*(args[1]) == 0) {
209 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
210 err_code |= ERR_ALERT | ERR_FATAL;
211 goto out;
212 }
213 global.tune.recv_enough = atol(args[1]);
214 }
215 else if (!strcmp(args[0], "tune.buffers.limit")) {
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.buf_limit = atol(args[1]);
224 if (global.tune.buf_limit) {
225 if (global.tune.buf_limit < 3)
226 global.tune.buf_limit = 3;
227 if (global.tune.buf_limit <= global.tune.reserved_bufs)
228 global.tune.buf_limit = global.tune.reserved_bufs + 1;
229 }
230 }
231 else if (!strcmp(args[0], "tune.buffers.reserve")) {
232 if (alertif_too_many_args(1, file, linenum, args, &err_code))
233 goto out;
234 if (*(args[1]) == 0) {
235 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
236 err_code |= ERR_ALERT | ERR_FATAL;
237 goto out;
238 }
239 global.tune.reserved_bufs = atol(args[1]);
240 if (global.tune.reserved_bufs < 2)
241 global.tune.reserved_bufs = 2;
242 if (global.tune.buf_limit && global.tune.buf_limit <= global.tune.reserved_bufs)
243 global.tune.buf_limit = global.tune.reserved_bufs + 1;
244 }
245 else if (!strcmp(args[0], "tune.bufsize")) {
246 if (alertif_too_many_args(1, file, linenum, args, &err_code))
247 goto out;
248 if (*(args[1]) == 0) {
249 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
250 err_code |= ERR_ALERT | ERR_FATAL;
251 goto out;
252 }
253 global.tune.bufsize = atol(args[1]);
Willy Tarreauc77d3642018-12-12 06:19:42 +0100254 /* round it up to support a two-pointer alignment at the end */
255 global.tune.bufsize = (global.tune.bufsize + 2 * sizeof(void *) - 1) & -(2 * sizeof(void *));
Willy Tarreau36b9e222018-11-11 15:19:52 +0100256 if (global.tune.bufsize <= 0) {
257 ha_alert("parsing [%s:%d] : '%s' expects a positive integer argument.\n", file, linenum, args[0]);
258 err_code |= ERR_ALERT | ERR_FATAL;
259 goto out;
260 }
261 }
262 else if (!strcmp(args[0], "tune.maxrewrite")) {
263 if (alertif_too_many_args(1, file, linenum, args, &err_code))
264 goto out;
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.maxrewrite = atol(args[1]);
271 if (global.tune.maxrewrite < 0) {
272 ha_alert("parsing [%s:%d] : '%s' expects a positive integer argument.\n", file, linenum, args[0]);
273 err_code |= ERR_ALERT | ERR_FATAL;
274 goto out;
275 }
276 }
277 else if (!strcmp(args[0], "tune.idletimer")) {
278 unsigned int idle;
279 const char *res;
280
281 if (alertif_too_many_args(1, file, linenum, args, &err_code))
282 goto out;
283 if (*(args[1]) == 0) {
284 ha_alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
285 err_code |= ERR_ALERT | ERR_FATAL;
286 goto out;
287 }
288
289 res = parse_time_err(args[1], &idle, TIME_UNIT_MS);
Willy Tarreau9faebe32019-06-07 19:00:37 +0200290 if (res == PARSE_TIME_OVER) {
291 ha_alert("parsing [%s:%d]: timer overflow in argument <%s> to <%s>, maximum value is 65535 ms.\n",
292 file, linenum, args[1], args[0]);
293 err_code |= ERR_ALERT | ERR_FATAL;
294 goto out;
295 }
296 else if (res == PARSE_TIME_UNDER) {
297 ha_alert("parsing [%s:%d]: timer underflow in argument <%s> to <%s>, minimum non-null value is 1 ms.\n",
298 file, linenum, args[1], args[0]);
299 err_code |= ERR_ALERT | ERR_FATAL;
300 goto out;
301 }
302 else if (res) {
Willy Tarreau36b9e222018-11-11 15:19:52 +0100303 ha_alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
Willy Tarreau9faebe32019-06-07 19:00:37 +0200304 file, linenum, *res, args[0]);
Willy Tarreau36b9e222018-11-11 15:19:52 +0100305 err_code |= ERR_ALERT | ERR_FATAL;
306 goto out;
307 }
308
309 if (idle > 65535) {
310 ha_alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
311 err_code |= ERR_ALERT | ERR_FATAL;
312 goto out;
313 }
314 global.tune.idle_timer = idle;
315 }
316 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
317 if (alertif_too_many_args(1, file, linenum, args, &err_code))
318 goto out;
319 if (global.tune.client_rcvbuf != 0) {
320 ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
321 err_code |= ERR_ALERT;
322 goto out;
323 }
324 if (*(args[1]) == 0) {
325 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
326 err_code |= ERR_ALERT | ERR_FATAL;
327 goto out;
328 }
329 global.tune.client_rcvbuf = atol(args[1]);
330 }
331 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
332 if (alertif_too_many_args(1, file, linenum, args, &err_code))
333 goto out;
334 if (global.tune.server_rcvbuf != 0) {
335 ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
336 err_code |= ERR_ALERT;
337 goto out;
338 }
339 if (*(args[1]) == 0) {
340 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
341 err_code |= ERR_ALERT | ERR_FATAL;
342 goto out;
343 }
344 global.tune.server_rcvbuf = atol(args[1]);
345 }
346 else if (!strcmp(args[0], "tune.sndbuf.client")) {
347 if (alertif_too_many_args(1, file, linenum, args, &err_code))
348 goto out;
349 if (global.tune.client_sndbuf != 0) {
350 ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
351 err_code |= ERR_ALERT;
352 goto out;
353 }
354 if (*(args[1]) == 0) {
355 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
356 err_code |= ERR_ALERT | ERR_FATAL;
357 goto out;
358 }
359 global.tune.client_sndbuf = atol(args[1]);
360 }
361 else if (!strcmp(args[0], "tune.sndbuf.server")) {
362 if (alertif_too_many_args(1, file, linenum, args, &err_code))
363 goto out;
364 if (global.tune.server_sndbuf != 0) {
365 ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
366 err_code |= ERR_ALERT;
367 goto out;
368 }
369 if (*(args[1]) == 0) {
370 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
371 err_code |= ERR_ALERT | ERR_FATAL;
372 goto out;
373 }
374 global.tune.server_sndbuf = atol(args[1]);
375 }
376 else if (!strcmp(args[0], "tune.pipesize")) {
377 if (alertif_too_many_args(1, file, linenum, args, &err_code))
378 goto out;
379 if (*(args[1]) == 0) {
380 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
381 err_code |= ERR_ALERT | ERR_FATAL;
382 goto out;
383 }
384 global.tune.pipesize = atol(args[1]);
385 }
386 else if (!strcmp(args[0], "tune.http.cookielen")) {
387 if (alertif_too_many_args(1, file, linenum, args, &err_code))
388 goto out;
389 if (*(args[1]) == 0) {
390 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
391 err_code |= ERR_ALERT | ERR_FATAL;
392 goto out;
393 }
394 global.tune.cookie_len = atol(args[1]) + 1;
395 }
396 else if (!strcmp(args[0], "tune.http.logurilen")) {
397 if (alertif_too_many_args(1, file, linenum, args, &err_code))
398 goto out;
399 if (*(args[1]) == 0) {
400 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
401 err_code |= ERR_ALERT | ERR_FATAL;
402 goto out;
403 }
404 global.tune.requri_len = atol(args[1]) + 1;
405 }
406 else if (!strcmp(args[0], "tune.http.maxhdr")) {
407 if (alertif_too_many_args(1, file, linenum, args, &err_code))
408 goto out;
409 if (*(args[1]) == 0) {
410 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
411 err_code |= ERR_ALERT | ERR_FATAL;
412 goto out;
413 }
414 global.tune.max_http_hdr = atoi(args[1]);
415 if (global.tune.max_http_hdr < 1 || global.tune.max_http_hdr > 32767) {
416 ha_alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 32767\n",
417 file, linenum, args[0]);
418 err_code |= ERR_ALERT | ERR_FATAL;
419 goto out;
420 }
421 }
422 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
423 if (alertif_too_many_args(1, file, linenum, args, &err_code))
424 goto out;
425 if (*args[1]) {
426 global.tune.comp_maxlevel = atoi(args[1]);
427 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
428 ha_alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
429 file, linenum, args[0]);
430 err_code |= ERR_ALERT | ERR_FATAL;
431 goto out;
432 }
433 } else {
434 ha_alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
435 file, linenum, args[0]);
436 err_code |= ERR_ALERT | ERR_FATAL;
437 goto out;
438 }
439 }
440 else if (!strcmp(args[0], "tune.pattern.cache-size")) {
441 if (*args[1]) {
442 global.tune.pattern_cache = atoi(args[1]);
443 if (global.tune.pattern_cache < 0) {
444 ha_alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
445 file, linenum, args[0]);
446 err_code |= ERR_ALERT | ERR_FATAL;
447 goto out;
448 }
449 } else {
450 ha_alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
451 file, linenum, args[0]);
452 err_code |= ERR_ALERT | ERR_FATAL;
453 goto out;
454 }
455 }
456 else if (!strcmp(args[0], "uid")) {
457 if (alertif_too_many_args(1, file, linenum, args, &err_code))
458 goto out;
459 if (global.uid != 0) {
460 ha_alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
461 err_code |= ERR_ALERT;
462 goto out;
463 }
464 if (*(args[1]) == 0) {
465 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
466 err_code |= ERR_ALERT | ERR_FATAL;
467 goto out;
468 }
469 if (strl2irc(args[1], strlen(args[1]), &global.uid) != 0) {
470 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]);
471 err_code |= ERR_WARN;
472 goto out;
473 }
474
475 }
476 else if (!strcmp(args[0], "gid")) {
477 if (alertif_too_many_args(1, file, linenum, args, &err_code))
478 goto out;
479 if (global.gid != 0) {
480 ha_alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
481 err_code |= ERR_ALERT;
482 goto out;
483 }
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 if (strl2irc(args[1], strlen(args[1]), &global.gid) != 0) {
490 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]);
491 err_code |= ERR_WARN;
492 goto out;
493 }
494 }
495 else if (!strcmp(args[0], "external-check")) {
496 if (alertif_too_many_args(0, file, linenum, args, &err_code))
497 goto out;
498 global.external_check = 1;
499 }
500 /* user/group name handling */
501 else if (!strcmp(args[0], "user")) {
502 struct passwd *ha_user;
503 if (alertif_too_many_args(1, file, linenum, args, &err_code))
504 goto out;
505 if (global.uid != 0) {
506 ha_alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
507 err_code |= ERR_ALERT;
508 goto out;
509 }
510 errno = 0;
511 ha_user = getpwnam(args[1]);
512 if (ha_user != NULL) {
513 global.uid = (int)ha_user->pw_uid;
514 }
515 else {
516 ha_alert("parsing [%s:%d] : cannot find user id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
517 err_code |= ERR_ALERT | ERR_FATAL;
518 }
519 }
520 else if (!strcmp(args[0], "group")) {
521 struct group *ha_group;
522 if (alertif_too_many_args(1, file, linenum, args, &err_code))
523 goto out;
524 if (global.gid != 0) {
525 ha_alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
526 err_code |= ERR_ALERT;
527 goto out;
528 }
529 errno = 0;
530 ha_group = getgrnam(args[1]);
531 if (ha_group != NULL) {
532 global.gid = (int)ha_group->gr_gid;
533 }
534 else {
535 ha_alert("parsing [%s:%d] : cannot find group id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
536 err_code |= ERR_ALERT | ERR_FATAL;
537 }
538 }
539 /* end of user/group name handling*/
540 else if (!strcmp(args[0], "nbproc")) {
541 if (alertif_too_many_args(1, file, linenum, args, &err_code))
542 goto out;
543 if (*(args[1]) == 0) {
544 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
545 err_code |= ERR_ALERT | ERR_FATAL;
546 goto out;
547 }
548 global.nbproc = atol(args[1]);
Willy Tarreaua38a7172019-02-02 17:11:28 +0100549 all_proc_mask = nbits(global.nbproc);
Willy Tarreauff9c9142019-02-07 10:39:36 +0100550 if (global.nbproc < 1 || global.nbproc > MAX_PROCS) {
Willy Tarreau36b9e222018-11-11 15:19:52 +0100551 ha_alert("parsing [%s:%d] : '%s' must be between 1 and %d (was %d).\n",
Willy Tarreauff9c9142019-02-07 10:39:36 +0100552 file, linenum, args[0], MAX_PROCS, global.nbproc);
Willy Tarreau36b9e222018-11-11 15:19:52 +0100553 err_code |= ERR_ALERT | ERR_FATAL;
554 goto out;
555 }
556 }
557 else if (!strcmp(args[0], "nbthread")) {
558 if (alertif_too_many_args(1, file, linenum, args, &err_code))
559 goto out;
560 if (*(args[1]) == 0) {
561 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
562 err_code |= ERR_ALERT | ERR_FATAL;
563 goto out;
564 }
565 global.nbthread = parse_nbthread(args[1], &errmsg);
566 if (!global.nbthread) {
567 ha_alert("parsing [%s:%d] : '%s' %s.\n",
568 file, linenum, args[0], errmsg);
569 err_code |= ERR_ALERT | ERR_FATAL;
570 goto out;
571 }
572 }
573 else if (!strcmp(args[0], "maxconn")) {
574 if (alertif_too_many_args(1, file, linenum, args, &err_code))
575 goto out;
576 if (global.maxconn != 0) {
577 ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
578 err_code |= ERR_ALERT;
579 goto out;
580 }
581 if (*(args[1]) == 0) {
582 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
583 err_code |= ERR_ALERT | ERR_FATAL;
584 goto out;
585 }
586 global.maxconn = atol(args[1]);
587#ifdef SYSTEM_MAXCONN
Willy Tarreauca783d42019-03-13 10:03:07 +0100588 if (global.maxconn > SYSTEM_MAXCONN && cfg_maxconn <= SYSTEM_MAXCONN) {
589 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, SYSTEM_MAXCONN);
590 global.maxconn = SYSTEM_MAXCONN;
Willy Tarreau36b9e222018-11-11 15:19:52 +0100591 err_code |= ERR_ALERT;
592 }
593#endif /* SYSTEM_MAXCONN */
594 }
595 else if (!strcmp(args[0], "ssl-server-verify")) {
596 if (alertif_too_many_args(1, file, linenum, args, &err_code))
597 goto out;
598 if (*(args[1]) == 0) {
599 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
600 err_code |= ERR_ALERT | ERR_FATAL;
601 goto out;
602 }
603 if (strcmp(args[1],"none") == 0)
604 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
605 else if (strcmp(args[1],"required") == 0)
606 global.ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED;
607 else {
608 ha_alert("parsing [%s:%d] : '%s' expects 'none' or 'required' as argument.\n", file, linenum, args[0]);
609 err_code |= ERR_ALERT | ERR_FATAL;
610 goto out;
611 }
612 }
613 else if (!strcmp(args[0], "maxconnrate")) {
614 if (alertif_too_many_args(1, file, linenum, args, &err_code))
615 goto out;
616 if (global.cps_lim != 0) {
617 ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
618 err_code |= ERR_ALERT;
619 goto out;
620 }
621 if (*(args[1]) == 0) {
622 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
623 err_code |= ERR_ALERT | ERR_FATAL;
624 goto out;
625 }
626 global.cps_lim = atol(args[1]);
627 }
628 else if (!strcmp(args[0], "maxsessrate")) {
629 if (alertif_too_many_args(1, file, linenum, args, &err_code))
630 goto out;
631 if (global.sps_lim != 0) {
632 ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
633 err_code |= ERR_ALERT;
634 goto out;
635 }
636 if (*(args[1]) == 0) {
637 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
638 err_code |= ERR_ALERT | ERR_FATAL;
639 goto out;
640 }
641 global.sps_lim = atol(args[1]);
642 }
643 else if (!strcmp(args[0], "maxsslrate")) {
644 if (alertif_too_many_args(1, file, linenum, args, &err_code))
645 goto out;
646 if (global.ssl_lim != 0) {
647 ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
648 err_code |= ERR_ALERT;
649 goto out;
650 }
651 if (*(args[1]) == 0) {
652 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
653 err_code |= ERR_ALERT | ERR_FATAL;
654 goto out;
655 }
656 global.ssl_lim = atol(args[1]);
657 }
658 else if (!strcmp(args[0], "maxcomprate")) {
659 if (alertif_too_many_args(1, file, linenum, args, &err_code))
660 goto out;
661 if (*(args[1]) == 0) {
662 ha_alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
663 err_code |= ERR_ALERT | ERR_FATAL;
664 goto out;
665 }
666 global.comp_rate_lim = atoi(args[1]) * 1024;
667 }
668 else if (!strcmp(args[0], "maxpipes")) {
669 if (alertif_too_many_args(1, file, linenum, args, &err_code))
670 goto out;
671 if (global.maxpipes != 0) {
672 ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
673 err_code |= ERR_ALERT;
674 goto out;
675 }
676 if (*(args[1]) == 0) {
677 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
678 err_code |= ERR_ALERT | ERR_FATAL;
679 goto out;
680 }
681 global.maxpipes = atol(args[1]);
682 }
683 else if (!strcmp(args[0], "maxzlibmem")) {
684 if (alertif_too_many_args(1, file, linenum, args, &err_code))
685 goto out;
686 if (*(args[1]) == 0) {
687 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
688 err_code |= ERR_ALERT | ERR_FATAL;
689 goto out;
690 }
691 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
692 }
693 else if (!strcmp(args[0], "maxcompcpuusage")) {
694 if (alertif_too_many_args(1, file, linenum, args, &err_code))
695 goto out;
696 if (*(args[1]) == 0) {
697 ha_alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
698 err_code |= ERR_ALERT | ERR_FATAL;
699 goto out;
700 }
701 compress_min_idle = 100 - atoi(args[1]);
702 if (compress_min_idle > 100) {
703 ha_alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
704 err_code |= ERR_ALERT | ERR_FATAL;
705 goto out;
706 }
707 }
708
709 else if (!strcmp(args[0], "ulimit-n")) {
710 if (alertif_too_many_args(1, file, linenum, args, &err_code))
711 goto out;
712 if (global.rlimit_nofile != 0) {
713 ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
714 err_code |= ERR_ALERT;
715 goto out;
716 }
717 if (*(args[1]) == 0) {
718 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
719 err_code |= ERR_ALERT | ERR_FATAL;
720 goto out;
721 }
722 global.rlimit_nofile = atol(args[1]);
723 }
724 else if (!strcmp(args[0], "chroot")) {
725 if (alertif_too_many_args(1, file, linenum, args, &err_code))
726 goto out;
727 if (global.chroot != NULL) {
728 ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
729 err_code |= ERR_ALERT;
730 goto out;
731 }
732 if (*(args[1]) == 0) {
733 ha_alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
734 err_code |= ERR_ALERT | ERR_FATAL;
735 goto out;
736 }
737 global.chroot = strdup(args[1]);
738 }
739 else if (!strcmp(args[0], "description")) {
740 int i, len=0;
741 char *d;
742
743 if (!*args[1]) {
744 ha_alert("parsing [%s:%d]: '%s' expects a string argument.\n",
745 file, linenum, args[0]);
746 err_code |= ERR_ALERT | ERR_FATAL;
747 goto out;
748 }
749
750 for (i = 1; *args[i]; i++)
751 len += strlen(args[i]) + 1;
752
753 if (global.desc)
754 free(global.desc);
755
756 global.desc = d = calloc(1, len);
757
758 d += snprintf(d, global.desc + len - d, "%s", args[1]);
759 for (i = 2; *args[i]; i++)
760 d += snprintf(d, global.desc + len - d, " %s", args[i]);
761 }
762 else if (!strcmp(args[0], "node")) {
763 int i;
764 char c;
765
766 if (alertif_too_many_args(1, file, linenum, args, &err_code))
767 goto out;
768
769 for (i=0; args[1][i]; i++) {
770 c = args[1][i];
771 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
772 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
773 break;
774 }
775
776 if (!i || args[1][i]) {
777 ha_alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
778 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
779 file, linenum, args[0]);
780 err_code |= ERR_ALERT | ERR_FATAL;
781 goto out;
782 }
783
784 if (global.node)
785 free(global.node);
786
787 global.node = strdup(args[1]);
788 }
789 else if (!strcmp(args[0], "pidfile")) {
790 if (alertif_too_many_args(1, file, linenum, args, &err_code))
791 goto out;
792 if (global.pidfile != NULL) {
793 ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
794 err_code |= ERR_ALERT;
795 goto out;
796 }
797 if (*(args[1]) == 0) {
798 ha_alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
799 err_code |= ERR_ALERT | ERR_FATAL;
800 goto out;
801 }
802 global.pidfile = strdup(args[1]);
803 }
804 else if (!strcmp(args[0], "unix-bind")) {
805 int cur_arg = 1;
806 while (*(args[cur_arg])) {
807 if (!strcmp(args[cur_arg], "prefix")) {
808 if (global.unix_bind.prefix != NULL) {
809 ha_alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
810 err_code |= ERR_ALERT;
811 cur_arg += 2;
812 continue;
813 }
814
815 if (*(args[cur_arg+1]) == 0) {
816 ha_alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
817 err_code |= ERR_ALERT | ERR_FATAL;
818 goto out;
819 }
820 global.unix_bind.prefix = strdup(args[cur_arg+1]);
821 cur_arg += 2;
822 continue;
823 }
824
825 if (!strcmp(args[cur_arg], "mode")) {
826
827 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
828 cur_arg += 2;
829 continue;
830 }
831
832 if (!strcmp(args[cur_arg], "uid")) {
833
834 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
835 cur_arg += 2;
836 continue;
837 }
838
839 if (!strcmp(args[cur_arg], "gid")) {
840
841 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
842 cur_arg += 2;
843 continue;
844 }
845
846 if (!strcmp(args[cur_arg], "user")) {
847 struct passwd *user;
848
849 user = getpwnam(args[cur_arg + 1]);
850 if (!user) {
851 ha_alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
852 file, linenum, args[0], args[cur_arg + 1 ]);
853 err_code |= ERR_ALERT | ERR_FATAL;
854 goto out;
855 }
856
857 global.unix_bind.ux.uid = user->pw_uid;
858 cur_arg += 2;
859 continue;
860 }
861
862 if (!strcmp(args[cur_arg], "group")) {
863 struct group *group;
864
865 group = getgrnam(args[cur_arg + 1]);
866 if (!group) {
867 ha_alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
868 file, linenum, args[0], args[cur_arg + 1 ]);
869 err_code |= ERR_ALERT | ERR_FATAL;
870 goto out;
871 }
872
873 global.unix_bind.ux.gid = group->gr_gid;
874 cur_arg += 2;
875 continue;
876 }
877
878 ha_alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
879 file, linenum, args[0]);
880 err_code |= ERR_ALERT | ERR_FATAL;
881 goto out;
882 }
883 }
884 else if (!strcmp(args[0], "log")) { /* "no log" or "log ..." */
885 if (!parse_logsrv(args, &global.logsrvs, (kwm == KWM_NO), &errmsg)) {
886 ha_alert("parsing [%s:%d] : %s : %s\n", file, linenum, args[0], errmsg);
887 err_code |= ERR_ALERT | ERR_FATAL;
888 goto out;
889 }
890 }
891 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
892 char *name;
893
894 if (global.log_send_hostname != NULL) {
895 ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
896 err_code |= ERR_ALERT;
897 goto out;
898 }
899
900 if (*(args[1]))
901 name = args[1];
902 else
903 name = hostname;
904
905 free(global.log_send_hostname);
906 global.log_send_hostname = strdup(name);
907 }
908 else if (!strcmp(args[0], "server-state-base")) { /* path base where HAProxy can find server state files */
909 if (global.server_state_base != NULL) {
910 ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
911 err_code |= ERR_ALERT;
912 goto out;
913 }
914
915 if (!*(args[1])) {
916 ha_alert("parsing [%s:%d] : '%s' expects one argument: a directory path.\n", file, linenum, args[0]);
917 err_code |= ERR_FATAL;
918 goto out;
919 }
920
921 global.server_state_base = strdup(args[1]);
922 }
923 else if (!strcmp(args[0], "server-state-file")) { /* path to the file where HAProxy can load the server states */
924 if (global.server_state_file != NULL) {
925 ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
926 err_code |= ERR_ALERT;
927 goto out;
928 }
929
930 if (!*(args[1])) {
931 ha_alert("parsing [%s:%d] : '%s' expect one argument: a file path.\n", file, linenum, args[0]);
932 err_code |= ERR_FATAL;
933 goto out;
934 }
935
936 global.server_state_file = strdup(args[1]);
937 }
938 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
939 if (alertif_too_many_args(1, file, linenum, args, &err_code))
940 goto out;
941 if (*(args[1]) == 0) {
942 ha_alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
943 err_code |= ERR_ALERT | ERR_FATAL;
944 goto out;
945 }
946 chunk_destroy(&global.log_tag);
947 chunk_initstr(&global.log_tag, strdup(args[1]));
948 }
949 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
950 if (alertif_too_many_args(1, file, linenum, args, &err_code))
951 goto out;
952 if (global.spread_checks != 0) {
953 ha_alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
954 err_code |= ERR_ALERT;
955 goto out;
956 }
957 if (*(args[1]) == 0) {
958 ha_alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
959 err_code |= ERR_ALERT | ERR_FATAL;
960 goto out;
961 }
962 global.spread_checks = atol(args[1]);
963 if (global.spread_checks < 0 || global.spread_checks > 50) {
964 ha_alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
965 err_code |= ERR_ALERT | ERR_FATAL;
966 }
967 }
968 else if (!strcmp(args[0], "max-spread-checks")) { /* maximum time between first and last check */
969 const char *err;
970 unsigned int val;
971
972 if (alertif_too_many_args(1, file, linenum, args, &err_code))
973 goto out;
974 if (*(args[1]) == 0) {
975 ha_alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
976 err_code |= ERR_ALERT | ERR_FATAL;
977 goto out;
978 }
979
980 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
Willy Tarreau9faebe32019-06-07 19:00:37 +0200981 if (err == PARSE_TIME_OVER) {
982 ha_alert("parsing [%s:%d]: timer overflow in argument <%s> to <%s>, maximum value is 2147483647 ms (~24.8 days).\n",
983 file, linenum, args[1], args[0]);
Willy Tarreau36b9e222018-11-11 15:19:52 +0100984 err_code |= ERR_ALERT | ERR_FATAL;
985 }
Willy Tarreau9faebe32019-06-07 19:00:37 +0200986 else if (err == PARSE_TIME_UNDER) {
987 ha_alert("parsing [%s:%d]: timer underflow in argument <%s> to <%s>, minimum non-null value is 1 ms.\n",
988 file, linenum, args[1], args[0]);
989 err_code |= ERR_ALERT | ERR_FATAL;
990 }
991 else if (err) {
992 ha_alert("parsing [%s:%d]: unsupported character '%c' in '%s' (wants an integer delay).\n", file, linenum, *err, args[0]);
Willy Tarreau36b9e222018-11-11 15:19:52 +0100993 err_code |= ERR_ALERT | ERR_FATAL;
994 }
Willy Tarreau9faebe32019-06-07 19:00:37 +0200995 global.max_spread_checks = val;
Willy Tarreau36b9e222018-11-11 15:19:52 +0100996 }
997 else if (strcmp(args[0], "cpu-map") == 0) {
998 /* map a process list to a CPU set */
999#ifdef USE_CPU_AFFINITY
1000 char *slash;
1001 unsigned long proc = 0, thread = 0, cpus;
1002 int i, j, n, autoinc;
1003
1004 if (!*args[1] || !*args[2]) {
1005 ha_alert("parsing [%s:%d] : %s expects a process number "
1006 " ('all', 'odd', 'even', a number from 1 to %d or a range), "
1007 " followed by a list of CPU ranges with numbers from 0 to %d.\n",
Willy Tarreau5799e9c2019-03-05 18:14:03 +01001008 file, linenum, args[0], LONGBITS, LONGBITS - 1);
Willy Tarreau36b9e222018-11-11 15:19:52 +01001009 err_code |= ERR_ALERT | ERR_FATAL;
1010 goto out;
1011 }
1012
1013 if ((slash = strchr(args[1], '/')) != NULL)
1014 *slash = 0;
1015
Willy Tarreau5799e9c2019-03-05 18:14:03 +01001016 /* note: we silently ignore processes over MAX_PROCS and
1017 * threads over MAX_THREADS so as not to make configurations a
1018 * pain to maintain.
1019 */
1020 if (parse_process_number(args[1], &proc, LONGBITS, &autoinc, &errmsg)) {
Willy Tarreau36b9e222018-11-11 15:19:52 +01001021 ha_alert("parsing [%s:%d] : %s : %s\n", file, linenum, args[0], errmsg);
1022 err_code |= ERR_ALERT | ERR_FATAL;
1023 goto out;
1024 }
1025
1026 if (slash) {
Willy Tarreau5799e9c2019-03-05 18:14:03 +01001027 if (parse_process_number(slash+1, &thread, LONGBITS, NULL, &errmsg)) {
Willy Tarreau36b9e222018-11-11 15:19:52 +01001028 ha_alert("parsing [%s:%d] : %s : %s\n", file, linenum, args[0], errmsg);
1029 err_code |= ERR_ALERT | ERR_FATAL;
1030 goto out;
1031 }
1032 *slash = '/';
1033
1034 if (autoinc && atleast2(proc) && atleast2(thread)) {
1035 ha_alert("parsing [%s:%d] : %s : '%s' : unable to automatically bind "
1036 "a process range _AND_ a thread range\n",
1037 file, linenum, args[0], args[1]);
1038 err_code |= ERR_ALERT | ERR_FATAL;
1039 goto out;
1040 }
1041 }
1042
1043 if (parse_cpu_set((const char **)args+2, &cpus, &errmsg)) {
1044 ha_alert("parsing [%s:%d] : %s : %s\n", file, linenum, args[0], errmsg);
1045 err_code |= ERR_ALERT | ERR_FATAL;
1046 goto out;
1047 }
1048
1049 if (autoinc &&
1050 my_popcountl(proc) != my_popcountl(cpus) &&
1051 my_popcountl(thread) != my_popcountl(cpus)) {
1052 ha_alert("parsing [%s:%d] : %s : PROC/THREAD range and CPU sets "
1053 "must have the same size to be automatically bound\n",
1054 file, linenum, args[0]);
1055 err_code |= ERR_ALERT | ERR_FATAL;
1056 goto out;
1057 }
1058
Willy Tarreau7764a572019-07-16 15:10:34 +02001059 /* we now have to deal with 3 real cases :
1060 * cpu-map P-Q => mapping for whole processes, numbers P to Q
1061 * cpu-map P-Q/1 => mapping of first thread of processes P to Q
1062 * cpu-map 1/T-U => mapping of threads T to U of process 1
1063 * Otherwise other combinations are silently ignored since nbthread
1064 * and nbproc cannot both be >1 :
1065 * cpu-map P-Q/T => mapping for thread T for processes P to Q.
1066 * Only one of T,Q may be > 1, others ignored.
1067 * cpu-map P/T-U => mapping for threads T to U of process P. Only
1068 * one of P,U may be > 1, others ignored.
1069 */
1070 if (!thread) {
1071 /* mapping for whole processes. E.g. cpu-map 1-4 0-3 */
Willy Tarreau81492c92019-05-03 09:41:23 +02001072 for (i = n = 0; i < MAX_PROCS; i++) {
1073 /* No mapping for this process */
1074 if (!(proc & (1UL << i)))
1075 continue;
1076
Willy Tarreau36b9e222018-11-11 15:19:52 +01001077 if (!autoinc)
1078 global.cpu_map.proc[i] = cpus;
1079 else {
1080 n += my_ffsl(cpus >> n);
1081 global.cpu_map.proc[i] = (1UL << (n-1));
1082 }
Willy Tarreau36b9e222018-11-11 15:19:52 +01001083 }
Willy Tarreau7764a572019-07-16 15:10:34 +02001084 } else {
1085 /* Mapping at the thread level. All threads are retained
1086 * for process 1, and only thread 1 is retained for other
1087 * processes.
1088 */
1089 if (thread == 0x1) {
1090 /* first thread, iterate on processes. E.g. cpu-map 1-4/1 0-3 */
1091 for (i = n = 0; i < MAX_PROCS; i++) {
1092 /* No mapping for this process */
1093 if (!(proc & (1UL << i)))
1094 continue;
1095 if (!autoinc)
1096 global.cpu_map.proc_t1[i] = cpus;
1097 else {
1098 n += my_ffsl(cpus >> n);
1099 global.cpu_map.proc_t1[i] = (1UL << (n-1));
1100 }
1101 }
1102 }
Willy Tarreau36b9e222018-11-11 15:19:52 +01001103
Willy Tarreau7764a572019-07-16 15:10:34 +02001104 if (proc == 0x1) {
1105 /* first process, iterate on threads. E.g. cpu-map 1/1-4 0-3 */
1106 for (j = n = 0; j < MAX_THREADS; j++) {
1107 /* No mapping for this thread */
1108 if (!(thread & (1UL << j)))
1109 continue;
Willy Tarreau36b9e222018-11-11 15:19:52 +01001110
Willy Tarreau7764a572019-07-16 15:10:34 +02001111 if (!autoinc)
1112 global.cpu_map.thread[j] = cpus;
1113 else {
1114 n += my_ffsl(cpus >> n);
1115 global.cpu_map.thread[j] = (1UL << (n-1));
1116 }
Willy Tarreau36b9e222018-11-11 15:19:52 +01001117 }
1118 }
1119 }
1120#else
1121 ha_alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n",
1122 file, linenum, args[0]);
1123 err_code |= ERR_ALERT | ERR_FATAL;
1124 goto out;
1125#endif /* ! USE_CPU_AFFINITY */
1126 }
1127 else if (strcmp(args[0], "setenv") == 0 || strcmp(args[0], "presetenv") == 0) {
1128 if (alertif_too_many_args(3, file, linenum, args, &err_code))
1129 goto out;
1130
1131 if (*(args[2]) == 0) {
1132 ha_alert("parsing [%s:%d]: '%s' expects a name and a value.\n", file, linenum, args[0]);
1133 err_code |= ERR_ALERT | ERR_FATAL;
1134 goto out;
1135 }
1136
1137 /* "setenv" overwrites, "presetenv" only sets if not yet set */
1138 if (setenv(args[1], args[2], (args[0][0] == 's')) != 0) {
1139 ha_alert("parsing [%s:%d]: '%s' failed on variable '%s' : %s.\n", file, linenum, args[0], args[1], strerror(errno));
1140 err_code |= ERR_ALERT | ERR_FATAL;
1141 goto out;
1142 }
1143 }
1144 else if (!strcmp(args[0], "unsetenv")) {
1145 int arg;
1146
1147 if (*(args[1]) == 0) {
1148 ha_alert("parsing [%s:%d]: '%s' expects at least one variable name.\n", file, linenum, args[0]);
1149 err_code |= ERR_ALERT | ERR_FATAL;
1150 goto out;
1151 }
1152
1153 for (arg = 1; *args[arg]; arg++) {
1154 if (unsetenv(args[arg]) != 0) {
1155 ha_alert("parsing [%s:%d]: '%s' failed on variable '%s' : %s.\n", file, linenum, args[0], args[arg], strerror(errno));
1156 err_code |= ERR_ALERT | ERR_FATAL;
1157 goto out;
1158 }
1159 }
1160 }
1161 else if (!strcmp(args[0], "resetenv")) {
1162 extern char **environ;
1163 char **env = environ;
1164
1165 /* args contain variable names to keep, one per argument */
1166 while (*env) {
1167 int arg;
1168
1169 /* look for current variable in among all those we want to keep */
1170 for (arg = 1; *args[arg]; arg++) {
1171 if (strncmp(*env, args[arg], strlen(args[arg])) == 0 &&
1172 (*env)[strlen(args[arg])] == '=')
1173 break;
1174 }
1175
1176 /* delete this variable */
1177 if (!*args[arg]) {
1178 char *delim = strchr(*env, '=');
1179
1180 if (!delim || delim - *env >= trash.size) {
1181 ha_alert("parsing [%s:%d]: '%s' failed to unset invalid variable '%s'.\n", file, linenum, args[0], *env);
1182 err_code |= ERR_ALERT | ERR_FATAL;
1183 goto out;
1184 }
1185
1186 memcpy(trash.area, *env, delim - *env);
1187 trash.area[delim - *env] = 0;
1188
1189 if (unsetenv(trash.area) != 0) {
1190 ha_alert("parsing [%s:%d]: '%s' failed to unset variable '%s' : %s.\n", file, linenum, args[0], *env, strerror(errno));
1191 err_code |= ERR_ALERT | ERR_FATAL;
1192 goto out;
1193 }
1194 }
1195 else
1196 env++;
1197 }
1198 }
William Dauchy0fec3ab2019-10-27 20:08:11 +01001199 else if (!strcmp(args[0], "strict-limits")) { /* "no strict-limits" or "strict-limits" */
1200 if (alertif_too_many_args(0, file, linenum, args, &err_code))
1201 goto out;
1202 if (kwm == KWM_NO)
1203 global.tune.options &= ~GTUNE_STRICT_LIMITS;
1204 else
1205 global.tune.options |= GTUNE_STRICT_LIMITS;
1206 }
Willy Tarreau36b9e222018-11-11 15:19:52 +01001207 else {
1208 struct cfg_kw_list *kwl;
1209 int index;
1210 int rc;
1211
1212 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1213 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1214 if (kwl->kw[index].section != CFG_GLOBAL)
1215 continue;
1216 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
1217 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
1218 if (rc < 0) {
1219 ha_alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
1220 err_code |= ERR_ALERT | ERR_FATAL;
1221 }
1222 else if (rc > 0) {
1223 ha_warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
1224 err_code |= ERR_WARN;
1225 goto out;
1226 }
1227 goto out;
1228 }
1229 }
1230 }
1231
1232 ha_alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
1233 err_code |= ERR_ALERT | ERR_FATAL;
1234 }
1235
1236 out:
1237 free(errmsg);
1238 return err_code;
1239}
1240