From: Alan T. DeKok Date: Mon, 9 Aug 2021 20:31:37 +0000 (-0400) Subject: rearrange code and move to common function X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b0f064fc38cef53cefd7d34053f7b02d0e9909c3;p=thirdparty%2Ffreeradius-server.git rearrange code and move to common function in preparation for automatically defining "decode/encode" xlats for all of the protocols --- diff --git a/src/lib/io/all.mk b/src/lib/io/all.mk index 68ba44c7497..6551d5ff2bb 100644 --- a/src/lib/io/all.mk +++ b/src/lib/io/all.mk @@ -9,6 +9,7 @@ SOURCES := \ master.c \ message.c \ network.c \ + pair.c \ queue.c \ ring_buffer.c \ schedule.c \ diff --git a/src/lib/io/pair.c b/src/lib/io/pair.c new file mode 100644 index 00000000000..dead6f60463 --- /dev/null +++ b/src/lib/io/pair.c @@ -0,0 +1,144 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +/** + * $Id$ + * + * @brief Protocol agnostic encode/decoders + * @file io/pair.c + * + * @copyright 2021 Network RADIUS SARL (legal@networkradius.com) + */ +RCSID("$Id$") + +#include + +/** Keep decoding pairs until all of the data has been used. + * + * @param[in] ctx to allocate new pairs in. + * @param[in] out the cursor to update + * @param[in] dict to use to lookup attributes. + * @param[in] data to decode. + * @param[in] data_len The length of the incoming data. + * @param[in] decode_ctx Any decode specific data such as secrets or configurable. + * @param[in] decode the function used to decode one specific pair. + * @return + * - <= 0 on error. May be the offset (as a negative value) where the error occurred. + * - > 0 on success. How many bytes were decoded. + */ +static ssize_t fr_pair_decode_multi(TALLOC_CTX *ctx, fr_dcursor_t *out, fr_dict_t const *dict, + uint8_t const *data, size_t data_len, void *decode_ctx, fr_pair_decode_t decode) +{ + uint8_t const *p, *end; + fr_pair_list_t head; + fr_dcursor_t cursor; + + /* + * Catch idiocies. + */ + if (data_len == 0) return 0; + + fr_pair_list_init(&head); + fr_dcursor_init(&cursor, &head); + + p = data; + end = data + data_len; + + while (p < end) { + ssize_t len; + + len = decode(ctx, &cursor, dict, p, end - p, decode_ctx); + if (len <= 0) { + fr_pair_list_free(&head); + return len - (p - data); + } + p += len; + } + + /* + * Add the pairs to the cursor + */ + fr_dcursor_head(&cursor); + fr_dcursor_merge(out, &cursor); + + return data_len; +} + + +/** Decode all of the value boxes into the output cursor + * + * @param[in] ctx to allocate new pairs in. + * @param[in] out the cursor to update + * @param[in] request the request + * @param[in] decode_ctx Any decode specific data such as secrets or configurable. + * @param[in] decode the function used to decode one specific pair. + * @param[in] in the list of value boxes to decode + * @return + * - <= 0 on error. May be the offset (as a negative value) where the error occurred. + * - > 0 on success. How many value boxes were decoded + */ +int fr_pair_decode_value_box_list(TALLOC_CTX *ctx, fr_dcursor_t *out, + request_t *request, void *decode_ctx, fr_pair_decode_t decode, + fr_value_box_list_t *in) +{ + int decoded = 0; + fr_value_box_t *vb = NULL; + fr_pair_t *vp = NULL; + fr_pair_list_t head; + fr_dcursor_t cursor; + + fr_pair_list_init(&head); + + while ((vb = fr_dlist_next(in, vb))) { + ssize_t len; + fr_pair_list_t vps; + + if (vb->type != FR_TYPE_OCTETS) { + RWDEBUG("Skipping value \"%pV\", expected value of type %s, got type %s", + vb, + fr_table_str_by_value(fr_value_box_type_table, FR_TYPE_OCTETS, ""), + fr_table_str_by_value(fr_value_box_type_table, vb->type, "")); + continue; + } + + fr_pair_list_init(&vps); + fr_dcursor_init(&cursor, &vps); + + len = fr_pair_decode_multi(ctx, &cursor, request->dict, + vb->vb_octets, vb->vb_length, decode_ctx, decode); + if (len <= 0) { + fr_pair_list_free(&head); + return -decoded; + } + fr_pair_list_append(&head, &vps); + decoded++; /* one more VB, but there may be many pairs in the decoded vps. */ + } + + if (RDEBUG_ENABLED2) { + char const *name = fr_dict_root(request->dict)->name; + + while ((vp = fr_pair_list_next(&head, vp))) { + RDEBUG2("decode %s: &%pP", name, vp); + } + } + + decoded = fr_dlist_num_elements(&head.head); + + fr_dcursor_init(&cursor, &head); + fr_dcursor_merge(out, &cursor); + + return decoded; +} diff --git a/src/lib/io/pair.h b/src/lib/io/pair.h index 7a78f2342c5..772769892e6 100644 --- a/src/lib/io/pair.h +++ b/src/lib/io/pair.h @@ -25,6 +25,8 @@ */ #include #include +#include +#include /** @name Encoder errors * @{ @@ -132,3 +134,7 @@ typedef ssize_t (*fr_pair_encode_t)(fr_dbuff_t *out, fr_dcursor_t *cursor, void */ typedef ssize_t (*fr_pair_decode_t)(TALLOC_CTX *ctx, fr_dcursor_t *cursor, fr_dict_t const *dict, uint8_t const *data, size_t data_len, void *decode_ctx); + +int fr_pair_decode_value_box_list(TALLOC_CTX *ctx, fr_dcursor_t *out, + request_t *request, void *decode_ctx, fr_pair_decode_t decode, + fr_value_box_list_t *in); diff --git a/src/modules/rlm_dhcpv4/rlm_dhcpv4.c b/src/modules/rlm_dhcpv4/rlm_dhcpv4.c index 4f97e26267d..e7c1dc3a9f3 100644 --- a/src/modules/rlm_dhcpv4/rlm_dhcpv4.c +++ b/src/modules/rlm_dhcpv4/rlm_dhcpv4.c @@ -27,6 +27,7 @@ RCSID("$Id$") #include #include +#include #include #include @@ -70,63 +71,32 @@ static xlat_action_t dhcpv4_decode_xlat(TALLOC_CTX *ctx, fr_dcursor_t *out, request_t *request, UNUSED void const *xlat_inst, UNUSED void *xlat_thread_inst, fr_value_box_list_t *in) { - fr_value_box_t *vb = NULL, *vb_decoded; - fr_pair_t *vp = NULL; + int decoded; + fr_value_box_t *vb; fr_pair_list_t head; - int decoded = 0; + fr_dcursor_t cursor; fr_pair_list_init(&head); + fr_dcursor_init(&cursor, &head); - while ((vb = fr_dlist_next(in, vb))) { - uint8_t const *p, *end; - ssize_t len; - fr_pair_list_t vps; - fr_dcursor_t options_cursor; - - fr_pair_list_init(&vps); - if (vb->type != FR_TYPE_OCTETS) { - RWDEBUG("Skipping value \"%pV\", expected value of type %s, got type %s", - vb, - fr_table_str_by_value(fr_value_box_type_table, FR_TYPE_OCTETS, ""), - fr_table_str_by_value(fr_value_box_type_table, vb->type, "")); - continue; - } - - fr_dcursor_init(&options_cursor, &vps); - - p = vb->vb_octets; - end = vb->vb_octets + vb->vb_length; - - /* - * Loop over all the options data - */ - while (p < end) { - len = fr_dhcpv4_decode_option(request->request_ctx, &options_cursor, dict_dhcpv4, - p, end - p, NULL); - if (len <= 0) { - RPERROR("DHCP option decoding failed"); - fr_pair_list_free(&head); - return XLAT_ACTION_FAIL; - } - p += len; - } - fr_pair_list_append(&head, &vps); - } - - while ((vp = fr_pair_list_next(&head, vp))) { - RDEBUG2("dhcp_option: &%pP", vp); - decoded++; + decoded = fr_pair_decode_value_box_list(request->request_ctx, &cursor, request, NULL, fr_dhcpv4_decode_option, in); + if (decoded <= 0) { + RPERROR("DHCP option decoding failed"); + return XLAT_ACTION_FAIL; } - fr_pair_list_move(&request->request_pairs, &head, T_OP_ADD); - - /* Free any unmoved pairs */ - fr_pair_list_free(&head); + /* + * 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 */ - MEM(vb_decoded = fr_value_box_alloc(ctx, FR_TYPE_UINT16, NULL, false)); - vb_decoded->vb_uint16 = decoded; - fr_dcursor_append(out, vb_decoded); + /* + * 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); return XLAT_ACTION_DONE; }