From: Arran Cudbard-Bell Date: Thu, 26 Mar 2020 22:24:46 +0000 (-0600) Subject: enocders: Create a struct for da_stack which includes depth. X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=cab46e658e007141c8cb873c3555f7fb455d5457;p=thirdparty%2Ffreeradius-server.git enocders: Create a struct for da_stack which includes depth. Means we no longer have to memset the entire stack on each rebuild. --- diff --git a/src/lib/eap_aka_sim/encode.c b/src/lib/eap_aka_sim/encode.c index a5f315d08ee..262dddb4fe3 100644 --- a/src/lib/eap_aka_sim/encode.c +++ b/src/lib/eap_aka_sim/encode.c @@ -55,7 +55,7 @@ RCSID("$Id$") */ static ssize_t encode_tlv_hdr(uint8_t *out, size_t outlen, - fr_dict_attr_t const **da_stack, unsigned int depth, + fr_da_stack_t *da_stack, unsigned int depth, fr_cursor_t *cursor, void *encoder_ctx); static inline bool is_encodable(fr_dict_attr_t const *root, VALUE_PAIR *vp) @@ -295,18 +295,18 @@ static ssize_t encode_encrypted_value(uint8_t *out, size_t outlen, * < 0, failure. */ static ssize_t encode_value(uint8_t *out, size_t outlen, - fr_dict_attr_t const **da_stack, int depth, + fr_da_stack_t *da_stack, int depth, fr_cursor_t *cursor, void *encoder_ctx) { ssize_t len; VALUE_PAIR const *vp = fr_cursor_current(cursor); - fr_dict_attr_t const *da = da_stack[depth]; + fr_dict_attr_t const *da = da_stack->da[depth]; fr_aka_sim_encode_ctx_t *packet_ctx = encoder_ctx; VP_VERIFY(vp); FR_PROTO_STACK_PRINT(da_stack, depth); - if (unlikely(da_stack[depth + 1] != NULL)) { + if (unlikely(da_stack->da[depth + 1] != NULL)) { fr_strerror_printf("%s: Encoding value but not at top of stack", __FUNCTION__); return PAIR_ENCODE_FATAL_ERROR; } @@ -319,7 +319,7 @@ static ssize_t encode_value(uint8_t *out, size_t outlen, switch (da->type) { case FR_TYPE_STRUCTURAL: fr_strerror_printf("%s: Called with structural type %s", __FUNCTION__, - fr_table_str_by_value(fr_value_box_type_table, da_stack[depth]->type, "?Unknown?")); + fr_table_str_by_value(fr_value_box_type_table, da_stack->da[depth]->type, "?Unknown?")); return PAIR_ENCODE_FATAL_ERROR; default: @@ -607,7 +607,7 @@ done: * */ static ssize_t encode_array(uint8_t *out, size_t outlen, - fr_dict_attr_t const **da_stack, int depth, + fr_da_stack_t *da_stack, int depth, fr_cursor_t *cursor, void *encoder_ctx) { uint8_t *p = out, *end = p + outlen; @@ -615,7 +615,7 @@ static ssize_t encode_array(uint8_t *out, size_t outlen, size_t pad_len; size_t element_len; uint16_t actual_len; - fr_dict_attr_t const *da = da_stack[depth]; + fr_dict_attr_t const *da = da_stack->da[depth]; rad_assert(da->flags.array); p += 2; @@ -684,7 +684,7 @@ static ssize_t encode_array(uint8_t *out, size_t outlen, * If it's a standard attribute, then vp->da->attr == attribute. * Otherwise, attribute may be something else. */ -static ssize_t encode_rfc_hdr(uint8_t *out, size_t outlen, fr_dict_attr_t const **da_stack, unsigned int depth, +static ssize_t encode_rfc_hdr(uint8_t *out, size_t outlen, fr_da_stack_t *da_stack, unsigned int depth, fr_cursor_t *cursor, void *encoder_ctx) { size_t pad_len; @@ -694,17 +694,17 @@ static ssize_t encode_rfc_hdr(uint8_t *out, size_t outlen, fr_dict_attr_t const FR_PROTO_STACK_PRINT(da_stack, depth); - switch (da_stack[depth]->type) { + switch (da_stack->da[depth]->type) { case FR_TYPE_STRUCTURAL: fr_strerror_printf("%s: Called with structural type %s", __FUNCTION__, - fr_table_str_by_value(fr_value_box_type_table, da_stack[depth]->type, "?Unknown?")); + fr_table_str_by_value(fr_value_box_type_table, da_stack->da[depth]->type, "?Unknown?")); return PAIR_ENCODE_FATAL_ERROR; default: - if (((fr_dict_vendor_num_by_da(da_stack[depth]) == 0) && (da_stack[depth]->attr == 0)) || - (da_stack[depth]->attr > 255)) { + if (((fr_dict_vendor_num_by_da(da_stack->da[depth]) == 0) && (da_stack->da[depth]->attr == 0)) || + (da_stack->da[depth]->attr > 255)) { fr_strerror_printf("%s: Called with non-standard attribute %u", __FUNCTION__, - da_stack[depth]->attr); + da_stack->da[depth]->attr); return PAIR_ENCODE_FATAL_ERROR; } break; @@ -721,7 +721,7 @@ static ssize_t encode_rfc_hdr(uint8_t *out, size_t outlen, fr_dict_attr_t const * zero and fill any subfields like actual * length. */ - da = da_stack[depth]; + da = da_stack->da[depth]; p += 2; /* Leave space for attr + len */ if (da->flags.array) { @@ -752,13 +752,13 @@ static ssize_t encode_rfc_hdr(uint8_t *out, size_t outlen, fr_dict_attr_t const } static inline ssize_t encode_tlv_internal(uint8_t *out, size_t outlen, - fr_dict_attr_t const **da_stack, unsigned int depth, + fr_da_stack_t *da_stack, unsigned int depth, fr_cursor_t *cursor, void *encoder_ctx) { ssize_t slen; uint8_t *p = out, *end = p + outlen, *value; VALUE_PAIR const *vp = fr_cursor_current(cursor); - fr_dict_attr_t const *da = da_stack[depth]; + fr_dict_attr_t const *da = da_stack->da[depth]; CHECK_FREESPACE(outlen, 2); *p++ = 0; /* Reserved (0) */ @@ -779,7 +779,7 @@ static inline ssize_t encode_tlv_internal(uint8_t *out, size_t outlen, /* * Determine the nested type and call the appropriate encoder */ - if (da_stack[depth + 1]->type == FR_TYPE_TLV) { + if (da_stack->da[depth + 1]->type == FR_TYPE_TLV) { slen = encode_tlv_hdr(p, sublen, da_stack, depth + 1, cursor, encoder_ctx); } else { slen = encode_rfc_hdr(p, sublen, da_stack, depth + 1, cursor, encoder_ctx); @@ -798,7 +798,7 @@ static inline ssize_t encode_tlv_internal(uint8_t *out, size_t outlen, * rebuilding the TLV Stack, the attribute * at this depth is the same. */ - if (da != da_stack[depth]) break; + if ((da != da_stack->da[depth]) || (da_stack->depth < da->depth)) break; vp = fr_cursor_current(cursor); } @@ -819,7 +819,7 @@ static inline ssize_t encode_tlv_internal(uint8_t *out, size_t outlen, } static ssize_t encode_tlv_hdr(uint8_t *out, size_t outlen, - fr_dict_attr_t const **da_stack, unsigned int depth, + fr_da_stack_t *da_stack, unsigned int depth, fr_cursor_t *cursor, void *encoder_ctx) { unsigned int total_len; @@ -830,13 +830,13 @@ static ssize_t encode_tlv_hdr(uint8_t *out, size_t outlen, VP_VERIFY(fr_cursor_current(cursor)); FR_PROTO_STACK_PRINT(da_stack, depth); - if (da_stack[depth]->type != FR_TYPE_TLV) { + if (da_stack->da[depth]->type != FR_TYPE_TLV) { fr_strerror_printf("%s: Expected type \"tlv\" got \"%s\"", __FUNCTION__, - fr_table_str_by_value(fr_value_box_type_table, da_stack[depth]->type, "?Unknown?")); + fr_table_str_by_value(fr_value_box_type_table, da_stack->da[depth]->type, "?Unknown?")); return PAIR_ENCODE_FATAL_ERROR; } - if (!da_stack[depth + 1]) { + if (!da_stack->da[depth + 1]) { fr_strerror_printf("%s: Can't encode empty TLV", __FUNCTION__); return PAIR_ENCODE_FATAL_ERROR; } @@ -846,7 +846,7 @@ static ssize_t encode_tlv_hdr(uint8_t *out, size_t outlen, * The ASCII art in the RFCs the attributes in * this order. */ - if (!da_stack[depth]->flags.extra && da_stack[depth]->flags.subtype) { + if (!da_stack->da[depth]->flags.extra && da_stack->da[depth]->flags.subtype) { len = encode_iv(out, outlen, encoder_ctx); if (len < 0) return len; @@ -857,7 +857,7 @@ static ssize_t encode_tlv_hdr(uint8_t *out, size_t outlen, if (outlen < 4) return 0; if (outlen > SIM_MAX_ATTRIBUTE_VALUE_LEN) outlen = SIM_MAX_ATTRIBUTE_VALUE_LEN; - da = da_stack[depth]; + da = da_stack->da[depth]; len = encode_tlv_internal(p + 2, outlen - 2, da_stack, depth, cursor, encoder_ctx); if (len <= 0) return len; @@ -882,7 +882,7 @@ ssize_t fr_aka_sim_encode_pair(uint8_t *out, size_t outlen, fr_cursor_t *cursor, ssize_t slen; size_t attr_len; - fr_dict_attr_t const *da_stack[FR_DICT_MAX_TLV_STACK + 1]; + fr_da_stack_t da_stack; fr_dict_attr_t const *da = NULL; fr_aka_sim_encode_ctx_t *packet_ctx = encoder_ctx; @@ -916,30 +916,31 @@ ssize_t fr_aka_sim_encode_pair(uint8_t *out, size_t outlen, fr_cursor_t *cursor, * Fast path for the common case. */ if ((vp->da->parent == packet_ctx->root) && !vp->da->flags.concat && (vp->vp_type != FR_TYPE_TLV)) { - da_stack[0] = vp->da; - da_stack[1] = NULL; - FR_PROTO_STACK_PRINT(da_stack, 0); - return encode_rfc_hdr(out, attr_len, da_stack, 0, cursor, encoder_ctx); + da_stack.da[0] = vp->da; + da_stack.da[1] = NULL; + da_stack.depth = 1; + FR_PROTO_STACK_PRINT(&da_stack, 0); + return encode_rfc_hdr(out, attr_len, &da_stack, 0, cursor, encoder_ctx); } /* * Do more work to set up the stack for the complex case. */ - fr_proto_da_stack_build(da_stack, vp->da); - FR_PROTO_STACK_PRINT(da_stack, 0); + fr_proto_da_stack_build(&da_stack, vp->da); + FR_PROTO_STACK_PRINT(&da_stack, 0); - da = da_stack[0]; + da = da_stack.da[0]; switch (da->type) { /* * Supported types */ default: - slen = encode_rfc_hdr(out, attr_len, da_stack, 0, cursor, encoder_ctx); + slen = encode_rfc_hdr(out, attr_len, &da_stack, 0, cursor, encoder_ctx); break; case FR_TYPE_TLV: - slen = encode_tlv_hdr(out, attr_len, da_stack, 0, cursor, encoder_ctx); + slen = encode_tlv_hdr(out, attr_len, &da_stack, 0, cursor, encoder_ctx); break; } diff --git a/src/lib/server/snmp.c b/src/lib/server/snmp.c index 3b50b966c84..6feb84c2bf3 100644 --- a/src/lib/server/snmp.c +++ b/src/lib/server/snmp.c @@ -458,7 +458,7 @@ static fr_snmp_map_t snmp_iso[] = { }; static ssize_t snmp_process(fr_cursor_t *out, REQUEST *request, - fr_dict_attr_t const *da_stack[], unsigned int depth, + fr_da_stack_t *da_stack, unsigned int depth, fr_cursor_t *cursor, fr_snmp_map_t const *map, void *snmp_ctx, unsigned int snmp_op); @@ -509,20 +509,20 @@ static fr_snmp_map_t const *snmp_map_search(fr_snmp_map_t const map[], fr_dict_a * @param[in] depth at which to start rewriting. * @param[in] map at this level. */ -static void snmp_next_leaf(fr_dict_attr_t const *da_stack[], unsigned int depth, fr_snmp_map_t const *map) +static void snmp_next_leaf(fr_da_stack_t *da_stack, unsigned int depth, fr_snmp_map_t const *map) { uint32_t i; fr_snmp_map_t const *map_p = map; for (i = depth; (i < FR_DICT_MAX_TLV_STACK) && map_p; i++) { - da_stack[i] = map_p->da; + da_stack->da[i] = map_p->da; map_p = map_p->child; } - da_stack[i] = NULL; + da_stack->depth = i; } static ssize_t snmp_process_index(fr_cursor_t *out, REQUEST *request, - fr_dict_attr_t const *da_stack[], unsigned int depth, + fr_da_stack_t *da_stack, unsigned int depth, fr_cursor_t cursor, fr_snmp_map_t const *map, void *snmp_ctx, unsigned int snmp_op, uint32_t index_num) @@ -613,7 +613,7 @@ static ssize_t snmp_process_index(fr_cursor_t *out, REQUEST *request, } static ssize_t snmp_process_index_attr(fr_cursor_t *out, REQUEST *request, - fr_dict_attr_t const *da_stack[], unsigned int depth, + fr_da_stack_t *da_stack, unsigned int depth, fr_cursor_t *cursor, fr_snmp_map_t const *map, void *snmp_ctx, unsigned int snmp_op) { @@ -640,10 +640,10 @@ static ssize_t snmp_process_index_attr(fr_cursor_t *out, REQUEST *request, goto error; } - if (da_stack[depth]->type != FR_TYPE_UINT32) { + if (da_stack->da[depth]->type != FR_TYPE_UINT32) { fr_strerror_printf("Bad index attribute: Index attribute \"%s\" should be a integer, " - "but is a %s", da_stack[depth]->name, - fr_table_str_by_value(fr_value_box_type_table, da_stack[depth]->type, "?Unknown?")); + "but is a %s", da_stack->da[depth]->name, + fr_table_str_by_value(fr_value_box_type_table, da_stack->da[depth]->type, "?Unknown?")); goto error; } @@ -672,7 +672,7 @@ static ssize_t snmp_process_index_attr(fr_cursor_t *out, REQUEST *request, } static ssize_t snmp_process_tlv(fr_cursor_t *out, REQUEST *request, - fr_dict_attr_t const *da_stack[], unsigned int depth, + fr_da_stack_t *da_stack, unsigned int depth, fr_cursor_t *cursor, fr_snmp_map_t const *map, void *snmp_ctx, unsigned int snmp_op) { @@ -685,7 +685,7 @@ static ssize_t snmp_process_tlv(fr_cursor_t *out, REQUEST *request, * Return element in map that matches the da at this * level in the da_stack. */ - map_p = snmp_map_search(map, da_stack[depth]); + map_p = snmp_map_search(map, da_stack->da[depth]); if (!map_p) { invalid: fr_strerror_printf("Invalid OID: Match stopped here"); @@ -715,7 +715,7 @@ static ssize_t snmp_process_tlv(fr_cursor_t *out, REQUEST *request, da_stack, depth, *cursor, map_p, snmp_ctx, snmp_op, - da_stack[depth]->attr); + da_stack->da[depth]->attr); } for (;;) { @@ -734,7 +734,7 @@ static ssize_t snmp_process_tlv(fr_cursor_t *out, REQUEST *request, } static ssize_t snmp_process_leaf(fr_cursor_t *out, REQUEST *request, - fr_dict_attr_t const *da_stack[], unsigned int depth, + fr_da_stack_t *da_stack, unsigned int depth, fr_cursor_t *cursor, fr_snmp_map_t const *map, void *snmp_ctx, unsigned int snmp_op) { @@ -749,7 +749,7 @@ static ssize_t snmp_process_leaf(fr_cursor_t *out, REQUEST *request, * Return element in map that matches the da at this * level in the da_stack. */ - map_p = snmp_map_search(map, da_stack[depth]); + map_p = snmp_map_search(map, da_stack->da[depth]); if (!map_p) { fr_strerror_printf("Invalid OID: Match stopped here"); error: @@ -872,7 +872,7 @@ static ssize_t snmp_process_leaf(fr_cursor_t *out, REQUEST *request, * - <0 the depth at which an error occurred, as a negative integer. */ static ssize_t snmp_process(fr_cursor_t *out, REQUEST *request, - fr_dict_attr_t const *da_stack[], unsigned int depth, + fr_da_stack_t *da_stack, unsigned int depth, fr_cursor_t *cursor, fr_snmp_map_t const *map, void *snmp_ctx, unsigned int snmp_op) { @@ -885,7 +885,7 @@ static ssize_t snmp_process(fr_cursor_t *out, REQUEST *request, * we're performing a getNext operation, in which * case we fake the rest of the stack. */ - if (!da_stack[depth]) { + if (!da_stack->da[depth]) { if (snmp_op != FR_FREERADIUS_SNMP_OPERATION_VALUE_GETNEXT) { fr_strerror_printf("Invalid OID: Not a leaf"); return -(ssize_t)(depth - 1); @@ -897,20 +897,20 @@ static ssize_t snmp_process(fr_cursor_t *out, REQUEST *request, * It's an index attribute, use the value of * the index attribute to traverse the index. */ - if (da_stack[depth]->attr == 0) return snmp_process_index_attr(out, request, - da_stack, depth, - cursor, - map, snmp_ctx, snmp_op); + if (da_stack->da[depth]->attr == 0) return snmp_process_index_attr(out, request, + da_stack, depth, + cursor, + map, snmp_ctx, snmp_op); /* * It's a TLV, recurse, and locate the map * matching the next deepest DA in the * da_stack. */ - if (da_stack[depth]->type == FR_TYPE_TLV) return snmp_process_tlv(out, request, - da_stack, depth, - cursor, - map, snmp_ctx, snmp_op); + if (da_stack->da[depth]->type == FR_TYPE_TLV) return snmp_process_tlv(out, request, + da_stack, depth, + cursor, + map, snmp_ctx, snmp_op); /* * Must be a leaf, call the appropriate get/set function @@ -930,7 +930,7 @@ int fr_snmp_process(REQUEST *request) char oid_str[FR_DICT_MAX_TLV_STACK * 4]; /* .{1,3} */ size_t oid_len, len; - fr_dict_attr_t const *da_stack[FR_DICT_MAX_TLV_STACK + 1]; + fr_da_stack_t da_stack; unsigned int depth; ssize_t ret; @@ -986,20 +986,20 @@ int fr_snmp_process(REQUEST *request) for (vp = fr_cursor_iter_by_ancestor_init(&request_cursor, &request->packet->vps, attr_snmp_root); vp; vp = fr_cursor_next(&request_cursor)) { - fr_proto_da_stack_build(da_stack, vp->da); + fr_proto_da_stack_build(&da_stack, vp->da); /* * Wind to the frame in the TLV stack that matches our * SNMP root. */ - for (depth = 0; da_stack[depth]; depth++) if (attr_snmp_root == da_stack[depth]) break; + for (depth = 0; da_stack.da[depth]; depth++) if (attr_snmp_root == da_stack.da[depth]) break; /* * Any attribute returned by fr_cursor_next_by_ancestor * should have the SNMP root attribute as an ancestor. */ - rad_assert(da_stack[depth]); - rad_assert(da_stack[depth] == attr_snmp_root); + rad_assert(da_stack.da[depth]); + rad_assert(da_stack.da[depth] == attr_snmp_root); /* * Operator attribute acts as a request delimiter @@ -1027,7 +1027,7 @@ int fr_snmp_process(REQUEST *request) * Returns depth (as negative integer) at which the error occurred */ ret = snmp_process(&out_cursor, request, - da_stack, depth, + &da_stack, depth, &request_cursor, snmp_iso, NULL, op->vp_uint32); if (ret < 0) { @@ -1036,11 +1036,10 @@ int fr_snmp_process(REQUEST *request) oid_str[0] = '.'; /* Get the length of the matching part */ - oid_len = fr_dict_print_attr_oid(NULL, oid_str + 1, sizeof(oid_str) - 1, attr_snmp_root, da_stack[-(ret)]); + oid_len = fr_dict_print_attr_oid(NULL, oid_str + 1, sizeof(oid_str) - 1, attr_snmp_root, da_stack.da[-(ret)]); /* Get the last frame in the current stack */ - for (depth = 0; da_stack[depth + 1]; depth++); - len = fr_dict_print_attr_oid(NULL, oid_str + 1, sizeof(oid_str) - 1, attr_snmp_root, da_stack[depth]); + len = fr_dict_print_attr_oid(NULL, oid_str + 1, sizeof(oid_str) - 1, attr_snmp_root, da_stack.da[da_stack.depth - 1]); /* Use the difference in OID string length to place the marker */ REMARKER(oid_str, oid_len - (len - oid_len), "%s", fr_strerror()); diff --git a/src/lib/util/dict_print.c b/src/lib/util/dict_print.c index 67fb33878b8..6a7999cd735 100644 --- a/src/lib/util/dict_print.c +++ b/src/lib/util/dict_print.c @@ -120,7 +120,7 @@ size_t fr_dict_print_attr_oid(size_t *need, char *out, size_t outlen, char *p = out, *end = p + outlen; int i; int depth = 0; - fr_dict_attr_t const *da_stack[FR_DICT_MAX_TLV_STACK + 1]; + fr_da_stack_t da_stack; RETURN_IF_NO_SPACE_INIT(need, 1, p, out, end); @@ -133,10 +133,10 @@ size_t fr_dict_print_attr_oid(size_t *need, char *out, size_t outlen, return 0; } - fr_proto_da_stack_build(da_stack, da); + fr_proto_da_stack_build(&da_stack, da); if (ancestor) { - if (da_stack[ancestor->depth - 1] != 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 -1; } @@ -147,11 +147,11 @@ size_t fr_dict_print_attr_oid(size_t *need, char *out, size_t outlen, * We don't print the ancestor, we print the OID * between it and the da. */ - len = snprintf(p, end - p, "%u", da_stack[depth]->attr); + len = snprintf(p, end - p, "%u", da_stack.da[depth]->attr); RETURN_IF_TRUNCATED(need, len, p, out, end); for (i = depth + 1; i < (int)da->depth; i++) { - len = snprintf(p, end - p, ".%u", da_stack[i]->attr); + len = snprintf(p, end - p, ".%u", da_stack.da[i]->attr); RETURN_IF_TRUNCATED(need, len, p, out, end); } diff --git a/src/lib/util/pair.c b/src/lib/util/pair.c index d8d99c18e88..83b06a72016 100644 --- a/src/lib/util/pair.c +++ b/src/lib/util/pair.c @@ -831,8 +831,8 @@ int8_t fr_pair_cmp_by_parent_num_tag(void const *a, void const *b) VALUE_PAIR const *vp_b = b; fr_dict_attr_t const *da_a = vp_a->da; fr_dict_attr_t const *da_b = vp_b->da; - fr_dict_attr_t const *da_stack_a[FR_DICT_MAX_TLV_STACK + 1]; - fr_dict_attr_t const *da_stack_b[FR_DICT_MAX_TLV_STACK + 1]; + fr_da_stack_t da_stack_a; + fr_da_stack_t da_stack_b; int i; /* @@ -841,10 +841,10 @@ int8_t fr_pair_cmp_by_parent_num_tag(void const *a, void const *b) */ if ((da_a->parent->flags.is_root) && (da_b->parent->flags.is_root)) return pair_cmp_by_num_tag(vp_a, vp_b); - fr_proto_da_stack_build(da_stack_a, da_a); - fr_proto_da_stack_build(da_stack_b, da_b); + fr_proto_da_stack_build(&da_stack_a, da_a); + fr_proto_da_stack_build(&da_stack_b, da_b); - for (i = 0; (da_a = da_stack_a[i]) && (da_b = da_stack_b[i]); i++) { + for (i = 0; (da_a = da_stack_a.da[i]) && (da_b = da_stack_b.da[i]); i++) { if (da_a->attr > da_b->attr) return +1; if (da_a->attr < da_b->attr) return -1; } diff --git a/src/lib/util/proto.c b/src/lib/util/proto.c index e7414141cf1..18e2aeb7a57 100644 --- a/src/lib/util/proto.c +++ b/src/lib/util/proto.c @@ -54,41 +54,73 @@ void fr_proto_print_hex_data(char const *file, int line, uint8_t const *data, si } DIAG_ON(format-nonliteral) -void fr_proto_da_stack_print(char const *file, int line, char const *func, fr_dict_attr_t const **da_stack, unsigned int depth) +void fr_proto_da_stack_print(char const *file, int line, char const *func, fr_da_stack_t *da_stack, unsigned int depth) { - int i; - - for (i = 0; (i < FR_DICT_MAX_TLV_STACK) && da_stack[i]; i++); - if (!i) return; + int i = da_stack->depth; fr_log(&default_log, L_DBG, file, line, "stk: Currently in %s", func); for (i--; i >= 0; i--) { fr_log(&default_log, L_DBG, file, line, "stk: %s [%i] %s: %s, vendor: 0x%x (%u), attr: 0x%x (%u)", (i == (int)depth) ? ">" : " ", i, - fr_table_str_by_value(fr_value_box_type_table, da_stack[i]->type, "?Unknown?"), - da_stack[i]->name, - fr_dict_vendor_num_by_da(da_stack[i]), fr_dict_vendor_num_by_da(da_stack[i]), - da_stack[i]->attr, da_stack[i]->attr); + fr_table_str_by_value(fr_value_box_type_table, da_stack->da[i]->type, "?Unknown?"), + da_stack->da[i]->name, + fr_dict_vendor_num_by_da(da_stack->da[i]), fr_dict_vendor_num_by_da(da_stack->da[i]), + da_stack->da[i]->attr, da_stack->da[i]->attr); } fr_log(&default_log, L_DBG, file, line, "stk:"); } -void fr_proto_da_stack_build(fr_dict_attr_t const **da_stack, fr_dict_attr_t const *da) +/** Build a complete TLV stack from the da back to the root + * + * @param[out] stack to populate. + * @param[in] da to build the stack for. + */ +void fr_proto_da_stack_build(fr_da_stack_t *stack, fr_dict_attr_t const *da) { - int i; - fr_dict_attr_t const *da_p; - - memset(da_stack, 0, sizeof(*da_stack) * (FR_DICT_MAX_TLV_STACK + 1)); + fr_dict_attr_t const *da_p, **da_o; if (!da) return; - /* - * We've finished encoding one nested structure - * now we need to rebuild the da_stack and determine - * where the common point is. - */ - for (i = da->depth, da_p = da; - da_p->parent && (i >= 0); - i--, da_p = da_p->parent) da_stack[i - 1] = da_p; + da_p = da; + da_o = stack->da + (da->depth - 1); + + while (da_o >= stack->da) { + *da_o-- = da_p; + da_p = da_p->parent; + } + + stack->depth = da->depth; + stack->da[stack->depth] = NULL; +} + +/** Complete the tlv stack for a child attribute + * + * @param[out] stack to populate. + * @param[in] parent to populate from. + * @param[in] da to populate to. + */ +void fr_proto_da_stack_partial_build(fr_da_stack_t *stack, fr_dict_attr_t const *parent, fr_dict_attr_t const *da) +{ + fr_dict_attr_t const *da_p, **da_q, **da_o; + +#ifndef NDEBUG + if (!fr_cond_assert(fr_dict_parent_common(parent, da, true) == parent)) { + fr_strerror_printf("Expected \"%s\" to be a descendent of \"%s\" but it isn't", + da->name, parent->name); + return; + } +#endif + + da_p = da; + da_q = stack->da + (parent->depth - 1); + da_o = stack->da + (da->depth - 1); + + while (da_o >= da_q) { + *da_o-- = da_p; + da_p = da_p->parent; + } + + stack->depth = da->depth; + stack->da[stack->depth] = NULL; } diff --git a/src/lib/util/proto.h b/src/lib/util/proto.h index 47c0b910843..e08bea8d1ac 100644 --- a/src/lib/util/proto.h +++ b/src/lib/util/proto.h @@ -46,13 +46,22 @@ do { \ # define FR_PROTO_STACK_PRINT(_x, _y) #endif +/** Structure for holding the stack of dictionary attributes being encoded + * + */ +typedef struct { + fr_dict_attr_t const *da[FR_DICT_MAX_TLV_STACK + 1]; //!< The stack. + uint8_t depth; //!< Deepest attribute in the stack. +} fr_da_stack_t; void fr_proto_print(char const *file, int line, char const *fmt, ...) CC_HINT(format (printf, 3, 4)); void fr_proto_print_hex_data(char const *file, int line, uint8_t const *data, size_t data_len, char const *fmt, ...); -void fr_proto_da_stack_print(char const *file, int line, char const *func, fr_dict_attr_t const **da_stack, unsigned int depth); +void fr_proto_da_stack_print(char const *file, int line, char const *func, fr_da_stack_t *da_stack, unsigned int depth); + +void fr_proto_da_stack_build(fr_da_stack_t *stack, fr_dict_attr_t const *da); -void fr_proto_da_stack_build(fr_dict_attr_t const **da_stack, fr_dict_attr_t const *da); +void fr_proto_da_stack_partial_build(fr_da_stack_t *stack, fr_dict_attr_t const *parent, fr_dict_attr_t const *da); #ifdef __cplusplus } diff --git a/src/lib/util/struct.c b/src/lib/util/struct.c index 08fe7774fc3..e28fe116295 100644 --- a/src/lib/util/struct.c +++ b/src/lib/util/struct.c @@ -411,7 +411,7 @@ static int put_bits(uint8_t *p, uint8_t const *end, int start_bit, int num_bits, ssize_t fr_struct_to_network(uint8_t *out, size_t outlen, - fr_dict_attr_t const **da_stack, unsigned int depth, + fr_da_stack_t *da_stack, unsigned int depth, fr_cursor_t *cursor, void *encoder_ctx, fr_encode_value_t encode_value) { @@ -429,7 +429,7 @@ ssize_t fr_struct_to_network(uint8_t *out, size_t outlen, } VP_VERIFY(vp); - parent = da_stack[depth]; + parent = da_stack->da[depth]; if (parent->type != FR_TYPE_STRUCT) { fr_strerror_printf("%s: Expected type \"struct\" got \"%s\"", __FUNCTION__, diff --git a/src/lib/util/struct.h b/src/lib/util/struct.h index 31c815bf206..ea3d65e9c9d 100644 --- a/src/lib/util/struct.h +++ b/src/lib/util/struct.h @@ -26,6 +26,7 @@ RCSIDH(struct_h, "$Id$") #include #include #include +#include #ifdef __cplusplus extern "C" { @@ -40,10 +41,10 @@ ssize_t fr_struct_from_network(TALLOC_CTX *ctx, fr_cursor_t *cursor, fr_dict_attr_t const **child, fr_decode_value_t decode_value, void *decoder_ctx) CC_HINT(nonnull(2,3,4)); -typedef ssize_t (*fr_encode_value_t)(uint8_t *out, size_t outlen, fr_dict_attr_t const **da_stack, unsigned int depth, +typedef ssize_t (*fr_encode_value_t)(uint8_t *out, size_t outlen, fr_da_stack_t *da_stack, unsigned int depth, fr_cursor_t *cursor, void *encoder_ctx); -ssize_t fr_struct_to_network(uint8_t *out, size_t outlen, fr_dict_attr_t const **da_stack, unsigned int depth, +ssize_t fr_struct_to_network(uint8_t *out, size_t outlen, fr_da_stack_t *da_stack, unsigned int depth, fr_cursor_t *cursor, void *encoder_ctx, fr_encode_value_t encode_value) CC_HINT(nonnull(1,3,5)); diff --git a/src/protocols/dhcpv4/encode.c b/src/protocols/dhcpv4/encode.c index 600cc7fc531..1d13aad7bbf 100644 --- a/src/protocols/dhcpv4/encode.c +++ b/src/protocols/dhcpv4/encode.c @@ -95,7 +95,7 @@ static inline VALUE_PAIR *first_encodable(fr_cursor_t *cursor, void *encoder_ctx * - -2 if unsupported type. */ static ssize_t encode_value(uint8_t *out, size_t outlen, - fr_dict_attr_t const **da_stack, unsigned int depth, + fr_da_stack_t *da_stack, unsigned int depth, fr_cursor_t *cursor, fr_dhcpv4_ctx_t *encoder_ctx) { VALUE_PAIR *vp = fr_cursor_current(cursor); @@ -108,7 +108,7 @@ static ssize_t encode_value(uint8_t *out, size_t outlen, if (outlen < vp->vp_length) return -1; /* Not enough output buffer space. */ - switch (da_stack[depth]->type) { + switch (da_stack->da[depth]->type) { case FR_TYPE_BOOL: case FR_TYPE_UINT8: case FR_TYPE_UINT16: @@ -250,13 +250,13 @@ static uint8_t *extend_option(uint8_t *start, uint8_t *end, uint8_t *p, int len) * - < 0 on error. */ static ssize_t encode_rfc_hdr(uint8_t *out, ssize_t outlen, - fr_dict_attr_t const **da_stack, unsigned int depth, + fr_da_stack_t *da_stack, unsigned int depth, fr_cursor_t *cursor, fr_dhcpv4_ctx_t *encoder_ctx) { ssize_t len; uint8_t *p = out; uint8_t *start, *end; - fr_dict_attr_t const *da = da_stack[depth]; + fr_dict_attr_t const *da = da_stack->da[depth]; VALUE_PAIR *vp = fr_cursor_current(cursor); if (outlen < 3) return 0; /* No space */ @@ -346,14 +346,14 @@ static ssize_t encode_rfc_hdr(uint8_t *out, ssize_t outlen, * - < 0 on error. */ static ssize_t encode_tlv_hdr(uint8_t *out, ssize_t outlen, - fr_dict_attr_t const **da_stack, unsigned int depth, + fr_da_stack_t *da_stack, unsigned int depth, fr_cursor_t *cursor, fr_dhcpv4_ctx_t *encoder_ctx) { ssize_t len; uint8_t *p = out; uint8_t *start, *end; VALUE_PAIR const *vp = fr_cursor_current(cursor); - fr_dict_attr_t const *da = da_stack[depth]; + fr_dict_attr_t const *da = da_stack->da[depth]; if (outlen < 5) return 0; /* No space */ @@ -376,7 +376,7 @@ static ssize_t encode_tlv_hdr(uint8_t *out, ssize_t outlen, /* * Determine the nested type and call the appropriate encoder */ - if (da_stack[depth + 1]->type == FR_TYPE_TLV) { + if (da_stack->da[depth + 1]->type == FR_TYPE_TLV) { len = encode_tlv_hdr(p, end - p, da_stack, depth + 1, cursor, encoder_ctx); } else { len = encode_rfc_hdr(p, end - p, da_stack, depth + 1, cursor, encoder_ctx); @@ -452,7 +452,7 @@ static ssize_t encode_tlv_hdr(uint8_t *out, ssize_t outlen, * rebuilding the TLV Stack, the attribute * at this depth is the same. */ - if (da != da_stack[depth]) break; + if ((da != da_stack->da[depth]) || (da_stack->depth < da->depth)) break; vp = fr_cursor_current(cursor); } @@ -475,7 +475,7 @@ ssize_t fr_dhcpv4_encode_option(uint8_t *out, size_t outlen, fr_cursor_t *cursor { VALUE_PAIR *vp; unsigned int depth = 0; - fr_dict_attr_t const *da_stack[FR_DICT_MAX_TLV_STACK + 1]; + fr_da_stack_t da_stack; ssize_t len; vp = first_encodable(cursor, encoder_ctx); @@ -489,20 +489,20 @@ ssize_t fr_dhcpv4_encode_option(uint8_t *out, size_t outlen, fr_cursor_t *cursor return 0; } - fr_proto_da_stack_build(da_stack, vp->da); + fr_proto_da_stack_build(&da_stack, vp->da); - FR_PROTO_STACK_PRINT(da_stack, depth); + FR_PROTO_STACK_PRINT(&da_stack, depth); /* * We only have two types of options in DHCPv4 */ - switch (da_stack[depth]->type) { + switch (da_stack.da[depth]->type) { case FR_TYPE_TLV: - len = encode_tlv_hdr(out, outlen, da_stack, depth, cursor, encoder_ctx); + len = encode_tlv_hdr(out, outlen, &da_stack, depth, cursor, encoder_ctx); break; default: - len = encode_rfc_hdr(out, outlen, da_stack, depth, cursor, encoder_ctx); + len = encode_rfc_hdr(out, outlen, &da_stack, depth, cursor, encoder_ctx); break; } diff --git a/src/protocols/dhcpv6/encode.c b/src/protocols/dhcpv6/encode.c index f3cf3e9271d..032943fa63c 100644 --- a/src/protocols/dhcpv6/encode.c +++ b/src/protocols/dhcpv6/encode.c @@ -39,15 +39,15 @@ #include "attrs.h" static ssize_t encode_value(uint8_t *out, size_t outlen, - fr_dict_attr_t const **da_stack, unsigned int depth, + fr_da_stack_t *da_stack, unsigned int depth, fr_cursor_t *cursor, void *encoder_ctx); static ssize_t encode_rfc_hdr(uint8_t *out, size_t outlen, - fr_dict_attr_t const **da_stack, unsigned int depth, + fr_da_stack_t *da_stack, unsigned int depth, fr_cursor_t *cursor, void *encoder_ctx); static ssize_t encode_tlv_hdr(uint8_t *out, size_t outlen, - fr_dict_attr_t const **da_stack, unsigned int depth, + fr_da_stack_t *da_stack, unsigned int depth, fr_cursor_t *cursor, void *encoder_ctx); static inline bool is_encodable(fr_dict_attr_t const *root, VALUE_PAIR const *vp) @@ -133,19 +133,19 @@ static inline ssize_t encode_option_hdr(uint8_t *out, size_t outlen, uint16_t op } static ssize_t encode_struct(uint8_t *out, size_t outlen, - fr_dict_attr_t const **da_stack, unsigned int depth, + fr_da_stack_t *da_stack, unsigned int depth, fr_cursor_t *cursor, void *encoder_ctx) { VP_VERIFY(fr_cursor_current(cursor)); FR_PROTO_STACK_PRINT(da_stack, depth); - if (da_stack[depth]->type != FR_TYPE_STRUCT) { + if (da_stack->da[depth]->type != FR_TYPE_STRUCT) { fr_strerror_printf("%s: Expected type \"struct\" got \"%s\"", __FUNCTION__, - fr_table_str_by_value(fr_value_box_type_table, da_stack[depth]->type, "?Unknown?")); + fr_table_str_by_value(fr_value_box_type_table, da_stack->da[depth]->type, "?Unknown?")); return PAIR_ENCODE_FATAL_ERROR; } - if (!da_stack[depth + 1]) { + if (!da_stack->da[depth + 1]) { fr_strerror_printf("%s: Can't encode empty struct", __FUNCTION__); return PAIR_ENCODE_FATAL_ERROR; } @@ -154,13 +154,13 @@ static ssize_t encode_struct(uint8_t *out, size_t outlen, } static ssize_t encode_value(uint8_t *out, size_t outlen, - fr_dict_attr_t const **da_stack, unsigned int depth, + fr_da_stack_t *da_stack, unsigned int depth, fr_cursor_t *cursor, void *encoder_ctx) { ssize_t slen; uint8_t *p = out, *end = p + outlen; VALUE_PAIR const *vp = fr_cursor_current(cursor); - fr_dict_attr_t const *da = da_stack[depth]; + fr_dict_attr_t const *da = da_stack->da[depth]; VP_VERIFY(vp); FR_PROTO_STACK_PRINT(da_stack, depth); @@ -193,7 +193,7 @@ static ssize_t encode_value(uint8_t *out, size_t outlen, * If it's not a TLV, it should be a value type RFC * attribute make sure that it is. */ - if (da_stack[depth + 1] != NULL) { + if (da_stack->da[depth + 1] != NULL) { fr_strerror_printf("%s: Encoding value but not at top of stack", __FUNCTION__); return PAIR_ENCODE_FATAL_ERROR; } @@ -479,14 +479,14 @@ static ssize_t encode_value(uint8_t *out, size_t outlen, } static inline ssize_t encode_array(uint8_t *out, size_t outlen, - fr_dict_attr_t const **da_stack, int depth, + fr_da_stack_t *da_stack, int depth, fr_cursor_t *cursor, void *encoder_ctx) { uint8_t *p = out, *end = p + outlen; ssize_t slen; size_t element_len; VALUE_PAIR *vp; - fr_dict_attr_t const *da = da_stack[depth]; + fr_dict_attr_t const *da = da_stack->da[depth]; if (!fr_cond_assert_msg(da->flags.array, "%s: Internal sanity check failed, attribute \"%s\" does not have array bit set", @@ -559,7 +559,7 @@ static inline ssize_t encode_array(uint8_t *out, size_t outlen, * Populate the length field */ if (len_field) *len_field = htons((uint16_t) slen); - + vp = fr_cursor_current(cursor); if (!vp || (vp->da != da)) break; /* Stop if we have an attribute of a different type */ } @@ -568,13 +568,13 @@ static inline ssize_t encode_array(uint8_t *out, size_t outlen, } static ssize_t encode_tlv(uint8_t *out, size_t outlen, - fr_dict_attr_t const **da_stack, unsigned int depth, + fr_da_stack_t *da_stack, unsigned int depth, fr_cursor_t *cursor, void *encoder_ctx) { ssize_t slen; uint8_t *p = out, *end = p + outlen; VALUE_PAIR const *vp = fr_cursor_current(cursor); - fr_dict_attr_t const *da = da_stack[depth]; + fr_dict_attr_t const *da = da_stack->da[depth]; CHECK_FREESPACE(outlen, OPT_HDR_LEN); @@ -584,7 +584,7 @@ static ssize_t encode_tlv(uint8_t *out, size_t outlen, /* * Determine the nested type and call the appropriate encoder */ - if (da_stack[depth + 1]->type == FR_TYPE_TLV) { + if (da_stack->da[depth + 1]->type == FR_TYPE_TLV) { slen = encode_tlv_hdr(p, end - p, da_stack, depth + 1, cursor, encoder_ctx); } else { slen = encode_rfc_hdr(p, end - p, da_stack, depth + 1, cursor, encoder_ctx); @@ -603,7 +603,7 @@ static ssize_t encode_tlv(uint8_t *out, size_t outlen, * rebuilding the TLV Stack, the attribute * at this depth is the same. */ - if (da != da_stack[depth]) break; + if ((da != da_stack->da[depth]) || (da_stack->depth < da->depth)) break; vp = fr_cursor_current(cursor); } @@ -621,12 +621,12 @@ static ssize_t encode_tlv(uint8_t *out, size_t outlen, * Otherwise, attribute may be something else. */ static ssize_t encode_rfc_hdr(uint8_t *out, size_t outlen, - fr_dict_attr_t const **da_stack, unsigned int depth, + fr_da_stack_t *da_stack, unsigned int depth, fr_cursor_t *cursor, void *encoder_ctx) { uint8_t *p = out, *end = p + outlen; ssize_t slen; - fr_dict_attr_t const *da = da_stack[depth]; + fr_dict_attr_t const *da = da_stack->da[depth]; FR_PROTO_STACK_PRINT(da_stack, depth); @@ -662,23 +662,23 @@ static ssize_t encode_rfc_hdr(uint8_t *out, size_t outlen, } static ssize_t encode_tlv_hdr(uint8_t *out, size_t outlen, - fr_dict_attr_t const **da_stack, unsigned int depth, + fr_da_stack_t *da_stack, unsigned int depth, fr_cursor_t *cursor, void *encoder_ctx) { ssize_t slen; uint8_t *p = out, *end = p + outlen; - fr_dict_attr_t const *da = da_stack[depth]; + fr_dict_attr_t const *da = da_stack->da[depth]; VP_VERIFY(fr_cursor_current(cursor)); FR_PROTO_STACK_PRINT(da_stack, depth); - if (da_stack[depth]->type != FR_TYPE_TLV) { + if (da_stack->da[depth]->type != FR_TYPE_TLV) { fr_strerror_printf("%s: Expected type \"tlv\" got \"%s\"", __FUNCTION__, - fr_table_str_by_value(fr_value_box_type_table, da_stack[depth]->type, "?Unknown?")); + fr_table_str_by_value(fr_value_box_type_table, da_stack->da[depth]->type, "?Unknown?")); return PAIR_ENCODE_FATAL_ERROR; } - if (!da_stack[depth + 1]) { + if (!da_stack->da[depth + 1]) { fr_strerror_printf("%s: Can't encode empty TLV", __FUNCTION__); return PAIR_ENCODE_FATAL_ERROR; } @@ -722,13 +722,13 @@ static ssize_t encode_tlv_hdr(uint8_t *out, size_t outlen, * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ static ssize_t encode_vsio_hdr(uint8_t *out, size_t outlen, - fr_dict_attr_t const **da_stack, unsigned int depth, + fr_da_stack_t *da_stack, unsigned int depth, fr_cursor_t *cursor, void *encoder_ctx) { ssize_t slen; uint32_t pen; uint8_t *p = out, *end = p + outlen; - fr_dict_attr_t const *da = da_stack[depth]; + fr_dict_attr_t const *da = da_stack->da[depth]; fr_dict_attr_t const *dv; FR_PROTO_STACK_PRINT(da_stack, depth); @@ -751,7 +751,7 @@ static ssize_t encode_vsio_hdr(uint8_t *out, size_t outlen, /* * Now process the vendor ID part (which is one attribute deeper) */ - dv = da_stack[++depth]; + dv = da_stack->da[++depth]; FR_PROTO_STACK_PRINT(da_stack, depth); if (dv->type != FR_TYPE_VENDOR) { @@ -828,7 +828,7 @@ ssize_t fr_dhcpv6_encode_option(uint8_t *out, size_t outlen, fr_cursor_t *cursor { VALUE_PAIR *vp; unsigned int depth = 0; - fr_dict_attr_t const *da_stack[FR_DICT_MAX_TLV_STACK + 1]; + fr_da_stack_t da_stack; ssize_t slen; vp = first_encodable(cursor, encoder_ctx); @@ -840,9 +840,9 @@ ssize_t fr_dhcpv6_encode_option(uint8_t *out, size_t outlen, fr_cursor_t *cursor return PAIR_ENCODE_SKIPPED; } - fr_proto_da_stack_build(da_stack, vp->da); + fr_proto_da_stack_build(&da_stack, vp->da); - FR_PROTO_STACK_PRINT(da_stack, depth); + FR_PROTO_STACK_PRINT(&da_stack, depth); /* * Trim output buffer size for sanity @@ -852,17 +852,17 @@ ssize_t fr_dhcpv6_encode_option(uint8_t *out, size_t outlen, fr_cursor_t *cursor /* * Deal with nested options */ - switch (da_stack[depth]->type) { + switch (da_stack.da[depth]->type) { case FR_TYPE_TLV: - slen = encode_tlv_hdr(out, outlen, da_stack, depth, cursor, encoder_ctx); + slen = encode_tlv_hdr(out, outlen, &da_stack, depth, cursor, encoder_ctx); break; case FR_TYPE_VSA: - slen = encode_vsio_hdr(out, outlen, da_stack, depth, cursor, encoder_ctx); + slen = encode_vsio_hdr(out, outlen, &da_stack, depth, cursor, encoder_ctx); break; default: - slen = encode_rfc_hdr(out, outlen, da_stack, depth, cursor, encoder_ctx); + slen = encode_rfc_hdr(out, outlen, &da_stack, depth, cursor, encoder_ctx); break; } diff --git a/src/protocols/radius/encode.c b/src/protocols/radius/encode.c index e7b115d8c42..d43d27db039 100644 --- a/src/protocols/radius/encode.c +++ b/src/protocols/radius/encode.c @@ -31,15 +31,15 @@ RCSID("$Id$") #include "attrs.h" static ssize_t encode_value(uint8_t *out, size_t outlen, - fr_dict_attr_t const **da_stack, unsigned int depth, + fr_da_stack_t *da_stack, unsigned int depth, fr_cursor_t *cursor, void *encoder_ctx); static ssize_t encode_rfc_hdr_internal(uint8_t *out, size_t outlen, - fr_dict_attr_t const **da_stack, unsigned int depth, + fr_da_stack_t *da_stack, unsigned int depth, fr_cursor_t *cursor, void *encoder_ctx); static ssize_t encode_tlv_hdr(uint8_t *out, size_t outlen, - fr_dict_attr_t const **da_stack, unsigned int depth, + fr_da_stack_t *da_stack, unsigned int depth, fr_cursor_t *cursor, void *encoder_ctx); @@ -266,13 +266,13 @@ static void encode_tunnel_password(uint8_t *out, ssize_t *outlen, } static ssize_t encode_tlv_hdr_internal(uint8_t *out, size_t outlen, - fr_dict_attr_t const **da_stack, unsigned int depth, + fr_da_stack_t *da_stack, unsigned int depth, fr_cursor_t *cursor, void *encoder_ctx) { ssize_t len; uint8_t *p = out; VALUE_PAIR const *vp = fr_cursor_current(cursor); - fr_dict_attr_t const *da = da_stack[depth]; + fr_dict_attr_t const *da = da_stack->da[depth]; while (outlen >= 5) { size_t sublen; @@ -288,7 +288,7 @@ static ssize_t encode_tlv_hdr_internal(uint8_t *out, size_t outlen, /* * Determine the nested type and call the appropriate encoder */ - if (da_stack[depth + 1]->type == FR_TYPE_TLV) { + if (da_stack->da[depth + 1]->type == FR_TYPE_TLV) { len = encode_tlv_hdr(p, sublen, da_stack, depth + 1, cursor, encoder_ctx); } else { len = encode_rfc_hdr_internal(p, sublen, da_stack, depth + 1, cursor, encoder_ctx); @@ -309,7 +309,7 @@ static ssize_t encode_tlv_hdr_internal(uint8_t *out, size_t outlen, * rebuilding the TLV Stack, the attribute * at this depth is the same. */ - if (da != da_stack[depth]) break; + if ((da != da_stack->da[depth]) || (da_stack->depth < da->depth)) break; vp = fr_cursor_current(cursor); } @@ -317,7 +317,7 @@ static ssize_t encode_tlv_hdr_internal(uint8_t *out, size_t outlen, } static ssize_t encode_tlv_hdr(uint8_t *out, size_t outlen, - fr_dict_attr_t const **da_stack, unsigned int depth, + fr_da_stack_t *da_stack, unsigned int depth, fr_cursor_t *cursor, void *encoder_ctx) { ssize_t len; @@ -325,13 +325,13 @@ static ssize_t encode_tlv_hdr(uint8_t *out, size_t outlen, VP_VERIFY(fr_cursor_current(cursor)); FR_PROTO_STACK_PRINT(da_stack, depth); - if (da_stack[depth]->type != FR_TYPE_TLV) { + if (da_stack->da[depth]->type != FR_TYPE_TLV) { fr_strerror_printf("%s: Expected type \"tlv\" got \"%s\"", __FUNCTION__, - fr_table_str_by_value(fr_value_box_type_table, da_stack[depth]->type, "?Unknown?")); + fr_table_str_by_value(fr_value_box_type_table, da_stack->da[depth]->type, "?Unknown?")); return -1; } - if (!da_stack[depth + 1]) { + if (!da_stack->da[depth + 1]) { fr_strerror_printf("%s: Can't encode empty TLV", __FUNCTION__); return -1; } @@ -341,7 +341,7 @@ static ssize_t encode_tlv_hdr(uint8_t *out, size_t outlen, /* * Encode the first level of TLVs */ - out[0] = da_stack[depth]->attr & 0xff; + out[0] = da_stack->da[depth]->attr & 0xff; out[1] = 2; /* TLV header */ if (outlen > 255) outlen = 255; @@ -362,7 +362,7 @@ static ssize_t encode_tlv_hdr(uint8_t *out, size_t outlen, * < 0, failure. */ static ssize_t encode_value(uint8_t *out, size_t outlen, - fr_dict_attr_t const **da_stack, unsigned int depth, + fr_da_stack_t *da_stack, unsigned int depth, fr_cursor_t *cursor, void *encoder_ctx) { size_t offset; @@ -371,7 +371,7 @@ static ssize_t encode_value(uint8_t *out, size_t outlen, uint8_t *ptr = out; uint8_t buffer[64]; VALUE_PAIR const *vp = fr_cursor_current(cursor); - fr_dict_attr_t const *da = da_stack[depth]; + fr_dict_attr_t const *da = da_stack->da[depth]; fr_radius_ctx_t *packet_ctx = encoder_ctx; VP_VERIFY(vp); @@ -420,7 +420,7 @@ static ssize_t encode_value(uint8_t *out, size_t outlen, * TLV to be encoded here. It's number is just * the field number in the struct. */ - while (vp && (da_stack[depth] == da) && (outlen > 0)) { + while (vp && (da_stack->da[depth] == da) && (da_stack->depth >= da->depth) && (outlen > 0)) { len = encode_tlv_hdr_internal(out, outlen, da_stack, depth + 1, cursor, encoder_ctx); if (len < 0) return len; @@ -437,7 +437,7 @@ static ssize_t encode_value(uint8_t *out, size_t outlen, * If it's not a TLV, it should be a value type RFC * attribute make sure that it is. */ - if (da_stack[depth + 1] != NULL) { + if (da_stack->da[depth + 1] != NULL) { fr_strerror_printf("%s: Encoding value but not at top of stack", __FUNCTION__); return -1; } @@ -450,7 +450,7 @@ static ssize_t encode_value(uint8_t *out, size_t outlen, switch (da->type) { case FR_TYPE_STRUCTURAL: fr_strerror_printf("%s: Called with structural type %s", __FUNCTION__, - fr_table_str_by_value(fr_value_box_type_table, da_stack[depth]->type, "?Unknown?")); + fr_table_str_by_value(fr_value_box_type_table, da_stack->da[depth]->type, "?Unknown?")); return -1; default: @@ -693,7 +693,7 @@ static ssize_t attr_shift(uint8_t const *start, uint8_t const *end, * */ static int encode_extended_hdr(uint8_t *out, size_t outlen, - fr_dict_attr_t const **da_stack, unsigned int depth, + fr_da_stack_t *da_stack, unsigned int depth, fr_cursor_t *cursor, void *encoder_ctx) { int len; @@ -709,14 +709,14 @@ static int encode_extended_hdr(uint8_t *out, size_t outlen, VP_VERIFY(vp); FR_PROTO_STACK_PRINT(da_stack, depth); - extra = (!da_stack[0]->flags.extra && (da_stack[0]->flags.subtype == FLAG_EXTENDED_ATTR)); + extra = (!da_stack->da[0]->flags.extra && (da_stack->da[0]->flags.subtype == FLAG_EXTENDED_ATTR)); /* * @fixme: check depth of stack */ - attr_type = da_stack[0]->type; + attr_type = da_stack->da[0]->type; #ifndef NDEBUG - vsa_type = da_stack[1]->type; + vsa_type = da_stack->da[1]->type; if (fr_debug_lvl > 3) { jump += extra; } @@ -732,9 +732,9 @@ static int encode_extended_hdr(uint8_t *out, size_t outlen, /* * Encode which extended attribute it is. */ - out[0] = da_stack[depth++]->attr & 0xff; + out[0] = da_stack->da[depth++]->attr & 0xff; out[1] = 3 + extra; - out[2] = da_stack[depth]->attr & 0xff; + out[2] = da_stack->da[depth]->attr & 0xff; if (extra) out[3] = 0; /* flags start off at zero */ break; @@ -742,7 +742,7 @@ static int encode_extended_hdr(uint8_t *out, size_t outlen, default: fr_strerror_printf("%s : Called for non-extended attribute type %s", __FUNCTION__, fr_table_str_by_value(fr_value_box_type_table, - da_stack[depth]->type, "?Unknown?")); + da_stack->da[depth]->type, "?Unknown?")); return -1; } @@ -751,7 +751,7 @@ static int encode_extended_hdr(uint8_t *out, size_t outlen, /* * Handle VSA as "VENDOR + attr" */ - if (da_stack[depth]->type == FR_TYPE_VSA) { + if (da_stack->da[depth]->type == FR_TYPE_VSA) { uint8_t *evs = out + out[1]; uint32_t lvalue; @@ -759,10 +759,10 @@ static int encode_extended_hdr(uint8_t *out, size_t outlen, depth++; - lvalue = htonl(da_stack[depth++]->attr); + lvalue = htonl(da_stack->da[depth++]->attr); memcpy(evs, &lvalue, 4); - evs[4] = da_stack[depth]->attr & 0xff; + evs[4] = da_stack->da[depth]->attr & 0xff; out[1] += 5; @@ -778,7 +778,7 @@ static int encode_extended_hdr(uint8_t *out, size_t outlen, */ if ((attr_type == FR_TYPE_EXTENDED) && !extra && (outlen > 255)) outlen = 255; - if (da_stack[depth]->type == FR_TYPE_TLV) { + if (da_stack->da[depth]->type == FR_TYPE_TLV) { len = encode_tlv_hdr_internal(out + out[1], outlen - out[1], da_stack, depth, cursor, encoder_ctx); } else { len = encode_value(out + out[1], outlen - out[1], da_stack, depth, cursor, encoder_ctx); @@ -817,7 +817,7 @@ static int encode_extended_hdr(uint8_t *out, size_t outlen, * prepended to each chunk. */ static ssize_t encode_concat(uint8_t *out, size_t outlen, - fr_dict_attr_t const **da_stack, unsigned int depth, + fr_da_stack_t *da_stack, unsigned int depth, fr_cursor_t *cursor, UNUSED void *encoder_ctx) { uint8_t *ptr = out; @@ -833,7 +833,7 @@ static ssize_t encode_concat(uint8_t *out, size_t outlen, while (len > 0) { if (outlen <= 2) break; - ptr[0] = da_stack[depth]->attr & 0xff; + ptr[0] = da_stack->da[depth]->attr & 0xff; ptr[1] = 2; left = len; @@ -874,25 +874,25 @@ static ssize_t encode_concat(uint8_t *out, size_t outlen, * Otherwise, attribute may be something else. */ static ssize_t encode_rfc_hdr_internal(uint8_t *out, size_t outlen, - fr_dict_attr_t const **da_stack, unsigned int depth, + fr_da_stack_t *da_stack, unsigned int depth, fr_cursor_t *cursor, void *encoder_ctx) { ssize_t len; FR_PROTO_STACK_PRINT(da_stack, depth); - switch (da_stack[depth]->type) { + switch (da_stack->da[depth]->type) { default: fr_strerror_printf("%s: Called with structural type %s", __FUNCTION__, - fr_table_str_by_value(fr_value_box_type_table, da_stack[depth]->type, "?Unknown?")); + fr_table_str_by_value(fr_value_box_type_table, da_stack->da[depth]->type, "?Unknown?")); return -1; case FR_TYPE_STRUCT: case FR_TYPE_VALUES: - if (((fr_dict_vendor_num_by_da(da_stack[depth]) == 0) && (da_stack[depth]->attr == 0)) || - (da_stack[depth]->attr > 255)) { + if (((fr_dict_vendor_num_by_da(da_stack->da[depth]) == 0) && (da_stack->da[depth]->attr == 0)) || + (da_stack->da[depth]->attr > 255)) { fr_strerror_printf("%s: Called with non-standard attribute %u", __FUNCTION__, - da_stack[depth]->attr); + da_stack->da[depth]->attr); return -1; } break; @@ -900,7 +900,7 @@ static ssize_t encode_rfc_hdr_internal(uint8_t *out, size_t outlen, if (outlen <= 2) return 0; - out[0] = da_stack[depth]->attr & 0xff; + out[0] = da_stack->da[depth]->attr & 0xff; out[1] = 2; if (outlen > 255) outlen = 255; @@ -921,7 +921,7 @@ static ssize_t encode_rfc_hdr_internal(uint8_t *out, size_t outlen, * If it's in the RFC format, call encode_rfc_hdr_internal. Otherwise, encode it here. */ static ssize_t encode_vendor_attr_hdr(uint8_t *out, size_t outlen, - fr_dict_attr_t const **da_stack, unsigned int depth, + fr_da_stack_t *da_stack, unsigned int depth, fr_cursor_t *cursor, void *encoder_ctx) { ssize_t len; @@ -930,14 +930,14 @@ static ssize_t encode_vendor_attr_hdr(uint8_t *out, size_t outlen, FR_PROTO_STACK_PRINT(da_stack, depth); - dv = da_stack[depth++]; + dv = da_stack->da[depth++]; if (dv->type != FR_TYPE_VENDOR) { fr_strerror_printf("Expected Vendor"); return -1; } - da = da_stack[depth]; + da = da_stack->da[depth]; if ((da->type != FR_TYPE_TLV) && (dv->flags.type_size == 1) && (dv->flags.length == 1)) { return encode_rfc_hdr_internal(out, outlen, da_stack, depth, cursor, encoder_ctx); @@ -997,7 +997,7 @@ static ssize_t encode_vendor_attr_hdr(uint8_t *out, size_t outlen, * if this is a TLV, we must process it via the * internal tlv function, else we get a double TLV header. */ - if (da_stack[depth]->type == FR_TYPE_TLV) { + if (da_stack->da[depth]->type == FR_TYPE_TLV) { len = encode_tlv_hdr_internal(out + hdr_len, outlen - hdr_len, da_stack, depth, cursor, encoder_ctx); } else { len = encode_value(out + hdr_len, outlen - hdr_len, da_stack, depth, cursor, encoder_ctx); @@ -1015,7 +1015,7 @@ static ssize_t encode_vendor_attr_hdr(uint8_t *out, size_t outlen, * */ static int encode_wimax_hdr(uint8_t *out, size_t outlen, - fr_dict_attr_t const **da_stack, unsigned int depth, + fr_da_stack_t *da_stack, unsigned int depth, fr_cursor_t *cursor, void *encoder_ctx) { int len; @@ -1032,14 +1032,14 @@ static int encode_wimax_hdr(uint8_t *out, size_t outlen, */ if (outlen < 9) return 0; - if (da_stack[depth++]->attr != FR_VENDOR_SPECIFIC) { + if (da_stack->da[depth++]->attr != FR_VENDOR_SPECIFIC) { fr_strerror_printf("%s: level[1] of da_stack is incorrect, must be Vendor-Specific (26)", __FUNCTION__); return -1; } FR_PROTO_STACK_PRINT(da_stack, depth); - if (da_stack[depth++]->attr != VENDORPEC_WIMAX) { + if (da_stack->da[depth++]->attr != VENDORPEC_WIMAX) { fr_strerror_printf("%s: level[2] of da_stack is incorrect, must be Wimax vendor %i", __FUNCTION__, VENDORPEC_WIMAX); return -1; @@ -1058,7 +1058,7 @@ static int encode_wimax_hdr(uint8_t *out, size_t outlen, /* * Encode the first attribute */ - out[6] = da_stack[depth]->attr; + out[6] = da_stack->da[depth]->attr; out[7] = 3; out[8] = 0; /* continuation byte */ @@ -1066,7 +1066,7 @@ static int encode_wimax_hdr(uint8_t *out, size_t outlen, * "outlen" can be larger than 255 because of the "continuation" byte. */ - if (da_stack[depth]->type == FR_TYPE_TLV) { + if (da_stack->da[depth]->type == FR_TYPE_TLV) { len = encode_tlv_hdr_internal(out + out[1], outlen - out[1], da_stack, depth, cursor, encoder_ctx); if (len <= 0) return len; } else { @@ -1096,12 +1096,12 @@ static int encode_wimax_hdr(uint8_t *out, size_t outlen, * */ static int encode_vsa_hdr(uint8_t *out, size_t outlen, - fr_dict_attr_t const **da_stack, unsigned int depth, + fr_da_stack_t *da_stack, unsigned int depth, fr_cursor_t *cursor, void *encoder_ctx) { ssize_t len; uint32_t lvalue; - fr_dict_attr_t const *da = da_stack[depth]; + fr_dict_attr_t const *da = da_stack->da[depth]; FR_PROTO_STACK_PRINT(da_stack, depth); @@ -1114,7 +1114,7 @@ static int encode_vsa_hdr(uint8_t *out, size_t outlen, /* * Double-check for WiMAX format */ - if (fr_dict_vendor_num_by_da(da_stack[depth + 1]) == VENDORPEC_WIMAX) { + if (fr_dict_vendor_num_by_da(da_stack->da[depth + 1]) == VENDORPEC_WIMAX) { return encode_wimax_hdr(out, outlen, da_stack, depth, cursor, encoder_ctx); } @@ -1132,7 +1132,7 @@ static int encode_vsa_hdr(uint8_t *out, size_t outlen, /* * Now process the vendor ID part (which is one attribute deeper) */ - da = da_stack[++depth]; + da = da_stack->da[++depth]; FR_PROTO_STACK_PRINT(da_stack, depth); if (da->type != FR_TYPE_VENDOR) { @@ -1159,7 +1159,7 @@ static int encode_vsa_hdr(uint8_t *out, size_t outlen, /** Encode an RFC standard attribute 1..255 * */ -static int encode_rfc_hdr(uint8_t *out, size_t outlen, fr_dict_attr_t const **da_stack, unsigned int depth, +static int encode_rfc_hdr(uint8_t *out, size_t outlen, fr_da_stack_t *da_stack, unsigned int depth, fr_cursor_t *cursor, void *encoder_ctx) { VALUE_PAIR const *vp = fr_cursor_current(cursor); @@ -1170,14 +1170,14 @@ static int encode_rfc_hdr(uint8_t *out, size_t outlen, fr_dict_attr_t const **da VP_VERIFY(vp); FR_PROTO_STACK_PRINT(da_stack, depth); - switch (da_stack[depth]->type) { + switch (da_stack->da[depth]->type) { case FR_TYPE_EXTENDED: case FR_TYPE_TLV: case FR_TYPE_VSA: case FR_TYPE_VENDOR: /* FR_TYPE_STRUCT is actually allowed... */ fr_strerror_printf("%s: Expected leaf type got \"%s\"", __FUNCTION__, - fr_table_str_by_value(fr_value_box_type_table, da_stack[depth]->type, "?Unknown?")); + fr_table_str_by_value(fr_value_box_type_table, da_stack->da[depth]->type, "?Unknown?")); return -1; default: @@ -1185,8 +1185,8 @@ static int encode_rfc_hdr(uint8_t *out, size_t outlen, fr_dict_attr_t const **da * Attribute 0 is fine as a TLV leaf, or VSA, but not * in the original standards space. */ - if (((fr_dict_vendor_num_by_da(da_stack[depth]) == 0) && (da_stack[depth]->attr == 0)) || - (da_stack[depth]->attr > 255)) { + if (((fr_dict_vendor_num_by_da(da_stack->da[depth]) == 0) && (da_stack->da[depth]->attr == 0)) || + (da_stack->da[depth]->attr > 255)) { fr_strerror_printf("%s: Called with non-standard attribute %u", __FUNCTION__, vp->da->attr); return -1; } @@ -1246,12 +1246,12 @@ static int encode_rfc_hdr(uint8_t *out, size_t outlen, fr_dict_attr_t const **da */ ssize_t fr_radius_encode_pair(uint8_t *out, size_t outlen, fr_cursor_t *cursor, void *encoder_ctx) { - VALUE_PAIR const *vp; - int ret; - size_t attr_len; + VALUE_PAIR const *vp; + int ret; + size_t attr_len; - fr_dict_attr_t const *da_stack[FR_DICT_MAX_TLV_STACK + 1]; - fr_dict_attr_t const *da = NULL; + fr_da_stack_t da_stack; + fr_dict_attr_t const *da = NULL; if (!cursor || !out || (outlen <= 2)) return -1; @@ -1291,19 +1291,20 @@ ssize_t fr_radius_encode_pair(uint8_t *out, size_t outlen, fr_cursor_t *cursor, * Fast path for the common case. */ if (vp->da->parent->flags.is_root && !vp->da->flags.concat && (vp->vp_type != FR_TYPE_TLV)) { - da_stack[0] = vp->da; - da_stack[1] = NULL; - FR_PROTO_STACK_PRINT(da_stack, 0); - return encode_rfc_hdr(out, attr_len, da_stack, 0, cursor, encoder_ctx); + da_stack.da[0] = vp->da; + da_stack.da[1] = NULL; + da_stack.depth = 1; + FR_PROTO_STACK_PRINT(&da_stack, 0); + return encode_rfc_hdr(out, attr_len, &da_stack, 0, cursor, encoder_ctx); } /* * Do more work to set up the stack for the complex case. */ - fr_proto_da_stack_build(da_stack, vp->da); - FR_PROTO_STACK_PRINT(da_stack, 0); + fr_proto_da_stack_build(&da_stack, vp->da); + FR_PROTO_STACK_PRINT(&da_stack, 0); - da = da_stack[0]; + da = da_stack.da[0]; switch (da->type) { default: if (da->flags.concat) { @@ -1313,10 +1314,10 @@ ssize_t fr_radius_encode_pair(uint8_t *out, size_t outlen, fr_cursor_t *cursor, * using a different scheme than the "long * extended" one. */ - ret = encode_concat(out, outlen, da_stack, 0, cursor, encoder_ctx); + ret = encode_concat(out, outlen, &da_stack, 0, cursor, encoder_ctx); break; } - ret = encode_rfc_hdr(out, attr_len, da_stack, 0, cursor, encoder_ctx); + ret = encode_rfc_hdr(out, attr_len, &da_stack, 0, cursor, encoder_ctx); break; case FR_TYPE_VSA: @@ -1327,18 +1328,18 @@ ssize_t fr_radius_encode_pair(uint8_t *out, size_t outlen, fr_cursor_t *cursor, * attributes by fragmenting them inside * of the WiMAX VSA space. */ - ret = encode_wimax_hdr(out, outlen, da_stack, 0, cursor, encoder_ctx); + ret = encode_wimax_hdr(out, outlen, &da_stack, 0, cursor, encoder_ctx); break; } - ret = encode_vsa_hdr(out, attr_len, da_stack, 0, cursor, encoder_ctx); + ret = encode_vsa_hdr(out, attr_len, &da_stack, 0, cursor, encoder_ctx); break; case FR_TYPE_TLV: - ret = encode_tlv_hdr(out, attr_len, da_stack, 0, cursor, encoder_ctx); + ret = encode_tlv_hdr(out, attr_len, &da_stack, 0, cursor, encoder_ctx); break; case FR_TYPE_EXTENDED: - ret = encode_extended_hdr(out, attr_len, da_stack, 0, cursor, encoder_ctx); + ret = encode_extended_hdr(out, attr_len, &da_stack, 0, cursor, encoder_ctx); break; case FR_TYPE_INVALID: