]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
move dns_labels to thread-local variable
authorAlan T. DeKok <aland@freeradius.org>
Wed, 13 Oct 2021 12:33:42 +0000 (08:33 -0400)
committerAlan T. DeKok <aland@freeradius.org>
Wed, 13 Oct 2021 12:34:18 +0000 (08:34 -0400)
because we don't yield when decoding the DNS packet.

src/listen/dns/proto_dns.c
src/protocols/dns/base.c
src/protocols/dns/decode.c
src/protocols/dns/dns.h
src/protocols/dns/encode.c

index c732b1f001d5a95a2c7415016cd0594e4af5868c..98091b7e14ec6c0ef427c10a5a34b8b31dce9e5a 100644 (file)
@@ -197,10 +197,8 @@ static int mod_decode(void const *instance, request_t *request, uint8_t *const d
        packet_ctx.tmp_ctx = talloc(request, uint8_t);
        packet_ctx.packet = request->packet->data;
        packet_ctx.packet_len = data_len;
-
-       packet_ctx.lb = fr_dns_labels_init(packet_ctx.tmp_ctx, packet_ctx.packet, data_len, 0);
+       packet_ctx.lb = fr_dns_labels_get(request->packet->data, data_len, true);
        fr_assert(packet_ctx.lb != NULL);
-       packet_ctx.lb->mark = talloc_zero_array(packet_ctx.lb, uint8_t, data_len);
 
        /*
         *      Note that we don't set a limit on max_attributes here.
@@ -270,9 +268,8 @@ static ssize_t mod_encode(void const *instance, request_t *request, uint8_t *buf
        packet_ctx.packet = buffer;
        packet_ctx.packet_len = buffer_len;
 
-       packet_ctx.lb = fr_dns_labels_init(packet_ctx.tmp_ctx, buffer, buffer_len, 256);
+       packet_ctx.lb = fr_dns_labels_get(buffer, buffer_len, false);
        fr_assert(packet_ctx.lb != NULL);
-       /* no need to set "mark" here, as that field is only used for decoding */
 
        data_len = fr_dns_encode(&FR_DBUFF_TMP(buffer, buffer_len), &request->reply_pairs, &packet_ctx);
        talloc_free(packet_ctx.tmp_ctx);
index 27abe690204b600395d4d95eadc6d6c7a04359af..ed629fe200d5eef45244bf938a212629c9793bce 100644 (file)
@@ -39,6 +39,8 @@ typedef struct {
 
 fr_dict_t const *dict_dns;
 
+static _Thread_local fr_dns_labels_t *fr_dns_labels;
+
 extern fr_dict_autoload_t dns_dict[];
 fr_dict_autoload_t dns_dict[] = {
        { .out = &dict_dns, .proto = "dns" },
@@ -146,6 +148,34 @@ size_t fr_dns_value_len(fr_pair_t const *vp)
        }
 }
 
+fr_dns_labels_t *fr_dns_labels_get(uint8_t const *packet, size_t packet_len, bool init_mark)
+{
+       fr_dns_labels_t *lb = fr_dns_labels;
+
+       if (!lb) return NULL;
+
+       lb->start = packet;
+       lb->end = packet + packet_len;
+
+       lb->num = 1;
+       lb->blocks[0].start = DNS_HDR_LEN;
+       lb->blocks[0].end = DNS_HDR_LEN;
+
+       if (init_mark) memset(lb->mark, 0, talloc_array_length(lb->mark));
+
+       return lb;
+}
+
+/** Cleanup the memory pool used by vlog_request
+ *
+ */
+static void _dns_labels_free(void *arg)
+{
+       talloc_free(arg);
+       fr_dns_labels = NULL;
+}
+
+
 /** Resolve/cache attributes in the DNS dictionary
  *
  * @return
@@ -154,6 +184,8 @@ size_t fr_dns_value_len(fr_pair_t const *vp)
  */
 int fr_dns_global_init(void)
 {
+       fr_dns_labels_t *lb;
+
        if (instance_count > 0) {
                instance_count++;
                return 0;
@@ -161,10 +193,24 @@ int fr_dns_global_init(void)
 
        if (fr_dict_autoload(dns_dict) < 0) return -1;
        if (fr_dict_attr_autoload(dns_dict_attr) < 0) {
+       fail:
                fr_dict_autofree(dns_dict);
                return -1;
        }
 
+       lb =  (fr_dns_labels_t *) talloc_zero_array(NULL, uint8_t, sizeof(*lb) + sizeof(lb->blocks[0]) * 256);
+       if (!lb) goto fail;
+
+       lb->max = 256;
+
+       lb->mark = talloc_array(lb, uint8_t, 65536);
+       if (!lb->mark) {
+               talloc_free(lb);
+               goto fail;
+       }
+
+       fr_atexit_thread_local(fr_dns_labels, _dns_labels_free, lb);
+
        instance_count++;
 
        return 0;
index ea2154d22d05e7719fd9689df256a74a26036c3d..3356aa0e3dc1ea77995ad84b5bb0555a30318a95 100644 (file)
@@ -684,28 +684,8 @@ static ssize_t fr_dns_decode_proto(TALLOC_CTX *ctx, fr_pair_list_t *out, uint8_t
 
        packet_ctx->packet = data;
        packet_ctx->packet_len = data_len;
-
-       if (packet_ctx->lb) {
-               fr_dns_labels_t *lb = packet_ctx->lb;
-
-               lb->start = data;
-               lb->end = data + data_len;
-
-               /*
-                *      Always skip the DNS packet header.
-                */
-               lb->blocks[0].start = 12;
-               lb->blocks[0].end = 12;
-               lb->num = 1;
-
-               memset(packet_ctx->lb->mark, 0, talloc_array_length(packet_ctx->lb->mark));
-       } else {
-               packet_ctx->lb = fr_dns_labels_init(packet_ctx, data, data_len, 256);
-               fr_assert(packet_ctx->lb != NULL);
-
-               packet_ctx->lb->end = data + data_len;
-               packet_ctx->lb->mark = talloc_zero_array(packet_ctx->lb, uint8_t, 65535);
-       }
+       packet_ctx->lb = fr_dns_labels_get(data, data_len, true);
+       fr_assert(packet_ctx->lb != NULL);
 
        return fr_dns_decode(ctx, out, data, data_len,  packet_ctx);
 }
index 0e2ca23b5355ccb906bb4da6f5b58ef56ead9e3a..34bee267bb506a78d0cb3199bc00c929f8cf3b69 100644 (file)
@@ -113,6 +113,8 @@ extern char const *fr_dns_packet_codes[FR_DNS_CODE_MAX];
 
 bool fr_dns_packet_ok(uint8_t const *packet, size_t packet_len, bool query);
 
+fr_dns_labels_t *fr_dns_labels_get(uint8_t const *packet, size_t packet_len, bool init_mark);
+
 size_t fr_dns_value_len(fr_pair_t const *vp);
 
 ssize_t        fr_dns_decode(TALLOC_CTX *ctx, fr_pair_list_t *out,
index a7736446d9095b3668ee30fedc4b1828a5a0b6fe..4a60c797c0a8d5a251a62f595a7a6ae4ca0904c2 100644 (file)
@@ -704,8 +704,7 @@ static ssize_t fr_dns_encode_proto(UNUSED TALLOC_CTX *ctx, fr_pair_list_t *vps,
 
        packet_ctx->packet = data;
        packet_ctx->packet_len = data_len;
-
-       packet_ctx->lb = fr_dns_labels_init(packet_ctx, data, data_len, 256);
+       packet_ctx->lb = fr_dns_labels_get(data, data_len, false);
        fr_assert(packet_ctx->lb != NULL);
 
        slen = fr_dns_encode(&FR_DBUFF_TMP(data, data_len), vps, packet_ctx);