diff --git a/include/haproxy/vars.h b/include/haproxy/vars.h index f809c62d5..0647cf346 100644 --- a/include/haproxy/vars.h +++ b/include/haproxy/vars.h @@ -34,11 +34,11 @@ void var_accounting_diff(struct vars *vars, struct session *sess, struct stream unsigned int var_clear(struct var *var); void vars_prune(struct vars *vars, struct session *sess, struct stream *strm); void vars_prune_per_sess(struct vars *vars); -int vars_get_by_name(const char *name, size_t len, struct sample *smp); +int vars_get_by_name(const char *name, size_t len, struct sample *smp, const struct buffer *def); int vars_set_by_name_ifexist(const char *name, size_t len, struct sample *smp); int vars_set_by_name(const char *name, size_t len, struct sample *smp); int vars_unset_by_name_ifexist(const char *name, size_t len, struct sample *smp); -int vars_get_by_desc(const struct var_desc *var_desc, struct sample *smp); +int vars_get_by_desc(const struct var_desc *var_desc, struct sample *smp, const struct buffer *def); int vars_check_arg(struct arg *arg, char **err); #endif diff --git a/src/hlua.c b/src/hlua.c index 039ebeca7..72d232491 100644 --- a/src/hlua.c +++ b/src/hlua.c @@ -4382,7 +4382,7 @@ __LJMP static int hlua_applet_tcp_get_var(lua_State *L) s = luactx->htxn.s; smp_set_owner(&smp, s->be, s->sess, s, 0); - if (!vars_get_by_name(name, len, &smp)) { + if (!vars_get_by_name(name, len, &smp, NULL)) { lua_pushnil(L); return 1; } @@ -4869,7 +4869,7 @@ __LJMP static int hlua_applet_http_get_var(lua_State *L) s = luactx->htxn.s; smp_set_owner(&smp, s->be, s->sess, s, 0); - if (!vars_get_by_name(name, len, &smp)) { + if (!vars_get_by_name(name, len, &smp, NULL)) { lua_pushnil(L); return 1; } @@ -6966,7 +6966,7 @@ __LJMP static int hlua_get_var(lua_State *L) name = MAY_LJMP(luaL_checklstring(L, 2, &len)); smp_set_owner(&smp, htxn->p, htxn->s->sess, htxn->s, htxn->dir & SMP_OPT_DIR); - if (!vars_get_by_name(name, len, &smp)) { + if (!vars_get_by_name(name, len, &smp, NULL)) { lua_pushnil(L); return 1; } diff --git a/src/sample.c b/src/sample.c index a0727d236..e4bb3182a 100644 --- a/src/sample.c +++ b/src/sample.c @@ -1747,7 +1747,7 @@ static inline int sample_conv_var2smp_str(const struct arg *arg, struct sample * smp->flags = SMP_F_CONST; return 1; case ARGT_VAR: - if (!vars_get_by_desc(&arg->data.var, smp)) + if (!vars_get_by_desc(&arg->data.var, smp, NULL)) return 0; if (!sample_casts[smp->data.type][SMP_T_STR]) return 0; @@ -2990,7 +2990,7 @@ static inline int sample_conv_var2smp(const struct arg *arg, struct sample *smp) smp->data.u.sint = arg->data.sint; return 1; case ARGT_VAR: - if (!vars_get_by_desc(&arg->data.var, smp)) + if (!vars_get_by_desc(&arg->data.var, smp, NULL)) return 0; if (!sample_casts[smp->data.type][SMP_T_SINT]) return 0; @@ -3317,7 +3317,7 @@ static int sample_conv_concat(const struct arg *arg_p, struct sample *smp, void * into a string. */ smp_set_owner(&tmp, smp->px, smp->sess, smp->strm, smp->opt); - if (arg_p[1].type == ARGT_VAR && vars_get_by_desc(&arg_p[1].data.var, &tmp) && + if (arg_p[1].type == ARGT_VAR && vars_get_by_desc(&arg_p[1].data.var, &tmp, NULL) && (sample_casts[tmp.data.type][SMP_T_STR] == c_none || sample_casts[tmp.data.type][SMP_T_STR](&tmp))) { @@ -3377,7 +3377,7 @@ static int sample_conv_strcmp(const struct arg *arg_p, struct sample *smp, void smp_set_owner(&tmp, smp->px, smp->sess, smp->strm, smp->opt); if (arg_p[0].type != ARGT_VAR) return 0; - if (!vars_get_by_desc(&arg_p[0].data.var, &tmp)) + if (!vars_get_by_desc(&arg_p[0].data.var, &tmp, NULL)) return 0; if (!sample_casts[tmp.data.type][SMP_T_STR](&tmp)) return 0; @@ -3415,7 +3415,7 @@ static int sample_conv_secure_memcmp(const struct arg *arg_p, struct sample *smp smp_set_owner(&tmp, smp->px, smp->sess, smp->strm, smp->opt); if (arg_p[0].type != ARGT_VAR) return 0; - if (!vars_get_by_desc(&arg_p[0].data.var, &tmp)) + if (!vars_get_by_desc(&arg_p[0].data.var, &tmp, NULL)) return 0; if (!sample_casts[tmp.data.type][SMP_T_BIN](&tmp)) return 0; diff --git a/src/vars.c b/src/vars.c index 236466b21..df421f71e 100644 --- a/src/vars.c +++ b/src/vars.c @@ -340,7 +340,7 @@ static int smp_fetch_var(const struct arg *args, struct sample *smp, const char { const struct var_desc *var_desc = &args[0].data.var; - return vars_get_by_desc(var_desc, smp); + return vars_get_by_desc(var_desc, smp, NULL); } /* This function search in the a variable with the same @@ -574,10 +574,11 @@ int vars_unset_by_name_ifexist(const char *name, size_t len, struct sample *smp) * release the variables lock ASAP (so a pre-allocated chunk is obtained * via get_trash_shunk()). The variables' lock is used for reads. * - * The function returns 0 if the variable was not found, otherwise 1 - * with the sample filled. + * The function returns 0 if the variable was not found and no default + * value was provided in , otherwise 1 with the sample filled. + * Default values are always returned as strings. */ -static int var_to_smp(struct vars *vars, const char *name, struct sample *smp) +static int var_to_smp(struct vars *vars, const char *name, struct sample *smp, const struct buffer *def) { struct var *var; @@ -585,12 +586,19 @@ static int var_to_smp(struct vars *vars, const char *name, struct sample *smp) HA_RWLOCK_RDLOCK(VARS_LOCK, &vars->rwlock); var = var_get(vars, name); if (!var) { - HA_RWLOCK_RDUNLOCK(VARS_LOCK, &vars->rwlock); - return 0; + if (!def) { + HA_RWLOCK_RDUNLOCK(VARS_LOCK, &vars->rwlock); + return 0; + } + + /* not found but we have a default value */ + smp->data.type = SMP_T_STR; + smp->data.u.str = *def; } + else + smp->data = var->data; /* Copy sample. */ - smp->data = var->data; smp_dup(smp); HA_RWLOCK_RDUNLOCK(VARS_LOCK, &vars->rwlock); @@ -603,9 +611,13 @@ static int var_to_smp(struct vars *vars, const char *name, struct sample *smp) * and it therefore uses a pre-allocated trash chunk as returned by * get_trash_chunk(). * + * If the variable is not valid in this scope, 0 is always returned. + * If the variable is valid but not found, either the default value + * is returned if not NULL, or zero is returned. + * * Returns 1 if the sample is filled, otherwise it returns 0. */ -int vars_get_by_name(const char *name, size_t len, struct sample *smp) +int vars_get_by_name(const char *name, size_t len, struct sample *smp, const struct buffer *def) { struct vars *vars; enum vars_scope scope; @@ -620,7 +632,8 @@ int vars_get_by_name(const char *name, size_t len, struct sample *smp) if (!vars || vars->scope != scope) return 0; - return var_to_smp(vars, name, smp); + + return var_to_smp(vars, name, smp, def); } /* This function fills a sample with the content of the variable described @@ -630,9 +643,13 @@ int vars_get_by_name(const char *name, size_t len, struct sample *smp) * and it therefore uses a pre-allocated trash chunk as returned by * get_trash_chunk(). * + * If the variable is not valid in this scope, 0 is always returned. + * If the variable is valid but not found, either the default value + * is returned if not NULL, or zero is returned. + * * Returns 1 if the sample is filled, otherwise it returns 0. */ -int vars_get_by_desc(const struct var_desc *var_desc, struct sample *smp) +int vars_get_by_desc(const struct var_desc *var_desc, struct sample *smp, const struct buffer *def) { struct vars *vars; @@ -643,7 +660,7 @@ int vars_get_by_desc(const struct var_desc *var_desc, struct sample *smp) if (!vars || vars->scope != var_desc->scope) return 0; - return var_to_smp(vars, var_desc->name, smp); + return var_to_smp(vars, var_desc->name, smp, def); } /* Always returns ACT_RET_CONT even if an error occurs. */ @@ -739,7 +756,7 @@ static void release_store_rule(struct act_rule *rule) /* This two function checks the variable name and replace the * configuration string name by the global string name. its * the same string, but the global pointer can be easy to - * compare. + * compare. They return non-zero on success, zero on failure. * * The first function checks a sample-fetch and the second * checks a converter. @@ -989,7 +1006,7 @@ static int vars_parse_cli_get_var(char **args, char *payload, struct appctx *app if (!vars || vars->scope != SCOPE_PROC) return 0; - if (!vars_get_by_name(args[2], strlen(args[2]), &smp)) + if (!vars_get_by_name(args[2], strlen(args[2]), &smp, NULL)) return cli_err(appctx, "Variable not found.\n"); /* the sample returned by vars_get_by_name() is allocated into a trash