* configure (AC_CHECK_FUNCS): Add sendmmsg.
* tests/mmsg.c: New file.
* tests/mmsg.expected: New file.
* tests/mmsg.test: New test.
* tests/.gitignore: Add mmsg.
* tests/Makefile.am (CHECK_PROGRAMS): Add mmsg.
(TESTS): Add mmsg.test.
(EXTRA_DIST): Add mmsg.expected.
Signed-off-by: Masatake YAMATO <yamato@redhat.com>
Signed-off-by: Dmitry V. Levin <ldv@altlinux.org>
process_vm_readv
pwritev
sendmsg
+ sendmmsg
sigaction
stpcpy
strerror
inet-accept-connect-send-recv
+mmsg
net-accept-connect
netlink_inet_diag
scm_rights
check_PROGRAMS = \
inet-accept-connect-send-recv \
+ mmsg \
net-accept-connect \
netlink_inet_diag \
scm_rights \
sigaction.test \
stat.test \
statfs.test \
+ mmsg.test \
net.test \
net-fd.test \
net-yy.test \
EXTRA_DIST = init.sh run.sh \
getdents.awk \
+ mmsg.expected \
net-yy-accept.awk \
net-yy-connect.awk \
sigaction.awk \
--- /dev/null
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+#include <sys/socket.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <assert.h>
+
+int
+main(void)
+{
+#if defined(HAVE_SENDMMSG) && defined(HAVE_STRUCT_MMSGHDR)
+ const int R = 0, W = 1;
+ int fd;
+ int sv[2];
+ char one[] = "one";
+ char two[] = "two";
+ char three[] = "three";
+
+ struct iovec iov[] = {
+ {
+ .iov_base = one,
+ .iov_len = sizeof(one) - 1
+ }, {
+ .iov_base = two,
+ .iov_len = sizeof(two) - 1
+ }, {
+ .iov_base = three,
+ .iov_len = sizeof(three) - 1
+ }
+ };
+
+ struct mmsghdr mmh[] = {
+ {
+ .msg_hdr = {
+ .msg_iov = iov + 0,
+ .msg_iovlen = 2,
+ }
+ }, {
+ .msg_hdr = {
+ .msg_iov = iov + 2,
+ .msg_iovlen = 1,
+ }
+ }
+ };
+#define n_mmh (sizeof(mmh)/sizeof(mmh[0]))
+
+ /*
+ * Following open/dup2/close calls make the output of strace
+ * more predictable, so we can just compare the output and
+ * expected output (mmsg.expected) for testing purposes.
+ */
+ while ((fd = open("/dev/null", O_RDWR)) < 3)
+ assert(fd >= 0);
+ (void) close(3);
+
+ assert(socketpair(AF_UNIX, SOCK_DGRAM, 0, sv) == 0);
+
+ assert(dup2(sv[W], W) == W);
+ assert(close(sv[W]) == 0);
+ assert(dup2(sv[R], R) == R);
+ assert(close(sv[R]) == 0);
+
+ assert(sendmmsg(W, mmh, n_mmh, 0) == n_mmh);
+ assert(close(W) == 0);
+
+ assert(recvmmsg(R, mmh, n_mmh, 0, NULL) == n_mmh);
+ assert(close(R) == 0);
+
+ return 0;
+#else
+ return 77;
+#endif
+}
--- /dev/null
+sendmmsg(1, {{{msg_name(0)=NULL, msg_iov(2)=[{"one", 3}, {"two", 3}], msg_controllen=0, msg_flags=0}, 6}, {{msg_name(0)=NULL, msg_iov(1)=[{"three", 5}], msg_controllen=0, msg_flags=0}, 5}}, 2, 0) = 2
+ = 2 buffers in vector 0
+ * 3 bytes in buffer 0
+ | 00000 6f 6e 65 one |
+ * 3 bytes in buffer 1
+ | 00000 74 77 6f two |
+ = 1 buffers in vector 1
+ * 5 bytes in buffer 0
+ | 00000 74 68 72 65 65 three |
+recvmmsg(0, {{{msg_name(0)=NULL, msg_iov(2)=[{"one", 3}, {"two", 3}], msg_controllen=0, msg_flags=0}, 6}, {{msg_name(0)=NULL, msg_iov(1)=[{"three", 5}], msg_controllen=0, msg_flags=0}, 5}}, 2, 0, NULL) = 2 (left NULL)
+ = 2 buffers in vector 0
+ * 3 bytes in buffer 0
+ | 00000 6f 6e 65 one |
+ * 3 bytes in buffer 1
+ | 00000 74 77 6f two |
+ = 1 buffers in vector 1
+ * 5 bytes in buffer 0
+ | 00000 74 68 72 65 65 three |
++++ exited with 0 +++
--- /dev/null
+#!/bin/sh
+
+# Check how iovecs in struct mmsghdr are decoded.
+
+. "${srcdir=.}/init.sh"
+
+mmsg_expected="${srcdir=.}/mmsg.expected"
+
+check_prog diff
+
+cat "$mmsg_expected" > /dev/null ||
+ fail_ "$mmsg_expected is not available"
+
+./mmsg || {
+ if [ $? -eq 77 ]; then
+ framework_skip_ 'sendmmsg/recvmmsg syscalls are not available'
+ else
+ fail_ 'mmsg failed'
+ fi
+}
+
+args="-e trace=recvmmsg,sendmmsg -e read=0 -e write=1 -o $LOG ./mmsg"
+$STRACE $args || {
+ cat $LOG
+ fail_ "$STRACE $args failed"
+}
+
+diff "$mmsg_expected" $LOG ||
+ fail_ "$STRACE $args failed to decode mmsghdr properly"
+
+exit 0