1 /***
2  * Copyright 2020 HAProxy Technologies
3  *
4  * This file is part of the HAProxy OpenTracing filter.
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
19  */
20 #include "include.h"
21 
22 
23 /***
24  * NAME
25  *   flt_ot_cli_set_msg -
26  *
27  * ARGUMENTS
28  *   appctx    -
29  *   err       -
30  *   msg       -
31  *   cli_state -
32  *
33  * DESCRIPTION
34  *   -
35  *
36  * RETURN VALUE
37  *   This function does not return a value.
38  */
cmn_cli_set_msg(struct appctx * appctx,char * err,char * msg,int cli_state)39 static void cmn_cli_set_msg(struct appctx *appctx, char *err, char *msg, int cli_state)
40 {
41 	FLT_OT_FUNC("%p, %p, %p, %d", appctx, err, msg, cli_state);
42 
43 	if ((appctx == NULL) || ((err == NULL) && (msg == NULL)))
44 		FLT_OT_RETURN();
45 
46 	appctx->ctx.cli.err = (err == NULL) ? msg : err;
47 	appctx->st0         = (appctx->ctx.cli.err == NULL) ? CLI_ST_PROMPT : cli_state;
48 
49 	FLT_OT_DBG(1, "err(%d): \"%s\"", appctx->st0, appctx->ctx.cli.err);
50 
51 	FLT_OT_RETURN();
52 }
53 
54 
55 #ifdef DEBUG_OT
56 
57 /***
58  * NAME
59  *   flt_ot_cli_parse_debug -
60  *
61  * ARGUMENTS
62  *   args    -
63  *   payload -
64  *   appctx  -
65  *   private -
66  *
67  * DESCRIPTION
68  *   -
69  *
70  * RETURN VALUE
71  *   -
72  */
flt_ot_cli_parse_debug(char ** args,char * payload,struct appctx * appctx,void * private)73 static int flt_ot_cli_parse_debug(char **args, char *payload, struct appctx *appctx, void *private)
74 {
75 	char    *err = NULL, *msg = NULL;
76 	uint8_t  value;
77 	int      retval = 0;
78 
79 	FLT_OT_FUNC("%p, \"%s\", %p, %p", args, payload, appctx, private);
80 
81 	FLT_OT_ARGS_DUMP();
82 
83 	if (FLT_OT_ARG_ISVALID(2)) {
84 		value = flt_ot_strtoll(args[2], 0, 255, &err);
85 		if (err == NULL) {
86 			_HA_ATOMIC_STORE(&(flt_ot_debug.level), value);
87 
88 			(void)memprintf(&msg, FLT_OT_CLI_CMD " : debug level set to %hhu", value);
89 		} else {
90 			retval = 1;
91 		}
92 	} else {
93 		value = _HA_ATOMIC_LOAD(&(flt_ot_debug.level));
94 
95 		(void)memprintf(&msg, FLT_OT_CLI_CMD " : current debug level is %hhu", value);
96 	}
97 
98 	cmn_cli_set_msg(appctx, err, msg, CLI_ST_PRINT_FREE);
99 
100 	FLT_OT_RETURN(retval);
101 }
102 
103 #endif /* DEBUG_OT */
104 
105 
106 /***
107  * NAME
108  *   flt_ot_cli_parse_disabled -
109  *
110  * ARGUMENTS
111  *   args    -
112  *   payload -
113  *   appctx  -
114  *   private -
115  *
116  * DESCRIPTION
117  *   -
118  *
119  * RETURN VALUE
120  *   -
121  */
flt_ot_cli_parse_disabled(char ** args,char * payload,struct appctx * appctx,void * private)122 static int flt_ot_cli_parse_disabled(char **args, char *payload, struct appctx *appctx, void *private)
123 {
124 	char *msg = NULL;
125 	bool  value = (uintptr_t)private;
126 	int   retval = 0;
127 
128 	FLT_OT_FUNC("%p, \"%s\", %p, %p", args, payload, appctx, private);
129 
130 	FLT_OT_ARGS_DUMP();
131 
132 	FLT_OT_PROXIES_LIST_START() {
133 		_HA_ATOMIC_STORE(&(conf->tracer->flag_disabled), value);
134 
135 		(void)memprintf(&msg, "%s%s" FLT_OT_CLI_CMD " : filter %sabled", FLT_OT_CLI_MSG_CAT(msg), value ? "dis" : "en");
136 	} FLT_OT_PROXIES_LIST_END();
137 
138 	cmn_cli_set_msg(appctx, NULL, msg, CLI_ST_PRINT_FREE);
139 
140 	FLT_OT_RETURN(retval);
141 }
142 
143 
144 /***
145  * NAME
146  *   flt_ot_cli_parse_option -
147  *
148  * ARGUMENTS
149  *   args    -
150  *   payload -
151  *   appctx  -
152  *   private -
153  *
154  * DESCRIPTION
155  *   -
156  *
157  * RETURN VALUE
158  *   -
159  */
flt_ot_cli_parse_option(char ** args,char * payload,struct appctx * appctx,void * private)160 static int flt_ot_cli_parse_option(char **args, char *payload, struct appctx *appctx, void *private)
161 {
162 	char *msg = NULL;
163 	bool  value = (uintptr_t)private;
164 	int   retval = 0;
165 
166 	FLT_OT_FUNC("%p, \"%s\", %p, %p", args, payload, appctx, private);
167 
168 	FLT_OT_ARGS_DUMP();
169 
170 	FLT_OT_PROXIES_LIST_START() {
171 		_HA_ATOMIC_STORE(&(conf->tracer->flag_harderr), value);
172 
173 		(void)memprintf(&msg, "%s%s" FLT_OT_CLI_CMD " : filter set %s-errors", FLT_OT_CLI_MSG_CAT(msg), value ? "hard" : "soft");
174 	} FLT_OT_PROXIES_LIST_END();
175 
176 	cmn_cli_set_msg(appctx, NULL, msg, CLI_ST_PRINT_FREE);
177 
178 	FLT_OT_RETURN(retval);
179 }
180 
181 
182 /***
183  * NAME
184  *   flt_ot_cli_parse_logging -
185  *
186  * ARGUMENTS
187  *   args    -
188  *   payload -
189  *   appctx  -
190  *   private -
191  *
192  * DESCRIPTION
193  *   -
194  *
195  * RETURN VALUE
196  *   -
197  */
flt_ot_cli_parse_logging(char ** args,char * payload,struct appctx * appctx,void * private)198 static int flt_ot_cli_parse_logging(char **args, char *payload, struct appctx *appctx, void *private)
199 {
200 	char    *err = NULL, *msg = NULL;
201 	uint8_t  value;
202 	int      retval = 0;
203 
204 	FLT_OT_FUNC("%p, \"%s\", %p, %p", args, payload, appctx, private);
205 
206 	FLT_OT_ARGS_DUMP();
207 
208 	if (FLT_OT_ARG_ISVALID(2)) {
209 		if (strcasecmp(args[2], FLT_OT_CLI_LOGGING_OFF) == 0) {
210 			value = FLT_OT_LOGGING_OFF;
211 		}
212 		else if (strcasecmp(args[2], FLT_OT_CLI_LOGGING_ON) == 0) {
213 			value = FLT_OT_LOGGING_ON;
214 		}
215 		else if (strcasecmp(args[2], FLT_OT_CLI_LOGGING_NOLOGNORM) == 0) {
216 			value = FLT_OT_LOGGING_ON | FLT_OT_LOGGING_NOLOGNORM;
217 		}
218 		else {
219 			(void)memprintf(&err, "'%s' : invalid value, use <" FLT_OT_CLI_LOGGING_OFF " | " FLT_OT_CLI_LOGGING_ON " | " FLT_OT_CLI_LOGGING_NOLOGNORM ">", args[2]);
220 
221 			retval = 1;
222 		}
223 
224 		if (retval == 0) {
225 			FLT_OT_PROXIES_LIST_START() {
226 				_HA_ATOMIC_STORE(&(conf->tracer->logging), value);
227 
228 				(void)memprintf(&msg, "%s%s" FLT_OT_CLI_CMD " : logging is %s", FLT_OT_CLI_MSG_CAT(msg), FLT_OT_CLI_LOGGING_STATE(value));
229 			} FLT_OT_PROXIES_LIST_END();
230 		}
231 	} else {
232 		FLT_OT_PROXIES_LIST_START() {
233 			value = _HA_ATOMIC_LOAD(&(conf->tracer->logging));
234 
235 			(void)memprintf(&msg, "%s%s" FLT_OT_CLI_CMD " : logging is currently %s", FLT_OT_CLI_MSG_CAT(msg), FLT_OT_CLI_LOGGING_STATE(value));
236 		} FLT_OT_PROXIES_LIST_END();
237 	}
238 
239 	cmn_cli_set_msg(appctx, err, msg, CLI_ST_PRINT_FREE);
240 
241 	FLT_OT_RETURN(retval);
242 }
243 
244 
245 /***
246  * NAME
247  *   flt_ot_cli_parse_rate -
248  *
249  * ARGUMENTS
250  *   args    -
251  *   payload -
252  *   appctx  -
253  *   private -
254  *
255  * DESCRIPTION
256  *   -
257  *
258  * RETURN VALUE
259  *   -
260  */
flt_ot_cli_parse_rate(char ** args,char * payload,struct appctx * appctx,void * private)261 static int flt_ot_cli_parse_rate(char **args, char *payload, struct appctx *appctx, void *private)
262 {
263 	char     *err = NULL, *msg = NULL;
264 	uint32_t  value;
265 	int       retval = 0;
266 
267 	FLT_OT_FUNC("%p, \"%s\", %p, %p", args, payload, appctx, private);
268 
269 	FLT_OT_ARGS_DUMP();
270 
271 	if (FLT_OT_ARG_ISVALID(2)) {
272 		value = FLT_OT_FLOAT_U32(flt_ot_strtod(args[2], 0.0, FLT_OT_RATE_LIMIT_MAX, &err), FLT_OT_RATE_LIMIT_MAX);
273 		if (err == NULL) {
274 			FLT_OT_PROXIES_LIST_START() {
275 				_HA_ATOMIC_STORE(&(conf->tracer->rate_limit), value);
276 
277 				(void)memprintf(&msg, "%s%s" FLT_OT_CLI_CMD " : rate limit set to %.2f", FLT_OT_CLI_MSG_CAT(msg), FLT_OT_U32_FLOAT(value, FLT_OT_RATE_LIMIT_MAX));
278 			} FLT_OT_PROXIES_LIST_END();
279 		} else {
280 			retval = 1;
281 		}
282 	} else {
283 		FLT_OT_PROXIES_LIST_START() {
284 			value = _HA_ATOMIC_LOAD(&(conf->tracer->rate_limit));
285 
286 			(void)memprintf(&msg, "%s%s" FLT_OT_CLI_CMD " : current rate limit is %.2f", FLT_OT_CLI_MSG_CAT(msg), FLT_OT_U32_FLOAT(value, FLT_OT_RATE_LIMIT_MAX));
287 		} FLT_OT_PROXIES_LIST_END();
288 	}
289 
290 	cmn_cli_set_msg(appctx, err, msg, CLI_ST_PRINT_FREE);
291 
292 	FLT_OT_RETURN(retval);
293 }
294 
295 
296 /***
297  * NAME
298  *   flt_ot_cli_parse_status -
299  *
300  * ARGUMENTS
301  *   args    -
302  *   payload -
303  *   appctx  -
304  *   private -
305  *
306  * DESCRIPTION
307  *   -
308  *
309  * RETURN VALUE
310  *   -
311  */
flt_ot_cli_parse_status(char ** args,char * payload,struct appctx * appctx,void * private)312 static int flt_ot_cli_parse_status(char **args, char *payload, struct appctx *appctx, void *private)
313 {
314 	const char *nl = "";
315 	char       *msg = NULL;
316 	int         retval = 0;
317 
318 	FLT_OT_FUNC("%p, \"%s\", %p, %p", args, payload, appctx, private);
319 
320 	FLT_OT_ARGS_DUMP();
321 	flt_ot_filters_dump();
322 
323 	(void)memprintf(&msg, " " FLT_OT_OPT_NAME " filter status\n" FLT_OT_STR_DASH_78);
324 #ifdef DEBUG_OT
325 	(void)memprintf(&msg, "%s\n   debug level: 0x%02hhx\n", msg, flt_ot_debug.level);
326 #endif
327 
328 	FLT_OT_PROXIES_LIST_START() {
329 		(void)memprintf(&msg, "%s\n%s   filter %s\n", msg, nl, conf->id);
330 		(void)memprintf(&msg, "%s     configuration: %s\n", msg, conf->cfg_file);
331 		(void)memprintf(&msg, "%s     disable count: %" PRIu64 " %" PRIu64 "\n\n", msg, conf->cnt.disabled[0], conf->cnt.disabled[1]);
332 		(void)memprintf(&msg, "%s     tracer %s\n", msg, conf->tracer->id);
333 		(void)memprintf(&msg, "%s       configuration: %s\n", msg, conf->tracer->config);
334 		(void)memprintf(&msg, "%s       plugin:        %s\n", msg, conf->tracer->plugin);
335 		(void)memprintf(&msg, "%s       rate limit:    %.2f %%\n", msg, FLT_OT_U32_FLOAT(conf->tracer->rate_limit, FLT_OT_RATE_LIMIT_MAX));
336 		(void)memprintf(&msg, "%s       hard errors:   %s\n", msg, FLT_OT_STR_FLAG_YN(conf->tracer->flag_harderr));
337 		(void)memprintf(&msg, "%s       disabled:      %s\n", msg, FLT_OT_STR_FLAG_YN(conf->tracer->flag_disabled));
338 		(void)memprintf(&msg, "%s       logging:       %s\n", msg, FLT_OT_CLI_LOGGING_STATE(conf->tracer->logging));
339 		(void)memprintf(&msg, "%s       analyzers:     %08x", msg, conf->tracer->analyzers);
340 
341 		nl = "\n";
342 	} FLT_OT_PROXIES_LIST_END();
343 
344 	cmn_cli_set_msg(appctx, NULL, msg, CLI_ST_PRINT_FREE);
345 
346 	FLT_OT_RETURN(retval);
347 }
348 
349 
350 static struct cli_kw_list cli_kws = { { }, {
351 #ifdef DEBUG_OT
352 	{ { FLT_OT_CLI_CMD, "debug", NULL }, FLT_OT_CLI_CMD " debug [level]   : set the OT filter debug level (default: get current debug level)", flt_ot_cli_parse_debug, NULL, NULL, NULL, 0 },
353 #endif
354 	{ { FLT_OT_CLI_CMD, "disable", NULL }, FLT_OT_CLI_CMD " disable         : disable the OT filter", flt_ot_cli_parse_disabled, NULL, NULL, (void *)1, 0 },
355 	{ { FLT_OT_CLI_CMD, "enable", NULL }, FLT_OT_CLI_CMD " enable          : enable the OT filter", flt_ot_cli_parse_disabled, NULL, NULL, (void *)0, 0 },
356 	{ { FLT_OT_CLI_CMD, "soft-errors", NULL }, FLT_OT_CLI_CMD " soft-errors     : turning off hard-errors mode", flt_ot_cli_parse_option, NULL, NULL, (void *)0, 0 },
357 	{ { FLT_OT_CLI_CMD, "hard-errors", NULL }, FLT_OT_CLI_CMD " hard-errors     : enabling hard-errors mode", flt_ot_cli_parse_option, NULL, NULL, (void *)1, 0 },
358 	{ { FLT_OT_CLI_CMD, "logging",  NULL }, FLT_OT_CLI_CMD " logging [state] : set logging state (default: get current logging state)", flt_ot_cli_parse_logging, NULL, NULL, NULL, 0 },
359 	{ { FLT_OT_CLI_CMD, "rate", NULL }, FLT_OT_CLI_CMD " rate [value]    : set the rate limit (default: get current rate value)", flt_ot_cli_parse_rate, NULL, NULL, NULL, 0 },
360 	{ { FLT_OT_CLI_CMD, "status", NULL }, FLT_OT_CLI_CMD " status          : show the OT filter status", flt_ot_cli_parse_status, NULL, NULL, NULL, 0 },
361 	{ /* END */ }
362 }};
363 
364 
365 /***
366  * NAME
367  *   flt_ot_cli_init -
368  *
369  * ARGUMENTS
370  *   This function takes no arguments.
371  *
372  * DESCRIPTION
373  *   -
374  *
375  * RETURN VALUE
376  *   This function does not return a value.
377  */
flt_ot_cli_init(void)378 void flt_ot_cli_init(void)
379 {
380 	FLT_OT_FUNC("");
381 
382 	/* Register CLI keywords. */
383 	cli_register_kw(&cli_kws);
384 
385 	FLT_OT_RETURN();
386 }
387 
388 /*
389  * Local variables:
390  *  c-indent-level: 8
391  *  c-basic-offset: 8
392  * End:
393  *
394  * vi: noexpandtab shiftwidth=8 tabstop=8
395  */
396