unlang_thread_instantiate(thread_ctx);
- if (!xlat_register(NULL, "test", xlat_test, NULL)) {
+ if (!xlat_register(NULL, "test", xlat_test, FR_TYPE_NULL, NULL)) {
ERROR("Failed registering xlat");
EXIT_WITH_FAILURE;
}
return;
}
- xlat = xlat_register(NULL, "aka_sim_id_method", aka_sim_xlat_id_method_xlat, NULL);
+ xlat = xlat_register(NULL, "aka_sim_id_method", aka_sim_xlat_id_method_xlat, FR_TYPE_STRING, NULL);
xlat_func_args(xlat, aka_sim_xlat_id_method_xlat_args);
- xlat = xlat_register(NULL, "aka_sim_id_type", aka_sim_xlat_id_type_xlat, NULL);
+ xlat = xlat_register(NULL, "aka_sim_id_type", aka_sim_xlat_id_type_xlat, FR_TYPE_STRING, NULL);
xlat_func_args(xlat, aka_sim_xlat_id_type_xlat_args);
- xlat = xlat_register(NULL, "3gpp_temporary_id_key_index", aka_sim_id_3gpp_temporary_id_key_index_xlat, NULL);
+ xlat = xlat_register(NULL, "3gpp_temporary_id_key_index", aka_sim_id_3gpp_temporary_id_key_index_xlat, FR_TYPE_UINT8, NULL);
xlat_func_args(xlat, aka_sim_id_3gpp_temporary_id_key_index_xlat_args);
- xlat = xlat_register(NULL, "3gpp_temporary_id_decrypt", aka_sim_3gpp_temporary_id_decrypt_xlat, NULL);
+ xlat = xlat_register(NULL, "3gpp_temporary_id_decrypt", aka_sim_3gpp_temporary_id_decrypt_xlat, FR_TYPE_STRING, NULL);
xlat_func_args(xlat, aka_sim_3gpp_temporary_id_decrypt_xlat_args);
- xlat = xlat_register(NULL, "3gpp_temporary_id_encrypt", aka_sim_3gpp_temporary_id_encrypt_xlat, NULL);
+ xlat = xlat_register(NULL, "3gpp_temporary_id_encrypt", aka_sim_3gpp_temporary_id_encrypt_xlat, FR_TYPE_STRING, NULL);
xlat_func_args(xlat, aka_sim_3gpp_temporary_id_encrypt_xlat_args);
aka_sim_xlat_refs = 1;
}
/*
* Register the %(config:section.subsection) xlat function.
*/
- xlat = xlat_register(NULL, "config", xlat_config, XLAT_FLAG_PURE);
+ xlat = xlat_register(NULL, "config", xlat_config, FR_TYPE_STRING, XLAT_FLAG_PURE);
xlat_func_args(xlat, xlat_config_args);
/*
xlat_t *x;
x = xlat_register(NULL, xlat_foreach_names[i],
- unlang_foreach_xlat, XLAT_FLAG_NEEDS_ASYNC);
+ unlang_foreach_xlat, FR_TYPE_VOID, XLAT_FLAG_NEEDS_ASYNC);
fr_assert(x);
x->uctx = &xlat_foreach_inst[i];
xlat_internal(x);
void unlang_interpret_init_global(void)
{
xlat_t *xlat;
- xlat = xlat_register(NULL, "interpreter", unlang_interpret_xlat, NULL);
+ /*
+ * Should be void, but someone decided not to register multiple xlats
+ * breaking the convention we use everywhere else in the server...
+ */
+ xlat = xlat_register(NULL, "interpreter", unlang_interpret_xlat, FR_TYPE_VOID, NULL);
xlat_func_args(xlat, unlang_interpret_xlat_args);
}
int xlat_resolve(xlat_exp_head_t *head, xlat_res_rules_t const *xr_rules);
xlat_t *xlat_register_module(TALLOC_CTX *ctx, module_inst_ctx_t const *mctx,
- char const *name, xlat_func_t func, xlat_flags_t const *flags);
-xlat_t *xlat_register(TALLOC_CTX *ctx, char const *name, xlat_func_t func, xlat_flags_t const *flags) CC_HINT(nonnull(2));
+ char const *name, xlat_func_t func, fr_type_t return_type, xlat_flags_t const *flags);
+xlat_t *xlat_register(TALLOC_CTX *ctx, char const *name, xlat_func_t func, fr_type_t return_type, xlat_flags_t const *flags) CC_HINT(nonnull(2));
int xlat_func_args(xlat_t *xlat, xlat_arg_parser_t const args[]) CC_HINT(nonnull);
* Will be duplicated and passed to future xlat calls.
* @param[in] name of the xlat.
* @param[in] func to register.
+ * @param[in] return_type what type of output the xlat function will produce.
* @param[in] flags various function flags
* @return
* - A handle for the newly registered xlat function on success.
* - NULL on failure.
*/
xlat_t *xlat_register_module(TALLOC_CTX *ctx, module_inst_ctx_t const *mctx,
- char const *name, xlat_func_t func, xlat_flags_t const *flags)
+ char const *name, xlat_func_t func, fr_type_t return_type, xlat_flags_t const *flags)
{
static const xlat_flags_t default_flags;
xlat_t *c;
*c = (xlat_t){
.name = talloc_typed_strdup(c, name),
.func = func,
+ .return_type = return_type,
.mctx = our_mctx,
.flags = *flags,
.input_type = XLAT_INPUT_UNPROCESSED /* set default - will be overridden if args are registered */
* @param[in] ctx Used to automate deregistration of the xlat fnction.
* @param[in] name of the xlat.
* @param[in] func to register.
+ * @param[in] return_type what type of output the xlat function will produce.
* @param[in] flags various function flags
* @return
* - A handle for the newly registered xlat function on success.
* - NULL on failure.
*/
-xlat_t *xlat_register(TALLOC_CTX *ctx, char const *name, xlat_func_t func, xlat_flags_t const *flags)
+xlat_t *xlat_register(TALLOC_CTX *ctx, char const *name, xlat_func_t func, fr_type_t return_type, xlat_flags_t const *flags)
{
- return xlat_register_module(ctx, NULL, name, func, flags);
+ return xlat_register_module(ctx, NULL, name, func, return_type, flags);
}
#if 0
xlat_flags_t flags = {};
xlat_arg_parser_t const *args = NULL;
+ fr_type_t return_type = FR_TYPE_NULL;
+ bool first = true;
+
xlat_t *xlat;
CONF_ITEM *ci = NULL;
*/
while ((ci = cf_item_next(cs, ci))) {
xlat_redundant_func_t *xrf;
- xlat_t *mod_func = NULL;
char const *mod_func_name;
+ xlat_t *mod_func;
if (!cf_item_is_pair(ci)) continue;
fr_assert(args == mod_func->args);
}
+ /*
+ * Degrade to a void return type if
+ * we have mixed types in a redundant
+ * section.
+ */
+ if (!first) {
+ if (mod_func->return_type != return_type) return_type = FR_TYPE_VOID;
+ } else {
+ return_type = mod_func->return_type;
+ first = false;
+ }
+
MEM(xrf = talloc_zero(xr, xlat_redundant_func_t));
xrf->func = mod_func;
fr_dlist_insert_tail(&xr->funcs, xrf);
return 1;
}
- xlat = xlat_register(NULL, name2, xlat_redundant, &flags);
+ xlat = xlat_register(NULL, name2, xlat_redundant, return_type, &flags);
if (!xlat) {
ERROR("Registering xlat for %s section failed",
fr_table_str_by_value(xlat_redundant_type_table, xr->type, "<INVALID>"));
if (tp_decode) {
snprintf(buffer, sizeof(buffer), "decode.%s", name);
- xlat = xlat_register(NULL, buffer, protocol_decode_xlat, NULL);
+ xlat = xlat_register(NULL, buffer, protocol_decode_xlat, FR_TYPE_UINT32, NULL);
if (!xlat) return -1;
xlat_func_args(xlat, protocol_decode_xlat_args);
/* coverity[suspicious_sizeof] */
if (tp_encode) {
snprintf(buffer, sizeof(buffer), "encode.%s", name);
- xlat = xlat_register(NULL, buffer, protocol_encode_xlat, NULL);
+ xlat = xlat_register(NULL, buffer, protocol_encode_xlat, FR_TYPE_OCTETS, NULL);
if (!xlat) return -1;
xlat_func_args(xlat, protocol_encode_xlat_args);
/* coverity[suspicious_sizeof] */
/*
* These are all "pure" functions.
*/
-#define XLAT_REGISTER_ARGS(_xlat, _func, _args) \
+#define XLAT_REGISTER_ARGS(_xlat, _func, _return_type, _args) \
do { \
- if (!(xlat = xlat_register(NULL, _xlat, _func, XLAT_FLAG_PURE))) return -1; \
+ if (!(xlat = xlat_register(NULL, _xlat, _func, _return_type, XLAT_FLAG_PURE))) return -1; \
xlat_func_args(xlat, _args); \
xlat_internal(xlat); \
} while (0)
- XLAT_REGISTER_ARGS("cast", xlat_func_cast, xlat_func_cast_args);
- XLAT_REGISTER_ARGS("concat", xlat_func_concat, xlat_func_concat_args);
- XLAT_REGISTER_ARGS("explode", xlat_func_explode, xlat_func_explode_args);
- XLAT_REGISTER_ARGS("hmacmd5", xlat_func_hmac_md5, xlat_hmac_args);
- XLAT_REGISTER_ARGS("hmacsha1", xlat_func_hmac_sha1, xlat_hmac_args);
- XLAT_REGISTER_ARGS("integer", xlat_func_integer, xlat_func_integer_args);
- XLAT_REGISTER_ARGS("join", xlat_func_join, xlat_func_join_args);
- XLAT_REGISTER_ARGS("ungroup", xlat_func_ungroup, xlat_func_join_args);
- XLAT_REGISTER_ARGS("length", xlat_func_length, xlat_func_length_args);
- XLAT_REGISTER_ARGS("lpad", xlat_func_lpad, xlat_func_pad_args);
- XLAT_REGISTER_ARGS("rpad", xlat_func_rpad, xlat_func_pad_args);
+ XLAT_REGISTER_ARGS("cast", xlat_func_cast, FR_TYPE_VOID, xlat_func_cast_args);
+ XLAT_REGISTER_ARGS("concat", xlat_func_concat, FR_TYPE_STRING, xlat_func_concat_args);
+ XLAT_REGISTER_ARGS("explode", xlat_func_explode, FR_TYPE_STRING, xlat_func_explode_args);
+ XLAT_REGISTER_ARGS("hmacmd5", xlat_func_hmac_md5, FR_TYPE_OCTETS, xlat_hmac_args);
+ XLAT_REGISTER_ARGS("hmacsha1", xlat_func_hmac_sha1, FR_TYPE_OCTETS, xlat_hmac_args);
+ XLAT_REGISTER_ARGS("integer", xlat_func_integer, FR_TYPE_VOID, xlat_func_integer_args);
+ XLAT_REGISTER_ARGS("join", xlat_func_join, FR_TYPE_VOID, xlat_func_join_args);
+ XLAT_REGISTER_ARGS("ungroup", xlat_func_ungroup, FR_TYPE_VOID, xlat_func_join_args);
+ XLAT_REGISTER_ARGS("length", xlat_func_length, FR_TYPE_SIZE, xlat_func_length_args);
+ XLAT_REGISTER_ARGS("lpad", xlat_func_lpad, FR_TYPE_STRING, xlat_func_pad_args);
+ XLAT_REGISTER_ARGS("rpad", xlat_func_rpad, FR_TYPE_STRING, xlat_func_pad_args);
/*
* The inputs to these functions are variable.
*/
#undef XLAT_REGISTER_ARGS
-#define XLAT_REGISTER_ARGS(_xlat, _func, _args) \
+#define XLAT_REGISTER_ARGS(_xlat, _func, _return_type, _args) \
do { \
- if (!(xlat = xlat_register(NULL, _xlat, _func, NULL))) return -1; \
+ if (!(xlat = xlat_register(NULL, _xlat, _func, _return_type, NULL))) return -1; \
xlat_func_args(xlat, _args); \
xlat_internal(xlat); \
} while (0)
- XLAT_REGISTER_ARGS("debug", xlat_func_debug, xlat_func_debug_args);
- XLAT_REGISTER_ARGS("debug_attr", xlat_func_debug_attr, xlat_func_debug_attr_args);
- XLAT_REGISTER_ARGS("nexttime", xlat_func_next_time, xlat_func_next_time_args);
- XLAT_REGISTER_ARGS("pairs", xlat_func_pairs, xlat_func_pairs_args);
- XLAT_REGISTER_ARGS("subst", xlat_func_subst, xlat_func_subst_args);
- XLAT_REGISTER_ARGS("trigger", trigger_xlat, trigger_xlat_args);
+ XLAT_REGISTER_ARGS("debug", xlat_func_debug, FR_TYPE_INT8, xlat_func_debug_args);
+ XLAT_REGISTER_ARGS("debug_attr", xlat_func_debug_attr, FR_TYPE_NULL, xlat_func_debug_attr_args);
+ XLAT_REGISTER_ARGS("nexttime", xlat_func_next_time, FR_TYPE_UINT64, xlat_func_next_time_args);
+ XLAT_REGISTER_ARGS("pairs", xlat_func_pairs, FR_TYPE_STRING, xlat_func_pairs_args);
+ XLAT_REGISTER_ARGS("subst", xlat_func_subst, FR_TYPE_STRING, xlat_func_subst_args);
+ XLAT_REGISTER_ARGS("trigger", trigger_xlat, FR_TYPE_STRING, trigger_xlat_args);
/*
* Temporary functions for migration.
*/
- XLAT_REGISTER_ARGS("flatten", xlat_func_flatten, xlat_func_debug_attr_args); /* takes an attribute reference */
- XLAT_REGISTER_ARGS("unflatten", xlat_func_unflatten, xlat_func_debug_attr_args); /* takes an attribute reference */
+ XLAT_REGISTER_ARGS("flatten", xlat_func_flatten, FR_TYPE_NULL, xlat_func_debug_attr_args); /* takes an attribute reference */
+ XLAT_REGISTER_ARGS("unflatten", xlat_func_unflatten, FR_TYPE_NULL, xlat_func_debug_attr_args); /* takes an attribute reference */
- xlat = xlat_register(NULL, "untaint", xlat_func_untaint, NULL);
+ xlat = xlat_register(NULL, "untaint", xlat_func_untaint, FR_TYPE_VOID, NULL);
xlat_internal(xlat);
- xlat = xlat_register(NULL, "taint", xlat_func_taint, NULL);
+ xlat = xlat_register(NULL, "taint", xlat_func_taint, FR_TYPE_VOID, NULL);
xlat_internal(xlat);
/*
* All of these functions are pure.
*/
-#define XLAT_REGISTER_MONO(_xlat, _func, _arg) \
+#define XLAT_REGISTER_MONO(_xlat, _func, _return_type, _arg) \
do { \
- if (!(xlat = xlat_register(NULL, _xlat, _func, XLAT_FLAG_PURE))) return -1; \
+ if (!(xlat = xlat_register(NULL, _xlat, _func, _return_type, XLAT_FLAG_PURE))) return -1; \
xlat_func_mono(xlat, &_arg); \
xlat_internal(xlat); \
} while (0)
- XLAT_REGISTER_MONO("base64", xlat_func_base64_encode, xlat_func_base64_encode_arg);
- XLAT_REGISTER_MONO("base64decode", xlat_func_base64_decode, xlat_func_base64_decode_arg);
- XLAT_REGISTER_MONO("bin", xlat_func_bin, xlat_func_bin_arg);
- XLAT_REGISTER_MONO("hex", xlat_func_hex, xlat_func_hex_arg);
- XLAT_REGISTER_MONO("map", xlat_func_map, xlat_func_map_arg);
- XLAT_REGISTER_MONO("md4", xlat_func_md4, xlat_func_md4_arg);
- XLAT_REGISTER_MONO("md5", xlat_func_md5, xlat_func_md5_arg);
- XLAT_REGISTER_MONO("pack", xlat_func_pack, xlat_func_pack_arg);
+ XLAT_REGISTER_MONO("base64", xlat_func_base64_encode, FR_TYPE_STRING, xlat_func_base64_encode_arg);
+ XLAT_REGISTER_MONO("base64decode", xlat_func_base64_decode, FR_TYPE_OCTETS, xlat_func_base64_decode_arg);
+ XLAT_REGISTER_MONO("bin", xlat_func_bin, FR_TYPE_OCTETS, xlat_func_bin_arg);
+ XLAT_REGISTER_MONO("hex", xlat_func_hex, FR_TYPE_STRING, xlat_func_hex_arg);
+ XLAT_REGISTER_MONO("map", xlat_func_map, FR_TYPE_INT8, xlat_func_map_arg);
+ XLAT_REGISTER_MONO("md4", xlat_func_md4, FR_TYPE_OCTETS, xlat_func_md4_arg);
+ XLAT_REGISTER_MONO("md5", xlat_func_md5, FR_TYPE_OCTETS, xlat_func_md5_arg);
+ XLAT_REGISTER_MONO("pack", xlat_func_pack, FR_TYPE_OCTETS, xlat_func_pack_arg);
#if defined(HAVE_REGEX_PCRE) || defined(HAVE_REGEX_PCRE2)
- xlat = xlat_register(NULL, "regex", xlat_func_regex, NULL);
+ xlat = xlat_register(NULL, "regex", xlat_func_regex, FR_TYPE_STRING, NULL);
xlat_internal(xlat);
#endif
- XLAT_REGISTER_MONO("sha1", xlat_func_sha1, xlat_func_sha_arg);
+ XLAT_REGISTER_MONO("sha1", xlat_func_sha1, FR_TYPE_OCTETS, xlat_func_sha_arg);
#ifdef HAVE_OPENSSL_EVP_H
- XLAT_REGISTER_MONO("sha2_224", xlat_func_sha2_224, xlat_func_sha_arg);
- XLAT_REGISTER_MONO("sha2_256", xlat_func_sha2_256, xlat_func_sha_arg);
- XLAT_REGISTER_MONO("sha2_384", xlat_func_sha2_384, xlat_func_sha_arg);
- XLAT_REGISTER_MONO("sha2_512", xlat_func_sha2_512, xlat_func_sha_arg);
+ XLAT_REGISTER_MONO("sha2_224", xlat_func_sha2_224, FR_TYPE_OCTETS, xlat_func_sha_arg);
+ XLAT_REGISTER_MONO("sha2_256", xlat_func_sha2_256, FR_TYPE_OCTETS, xlat_func_sha_arg);
+ XLAT_REGISTER_MONO("sha2_384", xlat_func_sha2_384, FR_TYPE_OCTETS, xlat_func_sha_arg);
+ XLAT_REGISTER_MONO("sha2_512", xlat_func_sha2_512, FR_TYPE_OCTETS, xlat_func_sha_arg);
- XLAT_REGISTER_MONO("blake2s_256", xlat_func_blake2s_256, xlat_func_sha_arg);
- XLAT_REGISTER_MONO("blake2b_512", xlat_func_blake2b_512, xlat_func_sha_arg);
+ XLAT_REGISTER_MONO("blake2s_256", xlat_func_blake2s_256, FR_TYPE_OCTETS, xlat_func_sha_arg);
+ XLAT_REGISTER_MONO("blake2b_512", xlat_func_blake2b_512, FR_TYPE_OCTETS, xlat_func_sha_arg);
# if OPENSSL_VERSION_NUMBER >= 0x10101000L
- XLAT_REGISTER_MONO("sha3_224", xlat_func_sha3_224, xlat_func_sha_arg);
- XLAT_REGISTER_MONO("sha3_256", xlat_func_sha3_256, xlat_func_sha_arg);
- XLAT_REGISTER_MONO("sha3_384", xlat_func_sha3_384, xlat_func_sha_arg);
- XLAT_REGISTER_MONO("sha3_512", xlat_func_sha3_512, xlat_func_sha_arg);
+ XLAT_REGISTER_MONO("sha3_224", xlat_func_sha3_224, FR_TYPE_OCTETS, xlat_func_sha_arg);
+ XLAT_REGISTER_MONO("sha3_256", xlat_func_sha3_256, FR_TYPE_OCTETS, xlat_func_sha_arg);
+ XLAT_REGISTER_MONO("sha3_384", xlat_func_sha3_384, FR_TYPE_OCTETS, xlat_func_sha_arg);
+ XLAT_REGISTER_MONO("sha3_512", xlat_func_sha3_512, FR_TYPE_OCTETS, xlat_func_sha_arg);
# endif
#endif
- XLAT_REGISTER_MONO("string", xlat_func_string, xlat_func_string_arg);
- XLAT_REGISTER_MONO("strlen", xlat_func_strlen, xlat_func_strlen_arg);
- XLAT_REGISTER_MONO("tolower", xlat_func_tolower, xlat_change_case_arg);
- XLAT_REGISTER_MONO("toupper", xlat_func_toupper, xlat_change_case_arg);
- XLAT_REGISTER_MONO("urlquote", xlat_func_urlquote, xlat_func_urlquote_arg);
- XLAT_REGISTER_MONO("urlunquote", xlat_func_urlunquote, xlat_func_urlunquote_arg);
- XLAT_REGISTER_MONO("eval", xlat_func_eval, xlat_func_eval_arg);
- XLAT_REGISTER_MONO("expr", xlat_func_expr, xlat_func_eval_arg);
+ XLAT_REGISTER_MONO("string", xlat_func_string, FR_TYPE_STRING, xlat_func_string_arg);
+ XLAT_REGISTER_MONO("strlen", xlat_func_strlen, FR_TYPE_SIZE, xlat_func_strlen_arg);
+ XLAT_REGISTER_MONO("tolower", xlat_func_tolower, FR_TYPE_STRING, xlat_change_case_arg);
+ XLAT_REGISTER_MONO("toupper", xlat_func_toupper, FR_TYPE_STRING, xlat_change_case_arg);
+ XLAT_REGISTER_MONO("urlquote", xlat_func_urlquote, FR_TYPE_STRING, xlat_func_urlquote_arg);
+ XLAT_REGISTER_MONO("urlunquote", xlat_func_urlunquote, FR_TYPE_STRING, xlat_func_urlunquote_arg);
+ XLAT_REGISTER_MONO("eval", xlat_func_eval, FR_TYPE_VOID, xlat_func_eval_arg);
+ XLAT_REGISTER_MONO("expr", xlat_func_expr, FR_TYPE_VOID, xlat_func_eval_arg);
#undef XLAT_REGISTER_MONO
-#define XLAT_REGISTER_MONO(_xlat, _func, _arg) \
+#define XLAT_REGISTER_MONO(_xlat, _func, _return_type, _arg) \
do { \
- if (!(xlat = xlat_register(NULL, _xlat, _func, NULL))) return -1; \
+ if (!(xlat = xlat_register(NULL, _xlat, _func, _return_type, NULL))) return -1; \
xlat_func_mono(xlat, &_arg); \
xlat_internal(xlat); \
} while (0)
- XLAT_REGISTER_MONO("rand", xlat_func_rand, xlat_func_rand_arg);
- XLAT_REGISTER_MONO("randstr", xlat_func_randstr, xlat_func_randstr_arg);
+ XLAT_REGISTER_MONO("rand", xlat_func_rand, FR_TYPE_UINT64, xlat_func_rand_arg);
+ XLAT_REGISTER_MONO("randstr", xlat_func_randstr, FR_TYPE_STRING, xlat_func_randstr_arg);
- xlat = xlat_register(NULL, "module", xlat_func_module, NULL);
+ xlat = xlat_register(NULL, "module", xlat_func_module, FR_TYPE_STRING, NULL);
xlat_internal(xlat);
return xlat_register_expressions();
RCSID("$Id$")
#include <freeradius-devel/server/base.h>
+#include <freeradius-devel/unlang/xlat.h>
#include <freeradius-devel/unlang/xlat_priv.h>
#include <freeradius-devel/util/debug.h>
+#include <freeradius-devel/util/types.h>
#include <freeradius-devel/unlang/unlang_priv.h> /* Remove when everything uses new xlat API */
return XLAT_ACTION_DONE;
}
+/** Validate that the return values from an xlat function match what it registered
+ *
+ * @param[in] request The current request.
+ * @param[in] func that was called.
+ * @param[in] returned the output list of the function.
+ * @param[in] pos current position in the output list.
+ * @return
+ * - true - If return values were correct.
+ * - false - If the return values were incorrect.
+ */
+static inline CC_HINT(nonnull)
+bool xlat_process_return(request_t *request, xlat_t const *func, FR_DLIST_HEAD(fr_value_box_list) const *returned, fr_value_box_t *pos)
+{
+ unsigned int count = 0;
+
+ /*
+ * Nothing to validate. We don't yet enforce that functions
+ * must return at least one instance of their type.
+ */
+ if (!fr_value_box_list_num_elements(returned) || fr_type_is_void(func->return_type)) return true;
+
+ if (fr_type_is_null(func->return_type)) {
+ /* Dynamic expansion to get the right name */
+ REDEBUG("%s return type registered as %s, but %s expansion produced data",
+ func->name, func->name, fr_type_to_str(func->return_type));
+
+ /* We are not forgiving for debug builds */
+ fr_assert_fail("Treating invalid return type as fatal");
+
+ return false;
+ }
+
+ do {
+ if (pos->type != func->return_type) {
+ REDEBUG("%s returned invalid result type at index %u. Expected type %s, got type %s",
+ func->name, count, fr_type_to_str(func->return_type), fr_type_to_str(pos->type));
+
+ /* We are not forgiving for debug builds */
+ fr_assert_fail("Treating invalid return type as fatal");
+ }
+ count++;
+ } while ((pos = fr_value_box_list_next(returned, pos)));
+
+ return true;
+}
+
/** One letter expansions
*
* @param[in] ctx to allocate boxed value, and buffers in.
case XLAT_ACTION_DONE:
fr_dcursor_next(out); /* Wind to the start of this functions output */
RDEBUG2("| --> %pV", fr_dcursor_current(out));
+ if (!xlat_process_return(request, exp->call.func, (FR_DLIST_HEAD(fr_value_box_list) *)out->dlist, fr_dcursor_current(out))) xa = XLAT_ACTION_FAIL;
break;
case XLAT_ACTION_FAIL:
fr_dcursor_next(out);
REXDENT();
xlat_debug_log_result(request, *in, fr_dcursor_current(out));
+ if (!xlat_process_return(request, node->call.func, (FR_DLIST_HEAD(fr_value_box_list) *)out->dlist, fr_dcursor_current(out))) xa = XLAT_ACTION_FAIL;
RINDENT();
break;
}
.allow_unresolved = false,
.list_as_attr = true,
},
- });
+ });
if (slen <= 0) goto fail;
talloc_free(rctx); /* no longer needed */
#undef XLAT_REGISTER_BINARY_OP
#define XLAT_REGISTER_BINARY_OP(_op, _name) \
do { \
- if (!(xlat = xlat_register(NULL, "op_" STRINGIFY(_name), xlat_func_op_ ## _name, XLAT_FLAG_PURE))) return -1; \
+ if (!(xlat = xlat_register(NULL, "op_" STRINGIFY(_name), xlat_func_op_ ## _name, FR_TYPE_VOID, XLAT_FLAG_PURE))) return -1; \
xlat_func_args(xlat, binary_op_xlat_args); \
xlat_internal(xlat); \
xlat_print_set(xlat, xlat_expr_print_binary); \
#undef XLAT_REGISTER_BINARY_CMP
#define XLAT_REGISTER_BINARY_CMP(_op, _name) \
do { \
- if (!(xlat = xlat_register(NULL, "cmp_" STRINGIFY(_name), xlat_func_cmp_ ## _name, XLAT_FLAG_PURE))) return -1; \
+ if (!(xlat = xlat_register(NULL, "cmp_" STRINGIFY(_name), xlat_func_cmp_ ## _name, FR_TYPE_VOID, XLAT_FLAG_PURE))) return -1; \
xlat_func_args(xlat, binary_op_xlat_args); \
xlat_internal(xlat); \
xlat_print_set(xlat, xlat_expr_print_binary); \
#undef XLAT_REGISTER_NARY_OP
#define XLAT_REGISTER_NARY_OP(_op, _name, _func_name) \
do { \
- if (!(xlat = xlat_register(NULL, STRINGIFY(_name), xlat_func_ ## _func_name, XLAT_FLAG_PURE))) return -1; \
+ if (!(xlat = xlat_register(NULL, STRINGIFY(_name), xlat_func_ ## _func_name, FR_TYPE_VOID, XLAT_FLAG_PURE))) return -1; \
xlat_async_instantiate_set(xlat, xlat_instantiate_ ## _func_name, xlat_ ## _func_name ## _inst_t, NULL, NULL); \
xlat_internal(xlat); \
xlat_print_set(xlat, xlat_expr_print_ ## _func_name); \
#undef XLAT_REGISTER_REGEX_OP
#define XLAT_REGISTER_REGEX_OP(_op, _name) \
do { \
- if (!(xlat = xlat_register(NULL, STRINGIFY(_name), xlat_func_ ## _name, XLAT_FLAG_PURE))) return -1; \
+ if (!(xlat = xlat_register(NULL, STRINGIFY(_name), xlat_func_ ## _name, FR_TYPE_VOID, XLAT_FLAG_PURE))) return -1; \
xlat_func_args(xlat, regex_op_xlat_args); \
xlat_async_instantiate_set(xlat, xlat_instantiate_regex, xlat_regex_inst_t, NULL, NULL); \
xlat_print_set(xlat, xlat_expr_print_regex); \
#define XLAT_REGISTER_MONO(_xlat, _func, _arg) \
do { \
- if (!(xlat = xlat_register(NULL, _xlat, _func, NULL))) return -1; \
+ if (!(xlat = xlat_register(NULL, _xlat, _func, FR_TYPE_VOID, NULL))) return -1; \
xlat_func_mono(xlat, &_arg); \
xlat_internal(xlat); \
} while (0)
#define XLAT_REGISTER_UNARY(_op, _xlat, _func) \
do { \
- if (!(xlat = xlat_register(NULL, _xlat, _func, XLAT_FLAG_PURE))) return -1; \
+ if (!(xlat = xlat_register(NULL, _xlat, _func, FR_TYPE_VOID, XLAT_FLAG_PURE))) return -1; \
xlat_func_args(xlat, unary_op_xlat_args); \
xlat_internal(xlat); \
xlat_print_set(xlat, xlat_expr_print_unary); \
/*
* Callback wrapper around old paircmp() API.
*/
- if (!(xlat = xlat_register(NULL, "paircmp", xlat_paircmp_func, NULL))) return -1; /* never pure! */
+ if (!(xlat = xlat_register(NULL, "paircmp", xlat_paircmp_func, FR_TYPE_VOID, NULL))) return -1; /* never pure! */
xlat_func_args(xlat, xlat_paircmp_xlat_args);
xlat_internal(xlat);
xlat_input_type_t input_type; //!< Type of input used.
xlat_arg_parser_t const *args; //!< Definition of args consumed.
+
+ fr_type_t return_type; //!< Function is guaranteed to return one or more boxes
+ ///< of this type. If the return type is FR_TYPE_VOID
+ ///< then the xlat function can return any type of output.
} xlat_t;
typedef enum {
return -1;
}
- xlat = xlat_register_module(inst, mctx, mctx->inst->name, always_xlat, NULL);
+ xlat = xlat_register_module(inst, mctx, mctx->inst->name, always_xlat, FR_TYPE_STRING, NULL);
xlat_func_args(xlat, always_xlat_args);
return 0;
/*
* Register the cache xlat function
*/
- xlat = xlat_register_module(inst, mctx, mctx->inst->name, cache_xlat, XLAT_FLAG_NEEDS_ASYNC);
+ xlat = xlat_register_module(inst, mctx, mctx->inst->name, cache_xlat, FR_TYPE_VOID, XLAT_FLAG_NEEDS_ASYNC);
xlat_func_args(xlat, cache_xlat_args);
return 0;
{
xlat_t *xlat;
- xlat = xlat_register(NULL, "chap_password", xlat_func_chap_password, NULL);
+ xlat = xlat_register(NULL, "chap_password", xlat_func_chap_password, FR_TYPE_OCTETS, NULL);
if (!xlat) return -1;
xlat_func_args(xlat, xlat_func_chap_password_args);
* Register decrypt xlat
*/
xlat_name = talloc_asprintf(inst, "%s_decrypt", mctx->inst->name);
- xlat = xlat_register_module(inst, mctx, xlat_name, cipher_rsa_decrypt_xlat, NULL);
+ xlat = xlat_register_module(inst, mctx, xlat_name, cipher_rsa_decrypt_xlat, FR_TYPE_STRING, NULL);
xlat_func_mono(xlat, &cipher_rsa_decrypt_xlat_arg);
talloc_free(xlat_name);
* Verify sign xlat
*/
xlat_name = talloc_asprintf(inst, "%s_verify", mctx->inst->name);
- xlat = xlat_register_module(inst, mctx, xlat_name, cipher_rsa_verify_xlat, NULL);
+ xlat = xlat_register_module(inst, mctx, xlat_name, cipher_rsa_verify_xlat, FR_TYPE_BOOL, NULL);
xlat_func_args(xlat, cipher_rsa_verify_xlat_arg);
talloc_free(xlat_name);
}
* Register encrypt xlat
*/
xlat_name = talloc_asprintf(inst, "%s_encrypt", mctx->inst->name);
- xlat = xlat_register_module(inst, mctx, xlat_name, cipher_rsa_encrypt_xlat, NULL);
+ xlat = xlat_register_module(inst, mctx, xlat_name, cipher_rsa_encrypt_xlat, FR_TYPE_OCTETS, NULL);
xlat_func_mono(xlat, &cipher_rsa_encrypt_xlat_arg);
talloc_free(xlat_name);
* Register sign xlat
*/
xlat_name = talloc_asprintf(inst, "%s_sign", mctx->inst->name);
- xlat = xlat_register_module(inst, mctx, xlat_name, cipher_rsa_sign_xlat, NULL);
+ xlat = xlat_register_module(inst, mctx, xlat_name, cipher_rsa_sign_xlat, FR_TYPE_OCTETS, NULL);
xlat_func_mono(xlat, &cipher_rsa_sign_xlat_arg);
talloc_free(xlat_name);
+ /*
+ * FIXME: These should probably be split into separate xlats
+ * so we can optimise for return types.
+ */
xlat_name = talloc_asprintf(inst, "%s_certificate", mctx->inst->name);
- xlat = xlat_register_module(inst, mctx, xlat_name, cipher_certificate_xlat, NULL);
+ xlat = xlat_register_module(inst, mctx, xlat_name, cipher_certificate_xlat, FR_TYPE_VOID, NULL);
xlat_func_args(xlat, cipher_certificate_xlat_args);
talloc_free(xlat_name);
{
xlat_t *xlat;
- xlat = xlat_register(NULL, "client", xlat_client, NULL);
+ xlat = xlat_register(NULL, "client", xlat_client, FR_TYPE_STRING, NULL);
if (!xlat) return -1;
xlat_func_args(xlat, xlat_client_args);
rlm_date_t *inst = talloc_get_type_abort(mctx->inst->data, rlm_date_t );
xlat_t *xlat;
- xlat = xlat_register_module(inst, mctx, mctx->inst->name, xlat_date_convert, NULL);
+ xlat = xlat_register_module(inst, mctx, mctx->inst->name, xlat_date_convert, FR_TYPE_VOID, NULL);
xlat_func_args(xlat, xlat_date_convert_args);
return 0;
rlm_delay_t *inst = talloc_get_type_abort(mctx->inst->data, rlm_delay_t);
xlat_t *xlat;
- xlat = xlat_register_module(inst, mctx, mctx->inst->name, xlat_delay, XLAT_FLAG_NEEDS_ASYNC);
+ xlat = xlat_register_module(inst, mctx, mctx->inst->name, xlat_delay, FR_TYPE_TIME_DELTA, XLAT_FLAG_NEEDS_ASYNC);
xlat_func_args(xlat, xlat_delay_args);
return 0;
}
*/
if (cf_section_name2(mctx->inst->conf) != NULL) return 0;
- xlat = xlat_register_module(inst, mctx, "attr_by_num", xlat_dict_attr_by_num, NULL);
+ xlat = xlat_register_module(inst, mctx, "attr_by_num", xlat_dict_attr_by_num, FR_TYPE_STRING, NULL);
xlat_func_args(xlat, xlat_dict_attr_by_num_args);
- xlat = xlat_register_module(inst, mctx, "attr_by_oid", xlat_dict_attr_by_oid, NULL);
+ xlat = xlat_register_module(inst, mctx, "attr_by_oid", xlat_dict_attr_by_oid, FR_TYPE_STRING, NULL);
xlat_func_args(xlat, xlat_dict_attr_by_oid_args);
- xlat = xlat_register_module(inst, mctx, "vendor", xlat_vendor, NULL);
+ xlat = xlat_register_module(inst, mctx, "vendor", xlat_vendor, FR_TYPE_STRING, NULL);
xlat_func_args(xlat, xlat_vendor_args);
- xlat = xlat_register_module(inst, mctx, "vendor_num", xlat_vendor_num, NULL);
+ xlat = xlat_register_module(inst, mctx, "vendor_num", xlat_vendor_num, FR_TYPE_UINT32, NULL);
xlat_func_args(xlat, xlat_vendor_num_args);
- xlat = xlat_register_module(inst, mctx, "attr", xlat_attr, NULL);
+ xlat = xlat_register_module(inst, mctx, "attr", xlat_attr, FR_TYPE_STRING, NULL);
xlat_func_args(xlat, xlat_attr_args);
- xlat = xlat_register_module(inst, mctx, "attr_num", xlat_attr_num, NULL);
+ xlat = xlat_register_module(inst, mctx, "attr_num", xlat_attr_num, FR_TYPE_UINT32, NULL);
xlat_func_args(xlat, xlat_attr_num_args);
return 0;
xlat_t *xlat;
MEM(unescape = talloc_asprintf(NULL, "un%s", mctx->inst->name));
- xlat = xlat_register_module(NULL, mctx, mctx->inst->name, escape_xlat, XLAT_FLAG_PURE);
+ xlat = xlat_register_module(NULL, mctx, mctx->inst->name, escape_xlat, FR_TYPE_STRING, XLAT_FLAG_PURE);
xlat_func_mono(xlat, &escape_xlat_arg);
- xlat = xlat_register_module(NULL, mctx, unescape, unescape_xlat, XLAT_FLAG_PURE);
+ xlat = xlat_register_module(NULL, mctx, unescape, unescape_xlat, FR_TYPE_STRING, XLAT_FLAG_PURE);
xlat_func_mono(xlat, &unescape_xlat_arg);
talloc_free(unescape);
xlat_t *xlat;
char const *p;
- xlat = xlat_register_module(NULL, mctx, mctx->inst->name, exec_xlat, XLAT_FLAG_NEEDS_ASYNC);
+ xlat = xlat_register_module(NULL, mctx, mctx->inst->name, exec_xlat, FR_TYPE_STRING, XLAT_FLAG_NEEDS_ASYNC);
xlat_func_args(xlat, exec_xlat_args);
if (inst->input) {
rlm_icmp_t *inst = talloc_get_type_abort(mctx->inst->data, rlm_icmp_t);
xlat_t *xlat;
- xlat = xlat_register_module(inst, mctx, mctx->inst->name, xlat_icmp, XLAT_FLAG_NEEDS_ASYNC);
+ xlat = xlat_register_module(inst, mctx, mctx->inst->name, xlat_icmp, FR_TYPE_BOOL, XLAT_FLAG_NEEDS_ASYNC);
xlat_func_args(xlat, xlat_icmp_args);
FR_TIME_DELTA_BOUND_CHECK("timeout", inst->timeout, >=, fr_time_delta_from_msec(100)); /* 1/10s minimum timeout */
rlm_idn_t *inst = talloc_get_type_abort(mctx->inst->data, rlm_idn_t);
xlat_t *xlat;
- xlat = xlat_register_module(inst, mctx, mctx->inst->name, xlat_idna, XLAT_FLAG_PURE);
+ xlat = xlat_register_module(inst, mctx, mctx->inst->name, xlat_idna, FR_TYPE_STRING, XLAT_FLAG_PURE);
xlat_func_mono(xlat, &xlat_idna_arg);
return 0;
char *name;
fr_json_format_t *format = inst->format;
- xlat = xlat_register_module(inst, mctx, "jsonquote", json_quote_xlat, NULL);
+ xlat = xlat_register_module(inst, mctx, "jsonquote", json_quote_xlat, FR_TYPE_STRING, NULL);
if (xlat) xlat_func_mono(xlat, &json_quote_xlat_arg);
- xlat = xlat_register_module(inst, mctx, "jpathvalidate", jpath_validate_xlat, NULL);
+ xlat = xlat_register_module(inst, mctx, "jpathvalidate", jpath_validate_xlat, FR_TYPE_STRING, NULL);
if (xlat) xlat_func_mono(xlat, &jpath_validate_xlat_arg);
name = talloc_asprintf(inst, "%s_encode", mctx->inst->name);
- xlat = xlat_register_module(inst, mctx, name, json_encode_xlat, NULL);
+ xlat = xlat_register_module(inst, mctx, name, json_encode_xlat, FR_TYPE_STRING, NULL);
xlat_func_mono(xlat, &json_encode_xlat_arg);
talloc_free(name);
inst->cache_da = inst->group_da; /* Default to the group_da */
}
- xlat = xlat_register_module(NULL, mctx, mctx->inst->name, ldap_xlat, NULL);
+ xlat = xlat_register_module(NULL, mctx, mctx->inst->name, ldap_xlat, FR_TYPE_STRING, NULL);
xlat_func_mono(xlat, &ldap_xlat_arg);
- xlat = xlat_register_module(NULL, mctx, "ldap_escape", ldap_escape_xlat, XLAT_FLAG_PURE);
+ xlat = xlat_register_module(NULL, mctx, "ldap_escape", ldap_escape_xlat, FR_TYPE_STRING, XLAT_FLAG_PURE);
if (xlat) xlat_func_mono(xlat, &ldap_escape_xlat_arg);
- xlat = xlat_register_module(NULL, mctx, "ldap_unescape", ldap_unescape_xlat, XLAT_FLAG_PURE);
+ xlat = xlat_register_module(NULL, mctx, "ldap_unescape", ldap_unescape_xlat, FR_TYPE_STRING, XLAT_FLAG_PURE);
if (xlat) xlat_func_mono(xlat, &ldap_escape_xlat_arg);
map_proc_register(inst, mctx->inst->name, mod_map_proc, ldap_map_verify, 0);
rlm_mschap_t *inst = talloc_get_type_abort(mctx->inst->data, rlm_mschap_t);
xlat_t *xlat;
- xlat = xlat_register_module(inst, mctx, mctx->inst->name, mschap_xlat, NULL);
+ xlat = xlat_register_module(inst, mctx, mctx->inst->name, mschap_xlat, FR_TYPE_VOID, NULL);
xlat_func_args(xlat, mschap_xlat_args);
return 0;
{
xlat_t *xlat;
- xlat = xlat_register_module(NULL, mctx, mctx->inst->name, perl_xlat, NULL);
+ xlat = xlat_register_module(NULL, mctx, mctx->inst->name, perl_xlat, FR_TYPE_VOID, NULL);
xlat_func_args(xlat, perl_xlat_args);
return 0;
char *name;
xlat_t *xlat;
- xlat = xlat_register_module(inst, mctx, mctx->inst->name, redis_xlat, NULL);
+ xlat = xlat_register_module(inst, mctx, mctx->inst->name, redis_xlat, FR_TYPE_VOID, NULL);
xlat_func_args(xlat, redis_args);
/*
* %(redis_node:<key>[ idx])
*/
name = talloc_asprintf(NULL, "%s_node", mctx->inst->name);
- xlat = xlat_register_module(inst, mctx, name, redis_node_xlat, NULL);
+ xlat = xlat_register_module(inst, mctx, name, redis_node_xlat, FR_TYPE_STRING, NULL);
xlat_func_args(xlat, redis_node_xlat_args);
talloc_free(name);
name = talloc_asprintf(NULL, "%s_remap", mctx->inst->name);
- xlat = xlat_register_module(inst, mctx, name, redis_remap_xlat, NULL);
+ xlat = xlat_register_module(inst, mctx, name, redis_remap_xlat, FR_TYPE_STRING, NULL);
xlat_func_args(xlat, redis_remap_xlat_args);
talloc_free(name);
rlm_rest_t *inst = talloc_get_type_abort(mctx->inst->data, rlm_rest_t);
xlat_t *xlat;
- xlat = xlat_register_module(inst, mctx, mctx->inst->name, rest_xlat, XLAT_FLAG_NEEDS_ASYNC);
+ xlat = xlat_register_module(inst, mctx, mctx->inst->name, rest_xlat, FR_TYPE_STRING, XLAT_FLAG_NEEDS_ASYNC);
xlat_func_args(xlat, rest_xlat_args);
return 0;
rlm_soh_t *inst = talloc_get_type_abort(mctx->inst->data, rlm_soh_t);
xlat_t *xlat;
- xlat = xlat_register_module(inst, mctx, mctx->inst->name, soh_xlat, NULL);
+ xlat = xlat_register_module(inst, mctx, mctx->inst->name, soh_xlat, FR_TYPE_STRING, NULL);
xlat_func_args(xlat, soh_xlat_args);
return 0;
/*
* Register the SQL xlat function
*/
- xlat = xlat_register_module(inst, mctx, mctx->inst->name, sql_xlat, NULL);
+ xlat = xlat_register_module(inst, mctx, mctx->inst->name, sql_xlat, FR_TYPE_VOID, NULL); /* Returns an integer sometimes */
/*
* The xlat escape function needs access to inst - so
}
if (!cf_section_name2(mctx->inst->conf)) {
- if (!(xlat = xlat_register_module(inst, mctx, "test_trigger", trigger_test_xlat, NULL))) return -1;
+ if (!(xlat = xlat_register_module(inst, mctx, "test_trigger", trigger_test_xlat, FR_TYPE_BOOL, NULL))) return -1;
xlat_func_args(xlat, trigger_test_xlat_args);
- if (!(xlat = xlat_register_module(inst, mctx, "test", test_xlat, NULL))) return -1;
+ if (!(xlat = xlat_register_module(inst, mctx, "test", test_xlat, FR_TYPE_STRING, NULL))) return -1;
xlat_func_args(xlat, test_xlat_args);
} else {
- if (!(xlat = xlat_register_module(inst, mctx, mctx->inst->name, test_xlat, NULL))) return -1;
+ if (!(xlat = xlat_register_module(inst, mctx, mctx->inst->name, test_xlat, FR_TYPE_VOID, NULL))) return -1;
xlat_func_args(xlat, test_xlat_args);
}
return -1;
}
- if(!(xlat = xlat_register_module(NULL, mctx, mctx->inst->name, xlat_unbound, XLAT_FLAG_NEEDS_ASYNC))) return -1;
+ if(!(xlat = xlat_register_module(NULL, mctx, mctx->inst->name, xlat_unbound, FR_TYPE_VOID, XLAT_FLAG_NEEDS_ASYNC))) return -1;
xlat_func_args(xlat, xlat_unbound_args);
return 0;
{
xlat_t *xlat;
- xlat = xlat_register_module(NULL, mctx, "unpack", unpack_xlat, XLAT_FLAG_PURE);
+ xlat = xlat_register_module(NULL, mctx, "unpack", unpack_xlat, FR_TYPE_VOID, XLAT_FLAG_PURE);
if (xlat) xlat_func_args(xlat, unpack_xlat_args);
return 0;
}
#endif
- xlat = xlat_register_module(inst, mctx, "modhextohex", modhex_to_hex_xlat, XLAT_FLAG_PURE);
+ xlat = xlat_register_module(inst, mctx, "modhextohex", modhex_to_hex_xlat, FR_TYPE_STRING, XLAT_FLAG_PURE);
if (xlat) xlat_func_mono(xlat, &modhex_to_hex_xlat_arg);
return 0;