128e955d747661fd0f437e70f41e477c9161467dfFabien Siron/*
228e955d747661fd0f437e70f41e477c9161467dfFabien Siron * This file is part of net-yy-netlink strace test.
328e955d747661fd0f437e70f41e477c9161467dfFabien Siron *
428e955d747661fd0f437e70f41e477c9161467dfFabien Siron * Copyright (c) 2014-2016 Dmitry V. Levin <ldv@altlinux.org>
528e955d747661fd0f437e70f41e477c9161467dfFabien Siron * Copyright (c) 2016 Fabien Siron <fabien.siron@epita.fr>
628e955d747661fd0f437e70f41e477c9161467dfFabien Siron * All rights reserved.
728e955d747661fd0f437e70f41e477c9161467dfFabien Siron *
828e955d747661fd0f437e70f41e477c9161467dfFabien Siron * Redistribution and use in source and binary forms, with or without
928e955d747661fd0f437e70f41e477c9161467dfFabien Siron * modification, are permitted provided that the following conditions
1028e955d747661fd0f437e70f41e477c9161467dfFabien Siron * are met:
1128e955d747661fd0f437e70f41e477c9161467dfFabien Siron * 1. Redistributions of source code must retain the above copyright
1228e955d747661fd0f437e70f41e477c9161467dfFabien Siron *    notice, this list of conditions and the following disclaimer.
1328e955d747661fd0f437e70f41e477c9161467dfFabien Siron * 2. Redistributions in binary form must reproduce the above copyright
1428e955d747661fd0f437e70f41e477c9161467dfFabien Siron *    notice, this list of conditions and the following disclaimer in the
1528e955d747661fd0f437e70f41e477c9161467dfFabien Siron *    documentation and/or other materials provided with the distribution.
1628e955d747661fd0f437e70f41e477c9161467dfFabien Siron * 3. The name of the author may not be used to endorse or promote products
1728e955d747661fd0f437e70f41e477c9161467dfFabien Siron *    derived from this software without specific prior written permission.
1828e955d747661fd0f437e70f41e477c9161467dfFabien Siron *
1928e955d747661fd0f437e70f41e477c9161467dfFabien Siron * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
2028e955d747661fd0f437e70f41e477c9161467dfFabien Siron * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
2128e955d747661fd0f437e70f41e477c9161467dfFabien Siron * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2228e955d747661fd0f437e70f41e477c9161467dfFabien Siron * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2328e955d747661fd0f437e70f41e477c9161467dfFabien Siron * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2428e955d747661fd0f437e70f41e477c9161467dfFabien Siron * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2528e955d747661fd0f437e70f41e477c9161467dfFabien Siron * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2628e955d747661fd0f437e70f41e477c9161467dfFabien Siron * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2728e955d747661fd0f437e70f41e477c9161467dfFabien Siron * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2828e955d747661fd0f437e70f41e477c9161467dfFabien Siron * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2928e955d747661fd0f437e70f41e477c9161467dfFabien Siron */
3028e955d747661fd0f437e70f41e477c9161467dfFabien Siron
3128e955d747661fd0f437e70f41e477c9161467dfFabien Siron#include "tests.h"
3228e955d747661fd0f437e70f41e477c9161467dfFabien Siron#include <errno.h>
3328e955d747661fd0f437e70f41e477c9161467dfFabien Siron#include <string.h>
3428e955d747661fd0f437e70f41e477c9161467dfFabien Siron#include <unistd.h>
3528e955d747661fd0f437e70f41e477c9161467dfFabien Siron#include <netinet/in.h>
3628e955d747661fd0f437e70f41e477c9161467dfFabien Siron#include <linux/netlink.h>
3728e955d747661fd0f437e70f41e477c9161467dfFabien Siron#include <linux/sock_diag.h>
3828e955d747661fd0f437e70f41e477c9161467dfFabien Siron#include <linux/netlink_diag.h>
3928e955d747661fd0f437e70f41e477c9161467dfFabien Siron
4028e955d747661fd0f437e70f41e477c9161467dfFabien Siron#if !defined NETLINK_SOCK_DIAG && defined NETLINK_INET_DIAG
4128e955d747661fd0f437e70f41e477c9161467dfFabien Siron# define NETLINK_SOCK_DIAG NETLINK_INET_DIAG
4228e955d747661fd0f437e70f41e477c9161467dfFabien Siron#endif
4328e955d747661fd0f437e70f41e477c9161467dfFabien Siron
4428e955d747661fd0f437e70f41e477c9161467dfFabien Sironstatic void
4528e955d747661fd0f437e70f41e477c9161467dfFabien Sironsend_query(const int fd)
4628e955d747661fd0f437e70f41e477c9161467dfFabien Siron{
4728e955d747661fd0f437e70f41e477c9161467dfFabien Siron	struct sockaddr_nl nladdr = {
4828e955d747661fd0f437e70f41e477c9161467dfFabien Siron		.nl_family = AF_NETLINK
4928e955d747661fd0f437e70f41e477c9161467dfFabien Siron	};
5028e955d747661fd0f437e70f41e477c9161467dfFabien Siron	struct {
5128e955d747661fd0f437e70f41e477c9161467dfFabien Siron		struct nlmsghdr nlh;
5228e955d747661fd0f437e70f41e477c9161467dfFabien Siron		struct netlink_diag_req ndr;
5328e955d747661fd0f437e70f41e477c9161467dfFabien Siron	} req = {
5428e955d747661fd0f437e70f41e477c9161467dfFabien Siron		.nlh = {
5528e955d747661fd0f437e70f41e477c9161467dfFabien Siron			.nlmsg_len = sizeof(req),
5628e955d747661fd0f437e70f41e477c9161467dfFabien Siron			.nlmsg_type = SOCK_DIAG_BY_FAMILY,
5728e955d747661fd0f437e70f41e477c9161467dfFabien Siron			.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST
5828e955d747661fd0f437e70f41e477c9161467dfFabien Siron		},
5928e955d747661fd0f437e70f41e477c9161467dfFabien Siron		.ndr = {
6028e955d747661fd0f437e70f41e477c9161467dfFabien Siron			.sdiag_family = AF_NETLINK,
6128e955d747661fd0f437e70f41e477c9161467dfFabien Siron			.sdiag_protocol = NDIAG_PROTO_ALL,
6228e955d747661fd0f437e70f41e477c9161467dfFabien Siron			.ndiag_show = NDIAG_SHOW_MEMINFO
6328e955d747661fd0f437e70f41e477c9161467dfFabien Siron		}
6428e955d747661fd0f437e70f41e477c9161467dfFabien Siron	};
6528e955d747661fd0f437e70f41e477c9161467dfFabien Siron	struct iovec iov = {
6628e955d747661fd0f437e70f41e477c9161467dfFabien Siron		.iov_base = &req,
6728e955d747661fd0f437e70f41e477c9161467dfFabien Siron		.iov_len = sizeof(req)
6828e955d747661fd0f437e70f41e477c9161467dfFabien Siron	};
6928e955d747661fd0f437e70f41e477c9161467dfFabien Siron	struct msghdr msg = {
7028e955d747661fd0f437e70f41e477c9161467dfFabien Siron		.msg_name = (void *) &nladdr,
7128e955d747661fd0f437e70f41e477c9161467dfFabien Siron		.msg_namelen = sizeof(nladdr),
7228e955d747661fd0f437e70f41e477c9161467dfFabien Siron		.msg_iov = &iov,
7328e955d747661fd0f437e70f41e477c9161467dfFabien Siron		.msg_iovlen = 1
7428e955d747661fd0f437e70f41e477c9161467dfFabien Siron	};
7528e955d747661fd0f437e70f41e477c9161467dfFabien Siron
7628e955d747661fd0f437e70f41e477c9161467dfFabien Siron	if (sendmsg(fd, &msg, 0) <= 0)
7728e955d747661fd0f437e70f41e477c9161467dfFabien Siron		perror_msg_and_skip("sendmsg");
7828e955d747661fd0f437e70f41e477c9161467dfFabien Siron}
7928e955d747661fd0f437e70f41e477c9161467dfFabien Siron
8028e955d747661fd0f437e70f41e477c9161467dfFabien Sironstatic void
8128e955d747661fd0f437e70f41e477c9161467dfFabien Sironcheck_responses(const int fd)
8228e955d747661fd0f437e70f41e477c9161467dfFabien Siron{
837b6979701b5ddda47ba53f82381a5f412708b0adDmitry V. Levin	static union {
847b6979701b5ddda47ba53f82381a5f412708b0adDmitry V. Levin		struct nlmsghdr hdr;
857b6979701b5ddda47ba53f82381a5f412708b0adDmitry V. Levin		long buf[8192 / sizeof(long)];
867b6979701b5ddda47ba53f82381a5f412708b0adDmitry V. Levin	} hdr_buf;
877b6979701b5ddda47ba53f82381a5f412708b0adDmitry V. Levin
8828e955d747661fd0f437e70f41e477c9161467dfFabien Siron	struct sockaddr_nl nladdr = {
8928e955d747661fd0f437e70f41e477c9161467dfFabien Siron		.nl_family = AF_NETLINK
9028e955d747661fd0f437e70f41e477c9161467dfFabien Siron	};
9128e955d747661fd0f437e70f41e477c9161467dfFabien Siron	struct iovec iov = {
927b6979701b5ddda47ba53f82381a5f412708b0adDmitry V. Levin		.iov_base = hdr_buf.buf,
937b6979701b5ddda47ba53f82381a5f412708b0adDmitry V. Levin		.iov_len = sizeof(hdr_buf.buf)
9428e955d747661fd0f437e70f41e477c9161467dfFabien Siron	};
9528e955d747661fd0f437e70f41e477c9161467dfFabien Siron	struct msghdr msg = {
9628e955d747661fd0f437e70f41e477c9161467dfFabien Siron		.msg_name = (void *) &nladdr,
9728e955d747661fd0f437e70f41e477c9161467dfFabien Siron		.msg_namelen = sizeof(nladdr),
9828e955d747661fd0f437e70f41e477c9161467dfFabien Siron		.msg_iov = &iov,
9928e955d747661fd0f437e70f41e477c9161467dfFabien Siron		.msg_iovlen = 1
10028e955d747661fd0f437e70f41e477c9161467dfFabien Siron	};
10128e955d747661fd0f437e70f41e477c9161467dfFabien Siron
10228e955d747661fd0f437e70f41e477c9161467dfFabien Siron	ssize_t ret = recvmsg(fd, &msg, 0);
10328e955d747661fd0f437e70f41e477c9161467dfFabien Siron	if (ret <= 0)
10428e955d747661fd0f437e70f41e477c9161467dfFabien Siron		perror_msg_and_skip("recvmsg");
10528e955d747661fd0f437e70f41e477c9161467dfFabien Siron
1067b6979701b5ddda47ba53f82381a5f412708b0adDmitry V. Levin	struct nlmsghdr *h = &hdr_buf.hdr;
10728e955d747661fd0f437e70f41e477c9161467dfFabien Siron	if (!NLMSG_OK(h, ret))
10828e955d747661fd0f437e70f41e477c9161467dfFabien Siron		error_msg_and_skip("!NLMSG_OK");
10928e955d747661fd0f437e70f41e477c9161467dfFabien Siron	if (h->nlmsg_type == NLMSG_ERROR) {
11028e955d747661fd0f437e70f41e477c9161467dfFabien Siron		const struct nlmsgerr *err = NLMSG_DATA(h);
11128e955d747661fd0f437e70f41e477c9161467dfFabien Siron		if (h->nlmsg_len < NLMSG_LENGTH(sizeof(*err)))
11228e955d747661fd0f437e70f41e477c9161467dfFabien Siron			error_msg_and_skip("NLMSG_ERROR");
11328e955d747661fd0f437e70f41e477c9161467dfFabien Siron		errno = -err->error;
11428e955d747661fd0f437e70f41e477c9161467dfFabien Siron		perror_msg_and_skip("NLMSG_ERROR");
11528e955d747661fd0f437e70f41e477c9161467dfFabien Siron	}
11628e955d747661fd0f437e70f41e477c9161467dfFabien Siron	if (h->nlmsg_type != SOCK_DIAG_BY_FAMILY)
11728e955d747661fd0f437e70f41e477c9161467dfFabien Siron		error_msg_and_skip("unexpected nlmsg_type %u",
11828e955d747661fd0f437e70f41e477c9161467dfFabien Siron				   (unsigned) h->nlmsg_type);
11928e955d747661fd0f437e70f41e477c9161467dfFabien Siron
12028e955d747661fd0f437e70f41e477c9161467dfFabien Siron	const struct netlink_diag_msg *diag = NLMSG_DATA(h);
12128e955d747661fd0f437e70f41e477c9161467dfFabien Siron	if (h->nlmsg_len < NLMSG_LENGTH(sizeof(*diag)))
12228e955d747661fd0f437e70f41e477c9161467dfFabien Siron		error_msg_and_skip("short response");
12328e955d747661fd0f437e70f41e477c9161467dfFabien Siron}
12428e955d747661fd0f437e70f41e477c9161467dfFabien Siron
12528e955d747661fd0f437e70f41e477c9161467dfFabien Sironint main(void)
12628e955d747661fd0f437e70f41e477c9161467dfFabien Siron{
12728e955d747661fd0f437e70f41e477c9161467dfFabien Siron	struct sockaddr_nl addr;
12828e955d747661fd0f437e70f41e477c9161467dfFabien Siron	socklen_t len = sizeof(addr);
12928e955d747661fd0f437e70f41e477c9161467dfFabien Siron
13028e955d747661fd0f437e70f41e477c9161467dfFabien Siron	memset(&addr, 0, sizeof(addr));
13128e955d747661fd0f437e70f41e477c9161467dfFabien Siron	addr.nl_family = AF_NETLINK;
13228e955d747661fd0f437e70f41e477c9161467dfFabien Siron
13328e955d747661fd0f437e70f41e477c9161467dfFabien Siron	close(0);
13428e955d747661fd0f437e70f41e477c9161467dfFabien Siron	close(1);
13528e955d747661fd0f437e70f41e477c9161467dfFabien Siron
13628e955d747661fd0f437e70f41e477c9161467dfFabien Siron	if (socket(AF_NETLINK, SOCK_RAW, NETLINK_SOCK_DIAG))
13728e955d747661fd0f437e70f41e477c9161467dfFabien Siron		perror_msg_and_skip("socket AF_NETLINK");
13828e955d747661fd0f437e70f41e477c9161467dfFabien Siron	if (bind(0, (struct sockaddr *) &addr, len))
13928e955d747661fd0f437e70f41e477c9161467dfFabien Siron		perror_msg_and_skip("bind");
14028e955d747661fd0f437e70f41e477c9161467dfFabien Siron
14128e955d747661fd0f437e70f41e477c9161467dfFabien Siron	if (socket(AF_NETLINK, SOCK_RAW, NETLINK_SOCK_DIAG) != 1)
14228e955d747661fd0f437e70f41e477c9161467dfFabien Siron		perror_msg_and_skip("socket AF_NETLINK");
14328e955d747661fd0f437e70f41e477c9161467dfFabien Siron
14428e955d747661fd0f437e70f41e477c9161467dfFabien Siron	send_query(1);
14528e955d747661fd0f437e70f41e477c9161467dfFabien Siron	check_responses(1);
14628e955d747661fd0f437e70f41e477c9161467dfFabien Siron	return 0;
14728e955d747661fd0f437e70f41e477c9161467dfFabien Siron}
148