FR_PROTO_HEX_DUMP(fr_dbuff_current(&hdr), hlen, "header extended");
}
+ /*
+ * This also handles TLVs
+ */
slen = encode_value(&work_dbuff, da_stack, depth, cursor, encode_ctx);
if (slen <= 0) return slen;
return fr_dbuff_set(dbuff, &work_dbuff);
}
+/*
+ * The encode_extended() function expects to see the TLV or
+ * STRUCT inside of the extended attribute, in which case it
+ * creates the attribute header and calls encode_value() for the
+ * leaf type, or child TLV / struct.
+ *
+ * If we see VSA or VENDOR, then we recurse past that to a child
+ * which is either a leaf, or a TLV, or a STRUCT.
+ */
+static ssize_t encode_extended_nested(fr_dbuff_t *dbuff,
+ fr_da_stack_t *da_stack, unsigned int depth,
+ fr_dcursor_t *cursor, void *encode_ctx)
+{
+ ssize_t slen;
+ fr_pair_t *parent, *vp;
+ fr_dcursor_t child_cursor;
+ fr_dbuff_t work_dbuff = FR_DBUFF(dbuff);
+
+ parent = fr_dcursor_current(cursor);
+ fr_assert(fr_type_is_structural(parent->vp_type));
+
+ (void) fr_pair_dcursor_init(&child_cursor, &parent->vp_group);
+
+ while ((vp = fr_dcursor_current(&child_cursor)) != NULL) {
+ if (fr_type_is_leaf(vp->vp_type) ||
+ ((depth > 1) && ((vp->vp_type == FR_TYPE_TLV) || (vp->vp_type == FR_TYPE_STRUCT)))) {
+ fr_proto_da_stack_build(da_stack, vp ? vp->da : NULL);
+ slen = encode_extended(&work_dbuff, da_stack, 0, &child_cursor, encode_ctx);
+
+ } else {
+ slen = encode_extended_nested(&work_dbuff, da_stack, 0, &child_cursor, encode_ctx);
+ }
+
+ if (slen < 0) return slen;
+ }
+
+ vp = fr_dcursor_next(cursor);
+
+ /*
+ * @fixme: attributes with 'concat' MUST of type
+ * 'octets', and therefore CANNOT have any TLV data in them.
+ */
+ fr_proto_da_stack_build(da_stack, vp ? vp->da : NULL);
+
+ return fr_dbuff_set(dbuff, &work_dbuff);
+}
+
+
/** Encode an RFC format attribute, with the "concat" flag set
*
* If there isn't enough freespace in the packet, the data is
{
uint8_t const *p;
size_t data_len;
- fr_pair_t const *vp = fr_dcursor_current(cursor);
+ fr_pair_t const *vp = fr_dcursor_current(cursor);
fr_dbuff_t work_dbuff = FR_DBUFF(dbuff);
fr_dbuff_marker_t hdr;
case FR_TYPE_TLV:
if (!flag_extended(&da->flags)) {
slen = encode_child(&work_dbuff, &da_stack, 0, cursor, encode_ctx);
- } else {
+
+ } else if (vp->da != da) {
slen = encode_extended(&work_dbuff, &da_stack, 0, cursor, encode_ctx);
+
+ } else {
+ slen = encode_extended_nested(&work_dbuff, &da_stack, 0, cursor, encode_ctx);
}
if (slen < 0) return slen;
break;