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