From: Alan T. DeKok Date: Fri, 14 May 2021 14:42:05 +0000 (-0400) Subject: add fr_dict_export() X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b86c95ef0834dd92d3e128d2b2fa4e77139fa1db;p=thirdparty%2Ffreeradius-server.git add fr_dict_export() which (mostly) prints attributes out in the standard dictionary form. --- diff --git a/src/lib/util/dict.h b/src/lib/util/dict.h index 94ea7ec27b1..102bd853acb 100644 --- a/src/lib/util/dict.h +++ b/src/lib/util/dict.h @@ -424,6 +424,8 @@ void fr_dict_namespace_debug(fr_dict_attr_t const *da); void fr_dict_attr_debug(fr_dict_attr_t const *da); void fr_dict_debug(fr_dict_t const *dict); + +void fr_dict_export(fr_dict_t const *dict); /** @} */ /** @name Attribute lineage diff --git a/src/lib/util/dict_print.c b/src/lib/util/dict_print.c index a01d6d7491b..37c0b13dacb 100644 --- a/src/lib/util/dict_print.c +++ b/src/lib/util/dict_print.c @@ -74,7 +74,7 @@ ssize_t fr_dict_print_flags(fr_sbuff_t *out, fr_dict_t const *dict, fr_type_t ty return fr_sbuff_set(out, &our_out); } -/** Build the da_stack for the specified DA and encode the path in OID form +/** Build the da_stack for the specified DA and encode the path by name in OID form * * @param[out] out Where to write the OID. * @param[in] ancestor If not NULL, only print OID portion between ancestor and da. @@ -119,10 +119,56 @@ ssize_t fr_dict_attr_oid_print(fr_sbuff_t *out, fr_dict_attr_t const *ancestor, return fr_sbuff_set(out, &our_out); } +/** Build the da_stack for the specified DA and encode the numerical path in OID form + * + * @param[out] out Where to write the OID. + * @param[in] ancestor If not NULL, only print OID portion between ancestor and da. + * @param[in] da to print OID string for. + * @return + * - >0 The number of bytes written to the buffer. + * - <= 0 The number of bytes we would have needed to write the + * next OID component. + */ +static ssize_t dict_attr_oid_print_oid(fr_sbuff_t *out, fr_dict_attr_t const *ancestor, fr_dict_attr_t const *da) +{ + int i; + int depth = 0; + fr_da_stack_t da_stack; + fr_sbuff_t our_out = FR_SBUFF_NO_ADVANCE(out); + + /* + * If the ancestor and the DA match, there's + * no OID string to print. + */ + if ((ancestor == da) || (da->depth == 0)) return 0; + + fr_proto_da_stack_build(&da_stack, da); + + if (ancestor) { + if (da_stack.da[ancestor->depth - 1] != ancestor) { + fr_strerror_printf("Attribute '%s' is not a descendent of \"%s\"", da->name, ancestor->name); + return 0; + } + depth = ancestor->depth; + } + + /* + * We don't print the ancestor, we print the OID + * between it and the da. + */ + FR_SBUFF_IN_SPRINTF_RETURN(&our_out, "%u", da_stack.da[depth]->attr); + for (i = depth + 1; i < (int)da->depth; i++) { + FR_SBUFF_IN_CHAR_RETURN(&our_out, '.'); + FR_SBUFF_IN_SPRINTF_RETURN(&our_out, "%u", da_stack.da[i]->attr); + } + return fr_sbuff_set(out, &our_out); +} + typedef struct { fr_dict_t const *dict; char prefix[256]; char flags[256]; + char oid[256]; unsigned int start_depth; } fr_dict_attr_debug_t; @@ -201,3 +247,39 @@ void fr_dict_debug(fr_dict_t const *dict) { fr_dict_attr_debug(fr_dict_root(dict)); } + +static int dict_attr_export(fr_dict_attr_t const *da, void *uctx) +{ + fr_dict_attr_debug_t *our_uctx = uctx; + + (void) fr_dict_attr_oid_print(&FR_SBUFF_OUT(our_uctx->prefix, sizeof(our_uctx->prefix)), + NULL, da); + (void) dict_attr_oid_print_oid(&FR_SBUFF_OUT(our_uctx->oid, sizeof(our_uctx->oid)), + NULL, da); + fr_dict_print_flags(&FR_SBUFF_OUT(our_uctx->flags, sizeof(our_uctx->flags)), + our_uctx->dict, da->type, &da->flags); + + FR_FAULT_LOG("ATTRIBUTE\t%-40s\t%-20s\t%s\t%s", + our_uctx->prefix, + our_uctx->oid, + fr_table_str_by_value(fr_value_box_type_table, da->type, "???"), + our_uctx->flags); + + return 0; +} + +static void fr_dict_attr_export(fr_dict_attr_t const *da) +{ + fr_dict_attr_debug_t uctx = { .dict = fr_dict_by_da(da), .start_depth = da->depth }; + + dict_attr_export(da, &uctx); + (void)fr_dict_walk(da, dict_attr_export, &uctx); +} + +/** Export in the standard form: ATTRIBUTE name oid flags + * + */ +void fr_dict_export(fr_dict_t const *dict) +{ + fr_dict_attr_export(fr_dict_root(dict)); +}