Means we no longer have to memset the entire stack on each rebuild.
*/
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)
* < 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;
}
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:
*
*/
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;
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;
* 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;
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;
* 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) {
}
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) */
/*
* 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);
* 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);
}
}
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;
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;
}
* 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;
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;
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;
* 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;
}
};
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);
* @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)
}
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)
{
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;
}
}
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)
{
* 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");
da_stack, depth,
*cursor,
map_p, snmp_ctx, snmp_op,
- da_stack[depth]->attr);
+ da_stack->da[depth]->attr);
}
for (;;) {
}
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)
{
* 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:
* - <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)
{
* 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);
* 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
char oid_str[FR_DICT_MAX_TLV_STACK * 4]; /* .<num>{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;
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
* 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) {
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());
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);
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;
}
* 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);
}
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;
/*
*/
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;
}
}
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;
}
# 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
}
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)
{
}
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__,
#include <freeradius-devel/util/value.h>
#include <freeradius-devel/util/cursor.h>
#include <freeradius-devel/util/pair.h>
+#include <freeradius-devel/util/proto.h>
#ifdef __cplusplus
extern "C" {
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));
* - -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);
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:
* - < 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 */
* - < 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 */
/*
* 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);
* 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);
}
{
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);
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;
}
#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)
}
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;
}
}
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);
* 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;
}
}
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",
* 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 */
}
}
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);
/*
* 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);
* 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);
}
* 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);
}
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;
}
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
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);
/*
* 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) {
{
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);
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
/*
* 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;
}
#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);
}
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;
/*
* 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);
* 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);
}
}
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;
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;
}
/*
* 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;
* < 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;
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);
* 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;
* 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;
}
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:
*
*/
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;
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;
}
/*
* 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;
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;
}
/*
* 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;
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;
*/
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);
* 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;
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;
* 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;
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;
* 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;
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);
* 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);
*
*/
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;
*/
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;
/*
* 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 */
* "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 {
*
*/
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);
/*
* 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);
}
/*
* 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) {
/** 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);
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:
* 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;
}
*/
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;
* 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) {
* 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:
* 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: