xref: /freebsd/tests/sys/net/routing/rtsock_config.h (revision 16038816)
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 
35 struct rtsock_config_options {
36 	int num_interfaces;	/* number of interfaces to create */
37 };
38 
39 struct 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 
61 struct rtsock_test_config *
62 config_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 	ATF_CHECK_ERRNO(0, true);
130 
131 	if (co->num_interfaces > 0) {
132 		/* Try loading if_epair and if that fails skip the test. */
133 		kldload("if_epair");
134 		ATF_REQUIRE_KERNEL_MODULE("if_epair");
135 		/* Clear errno for the following tests. */
136 		errno = 0;
137 
138 		c->ifnames = calloc(co->num_interfaces, sizeof(char *));
139 		for (int i = 0; i < co->num_interfaces; i++)
140 			c->ifnames[i] = iface_create("epair");
141 
142 		c->ifname = c->ifnames[0];
143 		c->ifindex = if_nametoindex(c->ifname);
144 		ATF_REQUIRE_MSG(c->ifindex != 0, "interface %s not found",
145 		    c->ifname);
146 	}
147 	c->num_interfaces = co->num_interfaces;
148 
149 	c->remote_lladdr = strdup(atf_tc_get_config_var_wd(tc,
150 	    "rtsock.remote_lladdr", "00:00:5E:00:53:42"));
151 
152 	return (c);
153 }
154 
155 void
156 config_generic_cleanup(const atf_tc_t *tc)
157 {
158 	const char *srcdir = atf_tc_get_config_var(tc, "srcdir");
159 	char cmd[512];
160 	int ret;
161 
162 	/* XXX: sleep 100ms to avoid epair qflush panic */
163 	usleep(1000 * 100);
164 	snprintf(cmd, sizeof(cmd), "%s/generic_cleanup.sh", srcdir);
165 	ret = system(cmd);
166 	if (ret != 0)
167 		RLOG("'%s' failed, error %d", cmd, ret);
168 }
169 
170 void
171 config_describe_root_test(atf_tc_t *tc, char *test_descr)
172 {
173 
174 	atf_tc_set_md_var(tc, "descr", test_descr);
175 	// Adding/deleting prefix requires root privileges
176 	atf_tc_set_md_var(tc, "require.user", "root");
177 }
178 
179 #endif
180