MINOR: cli/applet: Move appctx fields only used by the CLI in a private context

There are several fields in the appctx structure only used by the CLI. To
make things cleaner, all these fields are now placed in a dedicated context
inside the appctx structure. The final goal is to move it in the service
context and add an API for cli commands to get a command coontext inside the
cli context.
This commit is contained in:
Christopher Faulet 2025-04-24 11:17:07 +02:00
parent 03dc54d802
commit b734d7c156
12 changed files with 112 additions and 105 deletions

View File

@ -109,22 +109,29 @@ struct appctx {
struct buffer outbuf; struct buffer outbuf;
size_t to_forward; size_t to_forward;
struct buffer *chunk; /* used to store unfinished commands */
struct applet *applet; /* applet this context refers to */ struct applet *applet; /* applet this context refers to */
struct session *sess; /* session for frontend applets (NULL for backend applets) */ struct session *sess; /* session for frontend applets (NULL for backend applets) */
struct sedesc *sedesc; /* stream endpoint descriptor the applet is attached to */ struct sedesc *sedesc; /* stream endpoint descriptor the applet is attached to */
struct act_rule *rule; /* rule associated with the applet. */
struct {
struct buffer *cmdline; /* used to store unfinished commands */
int severity_output; /* used within the cli_io_handler to format severity output of informational feedback */
int level; /* the level of CLI which can be lowered dynamically */
char payload_pat[8]; /* Payload pattern */
char *payload; /* Pointer on the payload. NULL if no payload */
uint32_t anon_key; /* the key to anonymise with the hash in cli */
/* XXX 4 unused bytes here */
int (*io_handler)(struct appctx *appctx); /* used within the cli_io_handler when st0 = CLI_ST_CALLBACK */ int (*io_handler)(struct appctx *appctx); /* used within the cli_io_handler when st0 = CLI_ST_CALLBACK */
void (*io_release)(struct appctx *appctx); /* used within the cli_io_handler when st0 = CLI_ST_CALLBACK, void (*io_release)(struct appctx *appctx); /* used within the cli_io_handler when st0 = CLI_ST_CALLBACK,
if the command is terminated or the session released */ if the command is terminated or the session released */
int cli_severity_output; /* used within the cli_io_handler to format severity output of informational feedback */ } cli_ctx; /* context dedicated to the CLI applet */
int cli_level; /* the level of CLI which can be lowered dynamically */
char cli_payload_pat[8]; /* Payload pattern */ struct act_rule *rule; /* rule associated with the applet. */
char *cli_payload; /* Pointer on the payload. NULL if no payload */
uint32_t cli_anon_key; /* the key to anonymise with the hash in cli */
struct buffer_wait buffer_wait; /* position in the list of objects waiting for a buffer */ struct buffer_wait buffer_wait; /* position in the list of objects waiting for a buffer */
struct task *t; /* task associated to the applet */ struct task *t; /* task associated to the applet */
struct freq_ctr call_rate; /* appctx call rate */ struct freq_ctr call_rate; /* appctx call rate */
/* XXX 4 unused bytes here */
struct mt_list wait_entry; /* entry in a list of waiters for an event (e.g. ring events) */ struct mt_list wait_entry; /* entry in a list of waiters for an event (e.g. ring events) */
/* The pointer seen by application code is appctx->svcctx. In 2.7 the /* The pointer seen by application code is appctx->svcctx. In 2.7 the

View File

@ -24,7 +24,7 @@
#include <haproxy/applet-t.h> #include <haproxy/applet-t.h>
/* Access level for a stats socket (appctx->cli_level) */ /* Access level for a stats socket (appctx->cli_ctx.level) */
#define ACCESS_LVL_NONE 0x0000 #define ACCESS_LVL_NONE 0x0000
#define ACCESS_LVL_USER 0x0001 #define ACCESS_LVL_USER 0x0001
#define ACCESS_LVL_OPER 0x0002 #define ACCESS_LVL_OPER 0x0002

View File

@ -71,7 +71,7 @@
#define HA_ANON_PATH(key, str) hash_anon(key, str, "PATH(", ")") #define HA_ANON_PATH(key, str) hash_anon(key, str, "PATH(", ")")
/* use only in a function that contains an appctx (key comes from appctx). */ /* use only in a function that contains an appctx (key comes from appctx). */
#define HA_ANON_CLI(str) hash_anon(appctx->cli_anon_key, str, "", "") #define HA_ANON_CLI(str) hash_anon(appctx->cli_ctx.anon_key, str, "", "")
/* /*

154
src/cli.c
View File

@ -152,10 +152,10 @@ static char *cli_gen_usage_msg(struct appctx *appctx, char * const *args)
/* first, let's measure the longest match */ /* first, let's measure the longest match */
list_for_each_entry(kw_list, &cli_keywords.list, list) { list_for_each_entry(kw_list, &cli_keywords.list, list) {
for (kw = &kw_list->kw[0]; kw->str_kw[0]; kw++) { for (kw = &kw_list->kw[0]; kw->str_kw[0]; kw++) {
if (kw->level & ~appctx->cli_level & (ACCESS_MASTER_ONLY|ACCESS_EXPERT|ACCESS_EXPERIMENTAL)) if (kw->level & ~appctx->cli_ctx.level & (ACCESS_MASTER_ONLY|ACCESS_EXPERT|ACCESS_EXPERIMENTAL))
continue; continue;
if (!(appctx->cli_level & ACCESS_MCLI_DEBUG) && if (!(appctx->cli_ctx.level & ACCESS_MCLI_DEBUG) &&
(appctx->cli_level & ~kw->level & (ACCESS_MASTER_ONLY|ACCESS_MASTER)) == (appctx->cli_ctx.level & ~kw->level & (ACCESS_MASTER_ONLY|ACCESS_MASTER)) ==
(ACCESS_MASTER_ONLY|ACCESS_MASTER)) (ACCESS_MASTER_ONLY|ACCESS_MASTER))
continue; continue;
@ -200,10 +200,10 @@ static char *cli_gen_usage_msg(struct appctx *appctx, char * const *args)
if (args && args[length] && *args[length]) { if (args && args[length] && *args[length]) {
list_for_each_entry(kw_list, &cli_keywords.list, list) { list_for_each_entry(kw_list, &cli_keywords.list, list) {
for (kw = &kw_list->kw[0]; kw->str_kw[0]; kw++) { for (kw = &kw_list->kw[0]; kw->str_kw[0]; kw++) {
if (kw->level & ~appctx->cli_level & (ACCESS_MASTER_ONLY|ACCESS_EXPERT|ACCESS_EXPERIMENTAL)) if (kw->level & ~appctx->cli_ctx.level & (ACCESS_MASTER_ONLY|ACCESS_EXPERT|ACCESS_EXPERIMENTAL))
continue; continue;
if (!(appctx->cli_level & ACCESS_MCLI_DEBUG) && if (!(appctx->cli_ctx.level & ACCESS_MCLI_DEBUG) &&
((appctx->cli_level & ~kw->level & (ACCESS_MASTER_ONLY|ACCESS_MASTER)) == ((appctx->cli_ctx.level & ~kw->level & (ACCESS_MASTER_ONLY|ACCESS_MASTER)) ==
(ACCESS_MASTER_ONLY|ACCESS_MASTER))) (ACCESS_MASTER_ONLY|ACCESS_MASTER)))
continue; continue;
@ -287,15 +287,15 @@ static char *cli_gen_usage_msg(struct appctx *appctx, char * const *args)
/* in a worker or normal process, don't display master-only commands /* in a worker or normal process, don't display master-only commands
* nor expert/experimental mode commands if not in this mode. * nor expert/experimental mode commands if not in this mode.
*/ */
if (kw->level & ~appctx->cli_level & (ACCESS_MASTER_ONLY|ACCESS_EXPERT|ACCESS_EXPERIMENTAL)) if (kw->level & ~appctx->cli_ctx.level & (ACCESS_MASTER_ONLY|ACCESS_EXPERT|ACCESS_EXPERIMENTAL))
continue; continue;
/* in master, if the CLI don't have the /* in master, if the CLI don't have the
* ACCESS_MCLI_DEBUG don't display commands that have * ACCESS_MCLI_DEBUG don't display commands that have
* neither the master bit nor the master-only bit. * neither the master bit nor the master-only bit.
*/ */
if (!(appctx->cli_level & ACCESS_MCLI_DEBUG) && if (!(appctx->cli_ctx.level & ACCESS_MCLI_DEBUG) &&
((appctx->cli_level & ~kw->level & (ACCESS_MASTER_ONLY|ACCESS_MASTER)) == ((appctx->cli_ctx.level & ~kw->level & (ACCESS_MASTER_ONLY|ACCESS_MASTER)) ==
(ACCESS_MASTER_ONLY|ACCESS_MASTER))) (ACCESS_MASTER_ONLY|ACCESS_MASTER)))
continue; continue;
@ -701,7 +701,7 @@ REGISTER_CONFIG_POSTPARSER("cli", cli_socket_setenv);
int cli_has_level(struct appctx *appctx, int level) int cli_has_level(struct appctx *appctx, int level)
{ {
if ((appctx->cli_level & ACCESS_LVL_MASK) < level) { if ((appctx->cli_ctx.level & ACCESS_LVL_MASK) < level) {
cli_err(appctx, cli_permission_denied_msg); cli_err(appctx, cli_permission_denied_msg);
return 0; return 0;
} }
@ -720,8 +720,8 @@ int pcli_has_level(struct stream *s, int level)
/* Returns severity_output for the current session if set, or default for the socket */ /* Returns severity_output for the current session if set, or default for the socket */
static int cli_get_severity_output(struct appctx *appctx) static int cli_get_severity_output(struct appctx *appctx)
{ {
if (appctx->cli_severity_output) if (appctx->cli_ctx.severity_output)
return appctx->cli_severity_output; return appctx->cli_ctx.severity_output;
return strm_li(appctx_strm(appctx))->bind_conf->severity_output; return strm_li(appctx_strm(appctx))->bind_conf->severity_output;
} }
@ -741,7 +741,7 @@ static int cli_process_cmdline(struct appctx *appctx)
int i = 0, ret = 0; int i = 0, ret = 0;
struct cli_kw *kw; struct cli_kw *kw;
orig = p = b_head(appctx->chunk); orig = p = b_head(appctx->cli_ctx.cmdline);
end = p + strlen(p); end = p + strlen(p);
/* /*
@ -790,11 +790,11 @@ static int cli_process_cmdline(struct appctx *appctx)
/* Pass the payload to the last command. It happens when the end of the /* Pass the payload to the last command. It happens when the end of the
* commend is just before the payload pattern. * commend is just before the payload pattern.
*/ */
if (appctx->cli_payload && appctx->cli_payload == end + strlen(appctx->cli_payload_pat) + 3) { if (appctx->cli_ctx.payload && appctx->cli_ctx.payload == end + strlen(appctx->cli_ctx.payload_pat) + 3) {
appctx->st1 |= APPCTX_CLI_ST1_LASTCMD; appctx->st1 |= APPCTX_CLI_ST1_LASTCMD;
payload = appctx->cli_payload; payload = appctx->cli_ctx.payload;
} }
if (end+1 == b_tail(appctx->chunk)) if (end+1 == b_tail(appctx->cli_ctx.cmdline))
appctx->st1 |= APPCTX_CLI_ST1_LASTCMD; appctx->st1 |= APPCTX_CLI_ST1_LASTCMD;
/* throw an error if too many args are provided */ /* throw an error if too many args are provided */
@ -815,21 +815,21 @@ static int cli_process_cmdline(struct appctx *appctx)
kw = cli_find_kw(args); kw = cli_find_kw(args);
if (!kw || if (!kw ||
(kw->level & ~appctx->cli_level & ACCESS_MASTER_ONLY) || (kw->level & ~appctx->cli_ctx.level & ACCESS_MASTER_ONLY) ||
(!(appctx->cli_level & ACCESS_MCLI_DEBUG) && (!(appctx->cli_ctx.level & ACCESS_MCLI_DEBUG) &&
(appctx->cli_level & ~kw->level & (ACCESS_MASTER_ONLY|ACCESS_MASTER)) == (ACCESS_MASTER_ONLY|ACCESS_MASTER))) { (appctx->cli_ctx.level & ~kw->level & (ACCESS_MASTER_ONLY|ACCESS_MASTER)) == (ACCESS_MASTER_ONLY|ACCESS_MASTER))) {
/* keyword not found in this mode */ /* keyword not found in this mode */
cli_gen_usage_msg(appctx, args); cli_gen_usage_msg(appctx, args);
goto end; goto end;
} }
/* don't handle expert mode commands if not in this mode. */ /* don't handle expert mode commands if not in this mode. */
if (kw->level & ~appctx->cli_level & ACCESS_EXPERT) { if (kw->level & ~appctx->cli_ctx.level & ACCESS_EXPERT) {
cli_err(appctx, "This command is restricted to expert mode only.\n"); cli_err(appctx, "This command is restricted to expert mode only.\n");
goto end; goto end;
} }
if (kw->level & ~appctx->cli_level & ACCESS_EXPERIMENTAL) { if (kw->level & ~appctx->cli_ctx.level & ACCESS_EXPERIMENTAL) {
cli_err(appctx, "This command is restricted to experimental mode only.\n"); cli_err(appctx, "This command is restricted to experimental mode only.\n");
goto end; goto end;
} }
@ -839,8 +839,8 @@ static int cli_process_cmdline(struct appctx *appctx)
else if (kw->level == ACCESS_EXPERIMENTAL) else if (kw->level == ACCESS_EXPERIMENTAL)
mark_tainted(TAINTED_CLI_EXPERIMENTAL_MODE); mark_tainted(TAINTED_CLI_EXPERIMENTAL_MODE);
appctx->io_handler = kw->io_handler; appctx->cli_ctx.io_handler = kw->io_handler;
appctx->io_release = kw->io_release; appctx->cli_ctx.io_release = kw->io_release;
if (kw->parse && kw->parse(args, payload, appctx, kw->private) != 0) { if (kw->parse && kw->parse(args, payload, appctx, kw->private) != 0) {
ret = 1; ret = 1;
@ -848,7 +848,7 @@ static int cli_process_cmdline(struct appctx *appctx)
} }
/* kw->parse could set its own io_handler or io_release handler */ /* kw->parse could set its own io_handler or io_release handler */
if (!appctx->io_handler) { if (!appctx->cli_ctx.io_handler) {
ret = 1; ret = 1;
goto fail; goto fail;
} }
@ -858,12 +858,12 @@ static int cli_process_cmdline(struct appctx *appctx)
goto end; goto end;
fail: fail:
appctx->io_handler = NULL; appctx->cli_ctx.io_handler = NULL;
appctx->io_release = NULL; appctx->cli_ctx.io_release = NULL;
end: end:
/* Skip the command */ /* Skip the command */
b_del(appctx->chunk, end - orig + 1); b_del(appctx->cli_ctx.cmdline, end - orig + 1);
return ret; return ret;
} }
@ -915,12 +915,12 @@ int cli_init(struct appctx *appctx)
struct stconn *sc = appctx_sc(appctx); struct stconn *sc = appctx_sc(appctx);
struct bind_conf *bind_conf = strm_li(__sc_strm(sc))->bind_conf; struct bind_conf *bind_conf = strm_li(__sc_strm(sc))->bind_conf;
appctx->cli_severity_output = bind_conf->severity_output; appctx->cli_ctx.severity_output = bind_conf->severity_output;
applet_reset_svcctx(appctx); applet_reset_svcctx(appctx);
appctx->st0 = CLI_ST_PARSE_CMDLINE; appctx->st0 = CLI_ST_PARSE_CMDLINE;
appctx->cli_level = bind_conf->level; appctx->cli_ctx.level = bind_conf->level;
appctx->cli_payload = NULL; appctx->cli_ctx.payload = NULL;
appctx->chunk = NULL; appctx->cli_ctx.cmdline = NULL;
/* Wakeup the applet ASAP. */ /* Wakeup the applet ASAP. */
applet_need_more_data(appctx); applet_need_more_data(appctx);
@ -938,9 +938,9 @@ int cli_parse_cmdline(struct appctx *appctx)
goto end; goto end;
/* Allocate a chunk to process the command line */ /* Allocate a chunk to process the command line */
if (!appctx->chunk) { if (!appctx->cli_ctx.cmdline) {
appctx->chunk = alloc_trash_chunk(); appctx->cli_ctx.cmdline = alloc_trash_chunk();
if (!appctx->chunk) { if (!appctx->cli_ctx.cmdline) {
cli_err(appctx, "Failed to alloc a buffer to process the command line.\n"); cli_err(appctx, "Failed to alloc a buffer to process the command line.\n");
applet_set_error(appctx); applet_set_error(appctx);
b_reset(&appctx->inbuf); b_reset(&appctx->inbuf);
@ -956,14 +956,14 @@ int cli_parse_cmdline(struct appctx *appctx)
* Note we reserve one byte at the end to insert a trailing nul * Note we reserve one byte at the end to insert a trailing nul
* byte. * byte.
*/ */
str = b_tail(appctx->chunk); str = b_tail(appctx->cli_ctx.cmdline);
if (!(appctx->st1 & APPCTX_CLI_ST1_PAYLOAD)) if (!(appctx->st1 & APPCTX_CLI_ST1_PAYLOAD))
len = b_getdelim(&appctx->inbuf, 0, b_data(&appctx->inbuf), str, b_room(appctx->chunk), "\n;", '\\'); len = b_getdelim(&appctx->inbuf, 0, b_data(&appctx->inbuf), str, b_room(appctx->cli_ctx.cmdline), "\n;", '\\');
else else
len = b_getline(&appctx->inbuf, 0, b_data(&appctx->inbuf), str, b_room(appctx->chunk) - 1); len = b_getline(&appctx->inbuf, 0, b_data(&appctx->inbuf), str, b_room(appctx->cli_ctx.cmdline) - 1);
if (!len) { if (!len) {
if (!b_room(appctx->chunk) || (b_data(&appctx->inbuf) > b_room(appctx->chunk) - 1)) { if (!b_room(appctx->cli_ctx.cmdline) || (b_data(&appctx->inbuf) > b_room(appctx->cli_ctx.cmdline) - 1)) {
cli_err(appctx, "The command line is too big for the buffer size. Please change tune.bufsize in the configuration to use a bigger command.\n"); cli_err(appctx, "The command line is too big for the buffer size. Please change tune.bufsize in the configuration to use a bigger command.\n");
applet_set_error(appctx); applet_set_error(appctx);
b_reset(&appctx->inbuf); b_reset(&appctx->inbuf);
@ -972,7 +972,7 @@ int cli_parse_cmdline(struct appctx *appctx)
} }
b_del(&appctx->inbuf, len); b_del(&appctx->inbuf, len);
b_add(appctx->chunk, len); b_add(appctx->cli_ctx.cmdline, len);
if (!(appctx->st1 & APPCTX_CLI_ST1_PAYLOAD)) { if (!(appctx->st1 & APPCTX_CLI_ST1_PAYLOAD)) {
char *last_arg; char *last_arg;
@ -1017,10 +1017,10 @@ int cli_parse_cmdline(struct appctx *appctx)
/* A customized pattern can't be more than 7 characters /* A customized pattern can't be more than 7 characters
* if it's more, don't make it a payload * if it's more, don't make it a payload
*/ */
if (pat_len < sizeof(appctx->cli_payload_pat)) { if (pat_len < sizeof(appctx->cli_ctx.payload_pat)) {
/* copy the customized pattern, don't store the << */ /* copy the customized pattern, don't store the << */
strncpy(appctx->cli_payload_pat, last_arg + strlen(PAYLOAD_PATTERN), sizeof(appctx->cli_payload_pat)-1); strncpy(appctx->cli_ctx.payload_pat, last_arg + strlen(PAYLOAD_PATTERN), sizeof(appctx->cli_ctx.payload_pat)-1);
appctx->cli_payload_pat[sizeof(appctx->cli_payload_pat)-1] = '\0'; appctx->cli_ctx.payload_pat[sizeof(appctx->cli_ctx.payload_pat)-1] = '\0';
/* The last command finishes before the payload pattern. /* The last command finishes before the payload pattern.
* Dont' strip trailing spaces to be sure to detect when * Dont' strip trailing spaces to be sure to detect when
@ -1029,7 +1029,7 @@ int cli_parse_cmdline(struct appctx *appctx)
*last_arg = '\0'; *last_arg = '\0';
/* The payload will start on the next character in the buffer */ /* The payload will start on the next character in the buffer */
appctx->cli_payload = b_tail(appctx->chunk); appctx->cli_ctx.payload = b_tail(appctx->cli_ctx.cmdline);
appctx->st1 |= APPCTX_CLI_ST1_PAYLOAD; appctx->st1 |= APPCTX_CLI_ST1_PAYLOAD;
} }
} }
@ -1044,11 +1044,11 @@ int cli_parse_cmdline(struct appctx *appctx)
/* look for a pattern at the end of the payload /* look for a pattern at the end of the payload
* (take care to exclue last character because it is a \n) * (take care to exclue last character because it is a \n)
*/ */
if (len-1 == strlen(appctx->cli_payload_pat)) { if (len-1 == strlen(appctx->cli_ctx.payload_pat)) {
if (strncmp(str, appctx->cli_payload_pat, len-1) == 0) { if (strncmp(str, appctx->cli_ctx.payload_pat, len-1) == 0) {
/* end of payload was reached, rewind before the previous \n and replace it by a \0 */ /* end of payload was reached, rewind before the previous \n and replace it by a \0 */
b_sub(appctx->chunk, strlen(appctx->cli_payload_pat) + 2); b_sub(appctx->cli_ctx.cmdline, strlen(appctx->cli_ctx.payload_pat) + 2);
*b_tail(appctx->chunk) = '\0'; *b_tail(appctx->cli_ctx.cmdline) = '\0';
appctx->st1 &= ~APPCTX_CLI_ST1_PAYLOAD; appctx->st1 &= ~APPCTX_CLI_ST1_PAYLOAD;
} }
} }
@ -1178,13 +1178,13 @@ void cli_io_handler(struct appctx *appctx)
break; break;
case CLI_ST_CALLBACK: /* use custom pointer */ case CLI_ST_CALLBACK: /* use custom pointer */
if (appctx->io_handler) if (appctx->cli_ctx.io_handler)
if (appctx->io_handler(appctx)) { if (appctx->cli_ctx.io_handler(appctx)) {
appctx->t->expire = TICK_ETERNITY; appctx->t->expire = TICK_ETERNITY;
appctx->st0 = CLI_ST_PROMPT; appctx->st0 = CLI_ST_PROMPT;
if (appctx->io_release) { if (appctx->cli_ctx.io_release) {
appctx->io_release(appctx); appctx->cli_ctx.io_release(appctx);
appctx->io_release = NULL; appctx->cli_ctx.io_release = NULL;
/* some release handlers might have /* some release handlers might have
* pending output to print. * pending output to print.
*/ */
@ -1208,7 +1208,7 @@ void cli_io_handler(struct appctx *appctx)
* to emphasize that more data can still be sent */ * to emphasize that more data can still be sent */
prompt = "+ "; prompt = "+ ";
} }
else if (b_data(appctx->chunk) && !(appctx->st1 & APPCTX_CLI_ST1_LASTCMD)) { else if (b_data(appctx->cli_ctx.cmdline) && !(appctx->st1 & APPCTX_CLI_ST1_LASTCMD)) {
/* we are executing pipelined commands, don't display the prompt */ /* we are executing pipelined commands, don't display the prompt */
prompt = "\n"; prompt = "\n";
} }
@ -1246,9 +1246,9 @@ void cli_io_handler(struct appctx *appctx)
/* switch state back to PARSE_CMDLINE to read next requests in interactove mode, otherwise close */ /* switch state back to PARSE_CMDLINE to read next requests in interactove mode, otherwise close */
if (appctx->st1 & APPCTX_CLI_ST1_LASTCMD) { if (appctx->st1 & APPCTX_CLI_ST1_LASTCMD) {
applet_reset_svcctx(appctx); applet_reset_svcctx(appctx);
free_trash_chunk(appctx->chunk); free_trash_chunk(appctx->cli_ctx.cmdline);
appctx->cli_payload = NULL; appctx->cli_ctx.payload = NULL;
appctx->chunk = NULL; appctx->cli_ctx.cmdline = NULL;
appctx->st1 &= ~APPCTX_CLI_ST1_LASTCMD; appctx->st1 &= ~APPCTX_CLI_ST1_LASTCMD;
if (appctx->st1 & APPCTX_CLI_ST1_PROMPT) { if (appctx->st1 & APPCTX_CLI_ST1_PROMPT) {
appctx->st0 = CLI_ST_PARSE_CMDLINE; appctx->st0 = CLI_ST_PARSE_CMDLINE;
@ -1290,9 +1290,9 @@ void cli_io_handler(struct appctx *appctx)
*/ */
static void cli_release_handler(struct appctx *appctx) static void cli_release_handler(struct appctx *appctx)
{ {
if (appctx->io_release) { if (appctx->cli_ctx.io_release) {
appctx->io_release(appctx); appctx->cli_ctx.io_release(appctx);
appctx->io_release = NULL; appctx->cli_ctx.io_release = NULL;
} }
else if (appctx->st0 == CLI_ST_PRINT_DYN || appctx->st0 == CLI_ST_PRINT_DYNERR) { else if (appctx->st0 == CLI_ST_PRINT_DYN || appctx->st0 == CLI_ST_PRINT_DYNERR) {
struct cli_print_ctx *ctx = applet_reserve_svcctx(appctx, sizeof(*ctx)); struct cli_print_ctx *ctx = applet_reserve_svcctx(appctx, sizeof(*ctx));
@ -1818,7 +1818,7 @@ static int cli_parse_set_severity_output(char **args, char *payload, struct appc
if (strcmp(args[3], "-") == 0) if (strcmp(args[3], "-") == 0)
appctx->st1 |= APPCTX_CLI_ST1_NOLF; appctx->st1 |= APPCTX_CLI_ST1_NOLF;
if (*args[2] && set_severity_output(&appctx->cli_severity_output, args[2])) if (*args[2] && set_severity_output(&appctx->cli_ctx.severity_output, args[2]))
return 0; return 0;
return cli_err(appctx, "one of 'none', 'number', 'string' is a required argument\n"); return cli_err(appctx, "one of 'none', 'number', 'string' is a required argument\n");
@ -1828,11 +1828,11 @@ static int cli_parse_set_severity_output(char **args, char *payload, struct appc
/* show the level of the current CLI session */ /* show the level of the current CLI session */
static int cli_parse_show_lvl(char **args, char *payload, struct appctx *appctx, void *private) static int cli_parse_show_lvl(char **args, char *payload, struct appctx *appctx, void *private)
{ {
if ((appctx->cli_level & ACCESS_LVL_MASK) == ACCESS_LVL_ADMIN) if ((appctx->cli_ctx.level & ACCESS_LVL_MASK) == ACCESS_LVL_ADMIN)
return cli_msg(appctx, LOG_INFO, "admin\n"); return cli_msg(appctx, LOG_INFO, "admin\n");
else if ((appctx->cli_level & ACCESS_LVL_MASK) == ACCESS_LVL_OPER) else if ((appctx->cli_ctx.level & ACCESS_LVL_MASK) == ACCESS_LVL_OPER)
return cli_msg(appctx, LOG_INFO, "operator\n"); return cli_msg(appctx, LOG_INFO, "operator\n");
else if ((appctx->cli_level & ACCESS_LVL_MASK) == ACCESS_LVL_USER) else if ((appctx->cli_ctx.level & ACCESS_LVL_MASK) == ACCESS_LVL_USER)
return cli_msg(appctx, LOG_INFO, "user\n"); return cli_msg(appctx, LOG_INFO, "user\n");
else else
return cli_msg(appctx, LOG_INFO, "unknown\n"); return cli_msg(appctx, LOG_INFO, "unknown\n");
@ -1849,17 +1849,17 @@ static int cli_parse_set_lvl(char **args, char *payload, struct appctx *appctx,
if (!cli_has_level(appctx, ACCESS_LVL_OPER)) { if (!cli_has_level(appctx, ACCESS_LVL_OPER)) {
return 1; return 1;
} }
appctx->cli_level &= ~ACCESS_LVL_MASK; appctx->cli_ctx.level &= ~ACCESS_LVL_MASK;
appctx->cli_level |= ACCESS_LVL_OPER; appctx->cli_ctx.level |= ACCESS_LVL_OPER;
} else if (strcmp(args[0], "user") == 0) { } else if (strcmp(args[0], "user") == 0) {
if (!cli_has_level(appctx, ACCESS_LVL_USER)) { if (!cli_has_level(appctx, ACCESS_LVL_USER)) {
return 1; return 1;
} }
appctx->cli_level &= ~ACCESS_LVL_MASK; appctx->cli_ctx.level &= ~ACCESS_LVL_MASK;
appctx->cli_level |= ACCESS_LVL_USER; appctx->cli_ctx.level |= ACCESS_LVL_USER;
} }
appctx->cli_level &= ~(ACCESS_EXPERT|ACCESS_EXPERIMENTAL); appctx->cli_ctx.level &= ~(ACCESS_EXPERT|ACCESS_EXPERIMENTAL);
return 1; return 1;
} }
@ -1896,13 +1896,13 @@ static int cli_parse_expert_experimental_mode(char **args, char *payload, struct
if (!*args[1]) { if (!*args[1]) {
memprintf(&output, "%s is %s\n", level_str, memprintf(&output, "%s is %s\n", level_str,
(appctx->cli_level & level) ? "ON" : "OFF"); (appctx->cli_ctx.level & level) ? "ON" : "OFF");
return cli_dynmsg(appctx, LOG_INFO, output); return cli_dynmsg(appctx, LOG_INFO, output);
} }
appctx->cli_level &= ~level; appctx->cli_ctx.level &= ~level;
if (strcmp(args[1], "on") == 0) if (strcmp(args[1], "on") == 0)
appctx->cli_level |= level; appctx->cli_ctx.level |= level;
return 1; return 1;
} }
@ -1931,14 +1931,14 @@ static int cli_parse_set_anon(char **args, char *payload, struct appctx *appctx,
key = atoll(args[3]); key = atoll(args[3]);
if (key < 1 || key > UINT_MAX) if (key < 1 || key > UINT_MAX)
return cli_err(appctx, "Value out of range (1 to 4294967295 expected).\n"); return cli_err(appctx, "Value out of range (1 to 4294967295 expected).\n");
appctx->cli_anon_key = key; appctx->cli_ctx.anon_key = key;
} }
else { else {
tmp = HA_ATOMIC_LOAD(&global.anon_key); tmp = HA_ATOMIC_LOAD(&global.anon_key);
if (tmp != 0) if (tmp != 0)
appctx->cli_anon_key = tmp; appctx->cli_ctx.anon_key = tmp;
else else
appctx->cli_anon_key = ha_random32(); appctx->cli_ctx.anon_key = ha_random32();
} }
} }
else if (strcmp(args[2], "off") == 0) { else if (strcmp(args[2], "off") == 0) {
@ -1947,7 +1947,7 @@ static int cli_parse_set_anon(char **args, char *payload, struct appctx *appctx,
return cli_err(appctx, "Key can't be added while disabling anonymized mode\n"); return cli_err(appctx, "Key can't be added while disabling anonymized mode\n");
} }
else { else {
appctx->cli_anon_key = 0; appctx->cli_ctx.anon_key = 0;
} }
} }
else { else {
@ -1982,14 +1982,14 @@ static int cli_parse_show_anon(char **args, char *payload, struct appctx *appctx
{ {
char *msg = NULL; char *msg = NULL;
char *anon_mode = NULL; char *anon_mode = NULL;
uint32_t c_key = appctx->cli_anon_key; uint32_t c_key = appctx->cli_ctx.anon_key;
if (!c_key) if (!c_key)
anon_mode = "Anonymized mode disabled"; anon_mode = "Anonymized mode disabled";
else else
anon_mode = "Anonymized mode enabled"; anon_mode = "Anonymized mode enabled";
if ( !((appctx->cli_level & ACCESS_LVL_MASK) < ACCESS_LVL_OPER) && c_key != 0) { if ( !((appctx->cli_ctx.level & ACCESS_LVL_MASK) < ACCESS_LVL_OPER) && c_key != 0) {
cli_dynmsg(appctx, LOG_INFO, memprintf(&msg, "%s\nKey : %u\n", anon_mode, c_key)); cli_dynmsg(appctx, LOG_INFO, memprintf(&msg, "%s\nKey : %u\n", anon_mode, c_key));
} }
else { else {

View File

@ -715,7 +715,7 @@ static int cli_parse_show_map(char **args, char *payload, struct appctx *appctx,
/* no parameter: display all map available */ /* no parameter: display all map available */
if (!*args[2]) { if (!*args[2]) {
appctx->io_handler = cli_io_handler_pats_list; appctx->cli_ctx.io_handler = cli_io_handler_pats_list;
return 0; return 0;
} }
@ -745,8 +745,8 @@ static int cli_parse_show_map(char **args, char *payload, struct appctx *appctx,
ctx->curr_gen = ctx->ref->curr_gen; ctx->curr_gen = ctx->ref->curr_gen;
LIST_INIT(&ctx->bref.users); LIST_INIT(&ctx->bref.users);
appctx->io_handler = cli_io_handler_pat_list; appctx->cli_ctx.io_handler = cli_io_handler_pat_list;
appctx->io_release = cli_release_show_map; appctx->cli_ctx.io_release = cli_release_show_map;
return 0; return 0;
} }

View File

@ -1015,7 +1015,7 @@ static int cli_io_handler_show_loadstatus(struct appctx *appctx)
return 0; return 0;
if (startup_logs) { if (startup_logs) {
appctx->io_handler = NULL; appctx->cli_ctx.io_handler = NULL;
ring_attach_cli(startup_logs, appctx, 0); ring_attach_cli(startup_logs, appctx, 0);
return 0; return 0;
} }

View File

@ -2925,7 +2925,7 @@ static int dump_servers_state(struct appctx *appctx)
"\n", "\n",
px->uuid, HA_ANON_CLI(px->id), px->uuid, HA_ANON_CLI(px->id),
srv->puid, HA_ANON_CLI(srv->id), srv->puid, HA_ANON_CLI(srv->id),
hash_ipanon(appctx->cli_anon_key, srv_addr, 0), hash_ipanon(appctx->cli_ctx.anon_key, srv_addr, 0),
srv->cur_state, srv->cur_admin, srv->uweight, srv->iweight, srv->cur_state, srv->cur_admin, srv->uweight, srv->iweight,
(long int)srv_time_since_last_change, (long int)srv_time_since_last_change,
srv->check.status, srv->check.result, srv->check.health, srv->check.status, srv->check.result, srv->check.health,
@ -2941,7 +2941,7 @@ static int dump_servers_state(struct appctx *appctx)
chunk_printf(&trash, chunk_printf(&trash,
"%s/%s %d/%d %s %u - %u %u %u %u %u %u %d %u", "%s/%s %d/%d %s %u - %u %u %u %u %u %u %d %u",
HA_ANON_CLI(px->id), HA_ANON_CLI(srv->id), HA_ANON_CLI(px->id), HA_ANON_CLI(srv->id),
px->uuid, srv->puid, hash_ipanon(appctx->cli_anon_key, srv_addr, 0), px->uuid, srv->puid, hash_ipanon(appctx->cli_ctx.anon_key, srv_addr, 0),
srv->svc_port, srv->pool_purge_delay, srv->svc_port, srv->pool_purge_delay,
srv->curr_used_conns, srv->max_used_conns, srv->est_need_conns, srv->curr_used_conns, srv->max_used_conns, srv->est_need_conns,
srv->curr_idle_nb, srv->curr_safe_nb, (int)srv->max_idle_conns, srv->curr_idle_conns); srv->curr_idle_nb, srv->curr_safe_nb, (int)srv->max_idle_conns, srv->curr_idle_conns);

View File

@ -526,10 +526,10 @@ int ring_attach_cli(struct ring *ring, struct appctx *appctx, uint flags)
"Sorry, too many watchers (" TOSTR(RING_MAX_READERS) ") on this ring buffer. " "Sorry, too many watchers (" TOSTR(RING_MAX_READERS) ") on this ring buffer. "
"What could it have so interesting to attract so many watchers ?"); "What could it have so interesting to attract so many watchers ?");
if (!appctx->io_handler) if (!appctx->cli_ctx.io_handler)
appctx->io_handler = cli_io_handler_show_ring; appctx->cli_ctx.io_handler = cli_io_handler_show_ring;
if (!appctx->io_release) if (!appctx->cli_ctx.io_release)
appctx->io_release = cli_io_release_show_ring; appctx->cli_ctx.io_release = cli_io_release_show_ring;
memset(ctx, 0, sizeof(*ctx)); memset(ctx, 0, sizeof(*ctx));
ctx->ring = ring; ctx->ring = ring;

View File

@ -2375,10 +2375,10 @@ static int cli_parse_show_cert(char **args, char *payload, struct appctx *appctx
/* use the IO handler that shows details */ /* use the IO handler that shows details */
if (show_ocsp_detail) { if (show_ocsp_detail) {
ctx->transaction = from_transaction; ctx->transaction = from_transaction;
appctx->io_handler = cli_io_handler_show_cert_ocsp_detail; appctx->cli_ctx.io_handler = cli_io_handler_show_cert_ocsp_detail;
} }
else else
appctx->io_handler = cli_io_handler_show_cert_detail; appctx->cli_ctx.io_handler = cli_io_handler_show_cert_detail;
} }
return 0; return 0;
@ -3769,7 +3769,7 @@ static int cli_parse_show_cafile(char **args, char *payload, struct appctx *appc
ctx->cur_cafile_entry = cafile_entry; ctx->cur_cafile_entry = cafile_entry;
/* use the IO handler that shows details */ /* use the IO handler that shows details */
appctx->io_handler = cli_io_handler_show_cafile_detail; appctx->cli_ctx.io_handler = cli_io_handler_show_cafile_detail;
} }
return 0; return 0;
@ -4447,7 +4447,7 @@ static int cli_parse_show_crlfile(char **args, char *payload, struct appctx *app
ctx->cafile_entry = cafile_entry; ctx->cafile_entry = cafile_entry;
ctx->index = index; ctx->index = index;
/* use the IO handler that shows details */ /* use the IO handler that shows details */
appctx->io_handler = cli_io_handler_show_crlfile_detail; appctx->cli_ctx.io_handler = cli_io_handler_show_crlfile_detail;
} }
return 0; return 0;

View File

@ -1156,7 +1156,7 @@ static int cli_parse_dump_crtlist(char **args, char *payload, struct appctx *app
return cli_err(appctx, "didn't find the specified filename\n"); return cli_err(appctx, "didn't find the specified filename\n");
ctx->crtlist_node = lnode; ctx->crtlist_node = lnode;
appctx->io_handler = cli_io_handler_dump_crtlist_entries; appctx->cli_ctx.io_handler = cli_io_handler_dump_crtlist_entries;
} }
ctx->mode = mode; ctx->mode = mode;

View File

@ -1653,7 +1653,7 @@ static int cli_parse_show_ocspresponse(char **args, char *payload, struct appctx
HA_SPIN_UNLOCK(OCSP_LOCK, &ocsp_tree_lock); HA_SPIN_UNLOCK(OCSP_LOCK, &ocsp_tree_lock);
ctx->ocsp = ocsp; ctx->ocsp = ocsp;
appctx->io_handler = cli_io_handler_show_ocspresponse_detail; appctx->cli_ctx.io_handler = cli_io_handler_show_ocspresponse_detail;
} }
return 0; return 0;

View File

@ -3750,7 +3750,7 @@ static int stats_dump_full_strm_to_buffer(struct appctx *appctx, struct stream *
__fallthrough; __fallthrough;
case 1: case 1:
__strm_dump_to_buffer(&trash, ctx, strm, "", appctx->cli_anon_key); __strm_dump_to_buffer(&trash, ctx, strm, "", appctx->cli_ctx.anon_key);
if (applet_putchk(appctx, &trash) == -1) if (applet_putchk(appctx, &trash) == -1)
goto full; goto full;