summaryrefslogtreecommitdiffstats
path: root/usr.sbin/bind/lib/isc/unix/net.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin/bind/lib/isc/unix/net.c')
-rw-r--r--usr.sbin/bind/lib/isc/unix/net.c355
1 files changed, 4 insertions, 351 deletions
diff --git a/usr.sbin/bind/lib/isc/unix/net.c b/usr.sbin/bind/lib/isc/unix/net.c
index 9335da260ba..339a230b5c5 100644
--- a/usr.sbin/bind/lib/isc/unix/net.c
+++ b/usr.sbin/bind/lib/isc/unix/net.c
@@ -14,7 +14,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: net.c,v 1.7 2019/12/17 02:05:31 deraadt Exp $ */
+/* $Id: net.c,v 1.8 2019/12/17 18:08:48 deraadt Exp $ */
#include <config.h>
@@ -125,14 +125,15 @@ static isc_once_t once_ipv6pktinfo = ISC_ONCE_INIT;
#endif /* ! ISC_CMSG_IP_TOS */
static isc_once_t once = ISC_ONCE_INIT;
-static isc_once_t once_dscp = ISC_ONCE_INIT;
static isc_result_t ipv4_result = ISC_R_NOTFOUND;
static isc_result_t ipv6_result = ISC_R_NOTFOUND;
static isc_result_t unix_result = ISC_R_NOTFOUND;
static isc_result_t ipv6only_result = ISC_R_NOTFOUND;
static isc_result_t ipv6pktinfo_result = ISC_R_NOTFOUND;
-static unsigned int dscp_result = 0;
+static unsigned int dscp_result =
+ ISC_NET_DSCPSETV4 | ISC_NET_DSCPRECVV4 | ISC_NET_DSCPPKTV4 |
+ ISC_NET_DSCPSETV6 | ISC_NET_DSCPRECVV6 | ISC_NET_DSCPPKTV6;
static isc_result_t
try_proto(int domain) {
@@ -415,356 +416,8 @@ isc_net_probe_ipv6pktinfo(void) {
return (ipv6pktinfo_result);
}
-#if ISC_CMSG_IP_TOS || \
- defined(ISC_NET_BSD44MSGHDR) && defined(IPV6_TCLASS) && defined(WANT_IPV6)
-
-static inline ISC_SOCKADDR_LEN_T
-cmsg_len(ISC_SOCKADDR_LEN_T len) {
-#ifdef CMSG_LEN
- return (CMSG_LEN(len));
-#else
- ISC_SOCKADDR_LEN_T hdrlen;
-
- /*
- * Cast NULL so that any pointer arithmetic performed by CMSG_DATA
- * is correct.
- */
- hdrlen = (ISC_SOCKADDR_LEN_T)CMSG_DATA(((struct cmsghdr *)NULL));
- return (hdrlen + len);
-#endif
-}
-
-static inline ISC_SOCKADDR_LEN_T
-cmsg_space(ISC_SOCKADDR_LEN_T len) {
-#ifdef CMSG_SPACE
- return (CMSG_SPACE(len));
-#else
- struct msghdr msg;
- struct cmsghdr *cmsgp;
- /*
- * XXX: The buffer length is an ad-hoc value, but should be enough
- * in a practical sense.
- */
- char dummybuf[sizeof(struct cmsghdr) + 1024];
-
- memset(&msg, 0, sizeof(msg));
- msg.msg_control = dummybuf;
- msg.msg_controllen = sizeof(dummybuf);
-
- cmsgp = (struct cmsghdr *)dummybuf;
- cmsgp->cmsg_len = cmsg_len(len);
-
- cmsgp = CMSG_NXTHDR(&msg, cmsgp);
- if (cmsgp != NULL)
- return ((char *)cmsgp - (char *)msg.msg_control);
- else
- return (0);
-#endif
-}
-
-#ifdef ISC_NET_BSD44MSGHDR
-/*
- * Make a fd non-blocking.
- */
-static isc_result_t
-make_nonblock(int fd) {
- int ret;
- int flags;
- char strbuf[ISC_STRERRORSIZE];
-#ifdef USE_FIONBIO_IOCTL
- int on = 1;
-
- ret = ioctl(fd, FIONBIO, (char *)&on);
-#else
- flags = fcntl(fd, F_GETFL, 0);
- flags |= PORT_NONBLOCK;
- ret = fcntl(fd, F_SETFL, flags);
-#endif
-
- if (ret == -1) {
- isc__strerror(errno, strbuf, sizeof(strbuf));
- UNEXPECTED_ERROR(__FILE__, __LINE__,
-#ifdef USE_FIONBIO_IOCTL
- "ioctl(%d, FIONBIO, &on): %s", fd,
-#else
- "fcntl(%d, F_SETFL, %d): %s", fd, flags,
-#endif
- strbuf);
-
- return (ISC_R_UNEXPECTED);
- }
-
- return (ISC_R_SUCCESS);
-}
-
-static isc_boolean_t
-cmsgsend(int s, int level, int type, struct addrinfo *res) {
- char strbuf[ISC_STRERRORSIZE];
- struct sockaddr_storage ss;
- ISC_SOCKADDR_LEN_T len = sizeof(ss);
- struct msghdr msg;
- union {
- struct cmsghdr h;
- unsigned char b[256];
- } control;
- struct cmsghdr *cmsgp;
- int dscp = (46 << 2); /* Expedited forwarding. */
- struct iovec iovec;
- char buf[1] = { 0 };
- isc_result_t result;
-
- if (bind(s, res->ai_addr, res->ai_addrlen) < 0) {
- isc__strerror(errno, strbuf, sizeof(strbuf));
- isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL,
- ISC_LOGMODULE_SOCKET, ISC_LOG_DEBUG(10),
- "bind: %s", strbuf);
- return (ISC_FALSE);
- }
-
- if (getsockname(s, (struct sockaddr *)&ss, &len) < 0) {
- isc__strerror(errno, strbuf, sizeof(strbuf));
- isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL,
- ISC_LOGMODULE_SOCKET, ISC_LOG_DEBUG(10),
- "getsockname: %s", strbuf);
- return (ISC_FALSE);
- }
-
- iovec.iov_base = buf;
- iovec.iov_len = sizeof(buf);
-
- memset(&msg, 0, sizeof(msg));
- msg.msg_name = (struct sockaddr *)&ss;
- msg.msg_namelen = len;
- msg.msg_iov = &iovec;
- msg.msg_iovlen = 1;
- msg.msg_control = (void*)&control;
- msg.msg_controllen = 0;
- msg.msg_flags = 0;
-
- cmsgp = msg.msg_control;
-
- switch (type) {
-#ifdef IP_TOS
- case IP_TOS:
- memset(cmsgp, 0, cmsg_space(sizeof(char)));
- cmsgp->cmsg_level = level;
- cmsgp->cmsg_type = type;
- cmsgp->cmsg_len = cmsg_len(sizeof(char));
- *(unsigned char*)CMSG_DATA(cmsgp) = dscp;
- msg.msg_controllen += cmsg_space(sizeof(char));
- break;
-#endif
-#ifdef IPV6_TCLASS
- case IPV6_TCLASS:
- memset(cmsgp, 0, cmsg_space(sizeof(dscp)));
- cmsgp->cmsg_level = level;
- cmsgp->cmsg_type = type;
- cmsgp->cmsg_len = cmsg_len(sizeof(dscp));
- memmove(CMSG_DATA(cmsgp), &dscp, sizeof(dscp));
- msg.msg_controllen += cmsg_space(sizeof(dscp));
- break;
-#endif
- default:
- INSIST(0);
- }
-
- if (sendmsg(s, &msg, 0) < 0) {
- int debug = ISC_LOG_DEBUG(10);
- const char *typestr;
- const char *msgstr;
- switch (errno) {
-#ifdef ENOPROTOOPT
- case ENOPROTOOPT:
-#endif
-#ifdef EOPNOTSUPP
- case EOPNOTSUPP:
-#endif
- case EINVAL:
- case EPERM:
- break;
- default:
- debug = ISC_LOG_NOTICE;
- }
- isc__strerror(errno, strbuf, sizeof(strbuf));
- if (debug != ISC_LOG_NOTICE) {
- isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL,
- ISC_LOGMODULE_SOCKET, ISC_LOG_DEBUG(10),
- "sendmsg: %s", strbuf);
- } else {
- typestr = (type == IP_TOS) ? "IP_TOS" : "IPV6_TCLASS";
- msgstr = isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
- ISC_MSG_FAILED, "failed");
- UNEXPECTED_ERROR(__FILE__, __LINE__, "probing "
- "sendmsg() with %s=%02x %s: %s",
- typestr, dscp, msgstr, strbuf);
- }
- return (ISC_FALSE);
- }
-
- /*
- * Make sure the message actually got sent.
- */
- result = make_nonblock(s);
- RUNTIME_CHECK(result == ISC_R_SUCCESS);
-
- iovec.iov_base = buf;
- iovec.iov_len = sizeof(buf);
-
- memset(&msg, 0, sizeof(msg));
- msg.msg_name = (struct sockaddr *)&ss;
- msg.msg_namelen = sizeof(ss);
- msg.msg_iov = &iovec;
- msg.msg_iovlen = 1;
- msg.msg_control = NULL;
- msg.msg_controllen = 0;
- msg.msg_flags = 0;
-
- if (recvmsg(s, &msg, 0) < 0)
- return (ISC_FALSE);
-
- return (ISC_TRUE);
-}
-#endif
-#endif
-
-static void
-try_dscp_v4(void) {
-#ifdef IP_TOS
- char strbuf[ISC_STRERRORSIZE];
- struct addrinfo hints, *res0;
- int s, dscp = 0, n;
-#if 0 && defined(IP_RECVTOS)
- int on = 1;
-#endif /* IP_RECVTOS */
-
- memset(&hints, 0, sizeof(hints));
- hints.ai_family = AF_INET;
- hints.ai_socktype = SOCK_DGRAM;
- hints.ai_protocol = IPPROTO_UDP;
-#ifdef AI_NUMERICHOST
- hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST;
-#else
- hints.ai_flags = AI_PASSIVE;
-#endif
-
- n = getaddrinfo("127.0.0.1", NULL, &hints, &res0);
- if (n != 0 || res0 == NULL) {
- isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL,
- ISC_LOGMODULE_SOCKET, ISC_LOG_DEBUG(10),
- "getaddrinfo(127.0.0.1): %s", gai_strerror(n));
- return;
- }
-
- s = socket(res0->ai_family, res0->ai_socktype | SOCK_DNS, res0->ai_protocol);
-
- if (s == -1) {
- isc__strerror(errno, strbuf, sizeof(strbuf));
- isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL,
- ISC_LOGMODULE_SOCKET, ISC_LOG_DEBUG(10),
- "socket: %s", strbuf);
- freeaddrinfo(res0);
- return;
- }
-
- if (setsockopt(s, IPPROTO_IP, IP_TOS, &dscp, sizeof(dscp)) == 0)
- dscp_result |= ISC_NET_DSCPSETV4;
-
-#if 0 && defined(IP_RECVTOS)
- on = 1;
- if (setsockopt(s, IPPROTO_IP, IP_RECVTOS, &on, sizeof(on)) == 0)
- dscp_result |= ISC_NET_DSCPRECVV4;
-#endif /* IP_RECVTOS */
-
-#ifdef ISC_NET_BSD44MSGHDR
-
-#if ISC_CMSG_IP_TOS
- if (cmsgsend(s, IPPROTO_IP, IP_TOS, res0))
- dscp_result |= ISC_NET_DSCPPKTV4;
-#endif /* ISC_CMSG_IP_TOS */
-
-#endif /* ISC_NET_BSD44MSGHDR */
-
- freeaddrinfo(res0);
- close(s);
-
-#endif /* IP_TOS */
-}
-
-static void
-try_dscp_v6(void) {
-#ifdef ISC_PLATFORM_HAVEIPV6
-#ifdef WANT_IPV6
-#ifdef IPV6_TCLASS
- char strbuf[ISC_STRERRORSIZE];
- struct addrinfo hints, *res0;
- int s, dscp = 0, n;
-#if 0 && defined(IPV6_RECVTCLASS)
- int on = 1;
-#endif /* IPV6_RECVTCLASS */
-
- memset(&hints, 0, sizeof(hints));
- hints.ai_family = AF_INET6;
- hints.ai_socktype = SOCK_DGRAM;
- hints.ai_protocol = IPPROTO_UDP;
-#ifdef AI_NUMERICHOST
- hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST;
-#else
- hints.ai_flags = AI_PASSIVE;
-#endif
-
- n = getaddrinfo("::1", NULL, &hints, &res0);
- if (n != 0 || res0 == NULL) {
- isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL,
- ISC_LOGMODULE_SOCKET, ISC_LOG_DEBUG(10),
- "getaddrinfo(::1): %s", gai_strerror(n));
- return;
- }
-
- s = socket(res0->ai_family, res0->ai_socktype | SOCK_DNS, res0->ai_protocol);
- if (s == -1) {
- isc__strerror(errno, strbuf, sizeof(strbuf));
- isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL,
- ISC_LOGMODULE_SOCKET, ISC_LOG_DEBUG(10),
- "socket: %s", strbuf);
- freeaddrinfo(res0);
- return;
- }
- if (setsockopt(s, IPPROTO_IPV6, IPV6_TCLASS, &dscp, sizeof(dscp)) == 0)
- dscp_result |= ISC_NET_DSCPSETV6;
-
-#if 0 && defined(IPV6_RECVTCLASS)
- on = 1;
- if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVTCLASS, &on, sizeof(on)) == 0)
- dscp_result |= ISC_NET_DSCPRECVV6;
-#endif /* IPV6_RECVTCLASS */
-
-#ifdef ISC_NET_BSD44MSGHDR
- if (cmsgsend(s, IPPROTO_IPV6, IPV6_TCLASS, res0))
- dscp_result |= ISC_NET_DSCPPKTV6;
-#endif /* ISC_NET_BSD44MSGHDR */
-
- freeaddrinfo(res0);
- close(s);
-
-#endif /* IPV6_TCLASS */
-#endif /* WANT_IPV6 */
-#endif /* ISC_PLATFORM_HAVEIPV6 */
-}
-
-static void
-try_dscp(void) {
- try_dscp_v4();
- try_dscp_v6();
-}
-
-static void
-initialize_dscp(void) {
- RUNTIME_CHECK(isc_once_do(&once_dscp, try_dscp) == ISC_R_SUCCESS);
-}
-
unsigned int
isc_net_probedscp(void) {
- initialize_dscp();
return (dscp_result);
}