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

index 439ab1311fc89cba438e71b7dd7440e5ad012464..dc6ee368d2ead250c62e92d425680964cb325a23 100644 (file)
@@ -73,6 +73,14 @@ fr_dict_attr_autoload_t dns_dict_attr[] = {
        [FR_DNS_STATEFUL_OPERATION] = "Stateful-Operation",
 };
 
+FR_DICT_ATTR_FLAG_FUNC(fr_dns_attr_flags_t, dns_label)
+FR_DICT_ATTR_FLAG_FUNC(fr_dns_attr_flags_t, uncompressed)
+
+static fr_dict_flag_parser_t const dns_flags[] = {
+       { L("dns_label"),       { .func = dict_flag_dns_label } },
+       { L("uncompressed"),    { .func = dict_flag_uncompressed } }
+};
+
 #define DECODE_FAIL(_reason) if (reason) *reason = FR_DNS_DECODE_FAIL_ ## _reason
 
 static bool fr_dns_tlv_ok(uint8_t const *p, uint8_t const *end, fr_dns_decode_fail_t *reason)
@@ -432,12 +440,6 @@ void fr_dns_global_free(void)
        fr_dict_autofree(dns_dict);
 }
 
-static fr_table_num_ordered_t const subtype_table[] = {
-       { L("dns_label"),                       FLAG_ENCODE_DNS_LABEL },
-       { L("uncompressed"),                    FLAG_ENCODE_DNS_LABEL_UNCOMPRESSED },
-};
-
-
 static bool attr_valid(fr_dict_attr_t *da)
 {
        /*
@@ -448,19 +450,14 @@ static bool attr_valid(fr_dict_attr_t *da)
                da->flags.is_known_width = true;
        }
 
-       /*
-        *      "extra" signifies that subtype is being used by the
-        *      dictionaries itself.
-        */
-       if (da->flags.extra || !da->flags.subtype) return true;
-
-       if (da->type != FR_TYPE_STRING) {
-               fr_strerror_const("The 'dns_label' flag can only be used with attributes of type 'string'");
-               return false;
+       if (fr_dns_flag_dns_label(da) || fr_dns_flag_uncompressed(da)) {
+               if (da->type != FR_TYPE_STRING) {
+                       fr_strerror_const("The 'dns_label' flag can only be used with attributes of type 'string'");
+                       return false;
+               }
+               da->flags.is_known_width = true;        /* Lie so we don't trip up the main validation checks */
        }
 
-       da->flags.is_known_width = true;
-
        return true;
 }
 
@@ -469,9 +466,10 @@ fr_dict_protocol_t libfreeradius_dns_dict_protocol = {
        .name = "dns",
        .default_type_size = 2,
        .default_type_length = 2,
-       .subtype_table = subtype_table,
-       .subtype_table_len = NUM_ELEMENTS(subtype_table),
        .attr = {
+               .flags_table = dns_flags,
+               .flags_table_len = NUM_ELEMENTS(dns_flags),
+               .flags_len = sizeof(fr_dns_attr_flags_t),
                .valid = attr_valid
        },
 
index 3033910e1bdf3474aa396cc3609794aeb8181aec..8225be8157e2f5e8eb984da73f4cd17b5d4701ac 100644 (file)
@@ -70,15 +70,6 @@ typedef struct {
        uint16_t        arcount;
 } CC_HINT(__packed__) fr_dns_packet_t;
 
-/** subtype values for DHCPv4 and DHCPv6
- *
- */
-enum {
-       FLAG_ENCODE_NONE = 0,                           //!< no particular encoding for DNS strings
-       FLAG_ENCODE_DNS_LABEL,                          //!< encode as DNS label
-       FLAG_ENCODE_DNS_LABEL_UNCOMPRESSED,             //!< encode as uncompressed DNS label
-};
-
 typedef struct {
        TALLOC_CTX              *tmp_ctx;               //!< for temporary things cleaned up during decoding
        uint8_t const           *packet;                //!< DNS labels can point anywhere in the packet :(
@@ -140,6 +131,19 @@ typedef enum {
 
 #define DNS_HDR_LEN (12)
 
+typedef struct {
+       bool                    dns_label;
+       bool                    uncompressed;
+} fr_dns_attr_flags_t;
+
+static inline fr_dns_attr_flags_t const *fr_dns_attr_flags(fr_dict_attr_t const *da)
+{
+       return fr_dict_attr_ext(da, FR_DICT_ATTR_EXT_PROTOCOL_SPECIFIC);
+}
+
+#define fr_dns_flag_dns_label(_da)                     (fr_dns_attr_flags(_da)->dns_label)
+#define fr_dns_flag_uncompressed(_da)                  (fr_dns_attr_flags(_da)->uncompressed)
+
 extern fr_table_num_ordered_t fr_dns_reason_fail_table[];
 extern char const *fr_dns_packet_names[FR_DNS_CODE_MAX];
 extern size_t fr_dns_reason_fail_table_len;
index 7007cca77cf00bc2916b078683003bd36e32913a..8ae92b99f6870b91671a6a3bc0218d5df836cc35 100644 (file)
@@ -152,13 +152,13 @@ static ssize_t encode_value(fr_dbuff_t *dbuff,
                if (!da->flags.extra) {
                        fr_dbuff_marker_t       last_byte, src;
 
-                       fr_assert((da->flags.subtype == FLAG_ENCODE_DNS_LABEL) ||
-                                 (da->flags.subtype == FLAG_ENCODE_DNS_LABEL_UNCOMPRESSED));
+                       fr_assert(fr_dns_flag_dns_label(da) ||
+                                 fr_dns_flag_uncompressed(da));
 
                        fr_dbuff_marker(&last_byte, &work_dbuff);
                        fr_dbuff_marker(&src, &work_dbuff);
                        FR_PROTO_TRACE("encode DNS label %s", vp->vp_strvalue);
-                       slen = fr_dns_label_from_value_box_dbuff(&work_dbuff, (da->flags.subtype == FLAG_ENCODE_DNS_LABEL),
+                       slen = fr_dns_label_from_value_box_dbuff(&work_dbuff, fr_dns_flag_dns_label(da),
                                                                 &vp->data, packet_ctx->lb);
                        if (slen < 0) return slen;
                        break;