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