return data_len;
}
-/** Convert one VSA to a VP.
+/** Convert a top-level VSA to a VP.
*
* "length" can be LONGER than just this sub-vsa.
*/
-static ssize_t decode_vsa_single(TALLOC_CTX *ctx, fr_dcursor_t *cursor, fr_dict_t const *dict,
- fr_dict_attr_t const *parent,
- uint8_t const *data, size_t data_len,
- fr_radius_ctx_t *packet_ctx, fr_dict_vendor_t const *dv)
+static ssize_t decode_vsa_internal(TALLOC_CTX *ctx, fr_dcursor_t *cursor, fr_dict_t const *dict,
+ fr_dict_attr_t const *parent,
+ uint8_t const *data, size_t data_len,
+ fr_radius_ctx_t *packet_ctx, fr_dict_vendor_t const *dv)
{
unsigned int attribute;
ssize_t attrlen, my_len;
/*
* data = Ext-Attr Flag ...
*/
+
if (attr_len < 3) return -1;
/*
- * No continuation, just decode the attribute in place.
+ * No continuation, just decode the attributre in place.
*/
if ((data[1] & 0x80) == 0) {
ret = fr_radius_decode_pair_value(ctx, cursor, dict,
*
* @note Called ONLY for Vendor-Specific
*/
-static ssize_t decode_wimax(fr_pair_t *parent, fr_dict_t const *dict,
+static ssize_t decode_wimax(TALLOC_CTX *ctx, fr_dcursor_t *cursor, fr_dict_t const *dict,
+ fr_dict_attr_t const *parent,
uint8_t const *data, size_t attr_len, size_t packet_len,
fr_radius_ctx_t *packet_ctx)
{
ssize_t ret;
size_t wimax_len;
+ bool more;
uint8_t *head, *tail;
uint8_t const *attr, *end;
fr_dict_attr_t const *da;
- fr_pair_list_t list;
- fr_dcursor_t cursor;
#ifdef __clang_analyzer__
if (!packet_ctx->tmp_ctx) return -1;
#endif
- fr_assert(parent->da->type == FR_TYPE_VENDOR);
- fr_assert(parent->da->attr == VENDORPEC_WIMAX);
-
/*
- * We're passed data = WiMAX-Attr WiMAX-Len Continuation ...
+ * data = VID VID VID VID WiMAX-Attr WiMAX-Len Continuation ...
*/
- fr_assert(attr_len > 3);
+ if (attr_len < 8) return -1;
- da = fr_dict_attr_child_by_num(parent->da, data[0]);
+ /*
+ * WiMAX-Attr WiMAX-Len Continuation
+ */
+ if (data[5] < 3) return -1;
/*
- * Unknown attribute, or the WiMAX length doesn't match
- * the enclosing attribute length, it's an unknown
- * attribute.
+ * The WiMAX-Len + 4 VID must exactly fill the attribute.
*/
- if (!da || (data[1] != attr_len)) {
- da = fr_dict_unknown_attr_afrom_num(packet_ctx->tmp_ctx, parent->da, data[0]);
- if (!da) return -1;
- }
- FR_PROTO_TRACE("decode context changed %s -> %s", da->parent->name, da->name);
+ if (((size_t) (data[5] + 4)) != attr_len) return -1;
- fr_pair_list_init(&list);
- fr_dcursor_init(&cursor, &list);
+ da = fr_dict_attr_child_by_num(parent, data[4]);
+ if (!da) da = fr_dict_unknown_attr_afrom_num(packet_ctx->tmp_ctx, parent, data[4]);
+ if (!da) return -1;
+ FR_PROTO_TRACE("decode context changed %s -> %s", da->parent->name, da->name);
/*
- * No continuation, just decode the attribute in place.
+ * No continuation, just decode the attributre in place.
*/
- if ((data[2] & 0x80) == 0) {
- ret = fr_radius_decode_pair_value(parent, &cursor, dict,
- da, data + 3, data[1] - 3, data[1] - 3, packet_ctx);
+ if ((data[6] & 0x80) == 0) {
+ ret = fr_radius_decode_pair_value(ctx, cursor, dict,
+ da, data + 7, data[5] - 3, data[5] - 3, packet_ctx);
if (ret < 0) return ret;
- fr_pair_list_append(&parent->vp_group, &list);
return attr_len;
}
* now, they MUST be contiguous in the packet, and they
* MUST be all of the same VSA, WiMAX, and WiMAX-attr.
*
- * The first fragment has already been checked, so we
- * start off with that.
+ * The first fragment doesn't have a RADIUS attribute
+ * header.
*/
- wimax_len = attr_len - 3;
- attr = data + attr_len;
+ wimax_len = 0;
+ attr = data + 4;
end = data + packet_len;
- /*
- * Loop over the entire packet. The base RFC format is
- * valid, as the packet was already checked for sanity.
- */
while (attr < end) {
- uint32_t vendor;
- uint8_t const *wimax;
-
/*
- * This check shouldn't be necessary, but what
- * the heck.
+ * Not enough room for Attribute + length +
+ * continuation, it's bad.
*/
- if ((attr + 2) > end) break;
+ if ((end - attr) < 3) return -1;
/*
- * This check shouldn't be necessary, either.
+ * Must have non-zero data in the attribute.
*/
- if ((attr + attr[1]) > end) break;
+ if (attr[1] <= 3) return -1;
/*
- * The attribute isn't a VSA, stop.
+ * If the WiMAX attribute overflows the packet,
+ * it's bad.
*/
- if (attr[0] != FR_VENDOR_SPECIFIC) break;
+ if ((attr + attr[1]) > end) return -1;
/*
- * Not enough room for RFC header + Vendor-ID +
- * WiMAX header + Continuation, stop.
+ * Check the continuation flag.
*/
- if (attr[1] < 2 + 4 + 2 + 1) break;
+ more = ((attr[2] & 0x80) != 0);
/*
- * Not a WiMAX VSA, stop.
+ * Or, there's no more data, in which case we
+ * shorten "end" to finish at this attribute.
*/
- vendor = fr_net_to_uint32(attr + 2);
- if (vendor != VENDORPEC_WIMAX) break;
-
+ if (!more) end = attr + attr[1];
/*
- * Point to WiMAX-Attr
+ * There's more data, but we're at the end of the
+ * packet. The attribute is malformed!
*/
- wimax = attr + 2 + 4;
+ if (more && ((attr + attr[1]) == end)) return -1;
/*
- * Not the same WiMAX attribute.
+ * Add in the length of the data we need to
+ * concatenate together.
*/
- if (data[0] != wimax[0]) break;
+ wimax_len += attr[1] - 3;
/*
- * WiMAX attribute does not fill the
- * Vendor-Specific attribute, either
- * overflow or underflow.
+ * Go to the next attribute, and stop if there's
+ * no more.
*/
- if (attr[1] != (wimax[1] + 6)) break;
+ attr += attr[1];
+ if (!more) break;
/*
- * Seems OK, add the length in.
+ * data = VID VID VID VID WiMAX-Attr WimAX-Len Continuation ...
+ *
+ * attr = Vendor-Specific VSA-Length VID VID VID VID WiMAX-Attr WimAX-Len Continuation ...
+ *
*/
- wimax_len += wimax[1] - 3;
/*
- * We've successfully included this attribute, so
- * point to the next one.
+ * No room for Vendor-Specific + length +
+ * Vendor(4) + attr + length + continuation + data
*/
- attr += attr[1];
+ if ((end - attr) < 9) return -1;
+
+ if (attr[0] != FR_VENDOR_SPECIFIC) return -1;
+ if (attr[1] < 9) return -1;
+ if ((attr + attr[1]) > end) return -1;
+ if (memcmp(data, attr + 2, 4) != 0) return -1; /* not WiMAX Vendor ID */
+
+ if (attr[1] != (attr[7] + 6)) return -1; /* WiMAX attr doesn't exactly fill the VSA */
+
+ if (data[4] != attr[6]) return -1; /* different WiMAX attribute */
/*
- * No more continuation, stop.
+ * Skip over the Vendor-Specific header, and
+ * continue with the WiMAX attributes.
*/
- if ((wimax[2] & 0x80) == 0) break;
+ attr += 6;
}
/*
- * Remember where the continued WiMAX attributes ended.
+ * No data in the WiMAX attribute, make a "raw" one.
*/
- end = attr;
+ if (!wimax_len) return -1;
- head = tail = talloc_array(packet_ctx->tmp_ctx, uint8_t, wimax_len);
+ head = tail = talloc_array(ctx, uint8_t, wimax_len);
if (!head) return -1;
/*
* Copy the data over, this time trusting the attribute
- * contents. When this function is called, 'data' is
- * pointing to WiMAX-Attr. So we back up in order to be
- * able to point to the Vendor-Specific byte, which
- * treats all of the attributes the same.
+ * contents.
*/
- attr = data - 6;
+ attr = data;
while (attr < end) {
- uint8_t const *wimax = attr + 2 + 4;
-
- memcpy_bounded(tail, wimax + 3, wimax[1] - 3, end);
- tail += wimax[1] - 3;
- attr += attr[1];
+ memcpy_bounded(tail, attr + 4 + 3, attr[4 + 1] - 3, end);
+ tail += attr[4 + 1] - 3;
+ attr += 4 + attr[4 + 1]; /* skip VID+WiMax header */
+ attr += 2; /* skip Vendor-Specific header */
}
FR_PROTO_HEX_DUMP(head, wimax_len, "Wimax fragments");
- ret = fr_radius_decode_pair_value(parent, &cursor, dict,
+ ret = fr_radius_decode_pair_value(ctx, cursor, dict,
da, head, wimax_len, wimax_len, packet_ctx);
talloc_free(head);
if (ret < 0) return ret;
- fr_pair_list_append(&parent->vp_group, &list);
-
return end - data;
}
fr_radius_ctx_t *packet_ctx)
{
size_t total;
+ ssize_t ret;
uint32_t vendor;
fr_dict_vendor_t const *dv;
fr_pair_list_t head;
fr_dict_vendor_t my_dv;
fr_dict_attr_t const *vendor_da;
- fr_pair_t *vp;
fr_dcursor_t tlv_cursor;
fr_pair_list_init(&head);
if (!fr_cond_assert(parent->type == FR_TYPE_VSA)) return -1;
if (attr_len > packet_len) return -1;
- if (attr_len < 4) return -1; /* must have at least a 32-bit vendor ID */
+ if (attr_len < 5) return -1; /* vid, value */
+ if (data[0] != 0) return -1; /* we require 24-bit VIDs */
FR_PROTO_TRACE("Decoding VSA");
/*
* Verify that the parent (which should be a VSA)
- * contains a child which represents the vendor.
+ * contains a fake attribute representing the vendor.
+ *
+ * If it doesn't then this vendor is unknown, but
+ * (unlike DHCP) we know vendor attributes have a
+ * standard format, so we can decode the data anyway.
*/
vendor_da = fr_dict_attr_child_by_num(parent, vendor);
if (!vendor_da) {
fr_dict_attr_t *n;
+ /*
+ * RFC format is 1 octet type, 1 octet length
+ */
+ if (fr_radius_decode_tlv_ok(data + 4, attr_len - 4, 1, 1) < 0) {
+ FR_PROTO_TRACE("Unknown TLVs not OK: %s", fr_strerror());
+ return -1;
+ }
n = fr_dict_unknown_vendor_afrom_num(packet_ctx->tmp_ctx, parent, vendor);
if (!n) return -1;
vendor_da = n;
- }
- /*
- * Create an unknown DV if necessary. If the DV isn't
- * known, we default to RFC format.
- */
- dv = fr_dict_vendor_by_num(dict, vendor);
- if (!dv) {
+ /*
+ * Create an unknown DV too...
+ */
memset(&my_dv, 0, sizeof(my_dv));
my_dv.pen = vendor;
my_dv.length = 1;
dv = &my_dv;
+
+ goto create_attrs;
}
/*
- * VSAs should be in a TLV format.
+ * We found an attribute representing the vendor
+ * so it *MUST* exist in the vendor tree.
*/
- if (fr_radius_decode_tlv_ok(data + 4, attr_len - 4, dv->type, dv->length) < 0) {
- FR_PROTO_TRACE("TLVs not OK: %s", fr_strerror());
- return -1;
- }
+ dv = fr_dict_vendor_by_num(dict, vendor);
+ if (!fr_cond_assert(dv)) return -1;
+ FR_PROTO_TRACE("decode context %s -> %s", parent->name, vendor_da->name);
/*
- * Ensure that Vendor-Specific exists. If it doesn't
- * exist, create it and add it to the parent list.
- *
- * Since fr_radius_decode_tlv_ok() has returned OK, we
- * know that any malformed attributes will be created as
- * "raw" attributes. The decode functions we call will
- * return -1 only on OOM, or other unrecoverable error.
+ * WiMAX craziness
*/
- vp = packet_ctx->vendor_specific;
- if (!vp) {
- vp = fr_pair_afrom_da(ctx, parent);
- if (!vp) return -1;
-
- packet_ctx->vendor_specific = vp;
- fr_dcursor_append(cursor, vp);
+ if ((vendor == VENDORPEC_WIMAX) && dv->flags) {
+ ret = decode_wimax(ctx, cursor, dict, vendor_da, data, attr_len, packet_len, packet_ctx);
+ return ret;
}
/*
- * Ensure that a child VP of this vendor exists.
+ * VSAs should normally be in TLV format.
*/
- vp = fr_pair_find_by_da(&packet_ctx->vendor_specific->vp_group, vendor_da);
- if (!vp) {
- vp = fr_pair_afrom_da(packet_ctx->vendor_specific, vendor_da);
- if (!vp) return -1;
-
- fr_pair_append(&packet_ctx->vendor_specific->vp_group, vp);
+ if (fr_radius_decode_tlv_ok(data + 4, attr_len - 4, dv->type, dv->length) < 0) {
+ FR_PROTO_TRACE("TLVs not OK: %s", fr_strerror());
+ return -1;
}
+ /*
+ * There may be more than one VSA in the
+ * Vendor-Specific. If so, loop over them all.
+ */
+create_attrs:
data += 4;
attr_len -= 4;
packet_len -= 4;
total = 4;
- /*
- * WiMAX craziness.
- */
- if (vendor == VENDORPEC_WIMAX) {
- ssize_t slen;
-
- /*
- * If there's only Vendor-Attr + Vendor-Length,
- * then there's either continuation byte, or only
- * a continuation byte. We return zero
- * attributes.
- *
- * Note that we don't bother checking for the
- * continuation flag. If it's set, then there's
- * no reason to concatenate an empty attribute
- * with the next one.
- */
- if (attr_len <= 3) return total + attr_len;
-
- /*
- * There's a continuation byte, and some data.
- * Let's decode it.
- */
- slen = decode_wimax(vp, dict, data, attr_len, packet_len, packet_ctx);
- if (slen < 0) return slen;
- return total + slen;
- }
-
- FR_PROTO_TRACE("decode context %s -> %s", parent->name, vendor_da->name);
-
- /*
- * There may be many TLVs in the attribute. Loop over
- * them all.
- */
fr_dcursor_init(&tlv_cursor, &head);
while (attr_len > 0) {
- ssize_t slen;
+ ssize_t vsa_len;
/*
- * Decode this one VSA, which itself might have
- * child attributes.
+ * Vendor attributes can have subattributes (if you hadn't guessed)
*/
- slen = decode_vsa_single(vp, &tlv_cursor, dict,
- vendor_da, data, attr_len, packet_ctx, dv);
- if (slen < 0) {
+ vsa_len = decode_vsa_internal(ctx, &tlv_cursor, dict,
+ vendor_da, data, attr_len, packet_ctx, dv);
+ if (vsa_len < 0) {
fr_strerror_printf("%s: Internal sanity check %d", __FUNCTION__, __LINE__);
fr_pair_list_free(&head);
return -1;
}
- data += slen;
- attr_len -= slen;
- packet_len -= slen;
- total += slen;
+ data += vsa_len;
+ attr_len -= vsa_len;
+ packet_len -= vsa_len;
+ total += vsa_len;
}
+ fr_dcursor_head(&tlv_cursor);
+ fr_dcursor_tail(cursor);
+ fr_dcursor_merge(cursor, &tlv_cursor);
- fr_pair_list_append(&vp->vp_group, &head);
+ /*
+ * When the unknown attributes were created by
+ * decode_vsa_internal, the hierachy between that unknown
+ * attribute and first known attribute was cloned
+ * meaning we can now free the unknown vendor.
+ */
return total;
}
match 1a 0e 00 00 60 b5 01 08 00 01 05 31 2e 30
decode-pair -
-match Vendor-Specific = { WiMAX = { Capability = { Release = "1.0" } } }
+match Vendor-Specific.WiMAX.Capability = { Release = "1.0" }
encode-pair Vendor-Specific.WiMAX.Capability.Accounting-Capabilities = 1
match 1a 0c 00 00 60 b5 01 06 00 02 03 01
decode-pair -
-match Vendor-Specific = { WiMAX = { Capability = { Accounting-Capabilities = IP-Session-Based } } }
+match Vendor-Specific.WiMAX.Capability = { Accounting-Capabilities = IP-Session-Based }
encode-pair Vendor-Specific.WiMAX.Capability.Release = "1.0", Vendor-Specific.WiMAX.Capability.Accounting-Capabilities = 1
match 1a 11 00 00 60 b5 01 0b 00 01 05 31 2e 30 02 03 01
decode-pair -
-match Vendor-Specific = { WiMAX = { Capability = { Release = "1.0", Accounting-Capabilities = IP-Session-Based } } }
+match Vendor-Specific.WiMAX.Capability = { Release = "1.0", Accounting-Capabilities = IP-Session-Based }
encode-pair -
match 1a 11 00 00 60 b5 01 0b 00 01 05 31 2e 30 02 03 01
match 1a 14 00 00 60 b5 54 0e 00 09 0b 04 03 01 05 06 04 04 1a 99
decode-pair -
-match Vendor-Specific = { WiMAX = { Packet-Flow-Descriptor-v2 = { Classifier = { Direction = 1, Src-Spec = { Port = 6809 } } } } }
+match Vendor-Specific.WiMAX.Packet-Flow-Descriptor-v2 = { Classifier = { Direction = 1, Src-Spec = { Port = 6809 } } }
decode-pair 1a 11 00 00 60 b5 54 0b 00 09 08 05 06 04 04 1a 99
-match Vendor-Specific = { WiMAX = { Packet-Flow-Descriptor-v2 = { Classifier = { Src-Spec = { Port = 6809 } } } } }
+match Vendor-Specific.WiMAX.Packet-Flow-Descriptor-v2 = { Classifier = { Src-Spec = { Port = 6809 } } }
encode-pair -
match 1a 11 00 00 60 b5 54 0b 00 09 08 05 06 04 04 1a 99
# 26.24757.84.9.5 has the correct length.
# 26.24757.84.9.5.4 has the wrong length.
decode-pair 1a 14 00 00 60 b5 54 0e 00 09 0b 04 03 01 05 06 04 05 1a 99
-match Vendor-Specific = { WiMAX = { Packet-Flow-Descriptor-v2 = { Classifier = { Direction = 1, raw.Src-Spec = 0x04051a99 } } } }
+match Vendor-Specific.WiMAX.Packet-Flow-Descriptor-v2 = { Classifier = { Direction = 1, raw.Src-Spec = 0x04051a99 } }
# The 26.24757.1 has the wrong length
decode-pair 1a 11 00 00 60 b5 01 0a 00 01 05 31 2e 30 02 03 01
# 26.24757.1.1 has the wrong length
decode-pair 1a 11 00 00 60 b5 01 0b 00 01 04 31 2e 30 02 03 01
-match Vendor-Specific = { WiMAX = { raw.Capability = 0x0104312e30020301 } }
+match raw.Vendor-Specific.WiMAX.Capability = 0x0104312e30020301
decode-pair 1a 11 00 00 60 b5 01 0b 00 01 06 31 2e 30 02 03 01
-match Vendor-Specific = { WiMAX = { raw.Capability = 0x0106312e30020301 } }
+match raw.Vendor-Specific.WiMAX.Capability = 0x0106312e30020301
encode-pair -
match 1a 11 00 00 60 b5 01 0b 00 01 06 31 2e 30 02 03 01
# 26.24757.1.2 has the wrong length
decode-pair 1a 11 00 00 60 b5 01 0b 00 01 05 31 2e 30 02 02 01
-match Vendor-Specific = { WiMAX = { raw.Capability = 0x0105312e30020201 } }
+match raw.Vendor-Specific.WiMAX.Capability = 0x0105312e30020201
encode-pair -
match 1a 11 00 00 60 b5 01 0b 00 01 05 31 2e 30 02 02 01
# 26.24757.1.2 has the wrong length
# This means that 26.24757.1 is invalid, and we create a raw attribute.
decode-pair 1a 11 00 00 60 b5 01 0b 00 01 05 31 2e 30 02 04 01
-match Vendor-Specific = { WiMAX = { raw.Capability = 0x0105312e30020401 } }
+match raw.Vendor-Specific.WiMAX.Capability = 0x0105312e30020401
encode-pair -
match 1a 11 00 00 60 b5 01 0b 00 01 05 31 2e 30 02 04 01
match 1a 15 00 00 60 b5 54 0f 00 09 0c 09 0a 03 08 01 03 37 02 03 54
decode-pair -
-match Vendor-Specific = { WiMAX = { Packet-Flow-Descriptor-v2 = { Classifier = { Classifier-Eth-Option = { Eth-Priority-Range = { Low = 55, High = 84 } } } } } }
+match Vendor-Specific.WiMAX.Packet-Flow-Descriptor-v2 = { Classifier = { Classifier-Eth-Option = { Eth-Priority-Range = { Low = 55, High = 84 } } } }
# A less efficient encoding of the above data
decode-pair 1a 17 00 00 60 b5 54 11 00 09 0e 09 0c 03 05 01 03 37 03 05 02 03 54
-match Vendor-Specific = { WiMAX = { Packet-Flow-Descriptor-v2 = { Classifier = { Classifier-Eth-Option = { Eth-Priority-Range = { Low = 55 }, Eth-Priority-Range = { High = 84 } } } } } }
-
+match Vendor-Specific.WiMAX.Packet-Flow-Descriptor-v2 = { Classifier = { Classifier-Eth-Option = { Eth-Priority-Range = { Low = 55 }, Eth-Priority-Range = { High = 84 } } } }
# 26.24757.84.9.9.3.1 has the wrong length
decode-pair 1a 15 00 00 60 b5 54 0f 00 09 0c 09 0a 03 08 01 04 37 02 03 54
-match Vendor-Specific = { WiMAX = { Packet-Flow-Descriptor-v2 = { Classifier = { Classifier-Eth-Option = { raw.Eth-Priority-Range = 0x010437020354 } } } } }
+match Vendor-Specific.WiMAX.Packet-Flow-Descriptor-v2 = { Classifier = { Classifier-Eth-Option = { raw.Eth-Priority-Range = 0x010437020354 } } }
# 26.24757.84.9.9.3.2 has the wrong length
decode-pair 1a 15 00 00 60 b5 54 0f 00 09 0c 09 0a 03 08 01 03 37 02 04 54
-match Vendor-Specific = { WiMAX = { Packet-Flow-Descriptor-v2 = { Classifier = { Classifier-Eth-Option = { raw.Eth-Priority-Range = 0x010337020454 } } } } }
+match Vendor-Specific.WiMAX.Packet-Flow-Descriptor-v2 = { Classifier = { Classifier-Eth-Option = { raw.Eth-Priority-Range = 0x010337020454 } } }
# 26.24757.84.9.9.3.2 has the wrong length
# This means that the SECOND 26.24757.84.9.9.3 is invalid.
decode-pair 1a 17 00 00 60 b5 54 11 00 09 0e 09 0c 03 05 01 03 37 03 05 02 04 54
-match Vendor-Specific = { WiMAX = { Packet-Flow-Descriptor-v2 = { Classifier = { Classifier-Eth-Option = { Eth-Priority-Range = { Low = 55 }, raw.Eth-Priority-Range = 0x020454 } } } } }
+match Vendor-Specific.WiMAX.Packet-Flow-Descriptor-v2 = { Classifier = { Classifier-Eth-Option = { Eth-Priority-Range = { Low = 55 }, raw.Eth-Priority-Range = 0x020454 } } }
# 26.24757.84.9.9.3.1 has the wrong length
# This means that 26.24757.84.9.9.3 is invalid.
decode-pair 1a 17 00 00 60 b5 54 11 00 09 0e 09 0c 03 05 01 02 37 03 05 02 03 54
-match Vendor-Specific = { WiMAX = { Packet-Flow-Descriptor-v2 = { Classifier = { Classifier-Eth-Option = { raw.Eth-Priority-Range = 0x010237, Eth-Priority-Range = { High = 84 } } } } } }
+match Vendor-Specific.WiMAX.Packet-Flow-Descriptor-v2 = { Classifier = { Classifier-Eth-Option = { raw.Eth-Priority-Range = 0x010237, Eth-Priority-Range = { High = 84 } } } }
#
# Simple test for continued attributes
#
decode-pair 1a 0e 00 00 60 b5 01 08 80 01 05 31 2e 30 1a 0c 00 00 60 b5 01 06 00 02 03 00
-match Vendor-Specific = { WiMAX = { Capability = { Release = "1.0", Accounting-Capabilities = No-Accounting } } }
+match Vendor-Specific.WiMAX.Capability = { Release = "1.0", Accounting-Capabilities = No-Accounting }
#
# See if encoding multiple attributes works
# Structs not yet decoded into sub-groups
#
decode-pair -
-match Vendor-Specific = { WiMAX = { Packet-Flow-Descriptor = { Classifier = { Src-Spec = { IP-Address = 127.0.0.1, Port = 2112, Port-Range.Start = 2112, Port-Range.End = 6809 } } } } }
+match Vendor-Specific.WiMAX.Packet-Flow-Descriptor = { Classifier = { Src-Spec = { IP-Address = 127.0.0.1, Port = 2112, Port-Range.Start = 2112, Port-Range.End = 6809 } } }
encode-pair Vendor-Specific.WiMAX.DNS-Server = ::1
match 1a 19 00 00 60 b5 34 13 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01
match 1a ff 00 00 60 b5 01 f9 80 01 fd 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 1a 10 00 00 60 b5 01 0a 00 78 78 78 78 78 78 78
decode-pair -
-match Vendor-Specific = { WiMAX = { Capability = { Release = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" } } }
-
+match Vendor-Specific.WiMAX.Capability = { Release = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }
count
match 122