static void
init_br_port_msg(struct nlmsghdr *const nlh, const unsigned int msg_len)
{
	unsigned int len = msg_len;

	SET_STRUCT(struct nlmsghdr, nlh,
		.nlmsg_len = len,
		.nlmsg_type = RTM_GETMDB,
		.nlmsg_flags = NLM_F_DUMP
	);

	struct br_port_msg *const msg = NLMSG_DATA(nlh);
	SET_STRUCT(struct br_port_msg, msg,
		.family = AF_UNIX,
		.ifindex = ifindex_lo()
	);

	struct nlattr *nla = NLMSG_ATTR(nlh, sizeof(*msg));
	len -= NLMSG_SPACE(hdrlen);
	SET_STRUCT(struct nlattr, nla,
		.nla_len = len,
		.nla_type = MDBA_MDB
	);

	nla = nla + 1;
	len -= NLA_HDRLEN;
	SET_STRUCT(struct nlattr, nla,
		.nla_len = len,
		.nla_type = MDBA_MDB_ENTRY
	);
}
static void
test_inet_diag_bc_dev_cond(const int fd)
{
	static const struct inet_diag_bc_op op = {
		.code = INET_DIAG_BC_DEV_COND,
	};
	const uint32_t ifindex = ifindex_lo();
	char buf[sizeof(op) + sizeof(ifindex)];
	memcpy(buf, &op, sizeof(op));
	memcpy(buf + sizeof(op), pattern, sizeof(ifindex));

	TEST_NLATTR(fd, nlh0, hdrlen,
		    init_inet_diag_req_v2, print_inet_diag_req_v2,
		    INET_DIAG_REQ_BYTECODE,
		    sizeof(buf) - 1, buf, sizeof(buf) - 1,
		    print_inet_diag_bc_op("INET_DIAG_BC_DEV_COND");
		    print_quoted_hex(pattern, sizeof(ifindex) - 1);
		    printf("}"));

	TEST_NLATTR(fd, nlh0, hdrlen,
		    init_inet_diag_req_v2, print_inet_diag_req_v2,
		    INET_DIAG_REQ_BYTECODE,
		    sizeof(buf), buf, sizeof(buf) - 1,
		    print_inet_diag_bc_op("INET_DIAG_BC_DEV_COND");
		    printf("%p}", RTA_DATA(TEST_NLATTR_nla) + sizeof(op)));

	memcpy(buf + sizeof(op), &ifindex, sizeof(ifindex));
	TEST_NLATTR(fd, nlh0, hdrlen,
		    init_inet_diag_req_v2, print_inet_diag_req_v2,
		    INET_DIAG_REQ_BYTECODE,
		    sizeof(buf), buf, sizeof(buf),
		    print_inet_diag_bc_op("INET_DIAG_BC_DEV_COND");
		    printf(IFINDEX_LO_STR "}"));
}
static void
init_BPF_PROG_LOAD_attr4(struct bpf_attr_check *check)
{
	struct BPF_PROG_LOAD_struct *attr = &check->data.BPF_PROG_LOAD_data;

	attr->insns = (uintptr_t) insns;
	attr->license = (uintptr_t) license;
	attr->log_buf = (uintptr_t) get_log_buf();
	attr->prog_ifindex = ifindex_lo();

	strncpy(log_buf, "log test", 9);
}
static void
init_ifinfomsg(struct nlmsghdr *const nlh, const unsigned int msg_len)
{
	SET_STRUCT(struct nlmsghdr, nlh,
		.nlmsg_len = msg_len,
		.nlmsg_type = RTM_GETLINK,
		.nlmsg_flags = NLM_F_DUMP
	);

	struct ifinfomsg *const msg = NLMSG_DATA(nlh);
	SET_STRUCT(struct ifinfomsg, msg,
		.ifi_family = AF_UNIX,
		.ifi_type = ARPHRD_LOOPBACK,
		.ifi_index = ifindex_lo(),
		.ifi_flags = IFF_UP,
	);
}
static void
init_ndmsg(struct nlmsghdr *const nlh, const unsigned int msg_len)
{
	SET_STRUCT(struct nlmsghdr, nlh,
		.nlmsg_len = msg_len,
		.nlmsg_type = RTM_GETNEIGH,
		.nlmsg_flags = NLM_F_DUMP
	);

	struct ndmsg *const msg = NLMSG_DATA(nlh);
	SET_STRUCT(struct ndmsg, msg,
		.ndm_family = AF_UNIX,
		.ndm_ifindex = ifindex_lo(),
		.ndm_state = NUD_PERMANENT,
		.ndm_flags = NTF_PROXY,
		.ndm_type = RTN_UNSPEC
	);
}
int
main(void)
{
	skip_if_unavailable("/proc/self/fd/");

	const uint32_t ifindex = ifindex_lo();
	const uint8_t type = MDB_RTR_TYPE_DISABLED;
	static const struct nlattr nla = {
		.nla_len = NLA_HDRLEN + sizeof(type),
		.nla_type = MDBA_ROUTER_PATTR_TYPE
	};
	char buf[NLMSG_ALIGN(ifindex) + NLA_HDRLEN + sizeof(type)];

	const int fd = create_nl_socket(NETLINK_ROUTE);

	void *nlh0 = midtail_alloc(NLMSG_SPACE(hdrlen),
				   NLA_HDRLEN + sizeof(buf));

	static char pattern[4096];
	fill_memory_ex(pattern, sizeof(pattern), 'a', 'z' - 'a' + 1);

	TEST_NESTED_NLATTR_OBJECT(fd, nlh0, hdrlen,
				  init_br_port_msg, print_br_port_msg,
				  MDBA_ROUTER_PORT, pattern, ifindex,
				  printf(IFINDEX_LO_STR));

	memcpy(buf, &ifindex, sizeof(ifindex));
	memcpy(buf + NLMSG_ALIGN(ifindex), &nla, sizeof(nla));
	memcpy(buf + NLMSG_ALIGN(ifindex) + NLA_HDRLEN, &type, sizeof(type));
	TEST_NLATTR(fd, nlh0 - NLA_HDRLEN, hdrlen + NLA_HDRLEN,
		    init_br_port_msg, print_br_port_msg,
		    MDBA_ROUTER_PORT, sizeof(buf), buf, sizeof(buf),
		    printf(IFINDEX_LO_STR
			   ", {{nla_len=%u, nla_type=MDBA_ROUTER_PATTR_TYPE}"
			   ", MDB_RTR_TYPE_DISABLED}}",
			   nla.nla_len));

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

#else

SKIP_MAIN_UNDEFINED("HAVE_STRUCT_BR_PORT_MSG")
static void
init_ifinfomsg(struct nlmsghdr *const nlh, const unsigned int msg_len)
{
	SET_STRUCT(struct nlmsghdr, nlh,
		.nlmsg_len = msg_len,
		.nlmsg_type = RTM_GETLINK,
		.nlmsg_flags = NLM_F_DUMP
	);

	struct ifinfomsg *const msg = NLMSG_DATA(nlh);
	SET_STRUCT(struct ifinfomsg, msg,
		.ifi_family = AF_UNIX,
		.ifi_type = ARPHRD_LOOPBACK,
		.ifi_index = ifindex_lo(),
		.ifi_flags = IFF_UP,
	);

	struct nlattr *const nla = NLMSG_ATTR(nlh, sizeof(*msg));
	SET_STRUCT(struct nlattr, nla,
		.nla_len = msg_len - NLMSG_SPACE(hdrlen),
		.nla_type = IFLA_PORT_SELF
	);
}
static void
init_BPF_MAP_CREATE_attr7(struct bpf_attr_check *check)
{
	struct BPF_MAP_CREATE_struct *attr = &check->data.BPF_MAP_CREATE_data;
	attr->map_ifindex = ifindex_lo();
}
Exemple #9
0
int
main(void)
{
	TAIL_ALLOC_OBJECT_CONST_PTR(struct ip_mreq, m4);
	TAIL_ALLOC_OBJECT_CONST_PTR(struct ipv6_mreq, m6);
	unsigned int i;
	int rc;

	inet_pton(AF_INET, multi4addr, &m4->imr_multiaddr);
	inet_pton(AF_INET, interface, &m4->imr_interface);
	inet_pton(AF_INET6, multi6addr, &m6->ipv6mr_multiaddr);

	m6->ipv6mr_interface = ifindex_lo();
	if (!m6->ipv6mr_interface)
		perror_msg_and_skip("lo");

	(void) close(0);
	if (socket(AF_INET, SOCK_DGRAM, 0))
		perror_msg_and_skip("socket");

	struct {
		const int level;
		const char *const str_level;
		const int name;
		const char *str_name;
		const void *const val;
		unsigned int size;
		const char *const addr;
	} opts[] = {
		{
			ARG_STR(SOL_IP), ARG_STR(IP_ADD_MEMBERSHIP),
			m4, sizeof(*m4),
			"{imr_multiaddr=inet_addr(\"" multi4addr
			"\"), imr_interface=inet_addr(\"" interface "\")}"
		},
		{
			ARG_STR(SOL_IP), ARG_STR(IP_DROP_MEMBERSHIP),
			m4, sizeof(*m4),
			"{imr_multiaddr=inet_addr(\"" multi4addr
			"\"), imr_interface=inet_addr(\"" interface "\")}"
		},
		{
			ARG_STR(SOL_IPV6), ARG_STR(IPV6_ADD_MEMBERSHIP),
			m6, sizeof(*m6),
			"{inet_pton(AF_INET6, \"" multi6addr
			"\", &ipv6mr_multiaddr)"
			", ipv6mr_interface=" IFINDEX_LO_STR "}"
		},
		{
			ARG_STR(SOL_IPV6), ARG_STR(IPV6_DROP_MEMBERSHIP),
			m6, sizeof(*m6),
			"{inet_pton(AF_INET6, \"" multi6addr
			"\", &ipv6mr_multiaddr)"
			", ipv6mr_interface=" IFINDEX_LO_STR "}"
		},
		{
			ARG_STR(SOL_IPV6), ARG_STR(IPV6_JOIN_ANYCAST),
			m6, sizeof(*m6),
			"{inet_pton(AF_INET6, \"" multi6addr
			"\", &ipv6mr_multiaddr)"
			", ipv6mr_interface=" IFINDEX_LO_STR "}"
		},
		{
			ARG_STR(SOL_IPV6), ARG_STR(IPV6_LEAVE_ANYCAST),
			m6, sizeof(*m6),
			"{inet_pton(AF_INET6, \"" multi6addr
			"\", &ipv6mr_multiaddr)"
			", ipv6mr_interface=" IFINDEX_LO_STR "}"
		}
	};

	for (i = 0; i < ARRAY_SIZE(opts); ++i) {
		/* optlen < 0, EINVAL */
		rc = setsockopt(0, opts[i].level, opts[i].name,
				opts[i].val, -1);
		printf("setsockopt(0, %s, %s, %p, -1) = %s\n",
		       opts[i].str_level, opts[i].str_name,
		       opts[i].val, sprintrc(rc));

		/* optlen < sizeof(struct), EINVAL */
		rc = setsockopt(0, opts[i].level, opts[i].name,
				opts[i].val, opts[i].size - 1);
		printf("setsockopt(0, %s, %s, %p, %u) = %s\n",
		       opts[i].str_level, opts[i].str_name,
		       opts[i].val, opts[i].size - 1, sprintrc(rc));

		/* optval EFAULT */
		rc = setsockopt(0, opts[i].level, opts[i].name,
				opts[i].val + 1, opts[i].size);
		printf("setsockopt(0, %s, %s, %p, %u) = %s\n",
		       opts[i].str_level, opts[i].str_name,
		       opts[i].val + 1, opts[i].size, sprintrc(rc));

		/* classic */
		rc = setsockopt(0, opts[i].level, opts[i].name,
				opts[i].val, opts[i].size);
		printf("setsockopt(0, %s, %s, %s, %u) = %s\n",
		       opts[i].str_level, opts[i].str_name,
		       opts[i].addr, opts[i].size, sprintrc(rc));

		/* optlen > sizeof(struct), shortened */
		rc = setsockopt(0, opts[i].level, opts[i].name,
				opts[i].val, INT_MAX);
		printf("setsockopt(0, %s, %s, %s, %u) = %s\n",
		       opts[i].str_level, opts[i].str_name,
		       opts[i].addr, INT_MAX, sprintrc(rc));
	}

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