]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
correctly encode VSAs in DHCPv6.
authorAlan T. DeKok <aland@freeradius.org>
Fri, 25 Oct 2019 15:05:42 +0000 (11:05 -0400)
committerAlan T. DeKok <aland@freeradius.org>
Fri, 25 Oct 2019 15:06:04 +0000 (11:06 -0400)
And update the unit test to match.

src/protocols/dhcpv6/encode.c
src/tests/unit/dhcpv6.txt

index 5ca92b03ea1463fec4e17cbb4921fc008e760b24..ffe8f817b9633202bc72e5d739ede5355e858952 100644 (file)
@@ -657,70 +657,6 @@ static ssize_t encode_tlv_hdr(uint8_t *out, size_t outlen,
        return p - out;
 }
 
-/** Encode a VSIO (Vendor Specific Information Opion)
- *
- *     https://tools.ietf.org/html/rfc8415#section-21.17 says:
- *
- *   The vendor-option-data field MUST be encoded as a sequence of
- *   code/length/value fields of format identical to the DHCP options (see
- *   Section 21.1).  The sub-option codes are defined by the vendor
- *   identified in the enterprise-number field and are not managed by
- *   IANA.  Each of the sub-options is formatted as follows:
- *
- *       0                   1                   2                   3
- *       0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- *      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *      |          sub-opt-code         |         sub-option-len        |
- *      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *      .                                                               .
- *      .                        sub-option-data                        .
- *      .                                                               .
- *      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- */
-static ssize_t encode_vsio_suboption_hdr(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                 slen;
-       uint8_t                 *p = out, *end = p + outlen;
-       fr_dict_attr_t const    *da, *dv;
-
-       FR_PROTO_STACK_PRINT(tlv_stack, depth);
-
-       /*
-        *      This is the dictionary attribute which contains the
-        *      vendor IANA ID.
-        */
-       dv = tlv_stack[depth++];
-       if (dv->type != FR_TYPE_VENDOR) {
-               fr_strerror_printf("Expected Vendor");
-               return PAIR_ENCODE_ERROR;
-       }
-
-       da = tlv_stack[depth];
-
-       /*
-        *      Encode the different data types
-        */
-       if (da->type == FR_TYPE_TLV) {
-               slen = encode_tlv_hdr(p, end - p, tlv_stack, depth, cursor, encoder_ctx);
-
-       } else {
-               /*
-                *      Normal vendor option
-                */
-               slen = encode_rfc_hdr(p, end - p, tlv_stack, depth, cursor, encoder_ctx);
-       }
-
-       if (slen < 0) return slen;
-       p += slen;
-
-#ifndef NDEBUG
-       FR_PROTO_HEX_DUMP(out, end - p, "Done VSIO body");
-#endif
-
-       return p - out;
-}
 
 /** Encode a Vendor-Specific Information Option
  *
@@ -743,6 +679,7 @@ static ssize_t encode_vsio_hdr(uint8_t *out, size_t outlen,
        uint32_t                pen;
        uint8_t                 *p = out, *end = p + outlen;
        fr_dict_attr_t const    *da = tlv_stack[depth];
+       fr_dict_attr_t const    *dv;
 
        FR_PROTO_STACK_PRINT(tlv_stack, depth);
 
@@ -764,12 +701,12 @@ static ssize_t encode_vsio_hdr(uint8_t *out, size_t outlen,
        /*
         *      Now process the vendor ID part (which is one attribute deeper)
         */
-       da = tlv_stack[++depth];
+       dv = tlv_stack[++depth];
        FR_PROTO_STACK_PRINT(tlv_stack, depth);
 
-       if (da->type != FR_TYPE_VENDOR) {
+       if (dv->type != FR_TYPE_VENDOR) {
                fr_strerror_printf("%s: Expected type \"vsa\" got \"%s\"", __FUNCTION__,
-                                  fr_table_str_by_value(fr_value_box_type_table, da->type, "?Unknown?"));
+                                  fr_table_str_by_value(fr_value_box_type_table, dv->type, "?Unknown?"));
                return PAIR_ENCODE_ERROR;
        }
 
@@ -777,17 +714,47 @@ static ssize_t encode_vsio_hdr(uint8_t *out, size_t outlen,
         *      Copy in the 32bit PEN (Private Enterprise Number)
         */
        p += OPT_HDR_LEN;
-       pen = htonl(da->attr);
+       pen = htonl(dv->attr);
        memcpy(p, &pen, sizeof(pen));
+       p += 4;
+
+       /*
+        *      https://tools.ietf.org/html/rfc8415#section-21.17 says:
+        *
+        *   The vendor-option-data field MUST be encoded as a sequence of
+        *   code/length/value fields of format identical to the DHCP options (see
+        *   Section 21.1).  The sub-option codes are defined by the vendor
+        *   identified in the enterprise-number field and are not managed by
+        *   IANA.  Each of the sub-options is formatted as follows:
+        *
+        *       0                   1                   2                   3
+        *       0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+        *      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+        *      |          sub-opt-code         |         sub-option-len        |
+        *      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+        *      .                                                               .
+        *      .                        sub-option-data                        .
+        *      .                                                               .
+        *      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+        */
 
        /*
-        *      Encode the vendor specific option header
+        *      Encode the different data types
         */
-       slen = encode_vsio_suboption_hdr(p, end - p, tlv_stack, depth, cursor, encoder_ctx);
+       if (da->type == FR_TYPE_TLV) {
+               slen = encode_tlv_hdr(p, end - p, tlv_stack, depth + 1, cursor, encoder_ctx);
+
+       } else {
+               /*
+                *      Normal vendor option
+                */
+               slen = encode_rfc_hdr(p, end - p, tlv_stack, depth + 1, cursor, encoder_ctx);
+       }
+
        if (slen < 0) return slen;
        p += slen;
 
-       encode_option_hdr(out, outlen, da->attr, p - out);
+       encode_option_hdr(out, outlen, da->attr, p - (out + 4));
 
 #ifndef NDEBUG
        FR_PROTO_HEX_DUMP(out, end - p, "Done VSIO header");
index 5da5bfb33fe365eebc50dd4e6dc86b8745dda46c..f399bcc1f078c45d8425b673c330b80469f28f90 100644 (file)
@@ -197,7 +197,7 @@ match 00 01 00 12 00 04 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 00 00
 #  For now, the encoder is wrong :(
 #
 encode-pair Microsoft-Rogue-Detection-Request = 0x00
-no match 00 11 00 08 00 01 37 00 5e 00 01 00
+match 00 11 00 09 00 00 01 37 00 5e 00 01 00
 
 count
 match 88