From 6b07a361d0f9a97ea2734add840c115e1dd183fd Mon Sep 17 00:00:00 2001 From: Vsevolod Stakhov Date: Mon, 11 Jun 2018 14:49:10 +0100 Subject: [PATCH] [Minor] Improve fake names processing --- contrib/librdns/dns_private.h | 9 +++- contrib/librdns/rdns.h | 4 +- contrib/librdns/resolver.c | 82 +++++++++++++++++++++-------------- 3 files changed, 60 insertions(+), 35 deletions(-) diff --git a/contrib/librdns/dns_private.h b/contrib/librdns/dns_private.h index 44bb3dd84..a82ebd62e 100644 --- a/contrib/librdns/dns_private.h +++ b/contrib/librdns/dns_private.h @@ -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; }; diff --git a/contrib/librdns/rdns.h b/contrib/librdns/rdns.h index 545d9421f..cd4094d45 100644 --- a/contrib/librdns/rdns.h +++ b/contrib/librdns/rdns.h @@ -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, diff --git a/contrib/librdns/resolver.c b/contrib/librdns/resolver.c index 7afabb1ba..f3eaa44d9 100644 --- a/contrib/librdns/resolver.c +++ b/contrib/librdns/resolver.c @@ -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 -- 2.39.5