Does FreeBSD have sendmmsg or recvmmsg system calls?

Boris Astardzhiev boris.astardzhiev at gmail.com
Thu Jan 7 10:28:35 UTC 2016


> Please remove the autogenerated parts of the patch and resend.


On Thu, Jan 7, 2016 at 12:13 PM, Konstantin Belousov <kostikbel at gmail.com>
wrote:

> On Thu, Jan 07, 2016 at 11:51:24AM +0200, Boris Astardzhiev wrote:
> > Hello,
> >
> > Here's my implementation of the two system calls. The patch is against
> HEAD
> > from a couple of days:
> Please remove the autogenerated parts of the patch and resend.
>
-------------- next part --------------
diff --git a/lib/libc/include/libc_private.h b/lib/libc/include/libc_private.h
index 5caf9a3..7e2a902 100644
--- a/lib/libc/include/libc_private.h
+++ b/lib/libc/include/libc_private.h
@@ -200,8 +200,10 @@ enum {
 	INTERPOS_pselect,
 	INTERPOS_recvfrom,
 	INTERPOS_recvmsg,
+	INTERPOS_recvmmsg,
 	INTERPOS_select,
 	INTERPOS_sendmsg,
+	INTERPOS_sendmmsg,
 	INTERPOS_sendto,
 	INTERPOS_setcontext,
 	INTERPOS_sigaction,
@@ -289,6 +291,7 @@ struct fd_set;
 struct iovec;
 struct kevent;
 struct msghdr;
+struct mmsghdr;
 struct pollfd;
 struct rusage;
 struct sigaction;
@@ -334,9 +337,11 @@ __ssize_t	__sys_recv(int, void *, __size_t, int);
 __ssize_t	__sys_recvfrom(int, void *, __size_t, int, struct sockaddr *,
 		    __socklen_t *);
 __ssize_t	__sys_recvmsg(int, struct msghdr *, int);
+__ssize_t	__sys_recvmmsg(int, struct mmsghdr *, unsigned int, int);
 int		__sys_select(int, struct fd_set *, struct fd_set *,
 		    struct fd_set *, struct timeval *);
 __ssize_t	__sys_sendmsg(int, const struct msghdr *, int);
+__ssize_t	__sys_sendmmsg(int, const struct mmsghdr *, unsigned int, int);
 __ssize_t	__sys_sendto(int, const void *, __size_t, int,
 		    const struct sockaddr *, __socklen_t);
 int		__sys_setcontext(const struct __ucontext *);
diff --git a/lib/libc/include/namespace.h b/lib/libc/include/namespace.h
index 739d7b1..c95829e 100644
--- a/lib/libc/include/namespace.h
+++ b/lib/libc/include/namespace.h
@@ -208,6 +208,7 @@
 #define		readv				_readv
 #define		recvfrom			_recvfrom
 #define		recvmsg				_recvmsg
+#define		recvmmsg			_recvmmsg
 #define		select				_select
 #define		sem_close			_sem_close
 #define		sem_destroy			_sem_destroy
@@ -220,6 +221,7 @@
 #define		sem_unlink			_sem_unlink
 #define		sem_wait			_sem_wait
 #define		sendmsg				_sendmsg
+#define		sendmmsg			_sendmmsg
 #define		sendto				_sendto
 #define		setsockopt			_setsockopt
 /*#define		sigaction			_sigaction*/
diff --git a/lib/libc/include/un-namespace.h b/lib/libc/include/un-namespace.h
index f31fa7a..0233348 100644
--- a/lib/libc/include/un-namespace.h
+++ b/lib/libc/include/un-namespace.h
@@ -189,6 +189,7 @@
 #undef		readv
 #undef		recvfrom
 #undef		recvmsg
+#undef		recvmmsg
 #undef		select
 #undef		sem_close
 #undef		sem_destroy
@@ -201,6 +202,7 @@
 #undef		sem_unlink
 #undef		sem_wait
 #undef		sendmsg
+#undef		sendmmsg
 #undef		sendto
 #undef		setsockopt
 #undef		sigaction
diff --git a/lib/libc/sys/Makefile.inc b/lib/libc/sys/Makefile.inc
index e4fe1b2..1c09fce 100644
--- a/lib/libc/sys/Makefile.inc
+++ b/lib/libc/sys/Makefile.inc
@@ -49,8 +49,10 @@ INTERPOSED = \
 	readv \
 	recvfrom \
 	recvmsg \
+	recvmmsg \
 	select \
 	sendmsg \
+	sendmmsg \
 	sendto \
 	setcontext \
 	sigprocmask \
diff --git a/lib/libc/sys/Symbol.map b/lib/libc/sys/Symbol.map
index 7b3257c..6cc3c6e 100644
--- a/lib/libc/sys/Symbol.map
+++ b/lib/libc/sys/Symbol.map
@@ -220,6 +220,7 @@ FBSD_1.0 {
 	reboot;
 	recvfrom;
 	recvmsg;
+	recvmmsg;
 	rename;
 	revoke;
 	rfork;
@@ -240,6 +241,7 @@ FBSD_1.0 {
 	semsys;
 	sendfile;
 	sendmsg;
+	sendmmsg;
 	sendto;
 	setaudit;
 	setaudit_addr;
@@ -851,6 +853,8 @@ FBSDprivate_1.0 {
 	__sys_recvfrom;
 	_recvmsg;
 	__sys_recvmsg;
+	_recvmmsg;
+	__sys_recvmmsg;
 	_rename;
 	__sys_rename;
 	_revoke;
@@ -891,6 +895,8 @@ FBSDprivate_1.0 {
 	__sys_sendfile;
 	_sendmsg;
 	__sys_sendmsg;
+	_sendmmsg;
+	__sys_sendmmsg;
 	_sendto;
 	__sys_sendto;
 	_setaudit;
diff --git a/lib/libc/sys/interposing_table.c b/lib/libc/sys/interposing_table.c
index 08dfbb1..c866a75 100644
--- a/lib/libc/sys/interposing_table.c
+++ b/lib/libc/sys/interposing_table.c
@@ -56,8 +56,10 @@ interpos_func_t __libc_interposing[INTERPOS_MAX] = {
 	SLOT(readv, __sys_readv),
 	SLOT(recvfrom, __sys_recvfrom),
 	SLOT(recvmsg, __sys_recvmsg),
+	SLOT(recvmmsg, __sys_recvmmsg),
 	SLOT(select, __sys_select),
 	SLOT(sendmsg, __sys_sendmsg),
+	SLOT(sendmmsg, __sys_sendmmsg),
 	SLOT(sendto, __sys_sendto),
 	SLOT(setcontext, __sys_setcontext),
 	SLOT(sigaction, __sys_sigaction),
diff --git a/lib/libc/sys/recvmmsg.c b/lib/libc/sys/recvmmsg.c
new file mode 100644
index 0000000..bbb0588
--- /dev/null
+++ b/lib/libc/sys/recvmmsg.c
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2016 Boris Astardzhiev, Smartcom-Bulgaria AD
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice(s), this list of conditions and the following disclaimer as
+ *    the first lines of this file unmodified other than the possible
+ *    addition of one or more copyright notices.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice(s), this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/syscall.h>
+#include <sys/socket.h>
+#include "libc_private.h"
+
+__weak_reference(__sys_recvmmsg, __recvmmsg);
+
+#pragma weak recvmmsg
+ssize_t
+recvmmsg(int s, struct mmsghdr *msgvec, unsigned int vlen, int flags)
+{
+
+	return (((int (*)(int, struct mmsghdr *, int, int))
+	    __libc_interposing[INTERPOS_recvmmsg])(s, msgvec, vlen, flags));
+}
diff --git a/lib/libc/sys/sendmmsg.c b/lib/libc/sys/sendmmsg.c
new file mode 100644
index 0000000..398f9ca
--- /dev/null
+++ b/lib/libc/sys/sendmmsg.c
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2016 Boris Astardzhiev, Smartcom-Bulgaria AD
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice(s), this list of conditions and the following disclaimer as
+ *    the first lines of this file unmodified other than the possible
+ *    addition of one or more copyright notices.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice(s), this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/syscall.h>
+#include <sys/socket.h>
+#include "libc_private.h"
+
+__weak_reference(__sys_sendmmsg, __sendmmsg);
+
+#pragma weak sendmmsg
+ssize_t
+sendmmsg(int s, const struct mmsghdr *msgvec, unsigned int vlen, int flags)
+{
+
+	return (((int (*)(int, const struct mmsghdr *, int, int))
+	    __libc_interposing[INTERPOS_sendmmsg])(s, msgvec, vlen, flags));
+}
diff --git a/sys/bsm/audit_kevents.h b/sys/bsm/audit_kevents.h
index 3c16c73..2fc887a 100644
--- a/sys/bsm/audit_kevents.h
+++ b/sys/bsm/audit_kevents.h
@@ -611,6 +611,8 @@
 #define	AUE_BINDAT		43207	/* TrustedBSD. */
 #define	AUE_CONNECTAT		43208	/* TrustedBSD. */
 #define	AUE_CHFLAGSAT		43209	/* FreeBSD-specific. */
+#define	AUE_SENDMMSG		43210
+#define	AUE_RECVMMSG		43211
 
 /*
  * Darwin BSM uses a number of AUE_O_* definitions, which are aliased to the
diff --git a/sys/kern/syscalls.master b/sys/kern/syscalls.master
index 6e6fb38..6190895 100644
--- a/sys/kern/syscalls.master
+++ b/sys/kern/syscalls.master
@@ -994,6 +994,10 @@
 549	AUE_NULL	STD	{ int numa_setaffinity(cpuwhich_t which, \
 				    id_t id, \
 				    const struct vm_domain_policy_entry *policy); }
+550	AUE_SENDMMSG	STD	{ int sendmmsg(int s, struct mmsghdr *msgvec,\
+				    unsigned int vlen, int flags); }
+551	AUE_RECVMMSG	STD	{ int recvmmsg(int s, struct mmsghdr *msgvec,\
+				    unsigned int vlen, int flags); }
 
 ; Please copy any additions and changes to the following compatability tables:
 ; sys/compat/freebsd32/syscalls.master
diff --git a/sys/kern/uipc_syscalls.c b/sys/kern/uipc_syscalls.c
index c33a2cf..7354b4f 100644
--- a/sys/kern/uipc_syscalls.c
+++ b/sys/kern/uipc_syscalls.c
@@ -1038,6 +1038,82 @@ sys_sendmsg(td, uap)
 }
 
 int
+sys_sendmmsg(td, uap)
+	struct thread *td;
+	struct sendmmsg_args /* {
+		int	s;
+		struct mmsghdr	*msgvec;
+		unsigned int	vlen;
+		int	flags;
+	} */ *uap;
+{
+	struct mmsghdr *vec, *mmp;
+	struct msghdr *mp, msg;
+	struct iovec *iov;
+	unsigned int vlen, len;
+	int i, sent = 0, error;
+	struct socket *so = NULL;
+	struct file *fp;
+	cap_rights_t rights;
+
+	if (fget(td, uap->s, cap_rights_init(&rights, CAP_SEND), &fp) != 0)
+		return (EBADF);
+
+	so = fp->f_data;
+
+	vlen = uap->vlen;
+	if (vlen > UIO_MAXIOV)
+		vlen = UIO_MAXIOV;
+
+	len = vlen * sizeof(*uap->msgvec);
+	vec = malloc(len, M_TEMP, M_WAITOK);
+
+	error = copyin(uap->msgvec, vec, len);
+	if (error != 0)
+		goto out;
+
+	for (i = 0; i < vlen; i++) {
+		mmp = &vec[i];
+		mp = &mmp->msg_hdr;
+		msg = *mp;
+
+		error = copyiniov(msg.msg_iov, msg.msg_iovlen, &iov, EMSGSIZE);
+		if (error != 0)
+			goto out;
+
+		msg.msg_iov = iov;
+#ifdef COMPAT_OLDSOCK
+		msg.msg_flags = 0;
+#endif
+		error = sendit(td, uap->s, &msg, uap->flags);
+		free(iov, M_IOV);
+		if (error != 0)
+			goto out;
+
+		error = copyout(&td->td_retval[0], &uap->msgvec[i].msg_len,
+		    sizeof(td->td_retval[0]));
+		if (error != 0)
+			goto out;
+
+		sent++;
+	}
+
+	td->td_retval[0] = sent;
+
+out:
+	if (error != 0 && sent != 0 && sent != vlen) {
+		so->so_error = error;
+		error = 0;
+		td->td_retval[0] = sent;
+	}
+
+	fdrop(fp, td);
+
+	free(vec, M_TEMP);
+	return (error);
+}
+
+int
 kern_recvit(td, s, mp, fromseg, controlp)
 	struct thread *td;
 	int s;
@@ -1363,6 +1439,91 @@ sys_recvmsg(td, uap)
 	return (error);
 }
 
+int
+sys_recvmmsg(td, uap)
+	struct thread *td;
+	struct recvmmsg_args /* {
+		int	s;
+		struct mmsghdr	*msgvec;
+		unsigned int	vlen;
+		int	flags;
+	} */ *uap;
+{
+	struct mmsghdr *vec, *mmp;
+	struct msghdr *mp, msg;
+	struct iovec *uiov, *iov;
+	unsigned int vlen, len;
+	int i, rcvd = 0, error;
+	struct socket *so = NULL;
+	struct file *fp;
+	cap_rights_t rights;
+
+	if (fget(td, uap->s, cap_rights_init(&rights, CAP_RECV), &fp) != 0)
+		return (EBADF);
+
+	so = fp->f_data;
+
+	vlen = uap->vlen;
+	if (vlen > UIO_MAXIOV)
+		vlen = UIO_MAXIOV;
+
+	len = vlen * sizeof(*uap->msgvec);
+	vec = malloc(len, M_TEMP, M_WAITOK);
+
+	error = copyin(uap->msgvec, vec, len);
+	if (error != 0)
+		goto out;
+
+	for (i = 0; i < vlen; i++) {
+		mmp = &vec[i];
+		mp = &mmp->msg_hdr;
+		msg = *mp;
+
+		error = copyiniov(msg.msg_iov, msg.msg_iovlen, &iov, EMSGSIZE);
+		if (error != 0)
+			goto out;
+
+		msg.msg_flags = uap->flags;
+#ifdef COMPAT_OLDSOCK
+		msg.msg_flags &= ~MSG_COMPAT;
+#endif
+		uiov = msg.msg_iov;
+		msg.msg_iov = iov;
+
+		error = recvit(td, uap->s, &msg, NULL);
+		if (error == 0) {
+			msg.msg_iov = uiov;
+			error = copyout(&msg, &uap->msgvec[i].msg_hdr, sizeof(msg));
+			if (error != 0) {
+				free(iov, M_IOV);
+				goto out;
+			}
+			error = copyout(&td->td_retval[0], &uap->msgvec[i].msg_len,
+			    sizeof(td->td_retval[0]));
+			if (error != 0) {
+				free(iov, M_IOV);
+				goto out;
+			}
+		}
+		free(iov, M_IOV);
+		rcvd++;
+	}
+
+	td->td_retval[0] = rcvd;
+
+out:
+	if (error != 0 && rcvd != 0 && rcvd != vlen) {
+		so->so_error = error;
+		error = 0;
+		td->td_retval[0] = rcvd;
+	}
+
+	fdrop(fp, td);
+
+	free(vec, M_TEMP);
+	return (error);
+}
+
 /* ARGSUSED */
 int
 sys_shutdown(td, uap)
diff --git a/sys/sys/socket.h b/sys/sys/socket.h
index 18e2de1..d352cd2 100644
--- a/sys/sys/socket.h
+++ b/sys/sys/socket.h
@@ -414,6 +414,11 @@ struct msghdr {
 	int		 msg_flags;		/* flags on received message */
 };
 
+struct mmsghdr {
+	struct msghdr	msg_hdr;		/* message header */
+	unsigned int	msg_len;		/* message length  */
+};
+
 #define	MSG_OOB		0x1		/* process out-of-band data */
 #define	MSG_PEEK	0x2		/* peek at incoming message */
 #define	MSG_DONTROUTE	0x4		/* send without using routing tables */
@@ -615,10 +620,12 @@ int	listen(int, int);
 ssize_t	recv(int, void *, size_t, int);
 ssize_t	recvfrom(int, void *, size_t, int, struct sockaddr * __restrict, socklen_t * __restrict);
 ssize_t	recvmsg(int, struct msghdr *, int);
+ssize_t	recvmmsg(int, struct mmsghdr *, unsigned int, int);
 ssize_t	send(int, const void *, size_t, int);
 ssize_t	sendto(int, const void *,
 	    size_t, int, const struct sockaddr *, socklen_t);
 ssize_t	sendmsg(int, const struct msghdr *, int);
+ssize_t	sendmmsg(int, const struct mmsghdr *, unsigned int, int);
 #if __BSD_VISIBLE
 int	sendfile(int, int, off_t, size_t, struct sf_hdtr *, off_t *, int);
 int	setfib(int);


More information about the freebsd-net mailing list