commit 6dd638e: [Feature] Allow unconnected DNS servers operations
Vsevolod Stakhov
vsevolod at highsecure.ru
Sat Mar 30 10:14:04 UTC 2019
Author: Vsevolod Stakhov
Date: 2019-03-30 10:07:57 +0000
URL: https://github.com/rspamd/rspamd/commit/6dd638eafa3413f1adc77b483c0dc51d2cb86750 (HEAD -> master)
[Feature] Allow unconnected DNS servers operations
This allows to stop relying on resolvers initialisation and send
requests when the resolvers are available.
---
contrib/librdns/curve.c | 24 +++++++++----
contrib/librdns/dns_private.h | 3 ++
contrib/librdns/rdns.h | 7 ++--
contrib/librdns/resolver.c | 20 +++++++----
contrib/librdns/util.c | 84 ++++++++++++++++++++++++-------------------
contrib/librdns/util.h | 7 ++--
6 files changed, 90 insertions(+), 55 deletions(-)
diff --git a/contrib/librdns/curve.c b/contrib/librdns/curve.c
index 3976b14a0..0444dd489 100644
--- a/contrib/librdns/curve.c
+++ b/contrib/librdns/curve.c
@@ -448,9 +448,11 @@ rdns_curve_dtor (struct rdns_resolver *resolver, void *plugin_data)
#define crypto_box_ZEROBYTES 32
#define crypto_box_BOXZEROBYTES 16
-ssize_t rdns_curve_send (struct rdns_request *req, void *plugin_data);
+ssize_t rdns_curve_send (struct rdns_request *req, void *plugin_data,
+ struct sockaddr *saddr, socklen_t slen);
ssize_t rdns_curve_recv (struct rdns_io_channel *ioc, void *buf, size_t len,
- void *plugin_data, struct rdns_request **req_out);
+ void *plugin_data, struct rdns_request **req_out,
+ struct sockaddr *saddr, socklen_t slen);
void rdns_curve_finish_request (struct rdns_request *req, void *plugin_data);
void rdns_curve_dtor (struct rdns_resolver *resolver, void *plugin_data);
@@ -683,7 +685,8 @@ rdns_curve_register_plugin (struct rdns_resolver *resolver,
}
ssize_t
-rdns_curve_send (struct rdns_request *req, void *plugin_data)
+rdns_curve_send (struct rdns_request *req, void *plugin_data,
+ struct sockaddr *saddr, socklen_t slen)
{
struct rdns_curve_ctx *ctx = (struct rdns_curve_ctx *)plugin_data;
struct rdns_curve_entry *entry;
@@ -746,12 +749,19 @@ rdns_curve_send (struct rdns_request *req, void *plugin_data)
iov[3].iov_base = m + crypto_box_BOXZEROBYTES;
iov[3].iov_len = boxed_len - crypto_box_BOXZEROBYTES;
- ret = writev (req->io->sock, iov, sizeof (iov) / sizeof (iov[0]));
+ struct msghdr msg;
+
+ memset (&msg, 0, sizeof (msg));
+ msg.msg_namelen = slen;
+ msg.msg_name = saddr;
+ msg.msg_iov = iov;
+ msg.msg_iovlen = sizeof (iov) / sizeof (iov[0]);
+ ret = sendmsg (req->io->sock, &msg, 0);
rspamd_explicit_memzero (m, boxed_len);
free (m);
}
else {
- ret = write (req->io->sock, req->packet, req->pos);
+ ret = sendto (req->io->sock, req->packet, req->pos, 0, saddr, slen);
req->curve_plugin_data = NULL;
}
@@ -760,7 +770,7 @@ rdns_curve_send (struct rdns_request *req, void *plugin_data)
ssize_t
rdns_curve_recv (struct rdns_io_channel *ioc, void *buf, size_t len, void *plugin_data,
- struct rdns_request **req_out)
+ struct rdns_request **req_out, struct sockaddr *saddr, socklen_t slen)
{
struct rdns_curve_ctx *ctx = (struct rdns_curve_ctx *)plugin_data;
ssize_t ret, boxlen;
@@ -771,7 +781,7 @@ rdns_curve_recv (struct rdns_io_channel *ioc, void *buf, size_t len, void *plugi
struct rdns_resolver *resolver;
resolver = ctx->resolver;
- ret = read (ioc->sock, buf, len);
+ ret = recvfrom (ioc->sock, buf, len, 0, saddr, &slen);
if (ret <= 0 || ret < 64) {
/* Definitely not a DNSCurve packet */
diff --git a/contrib/librdns/dns_private.h b/contrib/librdns/dns_private.h
index 8200bf038..3d25d21b8 100644
--- a/contrib/librdns/dns_private.h
+++ b/contrib/librdns/dns_private.h
@@ -97,12 +97,15 @@ struct rdns_request {
ref_entry_t ref;
};
+
/**
* IO channel for a specific DNS server
*/
struct rdns_io_channel {
struct rdns_server *srv;
struct rdns_resolver *resolver;
+ struct sockaddr *saddr;
+ socklen_t slen;
int sock; /**< persistent socket */
bool active;
void *async_io; /** async opaque ptr */
diff --git a/contrib/librdns/rdns.h b/contrib/librdns/rdns.h
index 647f0f1b1..b563c7ea3 100644
--- a/contrib/librdns/rdns.h
+++ b/contrib/librdns/rdns.h
@@ -178,9 +178,12 @@ enum rdns_plugin_type {
RDNS_PLUGIN_CURVE = 0
};
-typedef ssize_t (*rdns_network_send_callback) (struct rdns_request *req, void *plugin_data);
+typedef ssize_t (*rdns_network_send_callback) (struct rdns_request *req, void *plugin_data,
+ struct sockaddr *saddr, socklen_t slen);
typedef ssize_t (*rdns_network_recv_callback) (struct rdns_io_channel *ioc, void *buf,
- size_t len, void *plugin_data, struct rdns_request **req_out);
+ size_t len, void *plugin_data,
+ struct rdns_request **req_out,
+ struct sockaddr *saddr, socklen_t slen);
typedef void (*rdns_network_finish_callback) (struct rdns_request *req, void *plugin_data);
typedef void (*rdns_plugin_dtor_callback) (struct rdns_resolver *resolver, void *plugin_data);
diff --git a/contrib/librdns/resolver.c b/contrib/librdns/resolver.c
index 522ec0d9c..5f15d242c 100644
--- a/contrib/librdns/resolver.c
+++ b/contrib/librdns/resolver.c
@@ -68,11 +68,15 @@ rdns_send_request (struct rdns_request *req, int fd, bool new_req)
}
if (resolver->curve_plugin == NULL) {
- r = send (fd, req->packet, req->pos, 0);
+ r = sendto (fd, req->packet, req->pos, 0,
+ req->io->saddr,
+ req->io->slen);
}
else {
r = resolver->curve_plugin->cb.curve_plugin.send_cb (req,
- resolver->curve_plugin->data);
+ resolver->curve_plugin->data,
+ req->io->saddr,
+ req->io->slen);
}
if (r == -1) {
if (errno == EAGAIN || errno == EINTR) {
@@ -253,14 +257,15 @@ rdns_process_read (int fd, void *arg)
/* First read packet from socket */
if (resolver->curve_plugin == NULL) {
- r = read (fd, in, sizeof (in));
+ r = recvfrom (fd, in, sizeof (in), 0, ioc->saddr, &ioc->slen);
if (r > (int)(sizeof (struct dns_header) + sizeof (struct dns_query))) {
req = rdns_find_dns_request (in, ioc);
}
}
else {
r = resolver->curve_plugin->cb.curve_plugin.recv_cb (ioc, in,
- sizeof (in), resolver->curve_plugin->data, &req);
+ sizeof (in), resolver->curve_plugin->data, &req,
+ ioc->saddr, ioc->slen);
if (req == NULL &&
r > (int)(sizeof (struct dns_header) + sizeof (struct dns_query))) {
req = rdns_find_dns_request (in, ioc);
@@ -446,7 +451,7 @@ rdns_process_ioc_refresh (void *arg)
continue;
}
nioc->sock = rdns_make_client_socket (serv->name, serv->port,
- SOCK_DGRAM);
+ SOCK_DGRAM, &nioc->saddr, &nioc->slen);
if (nioc->sock == -1) {
rdns_err ("cannot open socket to %s: %s", serv->name,
strerror (errno));
@@ -713,7 +718,7 @@ rdns_make_request_full (
}
req->async = resolver->async;
-
+retry:
if (resolver->ups) {
struct rdns_upstream_elt *elt;
@@ -791,7 +796,8 @@ rdns_resolver_init (struct rdns_resolver *resolver)
return false;
}
- ioc->sock = rdns_make_client_socket (serv->name, serv->port, SOCK_DGRAM);
+ ioc->sock = rdns_make_client_socket (serv->name, serv->port, SOCK_DGRAM,
+ &ioc->saddr, &ioc->slen);
if (ioc->sock == -1) {
ioc->active = false;
diff --git a/contrib/librdns/util.c b/contrib/librdns/util.c
index 9f1bc6018..863db3564 100644
--- a/contrib/librdns/util.c
+++ b/contrib/librdns/util.c
@@ -53,7 +53,8 @@ rdns_make_socket_nonblocking (int fd)
}
static int
-rdns_make_inet_socket (int type, struct addrinfo *addr)
+rdns_make_inet_socket (int type, struct addrinfo *addr, struct sockaddr **psockaddr,
+ socklen_t *psocklen)
{
int fd, r, s_error;
socklen_t optlen;
@@ -76,21 +77,9 @@ rdns_make_inet_socket (int type, struct addrinfo *addr)
goto out;
}
- r = connect (fd, cur->ai_addr, cur->ai_addrlen);
-
- if (r == -1) {
- if (errno != EINPROGRESS) {
- goto out;
- }
- }
- else {
- /* Still need to check SO_ERROR on socket */
- optlen = sizeof (s_error);
- getsockopt (fd, SOL_SOCKET, SO_ERROR, (void *)&s_error, &optlen);
- if (s_error) {
- errno = s_error;
- goto out;
- }
+ if (psockaddr) {
+ *psockaddr = cur->ai_addr;
+ *psocklen = cur->ai_addrlen;
}
break;
out:
@@ -100,6 +89,7 @@ out:
fd = -1;
cur = cur->ai_next;
}
+
return (fd);
}
@@ -136,23 +126,6 @@ rdns_make_unix_socket (const char *path, struct sockaddr_un *addr, int type)
goto out;
}
- r = connect (fd, (struct sockaddr *)addr, SUN_LEN (addr));
-
- if (r == -1) {
- if (errno != EINPROGRESS) {
- goto out;
- }
- }
- else {
- /* Still need to check SO_ERROR on socket */
- optlen = sizeof (s_error);
- getsockopt (fd, SOL_SOCKET, SO_ERROR, (void *)&s_error, &optlen);
- if (s_error) {
- errno = s_error;
- goto out;
- }
- }
-
return (fd);
out:
@@ -173,8 +146,11 @@ rdns_make_unix_socket (const char *path, struct sockaddr_un *addr, int type)
* @param try_resolve try name resolution for a socket (BLOCKING)
*/
int
-rdns_make_client_socket (const char *credits, uint16_t port,
- int type)
+rdns_make_client_socket (const char *credits,
+ uint16_t port,
+ int type,
+ struct sockaddr **psockaddr,
+ socklen_t *psocklen)
{
struct sockaddr_un un;
struct stat st;
@@ -196,7 +172,25 @@ rdns_make_client_socket (const char *credits, uint16_t port,
return -1;
}
else {
- return rdns_make_unix_socket (credits, &un, type);
+ r = rdns_make_unix_socket (credits, &un, type);
+
+ if (r != -1 && psockaddr) {
+ struct sockaddr *cpy;
+
+ cpy = calloc (1, sizeof (un));
+ *psockaddr = sizeof (un);
+
+ if (cpy == NULL) {
+ close (r);
+
+ return -1;
+ }
+
+ memcpy (cpy, &un, *psocklen);
+ *psockaddr = cpy;
+ }
+
+ return r;
}
}
}
@@ -215,7 +209,23 @@ rdns_make_client_socket (const char *credits, uint16_t port,
snprintf (portbuf, sizeof (portbuf), "%d", (int)port);
if ((r = getaddrinfo (credits, portbuf, &hints, &res)) == 0) {
- r = rdns_make_inet_socket (type, res);
+ r = rdns_make_inet_socket (type, res, psockaddr, psocklen);
+
+ if (r != -1 && psockaddr) {
+ struct sockaddr *cpy;
+
+ cpy = calloc (1, *psocklen);
+
+ if (cpy == NULL) {
+ close (r);
+
+ return -1;
+ }
+
+ memcpy (cpy, *psockaddr, *psocklen);
+ *psockaddr = cpy;
+ }
+
freeaddrinfo (res);
return r;
}
diff --git a/contrib/librdns/util.h b/contrib/librdns/util.h
index 4da927c3a..8d11d0cfc 100644
--- a/contrib/librdns/util.h
+++ b/contrib/librdns/util.h
@@ -32,8 +32,11 @@
* @param type of socket (SOCK_STREAM or SOCK_DGRAM)
*/
int
-rdns_make_client_socket (const char *credits, uint16_t port,
- int type);
+rdns_make_client_socket (const char *credits,
+ uint16_t port,
+ int type,
+ struct sockaddr **psockaddr,
+ socklen_t *psocklen);
/**
* Generate new random DNS id
More information about the Commits
mailing list