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