aboutsummaryrefslogtreecommitdiffstats
path: root/contrib
diff options
context:
space:
mode:
authorVsevolod Stakhov <vsevolod@highsecure.ru>2018-06-11 14:49:10 +0100
committerVsevolod Stakhov <vsevolod@highsecure.ru>2018-06-11 14:49:10 +0100
commit6b07a361d0f9a97ea2734add840c115e1dd183fd (patch)
tree5566dfea8f7886e48c7ca2584bf7a9ffb735f5fc /contrib
parent0e654a69f908ae3abe19663dc192f1dbc45d8ed0 (diff)
downloadrspamd-6b07a361d0f9a97ea2734add840c115e1dd183fd.tar.gz
rspamd-6b07a361d0f9a97ea2734add840c115e1dd183fd.zip
[Minor] Improve fake names processing
Diffstat (limited to 'contrib')
-rw-r--r--contrib/librdns/dns_private.h9
-rw-r--r--contrib/librdns/rdns.h4
-rw-r--r--contrib/librdns/resolver.c82
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