ssize_t fr_struct_to_network(uint8_t *out, size_t outlen,
- fr_dict_attr_t const *parent, fr_cursor_t *cursor)
+ fr_dict_attr_t const **tlv_stack, unsigned int depth,
+ fr_cursor_t *cursor, void *encoder_ctx,
+ fr_encode_value_t encode_value)
{
ssize_t len;
unsigned int child_num = 1;
uint8_t *p = out;
VALUE_PAIR const *vp = fr_cursor_current(cursor);
- fr_dict_attr_t const *key_da;
+ fr_dict_attr_t const *key_da, *parent;
if (!vp) {
fr_strerror_printf("%s: Can't encode empty struct", __FUNCTION__);
}
VP_VERIFY(vp);
+ parent = tlv_stack[depth];
if (parent->type != FR_TYPE_STRUCT) {
fr_strerror_printf("%s: Expected type \"struct\" got \"%s\"", __FUNCTION__,
}
/*
- * Encode fixed-size octets fields so that they
- * are exactly the fixed size, UNLESS the entire
- * output is truncated.
+ * Call the protocol encoder, but ONLY if there
+ * are special flags required.
*/
- if ((vp->da->type == FR_TYPE_OCTETS) && vp->da->flags.length) {
- size_t mylen = vp->da->flags.length;
+ if (encode_value && !child->flags.extra && child->flags.subtype) {
+ ssize_t slen;
- if (mylen > outlen) mylen = outlen;
-
- if (vp->vp_length < mylen) {
- memcpy(p, vp->vp_ptr, vp->vp_length);
- memset(p + vp->vp_length, 0, mylen - vp->vp_length);
- } else {
- memcpy(p, vp->vp_ptr, mylen);
- }
- len = mylen;
+ tlv_stack[depth + 1] = child;
+ slen = encode_value(p, outlen, tlv_stack, depth + 1, cursor, encoder_ctx);
+ if (slen < 0) return slen;
+ len = slen;
+ vp = fr_cursor_current(cursor);
} else {
/*
- * Determine the nested type and call the appropriate encoder
+ * Encode fixed-size octets fields so that they
+ * are exactly the fixed size, UNLESS the entire
+ * output is truncated.
*/
- len = fr_value_box_to_network(NULL, p, outlen, &vp->data);
- if (len <= 0) return -1;
+ if ((vp->da->type == FR_TYPE_OCTETS) && vp->da->flags.length) {
+ size_t mylen = vp->da->flags.length;
+
+ if (mylen > outlen) mylen = outlen;
+
+ if (vp->vp_length < mylen) {
+ memcpy(p, vp->vp_ptr, vp->vp_length);
+ memset(p + vp->vp_length, 0, mylen - vp->vp_length);
+ } else {
+ memcpy(p, vp->vp_ptr, mylen);
+ }
+ len = mylen;
+
+ } else {
+ /*
+ * Determine the nested type and call the appropriate encoder
+ */
+ len = fr_value_box_to_network(NULL, p, outlen, &vp->data);
+ if (len <= 0) return -1;
+ }
+
+ do {
+ vp = fr_cursor_next(cursor);
+ if (!vp || !vp->da->flags.internal) break;
+ } while (vp != NULL);
}
if (da_is_key_field(child)) {
outlen -= len; /* Subtract from the buffer we have available */
child_num++;
- do {
- vp = fr_cursor_next(cursor);
- if (!vp || !vp->da->flags.internal) break;
- } while (vp != NULL);
-
/*
* Nothing more to do, or we've done all of the
* entries in this structure, stop.
*/
if ((vp->da->parent->parent == key_da) &&
(vp->da->parent->type == FR_TYPE_STRUCT)) {
- len = fr_struct_to_network(p, outlen,
- vp->da->parent, cursor);
+ tlv_stack[depth + 1] = vp->da->parent; /* hackity hack */
+ len = fr_struct_to_network(p, outlen, tlv_stack, depth + 1,
+ cursor, encoder_ctx, encode_value);
if (len < 0) return len;
return (p - out) + len;
}
ssize_t fr_struct_from_network(TALLOC_CTX *ctx, fr_cursor_t *cursor,
fr_dict_attr_t const *parent, uint8_t const *data, size_t data_len,
fr_dict_attr_t const **child) CC_HINT(nonnull(2,3,4));
-ssize_t fr_struct_to_network(uint8_t *out, size_t outlen,
- fr_dict_attr_t const *parent, fr_cursor_t *cursor) CC_HINT(nonnull);
+
+typedef ssize_t (*fr_encode_value_t)(uint8_t *out, size_t outlen, fr_dict_attr_t const **tlv_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 **tlv_stack, unsigned int depth,
+ fr_cursor_t *cursor, void *encoder_ctx,
+ fr_encode_value_t encode_value) CC_HINT(nonnull(1,3,5));
VALUE_PAIR *fr_unknown_from_network(TALLOC_CTX *ctx, fr_dict_attr_t const *parent,
uint8_t const *data, size_t data_len) CC_HINT(nonnull);
static ssize_t encode_struct(uint8_t *out, size_t outlen,
fr_dict_attr_t const **tlv_stack, unsigned int depth,
- fr_cursor_t *cursor, UNUSED void *encoder_ctx)
+ fr_cursor_t *cursor, void *encoder_ctx)
{
VP_VERIFY(fr_cursor_current(cursor));
FR_PROTO_STACK_PRINT(tlv_stack, depth);
return PAIR_ENCODE_ERROR;
}
- return fr_struct_to_network(out, outlen, tlv_stack[depth], cursor);
+ return fr_struct_to_network(out, outlen, tlv_stack, depth, cursor, encoder_ctx, encode_value);
}
static ssize_t encode_value(uint8_t *out, size_t outlen,
static unsigned int salt_offset = 0;
static ssize_t encode_value(uint8_t *out, size_t outlen,
- fr_dict_attr_t const **tlv_stack, int depth,
+ fr_dict_attr_t const **tlv_stack, unsigned int depth,
fr_cursor_t *cursor, void *encoder_ctx);
static ssize_t encode_rfc_hdr_internal(uint8_t *out, size_t outlen,
* < 0, failure.
*/
static ssize_t encode_value(uint8_t *out, size_t outlen,
- fr_dict_attr_t const **tlv_stack, int depth,
+ fr_dict_attr_t const **tlv_stack, unsigned int depth,
fr_cursor_t *cursor, void *encoder_ctx)
{
size_t offset;
if (da->type == FR_TYPE_STRUCT) {
ssize_t struct_len;
- struct_len = fr_struct_to_network(out, outlen, tlv_stack[depth], cursor);
+ struct_len = fr_struct_to_network(out, outlen, tlv_stack, depth, cursor, encoder_ctx, encode_value);
if (struct_len <= 0) return struct_len;
vp = fr_cursor_current(cursor);