Commit 774c3a62 authored by Mark Andrews's avatar Mark Andrews

1566. [port] Support for the cmsg framework on Solaris and HP/UX.

                        This also solved the problem that match-destinations
                        for IPv6 addresses did not work on these systems.
                        [RT #10221]
parent f7e94169
1567. [bug] B.ROOT-SERVERS.NET is now 192.228.79.201.
1566. [placeholder] rt10221
1566. [port] Support for the cmsg framework on Solaris and HP/UX.
This also solved the problem that match-destinations
for IPv6 addresses did not work on these systems.
[RT #10221]
1565. [bug] CD flag should be copied to outgoing queries unless
the query is under a secure entry point in which case
......
......@@ -15,7 +15,7 @@
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: acconfig.h,v 1.42 2004/01/07 05:48:14 marka Exp $ */
/* $Id: acconfig.h,v 1.43 2004/01/29 04:39:18 marka Exp $ */
/***
*** This file is not to be included by any public header files, because
......@@ -59,14 +59,6 @@
/* define if you have the NET_RT_IFLIST sysctl variable and sys/sysctl.h */
#undef HAVE_IFLIST_SYSCTL
/* define if you need to #define _XPG4_2 before including sys/socket.h */
#undef NEED_XPG4_2_BEFORE_SOCKET_H
/* define if you need to #define _XOPEN_SOURCE_ENTENDED before including
* sys/socket.h
*/
#undef NEED_XSE_BEFORE_SOCKET_H
/* define if chroot() is available */
#undef HAVE_CHROOT
......
......@@ -16,7 +16,7 @@
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: config.h.in,v 1.57 2004/01/07 05:49:10 marka Exp $ */
/* $Id: config.h.in,v 1.58 2004/01/29 04:39:18 marka Exp $ */
/***
*** This file is not to be included by any public header files, because
......@@ -59,14 +59,6 @@
/* define if you have the NET_RT_IFLIST sysctl variable and sys/sysctl.h */
#undef HAVE_IFLIST_SYSCTL
/* define if you need to #define _XPG4_2 before including sys/socket.h */
#undef NEED_XPG4_2_BEFORE_SOCKET_H
/* define if you need to #define _XOPEN_SOURCE_ENTENDED before including
* sys/socket.h
*/
#undef NEED_XSE_BEFORE_SOCKET_H
/* define if chroot() is available */
#undef HAVE_CHROOT
......
......@@ -18,7 +18,7 @@ AC_DIVERT_PUSH(AC_DIVERSION_NOTICE)dnl
esyscmd([sed "s/^/# /" COPYRIGHT])dnl
AC_DIVERT_POP()dnl
AC_REVISION($Revision: 1.350 $)
AC_REVISION($Revision: 1.351 $)
AC_INIT(lib/dns/name.c)
AC_PREREQ(2.13)
......@@ -204,14 +204,26 @@ if test "$ac_env_CFLAGS_set" != set -a "X$GCC" = "Xyes"; then
fi
#
# OSF 5.0: recv/send are only avaliable with -D_POSIX_PII_SOCKET or
# -D_XOPEN_SOURCE_EXTENDED.
# OS dependent CC flags
#
case "$host" in
# OSF 5.0: recv/send are only avaliable with -D_POSIX_PII_SOCKET or
# -D_XOPEN_SOURCE_EXTENDED.
*-dec-osf*)
STD_CDEFINES="$STD_CDEFINES -D_POSIX_PII_SOCKET"
CPPFLAGS="$CPPFLAGS -D_POSIX_PII_SOCKET"
;;
#HP-UX: need -D_XOPEN_SOURCE_EXTENDED and -lxnet for CMSG macros
*-hp-hpux*)
STD_CDEFINES="$STD_CDEFINES -D_XOPEN_SOURCE_EXTENDED"
CPPFLAGS="$CPPFLAGS -D_XOPEN_SOURCE_EXTENDED"
LIBS="-lxnet $LIBS"
;;
# Solaris: need -D_XPG4_2 and -D__EXTENSIONS__ for CMSG macros
*-solaris*)
STD_CDEFINES="$STD_CDEFINES -D_XPG4_2 -D__EXTENSIONS__"
CPPFLAGS="$CPPFLAGS -D_XPG4_2 -D__EXTENSIONS__"
;;
esac
AC_HEADER_STDC
......
......@@ -15,7 +15,7 @@
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: socket.c,v 1.233 2004/01/26 23:33:32 marka Exp $ */
/* $Id: socket.c,v 1.234 2004/01/29 04:39:19 marka Exp $ */
#include <config.h>
......@@ -126,35 +126,6 @@ typedef isc_event_t intev_t;
#endif
#endif
/*
* Check to see if we have even basic support for cracking messages from
* the control data returned from/sent via recvmsg()/sendmsg().
*/
#if defined(USE_CMSG) && (!defined(CMSG_LEN) || !defined(CMSG_SPACE))
#undef USE_CMSG
#endif
/*
* Determine the size of the control data buffer.
*/
#if USE_CMSG
#ifdef ISC_PLATFORM_HAVEIPV6
#define CMSG_BUF_V6_SIZE (CMSG_SPACE(sizeof(struct in6_pktinfo)))
#else
#define CMSG_BUF_V6_SIZE 0
#endif
#ifdef SO_TIMESTAMP
#define CMSG_BUF_TS_SIZE (CMSG_SPACE(sizeof(struct timeval)))
#else
#define CMSG_BUF_TS_SIZE 0
#endif
#define CMSG_BUF_SIZE (CMSG_BUF_V6_SIZE + CMSG_BUF_TS_SIZE)
#endif /* USE_CMSG */
/*
* The number of times a send operation is repeated if the result is EINTR.
*/
......@@ -199,6 +170,11 @@ struct isc_socket {
#ifdef ISC_NET_RECVOVERFLOW
unsigned char overflow; /* used for MSG_TRUNC fake */
#endif
char *recvcmsgbuf;
ISC_SOCKADDR_LEN_T recvcmsgbuflen;
char *sendcmsgbuf;
ISC_SOCKADDR_LEN_T sendcmsgbuflen;
};
#define SOCKET_MANAGER_MAGIC ISC_MAGIC('I', 'O', 'm', 'g')
......@@ -255,11 +231,9 @@ static void internal_recv(isc_task_t *, isc_event_t *);
static void internal_send(isc_task_t *, isc_event_t *);
static void process_cmsg(isc_socket_t *, struct msghdr *, isc_socketevent_t *);
static void build_msghdr_send(isc_socket_t *, isc_socketevent_t *,
struct msghdr *, char *cmsg,
struct iovec *, size_t *);
struct msghdr *, struct iovec *, size_t *);
static void build_msghdr_recv(isc_socket_t *, isc_socketevent_t *,
struct msghdr *, char *cmsg,
struct iovec *, size_t *);
struct msghdr *, struct iovec *, size_t *);
#define SELECT_POKE_SHUTDOWN (-1)
#define SELECT_POKE_NOTHING (-2)
......@@ -472,6 +446,55 @@ make_nonblock(int fd) {
return (ISC_R_SUCCESS);
}
#ifdef USE_CMSG
/*
* Not all OSes support advanced CMSG macros: CMSG_LEN and CMSG_SPACE.
* In order to ensure as much portability as possible, we provide wrapper
* functions of these macros.
* Note that cmsg_space() could run slow on OSes that do not have
* CMSG_SPACE.
*/
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;
hdrlen = (ISC_SOCKADDR_LEN_T)CMSG_DATA(NULL); /* XXX */
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 ((void *)cmsgp - (void *)msg.msg_control);
else
return (0);
#endif
}
#endif /* USE_CMSG */
/*
* Process control messages received on a socket.
*/
......@@ -580,8 +603,7 @@ process_cmsg(isc_socket_t *sock, struct msghdr *msg, isc_socketevent_t *dev) {
*/
static void
build_msghdr_send(isc_socket_t *sock, isc_socketevent_t *dev,
struct msghdr *msg, char *cmsg,
struct iovec *iov, size_t *write_countp)
struct msghdr *msg, struct iovec *iov, size_t *write_countp)
{
unsigned int iovcount;
isc_buffer_t *buffer;
......@@ -589,10 +611,6 @@ build_msghdr_send(isc_socket_t *sock, isc_socketevent_t *dev,
size_t write_count;
size_t skip_count;
#ifndef USE_CMSG
UNUSED(cmsg);
#endif
memset(msg, 0, sizeof(*msg));
if (sock->type == isc_sockettype_udp) {
......@@ -669,13 +687,14 @@ build_msghdr_send(isc_socket_t *sock, isc_socketevent_t *dev,
"sendto pktinfo data, ifindex %u",
dev->pktinfo.ipi6_ifindex);
msg->msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo));
msg->msg_control = (void *)cmsg;
msg->msg_controllen = cmsg_space(sizeof(struct in6_pktinfo));
INSIST(msg->msg_controllen <= sock->sendcmsgbuflen);
msg->msg_control = (void *)sock->sendcmsgbuf;
cmsgp = (struct cmsghdr *)cmsg;
cmsgp = (struct cmsghdr *)sock->sendcmsgbuf;
cmsgp->cmsg_level = IPPROTO_IPV6;
cmsgp->cmsg_type = IPV6_PKTINFO;
cmsgp->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
cmsgp->cmsg_len = cmsg_len(sizeof(struct in6_pktinfo));
pktinfop = (struct in6_pktinfo *)CMSG_DATA(cmsgp);
memcpy(pktinfop, &dev->pktinfo, sizeof(struct in6_pktinfo));
}
......@@ -703,18 +722,13 @@ build_msghdr_send(isc_socket_t *sock, isc_socketevent_t *dev,
*/
static void
build_msghdr_recv(isc_socket_t *sock, isc_socketevent_t *dev,
struct msghdr *msg, char *cmsg,
struct iovec *iov, size_t *read_countp)
struct msghdr *msg, struct iovec *iov, size_t *read_countp)
{
unsigned int iovcount;
isc_buffer_t *buffer;
isc_region_t available;
size_t read_count;
#ifndef USE_CMSG
UNUSED(cmsg);
#endif
memset(msg, 0, sizeof(struct msghdr));
if (sock->type == isc_sockettype_udp) {
......@@ -796,8 +810,8 @@ build_msghdr_recv(isc_socket_t *sock, isc_socketevent_t *dev,
msg->msg_flags = 0;
#if defined(USE_CMSG)
if (sock->type == isc_sockettype_udp) {
msg->msg_control = cmsg;
msg->msg_controllen = CMSG_BUF_SIZE;
msg->msg_control = sock->recvcmsgbuf;
msg->msg_controllen = sock->recvcmsgbuflen;
}
#endif /* USE_CMSG */
#else /* ISC_NET_BSD44MSGHDR */
......@@ -882,14 +896,9 @@ doio_recv(isc_socket_t *sock, isc_socketevent_t *dev) {
struct msghdr msghdr;
isc_buffer_t *buffer;
int recv_errno;
#if USE_CMSG
char cmsg[CMSG_BUF_SIZE];
#else
char *cmsg = NULL;
#endif
char strbuf[ISC_STRERRORSIZE];
build_msghdr_recv(sock, dev, &msghdr, cmsg, iov, &read_count);
build_msghdr_recv(sock, dev, &msghdr, iov, &read_count);
#if defined(ISC_SOCKET_DEBUG)
dump_msg(&msghdr);
......@@ -1041,16 +1050,11 @@ doio_send(isc_socket_t *sock, isc_socketevent_t *dev) {
size_t write_count;
struct msghdr msghdr;
char addrbuf[ISC_SOCKADDR_FORMATSIZE];
#if USE_CMSG
char cmsg[CMSG_BUF_SIZE];
#else
char *cmsg = NULL;
#endif
int attempts = 0;
int send_errno;
char strbuf[ISC_STRERRORSIZE];
build_msghdr_send(sock, dev, &msghdr, cmsg, iov, &write_count);
build_msghdr_send(sock, dev, &msghdr, iov, &write_count);
resend:
cc = sendmsg(sock->fd, &msghdr, 0);
......@@ -1186,6 +1190,7 @@ allocate_socket(isc_socketmgr_t *manager, isc_sockettype_t type,
{
isc_socket_t *sock;
isc_result_t ret;
ISC_SOCKADDR_LEN_T cmsgbuflen;
sock = isc_mem_get(manager->mctx, sizeof(*sock));
......@@ -1203,6 +1208,37 @@ allocate_socket(isc_socketmgr_t *manager, isc_sockettype_t type,
ISC_LINK_INIT(sock, link);
sock->recvcmsgbuf = NULL;
sock->sendcmsgbuf = NULL;
/*
* set up cmsg buffers
*/
cmsgbuflen = 0;
#if defined(USE_CMSG) && defined(ISC_PLATFORM_HAVEIPV6)
cmsgbuflen = cmsg_space(sizeof(struct in6_pktinfo));
#endif
#if defined(USE_CMSG) && defined(SO_TIMESTAMP)
cmsgbuflen += cmsg_space(sizeof(struct timeval));
#endif
sock->recvcmsgbuflen = cmsgbuflen;
if (sock->recvcmsgbuflen != 0) {
sock->recvcmsgbuf = isc_mem_get(manager->mctx, cmsgbuflen);
if (sock->recvcmsgbuf == NULL)
goto error;
}
cmsgbuflen = 0;
#if defined(USE_CMSG) && defined(ISC_PLATFORM_HAVEIPV6)
cmsgbuflen = cmsg_space(sizeof(struct in6_pktinfo));
#endif
sock->sendcmsgbuflen = cmsgbuflen;
if (sock->sendcmsgbuflen != 0) {
sock->sendcmsgbuf = isc_mem_get(manager->mctx, cmsgbuflen);
if (sock->sendcmsgbuf == NULL)
goto error;
}
/*
* set up list of readers and writers to be initially empty
*/
......@@ -1247,6 +1283,12 @@ allocate_socket(isc_socketmgr_t *manager, isc_sockettype_t type,
return (ISC_R_SUCCESS);
error:
if (sock->recvcmsgbuf != NULL)
isc_mem_put(manager->mctx, sock->recvcmsgbuf,
sock->recvcmsgbuflen);
if (sock->sendcmsgbuf != NULL)
isc_mem_put(manager->mctx, sock->sendcmsgbuf,
sock->sendcmsgbuflen);
isc_mem_put(manager->mctx, sock, sizeof(*sock));
return (ret);
......@@ -1274,6 +1316,13 @@ free_socket(isc_socket_t **socketp) {
INSIST(ISC_LIST_EMPTY(sock->accept_list));
INSIST(!ISC_LINK_LINKED(sock, link));
if (sock->recvcmsgbuf != NULL)
isc_mem_put(sock->manager->mctx, sock->recvcmsgbuf,
sock->recvcmsgbuflen);
if (sock->sendcmsgbuf != NULL)
isc_mem_put(sock->manager->mctx, sock->sendcmsgbuf,
sock->sendcmsgbuflen);
sock->magic = 0;
DESTROYLOCK(&sock->lock);
......@@ -1415,6 +1464,15 @@ isc_socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type,
#endif /* SO_TIMESTAMP */
#if defined(ISC_PLATFORM_HAVEIPV6)
if (pf == AF_INET6 && sock->recvcmsgbuflen == 0) {
/*
* Warn explicitly because this anomaly can be hidden
* in usual operation (and unexpectedly appear later).
*/
UNEXPECTED_ERROR(__FILE__, __LINE__,
"No buffer available to receive "
"IPv6 destination");
}
#ifdef IPV6_RECVPKTINFO
/* 2292bis */
if ((pf == AF_INET6)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment