#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);
}
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;
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;
}
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;
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 */
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 */
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);
}
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) {
/* 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);
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));
}
req->async = resolver->async;
-
+retry:
if (resolver->ups) {
struct rdns_upstream_elt *elt;
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;
}
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;
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:
fd = -1;
cur = cur->ai_next;
}
+
return (fd);
}
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:
* @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;
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;
}
}
}
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;
}
* @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