1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause
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
28 #ifndef _NET_ROUTING_RTSOCK_CONFIG_H_
29 #define _NET_ROUTING_RTSOCK_CONFIG_H_
30
31 #include "params.h"
32
33 struct rtsock_config_options {
34 int num_interfaces; /* number of interfaces to create */
35 };
36
37 struct rtsock_test_config {
38 int ifindex;
39 char net4_str[INET_ADDRSTRLEN];
40 char addr4_str[INET_ADDRSTRLEN];
41 char net6_str[INET6_ADDRSTRLEN];
42 char addr6_str[INET6_ADDRSTRLEN];
43 struct sockaddr_in net4;
44 struct sockaddr_in mask4;
45 struct sockaddr_in addr4;
46 struct sockaddr_in6 net6;
47 struct sockaddr_in6 mask6;
48 struct sockaddr_in6 addr6;
49 int plen4;
50 int plen6;
51 char *remote_lladdr;
52 char *ifname;
53 char **ifnames;
54 bool autocreated_interface;
55 int rtsock_fd;
56 int num_interfaces;
57 };
58
59 struct rtsock_test_config *
config_setup(const atf_tc_t * tc,struct rtsock_config_options * co)60 config_setup(const atf_tc_t *tc, struct rtsock_config_options *co)
61 {
62 struct rtsock_config_options default_co;
63 struct rtsock_test_config *c;
64 char buf[64], *s;
65 const char *key;
66 int mask;
67
68 if (co == NULL) {
69 bzero(&default_co, sizeof(default_co));
70 co = &default_co;
71 co->num_interfaces = 1;
72 }
73
74 c = calloc(1, sizeof(struct rtsock_test_config));
75 c->rtsock_fd = -1;
76
77 key = atf_tc_get_config_var_wd(tc, "rtsock.v4prefix", "192.0.2.0/24");
78 strlcpy(buf, key, sizeof(buf));
79 if ((s = strchr(buf, '/')) == NULL)
80 return (NULL);
81 *s++ = '\0';
82 mask = strtol(s, NULL, 10);
83 if (mask < 0 || mask > 32)
84 return (NULL);
85 c->plen4 = mask;
86 inet_pton(AF_INET, buf, &c->net4.sin_addr);
87
88 c->net4.sin_len = sizeof(struct sockaddr_in);
89 c->net4.sin_family = AF_INET;
90 c->addr4.sin_len = sizeof(struct sockaddr_in);
91 c->addr4.sin_family = AF_INET;
92
93 sa_fill_mask4(&c->mask4, c->plen4);
94
95 /* Fill in interface IPv4 address. Assume the first address in net */
96 c->addr4.sin_addr.s_addr = htonl(ntohl(c->net4.sin_addr.s_addr) + 1);
97 inet_ntop(AF_INET, &c->net4.sin_addr, c->net4_str, INET_ADDRSTRLEN);
98 inet_ntop(AF_INET, &c->addr4.sin_addr, c->addr4_str, INET_ADDRSTRLEN);
99
100 key = atf_tc_get_config_var_wd(tc, "rtsock.v6prefix", "2001:DB8::/32");
101 strlcpy(buf, key, sizeof(buf));
102 if ((s = strchr(buf, '/')) == NULL)
103 return (NULL);
104 *s++ = '\0';
105 mask = strtol(s, NULL, 10);
106 if (mask < 0 || mask > 128)
107 return (NULL);
108 c->plen6 = mask;
109
110 inet_pton(AF_INET6, buf, &c->net6.sin6_addr);
111
112 c->net6.sin6_len = sizeof(struct sockaddr_in6);
113 c->net6.sin6_family = AF_INET6;
114 c->addr6.sin6_len = sizeof(struct sockaddr_in6);
115 c->addr6.sin6_family = AF_INET6;
116
117 sa_fill_mask6(&c->mask6, c->plen6);
118
119 /* Fill in interface IPv6 address. Assume the first address in net */
120 memcpy(&c->addr6.sin6_addr, &c->net6.sin6_addr, sizeof(struct in6_addr));
121 #define _s6_addr32 __u6_addr.__u6_addr32
122 c->addr6.sin6_addr._s6_addr32[3] = htonl(ntohl(c->net6.sin6_addr._s6_addr32[3]) + 1);
123 #undef _s6_addr32
124 inet_ntop(AF_INET6, &c->net6.sin6_addr, c->net6_str, INET6_ADDRSTRLEN);
125 inet_ntop(AF_INET6, &c->addr6.sin6_addr, c->addr6_str, INET6_ADDRSTRLEN);
126
127 ATF_CHECK_ERRNO(0, true);
128
129 if (co->num_interfaces > 0) {
130 /* Try loading if_epair and if that fails skip the test. */
131 kldload("if_epair");
132 ATF_REQUIRE_KERNEL_MODULE("if_epair");
133 /* Clear errno for the following tests. */
134 errno = 0;
135
136 c->ifnames = calloc(co->num_interfaces, sizeof(char *));
137 for (int i = 0; i < co->num_interfaces; i++)
138 c->ifnames[i] = iface_create("epair");
139
140 c->ifname = c->ifnames[0];
141 c->ifindex = if_nametoindex(c->ifname);
142 ATF_REQUIRE_MSG(c->ifindex != 0, "interface %s not found",
143 c->ifname);
144 }
145 c->num_interfaces = co->num_interfaces;
146
147 c->remote_lladdr = strdup(atf_tc_get_config_var_wd(tc,
148 "rtsock.remote_lladdr", "00:00:5E:00:53:42"));
149
150 return (c);
151 }
152
153 void
config_generic_cleanup(const atf_tc_t * tc)154 config_generic_cleanup(const atf_tc_t *tc)
155 {
156 const char *srcdir = atf_tc_get_config_var(tc, "srcdir");
157 char cmd[512];
158 int ret;
159
160 snprintf(cmd, sizeof(cmd), "%s/generic_cleanup.sh", srcdir);
161 ret = system(cmd);
162 if (ret != 0)
163 RLOG("'%s' failed, error %d", cmd, ret);
164 }
165
166 void
config_describe_root_test(atf_tc_t * tc,char * test_descr)167 config_describe_root_test(atf_tc_t *tc, char *test_descr)
168 {
169
170 atf_tc_set_md_var(tc, "descr", test_descr);
171 // Adding/deleting prefix requires root privileges
172 atf_tc_set_md_var(tc, "require.user", "root");
173 }
174
175 #endif
176