diff options
Diffstat (limited to 'usr.sbin/bind/lib/isc/unix/net.c')
| -rw-r--r-- | usr.sbin/bind/lib/isc/unix/net.c | 355 |
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); } |
