blob: dd37559a53a5a5db789f31d70447d5f495b57bcb [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 Tarreau36b9e222018-11-11 15:19:52 +010097 else if (!strcmp(args[0], "nosplice")) {
98 if (alertif_too_many_args(0, file, linenum, args, &err_code))
99 goto out;
100 global.tune.options &= ~GTUNE_USE_SPLICE;
101 }
102 else if (!strcmp(args[0], "nogetaddrinfo")) {
103 if (alertif_too_many_args(0, file, linenum, args, &err_code))
104 goto out;
105 global.tune.options &= ~GTUNE_USE_GAI;
106 }
107 else if (!strcmp(args[0], "noreuseport")) {
108 if (alertif_too_many_args(0, file, linenum, args, &err_code))
109 goto out;
110 global.tune.options &= ~GTUNE_USE_REUSEPORT;
111 }
112 else if (!strcmp(args[0], "quiet")) {
113 if (alertif_too_many_args(0, file, linenum, args, &err_code))
114 goto out;
115 global.mode |= MODE_QUIET;
116 }
117 else if (!strcmp(args[0], "tune.runqueue-depth")) {
118 if (alertif_too_many_args(1, file, linenum, args, &err_code))
119 goto out;
120 if (global.tune.runqueue_depth != 0) {
121 ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
122 err_code |= ERR_ALERT;
123 goto out;
124 }
125 if (*(args[1]) == 0) {
126 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
127 err_code |= ERR_ALERT | ERR_FATAL;
128 goto out;
129 }
130 global.tune.runqueue_depth = atol(args[1]);
131
132 }
133 else if (!strcmp(args[0], "tune.maxpollevents")) {
134 if (alertif_too_many_args(1, file, linenum, args, &err_code))
135 goto out;
136 if (global.tune.maxpollevents != 0) {
137 ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
138 err_code |= ERR_ALERT;
139 goto out;
140 }
141 if (*(args[1]) == 0) {
142 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
143 err_code |= ERR_ALERT | ERR_FATAL;
144 goto out;
145 }
146 global.tune.maxpollevents = atol(args[1]);
147 }
148 else if (!strcmp(args[0], "tune.maxaccept")) {
Christopher Faulet6b02ab82019-04-30 14:03:56 +0200149 long max;
150
Willy Tarreau36b9e222018-11-11 15:19:52 +0100151 if (alertif_too_many_args(1, file, linenum, args, &err_code))
152 goto out;
153 if (global.tune.maxaccept != 0) {
154 ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
155 err_code |= ERR_ALERT;
156 goto out;
157 }
158 if (*(args[1]) == 0) {
159 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
160 err_code |= ERR_ALERT | ERR_FATAL;
161 goto out;
162 }
Christopher Faulet6b02ab82019-04-30 14:03:56 +0200163 max = atol(args[1]);
164 if (/*max < -1 || */max > INT_MAX) {
165 ha_alert("parsing [%s:%d] : '%s' expects -1 or an integer from 0 to INT_MAX.\n", file, linenum, args[0]);
166 err_code |= ERR_ALERT | ERR_FATAL;
167 goto out;
168 }
169 global.tune.maxaccept = max;
Willy Tarreau36b9e222018-11-11 15:19:52 +0100170 }
171 else if (!strcmp(args[0], "tune.chksize")) {
172 if (alertif_too_many_args(1, file, linenum, args, &err_code))
173 goto out;
174 if (*(args[1]) == 0) {
175 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
176 err_code |= ERR_ALERT | ERR_FATAL;
177 goto out;
178 }
179 global.tune.chksize = atol(args[1]);
180 }
181 else if (!strcmp(args[0], "tune.recv_enough")) {
182 if (alertif_too_many_args(1, file, linenum, args, &err_code))
183 goto out;
184 if (*(args[1]) == 0) {
185 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
186 err_code |= ERR_ALERT | ERR_FATAL;
187 goto out;
188 }
189 global.tune.recv_enough = atol(args[1]);
190 }
191 else if (!strcmp(args[0], "tune.buffers.limit")) {
192 if (alertif_too_many_args(1, file, linenum, args, &err_code))
193 goto out;
194 if (*(args[1]) == 0) {
195 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
196 err_code |= ERR_ALERT | ERR_FATAL;
197 goto out;
198 }
199 global.tune.buf_limit = atol(args[1]);
200 if (global.tune.buf_limit) {
201 if (global.tune.buf_limit < 3)
202 global.tune.buf_limit = 3;
203 if (global.tune.buf_limit <= global.tune.reserved_bufs)
204 global.tune.buf_limit = global.tune.reserved_bufs + 1;
205 }
206 }
207 else if (!strcmp(args[0], "tune.buffers.reserve")) {
208 if (alertif_too_many_args(1, file, linenum, args, &err_code))
209 goto out;
210 if (*(args[1]) == 0) {
211 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
212 err_code |= ERR_ALERT | ERR_FATAL;
213 goto out;
214 }
215 global.tune.reserved_bufs = atol(args[1]);
216 if (global.tune.reserved_bufs < 2)
217 global.tune.reserved_bufs = 2;
218 if (global.tune.buf_limit && global.tune.buf_limit <= global.tune.reserved_bufs)
219 global.tune.buf_limit = global.tune.reserved_bufs + 1;
220 }
221 else if (!strcmp(args[0], "tune.bufsize")) {
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.bufsize = atol(args[1]);
Willy Tarreauc77d3642018-12-12 06:19:42 +0100230 /* round it up to support a two-pointer alignment at the end */
231 global.tune.bufsize = (global.tune.bufsize + 2 * sizeof(void *) - 1) & -(2 * sizeof(void *));
Willy Tarreau36b9e222018-11-11 15:19:52 +0100232 if (global.tune.bufsize <= 0) {
233 ha_alert("parsing [%s:%d] : '%s' expects a positive integer argument.\n", file, linenum, args[0]);
234 err_code |= ERR_ALERT | ERR_FATAL;
235 goto out;
236 }
237 }
238 else if (!strcmp(args[0], "tune.maxrewrite")) {
239 if (alertif_too_many_args(1, file, linenum, args, &err_code))
240 goto out;
241 if (*(args[1]) == 0) {
242 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
243 err_code |= ERR_ALERT | ERR_FATAL;
244 goto out;
245 }
246 global.tune.maxrewrite = atol(args[1]);
247 if (global.tune.maxrewrite < 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.idletimer")) {
254 unsigned int idle;
255 const char *res;
256
257 if (alertif_too_many_args(1, file, linenum, args, &err_code))
258 goto out;
259 if (*(args[1]) == 0) {
260 ha_alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
261 err_code |= ERR_ALERT | ERR_FATAL;
262 goto out;
263 }
264
265 res = parse_time_err(args[1], &idle, TIME_UNIT_MS);
Willy Tarreau9faebe32019-06-07 19:00:37 +0200266 if (res == PARSE_TIME_OVER) {
267 ha_alert("parsing [%s:%d]: timer overflow in argument <%s> to <%s>, maximum value is 65535 ms.\n",
268 file, linenum, args[1], args[0]);
269 err_code |= ERR_ALERT | ERR_FATAL;
270 goto out;
271 }
272 else if (res == PARSE_TIME_UNDER) {
273 ha_alert("parsing [%s:%d]: timer underflow in argument <%s> to <%s>, minimum non-null value is 1 ms.\n",
274 file, linenum, args[1], args[0]);
275 err_code |= ERR_ALERT | ERR_FATAL;
276 goto out;
277 }
278 else if (res) {
Willy Tarreau36b9e222018-11-11 15:19:52 +0100279 ha_alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
Willy Tarreau9faebe32019-06-07 19:00:37 +0200280 file, linenum, *res, args[0]);
Willy Tarreau36b9e222018-11-11 15:19:52 +0100281 err_code |= ERR_ALERT | ERR_FATAL;
282 goto out;
283 }
284
285 if (idle > 65535) {
286 ha_alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
287 err_code |= ERR_ALERT | ERR_FATAL;
288 goto out;
289 }
290 global.tune.idle_timer = idle;
291 }
292 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
293 if (alertif_too_many_args(1, file, linenum, args, &err_code))
294 goto out;
295 if (global.tune.client_rcvbuf != 0) {
296 ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
297 err_code |= ERR_ALERT;
298 goto out;
299 }
300 if (*(args[1]) == 0) {
301 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
302 err_code |= ERR_ALERT | ERR_FATAL;
303 goto out;
304 }
305 global.tune.client_rcvbuf = atol(args[1]);
306 }
307 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
308 if (alertif_too_many_args(1, file, linenum, args, &err_code))
309 goto out;
310 if (global.tune.server_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.server_rcvbuf = atol(args[1]);
321 }
322 else if (!strcmp(args[0], "tune.sndbuf.client")) {
323 if (alertif_too_many_args(1, file, linenum, args, &err_code))
324 goto out;
325 if (global.tune.client_sndbuf != 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.client_sndbuf = atol(args[1]);
336 }
337 else if (!strcmp(args[0], "tune.sndbuf.server")) {
338 if (alertif_too_many_args(1, file, linenum, args, &err_code))
339 goto out;
340 if (global.tune.server_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.server_sndbuf = atol(args[1]);
351 }
352 else if (!strcmp(args[0], "tune.pipesize")) {
353 if (alertif_too_many_args(1, file, linenum, args, &err_code))
354 goto out;
355 if (*(args[1]) == 0) {
356 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
357 err_code |= ERR_ALERT | ERR_FATAL;
358 goto out;
359 }
360 global.tune.pipesize = atol(args[1]);
361 }
362 else if (!strcmp(args[0], "tune.http.cookielen")) {
363 if (alertif_too_many_args(1, file, linenum, args, &err_code))
364 goto out;
365 if (*(args[1]) == 0) {
366 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
367 err_code |= ERR_ALERT | ERR_FATAL;
368 goto out;
369 }
370 global.tune.cookie_len = atol(args[1]) + 1;
371 }
372 else if (!strcmp(args[0], "tune.http.logurilen")) {
373 if (alertif_too_many_args(1, file, linenum, args, &err_code))
374 goto out;
375 if (*(args[1]) == 0) {
376 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
377 err_code |= ERR_ALERT | ERR_FATAL;
378 goto out;
379 }
380 global.tune.requri_len = atol(args[1]) + 1;
381 }
382 else if (!strcmp(args[0], "tune.http.maxhdr")) {
383 if (alertif_too_many_args(1, file, linenum, args, &err_code))
384 goto out;
385 if (*(args[1]) == 0) {
386 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
387 err_code |= ERR_ALERT | ERR_FATAL;
388 goto out;
389 }
390 global.tune.max_http_hdr = atoi(args[1]);
391 if (global.tune.max_http_hdr < 1 || global.tune.max_http_hdr > 32767) {
392 ha_alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 32767\n",
393 file, linenum, args[0]);
394 err_code |= ERR_ALERT | ERR_FATAL;
395 goto out;
396 }
397 }
398 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
399 if (alertif_too_many_args(1, file, linenum, args, &err_code))
400 goto out;
401 if (*args[1]) {
402 global.tune.comp_maxlevel = atoi(args[1]);
403 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
404 ha_alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
405 file, linenum, args[0]);
406 err_code |= ERR_ALERT | ERR_FATAL;
407 goto out;
408 }
409 } else {
410 ha_alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
411 file, linenum, args[0]);
412 err_code |= ERR_ALERT | ERR_FATAL;
413 goto out;
414 }
415 }
416 else if (!strcmp(args[0], "tune.pattern.cache-size")) {
417 if (*args[1]) {
418 global.tune.pattern_cache = atoi(args[1]);
419 if (global.tune.pattern_cache < 0) {
420 ha_alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
421 file, linenum, args[0]);
422 err_code |= ERR_ALERT | ERR_FATAL;
423 goto out;
424 }
425 } else {
426 ha_alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
427 file, linenum, args[0]);
428 err_code |= ERR_ALERT | ERR_FATAL;
429 goto out;
430 }
431 }
432 else if (!strcmp(args[0], "uid")) {
433 if (alertif_too_many_args(1, file, linenum, args, &err_code))
434 goto out;
435 if (global.uid != 0) {
436 ha_alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
437 err_code |= ERR_ALERT;
438 goto out;
439 }
440 if (*(args[1]) == 0) {
441 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
442 err_code |= ERR_ALERT | ERR_FATAL;
443 goto out;
444 }
445 if (strl2irc(args[1], strlen(args[1]), &global.uid) != 0) {
446 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]);
447 err_code |= ERR_WARN;
448 goto out;
449 }
450
451 }
452 else if (!strcmp(args[0], "gid")) {
453 if (alertif_too_many_args(1, file, linenum, args, &err_code))
454 goto out;
455 if (global.gid != 0) {
456 ha_alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
457 err_code |= ERR_ALERT;
458 goto out;
459 }
460 if (*(args[1]) == 0) {
461 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
462 err_code |= ERR_ALERT | ERR_FATAL;
463 goto out;
464 }
465 if (strl2irc(args[1], strlen(args[1]), &global.gid) != 0) {
466 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]);
467 err_code |= ERR_WARN;
468 goto out;
469 }
470 }
471 else if (!strcmp(args[0], "external-check")) {
472 if (alertif_too_many_args(0, file, linenum, args, &err_code))
473 goto out;
474 global.external_check = 1;
475 }
476 /* user/group name handling */
477 else if (!strcmp(args[0], "user")) {
478 struct passwd *ha_user;
479 if (alertif_too_many_args(1, file, linenum, args, &err_code))
480 goto out;
481 if (global.uid != 0) {
482 ha_alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
483 err_code |= ERR_ALERT;
484 goto out;
485 }
486 errno = 0;
487 ha_user = getpwnam(args[1]);
488 if (ha_user != NULL) {
489 global.uid = (int)ha_user->pw_uid;
490 }
491 else {
492 ha_alert("parsing [%s:%d] : cannot find user id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
493 err_code |= ERR_ALERT | ERR_FATAL;
494 }
495 }
496 else if (!strcmp(args[0], "group")) {
497 struct group *ha_group;
498 if (alertif_too_many_args(1, file, linenum, args, &err_code))
499 goto out;
500 if (global.gid != 0) {
501 ha_alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
502 err_code |= ERR_ALERT;
503 goto out;
504 }
505 errno = 0;
506 ha_group = getgrnam(args[1]);
507 if (ha_group != NULL) {
508 global.gid = (int)ha_group->gr_gid;
509 }
510 else {
511 ha_alert("parsing [%s:%d] : cannot find group id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
512 err_code |= ERR_ALERT | ERR_FATAL;
513 }
514 }
515 /* end of user/group name handling*/
516 else if (!strcmp(args[0], "nbproc")) {
517 if (alertif_too_many_args(1, file, linenum, args, &err_code))
518 goto out;
519 if (*(args[1]) == 0) {
520 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
521 err_code |= ERR_ALERT | ERR_FATAL;
522 goto out;
523 }
524 global.nbproc = atol(args[1]);
Willy Tarreaua38a7172019-02-02 17:11:28 +0100525 all_proc_mask = nbits(global.nbproc);
Willy Tarreauff9c9142019-02-07 10:39:36 +0100526 if (global.nbproc < 1 || global.nbproc > MAX_PROCS) {
Willy Tarreau36b9e222018-11-11 15:19:52 +0100527 ha_alert("parsing [%s:%d] : '%s' must be between 1 and %d (was %d).\n",
Willy Tarreauff9c9142019-02-07 10:39:36 +0100528 file, linenum, args[0], MAX_PROCS, global.nbproc);
Willy Tarreau36b9e222018-11-11 15:19:52 +0100529 err_code |= ERR_ALERT | ERR_FATAL;
530 goto out;
531 }
532 }
533 else if (!strcmp(args[0], "nbthread")) {
534 if (alertif_too_many_args(1, file, linenum, args, &err_code))
535 goto out;
536 if (*(args[1]) == 0) {
537 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
538 err_code |= ERR_ALERT | ERR_FATAL;
539 goto out;
540 }
541 global.nbthread = parse_nbthread(args[1], &errmsg);
542 if (!global.nbthread) {
543 ha_alert("parsing [%s:%d] : '%s' %s.\n",
544 file, linenum, args[0], errmsg);
545 err_code |= ERR_ALERT | ERR_FATAL;
546 goto out;
547 }
548 }
549 else if (!strcmp(args[0], "maxconn")) {
550 if (alertif_too_many_args(1, file, linenum, args, &err_code))
551 goto out;
552 if (global.maxconn != 0) {
553 ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
554 err_code |= ERR_ALERT;
555 goto out;
556 }
557 if (*(args[1]) == 0) {
558 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
559 err_code |= ERR_ALERT | ERR_FATAL;
560 goto out;
561 }
562 global.maxconn = atol(args[1]);
563#ifdef SYSTEM_MAXCONN
Willy Tarreauca783d42019-03-13 10:03:07 +0100564 if (global.maxconn > SYSTEM_MAXCONN && cfg_maxconn <= SYSTEM_MAXCONN) {
565 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);
566 global.maxconn = SYSTEM_MAXCONN;
Willy Tarreau36b9e222018-11-11 15:19:52 +0100567 err_code |= ERR_ALERT;
568 }
569#endif /* SYSTEM_MAXCONN */
570 }
571 else if (!strcmp(args[0], "ssl-server-verify")) {
572 if (alertif_too_many_args(1, file, linenum, args, &err_code))
573 goto out;
574 if (*(args[1]) == 0) {
575 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
576 err_code |= ERR_ALERT | ERR_FATAL;
577 goto out;
578 }
579 if (strcmp(args[1],"none") == 0)
580 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
581 else if (strcmp(args[1],"required") == 0)
582 global.ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED;
583 else {
584 ha_alert("parsing [%s:%d] : '%s' expects 'none' or 'required' as argument.\n", file, linenum, args[0]);
585 err_code |= ERR_ALERT | ERR_FATAL;
586 goto out;
587 }
588 }
589 else if (!strcmp(args[0], "maxconnrate")) {
590 if (alertif_too_many_args(1, file, linenum, args, &err_code))
591 goto out;
592 if (global.cps_lim != 0) {
593 ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
594 err_code |= ERR_ALERT;
595 goto out;
596 }
597 if (*(args[1]) == 0) {
598 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
599 err_code |= ERR_ALERT | ERR_FATAL;
600 goto out;
601 }
602 global.cps_lim = atol(args[1]);
603 }
604 else if (!strcmp(args[0], "maxsessrate")) {
605 if (alertif_too_many_args(1, file, linenum, args, &err_code))
606 goto out;
607 if (global.sps_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.sps_lim = atol(args[1]);
618 }
619 else if (!strcmp(args[0], "maxsslrate")) {
620 if (alertif_too_many_args(1, file, linenum, args, &err_code))
621 goto out;
622 if (global.ssl_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.ssl_lim = atol(args[1]);
633 }
634 else if (!strcmp(args[0], "maxcomprate")) {
635 if (alertif_too_many_args(1, file, linenum, args, &err_code))
636 goto out;
637 if (*(args[1]) == 0) {
638 ha_alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
639 err_code |= ERR_ALERT | ERR_FATAL;
640 goto out;
641 }
642 global.comp_rate_lim = atoi(args[1]) * 1024;
643 }
644 else if (!strcmp(args[0], "maxpipes")) {
645 if (alertif_too_many_args(1, file, linenum, args, &err_code))
646 goto out;
647 if (global.maxpipes != 0) {
648 ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
649 err_code |= ERR_ALERT;
650 goto out;
651 }
652 if (*(args[1]) == 0) {
653 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
654 err_code |= ERR_ALERT | ERR_FATAL;
655 goto out;
656 }
657 global.maxpipes = atol(args[1]);
658 }
659 else if (!strcmp(args[0], "maxzlibmem")) {
660 if (alertif_too_many_args(1, file, linenum, args, &err_code))
661 goto out;
662 if (*(args[1]) == 0) {
663 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
664 err_code |= ERR_ALERT | ERR_FATAL;
665 goto out;
666 }
667 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
668 }
669 else if (!strcmp(args[0], "maxcompcpuusage")) {
670 if (alertif_too_many_args(1, file, linenum, args, &err_code))
671 goto out;
672 if (*(args[1]) == 0) {
673 ha_alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
674 err_code |= ERR_ALERT | ERR_FATAL;
675 goto out;
676 }
677 compress_min_idle = 100 - atoi(args[1]);
678 if (compress_min_idle > 100) {
679 ha_alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
680 err_code |= ERR_ALERT | ERR_FATAL;
681 goto out;
682 }
683 }
684
685 else if (!strcmp(args[0], "ulimit-n")) {
686 if (alertif_too_many_args(1, file, linenum, args, &err_code))
687 goto out;
688 if (global.rlimit_nofile != 0) {
689 ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
690 err_code |= ERR_ALERT;
691 goto out;
692 }
693 if (*(args[1]) == 0) {
694 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
695 err_code |= ERR_ALERT | ERR_FATAL;
696 goto out;
697 }
698 global.rlimit_nofile = atol(args[1]);
699 }
700 else if (!strcmp(args[0], "chroot")) {
701 if (alertif_too_many_args(1, file, linenum, args, &err_code))
702 goto out;
703 if (global.chroot != NULL) {
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 a directory as an argument.\n", file, linenum, args[0]);
710 err_code |= ERR_ALERT | ERR_FATAL;
711 goto out;
712 }
713 global.chroot = strdup(args[1]);
714 }
715 else if (!strcmp(args[0], "description")) {
716 int i, len=0;
717 char *d;
718
719 if (!*args[1]) {
720 ha_alert("parsing [%s:%d]: '%s' expects a string argument.\n",
721 file, linenum, args[0]);
722 err_code |= ERR_ALERT | ERR_FATAL;
723 goto out;
724 }
725
726 for (i = 1; *args[i]; i++)
727 len += strlen(args[i]) + 1;
728
729 if (global.desc)
730 free(global.desc);
731
732 global.desc = d = calloc(1, len);
733
734 d += snprintf(d, global.desc + len - d, "%s", args[1]);
735 for (i = 2; *args[i]; i++)
736 d += snprintf(d, global.desc + len - d, " %s", args[i]);
737 }
738 else if (!strcmp(args[0], "node")) {
739 int i;
740 char c;
741
742 if (alertif_too_many_args(1, file, linenum, args, &err_code))
743 goto out;
744
745 for (i=0; args[1][i]; i++) {
746 c = args[1][i];
747 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
748 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
749 break;
750 }
751
752 if (!i || args[1][i]) {
753 ha_alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
754 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
755 file, linenum, args[0]);
756 err_code |= ERR_ALERT | ERR_FATAL;
757 goto out;
758 }
759
760 if (global.node)
761 free(global.node);
762
763 global.node = strdup(args[1]);
764 }
765 else if (!strcmp(args[0], "pidfile")) {
766 if (alertif_too_many_args(1, file, linenum, args, &err_code))
767 goto out;
768 if (global.pidfile != NULL) {
769 ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
770 err_code |= ERR_ALERT;
771 goto out;
772 }
773 if (*(args[1]) == 0) {
774 ha_alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
775 err_code |= ERR_ALERT | ERR_FATAL;
776 goto out;
777 }
778 global.pidfile = strdup(args[1]);
779 }
780 else if (!strcmp(args[0], "unix-bind")) {
781 int cur_arg = 1;
782 while (*(args[cur_arg])) {
783 if (!strcmp(args[cur_arg], "prefix")) {
784 if (global.unix_bind.prefix != NULL) {
785 ha_alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
786 err_code |= ERR_ALERT;
787 cur_arg += 2;
788 continue;
789 }
790
791 if (*(args[cur_arg+1]) == 0) {
792 ha_alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
793 err_code |= ERR_ALERT | ERR_FATAL;
794 goto out;
795 }
796 global.unix_bind.prefix = strdup(args[cur_arg+1]);
797 cur_arg += 2;
798 continue;
799 }
800
801 if (!strcmp(args[cur_arg], "mode")) {
802
803 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
804 cur_arg += 2;
805 continue;
806 }
807
808 if (!strcmp(args[cur_arg], "uid")) {
809
810 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
811 cur_arg += 2;
812 continue;
813 }
814
815 if (!strcmp(args[cur_arg], "gid")) {
816
817 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
818 cur_arg += 2;
819 continue;
820 }
821
822 if (!strcmp(args[cur_arg], "user")) {
823 struct passwd *user;
824
825 user = getpwnam(args[cur_arg + 1]);
826 if (!user) {
827 ha_alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
828 file, linenum, args[0], args[cur_arg + 1 ]);
829 err_code |= ERR_ALERT | ERR_FATAL;
830 goto out;
831 }
832
833 global.unix_bind.ux.uid = user->pw_uid;
834 cur_arg += 2;
835 continue;
836 }
837
838 if (!strcmp(args[cur_arg], "group")) {
839 struct group *group;
840
841 group = getgrnam(args[cur_arg + 1]);
842 if (!group) {
843 ha_alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
844 file, linenum, args[0], args[cur_arg + 1 ]);
845 err_code |= ERR_ALERT | ERR_FATAL;
846 goto out;
847 }
848
849 global.unix_bind.ux.gid = group->gr_gid;
850 cur_arg += 2;
851 continue;
852 }
853
854 ha_alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
855 file, linenum, args[0]);
856 err_code |= ERR_ALERT | ERR_FATAL;
857 goto out;
858 }
859 }
860 else if (!strcmp(args[0], "log")) { /* "no log" or "log ..." */
861 if (!parse_logsrv(args, &global.logsrvs, (kwm == KWM_NO), &errmsg)) {
862 ha_alert("parsing [%s:%d] : %s : %s\n", file, linenum, args[0], errmsg);
863 err_code |= ERR_ALERT | ERR_FATAL;
864 goto out;
865 }
866 }
867 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
868 char *name;
869
870 if (global.log_send_hostname != NULL) {
871 ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
872 err_code |= ERR_ALERT;
873 goto out;
874 }
875
876 if (*(args[1]))
877 name = args[1];
878 else
879 name = hostname;
880
881 free(global.log_send_hostname);
882 global.log_send_hostname = strdup(name);
883 }
884 else if (!strcmp(args[0], "server-state-base")) { /* path base where HAProxy can find server state files */
885 if (global.server_state_base != 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 ha_alert("parsing [%s:%d] : '%s' expects one argument: a directory path.\n", file, linenum, args[0]);
893 err_code |= ERR_FATAL;
894 goto out;
895 }
896
897 global.server_state_base = strdup(args[1]);
898 }
899 else if (!strcmp(args[0], "server-state-file")) { /* path to the file where HAProxy can load the server states */
900 if (global.server_state_file != 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' expect one argument: a file path.\n", file, linenum, args[0]);
908 err_code |= ERR_FATAL;
909 goto out;
910 }
911
912 global.server_state_file = strdup(args[1]);
913 }
914 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
915 if (alertif_too_many_args(1, file, linenum, args, &err_code))
916 goto out;
917 if (*(args[1]) == 0) {
918 ha_alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
919 err_code |= ERR_ALERT | ERR_FATAL;
920 goto out;
921 }
922 chunk_destroy(&global.log_tag);
923 chunk_initstr(&global.log_tag, strdup(args[1]));
924 }
925 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
926 if (alertif_too_many_args(1, file, linenum, args, &err_code))
927 goto out;
928 if (global.spread_checks != 0) {
929 ha_alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
930 err_code |= ERR_ALERT;
931 goto out;
932 }
933 if (*(args[1]) == 0) {
934 ha_alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
935 err_code |= ERR_ALERT | ERR_FATAL;
936 goto out;
937 }
938 global.spread_checks = atol(args[1]);
939 if (global.spread_checks < 0 || global.spread_checks > 50) {
940 ha_alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
941 err_code |= ERR_ALERT | ERR_FATAL;
942 }
943 }
944 else if (!strcmp(args[0], "max-spread-checks")) { /* maximum time between first and last check */
945 const char *err;
946 unsigned int val;
947
948 if (alertif_too_many_args(1, file, linenum, args, &err_code))
949 goto out;
950 if (*(args[1]) == 0) {
951 ha_alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
952 err_code |= ERR_ALERT | ERR_FATAL;
953 goto out;
954 }
955
956 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
Willy Tarreau9faebe32019-06-07 19:00:37 +0200957 if (err == PARSE_TIME_OVER) {
958 ha_alert("parsing [%s:%d]: timer overflow in argument <%s> to <%s>, maximum value is 2147483647 ms (~24.8 days).\n",
959 file, linenum, args[1], args[0]);
Willy Tarreau36b9e222018-11-11 15:19:52 +0100960 err_code |= ERR_ALERT | ERR_FATAL;
961 }
Willy Tarreau9faebe32019-06-07 19:00:37 +0200962 else if (err == PARSE_TIME_UNDER) {
963 ha_alert("parsing [%s:%d]: timer underflow in argument <%s> to <%s>, minimum non-null value is 1 ms.\n",
964 file, linenum, args[1], args[0]);
965 err_code |= ERR_ALERT | ERR_FATAL;
966 }
967 else if (err) {
968 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 +0100969 err_code |= ERR_ALERT | ERR_FATAL;
970 }
Willy Tarreau9faebe32019-06-07 19:00:37 +0200971 global.max_spread_checks = val;
Willy Tarreau36b9e222018-11-11 15:19:52 +0100972 }
973 else if (strcmp(args[0], "cpu-map") == 0) {
974 /* map a process list to a CPU set */
975#ifdef USE_CPU_AFFINITY
976 char *slash;
977 unsigned long proc = 0, thread = 0, cpus;
978 int i, j, n, autoinc;
979
980 if (!*args[1] || !*args[2]) {
981 ha_alert("parsing [%s:%d] : %s expects a process number "
982 " ('all', 'odd', 'even', a number from 1 to %d or a range), "
983 " followed by a list of CPU ranges with numbers from 0 to %d.\n",
Willy Tarreau5799e9c2019-03-05 18:14:03 +0100984 file, linenum, args[0], LONGBITS, LONGBITS - 1);
Willy Tarreau36b9e222018-11-11 15:19:52 +0100985 err_code |= ERR_ALERT | ERR_FATAL;
986 goto out;
987 }
988
989 if ((slash = strchr(args[1], '/')) != NULL)
990 *slash = 0;
991
Willy Tarreau5799e9c2019-03-05 18:14:03 +0100992 /* note: we silently ignore processes over MAX_PROCS and
993 * threads over MAX_THREADS so as not to make configurations a
994 * pain to maintain.
995 */
996 if (parse_process_number(args[1], &proc, LONGBITS, &autoinc, &errmsg)) {
Willy Tarreau36b9e222018-11-11 15:19:52 +0100997 ha_alert("parsing [%s:%d] : %s : %s\n", file, linenum, args[0], errmsg);
998 err_code |= ERR_ALERT | ERR_FATAL;
999 goto out;
1000 }
1001
1002 if (slash) {
Willy Tarreau5799e9c2019-03-05 18:14:03 +01001003 if (parse_process_number(slash+1, &thread, LONGBITS, NULL, &errmsg)) {
Willy Tarreau36b9e222018-11-11 15:19:52 +01001004 ha_alert("parsing [%s:%d] : %s : %s\n", file, linenum, args[0], errmsg);
1005 err_code |= ERR_ALERT | ERR_FATAL;
1006 goto out;
1007 }
1008 *slash = '/';
1009
1010 if (autoinc && atleast2(proc) && atleast2(thread)) {
1011 ha_alert("parsing [%s:%d] : %s : '%s' : unable to automatically bind "
1012 "a process range _AND_ a thread range\n",
1013 file, linenum, args[0], args[1]);
1014 err_code |= ERR_ALERT | ERR_FATAL;
1015 goto out;
1016 }
1017 }
1018
1019 if (parse_cpu_set((const char **)args+2, &cpus, &errmsg)) {
1020 ha_alert("parsing [%s:%d] : %s : %s\n", file, linenum, args[0], errmsg);
1021 err_code |= ERR_ALERT | ERR_FATAL;
1022 goto out;
1023 }
1024
1025 if (autoinc &&
1026 my_popcountl(proc) != my_popcountl(cpus) &&
1027 my_popcountl(thread) != my_popcountl(cpus)) {
1028 ha_alert("parsing [%s:%d] : %s : PROC/THREAD range and CPU sets "
1029 "must have the same size to be automatically bound\n",
1030 file, linenum, args[0]);
1031 err_code |= ERR_ALERT | ERR_FATAL;
1032 goto out;
1033 }
1034
Willy Tarreau7764a572019-07-16 15:10:34 +02001035 /* we now have to deal with 3 real cases :
1036 * cpu-map P-Q => mapping for whole processes, numbers P to Q
1037 * cpu-map P-Q/1 => mapping of first thread of processes P to Q
1038 * cpu-map 1/T-U => mapping of threads T to U of process 1
1039 * Otherwise other combinations are silently ignored since nbthread
1040 * and nbproc cannot both be >1 :
1041 * cpu-map P-Q/T => mapping for thread T for processes P to Q.
1042 * Only one of T,Q may be > 1, others ignored.
1043 * cpu-map P/T-U => mapping for threads T to U of process P. Only
1044 * one of P,U may be > 1, others ignored.
1045 */
1046 if (!thread) {
1047 /* mapping for whole processes. E.g. cpu-map 1-4 0-3 */
Willy Tarreau81492c92019-05-03 09:41:23 +02001048 for (i = n = 0; i < MAX_PROCS; i++) {
1049 /* No mapping for this process */
1050 if (!(proc & (1UL << i)))
1051 continue;
1052
Willy Tarreau36b9e222018-11-11 15:19:52 +01001053 if (!autoinc)
1054 global.cpu_map.proc[i] = cpus;
1055 else {
1056 n += my_ffsl(cpus >> n);
1057 global.cpu_map.proc[i] = (1UL << (n-1));
1058 }
Willy Tarreau36b9e222018-11-11 15:19:52 +01001059 }
Willy Tarreau7764a572019-07-16 15:10:34 +02001060 } else {
1061 /* Mapping at the thread level. All threads are retained
1062 * for process 1, and only thread 1 is retained for other
1063 * processes.
1064 */
1065 if (thread == 0x1) {
1066 /* first thread, iterate on processes. E.g. cpu-map 1-4/1 0-3 */
1067 for (i = n = 0; i < MAX_PROCS; i++) {
1068 /* No mapping for this process */
1069 if (!(proc & (1UL << i)))
1070 continue;
1071 if (!autoinc)
1072 global.cpu_map.proc_t1[i] = cpus;
1073 else {
1074 n += my_ffsl(cpus >> n);
1075 global.cpu_map.proc_t1[i] = (1UL << (n-1));
1076 }
1077 }
1078 }
Willy Tarreau36b9e222018-11-11 15:19:52 +01001079
Willy Tarreau7764a572019-07-16 15:10:34 +02001080 if (proc == 0x1) {
1081 /* first process, iterate on threads. E.g. cpu-map 1/1-4 0-3 */
1082 for (j = n = 0; j < MAX_THREADS; j++) {
1083 /* No mapping for this thread */
1084 if (!(thread & (1UL << j)))
1085 continue;
Willy Tarreau36b9e222018-11-11 15:19:52 +01001086
Willy Tarreau7764a572019-07-16 15:10:34 +02001087 if (!autoinc)
1088 global.cpu_map.thread[j] = cpus;
1089 else {
1090 n += my_ffsl(cpus >> n);
1091 global.cpu_map.thread[j] = (1UL << (n-1));
1092 }
Willy Tarreau36b9e222018-11-11 15:19:52 +01001093 }
1094 }
1095 }
1096#else
1097 ha_alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n",
1098 file, linenum, args[0]);
1099 err_code |= ERR_ALERT | ERR_FATAL;
1100 goto out;
1101#endif /* ! USE_CPU_AFFINITY */
1102 }
1103 else if (strcmp(args[0], "setenv") == 0 || strcmp(args[0], "presetenv") == 0) {
1104 if (alertif_too_many_args(3, file, linenum, args, &err_code))
1105 goto out;
1106
1107 if (*(args[2]) == 0) {
1108 ha_alert("parsing [%s:%d]: '%s' expects a name and a value.\n", file, linenum, args[0]);
1109 err_code |= ERR_ALERT | ERR_FATAL;
1110 goto out;
1111 }
1112
1113 /* "setenv" overwrites, "presetenv" only sets if not yet set */
1114 if (setenv(args[1], args[2], (args[0][0] == 's')) != 0) {
1115 ha_alert("parsing [%s:%d]: '%s' failed on variable '%s' : %s.\n", file, linenum, args[0], args[1], strerror(errno));
1116 err_code |= ERR_ALERT | ERR_FATAL;
1117 goto out;
1118 }
1119 }
1120 else if (!strcmp(args[0], "unsetenv")) {
1121 int arg;
1122
1123 if (*(args[1]) == 0) {
1124 ha_alert("parsing [%s:%d]: '%s' expects at least one variable name.\n", file, linenum, args[0]);
1125 err_code |= ERR_ALERT | ERR_FATAL;
1126 goto out;
1127 }
1128
1129 for (arg = 1; *args[arg]; arg++) {
1130 if (unsetenv(args[arg]) != 0) {
1131 ha_alert("parsing [%s:%d]: '%s' failed on variable '%s' : %s.\n", file, linenum, args[0], args[arg], strerror(errno));
1132 err_code |= ERR_ALERT | ERR_FATAL;
1133 goto out;
1134 }
1135 }
1136 }
1137 else if (!strcmp(args[0], "resetenv")) {
1138 extern char **environ;
1139 char **env = environ;
1140
1141 /* args contain variable names to keep, one per argument */
1142 while (*env) {
1143 int arg;
1144
1145 /* look for current variable in among all those we want to keep */
1146 for (arg = 1; *args[arg]; arg++) {
1147 if (strncmp(*env, args[arg], strlen(args[arg])) == 0 &&
1148 (*env)[strlen(args[arg])] == '=')
1149 break;
1150 }
1151
1152 /* delete this variable */
1153 if (!*args[arg]) {
1154 char *delim = strchr(*env, '=');
1155
1156 if (!delim || delim - *env >= trash.size) {
1157 ha_alert("parsing [%s:%d]: '%s' failed to unset invalid variable '%s'.\n", file, linenum, args[0], *env);
1158 err_code |= ERR_ALERT | ERR_FATAL;
1159 goto out;
1160 }
1161
1162 memcpy(trash.area, *env, delim - *env);
1163 trash.area[delim - *env] = 0;
1164
1165 if (unsetenv(trash.area) != 0) {
1166 ha_alert("parsing [%s:%d]: '%s' failed to unset variable '%s' : %s.\n", file, linenum, args[0], *env, strerror(errno));
1167 err_code |= ERR_ALERT | ERR_FATAL;
1168 goto out;
1169 }
1170 }
1171 else
1172 env++;
1173 }
1174 }
William Dauchy0fec3ab2019-10-27 20:08:11 +01001175 else if (!strcmp(args[0], "strict-limits")) { /* "no strict-limits" or "strict-limits" */
1176 if (alertif_too_many_args(0, file, linenum, args, &err_code))
1177 goto out;
1178 if (kwm == KWM_NO)
1179 global.tune.options &= ~GTUNE_STRICT_LIMITS;
1180 else
1181 global.tune.options |= GTUNE_STRICT_LIMITS;
1182 }
Willy Tarreau36b9e222018-11-11 15:19:52 +01001183 else {
1184 struct cfg_kw_list *kwl;
1185 int index;
1186 int rc;
1187
1188 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1189 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1190 if (kwl->kw[index].section != CFG_GLOBAL)
1191 continue;
1192 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
1193 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
1194 if (rc < 0) {
1195 ha_alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
1196 err_code |= ERR_ALERT | ERR_FATAL;
1197 }
1198 else if (rc > 0) {
1199 ha_warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
1200 err_code |= ERR_WARN;
1201 goto out;
1202 }
1203 goto out;
1204 }
1205 }
1206 }
1207
1208 ha_alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
1209 err_code |= ERR_ALERT | ERR_FATAL;
1210 }
1211
1212 out:
1213 free(errmsg);
1214 return err_code;
1215}
1216