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