1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (c) 2019 Alexander V. Chernikov 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 * 27 * $FreeBSD$ 28 */ 29 30 #include "rtsock_common.h" 31 #include "rtsock_config.h" 32 33 static inline struct rtsock_test_config * 34 presetup_ipv6(const atf_tc_t *tc) 35 { 36 struct rtsock_test_config *c; 37 int ret; 38 39 c = config_setup(tc); 40 41 ret = iface_turn_up(c->ifname); 42 ATF_REQUIRE_MSG(ret == 0, "Unable to turn up %s", c->ifname); 43 ret = iface_enable_ipv6(c->ifname); 44 ATF_REQUIRE_MSG(ret == 0, "Unable to enable IPv6 on %s", c->ifname); 45 46 c->rtsock_fd = rtsock_setup_socket(); 47 48 return (c); 49 } 50 51 static inline struct rtsock_test_config * 52 presetup_ipv4(const atf_tc_t *tc) 53 { 54 struct rtsock_test_config *c; 55 int ret; 56 57 c = config_setup(tc); 58 59 /* assumes ifconfig doing IFF_UP */ 60 ret = iface_setup_addr(c->ifname, c->addr4_str, c->plen4); 61 ATF_REQUIRE_MSG(ret == 0, "ifconfig failed"); 62 63 /* Actually open interface, so kernel writes won't fail */ 64 if (c->autocreated_interface) { 65 ret = iface_open(c->ifname); 66 ATF_REQUIRE_MSG(ret >= 0, "unable to open interface %s", c->ifname); 67 } 68 69 c->rtsock_fd = rtsock_setup_socket(); 70 71 return (c); 72 } 73 74 static void 75 prepare_route_message(struct rt_msghdr *rtm, int cmd, struct sockaddr *dst, 76 struct sockaddr *gw) 77 { 78 79 rtsock_prepare_route_message(rtm, cmd, dst, NULL, gw); 80 81 rtm->rtm_flags |= (RTF_HOST | RTF_STATIC | RTF_LLDATA); 82 } 83 84 /* TESTS */ 85 #define DECLARE_TEST_VARS \ 86 char buffer[2048], msg[512]; \ 87 ssize_t len; \ 88 int ret; \ 89 struct rtsock_test_config *c; \ 90 struct rt_msghdr *rtm = (struct rt_msghdr *)buffer; \ 91 struct sockaddr *sa; \ 92 \ 93 94 #define DECLARE_CLEANUP_VARS \ 95 struct rtsock_test_config *c = config_setup(tc); \ 96 \ 97 98 #define DESCRIBE_ROOT_TEST(_msg) config_describe_root_test(tc, _msg) 99 #define CLEANUP_AFTER_TEST config_generic_cleanup(config_setup(tc)) 100 101 #define RTM_DECLARE_ROOT_TEST(_name, _descr) \ 102 ATF_TC_WITH_CLEANUP(_name); \ 103 ATF_TC_HEAD(_name, tc) \ 104 { \ 105 DESCRIBE_ROOT_TEST(_descr); \ 106 } \ 107 ATF_TC_CLEANUP(_name, tc) \ 108 { \ 109 CLEANUP_AFTER_TEST; \ 110 } 111 112 RTM_DECLARE_ROOT_TEST(rtm_add_v6_ll_lle_success, "Tests addition of link-local IPv6 ND entry"); 113 ATF_TC_BODY(rtm_add_v6_ll_lle_success, tc) 114 { 115 DECLARE_TEST_VARS; 116 117 c = presetup_ipv6(tc); 118 119 char str_buf[128]; 120 struct sockaddr_in6 sin6; 121 /* Interface here is optional. XXX: verify kernel side. */ 122 char *v6addr = "fe80::4242:4242"; 123 snprintf(str_buf, sizeof(str_buf), "%s%%%s", v6addr, c->ifname); 124 sa_convert_str_to_sa(str_buf, (struct sockaddr *)&sin6); 125 126 struct sockaddr_dl ether; 127 snprintf(str_buf, sizeof(str_buf), "%s%%%s", c->remote_lladdr, c->ifname); 128 sa_convert_str_to_sa(str_buf, (struct sockaddr *)ðer); 129 130 prepare_route_message(rtm, RTM_ADD, (struct sockaddr *)&sin6, (struct sockaddr *)ðer); 131 rtsock_send_rtm(c->rtsock_fd, rtm); 132 133 /* 134 * Got message of size 240 on 2019-12-17 15:06:51 135 * RTM_ADD: Add Route: len 240, pid: 0, seq 0, errno 0, flags: <UP,HOST,DONE,LLINFO> 136 * sockaddrs: 0x3 <DST,GATEWAY> 137 * af=inet6 len=28 addr=fe80::4242:4242 scope_id=3 if_name=tap4242 138 * af=link len=54 sdl_index=3 if_name=tap4242 addr=52:54:00:14:E3:10 139 */ 140 141 rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq); 142 143 sa = rtsock_find_rtm_sa(rtm, RTA_DST); 144 ret = sa_equal_msg(sa, (struct sockaddr *)&sin6, msg, sizeof(msg)); 145 RTSOCK_ATF_REQUIRE_MSG(rtm, ret != 0, "DST sa diff: %s", msg); 146 147 sa = rtsock_find_rtm_sa(rtm, RTA_GATEWAY); 148 int sa_flags = SA_F_IGNORE_IFNAME | SA_F_IGNORE_IFTYPE | SA_F_IGNORE_MEMCMP; 149 ret = sa_equal_msg_flags(sa, (struct sockaddr *)ðer, msg, sizeof(msg), sa_flags); 150 RTSOCK_ATF_REQUIRE_MSG(rtm, ret != 0, "GATEWAY sa diff: %s", msg); 151 152 #if 0 153 /* Disable the check until https://reviews.freebsd.org/D22003 merge */ 154 /* Some additional checks to verify kernel has filled in interface data */ 155 struct sockaddr_dl *sdl = (struct sockaddr_dl *)sa; 156 RTSOCK_ATF_REQUIRE_MSG(rtm, sdl->sdl_type > 0, "sdl_type not set"); 157 #endif 158 } 159 160 RTM_DECLARE_ROOT_TEST(rtm_add_v6_gu_lle_success, "Tests addition of global IPv6 ND entry"); 161 ATF_TC_BODY(rtm_add_v6_gu_lle_success, tc) 162 { 163 DECLARE_TEST_VARS; 164 165 c = presetup_ipv6(tc); 166 167 char str_buf[128]; 168 169 struct sockaddr_in6 sin6; 170 sin6 = c->net6; 171 #define _s6_addr32 __u6_addr.__u6_addr32 172 sin6.sin6_addr._s6_addr32[3] = htonl(0x42424242); 173 #undef _s6_addr32 174 175 struct sockaddr_dl ether; 176 snprintf(str_buf, sizeof(str_buf), "%s%%%s", c->remote_lladdr, c->ifname); 177 sa_convert_str_to_sa(str_buf, (struct sockaddr *)ðer); 178 179 prepare_route_message(rtm, RTM_ADD, (struct sockaddr *)&sin6, (struct sockaddr *)ðer); 180 181 rtsock_send_rtm(c->rtsock_fd, rtm); 182 183 /* 184 * Got message of size 240 on 2019-12-17 14:56:43 185 * RTM_ADD: Add Route: len 240, pid: 0, seq 0, errno 0, flags: <UP,HOST,DONE,LLINFO> 186 * sockaddrs: 0x3 <DST,GATEWAY> 187 * af=inet6 len=28 addr=2001:db8::4242:4242 188 * af=link len=54 sdl_index=3 if_name=tap4242 addr=52:54:00:14:E3:10 189 */ 190 191 /* XXX: where is uRPF?! this should fail */ 192 193 rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq); 194 195 sa = rtsock_find_rtm_sa(rtm, RTA_DST); 196 ret = sa_equal_msg(sa, (struct sockaddr *)&sin6, msg, sizeof(msg)); 197 RTSOCK_ATF_REQUIRE_MSG(rtm, ret != 0, "DST sa diff: %s", msg); 198 199 sa = rtsock_find_rtm_sa(rtm, RTA_GATEWAY); 200 int sa_flags = SA_F_IGNORE_IFNAME | SA_F_IGNORE_IFTYPE | SA_F_IGNORE_MEMCMP; 201 ret = sa_equal_msg_flags(sa, (struct sockaddr *)ðer, msg, sizeof(msg), sa_flags); 202 RTSOCK_ATF_REQUIRE_MSG(rtm, ret != 0, "GATEWAY sa diff: %s", msg); 203 204 #if 0 205 /* Disable the check until https://reviews.freebsd.org/D22003 merge */ 206 /* Some additional checks to verify kernel has filled in interface data */ 207 struct sockaddr_dl *sdl = (struct sockaddr_dl *)sa; 208 RTSOCK_ATF_REQUIRE_MSG(rtm, sdl->sdl_type > 0, "sdl_type not set"); 209 #endif 210 } 211 212 RTM_DECLARE_ROOT_TEST(rtm_add_v4_gu_lle_success, "Tests addition of IPv4 ARP entry"); 213 ATF_TC_BODY(rtm_add_v4_gu_lle_success, tc) 214 { 215 DECLARE_TEST_VARS; 216 217 c = presetup_ipv4(tc); 218 219 char str_buf[128]; 220 221 struct sockaddr_in sin; 222 sin = c->addr4; 223 /* Use the next IPv4 address after self */ 224 sin.sin_addr.s_addr = htonl(ntohl(sin.sin_addr.s_addr) + 1); 225 226 struct sockaddr_dl ether; 227 snprintf(str_buf, sizeof(str_buf), "%s%%%s", c->remote_lladdr, c->ifname); 228 sa_convert_str_to_sa(str_buf, (struct sockaddr *)ðer); 229 230 prepare_route_message(rtm, RTM_ADD, (struct sockaddr *)&sin, (struct sockaddr *)ðer); 231 232 len = rtsock_send_rtm(c->rtsock_fd, rtm); 233 234 /* 235 * RTM_ADD: Add Route: len 224, pid: 43131, seq 42, errno 0, flags: <HOST,DONE,LLINFO,STATIC> 236 * sockaddrs: 0x3 <DST,GATEWAY> 237 * af=inet len=16 addr=192.0.2.2 238 * af=link len=54 sdl_index=3 if_name=tap4242 addr=52:54:00:14:E3:10 239 */ 240 241 rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq); 242 243 sa = rtsock_find_rtm_sa(rtm, RTA_DST); 244 ret = sa_equal_msg(sa, (struct sockaddr *)&sin, msg, sizeof(msg)); 245 RTSOCK_ATF_REQUIRE_MSG(rtm, ret != 0, "DST sa diff: %s", msg); 246 247 sa = rtsock_find_rtm_sa(rtm, RTA_GATEWAY); 248 int sa_flags = SA_F_IGNORE_IFNAME | SA_F_IGNORE_IFTYPE | SA_F_IGNORE_MEMCMP; 249 ret = sa_equal_msg_flags(sa, (struct sockaddr *)ðer, msg, sizeof(msg), sa_flags); 250 RTSOCK_ATF_REQUIRE_MSG(rtm, ret != 0, "GATEWAY sa diff: %s", msg); 251 252 /* 253 * TODO: Currently kernel code does not set sdl_type, contrary to IPv6. 254 */ 255 } 256 257 RTM_DECLARE_ROOT_TEST(rtm_del_v6_ll_lle_success, "Tests removal of link-local IPv6 ND entry"); 258 ATF_TC_BODY(rtm_del_v6_ll_lle_success, tc) 259 { 260 DECLARE_TEST_VARS; 261 262 c = presetup_ipv6(tc); 263 264 char str_buf[128]; 265 266 struct sockaddr_in6 sin6; 267 /* Interface here is optional. XXX: verify kernel side. */ 268 char *v6addr = "fe80::4242:4242"; 269 snprintf(str_buf, sizeof(str_buf), "%s%%%s", v6addr, c->ifname); 270 sa_convert_str_to_sa(str_buf, (struct sockaddr *)&sin6); 271 272 struct sockaddr_dl ether; 273 snprintf(str_buf, sizeof(str_buf), "%s%%%s", c->remote_lladdr, c->ifname); 274 sa_convert_str_to_sa(str_buf, (struct sockaddr *)ðer); 275 276 prepare_route_message(rtm, RTM_ADD, (struct sockaddr *)&sin6, (struct sockaddr *)ðer); 277 278 rtsock_send_rtm(c->rtsock_fd, rtm); 279 280 /* Successfully added an entry, let's try to remove it. */ 281 prepare_route_message(rtm, RTM_DELETE, (struct sockaddr *)&sin6, (struct sockaddr *)ðer); 282 283 rtsock_send_rtm(c->rtsock_fd, rtm); 284 285 rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq); 286 287 RTSOCK_ATF_REQUIRE_MSG(rtm, rtm->rtm_type == RTM_DELETE, "rtm_type is not delete"); 288 289 sa = rtsock_find_rtm_sa(rtm, RTA_DST); 290 ret = sa_equal_msg(sa, (struct sockaddr *)&sin6, msg, sizeof(msg)); 291 RTSOCK_ATF_REQUIRE_MSG(rtm, ret != 0, "DST sa diff: %s", msg); 292 293 sa = rtsock_find_rtm_sa(rtm, RTA_GATEWAY); 294 int sa_flags = SA_F_IGNORE_IFNAME | SA_F_IGNORE_IFTYPE | SA_F_IGNORE_MEMCMP; 295 ret = sa_equal_msg_flags(sa, (struct sockaddr *)ðer, msg, sizeof(msg), sa_flags); 296 RTSOCK_ATF_REQUIRE_MSG(rtm, ret != 0, "GATEWAY sa diff: %s", msg); 297 298 /* 299 * TODO: Currently kernel code does not set sdl_type on delete. 300 */ 301 } 302 303 RTM_DECLARE_ROOT_TEST(rtm_del_v6_gu_lle_success, "Tests removal of global IPv6 ND entry"); 304 ATF_TC_BODY(rtm_del_v6_gu_lle_success, tc) 305 { 306 DECLARE_TEST_VARS; 307 308 c = presetup_ipv6(tc); 309 310 char str_buf[128]; 311 312 struct sockaddr_in6 sin6; 313 sin6 = c->net6; 314 #define _s6_addr32 __u6_addr.__u6_addr32 315 sin6.sin6_addr._s6_addr32[3] = htonl(0x42424242); 316 #undef _s6_addr32 317 318 struct sockaddr_dl ether; 319 snprintf(str_buf, sizeof(str_buf), "%s%%%s", c->remote_lladdr, c->ifname); 320 sa_convert_str_to_sa(str_buf, (struct sockaddr *)ðer); 321 322 prepare_route_message(rtm, RTM_ADD, (struct sockaddr *)&sin6, (struct sockaddr *)ðer); 323 324 len = rtsock_send_rtm(c->rtsock_fd, rtm); 325 326 /* Successfully added an entry, let's try to remove it. */ 327 prepare_route_message(rtm, RTM_DELETE, (struct sockaddr *)&sin6, (struct sockaddr *)ðer); 328 329 rtsock_send_rtm(c->rtsock_fd, rtm); 330 331 rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq); 332 333 RTSOCK_ATF_REQUIRE_MSG(rtm, rtm->rtm_type == RTM_DELETE, "rtm_type is not delete"); 334 335 sa = rtsock_find_rtm_sa(rtm, RTA_DST); 336 ret = sa_equal_msg(sa, (struct sockaddr *)&sin6, msg, sizeof(msg)); 337 RTSOCK_ATF_REQUIRE_MSG(rtm, ret != 0, "DST sa diff: %s", msg); 338 339 sa = rtsock_find_rtm_sa(rtm, RTA_GATEWAY); 340 int sa_flags = SA_F_IGNORE_IFNAME | SA_F_IGNORE_IFTYPE | SA_F_IGNORE_MEMCMP; 341 ret = sa_equal_msg_flags(sa, (struct sockaddr *)ðer, msg, sizeof(msg), sa_flags); 342 RTSOCK_ATF_REQUIRE_MSG(rtm, ret != 0, "GATEWAY sa diff: %s", msg); 343 344 /* 345 * TODO: Currently kernel code does not set sdl_type on delete. 346 */ 347 } 348 349 RTM_DECLARE_ROOT_TEST(rtm_del_v4_gu_lle_success, "Tests removal of IPv4 ARP entry"); 350 ATF_TC_BODY(rtm_del_v4_gu_lle_success, tc) 351 { 352 DECLARE_TEST_VARS; 353 354 c = presetup_ipv4(tc); 355 356 char str_buf[128]; 357 358 struct sockaddr_in sin; 359 sin = c->addr4; 360 /* Use the next IPv4 address after self */ 361 sin.sin_addr.s_addr = htonl(ntohl(sin.sin_addr.s_addr) + 1); 362 363 struct sockaddr_dl ether; 364 snprintf(str_buf, sizeof(str_buf), "%s%%%s", c->remote_lladdr, c->ifname); 365 sa_convert_str_to_sa(str_buf, (struct sockaddr *)ðer); 366 367 prepare_route_message(rtm, RTM_ADD, (struct sockaddr *)&sin, (struct sockaddr *)ðer); 368 369 rtsock_send_rtm(c->rtsock_fd, rtm); 370 371 /* We successfully added an entry, let's try to remove it. */ 372 prepare_route_message(rtm, RTM_DELETE, (struct sockaddr *)&sin, (struct sockaddr *)ðer); 373 374 rtsock_send_rtm(c->rtsock_fd, rtm); 375 376 rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq); 377 378 RTSOCK_ATF_REQUIRE_MSG(rtm, rtm->rtm_type == RTM_DELETE, "rtm_type is not delete"); 379 380 sa = rtsock_find_rtm_sa(rtm, RTA_DST); 381 ret = sa_equal_msg(sa, (struct sockaddr *)&sin, msg, sizeof(msg)); 382 RTSOCK_ATF_REQUIRE_MSG(rtm, ret != 0, "DST sa diff: %s", msg); 383 384 sa = rtsock_find_rtm_sa(rtm, RTA_GATEWAY); 385 int sa_flags = SA_F_IGNORE_IFNAME | SA_F_IGNORE_IFTYPE | SA_F_IGNORE_MEMCMP; 386 ret = sa_equal_msg_flags(sa, (struct sockaddr *)ðer, msg, sizeof(msg), sa_flags); 387 RTSOCK_ATF_REQUIRE_MSG(rtm, ret != 0, "GATEWAY sa diff: %s", msg); 388 389 /* 390 * TODO: Currently kernel code does not set sdl_type, contrary to IPv6. 391 */ 392 } 393 394 ATF_TP_ADD_TCS(tp) 395 { 396 ATF_TP_ADD_TC(tp, rtm_add_v6_ll_lle_success); 397 ATF_TP_ADD_TC(tp, rtm_add_v6_gu_lle_success); 398 ATF_TP_ADD_TC(tp, rtm_add_v4_gu_lle_success); 399 ATF_TP_ADD_TC(tp, rtm_del_v6_ll_lle_success); 400 ATF_TP_ADD_TC(tp, rtm_del_v6_gu_lle_success); 401 ATF_TP_ADD_TC(tp, rtm_del_v4_gu_lle_success); 402 403 return (atf_no_error()); 404 } 405 406 407