add sendmmsg and recvmmsg
This commit is contained in:
parent
c16b94cc41
commit
2a4f2d0e56
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: linux_socket.c,v 1.136 2017/02/03 13:08:08 christos Exp $ */
|
||||
/* $NetBSD: linux_socket.c,v 1.137 2017/02/03 16:57:39 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1995, 1998, 2008 The NetBSD Foundation, Inc.
|
||||
|
@ -35,7 +35,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: linux_socket.c,v 1.136 2017/02/03 13:08:08 christos Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: linux_socket.c,v 1.137 2017/02/03 16:57:39 christos Exp $");
|
||||
|
||||
#if defined(_KERNEL_OPT)
|
||||
#include "opt_inet.h"
|
||||
|
@ -82,6 +82,7 @@ __KERNEL_RCSID(0, "$NetBSD: linux_socket.c,v 1.136 2017/02/03 13:08:08 christos
|
|||
#include <compat/linux/common/linux_util.h>
|
||||
#include <compat/linux/common/linux_signal.h>
|
||||
#include <compat/linux/common/linux_ioctl.h>
|
||||
#include <compat/linux/common/linux_sched.h>
|
||||
#include <compat/linux/common/linux_socket.h>
|
||||
#include <compat/linux/common/linux_fcntl.h>
|
||||
#if !defined(__alpha__) && !defined(__amd64__)
|
||||
|
@ -124,8 +125,8 @@ static int linux_get_sa(struct lwp *, int, struct sockaddr_big *,
|
|||
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 void linux_to_bsd_msghdr(const struct linux_msghdr *, struct msghdr *);
|
||||
static void bsd_to_linux_msghdr(const struct msghdr *, struct linux_msghdr *);
|
||||
|
||||
static const int linux_to_bsd_domain_[LINUX_AF_MAX] = {
|
||||
AF_UNSPEC,
|
||||
|
@ -433,7 +434,7 @@ linux_sys_sendto(struct lwp *l, const struct linux_sys_sendto_args *uap, registe
|
|||
}
|
||||
|
||||
static void
|
||||
linux_to_bsd_msghdr(struct linux_msghdr *lmsg, struct msghdr *bmsg)
|
||||
linux_to_bsd_msghdr(const struct linux_msghdr *lmsg, struct msghdr *bmsg)
|
||||
{
|
||||
bmsg->msg_name = lmsg->msg_name;
|
||||
bmsg->msg_namelen = lmsg->msg_namelen;
|
||||
|
@ -445,7 +446,7 @@ linux_to_bsd_msghdr(struct linux_msghdr *lmsg, struct msghdr *bmsg)
|
|||
}
|
||||
|
||||
static void
|
||||
bsd_to_linux_msghdr(struct msghdr *bmsg, struct linux_msghdr *lmsg)
|
||||
bsd_to_linux_msghdr(const struct msghdr *bmsg, struct linux_msghdr *lmsg)
|
||||
{
|
||||
lmsg->msg_name = bmsg->msg_name;
|
||||
lmsg->msg_namelen = bmsg->msg_namelen;
|
||||
|
@ -1742,3 +1743,190 @@ linux_sys_accept4(struct lwp *l, const struct linux_sys_accept4_args *uap, regis
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
linux_sys_sendmmsg(struct lwp *l, const struct linux_sys_sendmmsg_args *uap,
|
||||
register_t *retval)
|
||||
{
|
||||
/* {
|
||||
syscallarg(int) s;
|
||||
syscallarg(struct linux_mmsghdr *) msgvec;
|
||||
syscallarg(unsigned int) vlen;
|
||||
syscallarg(unsigned int) flags;
|
||||
} */
|
||||
struct linux_mmsghdr lmsg;
|
||||
struct mmsghdr bmsg;
|
||||
struct socket *so;
|
||||
file_t *fp;
|
||||
struct msghdr *msg = &bmsg.msg_hdr;
|
||||
int error, s;
|
||||
unsigned int vlen, flags, dg;
|
||||
|
||||
if ((flags = linux_to_bsd_msg_flags(SCARG(uap, flags))) == -1)
|
||||
return EINVAL;
|
||||
|
||||
flags = (flags & MSG_USERFLAGS) | MSG_IOVUSRSPACE;
|
||||
|
||||
s = SCARG(uap, s);
|
||||
if ((error = fd_getsock1(s, &so, &fp)) != 0)
|
||||
return error;
|
||||
|
||||
vlen = SCARG(uap, vlen);
|
||||
if (vlen > 1024)
|
||||
vlen = 1024;
|
||||
|
||||
for (dg = 0; dg < vlen;) {
|
||||
error = copyin(SCARG(uap, msgvec) + dg, &lmsg, sizeof(lmsg));
|
||||
if (error)
|
||||
break;
|
||||
linux_to_bsd_msghdr(&lmsg.msg_hdr, &bmsg.msg_hdr);
|
||||
|
||||
msg->msg_flags = flags;
|
||||
|
||||
error = do_sys_sendmsg_so(l, s, so, fp, msg, flags,
|
||||
&msg, sizeof(msg), retval);
|
||||
if (error)
|
||||
break;
|
||||
|
||||
ktrkuser("msghdr", msg, sizeof *msg);
|
||||
lmsg.msg_len = *retval;
|
||||
error = copyout(&lmsg, SCARG(uap, msgvec) + dg, sizeof(lmsg));
|
||||
if (error)
|
||||
break;
|
||||
dg++;
|
||||
|
||||
}
|
||||
|
||||
*retval = dg;
|
||||
if (error)
|
||||
so->so_error = error;
|
||||
|
||||
fd_putfile(s);
|
||||
|
||||
/*
|
||||
* If we succeeded at least once, return 0, hopefully so->so_error
|
||||
* will catch it next time.
|
||||
*/
|
||||
if (dg)
|
||||
return 0;
|
||||
return error;
|
||||
}
|
||||
|
||||
int
|
||||
linux_sys_recvmmsg(struct lwp *l, const struct linux_sys_recvmmsg_args *uap,
|
||||
register_t *retval)
|
||||
{
|
||||
/* {
|
||||
syscallarg(int) s;
|
||||
syscallarg(struct linux_mmsghdr *) msgvec;
|
||||
syscallarg(unsigned int) vlen;
|
||||
syscallarg(unsigned int) flags;
|
||||
syscallarg(struct linux_timespec *) timeout;
|
||||
} */
|
||||
struct linux_mmsghdr lmsg;
|
||||
struct mmsghdr bmsg;
|
||||
struct socket *so;
|
||||
struct msghdr *msg = &bmsg.msg_hdr;
|
||||
int error, s;
|
||||
struct mbuf *from, *control;
|
||||
struct timespec ts, now;
|
||||
struct linux_timespec lts;
|
||||
unsigned int vlen, flags, dg;
|
||||
|
||||
if (SCARG(uap, timeout)) {
|
||||
error = copyin(SCARG(uap, timeout), <s, sizeof(lts));
|
||||
return error;
|
||||
ts.tv_sec = lts.tv_sec;
|
||||
ts.tv_nsec = lts.tv_nsec;
|
||||
getnanotime(&now);
|
||||
timespecadd(&now, &ts, &ts);
|
||||
}
|
||||
|
||||
s = SCARG(uap, s);
|
||||
if ((error = fd_getsock(s, &so)) != 0)
|
||||
return error;
|
||||
|
||||
vlen = SCARG(uap, vlen);
|
||||
if (vlen > 1024)
|
||||
vlen = 1024;
|
||||
|
||||
from = NULL;
|
||||
flags = (SCARG(uap, flags) & MSG_USERFLAGS) | MSG_IOVUSRSPACE;
|
||||
|
||||
for (dg = 0; dg < vlen;) {
|
||||
error = copyin(SCARG(uap, msgvec) + dg, &lmsg, sizeof(lmsg));
|
||||
if (error)
|
||||
break;
|
||||
linux_to_bsd_msghdr(&lmsg.msg_hdr, &bmsg.msg_hdr);
|
||||
msg->msg_flags = flags & ~MSG_WAITFORONE;
|
||||
|
||||
if (from != NULL) {
|
||||
m_free(from);
|
||||
from = NULL;
|
||||
}
|
||||
|
||||
error = do_sys_recvmsg_so(l, s, so, msg, NULL, 0, &from,
|
||||
msg->msg_control != NULL ? &control : NULL, retval);
|
||||
if (error) {
|
||||
if (error == EAGAIN && dg > 0)
|
||||
error = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (msg->msg_control != NULL)
|
||||
error = linux_copyout_msg_control(l, msg, control);
|
||||
if (error)
|
||||
break;
|
||||
|
||||
if (from != NULL) {
|
||||
mtod(from, struct osockaddr *)->sa_family =
|
||||
bsd_to_linux_domain(mtod(from,
|
||||
struct sockaddr *)->sa_family);
|
||||
error = copyout_sockname(msg->msg_name,
|
||||
&msg->msg_namelen, 0, from);
|
||||
if (error)
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
lmsg.msg_len = *retval;
|
||||
ktrkuser("msghdr", msg, sizeof(*msg));
|
||||
bsd_to_linux_msghdr(msg, &lmsg.msg_hdr);
|
||||
error = copyout(&lmsg, SCARG(uap, msgvec) + dg, sizeof(lmsg));
|
||||
if (error)
|
||||
break;
|
||||
|
||||
dg++;
|
||||
if (msg->msg_flags & MSG_OOB)
|
||||
break;
|
||||
|
||||
if (SCARG(uap, timeout)) {
|
||||
getnanotime(&now);
|
||||
timespecsub(&now, &ts, &now);
|
||||
if (now.tv_sec > 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (flags & MSG_WAITFORONE)
|
||||
flags |= MSG_DONTWAIT;
|
||||
|
||||
}
|
||||
|
||||
if (from != NULL)
|
||||
m_free(from);
|
||||
|
||||
*retval = dg;
|
||||
if (error)
|
||||
so->so_error = error;
|
||||
|
||||
fd_putfile(s);
|
||||
|
||||
/*
|
||||
* If we succeeded at least once, return 0, hopefully so->so_error
|
||||
* will catch it next time.
|
||||
*/
|
||||
if (dg)
|
||||
return 0;
|
||||
|
||||
return error;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: linux_socket.h,v 1.22 2014/01/27 19:19:15 njoly Exp $ */
|
||||
/* $NetBSD: linux_socket.h,v 1.23 2017/02/03 16:57:39 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1995, 1998 The NetBSD Foundation, Inc.
|
||||
|
@ -140,6 +140,11 @@ struct linux_msghdr {
|
|||
unsigned int msg_flags;
|
||||
};
|
||||
|
||||
struct linux_mmsghdr {
|
||||
struct linux_msghdr msg_hdr;
|
||||
unsigned int msg_len;
|
||||
};
|
||||
|
||||
/*
|
||||
* Message flags (for sendmsg/recvmsg)
|
||||
*/
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: linux_socketcall.c,v 1.46 2017/02/03 13:08:08 christos Exp $ */
|
||||
/* $NetBSD: linux_socketcall.c,v 1.47 2017/02/03 16:57:39 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1995, 1998 The NetBSD Foundation, Inc.
|
||||
|
@ -30,7 +30,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: linux_socketcall.c,v 1.46 2017/02/03 13:08:08 christos Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: linux_socketcall.c,v 1.47 2017/02/03 16:57:39 christos Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/kernel.h>
|
||||
|
@ -219,6 +219,12 @@ linux_sys_socketcall(struct lwp *l, const struct linux_sys_socketcall_args *uap,
|
|||
case LINUX_SYS_ACCEPT4:
|
||||
error = linux_sys_accept4(l, (void *)&lda, retval);
|
||||
break;
|
||||
case LINUX_SYS_RECVMMSG:
|
||||
error = linux_sys_recvmmsg(l, (void *)&lda, retval);
|
||||
break;
|
||||
case LINUX_SYS_SENDMMSG:
|
||||
error = linux_sys_sendmmsg(l, (void *)&lda, retval);
|
||||
break;
|
||||
default:
|
||||
error = ENOSYS;
|
||||
break;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: linux_socketcall.h,v 1.18 2017/02/03 13:08:08 christos Exp $ */
|
||||
/* $NetBSD: linux_socketcall.h,v 1.19 2017/02/03 16:57:39 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1995, 1998 The NetBSD Foundation, Inc.
|
||||
|
@ -95,7 +95,7 @@
|
|||
#define LINUX_SYS_RECVMMSG 19
|
||||
#define LINUX_SYS_SENDMMSG 20
|
||||
|
||||
#define LINUX_MAX_SOCKETCALL 18 /* no send/recv mmsg yet */
|
||||
#define LINUX_MAX_SOCKETCALL 20
|
||||
|
||||
|
||||
/*
|
||||
|
@ -231,6 +231,21 @@ struct linux_sys_accept4_args {
|
|||
syscallarg(int) flags;
|
||||
};
|
||||
|
||||
struct linux_sys_recvmmsg_args {
|
||||
syscallarg(int) s;
|
||||
syscallarg(struct linux_mmsghdr *) msgvec;
|
||||
syscallarg(unsigned int) vlen;
|
||||
syscallarg(unsigned int) flags;
|
||||
syscallarg(struct linux_timespec *) timeout;
|
||||
};
|
||||
|
||||
struct linux_sys_sendmmsg_args {
|
||||
syscallarg(int) s;
|
||||
syscallarg(struct linux_mmsghdr *) msgvec;
|
||||
syscallarg(unsigned int) vlen;
|
||||
syscallarg(unsigned int) flags;
|
||||
};
|
||||
|
||||
# ifdef _KERNEL
|
||||
__BEGIN_DECLS
|
||||
#define SYS_DEF(foo) int foo(struct lwp *, const struct foo##_args *, register_t *);
|
||||
|
@ -250,6 +265,8 @@ SYS_DEF(linux_sys_recv)
|
|||
SYS_DEF(linux_sys_send)
|
||||
SYS_DEF(linux_sys_accept)
|
||||
SYS_DEF(linux_sys_accept4)
|
||||
SYS_DEF(linux_sys_recvmmsg)
|
||||
SYS_DEF(linux_sys_sendmmsg)
|
||||
#undef SYS_DEF
|
||||
__END_DECLS
|
||||
# endif /* !_KERNEL */
|
||||
|
|
Loading…
Reference in New Issue