/*
 * Check decoding of msg_name* fields of struct msghdr array argument
 * of sendmmsg and recvmmsg syscalls.
 *
 * Copyright (c) 2016 Dmitry V. Levin <ldv@altlinux.org>
 * Copyright (c) 2016-2018 The strace developers.
 * 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, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 "tests.h"

#include <errno.h>
#include <limits.h>
#include <stddef.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/un.h>

#include "msghdr.h"

#define IOV_MAX1 (IOV_MAX + 1)

#ifndef TEST_NAME
# define TEST_NAME "mmsg_name"
#endif

static void
print_msghdr(const struct msghdr *const msg, const int user_msg_namelen)
{
	const struct sockaddr_un *const un = msg->msg_name;
	const int offsetof_sun_path = offsetof(struct sockaddr_un, sun_path);

	printf("{msg_name=");
	if (!un)
		printf("NULL");
	else if (user_msg_namelen < offsetof_sun_path) {
		printf("%p", un);
	} else {
		printf("{sa_family=AF_UNIX");
		if (user_msg_namelen > offsetof_sun_path) {
			int len = user_msg_namelen < (int) msg->msg_namelen ?
				  user_msg_namelen : (int) msg->msg_namelen;
			len -= offsetof_sun_path;
			if (len > (int) sizeof(un->sun_path))
				len = sizeof(un->sun_path);
			printf(", sun_path=\"%.*s\"", len, un->sun_path);
		}
		printf("}");
	}
	printf(", msg_namelen=");
	if (user_msg_namelen != (int) msg->msg_namelen) {
		printf("%d->", user_msg_namelen);
	}
	printf("%d, msg_iov=[{iov_base=\"%c\", iov_len=1}]"
	       ", msg_iovlen=1, msg_controllen=0, msg_flags=0}",
	       (int) msg->msg_namelen, *(char *) msg->msg_iov[0].iov_base);
}

static void
test_mmsg_name(const int send_fd, const int recv_fd)
{
	struct sockaddr_un *const send_addr =
		tail_alloc(sizeof(*send_addr) * IOV_MAX1);
	char *const send_buf = tail_alloc(sizeof(*send_buf) * IOV_MAX1);
	struct iovec *const send_iov = tail_alloc(sizeof(*send_iov) * IOV_MAX1);
	struct mmsghdr *const send_mh = tail_alloc(sizeof(*send_mh) * IOV_MAX1);

	int i, rc;

	for (i = 0; i < IOV_MAX1; ++i) {
		int sun_len = i + 1 > (int) sizeof(send_addr[i].sun_path)
				    ? (int) sizeof(send_addr[i].sun_path)
				    : i + 1;

		send_addr[i].sun_family = AF_UNIX;
		memset(send_addr[i].sun_path, 'a' + i % 26, sun_len);

		send_buf[i] = '0' + i % 10;

		send_iov[i].iov_base = &send_buf[i];
		send_iov[i].iov_len = sizeof(*send_buf);

		send_mh[i].msg_hdr.msg_iov = &send_iov[i];
		send_mh[i].msg_hdr.msg_iovlen = 1;
		send_mh[i].msg_hdr.msg_name = &send_addr[i];
		send_mh[i].msg_hdr.msg_namelen = i + 1;
		send_mh[i].msg_hdr.msg_control = 0;
		send_mh[i].msg_hdr.msg_controllen = 0;
		send_mh[i].msg_hdr.msg_flags = 0;
	}

	rc = send_mmsg(send_fd, send_mh, IOV_MAX1, MSG_DONTWAIT);
	int saved_errno = errno;

	printf("sendmmsg(%d, [", send_fd);
	for (i = 0; i < IOV_MAX1; ++i) {
		if (i)
			printf(", ");
		if (i >= IOV_MAX
# if !VERBOSE
			|| i >= DEFAULT_STRLEN
# endif
		   ) {
			printf("...");
			break;
		}
		printf("{msg_hdr=");
		print_msghdr(&send_mh[i].msg_hdr, i + 1);
		printf("}");
	}
	errno = saved_errno;
	printf("], %u, MSG_DONTWAIT) = %d %s (%m)\n",
	       IOV_MAX1, rc, errno2name());

	for (i = 0; i < IOV_MAX1; ++i) {
		send_mh[i].msg_hdr.msg_name = 0;
		send_mh[i].msg_hdr.msg_namelen = 0;
	}

	/*
	 * When recvmmsg is called with a valid descriptor
	 * but inaccessible memory, it causes segfaults on some architectures.
	 * As in these cases we test decoding of failed recvmmsg calls,
	 * it's ok to fail recvmmsg with any reason as long as
	 * it doesn't read that inaccessible memory.
	 */
	rc = send_mmsg(-1, &send_mh[IOV_MAX], 2, MSG_DONTWAIT);
	saved_errno = errno;
	printf("sendmmsg(-1, [{msg_hdr=");
	print_msghdr(&send_mh[IOV_MAX].msg_hdr, 0);
	errno = saved_errno;
	printf("}, ... /* %p */], %u, MSG_DONTWAIT) = %d %s (%m)\n",
	       &send_mh[IOV_MAX1], 2, rc, errno2name());

	rc = send_mmsg(send_fd, send_mh, IOV_MAX1, MSG_DONTWAIT);
	if (rc < 0)
		perror_msg_and_skip("sendmmsg");

	printf("sendmmsg(%d, [", send_fd);
	for (i = 0; i < IOV_MAX1; ++i) {
		if (i)
			printf(", ");
		if (i >= IOV_MAX
#if !VERBOSE
			|| i >= DEFAULT_STRLEN
#endif
		   ) {
			printf("...");
			break;
		}
		printf("{msg_hdr=");
		print_msghdr(&send_mh[i].msg_hdr, 0);
		printf("%s}", i < rc ? ", msg_len=1" : "");
	}
	printf("], %u, MSG_DONTWAIT) = %d\n", IOV_MAX1, rc);

	struct sockaddr_un *const recv_addr =
		tail_alloc(sizeof(*recv_addr) * IOV_MAX1);
	char *const recv_buf = tail_alloc(sizeof(*recv_buf) * IOV_MAX1);
	struct iovec *const recv_iov = tail_alloc(sizeof(*recv_iov) * IOV_MAX1);
	struct mmsghdr *const recv_mh = tail_alloc(sizeof(*recv_mh) * IOV_MAX1);

	for (i = 0; i < IOV_MAX1; ++i) {
		recv_iov[i].iov_base = &recv_buf[i];
		recv_iov[i].iov_len = sizeof(*recv_buf);

		recv_mh[i].msg_hdr.msg_name = &recv_addr[i];
		recv_mh[i].msg_hdr.msg_namelen = i;
		recv_mh[i].msg_hdr.msg_iov = &recv_iov[i];
		recv_mh[i].msg_hdr.msg_iovlen = 1;
		recv_mh[i].msg_hdr.msg_control = 0;
		recv_mh[i].msg_hdr.msg_controllen = 0;
		recv_mh[i].msg_hdr.msg_flags = 0;
	}

	rc = recv_mmsg(recv_fd, recv_mh, IOV_MAX1, MSG_DONTWAIT, 0);
	if (rc < 0)
		perror_msg_and_skip("recvmmsg");

	printf("recvmmsg(%d, [", recv_fd);
	for (i = 0; i < rc; ++i) {
		if (i)
			printf(", ");
#if !VERBOSE
		if (i >= DEFAULT_STRLEN) {
			printf("...");
			break;
		}
#endif
		printf("{msg_hdr=");
		print_msghdr(&recv_mh[i].msg_hdr, i);
		printf(", msg_len=1}");
	}
	printf("], %u, MSG_DONTWAIT, NULL) = %d\n", IOV_MAX1, rc);
}

int
main(void)
{
	int fds[2];
	if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds))
		perror_msg_and_skip("socketpair");

	const struct sockaddr_un un = {
		.sun_family = AF_UNIX,
		.sun_path = TEST_NAME "-recvmmsg.test.send.socket"
	};

	(void) unlink(un.sun_path);
	if (bind(fds[1], (const void *) &un, sizeof(un)))
		perror_msg_and_skip("bind");
	(void) unlink(un.sun_path);

	test_mmsg_name(fds[1], fds[0]);

	puts("+++ exited with 0 +++");
	return 0;
}
