misc/69448: cmsghdr macros don't work with Alpha (and other 64bit
systems?)
Timo Sirainen
tss at iki.fi
Thu Jul 22 14:40:24 PDT 2004
>Number: 69448
>Category: misc
>Synopsis: cmsghdr macros don't work with Alpha (and other 64bit systems?)
>Confidential: no
>Severity: non-critical
>Priority: medium
>Responsible: freebsd-bugs
>State: open
>Quarter:
>Keywords:
>Date-Required:
>Class: sw-bug
>Submitter-Id: current-users
>Arrival-Date: Thu Jul 22 21:40:23 GMT 2004
>Closed-Date:
>Last-Modified:
>Originator: Timo Sirainen
>Release: 4.10
>Organization:
>Environment:
Alpha (not mine)
>Description:
CMSG_DATA and CMSG_LEN macros do 64bit alignment but kernel seems to want 32bit alignment. After overriding them it started working:
#define CMSG_LEN(l) (sizeof(struct cmsghdr) + (l))
#define CMSG_DATA(cmsg) ((u_char *)(cmsg) + sizeof(struct cmsghdr))
>How-To-Repeat:
This breaks:
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <limits.h>
#include <sys/un.h>
#include <sys/uio.h>
ssize_t fd_send(int handle, int send_fd, const void *data, size_t size)
{
struct msghdr msg;
struct iovec iov;
struct cmsghdr *cmsg;
char buf[CMSG_SPACE(sizeof(int))];
memset(&msg, 0, sizeof(struct msghdr));
iov.iov_base = (void *) data;
iov.iov_len = size;
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
if (send_fd != -1) {
memset(buf, 0, sizeof(buf));
msg.msg_control = buf;
msg.msg_controllen = sizeof(buf);
cmsg = CMSG_FIRSTHDR(&msg);
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SCM_RIGHTS;
cmsg->cmsg_len = CMSG_LEN(sizeof(int));
*((int *) CMSG_DATA(cmsg)) = send_fd;
msg.msg_controllen = cmsg->cmsg_len;
}
return sendmsg(handle, &msg, 0);
}
ssize_t fd_read(int handle, void *data, size_t size, int *fd)
{
struct msghdr msg;
struct iovec iov;
struct cmsghdr *cmsg;
ssize_t ret;
char buf[CMSG_SPACE(sizeof(int))];
memset(&msg, 0, sizeof (struct msghdr));
iov.iov_base = data;
iov.iov_len = size;
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
memset(buf, 0, sizeof(buf));
msg.msg_control = buf;
msg.msg_controllen = sizeof(buf);
ret = recvmsg(handle, &msg, 0);
if (ret <= 0) {
*fd = -1;
return ret;
}
cmsg = CMSG_FIRSTHDR(&msg);
if (cmsg == NULL)
*fd = -1;
else
*fd = *((int *) CMSG_DATA(cmsg));
return ret;
}
int main(void)
{
int fd[2], send_fd, recv_fd, status;
struct stat st, st2;
char data;
send_fd = open("conftest.fdpass", O_CREAT|O_WRONLY);
if (send_fd == -1) {
perror("open()");
return 2;
}
unlink("conftest.fdpass");
if (fstat(send_fd, &st) < 0) {
perror("fstat()");
return 2;
}
if (socketpair(AF_UNIX, SOCK_STREAM, 0, fd) < 0) {
perror("socketpair()");
return 2;
}
switch (fork()) {
case -1:
perror("fork()");
return 2;
case 0:
if (fd_send(fd[0], send_fd, &data, 1) != 1) {
perror("fd_send()");
return 2;
}
wait(&status);
return status;
default:
if (fd_read(fd[1], &data, 1, &recv_fd) != 1) {
perror("fd_read()");
return 1;
}
if (fstat(recv_fd, &st2) < 0) {
perror("fstat(recv_fd)");
return 2;
}
return st.st_ino == st2.st_ino ? 0 : 1;
}
}
>Fix:
>Release-Note:
>Audit-Trail:
>Unformatted:
More information about the freebsd-bugs
mailing list