From: Alan T. DeKok Date: Mon, 30 Nov 2020 20:12:22 +0000 (-0500) Subject: move decode_tlv() functionality into fr_struct_from_network() X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b4abe3d7e2165ecb74fa296f09d0d2942f51951d;p=thirdparty%2Ffreeradius-server.git move decode_tlv() functionality into fr_struct_from_network() --- diff --git a/src/lib/util/struct.c b/src/lib/util/struct.c index d4ad7ee123d..e4d97404216 100644 --- a/src/lib/util/struct.c +++ b/src/lib/util/struct.c @@ -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; diff --git a/src/lib/util/struct.h b/src/lib/util/struct.h index dcb7c4c6970..bfb0012569e 100644 --- a/src/lib/util/struct.h +++ b/src/lib/util/struct.h @@ -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, diff --git a/src/protocols/arp/base.c b/src/protocols/arp/base.c index c51351f8210..db6db694649 100644 --- a/src/protocols/arp/base.c +++ b/src/protocols/arp/base.c @@ -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); } diff --git a/src/protocols/dhcpv6/decode.c b/src/protocols/dhcpv6/decode.c index ba3f92b56b0..50c9b3d07d7 100644 --- a/src/protocols/dhcpv6/decode.c +++ b/src/protocols/dhcpv6/decode.c @@ -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: diff --git a/src/protocols/radius/decode.c b/src/protocols/radius/decode.c index c462671c40b..097cedf7acd 100644 --- a/src/protocols/radius/decode.c +++ b/src/protocols/radius/decode.c @@ -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: diff --git a/src/protocols/tacacs/decode.c b/src/protocols/tacacs/decode.c index b633a78ab63..879284fbb49 100644 --- a/src/protocols/tacacs/decode.c +++ b/src/protocols/tacacs/decode.c @@ -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; }