summaryrefslogtreecommitdiff
path: root/util/netevent.c
diff options
context:
space:
mode:
Diffstat (limited to 'util/netevent.c')
-rw-r--r--util/netevent.c65
1 files changed, 63 insertions, 2 deletions
diff --git a/util/netevent.c b/util/netevent.c
index 3bb8948889c5..b827e6540b1f 100644
--- a/util/netevent.c
+++ b/util/netevent.c
@@ -56,7 +56,9 @@
/* -------- Start of local definitions -------- */
/** if CMSG_ALIGN is not defined on this platform, a workaround */
#ifndef CMSG_ALIGN
-# ifdef _CMSG_DATA_ALIGN
+# ifdef __CMSG_ALIGN
+# define CMSG_ALIGN(n) __CMSG_ALIGN(n)
+# elif defined(CMSG_DATA_ALIGN)
# define CMSG_ALIGN _CMSG_DATA_ALIGN
# else
# define CMSG_ALIGN(len) (((len)+sizeof(long)-1) & ~(sizeof(long)-1))
@@ -356,7 +358,12 @@ udp_send_errno_needs_log(struct sockaddr* addr, socklen_t addrlen)
#endif
/* permission denied is gotten for every send if the
* network is disconnected (on some OS), squelch it */
- if(errno == EPERM && verbosity < VERB_DETAIL)
+ if( ((errno == EPERM)
+# ifdef EADDRNOTAVAIL
+ /* 'Cannot assign requested address' also when disconnected */
+ || (errno == EADDRNOTAVAIL)
+# endif
+ ) && verbosity < VERB_DETAIL)
return 0;
/* squelch errors where people deploy AAAA ::ffff:bla for
* authority servers, which we try for intranets. */
@@ -394,6 +401,31 @@ comm_point_send_udp_msg(struct comm_point *c, sldns_buffer* packet,
sldns_buffer_remaining(packet), 0,
addr, addrlen);
if(sent == -1) {
+ /* try again and block, waiting for IO to complete,
+ * we want to send the answer, and we will wait for
+ * the ethernet interface buffer to have space. */
+#ifndef USE_WINSOCK
+ if(errno == EAGAIN ||
+# ifdef EWOULDBLOCK
+ errno == EWOULDBLOCK ||
+# endif
+ errno == ENOBUFS) {
+#else
+ if(WSAGetLastError() == WSAEINPROGRESS ||
+ WSAGetLastError() == WSAENOBUFS ||
+ WSAGetLastError() == WSAEWOULDBLOCK) {
+#endif
+ int e;
+ fd_set_block(c->fd);
+ sent = sendto(c->fd, (void*)sldns_buffer_begin(packet),
+ sldns_buffer_remaining(packet), 0,
+ addr, addrlen);
+ e = errno;
+ fd_set_nonblock(c->fd);
+ errno = e;
+ }
+ }
+ if(sent == -1) {
if(!udp_send_errno_needs_log(addr, addrlen))
return 0;
#ifndef USE_WINSOCK
@@ -547,11 +579,40 @@ comm_point_send_udp_msg_if(struct comm_point *c, sldns_buffer* packet,
p_ancil("send_udp over interface", r);
sent = sendmsg(c->fd, &msg, 0);
if(sent == -1) {
+ /* try again and block, waiting for IO to complete,
+ * we want to send the answer, and we will wait for
+ * the ethernet interface buffer to have space. */
+#ifndef USE_WINSOCK
+ if(errno == EAGAIN ||
+# ifdef EWOULDBLOCK
+ errno == EWOULDBLOCK ||
+# endif
+ errno == ENOBUFS) {
+#else
+ if(WSAGetLastError() == WSAEINPROGRESS ||
+ WSAGetLastError() == WSAENOBUFS ||
+ WSAGetLastError() == WSAEWOULDBLOCK) {
+#endif
+ int e;
+ fd_set_block(c->fd);
+ sent = sendmsg(c->fd, &msg, 0);
+ e = errno;
+ fd_set_nonblock(c->fd);
+ errno = e;
+ }
+ }
+ if(sent == -1) {
if(!udp_send_errno_needs_log(addr, addrlen))
return 0;
verbose(VERB_OPS, "sendmsg failed: %s", strerror(errno));
log_addr(VERB_OPS, "remote address is",
(struct sockaddr_storage*)addr, addrlen);
+#ifdef __NetBSD__
+ /* netbsd 7 has IP_PKTINFO for recv but not send */
+ if(errno == EINVAL && r->srctype == 4)
+ log_err("sendmsg: No support for sendmsg(IP_PKTINFO). "
+ "Please disable interface-automatic");
+#endif
return 0;
} else if((size_t)sent != sldns_buffer_remaining(packet)) {
log_err("sent %d in place of %d bytes",