]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
rearrange code and move to common function
authorAlan T. DeKok <aland@freeradius.org>
Mon, 9 Aug 2021 20:31:37 +0000 (16:31 -0400)
committerAlan T. DeKok <aland@freeradius.org>
Tue, 10 Aug 2021 15:13:37 +0000 (11:13 -0400)
in preparation for automatically defining "decode/encode" xlats
for all of the protocols

src/lib/io/all.mk
src/lib/io/pair.c [new file with mode: 0644]
src/lib/io/pair.h
src/modules/rlm_dhcpv4/rlm_dhcpv4.c

index 68ba44c74978aeeb76d64464b63ae5fe8377cf7c..6551d5ff2bbd19655f9408edb68be91559aa11c6 100644 (file)
@@ -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 (file)
index 0000000..dead6f6
--- /dev/null
@@ -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 <freeradius-devel/io/pair.h>
+
+/** 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, "<INVALID>"),
+                               fr_table_str_by_value(fr_value_box_type_table, vb->type, "<INVALID>"));
+                       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;
+}
index 7a78f2342c5c8a70de55cab417cd9274fe28f7b6..772769892e69174207f361d0383601fe899f4343 100644 (file)
@@ -25,6 +25,8 @@
  */
 #include <freeradius-devel/util/dcursor.h>
 #include <freeradius-devel/util/value.h>
+#include <freeradius-devel/util/pair.h>
+#include <freeradius-devel/server/request.h>
 
 /** @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);
index 4f97e26267d4b991eb6a160aa9ecf9bfef373add..e7c1dc3a9f312f2ba9b8f2bad03b64d5f083d467 100644 (file)
@@ -27,6 +27,7 @@ RCSID("$Id$")
 
 #include <freeradius-devel/server/base.h>
 #include <freeradius-devel/server/module.h>
+#include <freeradius-devel/io/pair.h>
 #include <freeradius-devel/dhcpv4/dhcpv4.h>
 
 #include <ctype.h>
@@ -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, "<INVALID>"),
-                               fr_table_str_by_value(fr_value_box_type_table, vb->type, "<INVALID>"));
-                       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;
 }