1/*-
2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3 *
4 * Copyright (c) 2019 Alexander V. Chernikov
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 * $FreeBSD$
28 */
29
30#ifndef _NET_ROUTING_RTSOCK_CONFIG_H_
31#define _NET_ROUTING_RTSOCK_CONFIG_H_
32
33#include "params.h"
34
35struct rtsock_config_options {
36	int num_interfaces;	/* number of interfaces to create */
37};
38
39struct rtsock_test_config {
40	int ifindex;
41	char net4_str[INET_ADDRSTRLEN];
42	char addr4_str[INET_ADDRSTRLEN];
43	char net6_str[INET6_ADDRSTRLEN];
44	char addr6_str[INET6_ADDRSTRLEN];
45	struct sockaddr_in net4;
46	struct sockaddr_in mask4;
47	struct sockaddr_in addr4;
48	struct sockaddr_in6 net6;
49	struct sockaddr_in6 mask6;
50	struct sockaddr_in6 addr6;
51	int plen4;
52	int plen6;
53	char *remote_lladdr;
54	char *ifname;
55	char **ifnames;
56	bool autocreated_interface;
57	int rtsock_fd;
58	int num_interfaces;
59};
60
61struct rtsock_test_config *
62config_setup(const atf_tc_t *tc, struct rtsock_config_options *co)
63{
64	struct rtsock_config_options default_co;
65	struct rtsock_test_config *c;
66	char buf[64], *s;
67	const char *key;
68	int mask;
69
70	if (co == NULL) {
71		bzero(&default_co, sizeof(default_co));
72		co = &default_co;
73		co->num_interfaces = 1;
74	}
75
76	c = calloc(1, sizeof(struct rtsock_test_config));
77	c->rtsock_fd = -1;
78
79	key = atf_tc_get_config_var_wd(tc, "rtsock.v4prefix", "192.0.2.0/24");
80	strlcpy(buf, key, sizeof(buf));
81	if ((s = strchr(buf, '/')) == NULL)
82		return (NULL);
83	*s++ = '\0';
84	mask = strtol(s, NULL, 10);
85	if (mask < 0 || mask > 32)
86		return (NULL);
87	c->plen4 = mask;
88	inet_pton(AF_INET, buf, &c->net4.sin_addr);
89
90	c->net4.sin_len = sizeof(struct sockaddr_in);
91	c->net4.sin_family = AF_INET;
92	c->addr4.sin_len = sizeof(struct sockaddr_in);
93	c->addr4.sin_family = AF_INET;
94
95	sa_fill_mask4(&c->mask4, c->plen4);
96
97	/* Fill in interface IPv4 address. Assume the first address in net */
98	c->addr4.sin_addr.s_addr = htonl(ntohl(c->net4.sin_addr.s_addr) + 1);
99	inet_ntop(AF_INET, &c->net4.sin_addr, c->net4_str, INET_ADDRSTRLEN);
100	inet_ntop(AF_INET, &c->addr4.sin_addr, c->addr4_str, INET_ADDRSTRLEN);
101
102	key = atf_tc_get_config_var_wd(tc, "rtsock.v6prefix", "2001:DB8::/32");
103	strlcpy(buf, key, sizeof(buf));
104	if ((s = strchr(buf, '/')) == NULL)
105		return (NULL);
106	*s++ = '\0';
107	mask = strtol(s, NULL, 10);
108	if (mask < 0 || mask > 128)
109		return (NULL);
110	c->plen6 = mask;
111
112	inet_pton(AF_INET6, buf, &c->net6.sin6_addr);
113
114	c->net6.sin6_len = sizeof(struct sockaddr_in6);
115	c->net6.sin6_family = AF_INET6;
116	c->addr6.sin6_len = sizeof(struct sockaddr_in6);
117	c->addr6.sin6_family = AF_INET6;
118
119	sa_fill_mask6(&c->mask6, c->plen6);
120
121	/* Fill in interface IPv6 address. Assume the first address in net */
122	memcpy(&c->addr6.sin6_addr, &c->net6.sin6_addr, sizeof(struct in6_addr));
123#define _s6_addr32 __u6_addr.__u6_addr32
124	c->addr6.sin6_addr._s6_addr32[3] = htonl(ntohl(c->net6.sin6_addr._s6_addr32[3]) + 1);
125#undef _s6_addr32
126	inet_ntop(AF_INET6, &c->net6.sin6_addr, c->net6_str, INET6_ADDRSTRLEN);
127	inet_ntop(AF_INET6, &c->addr6.sin6_addr, c->addr6_str, INET6_ADDRSTRLEN);
128
129	if (co->num_interfaces > 0) {
130		kldload("if_epair");
131		ATF_REQUIRE_KERNEL_MODULE("if_epair");
132
133		c->ifnames = calloc(co->num_interfaces, sizeof(char *));
134		for (int i = 0; i < co->num_interfaces; i++)
135			c->ifnames[i] = iface_create("epair");
136
137		c->ifname = c->ifnames[0];
138		c->ifindex = if_nametoindex(c->ifname);
139		ATF_REQUIRE_MSG(c->ifindex != 0, "interface %s not found",
140		    c->ifname);
141	}
142	c->num_interfaces = co->num_interfaces;
143
144	c->remote_lladdr = strdup(atf_tc_get_config_var_wd(tc,
145	    "rtsock.remote_lladdr", "00:00:5E:00:53:42"));
146
147	return (c);
148}
149
150void
151config_generic_cleanup(const atf_tc_t *tc)
152{
153	const char *srcdir = atf_tc_get_config_var(tc, "srcdir");
154	char cmd[512];
155	int ret;
156
157	/* XXX: sleep 100ms to avoid epair qflush panic */
158	usleep(1000 * 100);
159	snprintf(cmd, sizeof(cmd), "%s/generic_cleanup.sh", srcdir);
160	ret = system(cmd);
161	if (ret != 0)
162		RLOG("'%s' failed, error %d", cmd, ret);
163}
164
165void
166config_describe_root_test(atf_tc_t *tc, char *test_descr)
167{
168
169	atf_tc_set_md_var(tc, "descr", test_descr);
170	// Adding/deleting prefix requires root privileges
171	atf_tc_set_md_var(tc, "require.user", "root");
172}
173
174#endif
175