1 /*
2  * Functions dedicated to statistics output and the stats socket
3  *
4  * Copyright 2000-2012 Willy Tarreau <w@1wt.eu>
5  * Copyright 2007-2009 Krzysztof Piotr Oledzki <ole@ans.pl>
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version
10  * 2 of the License, or (at your option) any later version.
11  *
12  */
13 
14 #include <ctype.h>
15 #include <errno.h>
16 #include <fcntl.h>
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <pwd.h>
21 #include <grp.h>
22 
23 #include <sys/socket.h>
24 #include <sys/stat.h>
25 #include <sys/types.h>
26 
27 #include <net/if.h>
28 
29 #include <haproxy/activity.h>
30 #include <haproxy/api.h>
31 #include <haproxy/applet-t.h>
32 #include <haproxy/base64.h>
33 #include <haproxy/cfgparse.h>
34 #include <haproxy/channel.h>
35 #include <haproxy/check.h>
36 #include <haproxy/cli.h>
37 #include <haproxy/compression.h>
38 #include <haproxy/dns-t.h>
39 #include <haproxy/errors.h>
40 #include <haproxy/fd.h>
41 #include <haproxy/freq_ctr.h>
42 #include <haproxy/frontend.h>
43 #include <haproxy/global.h>
44 #include <haproxy/list.h>
45 #include <haproxy/listener.h>
46 #include <haproxy/log.h>
47 #include <haproxy/mworker-t.h>
48 #include <haproxy/pattern-t.h>
49 #include <haproxy/peers.h>
50 #include <haproxy/pipe.h>
51 #include <haproxy/protocol.h>
52 #include <haproxy/proxy.h>
53 #include <haproxy/sample-t.h>
54 #include <haproxy/server.h>
55 #include <haproxy/session.h>
56 #include <haproxy/stats-t.h>
57 #include <haproxy/stream.h>
58 #include <haproxy/stream_interface.h>
59 #include <haproxy/task.h>
60 #include <haproxy/ticks.h>
61 #include <haproxy/time.h>
62 #include <haproxy/tools.h>
63 #include <haproxy/version.h>
64 
65 #define PAYLOAD_PATTERN "<<"
66 
67 static struct applet cli_applet;
68 
69 static const char stats_sock_usage_msg[] =
70 	"Unknown command. Please enter one of the following commands only :\n"
71 	"  help           : this message\n"
72 	"  prompt         : toggle interactive mode with prompt\n"
73 	"  quit           : disconnect\n"
74 	"";
75 
76 static const char stats_permission_denied_msg[] =
77 	"Permission denied\n"
78 	"";
79 
80 
81 static THREAD_LOCAL char *dynamic_usage_msg = NULL;
82 
83 /* List head of cli keywords */
84 static struct cli_kw_list cli_keywords = {
85 	.list = LIST_HEAD_INIT(cli_keywords.list)
86 };
87 
88 extern const char *stat_status_codes[];
89 
90 struct proxy *mworker_proxy; /* CLI proxy of the master */
91 
cli_gen_usage_msg(struct appctx * appctx)92 static char *cli_gen_usage_msg(struct appctx *appctx)
93 {
94 	struct cli_kw_list *kw_list;
95 	struct cli_kw *kw;
96 	struct buffer *tmp = get_trash_chunk();
97 	struct buffer out;
98 
99 	free(dynamic_usage_msg);
100 	dynamic_usage_msg = NULL;
101 
102 	if (LIST_ISEMPTY(&cli_keywords.list))
103 		goto end;
104 
105 	chunk_reset(tmp);
106 	chunk_strcat(tmp, stats_sock_usage_msg);
107 	list_for_each_entry(kw_list, &cli_keywords.list, list) {
108 		kw = &kw_list->kw[0];
109 		while (kw->str_kw[0]) {
110 
111 			/* in a worker or normal process, don't display master only commands */
112 			if (master == 0 && (kw->level & ACCESS_MASTER_ONLY))
113 				goto next_kw;
114 
115 			/* in master don't displays if we don't have the master bits */
116 			if (master == 1 && !(kw->level & (ACCESS_MASTER_ONLY|ACCESS_MASTER)))
117 				goto next_kw;
118 
119 			/* only show expert commands in expert mode */
120 			if ((kw->level & ~appctx->cli_level) & ACCESS_EXPERT)
121 				goto next_kw;
122 
123 			if (kw->usage)
124 				chunk_appendf(tmp, "  %s\n", kw->usage);
125 
126 next_kw:
127 
128 			kw++;
129 		}
130 	}
131 	chunk_init(&out, NULL, 0);
132 	chunk_dup(&out, tmp);
133 	dynamic_usage_msg = out.area;
134 
135 end:
136 	if (dynamic_usage_msg) {
137 		appctx->ctx.cli.severity = LOG_INFO;
138 		appctx->ctx.cli.msg = dynamic_usage_msg;
139 	}
140 	else {
141 		appctx->ctx.cli.severity = LOG_INFO;
142 		appctx->ctx.cli.msg = stats_sock_usage_msg;
143 	}
144 	appctx->st0 = CLI_ST_PRINT;
145 
146 	return dynamic_usage_msg;
147 }
148 
cli_find_kw(char ** args)149 struct cli_kw* cli_find_kw(char **args)
150 {
151 	struct cli_kw_list *kw_list;
152 	struct cli_kw *kw;/* current cli_kw */
153 	char **tmp_args;
154 	const char **tmp_str_kw;
155 	int found = 0;
156 
157 	if (LIST_ISEMPTY(&cli_keywords.list))
158 		return NULL;
159 
160 	list_for_each_entry(kw_list, &cli_keywords.list, list) {
161 		kw = &kw_list->kw[0];
162 		while (*kw->str_kw) {
163 			tmp_args = args;
164 			tmp_str_kw = kw->str_kw;
165 			while (*tmp_str_kw) {
166 				if (strcmp(*tmp_str_kw, *tmp_args) == 0) {
167 					found = 1;
168 				} else {
169 					found = 0;
170 					break;
171 				}
172 				tmp_args++;
173 				tmp_str_kw++;
174 			}
175 			if (found)
176 				return (kw);
177 			kw++;
178 		}
179 	}
180 	return NULL;
181 }
182 
cli_find_kw_exact(char ** args)183 struct cli_kw* cli_find_kw_exact(char **args)
184 {
185 	struct cli_kw_list *kw_list;
186 	int found = 0;
187 	int i;
188 	int j;
189 
190 	if (LIST_ISEMPTY(&cli_keywords.list))
191 		return NULL;
192 
193 	list_for_each_entry(kw_list, &cli_keywords.list, list) {
194 		for (i = 0; kw_list->kw[i].str_kw[0]; i++) {
195 			found = 1;
196 			for (j = 0; j < CLI_PREFIX_KW_NB; j++) {
197 				if (args[j] == NULL && kw_list->kw[i].str_kw[j] == NULL) {
198 					break;
199 				}
200 				if (args[j] == NULL || kw_list->kw[i].str_kw[j] == NULL) {
201 					found = 0;
202 					break;
203 				}
204 				if (strcmp(args[j], kw_list->kw[i].str_kw[j]) != 0) {
205 					found = 0;
206 					break;
207 				}
208 			}
209 			if (found)
210 				return &kw_list->kw[i];
211 		}
212 	}
213 	return NULL;
214 }
215 
cli_register_kw(struct cli_kw_list * kw_list)216 void cli_register_kw(struct cli_kw_list *kw_list)
217 {
218 	LIST_ADDQ(&cli_keywords.list, &kw_list->list);
219 }
220 
221 
222 /* allocate a new stats frontend named <name>, and return it
223  * (or NULL in case of lack of memory).
224  */
alloc_stats_fe(const char * name,const char * file,int line)225 static struct proxy *alloc_stats_fe(const char *name, const char *file, int line)
226 {
227 	struct proxy *fe;
228 
229 	fe = calloc(1, sizeof(*fe));
230 	if (!fe)
231 		return NULL;
232 
233 	init_new_proxy(fe);
234 	fe->next = proxies_list;
235 	proxies_list = fe;
236 	fe->last_change = now.tv_sec;
237 	fe->id = strdup("GLOBAL");
238 	fe->cap = PR_CAP_FE;
239 	fe->maxconn = 10;                 /* default to 10 concurrent connections */
240 	fe->timeout.client = MS_TO_TICKS(10000); /* default timeout of 10 seconds */
241 	fe->conf.file = strdup(file);
242 	fe->conf.line = line;
243 	fe->accept = frontend_accept;
244 	fe->default_target = &cli_applet.obj_type;
245 
246 	/* the stats frontend is the only one able to assign ID #0 */
247 	fe->conf.id.key = fe->uuid = 0;
248 	eb32_insert(&used_proxy_id, &fe->conf.id);
249 	return fe;
250 }
251 
252 /* This function parses a "stats" statement in the "global" section. It returns
253  * -1 if there is any error, otherwise zero. If it returns -1, it will write an
254  * error message into the <err> buffer which will be preallocated. The trailing
255  * '\n' must not be written. The function must be called with <args> pointing to
256  * the first word after "stats".
257  */
stats_parse_global(char ** args,int section_type,struct proxy * curpx,struct proxy * defpx,const char * file,int line,char ** err)258 static int stats_parse_global(char **args, int section_type, struct proxy *curpx,
259                               struct proxy *defpx, const char *file, int line,
260                               char **err)
261 {
262 	struct bind_conf *bind_conf;
263 	struct listener *l;
264 
265 	if (!strcmp(args[1], "socket")) {
266 		int cur_arg;
267 
268 		if (*args[2] == 0) {
269 			memprintf(err, "'%s %s' in global section expects an address or a path to a UNIX socket", args[0], args[1]);
270 			return -1;
271 		}
272 
273 		if (!global.stats_fe) {
274 			if ((global.stats_fe = alloc_stats_fe("GLOBAL", file, line)) == NULL) {
275 				memprintf(err, "'%s %s' : out of memory trying to allocate a frontend", args[0], args[1]);
276 				return -1;
277 			}
278 		}
279 
280 		bind_conf = bind_conf_alloc(global.stats_fe, file, line, args[2], xprt_get(XPRT_RAW));
281 		bind_conf->level &= ~ACCESS_LVL_MASK;
282 		bind_conf->level |= ACCESS_LVL_OPER; /* default access level */
283 
284 		if (!str2listener(args[2], global.stats_fe, bind_conf, file, line, err)) {
285 			memprintf(err, "parsing [%s:%d] : '%s %s' : %s\n",
286 			          file, line, args[0], args[1], err && *err ? *err : "error");
287 			return -1;
288 		}
289 
290 		cur_arg = 3;
291 		while (*args[cur_arg]) {
292 			static int bind_dumped;
293 			struct bind_kw *kw;
294 
295 			kw = bind_find_kw(args[cur_arg]);
296 			if (kw) {
297 				if (!kw->parse) {
298 					memprintf(err, "'%s %s' : '%s' option is not implemented in this version (check build options).",
299 						  args[0], args[1], args[cur_arg]);
300 					return -1;
301 				}
302 
303 				if (kw->parse(args, cur_arg, global.stats_fe, bind_conf, err) != 0) {
304 					if (err && *err)
305 						memprintf(err, "'%s %s' : '%s'", args[0], args[1], *err);
306 					else
307 						memprintf(err, "'%s %s' : error encountered while processing '%s'",
308 						          args[0], args[1], args[cur_arg]);
309 					return -1;
310 				}
311 
312 				cur_arg += 1 + kw->skip;
313 				continue;
314 			}
315 
316 			if (!bind_dumped) {
317 				bind_dump_kws(err);
318 				indent_msg(err, 4);
319 				bind_dumped = 1;
320 			}
321 
322 			memprintf(err, "'%s %s' : unknown keyword '%s'.%s%s",
323 			          args[0], args[1], args[cur_arg],
324 			          err && *err ? " Registered keywords :" : "", err && *err ? *err : "");
325 			return -1;
326 		}
327 
328 		list_for_each_entry(l, &bind_conf->listeners, by_bind) {
329 			l->accept = session_accept_fd;
330 			l->default_target = global.stats_fe->default_target;
331 			l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
332 			l->nice = -64;  /* we want to boost priority for local stats */
333 			global.maxsock++; /* for the listening socket */
334 		}
335 	}
336 	else if (!strcmp(args[1], "timeout")) {
337 		unsigned timeout;
338 		const char *res = parse_time_err(args[2], &timeout, TIME_UNIT_MS);
339 
340 		if (res == PARSE_TIME_OVER) {
341 			memprintf(err, "timer overflow in argument '%s' to '%s %s' (maximum value is 2147483647 ms or ~24.8 days)",
342 				 args[2], args[0], args[1]);
343 			return -1;
344 		}
345 		else if (res == PARSE_TIME_UNDER) {
346 			memprintf(err, "timer underflow in argument '%s' to '%s %s' (minimum non-null value is 1 ms)",
347 				 args[2], args[0], args[1]);
348 			return -1;
349 		}
350 		else if (res) {
351 			memprintf(err, "'%s %s' : unexpected character '%c'", args[0], args[1], *res);
352 			return -1;
353 		}
354 
355 		if (!timeout) {
356 			memprintf(err, "'%s %s' expects a positive value", args[0], args[1]);
357 			return -1;
358 		}
359 		if (!global.stats_fe) {
360 			if ((global.stats_fe = alloc_stats_fe("GLOBAL", file, line)) == NULL) {
361 				memprintf(err, "'%s %s' : out of memory trying to allocate a frontend", args[0], args[1]);
362 				return -1;
363 			}
364 		}
365 		global.stats_fe->timeout.client = MS_TO_TICKS(timeout);
366 	}
367 	else if (!strcmp(args[1], "maxconn")) {
368 		int maxconn = atol(args[2]);
369 
370 		if (maxconn <= 0) {
371 			memprintf(err, "'%s %s' expects a positive value", args[0], args[1]);
372 			return -1;
373 		}
374 
375 		if (!global.stats_fe) {
376 			if ((global.stats_fe = alloc_stats_fe("GLOBAL", file, line)) == NULL) {
377 				memprintf(err, "'%s %s' : out of memory trying to allocate a frontend", args[0], args[1]);
378 				return -1;
379 			}
380 		}
381 		global.stats_fe->maxconn = maxconn;
382 	}
383 	else if (!strcmp(args[1], "bind-process")) {  /* enable the socket only on some processes */
384 		int cur_arg = 2;
385 		unsigned long set = 0;
386 
387 		if (!global.stats_fe) {
388 			if ((global.stats_fe = alloc_stats_fe("GLOBAL", file, line)) == NULL) {
389 				memprintf(err, "'%s %s' : out of memory trying to allocate a frontend", args[0], args[1]);
390 				return -1;
391 			}
392 		}
393 
394 		while (*args[cur_arg]) {
395 			if (strcmp(args[cur_arg], "all") == 0) {
396 				set = 0;
397 				break;
398 			}
399 			if (parse_process_number(args[cur_arg], &set, MAX_PROCS, NULL, err)) {
400 				memprintf(err, "'%s %s' : %s", args[0], args[1], *err);
401 				return -1;
402 			}
403 			cur_arg++;
404 		}
405 		global.stats_fe->bind_proc = set;
406 	}
407 	else {
408 		memprintf(err, "'%s' only supports 'socket', 'maxconn', 'bind-process' and 'timeout' (got '%s')", args[0], args[1]);
409 		return -1;
410 	}
411 	return 0;
412 }
413 
414 /*
415  * This function exports the bound addresses of a <frontend> in the environment
416  * variable <varname>. Those addresses are separated by semicolons and prefixed
417  * with their type (abns@, unix@, sockpair@ etc)
418  * Return -1 upon error, 0 otherwise
419  */
listeners_setenv(struct proxy * frontend,const char * varname)420 int listeners_setenv(struct proxy *frontend, const char *varname)
421 {
422 	struct buffer *trash = get_trash_chunk();
423 	struct bind_conf *bind_conf;
424 
425 	if (frontend) {
426 		list_for_each_entry(bind_conf, &frontend->conf.bind, by_fe) {
427 			struct listener *l;
428 
429 			list_for_each_entry(l, &bind_conf->listeners, by_bind) {
430 				char addr[46];
431 				char port[6];
432 
433 				/* separate listener by semicolons */
434 				if (trash->data)
435 					chunk_appendf(trash, ";");
436 
437 				if (l->addr.ss_family == AF_UNIX) {
438 					const struct sockaddr_un *un;
439 
440 					un = (struct sockaddr_un *)&l->addr;
441 					if (un->sun_path[0] == '\0') {
442 						chunk_appendf(trash, "abns@%s", un->sun_path+1);
443 					} else {
444 						chunk_appendf(trash, "unix@%s", un->sun_path);
445 					}
446 				} else if (l->addr.ss_family == AF_INET) {
447 					addr_to_str(&l->addr, addr, sizeof(addr));
448 					port_to_str(&l->addr, port, sizeof(port));
449 					chunk_appendf(trash, "ipv4@%s:%s", addr, port);
450 				} else if (l->addr.ss_family == AF_INET6) {
451 					addr_to_str(&l->addr, addr, sizeof(addr));
452 					port_to_str(&l->addr, port, sizeof(port));
453 					chunk_appendf(trash, "ipv6@[%s]:%s", addr, port);
454 				} else if (l->addr.ss_family == AF_CUST_SOCKPAIR) {
455 					chunk_appendf(trash, "sockpair@%d", ((struct sockaddr_in *)&l->addr)->sin_addr.s_addr);
456 				}
457 			}
458 		}
459 		trash->area[trash->data++] = '\0';
460 		if (setenv(varname, trash->area, 1) < 0)
461 			return -1;
462 	}
463 
464 	return 0;
465 }
466 
cli_socket_setenv()467 int cli_socket_setenv()
468 {
469 	if (listeners_setenv(global.stats_fe, "HAPROXY_CLI") < 0)
470 		return -1;
471 	if (listeners_setenv(mworker_proxy, "HAPROXY_MASTER_CLI") < 0)
472 		return -1;
473 
474 	return 0;
475 }
476 
477 REGISTER_CONFIG_POSTPARSER("cli", cli_socket_setenv);
478 
479 /* Verifies that the CLI at least has a level at least as high as <level>
480  * (typically ACCESS_LVL_ADMIN). Returns 1 if OK, otherwise 0. In case of
481  * failure, an error message is prepared and the appctx's state is adjusted
482  * to print it so that a return 1 is enough to abort any processing.
483  */
cli_has_level(struct appctx * appctx,int level)484 int cli_has_level(struct appctx *appctx, int level)
485 {
486 
487 	if ((appctx->cli_level & ACCESS_LVL_MASK) < level) {
488 		cli_err(appctx, stats_permission_denied_msg);
489 		return 0;
490 	}
491 	return 1;
492 }
493 
494 /* same as cli_has_level but for the CLI proxy and without error message */
pcli_has_level(struct stream * s,int level)495 int pcli_has_level(struct stream *s, int level)
496 {
497 	if ((s->pcli_flags & ACCESS_LVL_MASK) < level) {
498 		return 0;
499 	}
500 	return 1;
501 }
502 
503 /* Returns severity_output for the current session if set, or default for the socket */
cli_get_severity_output(struct appctx * appctx)504 static int cli_get_severity_output(struct appctx *appctx)
505 {
506 	if (appctx->cli_severity_output)
507 		return appctx->cli_severity_output;
508 	return strm_li(si_strm(appctx->owner))->bind_conf->severity_output;
509 }
510 
511 /* Processes the CLI interpreter on the stats socket. This function is called
512  * from the CLI's IO handler running in an appctx context. The function returns 1
513  * if the request was understood, otherwise zero. It is called with appctx->st0
514  * set to CLI_ST_GETREQ and presets ->st2 to 0 so that parsers don't have to do
515  * it. It will possilbly leave st0 to CLI_ST_CALLBACK if the keyword needs to
516  * have its own I/O handler called again. Most of the time, parsers will only
517  * set st0 to CLI_ST_PRINT and put their message to be displayed into cli.msg.
518  * If a keyword parser is NULL and an I/O handler is declared, the I/O handler
519  * will automatically be used.
520  */
cli_parse_request(struct appctx * appctx)521 static int cli_parse_request(struct appctx *appctx)
522 {
523 	char *args[MAX_STATS_ARGS + 1], *p, *end, *payload = NULL;
524 	int i = 0;
525 	struct cli_kw *kw;
526 
527 	appctx->st2 = 0;
528 	memset(&appctx->ctx.cli, 0, sizeof(appctx->ctx.cli));
529 
530 	p = appctx->chunk->area;
531 	end = p + appctx->chunk->data;
532 
533 	/*
534 	 * Get pointers on words.
535 	 * One extra slot is reserved to store a pointer on a null byte.
536 	 */
537 	while (i < MAX_STATS_ARGS && p < end) {
538 		int j, k;
539 
540 		/* skip leading spaces/tabs */
541 		p += strspn(p, " \t");
542 		if (!*p)
543 			break;
544 
545 		if (strcmp(p, PAYLOAD_PATTERN) == 0) {
546 			/* payload pattern recognized here, this is not an arg anymore,
547 			 * the payload starts at the first byte that follows the zero
548 			 * after the pattern.
549 			 */
550 			payload = p + strlen(PAYLOAD_PATTERN) + 1;
551 			break;
552 		}
553 
554 		args[i] = p;
555 		while (1) {
556 			p += strcspn(p, " \t\\");
557 			/* escaped chars using backlashes (\) */
558 			if (*p == '\\') {
559 				if (!*++p)
560 					break;
561 				if (!*++p)
562 					break;
563 			} else {
564 				break;
565 			}
566 		}
567 		*p++ = 0;
568 
569 		/* unescape backslashes (\) */
570 		for (j = 0, k = 0; args[i][k]; k++) {
571 			if (args[i][k] == '\\') {
572 				if (args[i][k + 1] == '\\')
573 					k++;
574 				else
575 					continue;
576 			}
577 			args[i][j] = args[i][k];
578 			j++;
579 		}
580 		args[i][j] = 0;
581 
582 		i++;
583 	}
584 	/* fill unused slots */
585 	p = appctx->chunk->area + appctx->chunk->data;
586 	for (; i < MAX_STATS_ARGS + 1; i++)
587 		args[i] = p;
588 
589 	kw = cli_find_kw(args);
590 	if (!kw)
591 		return 0;
592 
593 	/* in a worker or normal process, don't display master only commands */
594 	if (master == 0 && (kw->level & ACCESS_MASTER_ONLY))
595 		return 0;
596 
597 	/* in master don't displays if we don't have the master bits */
598 	if (master == 1 && !(kw->level & (ACCESS_MASTER_ONLY|ACCESS_MASTER)))
599 		return 0;
600 
601 	/* only accept expert commands in expert mode */
602 	if ((kw->level & ~appctx->cli_level) & ACCESS_EXPERT)
603 		return 0;
604 
605 	appctx->io_handler = kw->io_handler;
606 	appctx->io_release = kw->io_release;
607 
608 	if (kw->parse && kw->parse(args, payload, appctx, kw->private) != 0)
609 		goto fail;
610 
611 	/* kw->parse could set its own io_handler or io_release handler */
612 	if (!appctx->io_handler)
613 		goto fail;
614 
615 	appctx->st0 = CLI_ST_CALLBACK;
616 	return 1;
617 fail:
618 	appctx->io_handler = NULL;
619 	appctx->io_release = NULL;
620 	return 1;
621 }
622 
623 /* prepends then outputs the argument msg with a syslog-type severity depending on severity_output value */
cli_output_msg(struct channel * chn,const char * msg,int severity,int severity_output)624 static int cli_output_msg(struct channel *chn, const char *msg, int severity, int severity_output)
625 {
626 	struct buffer *tmp;
627 
628 	if (likely(severity_output == CLI_SEVERITY_NONE))
629 		return ci_putblk(chn, msg, strlen(msg));
630 
631 	tmp = get_trash_chunk();
632 	chunk_reset(tmp);
633 
634 	if (severity < 0 || severity > 7) {
635 		ha_warning("socket command feedback with invalid severity %d", severity);
636 		chunk_printf(tmp, "[%d]: ", severity);
637 	}
638 	else {
639 		switch (severity_output) {
640 			case CLI_SEVERITY_NUMBER:
641 				chunk_printf(tmp, "[%d]: ", severity);
642 				break;
643 			case CLI_SEVERITY_STRING:
644 				chunk_printf(tmp, "[%s]: ", log_levels[severity]);
645 				break;
646 			default:
647 				ha_warning("Unrecognized severity output %d", severity_output);
648 		}
649 	}
650 	chunk_appendf(tmp, "%s", msg);
651 
652 	return ci_putblk(chn, tmp->area, strlen(tmp->area));
653 }
654 
655 /* This I/O handler runs as an applet embedded in a stream interface. It is
656  * used to processes I/O from/to the stats unix socket. The system relies on a
657  * state machine handling requests and various responses. We read a request,
658  * then we process it and send the response, and we possibly display a prompt.
659  * Then we can read again. The state is stored in appctx->st0 and is one of the
660  * CLI_ST_* constants. appctx->st1 is used to indicate whether prompt is enabled
661  * or not.
662  */
cli_io_handler(struct appctx * appctx)663 static void cli_io_handler(struct appctx *appctx)
664 {
665 	struct stream_interface *si = appctx->owner;
666 	struct channel *req = si_oc(si);
667 	struct channel *res = si_ic(si);
668 	struct bind_conf *bind_conf = strm_li(si_strm(si))->bind_conf;
669 	int reql;
670 	int len;
671 
672 	if (unlikely(si->state == SI_ST_DIS || si->state == SI_ST_CLO))
673 		goto out;
674 
675 	/* Check if the input buffer is available. */
676 	if (res->buf.size == 0) {
677 		/* buf.size==0 means we failed to get a buffer and were
678 		 * already subscribed to a wait list to get a buffer.
679 		 */
680 		goto out;
681 	}
682 
683 	while (1) {
684 		if (appctx->st0 == CLI_ST_INIT) {
685 			/* Stats output not initialized yet */
686 			memset(&appctx->ctx.stats, 0, sizeof(appctx->ctx.stats));
687 			/* reset severity to default at init */
688 			appctx->cli_severity_output = bind_conf->severity_output;
689 			appctx->st0 = CLI_ST_GETREQ;
690 			appctx->cli_level = bind_conf->level;
691 		}
692 		else if (appctx->st0 == CLI_ST_END) {
693 			/* Let's close for real now. We just close the request
694 			 * side, the conditions below will complete if needed.
695 			 */
696 			si_shutw(si);
697 			free_trash_chunk(appctx->chunk);
698 			appctx->chunk = NULL;
699 			break;
700 		}
701 		else if (appctx->st0 == CLI_ST_GETREQ) {
702 			char *str;
703 
704 			/* use a trash chunk to store received data */
705 			if (!appctx->chunk) {
706 				appctx->chunk = alloc_trash_chunk();
707 				if (!appctx->chunk) {
708 					appctx->st0 = CLI_ST_END;
709 					continue;
710 				}
711 			}
712 
713 			str = appctx->chunk->area + appctx->chunk->data;
714 
715 			/* ensure we have some output room left in the event we
716 			 * would want to return some info right after parsing.
717 			 */
718 			if (buffer_almost_full(si_ib(si))) {
719 				si_rx_room_blk(si);
720 				break;
721 			}
722 
723 			/* '- 1' is to ensure a null byte can always be inserted at the end */
724 			reql = co_getline(si_oc(si), str,
725 					  appctx->chunk->size - appctx->chunk->data - 1);
726 			if (reql <= 0) { /* closed or EOL not found */
727 				if (reql == 0)
728 					break;
729 				appctx->st0 = CLI_ST_END;
730 				continue;
731 			}
732 
733 			if (!(appctx->st1 & APPCTX_CLI_ST1_PAYLOAD)) {
734 				/* seek for a possible unescaped semi-colon. If we find
735 				 * one, we replace it with an LF and skip only this part.
736 				 */
737 				for (len = 0; len < reql; len++) {
738 					if (str[len] == '\\') {
739 						len++;
740 						continue;
741 					}
742 					if (str[len] == ';') {
743 						str[len] = '\n';
744 						reql = len + 1;
745 						break;
746 					}
747 				}
748 			}
749 
750 			/* now it is time to check that we have a full line,
751 			 * remove the trailing \n and possibly \r, then cut the
752 			 * line.
753 			 */
754 			len = reql - 1;
755 			if (str[len] != '\n') {
756 				appctx->st0 = CLI_ST_END;
757 				continue;
758 			}
759 
760 			if (len && str[len-1] == '\r')
761 				len--;
762 
763 			str[len] = '\0';
764 			appctx->chunk->data += len;
765 
766 			if (appctx->st1 & APPCTX_CLI_ST1_PAYLOAD) {
767 				appctx->chunk->area[appctx->chunk->data] = '\n';
768 				appctx->chunk->area[appctx->chunk->data + 1] = 0;
769 				appctx->chunk->data++;
770 			}
771 
772 			appctx->st0 = CLI_ST_PROMPT;
773 
774 			if (appctx->st1 & APPCTX_CLI_ST1_PAYLOAD) {
775 				/* empty line */
776 				if (!len) {
777 					/* remove the last two \n */
778 					appctx->chunk->data -= 2;
779 					appctx->chunk->area[appctx->chunk->data] = 0;
780 
781 					if (!cli_parse_request(appctx))
782 						cli_gen_usage_msg(appctx);
783 
784 					chunk_reset(appctx->chunk);
785 					/* NB: cli_sock_parse_request() may have put
786 					 * another CLI_ST_O_* into appctx->st0.
787 					 */
788 
789 					appctx->st1 &= ~APPCTX_CLI_ST1_PAYLOAD;
790 				}
791 			}
792 			else {
793 				/*
794 				 * Look for the "payload start" pattern at the end of a line
795 				 * Its location is not remembered here, this is just to switch
796 				 * to a gathering mode.
797 				 */
798 				if (strcmp(appctx->chunk->area + appctx->chunk->data - strlen(PAYLOAD_PATTERN), PAYLOAD_PATTERN) == 0) {
799 					appctx->st1 |= APPCTX_CLI_ST1_PAYLOAD;
800 					appctx->chunk->data++; // keep the trailing \0 after '<<'
801 				}
802 				else {
803 					/* no payload, the command is complete: parse the request */
804 					if (!cli_parse_request(appctx))
805 						cli_gen_usage_msg(appctx);
806 
807 					chunk_reset(appctx->chunk);
808 				}
809 			}
810 
811 			/* re-adjust req buffer */
812 			co_skip(si_oc(si), reql);
813 			req->flags |= CF_READ_DONTWAIT; /* we plan to read small requests */
814 		}
815 		else {	/* output functions */
816 			const char *msg;
817 			int sev;
818 
819 			switch (appctx->st0) {
820 			case CLI_ST_PROMPT:
821 				break;
822 			case CLI_ST_PRINT:       /* print const message in msg */
823 			case CLI_ST_PRINT_ERR:   /* print const error in msg */
824 			case CLI_ST_PRINT_DYN:   /* print dyn message in msg, free */
825 			case CLI_ST_PRINT_FREE:  /* print dyn error in err, free */
826 				if (appctx->st0 == CLI_ST_PRINT || appctx->st0 == CLI_ST_PRINT_ERR) {
827 					sev = appctx->st0 == CLI_ST_PRINT_ERR ?
828 						LOG_ERR : appctx->ctx.cli.severity;
829 					msg = appctx->ctx.cli.msg;
830 				}
831 				else if (appctx->st0 == CLI_ST_PRINT_DYN || appctx->st0 == CLI_ST_PRINT_FREE) {
832 					sev = appctx->st0 == CLI_ST_PRINT_FREE ?
833 						LOG_ERR : appctx->ctx.cli.severity;
834 					msg = appctx->ctx.cli.err;
835 					if (!msg) {
836 						sev = LOG_ERR;
837 						msg = "Out of memory.\n";
838 					}
839 				}
840 				else {
841 					sev = LOG_ERR;
842 					msg = "Internal error.\n";
843 				}
844 
845 				if (cli_output_msg(res, msg, sev, cli_get_severity_output(appctx)) != -1) {
846 					if (appctx->st0 == CLI_ST_PRINT_FREE ||
847 					    appctx->st0 == CLI_ST_PRINT_DYN) {
848 						free(appctx->ctx.cli.err);
849 						appctx->ctx.cli.err = NULL;
850 					}
851 					appctx->st0 = CLI_ST_PROMPT;
852 				}
853 				else
854 					si_rx_room_blk(si);
855 				break;
856 
857 			case CLI_ST_CALLBACK: /* use custom pointer */
858 				if (appctx->io_handler)
859 					if (appctx->io_handler(appctx)) {
860 						appctx->st0 = CLI_ST_PROMPT;
861 						if (appctx->io_release) {
862 							appctx->io_release(appctx);
863 							appctx->io_release = NULL;
864 						}
865 					}
866 				break;
867 			default: /* abnormal state */
868 				si->flags |= SI_FL_ERR;
869 				break;
870 			}
871 
872 			/* The post-command prompt is either LF alone or LF + '> ' in interactive mode */
873 			if (appctx->st0 == CLI_ST_PROMPT) {
874 				const char *prompt = "";
875 
876 				if (appctx->st1 & APPCTX_CLI_ST1_PROMPT) {
877 					/*
878 					 * when entering a payload with interactive mode, change the prompt
879 					 * to emphasize that more data can still be sent
880 					 */
881 					if (appctx->chunk->data && appctx->st1 & APPCTX_CLI_ST1_PAYLOAD)
882 						prompt = "+ ";
883 					else
884 						prompt = "\n> ";
885 				}
886 				else {
887 					if (!(appctx->st1 & (APPCTX_CLI_ST1_PAYLOAD|APPCTX_CLI_ST1_NOLF)))
888 						prompt = "\n";
889 				}
890 
891 				if (ci_putstr(si_ic(si), prompt) != -1)
892 					appctx->st0 = CLI_ST_GETREQ;
893 				else
894 					si_rx_room_blk(si);
895 			}
896 
897 			/* If the output functions are still there, it means they require more room. */
898 			if (appctx->st0 >= CLI_ST_OUTPUT)
899 				break;
900 
901 			/* Now we close the output if one of the writers did so,
902 			 * or if we're not in interactive mode and the request
903 			 * buffer is empty. This still allows pipelined requests
904 			 * to be sent in non-interactive mode.
905 			 */
906 			if (((res->flags & (CF_SHUTW|CF_SHUTW_NOW))) ||
907 			   (!(appctx->st1 & APPCTX_CLI_ST1_PROMPT) && !co_data(req) && (!(appctx->st1 & APPCTX_CLI_ST1_PAYLOAD)))) {
908 				appctx->st0 = CLI_ST_END;
909 				continue;
910 			}
911 
912 			/* switch state back to GETREQ to read next requests */
913 			appctx->st0 = CLI_ST_GETREQ;
914 			/* reactivate the \n at the end of the response for the next command */
915 			appctx->st1 &= ~APPCTX_CLI_ST1_NOLF;
916 		}
917 	}
918 
919 	if ((res->flags & CF_SHUTR) && (si->state == SI_ST_EST)) {
920 		DPRINTF(stderr, "%s@%d: si to buf closed. req=%08x, res=%08x, st=%d\n",
921 			__FUNCTION__, __LINE__, req->flags, res->flags, si->state);
922 		/* Other side has closed, let's abort if we have no more processing to do
923 		 * and nothing more to consume. This is comparable to a broken pipe, so
924 		 * we forward the close to the request side so that it flows upstream to
925 		 * the client.
926 		 */
927 		si_shutw(si);
928 	}
929 
930 	if ((req->flags & CF_SHUTW) && (si->state == SI_ST_EST) && (appctx->st0 < CLI_ST_OUTPUT)) {
931 		DPRINTF(stderr, "%s@%d: buf to si closed. req=%08x, res=%08x, st=%d\n",
932 			__FUNCTION__, __LINE__, req->flags, res->flags, si->state);
933 		/* We have no more processing to do, and nothing more to send, and
934 		 * the client side has closed. So we'll forward this state downstream
935 		 * on the response buffer.
936 		 */
937 		si_shutr(si);
938 		res->flags |= CF_READ_NULL;
939 	}
940 
941  out:
942 	DPRINTF(stderr, "%s@%d: st=%d, rqf=%x, rpf=%x, rqh=%lu, rqs=%lu, rh=%lu, rs=%lu\n",
943 		__FUNCTION__, __LINE__,
944 		si->state, req->flags, res->flags, ci_data(req), co_data(req), ci_data(res), co_data(res));
945 }
946 
947 /* This is called when the stream interface is closed. For instance, upon an
948  * external abort, we won't call the i/o handler anymore so we may need to
949  * remove back references to the stream currently being dumped.
950  */
cli_release_handler(struct appctx * appctx)951 static void cli_release_handler(struct appctx *appctx)
952 {
953 	free_trash_chunk(appctx->chunk);
954 	appctx->chunk = NULL;
955 
956 	if (appctx->io_release) {
957 		appctx->io_release(appctx);
958 		appctx->io_release = NULL;
959 	}
960 	else if (appctx->st0 == CLI_ST_PRINT_FREE || appctx->st0 == CLI_ST_PRINT_DYN) {
961 		free(appctx->ctx.cli.err);
962 		appctx->ctx.cli.err = NULL;
963 	}
964 }
965 
966 /* This function dumps all environmnent variables to the buffer. It returns 0
967  * if the output buffer is full and it needs to be called again, otherwise
968  * non-zero. Dumps only one entry if st2 == STAT_ST_END. It uses cli.p0 as the
969  * pointer to the current variable.
970  */
cli_io_handler_show_env(struct appctx * appctx)971 static int cli_io_handler_show_env(struct appctx *appctx)
972 {
973 	struct stream_interface *si = appctx->owner;
974 	char **var = appctx->ctx.cli.p0;
975 
976 	if (unlikely(si_ic(si)->flags & (CF_WRITE_ERROR|CF_SHUTW)))
977 		return 1;
978 
979 	chunk_reset(&trash);
980 
981 	/* we have two inner loops here, one for the proxy, the other one for
982 	 * the buffer.
983 	 */
984 	while (*var) {
985 		chunk_printf(&trash, "%s\n", *var);
986 
987 		if (ci_putchk(si_ic(si), &trash) == -1) {
988 			si_rx_room_blk(si);
989 			return 0;
990 		}
991 		if (appctx->st2 == STAT_ST_END)
992 			break;
993 		var++;
994 		appctx->ctx.cli.p0 = var;
995 	}
996 
997 	/* dump complete */
998 	return 1;
999 }
1000 
1001 /* This function dumps all file descriptors states (or the requested one) to
1002  * the buffer. It returns 0 if the output buffer is full and it needs to be
1003  * called again, otherwise non-zero. Dumps only one entry if st2 == STAT_ST_END.
1004  * It uses cli.i0 as the fd number to restart from.
1005  */
cli_io_handler_show_fd(struct appctx * appctx)1006 static int cli_io_handler_show_fd(struct appctx *appctx)
1007 {
1008 	struct stream_interface *si = appctx->owner;
1009 	int fd = appctx->ctx.cli.i0;
1010 	int ret = 1;
1011 
1012 	if (unlikely(si_ic(si)->flags & (CF_WRITE_ERROR|CF_SHUTW)))
1013 		goto end;
1014 
1015 	chunk_reset(&trash);
1016 
1017 	/* isolate the threads once per round. We're limited to a buffer worth
1018 	 * of output anyway, it cannot last very long.
1019 	 */
1020 	thread_isolate();
1021 
1022 	/* we have two inner loops here, one for the proxy, the other one for
1023 	 * the buffer.
1024 	 */
1025 	while (fd >= 0 && fd < global.maxsock) {
1026 		struct fdtab fdt;
1027 		const struct listener *li = NULL;
1028 		const struct server *sv = NULL;
1029 		const struct proxy *px = NULL;
1030 		const struct connection *conn = NULL;
1031 		const struct mux_ops *mux = NULL;
1032 		const struct xprt_ops *xprt = NULL;
1033 		const void *ctx = NULL;
1034 		const void *xprt_ctx = NULL;
1035 		uint32_t conn_flags = 0;
1036 		int is_back = 0;
1037 		int suspicious = 0;
1038 
1039 		fdt = fdtab[fd];
1040 
1041 		/* When DEBUG_FD is set, we also report closed FDs that have a
1042 		 * non-null event count to detect stuck ones.
1043 		 */
1044 		if (!fdt.owner) {
1045 #ifdef DEBUG_FD
1046 			if (!fdt.event_count)
1047 #endif
1048 				goto skip; // closed
1049 		}
1050 		else if (fdt.iocb == conn_fd_handler) {
1051 			conn = (const struct connection *)fdt.owner;
1052 			conn_flags = conn->flags;
1053 			mux        = conn->mux;
1054 			ctx        = conn->ctx;
1055 			xprt       = conn->xprt;
1056 			xprt_ctx   = conn->xprt_ctx;
1057 			li         = objt_listener(conn->target);
1058 			sv         = objt_server(conn->target);
1059 			px         = objt_proxy(conn->target);
1060 			is_back    = conn_is_back(conn);
1061 			if (atleast2(fdt.thread_mask))
1062 				suspicious = 1;
1063 			if (conn->handle.fd != fd)
1064 				suspicious = 1;
1065 		}
1066 		else if (fdt.iocb == listener_accept)
1067 			li = fdt.owner;
1068 
1069 		if (!fdt.thread_mask)
1070 			suspicious = 1;
1071 
1072 		chunk_printf(&trash,
1073 			     "  %5d : st=0x%02x(R:%c%c W:%c%c) ev=0x%02x(%c%c%c%c%c) [%c%c] tmask=0x%lx umask=0x%lx owner=%p iocb=%p(",
1074 			     fd,
1075 			     fdt.state,
1076 			     (fdt.state & FD_EV_READY_R)  ? 'R' : 'r',
1077 			     (fdt.state & FD_EV_ACTIVE_R) ? 'A' : 'a',
1078 			     (fdt.state & FD_EV_READY_W)  ? 'R' : 'r',
1079 			     (fdt.state & FD_EV_ACTIVE_W) ? 'A' : 'a',
1080 			     fdt.ev,
1081 			     (fdt.ev & FD_POLL_HUP) ? 'H' : 'h',
1082 			     (fdt.ev & FD_POLL_ERR) ? 'E' : 'e',
1083 			     (fdt.ev & FD_POLL_OUT) ? 'O' : 'o',
1084 			     (fdt.ev & FD_POLL_PRI) ? 'P' : 'p',
1085 			     (fdt.ev & FD_POLL_IN)  ? 'I' : 'i',
1086 			     fdt.linger_risk ? 'L' : 'l',
1087 			     fdt.cloned ? 'C' : 'c',
1088 			     fdt.thread_mask, fdt.update_mask,
1089 			     fdt.owner,
1090 			     fdt.iocb);
1091 		resolve_sym_name(&trash, NULL, fdt.iocb);
1092 
1093 		if (!fdt.owner) {
1094 			chunk_appendf(&trash, ")");
1095 		}
1096 		else if (fdt.iocb == conn_fd_handler) {
1097 			chunk_appendf(&trash, ") back=%d cflg=0x%08x", is_back, conn_flags);
1098 
1099 			if (conn->handle.fd != fd) {
1100 				chunk_appendf(&trash, " fd=%d(BOGUS)", conn->handle.fd);
1101 				suspicious = 1;
1102 			} else {
1103 				struct sockaddr_storage sa;
1104 				socklen_t salen;
1105 
1106 				salen = sizeof(sa);
1107 				if (getsockname(fd, (struct sockaddr *)&sa, &salen) != -1) {
1108 					if (sa.ss_family == AF_INET)
1109 						chunk_appendf(&trash, " fam=ipv4 lport=%d", ntohs(((const struct sockaddr_in *)&sa)->sin_port));
1110 					else if (sa.ss_family == AF_INET6)
1111 						chunk_appendf(&trash, " fam=ipv6 lport=%d", ntohs(((const struct sockaddr_in6 *)&sa)->sin6_port));
1112 					else if (sa.ss_family == AF_UNIX)
1113 						chunk_appendf(&trash, " fam=unix");
1114 				}
1115 
1116 				salen = sizeof(sa);
1117 				if (getpeername(fd, (struct sockaddr *)&sa, &salen) != -1) {
1118 					if (sa.ss_family == AF_INET)
1119 						chunk_appendf(&trash, " rport=%d", ntohs(((const struct sockaddr_in *)&sa)->sin_port));
1120 					else if (sa.ss_family == AF_INET6)
1121 						chunk_appendf(&trash, " rport=%d", ntohs(((const struct sockaddr_in6 *)&sa)->sin6_port));
1122 				}
1123 			}
1124 
1125 			if (px)
1126 				chunk_appendf(&trash, " px=%s", px->id);
1127 			else if (sv)
1128 				chunk_appendf(&trash, " sv=%s/%s", sv->proxy->id, sv->id);
1129 			else if (li)
1130 				chunk_appendf(&trash, " fe=%s", li->bind_conf->frontend->id);
1131 
1132 			if (mux) {
1133 				chunk_appendf(&trash, " mux=%s ctx=%p", mux->name, ctx);
1134 				if (!ctx)
1135 					suspicious = 1;
1136 				if (mux->show_fd)
1137 					suspicious |= mux->show_fd(&trash, fdt.owner);
1138 			}
1139 			else
1140 				chunk_appendf(&trash, " nomux");
1141 
1142 			chunk_appendf(&trash, " xprt=%s", xprt ? xprt->name : "");
1143 			if (xprt) {
1144 				if (xprt_ctx || xprt->show_fd)
1145 					chunk_appendf(&trash, " xprt_ctx=%p", xprt_ctx);
1146 				if (xprt->show_fd)
1147 					suspicious |= xprt->show_fd(&trash, conn, xprt_ctx);
1148 			}
1149 		}
1150 		else if (fdt.iocb == listener_accept) {
1151 			struct sockaddr_storage sa;
1152 			socklen_t salen;
1153 
1154 			chunk_appendf(&trash, ") l.st=%s fe=%s",
1155 			              listener_state_str(li),
1156 			              li->bind_conf->frontend->id);
1157 
1158 			salen = sizeof(sa);
1159 			if (getsockname(fd, (struct sockaddr *)&sa, &salen) != -1) {
1160 				if (sa.ss_family == AF_INET)
1161 					chunk_appendf(&trash, " fam=ipv4 lport=%d", ntohs(((const struct sockaddr_in *)&sa)->sin_port));
1162 				else if (sa.ss_family == AF_INET6)
1163 					chunk_appendf(&trash, " fam=ipv6 lport=%d", ntohs(((const struct sockaddr_in6 *)&sa)->sin6_port));
1164 				else if (sa.ss_family == AF_UNIX)
1165 					chunk_appendf(&trash, " fam=unix");
1166 			}
1167 		}
1168 		else
1169 			chunk_appendf(&trash, ")");
1170 
1171 #ifdef DEBUG_FD
1172 		chunk_appendf(&trash, " evcnt=%u", fdtab[fd].event_count);
1173 		if (fdtab[fd].event_count >= 1000000)
1174 			suspicious = 1;
1175 #endif
1176 		chunk_appendf(&trash, "%s\n", suspicious ? " !" : "");
1177 
1178 		if (ci_putchk(si_ic(si), &trash) == -1) {
1179 			si_rx_room_blk(si);
1180 			appctx->ctx.cli.i0 = fd;
1181 			ret = 0;
1182 			break;
1183 		}
1184 	skip:
1185 		if (appctx->st2 == STAT_ST_END)
1186 			break;
1187 
1188 		fd++;
1189 	}
1190 
1191  end:
1192 	/* dump complete */
1193 
1194 	thread_release();
1195 	return ret;
1196 }
1197 
1198 /* This function dumps some activity counters used by developers and support to
1199  * rule out some hypothesis during bug reports. It returns 0 if the output
1200  * buffer is full and it needs to be called again, otherwise non-zero. It dumps
1201  * everything at once in the buffer and is not designed to do it in multiple
1202  * passes.
1203  */
cli_io_handler_show_activity(struct appctx * appctx)1204 static int cli_io_handler_show_activity(struct appctx *appctx)
1205 {
1206 	struct stream_interface *si = appctx->owner;
1207 	int thr;
1208 
1209 	if (unlikely(si_ic(si)->flags & (CF_WRITE_ERROR|CF_SHUTW)))
1210 		return 1;
1211 
1212 	chunk_reset(&trash);
1213 
1214 #undef SHOW_TOT
1215 #define SHOW_TOT(t, x)							\
1216 	do {								\
1217 		unsigned int _v[MAX_THREADS];				\
1218 		unsigned int _tot;					\
1219 		const unsigned int _nbt = global.nbthread;		\
1220 		for (_tot = t = 0; t < _nbt; t++)			\
1221 			_tot += _v[t] = (x);				\
1222 		if (_nbt == 1) {					\
1223 			chunk_appendf(&trash, " %u\n", _tot);		\
1224 			break;						\
1225 		}							\
1226 		chunk_appendf(&trash, " %u [", _tot);			\
1227 		for (t = 0; t < _nbt; t++)				\
1228 			chunk_appendf(&trash, " %u", _v[t]);		\
1229 		chunk_appendf(&trash, " ]\n");				\
1230 	} while (0)
1231 
1232 #undef SHOW_AVG
1233 #define SHOW_AVG(t, x)							\
1234 	do {								\
1235 		unsigned int _v[MAX_THREADS];				\
1236 		unsigned int _tot;					\
1237 		const unsigned int _nbt = global.nbthread;		\
1238 		for (_tot = t = 0; t < _nbt; t++)			\
1239 			_tot += _v[t] = (x);				\
1240 		if (_nbt == 1) {					\
1241 			chunk_appendf(&trash, " %u\n", _tot);		\
1242 			break;						\
1243 		}							\
1244 		chunk_appendf(&trash, " %u [", (_tot + _nbt/2) / _nbt); \
1245 		for (t = 0; t < _nbt; t++)				\
1246 			chunk_appendf(&trash, " %u", _v[t]);		\
1247 		chunk_appendf(&trash, " ]\n");				\
1248 	} while (0)
1249 
1250 	chunk_appendf(&trash, "thread_id: %u (%u..%u)\n", tid + 1, 1, global.nbthread);
1251 	chunk_appendf(&trash, "date_now: %lu.%06lu\n", (long)now.tv_sec, (long)now.tv_usec);
1252 	chunk_appendf(&trash, "ctxsw:");        SHOW_TOT(thr, activity[thr].ctxsw);
1253 	chunk_appendf(&trash, "tasksw:");       SHOW_TOT(thr, activity[thr].tasksw);
1254 	chunk_appendf(&trash, "empty_rq:");     SHOW_TOT(thr, activity[thr].empty_rq);
1255 	chunk_appendf(&trash, "long_rq:");      SHOW_TOT(thr, activity[thr].long_rq);
1256 	chunk_appendf(&trash, "loops:");        SHOW_TOT(thr, activity[thr].loops);
1257 	chunk_appendf(&trash, "wake_tasks:");   SHOW_TOT(thr, activity[thr].wake_tasks);
1258 	chunk_appendf(&trash, "wake_signal:");  SHOW_TOT(thr, activity[thr].wake_signal);
1259 	chunk_appendf(&trash, "poll_io:");      SHOW_TOT(thr, activity[thr].poll_io);
1260 	chunk_appendf(&trash, "poll_exp:");     SHOW_TOT(thr, activity[thr].poll_exp);
1261 	chunk_appendf(&trash, "poll_drop_fd:"); SHOW_TOT(thr, activity[thr].poll_drop_fd);
1262 	chunk_appendf(&trash, "poll_dead_fd:"); SHOW_TOT(thr, activity[thr].poll_dead_fd);
1263 	chunk_appendf(&trash, "poll_skip_fd:"); SHOW_TOT(thr, activity[thr].poll_skip_fd);
1264 	chunk_appendf(&trash, "conn_dead:");    SHOW_TOT(thr, activity[thr].conn_dead);
1265 	chunk_appendf(&trash, "stream_calls:"); SHOW_TOT(thr, activity[thr].stream_calls);
1266 	chunk_appendf(&trash, "pool_fail:");    SHOW_TOT(thr, activity[thr].pool_fail);
1267 	chunk_appendf(&trash, "buf_wait:");     SHOW_TOT(thr, activity[thr].buf_wait);
1268 	chunk_appendf(&trash, "cpust_ms_tot:"); SHOW_TOT(thr, activity[thr].cpust_total / 2);
1269 	chunk_appendf(&trash, "cpust_ms_1s:");  SHOW_TOT(thr, read_freq_ctr(&activity[thr].cpust_1s) / 2);
1270 	chunk_appendf(&trash, "cpust_ms_15s:"); SHOW_TOT(thr, read_freq_ctr_period(&activity[thr].cpust_15s, 15000) / 2);
1271 	chunk_appendf(&trash, "avg_loop_us:");  SHOW_AVG(thr, swrate_avg(activity[thr].avg_loop_us, TIME_STATS_SAMPLES));
1272 	chunk_appendf(&trash, "accepted:");     SHOW_TOT(thr, activity[thr].accepted);
1273 	chunk_appendf(&trash, "accq_pushed:");  SHOW_TOT(thr, activity[thr].accq_pushed);
1274 	chunk_appendf(&trash, "accq_full:");    SHOW_TOT(thr, activity[thr].accq_full);
1275 #ifdef USE_THREAD
1276 	chunk_appendf(&trash, "accq_ring:");    SHOW_TOT(thr, (accept_queue_rings[thr].tail - accept_queue_rings[thr].head + ACCEPT_QUEUE_SIZE) % ACCEPT_QUEUE_SIZE);
1277 	chunk_appendf(&trash, "fd_takeover:");  SHOW_TOT(thr, activity[thr].fd_takeover);
1278 #endif
1279 
1280 #if defined(DEBUG_DEV)
1281 	/* keep these ones at the end */
1282 	chunk_appendf(&trash, "ctr0:");         SHOW_TOT(thr, activity[thr].ctr0);
1283 	chunk_appendf(&trash, "ctr1:");         SHOW_TOT(thr, activity[thr].ctr1);
1284 	chunk_appendf(&trash, "ctr2:");         SHOW_TOT(thr, activity[thr].ctr2);
1285 #endif
1286 
1287 	if (ci_putchk(si_ic(si), &trash) == -1) {
1288 		chunk_reset(&trash);
1289 		chunk_printf(&trash, "[output too large, cannot dump]\n");
1290 		si_rx_room_blk(si);
1291 	}
1292 
1293 #undef SHOW_AVG
1294 #undef SHOW_TOT
1295 	/* dump complete */
1296 	return 1;
1297 }
1298 
1299 /*
1300  * CLI IO handler for `show cli sockets`.
1301  * Uses ctx.cli.p0 to store the restart pointer.
1302  */
cli_io_handler_show_cli_sock(struct appctx * appctx)1303 static int cli_io_handler_show_cli_sock(struct appctx *appctx)
1304 {
1305 	struct bind_conf *bind_conf;
1306 	struct stream_interface *si = appctx->owner;
1307 
1308 	chunk_reset(&trash);
1309 
1310 	switch (appctx->st2) {
1311 		case STAT_ST_INIT:
1312 			chunk_printf(&trash, "# socket lvl processes\n");
1313 			if (ci_putchk(si_ic(si), &trash) == -1) {
1314 				si_rx_room_blk(si);
1315 				return 0;
1316 			}
1317 			appctx->st2 = STAT_ST_LIST;
1318 			/* fall through */
1319 
1320 		case STAT_ST_LIST:
1321 			if (global.stats_fe) {
1322 				list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
1323 					struct listener *l;
1324 
1325 					/*
1326 					 * get the latest dumped node in appctx->ctx.cli.p0
1327 					 * if the current node is the first of the list
1328 					 */
1329 
1330 					if (appctx->ctx.cli.p0  &&
1331 					    &bind_conf->by_fe == (&global.stats_fe->conf.bind)->n) {
1332 						/* change the current node to the latest dumped and continue the loop */
1333 						bind_conf = LIST_ELEM(appctx->ctx.cli.p0, typeof(bind_conf), by_fe);
1334 						continue;
1335 					}
1336 
1337 					list_for_each_entry(l, &bind_conf->listeners, by_bind) {
1338 
1339 						char addr[46];
1340 						char port[6];
1341 
1342 						if (l->addr.ss_family == AF_UNIX) {
1343 							const struct sockaddr_un *un;
1344 
1345 							un = (struct sockaddr_un *)&l->addr;
1346 							if (un->sun_path[0] == '\0') {
1347 								chunk_appendf(&trash, "abns@%s ", un->sun_path+1);
1348 							} else {
1349 								chunk_appendf(&trash, "unix@%s ", un->sun_path);
1350 							}
1351 						} else if (l->addr.ss_family == AF_INET) {
1352 							addr_to_str(&l->addr, addr, sizeof(addr));
1353 							port_to_str(&l->addr, port, sizeof(port));
1354 							chunk_appendf(&trash, "ipv4@%s:%s ", addr, port);
1355 						} else if (l->addr.ss_family == AF_INET6) {
1356 							addr_to_str(&l->addr, addr, sizeof(addr));
1357 							port_to_str(&l->addr, port, sizeof(port));
1358 							chunk_appendf(&trash, "ipv6@[%s]:%s ", addr, port);
1359 						} else if (l->addr.ss_family == AF_CUST_SOCKPAIR) {
1360 							chunk_appendf(&trash, "sockpair@%d ", ((struct sockaddr_in *)&l->addr)->sin_addr.s_addr);
1361 						} else
1362 							chunk_appendf(&trash, "unknown ");
1363 
1364 						if ((bind_conf->level & ACCESS_LVL_MASK) == ACCESS_LVL_ADMIN)
1365 							chunk_appendf(&trash, "admin ");
1366 						else if ((bind_conf->level & ACCESS_LVL_MASK) == ACCESS_LVL_OPER)
1367 							chunk_appendf(&trash, "operator ");
1368 						else if ((bind_conf->level & ACCESS_LVL_MASK) == ACCESS_LVL_USER)
1369 							chunk_appendf(&trash, "user ");
1370 						else
1371 							chunk_appendf(&trash, "  ");
1372 
1373 						if (bind_conf->bind_proc != 0) {
1374 							int pos;
1375 							for (pos = 0; pos < 8 * sizeof(bind_conf->bind_proc); pos++) {
1376 								if (bind_conf->bind_proc & (1UL << pos)) {
1377 									chunk_appendf(&trash, "%d,", pos+1);
1378 								}
1379 							}
1380 							/* replace the latest comma by a newline */
1381 							trash.area[trash.data-1] = '\n';
1382 
1383 						} else {
1384 							chunk_appendf(&trash, "all\n");
1385 						}
1386 
1387 						if (ci_putchk(si_ic(si), &trash) == -1) {
1388 							si_rx_room_blk(si);
1389 							return 0;
1390 						}
1391 					}
1392 					appctx->ctx.cli.p0 = &bind_conf->by_fe; /* store the latest list node dumped */
1393 				}
1394 			}
1395 			/* fall through */
1396 		default:
1397 			appctx->st2 = STAT_ST_FIN;
1398 			return 1;
1399 	}
1400 }
1401 
1402 
1403 /* parse a "show env" CLI request. Returns 0 if it needs to continue, 1 if it
1404  * wants to stop here. It puts the variable to be dumped into cli.p0 if a single
1405  * variable is requested otherwise puts environ there.
1406  */
cli_parse_show_env(char ** args,char * payload,struct appctx * appctx,void * private)1407 static int cli_parse_show_env(char **args, char *payload, struct appctx *appctx, void *private)
1408 {
1409 	extern char **environ;
1410 	char **var;
1411 
1412 	if (!cli_has_level(appctx, ACCESS_LVL_OPER))
1413 		return 1;
1414 
1415 	var = environ;
1416 
1417 	if (*args[2]) {
1418 		int len = strlen(args[2]);
1419 
1420 		for (; *var; var++) {
1421 			if (strncmp(*var, args[2], len) == 0 &&
1422 			    (*var)[len] == '=')
1423 				break;
1424 		}
1425 		if (!*var)
1426 			return cli_err(appctx, "Variable not found\n");
1427 
1428 		appctx->st2 = STAT_ST_END;
1429 	}
1430 	appctx->ctx.cli.p0 = var;
1431 	return 0;
1432 }
1433 
1434 /* parse a "show fd" CLI request. Returns 0 if it needs to continue, 1 if it
1435  * wants to stop here. It puts the FD number into cli.i0 if a specific FD is
1436  * requested and sets st2 to STAT_ST_END, otherwise leaves 0 in i0.
1437  */
cli_parse_show_fd(char ** args,char * payload,struct appctx * appctx,void * private)1438 static int cli_parse_show_fd(char **args, char *payload, struct appctx *appctx, void *private)
1439 {
1440 	if (!cli_has_level(appctx, ACCESS_LVL_OPER))
1441 		return 1;
1442 
1443 	appctx->ctx.cli.i0 = 0;
1444 
1445 	if (*args[2]) {
1446 		appctx->ctx.cli.i0 = atoi(args[2]);
1447 		appctx->st2 = STAT_ST_END;
1448 	}
1449 	return 0;
1450 }
1451 
1452 /* parse a "set timeout" CLI request. It always returns 1. */
cli_parse_set_timeout(char ** args,char * payload,struct appctx * appctx,void * private)1453 static int cli_parse_set_timeout(char **args, char *payload, struct appctx *appctx, void *private)
1454 {
1455 	struct stream_interface *si = appctx->owner;
1456 	struct stream *s = si_strm(si);
1457 
1458 	if (strcmp(args[2], "cli") == 0) {
1459 		unsigned timeout;
1460 		const char *res;
1461 
1462 		if (!*args[3])
1463 			return cli_err(appctx, "Expects an integer value.\n");
1464 
1465 		res = parse_time_err(args[3], &timeout, TIME_UNIT_S);
1466 		if (res || timeout < 1)
1467 			return cli_err(appctx, "Invalid timeout value.\n");
1468 
1469 		s->req.rto = s->res.wto = 1 + MS_TO_TICKS(timeout*1000);
1470 		task_wakeup(s->task, TASK_WOKEN_MSG); // recompute timeouts
1471 		return 1;
1472 	}
1473 
1474 	return cli_err(appctx, "'set timeout' only supports 'cli'.\n");
1475 }
1476 
1477 /* parse a "set maxconn global" command. It always returns 1. */
cli_parse_set_maxconn_global(char ** args,char * payload,struct appctx * appctx,void * private)1478 static int cli_parse_set_maxconn_global(char **args, char *payload, struct appctx *appctx, void *private)
1479 {
1480 	int v;
1481 
1482 	if (!cli_has_level(appctx, ACCESS_LVL_ADMIN))
1483 		return 1;
1484 
1485 	if (!*args[3])
1486 		return cli_err(appctx, "Expects an integer value.\n");
1487 
1488 	v = atoi(args[3]);
1489 	if (v > global.hardmaxconn)
1490 		return cli_err(appctx, "Value out of range.\n");
1491 
1492 	/* check for unlimited values */
1493 	if (v <= 0)
1494 		v = global.hardmaxconn;
1495 
1496 	global.maxconn = v;
1497 
1498 	/* Dequeues all of the listeners waiting for a resource */
1499 	dequeue_all_listeners();
1500 
1501 	return 1;
1502 }
1503 
set_severity_output(int * target,char * argument)1504 static int set_severity_output(int *target, char *argument)
1505 {
1506 	if (!strcmp(argument, "none")) {
1507 		*target = CLI_SEVERITY_NONE;
1508 		return 1;
1509 	}
1510 	else if (!strcmp(argument, "number")) {
1511 		*target = CLI_SEVERITY_NUMBER;
1512 		return 1;
1513 	}
1514 	else if (!strcmp(argument, "string")) {
1515 		*target = CLI_SEVERITY_STRING;
1516 		return 1;
1517 	}
1518 	return 0;
1519 }
1520 
1521 /* parse a "set severity-output" command. */
cli_parse_set_severity_output(char ** args,char * payload,struct appctx * appctx,void * private)1522 static int cli_parse_set_severity_output(char **args, char *payload, struct appctx *appctx, void *private)
1523 {
1524 	if (*args[2] && set_severity_output(&appctx->cli_severity_output, args[2]))
1525 		return 0;
1526 
1527 	return cli_err(appctx, "one of 'none', 'number', 'string' is a required argument\n");
1528 }
1529 
1530 
1531 /* show the level of the current CLI session */
cli_parse_show_lvl(char ** args,char * payload,struct appctx * appctx,void * private)1532 static int cli_parse_show_lvl(char **args, char *payload, struct appctx *appctx, void *private)
1533 {
1534 	if ((appctx->cli_level & ACCESS_LVL_MASK) == ACCESS_LVL_ADMIN)
1535 		return cli_msg(appctx, LOG_INFO, "admin\n");
1536 	else if ((appctx->cli_level & ACCESS_LVL_MASK) == ACCESS_LVL_OPER)
1537 		return cli_msg(appctx, LOG_INFO, "operator\n");
1538 	else if ((appctx->cli_level & ACCESS_LVL_MASK) == ACCESS_LVL_USER)
1539 		return cli_msg(appctx, LOG_INFO, "user\n");
1540 	else
1541 		return cli_msg(appctx, LOG_INFO, "unknown\n");
1542 }
1543 
1544 /* parse and set the CLI level dynamically */
cli_parse_set_lvl(char ** args,char * payload,struct appctx * appctx,void * private)1545 static int cli_parse_set_lvl(char **args, char *payload, struct appctx *appctx, void *private)
1546 {
1547 	/* this will ask the applet to not output a \n after the command */
1548 	if (!strcmp(args[1], "-"))
1549 	    appctx->st1 |= APPCTX_CLI_ST1_NOLF;
1550 
1551 	if (!strcmp(args[0], "operator")) {
1552 		if (!cli_has_level(appctx, ACCESS_LVL_OPER)) {
1553 			return 1;
1554 		}
1555 		appctx->cli_level &= ~ACCESS_LVL_MASK;
1556 		appctx->cli_level |= ACCESS_LVL_OPER;
1557 
1558 	} else if (!strcmp(args[0], "user")) {
1559 		if (!cli_has_level(appctx, ACCESS_LVL_USER)) {
1560 			return 1;
1561 		}
1562 		appctx->cli_level &= ~ACCESS_LVL_MASK;
1563 		appctx->cli_level |= ACCESS_LVL_USER;
1564 	}
1565 	appctx->cli_level &= ~ACCESS_EXPERT;
1566 	return 1;
1567 }
1568 
1569 
1570 /* parse and set the CLI expert-mode dynamically */
cli_parse_expert_mode(char ** args,char * payload,struct appctx * appctx,void * private)1571 static int cli_parse_expert_mode(char **args, char *payload, struct appctx *appctx, void *private)
1572 {
1573 	if (!cli_has_level(appctx, ACCESS_LVL_ADMIN))
1574 		return 1;
1575 
1576 	if (!*args[1])
1577 		return (appctx->cli_level & ACCESS_EXPERT)
1578 			? cli_msg(appctx, LOG_INFO, "expert-mode is ON\n")
1579 			: cli_msg(appctx, LOG_INFO, "expert-mode is OFF\n");
1580 
1581 	appctx->cli_level &= ~ACCESS_EXPERT;
1582 	if (strcmp(args[1], "on") == 0)
1583 		appctx->cli_level |= ACCESS_EXPERT;
1584 	return 1;
1585 }
1586 
1587 
cli_parse_default(char ** args,char * payload,struct appctx * appctx,void * private)1588 int cli_parse_default(char **args, char *payload, struct appctx *appctx, void *private)
1589 {
1590 	return 0;
1591 }
1592 
1593 /* parse a "set rate-limit" command. It always returns 1. */
cli_parse_set_ratelimit(char ** args,char * payload,struct appctx * appctx,void * private)1594 static int cli_parse_set_ratelimit(char **args, char *payload, struct appctx *appctx, void *private)
1595 {
1596 	int v;
1597 	int *res;
1598 	int mul = 1;
1599 
1600 	if (!cli_has_level(appctx, ACCESS_LVL_ADMIN))
1601 		return 1;
1602 
1603 	if (strcmp(args[2], "connections") == 0 && strcmp(args[3], "global") == 0)
1604 		res = &global.cps_lim;
1605 	else if (strcmp(args[2], "sessions") == 0 && strcmp(args[3], "global") == 0)
1606 		res = &global.sps_lim;
1607 #ifdef USE_OPENSSL
1608 	else if (strcmp(args[2], "ssl-sessions") == 0 && strcmp(args[3], "global") == 0)
1609 		res = &global.ssl_lim;
1610 #endif
1611 	else if (strcmp(args[2], "http-compression") == 0 && strcmp(args[3], "global") == 0) {
1612 		res = &global.comp_rate_lim;
1613 		mul = 1024;
1614 	}
1615 	else {
1616 		return cli_err(appctx,
1617 			"'set rate-limit' only supports :\n"
1618 			"   - 'connections global' to set the per-process maximum connection rate\n"
1619 			"   - 'sessions global' to set the per-process maximum session rate\n"
1620 #ifdef USE_OPENSSL
1621 			"   - 'ssl-sessions global' to set the per-process maximum SSL session rate\n"
1622 #endif
1623 			"   - 'http-compression global' to set the per-process maximum compression speed in kB/s\n");
1624 	}
1625 
1626 	if (!*args[4])
1627 		return cli_err(appctx, "Expects an integer value.\n");
1628 
1629 	v = atoi(args[4]);
1630 	if (v < 0)
1631 		return cli_err(appctx, "Value out of range.\n");
1632 
1633 	*res = v * mul;
1634 
1635 	/* Dequeues all of the listeners waiting for a resource */
1636 	dequeue_all_listeners();
1637 
1638 	return 1;
1639 }
1640 
1641 /* parse the "expose-fd" argument on the bind lines */
bind_parse_expose_fd(char ** args,int cur_arg,struct proxy * px,struct bind_conf * conf,char ** err)1642 static int bind_parse_expose_fd(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1643 {
1644 	if (!*args[cur_arg + 1]) {
1645 		memprintf(err, "'%s' : missing fd type", args[cur_arg]);
1646 		return ERR_ALERT | ERR_FATAL;
1647 	}
1648 	if (!strcmp(args[cur_arg+1], "listeners")) {
1649 		conf->level |= ACCESS_FD_LISTENERS;
1650 	} else {
1651 		memprintf(err, "'%s' only supports 'listeners' (got '%s')",
1652 			  args[cur_arg], args[cur_arg+1]);
1653 		return ERR_ALERT | ERR_FATAL;
1654 	}
1655 
1656 	return 0;
1657 }
1658 
1659 /* parse the "level" argument on the bind lines */
bind_parse_level(char ** args,int cur_arg,struct proxy * px,struct bind_conf * conf,char ** err)1660 static int bind_parse_level(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1661 {
1662 	if (!*args[cur_arg + 1]) {
1663 		memprintf(err, "'%s' : missing level", args[cur_arg]);
1664 		return ERR_ALERT | ERR_FATAL;
1665 	}
1666 
1667 	if (!strcmp(args[cur_arg+1], "user")) {
1668 		conf->level &= ~ACCESS_LVL_MASK;
1669 		conf->level |= ACCESS_LVL_USER;
1670 	} else if (!strcmp(args[cur_arg+1], "operator")) {
1671 		conf->level &= ~ACCESS_LVL_MASK;
1672 		conf->level |= ACCESS_LVL_OPER;
1673 	} else if (!strcmp(args[cur_arg+1], "admin")) {
1674 		conf->level &= ~ACCESS_LVL_MASK;
1675 		conf->level |= ACCESS_LVL_ADMIN;
1676 	} else {
1677 		memprintf(err, "'%s' only supports 'user', 'operator', and 'admin' (got '%s')",
1678 			  args[cur_arg], args[cur_arg+1]);
1679 		return ERR_ALERT | ERR_FATAL;
1680 	}
1681 
1682 	return 0;
1683 }
1684 
bind_parse_severity_output(char ** args,int cur_arg,struct proxy * px,struct bind_conf * conf,char ** err)1685 static int bind_parse_severity_output(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
1686 {
1687 	if (!*args[cur_arg + 1]) {
1688 		memprintf(err, "'%s' : missing severity format", args[cur_arg]);
1689 		return ERR_ALERT | ERR_FATAL;
1690 	}
1691 
1692 	if (set_severity_output(&conf->severity_output, args[cur_arg+1]))
1693 		return 0;
1694 	else {
1695 		memprintf(err, "'%s' only supports 'none', 'number', and 'string' (got '%s')",
1696 				args[cur_arg], args[cur_arg+1]);
1697 		return ERR_ALERT | ERR_FATAL;
1698 	}
1699 }
1700 
1701 /*
1702  * For one proxy, fill the iov and send the msghdr. Also update fd_it and offset.
1703  * Return -1 upon error, otherwise 0.
1704  *
1705  * This function is only meant to deduplicate the code between the peers and
1706  * the proxy list in _getsocks(), not to be used anywhere else.
1707  */
_getsocks_gen_send(struct proxy * px,int sendfd,int * tmpfd,struct iovec * iov,int tot_fd_nb,int * fd_it,int * offset,struct msghdr * msghdr)1708 inline static int _getsocks_gen_send(struct proxy *px, int sendfd, int *tmpfd, struct iovec *iov,
1709                                      int tot_fd_nb, int *fd_it, int *offset, struct msghdr *msghdr)
1710 {
1711 	int i = *fd_it;
1712 	int curoff = *offset;
1713 	struct listener *l;
1714 	unsigned char *tmpbuf = iov->iov_base;
1715 
1716 	list_for_each_entry(l, &px->conf.listeners, by_fe) {
1717 		int ret;
1718 		/* Only transfer IPv4/IPv6 sockets */
1719 		if (l->state >= LI_ZOMBIE &&
1720 		    (l->proto->sock_family == AF_INET ||
1721 		     l->proto->sock_family == AF_INET6 ||
1722 		     l->proto->sock_family == AF_UNIX)) {
1723 			memcpy(&tmpfd[i % MAX_SEND_FD], &l->fd, sizeof(l->fd));
1724 			if (!l->netns)
1725 				tmpbuf[curoff++] = 0;
1726 #ifdef USE_NS
1727 			else {
1728 				char *name = l->netns->node.key;
1729 				unsigned char len = l->netns->name_len;
1730 				tmpbuf[curoff++] = len;
1731 				memcpy(tmpbuf + curoff, name, len);
1732 				curoff += len;
1733 			}
1734 #endif
1735 			if (l->interface) {
1736 				unsigned char len = strlen(l->interface);
1737 				tmpbuf[curoff++] = len;
1738 				memcpy(tmpbuf + curoff, l->interface, len);
1739 				curoff += len;
1740 			} else
1741 				tmpbuf[curoff++] = 0;
1742 			memcpy(tmpbuf + curoff, &l->options,
1743 			       sizeof(l->options));
1744 			curoff += sizeof(l->options);
1745 
1746 			i++;
1747 		} else
1748 			continue;
1749 		/* if it reaches the max number of fd per msghdr */
1750 		if ((!(i % MAX_SEND_FD))) {
1751 			iov->iov_len = curoff;
1752 			if (sendmsg(sendfd, msghdr, 0) != curoff) {
1753 				ha_warning("Failed to transfer sockets\n");
1754 				return -1;
1755 			}
1756 			/* Wait for an ack */
1757 			do {
1758 				ret = recv(sendfd, &tot_fd_nb,
1759 				           sizeof(tot_fd_nb), 0);
1760 			} while (ret == -1 && errno == EINTR);
1761 			if (ret <= 0) {
1762 				ha_warning("Unexpected error while transferring sockets\n");
1763 				return -1;
1764 			}
1765 			curoff = 0;
1766 		}
1767 	}
1768 
1769 	*fd_it = i;
1770 	*offset = curoff;
1771 
1772 	return 0;
1773 }
1774 
1775 
1776 /* Send all the bound sockets, always returns 1 */
_getsocks(char ** args,char * payload,struct appctx * appctx,void * private)1777 static int _getsocks(char **args, char *payload, struct appctx *appctx, void *private)
1778 {
1779 	char *cmsgbuf = NULL;
1780 	unsigned char *tmpbuf = NULL;
1781 	struct cmsghdr *cmsg;
1782 	struct stream_interface *si = appctx->owner;
1783 	struct stream *s = si_strm(si);
1784 	struct connection *remote = cs_conn(objt_cs(si_opposite(si)->end));
1785 	struct msghdr msghdr;
1786 	struct iovec iov;
1787 	struct timeval tv = { .tv_sec = 1, .tv_usec = 0 };
1788 	int *tmpfd;
1789 	int tot_fd_nb = 0;
1790 	struct proxy *px;
1791 	struct peers *prs;
1792 	int i = 0;
1793 	int fd = -1;
1794 	int curoff = 0;
1795 	int old_fcntl = -1;
1796 	int ret;
1797 
1798 	if (!remote) {
1799 		ha_warning("Only works on real connections\n");
1800 		goto out;
1801 	}
1802 
1803 	fd = remote->handle.fd;
1804 
1805 	/* Temporary set the FD in blocking mode, that will make our life easier */
1806 	old_fcntl = fcntl(fd, F_GETFL);
1807 	if (old_fcntl < 0) {
1808 		ha_warning("Couldn't get the flags for the unix socket\n");
1809 		goto out;
1810 	}
1811 	cmsgbuf = malloc(CMSG_SPACE(sizeof(int) * MAX_SEND_FD));
1812 	if (!cmsgbuf) {
1813 		ha_warning("Failed to allocate memory to send sockets\n");
1814 		goto out;
1815 	}
1816 	if (fcntl(fd, F_SETFL, old_fcntl &~ O_NONBLOCK) == -1) {
1817 		ha_warning("Cannot make the unix socket blocking\n");
1818 		goto out;
1819 	}
1820 	setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, (void *)&tv, sizeof(tv));
1821 	iov.iov_base = &tot_fd_nb;
1822 	iov.iov_len = sizeof(tot_fd_nb);
1823 	if (!(strm_li(s)->bind_conf->level & ACCESS_FD_LISTENERS))
1824 		goto out;
1825 	memset(&msghdr, 0, sizeof(msghdr));
1826 	/*
1827 	 * First, calculates the total number of FD, so that we can let
1828 	 * the caller know how much he should expects.
1829 	 */
1830 	px = proxies_list;
1831 	while (px) {
1832 		struct listener *l;
1833 
1834 		list_for_each_entry(l, &px->conf.listeners, by_fe) {
1835 			/* Only transfer IPv4/IPv6/UNIX sockets */
1836 			if (l->state >= LI_ZOMBIE &&
1837 			    (l->proto->sock_family == AF_INET ||
1838 			    l->proto->sock_family == AF_INET6 ||
1839 			    l->proto->sock_family == AF_UNIX))
1840 				tot_fd_nb++;
1841 		}
1842 		px = px->next;
1843 	}
1844 	prs = cfg_peers;
1845 	while (prs) {
1846 		if (prs->peers_fe) {
1847 			struct listener *l;
1848 
1849 			list_for_each_entry(l, &prs->peers_fe->conf.listeners, by_fe) {
1850 				/* Only transfer IPv4/IPv6/UNIX sockets */
1851 				if (l->state >= LI_ZOMBIE &&
1852 				    (l->proto->sock_family == AF_INET ||
1853 				     l->proto->sock_family == AF_INET6 ||
1854 				     l->proto->sock_family == AF_UNIX))
1855 					tot_fd_nb++;
1856 			}
1857 		}
1858 		prs = prs->next;
1859 	}
1860 	if (tot_fd_nb == 0)
1861 		goto out;
1862 
1863 	/* First send the total number of file descriptors, so that the
1864 	 * receiving end knows what to expect.
1865 	 */
1866 	msghdr.msg_iov = &iov;
1867 	msghdr.msg_iovlen = 1;
1868 	ret = sendmsg(fd, &msghdr, 0);
1869 	if (ret != sizeof(tot_fd_nb)) {
1870 		ha_warning("Failed to send the number of sockets to send\n");
1871 		goto out;
1872 	}
1873 
1874 	/* Now send the fds */
1875 	msghdr.msg_control = cmsgbuf;
1876 	msghdr.msg_controllen = CMSG_SPACE(sizeof(int) * MAX_SEND_FD);
1877 	cmsg = CMSG_FIRSTHDR(&msghdr);
1878 	cmsg->cmsg_len = CMSG_LEN(MAX_SEND_FD * sizeof(int));
1879 	cmsg->cmsg_level = SOL_SOCKET;
1880 	cmsg->cmsg_type = SCM_RIGHTS;
1881 	tmpfd = (int *)CMSG_DATA(cmsg);
1882 
1883 	/* For each socket, e message is sent, containing the following :
1884 	 *  Size of the namespace name (or 0 if none), as an unsigned char.
1885 	 *  The namespace name, if any
1886 	 *  Size of the interface name (or 0 if none), as an unsigned char
1887 	 *  The interface name, if any
1888 	 *  Listener options, as an int.
1889 	 */
1890 	/* We will send sockets MAX_SEND_FD per MAX_SEND_FD, allocate a
1891 	 * buffer big enough to store the socket information.
1892 	 */
1893 	tmpbuf = malloc(MAX_SEND_FD * (1 + MAXPATHLEN + 1 + IFNAMSIZ + sizeof(int)));
1894 	if (tmpbuf == NULL) {
1895 		ha_warning("Failed to allocate memory to transfer socket information\n");
1896 		goto out;
1897 	}
1898 	iov.iov_base = tmpbuf;
1899 	px = proxies_list;
1900 	while (px) {
1901 		if (_getsocks_gen_send(px, fd, tmpfd, &iov,
1902 		                   tot_fd_nb, &i, &curoff, &msghdr) < 0)
1903 			goto out;
1904 		px = px->next;
1905 	}
1906 	/* should be done for peers too */
1907 	prs = cfg_peers;
1908 	while (prs) {
1909 		if (prs->peers_fe)
1910 			if (_getsocks_gen_send(prs->peers_fe, fd, tmpfd, &iov,
1911 			                       tot_fd_nb, &i, &curoff, &msghdr) < 0)
1912 				goto out;
1913 		prs = prs->next;
1914 	}
1915 
1916 	if (i % MAX_SEND_FD) {
1917 		iov.iov_len = curoff;
1918 		cmsg->cmsg_len = CMSG_LEN((i % MAX_SEND_FD) * sizeof(int));
1919 		msghdr.msg_controllen = CMSG_SPACE(sizeof(int) *  (i % MAX_SEND_FD));
1920 		if (sendmsg(fd, &msghdr, 0) != curoff) {
1921 			ha_warning("Failed to transfer sockets\n");
1922 			goto out;
1923 		}
1924 	}
1925 
1926 out:
1927 	if (fd >= 0 && old_fcntl >= 0 && fcntl(fd, F_SETFL, old_fcntl) == -1) {
1928 		ha_warning("Cannot make the unix socket non-blocking\n");
1929 		goto out;
1930 	}
1931 	appctx->st0 = CLI_ST_END;
1932 	free(cmsgbuf);
1933 	free(tmpbuf);
1934 	return 1;
1935 }
1936 
cli_parse_simple(char ** args,char * payload,struct appctx * appctx,void * private)1937 static int cli_parse_simple(char **args, char *payload, struct appctx *appctx, void *private)
1938 {
1939 	if (*args[0] == 'h')
1940 		/* help */
1941 		cli_gen_usage_msg(appctx);
1942 	else if (*args[0] == 'p')
1943 		/* prompt */
1944 		appctx->st1 ^= APPCTX_CLI_ST1_PROMPT;
1945 	else if (*args[0] == 'q')
1946 		/* quit */
1947 		appctx->st0 = CLI_ST_END;
1948 
1949 	return 1;
1950 }
1951 
pcli_write_prompt(struct stream * s)1952 void pcli_write_prompt(struct stream *s)
1953 {
1954 	struct buffer *msg = get_trash_chunk();
1955 	struct channel *oc = si_oc(&s->si[0]);
1956 
1957 	if (!(s->pcli_flags & PCLI_F_PROMPT))
1958 		return;
1959 
1960 	if (s->pcli_flags & PCLI_F_PAYLOAD) {
1961 		chunk_appendf(msg, "+ ");
1962 	} else {
1963 		if (s->pcli_next_pid == 0)
1964 			chunk_appendf(msg, "master%s> ",
1965 			              (global.mode & MODE_MWORKER_WAIT) ? "[ReloadFailed]" : "");
1966 		else
1967 			chunk_appendf(msg, "%d> ", s->pcli_next_pid);
1968 	}
1969 	co_inject(oc, msg->area, msg->data);
1970 }
1971 
1972 
1973 /* The pcli_* functions are used for the CLI proxy in the master */
1974 
pcli_reply_and_close(struct stream * s,const char * msg)1975 void pcli_reply_and_close(struct stream *s, const char *msg)
1976 {
1977 	struct buffer *buf = get_trash_chunk();
1978 
1979 	chunk_initstr(buf, msg);
1980 	si_retnclose(&s->si[0], buf);
1981 }
1982 
pcli_pid_to_server(int proc_pid)1983 static enum obj_type *pcli_pid_to_server(int proc_pid)
1984 {
1985 	struct mworker_proc *child;
1986 
1987 	/* return the CLI applet of the master */
1988 	if (proc_pid == 0)
1989 		return &cli_applet.obj_type;
1990 
1991 	list_for_each_entry(child, &proc_list, list) {
1992 		if (child->pid == proc_pid){
1993 			return &child->srv->obj_type;
1994 		}
1995 	}
1996 	return NULL;
1997 }
1998 
1999 /* Take a CLI prefix in argument (eg: @!1234 @master @1)
2000  *  Return:
2001  *     0: master
2002  *   > 0: pid of a worker
2003  *   < 0: didn't find a worker
2004  */
pcli_prefix_to_pid(const char * prefix)2005 static int pcli_prefix_to_pid(const char *prefix)
2006 {
2007 	int proc_pid;
2008 	struct mworker_proc *child;
2009 	char *errtol = NULL;
2010 
2011 	if (*prefix != '@') /* not a prefix, should not happen */
2012 		return -1;
2013 
2014 	prefix++;
2015 	if (!*prefix)    /* sent @ alone, return the master */
2016 		return 0;
2017 
2018 	if (strcmp("master", prefix) == 0) {
2019 		return 0;
2020 	} else if (*prefix == '!') {
2021 		prefix++;
2022 		if (!*prefix)
2023 			return -1;
2024 
2025 		proc_pid = strtol(prefix, &errtol, 10);
2026 		if (*errtol != '\0')
2027 			return -1;
2028 		list_for_each_entry(child, &proc_list, list) {
2029 			if (!(child->options & PROC_O_TYPE_WORKER))
2030 				continue;
2031 			if (child->pid == proc_pid){
2032 				return child->pid;
2033 			}
2034 		}
2035 	} else {
2036 		struct mworker_proc *chosen = NULL;
2037 		/* this is a relative pid */
2038 
2039 		proc_pid = strtol(prefix, &errtol, 10);
2040 		if (*errtol != '\0')
2041 			return -1;
2042 
2043 		if (proc_pid == 0) /* return the master */
2044 			return 0;
2045 
2046 		/* chose the right process, the current one is the one with the
2047 		 least number of reloads */
2048 		list_for_each_entry(child, &proc_list, list) {
2049 			if (!(child->options & PROC_O_TYPE_WORKER))
2050 				continue;
2051 			if (child->relative_pid == proc_pid){
2052 				if (child->reloads == 0)
2053 					return child->pid;
2054 				else if (chosen == NULL || child->reloads < chosen->reloads)
2055 					chosen = child;
2056 			}
2057 		}
2058 		if (chosen)
2059 			return chosen->pid;
2060 	}
2061 	return -1;
2062 }
2063 
2064 /* Return::
2065  *  >= 0 : number of words to escape
2066  *  = -1 : error
2067  */
2068 
pcli_find_and_exec_kw(struct stream * s,char ** args,int argl,char ** errmsg,int * next_pid)2069 int pcli_find_and_exec_kw(struct stream *s, char **args, int argl, char **errmsg, int *next_pid)
2070 {
2071 	if (argl < 1)
2072 		return 0;
2073 
2074 	/* there is a prefix */
2075 	if (args[0][0] == '@') {
2076 		int target_pid = pcli_prefix_to_pid(args[0]);
2077 
2078 		if (target_pid == -1) {
2079 			memprintf(errmsg, "Can't find the target PID matching the prefix '%s'\n", args[0]);
2080 			return -1;
2081 		}
2082 
2083 		/* if the prefix is alone, define a default target */
2084 		if (argl == 1)
2085 			s->pcli_next_pid = target_pid;
2086 		else
2087 			*next_pid = target_pid;
2088 		return 1;
2089 	} else if (!strcmp("prompt", args[0])) {
2090 		s->pcli_flags ^= PCLI_F_PROMPT;
2091 		return argl; /* return the number of elements in the array */
2092 
2093 	} else if (!strcmp("quit", args[0])) {
2094 		channel_shutr_now(&s->req);
2095 		channel_shutw_now(&s->res);
2096 		return argl; /* return the number of elements in the array */
2097 	} else if (!strcmp(args[0], "operator")) {
2098 		if (!pcli_has_level(s, ACCESS_LVL_OPER)) {
2099 			memprintf(errmsg, "Permission denied!\n");
2100 			return -1;
2101 		}
2102 		s->pcli_flags &= ~ACCESS_LVL_MASK;
2103 		s->pcli_flags |= ACCESS_LVL_OPER;
2104 		return argl;
2105 
2106 	} else if (!strcmp(args[0], "user")) {
2107 		if (!pcli_has_level(s, ACCESS_LVL_USER)) {
2108 			memprintf(errmsg, "Permission denied!\n");
2109 			return -1;
2110 		}
2111 		s->pcli_flags &= ~ACCESS_LVL_MASK;
2112 		s->pcli_flags |= ACCESS_LVL_USER;
2113 		return argl;
2114 	}
2115 
2116 	return 0;
2117 }
2118 
2119 /*
2120  * Parse the CLI request:
2121  *  - It does basically the same as the cli_io_handler, but as a proxy
2122  *  - It can exec a command and strip non forwardable commands
2123  *
2124  *  Return:
2125  *  - the number of characters to forward or
2126  *  - 1 if there is an error or not enough data
2127  */
pcli_parse_request(struct stream * s,struct channel * req,char ** errmsg,int * next_pid)2128 int pcli_parse_request(struct stream *s, struct channel *req, char **errmsg, int *next_pid)
2129 {
2130 	char *str = (char *)ci_head(req);
2131 	char *end = (char *)ci_stop(req);
2132 	char *args[MAX_STATS_ARGS + 1]; /* +1 for storing a NULL */
2133 	int argl; /* number of args */
2134 	char *p;
2135 	char *trim = NULL;
2136 	char *payload = NULL;
2137 	int wtrim = 0; /* number of words to trim */
2138 	int reql = 0;
2139 	int ret;
2140 	int i = 0;
2141 
2142 	p = str;
2143 
2144 	if (!(s->pcli_flags & PCLI_F_PAYLOAD)) {
2145 
2146 		/* Looks for the end of one command */
2147 		while (p+reql < end) {
2148 			/* handle escaping */
2149 			if (p[reql] == '\\') {
2150 				reql+=2;
2151 				continue;
2152 			}
2153 			if (p[reql] == ';' || p[reql] == '\n') {
2154 				/* found the end of the command */
2155 				p[reql] = '\n';
2156 				reql++;
2157 				break;
2158 			}
2159 			reql++;
2160 		}
2161 	} else {
2162 		while (p+reql < end) {
2163 			if (p[reql] == '\n') {
2164 				/* found the end of the line */
2165 				reql++;
2166 				break;
2167 			}
2168 			reql++;
2169 		}
2170 	}
2171 
2172 	/* set end to first byte after the end of the command */
2173 	end = p + reql;
2174 
2175 	/* there is no end to this command, need more to parse ! */
2176 	if (*(end-1) != '\n') {
2177 		return -1;
2178 	}
2179 
2180 	if (s->pcli_flags & PCLI_F_PAYLOAD) {
2181 		if (reql == 1) /* last line of the payload */
2182 			s->pcli_flags &= ~PCLI_F_PAYLOAD;
2183 		return reql;
2184 	}
2185 
2186 	*(end-1) = '\0';
2187 
2188 	/* splits the command in words */
2189 	while (i < MAX_STATS_ARGS && p < end) {
2190 		/* skip leading spaces/tabs */
2191 		p += strspn(p, " \t");
2192 		if (!*p)
2193 			break;
2194 
2195 		args[i] = p;
2196 		while (1) {
2197 			p += strcspn(p, " \t\\");
2198 			/* escaped chars using backlashes (\) */
2199 			if (*p == '\\') {
2200 				if (!*++p)
2201 					break;
2202 				if (!*++p)
2203 					break;
2204 			} else {
2205 				break;
2206 			}
2207 		}
2208 		*p++ = 0;
2209 		i++;
2210 	}
2211 
2212 	argl = i;
2213 
2214 	for (; i < MAX_STATS_ARGS + 1; i++)
2215 		args[i] = NULL;
2216 
2217 	wtrim = pcli_find_and_exec_kw(s, args, argl, errmsg, next_pid);
2218 
2219 	/* End of words are ending by \0, we need to replace the \0s by spaces
2220 1	   before forwarding them */
2221 	p = str;
2222 	while (p < end-1) {
2223 		if (*p == '\0')
2224 			*p = ' ';
2225 		p++;
2226 	}
2227 
2228 	payload = strstr(str, PAYLOAD_PATTERN);
2229 	if ((end - 1) == (payload + strlen(PAYLOAD_PATTERN))) {
2230 		/* if the payload pattern is at the end */
2231 		s->pcli_flags |= PCLI_F_PAYLOAD;
2232 		ret = reql;
2233 	}
2234 
2235 	*(end-1) = '\n';
2236 
2237 	if (wtrim > 0) {
2238 		trim = &args[wtrim][0];
2239 		if (trim == NULL) /* if this was the last word in the table */
2240 			trim = end;
2241 
2242 		b_del(&req->buf, trim - str);
2243 
2244 		ret = end - trim;
2245 	} else if (wtrim < 0) {
2246 		/* parsing error */
2247 		return -1;
2248 	} else {
2249 		/* the whole string */
2250 		ret = end - str;
2251 	}
2252 
2253 	if (ret > 1) {
2254 		if (pcli_has_level(s, ACCESS_LVL_ADMIN)) {
2255 			goto end;
2256 		} else if (pcli_has_level(s, ACCESS_LVL_OPER)) {
2257 			ci_insert_line2(req, 0, "operator -", strlen("operator -"));
2258 			ret += strlen("operator -") + 2;
2259 		} else if (pcli_has_level(s, ACCESS_LVL_USER)) {
2260 			ci_insert_line2(req, 0, "user -", strlen("user -"));
2261 			ret += strlen("user -") + 2;
2262 		}
2263 	}
2264 end:
2265 
2266 	return ret;
2267 }
2268 
pcli_wait_for_request(struct stream * s,struct channel * req,int an_bit)2269 int pcli_wait_for_request(struct stream *s, struct channel *req, int an_bit)
2270 {
2271 	int next_pid = -1;
2272 	int to_forward;
2273 	char *errmsg = NULL;
2274 
2275 	if ((s->pcli_flags & ACCESS_LVL_MASK) == ACCESS_LVL_NONE)
2276 		s->pcli_flags |= strm_li(s)->bind_conf->level & ACCESS_LVL_MASK;
2277 
2278 read_again:
2279 	/* if the channel is closed for read, we won't receive any more data
2280 	   from the client, but we don't want to forward this close to the
2281 	   server */
2282 	channel_dont_close(req);
2283 
2284 	/* We don't know yet to which server we will connect */
2285 	channel_dont_connect(req);
2286 
2287 
2288 	/* we are not waiting for a response, there is no more request and we
2289 	 * receive a close from the client, we can leave */
2290 	if (!(ci_data(req)) && req->flags & CF_SHUTR) {
2291 		channel_shutw_now(&s->res);
2292 		s->req.analysers &= ~AN_REQ_WAIT_CLI;
2293 		return 1;
2294 	}
2295 
2296 	req->flags |= CF_READ_DONTWAIT;
2297 
2298 	/* need more data */
2299 	if (!ci_data(req))
2300 		return 0;
2301 
2302 	/* If there is data available for analysis, log the end of the idle time. */
2303 	if (c_data(req) && s->logs.t_idle == -1)
2304 		s->logs.t_idle = tv_ms_elapsed(&s->logs.tv_accept, &now) - s->logs.t_handshake;
2305 
2306 	to_forward = pcli_parse_request(s, req, &errmsg, &next_pid);
2307 	if (to_forward > 0) {
2308 		int target_pid;
2309 		/* enough data */
2310 
2311 		/* forward only 1 command */
2312 		channel_forward(req, to_forward);
2313 
2314 		if (!(s->pcli_flags & PCLI_F_PAYLOAD)) {
2315 			/* we send only 1 command per request, and we write close after it */
2316 			channel_shutw_now(req);
2317 		} else {
2318 			pcli_write_prompt(s);
2319 		}
2320 
2321 		s->res.flags |= CF_WAKE_ONCE; /* need to be called again */
2322 
2323 		/* remove the XFER_DATA analysers, which forwards all
2324 		 * the data, we don't want to forward the next requests
2325 		 * We need to add CF_FLT_ANALYZE to abort the forward too.
2326 		 */
2327 		req->analysers &= ~(AN_REQ_FLT_XFER_DATA|AN_REQ_WAIT_CLI);
2328 		req->analysers |= AN_REQ_FLT_END|CF_FLT_ANALYZE;
2329 		s->res.analysers |= AN_RES_WAIT_CLI;
2330 
2331 		if (!(s->flags & SF_ASSIGNED)) {
2332 			if (next_pid > -1)
2333 				target_pid = next_pid;
2334 			else
2335 				target_pid = s->pcli_next_pid;
2336 			/* we can connect now */
2337 			s->target = pcli_pid_to_server(target_pid);
2338 
2339 			s->flags |= (SF_DIRECT | SF_ASSIGNED);
2340 			channel_auto_connect(req);
2341 		}
2342 
2343 	} else if (to_forward == 0) {
2344 		/* we trimmed things but we might have other commands to consume */
2345 		pcli_write_prompt(s);
2346 		goto read_again;
2347 	} else if (to_forward == -1 && errmsg) {
2348 		/* there was an error during the parsing */
2349 			pcli_reply_and_close(s, errmsg);
2350 			return 0;
2351 	} else if (to_forward == -1 && channel_full(req, global.tune.maxrewrite)) {
2352 		/* buffer is full and we didn't catch the end of a command */
2353 		goto send_help;
2354 	}
2355 
2356 	return 0;
2357 
2358 send_help:
2359 	b_reset(&req->buf);
2360 	b_putblk(&req->buf, "help\n", 5);
2361 	goto read_again;
2362 }
2363 
pcli_wait_for_response(struct stream * s,struct channel * rep,int an_bit)2364 int pcli_wait_for_response(struct stream *s, struct channel *rep, int an_bit)
2365 {
2366 	struct proxy *fe = strm_fe(s);
2367 	struct proxy *be = s->be;
2368 
2369 	if (rep->flags & CF_READ_ERROR) {
2370 		pcli_reply_and_close(s, "Can't connect to the target CLI!\n");
2371 		s->res.analysers &= ~AN_RES_WAIT_CLI;
2372 		return 0;
2373 	}
2374 	rep->flags |= CF_READ_DONTWAIT; /* try to get back here ASAP */
2375 	rep->flags |= CF_NEVER_WAIT;
2376 
2377 	/* don't forward the close */
2378 	channel_dont_close(&s->res);
2379 	channel_dont_close(&s->req);
2380 
2381 	if (s->pcli_flags & PCLI_F_PAYLOAD) {
2382 		s->req.analysers |= AN_REQ_WAIT_CLI;
2383 		s->res.analysers &= ~AN_RES_WAIT_CLI;
2384 		s->req.flags |= CF_WAKE_ONCE; /* need to be called again if there is some command left in the request */
2385 		return 0;
2386 	}
2387 
2388 	/* forward the data */
2389 	if (ci_data(rep)) {
2390 		c_adv(rep, ci_data(rep));
2391 		return 0;
2392 	}
2393 
2394 	if ((rep->flags & (CF_SHUTR|CF_READ_NULL))) {
2395 		/* stream cleanup */
2396 
2397 		pcli_write_prompt(s);
2398 
2399 		s->si[1].flags |= SI_FL_NOLINGER | SI_FL_NOHALF;
2400 		si_shutr(&s->si[1]);
2401 		si_shutw(&s->si[1]);
2402 
2403 		/*
2404 		 * starting from there this the same code as
2405 		 * http_end_txn_clean_session().
2406 		 *
2407 		 * It allows to do frontend keepalive while reconnecting to a
2408 		 * new server for each request.
2409 		 */
2410 
2411 		if (s->flags & SF_BE_ASSIGNED) {
2412 			HA_ATOMIC_SUB(&be->beconn, 1);
2413 			if (unlikely(s->srv_conn))
2414 				sess_change_server(s, NULL);
2415 		}
2416 
2417 		s->logs.t_close = tv_ms_elapsed(&s->logs.tv_accept, &now);
2418 		stream_process_counters(s);
2419 
2420 		/* don't count other requests' data */
2421 		s->logs.bytes_in  -= ci_data(&s->req);
2422 		s->logs.bytes_out -= ci_data(&s->res);
2423 
2424 		/* we may need to know the position in the queue */
2425 		pendconn_free(s);
2426 
2427 		/* let's do a final log if we need it */
2428 		if (!LIST_ISEMPTY(&fe->logformat) && s->logs.logwait &&
2429 		    !(s->flags & SF_MONITOR) &&
2430 		    (!(fe->options & PR_O_NULLNOLOG) || s->req.total)) {
2431 			s->do_log(s);
2432 		}
2433 
2434 		/* stop tracking content-based counters */
2435 		stream_stop_content_counters(s);
2436 		stream_update_time_stats(s);
2437 
2438 		s->logs.accept_date = date; /* user-visible date for logging */
2439 		s->logs.tv_accept = now;  /* corrected date for internal use */
2440 		s->logs.t_handshake = 0; /* There are no handshake in keep alive connection. */
2441 		s->logs.t_idle = -1;
2442 		tv_zero(&s->logs.tv_request);
2443 		s->logs.t_queue = -1;
2444 		s->logs.t_connect = -1;
2445 		s->logs.t_data = -1;
2446 		s->logs.t_close = 0;
2447 		s->logs.prx_queue_pos = 0;  /* we get the number of pending conns before us */
2448 		s->logs.srv_queue_pos = 0; /* we will get this number soon */
2449 
2450 		s->logs.bytes_in = s->req.total = ci_data(&s->req);
2451 		s->logs.bytes_out = s->res.total = ci_data(&s->res);
2452 
2453 		stream_del_srv_conn(s);
2454 		if (objt_server(s->target)) {
2455 			if (s->flags & SF_CURR_SESS) {
2456 				s->flags &= ~SF_CURR_SESS;
2457 				HA_ATOMIC_SUB(&__objt_server(s->target)->cur_sess, 1);
2458 			}
2459 			if (may_dequeue_tasks(__objt_server(s->target), be))
2460 				process_srv_queue(__objt_server(s->target), 0);
2461 		}
2462 
2463 		s->target = NULL;
2464 
2465 		/* only release our endpoint if we don't intend to reuse the
2466 		 * connection.
2467 		 */
2468 		if (!si_conn_ready(&s->si[1])) {
2469 			si_release_endpoint(&s->si[1]);
2470 			s->srv_conn = NULL;
2471 		}
2472 
2473 		sockaddr_free(&s->target_addr);
2474 
2475 		s->si[1].state     = s->si[1].prev_state = SI_ST_INI;
2476 		s->si[1].err_type  = SI_ET_NONE;
2477 		s->si[1].conn_retries = 0;  /* used for logging too */
2478 		s->si[1].exp       = TICK_ETERNITY;
2479 		s->si[1].flags    &= SI_FL_ISBACK | SI_FL_DONT_WAKE; /* we're in the context of process_stream */
2480 		s->req.flags &= ~(CF_SHUTW|CF_SHUTW_NOW|CF_AUTO_CONNECT|CF_WRITE_ERROR|CF_STREAMER|CF_STREAMER_FAST|CF_NEVER_WAIT|CF_WROTE_DATA);
2481 		s->res.flags &= ~(CF_SHUTR|CF_SHUTR_NOW|CF_READ_ATTACHED|CF_READ_ERROR|CF_READ_NOEXP|CF_STREAMER|CF_STREAMER_FAST|CF_WRITE_PARTIAL|CF_NEVER_WAIT|CF_WROTE_DATA|CF_READ_NULL);
2482 		s->flags &= ~(SF_DIRECT|SF_ASSIGNED|SF_ADDR_SET|SF_BE_ASSIGNED|SF_FORCE_PRST|SF_IGNORE_PRST);
2483 		s->flags &= ~(SF_CURR_SESS|SF_REDIRECTABLE|SF_SRV_REUSED);
2484 		s->flags &= ~(SF_ERR_MASK|SF_FINST_MASK|SF_REDISP);
2485 		/* reinitialise the current rule list pointer to NULL. We are sure that
2486 		 * any rulelist match the NULL pointer.
2487 		 */
2488 		s->current_rule_list = NULL;
2489 
2490 		s->be = strm_fe(s);
2491 		s->logs.logwait = strm_fe(s)->to_log;
2492 		s->logs.level = 0;
2493 		stream_del_srv_conn(s);
2494 		s->target = NULL;
2495 		/* re-init store persistence */
2496 		s->store_count = 0;
2497 		s->uniq_id = global.req_count++;
2498 
2499 		s->req.flags |= CF_READ_DONTWAIT; /* one read is usually enough */
2500 
2501 		s->req.flags |= CF_WAKE_ONCE; /* need to be called again if there is some command left in the request */
2502 
2503 		s->req.analysers |= AN_REQ_WAIT_CLI;
2504 		s->res.analysers &= ~AN_RES_WAIT_CLI;
2505 
2506 		/* We must trim any excess data from the response buffer, because we
2507 		 * may have blocked an invalid response from a server that we don't
2508 		 * want to accidentally forward once we disable the analysers, nor do
2509 		 * we want those data to come along with next response. A typical
2510 		 * example of such data would be from a buggy server responding to
2511 		 * a HEAD with some data, or sending more than the advertised
2512 		 * content-length.
2513 		 */
2514 		if (unlikely(ci_data(&s->res)))
2515 			b_set_data(&s->res.buf, co_data(&s->res));
2516 
2517 		/* Now we can realign the response buffer */
2518 		c_realign_if_empty(&s->res);
2519 
2520 		s->req.rto = strm_fe(s)->timeout.client;
2521 		s->req.wto = TICK_ETERNITY;
2522 
2523 		s->res.rto = TICK_ETERNITY;
2524 		s->res.wto = strm_fe(s)->timeout.client;
2525 
2526 		s->req.rex = TICK_ETERNITY;
2527 		s->req.wex = TICK_ETERNITY;
2528 		s->req.analyse_exp = TICK_ETERNITY;
2529 		s->res.rex = TICK_ETERNITY;
2530 		s->res.wex = TICK_ETERNITY;
2531 		s->res.analyse_exp = TICK_ETERNITY;
2532 		s->si[1].hcto = TICK_ETERNITY;
2533 
2534 		/* we're removing the analysers, we MUST re-enable events detection.
2535 		 * We don't enable close on the response channel since it's either
2536 		 * already closed, or in keep-alive with an idle connection handler.
2537 		 */
2538 		channel_auto_read(&s->req);
2539 		channel_auto_close(&s->req);
2540 		channel_auto_read(&s->res);
2541 
2542 
2543 		return 1;
2544 	}
2545 	return 0;
2546 }
2547 
2548 /*
2549  * The mworker functions are used to initialize the CLI in the master process
2550  */
2551 
2552  /*
2553  * Stop the mworker proxy
2554  */
mworker_cli_proxy_stop()2555 void mworker_cli_proxy_stop()
2556 {
2557 	if (mworker_proxy)
2558 		stop_proxy(mworker_proxy);
2559 }
2560 
2561 /*
2562  * Create the mworker CLI proxy
2563  */
mworker_cli_proxy_create()2564 int mworker_cli_proxy_create()
2565 {
2566 	struct mworker_proc *child;
2567 	char *msg = NULL;
2568 	char *errmsg = NULL;
2569 
2570 	mworker_proxy = calloc(1, sizeof(*mworker_proxy));
2571 	if (!mworker_proxy)
2572 		return -1;
2573 
2574 	init_new_proxy(mworker_proxy);
2575 	mworker_proxy->next = proxies_list;
2576 	proxies_list = mworker_proxy;
2577 	mworker_proxy->id = strdup("MASTER");
2578 	mworker_proxy->mode = PR_MODE_CLI;
2579 	mworker_proxy->state = PR_STNEW;
2580 	mworker_proxy->last_change = now.tv_sec;
2581 	mworker_proxy->cap = PR_CAP_LISTEN; /* this is a listen section */
2582 	mworker_proxy->maxconn = 10;                 /* default to 10 concurrent connections */
2583 	mworker_proxy->timeout.client = 0; /* no timeout */
2584 	mworker_proxy->conf.file = strdup("MASTER");
2585 	mworker_proxy->conf.line = 0;
2586 	mworker_proxy->accept = frontend_accept;
2587 	mworker_proxy-> lbprm.algo = BE_LB_ALGO_NONE;
2588 
2589 	/* Does not init the default target the CLI applet, but must be done in
2590 	 * the request parsing code */
2591 	mworker_proxy->default_target = NULL;
2592 
2593 	/* the check_config_validity() will get an ID for the proxy */
2594 	mworker_proxy->uuid = -1;
2595 
2596 	proxy_store_name(mworker_proxy);
2597 
2598 	/* create all servers using the mworker_proc list */
2599 	list_for_each_entry(child, &proc_list, list) {
2600 		struct server *newsrv = NULL;
2601 		struct sockaddr_storage *sk;
2602 		int port1, port2, port;
2603 		struct protocol *proto;
2604 
2605 		/* only the workers support the master CLI */
2606 		if (!(child->options & PROC_O_TYPE_WORKER))
2607 			continue;
2608 
2609 		newsrv = new_server(mworker_proxy);
2610 		if (!newsrv)
2611 			goto error;
2612 
2613 		/* we don't know the new pid yet */
2614 		if (child->pid == -1)
2615 			memprintf(&msg, "cur-%d", child->relative_pid);
2616 		else
2617 			memprintf(&msg, "old-%d", child->pid);
2618 
2619 		newsrv->next = mworker_proxy->srv;
2620 		mworker_proxy->srv = newsrv;
2621 		newsrv->conf.file = strdup(msg);
2622 		newsrv->id = strdup(msg);
2623 		newsrv->conf.line = 0;
2624 
2625 		memprintf(&msg, "sockpair@%d", child->ipc_fd[0]);
2626 		if ((sk = str2sa_range(msg, &port, &port1, &port2, &errmsg, NULL, NULL, 0)) == 0) {
2627 			goto error;
2628 		}
2629 		free(msg);
2630 		msg = NULL;
2631 
2632 		proto = protocol_by_family(sk->ss_family);
2633 		if (!proto || !proto->connect) {
2634 			goto error;
2635 		}
2636 
2637 		/* no port specified */
2638 		newsrv->flags |= SRV_F_MAPPORTS;
2639 		newsrv->addr = *sk;
2640 		/* don't let the server participate to load balancing */
2641 		newsrv->iweight = 0;
2642 		newsrv->uweight = 0;
2643 		srv_lb_commit_status(newsrv);
2644 
2645 		child->srv = newsrv;
2646 	}
2647 	return 0;
2648 
2649 error:
2650 	ha_alert("%s\n", errmsg);
2651 
2652 	list_for_each_entry(child, &proc_list, list) {
2653 		free((char *)child->srv->conf.file); /* cast because of const char *  */
2654 		free(child->srv->id);
2655 		free(child->srv);
2656 		child->srv = NULL;
2657 	}
2658 	free(mworker_proxy->id);
2659 	free(mworker_proxy->conf.file);
2660 	free(mworker_proxy);
2661 	mworker_proxy = NULL;
2662 	free(errmsg);
2663 	free(msg);
2664 
2665 	return -1;
2666 }
2667 
2668 /*
2669  * Create a new listener for the master CLI proxy
2670  */
mworker_cli_proxy_new_listener(char * line)2671 int mworker_cli_proxy_new_listener(char *line)
2672 {
2673 	struct bind_conf *bind_conf;
2674 	struct listener *l;
2675 	char *err = NULL;
2676 	char *args[MAX_LINE_ARGS + 1];
2677 	int arg;
2678 	int cur_arg;
2679 
2680 	arg = 1;
2681 	args[0] = line;
2682 
2683 	/* args is a bind configuration with spaces replaced by commas */
2684 	while (*line && arg < MAX_LINE_ARGS) {
2685 
2686 		if (*line == ',') {
2687 			*line++ = '\0';
2688 			while (*line == ',')
2689 				line++;
2690 			args[arg++] = line;
2691 		}
2692 		line++;
2693 	}
2694 
2695 	args[arg] = "\0";
2696 
2697 	bind_conf = bind_conf_alloc(mworker_proxy, "master-socket", 0, "", xprt_get(XPRT_RAW));
2698 	if (!bind_conf)
2699 		goto err;
2700 
2701 	bind_conf->level &= ~ACCESS_LVL_MASK;
2702 	bind_conf->level |= ACCESS_LVL_ADMIN;
2703 
2704 	if (!str2listener(args[0], mworker_proxy, bind_conf, "master-socket", 0, &err)) {
2705 		ha_alert("Cannot create the listener of the master CLI\n");
2706 		goto err;
2707 	}
2708 
2709 	cur_arg = 1;
2710 
2711 	while (*args[cur_arg]) {
2712 			static int bind_dumped;
2713 			struct bind_kw *kw;
2714 
2715 			kw = bind_find_kw(args[cur_arg]);
2716 			if (kw) {
2717 				if (!kw->parse) {
2718 					memprintf(&err, "'%s %s' : '%s' option is not implemented in this version (check build options).",
2719 						  args[0], args[1], args[cur_arg]);
2720 					goto err;
2721 				}
2722 
2723 				if (kw->parse(args, cur_arg, global.stats_fe, bind_conf, &err) != 0) {
2724 					if (err)
2725 						memprintf(&err, "'%s %s' : '%s'", args[0], args[1], err);
2726 					else
2727 						memprintf(&err, "'%s %s' : error encountered while processing '%s'",
2728 						          args[0], args[1], args[cur_arg]);
2729 					goto err;
2730 				}
2731 
2732 				cur_arg += 1 + kw->skip;
2733 				continue;
2734 			}
2735 
2736 			if (!bind_dumped) {
2737 				bind_dump_kws(&err);
2738 				indent_msg(&err, 4);
2739 				bind_dumped = 1;
2740 			}
2741 
2742 			memprintf(&err, "'%s %s' : unknown keyword '%s'.%s%s",
2743 			          args[0], args[1], args[cur_arg],
2744 			          err ? " Registered keywords :" : "", err ? err : "");
2745 			goto err;
2746 	}
2747 
2748 
2749 	list_for_each_entry(l, &bind_conf->listeners, by_bind) {
2750 		l->accept = session_accept_fd;
2751 		l->default_target = mworker_proxy->default_target;
2752 		/* don't make the peers subject to global limits and don't close it in the master */
2753 		l->options |= (LI_O_UNLIMITED|LI_O_MWORKER); /* we are keeping this FD in the master */
2754 		l->nice = -64;  /* we want to boost priority for local stats */
2755 		global.maxsock++; /* for the listening socket */
2756 	}
2757 	global.maxsock += mworker_proxy->maxconn;
2758 
2759 	return 0;
2760 
2761 err:
2762 	ha_alert("%s\n", err);
2763 	free(err);
2764 	free(bind_conf);
2765 	return -1;
2766 
2767 }
2768 
2769 /*
2770  * Create a new CLI socket using a socketpair for a worker process
2771  * <mworker_proc> is the process structure, and <proc> is the process number
2772  */
mworker_cli_sockpair_new(struct mworker_proc * mworker_proc,int proc)2773 int mworker_cli_sockpair_new(struct mworker_proc *mworker_proc, int proc)
2774 {
2775 	struct bind_conf *bind_conf;
2776 	struct listener *l;
2777 	char *path = NULL;
2778 	char *err = NULL;
2779 
2780 	/* master pipe to ensure the master is still alive  */
2781 	if (socketpair(AF_UNIX, SOCK_STREAM, 0, mworker_proc->ipc_fd) < 0) {
2782 		ha_alert("Cannot create worker socketpair.\n");
2783 		return -1;
2784 	}
2785 
2786 	/* XXX: we might want to use a separate frontend at some point */
2787 	if (!global.stats_fe) {
2788 		if ((global.stats_fe = alloc_stats_fe("GLOBAL", "master-socket", 0)) == NULL) {
2789 			ha_alert("out of memory trying to allocate the stats frontend");
2790 			goto error;
2791 		}
2792 	}
2793 
2794 	bind_conf = bind_conf_alloc(global.stats_fe, "master-socket", 0, "", xprt_get(XPRT_RAW));
2795 	if (!bind_conf)
2796 		goto error;
2797 
2798 	bind_conf->level &= ~ACCESS_LVL_MASK;
2799 	bind_conf->level |= ACCESS_LVL_ADMIN; /* TODO: need to lower the rights with a CLI keyword*/
2800 
2801 	bind_conf->bind_proc = 1UL << proc;
2802 	global.stats_fe->bind_proc = 0; /* XXX: we should be careful with that, it can be removed by configuration */
2803 
2804 	if (!memprintf(&path, "sockpair@%d", mworker_proc->ipc_fd[1])) {
2805 		ha_alert("Cannot allocate listener.\n");
2806 		goto error;
2807 	}
2808 
2809 	if (!str2listener(path, global.stats_fe, bind_conf, "master-socket", 0, &err)) {
2810 		free(path);
2811 		ha_alert("Cannot create a CLI sockpair listener for process #%d\n", proc);
2812 		goto error;
2813 	}
2814 	free(path);
2815 	path = NULL;
2816 
2817 	list_for_each_entry(l, &bind_conf->listeners, by_bind) {
2818 		l->accept = session_accept_fd;
2819 		l->default_target = global.stats_fe->default_target;
2820 		l->options |= (LI_O_UNLIMITED | LI_O_NOSTOP);
2821 		/* it's a sockpair but we don't want to keep the fd in the master */
2822 		l->options &= ~LI_O_INHERITED;
2823 		l->nice = -64;  /* we want to boost priority for local stats */
2824 		global.maxsock++; /* for the listening socket */
2825 	}
2826 
2827 	return 0;
2828 
2829 error:
2830 	close(mworker_proc->ipc_fd[0]);
2831 	close(mworker_proc->ipc_fd[1]);
2832 	free(err);
2833 
2834 	return -1;
2835 }
2836 
2837 static struct applet cli_applet = {
2838 	.obj_type = OBJ_TYPE_APPLET,
2839 	.name = "<CLI>", /* used for logging */
2840 	.fct = cli_io_handler,
2841 	.release = cli_release_handler,
2842 };
2843 
2844 /* register cli keywords */
2845 static struct cli_kw_list cli_kws = {{ },{
2846 	{ { "help", NULL }, NULL, cli_parse_simple, NULL },
2847 	{ { "prompt", NULL }, NULL, cli_parse_simple, NULL },
2848 	{ { "quit", NULL }, NULL, cli_parse_simple, NULL },
2849 	{ { "set", "maxconn", "global",  NULL }, "set maxconn global : change the per-process maxconn setting", cli_parse_set_maxconn_global, NULL },
2850 	{ { "set", "rate-limit", NULL }, "set rate-limit : change a rate limiting value", cli_parse_set_ratelimit, NULL },
2851 	{ { "set", "severity-output",  NULL }, "set severity-output [none|number|string] : set presence of severity level in feedback information", cli_parse_set_severity_output, NULL, NULL },
2852 	{ { "set", "timeout",  NULL }, "set timeout    : change a timeout setting", cli_parse_set_timeout, NULL, NULL },
2853 	{ { "show", "env",  NULL }, "show env [var] : dump environment variables known to the process", cli_parse_show_env, cli_io_handler_show_env, NULL },
2854 	{ { "show", "cli", "sockets",  NULL }, "show cli sockets : dump list of cli sockets", cli_parse_default, cli_io_handler_show_cli_sock, NULL, NULL, ACCESS_MASTER },
2855 	{ { "show", "cli", "level", NULL },    "show cli level   : display the level of the current CLI session", cli_parse_show_lvl, NULL, NULL, NULL, ACCESS_MASTER},
2856 	{ { "show", "fd", NULL }, "show fd [num] : dump list of file descriptors in use", cli_parse_show_fd, cli_io_handler_show_fd, NULL },
2857 	{ { "show", "activity", NULL }, "show activity : show per-thread activity stats (for support/developers)", cli_parse_default, cli_io_handler_show_activity, NULL },
2858 	{ { "operator", NULL },  "operator       : lower the level of the current CLI session to operator", cli_parse_set_lvl, NULL, NULL, NULL, ACCESS_MASTER},
2859 	{ { "user", NULL },      "user           : lower the level of the current CLI session to user", cli_parse_set_lvl, NULL, NULL, NULL, ACCESS_MASTER},
2860 	{ { "_getsocks", NULL }, NULL,  _getsocks, NULL },
2861 	{ { "expert-mode", NULL },  NULL,  cli_parse_expert_mode, NULL }, // not listed
2862 	{{},}
2863 }};
2864 
2865 INITCALL1(STG_REGISTER, cli_register_kw, &cli_kws);
2866 
2867 static struct cfg_kw_list cfg_kws = {ILH, {
2868 	{ CFG_GLOBAL, "stats", stats_parse_global },
2869 	{ 0, NULL, NULL },
2870 }};
2871 
2872 INITCALL1(STG_REGISTER, cfg_register_keywords, &cfg_kws);
2873 
2874 static struct bind_kw_list bind_kws = { "STAT", { }, {
2875 	{ "level",     bind_parse_level,    1 }, /* set the unix socket admin level */
2876 	{ "expose-fd", bind_parse_expose_fd, 1 }, /* set the unix socket expose fd rights */
2877 	{ "severity-output", bind_parse_severity_output, 1 }, /* set the severity output format */
2878 	{ NULL, NULL, 0 },
2879 }};
2880 
2881 INITCALL1(STG_REGISTER, bind_register_keywords, &bind_kws);
2882 
2883 /*
2884  * Local variables:
2885  *  c-indent-level: 8
2886  *  c-basic-offset: 8
2887  * End:
2888  */
2889