mirror of
https://git.FreeBSD.org/src.git
synced 2024-12-24 11:29:10 +00:00
Implement recvmmsg() and sendmmsg() system calls.
This commit is contained in:
parent
b7aaa9fdb0
commit
e1ff74c0f7
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=283488
@ -108,14 +108,12 @@ DUMMY(preadv);
|
|||||||
DUMMY(pwritev);
|
DUMMY(pwritev);
|
||||||
DUMMY(rt_tsigqueueinfo);
|
DUMMY(rt_tsigqueueinfo);
|
||||||
DUMMY(perf_event_open);
|
DUMMY(perf_event_open);
|
||||||
DUMMY(recvmmsg);
|
|
||||||
DUMMY(fanotify_init);
|
DUMMY(fanotify_init);
|
||||||
DUMMY(fanotify_mark);
|
DUMMY(fanotify_mark);
|
||||||
DUMMY(name_to_handle_at);
|
DUMMY(name_to_handle_at);
|
||||||
DUMMY(open_by_handle_at);
|
DUMMY(open_by_handle_at);
|
||||||
DUMMY(clock_adjtime);
|
DUMMY(clock_adjtime);
|
||||||
DUMMY(syncfs);
|
DUMMY(syncfs);
|
||||||
DUMMY(sendmmsg);
|
|
||||||
DUMMY(setns);
|
DUMMY(setns);
|
||||||
DUMMY(process_vm_readv);
|
DUMMY(process_vm_readv);
|
||||||
DUMMY(process_vm_writev);
|
DUMMY(process_vm_writev);
|
||||||
|
@ -492,7 +492,9 @@
|
|||||||
296 AUE_NULL STD { int linux_pwritev(void); }
|
296 AUE_NULL STD { int linux_pwritev(void); }
|
||||||
297 AUE_NULL STD { int linux_rt_tsigqueueinfo(void); }
|
297 AUE_NULL STD { int linux_rt_tsigqueueinfo(void); }
|
||||||
298 AUE_NULL STD { int linux_perf_event_open(void); }
|
298 AUE_NULL STD { int linux_perf_event_open(void); }
|
||||||
299 AUE_NULL STD { int linux_recvmmsg(void); }
|
299 AUE_NULL STD { int linux_recvmmsg(l_int s, \
|
||||||
|
struct l_mmsghdr *msg, l_uint vlen, \
|
||||||
|
l_uint flags, struct l_timespec *timeout); }
|
||||||
300 AUE_NULL STD { int linux_fanotify_init(void); }
|
300 AUE_NULL STD { int linux_fanotify_init(void); }
|
||||||
301 AUE_NULL STD { int linux_fanotify_mark(void); }
|
301 AUE_NULL STD { int linux_fanotify_mark(void); }
|
||||||
302 AUE_NULL STD { int linux_prlimit64(l_pid_t pid, l_uint resource, \
|
302 AUE_NULL STD { int linux_prlimit64(l_pid_t pid, l_uint resource, \
|
||||||
@ -501,7 +503,9 @@
|
|||||||
304 AUE_NULL STD { int linux_open_by_handle_at(void); }
|
304 AUE_NULL STD { int linux_open_by_handle_at(void); }
|
||||||
305 AUE_NULL STD { int linux_clock_adjtime(void); }
|
305 AUE_NULL STD { int linux_clock_adjtime(void); }
|
||||||
306 AUE_NULL STD { int linux_syncfs(void); }
|
306 AUE_NULL STD { int linux_syncfs(void); }
|
||||||
307 AUE_NULL STD { int linux_sendmmsg(void); }
|
307 AUE_NULL STD { int linux_sendmmsg(l_int s, \
|
||||||
|
struct l_mmsghdr *msg, l_uint vlen, \
|
||||||
|
l_uint flags); }
|
||||||
308 AUE_NULL STD { int linux_setns(void); }
|
308 AUE_NULL STD { int linux_setns(void); }
|
||||||
309 AUE_NULL STD { int linux_process_vm_readv(void); }
|
309 AUE_NULL STD { int linux_process_vm_readv(void); }
|
||||||
310 AUE_NULL STD { int linux_process_vm_writev(void); }
|
310 AUE_NULL STD { int linux_process_vm_writev(void); }
|
||||||
|
@ -118,7 +118,6 @@ DUMMY(pwritev);
|
|||||||
DUMMY(rt_tsigqueueinfo);
|
DUMMY(rt_tsigqueueinfo);
|
||||||
DUMMY(perf_event_open);
|
DUMMY(perf_event_open);
|
||||||
/* linux 2.6.33: */
|
/* linux 2.6.33: */
|
||||||
DUMMY(recvmmsg);
|
|
||||||
DUMMY(fanotify_init);
|
DUMMY(fanotify_init);
|
||||||
DUMMY(fanotify_mark);
|
DUMMY(fanotify_mark);
|
||||||
/* later: */
|
/* later: */
|
||||||
@ -126,7 +125,6 @@ DUMMY(name_to_handle_at);
|
|||||||
DUMMY(open_by_handle_at);
|
DUMMY(open_by_handle_at);
|
||||||
DUMMY(clock_adjtime);
|
DUMMY(clock_adjtime);
|
||||||
DUMMY(syncfs);
|
DUMMY(syncfs);
|
||||||
DUMMY(sendmmsg);
|
|
||||||
DUMMY(setns);
|
DUMMY(setns);
|
||||||
DUMMY(process_vm_readv);
|
DUMMY(process_vm_readv);
|
||||||
DUMMY(process_vm_writev);
|
DUMMY(process_vm_writev);
|
||||||
|
@ -559,7 +559,9 @@
|
|||||||
335 AUE_NULL STD { int linux_rt_tsigqueueinfo(void); }
|
335 AUE_NULL STD { int linux_rt_tsigqueueinfo(void); }
|
||||||
336 AUE_NULL STD { int linux_perf_event_open(void); }
|
336 AUE_NULL STD { int linux_perf_event_open(void); }
|
||||||
; linux 2.6.33:
|
; linux 2.6.33:
|
||||||
337 AUE_NULL STD { int linux_recvmmsg(void); }
|
337 AUE_NULL STD { int linux_recvmmsg(l_int s, \
|
||||||
|
struct l_mmsghdr *msg, l_uint vlen, \
|
||||||
|
l_uint flags, struct l_timespec *timeout); }
|
||||||
338 AUE_NULL STD { int linux_fanotify_init(void); }
|
338 AUE_NULL STD { int linux_fanotify_init(void); }
|
||||||
339 AUE_NULL STD { int linux_fanotify_mark(void); }
|
339 AUE_NULL STD { int linux_fanotify_mark(void); }
|
||||||
; linux 2.6.36:
|
; linux 2.6.36:
|
||||||
@ -572,7 +574,9 @@
|
|||||||
342 AUE_NULL STD { int linux_open_by_handle_at(void); }
|
342 AUE_NULL STD { int linux_open_by_handle_at(void); }
|
||||||
343 AUE_NULL STD { int linux_clock_adjtime(void); }
|
343 AUE_NULL STD { int linux_clock_adjtime(void); }
|
||||||
344 AUE_NULL STD { int linux_syncfs(void); }
|
344 AUE_NULL STD { int linux_syncfs(void); }
|
||||||
345 AUE_NULL STD { int linux_sendmmsg(void); }
|
345 AUE_NULL STD { int linux_sendmmsg(l_int s, \
|
||||||
|
struct l_mmsghdr *msg, l_uint vlen, \
|
||||||
|
l_uint flags); }
|
||||||
346 AUE_NULL STD { int linux_setns(void); }
|
346 AUE_NULL STD { int linux_setns(void); }
|
||||||
347 AUE_NULL STD { int linux_process_vm_readv(void); }
|
347 AUE_NULL STD { int linux_process_vm_readv(void); }
|
||||||
348 AUE_NULL STD { int linux_process_vm_writev(void); }
|
348 AUE_NULL STD { int linux_process_vm_writev(void); }
|
||||||
|
@ -72,9 +72,14 @@ __FBSDID("$FreeBSD$");
|
|||||||
#endif
|
#endif
|
||||||
#include <compat/linux/linux_file.h>
|
#include <compat/linux/linux_file.h>
|
||||||
#include <compat/linux/linux_socket.h>
|
#include <compat/linux/linux_socket.h>
|
||||||
|
#include <compat/linux/linux_timer.h>
|
||||||
#include <compat/linux/linux_util.h>
|
#include <compat/linux/linux_util.h>
|
||||||
|
|
||||||
static int linux_to_bsd_domain(int);
|
static int linux_to_bsd_domain(int);
|
||||||
|
static int linux_sendmsg_common(struct thread *, l_int, struct l_msghdr *,
|
||||||
|
l_uint);
|
||||||
|
static int linux_recvmsg_common(struct thread *, l_int, struct l_msghdr *,
|
||||||
|
l_uint, struct msghdr *);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Reads a linux sockaddr and does any necessary translation.
|
* Reads a linux sockaddr and does any necessary translation.
|
||||||
@ -1073,8 +1078,9 @@ linux_recvfrom(struct thread *td, struct linux_recvfrom_args *args)
|
|||||||
return (error);
|
return (error);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
static int
|
||||||
linux_sendmsg(struct thread *td, struct linux_sendmsg_args *args)
|
linux_sendmsg_common(struct thread *td, l_int s, struct l_msghdr *msghdr,
|
||||||
|
l_uint flags)
|
||||||
{
|
{
|
||||||
struct cmsghdr *cmsg;
|
struct cmsghdr *cmsg;
|
||||||
struct cmsgcred cmcred;
|
struct cmsgcred cmcred;
|
||||||
@ -1090,8 +1096,8 @@ linux_sendmsg(struct thread *td, struct linux_sendmsg_args *args)
|
|||||||
void *data;
|
void *data;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
error = copyin(PTRIN(args->msg), &linux_msg, sizeof(linux_msg));
|
error = copyin(msghdr, &linux_msg, sizeof(linux_msg));
|
||||||
if (error)
|
if (error != 0)
|
||||||
return (error);
|
return (error);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1105,7 +1111,7 @@ linux_sendmsg(struct thread *td, struct linux_sendmsg_args *args)
|
|||||||
linux_msg.msg_control = PTROUT(NULL);
|
linux_msg.msg_control = PTROUT(NULL);
|
||||||
|
|
||||||
error = linux_to_bsd_msghdr(&msg, &linux_msg);
|
error = linux_to_bsd_msghdr(&msg, &linux_msg);
|
||||||
if (error)
|
if (error != 0)
|
||||||
return (error);
|
return (error);
|
||||||
|
|
||||||
#ifdef COMPAT_LINUX32
|
#ifdef COMPAT_LINUX32
|
||||||
@ -1114,21 +1120,21 @@ linux_sendmsg(struct thread *td, struct linux_sendmsg_args *args)
|
|||||||
#else
|
#else
|
||||||
error = copyiniov(msg.msg_iov, msg.msg_iovlen, &iov, EMSGSIZE);
|
error = copyiniov(msg.msg_iov, msg.msg_iovlen, &iov, EMSGSIZE);
|
||||||
#endif
|
#endif
|
||||||
if (error)
|
if (error != 0)
|
||||||
return (error);
|
return (error);
|
||||||
|
|
||||||
control = NULL;
|
control = NULL;
|
||||||
cmsg = NULL;
|
cmsg = NULL;
|
||||||
|
|
||||||
if ((ptr_cmsg = LINUX_CMSG_FIRSTHDR(&linux_msg)) != NULL) {
|
if ((ptr_cmsg = LINUX_CMSG_FIRSTHDR(&linux_msg)) != NULL) {
|
||||||
error = kern_getsockname(td, args->s, &sa, &datalen);
|
error = kern_getsockname(td, s, &sa, &datalen);
|
||||||
if (error)
|
if (error != 0)
|
||||||
goto bad;
|
goto bad;
|
||||||
sa_family = sa->sa_family;
|
sa_family = sa->sa_family;
|
||||||
free(sa, M_SONAME);
|
free(sa, M_SONAME);
|
||||||
|
|
||||||
error = ENOBUFS;
|
error = ENOBUFS;
|
||||||
cmsg = malloc(CMSG_HDRSZ, M_LINUX, M_WAITOK | M_ZERO);
|
cmsg = malloc(CMSG_HDRSZ, M_LINUX, M_WAITOK|M_ZERO);
|
||||||
control = m_get(M_WAITOK, MT_CONTROL);
|
control = m_get(M_WAITOK, MT_CONTROL);
|
||||||
if (control == NULL)
|
if (control == NULL)
|
||||||
goto bad;
|
goto bad;
|
||||||
@ -1136,7 +1142,7 @@ linux_sendmsg(struct thread *td, struct linux_sendmsg_args *args)
|
|||||||
do {
|
do {
|
||||||
error = copyin(ptr_cmsg, &linux_cmsg,
|
error = copyin(ptr_cmsg, &linux_cmsg,
|
||||||
sizeof(struct l_cmsghdr));
|
sizeof(struct l_cmsghdr));
|
||||||
if (error)
|
if (error != 0)
|
||||||
goto bad;
|
goto bad;
|
||||||
|
|
||||||
error = EINVAL;
|
error = EINVAL;
|
||||||
@ -1200,8 +1206,7 @@ linux_sendmsg(struct thread *td, struct linux_sendmsg_args *args)
|
|||||||
|
|
||||||
msg.msg_iov = iov;
|
msg.msg_iov = iov;
|
||||||
msg.msg_flags = 0;
|
msg.msg_flags = 0;
|
||||||
error = linux_sendit(td, args->s, &msg, args->flags, control,
|
error = linux_sendit(td, s, &msg, flags, control, UIO_USERSPACE);
|
||||||
UIO_USERSPACE);
|
|
||||||
|
|
||||||
bad:
|
bad:
|
||||||
free(iov, M_IOV);
|
free(iov, M_IOV);
|
||||||
@ -1211,11 +1216,49 @@ linux_sendmsg(struct thread *td, struct linux_sendmsg_args *args)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
linux_recvmsg(struct thread *td, struct linux_recvmsg_args *args)
|
linux_sendmsg(struct thread *td, struct linux_sendmsg_args *args)
|
||||||
|
{
|
||||||
|
|
||||||
|
return (linux_sendmsg_common(td, args->s, PTRIN(args->msg),
|
||||||
|
args->flags));
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
linux_sendmmsg(struct thread *td, struct linux_sendmmsg_args *args)
|
||||||
|
{
|
||||||
|
struct l_mmsghdr *msg;
|
||||||
|
l_uint retval;
|
||||||
|
int error, datagrams;
|
||||||
|
|
||||||
|
if (args->vlen > UIO_MAXIOV)
|
||||||
|
args->vlen = UIO_MAXIOV;
|
||||||
|
|
||||||
|
msg = PTRIN(args->msg);
|
||||||
|
datagrams = 0;
|
||||||
|
while (datagrams < args->vlen) {
|
||||||
|
error = linux_sendmsg_common(td, args->s, &msg->msg_hdr,
|
||||||
|
args->flags);
|
||||||
|
if (error != 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
retval = td->td_retval[0];
|
||||||
|
error = copyout(&retval, &msg->msg_len, sizeof(msg->msg_len));
|
||||||
|
if (error != 0)
|
||||||
|
break;
|
||||||
|
++msg;
|
||||||
|
++datagrams;
|
||||||
|
}
|
||||||
|
if (error == 0)
|
||||||
|
td->td_retval[0] = datagrams;
|
||||||
|
return (error);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
linux_recvmsg_common(struct thread *td, l_int s, struct l_msghdr *msghdr,
|
||||||
|
l_uint flags, struct msghdr *msg)
|
||||||
{
|
{
|
||||||
struct cmsghdr *cm;
|
struct cmsghdr *cm;
|
||||||
struct cmsgcred *cmcred;
|
struct cmsgcred *cmcred;
|
||||||
struct msghdr msg;
|
|
||||||
struct l_cmsghdr *linux_cmsg = NULL;
|
struct l_cmsghdr *linux_cmsg = NULL;
|
||||||
struct l_ucred linux_ucred;
|
struct l_ucred linux_ucred;
|
||||||
socklen_t datalen, outlen;
|
socklen_t datalen, outlen;
|
||||||
@ -1227,51 +1270,51 @@ linux_recvmsg(struct thread *td, struct linux_recvmsg_args *args)
|
|||||||
void *data;
|
void *data;
|
||||||
int error, i, fd, fds, *fdp;
|
int error, i, fd, fds, *fdp;
|
||||||
|
|
||||||
error = copyin(PTRIN(args->msg), &linux_msg, sizeof(linux_msg));
|
error = copyin(msghdr, &linux_msg, sizeof(linux_msg));
|
||||||
if (error)
|
if (error != 0)
|
||||||
return (error);
|
return (error);
|
||||||
|
|
||||||
error = linux_to_bsd_msghdr(&msg, &linux_msg);
|
error = linux_to_bsd_msghdr(msg, &linux_msg);
|
||||||
if (error)
|
if (error != 0)
|
||||||
return (error);
|
return (error);
|
||||||
|
|
||||||
#ifdef COMPAT_LINUX32
|
#ifdef COMPAT_LINUX32
|
||||||
error = linux32_copyiniov(PTRIN(msg.msg_iov), msg.msg_iovlen,
|
error = linux32_copyiniov(PTRIN(msg->msg_iov), msg->msg_iovlen,
|
||||||
&iov, EMSGSIZE);
|
&iov, EMSGSIZE);
|
||||||
#else
|
#else
|
||||||
error = copyiniov(msg.msg_iov, msg.msg_iovlen, &iov, EMSGSIZE);
|
error = copyiniov(msg->msg_iov, msg->msg_iovlen, &iov, EMSGSIZE);
|
||||||
#endif
|
#endif
|
||||||
if (error)
|
if (error != 0)
|
||||||
return (error);
|
return (error);
|
||||||
|
|
||||||
if (msg.msg_name) {
|
if (msg->msg_name) {
|
||||||
error = linux_to_bsd_sockaddr((struct sockaddr *)msg.msg_name,
|
error = linux_to_bsd_sockaddr((struct sockaddr *)msg->msg_name,
|
||||||
msg.msg_namelen);
|
msg->msg_namelen);
|
||||||
if (error)
|
if (error != 0)
|
||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
|
|
||||||
uiov = msg.msg_iov;
|
uiov = msg->msg_iov;
|
||||||
msg.msg_iov = iov;
|
msg->msg_iov = iov;
|
||||||
controlp = (msg.msg_control != NULL) ? &control : NULL;
|
controlp = (msg->msg_control != NULL) ? &control : NULL;
|
||||||
error = kern_recvit(td, args->s, &msg, UIO_USERSPACE, controlp);
|
error = kern_recvit(td, s, msg, UIO_USERSPACE, controlp);
|
||||||
msg.msg_iov = uiov;
|
msg->msg_iov = uiov;
|
||||||
if (error)
|
if (error != 0)
|
||||||
goto bad;
|
goto bad;
|
||||||
|
|
||||||
error = bsd_to_linux_msghdr(&msg, &linux_msg);
|
error = bsd_to_linux_msghdr(msg, &linux_msg);
|
||||||
if (error)
|
if (error != 0)
|
||||||
goto bad;
|
goto bad;
|
||||||
|
|
||||||
if (linux_msg.msg_name) {
|
if (linux_msg.msg_name) {
|
||||||
error = bsd_to_linux_sockaddr((struct sockaddr *)
|
error = bsd_to_linux_sockaddr((struct sockaddr *)
|
||||||
PTRIN(linux_msg.msg_name));
|
PTRIN(linux_msg.msg_name));
|
||||||
if (error)
|
if (error != 0)
|
||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
if (linux_msg.msg_name && linux_msg.msg_namelen > 2) {
|
if (linux_msg.msg_name && linux_msg.msg_namelen > 2) {
|
||||||
error = linux_sa_put(PTRIN(linux_msg.msg_name));
|
error = linux_sa_put(PTRIN(linux_msg.msg_name));
|
||||||
if (error)
|
if (error != 0)
|
||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1281,10 +1324,10 @@ linux_recvmsg(struct thread *td, struct linux_recvmsg_args *args)
|
|||||||
if (control) {
|
if (control) {
|
||||||
linux_cmsg = malloc(L_CMSG_HDRSZ, M_LINUX, M_WAITOK | M_ZERO);
|
linux_cmsg = malloc(L_CMSG_HDRSZ, M_LINUX, M_WAITOK | M_ZERO);
|
||||||
|
|
||||||
msg.msg_control = mtod(control, struct cmsghdr *);
|
msg->msg_control = mtod(control, struct cmsghdr *);
|
||||||
msg.msg_controllen = control->m_len;
|
msg->msg_controllen = control->m_len;
|
||||||
|
|
||||||
cm = CMSG_FIRSTHDR(&msg);
|
cm = CMSG_FIRSTHDR(msg);
|
||||||
|
|
||||||
while (cm != NULL) {
|
while (cm != NULL) {
|
||||||
linux_cmsg->cmsg_type =
|
linux_cmsg->cmsg_type =
|
||||||
@ -1304,7 +1347,7 @@ linux_recvmsg(struct thread *td, struct linux_recvmsg_args *args)
|
|||||||
switch (cm->cmsg_type)
|
switch (cm->cmsg_type)
|
||||||
{
|
{
|
||||||
case SCM_RIGHTS:
|
case SCM_RIGHTS:
|
||||||
if (args->flags & LINUX_MSG_CMSG_CLOEXEC) {
|
if (flags & LINUX_MSG_CMSG_CLOEXEC) {
|
||||||
fds = datalen / sizeof(int);
|
fds = datalen / sizeof(int);
|
||||||
fdp = data;
|
fdp = data;
|
||||||
for (i = 0; i < fds; i++) {
|
for (i = 0; i < fds; i++) {
|
||||||
@ -1361,13 +1404,13 @@ linux_recvmsg(struct thread *td, struct linux_recvmsg_args *args)
|
|||||||
outbuf += LINUX_CMSG_ALIGN(datalen);
|
outbuf += LINUX_CMSG_ALIGN(datalen);
|
||||||
outlen += LINUX_CMSG_LEN(datalen);
|
outlen += LINUX_CMSG_LEN(datalen);
|
||||||
|
|
||||||
cm = CMSG_NXTHDR(&msg, cm);
|
cm = CMSG_NXTHDR(msg, cm);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
linux_msg.msg_controllen = outlen;
|
linux_msg.msg_controllen = outlen;
|
||||||
error = copyout(&linux_msg, PTRIN(args->msg), sizeof(linux_msg));
|
error = copyout(&linux_msg, msghdr, sizeof(linux_msg));
|
||||||
|
|
||||||
bad:
|
bad:
|
||||||
free(iov, M_IOV);
|
free(iov, M_IOV);
|
||||||
@ -1377,6 +1420,75 @@ linux_recvmsg(struct thread *td, struct linux_recvmsg_args *args)
|
|||||||
return (error);
|
return (error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
linux_recvmsg(struct thread *td, struct linux_recvmsg_args *args)
|
||||||
|
{
|
||||||
|
struct msghdr bsd_msg;
|
||||||
|
|
||||||
|
return (linux_recvmsg_common(td, args->s, PTRIN(args->msg),
|
||||||
|
args->flags, &bsd_msg));
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
linux_recvmmsg(struct thread *td, struct linux_recvmmsg_args *args)
|
||||||
|
{
|
||||||
|
struct l_mmsghdr *msg;
|
||||||
|
struct msghdr bsd_msg;
|
||||||
|
struct l_timespec lts;
|
||||||
|
struct timespec ts, tts;
|
||||||
|
l_uint retval;
|
||||||
|
int error, datagrams;
|
||||||
|
|
||||||
|
if (args->timeout) {
|
||||||
|
error = copyin(args->timeout, <s, sizeof(struct l_timespec));
|
||||||
|
if (error != 0)
|
||||||
|
return (error);
|
||||||
|
error = linux_to_native_timespec(&ts, <s);
|
||||||
|
if (error != 0)
|
||||||
|
return (error);
|
||||||
|
getnanotime(&tts);
|
||||||
|
timespecadd(&tts, &ts);
|
||||||
|
}
|
||||||
|
|
||||||
|
msg = PTRIN(args->msg);
|
||||||
|
datagrams = 0;
|
||||||
|
while (datagrams < args->vlen) {
|
||||||
|
error = linux_recvmsg_common(td, args->s, &msg->msg_hdr,
|
||||||
|
args->flags & ~LINUX_MSG_WAITFORONE, &bsd_msg);
|
||||||
|
if (error != 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
retval = td->td_retval[0];
|
||||||
|
error = copyout(&retval, &msg->msg_len, sizeof(msg->msg_len));
|
||||||
|
if (error != 0)
|
||||||
|
break;
|
||||||
|
++msg;
|
||||||
|
++datagrams;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* MSG_WAITFORONE turns on MSG_DONTWAIT after one packet.
|
||||||
|
*/
|
||||||
|
if (args->flags & LINUX_MSG_WAITFORONE)
|
||||||
|
args->flags |= LINUX_MSG_DONTWAIT;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* See BUGS section of recvmmsg(2).
|
||||||
|
*/
|
||||||
|
if (args->timeout) {
|
||||||
|
getnanotime(&ts);
|
||||||
|
timespecsub(&ts, &tts);
|
||||||
|
if (!timespecisset(&ts) || ts.tv_sec > 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* Out of band data, return right away. */
|
||||||
|
if (bsd_msg.msg_flags & MSG_OOB)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (error == 0)
|
||||||
|
td->td_retval[0] = datagrams;
|
||||||
|
return (error);
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
linux_shutdown(struct thread *td, struct linux_shutdown_args *args)
|
linux_shutdown(struct thread *td, struct linux_shutdown_args *args)
|
||||||
{
|
{
|
||||||
@ -1555,7 +1667,8 @@ static const unsigned char lxs_args[] = {
|
|||||||
LINUX_AL(6) /* recvfrom */, LINUX_AL(2) /* shutdown */,
|
LINUX_AL(6) /* recvfrom */, LINUX_AL(2) /* shutdown */,
|
||||||
LINUX_AL(5) /* setsockopt */, LINUX_AL(5) /* getsockopt */,
|
LINUX_AL(5) /* setsockopt */, LINUX_AL(5) /* getsockopt */,
|
||||||
LINUX_AL(3) /* sendmsg */, LINUX_AL(3) /* recvmsg */,
|
LINUX_AL(3) /* sendmsg */, LINUX_AL(3) /* recvmsg */,
|
||||||
LINUX_AL(4) /* accept4 */
|
LINUX_AL(4) /* accept4 */, LINUX_AL(5) /* recvmmsg */,
|
||||||
|
LINUX_AL(4) /* sendmmsg */
|
||||||
};
|
};
|
||||||
|
|
||||||
#define LINUX_AL_SIZE sizeof(lxs_args) / sizeof(lxs_args[0]) - 1
|
#define LINUX_AL_SIZE sizeof(lxs_args) / sizeof(lxs_args[0]) - 1
|
||||||
@ -1611,6 +1724,10 @@ linux_socketcall(struct thread *td, struct linux_socketcall_args *args)
|
|||||||
return (linux_recvmsg(td, arg));
|
return (linux_recvmsg(td, arg));
|
||||||
case LINUX_ACCEPT4:
|
case LINUX_ACCEPT4:
|
||||||
return (linux_accept4(td, arg));
|
return (linux_accept4(td, arg));
|
||||||
|
case LINUX_RECVMMSG:
|
||||||
|
return (linux_recvmmsg(td, arg));
|
||||||
|
case LINUX_SENDMMSG:
|
||||||
|
return (linux_sendmmsg(td, arg));
|
||||||
}
|
}
|
||||||
|
|
||||||
uprintf("LINUX: 'socket' typ=%d not implemented\n", args->what);
|
uprintf("LINUX: 'socket' typ=%d not implemented\n", args->what);
|
||||||
|
@ -48,6 +48,7 @@
|
|||||||
#define LINUX_MSG_RST 0x1000
|
#define LINUX_MSG_RST 0x1000
|
||||||
#define LINUX_MSG_ERRQUEUE 0x2000
|
#define LINUX_MSG_ERRQUEUE 0x2000
|
||||||
#define LINUX_MSG_NOSIGNAL 0x4000
|
#define LINUX_MSG_NOSIGNAL 0x4000
|
||||||
|
#define LINUX_MSG_WAITFORONE 0x10000
|
||||||
#define LINUX_MSG_CMSG_CLOEXEC 0x40000000
|
#define LINUX_MSG_CMSG_CLOEXEC 0x40000000
|
||||||
|
|
||||||
/* Socket-level control message types */
|
/* Socket-level control message types */
|
||||||
@ -65,6 +66,12 @@ struct l_msghdr {
|
|||||||
l_uint msg_flags;
|
l_uint msg_flags;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct l_mmsghdr {
|
||||||
|
struct l_msghdr msg_hdr;
|
||||||
|
l_uint msg_len;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
struct l_cmsghdr {
|
struct l_cmsghdr {
|
||||||
l_size_t cmsg_len;
|
l_size_t cmsg_len;
|
||||||
l_int cmsg_level;
|
l_int cmsg_level;
|
||||||
@ -279,6 +286,8 @@ int linux_getsockopt(struct thread *td, struct linux_getsockopt_args *args);
|
|||||||
#define LINUX_SENDMSG 16
|
#define LINUX_SENDMSG 16
|
||||||
#define LINUX_RECVMSG 17
|
#define LINUX_RECVMSG 17
|
||||||
#define LINUX_ACCEPT4 18
|
#define LINUX_ACCEPT4 18
|
||||||
|
#define LINUX_RECVMMSG 19
|
||||||
|
#define LINUX_SENDMMSG 20
|
||||||
|
|
||||||
/* Socket options */
|
/* Socket options */
|
||||||
#define LINUX_IP_TOS 1
|
#define LINUX_IP_TOS 1
|
||||||
|
@ -114,7 +114,6 @@ DUMMY(pwritev);
|
|||||||
DUMMY(rt_tsigqueueinfo);
|
DUMMY(rt_tsigqueueinfo);
|
||||||
DUMMY(perf_event_open);
|
DUMMY(perf_event_open);
|
||||||
/* linux 2.6.33: */
|
/* linux 2.6.33: */
|
||||||
DUMMY(recvmmsg);
|
|
||||||
DUMMY(fanotify_init);
|
DUMMY(fanotify_init);
|
||||||
DUMMY(fanotify_mark);
|
DUMMY(fanotify_mark);
|
||||||
/* later: */
|
/* later: */
|
||||||
@ -122,7 +121,6 @@ DUMMY(name_to_handle_at);
|
|||||||
DUMMY(open_by_handle_at);
|
DUMMY(open_by_handle_at);
|
||||||
DUMMY(clock_adjtime);
|
DUMMY(clock_adjtime);
|
||||||
DUMMY(syncfs);
|
DUMMY(syncfs);
|
||||||
DUMMY(sendmmsg);
|
|
||||||
DUMMY(setns);
|
DUMMY(setns);
|
||||||
DUMMY(process_vm_readv);
|
DUMMY(process_vm_readv);
|
||||||
DUMMY(process_vm_writev);
|
DUMMY(process_vm_writev);
|
||||||
|
@ -567,7 +567,9 @@
|
|||||||
335 AUE_NULL STD { int linux_rt_tsigqueueinfo(void); }
|
335 AUE_NULL STD { int linux_rt_tsigqueueinfo(void); }
|
||||||
336 AUE_NULL STD { int linux_perf_event_open(void); }
|
336 AUE_NULL STD { int linux_perf_event_open(void); }
|
||||||
; linux 2.6.33:
|
; linux 2.6.33:
|
||||||
337 AUE_NULL STD { int linux_recvmmsg(void); }
|
337 AUE_NULL STD { int linux_recvmmsg(l_int s, \
|
||||||
|
struct l_mmsghdr *msg, l_uint vlen, \
|
||||||
|
l_uint flags, struct l_timespec *timeout); }
|
||||||
338 AUE_NULL STD { int linux_fanotify_init(void); }
|
338 AUE_NULL STD { int linux_fanotify_init(void); }
|
||||||
339 AUE_NULL STD { int linux_fanotify_mark(void); }
|
339 AUE_NULL STD { int linux_fanotify_mark(void); }
|
||||||
; linux 2.6.36:
|
; linux 2.6.36:
|
||||||
@ -580,7 +582,9 @@
|
|||||||
342 AUE_NULL STD { int linux_open_by_handle_at(void); }
|
342 AUE_NULL STD { int linux_open_by_handle_at(void); }
|
||||||
343 AUE_NULL STD { int linux_clock_adjtime(void); }
|
343 AUE_NULL STD { int linux_clock_adjtime(void); }
|
||||||
344 AUE_NULL STD { int linux_syncfs(void); }
|
344 AUE_NULL STD { int linux_syncfs(void); }
|
||||||
345 AUE_NULL STD { int linux_sendmmsg(void); }
|
345 AUE_NULL STD { int linux_sendmmsg(l_int s, \
|
||||||
|
struct l_mmsghdr *msg, l_uint vlen, \
|
||||||
|
l_uint flags); }
|
||||||
346 AUE_NULL STD { int linux_setns(void); }
|
346 AUE_NULL STD { int linux_setns(void); }
|
||||||
347 AUE_NULL STD { int linux_process_vm_readv(void); }
|
347 AUE_NULL STD { int linux_process_vm_readv(void); }
|
||||||
348 AUE_NULL STD { int linux_process_vm_writev(void); }
|
348 AUE_NULL STD { int linux_process_vm_writev(void); }
|
||||||
|
Loading…
Reference in New Issue
Block a user