]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
Switch DHCPv6 to using custom flag parsers
authorArran Cudbard-Bell <a.cudbardb@freeradius.org>
Fri, 25 Oct 2024 05:20:36 +0000 (23:20 -0600)
committerArran Cudbard-Bell <a.cudbardb@freeradius.org>
Fri, 25 Oct 2024 05:20:36 +0000 (23:20 -0600)
src/protocols/dhcpv6/base.c
src/protocols/dhcpv6/decode.c
src/protocols/dhcpv6/dhcpv6.h
src/protocols/dhcpv6/encode.c

index 9c578ba01c37117ad916062f1d9facd8d2a3cdab..6a4081939410292a080ebfb95ff90cab27c18c6c 100644 (file)
@@ -107,9 +107,12 @@ char const *fr_dhcpv6_packet_names[FR_DHCPV6_CODE_MAX] = {
         [FR_PACKET_TYPE_VALUE_CONTACT]                 = "Contact"
 };
 
-static fr_table_num_ordered_t const subtype_table[] = {
-       { L("dns_label"),                       FLAG_ENCODE_DNS_LABEL },
-       { L("partial_dns_label"),               FLAG_ENCODE_PARTIAL_DNS_LABEL }
+FR_DICT_ATTR_FLAG_FUNC(fr_dhcpv6_attr_flags_t, dns_label)
+FR_DICT_ATTR_FLAG_FUNC(fr_dhcpv6_attr_flags_t, partial_dns_label)
+
+static fr_dict_flag_parser_t const dhcpv6_flags[] = {
+       { L("dns_label"),               { .func = dict_flag_dns_label } },
+       { L("partial_dns_label"),       { .func = dict_flag_partial_dns_label } }
 };
 
 static ssize_t fr_dhcpv6_ok_internal(uint8_t const *packet, uint8_t const *end, size_t max_attributes, int depth);
@@ -970,7 +973,7 @@ static bool attr_valid(fr_dict_attr_t *da)
         */
        if (da->flags.extra || !da->flags.subtype) return true;
 
-       if ((da->type != FR_TYPE_STRING) && ((da->flags.subtype == FLAG_ENCODE_DNS_LABEL) || (da->flags.subtype == FLAG_ENCODE_PARTIAL_DNS_LABEL))) {
+       if ((da->type != FR_TYPE_STRING) && fr_dhcpv6_flag_any_dns_label(da)) {
                fr_strerror_const("The 'dns_label' flag can only be used with attributes of type 'string'");
                return false;
        }
@@ -985,10 +988,12 @@ fr_dict_protocol_t libfreeradius_dhcpv6_dict_protocol = {
        .name = "dhcpv6",
        .default_type_size = 2,
        .default_type_length = 2,
-       .subtype_table = subtype_table,
-       .subtype_table_len = NUM_ELEMENTS(subtype_table),
+
        .attr = {
                .valid = attr_valid,
+               .flags_table = dhcpv6_flags,
+               .flags_table_len = NUM_ELEMENTS(dhcpv6_flags),
+               .flags_len = sizeof(fr_dhcpv6_attr_flags_t)
        },
 
        .init = fr_dhcpv6_global_init,
index 5840ef16ade4fb6248c61aa29f562a5f6203ebc7..e7ed490dfb1a2afd1d526de83c7b7c3de806da06 100644 (file)
@@ -58,7 +58,7 @@ static ssize_t decode_value_trampoline(TALLOC_CTX *ctx, fr_pair_list_t *out,
                                       fr_dict_attr_t const *parent,
                                       uint8_t const *data, size_t const data_len, void *decode_ctx)
 {
-       if ((parent->type == FR_TYPE_STRING) && da_is_dns_label(parent)) {
+       if ((parent->type == FR_TYPE_STRING) && fr_dhcpv6_flag_any_dns_label(parent)) {
                return fr_pair_dns_labels_from_network(ctx, out, parent, data, data, data_len, NULL, false);
        }
 
@@ -369,7 +369,7 @@ static ssize_t decode_option(TALLOC_CTX *ctx, fr_pair_list_t *out,
 
                fr_pair_append(out, vp);
 
-       } else if ((da->type == FR_TYPE_STRING) && da_is_dns_label(da)) {
+       } else if ((da->type == FR_TYPE_STRING) && fr_dhcpv6_flag_any_dns_label(da)) {
                slen = fr_pair_dns_labels_from_network(ctx, out, da, data + 4, data + 4, len, NULL, true);
                if (slen < 0) return slen;
 
index b9484cc5a4e2504dd813a9a2752e75f4a880e9e4..c8eb3e6c090bc48d899e1e508608ef5b7f73d408 100644 (file)
@@ -111,14 +111,6 @@ extern char const          *fr_dhcpv6_packet_names[FR_DHCPV6_CODE_MAX];
 /** subtype values for DHCPv4 and DHCPv6
  *
  */
-enum {
-       FLAG_ENCODE_NONE = 0,                           //!< no particular encoding for DHCPv6 strings
-       FLAG_ENCODE_DNS_LABEL,                          //!< encode as DNS label
-       FLAG_ENCODE_PARTIAL_DNS_LABEL,                  //!< encode as a partial DNS label
-};
-
-#define da_is_dns_label(_da) (!(_da)->flags.extra && (((_da)->flags.subtype == FLAG_ENCODE_DNS_LABEL) || ((_da)->flags.subtype == FLAG_ENCODE_PARTIAL_DNS_LABEL)))
-
 typedef struct CC_HINT(__packed__) {
        uint8_t         code;
        uint8_t         transaction_id[3];
@@ -144,6 +136,26 @@ typedef struct {
        size_t                  duid_len;               //!< length of the expected DUID
 } fr_dhcpv6_decode_ctx_t;
 
+typedef struct {
+       bool                    dns_label;
+       bool                    partial_dns_label;
+} fr_dhcpv6_attr_flags_t;
+
+static inline fr_dhcpv6_attr_flags_t const *fr_dhcpv6_attr_flags(fr_dict_attr_t const *da)
+{
+       return fr_dict_attr_ext(da, FR_DICT_ATTR_EXT_PROTOCOL_SPECIFIC);
+}
+
+#define fr_dhcpv6_flag_dns_label(_da)                  (fr_dhcpv6_attr_flags(_da)->dns_label)
+#define fr_dhcpv6_flag_partial_dns_label(_da)          (fr_dhcpv6_attr_flags(_da)->partial_dns_label)
+
+static inline bool fr_dhcpv6_flag_any_dns_label(fr_dict_attr_t const *da)
+{
+       fr_dhcpv6_attr_flags_t const *flags = fr_dhcpv6_attr_flags(da);
+
+       return flags->dns_label || flags->partial_dns_label;
+}
+
 /*
  *     base.c
  */
index 8a502a4c80fa073f94718e2c32bb71fd9c88663e..c78dd365d22d6a42b65ac26c007fe230372df3dc 100644 (file)
@@ -140,7 +140,7 @@ static ssize_t encode_value(fr_dbuff_t *dbuff,
                 *
                 *      https://tools.ietf.org/html/rfc8415#section-10
                 */
-               if (da_is_dns_label(da)) {
+               if (fr_dhcpv6_flag_any_dns_label(da)) {
                        fr_dbuff_marker_t       last_byte, src;
 
                        fr_dbuff_marker(&last_byte, &work_dbuff);
@@ -154,7 +154,7 @@ static ssize_t encode_value(fr_dbuff_t *dbuff,
                         *      partial name, and we omit the trailing
                         *      zero.
                         */
-                       if ((da->flags.subtype == FLAG_ENCODE_PARTIAL_DNS_LABEL) && slen > 0) {
+                       if (fr_dhcpv6_flag_partial_dns_label(da) && slen > 0) {
                                uint8_t c = 0;
 
                                fr_dbuff_advance(&last_byte, (size_t)(slen - 1));