]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
move decode_tlv() functionality into fr_struct_from_network()
authorAlan T. DeKok <aland@freeradius.org>
Mon, 30 Nov 2020 20:12:22 +0000 (15:12 -0500)
committerAlan T. DeKok <aland@freeradius.org>
Mon, 30 Nov 2020 20:16:15 +0000 (15:16 -0500)
src/lib/util/struct.c
src/lib/util/struct.h
src/protocols/arp/base.c
src/protocols/dhcpv6/decode.c
src/protocols/radius/decode.c
src/protocols/tacacs/decode.c

index d4ad7ee123d6251ca9bacec9701059cd4d158415..e4d974042168757a4deb6a16dbc95ab951e78df2 100644 (file)
@@ -37,7 +37,7 @@ fr_pair_t *fr_raw_from_network(TALLOC_CTX *ctx, fr_dict_attr_t const *parent, ui
 #endif
 
        /*
-        *      Build an unknown attr of the entire STRUCT.
+        *      Build an unknown attr of the entire data.
         */
        unknown = fr_dict_unknown_attr_afrom_da(ctx, parent);
        if (!unknown) return NULL;
@@ -64,7 +64,7 @@ fr_pair_t *fr_raw_from_network(TALLOC_CTX *ctx, fr_dict_attr_t const *parent, ui
  */
 ssize_t fr_struct_from_network(TALLOC_CTX *ctx, fr_cursor_t *cursor,
                               fr_dict_attr_t const *parent, uint8_t const *data, size_t data_len,
-                              fr_dict_attr_t const **child_p, void *decoder_ctx,
+                              void *decoder_ctx,
                               fr_decode_value_t decode_value, fr_decode_value_t decode_tlv)
 {
        unsigned int            child_num;
@@ -84,7 +84,6 @@ ssize_t fr_struct_from_network(TALLOC_CTX *ctx, fr_cursor_t *cursor,
         *      Record where we were in the list when this function was called
         */
        fr_cursor_init(&child_cursor, &head);
-       *child_p = NULL;
        child_num = 1;
        key_vp = NULL;
 
@@ -177,20 +176,27 @@ ssize_t fr_struct_from_network(TALLOC_CTX *ctx, fr_cursor_t *cursor,
 
                /*
                 *      Decode child TLVs, according to the parent attribute.
-                *
-                *      Return only PARTIALLY decoded data.  Let the
-                *      caller decode the rest.
-                *
-                *      @todo - pass TLVs to the "decode_value"
-                *      function, so it can decode them.
                 */
                if (child->type == FR_TYPE_TLV) {
-                       *child_p = child;
+                       ssize_t slen;
+
+                       fr_assert(!key_vp);
+
+                       if (!decode_tlv) {
+                               fr_strerror_printf("Decoding TLVs requires a decode_tlv() function to be passed");
+                               return -(p - data);
+                       }
+
+                       /*
+                        *      Decode EVERYTHING as a TLV.
+                        */
+                       while (p < end) {
+                               slen = decode_tlv(ctx, &child_cursor, fr_dict_by_da(child), child, p, end - p, decoder_ctx);
+                               if (slen < 0) goto unknown;
+                               p += slen;
+                       }
 
-                       fr_cursor_head(&child_cursor);
-                       fr_cursor_tail(cursor);
-                       fr_cursor_merge(cursor, &child_cursor); /* Wind to the end of the new pairs */
-                       return (p - data);
+                       goto done;
                }
 
                child_length = child->flags.length;
@@ -322,7 +328,7 @@ ssize_t fr_struct_from_network(TALLOC_CTX *ctx, fr_cursor_t *cursor,
                } else {
                        fr_assert(child->type == FR_TYPE_STRUCT);
 
-                       slen = fr_struct_from_network(ctx, &child_cursor, child, p, end - p, child_p,
+                       slen = fr_struct_from_network(ctx, &child_cursor, child, p, end - p,
                                                      decoder_ctx, decode_value, decode_tlv);
                        if (slen <= 0) goto unknown_child;
                        p += slen;
index dcb7c4c697000c46b07a6ca50ac8bf0413b38198..bfb0012569e149755455227104103f8841b1424b 100644 (file)
@@ -38,7 +38,7 @@ typedef ssize_t (*fr_decode_value_t)(TALLOC_CTX *ctx, fr_cursor_t *cursor, fr_di
 
 ssize_t fr_struct_from_network(TALLOC_CTX *ctx, fr_cursor_t *cursor,
                               fr_dict_attr_t const *parent, uint8_t const *data, size_t data_len,
-                              fr_dict_attr_t const **child, void *decoder_ctx,
+                              void *decoder_ctx,
                               fr_decode_value_t decode_value, fr_decode_value_t decode_tlv) CC_HINT(nonnull(2,3,4));
 
 typedef ssize_t (*fr_encode_dbuff_t)(fr_dbuff_t *dbuff, fr_da_stack_t *da_stack, unsigned int depth,
index c51351f82105f34f4e9811e1a5ef257a7d707cba..db6db694649e0e4bd1d7390d6481aeaf586cc35a 100644 (file)
@@ -224,7 +224,6 @@ ssize_t fr_arp_decode(TALLOC_CTX *ctx, uint8_t const *packet, size_t packet_len,
 {
        fr_arp_packet_t const *arp;
        fr_cursor_t cursor;
-       fr_dict_attr_t const *child;
 
        if (packet_len < FR_ARP_PACKET_SIZE) {
                fr_strerror_printf("Packet is too small (%d) to be ARP", (int) packet_len);
@@ -260,7 +259,7 @@ ssize_t fr_arp_decode(TALLOC_CTX *ctx, uint8_t const *packet, size_t packet_len,
         */
        fr_pair_list_init(list);
        fr_cursor_init(&cursor, list);
-       return fr_struct_from_network(ctx, &cursor, attr_arp_packet, packet, FR_ARP_PACKET_SIZE, &child,
+       return fr_struct_from_network(ctx, &cursor, attr_arp_packet, packet, FR_ARP_PACKET_SIZE,
                                      NULL, NULL, NULL);
 }
 
index ba3f92b56b0aaab0aca875dbf3949dabcb164339..50c9b3d07d777874fd798cd7a7747de69ce8141c 100644 (file)
@@ -45,6 +45,14 @@ static ssize_t decode_tlvs(TALLOC_CTX *ctx, fr_cursor_t *cursor, fr_dict_t const
                           fr_dict_attr_t const *parent,
                           uint8_t const *data, size_t const data_len, void *decoder_ctx, bool do_raw);
 
+static ssize_t decode_tlv_trampoline(TALLOC_CTX *ctx, fr_cursor_t *cursor, fr_dict_t const *dict,
+                                    fr_dict_attr_t const *parent,
+                                    uint8_t const *data, size_t const data_len, void *decoder_ctx)
+{
+       return decode_tlvs(ctx, cursor, dict, parent, data, data_len, decoder_ctx, true);
+}
+
+
 static ssize_t decode_raw(TALLOC_CTX *ctx, fr_cursor_t *cursor, UNUSED fr_dict_t const *dict,
                          fr_dict_attr_t const *parent,
                          uint8_t const *data, size_t const data_len, void *decoder_ctx)
@@ -126,7 +134,6 @@ static ssize_t decode_value(TALLOC_CTX *ctx, fr_cursor_t *cursor, fr_dict_t cons
 {
        ssize_t                 slen;
        fr_pair_t               *vp;
-       fr_dict_attr_t const    *tlv;
        uint8_t                 prefix_len;
 
        FR_PROTO_HEX_DUMP(data, data_len, "decode_value");
@@ -223,15 +230,9 @@ static ssize_t decode_value(TALLOC_CTX *ctx, fr_cursor_t *cursor, fr_dict_t cons
                break;
 
        case FR_TYPE_STRUCT:
-               slen = fr_struct_from_network(ctx, cursor, parent, data, data_len, &tlv,
-                                             decoder_ctx, decode_value_trampoline, NULL);
+               slen = fr_struct_from_network(ctx, cursor, parent, data, data_len,
+                                             decoder_ctx, decode_value_trampoline, decode_tlv_trampoline);
                if (slen < 0) return slen;
-
-               if (tlv) {
-                       fr_strerror_printf("decode children not implemented");
-                       return PAIR_DECODE_FATAL_ERROR;
-               }
-
                return data_len;
 
        case FR_TYPE_GROUP:
index c462671c40b7990be26249e8133b203685b79d02..097cedf7acd75e249b94fc4d28a97dccbf009021 100644 (file)
@@ -989,6 +989,17 @@ static ssize_t decode_value(TALLOC_CTX *ctx, fr_cursor_t *cursor, fr_dict_t cons
        return fr_radius_decode_pair_value(ctx, cursor, dict, parent, data, data_len, data_len, decoder_ctx);
 }
 
+/** Wrapper called by fr_struct_from_network()
+ */
+static ssize_t decode_tlv(TALLOC_CTX *ctx, fr_cursor_t *cursor, fr_dict_t const *dict,
+                           fr_dict_attr_t const *parent,
+                           uint8_t const *data, size_t data_len, void *decoder_ctx)
+{
+       FR_PROTO_HEX_DUMP(data, data_len, "%s", __FUNCTION__ );
+
+       return fr_radius_decode_tlv(ctx, cursor, dict, parent, data, data_len, decoder_ctx);
+}
+
 
 /** Create any kind of VP from the attribute contents
  *
@@ -1446,31 +1457,9 @@ ssize_t fr_radius_decode_pair_value(TALLOC_CTX *ctx, fr_cursor_t *cursor, fr_dic
                 *      attribute, OR it's already been grouped
                 *      into a contiguous memory buffer.
                 */
-               ret = fr_struct_from_network(ctx, cursor, parent, p, attr_len, &child,
-                                            decoder_ctx, decode_value, NULL);
+               ret = fr_struct_from_network(ctx, cursor, parent, p, attr_len,
+                                            decoder_ctx, decode_value, decode_tlv);
                if (ret < 0) goto raw;
-
-               /*
-                *      The above function only decodes fixed fields
-                *      and strings.  If there are TLVs at the end of
-                *      the struct, we have to decode them manually
-                *      here.
-                */
-               if (child && ((size_t) ret < attr_len)) {
-                       ssize_t tlv_len;
-
-                       /*
-                        *      Try to decode the TLVs
-                        */
-                       tlv_len = fr_radius_decode_tlv(ctx, cursor, dict,
-                                                      child, p + ret, attr_len - ret,
-                                                      decoder_ctx);
-                       if (tlv_len < 0) {
-                               vp = fr_raw_from_network(ctx, child, p + ret, attr_len - ret);
-                               if (vp) fr_cursor_append(cursor, vp);
-                       }
-               }
-
                return attr_len;
 
        default:
index b633a78ab6318d02c0efe257b54390dd502c476b..879284fbb499d08b980232b6eae301e11c183572 100644 (file)
@@ -157,7 +157,6 @@ static int tacacs_decode_field(TALLOC_CTX *ctx, fr_cursor_t *cursor, fr_dict_att
  */
 ssize_t fr_tacacs_decode(TALLOC_CTX *ctx, uint8_t const *buffer, size_t buffer_len, UNUSED const uint8_t *original, char const * const secret, size_t secret_len, fr_cursor_t *cursor)
 {
-       fr_dict_attr_t const    *tlv;
        fr_tacacs_packet_t const *pkt;
        fr_pair_t               *vp;
        uint8_t const           *p, *end;
@@ -232,7 +231,7 @@ ssize_t fr_tacacs_decode(TALLOC_CTX *ctx, uint8_t const *buffer, size_t buffer_l
        /*
         *      Call the struct encoder to do the actual work.
         */
-       if (fr_struct_from_network(ctx, cursor, attr_tacacs_packet, buffer, buffer_len, &tlv, NULL, NULL, NULL) < 0) {
+       if (fr_struct_from_network(ctx, cursor, attr_tacacs_packet, buffer, buffer_len, NULL, NULL, NULL) < 0) {
                fr_strerror_printf("Problems to decode %s using fr_struct_from_network()", attr_tacacs_packet->name);
                return -1;
        }