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 #include "rtsock_common.h" 31 #include "rtsock_config.h" 32 33 static void 34 jump_vnet(struct rtsock_test_config *c, const atf_tc_t *tc) 35 { 36 char vnet_name[512]; 37 38 snprintf(vnet_name, sizeof(vnet_name), "vt-%s", atf_tc_get_ident(tc)); 39 RLOG("jumping to %s", vnet_name); 40 41 vnet_switch_one(vnet_name, c->ifname); 42 43 /* Update ifindex cache */ 44 c->ifindex = if_nametoindex(c->ifname); 45 } 46 47 static inline struct rtsock_test_config * 48 presetup_ipv6(const atf_tc_t *tc) 49 { 50 struct rtsock_test_config *c; 51 int ret; 52 53 c = config_setup(tc, NULL); 54 55 jump_vnet(c, tc); 56 57 ret = iface_turn_up(c->ifname); 58 ATF_REQUIRE_MSG(ret == 0, "Unable to turn up %s", c->ifname); 59 ret = iface_enable_ipv6(c->ifname); 60 ATF_REQUIRE_MSG(ret == 0, "Unable to enable IPv6 on %s", c->ifname); 61 62 c->rtsock_fd = rtsock_setup_socket(); 63 64 return (c); 65 } 66 67 static inline struct rtsock_test_config * 68 presetup_ipv4(const atf_tc_t *tc) 69 { 70 struct rtsock_test_config *c; 71 int ret; 72 73 c = config_setup(tc, NULL); 74 75 jump_vnet(c, tc); 76 77 /* assumes ifconfig doing IFF_UP */ 78 ret = iface_setup_addr(c->ifname, c->addr4_str, c->plen4); 79 ATF_REQUIRE_MSG(ret == 0, "ifconfig failed"); 80 81 c->rtsock_fd = rtsock_setup_socket(); 82 83 return (c); 84 } 85 86 static void 87 prepare_route_message(struct rt_msghdr *rtm, int cmd, struct sockaddr *dst, 88 struct sockaddr *gw) 89 { 90 91 rtsock_prepare_route_message(rtm, cmd, dst, NULL, gw); 92 93 rtm->rtm_flags |= (RTF_HOST | RTF_STATIC | RTF_LLDATA); 94 } 95 96 /* TESTS */ 97 #define DECLARE_TEST_VARS \ 98 char buffer[2048], msg[512]; \ 99 ssize_t len; \ 100 int ret; \ 101 struct rtsock_test_config *c; \ 102 struct rt_msghdr *rtm = (struct rt_msghdr *)buffer; \ 103 struct sockaddr *sa; \ 104 \ 105 106 #define DECLARE_CLEANUP_VARS \ 107 struct rtsock_test_config *c = config_setup(tc); \ 108 \ 109 110 #define DESCRIBE_ROOT_TEST(_msg) config_describe_root_test(tc, _msg) 111 #define CLEANUP_AFTER_TEST config_generic_cleanup(tc) 112 113 #define RTM_DECLARE_ROOT_TEST(_name, _descr) \ 114 ATF_TC_WITH_CLEANUP(_name); \ 115 ATF_TC_HEAD(_name, tc) \ 116 { \ 117 DESCRIBE_ROOT_TEST(_descr); \ 118 } \ 119 ATF_TC_CLEANUP(_name, tc) \ 120 { \ 121 CLEANUP_AFTER_TEST; \ 122 } 123 124 RTM_DECLARE_ROOT_TEST(rtm_add_v6_ll_lle_success, "Tests addition of link-local IPv6 ND entry"); 125 ATF_TC_BODY(rtm_add_v6_ll_lle_success, tc) 126 { 127 DECLARE_TEST_VARS; 128 129 c = presetup_ipv6(tc); 130 131 char str_buf[128]; 132 struct sockaddr_in6 sin6; 133 /* Interface here is optional. XXX: verify kernel side. */ 134 char *v6addr = "fe80::4242:4242"; 135 snprintf(str_buf, sizeof(str_buf), "%s%%%s", v6addr, c->ifname); 136 sa_convert_str_to_sa(str_buf, (struct sockaddr *)&sin6); 137 138 struct sockaddr_dl ether; 139 snprintf(str_buf, sizeof(str_buf), "%s%%%s", c->remote_lladdr, c->ifname); 140 sa_convert_str_to_sa(str_buf, (struct sockaddr *)ðer); 141 142 prepare_route_message(rtm, RTM_ADD, (struct sockaddr *)&sin6, (struct sockaddr *)ðer); 143 rtsock_send_rtm(c->rtsock_fd, rtm); 144 145 /* 146 * Got message of size 240 on 2019-12-17 15:06:51 147 * RTM_ADD: Add Route: len 240, pid: 0, seq 0, errno 0, flags: <UP,HOST,DONE,LLINFO> 148 * sockaddrs: 0x3 <DST,GATEWAY> 149 * af=inet6 len=28 addr=fe80::4242:4242 scope_id=3 if_name=tap4242 150 * af=link len=54 sdl_index=3 if_name=tap4242 addr=52:54:00:14:E3:10 151 */ 152 153 rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq); 154 155 sa = rtsock_find_rtm_sa(rtm, RTA_DST); 156 ret = sa_equal_msg(sa, (struct sockaddr *)&sin6, msg, sizeof(msg)); 157 RTSOCK_ATF_REQUIRE_MSG(rtm, ret != 0, "DST sa diff: %s", msg); 158 159 sa = rtsock_find_rtm_sa(rtm, RTA_GATEWAY); 160 int sa_flags = SA_F_IGNORE_IFNAME | SA_F_IGNORE_IFTYPE | SA_F_IGNORE_MEMCMP; 161 ret = sa_equal_msg_flags(sa, (struct sockaddr *)ðer, msg, sizeof(msg), sa_flags); 162 RTSOCK_ATF_REQUIRE_MSG(rtm, ret != 0, "GATEWAY sa diff: %s", msg); 163 164 #if 0 165 /* Disable the check until https://reviews.freebsd.org/D22003 merge */ 166 /* Some additional checks to verify kernel has filled in interface data */ 167 struct sockaddr_dl *sdl = (struct sockaddr_dl *)sa; 168 RTSOCK_ATF_REQUIRE_MSG(rtm, sdl->sdl_type > 0, "sdl_type not set"); 169 #endif 170 } 171 172 RTM_DECLARE_ROOT_TEST(rtm_add_v6_gu_lle_success, "Tests addition of global IPv6 ND entry"); 173 ATF_TC_BODY(rtm_add_v6_gu_lle_success, tc) 174 { 175 DECLARE_TEST_VARS; 176 177 c = presetup_ipv6(tc); 178 179 char str_buf[128]; 180 181 struct sockaddr_in6 sin6; 182 sin6 = c->net6; 183 #define _s6_addr32 __u6_addr.__u6_addr32 184 sin6.sin6_addr._s6_addr32[3] = htonl(0x42424242); 185 #undef _s6_addr32 186 187 struct sockaddr_dl ether; 188 snprintf(str_buf, sizeof(str_buf), "%s%%%s", c->remote_lladdr, c->ifname); 189 sa_convert_str_to_sa(str_buf, (struct sockaddr *)ðer); 190 191 prepare_route_message(rtm, RTM_ADD, (struct sockaddr *)&sin6, (struct sockaddr *)ðer); 192 193 rtsock_send_rtm(c->rtsock_fd, rtm); 194 195 /* 196 * Got message of size 240 on 2019-12-17 14:56:43 197 * RTM_ADD: Add Route: len 240, pid: 0, seq 0, errno 0, flags: <UP,HOST,DONE,LLINFO> 198 * sockaddrs: 0x3 <DST,GATEWAY> 199 * af=inet6 len=28 addr=2001:db8::4242:4242 200 * af=link len=54 sdl_index=3 if_name=tap4242 addr=52:54:00:14:E3:10 201 */ 202 203 /* XXX: where is uRPF?! this should fail */ 204 205 rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq); 206 207 sa = rtsock_find_rtm_sa(rtm, RTA_DST); 208 ret = sa_equal_msg(sa, (struct sockaddr *)&sin6, msg, sizeof(msg)); 209 RTSOCK_ATF_REQUIRE_MSG(rtm, ret != 0, "DST sa diff: %s", msg); 210 211 sa = rtsock_find_rtm_sa(rtm, RTA_GATEWAY); 212 int sa_flags = SA_F_IGNORE_IFNAME | SA_F_IGNORE_IFTYPE | SA_F_IGNORE_MEMCMP; 213 ret = sa_equal_msg_flags(sa, (struct sockaddr *)ðer, msg, sizeof(msg), sa_flags); 214 RTSOCK_ATF_REQUIRE_MSG(rtm, ret != 0, "GATEWAY sa diff: %s", msg); 215 216 #if 0 217 /* Disable the check until https://reviews.freebsd.org/D22003 merge */ 218 /* Some additional checks to verify kernel has filled in interface data */ 219 struct sockaddr_dl *sdl = (struct sockaddr_dl *)sa; 220 RTSOCK_ATF_REQUIRE_MSG(rtm, sdl->sdl_type > 0, "sdl_type not set"); 221 #endif 222 } 223 224 RTM_DECLARE_ROOT_TEST(rtm_add_v4_gu_lle_success, "Tests addition of IPv4 ARP entry"); 225 ATF_TC_BODY(rtm_add_v4_gu_lle_success, tc) 226 { 227 DECLARE_TEST_VARS; 228 229 c = presetup_ipv4(tc); 230 231 char str_buf[128]; 232 233 struct sockaddr_in sin; 234 sin = c->addr4; 235 /* Use the next IPv4 address after self */ 236 sin.sin_addr.s_addr = htonl(ntohl(sin.sin_addr.s_addr) + 1); 237 238 struct sockaddr_dl ether; 239 snprintf(str_buf, sizeof(str_buf), "%s%%%s", c->remote_lladdr, c->ifname); 240 sa_convert_str_to_sa(str_buf, (struct sockaddr *)ðer); 241 242 prepare_route_message(rtm, RTM_ADD, (struct sockaddr *)&sin, (struct sockaddr *)ðer); 243 244 len = rtsock_send_rtm(c->rtsock_fd, rtm); 245 246 /* 247 * RTM_ADD: Add Route: len 224, pid: 43131, seq 42, errno 0, flags: <HOST,DONE,LLINFO,STATIC> 248 * sockaddrs: 0x3 <DST,GATEWAY> 249 * af=inet len=16 addr=192.0.2.2 250 * af=link len=54 sdl_index=3 if_name=tap4242 addr=52:54:00:14:E3:10 251 */ 252 253 rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq); 254 255 sa = rtsock_find_rtm_sa(rtm, RTA_DST); 256 ret = sa_equal_msg(sa, (struct sockaddr *)&sin, msg, sizeof(msg)); 257 RTSOCK_ATF_REQUIRE_MSG(rtm, ret != 0, "DST sa diff: %s", msg); 258 259 sa = rtsock_find_rtm_sa(rtm, RTA_GATEWAY); 260 int sa_flags = SA_F_IGNORE_IFNAME | SA_F_IGNORE_IFTYPE | SA_F_IGNORE_MEMCMP; 261 ret = sa_equal_msg_flags(sa, (struct sockaddr *)ðer, msg, sizeof(msg), sa_flags); 262 RTSOCK_ATF_REQUIRE_MSG(rtm, ret != 0, "GATEWAY sa diff: %s", msg); 263 264 /* 265 * TODO: Currently kernel code does not set sdl_type, contrary to IPv6. 266 */ 267 } 268 269 RTM_DECLARE_ROOT_TEST(rtm_del_v6_ll_lle_success, "Tests removal of link-local IPv6 ND entry"); 270 ATF_TC_BODY(rtm_del_v6_ll_lle_success, tc) 271 { 272 DECLARE_TEST_VARS; 273 274 c = presetup_ipv6(tc); 275 276 char str_buf[128]; 277 278 struct sockaddr_in6 sin6; 279 /* Interface here is optional. XXX: verify kernel side. */ 280 char *v6addr = "fe80::4242:4242"; 281 snprintf(str_buf, sizeof(str_buf), "%s%%%s", v6addr, c->ifname); 282 sa_convert_str_to_sa(str_buf, (struct sockaddr *)&sin6); 283 284 struct sockaddr_dl ether; 285 snprintf(str_buf, sizeof(str_buf), "%s%%%s", c->remote_lladdr, c->ifname); 286 sa_convert_str_to_sa(str_buf, (struct sockaddr *)ðer); 287 288 prepare_route_message(rtm, RTM_ADD, (struct sockaddr *)&sin6, (struct sockaddr *)ðer); 289 290 rtsock_send_rtm(c->rtsock_fd, rtm); 291 292 /* Successfully added an entry, let's try to remove it. */ 293 prepare_route_message(rtm, RTM_DELETE, (struct sockaddr *)&sin6, (struct sockaddr *)ðer); 294 295 rtsock_send_rtm(c->rtsock_fd, rtm); 296 297 rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq); 298 299 RTSOCK_ATF_REQUIRE_MSG(rtm, rtm->rtm_type == RTM_DELETE, "rtm_type is not delete"); 300 301 sa = rtsock_find_rtm_sa(rtm, RTA_DST); 302 ret = sa_equal_msg(sa, (struct sockaddr *)&sin6, msg, sizeof(msg)); 303 RTSOCK_ATF_REQUIRE_MSG(rtm, ret != 0, "DST sa diff: %s", msg); 304 305 sa = rtsock_find_rtm_sa(rtm, RTA_GATEWAY); 306 int sa_flags = SA_F_IGNORE_IFNAME | SA_F_IGNORE_IFTYPE | SA_F_IGNORE_MEMCMP; 307 ret = sa_equal_msg_flags(sa, (struct sockaddr *)ðer, msg, sizeof(msg), sa_flags); 308 RTSOCK_ATF_REQUIRE_MSG(rtm, ret != 0, "GATEWAY sa diff: %s", msg); 309 310 /* 311 * TODO: Currently kernel code does not set sdl_type on delete. 312 */ 313 } 314 315 RTM_DECLARE_ROOT_TEST(rtm_del_v6_gu_lle_success, "Tests removal of global IPv6 ND entry"); 316 ATF_TC_BODY(rtm_del_v6_gu_lle_success, tc) 317 { 318 DECLARE_TEST_VARS; 319 320 c = presetup_ipv6(tc); 321 322 char str_buf[128]; 323 324 struct sockaddr_in6 sin6; 325 sin6 = c->net6; 326 #define _s6_addr32 __u6_addr.__u6_addr32 327 sin6.sin6_addr._s6_addr32[3] = htonl(0x42424242); 328 #undef _s6_addr32 329 330 struct sockaddr_dl ether; 331 snprintf(str_buf, sizeof(str_buf), "%s%%%s", c->remote_lladdr, c->ifname); 332 sa_convert_str_to_sa(str_buf, (struct sockaddr *)ðer); 333 334 prepare_route_message(rtm, RTM_ADD, (struct sockaddr *)&sin6, (struct sockaddr *)ðer); 335 336 len = rtsock_send_rtm(c->rtsock_fd, rtm); 337 338 /* Successfully added an entry, let's try to remove it. */ 339 prepare_route_message(rtm, RTM_DELETE, (struct sockaddr *)&sin6, (struct sockaddr *)ðer); 340 341 rtsock_send_rtm(c->rtsock_fd, rtm); 342 343 rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq); 344 345 RTSOCK_ATF_REQUIRE_MSG(rtm, rtm->rtm_type == RTM_DELETE, "rtm_type is not delete"); 346 347 sa = rtsock_find_rtm_sa(rtm, RTA_DST); 348 ret = sa_equal_msg(sa, (struct sockaddr *)&sin6, msg, sizeof(msg)); 349 RTSOCK_ATF_REQUIRE_MSG(rtm, ret != 0, "DST sa diff: %s", msg); 350 351 sa = rtsock_find_rtm_sa(rtm, RTA_GATEWAY); 352 int sa_flags = SA_F_IGNORE_IFNAME | SA_F_IGNORE_IFTYPE | SA_F_IGNORE_MEMCMP; 353 ret = sa_equal_msg_flags(sa, (struct sockaddr *)ðer, msg, sizeof(msg), sa_flags); 354 RTSOCK_ATF_REQUIRE_MSG(rtm, ret != 0, "GATEWAY sa diff: %s", msg); 355 356 /* 357 * TODO: Currently kernel code does not set sdl_type on delete. 358 */ 359 } 360 361 RTM_DECLARE_ROOT_TEST(rtm_del_v4_gu_lle_success, "Tests removal of IPv4 ARP entry"); 362 ATF_TC_BODY(rtm_del_v4_gu_lle_success, tc) 363 { 364 DECLARE_TEST_VARS; 365 366 c = presetup_ipv4(tc); 367 368 char str_buf[128]; 369 370 struct sockaddr_in sin; 371 sin = c->addr4; 372 /* Use the next IPv4 address after self */ 373 sin.sin_addr.s_addr = htonl(ntohl(sin.sin_addr.s_addr) + 1); 374 375 struct sockaddr_dl ether; 376 snprintf(str_buf, sizeof(str_buf), "%s%%%s", c->remote_lladdr, c->ifname); 377 sa_convert_str_to_sa(str_buf, (struct sockaddr *)ðer); 378 379 prepare_route_message(rtm, RTM_ADD, (struct sockaddr *)&sin, (struct sockaddr *)ðer); 380 381 rtsock_send_rtm(c->rtsock_fd, rtm); 382 383 /* We successfully added an entry, let's try to remove it. */ 384 prepare_route_message(rtm, RTM_DELETE, (struct sockaddr *)&sin, (struct sockaddr *)ðer); 385 386 rtsock_send_rtm(c->rtsock_fd, rtm); 387 388 rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq); 389 390 RTSOCK_ATF_REQUIRE_MSG(rtm, rtm->rtm_type == RTM_DELETE, "rtm_type is not delete"); 391 392 sa = rtsock_find_rtm_sa(rtm, RTA_DST); 393 ret = sa_equal_msg(sa, (struct sockaddr *)&sin, msg, sizeof(msg)); 394 RTSOCK_ATF_REQUIRE_MSG(rtm, ret != 0, "DST sa diff: %s", msg); 395 396 sa = rtsock_find_rtm_sa(rtm, RTA_GATEWAY); 397 int sa_flags = SA_F_IGNORE_IFNAME | SA_F_IGNORE_IFTYPE | SA_F_IGNORE_MEMCMP; 398 ret = sa_equal_msg_flags(sa, (struct sockaddr *)ðer, msg, sizeof(msg), sa_flags); 399 RTSOCK_ATF_REQUIRE_MSG(rtm, ret != 0, "GATEWAY sa diff: %s", msg); 400 401 /* 402 * TODO: Currently kernel code does not set sdl_type, contrary to IPv6. 403 */ 404 } 405 406 ATF_TP_ADD_TCS(tp) 407 { 408 ATF_TP_ADD_TC(tp, rtm_add_v6_ll_lle_success); 409 ATF_TP_ADD_TC(tp, rtm_add_v6_gu_lle_success); 410 ATF_TP_ADD_TC(tp, rtm_add_v4_gu_lle_success); 411 ATF_TP_ADD_TC(tp, rtm_del_v6_ll_lle_success); 412 ATF_TP_ADD_TC(tp, rtm_del_v6_gu_lle_success); 413 ATF_TP_ADD_TC(tp, rtm_del_v4_gu_lle_success); 414 415 return (atf_no_error()); 416 } 417 418 419