From: Alan T. DeKok Date: Tue, 10 Aug 2021 13:28:50 +0000 (-0400) Subject: add protocol-generic decode routines X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0b0caa9118ab29a061637ef8843993570f607ecb;p=thirdparty%2Ffreeradius-server.git add protocol-generic decode routines --- diff --git a/src/lib/io/all.mk b/src/lib/io/all.mk index 6551d5ff2bb..68ba44c7497 100644 --- a/src/lib/io/all.mk +++ b/src/lib/io/all.mk @@ -9,7 +9,6 @@ SOURCES := \ master.c \ message.c \ network.c \ - pair.c \ queue.c \ ring_buffer.c \ schedule.c \ diff --git a/src/lib/unlang/all.mk b/src/lib/unlang/all.mk index 88bca5072b2..fb31b599eb4 100644 --- a/src/lib/unlang/all.mk +++ b/src/lib/unlang/all.mk @@ -25,7 +25,8 @@ SOURCES := base.c \ xlat_builtin.c \ xlat_eval.c \ xlat_inst.c \ - xlat_tokenize.c + xlat_tokenize.c \ + xlat_pair.c HEADERS := $(subst src/lib/,,$(wildcard src/lib/unlang/*.h)) diff --git a/src/lib/unlang/xlat_builtin.c b/src/lib/unlang/xlat_builtin.c index bcda6a07b36..0149589863d 100644 --- a/src/lib/unlang/xlat_builtin.c +++ b/src/lib/unlang/xlat_builtin.c @@ -35,6 +35,8 @@ RCSID("$Id$") #include #include +#include + #include #include #include @@ -424,9 +426,7 @@ void _xlat_async_instantiate_set(xlat_t const *xlat, xlat_detach_t detach, void *uctx) { - xlat_t *c; - - memcpy(&c, &xlat, sizeof(c)); + xlat_t *c = UNCONST(xlat_t *, xlat); c->instantiate = instantiate; c->inst_type = inst_type; @@ -456,9 +456,7 @@ void _xlat_async_thread_instantiate_set(xlat_t const *xlat, xlat_thread_detach_t thread_detach, void *uctx) { - xlat_t *c; - - memcpy(&c, &xlat, sizeof(c)); + xlat_t *c = UNCONST(xlat_t *, xlat); c->thread_instantiate = thread_instantiate; c->thread_inst_type = thread_inst_type; @@ -3049,6 +3047,121 @@ static xlat_arg_parser_t const trigger_xlat_args[] = { XLAT_ARG_PARSER_TERMINATOR }; +static xlat_arg_parser_t const protocol_decode_xlat_args[] = { + { .single = true, .variadic = true, .type = FR_TYPE_VOID }, + XLAT_ARG_PARSER_TERMINATOR +}; + +/** Decode any protocol attribute / options + * + * Creates protocol-specific attributes based on the given binary option data + * + * Example: +@verbatim +%(decode.dhcpv4:%{Tmp-Octets-0}) +@endverbatim + * + * @ingroup xlat_functions + */ +static xlat_action_t protocol_decode_xlat(TALLOC_CTX *ctx, fr_dcursor_t *out, + request_t *request, void const *xlat_inst, UNUSED void *xlat_thread_inst, + fr_value_box_list_t *in) +{ + int decoded; + fr_value_box_t *vb; + fr_pair_list_t head; + fr_dcursor_t cursor; + void *decode_ctx = NULL; + fr_test_point_pair_decode_t const *tp_decode; + + memcpy(&tp_decode, xlat_inst, sizeof(tp_decode)); /* const issues */ + + if (tp_decode->test_ctx) { + if (tp_decode->test_ctx(&decode_ctx, ctx) < 0) { + return XLAT_ACTION_FAIL; + } + } + + fr_pair_list_init(&head); + fr_dcursor_init(&cursor, &head); + + decoded = fr_pair_decode_value_box_list(request->request_ctx, &cursor, request, decode_ctx, tp_decode->func, in); + if (decoded <= 0) { + talloc_free(decode_ctx); + RPERROR("Protocol decoding failed"); + return XLAT_ACTION_FAIL; + } + + /* + * Append the decoded options to the request list. + */ + fr_pair_list_append(&request->request_pairs, &head); + + /* + * Create a value box to hold the decoded count, and add + * it to the output list. + */ + MEM(vb = fr_value_box_alloc(ctx, FR_TYPE_UINT32, NULL, false)); + vb->vb_uint32 = decoded; + fr_dcursor_append(out, vb); + + talloc_free(decode_ctx); + return XLAT_ACTION_DONE; +} + +static int protocol_decode_xlat_instantiate(void *xlat_inst, UNUSED xlat_exp_t const *exp, void *uctx) +{ + *(void **) xlat_inst = uctx; + return 0; +} + + +static int xlat_protocol_init(void) +{ + fr_dict_t *dict; + fr_dict_global_ctx_iter_t iter; + char *p, buffer[256], name[256]; + + /* + * @todo - add encoder, too + * + * @todo - and for the "internal" protocol, too. + */ + for (dict = fr_dict_global_ctx_iter_init(&iter); + dict != NULL; + dict = fr_dict_global_ctx_iter_next(&iter)) { + dl_t *dl = fr_dict_dl(dict); + fr_test_point_pair_decode_t *tp_decode; + xlat_t *xlat; + + strlcpy(name, fr_dict_root(dict)->name, sizeof(name)); + for (p = name; *p != '\0'; p++) { + *p = tolower((int) *p); + } + + /* + * See if there's a decode function for it. + */ + snprintf(buffer, sizeof(buffer), "%s_tp_decode_pair", name); + + /* + * No decode == soft fail. + */ + tp_decode = dlsym(dl->handle, buffer); + if (!tp_decode) continue; + + snprintf(buffer, sizeof(buffer), "decode.%s", name); + ERROR("TP Decode %s -> %p", name, tp_decode); + + xlat = xlat_register(NULL, buffer, protocol_decode_xlat, false); + xlat_func_args(xlat, protocol_decode_xlat_args); + xlat_async_instantiate_set(xlat, protocol_decode_xlat_instantiate, fr_test_point_pair_decode_t *, NULL, tp_decode); + } + + return 0; +} + + /** Global initialisation for xlat * * @note Free memory with #xlat_free @@ -3082,6 +3195,11 @@ int xlat_init(void) return -1; } + /* + * Define encode/decode for the various protocols. + */ + if (xlat_protocol_init() < 0) return -1; + #define XLAT_REGISTER(_x) xlat = xlat_register_legacy(NULL, STRINGIFY(_x), xlat_func_ ## _x, NULL, NULL, 0, XLAT_DEFAULT_BUF_LEN); \ xlat_internal(xlat); diff --git a/src/lib/io/pair.c b/src/lib/unlang/xlat_pair.c similarity index 99% rename from src/lib/io/pair.c rename to src/lib/unlang/xlat_pair.c index dead6f60463..d7d12776798 100644 --- a/src/lib/io/pair.c +++ b/src/lib/unlang/xlat_pair.c @@ -18,7 +18,7 @@ * $Id$ * * @brief Protocol agnostic encode/decoders - * @file io/pair.c + * @file unlang/xlat_pair.c * * @copyright 2021 Network RADIUS SARL (legal@networkradius.com) */ diff --git a/src/tests/keywords/xlat-dhcpv4 b/src/tests/keywords/xlat-dhcpv4 index d87023000b1..2a7353d556c 100644 --- a/src/tests/keywords/xlat-dhcpv4 +++ b/src/tests/keywords/xlat-dhcpv4 @@ -7,7 +7,7 @@ update control { &Tmp-Octets-0 := 0x520d0103abcdef0206010203040506 } -if ("%(dhcpv4_decode:%{control.Tmp-Octets-0})" != 2) { +if ("%(decode.dhcpv4:%{control.Tmp-Octets-0})" != 2) { test_fail }