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