From: Alan T. DeKok Date: Sat, 28 Nov 2020 23:09:08 +0000 (-0500) Subject: move common code to struct_to_network() X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d4b2c1c853e85f40fcd4b335803839fff97bb186;p=thirdparty%2Ffreeradius-server.git move common code to struct_to_network() --- diff --git a/src/lib/util/struct.c b/src/lib/util/struct.c index 2f213f14e1a..7fb62c2f07e 100644 --- a/src/lib/util/struct.c +++ b/src/lib/util/struct.c @@ -388,9 +388,18 @@ static int put_bits_dbuff(fr_dbuff_t *dbuff, uint8_t *p, int start_bit, uint8_t return start_bit % 8; } +static int8_t pair_sort_increasing(void const *a, void const *b) +{ + fr_pair_t const *my_a = a; + fr_pair_t const *my_b = b; + + return (my_a->da->attr > my_b->da->attr) - (my_a->da->attr < my_b->da->attr); +} + + ssize_t fr_struct_to_network(fr_dbuff_t *dbuff, fr_da_stack_t *da_stack, unsigned int depth, - fr_cursor_t *cursor, void *encoder_ctx, + fr_cursor_t *parent_cursor, void *encoder_ctx, fr_encode_dbuff_t encode_value, fr_encode_dbuff_t encode_tlv) { fr_dbuff_t work_dbuff = FR_DBUFF_NO_ADVANCE(dbuff); @@ -399,8 +408,9 @@ ssize_t fr_struct_to_network(fr_dbuff_t *dbuff, unsigned int child_num = 1; bool do_length = false; uint8_t bit_buffer = 0; - fr_pair_t const *vp = fr_cursor_current(cursor); + fr_pair_t const *vp = fr_cursor_current(parent_cursor); fr_dict_attr_t const *key_da, *parent, *tlv = NULL; + fr_cursor_t child_cursor, *cursor; if (!vp) { fr_strerror_printf("%s: Can't encode empty struct", __FUNCTION__); @@ -416,6 +426,33 @@ ssize_t fr_struct_to_network(fr_dbuff_t *dbuff, return -1; } + /* + * If we get passed a struct VP, sort it's children. + */ + if (vp->da->type == FR_TYPE_STRUCT) { + fr_pair_t *sorted = fr_cursor_current(parent_cursor); /* NOT const */ + + fr_pair_list_sort(&sorted->vp_group, pair_sort_increasing); + fr_cursor_init(&child_cursor, &sorted->vp_group); + + /* + * Always skip the VP containing the struct. + * + * @todo - do this only on success. + */ + (void) fr_cursor_next(parent_cursor); + + /* + * Build the da_stack for the new structure. + */ + vp = fr_cursor_current(&child_cursor); + fr_proto_da_stack_build(da_stack, vp ? vp->da : NULL); + + cursor = &child_cursor; + } else { + cursor = parent_cursor; + } + /* * @todo - if we get a child which *eventually* has the * given parent, then allow encoding of that struct, too. diff --git a/src/protocols/dhcpv6/encode.c b/src/protocols/dhcpv6/encode.c index e6a8408293b..41b290a4167 100644 --- a/src/protocols/dhcpv6/encode.c +++ b/src/protocols/dhcpv6/encode.c @@ -81,14 +81,6 @@ static inline ssize_t encode_option_hdr(fr_dbuff_t *dbuff, uint16_t option, size } -static int8_t pair_sort_increasing(void const *a, void const *b) -{ - fr_pair_t const *my_a = a; - fr_pair_t const *my_b = b; - - return (my_a->da->attr > my_b->da->attr) - (my_a->da->attr < my_b->da->attr); -} - static ssize_t encode_value(fr_dbuff_t *dbuff, fr_da_stack_t *da_stack, unsigned int depth, fr_cursor_t *cursor, void *encoder_ctx) @@ -104,26 +96,10 @@ static ssize_t encode_value(fr_dbuff_t *dbuff, /* * Pack multiple attributes into into a single option */ - if (vp->da->type == FR_TYPE_STRUCT) { - fr_cursor_t child_cursor; - fr_pair_t *sorted = fr_cursor_current(cursor); /* NOT const */ - - fr_assert(vp->da == da); - - fr_pair_list_sort(&sorted->vp_group, pair_sort_increasing); - fr_cursor_init(&child_cursor, &sorted->vp_group); - - /* - * Build the da_stack for the new structure. - */ - vp = fr_cursor_head(&child_cursor); - fr_proto_da_stack_build(da_stack, vp ? vp->da : NULL); - + if ((vp->da->type == FR_TYPE_STRUCT) || (da->type == FR_TYPE_STRUCT)) { slen = fr_struct_to_network(&work_dbuff, da_stack, depth, cursor, encoder_ctx, encode_value, encode_tlv); if (slen <= 0) return slen; - (void) fr_cursor_next(cursor); /* skip the VP containing the struct */ - /* * Rebuild the da_stack for the next option. */ @@ -132,19 +108,6 @@ static ssize_t encode_value(fr_dbuff_t *dbuff, return fr_dbuff_set(dbuff, &work_dbuff); } - /* - * If there's a struct on the da_stack, then the struct - * members MUST be in a flat list. - */ - if (da->type == FR_TYPE_STRUCT) { - slen = fr_struct_to_network(&work_dbuff, da_stack, depth, cursor, encoder_ctx, encode_value, encode_tlv); - if (slen <= 0) return slen; - - vp = fr_cursor_current(cursor); - fr_proto_da_stack_build(da_stack, vp ? vp->da : NULL); - return fr_dbuff_set(dbuff, &work_dbuff); - } - /* * If it's not a TLV, it should be a value type RFC * attribute make sure that it is. diff --git a/src/protocols/radius/encode.c b/src/protocols/radius/encode.c index 2376514645c..8e84123caad 100644 --- a/src/protocols/radius/encode.c +++ b/src/protocols/radius/encode.c @@ -393,29 +393,7 @@ static ssize_t encode_value(fr_dbuff_t *dbuff, /* * This has special requirements. */ - if (vp->da->type == FR_TYPE_STRUCT) { - fr_cursor_t child_cursor; - - fr_assert(vp->da == da); - - fr_cursor_init(&child_cursor, &vp->vp_group); - - slen = fr_struct_to_network(&work_dbuff, da_stack, depth, &child_cursor, encoder_ctx, encode_value, - encode_tlv_hdr_internal); - if (slen <= 0) return slen; - - /* - * Skip the attribute we just encoded, and re-build the da_stack. - */ - vp = fr_cursor_next(cursor); - fr_proto_da_stack_build(da_stack, vp ? vp->da : NULL); - return fr_dbuff_set(dbuff, &work_dbuff); - } - - /* - * Old-style struct fields in a flat list. - */ - if (da->type == FR_TYPE_STRUCT) { + if ((vp->da->type == FR_TYPE_STRUCT) || (da->type == FR_TYPE_STRUCT)) { slen = fr_struct_to_network(&work_dbuff, da_stack, depth, cursor, encoder_ctx, encode_value, encode_tlv_hdr_internal); if (slen <= 0) return slen;