]> source.dussan.org Git - rspamd.git/commitdiff
[Feature] Allow unconnected DNS servers operations
authorVsevolod Stakhov <vsevolod@highsecure.ru>
Sat, 30 Mar 2019 10:07:57 +0000 (10:07 +0000)
committerVsevolod Stakhov <vsevolod@highsecure.ru>
Sat, 30 Mar 2019 10:07:57 +0000 (10:07 +0000)
This allows to stop relying on resolvers initialisation and send
requests when the resolvers are available.

contrib/librdns/curve.c
contrib/librdns/dns_private.h
contrib/librdns/rdns.h
contrib/librdns/resolver.c
contrib/librdns/util.c
contrib/librdns/util.h

index 3976b14a01414b12c35b3cbd1ea93545aacbe6ae..0444dd4896efb24ef8ca2844fec534638066867d 100644 (file)
@@ -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 */
index 8200bf038ed26257e9a1893c17907abf05f6ee16..3d25d21b8afa03a854e27cbbde2eb04a424c1089 100644 (file)
@@ -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 */
index 647f0f1b116877e3c9f97bdb1ed1074051eb86e8..b563c7ea3fc20e6ceca83d58cbf579dee1923f4c 100644 (file)
@@ -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);
 
index 522ec0d9cba0f2b81c20af709291f96e77fc0a6c..5f15d242c76524e3fdc107435fb3ad6b67b95b97 100644 (file)
@@ -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;
index 9f1bc60182275e22048d37c65fcbe71b4edaf9cb..863db35645b194f4ae0bcf716ce95aac277e1dda 100644 (file)
@@ -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;
                }
index 4da927c3a1d54016ad97297e0af073a61847c945..8d11d0cfca48fc02d5b966e14b56da7f83ce43ee 100644 (file)
  * @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