From: Alan T. DeKok Date: Sun, 28 Jan 2024 16:37:58 +0000 (-0500) Subject: hoist encode foreign ref to common function X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=9801b1b2718121c873b1b43861d27ded4df703e9;p=thirdparty%2Ffreeradius-server.git hoist encode foreign ref to common function --- diff --git a/src/lib/util/encode.c b/src/lib/util/encode.c index e3c02218be8..7c35150c3ff 100644 --- a/src/lib/util/encode.c +++ b/src/lib/util/encode.c @@ -108,3 +108,58 @@ ssize_t fr_pair_cursor_to_network(fr_dbuff_t *dbuff, return fr_dbuff_set(dbuff, &work_dbuff); } + +/** Encode a foreign reference to the network + * + * @param[out] dbuff buffer to write the TLV to. + * @param[in] da_stack Describing nesting of options. + * @param[in] depth in the da_stack. + * @param[in,out] cursor Current attribute we're encoding. + * @return + * - >0 length of data encoded. + * - 0 if we ran out of space. + * - < 0 on error. + */ +ssize_t fr_pair_ref_to_network(fr_dbuff_t *dbuff, fr_da_stack_t *da_stack, unsigned int depth, + fr_dcursor_t *cursor) +{ + ssize_t slen; + fr_dict_attr_t const *da; + fr_pair_t const *vp = fr_dcursor_current(cursor); + fr_dbuff_t work_dbuff = FR_DBUFF(dbuff); + + fr_dict_attr_t const *ref; + fr_dict_protocol_t const *proto; + + FR_PROTO_STACK_PRINT(da_stack, depth); + + da = da_stack->da[depth]; + fr_assert(da->type == FR_TYPE_GROUP); + + ref = fr_dict_attr_ref(da); + if (!ref) { + fr_strerror_printf("Invalid attribute reference for %s", da->name); + return PAIR_ENCODE_SKIPPED; + } + + proto = fr_dict_protocol(ref->dict); + fr_assert(proto != NULL); + + if (!proto->encode) { + fr_strerror_printf("Attribute %s -> %s does not have an encoder", da->name, ref->name); + return PAIR_ENCODE_SKIPPED; + } + + /* + * The foreign functions don't take a cursor, so we have to update the cursor ourselves. + */ + slen = proto->encode(&work_dbuff, &vp->vp_group); + if (slen <= 0) return slen; + + FR_PROTO_HEX_DUMP(fr_dbuff_start(&work_dbuff), fr_dbuff_used(&work_dbuff), "group ref"); + + vp = fr_dcursor_next(cursor); + fr_proto_da_stack_build(da_stack, vp ? vp->da : NULL); + + return fr_dbuff_set(dbuff, &work_dbuff); +} diff --git a/src/lib/util/encode.h b/src/lib/util/encode.h index e4f86db5d4f..cd61a117e08 100644 --- a/src/lib/util/encode.h +++ b/src/lib/util/encode.h @@ -46,6 +46,9 @@ ssize_t fr_pair_array_to_network(fr_dbuff_t *dbuff, fr_da_stack_t *da_stack, int ssize_t fr_pair_cursor_to_network(fr_dbuff_t *dbuff, fr_da_stack_t *da_stack, unsigned int depth, fr_dcursor_t *cursor, void *encode_ctx, fr_encode_dbuff_t encode_pair) CC_HINT(nonnull(1,2,4,6)); +ssize_t fr_pair_ref_to_network(fr_dbuff_t *dbuff, fr_da_stack_t *da_stack, unsigned int depth, + fr_dcursor_t *cursor) CC_HINT(nonnull); + #ifdef __cplusplus } #endif diff --git a/src/protocols/radius/encode.c b/src/protocols/radius/encode.c index 7ef6ff184dc..ea096786c91 100644 --- a/src/protocols/radius/encode.c +++ b/src/protocols/radius/encode.c @@ -41,10 +41,6 @@ static ssize_t encode_child(fr_dbuff_t *dbuff, fr_da_stack_t *da_stack, unsigned int depth, fr_dcursor_t *cursor, void *encode_ctx); -static ssize_t encode_group(fr_dbuff_t *dbuff, - fr_da_stack_t *da_stack, unsigned int depth, - fr_dcursor_t *cursor, void *encode_ctx); - /** "encrypt" a password RADIUS style * * Input and output buffers can be identical if in-place encryption is needed. @@ -353,7 +349,7 @@ static ssize_t encode_value(fr_dbuff_t *dbuff, */ if (da->type == FR_TYPE_TLV) return encode_tlv(dbuff, da_stack, depth, cursor, encode_ctx); - if (da->type == FR_TYPE_GROUP) return encode_group(dbuff, da_stack, depth, cursor, encode_ctx); + if (da->type == FR_TYPE_GROUP) return fr_pair_ref_to_network(dbuff, da_stack, depth, cursor); /* * Catch errors early on. @@ -607,52 +603,6 @@ static ssize_t encode_value(fr_dbuff_t *dbuff, return fr_dbuff_set(dbuff, &work_dbuff); } -static ssize_t encode_group(fr_dbuff_t *dbuff, - fr_da_stack_t *da_stack, unsigned int depth, - fr_dcursor_t *cursor, UNUSED void *encode_ctx) -{ - ssize_t slen; - fr_dict_attr_t const *da; - fr_pair_t const *vp = fr_dcursor_current(cursor); - fr_dbuff_t work_dbuff = FR_DBUFF(dbuff); - - fr_dict_attr_t const *ref; - fr_dict_protocol_t const *proto; - - FR_PROTO_STACK_PRINT(da_stack, depth); - - da = da_stack->da[depth]; - - ref = fr_dict_attr_ref(da); - if (!ref) { - fr_strerror_printf("Invalid attribute reference for %s", da->name); - return PAIR_ENCODE_SKIPPED; - } - - fr_assert(ref->dict != dict_radius); - - proto = fr_dict_protocol(ref->dict); - fr_assert(proto != NULL); - - if (!proto->encode) { - fr_strerror_printf("Attribute %s -> %s does not have an encoder", da->name, ref->name); - return PAIR_ENCODE_SKIPPED; - } - - /* - * The foreign functions don't take a cursor, so we have to update the cursor ourselves. - */ - slen = proto->encode(&work_dbuff, &vp->vp_group); - if (slen <= 0) return slen; - - FR_PROTO_HEX_DUMP(fr_dbuff_start(&work_dbuff), fr_dbuff_used(&work_dbuff), "group ref"); - - vp = fr_dcursor_next(cursor); - fr_proto_da_stack_build(da_stack, vp ? vp->da : NULL); - - return fr_dbuff_set(dbuff, &work_dbuff); -} - /** Breaks down large data into pieces, each with a header * * @param[out] data we're fragmenting.