From 7fc1aaf2ceba53eb3806799709e73cae8d505e5c Mon Sep 17 00:00:00 2001 From: Nicolas Joly Date: Wed, 17 Jun 2009 14:18:51 +0000 Subject: [PATCH] Add a new linux_msghdr structure, as its size differs on 64bit archs. Do the needed conversions in sendmsg/recvmsg syscalls, and adjust their definitions accordingly. --- sys/compat/linux/arch/alpha/syscalls.master | 8 ++--- sys/compat/linux/arch/amd64/syscalls.master | 6 ++-- sys/compat/linux/arch/mips/syscalls.master | 10 +++--- sys/compat/linux/common/linux_socket.c | 51 +++++++++++++++++++++++------ sys/compat/linux/common/linux_socket.h | 12 ++++++- sys/compat/linux/common/linux_socketcall.h | 6 ++-- 6 files changed, 67 insertions(+), 26 deletions(-) diff --git a/sys/compat/linux/arch/alpha/syscalls.master b/sys/compat/linux/arch/alpha/syscalls.master index 1c27a8d7a62..89ef5ac4f8e 100644 --- a/sys/compat/linux/arch/alpha/syscalls.master +++ b/sys/compat/linux/arch/alpha/syscalls.master @@ -1,4 +1,4 @@ - $NetBSD: syscalls.master,v 1.68 2009/01/17 22:28:52 njoly Exp $ + $NetBSD: syscalls.master,v 1.69 2009/06/08 13:26:57 njoly Exp $ ; ; @(#)syscalls.master 8.1 (Berkeley) 7/19/93 @@ -233,10 +233,10 @@ ;112 ALIAS osf1_sys_sigstack 112 NOARGS { int|compat_43_sys||sigstack(struct sigstack *nss, \ struct sigstack *oss); } -113 STD { ssize_t|linux_sys||recvmsg(int s, struct msghdr *msg, \ - int flags); } +113 STD { ssize_t|linux_sys||recvmsg(int s, \ + struct linux_msghdr *msg, int flags); } 114 STD { ssize_t|linux_sys||sendmsg(int s, \ - const struct msghdr *msg, int flags); } + const struct linux_msghdr *msg, int flags); } 115 UNIMPL 116 NODEF { int|osf1_sys||gettimeofday(struct osf1_timeval *tv, \ struct osf1_timezone *tzp); } diff --git a/sys/compat/linux/arch/amd64/syscalls.master b/sys/compat/linux/arch/amd64/syscalls.master index 9a23d7168cb..e3eff5feea5 100644 --- a/sys/compat/linux/arch/amd64/syscalls.master +++ b/sys/compat/linux/arch/amd64/syscalls.master @@ -1,4 +1,4 @@ - $NetBSD: syscalls.master,v 1.30 2009/01/17 22:28:52 njoly Exp $ + $NetBSD: syscalls.master,v 1.31 2009/06/08 13:26:57 njoly Exp $ ; @(#)syscalls.master 8.1 (Berkeley) 7/19/93 @@ -154,9 +154,9 @@ size_t len, int flags, struct osockaddr *from, \ unsigned int *fromlenaddr); } 46 STD { int|linux_sys||sendmsg(int s, \ - const struct msghdr *msg, int flags); } + const struct linux_msghdr *msg, int flags); } 47 STD { ssize_t|linux_sys||recvmsg(int s, \ - struct msghdr *msg, int flags); } + struct linux_msghdr *msg, int flags); } 48 NOARGS { int|sys||shutdown(int s, int how); } 49 STD { int|linux_sys||bind(int s, \ const struct osockaddr *name, \ diff --git a/sys/compat/linux/arch/mips/syscalls.master b/sys/compat/linux/arch/mips/syscalls.master index 0cddd1b068b..a92a7b43086 100644 --- a/sys/compat/linux/arch/mips/syscalls.master +++ b/sys/compat/linux/arch/mips/syscalls.master @@ -1,4 +1,4 @@ - $NetBSD: syscalls.master,v 1.34 2009/01/17 22:28:52 njoly Exp $ + $NetBSD: syscalls.master,v 1.35 2009/06/08 13:26:57 njoly Exp $ ; @(#)syscalls.master 8.1 (Berkeley) 7/19/93 @@ -298,12 +298,12 @@ 176 NOARGS { int|linux_sys||recvfrom(int s, void *buf, int len, \ int flags, struct osockaddr *from, \ int *fromlenaddr); } -177 NOARGS { int|linux_sys||recvmsg(int s, struct msghdr *msg, \ - u_int flags); } +177 NOARGS { int|linux_sys||recvmsg(int s, \ + struct linux_msghdr *msg, u_int flags); } 178 NOARGS { int|linux_sys||send(int s, void *buf, int len, \ int flags); } -179 NOARGS { int|linux_sys||sendmsg(int s, struct msghdr *msg, \ - u_int flags); } +179 NOARGS { int|linux_sys||sendmsg(int s, \ + struct linux_msghdr *msg, u_int flags); } 180 NOARGS { int|linux_sys||sendto(int s, void *msg, \ int len, int flags, struct osockaddr *to, \ int tolen); } diff --git a/sys/compat/linux/common/linux_socket.c b/sys/compat/linux/common/linux_socket.c index 1fa1efa9672..5f228151b3c 100644 --- a/sys/compat/linux/common/linux_socket.c +++ b/sys/compat/linux/common/linux_socket.c @@ -1,4 +1,4 @@ -/* $NetBSD: linux_socket.c,v 1.102 2009/06/16 22:56:49 njoly Exp $ */ +/* $NetBSD: linux_socket.c,v 1.103 2009/06/16 23:17:02 njoly Exp $ */ /*- * Copyright (c) 1995, 1998, 2008 The NetBSD Foundation, Inc. @@ -35,7 +35,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: linux_socket.c,v 1.102 2009/06/16 22:56:49 njoly Exp $"); +__KERNEL_RCSID(0, "$NetBSD: linux_socket.c,v 1.103 2009/06/16 23:17:02 njoly Exp $"); #if defined(_KERNEL_OPT) #include "opt_inet.h" @@ -121,6 +121,8 @@ static int linux_get_sa(struct lwp *, int, struct mbuf **, static int linux_sa_put(struct osockaddr *osa); static int linux_to_bsd_msg_flags(int); static int bsd_to_linux_msg_flags(int); +static void linux_to_bsd_msghdr(struct linux_msghdr *, struct msghdr *); +static void bsd_to_linux_msghdr(struct msghdr *, struct linux_msghdr *); static const int linux_to_bsd_domain_[LINUX_AF_MAX] = { AF_UNSPEC, @@ -394,24 +396,50 @@ linux_sys_sendto(struct lwp *l, const struct linux_sys_sendto_args *uap, registe return do_sys_sendmsg(l, SCARG(uap, s), &msg, bflags, retval); } +static void +linux_to_bsd_msghdr(struct linux_msghdr *lmsg, struct msghdr *bmsg) +{ + bmsg->msg_name = lmsg->msg_name; + bmsg->msg_namelen = lmsg->msg_namelen; + bmsg->msg_iov = lmsg->msg_iov; + bmsg->msg_iovlen = lmsg->msg_iovlen; + bmsg->msg_control = lmsg->msg_control; + bmsg->msg_controllen = lmsg->msg_controllen; + bmsg->msg_flags = lmsg->msg_flags; +} + +static void +bsd_to_linux_msghdr(struct msghdr *bmsg, struct linux_msghdr *lmsg) +{ + lmsg->msg_name = bmsg->msg_name; + lmsg->msg_namelen = bmsg->msg_namelen; + lmsg->msg_iov = bmsg->msg_iov; + lmsg->msg_iovlen = bmsg->msg_iovlen; + lmsg->msg_control = bmsg->msg_control; + lmsg->msg_controllen = bmsg->msg_controllen; + lmsg->msg_flags = bmsg->msg_flags; +} + int linux_sys_sendmsg(struct lwp *l, const struct linux_sys_sendmsg_args *uap, register_t *retval) { /* { syscallarg(int) s; - syscallarg(struct msghdr *) msg; + syscallarg(struct linux_msghdr *) msg; syscallarg(u_int) flags; } */ struct msghdr msg; + struct linux_msghdr lmsg; int error; int bflags; struct mbuf *nam; u_int8_t *control; struct mbuf *ctl_mbuf = NULL; - error = copyin(SCARG(uap, msg), &msg, sizeof(msg)); + error = copyin(SCARG(uap, msg), &lmsg, sizeof(lmsg)); if (error) return error; + linux_to_bsd_msghdr(&lmsg, &msg); msg.msg_flags = MSG_IOVUSRSPACE; @@ -423,7 +451,7 @@ linux_sys_sendmsg(struct lwp *l, const struct linux_sys_sendmsg_args *uap, regis /* Some supported flag */ return EINVAL; - if (msg.msg_name) { + if (lmsg.msg_name) { /* Read in and convert the sockaddr */ error = linux_get_sa(l, SCARG(uap, s), &nam, msg.msg_name, msg.msg_namelen); @@ -436,7 +464,7 @@ linux_sys_sendmsg(struct lwp *l, const struct linux_sys_sendmsg_args *uap, regis /* * Handle cmsg if there is any. */ - if (CMSG_FIRSTHDR(&msg)) { + if (LINUX_CMSG_FIRSTHDR(&lmsg)) { struct linux_cmsghdr l_cmsg, *l_cc; struct cmsghdr *cmsg; ssize_t resid = msg.msg_controllen; @@ -446,7 +474,7 @@ linux_sys_sendmsg(struct lwp *l, const struct linux_sys_sendmsg_args *uap, regis clen = MLEN; control = mtod(ctl_mbuf, void *); - l_cc = LINUX_CMSG_FIRSTHDR(&msg); + l_cc = LINUX_CMSG_FIRSTHDR(&lmsg); do { error = copyin(l_cc, &l_cmsg, sizeof(l_cmsg)); if (error) @@ -688,16 +716,18 @@ linux_sys_recvmsg(struct lwp *l, const struct linux_sys_recvmsg_args *uap, regis { /* { syscallarg(int) s; - syscallarg(struct msghdr *) msg; + syscallarg(struct linux_msghdr *) msg; syscallarg(u_int) flags; } */ struct msghdr msg; + struct linux_msghdr lmsg; int error; struct mbuf *from, *control; - error = copyin(SCARG(uap, msg), &msg, sizeof(msg)); + error = copyin(SCARG(uap, msg), &lmsg, sizeof(lmsg)); if (error) return (error); + linux_to_bsd_msghdr(&lmsg, &msg); msg.msg_flags = linux_to_bsd_msg_flags(SCARG(uap, flags)); if (msg.msg_flags < 0) { @@ -732,7 +762,8 @@ linux_sys_recvmsg(struct lwp *l, const struct linux_sys_recvmsg_args *uap, regis error = EINVAL; else { ktrkuser("msghdr", &msg, sizeof(msg)); - error = copyout(&msg, SCARG(uap, msg), sizeof(msg)); + bsd_to_linux_msghdr(&msg, &lmsg); + error = copyout(&lmsg, SCARG(uap, msg), sizeof(lmsg)); } } diff --git a/sys/compat/linux/common/linux_socket.h b/sys/compat/linux/common/linux_socket.h index 4a6a625ba4b..ffe624a6fcb 100644 --- a/sys/compat/linux/common/linux_socket.h +++ b/sys/compat/linux/common/linux_socket.h @@ -1,4 +1,4 @@ -/* $NetBSD: linux_socket.h,v 1.16 2008/04/28 20:23:44 martin Exp $ */ +/* $NetBSD: linux_socket.h,v 1.17 2009/06/16 23:17:02 njoly Exp $ */ /*- * Copyright (c) 1995, 1998 The NetBSD Foundation, Inc. @@ -123,6 +123,16 @@ #define LINUX_SCM_TIMESTAMP LINUX_SO_TIMESTAMP /* not actually implemented in Linux 2.5.15? */ +struct linux_msghdr { + void *msg_name; + int msg_namelen; + struct iovec *msg_iov; + size_t msg_iovlen; + void *msg_control; + size_t msg_controllen; + unsigned int msg_flags; +}; + /* * Message flags (for sendmsg/recvmsg) */ diff --git a/sys/compat/linux/common/linux_socketcall.h b/sys/compat/linux/common/linux_socketcall.h index 0acb3da8904..31e4d7baf0d 100644 --- a/sys/compat/linux/common/linux_socketcall.h +++ b/sys/compat/linux/common/linux_socketcall.h @@ -1,4 +1,4 @@ -/* $NetBSD: linux_socketcall.h,v 1.14 2007/12/20 23:02:57 dsl Exp $ */ +/* $NetBSD: linux_socketcall.h,v 1.15 2008/04/28 20:23:44 martin Exp $ */ /*- * Copyright (c) 1995, 1998 The NetBSD Foundation, Inc. @@ -185,13 +185,13 @@ struct linux_sys_getpeername_args { struct linux_sys_sendmsg_args { syscallarg(int) s; - syscallarg(struct msghdr *) msg; + syscallarg(struct linux_msghdr *) msg; syscallarg(u_int) flags; }; struct linux_sys_recvmsg_args { syscallarg(int) s; - syscallarg(struct msghdr *) msg; + syscallarg(struct linux_msghdr *) msg; syscallarg(u_int) flags; }; -- 2.11.4.GIT