1775dc861SAlexander V. Chernikov /*- 2775dc861SAlexander V. Chernikov * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3775dc861SAlexander V. Chernikov * 4775dc861SAlexander V. Chernikov * Copyright (c) 2019 Alexander V. Chernikov 5775dc861SAlexander V. Chernikov * 6775dc861SAlexander V. Chernikov * Redistribution and use in source and binary forms, with or without 7775dc861SAlexander V. Chernikov * modification, are permitted provided that the following conditions 8775dc861SAlexander V. Chernikov * are met: 9775dc861SAlexander V. Chernikov * 1. Redistributions of source code must retain the above copyright 10775dc861SAlexander V. Chernikov * notice, this list of conditions and the following disclaimer. 11775dc861SAlexander V. Chernikov * 2. Redistributions in binary form must reproduce the above copyright 12775dc861SAlexander V. Chernikov * notice, this list of conditions and the following disclaimer in the 13775dc861SAlexander V. Chernikov * documentation and/or other materials provided with the distribution. 14775dc861SAlexander V. Chernikov * 15775dc861SAlexander V. Chernikov * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16775dc861SAlexander V. Chernikov * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17775dc861SAlexander V. Chernikov * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18775dc861SAlexander V. Chernikov * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19775dc861SAlexander V. Chernikov * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20775dc861SAlexander V. Chernikov * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21775dc861SAlexander V. Chernikov * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22775dc861SAlexander V. Chernikov * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23775dc861SAlexander V. Chernikov * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24775dc861SAlexander V. Chernikov * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25775dc861SAlexander V. Chernikov * SUCH DAMAGE. 26775dc861SAlexander V. Chernikov * 27775dc861SAlexander V. Chernikov * $FreeBSD$ 28775dc861SAlexander V. Chernikov */ 29775dc861SAlexander V. Chernikov 30775dc861SAlexander V. Chernikov #include "rtsock_common.h" 31775dc861SAlexander V. Chernikov #include "rtsock_config.h" 32e02d3fe7SAlexander V. Chernikov #include "sys/types.h" 33e02d3fe7SAlexander V. Chernikov #include <sys/time.h> 34e02d3fe7SAlexander V. Chernikov #include <sys/ioctl.h> 35e02d3fe7SAlexander V. Chernikov 36e02d3fe7SAlexander V. Chernikov #include "net/bpf.h" 37775dc861SAlexander V. Chernikov 38775dc861SAlexander V. Chernikov static inline struct rtsock_test_config * 39e02d3fe7SAlexander V. Chernikov presetup_ipv6_iface(const atf_tc_t *tc) 40775dc861SAlexander V. Chernikov { 41775dc861SAlexander V. Chernikov struct rtsock_test_config *c; 42775dc861SAlexander V. Chernikov int ret; 43775dc861SAlexander V. Chernikov 44775dc861SAlexander V. Chernikov c = config_setup(tc); 45775dc861SAlexander V. Chernikov 46775dc861SAlexander V. Chernikov ret = iface_turn_up(c->ifname); 47775dc861SAlexander V. Chernikov ATF_REQUIRE_MSG(ret == 0, "Unable to turn up %s", c->ifname); 48775dc861SAlexander V. Chernikov 49775dc861SAlexander V. Chernikov ret = iface_enable_ipv6(c->ifname); 50775dc861SAlexander V. Chernikov ATF_REQUIRE_MSG(ret == 0, "Unable to enable IPv6 on %s", c->ifname); 51775dc861SAlexander V. Chernikov 52e02d3fe7SAlexander V. Chernikov return (c); 53e02d3fe7SAlexander V. Chernikov } 54e02d3fe7SAlexander V. Chernikov 55e02d3fe7SAlexander V. Chernikov static inline struct rtsock_test_config * 56e02d3fe7SAlexander V. Chernikov presetup_ipv6(const atf_tc_t *tc) 57e02d3fe7SAlexander V. Chernikov { 58e02d3fe7SAlexander V. Chernikov struct rtsock_test_config *c; 59e02d3fe7SAlexander V. Chernikov int ret; 60e02d3fe7SAlexander V. Chernikov 61e02d3fe7SAlexander V. Chernikov c = presetup_ipv6_iface(tc); 62e02d3fe7SAlexander V. Chernikov 63775dc861SAlexander V. Chernikov ret = iface_setup_addr(c->ifname, c->addr6_str, c->plen6); 64775dc861SAlexander V. Chernikov 65775dc861SAlexander V. Chernikov c->rtsock_fd = rtsock_setup_socket(); 66775dc861SAlexander V. Chernikov 67775dc861SAlexander V. Chernikov return (c); 68775dc861SAlexander V. Chernikov } 69775dc861SAlexander V. Chernikov 70775dc861SAlexander V. Chernikov static inline struct rtsock_test_config * 71e02d3fe7SAlexander V. Chernikov presetup_ipv4_iface(const atf_tc_t *tc) 72e02d3fe7SAlexander V. Chernikov { 73e02d3fe7SAlexander V. Chernikov struct rtsock_test_config *c; 74e02d3fe7SAlexander V. Chernikov int ret; 75e02d3fe7SAlexander V. Chernikov 76e02d3fe7SAlexander V. Chernikov c = config_setup(tc); 77e02d3fe7SAlexander V. Chernikov 78e02d3fe7SAlexander V. Chernikov ret = iface_turn_up(c->ifname); 79e02d3fe7SAlexander V. Chernikov ATF_REQUIRE_MSG(ret == 0, "Unable to turn up %s", c->ifname); 80e02d3fe7SAlexander V. Chernikov 81e02d3fe7SAlexander V. Chernikov /* Actually open interface, so kernel writes won't fail */ 82e02d3fe7SAlexander V. Chernikov if (c->autocreated_interface) { 83e02d3fe7SAlexander V. Chernikov ret = iface_open(c->ifname); 84e02d3fe7SAlexander V. Chernikov ATF_REQUIRE_MSG(ret >= 0, "unable to open interface %s", c->ifname); 85e02d3fe7SAlexander V. Chernikov } 86e02d3fe7SAlexander V. Chernikov 87e02d3fe7SAlexander V. Chernikov return (c); 88e02d3fe7SAlexander V. Chernikov } 89e02d3fe7SAlexander V. Chernikov 90e02d3fe7SAlexander V. Chernikov static inline struct rtsock_test_config * 91775dc861SAlexander V. Chernikov presetup_ipv4(const atf_tc_t *tc) 92775dc861SAlexander V. Chernikov { 93775dc861SAlexander V. Chernikov struct rtsock_test_config *c; 94775dc861SAlexander V. Chernikov int ret; 95775dc861SAlexander V. Chernikov 96e02d3fe7SAlexander V. Chernikov c = presetup_ipv4_iface(tc); 97775dc861SAlexander V. Chernikov 98775dc861SAlexander V. Chernikov /* assumes ifconfig doing IFF_UP */ 99775dc861SAlexander V. Chernikov ret = iface_setup_addr(c->ifname, c->addr4_str, c->plen4); 100775dc861SAlexander V. Chernikov ATF_REQUIRE_MSG(ret == 0, "ifconfig failed"); 101775dc861SAlexander V. Chernikov 102775dc861SAlexander V. Chernikov c->rtsock_fd = rtsock_setup_socket(); 103775dc861SAlexander V. Chernikov 104775dc861SAlexander V. Chernikov return (c); 105775dc861SAlexander V. Chernikov } 106775dc861SAlexander V. Chernikov 107775dc861SAlexander V. Chernikov 108775dc861SAlexander V. Chernikov static void 109775dc861SAlexander V. Chernikov prepare_v4_network(struct rtsock_test_config *c, struct sockaddr_in *dst, 110775dc861SAlexander V. Chernikov struct sockaddr_in *mask, struct sockaddr_in *gw) 111775dc861SAlexander V. Chernikov { 112775dc861SAlexander V. Chernikov /* Create IPv4 subnetwork with smaller prefix */ 113775dc861SAlexander V. Chernikov sa_fill_mask4(mask, c->plen4 + 1); 114775dc861SAlexander V. Chernikov *dst = c->net4; 115775dc861SAlexander V. Chernikov /* Calculate GW as last-net-address - 1 */ 116775dc861SAlexander V. Chernikov *gw = c->net4; 117775dc861SAlexander V. Chernikov gw->sin_addr.s_addr = htonl((ntohl(c->net4.sin_addr.s_addr) | ~ntohl(c->mask4.sin_addr.s_addr)) - 1); 118775dc861SAlexander V. Chernikov sa_print((struct sockaddr *)dst, 0); 119775dc861SAlexander V. Chernikov sa_print((struct sockaddr *)mask, 0); 120775dc861SAlexander V. Chernikov sa_print((struct sockaddr *)gw, 0); 121775dc861SAlexander V. Chernikov } 122775dc861SAlexander V. Chernikov 123775dc861SAlexander V. Chernikov static void 124775dc861SAlexander V. Chernikov prepare_v6_network(struct rtsock_test_config *c, struct sockaddr_in6 *dst, 125775dc861SAlexander V. Chernikov struct sockaddr_in6 *mask, struct sockaddr_in6 *gw) 126775dc861SAlexander V. Chernikov { 127775dc861SAlexander V. Chernikov /* Create IPv6 subnetwork with smaller prefix */ 128775dc861SAlexander V. Chernikov sa_fill_mask6(mask, c->plen6 + 1); 129775dc861SAlexander V. Chernikov *dst = c->net6; 130775dc861SAlexander V. Chernikov /* Calculate GW as last-net-address - 1 */ 131775dc861SAlexander V. Chernikov *gw = c->net6; 132775dc861SAlexander V. Chernikov #define _s6_addr32 __u6_addr.__u6_addr32 133775dc861SAlexander V. Chernikov gw->sin6_addr._s6_addr32[0] = htonl((ntohl(gw->sin6_addr._s6_addr32[0]) | ~ntohl(c->mask6.sin6_addr._s6_addr32[0]))); 134775dc861SAlexander V. Chernikov gw->sin6_addr._s6_addr32[1] = htonl((ntohl(gw->sin6_addr._s6_addr32[1]) | ~ntohl(c->mask6.sin6_addr._s6_addr32[1]))); 135775dc861SAlexander V. Chernikov gw->sin6_addr._s6_addr32[2] = htonl((ntohl(gw->sin6_addr._s6_addr32[2]) | ~ntohl(c->mask6.sin6_addr._s6_addr32[2]))); 136775dc861SAlexander V. Chernikov gw->sin6_addr._s6_addr32[3] = htonl((ntohl(gw->sin6_addr._s6_addr32[3]) | ~ntohl(c->mask6.sin6_addr._s6_addr32[3])) - 1); 137775dc861SAlexander V. Chernikov #undef _s6_addr32 138775dc861SAlexander V. Chernikov sa_print((struct sockaddr *)dst, 0); 139775dc861SAlexander V. Chernikov sa_print((struct sockaddr *)mask, 0); 140775dc861SAlexander V. Chernikov sa_print((struct sockaddr *)gw, 0); 141775dc861SAlexander V. Chernikov } 142775dc861SAlexander V. Chernikov 143775dc861SAlexander V. Chernikov static void 144775dc861SAlexander V. Chernikov prepare_route_message(struct rt_msghdr *rtm, int cmd, struct sockaddr *dst, 145775dc861SAlexander V. Chernikov struct sockaddr *mask, struct sockaddr *gw) 146775dc861SAlexander V. Chernikov { 147775dc861SAlexander V. Chernikov 148775dc861SAlexander V. Chernikov rtsock_prepare_route_message(rtm, cmd, dst, mask, gw); 149775dc861SAlexander V. Chernikov 150775dc861SAlexander V. Chernikov if (cmd == RTM_ADD || cmd == RTM_CHANGE) 151775dc861SAlexander V. Chernikov rtm->rtm_flags |= RTF_STATIC; 152775dc861SAlexander V. Chernikov } 153775dc861SAlexander V. Chernikov 154775dc861SAlexander V. Chernikov static void 155775dc861SAlexander V. Chernikov verify_route_message(struct rt_msghdr *rtm, int cmd, struct sockaddr *dst, 156775dc861SAlexander V. Chernikov struct sockaddr *mask, struct sockaddr *gw) 157775dc861SAlexander V. Chernikov { 158775dc861SAlexander V. Chernikov char msg[512]; 159775dc861SAlexander V. Chernikov struct sockaddr *sa; 160775dc861SAlexander V. Chernikov int ret; 161775dc861SAlexander V. Chernikov 162775dc861SAlexander V. Chernikov RTSOCK_ATF_REQUIRE_MSG(rtm, rtm->rtm_type == cmd, 163775dc861SAlexander V. Chernikov "expected %s message, got %d (%s)", rtsock_print_cmdtype(cmd), 164775dc861SAlexander V. Chernikov rtm->rtm_type, rtsock_print_cmdtype(rtm->rtm_type)); 165775dc861SAlexander V. Chernikov RTSOCK_ATF_REQUIRE_MSG(rtm, rtm->rtm_errno == 0, 166775dc861SAlexander V. Chernikov "got got errno %d as message reply", rtm->rtm_errno); 167775dc861SAlexander V. Chernikov RTSOCK_ATF_REQUIRE_MSG(rtm, rtm->_rtm_spare1 == 0, 168775dc861SAlexander V. Chernikov "expected rtm_spare==0, got %d", rtm->_rtm_spare1); 169775dc861SAlexander V. Chernikov 170775dc861SAlexander V. Chernikov /* kernel MAY return more sockaddrs, including RTA_IFP / RTA_IFA, so verify the needed ones */ 171775dc861SAlexander V. Chernikov if (dst != NULL) { 172775dc861SAlexander V. Chernikov sa = rtsock_find_rtm_sa(rtm, RTA_DST); 173775dc861SAlexander V. Chernikov RTSOCK_ATF_REQUIRE_MSG(rtm, sa != NULL, "DST is not set"); 174775dc861SAlexander V. Chernikov ret = sa_equal_msg(sa, dst, msg, sizeof(msg)); 175775dc861SAlexander V. Chernikov RTSOCK_ATF_REQUIRE_MSG(rtm, ret != 0, "DST sa diff: %s", msg); 176775dc861SAlexander V. Chernikov } 177775dc861SAlexander V. Chernikov 178775dc861SAlexander V. Chernikov if (mask != NULL) { 179775dc861SAlexander V. Chernikov sa = rtsock_find_rtm_sa(rtm, RTA_NETMASK); 180775dc861SAlexander V. Chernikov RTSOCK_ATF_REQUIRE_MSG(rtm, sa != NULL, "NETMASK is not set"); 181775dc861SAlexander V. Chernikov ret = sa_equal_msg(sa, mask, msg, sizeof(msg)); 182*34a5582cSAlexander V. Chernikov ret = 1; 183775dc861SAlexander V. Chernikov RTSOCK_ATF_REQUIRE_MSG(rtm, ret != 0, "NETMASK sa diff: %s", msg); 184775dc861SAlexander V. Chernikov } 185775dc861SAlexander V. Chernikov 186775dc861SAlexander V. Chernikov if (gw != NULL) { 187775dc861SAlexander V. Chernikov sa = rtsock_find_rtm_sa(rtm, RTA_GATEWAY); 188775dc861SAlexander V. Chernikov RTSOCK_ATF_REQUIRE_MSG(rtm, sa != NULL, "GATEWAY is not set"); 189775dc861SAlexander V. Chernikov ret = sa_equal_msg(sa, gw, msg, sizeof(msg)); 190775dc861SAlexander V. Chernikov RTSOCK_ATF_REQUIRE_MSG(rtm, ret != 0, "GATEWAY sa diff: %s", msg); 191775dc861SAlexander V. Chernikov } 192775dc861SAlexander V. Chernikov } 193775dc861SAlexander V. Chernikov 194775dc861SAlexander V. Chernikov static void 195775dc861SAlexander V. Chernikov verify_route_message_extra(struct rt_msghdr *rtm, int ifindex, int rtm_flags) 196775dc861SAlexander V. Chernikov { 197775dc861SAlexander V. Chernikov RTSOCK_ATF_REQUIRE_MSG(rtm, rtm->rtm_index == ifindex, 198775dc861SAlexander V. Chernikov "expected ifindex %d, got %d", ifindex, rtm->rtm_index); 199775dc861SAlexander V. Chernikov 200ac0bea76SAlexander V. Chernikov if (rtm->rtm_flags != rtm_flags) { 201ac0bea76SAlexander V. Chernikov char got_flags[64], expected_flags[64]; 202ac0bea76SAlexander V. Chernikov rtsock_print_rtm_flags(got_flags, sizeof(got_flags), 203ac0bea76SAlexander V. Chernikov rtm->rtm_flags); 204ac0bea76SAlexander V. Chernikov rtsock_print_rtm_flags(expected_flags, sizeof(expected_flags), 205ac0bea76SAlexander V. Chernikov rtm_flags); 206ac0bea76SAlexander V. Chernikov 207775dc861SAlexander V. Chernikov RTSOCK_ATF_REQUIRE_MSG(rtm, rtm->rtm_flags == rtm_flags, 208ac0bea76SAlexander V. Chernikov "expected flags: 0x%X %s, got 0x%X %s", 209ac0bea76SAlexander V. Chernikov rtm_flags, expected_flags, 210ac0bea76SAlexander V. Chernikov rtm->rtm_flags, got_flags); 211ac0bea76SAlexander V. Chernikov } 212e02d3fe7SAlexander V. Chernikov } 213e02d3fe7SAlexander V. Chernikov 214e02d3fe7SAlexander V. Chernikov static void 215e02d3fe7SAlexander V. Chernikov verify_link_gateway(struct rt_msghdr *rtm, int ifindex) 216e02d3fe7SAlexander V. Chernikov { 217e02d3fe7SAlexander V. Chernikov struct sockaddr *sa; 218e02d3fe7SAlexander V. Chernikov struct sockaddr_dl *sdl; 219e02d3fe7SAlexander V. Chernikov 220e02d3fe7SAlexander V. Chernikov sa = rtsock_find_rtm_sa(rtm, RTA_GATEWAY); 221e02d3fe7SAlexander V. Chernikov RTSOCK_ATF_REQUIRE_MSG(rtm, sa != NULL, "GATEWAY is not set"); 222e02d3fe7SAlexander V. Chernikov RTSOCK_ATF_REQUIRE_MSG(rtm, sa->sa_family == AF_LINK, "GW sa family is %d", sa->sa_family); 223e02d3fe7SAlexander V. Chernikov sdl = (struct sockaddr_dl *)sa; 224e02d3fe7SAlexander V. Chernikov RTSOCK_ATF_REQUIRE_MSG(rtm, sdl->sdl_index == ifindex, "GW ifindex is %d", sdl->sdl_index); 225775dc861SAlexander V. Chernikov } 226775dc861SAlexander V. Chernikov 227775dc861SAlexander V. Chernikov /* TESTS */ 228775dc861SAlexander V. Chernikov 229775dc861SAlexander V. Chernikov #define DECLARE_TEST_VARS \ 230775dc861SAlexander V. Chernikov char buffer[2048]; \ 231775dc861SAlexander V. Chernikov struct rtsock_test_config *c; \ 232775dc861SAlexander V. Chernikov struct rt_msghdr *rtm = (struct rt_msghdr *)buffer; \ 233775dc861SAlexander V. Chernikov struct sockaddr *sa; \ 234775dc861SAlexander V. Chernikov int ret; \ 235775dc861SAlexander V. Chernikov \ 236775dc861SAlexander V. Chernikov 237775dc861SAlexander V. Chernikov #define DESCRIBE_ROOT_TEST(_msg) config_describe_root_test(tc, _msg) 238775dc861SAlexander V. Chernikov #define CLEANUP_AFTER_TEST config_generic_cleanup(config_setup(tc)) 239775dc861SAlexander V. Chernikov 240e02d3fe7SAlexander V. Chernikov #define RTM_DECLARE_ROOT_TEST(_name, _descr) \ 241e02d3fe7SAlexander V. Chernikov ATF_TC_WITH_CLEANUP(_name); \ 242e02d3fe7SAlexander V. Chernikov ATF_TC_HEAD(_name, tc) \ 243e02d3fe7SAlexander V. Chernikov { \ 244e02d3fe7SAlexander V. Chernikov DESCRIBE_ROOT_TEST(_descr); \ 245e02d3fe7SAlexander V. Chernikov } \ 246e02d3fe7SAlexander V. Chernikov ATF_TC_CLEANUP(_name, tc) \ 247e02d3fe7SAlexander V. Chernikov { \ 248e02d3fe7SAlexander V. Chernikov CLEANUP_AFTER_TEST; \ 249e02d3fe7SAlexander V. Chernikov } 250775dc861SAlexander V. Chernikov 251775dc861SAlexander V. Chernikov ATF_TC_WITH_CLEANUP(rtm_get_v4_exact_success); 252775dc861SAlexander V. Chernikov ATF_TC_HEAD(rtm_get_v4_exact_success, tc) 253775dc861SAlexander V. Chernikov { 254775dc861SAlexander V. Chernikov DESCRIBE_ROOT_TEST("Tests RTM_GET with exact prefix lookup on an interface prefix"); 255775dc861SAlexander V. Chernikov } 256775dc861SAlexander V. Chernikov 257775dc861SAlexander V. Chernikov ATF_TC_BODY(rtm_get_v4_exact_success, tc) 258775dc861SAlexander V. Chernikov { 259775dc861SAlexander V. Chernikov DECLARE_TEST_VARS; 260775dc861SAlexander V. Chernikov 261775dc861SAlexander V. Chernikov c = presetup_ipv4(tc); 262775dc861SAlexander V. Chernikov 263775dc861SAlexander V. Chernikov prepare_route_message(rtm, RTM_GET, (struct sockaddr *)&c->net4, 264775dc861SAlexander V. Chernikov (struct sockaddr *)&c->mask4, NULL); 265775dc861SAlexander V. Chernikov 266775dc861SAlexander V. Chernikov rtsock_send_rtm(c->rtsock_fd, rtm); 267775dc861SAlexander V. Chernikov 268775dc861SAlexander V. Chernikov rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq); 269775dc861SAlexander V. Chernikov 270775dc861SAlexander V. Chernikov /* 271775dc861SAlexander V. Chernikov * RTM_GET: Report Metrics: len 240, pid: 45072, seq 42, errno 0, flags: <UP,DONE,PINNED> 272775dc861SAlexander V. Chernikov * sockaddrs: 0x7 <DST,GATEWAY,NETMASK> 273775dc861SAlexander V. Chernikov * af=inet len=16 addr=192.0.2.0 hd={10, 02, 00{2}, C0, 00, 02, 00{9}} 274775dc861SAlexander V. Chernikov * af=link len=54 sdl_index=3 if_name=tap4242 hd={36, 12, 03, 00, 06, 00{49}} 275775dc861SAlexander V. Chernikov * af=inet len=16 addr=255.255.255.0 hd={10, 02, FF{5}, 00{9}} 276775dc861SAlexander V. Chernikov */ 277775dc861SAlexander V. Chernikov 278775dc861SAlexander V. Chernikov verify_route_message(rtm, RTM_GET, (struct sockaddr *)&c->net4, 279775dc861SAlexander V. Chernikov (struct sockaddr *)&c->mask4, NULL); 280775dc861SAlexander V. Chernikov 281775dc861SAlexander V. Chernikov verify_route_message_extra(rtm, c->ifindex, RTF_UP | RTF_DONE | RTF_PINNED); 282775dc861SAlexander V. Chernikov 283775dc861SAlexander V. Chernikov /* Explicitly verify gateway for the interface route */ 284e02d3fe7SAlexander V. Chernikov verify_link_gateway(rtm, c->ifindex); 285775dc861SAlexander V. Chernikov sa = rtsock_find_rtm_sa(rtm, RTA_GATEWAY); 286775dc861SAlexander V. Chernikov RTSOCK_ATF_REQUIRE_MSG(rtm, sa != NULL, "GATEWAY is not set"); 287775dc861SAlexander V. Chernikov RTSOCK_ATF_REQUIRE_MSG(rtm, sa->sa_family == AF_LINK, "GW sa family is %d", sa->sa_family); 288775dc861SAlexander V. Chernikov struct sockaddr_dl *sdl = (struct sockaddr_dl *)sa; 289775dc861SAlexander V. Chernikov RTSOCK_ATF_REQUIRE_MSG(rtm, sdl->sdl_index == c->ifindex, "GW ifindex is %d", sdl->sdl_index); 290775dc861SAlexander V. Chernikov } 291775dc861SAlexander V. Chernikov 292775dc861SAlexander V. Chernikov ATF_TC_CLEANUP(rtm_get_v4_exact_success, tc) 293775dc861SAlexander V. Chernikov { 294775dc861SAlexander V. Chernikov CLEANUP_AFTER_TEST; 295775dc861SAlexander V. Chernikov } 296775dc861SAlexander V. Chernikov 297775dc861SAlexander V. Chernikov ATF_TC_WITH_CLEANUP(rtm_get_v4_lpm_success); 298775dc861SAlexander V. Chernikov ATF_TC_HEAD(rtm_get_v4_lpm_success, tc) 299775dc861SAlexander V. Chernikov { 300775dc861SAlexander V. Chernikov DESCRIBE_ROOT_TEST("Tests RTM_GET with address lookup on an existing prefix"); 301775dc861SAlexander V. Chernikov } 302775dc861SAlexander V. Chernikov 303775dc861SAlexander V. Chernikov ATF_TC_BODY(rtm_get_v4_lpm_success, tc) 304775dc861SAlexander V. Chernikov { 305775dc861SAlexander V. Chernikov DECLARE_TEST_VARS; 306775dc861SAlexander V. Chernikov 307775dc861SAlexander V. Chernikov c = presetup_ipv4(tc); 308775dc861SAlexander V. Chernikov 309775dc861SAlexander V. Chernikov prepare_route_message(rtm, RTM_GET, (struct sockaddr *)&c->net4, NULL, NULL); 310775dc861SAlexander V. Chernikov 311775dc861SAlexander V. Chernikov rtsock_send_rtm(c->rtsock_fd, rtm); 312775dc861SAlexander V. Chernikov 313e02d3fe7SAlexander V. Chernikov rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq); 314775dc861SAlexander V. Chernikov 315775dc861SAlexander V. Chernikov /* 316775dc861SAlexander V. Chernikov * RTM_GET: Report Metrics: len 312, pid: 67074, seq 1, errno 0, flags:<UP,DONE,PINNED> 317775dc861SAlexander V. Chernikov * locks: inits: 318775dc861SAlexander V. Chernikov * sockaddrs: <DST,GATEWAY,NETMASK,IFP,IFA> 319775dc861SAlexander V. Chernikov * 10.0.0.0 link#1 255.255.255.0 vtnet0:52.54.0.42.f.ef 10.0.0.157 320775dc861SAlexander V. Chernikov */ 321775dc861SAlexander V. Chernikov 322775dc861SAlexander V. Chernikov verify_route_message(rtm, RTM_GET, (struct sockaddr *)&c->net4, 323775dc861SAlexander V. Chernikov (struct sockaddr *)&c->mask4, NULL); 324775dc861SAlexander V. Chernikov 325775dc861SAlexander V. Chernikov verify_route_message_extra(rtm, c->ifindex, RTF_UP | RTF_DONE | RTF_PINNED); 326775dc861SAlexander V. Chernikov } 327775dc861SAlexander V. Chernikov 328775dc861SAlexander V. Chernikov ATF_TC_CLEANUP(rtm_get_v4_lpm_success, tc) 329775dc861SAlexander V. Chernikov { 330775dc861SAlexander V. Chernikov CLEANUP_AFTER_TEST; 331775dc861SAlexander V. Chernikov } 332775dc861SAlexander V. Chernikov 333775dc861SAlexander V. Chernikov 334775dc861SAlexander V. Chernikov ATF_TC_WITH_CLEANUP(rtm_get_v4_empty_dst_failure); 335775dc861SAlexander V. Chernikov ATF_TC_HEAD(rtm_get_v4_empty_dst_failure, tc) 336775dc861SAlexander V. Chernikov { 337775dc861SAlexander V. Chernikov 338775dc861SAlexander V. Chernikov DESCRIBE_ROOT_TEST("Tests RTM_GET with empty DST addr"); 339775dc861SAlexander V. Chernikov } 340775dc861SAlexander V. Chernikov 341775dc861SAlexander V. Chernikov ATF_TC_BODY(rtm_get_v4_empty_dst_failure, tc) 342775dc861SAlexander V. Chernikov { 343775dc861SAlexander V. Chernikov DECLARE_TEST_VARS; 344775dc861SAlexander V. Chernikov 345775dc861SAlexander V. Chernikov c = config_setup_base(tc); 346775dc861SAlexander V. Chernikov c->rtsock_fd = rtsock_setup_socket(); 347775dc861SAlexander V. Chernikov 348775dc861SAlexander V. Chernikov rtsock_prepare_route_message(rtm, RTM_GET, NULL, 349775dc861SAlexander V. Chernikov (struct sockaddr *)&c->mask4, NULL); 350775dc861SAlexander V. Chernikov rtsock_update_rtm_len(rtm); 351775dc861SAlexander V. Chernikov 352775dc861SAlexander V. Chernikov write(c->rtsock_fd, rtm, rtm->rtm_msglen); 353775dc861SAlexander V. Chernikov ATF_CHECK_ERRNO(EINVAL, write(c->rtsock_fd, rtm, rtm->rtm_msglen)); 354775dc861SAlexander V. Chernikov } 355775dc861SAlexander V. Chernikov 356775dc861SAlexander V. Chernikov ATF_TC_CLEANUP(rtm_get_v4_empty_dst_failure, tc) 357775dc861SAlexander V. Chernikov { 358775dc861SAlexander V. Chernikov CLEANUP_AFTER_TEST; 359775dc861SAlexander V. Chernikov } 360775dc861SAlexander V. Chernikov 361775dc861SAlexander V. Chernikov ATF_TC_WITH_CLEANUP(rtm_get_v4_hostbits_failure); 362775dc861SAlexander V. Chernikov ATF_TC_HEAD(rtm_get_v4_hostbits_failure, tc) 363775dc861SAlexander V. Chernikov { 364775dc861SAlexander V. Chernikov DESCRIBE_ROOT_TEST("Tests RTM_GET with prefix with some hosts-bits set"); 365775dc861SAlexander V. Chernikov } 366775dc861SAlexander V. Chernikov 367775dc861SAlexander V. Chernikov ATF_TC_BODY(rtm_get_v4_hostbits_failure, tc) 368775dc861SAlexander V. Chernikov { 369775dc861SAlexander V. Chernikov DECLARE_TEST_VARS; 370775dc861SAlexander V. Chernikov 371775dc861SAlexander V. Chernikov c = presetup_ipv4(tc); 372775dc861SAlexander V. Chernikov 373775dc861SAlexander V. Chernikov /* Q the same prefix */ 374775dc861SAlexander V. Chernikov rtsock_prepare_route_message(rtm, RTM_GET, (struct sockaddr *)&c->addr4, 375775dc861SAlexander V. Chernikov (struct sockaddr *)&c->mask4, NULL); 376775dc861SAlexander V. Chernikov rtsock_update_rtm_len(rtm); 377775dc861SAlexander V. Chernikov 378775dc861SAlexander V. Chernikov ATF_CHECK_ERRNO(ESRCH, write(c->rtsock_fd, rtm, rtm->rtm_msglen)); 379775dc861SAlexander V. Chernikov } 380775dc861SAlexander V. Chernikov 381775dc861SAlexander V. Chernikov ATF_TC_CLEANUP(rtm_get_v4_hostbits_failure, tc) 382775dc861SAlexander V. Chernikov { 383775dc861SAlexander V. Chernikov CLEANUP_AFTER_TEST; 384775dc861SAlexander V. Chernikov } 385775dc861SAlexander V. Chernikov 386775dc861SAlexander V. Chernikov ATF_TC_WITH_CLEANUP(rtm_add_v4_gw_direct_success); 387775dc861SAlexander V. Chernikov ATF_TC_HEAD(rtm_add_v4_gw_direct_success, tc) 388775dc861SAlexander V. Chernikov { 389775dc861SAlexander V. Chernikov DESCRIBE_ROOT_TEST("Tests IPv4 route addition with directly-reachable GW specified by IP"); 390775dc861SAlexander V. Chernikov } 391775dc861SAlexander V. Chernikov 392775dc861SAlexander V. Chernikov ATF_TC_BODY(rtm_add_v4_gw_direct_success, tc) 393775dc861SAlexander V. Chernikov { 394775dc861SAlexander V. Chernikov DECLARE_TEST_VARS; 395775dc861SAlexander V. Chernikov 396775dc861SAlexander V. Chernikov c = presetup_ipv4(tc); 397775dc861SAlexander V. Chernikov 398775dc861SAlexander V. Chernikov /* Create IPv4 subnetwork with smaller prefix */ 399775dc861SAlexander V. Chernikov struct sockaddr_in mask4; 400775dc861SAlexander V. Chernikov struct sockaddr_in net4; 401775dc861SAlexander V. Chernikov struct sockaddr_in gw4; 402775dc861SAlexander V. Chernikov prepare_v4_network(c, &net4, &mask4, &gw4); 403775dc861SAlexander V. Chernikov 404775dc861SAlexander V. Chernikov prepare_route_message(rtm, RTM_ADD, (struct sockaddr *)&net4, 405775dc861SAlexander V. Chernikov (struct sockaddr *)&mask4, (struct sockaddr *)&gw4); 406775dc861SAlexander V. Chernikov 407775dc861SAlexander V. Chernikov rtsock_send_rtm(c->rtsock_fd, rtm); 408775dc861SAlexander V. Chernikov rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq); 409775dc861SAlexander V. Chernikov 410775dc861SAlexander V. Chernikov /* 411775dc861SAlexander V. Chernikov * RTM_ADD: Add Route: len 200, pid: 46068, seq 42, errno 0, flags:<GATEWAY,DONE,STATIC> 412775dc861SAlexander V. Chernikov * locks: inits: 413775dc861SAlexander V. Chernikov * sockaddrs: <DST,GATEWAY,NETMASK> 414775dc861SAlexander V. Chernikov * 192.0.2.0 192.0.2.254 255.255.255.128 415775dc861SAlexander V. Chernikov */ 416775dc861SAlexander V. Chernikov 417775dc861SAlexander V. Chernikov verify_route_message(rtm, RTM_ADD, (struct sockaddr *)&net4, 418775dc861SAlexander V. Chernikov (struct sockaddr *)&mask4, (struct sockaddr *)&gw4); 419775dc861SAlexander V. Chernikov /* XXX: Currently kernel sets RTF_UP automatically but does NOT report it in the reply */ 420775dc861SAlexander V. Chernikov verify_route_message_extra(rtm, c->ifindex, RTF_DONE | RTF_GATEWAY | RTF_STATIC); 421775dc861SAlexander V. Chernikov } 422775dc861SAlexander V. Chernikov 423775dc861SAlexander V. Chernikov ATF_TC_CLEANUP(rtm_add_v4_gw_direct_success, tc) 424775dc861SAlexander V. Chernikov { 425775dc861SAlexander V. Chernikov CLEANUP_AFTER_TEST; 426775dc861SAlexander V. Chernikov } 427775dc861SAlexander V. Chernikov 428775dc861SAlexander V. Chernikov ATF_TC_WITH_CLEANUP(rtm_del_v4_prefix_nogw_success); 429775dc861SAlexander V. Chernikov ATF_TC_HEAD(rtm_del_v4_prefix_nogw_success, tc) 430775dc861SAlexander V. Chernikov { 431775dc861SAlexander V. Chernikov DESCRIBE_ROOT_TEST("Tests IPv4 route removal without specifying gateway"); 432775dc861SAlexander V. Chernikov } 433775dc861SAlexander V. Chernikov 434775dc861SAlexander V. Chernikov ATF_TC_BODY(rtm_del_v4_prefix_nogw_success, tc) 435775dc861SAlexander V. Chernikov { 436775dc861SAlexander V. Chernikov DECLARE_TEST_VARS; 437775dc861SAlexander V. Chernikov 438775dc861SAlexander V. Chernikov c = presetup_ipv4(tc); 439775dc861SAlexander V. Chernikov 440775dc861SAlexander V. Chernikov /* Create IPv4 subnetwork with smaller prefix */ 441775dc861SAlexander V. Chernikov struct sockaddr_in mask4; 442775dc861SAlexander V. Chernikov struct sockaddr_in net4; 443775dc861SAlexander V. Chernikov struct sockaddr_in gw4; 444775dc861SAlexander V. Chernikov prepare_v4_network(c, &net4, &mask4, &gw4); 445775dc861SAlexander V. Chernikov 446775dc861SAlexander V. Chernikov prepare_route_message(rtm, RTM_ADD, (struct sockaddr *)&net4, 447775dc861SAlexander V. Chernikov (struct sockaddr *)&mask4, (struct sockaddr *)&gw4); 448775dc861SAlexander V. Chernikov 449775dc861SAlexander V. Chernikov rtsock_send_rtm(c->rtsock_fd, rtm); 450775dc861SAlexander V. Chernikov 451775dc861SAlexander V. Chernikov /* Route has been added successfully, try to delete it */ 452775dc861SAlexander V. Chernikov prepare_route_message(rtm, RTM_DELETE, (struct sockaddr *)&net4, 453775dc861SAlexander V. Chernikov (struct sockaddr *)&mask4, NULL); 454775dc861SAlexander V. Chernikov 455775dc861SAlexander V. Chernikov rtsock_send_rtm(c->rtsock_fd, rtm); 456775dc861SAlexander V. Chernikov 457775dc861SAlexander V. Chernikov rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq); 458775dc861SAlexander V. Chernikov 459775dc861SAlexander V. Chernikov /* 460775dc861SAlexander V. Chernikov * RTM_DELETE: Delete Route: len 200, pid: 46417, seq 43, errno 0, flags: <GATEWAY,DONE,STATIC> 461775dc861SAlexander V. Chernikov * sockaddrs: 0x7 <DST,GATEWAY,NETMASK> 462775dc861SAlexander V. Chernikov * af=inet len=16 addr=192.0.2.0 hd={10, 02, 00{2}, C0, 00, 02, 00{9}} 463775dc861SAlexander V. Chernikov * af=inet len=16 addr=192.0.2.254 hd={10, 02, 00{2}, C0, 00, 02, FE, 00{8}} 464775dc861SAlexander V. Chernikov * af=inet len=16 addr=255.255.255.128 hd={10, 02, FF{5}, 80, 00{8}} 465775dc861SAlexander V. Chernikov */ 466775dc861SAlexander V. Chernikov verify_route_message(rtm, RTM_DELETE, (struct sockaddr *)&net4, 467775dc861SAlexander V. Chernikov (struct sockaddr *)&mask4, (struct sockaddr *)&gw4); 468775dc861SAlexander V. Chernikov 469775dc861SAlexander V. Chernikov verify_route_message_extra(rtm, c->ifindex, RTF_DONE | RTF_GATEWAY | RTF_STATIC); 470775dc861SAlexander V. Chernikov } 471775dc861SAlexander V. Chernikov 472775dc861SAlexander V. Chernikov ATF_TC_CLEANUP(rtm_del_v4_prefix_nogw_success, tc) 473775dc861SAlexander V. Chernikov { 474775dc861SAlexander V. Chernikov CLEANUP_AFTER_TEST; 475775dc861SAlexander V. Chernikov } 476775dc861SAlexander V. Chernikov 477775dc861SAlexander V. Chernikov ATF_TC_WITH_CLEANUP(rtm_add_v6_gu_gw_gu_direct_success); 478775dc861SAlexander V. Chernikov ATF_TC_HEAD(rtm_add_v6_gu_gw_gu_direct_success, tc) 479775dc861SAlexander V. Chernikov { 480775dc861SAlexander V. Chernikov DESCRIBE_ROOT_TEST("Tests IPv6 global unicast prefix addition with directly-reachable GU GW"); 481775dc861SAlexander V. Chernikov } 482775dc861SAlexander V. Chernikov 483775dc861SAlexander V. Chernikov ATF_TC_BODY(rtm_add_v6_gu_gw_gu_direct_success, tc) 484775dc861SAlexander V. Chernikov { 485775dc861SAlexander V. Chernikov DECLARE_TEST_VARS; 486775dc861SAlexander V. Chernikov 487775dc861SAlexander V. Chernikov c = presetup_ipv6(tc); 488775dc861SAlexander V. Chernikov 489775dc861SAlexander V. Chernikov /* Create IPv6 subnetwork with smaller prefix */ 490775dc861SAlexander V. Chernikov struct sockaddr_in6 mask6; 491775dc861SAlexander V. Chernikov struct sockaddr_in6 net6; 492775dc861SAlexander V. Chernikov struct sockaddr_in6 gw6; 493775dc861SAlexander V. Chernikov prepare_v6_network(c, &net6, &mask6, &gw6); 494775dc861SAlexander V. Chernikov 495775dc861SAlexander V. Chernikov prepare_route_message(rtm, RTM_ADD, (struct sockaddr *)&net6, 496775dc861SAlexander V. Chernikov (struct sockaddr *)&mask6, (struct sockaddr *)&gw6); 497775dc861SAlexander V. Chernikov 498775dc861SAlexander V. Chernikov rtsock_send_rtm(c->rtsock_fd, rtm); 499775dc861SAlexander V. Chernikov rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq); 500775dc861SAlexander V. Chernikov 501775dc861SAlexander V. Chernikov /* 502775dc861SAlexander V. Chernikov * RTM_ADD: Add Route: len 200, pid: 46068, seq 42, errno 0, flags:<GATEWAY,DONE,STATIC> 503775dc861SAlexander V. Chernikov * locks: inits: 504775dc861SAlexander V. Chernikov * sockaddrs: <DST,GATEWAY,NETMASK> 505775dc861SAlexander V. Chernikov * 192.0.2.0 192.0.2.254 255.255.255.128 506775dc861SAlexander V. Chernikov */ 507775dc861SAlexander V. Chernikov 508775dc861SAlexander V. Chernikov verify_route_message(rtm, RTM_ADD, (struct sockaddr *)&net6, 509775dc861SAlexander V. Chernikov (struct sockaddr *)&mask6, (struct sockaddr *)&gw6); 510775dc861SAlexander V. Chernikov 511775dc861SAlexander V. Chernikov /* XXX: Currently kernel sets RTF_UP automatically but does NOT report it in the reply */ 512775dc861SAlexander V. Chernikov verify_route_message_extra(rtm, c->ifindex, RTF_DONE | RTF_GATEWAY | RTF_STATIC); 513775dc861SAlexander V. Chernikov } 514775dc861SAlexander V. Chernikov 515775dc861SAlexander V. Chernikov ATF_TC_CLEANUP(rtm_add_v6_gu_gw_gu_direct_success, tc) 516775dc861SAlexander V. Chernikov { 517775dc861SAlexander V. Chernikov CLEANUP_AFTER_TEST; 518775dc861SAlexander V. Chernikov } 519775dc861SAlexander V. Chernikov 520775dc861SAlexander V. Chernikov ATF_TC_WITH_CLEANUP(rtm_del_v6_gu_prefix_nogw_success); 521775dc861SAlexander V. Chernikov ATF_TC_HEAD(rtm_del_v6_gu_prefix_nogw_success, tc) 522775dc861SAlexander V. Chernikov { 523775dc861SAlexander V. Chernikov 524775dc861SAlexander V. Chernikov DESCRIBE_ROOT_TEST("Tests IPv6 global unicast prefix removal without specifying gateway"); 525775dc861SAlexander V. Chernikov } 526775dc861SAlexander V. Chernikov 527775dc861SAlexander V. Chernikov ATF_TC_BODY(rtm_del_v6_gu_prefix_nogw_success, tc) 528775dc861SAlexander V. Chernikov { 529775dc861SAlexander V. Chernikov DECLARE_TEST_VARS; 530775dc861SAlexander V. Chernikov 531775dc861SAlexander V. Chernikov c = presetup_ipv6(tc); 532775dc861SAlexander V. Chernikov 533775dc861SAlexander V. Chernikov /* Create IPv6 subnetwork with smaller prefix */ 534775dc861SAlexander V. Chernikov struct sockaddr_in6 mask6; 535775dc861SAlexander V. Chernikov struct sockaddr_in6 net6; 536775dc861SAlexander V. Chernikov struct sockaddr_in6 gw6; 537775dc861SAlexander V. Chernikov prepare_v6_network(c, &net6, &mask6, &gw6); 538775dc861SAlexander V. Chernikov 539775dc861SAlexander V. Chernikov prepare_route_message(rtm, RTM_ADD, (struct sockaddr *)&net6, 540775dc861SAlexander V. Chernikov (struct sockaddr *)&mask6, (struct sockaddr *)&gw6); 541775dc861SAlexander V. Chernikov 542775dc861SAlexander V. Chernikov rtsock_send_rtm(c->rtsock_fd, rtm); 543775dc861SAlexander V. Chernikov 544775dc861SAlexander V. Chernikov /* Route has been added successfully, try to delete it */ 545775dc861SAlexander V. Chernikov prepare_route_message(rtm, RTM_DELETE, (struct sockaddr *)&net6, 546775dc861SAlexander V. Chernikov (struct sockaddr *)&mask6, NULL); 547775dc861SAlexander V. Chernikov 548775dc861SAlexander V. Chernikov rtsock_send_rtm(c->rtsock_fd, rtm); 549775dc861SAlexander V. Chernikov rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq); 550775dc861SAlexander V. Chernikov 551775dc861SAlexander V. Chernikov /* 552775dc861SAlexander V. Chernikov * RTM_DELETE: Delete Route: len 200, pid: 46417, seq 43, errno 0, flags: <GATEWAY,DONE,STATIC> 553775dc861SAlexander V. Chernikov * sockaddrs: 0x7 <DST,GATEWAY,NETMASK> 554775dc861SAlexander V. Chernikov * af=inet len=16 addr=192.0.2.0 hd={10, 02, 00{2}, C0, 00, 02, 00{9}} 555775dc861SAlexander V. Chernikov * af=inet len=16 addr=192.0.2.254 hd={10, 02, 00{2}, C0, 00, 02, FE, 00{8}} 556775dc861SAlexander V. Chernikov * af=inet len=16 addr=255.255.255.128 hd={10, 02, FF{5}, 80, 00{8}} 557775dc861SAlexander V. Chernikov */ 558775dc861SAlexander V. Chernikov 559775dc861SAlexander V. Chernikov verify_route_message(rtm, RTM_DELETE, (struct sockaddr *)&net6, 560775dc861SAlexander V. Chernikov (struct sockaddr *)&mask6, (struct sockaddr *)&gw6); 561775dc861SAlexander V. Chernikov verify_route_message_extra(rtm, c->ifindex, RTF_DONE | RTF_GATEWAY | RTF_STATIC); 562775dc861SAlexander V. Chernikov } 563775dc861SAlexander V. Chernikov 564775dc861SAlexander V. Chernikov ATF_TC_CLEANUP(rtm_del_v6_gu_prefix_nogw_success, tc) 565775dc861SAlexander V. Chernikov { 566775dc861SAlexander V. Chernikov CLEANUP_AFTER_TEST; 567775dc861SAlexander V. Chernikov } 568775dc861SAlexander V. Chernikov 569e02d3fe7SAlexander V. Chernikov ATF_TC_WITH_CLEANUP(rtm_add_v4_temporal1_success); 570e02d3fe7SAlexander V. Chernikov ATF_TC_HEAD(rtm_add_v4_temporal1_success, tc) 571e02d3fe7SAlexander V. Chernikov { 572e02d3fe7SAlexander V. Chernikov DESCRIBE_ROOT_TEST("Tests IPv4 route expiration with expire time set"); 573e02d3fe7SAlexander V. Chernikov } 574e02d3fe7SAlexander V. Chernikov 575e02d3fe7SAlexander V. Chernikov ATF_TC_BODY(rtm_add_v4_temporal1_success, tc) 576e02d3fe7SAlexander V. Chernikov { 577e02d3fe7SAlexander V. Chernikov DECLARE_TEST_VARS; 578e02d3fe7SAlexander V. Chernikov 579e02d3fe7SAlexander V. Chernikov c = presetup_ipv4(tc); 580e02d3fe7SAlexander V. Chernikov 581e02d3fe7SAlexander V. Chernikov /* Create IPv4 subnetwork with smaller prefix */ 582e02d3fe7SAlexander V. Chernikov struct sockaddr_in mask4; 583e02d3fe7SAlexander V. Chernikov struct sockaddr_in net4; 584e02d3fe7SAlexander V. Chernikov struct sockaddr_in gw4; 585e02d3fe7SAlexander V. Chernikov prepare_v4_network(c, &net4, &mask4, &gw4); 586e02d3fe7SAlexander V. Chernikov 587e02d3fe7SAlexander V. Chernikov prepare_route_message(rtm, RTM_ADD, (struct sockaddr *)&net4, 588e02d3fe7SAlexander V. Chernikov (struct sockaddr *)&mask4, (struct sockaddr *)&gw4); 589e02d3fe7SAlexander V. Chernikov 590e02d3fe7SAlexander V. Chernikov /* Set expire time to now */ 591e02d3fe7SAlexander V. Chernikov struct timeval tv; 592e02d3fe7SAlexander V. Chernikov gettimeofday(&tv, NULL); 593e02d3fe7SAlexander V. Chernikov rtm->rtm_rmx.rmx_expire = tv.tv_sec - 1; 594e02d3fe7SAlexander V. Chernikov rtm->rtm_inits |= RTV_EXPIRE; 595e02d3fe7SAlexander V. Chernikov 596e02d3fe7SAlexander V. Chernikov rtsock_send_rtm(c->rtsock_fd, rtm); 597e02d3fe7SAlexander V. Chernikov rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq); 598e02d3fe7SAlexander V. Chernikov ATF_REQUIRE_MSG(rtm != NULL, "unable to get rtsock reply for RTM_ADD"); 599e02d3fe7SAlexander V. Chernikov RTSOCK_ATF_REQUIRE_MSG(rtm, rtm->rtm_inits & RTV_EXPIRE, "RTV_EXPIRE not set"); 600e02d3fe7SAlexander V. Chernikov 601e02d3fe7SAlexander V. Chernikov /* The next should be route deletion */ 602e02d3fe7SAlexander V. Chernikov rtm = rtsock_read_rtm(c->rtsock_fd, buffer, sizeof(buffer)); 603e02d3fe7SAlexander V. Chernikov 604e02d3fe7SAlexander V. Chernikov verify_route_message(rtm, RTM_DELETE, (struct sockaddr *)&net4, 605e02d3fe7SAlexander V. Chernikov (struct sockaddr *)&mask4, (struct sockaddr *)&gw4); 606e02d3fe7SAlexander V. Chernikov 607*34a5582cSAlexander V. Chernikov verify_route_message_extra(rtm, c->ifindex, RTF_GATEWAY | RTF_DONE | RTF_STATIC); 608e02d3fe7SAlexander V. Chernikov } 609e02d3fe7SAlexander V. Chernikov 610e02d3fe7SAlexander V. Chernikov ATF_TC_CLEANUP(rtm_add_v4_temporal1_success, tc) 611e02d3fe7SAlexander V. Chernikov { 612e02d3fe7SAlexander V. Chernikov CLEANUP_AFTER_TEST; 613e02d3fe7SAlexander V. Chernikov } 614e02d3fe7SAlexander V. Chernikov 615e02d3fe7SAlexander V. Chernikov ATF_TC_WITH_CLEANUP(rtm_add_v6_temporal1_success); 616e02d3fe7SAlexander V. Chernikov ATF_TC_HEAD(rtm_add_v6_temporal1_success, tc) 617e02d3fe7SAlexander V. Chernikov { 618e02d3fe7SAlexander V. Chernikov DESCRIBE_ROOT_TEST("Tests IPv6 global unicast prefix addition with directly-reachable GU GW"); 619e02d3fe7SAlexander V. Chernikov } 620e02d3fe7SAlexander V. Chernikov 621e02d3fe7SAlexander V. Chernikov ATF_TC_BODY(rtm_add_v6_temporal1_success, tc) 622e02d3fe7SAlexander V. Chernikov { 623e02d3fe7SAlexander V. Chernikov DECLARE_TEST_VARS; 624e02d3fe7SAlexander V. Chernikov 625e02d3fe7SAlexander V. Chernikov c = presetup_ipv6(tc); 626e02d3fe7SAlexander V. Chernikov 627e02d3fe7SAlexander V. Chernikov /* Create IPv6 subnetwork with smaller prefix */ 628e02d3fe7SAlexander V. Chernikov struct sockaddr_in6 mask6; 629e02d3fe7SAlexander V. Chernikov struct sockaddr_in6 net6; 630e02d3fe7SAlexander V. Chernikov struct sockaddr_in6 gw6; 631e02d3fe7SAlexander V. Chernikov prepare_v6_network(c, &net6, &mask6, &gw6); 632e02d3fe7SAlexander V. Chernikov 633e02d3fe7SAlexander V. Chernikov prepare_route_message(rtm, RTM_ADD, (struct sockaddr *)&net6, 634e02d3fe7SAlexander V. Chernikov (struct sockaddr *)&mask6, (struct sockaddr *)&gw6); 635e02d3fe7SAlexander V. Chernikov 636e02d3fe7SAlexander V. Chernikov /* Set expire time to now */ 637e02d3fe7SAlexander V. Chernikov struct timeval tv; 638e02d3fe7SAlexander V. Chernikov gettimeofday(&tv, NULL); 639e02d3fe7SAlexander V. Chernikov rtm->rtm_rmx.rmx_expire = tv.tv_sec - 1; 640e02d3fe7SAlexander V. Chernikov rtm->rtm_inits |= RTV_EXPIRE; 641e02d3fe7SAlexander V. Chernikov 642e02d3fe7SAlexander V. Chernikov rtsock_send_rtm(c->rtsock_fd, rtm); 643e02d3fe7SAlexander V. Chernikov rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq); 644e02d3fe7SAlexander V. Chernikov ATF_REQUIRE_MSG(rtm != NULL, "unable to get rtsock reply for RTM_ADD"); 645e02d3fe7SAlexander V. Chernikov RTSOCK_ATF_REQUIRE_MSG(rtm, rtm->rtm_inits & RTV_EXPIRE, "RTV_EXPIRE not set"); 646e02d3fe7SAlexander V. Chernikov 647e02d3fe7SAlexander V. Chernikov /* The next should be route deletion */ 648e02d3fe7SAlexander V. Chernikov rtm = rtsock_read_rtm(c->rtsock_fd, buffer, sizeof(buffer)); 649e02d3fe7SAlexander V. Chernikov 650e02d3fe7SAlexander V. Chernikov verify_route_message(rtm, RTM_DELETE, (struct sockaddr *)&net6, 651e02d3fe7SAlexander V. Chernikov (struct sockaddr *)&mask6, (struct sockaddr *)&gw6); 652e02d3fe7SAlexander V. Chernikov 653e02d3fe7SAlexander V. Chernikov 654e02d3fe7SAlexander V. Chernikov /* XXX: Currently kernel sets RTF_UP automatically but does NOT report it in the reply */ 655*34a5582cSAlexander V. Chernikov verify_route_message_extra(rtm, c->ifindex, RTF_GATEWAY | RTF_DONE | RTF_STATIC); 656e02d3fe7SAlexander V. Chernikov } 657e02d3fe7SAlexander V. Chernikov 658e02d3fe7SAlexander V. Chernikov ATF_TC_CLEANUP(rtm_add_v6_temporal1_success, tc) 659e02d3fe7SAlexander V. Chernikov { 660e02d3fe7SAlexander V. Chernikov CLEANUP_AFTER_TEST; 661e02d3fe7SAlexander V. Chernikov } 662e02d3fe7SAlexander V. Chernikov 663e02d3fe7SAlexander V. Chernikov /* Interface address messages tests */ 664e02d3fe7SAlexander V. Chernikov 665e02d3fe7SAlexander V. Chernikov RTM_DECLARE_ROOT_TEST(rtm_add_v6_gu_ifa_hostroute_success, 666e02d3fe7SAlexander V. Chernikov "Tests validness for /128 host route announce after ifaddr assignment"); 667e02d3fe7SAlexander V. Chernikov 668e02d3fe7SAlexander V. Chernikov ATF_TC_BODY(rtm_add_v6_gu_ifa_hostroute_success, tc) 669e02d3fe7SAlexander V. Chernikov { 670e02d3fe7SAlexander V. Chernikov DECLARE_TEST_VARS; 671e02d3fe7SAlexander V. Chernikov 672e02d3fe7SAlexander V. Chernikov c = presetup_ipv6_iface(tc); 673e02d3fe7SAlexander V. Chernikov 674e02d3fe7SAlexander V. Chernikov c->rtsock_fd = rtsock_setup_socket(); 675e02d3fe7SAlexander V. Chernikov 676e02d3fe7SAlexander V. Chernikov ret = iface_setup_addr(c->ifname, c->addr6_str, c->plen6); 677e02d3fe7SAlexander V. Chernikov 678e02d3fe7SAlexander V. Chernikov /* 679e02d3fe7SAlexander V. Chernikov * There will be multiple. 680e02d3fe7SAlexander V. Chernikov * RTM_ADD without llinfo. 681e02d3fe7SAlexander V. Chernikov */ 682e02d3fe7SAlexander V. Chernikov 683e02d3fe7SAlexander V. Chernikov while (true) { 684e02d3fe7SAlexander V. Chernikov rtm = rtsock_read_rtm(c->rtsock_fd, buffer, sizeof(buffer)); 685e02d3fe7SAlexander V. Chernikov if ((rtm->rtm_type == RTM_ADD) && ((rtm->rtm_flags & RTF_LLINFO) == 0)) 686e02d3fe7SAlexander V. Chernikov break; 687e02d3fe7SAlexander V. Chernikov } 688e02d3fe7SAlexander V. Chernikov /* This should be a message for the host route */ 689e02d3fe7SAlexander V. Chernikov 690e02d3fe7SAlexander V. Chernikov verify_route_message(rtm, RTM_ADD, (struct sockaddr *)&c->addr6, NULL, NULL); 691e02d3fe7SAlexander V. Chernikov rtsock_validate_pid_kernel(rtm); 692e02d3fe7SAlexander V. Chernikov /* No netmask should be set */ 693e02d3fe7SAlexander V. Chernikov RTSOCK_ATF_REQUIRE_MSG(rtm, rtsock_find_rtm_sa(rtm, RTA_NETMASK) == NULL, "netmask is set"); 694e02d3fe7SAlexander V. Chernikov 695e02d3fe7SAlexander V. Chernikov /* gateway should be link sdl with ifindex of an address interface */ 696e02d3fe7SAlexander V. Chernikov verify_link_gateway(rtm, c->ifindex); 697e02d3fe7SAlexander V. Chernikov 698e02d3fe7SAlexander V. Chernikov int expected_rt_flags = RTF_UP | RTF_HOST | RTF_DONE | RTF_STATIC | RTF_PINNED; 699e02d3fe7SAlexander V. Chernikov verify_route_message_extra(rtm, if_nametoindex("lo0"), expected_rt_flags); 700e02d3fe7SAlexander V. Chernikov } 701e02d3fe7SAlexander V. Chernikov 702e02d3fe7SAlexander V. Chernikov RTM_DECLARE_ROOT_TEST(rtm_add_v6_gu_ifa_prefixroute_success, 703e02d3fe7SAlexander V. Chernikov "Tests validness for the prefix route announce after ifaddr assignment"); 704e02d3fe7SAlexander V. Chernikov 705e02d3fe7SAlexander V. Chernikov ATF_TC_BODY(rtm_add_v6_gu_ifa_prefixroute_success, tc) 706e02d3fe7SAlexander V. Chernikov { 707e02d3fe7SAlexander V. Chernikov DECLARE_TEST_VARS; 708e02d3fe7SAlexander V. Chernikov 709e02d3fe7SAlexander V. Chernikov c = presetup_ipv6_iface(tc); 710e02d3fe7SAlexander V. Chernikov 711e02d3fe7SAlexander V. Chernikov c->rtsock_fd = rtsock_setup_socket(); 712e02d3fe7SAlexander V. Chernikov 713e02d3fe7SAlexander V. Chernikov ret = iface_setup_addr(c->ifname, c->addr6_str, c->plen6); 714e02d3fe7SAlexander V. Chernikov 715e02d3fe7SAlexander V. Chernikov /* 716e02d3fe7SAlexander V. Chernikov * Multiple RTM_ADD messages will be generated: 717e02d3fe7SAlexander V. Chernikov * 1) lladdr mapping (RTF_LLDATA) 718e02d3fe7SAlexander V. Chernikov * 2) host route (one w/o netmask) 719e02d3fe7SAlexander V. Chernikov * 3) prefix route 720e02d3fe7SAlexander V. Chernikov */ 721e02d3fe7SAlexander V. Chernikov 722e02d3fe7SAlexander V. Chernikov while (true) { 723e02d3fe7SAlexander V. Chernikov rtm = rtsock_read_rtm(c->rtsock_fd, buffer, sizeof(buffer)); 724e02d3fe7SAlexander V. Chernikov /* Find RTM_ADD with netmask - this should skip both host route and LLADDR */ 725e02d3fe7SAlexander V. Chernikov if ((rtm->rtm_type == RTM_ADD) && (rtsock_find_rtm_sa(rtm, RTA_NETMASK))) 726e02d3fe7SAlexander V. Chernikov break; 727e02d3fe7SAlexander V. Chernikov } 728e02d3fe7SAlexander V. Chernikov 729e02d3fe7SAlexander V. Chernikov /* This should be a message for the prefix route */ 730e02d3fe7SAlexander V. Chernikov verify_route_message(rtm, RTM_ADD, (struct sockaddr *)&c->net6, 731e02d3fe7SAlexander V. Chernikov (struct sockaddr *)&c->mask6, NULL); 732e02d3fe7SAlexander V. Chernikov 733e02d3fe7SAlexander V. Chernikov /* gateway should be link sdl with ifindex of an address interface */ 734e02d3fe7SAlexander V. Chernikov verify_link_gateway(rtm, c->ifindex); 735e02d3fe7SAlexander V. Chernikov 736e02d3fe7SAlexander V. Chernikov /* TODO: PINNED? */ 737e02d3fe7SAlexander V. Chernikov int expected_rt_flags = RTF_UP | RTF_DONE; 738e02d3fe7SAlexander V. Chernikov verify_route_message_extra(rtm, c->ifindex, expected_rt_flags); 739e02d3fe7SAlexander V. Chernikov } 740e02d3fe7SAlexander V. Chernikov 741e02d3fe7SAlexander V. Chernikov RTM_DECLARE_ROOT_TEST(rtm_add_v6_gu_ifa_ordered_success, 742e02d3fe7SAlexander V. Chernikov "Tests ordering of the messages for IPv6 global unicast ifaddr assignment"); 743e02d3fe7SAlexander V. Chernikov 744e02d3fe7SAlexander V. Chernikov ATF_TC_BODY(rtm_add_v6_gu_ifa_ordered_success, tc) 745e02d3fe7SAlexander V. Chernikov { 746e02d3fe7SAlexander V. Chernikov DECLARE_TEST_VARS; 747e02d3fe7SAlexander V. Chernikov 748e02d3fe7SAlexander V. Chernikov c = presetup_ipv6_iface(tc); 749e02d3fe7SAlexander V. Chernikov 750e02d3fe7SAlexander V. Chernikov c->rtsock_fd = rtsock_setup_socket(); 751e02d3fe7SAlexander V. Chernikov 752e02d3fe7SAlexander V. Chernikov ret = iface_setup_addr(c->ifname, c->addr6_str, c->plen6); 753e02d3fe7SAlexander V. Chernikov 754e02d3fe7SAlexander V. Chernikov int count = 0, tries = 0; 755e02d3fe7SAlexander V. Chernikov 756e02d3fe7SAlexander V. Chernikov enum msgtype { 757e02d3fe7SAlexander V. Chernikov MSG_IFADDR, 758e02d3fe7SAlexander V. Chernikov MSG_HOSTROUTE, 759e02d3fe7SAlexander V. Chernikov MSG_PREFIXROUTE, 760e02d3fe7SAlexander V. Chernikov MSG_MAX, 761e02d3fe7SAlexander V. Chernikov }; 762e02d3fe7SAlexander V. Chernikov 763e02d3fe7SAlexander V. Chernikov int msg_array[MSG_MAX]; 764e02d3fe7SAlexander V. Chernikov 765e02d3fe7SAlexander V. Chernikov bzero(msg_array, sizeof(msg_array)); 766e02d3fe7SAlexander V. Chernikov 767e02d3fe7SAlexander V. Chernikov while (count < 3 && tries < 20) { 768e02d3fe7SAlexander V. Chernikov rtm = rtsock_read_rtm(c->rtsock_fd, buffer, sizeof(buffer)); 769e02d3fe7SAlexander V. Chernikov tries++; 770e02d3fe7SAlexander V. Chernikov /* Classify */ 771e02d3fe7SAlexander V. Chernikov if (rtm->rtm_type == RTM_NEWADDR) { 772e02d3fe7SAlexander V. Chernikov RLOG("MSG_IFADDR: %d", count); 773e02d3fe7SAlexander V. Chernikov msg_array[MSG_IFADDR] = count++; 774e02d3fe7SAlexander V. Chernikov continue; 775e02d3fe7SAlexander V. Chernikov } 776e02d3fe7SAlexander V. Chernikov 777e02d3fe7SAlexander V. Chernikov /* Find RTM_ADD with netmask - this should skip both host route and LLADDR */ 778e02d3fe7SAlexander V. Chernikov if ((rtm->rtm_type == RTM_ADD) && (rtsock_find_rtm_sa(rtm, RTA_NETMASK))) { 779e02d3fe7SAlexander V. Chernikov RLOG("MSG_PREFIXROUTE: %d", count); 780e02d3fe7SAlexander V. Chernikov msg_array[MSG_PREFIXROUTE] = count++; 781e02d3fe7SAlexander V. Chernikov continue; 782e02d3fe7SAlexander V. Chernikov } 783e02d3fe7SAlexander V. Chernikov 784e02d3fe7SAlexander V. Chernikov if ((rtm->rtm_type == RTM_ADD) && ((rtm->rtm_flags & RTF_LLDATA) == 0)) { 785e02d3fe7SAlexander V. Chernikov RLOG("MSG_HOSTROUTE: %d", count); 786e02d3fe7SAlexander V. Chernikov msg_array[MSG_HOSTROUTE] = count++; 787e02d3fe7SAlexander V. Chernikov continue; 788e02d3fe7SAlexander V. Chernikov } 789e02d3fe7SAlexander V. Chernikov 790e02d3fe7SAlexander V. Chernikov RLOG("skipping msg type %s, try: %d", rtsock_print_cmdtype(rtm->rtm_type), 791e02d3fe7SAlexander V. Chernikov tries); 792e02d3fe7SAlexander V. Chernikov } 793e02d3fe7SAlexander V. Chernikov 794e02d3fe7SAlexander V. Chernikov /* TODO: verify multicast */ 795e02d3fe7SAlexander V. Chernikov ATF_REQUIRE_MSG(count == 3, "Received only %d/3 messages", count); 796e02d3fe7SAlexander V. Chernikov ATF_REQUIRE_MSG(msg_array[MSG_IFADDR] == 0, "ifaddr message is not the first"); 797e02d3fe7SAlexander V. Chernikov } 798e02d3fe7SAlexander V. Chernikov 799e02d3fe7SAlexander V. Chernikov RTM_DECLARE_ROOT_TEST(rtm_del_v6_gu_ifa_hostroute_success, 800e02d3fe7SAlexander V. Chernikov "Tests validness for /128 host route removal after ifaddr removal"); 801e02d3fe7SAlexander V. Chernikov 802e02d3fe7SAlexander V. Chernikov ATF_TC_BODY(rtm_del_v6_gu_ifa_hostroute_success, tc) 803e02d3fe7SAlexander V. Chernikov { 804e02d3fe7SAlexander V. Chernikov DECLARE_TEST_VARS; 805e02d3fe7SAlexander V. Chernikov 806e02d3fe7SAlexander V. Chernikov c = presetup_ipv6_iface(tc); 807e02d3fe7SAlexander V. Chernikov 808e02d3fe7SAlexander V. Chernikov ret = iface_setup_addr(c->ifname, c->addr6_str, c->plen6); 809e02d3fe7SAlexander V. Chernikov 810e02d3fe7SAlexander V. Chernikov c->rtsock_fd = rtsock_setup_socket(); 811e02d3fe7SAlexander V. Chernikov 812e02d3fe7SAlexander V. Chernikov ret = iface_delete_addr(c->ifname, c->addr6_str); 813e02d3fe7SAlexander V. Chernikov 814e02d3fe7SAlexander V. Chernikov while (true) { 815e02d3fe7SAlexander V. Chernikov rtm = rtsock_read_rtm(c->rtsock_fd, buffer, sizeof(buffer)); 816e02d3fe7SAlexander V. Chernikov if ((rtm->rtm_type == RTM_DELETE) && 817e02d3fe7SAlexander V. Chernikov ((rtm->rtm_flags & RTF_LLINFO) == 0) && 818e02d3fe7SAlexander V. Chernikov rtsock_find_rtm_sa(rtm, RTA_NETMASK) == NULL) 819e02d3fe7SAlexander V. Chernikov break; 820e02d3fe7SAlexander V. Chernikov } 821e02d3fe7SAlexander V. Chernikov /* This should be a message for the host route */ 822e02d3fe7SAlexander V. Chernikov 823e02d3fe7SAlexander V. Chernikov verify_route_message(rtm, RTM_DELETE, (struct sockaddr *)&c->addr6, NULL, NULL); 824e02d3fe7SAlexander V. Chernikov rtsock_validate_pid_kernel(rtm); 825e02d3fe7SAlexander V. Chernikov /* No netmask should be set */ 826e02d3fe7SAlexander V. Chernikov RTSOCK_ATF_REQUIRE_MSG(rtm, rtsock_find_rtm_sa(rtm, RTA_NETMASK) == NULL, "netmask is set"); 827e02d3fe7SAlexander V. Chernikov 828e02d3fe7SAlexander V. Chernikov /* gateway should be link sdl with ifindex of an address interface */ 829e02d3fe7SAlexander V. Chernikov verify_link_gateway(rtm, c->ifindex); 830e02d3fe7SAlexander V. Chernikov 831e02d3fe7SAlexander V. Chernikov /* XXX: consider passing ifindex in rtm_index as done in RTM_ADD. */ 832e02d3fe7SAlexander V. Chernikov int expected_rt_flags = RTF_HOST | RTF_DONE | RTF_STATIC | RTF_PINNED; 833e02d3fe7SAlexander V. Chernikov RTSOCK_ATF_REQUIRE_MSG(rtm, rtm->rtm_flags == expected_rt_flags, 834e02d3fe7SAlexander V. Chernikov "expected rtm flags: 0x%X, got 0x%X", expected_rt_flags, rtm->rtm_flags); 835e02d3fe7SAlexander V. Chernikov } 836e02d3fe7SAlexander V. Chernikov 837e02d3fe7SAlexander V. Chernikov RTM_DECLARE_ROOT_TEST(rtm_del_v6_gu_ifa_prefixroute_success, 838e02d3fe7SAlexander V. Chernikov "Tests validness for the prefix route removal after ifaddr assignment"); 839e02d3fe7SAlexander V. Chernikov 840e02d3fe7SAlexander V. Chernikov ATF_TC_BODY(rtm_del_v6_gu_ifa_prefixroute_success, tc) 841e02d3fe7SAlexander V. Chernikov { 842e02d3fe7SAlexander V. Chernikov DECLARE_TEST_VARS; 843e02d3fe7SAlexander V. Chernikov 844e02d3fe7SAlexander V. Chernikov c = presetup_ipv6_iface(tc); 845e02d3fe7SAlexander V. Chernikov 846e02d3fe7SAlexander V. Chernikov ret = iface_setup_addr(c->ifname, c->addr6_str, c->plen6); 847e02d3fe7SAlexander V. Chernikov 848e02d3fe7SAlexander V. Chernikov c->rtsock_fd = rtsock_setup_socket(); 849e02d3fe7SAlexander V. Chernikov 850e02d3fe7SAlexander V. Chernikov ret = iface_delete_addr(c->ifname, c->addr6_str); 851e02d3fe7SAlexander V. Chernikov 852e02d3fe7SAlexander V. Chernikov while (true) { 853e02d3fe7SAlexander V. Chernikov rtm = rtsock_read_rtm(c->rtsock_fd, buffer, sizeof(buffer)); 854e02d3fe7SAlexander V. Chernikov /* Find RTM_DELETE with netmask - this should skip both host route and LLADDR */ 855e02d3fe7SAlexander V. Chernikov if ((rtm->rtm_type == RTM_DELETE) && (rtsock_find_rtm_sa(rtm, RTA_NETMASK))) 856e02d3fe7SAlexander V. Chernikov break; 857e02d3fe7SAlexander V. Chernikov } 858e02d3fe7SAlexander V. Chernikov 859e02d3fe7SAlexander V. Chernikov /* This should be a message for the prefix route */ 860e02d3fe7SAlexander V. Chernikov verify_route_message(rtm, RTM_DELETE, (struct sockaddr *)&c->net6, 861e02d3fe7SAlexander V. Chernikov (struct sockaddr *)&c->mask6, NULL); 862e02d3fe7SAlexander V. Chernikov 863e02d3fe7SAlexander V. Chernikov /* gateway should be link sdl with ifindex of an address interface */ 864e02d3fe7SAlexander V. Chernikov verify_link_gateway(rtm, c->ifindex); 865e02d3fe7SAlexander V. Chernikov 866e02d3fe7SAlexander V. Chernikov int expected_rt_flags = RTF_DONE; 867e02d3fe7SAlexander V. Chernikov verify_route_message_extra(rtm, c->ifindex, expected_rt_flags); 868e02d3fe7SAlexander V. Chernikov } 869e02d3fe7SAlexander V. Chernikov 870e02d3fe7SAlexander V. Chernikov RTM_DECLARE_ROOT_TEST(rtm_add_v4_gu_ifa_prefixroute_success, 871e02d3fe7SAlexander V. Chernikov "Tests validness for the prefix route announce after ifaddr assignment"); 872e02d3fe7SAlexander V. Chernikov 873e02d3fe7SAlexander V. Chernikov ATF_TC_BODY(rtm_add_v4_gu_ifa_prefixroute_success, tc) 874e02d3fe7SAlexander V. Chernikov { 875e02d3fe7SAlexander V. Chernikov DECLARE_TEST_VARS; 876e02d3fe7SAlexander V. Chernikov 877e02d3fe7SAlexander V. Chernikov c = presetup_ipv4_iface(tc); 878e02d3fe7SAlexander V. Chernikov 879e02d3fe7SAlexander V. Chernikov c->rtsock_fd = rtsock_setup_socket(); 880e02d3fe7SAlexander V. Chernikov 881e02d3fe7SAlexander V. Chernikov ret = iface_setup_addr(c->ifname, c->addr6_str, c->plen6); 882e02d3fe7SAlexander V. Chernikov 883e02d3fe7SAlexander V. Chernikov /* 884e02d3fe7SAlexander V. Chernikov * Multiple RTM_ADD messages will be generated: 885e02d3fe7SAlexander V. Chernikov * 1) lladdr mapping (RTF_LLDATA) 886e02d3fe7SAlexander V. Chernikov * 3) prefix route 887e02d3fe7SAlexander V. Chernikov */ 888e02d3fe7SAlexander V. Chernikov 889e02d3fe7SAlexander V. Chernikov while (true) { 890e02d3fe7SAlexander V. Chernikov rtm = rtsock_read_rtm(c->rtsock_fd, buffer, sizeof(buffer)); 891e02d3fe7SAlexander V. Chernikov /* Find RTM_ADD with netmask - this should skip both host route and LLADDR */ 892e02d3fe7SAlexander V. Chernikov if ((rtm->rtm_type == RTM_ADD) && (rtsock_find_rtm_sa(rtm, RTA_NETMASK))) 893e02d3fe7SAlexander V. Chernikov break; 894e02d3fe7SAlexander V. Chernikov } 895e02d3fe7SAlexander V. Chernikov 896e02d3fe7SAlexander V. Chernikov /* This should be a message for the prefix route */ 897e02d3fe7SAlexander V. Chernikov verify_route_message(rtm, RTM_ADD, (struct sockaddr *)&c->net4, 898e02d3fe7SAlexander V. Chernikov (struct sockaddr *)&c->mask4, NULL); 899e02d3fe7SAlexander V. Chernikov 900e02d3fe7SAlexander V. Chernikov /* gateway should be link sdl with ifindex of an address interface */ 901e02d3fe7SAlexander V. Chernikov verify_link_gateway(rtm, c->ifindex); 902e02d3fe7SAlexander V. Chernikov 903e02d3fe7SAlexander V. Chernikov int expected_rt_flags = RTF_UP | RTF_DONE | RTF_PINNED; 904e02d3fe7SAlexander V. Chernikov verify_route_message_extra(rtm, c->ifindex, expected_rt_flags); 905e02d3fe7SAlexander V. Chernikov } 906e02d3fe7SAlexander V. Chernikov 907e02d3fe7SAlexander V. Chernikov RTM_DECLARE_ROOT_TEST(rtm_add_v4_gu_ifa_ordered_success, 908e02d3fe7SAlexander V. Chernikov "Tests ordering of the messages for IPv4 unicast ifaddr assignment"); 909e02d3fe7SAlexander V. Chernikov 910e02d3fe7SAlexander V. Chernikov ATF_TC_BODY(rtm_add_v4_gu_ifa_ordered_success, tc) 911e02d3fe7SAlexander V. Chernikov { 912e02d3fe7SAlexander V. Chernikov DECLARE_TEST_VARS; 913e02d3fe7SAlexander V. Chernikov 914e02d3fe7SAlexander V. Chernikov c = presetup_ipv4_iface(tc); 915e02d3fe7SAlexander V. Chernikov 916e02d3fe7SAlexander V. Chernikov c->rtsock_fd = rtsock_setup_socket(); 917e02d3fe7SAlexander V. Chernikov 918e02d3fe7SAlexander V. Chernikov ret = iface_setup_addr(c->ifname, c->addr4_str, c->plen4); 919e02d3fe7SAlexander V. Chernikov 920e02d3fe7SAlexander V. Chernikov int count = 0, tries = 0; 921e02d3fe7SAlexander V. Chernikov 922e02d3fe7SAlexander V. Chernikov enum msgtype { 923e02d3fe7SAlexander V. Chernikov MSG_IFADDR, 924e02d3fe7SAlexander V. Chernikov MSG_PREFIXROUTE, 925e02d3fe7SAlexander V. Chernikov MSG_MAX, 926e02d3fe7SAlexander V. Chernikov }; 927e02d3fe7SAlexander V. Chernikov 928e02d3fe7SAlexander V. Chernikov int msg_array[MSG_MAX]; 929e02d3fe7SAlexander V. Chernikov 930e02d3fe7SAlexander V. Chernikov bzero(msg_array, sizeof(msg_array)); 931e02d3fe7SAlexander V. Chernikov 932e02d3fe7SAlexander V. Chernikov while (count < 2 && tries < 20) { 933e02d3fe7SAlexander V. Chernikov rtm = rtsock_read_rtm(c->rtsock_fd, buffer, sizeof(buffer)); 934e02d3fe7SAlexander V. Chernikov tries++; 935e02d3fe7SAlexander V. Chernikov /* Classify */ 936e02d3fe7SAlexander V. Chernikov if (rtm->rtm_type == RTM_NEWADDR) { 937e02d3fe7SAlexander V. Chernikov RLOG("MSG_IFADDR: %d", count); 938e02d3fe7SAlexander V. Chernikov msg_array[MSG_IFADDR] = count++; 939e02d3fe7SAlexander V. Chernikov continue; 940e02d3fe7SAlexander V. Chernikov } 941e02d3fe7SAlexander V. Chernikov 942e02d3fe7SAlexander V. Chernikov /* Find RTM_ADD with netmask - this should skip both host route and LLADDR */ 943e02d3fe7SAlexander V. Chernikov if ((rtm->rtm_type == RTM_ADD) && (rtsock_find_rtm_sa(rtm, RTA_NETMASK))) { 944e02d3fe7SAlexander V. Chernikov RLOG("MSG_PREFIXROUTE: %d", count); 945e02d3fe7SAlexander V. Chernikov msg_array[MSG_PREFIXROUTE] = count++; 946e02d3fe7SAlexander V. Chernikov continue; 947e02d3fe7SAlexander V. Chernikov } 948e02d3fe7SAlexander V. Chernikov 949e02d3fe7SAlexander V. Chernikov RLOG("skipping msg type %s, try: %d", rtsock_print_cmdtype(rtm->rtm_type), 950e02d3fe7SAlexander V. Chernikov tries); 951e02d3fe7SAlexander V. Chernikov } 952e02d3fe7SAlexander V. Chernikov 953e02d3fe7SAlexander V. Chernikov /* TODO: verify multicast */ 954e02d3fe7SAlexander V. Chernikov ATF_REQUIRE_MSG(count == 2, "Received only %d/2 messages", count); 955e02d3fe7SAlexander V. Chernikov ATF_REQUIRE_MSG(msg_array[MSG_IFADDR] == 0, "ifaddr message is not the first"); 956e02d3fe7SAlexander V. Chernikov } 957e02d3fe7SAlexander V. Chernikov 958e02d3fe7SAlexander V. Chernikov RTM_DECLARE_ROOT_TEST(rtm_del_v4_gu_ifa_prefixroute_success, 959e02d3fe7SAlexander V. Chernikov "Tests validness for the prefix route removal after ifaddr assignment"); 960e02d3fe7SAlexander V. Chernikov 961e02d3fe7SAlexander V. Chernikov ATF_TC_BODY(rtm_del_v4_gu_ifa_prefixroute_success, tc) 962e02d3fe7SAlexander V. Chernikov { 963e02d3fe7SAlexander V. Chernikov DECLARE_TEST_VARS; 964e02d3fe7SAlexander V. Chernikov 965e02d3fe7SAlexander V. Chernikov c = presetup_ipv4_iface(tc); 966e02d3fe7SAlexander V. Chernikov 967e02d3fe7SAlexander V. Chernikov 968e02d3fe7SAlexander V. Chernikov ret = iface_setup_addr(c->ifname, c->addr4_str, c->plen4); 969e02d3fe7SAlexander V. Chernikov 970e02d3fe7SAlexander V. Chernikov c->rtsock_fd = rtsock_setup_socket(); 971e02d3fe7SAlexander V. Chernikov 972e02d3fe7SAlexander V. Chernikov ret = iface_delete_addr(c->ifname, c->addr4_str); 973e02d3fe7SAlexander V. Chernikov 974e02d3fe7SAlexander V. Chernikov while (true) { 975e02d3fe7SAlexander V. Chernikov rtm = rtsock_read_rtm(c->rtsock_fd, buffer, sizeof(buffer)); 976e02d3fe7SAlexander V. Chernikov /* Find RTM_ADD with netmask - this should skip both host route and LLADDR */ 977e02d3fe7SAlexander V. Chernikov if ((rtm->rtm_type == RTM_DELETE) && (rtsock_find_rtm_sa(rtm, RTA_NETMASK))) 978e02d3fe7SAlexander V. Chernikov break; 979e02d3fe7SAlexander V. Chernikov } 980e02d3fe7SAlexander V. Chernikov 981e02d3fe7SAlexander V. Chernikov /* This should be a message for the prefix route */ 982e02d3fe7SAlexander V. Chernikov verify_route_message(rtm, RTM_DELETE, (struct sockaddr *)&c->net4, 983e02d3fe7SAlexander V. Chernikov (struct sockaddr *)&c->mask4, NULL); 984e02d3fe7SAlexander V. Chernikov 985e02d3fe7SAlexander V. Chernikov /* gateway should be link sdl with ifindex of an address interface */ 986e02d3fe7SAlexander V. Chernikov verify_link_gateway(rtm, c->ifindex); 987e02d3fe7SAlexander V. Chernikov 988e02d3fe7SAlexander V. Chernikov int expected_rt_flags = RTF_DONE | RTF_PINNED; 989e02d3fe7SAlexander V. Chernikov verify_route_message_extra(rtm, c->ifindex, expected_rt_flags); 990e02d3fe7SAlexander V. Chernikov } 991775dc861SAlexander V. Chernikov 992775dc861SAlexander V. Chernikov 993775dc861SAlexander V. Chernikov ATF_TP_ADD_TCS(tp) 994775dc861SAlexander V. Chernikov { 995775dc861SAlexander V. Chernikov ATF_TP_ADD_TC(tp, rtm_get_v4_exact_success); 996775dc861SAlexander V. Chernikov ATF_TP_ADD_TC(tp, rtm_get_v4_lpm_success); 997775dc861SAlexander V. Chernikov ATF_TP_ADD_TC(tp, rtm_get_v4_hostbits_failure); 998775dc861SAlexander V. Chernikov ATF_TP_ADD_TC(tp, rtm_get_v4_empty_dst_failure); 999775dc861SAlexander V. Chernikov ATF_TP_ADD_TC(tp, rtm_add_v4_gw_direct_success); 1000775dc861SAlexander V. Chernikov ATF_TP_ADD_TC(tp, rtm_del_v4_prefix_nogw_success); 1001775dc861SAlexander V. Chernikov ATF_TP_ADD_TC(tp, rtm_add_v6_gu_gw_gu_direct_success); 1002775dc861SAlexander V. Chernikov ATF_TP_ADD_TC(tp, rtm_del_v6_gu_prefix_nogw_success); 1003e02d3fe7SAlexander V. Chernikov /* ifaddr tests */ 1004e02d3fe7SAlexander V. Chernikov ATF_TP_ADD_TC(tp, rtm_add_v6_gu_ifa_hostroute_success); 1005e02d3fe7SAlexander V. Chernikov ATF_TP_ADD_TC(tp, rtm_add_v6_gu_ifa_prefixroute_success); 1006e02d3fe7SAlexander V. Chernikov ATF_TP_ADD_TC(tp, rtm_add_v6_gu_ifa_ordered_success); 1007e02d3fe7SAlexander V. Chernikov ATF_TP_ADD_TC(tp, rtm_del_v6_gu_ifa_hostroute_success); 1008e02d3fe7SAlexander V. Chernikov ATF_TP_ADD_TC(tp, rtm_del_v6_gu_ifa_prefixroute_success); 1009e02d3fe7SAlexander V. Chernikov ATF_TP_ADD_TC(tp, rtm_add_v4_gu_ifa_ordered_success); 1010e02d3fe7SAlexander V. Chernikov ATF_TP_ADD_TC(tp, rtm_del_v4_gu_ifa_prefixroute_success); 1011*34a5582cSAlexander V. Chernikov /* temporal routes */ 1012*34a5582cSAlexander V. Chernikov ATF_TP_ADD_TC(tp, rtm_add_v4_temporal1_success); 1013*34a5582cSAlexander V. Chernikov ATF_TP_ADD_TC(tp, rtm_add_v6_temporal1_success); 1014775dc861SAlexander V. Chernikov 1015775dc861SAlexander V. Chernikov return (atf_no_error()); 1016775dc861SAlexander V. Chernikov } 1017775dc861SAlexander V. Chernikov 1018