diff options
author | ps <ps@FreeBSD.org> | 2005-10-15 05:57:06 +0000 |
---|---|---|
committer | ps <ps@FreeBSD.org> | 2005-10-15 05:57:06 +0000 |
commit | a72385743d68a9b60d4489c5ed5297cfc7f37f32 (patch) | |
tree | f91e801ad8f8849ea2dc8840f311e80b890f6396 /sys/compat | |
parent | 36d05b2d9f097b4798aa795664af98d80e9849cf (diff) | |
download | FreeBSD-src-a72385743d68a9b60d4489c5ed5297cfc7f37f32.zip FreeBSD-src-a72385743d68a9b60d4489c5ed5297cfc7f37f32.tar.gz |
Implement the 32bit versions of recvmsg, recvfrom, sendmsg
Partially obtained from: jhb
Diffstat (limited to 'sys/compat')
-rw-r--r-- | sys/compat/freebsd32/freebsd32_misc.c | 165 | ||||
-rw-r--r-- | sys/compat/freebsd32/syscalls.master | 11 |
2 files changed, 171 insertions, 5 deletions
diff --git a/sys/compat/freebsd32/freebsd32_misc.c b/sys/compat/freebsd32/freebsd32_misc.c index d3aa4e8..1506935 100644 --- a/sys/compat/freebsd32/freebsd32_misc.c +++ b/sys/compat/freebsd32/freebsd32_misc.c @@ -797,6 +797,171 @@ freebsd32_pwritev(struct thread *td, struct freebsd32_pwritev_args *uap) return (error); } +static int +freebsd32_copyiniov(struct iovec32 *iovp, u_int iovcnt, struct iovec **iov, + int error) +{ + struct iovec32 iov32; + int i; + + u_int iovlen; + + *iov = NULL; + if (iovcnt > UIO_MAXIOV) + return (error); + iovlen = iovcnt * sizeof(struct iovec); + *iov = malloc(iovlen, M_IOV, M_WAITOK); + for (i = 0; i < iovcnt; i++) { + error = copyin(&iovp[i], &iov32, sizeof(struct iovec32)); + if (error) { + free(*iov, M_IOV); + *iov = NULL; + return (error); + } + iov[i]->iov_base = PTRIN(iov32.iov_base); + iov[i]->iov_len = iov32.iov_len; + } + return (0); +} + +struct msghdr32 { + u_int32_t msg_name; + socklen_t msg_namelen; + u_int32_t msg_iov; + int msg_iovlen; + u_int32_t msg_control; + socklen_t msg_controllen; + int msg_flags; +}; +CTASSERT(sizeof(struct msghdr32) == 28); + +static int +freebsd32_copyinmsghdr(struct msghdr32 *msg32, struct msghdr *msg) +{ + struct msghdr32 m32; + int error; + + error = copyin(msg32, &m32, sizeof(m32)); + if (error) + return (error); + msg->msg_name = PTRIN(m32.msg_name); + msg->msg_namelen = m32.msg_namelen; + msg->msg_iov = PTRIN(m32.msg_iov); + msg->msg_iovlen = m32.msg_iovlen; + msg->msg_control = PTRIN(m32.msg_control); + msg->msg_controllen = m32.msg_controllen; + msg->msg_flags = m32.msg_flags; + return (freebsd32_copyiniov((struct iovec32 *)(uintptr_t)m32.msg_iov, m32.msg_iovlen, &msg->msg_iov, + EMSGSIZE)); +} + +static int +freebsd32_copyoutmsghdr(struct msghdr *msg, struct msghdr32 *msg32) +{ + struct msghdr32 m32; + int error; + + m32.msg_name = PTROUT(msg->msg_name); + m32.msg_namelen = msg->msg_namelen; + m32.msg_iov = PTROUT(msg->msg_iov); + m32.msg_iovlen = msg->msg_iovlen; + m32.msg_control = PTROUT(msg->msg_control); + m32.msg_controllen = msg->msg_controllen; + m32.msg_flags = msg->msg_flags; + error = copyout(&m32, msg32, sizeof(m32)); + return (error); +} + +int +freebsd32_recvmsg(td, uap) + struct thread *td; + struct freebsd32_recvmsg_args /* { + int s; + struct msghdr32 *msg; + int flags; + } */ *uap; +{ + struct msghdr msg; + struct msghdr32 m32; + struct iovec *uiov, *iov; + int error; + + error = copyin(uap->msg, &m32, sizeof(m32)); + if (error) + return (error); + error = freebsd32_copyinmsghdr(uap->msg, &msg); + if (error) + return (error); + error = freebsd32_copyiniov((struct iovec32 *)(uintptr_t)m32.msg_iov, + m32.msg_iovlen, &iov, EMSGSIZE); + if (error) + return (error); + msg.msg_flags = uap->flags; + uiov = msg.msg_iov; + msg.msg_iov = iov; + error = kern_recvit(td, uap->s, &msg, NULL, UIO_SYSSPACE); + if (error == 0) { + msg.msg_iov = uiov; + error = freebsd32_copyoutmsghdr(&msg, uap->msg); + } + free(iov, M_IOV); + free(uiov, M_IOV); + return (error); +} + +int +freebsd32_sendmsg(struct thread *td, + struct freebsd32_sendmsg_args *uap) +{ + struct msghdr msg; + struct msghdr32 m32; + struct iovec *iov; + int error; + + error = copyin(uap->msg, &m32, sizeof(m32)); + if (error) + return (error); + error = freebsd32_copyinmsghdr(uap->msg, &msg); + if (error) + return (error); + error = freebsd32_copyiniov((struct iovec32 *)(uintptr_t)m32.msg_iov, + m32.msg_iovlen, &iov, EMSGSIZE); + if (error) + return (error); + msg.msg_iov = iov; + error = kern_sendit(td, uap->s, &msg, uap->flags, NULL, UIO_SYSSPACE); + free(iov, M_IOV); + return (error); +} + +int +freebsd32_recvfrom(struct thread *td, + struct freebsd32_recvfrom_args *uap) +{ + struct msghdr msg; + struct iovec aiov; + int error; + + if (uap->fromlenaddr) { + error = copyin((void *)(uintptr_t)uap->fromlenaddr, + &msg.msg_namelen, sizeof(msg.msg_namelen)); + if (error) + return (error); + } else { + msg.msg_namelen = 0; + } + + msg.msg_name = (void *)(uintptr_t)uap->from; + msg.msg_iov = &aiov; + msg.msg_iovlen = 1; + aiov.iov_base = (void *)(uintptr_t)uap->buf; + aiov.iov_len = uap->len; + msg.msg_control = 0; + msg.msg_flags = uap->flags; + error = kern_recvit(td, uap->s, &msg, (void *)(uintptr_t)uap->fromlenaddr, UIO_USERSPACE); + return (error); +} + int freebsd32_settimeofday(struct thread *td, struct freebsd32_settimeofday_args *uap) diff --git a/sys/compat/freebsd32/syscalls.master b/sys/compat/freebsd32/syscalls.master index 8e6806a..59a0c1c 100644 --- a/sys/compat/freebsd32/syscalls.master +++ b/sys/compat/freebsd32/syscalls.master @@ -88,12 +88,13 @@ 26 AUE_NULL MNOPROTO { int ptrace(int req, pid_t pid, \ caddr_t addr, int data); } ; XXX implement -27 AUE_NULL UNIMPL recvmsg -28 AUE_NULL MNOPROTO { int sendmsg(int s, caddr_t msg, \ +27 AUE_NULL MSTD { int freebsd32_recvmsg(int s, struct msghdr32 *msg, \ int flags); } -29 AUE_NULL MNOPROTO { int recvfrom(int s, caddr_t buf, \ - size_t len, int flags, caddr_t from, \ - int *fromlenaddr); } +28 AUE_NULL MSTD { int freebsd32_sendmsg(int s, struct msghdr32 *msg, \ + int flags); } +29 AUE_NULL MSTD { int freebsd32_recvfrom(int s, u_int32_t buf, \ + u_int32_t len, int flags, u_int32_t from, \ + u_int32_t fromlenaddr); } 30 AUE_NULL MNOPROTO { int accept(int s, caddr_t name, \ int *anamelen); } 31 AUE_NULL MNOPROTO { int getpeername(int fdes, caddr_t asa, \ |