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