}
-/** Encode a VSA which is a TLV
- *
- * If it's in the RFC format, call encode_rfc_format. Otherwise, encode it here.
+/** Encode one full Vendor-Specific + Vendor-ID + Vendor-Attr + Vendor-Length + ...
*/
static ssize_t encode_vendor_attr(fr_dbuff_t *dbuff,
fr_da_stack_t *da_stack, unsigned int depth,
{
ssize_t slen;
size_t hdr_len;
- fr_dbuff_t work_dbuff = FR_DBUFF_NO_ADVANCE(dbuff);
- fr_dbuff_marker_t hdr, src, dest;
+ fr_dbuff_t work_dbuff = FR_DBUFF_MAX_NO_ADVANCE(dbuff, 255);
+ fr_dbuff_marker_t vsa_hdr, hdr, src, dest;
fr_dict_attr_t const *da, *dv;
FR_PROTO_STACK_PRINT(da_stack, depth);
- fr_dbuff_marker(&hdr, &work_dbuff);
- fr_dbuff_marker(&src, &work_dbuff);
- fr_dbuff_marker(&dest, &work_dbuff);
dv = da_stack->da[depth++];
return PAIR_ENCODE_FATAL_ERROR;
}
+ fr_dbuff_marker(&vsa_hdr, &work_dbuff);
+
+ /*
+ * Build the Vendor-Specific header
+ */
+ FR_DBUFF_IN_BYTES_RETURN(&work_dbuff, FR_VENDOR_SPECIFIC, 0x06);
+
+ FR_DBUFF_IN_RETURN(&work_dbuff, (uint32_t)dv->attr); /* Copy in the 32bit vendor ID */
+
+ /*
+ * Now we encode one vendor attribute.
+ */
da = da_stack->da[depth];
fr_assert(da != NULL);
- if ((da->type != FR_TYPE_TLV) && (dv->flags.type_size == 1) && (dv->flags.length == 1)) {
- return encode_rfc_format(dbuff, da_stack, depth, cursor, encode_ctx);
- }
-
+ fr_dbuff_marker(&hdr, &work_dbuff);
+ fr_dbuff_marker(&src, &work_dbuff);
+ fr_dbuff_marker(&dest, &work_dbuff);
hdr_len = dv->flags.type_size + dv->flags.length;
/*
* internal tlv function, else we get a double TLV header.
*/
if (da_stack->da[depth]->type == FR_TYPE_TLV) {
- slen = encode_tlv_children(&FR_DBUFF_MAX(&work_dbuff, 255), da_stack, depth, cursor, encode_ctx);
+ slen = encode_tlv_children(&work_dbuff, da_stack, depth, cursor, encode_ctx);
} else {
- slen = encode_value(&FR_DBUFF_MAX(&work_dbuff, 255), da_stack, depth, cursor, encode_ctx);
+ slen = encode_value(&work_dbuff, da_stack, depth, cursor, encode_ctx);
}
if (slen <= 0) return slen;
fr_dbuff_in(&dest, (uint8_t)(len + slen));
}
- FR_PROTO_HEX_DUMP(fr_dbuff_current(&hdr), hdr_len, "header vsa");
+ fr_dbuff_set(&src, &vsa_hdr);
+ fr_dbuff_advance(&src, 1);
+ fr_dbuff_in_bytes(&src, (uint8_t) fr_dbuff_used(&work_dbuff));
+
+ FR_PROTO_HEX_DUMP(fr_dbuff_current(&vsa_hdr), 6 + hdr_len, "header vsa");
return fr_dbuff_set(dbuff, &work_dbuff);
}
fr_da_stack_t *da_stack, unsigned int depth,
fr_dcursor_t *cursor, void *encode_ctx)
{
- fr_dbuff_marker_t hdr;
- fr_dbuff_t work_dbuff = FR_DBUFF_MAX_NO_ADVANCE(dbuff, 253);
fr_dict_attr_t const *da = da_stack->da[depth];
ssize_t slen;
-
- fr_dbuff_marker(&hdr, &work_dbuff);
+ fr_pair_t *vp;
+ fr_dcursor_t child_cursor;
+ fr_dbuff_t work_dbuff;
FR_PROTO_STACK_PRINT(da_stack, depth);
return PAIR_ENCODE_FATAL_ERROR;
}
- /*
- * Build the Vendor-Specific header
- */
- FR_DBUFF_IN_BYTES_RETURN(&work_dbuff, FR_VENDOR_SPECIFIC, 0x06);
-
/*
* Now process the vendor ID part (which is one attribute deeper)
*/
return PAIR_ENCODE_FATAL_ERROR;
}
- FR_DBUFF_IN_RETURN(&work_dbuff, (uint32_t)da->attr); /* Copy in the 32bit vendor ID */
-
+ /*
+ * Flat hierarchy, encode one attribute at a time.
+ *
+ * Note that there's no attempt to encode multiple VSAs
+ * into one attribute. We can add that back as a flag,
+ * once all of the nested attribute conversion has been
+ * done.
+ */
if (da_stack->da[depth + 1]) {
- slen = encode_vendor_attr(&work_dbuff, da_stack, depth, cursor, encode_ctx);
- if (slen <= 0) return slen;
- } else {
- fr_pair_t *vp;
- fr_dcursor_t child_cursor;
+ return encode_vendor_attr(dbuff, da_stack, depth, cursor, encode_ctx);
+ }
- vp = fr_dcursor_current(cursor);
- fr_assert(vp->da == da);
+ /*
+ * Loop over the children of this Vendor-Specific attribute.
+ */
+ vp = fr_dcursor_current(cursor);
+ fr_assert(vp->da == da);
+ work_dbuff = FR_DBUFF_NO_ADVANCE(dbuff);
- fr_dcursor_init(&child_cursor, &vp->vp_group);
- while ((vp = fr_dcursor_current(&child_cursor)) != NULL) {
- fr_proto_da_stack_build(da_stack, vp->da);
+ fr_dcursor_init(&child_cursor, &vp->vp_group);
+ while ((vp = fr_dcursor_current(&child_cursor)) != NULL) {
+ fr_proto_da_stack_build(da_stack, vp->da);
- /*
- * @todo - if we run out of room, re-do
- * the header, redo the work buffer, and
- * continue.
- */
- slen = encode_vendor_attr(&work_dbuff, da_stack, depth, &child_cursor, encode_ctx);
- if (slen <= 0) {
- if (slen == PAIR_ENCODE_SKIPPED) continue;
- return slen;
- }
+ slen = encode_vendor_attr(&work_dbuff, da_stack, depth, &child_cursor, encode_ctx);
+ if (slen <= 0) {
+ if (slen == PAIR_ENCODE_SKIPPED) continue;
+ return slen;
}
-
- vp = fr_dcursor_next(cursor);
- fr_proto_da_stack_build(da_stack, vp ? vp->da : NULL);
}
- fr_dbuff_advance(&hdr, 1);
- fr_dbuff_in_bytes(&hdr, (uint8_t) fr_dbuff_used(&work_dbuff));
-
- FR_PROTO_HEX_DUMP(fr_dbuff_start(&work_dbuff), 6, "header vsa");
+ vp = fr_dcursor_next(cursor);
+ fr_proto_da_stack_build(da_stack, vp ? vp->da : NULL);
return fr_dbuff_set(dbuff, &work_dbuff);
-
}
/** Encode a Vendor-Specific attribute