2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
4 * Copyright (c) 2019 Alexander V. Chernikov
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
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.
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
30 #include "rtsock_common.h"
31 #include "rtsock_config.h"
34 jump_vnet(struct rtsock_test_config *c, const atf_tc_t *tc)
38 snprintf(vnet_name, sizeof(vnet_name), "vt-%s", atf_tc_get_ident(tc));
39 RLOG("jumping to %s", vnet_name);
41 vnet_switch_one(vnet_name, c->ifname);
43 /* Update ifindex cache */
44 c->ifindex = if_nametoindex(c->ifname);
47 static inline struct rtsock_test_config *
48 presetup_ipv6(const atf_tc_t *tc)
50 struct rtsock_test_config *c;
53 c = config_setup(tc, NULL);
57 ret = iface_turn_up(c->ifname);
58 ATF_REQUIRE_MSG(ret == 0, "Unable to turn up %s", c->ifname);
59 ret = iface_enable_ipv6(c->ifname);
60 ATF_REQUIRE_MSG(ret == 0, "Unable to enable IPv6 on %s", c->ifname);
62 c->rtsock_fd = rtsock_setup_socket();
67 static inline struct rtsock_test_config *
68 presetup_ipv4(const atf_tc_t *tc)
70 struct rtsock_test_config *c;
73 c = config_setup(tc, NULL);
77 /* assumes ifconfig doing IFF_UP */
78 ret = iface_setup_addr(c->ifname, c->addr4_str, c->plen4);
79 ATF_REQUIRE_MSG(ret == 0, "ifconfig failed");
81 c->rtsock_fd = rtsock_setup_socket();
87 prepare_route_message(struct rt_msghdr *rtm, int cmd, struct sockaddr *dst,
91 rtsock_prepare_route_message(rtm, cmd, dst, NULL, gw);
93 rtm->rtm_flags |= (RTF_HOST | RTF_STATIC | RTF_LLDATA);
97 #define DECLARE_TEST_VARS \
98 char buffer[2048], msg[512]; \
101 struct rtsock_test_config *c; \
102 struct rt_msghdr *rtm = (struct rt_msghdr *)buffer; \
103 struct sockaddr *sa; \
106 #define DECLARE_CLEANUP_VARS \
107 struct rtsock_test_config *c = config_setup(tc); \
110 #define DESCRIBE_ROOT_TEST(_msg) config_describe_root_test(tc, _msg)
111 #define CLEANUP_AFTER_TEST config_generic_cleanup(tc)
113 #define RTM_DECLARE_ROOT_TEST(_name, _descr) \
114 ATF_TC_WITH_CLEANUP(_name); \
115 ATF_TC_HEAD(_name, tc) \
117 DESCRIBE_ROOT_TEST(_descr); \
119 ATF_TC_CLEANUP(_name, tc) \
121 CLEANUP_AFTER_TEST; \
124 RTM_DECLARE_ROOT_TEST(rtm_add_v6_ll_lle_success, "Tests addition of link-local IPv6 ND entry");
125 ATF_TC_BODY(rtm_add_v6_ll_lle_success, tc)
129 c = presetup_ipv6(tc);
132 struct sockaddr_in6 sin6;
133 /* Interface here is optional. XXX: verify kernel side. */
134 char *v6addr = "fe80::4242:4242";
135 snprintf(str_buf, sizeof(str_buf), "%s%%%s", v6addr, c->ifname);
136 sa_convert_str_to_sa(str_buf, (struct sockaddr *)&sin6);
138 struct sockaddr_dl ether;
139 snprintf(str_buf, sizeof(str_buf), "%s%%%s", c->remote_lladdr, c->ifname);
140 sa_convert_str_to_sa(str_buf, (struct sockaddr *)ðer);
142 prepare_route_message(rtm, RTM_ADD, (struct sockaddr *)&sin6, (struct sockaddr *)ðer);
143 rtsock_send_rtm(c->rtsock_fd, rtm);
146 * Got message of size 240 on 2019-12-17 15:06:51
147 * RTM_ADD: Add Route: len 240, pid: 0, seq 0, errno 0, flags: <UP,HOST,DONE,LLINFO>
148 * sockaddrs: 0x3 <DST,GATEWAY>
149 * af=inet6 len=28 addr=fe80::4242:4242 scope_id=3 if_name=tap4242
150 * af=link len=54 sdl_index=3 if_name=tap4242 addr=52:54:00:14:E3:10
153 rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq);
155 sa = rtsock_find_rtm_sa(rtm, RTA_DST);
156 ret = sa_equal_msg(sa, (struct sockaddr *)&sin6, msg, sizeof(msg));
157 RTSOCK_ATF_REQUIRE_MSG(rtm, ret != 0, "DST sa diff: %s", msg);
159 sa = rtsock_find_rtm_sa(rtm, RTA_GATEWAY);
160 int sa_flags = SA_F_IGNORE_IFNAME | SA_F_IGNORE_IFTYPE | SA_F_IGNORE_MEMCMP;
161 ret = sa_equal_msg_flags(sa, (struct sockaddr *)ðer, msg, sizeof(msg), sa_flags);
162 RTSOCK_ATF_REQUIRE_MSG(rtm, ret != 0, "GATEWAY sa diff: %s", msg);
165 /* Disable the check until https://reviews.freebsd.org/D22003 merge */
166 /* Some additional checks to verify kernel has filled in interface data */
167 struct sockaddr_dl *sdl = (struct sockaddr_dl *)sa;
168 RTSOCK_ATF_REQUIRE_MSG(rtm, sdl->sdl_type > 0, "sdl_type not set");
172 RTM_DECLARE_ROOT_TEST(rtm_add_v6_gu_lle_success, "Tests addition of global IPv6 ND entry");
173 ATF_TC_BODY(rtm_add_v6_gu_lle_success, tc)
177 c = presetup_ipv6(tc);
181 struct sockaddr_in6 sin6;
183 #define _s6_addr32 __u6_addr.__u6_addr32
184 sin6.sin6_addr._s6_addr32[3] = htonl(0x42424242);
187 struct sockaddr_dl ether;
188 snprintf(str_buf, sizeof(str_buf), "%s%%%s", c->remote_lladdr, c->ifname);
189 sa_convert_str_to_sa(str_buf, (struct sockaddr *)ðer);
191 prepare_route_message(rtm, RTM_ADD, (struct sockaddr *)&sin6, (struct sockaddr *)ðer);
193 rtsock_send_rtm(c->rtsock_fd, rtm);
196 * Got message of size 240 on 2019-12-17 14:56:43
197 * RTM_ADD: Add Route: len 240, pid: 0, seq 0, errno 0, flags: <UP,HOST,DONE,LLINFO>
198 * sockaddrs: 0x3 <DST,GATEWAY>
199 * af=inet6 len=28 addr=2001:db8::4242:4242
200 * af=link len=54 sdl_index=3 if_name=tap4242 addr=52:54:00:14:E3:10
203 /* XXX: where is uRPF?! this should fail */
205 rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq);
207 sa = rtsock_find_rtm_sa(rtm, RTA_DST);
208 ret = sa_equal_msg(sa, (struct sockaddr *)&sin6, msg, sizeof(msg));
209 RTSOCK_ATF_REQUIRE_MSG(rtm, ret != 0, "DST sa diff: %s", msg);
211 sa = rtsock_find_rtm_sa(rtm, RTA_GATEWAY);
212 int sa_flags = SA_F_IGNORE_IFNAME | SA_F_IGNORE_IFTYPE | SA_F_IGNORE_MEMCMP;
213 ret = sa_equal_msg_flags(sa, (struct sockaddr *)ðer, msg, sizeof(msg), sa_flags);
214 RTSOCK_ATF_REQUIRE_MSG(rtm, ret != 0, "GATEWAY sa diff: %s", msg);
217 /* Disable the check until https://reviews.freebsd.org/D22003 merge */
218 /* Some additional checks to verify kernel has filled in interface data */
219 struct sockaddr_dl *sdl = (struct sockaddr_dl *)sa;
220 RTSOCK_ATF_REQUIRE_MSG(rtm, sdl->sdl_type > 0, "sdl_type not set");
224 RTM_DECLARE_ROOT_TEST(rtm_add_v4_gu_lle_success, "Tests addition of IPv4 ARP entry");
225 ATF_TC_BODY(rtm_add_v4_gu_lle_success, tc)
229 c = presetup_ipv4(tc);
233 struct sockaddr_in sin;
235 /* Use the next IPv4 address after self */
236 sin.sin_addr.s_addr = htonl(ntohl(sin.sin_addr.s_addr) + 1);
238 struct sockaddr_dl ether;
239 snprintf(str_buf, sizeof(str_buf), "%s%%%s", c->remote_lladdr, c->ifname);
240 sa_convert_str_to_sa(str_buf, (struct sockaddr *)ðer);
242 prepare_route_message(rtm, RTM_ADD, (struct sockaddr *)&sin, (struct sockaddr *)ðer);
244 len = rtsock_send_rtm(c->rtsock_fd, rtm);
247 * RTM_ADD: Add Route: len 224, pid: 43131, seq 42, errno 0, flags: <HOST,DONE,LLINFO,STATIC>
248 * sockaddrs: 0x3 <DST,GATEWAY>
249 * af=inet len=16 addr=192.0.2.2
250 * af=link len=54 sdl_index=3 if_name=tap4242 addr=52:54:00:14:E3:10
253 rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq);
255 sa = rtsock_find_rtm_sa(rtm, RTA_DST);
256 ret = sa_equal_msg(sa, (struct sockaddr *)&sin, msg, sizeof(msg));
257 RTSOCK_ATF_REQUIRE_MSG(rtm, ret != 0, "DST sa diff: %s", msg);
259 sa = rtsock_find_rtm_sa(rtm, RTA_GATEWAY);
260 int sa_flags = SA_F_IGNORE_IFNAME | SA_F_IGNORE_IFTYPE | SA_F_IGNORE_MEMCMP;
261 ret = sa_equal_msg_flags(sa, (struct sockaddr *)ðer, msg, sizeof(msg), sa_flags);
262 RTSOCK_ATF_REQUIRE_MSG(rtm, ret != 0, "GATEWAY sa diff: %s", msg);
265 * TODO: Currently kernel code does not set sdl_type, contrary to IPv6.
269 RTM_DECLARE_ROOT_TEST(rtm_del_v6_ll_lle_success, "Tests removal of link-local IPv6 ND entry");
270 ATF_TC_BODY(rtm_del_v6_ll_lle_success, tc)
274 c = presetup_ipv6(tc);
278 struct sockaddr_in6 sin6;
279 /* Interface here is optional. XXX: verify kernel side. */
280 char *v6addr = "fe80::4242:4242";
281 snprintf(str_buf, sizeof(str_buf), "%s%%%s", v6addr, c->ifname);
282 sa_convert_str_to_sa(str_buf, (struct sockaddr *)&sin6);
284 struct sockaddr_dl ether;
285 snprintf(str_buf, sizeof(str_buf), "%s%%%s", c->remote_lladdr, c->ifname);
286 sa_convert_str_to_sa(str_buf, (struct sockaddr *)ðer);
288 prepare_route_message(rtm, RTM_ADD, (struct sockaddr *)&sin6, (struct sockaddr *)ðer);
290 rtsock_send_rtm(c->rtsock_fd, rtm);
292 /* Successfully added an entry, let's try to remove it. */
293 prepare_route_message(rtm, RTM_DELETE, (struct sockaddr *)&sin6, (struct sockaddr *)ðer);
295 rtsock_send_rtm(c->rtsock_fd, rtm);
297 rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq);
299 RTSOCK_ATF_REQUIRE_MSG(rtm, rtm->rtm_type == RTM_DELETE, "rtm_type is not delete");
301 sa = rtsock_find_rtm_sa(rtm, RTA_DST);
302 ret = sa_equal_msg(sa, (struct sockaddr *)&sin6, msg, sizeof(msg));
303 RTSOCK_ATF_REQUIRE_MSG(rtm, ret != 0, "DST sa diff: %s", msg);
305 sa = rtsock_find_rtm_sa(rtm, RTA_GATEWAY);
306 int sa_flags = SA_F_IGNORE_IFNAME | SA_F_IGNORE_IFTYPE | SA_F_IGNORE_MEMCMP;
307 ret = sa_equal_msg_flags(sa, (struct sockaddr *)ðer, msg, sizeof(msg), sa_flags);
308 RTSOCK_ATF_REQUIRE_MSG(rtm, ret != 0, "GATEWAY sa diff: %s", msg);
311 * TODO: Currently kernel code does not set sdl_type on delete.
315 RTM_DECLARE_ROOT_TEST(rtm_del_v6_gu_lle_success, "Tests removal of global IPv6 ND entry");
316 ATF_TC_BODY(rtm_del_v6_gu_lle_success, tc)
320 c = presetup_ipv6(tc);
324 struct sockaddr_in6 sin6;
326 #define _s6_addr32 __u6_addr.__u6_addr32
327 sin6.sin6_addr._s6_addr32[3] = htonl(0x42424242);
330 struct sockaddr_dl ether;
331 snprintf(str_buf, sizeof(str_buf), "%s%%%s", c->remote_lladdr, c->ifname);
332 sa_convert_str_to_sa(str_buf, (struct sockaddr *)ðer);
334 prepare_route_message(rtm, RTM_ADD, (struct sockaddr *)&sin6, (struct sockaddr *)ðer);
336 len = rtsock_send_rtm(c->rtsock_fd, rtm);
338 /* Successfully added an entry, let's try to remove it. */
339 prepare_route_message(rtm, RTM_DELETE, (struct sockaddr *)&sin6, (struct sockaddr *)ðer);
341 rtsock_send_rtm(c->rtsock_fd, rtm);
343 rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq);
345 RTSOCK_ATF_REQUIRE_MSG(rtm, rtm->rtm_type == RTM_DELETE, "rtm_type is not delete");
347 sa = rtsock_find_rtm_sa(rtm, RTA_DST);
348 ret = sa_equal_msg(sa, (struct sockaddr *)&sin6, msg, sizeof(msg));
349 RTSOCK_ATF_REQUIRE_MSG(rtm, ret != 0, "DST sa diff: %s", msg);
351 sa = rtsock_find_rtm_sa(rtm, RTA_GATEWAY);
352 int sa_flags = SA_F_IGNORE_IFNAME | SA_F_IGNORE_IFTYPE | SA_F_IGNORE_MEMCMP;
353 ret = sa_equal_msg_flags(sa, (struct sockaddr *)ðer, msg, sizeof(msg), sa_flags);
354 RTSOCK_ATF_REQUIRE_MSG(rtm, ret != 0, "GATEWAY sa diff: %s", msg);
357 * TODO: Currently kernel code does not set sdl_type on delete.
361 RTM_DECLARE_ROOT_TEST(rtm_del_v4_gu_lle_success, "Tests removal of IPv4 ARP entry");
362 ATF_TC_BODY(rtm_del_v4_gu_lle_success, tc)
366 c = presetup_ipv4(tc);
370 struct sockaddr_in sin;
372 /* Use the next IPv4 address after self */
373 sin.sin_addr.s_addr = htonl(ntohl(sin.sin_addr.s_addr) + 1);
375 struct sockaddr_dl ether;
376 snprintf(str_buf, sizeof(str_buf), "%s%%%s", c->remote_lladdr, c->ifname);
377 sa_convert_str_to_sa(str_buf, (struct sockaddr *)ðer);
379 prepare_route_message(rtm, RTM_ADD, (struct sockaddr *)&sin, (struct sockaddr *)ðer);
381 rtsock_send_rtm(c->rtsock_fd, rtm);
383 /* We successfully added an entry, let's try to remove it. */
384 prepare_route_message(rtm, RTM_DELETE, (struct sockaddr *)&sin, (struct sockaddr *)ðer);
386 rtsock_send_rtm(c->rtsock_fd, rtm);
388 rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq);
390 RTSOCK_ATF_REQUIRE_MSG(rtm, rtm->rtm_type == RTM_DELETE, "rtm_type is not delete");
392 sa = rtsock_find_rtm_sa(rtm, RTA_DST);
393 ret = sa_equal_msg(sa, (struct sockaddr *)&sin, msg, sizeof(msg));
394 RTSOCK_ATF_REQUIRE_MSG(rtm, ret != 0, "DST sa diff: %s", msg);
396 sa = rtsock_find_rtm_sa(rtm, RTA_GATEWAY);
397 int sa_flags = SA_F_IGNORE_IFNAME | SA_F_IGNORE_IFTYPE | SA_F_IGNORE_MEMCMP;
398 ret = sa_equal_msg_flags(sa, (struct sockaddr *)ðer, msg, sizeof(msg), sa_flags);
399 RTSOCK_ATF_REQUIRE_MSG(rtm, ret != 0, "GATEWAY sa diff: %s", msg);
402 * TODO: Currently kernel code does not set sdl_type, contrary to IPv6.
408 ATF_TP_ADD_TC(tp, rtm_add_v6_ll_lle_success);
409 ATF_TP_ADD_TC(tp, rtm_add_v6_gu_lle_success);
410 ATF_TP_ADD_TC(tp, rtm_add_v4_gu_lle_success);
411 ATF_TP_ADD_TC(tp, rtm_del_v6_ll_lle_success);
412 ATF_TP_ADD_TC(tp, rtm_del_v6_gu_lle_success);
413 ATF_TP_ADD_TC(tp, rtm_del_v4_gu_lle_success);
415 return (atf_no_error());