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 #include "sys/types.h" 33 #include <sys/time.h> 34 #include <sys/ioctl.h> 35 36 #include "net/bpf.h" 37 38 static inline struct rtsock_test_config * 39 presetup_ipv6_iface(const atf_tc_t *tc) 40 { 41 struct rtsock_test_config *c; 42 int ret; 43 44 c = config_setup(tc); 45 46 ret = iface_turn_up(c->ifname); 47 ATF_REQUIRE_MSG(ret == 0, "Unable to turn up %s", c->ifname); 48 49 ret = iface_enable_ipv6(c->ifname); 50 ATF_REQUIRE_MSG(ret == 0, "Unable to enable IPv6 on %s", c->ifname); 51 52 return (c); 53 } 54 55 static inline struct rtsock_test_config * 56 presetup_ipv6(const atf_tc_t *tc) 57 { 58 struct rtsock_test_config *c; 59 int ret; 60 61 c = presetup_ipv6_iface(tc); 62 63 ret = iface_setup_addr(c->ifname, c->addr6_str, c->plen6); 64 65 c->rtsock_fd = rtsock_setup_socket(); 66 67 return (c); 68 } 69 70 static inline struct rtsock_test_config * 71 presetup_ipv4_iface(const atf_tc_t *tc) 72 { 73 struct rtsock_test_config *c; 74 int ret; 75 76 c = config_setup(tc); 77 78 ret = iface_turn_up(c->ifname); 79 ATF_REQUIRE_MSG(ret == 0, "Unable to turn up %s", c->ifname); 80 81 /* Actually open interface, so kernel writes won't fail */ 82 if (c->autocreated_interface) { 83 ret = iface_open(c->ifname); 84 ATF_REQUIRE_MSG(ret >= 0, "unable to open interface %s", c->ifname); 85 } 86 87 return (c); 88 } 89 90 static inline struct rtsock_test_config * 91 presetup_ipv4(const atf_tc_t *tc) 92 { 93 struct rtsock_test_config *c; 94 int ret; 95 96 c = presetup_ipv4_iface(tc); 97 98 /* assumes ifconfig doing IFF_UP */ 99 ret = iface_setup_addr(c->ifname, c->addr4_str, c->plen4); 100 ATF_REQUIRE_MSG(ret == 0, "ifconfig failed"); 101 102 c->rtsock_fd = rtsock_setup_socket(); 103 104 return (c); 105 } 106 107 108 static void 109 prepare_v4_network(struct rtsock_test_config *c, struct sockaddr_in *dst, 110 struct sockaddr_in *mask, struct sockaddr_in *gw) 111 { 112 /* Create IPv4 subnetwork with smaller prefix */ 113 sa_fill_mask4(mask, c->plen4 + 1); 114 *dst = c->net4; 115 /* Calculate GW as last-net-address - 1 */ 116 *gw = c->net4; 117 gw->sin_addr.s_addr = htonl((ntohl(c->net4.sin_addr.s_addr) | ~ntohl(c->mask4.sin_addr.s_addr)) - 1); 118 sa_print((struct sockaddr *)dst, 0); 119 sa_print((struct sockaddr *)mask, 0); 120 sa_print((struct sockaddr *)gw, 0); 121 } 122 123 static void 124 prepare_v6_network(struct rtsock_test_config *c, struct sockaddr_in6 *dst, 125 struct sockaddr_in6 *mask, struct sockaddr_in6 *gw) 126 { 127 /* Create IPv6 subnetwork with smaller prefix */ 128 sa_fill_mask6(mask, c->plen6 + 1); 129 *dst = c->net6; 130 /* Calculate GW as last-net-address - 1 */ 131 *gw = c->net6; 132 #define _s6_addr32 __u6_addr.__u6_addr32 133 gw->sin6_addr._s6_addr32[0] = htonl((ntohl(gw->sin6_addr._s6_addr32[0]) | ~ntohl(c->mask6.sin6_addr._s6_addr32[0]))); 134 gw->sin6_addr._s6_addr32[1] = htonl((ntohl(gw->sin6_addr._s6_addr32[1]) | ~ntohl(c->mask6.sin6_addr._s6_addr32[1]))); 135 gw->sin6_addr._s6_addr32[2] = htonl((ntohl(gw->sin6_addr._s6_addr32[2]) | ~ntohl(c->mask6.sin6_addr._s6_addr32[2]))); 136 gw->sin6_addr._s6_addr32[3] = htonl((ntohl(gw->sin6_addr._s6_addr32[3]) | ~ntohl(c->mask6.sin6_addr._s6_addr32[3])) - 1); 137 #undef _s6_addr32 138 sa_print((struct sockaddr *)dst, 0); 139 sa_print((struct sockaddr *)mask, 0); 140 sa_print((struct sockaddr *)gw, 0); 141 } 142 143 static void 144 prepare_route_message(struct rt_msghdr *rtm, int cmd, struct sockaddr *dst, 145 struct sockaddr *mask, struct sockaddr *gw) 146 { 147 148 rtsock_prepare_route_message(rtm, cmd, dst, mask, gw); 149 150 if (cmd == RTM_ADD || cmd == RTM_CHANGE) 151 rtm->rtm_flags |= RTF_STATIC; 152 } 153 154 static void 155 verify_route_message(struct rt_msghdr *rtm, int cmd, struct sockaddr *dst, 156 struct sockaddr *mask, struct sockaddr *gw) 157 { 158 char msg[512]; 159 struct sockaddr *sa; 160 int ret; 161 162 RTSOCK_ATF_REQUIRE_MSG(rtm, rtm->rtm_type == cmd, 163 "expected %s message, got %d (%s)", rtsock_print_cmdtype(cmd), 164 rtm->rtm_type, rtsock_print_cmdtype(rtm->rtm_type)); 165 RTSOCK_ATF_REQUIRE_MSG(rtm, rtm->rtm_errno == 0, 166 "got got errno %d as message reply", rtm->rtm_errno); 167 RTSOCK_ATF_REQUIRE_MSG(rtm, rtm->_rtm_spare1 == 0, 168 "expected rtm_spare==0, got %d", rtm->_rtm_spare1); 169 170 /* kernel MAY return more sockaddrs, including RTA_IFP / RTA_IFA, so verify the needed ones */ 171 if (dst != NULL) { 172 sa = rtsock_find_rtm_sa(rtm, RTA_DST); 173 RTSOCK_ATF_REQUIRE_MSG(rtm, sa != NULL, "DST is not set"); 174 ret = sa_equal_msg(sa, dst, msg, sizeof(msg)); 175 RTSOCK_ATF_REQUIRE_MSG(rtm, ret != 0, "DST sa diff: %s", msg); 176 } 177 178 if (mask != NULL) { 179 sa = rtsock_find_rtm_sa(rtm, RTA_NETMASK); 180 RTSOCK_ATF_REQUIRE_MSG(rtm, sa != NULL, "NETMASK is not set"); 181 ret = sa_equal_msg(sa, mask, msg, sizeof(msg)); 182 ret = 1; 183 RTSOCK_ATF_REQUIRE_MSG(rtm, ret != 0, "NETMASK sa diff: %s", msg); 184 } 185 186 if (gw != NULL) { 187 sa = rtsock_find_rtm_sa(rtm, RTA_GATEWAY); 188 RTSOCK_ATF_REQUIRE_MSG(rtm, sa != NULL, "GATEWAY is not set"); 189 ret = sa_equal_msg(sa, gw, msg, sizeof(msg)); 190 RTSOCK_ATF_REQUIRE_MSG(rtm, ret != 0, "GATEWAY sa diff: %s", msg); 191 } 192 } 193 194 static void 195 verify_route_message_extra(struct rt_msghdr *rtm, int ifindex, int rtm_flags) 196 { 197 RTSOCK_ATF_REQUIRE_MSG(rtm, rtm->rtm_index == ifindex, 198 "expected ifindex %d, got %d", ifindex, rtm->rtm_index); 199 200 if (rtm->rtm_flags != rtm_flags) { 201 char got_flags[64], expected_flags[64]; 202 rtsock_print_rtm_flags(got_flags, sizeof(got_flags), 203 rtm->rtm_flags); 204 rtsock_print_rtm_flags(expected_flags, sizeof(expected_flags), 205 rtm_flags); 206 207 RTSOCK_ATF_REQUIRE_MSG(rtm, rtm->rtm_flags == rtm_flags, 208 "expected flags: 0x%X %s, got 0x%X %s", 209 rtm_flags, expected_flags, 210 rtm->rtm_flags, got_flags); 211 } 212 } 213 214 static void 215 verify_link_gateway(struct rt_msghdr *rtm, int ifindex) 216 { 217 struct sockaddr *sa; 218 struct sockaddr_dl *sdl; 219 220 sa = rtsock_find_rtm_sa(rtm, RTA_GATEWAY); 221 RTSOCK_ATF_REQUIRE_MSG(rtm, sa != NULL, "GATEWAY is not set"); 222 RTSOCK_ATF_REQUIRE_MSG(rtm, sa->sa_family == AF_LINK, "GW sa family is %d", sa->sa_family); 223 sdl = (struct sockaddr_dl *)sa; 224 RTSOCK_ATF_REQUIRE_MSG(rtm, sdl->sdl_index == ifindex, "GW ifindex is %d", sdl->sdl_index); 225 } 226 227 /* TESTS */ 228 229 #define DECLARE_TEST_VARS \ 230 char buffer[2048]; \ 231 struct rtsock_test_config *c; \ 232 struct rt_msghdr *rtm = (struct rt_msghdr *)buffer; \ 233 struct sockaddr *sa; \ 234 int ret; \ 235 \ 236 237 #define DESCRIBE_ROOT_TEST(_msg) config_describe_root_test(tc, _msg) 238 #define CLEANUP_AFTER_TEST config_generic_cleanup(config_setup(tc)) 239 240 #define RTM_DECLARE_ROOT_TEST(_name, _descr) \ 241 ATF_TC_WITH_CLEANUP(_name); \ 242 ATF_TC_HEAD(_name, tc) \ 243 { \ 244 DESCRIBE_ROOT_TEST(_descr); \ 245 } \ 246 ATF_TC_CLEANUP(_name, tc) \ 247 { \ 248 CLEANUP_AFTER_TEST; \ 249 } 250 251 ATF_TC_WITH_CLEANUP(rtm_get_v4_exact_success); 252 ATF_TC_HEAD(rtm_get_v4_exact_success, tc) 253 { 254 DESCRIBE_ROOT_TEST("Tests RTM_GET with exact prefix lookup on an interface prefix"); 255 } 256 257 ATF_TC_BODY(rtm_get_v4_exact_success, tc) 258 { 259 DECLARE_TEST_VARS; 260 261 c = presetup_ipv4(tc); 262 263 prepare_route_message(rtm, RTM_GET, (struct sockaddr *)&c->net4, 264 (struct sockaddr *)&c->mask4, NULL); 265 266 rtsock_send_rtm(c->rtsock_fd, rtm); 267 268 rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq); 269 270 /* 271 * RTM_GET: Report Metrics: len 240, pid: 45072, seq 42, errno 0, flags: <UP,DONE,PINNED> 272 * sockaddrs: 0x7 <DST,GATEWAY,NETMASK> 273 * af=inet len=16 addr=192.0.2.0 hd={10, 02, 00{2}, C0, 00, 02, 00{9}} 274 * af=link len=54 sdl_index=3 if_name=tap4242 hd={36, 12, 03, 00, 06, 00{49}} 275 * af=inet len=16 addr=255.255.255.0 hd={10, 02, FF{5}, 00{9}} 276 */ 277 278 verify_route_message(rtm, RTM_GET, (struct sockaddr *)&c->net4, 279 (struct sockaddr *)&c->mask4, NULL); 280 281 verify_route_message_extra(rtm, c->ifindex, RTF_UP | RTF_DONE | RTF_PINNED); 282 283 /* Explicitly verify gateway for the interface route */ 284 verify_link_gateway(rtm, c->ifindex); 285 sa = rtsock_find_rtm_sa(rtm, RTA_GATEWAY); 286 RTSOCK_ATF_REQUIRE_MSG(rtm, sa != NULL, "GATEWAY is not set"); 287 RTSOCK_ATF_REQUIRE_MSG(rtm, sa->sa_family == AF_LINK, "GW sa family is %d", sa->sa_family); 288 struct sockaddr_dl *sdl = (struct sockaddr_dl *)sa; 289 RTSOCK_ATF_REQUIRE_MSG(rtm, sdl->sdl_index == c->ifindex, "GW ifindex is %d", sdl->sdl_index); 290 } 291 292 ATF_TC_CLEANUP(rtm_get_v4_exact_success, tc) 293 { 294 CLEANUP_AFTER_TEST; 295 } 296 297 ATF_TC_WITH_CLEANUP(rtm_get_v4_lpm_success); 298 ATF_TC_HEAD(rtm_get_v4_lpm_success, tc) 299 { 300 DESCRIBE_ROOT_TEST("Tests RTM_GET with address lookup on an existing prefix"); 301 } 302 303 ATF_TC_BODY(rtm_get_v4_lpm_success, tc) 304 { 305 DECLARE_TEST_VARS; 306 307 c = presetup_ipv4(tc); 308 309 prepare_route_message(rtm, RTM_GET, (struct sockaddr *)&c->net4, NULL, NULL); 310 311 rtsock_send_rtm(c->rtsock_fd, rtm); 312 313 rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq); 314 315 /* 316 * RTM_GET: Report Metrics: len 312, pid: 67074, seq 1, errno 0, flags:<UP,DONE,PINNED> 317 * locks: inits: 318 * sockaddrs: <DST,GATEWAY,NETMASK,IFP,IFA> 319 * 10.0.0.0 link#1 255.255.255.0 vtnet0:52.54.0.42.f.ef 10.0.0.157 320 */ 321 322 verify_route_message(rtm, RTM_GET, (struct sockaddr *)&c->net4, 323 (struct sockaddr *)&c->mask4, NULL); 324 325 verify_route_message_extra(rtm, c->ifindex, RTF_UP | RTF_DONE | RTF_PINNED); 326 } 327 328 ATF_TC_CLEANUP(rtm_get_v4_lpm_success, tc) 329 { 330 CLEANUP_AFTER_TEST; 331 } 332 333 334 ATF_TC_WITH_CLEANUP(rtm_get_v4_empty_dst_failure); 335 ATF_TC_HEAD(rtm_get_v4_empty_dst_failure, tc) 336 { 337 338 DESCRIBE_ROOT_TEST("Tests RTM_GET with empty DST addr"); 339 } 340 341 ATF_TC_BODY(rtm_get_v4_empty_dst_failure, tc) 342 { 343 DECLARE_TEST_VARS; 344 345 c = config_setup_base(tc); 346 c->rtsock_fd = rtsock_setup_socket(); 347 348 rtsock_prepare_route_message(rtm, RTM_GET, NULL, 349 (struct sockaddr *)&c->mask4, NULL); 350 rtsock_update_rtm_len(rtm); 351 352 write(c->rtsock_fd, rtm, rtm->rtm_msglen); 353 ATF_CHECK_ERRNO(EINVAL, write(c->rtsock_fd, rtm, rtm->rtm_msglen)); 354 } 355 356 ATF_TC_CLEANUP(rtm_get_v4_empty_dst_failure, tc) 357 { 358 CLEANUP_AFTER_TEST; 359 } 360 361 ATF_TC_WITH_CLEANUP(rtm_get_v4_hostbits_failure); 362 ATF_TC_HEAD(rtm_get_v4_hostbits_failure, tc) 363 { 364 DESCRIBE_ROOT_TEST("Tests RTM_GET with prefix with some hosts-bits set"); 365 } 366 367 ATF_TC_BODY(rtm_get_v4_hostbits_failure, tc) 368 { 369 DECLARE_TEST_VARS; 370 371 c = presetup_ipv4(tc); 372 373 /* Q the same prefix */ 374 rtsock_prepare_route_message(rtm, RTM_GET, (struct sockaddr *)&c->addr4, 375 (struct sockaddr *)&c->mask4, NULL); 376 rtsock_update_rtm_len(rtm); 377 378 ATF_CHECK_ERRNO(ESRCH, write(c->rtsock_fd, rtm, rtm->rtm_msglen)); 379 } 380 381 ATF_TC_CLEANUP(rtm_get_v4_hostbits_failure, tc) 382 { 383 CLEANUP_AFTER_TEST; 384 } 385 386 ATF_TC_WITH_CLEANUP(rtm_add_v4_gw_direct_success); 387 ATF_TC_HEAD(rtm_add_v4_gw_direct_success, tc) 388 { 389 DESCRIBE_ROOT_TEST("Tests IPv4 route addition with directly-reachable GW specified by IP"); 390 } 391 392 ATF_TC_BODY(rtm_add_v4_gw_direct_success, tc) 393 { 394 DECLARE_TEST_VARS; 395 396 c = presetup_ipv4(tc); 397 398 /* Create IPv4 subnetwork with smaller prefix */ 399 struct sockaddr_in mask4; 400 struct sockaddr_in net4; 401 struct sockaddr_in gw4; 402 prepare_v4_network(c, &net4, &mask4, &gw4); 403 404 prepare_route_message(rtm, RTM_ADD, (struct sockaddr *)&net4, 405 (struct sockaddr *)&mask4, (struct sockaddr *)&gw4); 406 407 rtsock_send_rtm(c->rtsock_fd, rtm); 408 rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq); 409 410 /* 411 * RTM_ADD: Add Route: len 200, pid: 46068, seq 42, errno 0, flags:<GATEWAY,DONE,STATIC> 412 * locks: inits: 413 * sockaddrs: <DST,GATEWAY,NETMASK> 414 * 192.0.2.0 192.0.2.254 255.255.255.128 415 */ 416 417 verify_route_message(rtm, RTM_ADD, (struct sockaddr *)&net4, 418 (struct sockaddr *)&mask4, (struct sockaddr *)&gw4); 419 /* XXX: Currently kernel sets RTF_UP automatically but does NOT report it in the reply */ 420 verify_route_message_extra(rtm, c->ifindex, RTF_DONE | RTF_GATEWAY | RTF_STATIC); 421 } 422 423 ATF_TC_CLEANUP(rtm_add_v4_gw_direct_success, tc) 424 { 425 CLEANUP_AFTER_TEST; 426 } 427 428 ATF_TC_WITH_CLEANUP(rtm_del_v4_prefix_nogw_success); 429 ATF_TC_HEAD(rtm_del_v4_prefix_nogw_success, tc) 430 { 431 DESCRIBE_ROOT_TEST("Tests IPv4 route removal without specifying gateway"); 432 } 433 434 ATF_TC_BODY(rtm_del_v4_prefix_nogw_success, tc) 435 { 436 DECLARE_TEST_VARS; 437 438 c = presetup_ipv4(tc); 439 440 /* Create IPv4 subnetwork with smaller prefix */ 441 struct sockaddr_in mask4; 442 struct sockaddr_in net4; 443 struct sockaddr_in gw4; 444 prepare_v4_network(c, &net4, &mask4, &gw4); 445 446 prepare_route_message(rtm, RTM_ADD, (struct sockaddr *)&net4, 447 (struct sockaddr *)&mask4, (struct sockaddr *)&gw4); 448 449 rtsock_send_rtm(c->rtsock_fd, rtm); 450 451 /* Route has been added successfully, try to delete it */ 452 prepare_route_message(rtm, RTM_DELETE, (struct sockaddr *)&net4, 453 (struct sockaddr *)&mask4, NULL); 454 455 rtsock_send_rtm(c->rtsock_fd, rtm); 456 457 rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq); 458 459 /* 460 * RTM_DELETE: Delete Route: len 200, pid: 46417, seq 43, errno 0, flags: <GATEWAY,DONE,STATIC> 461 * sockaddrs: 0x7 <DST,GATEWAY,NETMASK> 462 * af=inet len=16 addr=192.0.2.0 hd={10, 02, 00{2}, C0, 00, 02, 00{9}} 463 * af=inet len=16 addr=192.0.2.254 hd={10, 02, 00{2}, C0, 00, 02, FE, 00{8}} 464 * af=inet len=16 addr=255.255.255.128 hd={10, 02, FF{5}, 80, 00{8}} 465 */ 466 verify_route_message(rtm, RTM_DELETE, (struct sockaddr *)&net4, 467 (struct sockaddr *)&mask4, (struct sockaddr *)&gw4); 468 469 verify_route_message_extra(rtm, c->ifindex, RTF_DONE | RTF_GATEWAY | RTF_STATIC); 470 } 471 472 ATF_TC_CLEANUP(rtm_del_v4_prefix_nogw_success, tc) 473 { 474 CLEANUP_AFTER_TEST; 475 } 476 477 ATF_TC_WITH_CLEANUP(rtm_add_v6_gu_gw_gu_direct_success); 478 ATF_TC_HEAD(rtm_add_v6_gu_gw_gu_direct_success, tc) 479 { 480 DESCRIBE_ROOT_TEST("Tests IPv6 global unicast prefix addition with directly-reachable GU GW"); 481 } 482 483 ATF_TC_BODY(rtm_add_v6_gu_gw_gu_direct_success, tc) 484 { 485 DECLARE_TEST_VARS; 486 487 c = presetup_ipv6(tc); 488 489 /* Create IPv6 subnetwork with smaller prefix */ 490 struct sockaddr_in6 mask6; 491 struct sockaddr_in6 net6; 492 struct sockaddr_in6 gw6; 493 prepare_v6_network(c, &net6, &mask6, &gw6); 494 495 prepare_route_message(rtm, RTM_ADD, (struct sockaddr *)&net6, 496 (struct sockaddr *)&mask6, (struct sockaddr *)&gw6); 497 498 rtsock_send_rtm(c->rtsock_fd, rtm); 499 rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq); 500 501 /* 502 * RTM_ADD: Add Route: len 200, pid: 46068, seq 42, errno 0, flags:<GATEWAY,DONE,STATIC> 503 * locks: inits: 504 * sockaddrs: <DST,GATEWAY,NETMASK> 505 * 192.0.2.0 192.0.2.254 255.255.255.128 506 */ 507 508 verify_route_message(rtm, RTM_ADD, (struct sockaddr *)&net6, 509 (struct sockaddr *)&mask6, (struct sockaddr *)&gw6); 510 511 /* XXX: Currently kernel sets RTF_UP automatically but does NOT report it in the reply */ 512 verify_route_message_extra(rtm, c->ifindex, RTF_DONE | RTF_GATEWAY | RTF_STATIC); 513 } 514 515 ATF_TC_CLEANUP(rtm_add_v6_gu_gw_gu_direct_success, tc) 516 { 517 CLEANUP_AFTER_TEST; 518 } 519 520 ATF_TC_WITH_CLEANUP(rtm_del_v6_gu_prefix_nogw_success); 521 ATF_TC_HEAD(rtm_del_v6_gu_prefix_nogw_success, tc) 522 { 523 524 DESCRIBE_ROOT_TEST("Tests IPv6 global unicast prefix removal without specifying gateway"); 525 } 526 527 ATF_TC_BODY(rtm_del_v6_gu_prefix_nogw_success, tc) 528 { 529 DECLARE_TEST_VARS; 530 531 c = presetup_ipv6(tc); 532 533 /* Create IPv6 subnetwork with smaller prefix */ 534 struct sockaddr_in6 mask6; 535 struct sockaddr_in6 net6; 536 struct sockaddr_in6 gw6; 537 prepare_v6_network(c, &net6, &mask6, &gw6); 538 539 prepare_route_message(rtm, RTM_ADD, (struct sockaddr *)&net6, 540 (struct sockaddr *)&mask6, (struct sockaddr *)&gw6); 541 542 rtsock_send_rtm(c->rtsock_fd, rtm); 543 544 /* Route has been added successfully, try to delete it */ 545 prepare_route_message(rtm, RTM_DELETE, (struct sockaddr *)&net6, 546 (struct sockaddr *)&mask6, NULL); 547 548 rtsock_send_rtm(c->rtsock_fd, rtm); 549 rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq); 550 551 /* 552 * RTM_DELETE: Delete Route: len 200, pid: 46417, seq 43, errno 0, flags: <GATEWAY,DONE,STATIC> 553 * sockaddrs: 0x7 <DST,GATEWAY,NETMASK> 554 * af=inet len=16 addr=192.0.2.0 hd={10, 02, 00{2}, C0, 00, 02, 00{9}} 555 * af=inet len=16 addr=192.0.2.254 hd={10, 02, 00{2}, C0, 00, 02, FE, 00{8}} 556 * af=inet len=16 addr=255.255.255.128 hd={10, 02, FF{5}, 80, 00{8}} 557 */ 558 559 verify_route_message(rtm, RTM_DELETE, (struct sockaddr *)&net6, 560 (struct sockaddr *)&mask6, (struct sockaddr *)&gw6); 561 verify_route_message_extra(rtm, c->ifindex, RTF_DONE | RTF_GATEWAY | RTF_STATIC); 562 } 563 564 ATF_TC_CLEANUP(rtm_del_v6_gu_prefix_nogw_success, tc) 565 { 566 CLEANUP_AFTER_TEST; 567 } 568 569 ATF_TC_WITH_CLEANUP(rtm_add_v4_temporal1_success); 570 ATF_TC_HEAD(rtm_add_v4_temporal1_success, tc) 571 { 572 DESCRIBE_ROOT_TEST("Tests IPv4 route expiration with expire time set"); 573 } 574 575 ATF_TC_BODY(rtm_add_v4_temporal1_success, tc) 576 { 577 DECLARE_TEST_VARS; 578 579 c = presetup_ipv4(tc); 580 581 /* Create IPv4 subnetwork with smaller prefix */ 582 struct sockaddr_in mask4; 583 struct sockaddr_in net4; 584 struct sockaddr_in gw4; 585 prepare_v4_network(c, &net4, &mask4, &gw4); 586 587 prepare_route_message(rtm, RTM_ADD, (struct sockaddr *)&net4, 588 (struct sockaddr *)&mask4, (struct sockaddr *)&gw4); 589 590 /* Set expire time to now */ 591 struct timeval tv; 592 gettimeofday(&tv, NULL); 593 rtm->rtm_rmx.rmx_expire = tv.tv_sec - 1; 594 rtm->rtm_inits |= RTV_EXPIRE; 595 596 rtsock_send_rtm(c->rtsock_fd, rtm); 597 rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq); 598 ATF_REQUIRE_MSG(rtm != NULL, "unable to get rtsock reply for RTM_ADD"); 599 RTSOCK_ATF_REQUIRE_MSG(rtm, rtm->rtm_inits & RTV_EXPIRE, "RTV_EXPIRE not set"); 600 601 /* The next should be route deletion */ 602 rtm = rtsock_read_rtm(c->rtsock_fd, buffer, sizeof(buffer)); 603 604 verify_route_message(rtm, RTM_DELETE, (struct sockaddr *)&net4, 605 (struct sockaddr *)&mask4, (struct sockaddr *)&gw4); 606 607 verify_route_message_extra(rtm, c->ifindex, RTF_GATEWAY | RTF_DONE | RTF_STATIC); 608 } 609 610 ATF_TC_CLEANUP(rtm_add_v4_temporal1_success, tc) 611 { 612 CLEANUP_AFTER_TEST; 613 } 614 615 ATF_TC_WITH_CLEANUP(rtm_add_v6_temporal1_success); 616 ATF_TC_HEAD(rtm_add_v6_temporal1_success, tc) 617 { 618 DESCRIBE_ROOT_TEST("Tests IPv6 global unicast prefix addition with directly-reachable GU GW"); 619 } 620 621 ATF_TC_BODY(rtm_add_v6_temporal1_success, tc) 622 { 623 DECLARE_TEST_VARS; 624 625 c = presetup_ipv6(tc); 626 627 /* Create IPv6 subnetwork with smaller prefix */ 628 struct sockaddr_in6 mask6; 629 struct sockaddr_in6 net6; 630 struct sockaddr_in6 gw6; 631 prepare_v6_network(c, &net6, &mask6, &gw6); 632 633 prepare_route_message(rtm, RTM_ADD, (struct sockaddr *)&net6, 634 (struct sockaddr *)&mask6, (struct sockaddr *)&gw6); 635 636 /* Set expire time to now */ 637 struct timeval tv; 638 gettimeofday(&tv, NULL); 639 rtm->rtm_rmx.rmx_expire = tv.tv_sec - 1; 640 rtm->rtm_inits |= RTV_EXPIRE; 641 642 rtsock_send_rtm(c->rtsock_fd, rtm); 643 rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq); 644 ATF_REQUIRE_MSG(rtm != NULL, "unable to get rtsock reply for RTM_ADD"); 645 RTSOCK_ATF_REQUIRE_MSG(rtm, rtm->rtm_inits & RTV_EXPIRE, "RTV_EXPIRE not set"); 646 647 /* The next should be route deletion */ 648 rtm = rtsock_read_rtm(c->rtsock_fd, buffer, sizeof(buffer)); 649 650 verify_route_message(rtm, RTM_DELETE, (struct sockaddr *)&net6, 651 (struct sockaddr *)&mask6, (struct sockaddr *)&gw6); 652 653 654 /* XXX: Currently kernel sets RTF_UP automatically but does NOT report it in the reply */ 655 verify_route_message_extra(rtm, c->ifindex, RTF_GATEWAY | RTF_DONE | RTF_STATIC); 656 } 657 658 ATF_TC_CLEANUP(rtm_add_v6_temporal1_success, tc) 659 { 660 CLEANUP_AFTER_TEST; 661 } 662 663 /* Interface address messages tests */ 664 665 RTM_DECLARE_ROOT_TEST(rtm_add_v6_gu_ifa_hostroute_success, 666 "Tests validness for /128 host route announce after ifaddr assignment"); 667 668 ATF_TC_BODY(rtm_add_v6_gu_ifa_hostroute_success, tc) 669 { 670 DECLARE_TEST_VARS; 671 672 c = presetup_ipv6_iface(tc); 673 674 c->rtsock_fd = rtsock_setup_socket(); 675 676 ret = iface_setup_addr(c->ifname, c->addr6_str, c->plen6); 677 678 /* 679 * There will be multiple. 680 * RTM_ADD without llinfo. 681 */ 682 683 while (true) { 684 rtm = rtsock_read_rtm(c->rtsock_fd, buffer, sizeof(buffer)); 685 if ((rtm->rtm_type == RTM_ADD) && ((rtm->rtm_flags & RTF_LLINFO) == 0)) 686 break; 687 } 688 /* This should be a message for the host route */ 689 690 verify_route_message(rtm, RTM_ADD, (struct sockaddr *)&c->addr6, NULL, NULL); 691 rtsock_validate_pid_kernel(rtm); 692 /* No netmask should be set */ 693 RTSOCK_ATF_REQUIRE_MSG(rtm, rtsock_find_rtm_sa(rtm, RTA_NETMASK) == NULL, "netmask is set"); 694 695 /* gateway should be link sdl with ifindex of an address interface */ 696 verify_link_gateway(rtm, c->ifindex); 697 698 int expected_rt_flags = RTF_UP | RTF_HOST | RTF_DONE | RTF_STATIC | RTF_PINNED; 699 verify_route_message_extra(rtm, if_nametoindex("lo0"), expected_rt_flags); 700 } 701 702 RTM_DECLARE_ROOT_TEST(rtm_add_v6_gu_ifa_prefixroute_success, 703 "Tests validness for the prefix route announce after ifaddr assignment"); 704 705 ATF_TC_BODY(rtm_add_v6_gu_ifa_prefixroute_success, tc) 706 { 707 DECLARE_TEST_VARS; 708 709 c = presetup_ipv6_iface(tc); 710 711 c->rtsock_fd = rtsock_setup_socket(); 712 713 ret = iface_setup_addr(c->ifname, c->addr6_str, c->plen6); 714 715 /* 716 * Multiple RTM_ADD messages will be generated: 717 * 1) lladdr mapping (RTF_LLDATA) 718 * 2) host route (one w/o netmask) 719 * 3) prefix route 720 */ 721 722 while (true) { 723 rtm = rtsock_read_rtm(c->rtsock_fd, buffer, sizeof(buffer)); 724 /* Find RTM_ADD with netmask - this should skip both host route and LLADDR */ 725 if ((rtm->rtm_type == RTM_ADD) && (rtsock_find_rtm_sa(rtm, RTA_NETMASK))) 726 break; 727 } 728 729 /* This should be a message for the prefix route */ 730 verify_route_message(rtm, RTM_ADD, (struct sockaddr *)&c->net6, 731 (struct sockaddr *)&c->mask6, NULL); 732 733 /* gateway should be link sdl with ifindex of an address interface */ 734 verify_link_gateway(rtm, c->ifindex); 735 736 /* TODO: PINNED? */ 737 int expected_rt_flags = RTF_UP | RTF_DONE; 738 verify_route_message_extra(rtm, c->ifindex, expected_rt_flags); 739 } 740 741 RTM_DECLARE_ROOT_TEST(rtm_add_v6_gu_ifa_ordered_success, 742 "Tests ordering of the messages for IPv6 global unicast ifaddr assignment"); 743 744 ATF_TC_BODY(rtm_add_v6_gu_ifa_ordered_success, tc) 745 { 746 DECLARE_TEST_VARS; 747 748 c = presetup_ipv6_iface(tc); 749 750 c->rtsock_fd = rtsock_setup_socket(); 751 752 ret = iface_setup_addr(c->ifname, c->addr6_str, c->plen6); 753 754 int count = 0, tries = 0; 755 756 enum msgtype { 757 MSG_IFADDR, 758 MSG_HOSTROUTE, 759 MSG_PREFIXROUTE, 760 MSG_MAX, 761 }; 762 763 int msg_array[MSG_MAX]; 764 765 bzero(msg_array, sizeof(msg_array)); 766 767 while (count < 3 && tries < 20) { 768 rtm = rtsock_read_rtm(c->rtsock_fd, buffer, sizeof(buffer)); 769 tries++; 770 /* Classify */ 771 if (rtm->rtm_type == RTM_NEWADDR) { 772 RLOG("MSG_IFADDR: %d", count); 773 msg_array[MSG_IFADDR] = count++; 774 continue; 775 } 776 777 /* Find RTM_ADD with netmask - this should skip both host route and LLADDR */ 778 if ((rtm->rtm_type == RTM_ADD) && (rtsock_find_rtm_sa(rtm, RTA_NETMASK))) { 779 RLOG("MSG_PREFIXROUTE: %d", count); 780 msg_array[MSG_PREFIXROUTE] = count++; 781 continue; 782 } 783 784 if ((rtm->rtm_type == RTM_ADD) && ((rtm->rtm_flags & RTF_LLDATA) == 0)) { 785 RLOG("MSG_HOSTROUTE: %d", count); 786 msg_array[MSG_HOSTROUTE] = count++; 787 continue; 788 } 789 790 RLOG("skipping msg type %s, try: %d", rtsock_print_cmdtype(rtm->rtm_type), 791 tries); 792 } 793 794 /* TODO: verify multicast */ 795 ATF_REQUIRE_MSG(count == 3, "Received only %d/3 messages", count); 796 ATF_REQUIRE_MSG(msg_array[MSG_IFADDR] == 0, "ifaddr message is not the first"); 797 } 798 799 RTM_DECLARE_ROOT_TEST(rtm_del_v6_gu_ifa_hostroute_success, 800 "Tests validness for /128 host route removal after ifaddr removal"); 801 802 ATF_TC_BODY(rtm_del_v6_gu_ifa_hostroute_success, tc) 803 { 804 DECLARE_TEST_VARS; 805 806 c = presetup_ipv6_iface(tc); 807 808 ret = iface_setup_addr(c->ifname, c->addr6_str, c->plen6); 809 810 c->rtsock_fd = rtsock_setup_socket(); 811 812 ret = iface_delete_addr(c->ifname, c->addr6_str); 813 814 while (true) { 815 rtm = rtsock_read_rtm(c->rtsock_fd, buffer, sizeof(buffer)); 816 if ((rtm->rtm_type == RTM_DELETE) && 817 ((rtm->rtm_flags & RTF_LLINFO) == 0) && 818 rtsock_find_rtm_sa(rtm, RTA_NETMASK) == NULL) 819 break; 820 } 821 /* This should be a message for the host route */ 822 823 verify_route_message(rtm, RTM_DELETE, (struct sockaddr *)&c->addr6, NULL, NULL); 824 rtsock_validate_pid_kernel(rtm); 825 /* No netmask should be set */ 826 RTSOCK_ATF_REQUIRE_MSG(rtm, rtsock_find_rtm_sa(rtm, RTA_NETMASK) == NULL, "netmask is set"); 827 828 /* gateway should be link sdl with ifindex of an address interface */ 829 verify_link_gateway(rtm, c->ifindex); 830 831 /* XXX: consider passing ifindex in rtm_index as done in RTM_ADD. */ 832 int expected_rt_flags = RTF_HOST | RTF_DONE | RTF_STATIC | RTF_PINNED; 833 RTSOCK_ATF_REQUIRE_MSG(rtm, rtm->rtm_flags == expected_rt_flags, 834 "expected rtm flags: 0x%X, got 0x%X", expected_rt_flags, rtm->rtm_flags); 835 } 836 837 RTM_DECLARE_ROOT_TEST(rtm_del_v6_gu_ifa_prefixroute_success, 838 "Tests validness for the prefix route removal after ifaddr assignment"); 839 840 ATF_TC_BODY(rtm_del_v6_gu_ifa_prefixroute_success, tc) 841 { 842 DECLARE_TEST_VARS; 843 844 c = presetup_ipv6_iface(tc); 845 846 ret = iface_setup_addr(c->ifname, c->addr6_str, c->plen6); 847 848 c->rtsock_fd = rtsock_setup_socket(); 849 850 ret = iface_delete_addr(c->ifname, c->addr6_str); 851 852 while (true) { 853 rtm = rtsock_read_rtm(c->rtsock_fd, buffer, sizeof(buffer)); 854 /* Find RTM_DELETE with netmask - this should skip both host route and LLADDR */ 855 if ((rtm->rtm_type == RTM_DELETE) && (rtsock_find_rtm_sa(rtm, RTA_NETMASK))) 856 break; 857 } 858 859 /* This should be a message for the prefix route */ 860 verify_route_message(rtm, RTM_DELETE, (struct sockaddr *)&c->net6, 861 (struct sockaddr *)&c->mask6, NULL); 862 863 /* gateway should be link sdl with ifindex of an address interface */ 864 verify_link_gateway(rtm, c->ifindex); 865 866 int expected_rt_flags = RTF_DONE; 867 verify_route_message_extra(rtm, c->ifindex, expected_rt_flags); 868 } 869 870 RTM_DECLARE_ROOT_TEST(rtm_add_v4_gu_ifa_prefixroute_success, 871 "Tests validness for the prefix route announce after ifaddr assignment"); 872 873 ATF_TC_BODY(rtm_add_v4_gu_ifa_prefixroute_success, tc) 874 { 875 DECLARE_TEST_VARS; 876 877 c = presetup_ipv4_iface(tc); 878 879 c->rtsock_fd = rtsock_setup_socket(); 880 881 ret = iface_setup_addr(c->ifname, c->addr6_str, c->plen6); 882 883 /* 884 * Multiple RTM_ADD messages will be generated: 885 * 1) lladdr mapping (RTF_LLDATA) 886 * 3) prefix route 887 */ 888 889 while (true) { 890 rtm = rtsock_read_rtm(c->rtsock_fd, buffer, sizeof(buffer)); 891 /* Find RTM_ADD with netmask - this should skip both host route and LLADDR */ 892 if ((rtm->rtm_type == RTM_ADD) && (rtsock_find_rtm_sa(rtm, RTA_NETMASK))) 893 break; 894 } 895 896 /* This should be a message for the prefix route */ 897 verify_route_message(rtm, RTM_ADD, (struct sockaddr *)&c->net4, 898 (struct sockaddr *)&c->mask4, NULL); 899 900 /* gateway should be link sdl with ifindex of an address interface */ 901 verify_link_gateway(rtm, c->ifindex); 902 903 int expected_rt_flags = RTF_UP | RTF_DONE | RTF_PINNED; 904 verify_route_message_extra(rtm, c->ifindex, expected_rt_flags); 905 } 906 907 RTM_DECLARE_ROOT_TEST(rtm_add_v4_gu_ifa_ordered_success, 908 "Tests ordering of the messages for IPv4 unicast ifaddr assignment"); 909 910 ATF_TC_BODY(rtm_add_v4_gu_ifa_ordered_success, tc) 911 { 912 DECLARE_TEST_VARS; 913 914 c = presetup_ipv4_iface(tc); 915 916 c->rtsock_fd = rtsock_setup_socket(); 917 918 ret = iface_setup_addr(c->ifname, c->addr4_str, c->plen4); 919 920 int count = 0, tries = 0; 921 922 enum msgtype { 923 MSG_IFADDR, 924 MSG_PREFIXROUTE, 925 MSG_MAX, 926 }; 927 928 int msg_array[MSG_MAX]; 929 930 bzero(msg_array, sizeof(msg_array)); 931 932 while (count < 2 && tries < 20) { 933 rtm = rtsock_read_rtm(c->rtsock_fd, buffer, sizeof(buffer)); 934 tries++; 935 /* Classify */ 936 if (rtm->rtm_type == RTM_NEWADDR) { 937 RLOG("MSG_IFADDR: %d", count); 938 msg_array[MSG_IFADDR] = count++; 939 continue; 940 } 941 942 /* Find RTM_ADD with netmask - this should skip both host route and LLADDR */ 943 if ((rtm->rtm_type == RTM_ADD) && (rtsock_find_rtm_sa(rtm, RTA_NETMASK))) { 944 RLOG("MSG_PREFIXROUTE: %d", count); 945 msg_array[MSG_PREFIXROUTE] = count++; 946 continue; 947 } 948 949 RLOG("skipping msg type %s, try: %d", rtsock_print_cmdtype(rtm->rtm_type), 950 tries); 951 } 952 953 /* TODO: verify multicast */ 954 ATF_REQUIRE_MSG(count == 2, "Received only %d/2 messages", count); 955 ATF_REQUIRE_MSG(msg_array[MSG_IFADDR] == 0, "ifaddr message is not the first"); 956 } 957 958 RTM_DECLARE_ROOT_TEST(rtm_del_v4_gu_ifa_prefixroute_success, 959 "Tests validness for the prefix route removal after ifaddr assignment"); 960 961 ATF_TC_BODY(rtm_del_v4_gu_ifa_prefixroute_success, tc) 962 { 963 DECLARE_TEST_VARS; 964 965 c = presetup_ipv4_iface(tc); 966 967 968 ret = iface_setup_addr(c->ifname, c->addr4_str, c->plen4); 969 970 c->rtsock_fd = rtsock_setup_socket(); 971 972 ret = iface_delete_addr(c->ifname, c->addr4_str); 973 974 while (true) { 975 rtm = rtsock_read_rtm(c->rtsock_fd, buffer, sizeof(buffer)); 976 /* Find RTM_ADD with netmask - this should skip both host route and LLADDR */ 977 if ((rtm->rtm_type == RTM_DELETE) && (rtsock_find_rtm_sa(rtm, RTA_NETMASK))) 978 break; 979 } 980 981 /* This should be a message for the prefix route */ 982 verify_route_message(rtm, RTM_DELETE, (struct sockaddr *)&c->net4, 983 (struct sockaddr *)&c->mask4, NULL); 984 985 /* gateway should be link sdl with ifindex of an address interface */ 986 verify_link_gateway(rtm, c->ifindex); 987 988 int expected_rt_flags = RTF_DONE | RTF_PINNED; 989 verify_route_message_extra(rtm, c->ifindex, expected_rt_flags); 990 } 991 992 993 ATF_TP_ADD_TCS(tp) 994 { 995 ATF_TP_ADD_TC(tp, rtm_get_v4_exact_success); 996 ATF_TP_ADD_TC(tp, rtm_get_v4_lpm_success); 997 ATF_TP_ADD_TC(tp, rtm_get_v4_hostbits_failure); 998 ATF_TP_ADD_TC(tp, rtm_get_v4_empty_dst_failure); 999 ATF_TP_ADD_TC(tp, rtm_add_v4_gw_direct_success); 1000 ATF_TP_ADD_TC(tp, rtm_del_v4_prefix_nogw_success); 1001 ATF_TP_ADD_TC(tp, rtm_add_v6_gu_gw_gu_direct_success); 1002 ATF_TP_ADD_TC(tp, rtm_del_v6_gu_prefix_nogw_success); 1003 /* ifaddr tests */ 1004 ATF_TP_ADD_TC(tp, rtm_add_v6_gu_ifa_hostroute_success); 1005 ATF_TP_ADD_TC(tp, rtm_add_v6_gu_ifa_prefixroute_success); 1006 ATF_TP_ADD_TC(tp, rtm_add_v6_gu_ifa_ordered_success); 1007 ATF_TP_ADD_TC(tp, rtm_del_v6_gu_ifa_hostroute_success); 1008 ATF_TP_ADD_TC(tp, rtm_del_v6_gu_ifa_prefixroute_success); 1009 ATF_TP_ADD_TC(tp, rtm_add_v4_gu_ifa_ordered_success); 1010 ATF_TP_ADD_TC(tp, rtm_del_v4_gu_ifa_prefixroute_success); 1011 /* temporal routes */ 1012 ATF_TP_ADD_TC(tp, rtm_add_v4_temporal1_success); 1013 ATF_TP_ADD_TC(tp, rtm_add_v6_temporal1_success); 1014 1015 return (atf_no_error()); 1016 } 1017 1018