]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - tests/sys/net/routing/test_rtsock_lladdr.c
MFV r362565:
[FreeBSD/FreeBSD.git] / tests / sys / net / routing / test_rtsock_lladdr.c
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 void
34 jump_vnet(struct rtsock_test_config *c, const atf_tc_t *tc)
35 {
36         char vnet_name[512];
37
38         snprintf(vnet_name, sizeof(vnet_name), "vt-%s", atf_tc_get_ident(tc));
39         RLOG("jumping to %s", vnet_name);
40
41         vnet_switch_one(vnet_name, c->ifname);
42
43         /* Update ifindex cache */
44         c->ifindex = if_nametoindex(c->ifname);
45 }
46
47 static inline struct rtsock_test_config *
48 presetup_ipv6(const atf_tc_t *tc)
49 {
50         struct rtsock_test_config *c;
51         int ret;
52
53         c = config_setup(tc, NULL);
54
55         jump_vnet(c, tc);
56
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);
61
62         c->rtsock_fd = rtsock_setup_socket();
63
64         return (c);
65 }
66
67 static inline struct rtsock_test_config *
68 presetup_ipv4(const atf_tc_t *tc)
69 {
70         struct rtsock_test_config *c;
71         int ret;
72
73         c = config_setup(tc, NULL);
74
75         jump_vnet(c, tc);
76
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");
80
81         c->rtsock_fd = rtsock_setup_socket();
82
83         return (c);
84 }
85
86 static void
87 prepare_route_message(struct rt_msghdr *rtm, int cmd, struct sockaddr *dst,
88   struct sockaddr *gw)
89 {
90
91         rtsock_prepare_route_message(rtm, cmd, dst, NULL, gw);
92
93         rtm->rtm_flags |= (RTF_HOST | RTF_STATIC | RTF_LLDATA);
94 }
95
96 /* TESTS */
97 #define DECLARE_TEST_VARS                                       \
98         char buffer[2048], msg[512];                            \
99         ssize_t len;                                            \
100         int ret;                                                \
101         struct rtsock_test_config *c;                           \
102         struct rt_msghdr *rtm = (struct rt_msghdr *)buffer;     \
103         struct sockaddr *sa;                                    \
104                                                                 \
105
106 #define DECLARE_CLEANUP_VARS                                    \
107         struct rtsock_test_config *c = config_setup(tc);        \
108                                                                 \
109
110 #define DESCRIBE_ROOT_TEST(_msg)        config_describe_root_test(tc, _msg)
111 #define CLEANUP_AFTER_TEST      config_generic_cleanup(tc)
112
113 #define RTM_DECLARE_ROOT_TEST(_name, _descr)                    \
114 ATF_TC_WITH_CLEANUP(_name);                                     \
115 ATF_TC_HEAD(_name, tc)                                          \
116 {                                                               \
117         DESCRIBE_ROOT_TEST(_descr);                             \
118 }                                                               \
119 ATF_TC_CLEANUP(_name, tc)                                       \
120 {                                                               \
121         CLEANUP_AFTER_TEST;                                     \
122 }
123
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)
126 {
127         DECLARE_TEST_VARS;
128
129         c = presetup_ipv6(tc);
130
131         char str_buf[128];
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);
137
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 *)&ether);
141
142         prepare_route_message(rtm, RTM_ADD, (struct sockaddr *)&sin6, (struct sockaddr *)&ether);
143         rtsock_send_rtm(c->rtsock_fd, rtm);
144
145         /*
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
151          */
152
153         rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq);
154
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);
158
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 *)&ether, msg, sizeof(msg), sa_flags);
162         RTSOCK_ATF_REQUIRE_MSG(rtm, ret != 0, "GATEWAY sa diff: %s", msg);
163
164 #if 0
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");
169 #endif
170 }
171
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)
174 {
175         DECLARE_TEST_VARS;
176
177         c = presetup_ipv6(tc);
178
179         char str_buf[128];
180
181         struct sockaddr_in6 sin6;
182         sin6 = c->net6;
183 #define _s6_addr32 __u6_addr.__u6_addr32
184         sin6.sin6_addr._s6_addr32[3] = htonl(0x42424242);
185 #undef _s6_addr32
186
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 *)&ether);
190
191         prepare_route_message(rtm, RTM_ADD, (struct sockaddr *)&sin6, (struct sockaddr *)&ether);
192
193         rtsock_send_rtm(c->rtsock_fd, rtm);
194
195         /*
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
201          */
202
203         /* XXX: where is uRPF?! this should fail */
204
205         rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq);
206
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);
210
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 *)&ether, msg, sizeof(msg), sa_flags);
214         RTSOCK_ATF_REQUIRE_MSG(rtm, ret != 0, "GATEWAY sa diff: %s", msg);
215
216 #if 0
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");
221 #endif
222 }
223
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)
226 {
227         DECLARE_TEST_VARS;
228
229         c = presetup_ipv4(tc);
230
231         char str_buf[128];
232
233         struct sockaddr_in sin;
234         sin = c->addr4;
235         /* Use the next IPv4 address after self */
236         sin.sin_addr.s_addr = htonl(ntohl(sin.sin_addr.s_addr) + 1);
237
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 *)&ether);
241
242         prepare_route_message(rtm, RTM_ADD, (struct sockaddr *)&sin, (struct sockaddr *)&ether);
243
244         len = rtsock_send_rtm(c->rtsock_fd, rtm);
245
246         /*
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
251          */
252
253         rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq);
254
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);
258
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 *)&ether, msg, sizeof(msg), sa_flags);
262         RTSOCK_ATF_REQUIRE_MSG(rtm, ret != 0, "GATEWAY sa diff: %s", msg);
263
264         /*
265          * TODO: Currently kernel code does not set sdl_type, contrary to IPv6.
266          */
267 }
268
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)
271 {
272         DECLARE_TEST_VARS;
273
274         c = presetup_ipv6(tc);
275
276         char str_buf[128];
277
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);
283
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 *)&ether);
287
288         prepare_route_message(rtm, RTM_ADD, (struct sockaddr *)&sin6, (struct sockaddr *)&ether);
289
290         rtsock_send_rtm(c->rtsock_fd, rtm);
291
292         /* Successfully added an entry, let's try to remove it. */
293         prepare_route_message(rtm, RTM_DELETE, (struct sockaddr *)&sin6, (struct sockaddr *)&ether);
294
295         rtsock_send_rtm(c->rtsock_fd, rtm);
296
297         rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq);
298
299         RTSOCK_ATF_REQUIRE_MSG(rtm, rtm->rtm_type == RTM_DELETE, "rtm_type is not delete");
300
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);
304
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 *)&ether, msg, sizeof(msg), sa_flags);
308         RTSOCK_ATF_REQUIRE_MSG(rtm, ret != 0, "GATEWAY sa diff: %s", msg);
309
310         /*
311          * TODO: Currently kernel code does not set sdl_type on delete.
312          */
313 }
314
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)
317 {
318         DECLARE_TEST_VARS;
319
320         c = presetup_ipv6(tc);
321
322         char str_buf[128];
323
324         struct sockaddr_in6 sin6;
325         sin6 = c->net6;
326 #define _s6_addr32 __u6_addr.__u6_addr32
327         sin6.sin6_addr._s6_addr32[3] = htonl(0x42424242);
328 #undef _s6_addr32
329
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 *)&ether);
333
334         prepare_route_message(rtm, RTM_ADD, (struct sockaddr *)&sin6, (struct sockaddr *)&ether);
335
336         len = rtsock_send_rtm(c->rtsock_fd, rtm);
337
338         /* Successfully added an entry, let's try to remove it. */
339         prepare_route_message(rtm, RTM_DELETE, (struct sockaddr *)&sin6, (struct sockaddr *)&ether);
340
341         rtsock_send_rtm(c->rtsock_fd, rtm);
342
343         rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq);
344
345         RTSOCK_ATF_REQUIRE_MSG(rtm, rtm->rtm_type == RTM_DELETE, "rtm_type is not delete");
346
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);
350
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 *)&ether, msg, sizeof(msg), sa_flags);
354         RTSOCK_ATF_REQUIRE_MSG(rtm, ret != 0, "GATEWAY sa diff: %s", msg);
355
356         /*
357          * TODO: Currently kernel code does not set sdl_type on delete.
358          */
359 }
360
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)
363 {
364         DECLARE_TEST_VARS;
365
366         c = presetup_ipv4(tc);
367
368         char str_buf[128];
369
370         struct sockaddr_in sin;
371         sin = c->addr4;
372         /* Use the next IPv4 address after self */
373         sin.sin_addr.s_addr = htonl(ntohl(sin.sin_addr.s_addr) + 1);
374
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 *)&ether);
378
379         prepare_route_message(rtm, RTM_ADD, (struct sockaddr *)&sin, (struct sockaddr *)&ether);
380
381         rtsock_send_rtm(c->rtsock_fd, rtm);
382
383         /* We successfully added an entry, let's try to remove it. */
384         prepare_route_message(rtm, RTM_DELETE, (struct sockaddr *)&sin, (struct sockaddr *)&ether);
385
386         rtsock_send_rtm(c->rtsock_fd, rtm);
387
388         rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq);
389
390         RTSOCK_ATF_REQUIRE_MSG(rtm, rtm->rtm_type == RTM_DELETE, "rtm_type is not delete");
391
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);
395
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 *)&ether, msg, sizeof(msg), sa_flags);
399         RTSOCK_ATF_REQUIRE_MSG(rtm, ret != 0, "GATEWAY sa diff: %s", msg);
400
401         /*
402          * TODO: Currently kernel code does not set sdl_type, contrary to IPv6.
403          */
404 }
405
406 ATF_TP_ADD_TCS(tp)
407 {
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);
414
415         return (atf_no_error());
416 }
417
418