From: Vsevolod Stakhov Date: Sat, 30 Mar 2019 10:07:57 +0000 (+0000) Subject: [Feature] Allow unconnected DNS servers operations X-Git-Tag: 1.9.1~22 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=6dd638eafa3413f1adc77b483c0dc51d2cb86750;p=rspamd.git [Feature] Allow unconnected DNS servers operations This allows to stop relying on resolvers initialisation and send requests when the resolvers are available. --- 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