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