Implement the 32bit versions of recvmsg, recvfrom, sendmsg

Partially obtained from:	jhb
This commit is contained in:
ps 2005-10-15 05:57:06 +00:00
parent 36d05b2d9f
commit a72385743d
4 changed files with 188 additions and 8 deletions

View File

@ -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)

View File

@ -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, \

View File

@ -922,12 +922,13 @@ sendmsg(td, uap)
return (error);
}
static int
recvit(td, s, mp, namelenp)
int
kern_recvit(td, s, mp, namelenp, segflg)
struct thread *td;
int s;
struct msghdr *mp;
void *namelenp;
enum uio_seg segflg;
{
struct uio auio;
struct iovec *iov;
@ -964,7 +965,7 @@ recvit(td, s, mp, namelenp)
auio.uio_iov = mp->msg_iov;
auio.uio_iovcnt = mp->msg_iovlen;
auio.uio_segflg = UIO_USERSPACE;
auio.uio_segflg = segflg;
auio.uio_rw = UIO_READ;
auio.uio_td = td;
auio.uio_offset = 0; /* XXX */
@ -1082,6 +1083,17 @@ out:
return (error);
}
static int
recvit(td, s, mp, namelenp)
struct thread *td;
int s;
struct msghdr *mp;
void *namelenp;
{
return (kern_recvit(td, s, mp, namelenp, UIO_USERSPACE));
}
/*
* MPSAFE
*/

View File

@ -111,6 +111,8 @@ int kern_pwritev(struct thread *td, int fd, struct uio *auio, off_t offset);
int kern_readlink(struct thread *td, char *path, enum uio_seg pathseg,
char *buf, enum uio_seg bufseg, int count);
int kern_readv(struct thread *td, int fd, struct uio *auio);
int kern_recvit(struct thread *td, int s, struct msghdr *mp, void *namelenp,
enum uio_seg segflg);
int kern_rename(struct thread *td, char *from, char *to,
enum uio_seg pathseg);
int kern_rmdir(struct thread *td, char *path, enum uio_seg pathseg);