uint8_t arg_cnt, uint8_t const *argv, uint8_t const *attrs, NDEBUG_UNUSED uint8_t const *end)
{
uint8_t i;
+ bool append = false;
uint8_t const *p = attrs;
fr_pair_t *vp;
+ fr_pair_t *vendor = NULL;
/*
* No one? Just get out!
*/
if (!arg_cnt) return 0;
+ /*
+ * Try to decode as nested attributes. If we can't, everything is
+ *
+ * Argument-List = "foo=bar"
+ */
+ if (parent) {
+ vendor = fr_pair_find_by_da(out, NULL, parent);
+ if (!vendor) {
+ vendor = fr_pair_afrom_da(ctx, parent);
+ if (!vendor) return -1;
+
+ append = true;
+ }
+ }
+
/*
* Then, do the dirty job of creating attributes.
*/
*
* Argument-List += "name=value"
*/
- if (parent) {
+ if (vendor) {
da = fr_dict_attr_by_name(NULL, parent, (char *) buffer);
if (!da) goto raw;
- vp = fr_pair_afrom_da(ctx, da);
+ vp = fr_pair_afrom_da(vendor, da);
if (!vp) goto oom;
/*
if (da->type == FR_TYPE_OCTETS) {
if ((arg_end > value) &&
(fr_pair_value_memdup(vp, value, arg_end - value, true) < 0)) {
- talloc_free(vp);
- return -1;
+ goto fail;
}
} else if (da->type == FR_TYPE_STRING) {
if ((arg_end > value) &&
(fr_pair_value_bstrndup(vp, (char const *) value, arg_end - value, true) < 0)) {
- talloc_free(vp);
- return -1;
+ goto fail;
}
} else if (arg_end == value) {
/*
* Any other leaf type MUST have non-zero contents.
*/
+ talloc_free(vp);
goto raw;
} else {
-
/*
* Parse the string, and try to convert it to the
* underlying data type. If it can't be
}
/*
- * Else it parsed fine, append it to the output list.
+ * Else it parsed fine, append it to the output vendor list.
*/
}
+ fr_pair_append(&vendor->vp_group, vp);
+
} else {
raw:
vp = fr_pair_afrom_da(ctx, attr_tacacs_argument_list);
if (!vp) {
oom:
fr_strerror_const("Out of Memory");
+ fail:
+ if (append) {
+ talloc_free(vendor);
+ } else {
+ talloc_free(vp);
+ }
return -1;
}
if ((arg_end > value) &&
(fr_pair_value_bstrndup(vp, (char const *) value, arg_end - value, true) < 0)) {
- talloc_free(vp);
- return -1;
+ goto fail;
}
- }
- fr_pair_append(out, vp);
+ fr_pair_append(out, vp);
+ }
next:
p += argv[i];
}
+ if (append) {
+ if (fr_pair_list_num_elements(&vendor->vp_group) > 0) {
+ fr_pair_append(out, vendor);
+ } else {
+ talloc_free(vendor);
+ }
+ }
+
return 0;
}
*/
static uint8_t tacacs_encode_body_arg_cnt(fr_pair_list_t *vps, fr_dict_attr_t const *da)
{
- uint8_t arg_cnt = 0;
- fr_pair_t *vp;
+ int arg_cnt = 0;
+ fr_pair_t *vp;
for (vp = fr_pair_list_head(vps);
vp;
continue;
}
+ fr_assert(fr_dict_by_da(vp->da) == dict_tacacs);
+
/*
- * @todo - if we find a Vendor, count its children
+ * Recurse into children.
*/
-
- fr_assert(fr_dict_by_da(vp->da) == dict_tacacs);
+ if (vp->da->type == FR_TYPE_VENDOR) {
+ arg_cnt += tacacs_encode_body_arg_cnt(&vp->vp_group, NULL);
+ }
if (vp->da->parent->type != FR_TYPE_VENDOR) continue;
# Authorization - Response: (Client <- Server)
#
decode-proto c0 02 02 00 e1 66 78 e6 00 00 00 13 02 59 f9 90 38 81 e1 bb 9d a6 13 93 fc 86 7e 4a 14 1c 24
-match Packet.Version-Major = Plus, Packet.Version-Minor = 0, Packet.Packet-Type = Authorization, Packet.Sequence-Number = 2, Packet.Flags = None, Packet.Session-Id = 3781589222, Packet.Length = 19, Packet-Body-Type = Response, Authorization-Status = Pass-Add, Server-Message = "", Data = 0x, Test.addr = 1.2.3.4
+match Packet.Version-Major = Plus, Packet.Version-Minor = 0, Packet.Packet-Type = Authorization, Packet.Sequence-Number = 2, Packet.Flags = None, Packet.Session-Id = 3781589222, Packet.Length = 19, Packet-Body-Type = Response, Authorization-Status = Pass-Add, Server-Message = "", Data = 0x, Test = { addr = 1.2.3.4 }
encode-proto -
match c0 02 02 00 e1 66 78 e6 00 00 00 13 02 59 f9 90 38 81 e1 bb 9d a6 13 93 fc 86 7e 4a 14 1c 24