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 38ddc75076SAlexander V. Chernikov static void 39ddc75076SAlexander V. Chernikov jump_vnet(struct rtsock_test_config *c, const atf_tc_t *tc) 40ddc75076SAlexander V. Chernikov { 41ddc75076SAlexander V. Chernikov char vnet_name[512]; 42ddc75076SAlexander V. Chernikov 43ddc75076SAlexander V. Chernikov snprintf(vnet_name, sizeof(vnet_name), "vt-%s", atf_tc_get_ident(tc)); 44ddc75076SAlexander V. Chernikov RLOG("jumping to %s", vnet_name); 45ddc75076SAlexander V. Chernikov 46*272bd698SAlexander V. Chernikov vnet_switch(vnet_name, c->ifnames, c->num_interfaces); 47ddc75076SAlexander V. Chernikov 48ddc75076SAlexander V. Chernikov /* Update ifindex cache */ 49ddc75076SAlexander V. Chernikov c->ifindex = if_nametoindex(c->ifname); 50ddc75076SAlexander V. Chernikov } 51ddc75076SAlexander V. Chernikov 52775dc861SAlexander V. Chernikov static inline struct rtsock_test_config * 53e02d3fe7SAlexander V. Chernikov presetup_ipv6_iface(const atf_tc_t *tc) 54775dc861SAlexander V. Chernikov { 55775dc861SAlexander V. Chernikov struct rtsock_test_config *c; 56775dc861SAlexander V. Chernikov int ret; 57775dc861SAlexander V. Chernikov 58*272bd698SAlexander V. Chernikov c = config_setup(tc, NULL); 59775dc861SAlexander V. Chernikov 60ddc75076SAlexander V. Chernikov jump_vnet(c, tc); 61ddc75076SAlexander V. Chernikov 62775dc861SAlexander V. Chernikov ret = iface_turn_up(c->ifname); 63775dc861SAlexander V. Chernikov ATF_REQUIRE_MSG(ret == 0, "Unable to turn up %s", c->ifname); 64775dc861SAlexander V. Chernikov 65775dc861SAlexander V. Chernikov ret = iface_enable_ipv6(c->ifname); 66775dc861SAlexander V. Chernikov ATF_REQUIRE_MSG(ret == 0, "Unable to enable IPv6 on %s", c->ifname); 67775dc861SAlexander V. Chernikov 68e02d3fe7SAlexander V. Chernikov return (c); 69e02d3fe7SAlexander V. Chernikov } 70e02d3fe7SAlexander V. Chernikov 71e02d3fe7SAlexander V. Chernikov static inline struct rtsock_test_config * 72e02d3fe7SAlexander V. Chernikov presetup_ipv6(const atf_tc_t *tc) 73e02d3fe7SAlexander V. Chernikov { 74e02d3fe7SAlexander V. Chernikov struct rtsock_test_config *c; 75e02d3fe7SAlexander V. Chernikov int ret; 76e02d3fe7SAlexander V. Chernikov 77e02d3fe7SAlexander V. Chernikov c = presetup_ipv6_iface(tc); 78e02d3fe7SAlexander V. Chernikov 79775dc861SAlexander V. Chernikov ret = iface_setup_addr(c->ifname, c->addr6_str, c->plen6); 80775dc861SAlexander V. Chernikov 81775dc861SAlexander V. Chernikov c->rtsock_fd = rtsock_setup_socket(); 82775dc861SAlexander V. Chernikov 83775dc861SAlexander V. Chernikov return (c); 84775dc861SAlexander V. Chernikov } 85775dc861SAlexander V. Chernikov 86775dc861SAlexander V. Chernikov static inline struct rtsock_test_config * 87e02d3fe7SAlexander V. Chernikov presetup_ipv4_iface(const atf_tc_t *tc) 88e02d3fe7SAlexander V. Chernikov { 89e02d3fe7SAlexander V. Chernikov struct rtsock_test_config *c; 90e02d3fe7SAlexander V. Chernikov int ret; 91e02d3fe7SAlexander V. Chernikov 92*272bd698SAlexander V. Chernikov c = config_setup(tc, NULL); 93e02d3fe7SAlexander V. Chernikov 94ddc75076SAlexander V. Chernikov jump_vnet(c, tc); 95ddc75076SAlexander V. Chernikov 96e02d3fe7SAlexander V. Chernikov ret = iface_turn_up(c->ifname); 97e02d3fe7SAlexander V. Chernikov ATF_REQUIRE_MSG(ret == 0, "Unable to turn up %s", c->ifname); 98e02d3fe7SAlexander V. Chernikov 99e02d3fe7SAlexander V. Chernikov return (c); 100e02d3fe7SAlexander V. Chernikov } 101e02d3fe7SAlexander V. Chernikov 102e02d3fe7SAlexander V. Chernikov static inline struct rtsock_test_config * 103775dc861SAlexander V. Chernikov presetup_ipv4(const atf_tc_t *tc) 104775dc861SAlexander V. Chernikov { 105775dc861SAlexander V. Chernikov struct rtsock_test_config *c; 106775dc861SAlexander V. Chernikov int ret; 107775dc861SAlexander V. Chernikov 108e02d3fe7SAlexander V. Chernikov c = presetup_ipv4_iface(tc); 109775dc861SAlexander V. Chernikov 110775dc861SAlexander V. Chernikov /* assumes ifconfig doing IFF_UP */ 111775dc861SAlexander V. Chernikov ret = iface_setup_addr(c->ifname, c->addr4_str, c->plen4); 112775dc861SAlexander V. Chernikov ATF_REQUIRE_MSG(ret == 0, "ifconfig failed"); 113775dc861SAlexander V. Chernikov 114775dc861SAlexander V. Chernikov c->rtsock_fd = rtsock_setup_socket(); 115775dc861SAlexander V. Chernikov 116775dc861SAlexander V. Chernikov return (c); 117775dc861SAlexander V. Chernikov } 118775dc861SAlexander V. Chernikov 119775dc861SAlexander V. Chernikov 120775dc861SAlexander V. Chernikov static void 121775dc861SAlexander V. Chernikov prepare_v4_network(struct rtsock_test_config *c, struct sockaddr_in *dst, 122775dc861SAlexander V. Chernikov struct sockaddr_in *mask, struct sockaddr_in *gw) 123775dc861SAlexander V. Chernikov { 124775dc861SAlexander V. Chernikov /* Create IPv4 subnetwork with smaller prefix */ 125775dc861SAlexander V. Chernikov sa_fill_mask4(mask, c->plen4 + 1); 126775dc861SAlexander V. Chernikov *dst = c->net4; 127775dc861SAlexander V. Chernikov /* Calculate GW as last-net-address - 1 */ 128775dc861SAlexander V. Chernikov *gw = c->net4; 129775dc861SAlexander V. Chernikov gw->sin_addr.s_addr = htonl((ntohl(c->net4.sin_addr.s_addr) | ~ntohl(c->mask4.sin_addr.s_addr)) - 1); 130775dc861SAlexander V. Chernikov sa_print((struct sockaddr *)dst, 0); 131775dc861SAlexander V. Chernikov sa_print((struct sockaddr *)mask, 0); 132775dc861SAlexander V. Chernikov sa_print((struct sockaddr *)gw, 0); 133775dc861SAlexander V. Chernikov } 134775dc861SAlexander V. Chernikov 135775dc861SAlexander V. Chernikov static void 136775dc861SAlexander V. Chernikov prepare_v6_network(struct rtsock_test_config *c, struct sockaddr_in6 *dst, 137775dc861SAlexander V. Chernikov struct sockaddr_in6 *mask, struct sockaddr_in6 *gw) 138775dc861SAlexander V. Chernikov { 139775dc861SAlexander V. Chernikov /* Create IPv6 subnetwork with smaller prefix */ 140775dc861SAlexander V. Chernikov sa_fill_mask6(mask, c->plen6 + 1); 141775dc861SAlexander V. Chernikov *dst = c->net6; 142775dc861SAlexander V. Chernikov /* Calculate GW as last-net-address - 1 */ 143775dc861SAlexander V. Chernikov *gw = c->net6; 144775dc861SAlexander V. Chernikov #define _s6_addr32 __u6_addr.__u6_addr32 145775dc861SAlexander V. Chernikov gw->sin6_addr._s6_addr32[0] = htonl((ntohl(gw->sin6_addr._s6_addr32[0]) | ~ntohl(c->mask6.sin6_addr._s6_addr32[0]))); 146775dc861SAlexander V. Chernikov gw->sin6_addr._s6_addr32[1] = htonl((ntohl(gw->sin6_addr._s6_addr32[1]) | ~ntohl(c->mask6.sin6_addr._s6_addr32[1]))); 147775dc861SAlexander V. Chernikov gw->sin6_addr._s6_addr32[2] = htonl((ntohl(gw->sin6_addr._s6_addr32[2]) | ~ntohl(c->mask6.sin6_addr._s6_addr32[2]))); 148775dc861SAlexander 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); 149775dc861SAlexander V. Chernikov #undef _s6_addr32 150775dc861SAlexander V. Chernikov sa_print((struct sockaddr *)dst, 0); 151775dc861SAlexander V. Chernikov sa_print((struct sockaddr *)mask, 0); 152775dc861SAlexander V. Chernikov sa_print((struct sockaddr *)gw, 0); 153775dc861SAlexander V. Chernikov } 154775dc861SAlexander V. Chernikov 155775dc861SAlexander V. Chernikov static void 156775dc861SAlexander V. Chernikov prepare_route_message(struct rt_msghdr *rtm, int cmd, struct sockaddr *dst, 157775dc861SAlexander V. Chernikov struct sockaddr *mask, struct sockaddr *gw) 158775dc861SAlexander V. Chernikov { 159775dc861SAlexander V. Chernikov 160775dc861SAlexander V. Chernikov rtsock_prepare_route_message(rtm, cmd, dst, mask, gw); 161775dc861SAlexander V. Chernikov 162775dc861SAlexander V. Chernikov if (cmd == RTM_ADD || cmd == RTM_CHANGE) 163775dc861SAlexander V. Chernikov rtm->rtm_flags |= RTF_STATIC; 164775dc861SAlexander V. Chernikov } 165775dc861SAlexander V. Chernikov 166775dc861SAlexander V. Chernikov static void 167775dc861SAlexander V. Chernikov verify_route_message(struct rt_msghdr *rtm, int cmd, struct sockaddr *dst, 168775dc861SAlexander V. Chernikov struct sockaddr *mask, struct sockaddr *gw) 169775dc861SAlexander V. Chernikov { 170775dc861SAlexander V. Chernikov char msg[512]; 171775dc861SAlexander V. Chernikov struct sockaddr *sa; 172775dc861SAlexander V. Chernikov int ret; 173775dc861SAlexander V. Chernikov 174775dc861SAlexander V. Chernikov RTSOCK_ATF_REQUIRE_MSG(rtm, rtm->rtm_type == cmd, 175775dc861SAlexander V. Chernikov "expected %s message, got %d (%s)", rtsock_print_cmdtype(cmd), 176775dc861SAlexander V. Chernikov rtm->rtm_type, rtsock_print_cmdtype(rtm->rtm_type)); 177775dc861SAlexander V. Chernikov RTSOCK_ATF_REQUIRE_MSG(rtm, rtm->rtm_errno == 0, 178775dc861SAlexander V. Chernikov "got got errno %d as message reply", rtm->rtm_errno); 179775dc861SAlexander V. Chernikov RTSOCK_ATF_REQUIRE_MSG(rtm, rtm->_rtm_spare1 == 0, 180775dc861SAlexander V. Chernikov "expected rtm_spare==0, got %d", rtm->_rtm_spare1); 181775dc861SAlexander V. Chernikov 182775dc861SAlexander V. Chernikov /* kernel MAY return more sockaddrs, including RTA_IFP / RTA_IFA, so verify the needed ones */ 183775dc861SAlexander V. Chernikov if (dst != NULL) { 184775dc861SAlexander V. Chernikov sa = rtsock_find_rtm_sa(rtm, RTA_DST); 185775dc861SAlexander V. Chernikov RTSOCK_ATF_REQUIRE_MSG(rtm, sa != NULL, "DST is not set"); 186775dc861SAlexander V. Chernikov ret = sa_equal_msg(sa, dst, msg, sizeof(msg)); 187775dc861SAlexander V. Chernikov RTSOCK_ATF_REQUIRE_MSG(rtm, ret != 0, "DST sa diff: %s", msg); 188775dc861SAlexander V. Chernikov } 189775dc861SAlexander V. Chernikov 190775dc861SAlexander V. Chernikov if (mask != NULL) { 191775dc861SAlexander V. Chernikov sa = rtsock_find_rtm_sa(rtm, RTA_NETMASK); 192775dc861SAlexander V. Chernikov RTSOCK_ATF_REQUIRE_MSG(rtm, sa != NULL, "NETMASK is not set"); 193775dc861SAlexander V. Chernikov ret = sa_equal_msg(sa, mask, msg, sizeof(msg)); 19434a5582cSAlexander V. Chernikov ret = 1; 195775dc861SAlexander V. Chernikov RTSOCK_ATF_REQUIRE_MSG(rtm, ret != 0, "NETMASK sa diff: %s", msg); 196775dc861SAlexander V. Chernikov } 197775dc861SAlexander V. Chernikov 198775dc861SAlexander V. Chernikov if (gw != NULL) { 199775dc861SAlexander V. Chernikov sa = rtsock_find_rtm_sa(rtm, RTA_GATEWAY); 200775dc861SAlexander V. Chernikov RTSOCK_ATF_REQUIRE_MSG(rtm, sa != NULL, "GATEWAY is not set"); 201775dc861SAlexander V. Chernikov ret = sa_equal_msg(sa, gw, msg, sizeof(msg)); 202775dc861SAlexander V. Chernikov RTSOCK_ATF_REQUIRE_MSG(rtm, ret != 0, "GATEWAY sa diff: %s", msg); 203775dc861SAlexander V. Chernikov } 204775dc861SAlexander V. Chernikov } 205775dc861SAlexander V. Chernikov 206775dc861SAlexander V. Chernikov static void 207775dc861SAlexander V. Chernikov verify_route_message_extra(struct rt_msghdr *rtm, int ifindex, int rtm_flags) 208775dc861SAlexander V. Chernikov { 209775dc861SAlexander V. Chernikov RTSOCK_ATF_REQUIRE_MSG(rtm, rtm->rtm_index == ifindex, 210775dc861SAlexander V. Chernikov "expected ifindex %d, got %d", ifindex, rtm->rtm_index); 211775dc861SAlexander V. Chernikov 212ac0bea76SAlexander V. Chernikov if (rtm->rtm_flags != rtm_flags) { 213ac0bea76SAlexander V. Chernikov char got_flags[64], expected_flags[64]; 214ac0bea76SAlexander V. Chernikov rtsock_print_rtm_flags(got_flags, sizeof(got_flags), 215ac0bea76SAlexander V. Chernikov rtm->rtm_flags); 216ac0bea76SAlexander V. Chernikov rtsock_print_rtm_flags(expected_flags, sizeof(expected_flags), 217ac0bea76SAlexander V. Chernikov rtm_flags); 218ac0bea76SAlexander V. Chernikov 219775dc861SAlexander V. Chernikov RTSOCK_ATF_REQUIRE_MSG(rtm, rtm->rtm_flags == rtm_flags, 220ac0bea76SAlexander V. Chernikov "expected flags: 0x%X %s, got 0x%X %s", 221ac0bea76SAlexander V. Chernikov rtm_flags, expected_flags, 222ac0bea76SAlexander V. Chernikov rtm->rtm_flags, got_flags); 223ac0bea76SAlexander V. Chernikov } 224e02d3fe7SAlexander V. Chernikov } 225e02d3fe7SAlexander V. Chernikov 226e02d3fe7SAlexander V. Chernikov static void 227e02d3fe7SAlexander V. Chernikov verify_link_gateway(struct rt_msghdr *rtm, int ifindex) 228e02d3fe7SAlexander V. Chernikov { 229e02d3fe7SAlexander V. Chernikov struct sockaddr *sa; 230e02d3fe7SAlexander V. Chernikov struct sockaddr_dl *sdl; 231e02d3fe7SAlexander V. Chernikov 232e02d3fe7SAlexander V. Chernikov sa = rtsock_find_rtm_sa(rtm, RTA_GATEWAY); 233e02d3fe7SAlexander V. Chernikov RTSOCK_ATF_REQUIRE_MSG(rtm, sa != NULL, "GATEWAY is not set"); 234e02d3fe7SAlexander V. Chernikov RTSOCK_ATF_REQUIRE_MSG(rtm, sa->sa_family == AF_LINK, "GW sa family is %d", sa->sa_family); 235e02d3fe7SAlexander V. Chernikov sdl = (struct sockaddr_dl *)sa; 236e02d3fe7SAlexander V. Chernikov RTSOCK_ATF_REQUIRE_MSG(rtm, sdl->sdl_index == ifindex, "GW ifindex is %d", sdl->sdl_index); 237775dc861SAlexander V. Chernikov } 238775dc861SAlexander V. Chernikov 239775dc861SAlexander V. Chernikov /* TESTS */ 240775dc861SAlexander V. Chernikov 241775dc861SAlexander V. Chernikov #define DECLARE_TEST_VARS \ 242775dc861SAlexander V. Chernikov char buffer[2048]; \ 243775dc861SAlexander V. Chernikov struct rtsock_test_config *c; \ 244775dc861SAlexander V. Chernikov struct rt_msghdr *rtm = (struct rt_msghdr *)buffer; \ 245775dc861SAlexander V. Chernikov struct sockaddr *sa; \ 246775dc861SAlexander V. Chernikov int ret; \ 247775dc861SAlexander V. Chernikov \ 248775dc861SAlexander V. Chernikov 249775dc861SAlexander V. Chernikov #define DESCRIBE_ROOT_TEST(_msg) config_describe_root_test(tc, _msg) 250ddc75076SAlexander V. Chernikov #define CLEANUP_AFTER_TEST config_generic_cleanup(tc) 251775dc861SAlexander V. Chernikov 252e02d3fe7SAlexander V. Chernikov #define RTM_DECLARE_ROOT_TEST(_name, _descr) \ 253e02d3fe7SAlexander V. Chernikov ATF_TC_WITH_CLEANUP(_name); \ 254e02d3fe7SAlexander V. Chernikov ATF_TC_HEAD(_name, tc) \ 255e02d3fe7SAlexander V. Chernikov { \ 256e02d3fe7SAlexander V. Chernikov DESCRIBE_ROOT_TEST(_descr); \ 257e02d3fe7SAlexander V. Chernikov } \ 258e02d3fe7SAlexander V. Chernikov ATF_TC_CLEANUP(_name, tc) \ 259e02d3fe7SAlexander V. Chernikov { \ 260e02d3fe7SAlexander V. Chernikov CLEANUP_AFTER_TEST; \ 261e02d3fe7SAlexander V. Chernikov } 262775dc861SAlexander V. Chernikov 263775dc861SAlexander V. Chernikov ATF_TC_WITH_CLEANUP(rtm_get_v4_exact_success); 264775dc861SAlexander V. Chernikov ATF_TC_HEAD(rtm_get_v4_exact_success, tc) 265775dc861SAlexander V. Chernikov { 266775dc861SAlexander V. Chernikov DESCRIBE_ROOT_TEST("Tests RTM_GET with exact prefix lookup on an interface prefix"); 267775dc861SAlexander V. Chernikov } 268775dc861SAlexander V. Chernikov 269775dc861SAlexander V. Chernikov ATF_TC_BODY(rtm_get_v4_exact_success, tc) 270775dc861SAlexander V. Chernikov { 271775dc861SAlexander V. Chernikov DECLARE_TEST_VARS; 272775dc861SAlexander V. Chernikov 273775dc861SAlexander V. Chernikov c = presetup_ipv4(tc); 274775dc861SAlexander V. Chernikov 275775dc861SAlexander V. Chernikov prepare_route_message(rtm, RTM_GET, (struct sockaddr *)&c->net4, 276775dc861SAlexander V. Chernikov (struct sockaddr *)&c->mask4, NULL); 277775dc861SAlexander V. Chernikov 278775dc861SAlexander V. Chernikov rtsock_send_rtm(c->rtsock_fd, rtm); 279775dc861SAlexander V. Chernikov 280775dc861SAlexander V. Chernikov rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq); 281775dc861SAlexander V. Chernikov 282775dc861SAlexander V. Chernikov /* 283775dc861SAlexander V. Chernikov * RTM_GET: Report Metrics: len 240, pid: 45072, seq 42, errno 0, flags: <UP,DONE,PINNED> 284775dc861SAlexander V. Chernikov * sockaddrs: 0x7 <DST,GATEWAY,NETMASK> 285775dc861SAlexander V. Chernikov * af=inet len=16 addr=192.0.2.0 hd={10, 02, 00{2}, C0, 00, 02, 00{9}} 286775dc861SAlexander V. Chernikov * af=link len=54 sdl_index=3 if_name=tap4242 hd={36, 12, 03, 00, 06, 00{49}} 287775dc861SAlexander V. Chernikov * af=inet len=16 addr=255.255.255.0 hd={10, 02, FF{5}, 00{9}} 288775dc861SAlexander V. Chernikov */ 289775dc861SAlexander V. Chernikov 290775dc861SAlexander V. Chernikov verify_route_message(rtm, RTM_GET, (struct sockaddr *)&c->net4, 291775dc861SAlexander V. Chernikov (struct sockaddr *)&c->mask4, NULL); 292775dc861SAlexander V. Chernikov 293775dc861SAlexander V. Chernikov verify_route_message_extra(rtm, c->ifindex, RTF_UP | RTF_DONE | RTF_PINNED); 294775dc861SAlexander V. Chernikov 295775dc861SAlexander V. Chernikov /* Explicitly verify gateway for the interface route */ 296e02d3fe7SAlexander V. Chernikov verify_link_gateway(rtm, c->ifindex); 297775dc861SAlexander V. Chernikov sa = rtsock_find_rtm_sa(rtm, RTA_GATEWAY); 298775dc861SAlexander V. Chernikov RTSOCK_ATF_REQUIRE_MSG(rtm, sa != NULL, "GATEWAY is not set"); 299775dc861SAlexander V. Chernikov RTSOCK_ATF_REQUIRE_MSG(rtm, sa->sa_family == AF_LINK, "GW sa family is %d", sa->sa_family); 300775dc861SAlexander V. Chernikov struct sockaddr_dl *sdl = (struct sockaddr_dl *)sa; 301775dc861SAlexander V. Chernikov RTSOCK_ATF_REQUIRE_MSG(rtm, sdl->sdl_index == c->ifindex, "GW ifindex is %d", sdl->sdl_index); 302775dc861SAlexander V. Chernikov } 303775dc861SAlexander V. Chernikov 304775dc861SAlexander V. Chernikov ATF_TC_CLEANUP(rtm_get_v4_exact_success, tc) 305775dc861SAlexander V. Chernikov { 306775dc861SAlexander V. Chernikov CLEANUP_AFTER_TEST; 307775dc861SAlexander V. Chernikov } 308775dc861SAlexander V. Chernikov 309775dc861SAlexander V. Chernikov ATF_TC_WITH_CLEANUP(rtm_get_v4_lpm_success); 310775dc861SAlexander V. Chernikov ATF_TC_HEAD(rtm_get_v4_lpm_success, tc) 311775dc861SAlexander V. Chernikov { 312775dc861SAlexander V. Chernikov DESCRIBE_ROOT_TEST("Tests RTM_GET with address lookup on an existing prefix"); 313775dc861SAlexander V. Chernikov } 314775dc861SAlexander V. Chernikov 315775dc861SAlexander V. Chernikov ATF_TC_BODY(rtm_get_v4_lpm_success, tc) 316775dc861SAlexander V. Chernikov { 317775dc861SAlexander V. Chernikov DECLARE_TEST_VARS; 318775dc861SAlexander V. Chernikov 319775dc861SAlexander V. Chernikov c = presetup_ipv4(tc); 320775dc861SAlexander V. Chernikov 321775dc861SAlexander V. Chernikov prepare_route_message(rtm, RTM_GET, (struct sockaddr *)&c->net4, NULL, NULL); 322775dc861SAlexander V. Chernikov 323775dc861SAlexander V. Chernikov rtsock_send_rtm(c->rtsock_fd, rtm); 324775dc861SAlexander V. Chernikov 325e02d3fe7SAlexander V. Chernikov rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq); 326775dc861SAlexander V. Chernikov 327775dc861SAlexander V. Chernikov /* 328775dc861SAlexander V. Chernikov * RTM_GET: Report Metrics: len 312, pid: 67074, seq 1, errno 0, flags:<UP,DONE,PINNED> 329775dc861SAlexander V. Chernikov * locks: inits: 330775dc861SAlexander V. Chernikov * sockaddrs: <DST,GATEWAY,NETMASK,IFP,IFA> 331775dc861SAlexander V. Chernikov * 10.0.0.0 link#1 255.255.255.0 vtnet0:52.54.0.42.f.ef 10.0.0.157 332775dc861SAlexander V. Chernikov */ 333775dc861SAlexander V. Chernikov 334775dc861SAlexander V. Chernikov verify_route_message(rtm, RTM_GET, (struct sockaddr *)&c->net4, 335775dc861SAlexander V. Chernikov (struct sockaddr *)&c->mask4, NULL); 336775dc861SAlexander V. Chernikov 337775dc861SAlexander V. Chernikov verify_route_message_extra(rtm, c->ifindex, RTF_UP | RTF_DONE | RTF_PINNED); 338775dc861SAlexander V. Chernikov } 339775dc861SAlexander V. Chernikov 340775dc861SAlexander V. Chernikov ATF_TC_CLEANUP(rtm_get_v4_lpm_success, tc) 341775dc861SAlexander V. Chernikov { 342775dc861SAlexander V. Chernikov CLEANUP_AFTER_TEST; 343775dc861SAlexander V. Chernikov } 344775dc861SAlexander V. Chernikov 345775dc861SAlexander V. Chernikov 346775dc861SAlexander V. Chernikov ATF_TC_WITH_CLEANUP(rtm_get_v4_empty_dst_failure); 347775dc861SAlexander V. Chernikov ATF_TC_HEAD(rtm_get_v4_empty_dst_failure, tc) 348775dc861SAlexander V. Chernikov { 349775dc861SAlexander V. Chernikov 350775dc861SAlexander V. Chernikov DESCRIBE_ROOT_TEST("Tests RTM_GET with empty DST addr"); 351775dc861SAlexander V. Chernikov } 352775dc861SAlexander V. Chernikov 353775dc861SAlexander V. Chernikov ATF_TC_BODY(rtm_get_v4_empty_dst_failure, tc) 354775dc861SAlexander V. Chernikov { 355775dc861SAlexander V. Chernikov DECLARE_TEST_VARS; 356*272bd698SAlexander V. Chernikov struct rtsock_config_options co; 357775dc861SAlexander V. Chernikov 358*272bd698SAlexander V. Chernikov bzero(&co, sizeof(co)); 359*272bd698SAlexander V. Chernikov co.num_interfaces = 0; 360*272bd698SAlexander V. Chernikov 361*272bd698SAlexander V. Chernikov c = config_setup(tc,&co); 362775dc861SAlexander V. Chernikov c->rtsock_fd = rtsock_setup_socket(); 363775dc861SAlexander V. Chernikov 364775dc861SAlexander V. Chernikov rtsock_prepare_route_message(rtm, RTM_GET, NULL, 365775dc861SAlexander V. Chernikov (struct sockaddr *)&c->mask4, NULL); 366775dc861SAlexander V. Chernikov rtsock_update_rtm_len(rtm); 367775dc861SAlexander V. Chernikov 368775dc861SAlexander V. Chernikov write(c->rtsock_fd, rtm, rtm->rtm_msglen); 369775dc861SAlexander V. Chernikov ATF_CHECK_ERRNO(EINVAL, write(c->rtsock_fd, rtm, rtm->rtm_msglen)); 370775dc861SAlexander V. Chernikov } 371775dc861SAlexander V. Chernikov 372775dc861SAlexander V. Chernikov ATF_TC_CLEANUP(rtm_get_v4_empty_dst_failure, tc) 373775dc861SAlexander V. Chernikov { 374775dc861SAlexander V. Chernikov CLEANUP_AFTER_TEST; 375775dc861SAlexander V. Chernikov } 376775dc861SAlexander V. Chernikov 377775dc861SAlexander V. Chernikov ATF_TC_WITH_CLEANUP(rtm_get_v4_hostbits_failure); 378775dc861SAlexander V. Chernikov ATF_TC_HEAD(rtm_get_v4_hostbits_failure, tc) 379775dc861SAlexander V. Chernikov { 380775dc861SAlexander V. Chernikov DESCRIBE_ROOT_TEST("Tests RTM_GET with prefix with some hosts-bits set"); 381775dc861SAlexander V. Chernikov } 382775dc861SAlexander V. Chernikov 383775dc861SAlexander V. Chernikov ATF_TC_BODY(rtm_get_v4_hostbits_failure, tc) 384775dc861SAlexander V. Chernikov { 385775dc861SAlexander V. Chernikov DECLARE_TEST_VARS; 386775dc861SAlexander V. Chernikov 387775dc861SAlexander V. Chernikov c = presetup_ipv4(tc); 388775dc861SAlexander V. Chernikov 389775dc861SAlexander V. Chernikov /* Q the same prefix */ 390775dc861SAlexander V. Chernikov rtsock_prepare_route_message(rtm, RTM_GET, (struct sockaddr *)&c->addr4, 391775dc861SAlexander V. Chernikov (struct sockaddr *)&c->mask4, NULL); 392775dc861SAlexander V. Chernikov rtsock_update_rtm_len(rtm); 393775dc861SAlexander V. Chernikov 394775dc861SAlexander V. Chernikov ATF_CHECK_ERRNO(ESRCH, write(c->rtsock_fd, rtm, rtm->rtm_msglen)); 395775dc861SAlexander V. Chernikov } 396775dc861SAlexander V. Chernikov 397775dc861SAlexander V. Chernikov ATF_TC_CLEANUP(rtm_get_v4_hostbits_failure, tc) 398775dc861SAlexander V. Chernikov { 399775dc861SAlexander V. Chernikov CLEANUP_AFTER_TEST; 400775dc861SAlexander V. Chernikov } 401775dc861SAlexander V. Chernikov 402775dc861SAlexander V. Chernikov ATF_TC_WITH_CLEANUP(rtm_add_v4_gw_direct_success); 403775dc861SAlexander V. Chernikov ATF_TC_HEAD(rtm_add_v4_gw_direct_success, tc) 404775dc861SAlexander V. Chernikov { 405775dc861SAlexander V. Chernikov DESCRIBE_ROOT_TEST("Tests IPv4 route addition with directly-reachable GW specified by IP"); 406775dc861SAlexander V. Chernikov } 407775dc861SAlexander V. Chernikov 408775dc861SAlexander V. Chernikov ATF_TC_BODY(rtm_add_v4_gw_direct_success, tc) 409775dc861SAlexander V. Chernikov { 410775dc861SAlexander V. Chernikov DECLARE_TEST_VARS; 411775dc861SAlexander V. Chernikov 412775dc861SAlexander V. Chernikov c = presetup_ipv4(tc); 413775dc861SAlexander V. Chernikov 414775dc861SAlexander V. Chernikov /* Create IPv4 subnetwork with smaller prefix */ 415775dc861SAlexander V. Chernikov struct sockaddr_in mask4; 416775dc861SAlexander V. Chernikov struct sockaddr_in net4; 417775dc861SAlexander V. Chernikov struct sockaddr_in gw4; 418775dc861SAlexander V. Chernikov prepare_v4_network(c, &net4, &mask4, &gw4); 419775dc861SAlexander V. Chernikov 420775dc861SAlexander V. Chernikov prepare_route_message(rtm, RTM_ADD, (struct sockaddr *)&net4, 421775dc861SAlexander V. Chernikov (struct sockaddr *)&mask4, (struct sockaddr *)&gw4); 422775dc861SAlexander V. Chernikov 423775dc861SAlexander V. Chernikov rtsock_send_rtm(c->rtsock_fd, rtm); 424775dc861SAlexander V. Chernikov rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq); 425775dc861SAlexander V. Chernikov 426775dc861SAlexander V. Chernikov /* 427775dc861SAlexander V. Chernikov * RTM_ADD: Add Route: len 200, pid: 46068, seq 42, errno 0, flags:<GATEWAY,DONE,STATIC> 428775dc861SAlexander V. Chernikov * locks: inits: 429775dc861SAlexander V. Chernikov * sockaddrs: <DST,GATEWAY,NETMASK> 430775dc861SAlexander V. Chernikov * 192.0.2.0 192.0.2.254 255.255.255.128 431775dc861SAlexander V. Chernikov */ 432775dc861SAlexander V. Chernikov 433775dc861SAlexander V. Chernikov verify_route_message(rtm, RTM_ADD, (struct sockaddr *)&net4, 434775dc861SAlexander V. Chernikov (struct sockaddr *)&mask4, (struct sockaddr *)&gw4); 435775dc861SAlexander V. Chernikov /* XXX: Currently kernel sets RTF_UP automatically but does NOT report it in the reply */ 436775dc861SAlexander V. Chernikov verify_route_message_extra(rtm, c->ifindex, RTF_DONE | RTF_GATEWAY | RTF_STATIC); 437775dc861SAlexander V. Chernikov } 438775dc861SAlexander V. Chernikov 439775dc861SAlexander V. Chernikov ATF_TC_CLEANUP(rtm_add_v4_gw_direct_success, tc) 440775dc861SAlexander V. Chernikov { 441775dc861SAlexander V. Chernikov CLEANUP_AFTER_TEST; 442775dc861SAlexander V. Chernikov } 443775dc861SAlexander V. Chernikov 444775dc861SAlexander V. Chernikov ATF_TC_WITH_CLEANUP(rtm_del_v4_prefix_nogw_success); 445775dc861SAlexander V. Chernikov ATF_TC_HEAD(rtm_del_v4_prefix_nogw_success, tc) 446775dc861SAlexander V. Chernikov { 447775dc861SAlexander V. Chernikov DESCRIBE_ROOT_TEST("Tests IPv4 route removal without specifying gateway"); 448775dc861SAlexander V. Chernikov } 449775dc861SAlexander V. Chernikov 450775dc861SAlexander V. Chernikov ATF_TC_BODY(rtm_del_v4_prefix_nogw_success, tc) 451775dc861SAlexander V. Chernikov { 452775dc861SAlexander V. Chernikov DECLARE_TEST_VARS; 453775dc861SAlexander V. Chernikov 454775dc861SAlexander V. Chernikov c = presetup_ipv4(tc); 455775dc861SAlexander V. Chernikov 456775dc861SAlexander V. Chernikov /* Create IPv4 subnetwork with smaller prefix */ 457775dc861SAlexander V. Chernikov struct sockaddr_in mask4; 458775dc861SAlexander V. Chernikov struct sockaddr_in net4; 459775dc861SAlexander V. Chernikov struct sockaddr_in gw4; 460775dc861SAlexander V. Chernikov prepare_v4_network(c, &net4, &mask4, &gw4); 461775dc861SAlexander V. Chernikov 462775dc861SAlexander V. Chernikov prepare_route_message(rtm, RTM_ADD, (struct sockaddr *)&net4, 463775dc861SAlexander V. Chernikov (struct sockaddr *)&mask4, (struct sockaddr *)&gw4); 464775dc861SAlexander V. Chernikov 465775dc861SAlexander V. Chernikov rtsock_send_rtm(c->rtsock_fd, rtm); 466775dc861SAlexander V. Chernikov 467775dc861SAlexander V. Chernikov /* Route has been added successfully, try to delete it */ 468775dc861SAlexander V. Chernikov prepare_route_message(rtm, RTM_DELETE, (struct sockaddr *)&net4, 469775dc861SAlexander V. Chernikov (struct sockaddr *)&mask4, NULL); 470775dc861SAlexander V. Chernikov 471775dc861SAlexander V. Chernikov rtsock_send_rtm(c->rtsock_fd, rtm); 472775dc861SAlexander V. Chernikov 473775dc861SAlexander V. Chernikov rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq); 474775dc861SAlexander V. Chernikov 475775dc861SAlexander V. Chernikov /* 476775dc861SAlexander V. Chernikov * RTM_DELETE: Delete Route: len 200, pid: 46417, seq 43, errno 0, flags: <GATEWAY,DONE,STATIC> 477775dc861SAlexander V. Chernikov * sockaddrs: 0x7 <DST,GATEWAY,NETMASK> 478775dc861SAlexander V. Chernikov * af=inet len=16 addr=192.0.2.0 hd={10, 02, 00{2}, C0, 00, 02, 00{9}} 479775dc861SAlexander V. Chernikov * af=inet len=16 addr=192.0.2.254 hd={10, 02, 00{2}, C0, 00, 02, FE, 00{8}} 480775dc861SAlexander V. Chernikov * af=inet len=16 addr=255.255.255.128 hd={10, 02, FF{5}, 80, 00{8}} 481775dc861SAlexander V. Chernikov */ 482775dc861SAlexander V. Chernikov verify_route_message(rtm, RTM_DELETE, (struct sockaddr *)&net4, 483775dc861SAlexander V. Chernikov (struct sockaddr *)&mask4, (struct sockaddr *)&gw4); 484775dc861SAlexander V. Chernikov 485775dc861SAlexander V. Chernikov verify_route_message_extra(rtm, c->ifindex, RTF_DONE | RTF_GATEWAY | RTF_STATIC); 486775dc861SAlexander V. Chernikov } 487775dc861SAlexander V. Chernikov 488775dc861SAlexander V. Chernikov ATF_TC_CLEANUP(rtm_del_v4_prefix_nogw_success, tc) 489775dc861SAlexander V. Chernikov { 490775dc861SAlexander V. Chernikov CLEANUP_AFTER_TEST; 491775dc861SAlexander V. Chernikov } 492775dc861SAlexander V. Chernikov 493*272bd698SAlexander V. Chernikov RTM_DECLARE_ROOT_TEST(rtm_change_v4_gw_success, 494*272bd698SAlexander V. Chernikov "Tests IPv4 gateway change"); 495*272bd698SAlexander V. Chernikov 496*272bd698SAlexander V. Chernikov ATF_TC_BODY(rtm_change_v4_gw_success, tc) 497*272bd698SAlexander V. Chernikov { 498*272bd698SAlexander V. Chernikov DECLARE_TEST_VARS; 499*272bd698SAlexander V. Chernikov struct rtsock_config_options co; 500*272bd698SAlexander V. Chernikov 501*272bd698SAlexander V. Chernikov bzero(&co, sizeof(co)); 502*272bd698SAlexander V. Chernikov co.num_interfaces = 2; 503*272bd698SAlexander V. Chernikov 504*272bd698SAlexander V. Chernikov c = config_setup(tc, &co); 505*272bd698SAlexander V. Chernikov jump_vnet(c, tc); 506*272bd698SAlexander V. Chernikov 507*272bd698SAlexander V. Chernikov ret = iface_turn_up(c->ifnames[0]); 508*272bd698SAlexander V. Chernikov ATF_REQUIRE_MSG(ret == 0, "Unable to turn up %s", c->ifnames[0]); 509*272bd698SAlexander V. Chernikov ret = iface_turn_up(c->ifnames[1]); 510*272bd698SAlexander V. Chernikov ATF_REQUIRE_MSG(ret == 0, "Unable to turn up %s", c->ifnames[1]); 511*272bd698SAlexander V. Chernikov 512*272bd698SAlexander V. Chernikov ret = iface_setup_addr(c->ifnames[0], c->addr4_str, c->plen4); 513*272bd698SAlexander V. Chernikov ATF_REQUIRE_MSG(ret == 0, "ifconfig failed"); 514*272bd698SAlexander V. Chernikov 515*272bd698SAlexander V. Chernikov /* Use 198.51.100.0/24 "TEST-NET-2" for the second interface */ 516*272bd698SAlexander V. Chernikov ret = iface_setup_addr(c->ifnames[1], "198.51.100.1", 24); 517*272bd698SAlexander V. Chernikov ATF_REQUIRE_MSG(ret == 0, "ifconfig failed"); 518*272bd698SAlexander V. Chernikov 519*272bd698SAlexander V. Chernikov c->rtsock_fd = rtsock_setup_socket(); 520*272bd698SAlexander V. Chernikov 521*272bd698SAlexander V. Chernikov /* Create IPv4 subnetwork with smaller prefix */ 522*272bd698SAlexander V. Chernikov struct sockaddr_in mask4; 523*272bd698SAlexander V. Chernikov struct sockaddr_in net4; 524*272bd698SAlexander V. Chernikov struct sockaddr_in gw4; 525*272bd698SAlexander V. Chernikov prepare_v4_network(c, &net4, &mask4, &gw4); 526*272bd698SAlexander V. Chernikov 527*272bd698SAlexander V. Chernikov prepare_route_message(rtm, RTM_ADD, (struct sockaddr *)&net4, 528*272bd698SAlexander V. Chernikov (struct sockaddr *)&mask4, (struct sockaddr *)&gw4); 529*272bd698SAlexander V. Chernikov 530*272bd698SAlexander V. Chernikov rtsock_send_rtm(c->rtsock_fd, rtm); 531*272bd698SAlexander V. Chernikov rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq); 532*272bd698SAlexander V. Chernikov 533*272bd698SAlexander V. Chernikov verify_route_message(rtm, RTM_ADD, (struct sockaddr *)&net4, 534*272bd698SAlexander V. Chernikov (struct sockaddr *)&mask4, (struct sockaddr *)&gw4); 535*272bd698SAlexander V. Chernikov 536*272bd698SAlexander V. Chernikov /* Change gateway to the one on desiding on the other interface */ 537*272bd698SAlexander V. Chernikov inet_pton(AF_INET, "198.51.100.2", &gw4.sin_addr.s_addr); 538*272bd698SAlexander V. Chernikov prepare_route_message(rtm, RTM_CHANGE, (struct sockaddr *)&net4, 539*272bd698SAlexander V. Chernikov (struct sockaddr *)&mask4, (struct sockaddr *)&gw4); 540*272bd698SAlexander V. Chernikov rtsock_send_rtm(c->rtsock_fd, rtm); 541*272bd698SAlexander V. Chernikov 542*272bd698SAlexander V. Chernikov rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq); 543*272bd698SAlexander V. Chernikov 544*272bd698SAlexander V. Chernikov verify_route_message(rtm, RTM_CHANGE, (struct sockaddr *)&net4, 545*272bd698SAlexander V. Chernikov (struct sockaddr *)&mask4, (struct sockaddr *)&gw4); 546*272bd698SAlexander V. Chernikov 547*272bd698SAlexander V. Chernikov verify_route_message_extra(rtm, if_nametoindex(c->ifnames[1]), 548*272bd698SAlexander V. Chernikov RTF_DONE | RTF_GATEWAY | RTF_STATIC); 549*272bd698SAlexander V. Chernikov 550*272bd698SAlexander V. Chernikov /* Verify the change has actually taken place */ 551*272bd698SAlexander V. Chernikov prepare_route_message(rtm, RTM_GET, (struct sockaddr *)&net4, 552*272bd698SAlexander V. Chernikov (struct sockaddr *)&mask4, NULL); 553*272bd698SAlexander V. Chernikov 554*272bd698SAlexander V. Chernikov rtsock_send_rtm(c->rtsock_fd, rtm); 555*272bd698SAlexander V. Chernikov 556*272bd698SAlexander V. Chernikov /* 557*272bd698SAlexander V. Chernikov * RTM_GET: len 200, pid: 3894, seq 44, errno 0, flags: <UP,GATEWAY,DONE,STATIC> 558*272bd698SAlexander V. Chernikov * sockaddrs: 0x7 <DST,GATEWAY,NETMASK> 559*272bd698SAlexander V. Chernikov * af=inet len=16 addr=192.0.2.0 hd={x10, x02, x00{2}, xC0, x00, x02, x00{9}} 560*272bd698SAlexander V. Chernikov * af=inet len=16 addr=198.51.100.2 hd={x10, x02, x00{2}, xC6, x33, x64, x02, x00{8}} 561*272bd698SAlexander V. Chernikov * af=inet len=16 addr=255.255.255.128 hd={x10, x02, xFF, xFF, xFF, xFF, xFF, x80, x00{8}} 562*272bd698SAlexander V. Chernikov */ 563*272bd698SAlexander V. Chernikov 564*272bd698SAlexander V. Chernikov rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq); 565*272bd698SAlexander V. Chernikov verify_route_message_extra(rtm, if_nametoindex(c->ifnames[1]), 566*272bd698SAlexander V. Chernikov RTF_UP | RTF_DONE | RTF_GATEWAY | RTF_STATIC); 567*272bd698SAlexander V. Chernikov 568*272bd698SAlexander V. Chernikov } 569*272bd698SAlexander V. Chernikov 570*272bd698SAlexander V. Chernikov RTM_DECLARE_ROOT_TEST(rtm_change_v4_mtu_success, 571*272bd698SAlexander V. Chernikov "Tests IPv4 path mtu change"); 572*272bd698SAlexander V. Chernikov 573*272bd698SAlexander V. Chernikov ATF_TC_BODY(rtm_change_v4_mtu_success, tc) 574*272bd698SAlexander V. Chernikov { 575*272bd698SAlexander V. Chernikov DECLARE_TEST_VARS; 576*272bd698SAlexander V. Chernikov 577*272bd698SAlexander V. Chernikov unsigned long test_mtu = 1442; 578*272bd698SAlexander V. Chernikov 579*272bd698SAlexander V. Chernikov c = presetup_ipv4(tc); 580*272bd698SAlexander V. Chernikov 581*272bd698SAlexander V. Chernikov /* Create IPv4 subnetwork with smaller prefix */ 582*272bd698SAlexander V. Chernikov struct sockaddr_in mask4; 583*272bd698SAlexander V. Chernikov struct sockaddr_in net4; 584*272bd698SAlexander V. Chernikov struct sockaddr_in gw4; 585*272bd698SAlexander V. Chernikov prepare_v4_network(c, &net4, &mask4, &gw4); 586*272bd698SAlexander V. Chernikov 587*272bd698SAlexander V. Chernikov prepare_route_message(rtm, RTM_ADD, (struct sockaddr *)&net4, 588*272bd698SAlexander V. Chernikov (struct sockaddr *)&mask4, (struct sockaddr *)&gw4); 589*272bd698SAlexander V. Chernikov 590*272bd698SAlexander V. Chernikov rtsock_send_rtm(c->rtsock_fd, rtm); 591*272bd698SAlexander V. Chernikov rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq); 592*272bd698SAlexander V. Chernikov 593*272bd698SAlexander V. Chernikov /* Change MTU */ 594*272bd698SAlexander V. Chernikov prepare_route_message(rtm, RTM_CHANGE, (struct sockaddr *)&net4, 595*272bd698SAlexander V. Chernikov (struct sockaddr *)&mask4, NULL); 596*272bd698SAlexander V. Chernikov rtm->rtm_inits |= RTV_MTU; 597*272bd698SAlexander V. Chernikov rtm->rtm_rmx.rmx_mtu = test_mtu; 598*272bd698SAlexander V. Chernikov 599*272bd698SAlexander V. Chernikov rtsock_send_rtm(c->rtsock_fd, rtm); 600*272bd698SAlexander V. Chernikov rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq); 601*272bd698SAlexander V. Chernikov 602*272bd698SAlexander V. Chernikov verify_route_message(rtm, RTM_CHANGE, (struct sockaddr *)&net4, 603*272bd698SAlexander V. Chernikov (struct sockaddr *)&mask4, NULL); 604*272bd698SAlexander V. Chernikov 605*272bd698SAlexander V. Chernikov RTSOCK_ATF_REQUIRE_MSG(rtm, rtm->rtm_rmx.rmx_mtu == test_mtu, 606*272bd698SAlexander V. Chernikov "expected mtu: %lu, got %lu", test_mtu, rtm->rtm_rmx.rmx_mtu); 607*272bd698SAlexander V. Chernikov 608*272bd698SAlexander V. Chernikov /* Verify the change has actually taken place */ 609*272bd698SAlexander V. Chernikov prepare_route_message(rtm, RTM_GET, (struct sockaddr *)&net4, 610*272bd698SAlexander V. Chernikov (struct sockaddr *)&mask4, NULL); 611*272bd698SAlexander V. Chernikov 612*272bd698SAlexander V. Chernikov rtsock_send_rtm(c->rtsock_fd, rtm); 613*272bd698SAlexander V. Chernikov rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq); 614*272bd698SAlexander V. Chernikov 615*272bd698SAlexander V. Chernikov RTSOCK_ATF_REQUIRE_MSG(rtm, rtm->rtm_rmx.rmx_mtu == test_mtu, 616*272bd698SAlexander V. Chernikov "expected mtu: %lu, got %lu", test_mtu, rtm->rtm_rmx.rmx_mtu); 617*272bd698SAlexander V. Chernikov } 618*272bd698SAlexander V. Chernikov 619*272bd698SAlexander V. Chernikov 620775dc861SAlexander V. Chernikov ATF_TC_WITH_CLEANUP(rtm_add_v6_gu_gw_gu_direct_success); 621775dc861SAlexander V. Chernikov ATF_TC_HEAD(rtm_add_v6_gu_gw_gu_direct_success, tc) 622775dc861SAlexander V. Chernikov { 623775dc861SAlexander V. Chernikov DESCRIBE_ROOT_TEST("Tests IPv6 global unicast prefix addition with directly-reachable GU GW"); 624775dc861SAlexander V. Chernikov } 625775dc861SAlexander V. Chernikov 626775dc861SAlexander V. Chernikov ATF_TC_BODY(rtm_add_v6_gu_gw_gu_direct_success, tc) 627775dc861SAlexander V. Chernikov { 628775dc861SAlexander V. Chernikov DECLARE_TEST_VARS; 629775dc861SAlexander V. Chernikov 630775dc861SAlexander V. Chernikov c = presetup_ipv6(tc); 631775dc861SAlexander V. Chernikov 632775dc861SAlexander V. Chernikov /* Create IPv6 subnetwork with smaller prefix */ 633775dc861SAlexander V. Chernikov struct sockaddr_in6 mask6; 634775dc861SAlexander V. Chernikov struct sockaddr_in6 net6; 635775dc861SAlexander V. Chernikov struct sockaddr_in6 gw6; 636775dc861SAlexander V. Chernikov prepare_v6_network(c, &net6, &mask6, &gw6); 637775dc861SAlexander V. Chernikov 638775dc861SAlexander V. Chernikov prepare_route_message(rtm, RTM_ADD, (struct sockaddr *)&net6, 639775dc861SAlexander V. Chernikov (struct sockaddr *)&mask6, (struct sockaddr *)&gw6); 640775dc861SAlexander V. Chernikov 641775dc861SAlexander V. Chernikov rtsock_send_rtm(c->rtsock_fd, rtm); 642775dc861SAlexander V. Chernikov rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq); 643775dc861SAlexander V. Chernikov 644775dc861SAlexander V. Chernikov /* 645775dc861SAlexander V. Chernikov * RTM_ADD: Add Route: len 200, pid: 46068, seq 42, errno 0, flags:<GATEWAY,DONE,STATIC> 646775dc861SAlexander V. Chernikov * locks: inits: 647775dc861SAlexander V. Chernikov * sockaddrs: <DST,GATEWAY,NETMASK> 648775dc861SAlexander V. Chernikov * 192.0.2.0 192.0.2.254 255.255.255.128 649775dc861SAlexander V. Chernikov */ 650775dc861SAlexander V. Chernikov 651775dc861SAlexander V. Chernikov verify_route_message(rtm, RTM_ADD, (struct sockaddr *)&net6, 652775dc861SAlexander V. Chernikov (struct sockaddr *)&mask6, (struct sockaddr *)&gw6); 653775dc861SAlexander V. Chernikov 654775dc861SAlexander V. Chernikov /* XXX: Currently kernel sets RTF_UP automatically but does NOT report it in the reply */ 655775dc861SAlexander V. Chernikov verify_route_message_extra(rtm, c->ifindex, RTF_DONE | RTF_GATEWAY | RTF_STATIC); 656775dc861SAlexander V. Chernikov } 657775dc861SAlexander V. Chernikov 658775dc861SAlexander V. Chernikov ATF_TC_CLEANUP(rtm_add_v6_gu_gw_gu_direct_success, tc) 659775dc861SAlexander V. Chernikov { 660775dc861SAlexander V. Chernikov CLEANUP_AFTER_TEST; 661775dc861SAlexander V. Chernikov } 662775dc861SAlexander V. Chernikov 663775dc861SAlexander V. Chernikov ATF_TC_WITH_CLEANUP(rtm_del_v6_gu_prefix_nogw_success); 664775dc861SAlexander V. Chernikov ATF_TC_HEAD(rtm_del_v6_gu_prefix_nogw_success, tc) 665775dc861SAlexander V. Chernikov { 666775dc861SAlexander V. Chernikov 667775dc861SAlexander V. Chernikov DESCRIBE_ROOT_TEST("Tests IPv6 global unicast prefix removal without specifying gateway"); 668775dc861SAlexander V. Chernikov } 669775dc861SAlexander V. Chernikov 670775dc861SAlexander V. Chernikov ATF_TC_BODY(rtm_del_v6_gu_prefix_nogw_success, tc) 671775dc861SAlexander V. Chernikov { 672775dc861SAlexander V. Chernikov DECLARE_TEST_VARS; 673775dc861SAlexander V. Chernikov 674775dc861SAlexander V. Chernikov c = presetup_ipv6(tc); 675775dc861SAlexander V. Chernikov 676775dc861SAlexander V. Chernikov /* Create IPv6 subnetwork with smaller prefix */ 677775dc861SAlexander V. Chernikov struct sockaddr_in6 mask6; 678775dc861SAlexander V. Chernikov struct sockaddr_in6 net6; 679775dc861SAlexander V. Chernikov struct sockaddr_in6 gw6; 680775dc861SAlexander V. Chernikov prepare_v6_network(c, &net6, &mask6, &gw6); 681775dc861SAlexander V. Chernikov 682775dc861SAlexander V. Chernikov prepare_route_message(rtm, RTM_ADD, (struct sockaddr *)&net6, 683775dc861SAlexander V. Chernikov (struct sockaddr *)&mask6, (struct sockaddr *)&gw6); 684775dc861SAlexander V. Chernikov 685775dc861SAlexander V. Chernikov rtsock_send_rtm(c->rtsock_fd, rtm); 686775dc861SAlexander V. Chernikov 687775dc861SAlexander V. Chernikov /* Route has been added successfully, try to delete it */ 688775dc861SAlexander V. Chernikov prepare_route_message(rtm, RTM_DELETE, (struct sockaddr *)&net6, 689775dc861SAlexander V. Chernikov (struct sockaddr *)&mask6, NULL); 690775dc861SAlexander V. Chernikov 691775dc861SAlexander V. Chernikov rtsock_send_rtm(c->rtsock_fd, rtm); 692775dc861SAlexander V. Chernikov rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq); 693775dc861SAlexander V. Chernikov 694775dc861SAlexander V. Chernikov /* 695775dc861SAlexander V. Chernikov * RTM_DELETE: Delete Route: len 200, pid: 46417, seq 43, errno 0, flags: <GATEWAY,DONE,STATIC> 696775dc861SAlexander V. Chernikov * sockaddrs: 0x7 <DST,GATEWAY,NETMASK> 697775dc861SAlexander V. Chernikov * af=inet len=16 addr=192.0.2.0 hd={10, 02, 00{2}, C0, 00, 02, 00{9}} 698775dc861SAlexander V. Chernikov * af=inet len=16 addr=192.0.2.254 hd={10, 02, 00{2}, C0, 00, 02, FE, 00{8}} 699775dc861SAlexander V. Chernikov * af=inet len=16 addr=255.255.255.128 hd={10, 02, FF{5}, 80, 00{8}} 700775dc861SAlexander V. Chernikov */ 701775dc861SAlexander V. Chernikov 702775dc861SAlexander V. Chernikov verify_route_message(rtm, RTM_DELETE, (struct sockaddr *)&net6, 703775dc861SAlexander V. Chernikov (struct sockaddr *)&mask6, (struct sockaddr *)&gw6); 704775dc861SAlexander V. Chernikov verify_route_message_extra(rtm, c->ifindex, RTF_DONE | RTF_GATEWAY | RTF_STATIC); 705775dc861SAlexander V. Chernikov } 706775dc861SAlexander V. Chernikov 707775dc861SAlexander V. Chernikov ATF_TC_CLEANUP(rtm_del_v6_gu_prefix_nogw_success, tc) 708775dc861SAlexander V. Chernikov { 709775dc861SAlexander V. Chernikov CLEANUP_AFTER_TEST; 710775dc861SAlexander V. Chernikov } 711775dc861SAlexander V. Chernikov 712*272bd698SAlexander V. Chernikov RTM_DECLARE_ROOT_TEST(rtm_change_v6_gw_success, 713*272bd698SAlexander V. Chernikov "Tests IPv6 gateway change"); 714*272bd698SAlexander V. Chernikov 715*272bd698SAlexander V. Chernikov ATF_TC_BODY(rtm_change_v6_gw_success, tc) 716*272bd698SAlexander V. Chernikov { 717*272bd698SAlexander V. Chernikov DECLARE_TEST_VARS; 718*272bd698SAlexander V. Chernikov struct rtsock_config_options co; 719*272bd698SAlexander V. Chernikov 720*272bd698SAlexander V. Chernikov bzero(&co, sizeof(co)); 721*272bd698SAlexander V. Chernikov co.num_interfaces = 2; 722*272bd698SAlexander V. Chernikov 723*272bd698SAlexander V. Chernikov c = config_setup(tc, &co); 724*272bd698SAlexander V. Chernikov jump_vnet(c, tc); 725*272bd698SAlexander V. Chernikov 726*272bd698SAlexander V. Chernikov ret = iface_turn_up(c->ifnames[0]); 727*272bd698SAlexander V. Chernikov ATF_REQUIRE_MSG(ret == 0, "Unable to turn up %s", c->ifnames[0]); 728*272bd698SAlexander V. Chernikov ret = iface_turn_up(c->ifnames[1]); 729*272bd698SAlexander V. Chernikov ATF_REQUIRE_MSG(ret == 0, "Unable to turn up %s", c->ifnames[1]); 730*272bd698SAlexander V. Chernikov 731*272bd698SAlexander V. Chernikov ret = iface_enable_ipv6(c->ifnames[0]); 732*272bd698SAlexander V. Chernikov ATF_REQUIRE_MSG(ret == 0, "Unable to enable IPv6 on %s", c->ifnames[0]); 733*272bd698SAlexander V. Chernikov ret = iface_enable_ipv6(c->ifnames[1]); 734*272bd698SAlexander V. Chernikov ATF_REQUIRE_MSG(ret == 0, "Unable to enable IPv6 on %s", c->ifnames[1]); 735*272bd698SAlexander V. Chernikov 736*272bd698SAlexander V. Chernikov ret = iface_setup_addr(c->ifnames[0], c->addr6_str, c->plen6); 737*272bd698SAlexander V. Chernikov ATF_REQUIRE_MSG(ret == 0, "ifconfig failed"); 738*272bd698SAlexander V. Chernikov 739*272bd698SAlexander V. Chernikov ret = iface_setup_addr(c->ifnames[1], "2001:DB8:4242::1", 64); 740*272bd698SAlexander V. Chernikov ATF_REQUIRE_MSG(ret == 0, "ifconfig failed"); 741*272bd698SAlexander V. Chernikov 742*272bd698SAlexander V. Chernikov c->rtsock_fd = rtsock_setup_socket(); 743*272bd698SAlexander V. Chernikov 744*272bd698SAlexander V. Chernikov /* Create IPv6 subnetwork with smaller prefix */ 745*272bd698SAlexander V. Chernikov struct sockaddr_in6 mask6; 746*272bd698SAlexander V. Chernikov struct sockaddr_in6 net6; 747*272bd698SAlexander V. Chernikov struct sockaddr_in6 gw6; 748*272bd698SAlexander V. Chernikov prepare_v6_network(c, &net6, &mask6, &gw6); 749*272bd698SAlexander V. Chernikov 750*272bd698SAlexander V. Chernikov prepare_route_message(rtm, RTM_ADD, (struct sockaddr *)&net6, 751*272bd698SAlexander V. Chernikov (struct sockaddr *)&mask6, (struct sockaddr *)&gw6); 752*272bd698SAlexander V. Chernikov 753*272bd698SAlexander V. Chernikov rtsock_send_rtm(c->rtsock_fd, rtm); 754*272bd698SAlexander V. Chernikov rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq); 755*272bd698SAlexander V. Chernikov 756*272bd698SAlexander V. Chernikov verify_route_message(rtm, RTM_ADD, (struct sockaddr *)&net6, 757*272bd698SAlexander V. Chernikov (struct sockaddr *)&mask6, (struct sockaddr *)&gw6); 758*272bd698SAlexander V. Chernikov 759*272bd698SAlexander V. Chernikov /* Change gateway to the one on residing on the other interface */ 760*272bd698SAlexander V. Chernikov inet_pton(AF_INET6, "2001:DB8:4242::4242", &gw6.sin6_addr); 761*272bd698SAlexander V. Chernikov prepare_route_message(rtm, RTM_CHANGE, (struct sockaddr *)&net6, 762*272bd698SAlexander V. Chernikov (struct sockaddr *)&mask6, (struct sockaddr *)&gw6); 763*272bd698SAlexander V. Chernikov rtsock_send_rtm(c->rtsock_fd, rtm); 764*272bd698SAlexander V. Chernikov 765*272bd698SAlexander V. Chernikov rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq); 766*272bd698SAlexander V. Chernikov 767*272bd698SAlexander V. Chernikov verify_route_message(rtm, RTM_CHANGE, (struct sockaddr *)&net6, 768*272bd698SAlexander V. Chernikov (struct sockaddr *)&mask6, (struct sockaddr *)&gw6); 769*272bd698SAlexander V. Chernikov 770*272bd698SAlexander V. Chernikov verify_route_message_extra(rtm, if_nametoindex(c->ifnames[1]), 771*272bd698SAlexander V. Chernikov RTF_DONE | RTF_GATEWAY | RTF_STATIC); 772*272bd698SAlexander V. Chernikov 773*272bd698SAlexander V. Chernikov /* Verify the change has actually taken place */ 774*272bd698SAlexander V. Chernikov prepare_route_message(rtm, RTM_GET, (struct sockaddr *)&net6, 775*272bd698SAlexander V. Chernikov (struct sockaddr *)&mask6, NULL); 776*272bd698SAlexander V. Chernikov 777*272bd698SAlexander V. Chernikov rtsock_send_rtm(c->rtsock_fd, rtm); 778*272bd698SAlexander V. Chernikov 779*272bd698SAlexander V. Chernikov /* 780*272bd698SAlexander V. Chernikov * RTM_GET: len 248, pid: 2268, seq 44, errno 0, flags: <UP,GATEWAY,DONE,STATIC> 781*272bd698SAlexander V. Chernikov * sockaddrs: 0x7 <DST,GATEWAY,NETMASK> 782*272bd698SAlexander V. Chernikov * af=inet6 len=28 addr=2001:db8:: hd={x1C, x1C, x00{6}, x20, x01, x0D, xB8, x00{16}} 783*272bd698SAlexander V. Chernikov * af=inet6 len=28 addr=2001:db8:4242::4242 hd={x1C, x1C, x00{6}, x20, x01, x0D, xB8, x42, x42, x00{8}, x42, x42, x00{4}} 784*272bd698SAlexander V. Chernikov * af=inet6 len=28 addr=ffff:ffff:8000:: hd={x1C, x1C, xFF, xFF, xFF, xFF, xFF, xFF, xFF, xFF, xFF, xFF, x80, x00{15}} 785*272bd698SAlexander V. Chernikov */ 786*272bd698SAlexander V. Chernikov 787*272bd698SAlexander V. Chernikov rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq); 788*272bd698SAlexander V. Chernikov verify_route_message_extra(rtm, if_nametoindex(c->ifnames[1]), 789*272bd698SAlexander V. Chernikov RTF_UP | RTF_DONE | RTF_GATEWAY | RTF_STATIC); 790*272bd698SAlexander V. Chernikov } 791*272bd698SAlexander V. Chernikov 792*272bd698SAlexander V. Chernikov RTM_DECLARE_ROOT_TEST(rtm_change_v6_mtu_success, 793*272bd698SAlexander V. Chernikov "Tests IPv6 path mtu change"); 794*272bd698SAlexander V. Chernikov 795*272bd698SAlexander V. Chernikov ATF_TC_BODY(rtm_change_v6_mtu_success, tc) 796*272bd698SAlexander V. Chernikov { 797*272bd698SAlexander V. Chernikov DECLARE_TEST_VARS; 798*272bd698SAlexander V. Chernikov 799*272bd698SAlexander V. Chernikov unsigned long test_mtu = 1442; 800*272bd698SAlexander V. Chernikov 801*272bd698SAlexander V. Chernikov c = presetup_ipv6(tc); 802*272bd698SAlexander V. Chernikov 803*272bd698SAlexander V. Chernikov /* Create IPv6 subnetwork with smaller prefix */ 804*272bd698SAlexander V. Chernikov struct sockaddr_in6 mask6; 805*272bd698SAlexander V. Chernikov struct sockaddr_in6 net6; 806*272bd698SAlexander V. Chernikov struct sockaddr_in6 gw6; 807*272bd698SAlexander V. Chernikov prepare_v6_network(c, &net6, &mask6, &gw6); 808*272bd698SAlexander V. Chernikov 809*272bd698SAlexander V. Chernikov prepare_route_message(rtm, RTM_ADD, (struct sockaddr *)&net6, 810*272bd698SAlexander V. Chernikov (struct sockaddr *)&mask6, (struct sockaddr *)&gw6); 811*272bd698SAlexander V. Chernikov 812*272bd698SAlexander V. Chernikov /* Send route add */ 813*272bd698SAlexander V. Chernikov rtsock_send_rtm(c->rtsock_fd, rtm); 814*272bd698SAlexander V. Chernikov rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq); 815*272bd698SAlexander V. Chernikov 816*272bd698SAlexander V. Chernikov /* Change MTU */ 817*272bd698SAlexander V. Chernikov prepare_route_message(rtm, RTM_CHANGE, (struct sockaddr *)&net6, 818*272bd698SAlexander V. Chernikov (struct sockaddr *)&mask6, NULL); 819*272bd698SAlexander V. Chernikov rtm->rtm_inits |= RTV_MTU; 820*272bd698SAlexander V. Chernikov rtm->rtm_rmx.rmx_mtu = test_mtu; 821*272bd698SAlexander V. Chernikov 822*272bd698SAlexander V. Chernikov rtsock_send_rtm(c->rtsock_fd, rtm); 823*272bd698SAlexander V. Chernikov rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq); 824*272bd698SAlexander V. Chernikov 825*272bd698SAlexander V. Chernikov verify_route_message(rtm, RTM_CHANGE, (struct sockaddr *)&net6, 826*272bd698SAlexander V. Chernikov (struct sockaddr *)&mask6, NULL); 827*272bd698SAlexander V. Chernikov 828*272bd698SAlexander V. Chernikov RTSOCK_ATF_REQUIRE_MSG(rtm, rtm->rtm_rmx.rmx_mtu == test_mtu, 829*272bd698SAlexander V. Chernikov "expected mtu: %lu, got %lu", test_mtu, rtm->rtm_rmx.rmx_mtu); 830*272bd698SAlexander V. Chernikov 831*272bd698SAlexander V. Chernikov /* Verify the change has actually taken place */ 832*272bd698SAlexander V. Chernikov prepare_route_message(rtm, RTM_GET, (struct sockaddr *)&net6, 833*272bd698SAlexander V. Chernikov (struct sockaddr *)&mask6, NULL); 834*272bd698SAlexander V. Chernikov 835*272bd698SAlexander V. Chernikov rtsock_send_rtm(c->rtsock_fd, rtm); 836*272bd698SAlexander V. Chernikov rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq); 837*272bd698SAlexander V. Chernikov 838*272bd698SAlexander V. Chernikov RTSOCK_ATF_REQUIRE_MSG(rtm, rtm->rtm_rmx.rmx_mtu == test_mtu, 839*272bd698SAlexander V. Chernikov "expected mtu: %lu, got %lu", test_mtu, rtm->rtm_rmx.rmx_mtu); 840*272bd698SAlexander V. Chernikov } 841*272bd698SAlexander V. Chernikov 842e02d3fe7SAlexander V. Chernikov ATF_TC_WITH_CLEANUP(rtm_add_v4_temporal1_success); 843e02d3fe7SAlexander V. Chernikov ATF_TC_HEAD(rtm_add_v4_temporal1_success, tc) 844e02d3fe7SAlexander V. Chernikov { 845e02d3fe7SAlexander V. Chernikov DESCRIBE_ROOT_TEST("Tests IPv4 route expiration with expire time set"); 846e02d3fe7SAlexander V. Chernikov } 847e02d3fe7SAlexander V. Chernikov 848e02d3fe7SAlexander V. Chernikov ATF_TC_BODY(rtm_add_v4_temporal1_success, tc) 849e02d3fe7SAlexander V. Chernikov { 850e02d3fe7SAlexander V. Chernikov DECLARE_TEST_VARS; 851e02d3fe7SAlexander V. Chernikov 852e02d3fe7SAlexander V. Chernikov c = presetup_ipv4(tc); 853e02d3fe7SAlexander V. Chernikov 854e02d3fe7SAlexander V. Chernikov /* Create IPv4 subnetwork with smaller prefix */ 855e02d3fe7SAlexander V. Chernikov struct sockaddr_in mask4; 856e02d3fe7SAlexander V. Chernikov struct sockaddr_in net4; 857e02d3fe7SAlexander V. Chernikov struct sockaddr_in gw4; 858e02d3fe7SAlexander V. Chernikov prepare_v4_network(c, &net4, &mask4, &gw4); 859e02d3fe7SAlexander V. Chernikov 860e02d3fe7SAlexander V. Chernikov prepare_route_message(rtm, RTM_ADD, (struct sockaddr *)&net4, 861e02d3fe7SAlexander V. Chernikov (struct sockaddr *)&mask4, (struct sockaddr *)&gw4); 862e02d3fe7SAlexander V. Chernikov 863e02d3fe7SAlexander V. Chernikov /* Set expire time to now */ 864e02d3fe7SAlexander V. Chernikov struct timeval tv; 865e02d3fe7SAlexander V. Chernikov gettimeofday(&tv, NULL); 866e02d3fe7SAlexander V. Chernikov rtm->rtm_rmx.rmx_expire = tv.tv_sec - 1; 867e02d3fe7SAlexander V. Chernikov rtm->rtm_inits |= RTV_EXPIRE; 868e02d3fe7SAlexander V. Chernikov 869e02d3fe7SAlexander V. Chernikov rtsock_send_rtm(c->rtsock_fd, rtm); 870e02d3fe7SAlexander V. Chernikov rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq); 871e02d3fe7SAlexander V. Chernikov ATF_REQUIRE_MSG(rtm != NULL, "unable to get rtsock reply for RTM_ADD"); 872e02d3fe7SAlexander V. Chernikov RTSOCK_ATF_REQUIRE_MSG(rtm, rtm->rtm_inits & RTV_EXPIRE, "RTV_EXPIRE not set"); 873e02d3fe7SAlexander V. Chernikov 874e02d3fe7SAlexander V. Chernikov /* The next should be route deletion */ 875e02d3fe7SAlexander V. Chernikov rtm = rtsock_read_rtm(c->rtsock_fd, buffer, sizeof(buffer)); 876e02d3fe7SAlexander V. Chernikov 877e02d3fe7SAlexander V. Chernikov verify_route_message(rtm, RTM_DELETE, (struct sockaddr *)&net4, 878e02d3fe7SAlexander V. Chernikov (struct sockaddr *)&mask4, (struct sockaddr *)&gw4); 879e02d3fe7SAlexander V. Chernikov 88034a5582cSAlexander V. Chernikov verify_route_message_extra(rtm, c->ifindex, RTF_GATEWAY | RTF_DONE | RTF_STATIC); 881e02d3fe7SAlexander V. Chernikov } 882e02d3fe7SAlexander V. Chernikov 883e02d3fe7SAlexander V. Chernikov ATF_TC_CLEANUP(rtm_add_v4_temporal1_success, tc) 884e02d3fe7SAlexander V. Chernikov { 885e02d3fe7SAlexander V. Chernikov CLEANUP_AFTER_TEST; 886e02d3fe7SAlexander V. Chernikov } 887e02d3fe7SAlexander V. Chernikov 888e02d3fe7SAlexander V. Chernikov ATF_TC_WITH_CLEANUP(rtm_add_v6_temporal1_success); 889e02d3fe7SAlexander V. Chernikov ATF_TC_HEAD(rtm_add_v6_temporal1_success, tc) 890e02d3fe7SAlexander V. Chernikov { 891e02d3fe7SAlexander V. Chernikov DESCRIBE_ROOT_TEST("Tests IPv6 global unicast prefix addition with directly-reachable GU GW"); 892e02d3fe7SAlexander V. Chernikov } 893e02d3fe7SAlexander V. Chernikov 894e02d3fe7SAlexander V. Chernikov ATF_TC_BODY(rtm_add_v6_temporal1_success, tc) 895e02d3fe7SAlexander V. Chernikov { 896e02d3fe7SAlexander V. Chernikov DECLARE_TEST_VARS; 897e02d3fe7SAlexander V. Chernikov 898e02d3fe7SAlexander V. Chernikov c = presetup_ipv6(tc); 899e02d3fe7SAlexander V. Chernikov 900e02d3fe7SAlexander V. Chernikov /* Create IPv6 subnetwork with smaller prefix */ 901e02d3fe7SAlexander V. Chernikov struct sockaddr_in6 mask6; 902e02d3fe7SAlexander V. Chernikov struct sockaddr_in6 net6; 903e02d3fe7SAlexander V. Chernikov struct sockaddr_in6 gw6; 904e02d3fe7SAlexander V. Chernikov prepare_v6_network(c, &net6, &mask6, &gw6); 905e02d3fe7SAlexander V. Chernikov 906e02d3fe7SAlexander V. Chernikov prepare_route_message(rtm, RTM_ADD, (struct sockaddr *)&net6, 907e02d3fe7SAlexander V. Chernikov (struct sockaddr *)&mask6, (struct sockaddr *)&gw6); 908e02d3fe7SAlexander V. Chernikov 909e02d3fe7SAlexander V. Chernikov /* Set expire time to now */ 910e02d3fe7SAlexander V. Chernikov struct timeval tv; 911e02d3fe7SAlexander V. Chernikov gettimeofday(&tv, NULL); 912e02d3fe7SAlexander V. Chernikov rtm->rtm_rmx.rmx_expire = tv.tv_sec - 1; 913e02d3fe7SAlexander V. Chernikov rtm->rtm_inits |= RTV_EXPIRE; 914e02d3fe7SAlexander V. Chernikov 915e02d3fe7SAlexander V. Chernikov rtsock_send_rtm(c->rtsock_fd, rtm); 916e02d3fe7SAlexander V. Chernikov rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq); 917e02d3fe7SAlexander V. Chernikov ATF_REQUIRE_MSG(rtm != NULL, "unable to get rtsock reply for RTM_ADD"); 918e02d3fe7SAlexander V. Chernikov RTSOCK_ATF_REQUIRE_MSG(rtm, rtm->rtm_inits & RTV_EXPIRE, "RTV_EXPIRE not set"); 919e02d3fe7SAlexander V. Chernikov 920e02d3fe7SAlexander V. Chernikov /* The next should be route deletion */ 921e02d3fe7SAlexander V. Chernikov rtm = rtsock_read_rtm(c->rtsock_fd, buffer, sizeof(buffer)); 922e02d3fe7SAlexander V. Chernikov 923e02d3fe7SAlexander V. Chernikov verify_route_message(rtm, RTM_DELETE, (struct sockaddr *)&net6, 924e02d3fe7SAlexander V. Chernikov (struct sockaddr *)&mask6, (struct sockaddr *)&gw6); 925e02d3fe7SAlexander V. Chernikov 926e02d3fe7SAlexander V. Chernikov 927e02d3fe7SAlexander V. Chernikov /* XXX: Currently kernel sets RTF_UP automatically but does NOT report it in the reply */ 92834a5582cSAlexander V. Chernikov verify_route_message_extra(rtm, c->ifindex, RTF_GATEWAY | RTF_DONE | RTF_STATIC); 929e02d3fe7SAlexander V. Chernikov } 930e02d3fe7SAlexander V. Chernikov 931e02d3fe7SAlexander V. Chernikov ATF_TC_CLEANUP(rtm_add_v6_temporal1_success, tc) 932e02d3fe7SAlexander V. Chernikov { 933e02d3fe7SAlexander V. Chernikov CLEANUP_AFTER_TEST; 934e02d3fe7SAlexander V. Chernikov } 935e02d3fe7SAlexander V. Chernikov 936e02d3fe7SAlexander V. Chernikov /* Interface address messages tests */ 937e02d3fe7SAlexander V. Chernikov 938e02d3fe7SAlexander V. Chernikov RTM_DECLARE_ROOT_TEST(rtm_add_v6_gu_ifa_hostroute_success, 939e02d3fe7SAlexander V. Chernikov "Tests validness for /128 host route announce after ifaddr assignment"); 940e02d3fe7SAlexander V. Chernikov 941e02d3fe7SAlexander V. Chernikov ATF_TC_BODY(rtm_add_v6_gu_ifa_hostroute_success, tc) 942e02d3fe7SAlexander V. Chernikov { 943e02d3fe7SAlexander V. Chernikov DECLARE_TEST_VARS; 944e02d3fe7SAlexander V. Chernikov 945e02d3fe7SAlexander V. Chernikov c = presetup_ipv6_iface(tc); 946e02d3fe7SAlexander V. Chernikov 947e02d3fe7SAlexander V. Chernikov c->rtsock_fd = rtsock_setup_socket(); 948e02d3fe7SAlexander V. Chernikov 949e02d3fe7SAlexander V. Chernikov ret = iface_setup_addr(c->ifname, c->addr6_str, c->plen6); 950e02d3fe7SAlexander V. Chernikov 951e02d3fe7SAlexander V. Chernikov /* 952e02d3fe7SAlexander V. Chernikov * There will be multiple. 953e02d3fe7SAlexander V. Chernikov * RTM_ADD without llinfo. 954e02d3fe7SAlexander V. Chernikov */ 955e02d3fe7SAlexander V. Chernikov 956e02d3fe7SAlexander V. Chernikov while (true) { 957e02d3fe7SAlexander V. Chernikov rtm = rtsock_read_rtm(c->rtsock_fd, buffer, sizeof(buffer)); 958e02d3fe7SAlexander V. Chernikov if ((rtm->rtm_type == RTM_ADD) && ((rtm->rtm_flags & RTF_LLINFO) == 0)) 959e02d3fe7SAlexander V. Chernikov break; 960e02d3fe7SAlexander V. Chernikov } 961e02d3fe7SAlexander V. Chernikov /* This should be a message for the host route */ 962e02d3fe7SAlexander V. Chernikov 963e02d3fe7SAlexander V. Chernikov verify_route_message(rtm, RTM_ADD, (struct sockaddr *)&c->addr6, NULL, NULL); 964e02d3fe7SAlexander V. Chernikov rtsock_validate_pid_kernel(rtm); 965e02d3fe7SAlexander V. Chernikov /* No netmask should be set */ 966e02d3fe7SAlexander V. Chernikov RTSOCK_ATF_REQUIRE_MSG(rtm, rtsock_find_rtm_sa(rtm, RTA_NETMASK) == NULL, "netmask is set"); 967e02d3fe7SAlexander V. Chernikov 968e02d3fe7SAlexander V. Chernikov /* gateway should be link sdl with ifindex of an address interface */ 969e02d3fe7SAlexander V. Chernikov verify_link_gateway(rtm, c->ifindex); 970e02d3fe7SAlexander V. Chernikov 971e02d3fe7SAlexander V. Chernikov int expected_rt_flags = RTF_UP | RTF_HOST | RTF_DONE | RTF_STATIC | RTF_PINNED; 972e02d3fe7SAlexander V. Chernikov verify_route_message_extra(rtm, if_nametoindex("lo0"), expected_rt_flags); 973e02d3fe7SAlexander V. Chernikov } 974e02d3fe7SAlexander V. Chernikov 975e02d3fe7SAlexander V. Chernikov RTM_DECLARE_ROOT_TEST(rtm_add_v6_gu_ifa_prefixroute_success, 976e02d3fe7SAlexander V. Chernikov "Tests validness for the prefix route announce after ifaddr assignment"); 977e02d3fe7SAlexander V. Chernikov 978e02d3fe7SAlexander V. Chernikov ATF_TC_BODY(rtm_add_v6_gu_ifa_prefixroute_success, tc) 979e02d3fe7SAlexander V. Chernikov { 980e02d3fe7SAlexander V. Chernikov DECLARE_TEST_VARS; 981e02d3fe7SAlexander V. Chernikov 982e02d3fe7SAlexander V. Chernikov c = presetup_ipv6_iface(tc); 983e02d3fe7SAlexander V. Chernikov 984e02d3fe7SAlexander V. Chernikov c->rtsock_fd = rtsock_setup_socket(); 985e02d3fe7SAlexander V. Chernikov 986e02d3fe7SAlexander V. Chernikov ret = iface_setup_addr(c->ifname, c->addr6_str, c->plen6); 987e02d3fe7SAlexander V. Chernikov 988e02d3fe7SAlexander V. Chernikov /* 989e02d3fe7SAlexander V. Chernikov * Multiple RTM_ADD messages will be generated: 990e02d3fe7SAlexander V. Chernikov * 1) lladdr mapping (RTF_LLDATA) 991e02d3fe7SAlexander V. Chernikov * 2) host route (one w/o netmask) 992e02d3fe7SAlexander V. Chernikov * 3) prefix route 993e02d3fe7SAlexander V. Chernikov */ 994e02d3fe7SAlexander V. Chernikov 995e02d3fe7SAlexander V. Chernikov while (true) { 996e02d3fe7SAlexander V. Chernikov rtm = rtsock_read_rtm(c->rtsock_fd, buffer, sizeof(buffer)); 997e02d3fe7SAlexander V. Chernikov /* Find RTM_ADD with netmask - this should skip both host route and LLADDR */ 998e02d3fe7SAlexander V. Chernikov if ((rtm->rtm_type == RTM_ADD) && (rtsock_find_rtm_sa(rtm, RTA_NETMASK))) 999e02d3fe7SAlexander V. Chernikov break; 1000e02d3fe7SAlexander V. Chernikov } 1001e02d3fe7SAlexander V. Chernikov 1002e02d3fe7SAlexander V. Chernikov /* This should be a message for the prefix route */ 1003e02d3fe7SAlexander V. Chernikov verify_route_message(rtm, RTM_ADD, (struct sockaddr *)&c->net6, 1004e02d3fe7SAlexander V. Chernikov (struct sockaddr *)&c->mask6, NULL); 1005e02d3fe7SAlexander V. Chernikov 1006e02d3fe7SAlexander V. Chernikov /* gateway should be link sdl with ifindex of an address interface */ 1007e02d3fe7SAlexander V. Chernikov verify_link_gateway(rtm, c->ifindex); 1008e02d3fe7SAlexander V. Chernikov 1009e02d3fe7SAlexander V. Chernikov /* TODO: PINNED? */ 1010e02d3fe7SAlexander V. Chernikov int expected_rt_flags = RTF_UP | RTF_DONE; 1011e02d3fe7SAlexander V. Chernikov verify_route_message_extra(rtm, c->ifindex, expected_rt_flags); 1012e02d3fe7SAlexander V. Chernikov } 1013e02d3fe7SAlexander V. Chernikov 1014e02d3fe7SAlexander V. Chernikov RTM_DECLARE_ROOT_TEST(rtm_add_v6_gu_ifa_ordered_success, 1015e02d3fe7SAlexander V. Chernikov "Tests ordering of the messages for IPv6 global unicast ifaddr assignment"); 1016e02d3fe7SAlexander V. Chernikov 1017e02d3fe7SAlexander V. Chernikov ATF_TC_BODY(rtm_add_v6_gu_ifa_ordered_success, tc) 1018e02d3fe7SAlexander V. Chernikov { 1019e02d3fe7SAlexander V. Chernikov DECLARE_TEST_VARS; 1020e02d3fe7SAlexander V. Chernikov 1021e02d3fe7SAlexander V. Chernikov c = presetup_ipv6_iface(tc); 1022e02d3fe7SAlexander V. Chernikov 1023e02d3fe7SAlexander V. Chernikov c->rtsock_fd = rtsock_setup_socket(); 1024e02d3fe7SAlexander V. Chernikov 1025e02d3fe7SAlexander V. Chernikov ret = iface_setup_addr(c->ifname, c->addr6_str, c->plen6); 1026e02d3fe7SAlexander V. Chernikov 1027e02d3fe7SAlexander V. Chernikov int count = 0, tries = 0; 1028e02d3fe7SAlexander V. Chernikov 1029e02d3fe7SAlexander V. Chernikov enum msgtype { 1030e02d3fe7SAlexander V. Chernikov MSG_IFADDR, 1031e02d3fe7SAlexander V. Chernikov MSG_HOSTROUTE, 1032e02d3fe7SAlexander V. Chernikov MSG_PREFIXROUTE, 1033e02d3fe7SAlexander V. Chernikov MSG_MAX, 1034e02d3fe7SAlexander V. Chernikov }; 1035e02d3fe7SAlexander V. Chernikov 1036e02d3fe7SAlexander V. Chernikov int msg_array[MSG_MAX]; 1037e02d3fe7SAlexander V. Chernikov 1038e02d3fe7SAlexander V. Chernikov bzero(msg_array, sizeof(msg_array)); 1039e02d3fe7SAlexander V. Chernikov 1040e02d3fe7SAlexander V. Chernikov while (count < 3 && tries < 20) { 1041e02d3fe7SAlexander V. Chernikov rtm = rtsock_read_rtm(c->rtsock_fd, buffer, sizeof(buffer)); 1042e02d3fe7SAlexander V. Chernikov tries++; 1043e02d3fe7SAlexander V. Chernikov /* Classify */ 1044e02d3fe7SAlexander V. Chernikov if (rtm->rtm_type == RTM_NEWADDR) { 1045e02d3fe7SAlexander V. Chernikov RLOG("MSG_IFADDR: %d", count); 1046e02d3fe7SAlexander V. Chernikov msg_array[MSG_IFADDR] = count++; 1047e02d3fe7SAlexander V. Chernikov continue; 1048e02d3fe7SAlexander V. Chernikov } 1049e02d3fe7SAlexander V. Chernikov 1050e02d3fe7SAlexander V. Chernikov /* Find RTM_ADD with netmask - this should skip both host route and LLADDR */ 1051e02d3fe7SAlexander V. Chernikov if ((rtm->rtm_type == RTM_ADD) && (rtsock_find_rtm_sa(rtm, RTA_NETMASK))) { 1052e02d3fe7SAlexander V. Chernikov RLOG("MSG_PREFIXROUTE: %d", count); 1053e02d3fe7SAlexander V. Chernikov msg_array[MSG_PREFIXROUTE] = count++; 1054e02d3fe7SAlexander V. Chernikov continue; 1055e02d3fe7SAlexander V. Chernikov } 1056e02d3fe7SAlexander V. Chernikov 1057e02d3fe7SAlexander V. Chernikov if ((rtm->rtm_type == RTM_ADD) && ((rtm->rtm_flags & RTF_LLDATA) == 0)) { 1058e02d3fe7SAlexander V. Chernikov RLOG("MSG_HOSTROUTE: %d", count); 1059e02d3fe7SAlexander V. Chernikov msg_array[MSG_HOSTROUTE] = count++; 1060e02d3fe7SAlexander V. Chernikov continue; 1061e02d3fe7SAlexander V. Chernikov } 1062e02d3fe7SAlexander V. Chernikov 1063e02d3fe7SAlexander V. Chernikov RLOG("skipping msg type %s, try: %d", rtsock_print_cmdtype(rtm->rtm_type), 1064e02d3fe7SAlexander V. Chernikov tries); 1065e02d3fe7SAlexander V. Chernikov } 1066e02d3fe7SAlexander V. Chernikov 1067e02d3fe7SAlexander V. Chernikov /* TODO: verify multicast */ 1068e02d3fe7SAlexander V. Chernikov ATF_REQUIRE_MSG(count == 3, "Received only %d/3 messages", count); 1069e02d3fe7SAlexander V. Chernikov ATF_REQUIRE_MSG(msg_array[MSG_IFADDR] == 0, "ifaddr message is not the first"); 1070e02d3fe7SAlexander V. Chernikov } 1071e02d3fe7SAlexander V. Chernikov 1072e02d3fe7SAlexander V. Chernikov RTM_DECLARE_ROOT_TEST(rtm_del_v6_gu_ifa_hostroute_success, 1073e02d3fe7SAlexander V. Chernikov "Tests validness for /128 host route removal after ifaddr removal"); 1074e02d3fe7SAlexander V. Chernikov 1075e02d3fe7SAlexander V. Chernikov ATF_TC_BODY(rtm_del_v6_gu_ifa_hostroute_success, tc) 1076e02d3fe7SAlexander V. Chernikov { 1077e02d3fe7SAlexander V. Chernikov DECLARE_TEST_VARS; 1078e02d3fe7SAlexander V. Chernikov 1079e02d3fe7SAlexander V. Chernikov c = presetup_ipv6_iface(tc); 1080e02d3fe7SAlexander V. Chernikov 1081e02d3fe7SAlexander V. Chernikov ret = iface_setup_addr(c->ifname, c->addr6_str, c->plen6); 1082e02d3fe7SAlexander V. Chernikov 1083e02d3fe7SAlexander V. Chernikov c->rtsock_fd = rtsock_setup_socket(); 1084e02d3fe7SAlexander V. Chernikov 1085e02d3fe7SAlexander V. Chernikov ret = iface_delete_addr(c->ifname, c->addr6_str); 1086e02d3fe7SAlexander V. Chernikov 1087e02d3fe7SAlexander V. Chernikov while (true) { 1088e02d3fe7SAlexander V. Chernikov rtm = rtsock_read_rtm(c->rtsock_fd, buffer, sizeof(buffer)); 1089e02d3fe7SAlexander V. Chernikov if ((rtm->rtm_type == RTM_DELETE) && 1090e02d3fe7SAlexander V. Chernikov ((rtm->rtm_flags & RTF_LLINFO) == 0) && 1091e02d3fe7SAlexander V. Chernikov rtsock_find_rtm_sa(rtm, RTA_NETMASK) == NULL) 1092e02d3fe7SAlexander V. Chernikov break; 1093e02d3fe7SAlexander V. Chernikov } 1094e02d3fe7SAlexander V. Chernikov /* This should be a message for the host route */ 1095e02d3fe7SAlexander V. Chernikov 1096e02d3fe7SAlexander V. Chernikov verify_route_message(rtm, RTM_DELETE, (struct sockaddr *)&c->addr6, NULL, NULL); 1097e02d3fe7SAlexander V. Chernikov rtsock_validate_pid_kernel(rtm); 1098e02d3fe7SAlexander V. Chernikov /* No netmask should be set */ 1099e02d3fe7SAlexander V. Chernikov RTSOCK_ATF_REQUIRE_MSG(rtm, rtsock_find_rtm_sa(rtm, RTA_NETMASK) == NULL, "netmask is set"); 1100e02d3fe7SAlexander V. Chernikov 1101e02d3fe7SAlexander V. Chernikov /* gateway should be link sdl with ifindex of an address interface */ 1102e02d3fe7SAlexander V. Chernikov verify_link_gateway(rtm, c->ifindex); 1103e02d3fe7SAlexander V. Chernikov 1104e02d3fe7SAlexander V. Chernikov /* XXX: consider passing ifindex in rtm_index as done in RTM_ADD. */ 1105e02d3fe7SAlexander V. Chernikov int expected_rt_flags = RTF_HOST | RTF_DONE | RTF_STATIC | RTF_PINNED; 1106e02d3fe7SAlexander V. Chernikov RTSOCK_ATF_REQUIRE_MSG(rtm, rtm->rtm_flags == expected_rt_flags, 1107e02d3fe7SAlexander V. Chernikov "expected rtm flags: 0x%X, got 0x%X", expected_rt_flags, rtm->rtm_flags); 1108e02d3fe7SAlexander V. Chernikov } 1109e02d3fe7SAlexander V. Chernikov 1110e02d3fe7SAlexander V. Chernikov RTM_DECLARE_ROOT_TEST(rtm_del_v6_gu_ifa_prefixroute_success, 1111e02d3fe7SAlexander V. Chernikov "Tests validness for the prefix route removal after ifaddr assignment"); 1112e02d3fe7SAlexander V. Chernikov 1113e02d3fe7SAlexander V. Chernikov ATF_TC_BODY(rtm_del_v6_gu_ifa_prefixroute_success, tc) 1114e02d3fe7SAlexander V. Chernikov { 1115e02d3fe7SAlexander V. Chernikov DECLARE_TEST_VARS; 1116e02d3fe7SAlexander V. Chernikov 1117e02d3fe7SAlexander V. Chernikov c = presetup_ipv6_iface(tc); 1118e02d3fe7SAlexander V. Chernikov 1119e02d3fe7SAlexander V. Chernikov ret = iface_setup_addr(c->ifname, c->addr6_str, c->plen6); 1120e02d3fe7SAlexander V. Chernikov 1121e02d3fe7SAlexander V. Chernikov c->rtsock_fd = rtsock_setup_socket(); 1122e02d3fe7SAlexander V. Chernikov 1123e02d3fe7SAlexander V. Chernikov ret = iface_delete_addr(c->ifname, c->addr6_str); 1124e02d3fe7SAlexander V. Chernikov 1125e02d3fe7SAlexander V. Chernikov while (true) { 1126e02d3fe7SAlexander V. Chernikov rtm = rtsock_read_rtm(c->rtsock_fd, buffer, sizeof(buffer)); 1127e02d3fe7SAlexander V. Chernikov /* Find RTM_DELETE with netmask - this should skip both host route and LLADDR */ 1128e02d3fe7SAlexander V. Chernikov if ((rtm->rtm_type == RTM_DELETE) && (rtsock_find_rtm_sa(rtm, RTA_NETMASK))) 1129e02d3fe7SAlexander V. Chernikov break; 1130e02d3fe7SAlexander V. Chernikov } 1131e02d3fe7SAlexander V. Chernikov 1132e02d3fe7SAlexander V. Chernikov /* This should be a message for the prefix route */ 1133e02d3fe7SAlexander V. Chernikov verify_route_message(rtm, RTM_DELETE, (struct sockaddr *)&c->net6, 1134e02d3fe7SAlexander V. Chernikov (struct sockaddr *)&c->mask6, NULL); 1135e02d3fe7SAlexander V. Chernikov 1136e02d3fe7SAlexander V. Chernikov /* gateway should be link sdl with ifindex of an address interface */ 1137e02d3fe7SAlexander V. Chernikov verify_link_gateway(rtm, c->ifindex); 1138e02d3fe7SAlexander V. Chernikov 1139e02d3fe7SAlexander V. Chernikov int expected_rt_flags = RTF_DONE; 1140e02d3fe7SAlexander V. Chernikov verify_route_message_extra(rtm, c->ifindex, expected_rt_flags); 1141e02d3fe7SAlexander V. Chernikov } 1142e02d3fe7SAlexander V. Chernikov 1143e02d3fe7SAlexander V. Chernikov RTM_DECLARE_ROOT_TEST(rtm_add_v4_gu_ifa_prefixroute_success, 1144e02d3fe7SAlexander V. Chernikov "Tests validness for the prefix route announce after ifaddr assignment"); 1145e02d3fe7SAlexander V. Chernikov 1146e02d3fe7SAlexander V. Chernikov ATF_TC_BODY(rtm_add_v4_gu_ifa_prefixroute_success, tc) 1147e02d3fe7SAlexander V. Chernikov { 1148e02d3fe7SAlexander V. Chernikov DECLARE_TEST_VARS; 1149e02d3fe7SAlexander V. Chernikov 1150e02d3fe7SAlexander V. Chernikov c = presetup_ipv4_iface(tc); 1151e02d3fe7SAlexander V. Chernikov 1152e02d3fe7SAlexander V. Chernikov c->rtsock_fd = rtsock_setup_socket(); 1153e02d3fe7SAlexander V. Chernikov 1154e02d3fe7SAlexander V. Chernikov ret = iface_setup_addr(c->ifname, c->addr6_str, c->plen6); 1155e02d3fe7SAlexander V. Chernikov 1156e02d3fe7SAlexander V. Chernikov /* 1157e02d3fe7SAlexander V. Chernikov * Multiple RTM_ADD messages will be generated: 1158e02d3fe7SAlexander V. Chernikov * 1) lladdr mapping (RTF_LLDATA) 1159e02d3fe7SAlexander V. Chernikov * 3) prefix route 1160e02d3fe7SAlexander V. Chernikov */ 1161e02d3fe7SAlexander V. Chernikov 1162e02d3fe7SAlexander V. Chernikov while (true) { 1163e02d3fe7SAlexander V. Chernikov rtm = rtsock_read_rtm(c->rtsock_fd, buffer, sizeof(buffer)); 1164e02d3fe7SAlexander V. Chernikov /* Find RTM_ADD with netmask - this should skip both host route and LLADDR */ 1165e02d3fe7SAlexander V. Chernikov if ((rtm->rtm_type == RTM_ADD) && (rtsock_find_rtm_sa(rtm, RTA_NETMASK))) 1166e02d3fe7SAlexander V. Chernikov break; 1167e02d3fe7SAlexander V. Chernikov } 1168e02d3fe7SAlexander V. Chernikov 1169e02d3fe7SAlexander V. Chernikov /* This should be a message for the prefix route */ 1170e02d3fe7SAlexander V. Chernikov verify_route_message(rtm, RTM_ADD, (struct sockaddr *)&c->net4, 1171e02d3fe7SAlexander V. Chernikov (struct sockaddr *)&c->mask4, NULL); 1172e02d3fe7SAlexander V. Chernikov 1173e02d3fe7SAlexander V. Chernikov /* gateway should be link sdl with ifindex of an address interface */ 1174e02d3fe7SAlexander V. Chernikov verify_link_gateway(rtm, c->ifindex); 1175e02d3fe7SAlexander V. Chernikov 1176e02d3fe7SAlexander V. Chernikov int expected_rt_flags = RTF_UP | RTF_DONE | RTF_PINNED; 1177e02d3fe7SAlexander V. Chernikov verify_route_message_extra(rtm, c->ifindex, expected_rt_flags); 1178e02d3fe7SAlexander V. Chernikov } 1179e02d3fe7SAlexander V. Chernikov 1180e02d3fe7SAlexander V. Chernikov RTM_DECLARE_ROOT_TEST(rtm_add_v4_gu_ifa_ordered_success, 1181e02d3fe7SAlexander V. Chernikov "Tests ordering of the messages for IPv4 unicast ifaddr assignment"); 1182e02d3fe7SAlexander V. Chernikov 1183e02d3fe7SAlexander V. Chernikov ATF_TC_BODY(rtm_add_v4_gu_ifa_ordered_success, tc) 1184e02d3fe7SAlexander V. Chernikov { 1185e02d3fe7SAlexander V. Chernikov DECLARE_TEST_VARS; 1186e02d3fe7SAlexander V. Chernikov 1187e02d3fe7SAlexander V. Chernikov c = presetup_ipv4_iface(tc); 1188e02d3fe7SAlexander V. Chernikov 1189e02d3fe7SAlexander V. Chernikov c->rtsock_fd = rtsock_setup_socket(); 1190e02d3fe7SAlexander V. Chernikov 1191e02d3fe7SAlexander V. Chernikov ret = iface_setup_addr(c->ifname, c->addr4_str, c->plen4); 1192e02d3fe7SAlexander V. Chernikov 1193e02d3fe7SAlexander V. Chernikov int count = 0, tries = 0; 1194e02d3fe7SAlexander V. Chernikov 1195e02d3fe7SAlexander V. Chernikov enum msgtype { 1196e02d3fe7SAlexander V. Chernikov MSG_IFADDR, 1197e02d3fe7SAlexander V. Chernikov MSG_PREFIXROUTE, 1198e02d3fe7SAlexander V. Chernikov MSG_MAX, 1199e02d3fe7SAlexander V. Chernikov }; 1200e02d3fe7SAlexander V. Chernikov 1201e02d3fe7SAlexander V. Chernikov int msg_array[MSG_MAX]; 1202e02d3fe7SAlexander V. Chernikov 1203e02d3fe7SAlexander V. Chernikov bzero(msg_array, sizeof(msg_array)); 1204e02d3fe7SAlexander V. Chernikov 1205e02d3fe7SAlexander V. Chernikov while (count < 2 && tries < 20) { 1206e02d3fe7SAlexander V. Chernikov rtm = rtsock_read_rtm(c->rtsock_fd, buffer, sizeof(buffer)); 1207e02d3fe7SAlexander V. Chernikov tries++; 1208e02d3fe7SAlexander V. Chernikov /* Classify */ 1209e02d3fe7SAlexander V. Chernikov if (rtm->rtm_type == RTM_NEWADDR) { 1210e02d3fe7SAlexander V. Chernikov RLOG("MSG_IFADDR: %d", count); 1211e02d3fe7SAlexander V. Chernikov msg_array[MSG_IFADDR] = count++; 1212e02d3fe7SAlexander V. Chernikov continue; 1213e02d3fe7SAlexander V. Chernikov } 1214e02d3fe7SAlexander V. Chernikov 1215e02d3fe7SAlexander V. Chernikov /* Find RTM_ADD with netmask - this should skip both host route and LLADDR */ 1216e02d3fe7SAlexander V. Chernikov if ((rtm->rtm_type == RTM_ADD) && (rtsock_find_rtm_sa(rtm, RTA_NETMASK))) { 1217e02d3fe7SAlexander V. Chernikov RLOG("MSG_PREFIXROUTE: %d", count); 1218e02d3fe7SAlexander V. Chernikov msg_array[MSG_PREFIXROUTE] = count++; 1219e02d3fe7SAlexander V. Chernikov continue; 1220e02d3fe7SAlexander V. Chernikov } 1221e02d3fe7SAlexander V. Chernikov 1222e02d3fe7SAlexander V. Chernikov RLOG("skipping msg type %s, try: %d", rtsock_print_cmdtype(rtm->rtm_type), 1223e02d3fe7SAlexander V. Chernikov tries); 1224e02d3fe7SAlexander V. Chernikov } 1225e02d3fe7SAlexander V. Chernikov 1226e02d3fe7SAlexander V. Chernikov /* TODO: verify multicast */ 1227e02d3fe7SAlexander V. Chernikov ATF_REQUIRE_MSG(count == 2, "Received only %d/2 messages", count); 1228e02d3fe7SAlexander V. Chernikov ATF_REQUIRE_MSG(msg_array[MSG_IFADDR] == 0, "ifaddr message is not the first"); 1229e02d3fe7SAlexander V. Chernikov } 1230e02d3fe7SAlexander V. Chernikov 1231e02d3fe7SAlexander V. Chernikov RTM_DECLARE_ROOT_TEST(rtm_del_v4_gu_ifa_prefixroute_success, 1232e02d3fe7SAlexander V. Chernikov "Tests validness for the prefix route removal after ifaddr assignment"); 1233e02d3fe7SAlexander V. Chernikov 1234e02d3fe7SAlexander V. Chernikov ATF_TC_BODY(rtm_del_v4_gu_ifa_prefixroute_success, tc) 1235e02d3fe7SAlexander V. Chernikov { 1236e02d3fe7SAlexander V. Chernikov DECLARE_TEST_VARS; 1237e02d3fe7SAlexander V. Chernikov 1238e02d3fe7SAlexander V. Chernikov c = presetup_ipv4_iface(tc); 1239e02d3fe7SAlexander V. Chernikov 1240e02d3fe7SAlexander V. Chernikov 1241e02d3fe7SAlexander V. Chernikov ret = iface_setup_addr(c->ifname, c->addr4_str, c->plen4); 1242e02d3fe7SAlexander V. Chernikov 1243e02d3fe7SAlexander V. Chernikov c->rtsock_fd = rtsock_setup_socket(); 1244e02d3fe7SAlexander V. Chernikov 1245e02d3fe7SAlexander V. Chernikov ret = iface_delete_addr(c->ifname, c->addr4_str); 1246e02d3fe7SAlexander V. Chernikov 1247e02d3fe7SAlexander V. Chernikov while (true) { 1248e02d3fe7SAlexander V. Chernikov rtm = rtsock_read_rtm(c->rtsock_fd, buffer, sizeof(buffer)); 1249e02d3fe7SAlexander V. Chernikov /* Find RTM_ADD with netmask - this should skip both host route and LLADDR */ 1250e02d3fe7SAlexander V. Chernikov if ((rtm->rtm_type == RTM_DELETE) && (rtsock_find_rtm_sa(rtm, RTA_NETMASK))) 1251e02d3fe7SAlexander V. Chernikov break; 1252e02d3fe7SAlexander V. Chernikov } 1253e02d3fe7SAlexander V. Chernikov 1254e02d3fe7SAlexander V. Chernikov /* This should be a message for the prefix route */ 1255e02d3fe7SAlexander V. Chernikov verify_route_message(rtm, RTM_DELETE, (struct sockaddr *)&c->net4, 1256e02d3fe7SAlexander V. Chernikov (struct sockaddr *)&c->mask4, NULL); 1257e02d3fe7SAlexander V. Chernikov 1258e02d3fe7SAlexander V. Chernikov /* gateway should be link sdl with ifindex of an address interface */ 1259e02d3fe7SAlexander V. Chernikov verify_link_gateway(rtm, c->ifindex); 1260e02d3fe7SAlexander V. Chernikov 1261e02d3fe7SAlexander V. Chernikov int expected_rt_flags = RTF_DONE | RTF_PINNED; 1262e02d3fe7SAlexander V. Chernikov verify_route_message_extra(rtm, c->ifindex, expected_rt_flags); 1263e02d3fe7SAlexander V. Chernikov } 1264775dc861SAlexander V. Chernikov 1265775dc861SAlexander V. Chernikov 1266775dc861SAlexander V. Chernikov ATF_TP_ADD_TCS(tp) 1267775dc861SAlexander V. Chernikov { 1268775dc861SAlexander V. Chernikov ATF_TP_ADD_TC(tp, rtm_get_v4_exact_success); 1269775dc861SAlexander V. Chernikov ATF_TP_ADD_TC(tp, rtm_get_v4_lpm_success); 1270775dc861SAlexander V. Chernikov ATF_TP_ADD_TC(tp, rtm_get_v4_hostbits_failure); 1271775dc861SAlexander V. Chernikov ATF_TP_ADD_TC(tp, rtm_get_v4_empty_dst_failure); 1272775dc861SAlexander V. Chernikov ATF_TP_ADD_TC(tp, rtm_add_v4_gw_direct_success); 1273775dc861SAlexander V. Chernikov ATF_TP_ADD_TC(tp, rtm_del_v4_prefix_nogw_success); 1274775dc861SAlexander V. Chernikov ATF_TP_ADD_TC(tp, rtm_add_v6_gu_gw_gu_direct_success); 1275775dc861SAlexander V. Chernikov ATF_TP_ADD_TC(tp, rtm_del_v6_gu_prefix_nogw_success); 1276*272bd698SAlexander V. Chernikov ATF_TP_ADD_TC(tp, rtm_change_v4_gw_success); 1277*272bd698SAlexander V. Chernikov ATF_TP_ADD_TC(tp, rtm_change_v4_mtu_success); 1278*272bd698SAlexander V. Chernikov ATF_TP_ADD_TC(tp, rtm_change_v6_gw_success); 1279*272bd698SAlexander V. Chernikov ATF_TP_ADD_TC(tp, rtm_change_v6_mtu_success); 1280e02d3fe7SAlexander V. Chernikov /* ifaddr tests */ 1281e02d3fe7SAlexander V. Chernikov ATF_TP_ADD_TC(tp, rtm_add_v6_gu_ifa_hostroute_success); 1282e02d3fe7SAlexander V. Chernikov ATF_TP_ADD_TC(tp, rtm_add_v6_gu_ifa_prefixroute_success); 1283e02d3fe7SAlexander V. Chernikov ATF_TP_ADD_TC(tp, rtm_add_v6_gu_ifa_ordered_success); 1284e02d3fe7SAlexander V. Chernikov ATF_TP_ADD_TC(tp, rtm_del_v6_gu_ifa_hostroute_success); 1285e02d3fe7SAlexander V. Chernikov ATF_TP_ADD_TC(tp, rtm_del_v6_gu_ifa_prefixroute_success); 1286e02d3fe7SAlexander V. Chernikov ATF_TP_ADD_TC(tp, rtm_add_v4_gu_ifa_ordered_success); 1287e02d3fe7SAlexander V. Chernikov ATF_TP_ADD_TC(tp, rtm_del_v4_gu_ifa_prefixroute_success); 128834a5582cSAlexander V. Chernikov /* temporal routes */ 128934a5582cSAlexander V. Chernikov ATF_TP_ADD_TC(tp, rtm_add_v4_temporal1_success); 129034a5582cSAlexander V. Chernikov ATF_TP_ADD_TC(tp, rtm_add_v6_temporal1_success); 1291775dc861SAlexander V. Chernikov 1292775dc861SAlexander V. Chernikov return (atf_no_error()); 1293775dc861SAlexander V. Chernikov } 1294775dc861SAlexander V. Chernikov 1295