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