`msghdr.msg_accrights` was the [4.3BSD mechanism](https://man.freebsd.org/cgi/man.cgi?query=recv&apropos=0&sektion=2&a...) for passing FDs over a Unix domain socket, it's now long obsolete. The only recent OS where it's still available is Solaris, but that's also supported `msg_control` for decades (although additional `#defines` were required pre-11.4).
From: Brendan Shanks bshanks@codeweavers.com
--- dlls/ntdll/unix/server.c | 44 +++++++++++++++------------------------- dlls/ntdll/unix/socket.c | 14 +------------ 2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/dlls/ntdll/unix/server.c b/dlls/ntdll/unix/server.c index 88ac9551060..c1ee8e27f0c 100644 --- a/dlls/ntdll/unix/server.c +++ b/dlls/ntdll/unix/server.c @@ -872,29 +872,17 @@ void wine_server_send_fd( int fd ) struct send_fd data; struct msghdr msghdr; struct iovec vec; - int ret; - -#ifdef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS - msghdr.msg_accrights = (void *)&fd; - msghdr.msg_accrightslen = sizeof(fd); -#else /* HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS */ char cmsg_buffer[256]; struct cmsghdr *cmsg; - msghdr.msg_control = cmsg_buffer; - msghdr.msg_controllen = sizeof(cmsg_buffer); - msghdr.msg_flags = 0; - cmsg = CMSG_FIRSTHDR( &msghdr ); - cmsg->cmsg_len = CMSG_LEN( sizeof(fd) ); - cmsg->cmsg_level = SOL_SOCKET; - cmsg->cmsg_type = SCM_RIGHTS; - *(int *)CMSG_DATA(cmsg) = fd; - msghdr.msg_controllen = cmsg->cmsg_len; -#endif /* HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS */ + int ret;
msghdr.msg_name = NULL; msghdr.msg_namelen = 0; msghdr.msg_iov = &vec; msghdr.msg_iovlen = 1; + msghdr.msg_control = cmsg_buffer; + msghdr.msg_controllen = sizeof(cmsg_buffer); + msghdr.msg_flags = 0;
vec.iov_base = (void *)&data; vec.iov_len = sizeof(data); @@ -902,6 +890,13 @@ void wine_server_send_fd( int fd ) data.tid = GetCurrentThreadId(); data.fd = fd;
+ cmsg = CMSG_FIRSTHDR( &msghdr ); + cmsg->cmsg_len = CMSG_LEN( sizeof(fd) ); + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_RIGHTS; + *(int *)CMSG_DATA(cmsg) = fd; + msghdr.msg_controllen = cmsg->cmsg_len; + for (;;) { if ((ret = sendmsg( fd_socket, &msghdr, 0 )) == sizeof(data)) return; @@ -922,22 +917,17 @@ static int receive_fd( obj_handle_t *handle ) { struct iovec vec; struct msghdr msghdr; - int ret, fd = -1; - -#ifdef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS - msghdr.msg_accrights = (void *)&fd; - msghdr.msg_accrightslen = sizeof(fd); -#else /* HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS */ char cmsg_buffer[256]; - msghdr.msg_control = cmsg_buffer; - msghdr.msg_controllen = sizeof(cmsg_buffer); - msghdr.msg_flags = 0; -#endif /* HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS */ + int ret, fd = -1;
msghdr.msg_name = NULL; msghdr.msg_namelen = 0; msghdr.msg_iov = &vec; msghdr.msg_iovlen = 1; + msghdr.msg_control = cmsg_buffer; + msghdr.msg_controllen = sizeof(cmsg_buffer); + msghdr.msg_flags = 0; + vec.iov_base = (void *)handle; vec.iov_len = sizeof(*handle);
@@ -945,7 +935,6 @@ static int receive_fd( obj_handle_t *handle ) { if ((ret = recvmsg( fd_socket, &msghdr, MSG_CMSG_CLOEXEC )) > 0) { -#ifndef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS struct cmsghdr *cmsg; for (cmsg = CMSG_FIRSTHDR( &msghdr ); cmsg; cmsg = CMSG_NXTHDR( &msghdr, cmsg )) { @@ -959,7 +948,6 @@ static int receive_fd( obj_handle_t *handle ) } #endif } -#endif /* HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS */ if (fd != -1) fcntl( fd, F_SETFD, FD_CLOEXEC ); /* in case MSG_CMSG_CLOEXEC is not supported */ return fd; } diff --git a/dlls/ntdll/unix/socket.c b/dlls/ntdll/unix/socket.c index 4b0dca37e7d..65f30759db3 100644 --- a/dlls/ntdll/unix/socket.c +++ b/dlls/ntdll/unix/socket.c @@ -371,7 +371,6 @@ static int sockaddr_from_unix( const union unix_sockaddr *uaddr, struct WS_socka } }
-#ifndef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS static WSACMSGHDR *fill_control_message( int level, int type, WSACMSGHDR *current, ULONG *maxsize, void *data, int len ) { ULONG msgsize = sizeof(WSACMSGHDR) + WSA_CMSG_ALIGN(len); @@ -513,14 +512,6 @@ error: control->len = 0; return 0; } -#else -static int convert_control_headers(struct msghdr *hdr, WSABUF *control) -{ - ERR( "Message control headers cannot be properly supported on this system.\n" ); - control->len = 0; - return 0; -} -#endif /* HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS */
struct cmsghdr_32 { @@ -721,9 +712,7 @@ static ssize_t fixup_icmp_over_dgram( struct msghdr *hdr, union unix_sockaddr *u
static NTSTATUS try_recv( int fd, struct async_recv_ioctl *async, ULONG_PTR *size ) { -#ifndef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS char control_buffer[512]; -#endif union unix_sockaddr unix_addr; struct msghdr hdr; NTSTATUS status; @@ -737,10 +726,9 @@ static NTSTATUS try_recv( int fd, struct async_recv_ioctl *async, ULONG_PTR *siz } hdr.msg_iov = async->iov; hdr.msg_iovlen = async->count; -#ifndef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS hdr.msg_control = control_buffer; hdr.msg_controllen = sizeof(control_buffer); -#endif + while ((ret = virtual_locked_recvmsg( fd, &hdr, async->unix_flags )) < 0 && errno == EINTR);
if (ret < 0)
From: Brendan Shanks bshanks@codeweavers.com
--- configure.ac | 2 +- server/request.c | 44 ++++++++++++++++---------------------------- 2 files changed, 17 insertions(+), 29 deletions(-)
diff --git a/configure.ac b/configure.ac index 417b1a63a13..07a832c0b6f 100644 --- a/configure.ac +++ b/configure.ac @@ -2163,7 +2163,7 @@ AC_CACHE_CHECK([whether we can use re-entrant gethostbyname_r Linux style], fi
dnl Check for socket structure members -AC_CHECK_MEMBERS([struct msghdr.msg_accrights, struct sockaddr_un.sun_len],,, +AC_CHECK_MEMBERS([struct sockaddr_un.sun_len],,, [#include <sys/types.h> #include <sys/socket.h> #ifdef HAVE_SYS_UN_H diff --git a/server/request.c b/server/request.c index 7021741c765..82b4a722d61 100644 --- a/server/request.c +++ b/server/request.c @@ -379,28 +379,22 @@ int receive_fd( struct process *process ) struct iovec vec; struct send_fd data; struct msghdr msghdr; - int fd = -1, ret; - -#ifdef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS - msghdr.msg_accrightslen = sizeof(int); - msghdr.msg_accrights = (void *)&fd; -#else /* HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS */ char cmsg_buffer[256]; - msghdr.msg_control = cmsg_buffer; - msghdr.msg_controllen = sizeof(cmsg_buffer); - msghdr.msg_flags = 0; -#endif /* HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS */ + int fd = -1, ret;
msghdr.msg_name = NULL; msghdr.msg_namelen = 0; msghdr.msg_iov = &vec; msghdr.msg_iovlen = 1; + msghdr.msg_control = cmsg_buffer; + msghdr.msg_controllen = sizeof(cmsg_buffer); + msghdr.msg_flags = 0; + vec.iov_base = (void *)&data; vec.iov_len = sizeof(data);
ret = recvmsg( get_unix_fd( process->msg_fd ), &msghdr, 0 );
-#ifndef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS if (ret > 0) { struct cmsghdr *cmsg; @@ -410,7 +404,6 @@ int receive_fd( struct process *process ) if (cmsg->cmsg_type == SCM_RIGHTS) fd = *(int *)CMSG_DATA(cmsg); } } -#endif /* HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS */
if (ret == sizeof(data)) { @@ -465,33 +458,28 @@ int send_client_fd( struct process *process, int fd, obj_handle_t handle ) { struct iovec vec; struct msghdr msghdr; - int ret; - -#ifdef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS - msghdr.msg_accrightslen = sizeof(fd); - msghdr.msg_accrights = (void *)&fd; -#else /* HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS */ char cmsg_buffer[256]; struct cmsghdr *cmsg; - msghdr.msg_control = cmsg_buffer; - msghdr.msg_controllen = sizeof(cmsg_buffer); - msghdr.msg_flags = 0; - cmsg = CMSG_FIRSTHDR( &msghdr ); - cmsg->cmsg_len = CMSG_LEN( sizeof(fd) ); - cmsg->cmsg_level = SOL_SOCKET; - cmsg->cmsg_type = SCM_RIGHTS; - *(int *)CMSG_DATA(cmsg) = fd; - msghdr.msg_controllen = cmsg->cmsg_len; -#endif /* HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS */ + int ret;
msghdr.msg_name = NULL; msghdr.msg_namelen = 0; msghdr.msg_iov = &vec; msghdr.msg_iovlen = 1; + msghdr.msg_control = cmsg_buffer; + msghdr.msg_controllen = sizeof(cmsg_buffer); + msghdr.msg_flags = 0;
vec.iov_base = (void *)&handle; vec.iov_len = sizeof(handle);
+ cmsg = CMSG_FIRSTHDR( &msghdr ); + cmsg->cmsg_len = CMSG_LEN( sizeof(fd) ); + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_RIGHTS; + *(int *)CMSG_DATA(cmsg) = fd; + msghdr.msg_controllen = cmsg->cmsg_len; + if (debug_level) fprintf( stderr, "%04x: *fd* %04x -> %d\n", current ? current->id : process->id, handle, fd );