]> source.dussan.org Git - rspamd.git/commitdiff
[Minor] Improve fake names processing
authorVsevolod Stakhov <vsevolod@highsecure.ru>
Mon, 11 Jun 2018 13:49:10 +0000 (14:49 +0100)
committerVsevolod Stakhov <vsevolod@highsecure.ru>
Mon, 11 Jun 2018 13:49:10 +0000 (14:49 +0100)
contrib/librdns/dns_private.h
contrib/librdns/rdns.h
contrib/librdns/resolver.c

index 44bb3dd841df3abd4c370186869513caf94339b5..a82ebd62e25a07f2248f85bbcc6abbaf5bf365bd 100644 (file)
@@ -111,11 +111,16 @@ struct rdns_io_channel {
        ref_entry_t ref;
 };
 
-struct rdns_fake_reply {
-       char *request;
+struct rdns_fake_reply_idx {
        enum dns_rcode rcode;
+       unsigned len;
+       char request[0];
+};
+
+struct rdns_fake_reply {
        struct rdns_reply_entry *result;
        UT_hash_handle hh;
+       struct rdns_fake_reply_idx key;
 };
 
 
index 545d9421fb52b990bc8c8ec17e29056d39a9864d..cd4094d45d590ddd9034c2186b7d218181afd272 100644 (file)
@@ -221,6 +221,8 @@ struct rdns_request_name {
        unsigned int len;
 };
 
+#define MAX_FAKE_NAME 1000
+
 /*
  * RDNS API
  */
@@ -327,7 +329,7 @@ void rdns_resolver_register_plugin (struct rdns_resolver *resolver,
  * Add a fake reply for a specified name
  * @param resolver
  * @param type
- * @param name
+ * @param name (must not be larger than MAX_FAKE_NAME)
  * @param reply
  */
 void rdns_resolver_set_fake_reply (struct rdns_resolver *resolver,
index 7afabb1baded003beeff96bae7a157a0634cdc7a..f3eaa44d96e0a551e695ce85e2aadfd51be064a7 100644 (file)
@@ -521,6 +521,9 @@ rdns_process_retransmit (int fd, void *arg)
        }
 }
 
+#define align_ptr(p, a)                                                   \
+    (guint8 *) (((uintptr_t) (p) + ((uintptr_t) a - 1)) & ~((uintptr_t) a - 1))
+
 struct rdns_request*
 rdns_make_request_full (
                struct rdns_resolver *resolver,
@@ -541,6 +544,8 @@ rdns_make_request_full (
        const char *cur_name, *last_name = NULL;
        struct rdns_compression_entry *comp = NULL;
        struct rdns_fake_reply *fake_rep = NULL;
+       char fake_buf[MAX_FAKE_NAME + sizeof (struct rdns_fake_reply_idx) + 16];
+       struct rdns_fake_reply_idx *idx;
 
        if (resolver == NULL || !resolver->initialized) {
                return NULL;
@@ -578,26 +583,35 @@ rdns_make_request_full (
        for (i = 0; i < queries * 2; i += 2) {
                cur = i / 2;
                cur_name = va_arg (args, const char *);
-
-               if (last_name == NULL) {
-                       HASH_FIND_STR (resolver->fake_elts, cur_name, fake_rep);
-
-                       if (fake_rep) {
-                               /* We actually treat it as a short-circuit */
-                               req->reply = rdns_make_reply (req, fake_rep->rcode);
-                               req->reply->entries = fake_rep->result;
-                               req->state = RDNS_REQUEST_FAKE;
-                       }
-               }
+               type = va_arg (args, int);
 
                if (cur_name != NULL) {
-                       last_name = cur_name;
                        clen = strlen (cur_name);
+
                        if (clen == 0) {
                                rdns_info ("got empty name to resolve");
                                rdns_request_free (req);
                                return NULL;
                        }
+
+                       if (last_name == NULL && queries == 1 && clen < MAX_FAKE_NAME) {
+                               /* We allocate structure in the static space */
+                               idx = (struct rdns_fake_reply_idx *)align_ptr (fake_buf, 16);
+                               idx->rcode = type;
+                               idx->len = clen;
+                               memcpy (idx->request, cur_name, clen);
+                               HASH_FIND (hh, resolver->fake_elts, idx, sizeof (*idx) + clen,
+                                               fake_rep);
+
+                               if (fake_rep) {
+                                       /* We actually treat it as a short-circuit */
+                                       req->reply = rdns_make_reply (req, idx->rcode);
+                                       req->reply->entries = fake_rep->result;
+                                       req->state = RDNS_REQUEST_FAKE;
+                               }
+                       }
+
+                       last_name = cur_name;
                        tlen += clen;
                }
                else if (last_name == NULL) {
@@ -606,17 +620,22 @@ rdns_make_request_full (
                        return NULL;
                }
 
-               if (req->state != RDNS_REQUEST_FAKE &&
-                       !rdns_format_dns_name (resolver, last_name, clen,
-                               &req->requested_names[cur].name, &olen)) {
-                       rdns_request_free (req);
-                       return NULL;
+               if (req->state != RDNS_REQUEST_FAKE) {
+                       if (!rdns_format_dns_name (resolver, last_name, clen,
+                                       &req->requested_names[cur].name, &olen)) {
+                               rdns_request_free (req);
+                               return NULL;
+                       }
+
+                       req->requested_names[cur].len = olen;
+               }
+               else {
+                       req->requested_names[cur].len = clen;
                }
 
-               type = va_arg (args, int);
                req->requested_names[cur].type = type;
-               req->requested_names[cur].len = olen;
        }
+
        va_end (args);
 
        if (req->state != RDNS_REQUEST_FAKE) {
@@ -928,31 +947,30 @@ void rdns_resolver_set_fake_reply (struct rdns_resolver *resolver,
                                                                   struct rdns_reply_entry *reply)
 {
        struct rdns_fake_reply *fake_rep;
+       struct rdns_fake_reply_idx *srch;
+       unsigned len = strlen (name);
+
+       assert (len < MAX_FAKE_NAME);
+       srch = malloc (sizeof (*srch) + len);
+       srch->len = len;
+       srch->rcode = rcode;
+       memcpy (srch->request, name, len);
 
-       HASH_FIND_STR (resolver->fake_elts, name, fake_rep);
+       HASH_FIND (hh, resolver->fake_elts, srch, len + sizeof (*srch), fake_rep);
 
        if (fake_rep) {
                /* Append reply to the existing list */
-               fake_rep->rcode = rcode;
                DL_APPEND (fake_rep->result, reply);
        }
        else {
-               fake_rep = calloc (1, sizeof (*fake_rep));
+               fake_rep = calloc (1, sizeof (*fake_rep) + len);
 
                if (fake_rep == NULL) {
                        abort ();
                }
 
-               fake_rep->request = strdup (name);
-
-               if (fake_rep->request == NULL) {
-                       abort ();
-               }
-
-               fake_rep->rcode = rcode;
+               memcpy (&fake_rep->key, srch, sizeof (*srch) + len);
                DL_APPEND (fake_rep->result, reply);
-
-               HASH_ADD_KEYPTR (hh, resolver->fake_elts, fake_rep->request,
-                               strlen (fake_rep->request), fake_rep);
+               HASH_ADD (hh, resolver->fake_elts, key, sizeof (*srch) + len, fake_rep);
        }
 }
\ No newline at end of file