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