xref: /freebsd/tests/sys/net/routing/test_rtsock_lladdr.c (revision f976241773df2260e6170317080761d1c5814fe5)
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 
102 ATF_TC_WITH_CLEANUP(rtm_add_v6_ll_lle_success);
103 ATF_TC_HEAD(rtm_add_v6_ll_lle_success, tc)
104 {
105 
106 	DESCRIBE_ROOT_TEST("Tests addition of link-local IPv6 ND entry");
107 }
108 
109 ATF_TC_BODY(rtm_add_v6_ll_lle_success, tc)
110 {
111 	DECLARE_TEST_VARS;
112 
113 	c = presetup_ipv6(tc);
114 
115 	char str_buf[128];
116 	struct sockaddr_in6 sin6;
117 	/* Interface here is optional. XXX: verify kernel side. */
118 	char *v6addr = "fe80::4242:4242";
119 	snprintf(str_buf, sizeof(str_buf), "%s%%%s", v6addr, c->ifname);
120 	sa_convert_str_to_sa(str_buf, (struct sockaddr *)&sin6);
121 
122 	struct sockaddr_dl ether;
123 	snprintf(str_buf, sizeof(str_buf), "%s%%%s", c->remote_lladdr, c->ifname);
124 	sa_convert_str_to_sa(str_buf, (struct sockaddr *)&ether);
125 
126 	prepare_route_message(rtm, RTM_ADD, (struct sockaddr *)&sin6, (struct sockaddr *)&ether);
127 	rtsock_send_rtm(c->rtsock_fd, rtm);
128 
129 	/*
130 	 * Got message of size 240 on 2019-12-17 15:06:51
131 	 * RTM_ADD: Add Route: len 240, pid: 0, seq 0, errno 0, flags: <UP,HOST,DONE,LLINFO>
132 	 * sockaddrs: 0x3 <DST,GATEWAY>
133 	 *  af=inet6 len=28 addr=fe80::4242:4242 scope_id=3 if_name=tap4242
134 	 *  af=link len=54 sdl_index=3 if_name=tap4242 addr=52:54:00:14:E3:10
135 	 */
136 
137 	rtm = rtsock_read_rtm(c->rtsock_fd, buffer, sizeof(buffer));
138 
139 	sa = rtsock_find_rtm_sa(rtm, RTA_DST);
140 	ret = sa_equal_msg(sa, (struct sockaddr *)&sin6, msg, sizeof(msg));
141 	RTSOCK_ATF_REQUIRE_MSG(rtm, ret != 0, "DST sa diff: %s", msg);
142 
143 	sa = rtsock_find_rtm_sa(rtm, RTA_GATEWAY);
144 	int sa_flags = SA_F_IGNORE_IFNAME | SA_F_IGNORE_IFTYPE | SA_F_IGNORE_MEMCMP;
145 	ret = sa_equal_msg_flags(sa, (struct sockaddr *)&ether, msg, sizeof(msg), sa_flags);
146 	RTSOCK_ATF_REQUIRE_MSG(rtm, ret != 0, "GATEWAY sa diff: %s", msg);
147 
148 	/* Some additional checks to verify kernel has filled in interface data */
149 	struct sockaddr_dl *sdl = (struct sockaddr_dl *)sa;
150 	RTSOCK_ATF_REQUIRE_MSG(rtm, sdl->sdl_type > 0, "sdl_type not set");
151 }
152 
153 ATF_TC_CLEANUP(rtm_add_v6_ll_lle_success, tc)
154 {
155 	CLEANUP_AFTER_TEST;
156 }
157 
158 ATF_TC_WITH_CLEANUP(rtm_add_v6_gu_lle_success);
159 ATF_TC_HEAD(rtm_add_v6_gu_lle_success, tc)
160 {
161 
162 	DESCRIBE_ROOT_TEST("Tests addition of global IPv6 ND entry");
163 }
164 
165 ATF_TC_BODY(rtm_add_v6_gu_lle_success, tc)
166 {
167 	DECLARE_TEST_VARS;
168 
169 	c = presetup_ipv6(tc);
170 
171 	char str_buf[128];
172 
173 	struct sockaddr_in6 sin6;
174 	sin6 = c->net6;
175 #define _s6_addr32 __u6_addr.__u6_addr32
176 	sin6.sin6_addr._s6_addr32[3] = htonl(0x42424242);
177 #undef _s6_addr32
178 
179 	struct sockaddr_dl ether;
180 	snprintf(str_buf, sizeof(str_buf), "%s%%%s", c->remote_lladdr, c->ifname);
181 	sa_convert_str_to_sa(str_buf, (struct sockaddr *)&ether);
182 
183 	prepare_route_message(rtm, RTM_ADD, (struct sockaddr *)&sin6, (struct sockaddr *)&ether);
184 
185 	rtsock_send_rtm(c->rtsock_fd, rtm);
186 
187 	/*
188 	 * Got message of size 240 on 2019-12-17 14:56:43
189 	 * RTM_ADD: Add Route: len 240, pid: 0, seq 0, errno 0, flags: <UP,HOST,DONE,LLINFO>
190 	 * sockaddrs: 0x3 <DST,GATEWAY>
191 	 *  af=inet6 len=28 addr=2001:db8::4242:4242
192  	 *  af=link len=54 sdl_index=3 if_name=tap4242 addr=52:54:00:14:E3:10
193 	 */
194 
195 	/* XXX: where is uRPF?! this should fail */
196 
197 	rtm = rtsock_read_rtm(c->rtsock_fd, buffer, sizeof(buffer));
198 
199 	sa = rtsock_find_rtm_sa(rtm, RTA_DST);
200 	ret = sa_equal_msg(sa, (struct sockaddr *)&sin6, msg, sizeof(msg));
201 	RTSOCK_ATF_REQUIRE_MSG(rtm, ret != 0, "DST sa diff: %s", msg);
202 
203 	sa = rtsock_find_rtm_sa(rtm, RTA_GATEWAY);
204 	int sa_flags = SA_F_IGNORE_IFNAME | SA_F_IGNORE_IFTYPE | SA_F_IGNORE_MEMCMP;
205 	ret = sa_equal_msg_flags(sa, (struct sockaddr *)&ether, msg, sizeof(msg), sa_flags);
206 	RTSOCK_ATF_REQUIRE_MSG(rtm, ret != 0, "GATEWAY sa diff: %s", msg);
207 
208 	/* Some additional checks to verify kernel has filled in interface data */
209 	struct sockaddr_dl *sdl = (struct sockaddr_dl *)sa;
210 	RTSOCK_ATF_REQUIRE_MSG(rtm, sdl->sdl_type > 0, "sdl_type not set");
211 }
212 
213 ATF_TC_CLEANUP(rtm_add_v6_gu_lle_success, tc)
214 {
215 	CLEANUP_AFTER_TEST;
216 }
217 
218 ATF_TC_WITH_CLEANUP(rtm_add_v4_gu_lle_success);
219 ATF_TC_HEAD(rtm_add_v4_gu_lle_success, tc)
220 {
221 
222 	DESCRIBE_ROOT_TEST("Tests addition of IPv4 ARP entry");
223 }
224 
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(c->rtsock_fd, buffer, sizeof(buffer));
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 ATF_TC_CLEANUP(rtm_add_v4_gu_lle_success, tc)
270 {
271 	CLEANUP_AFTER_TEST;
272 }
273 
274 ATF_TC_WITH_CLEANUP(rtm_del_v6_ll_lle_success);
275 ATF_TC_HEAD(rtm_del_v6_ll_lle_success, tc)
276 {
277 
278 	DESCRIBE_ROOT_TEST("Tests removal of link-local IPv6 ND entry");
279 }
280 
281 ATF_TC_BODY(rtm_del_v6_ll_lle_success, tc)
282 {
283 	DECLARE_TEST_VARS;
284 
285 	c = presetup_ipv6(tc);
286 
287 	char str_buf[128];
288 
289 	struct sockaddr_in6 sin6;
290 	/* Interface here is optional. XXX: verify kernel side. */
291 	char *v6addr = "fe80::4242:4242";
292 	snprintf(str_buf, sizeof(str_buf), "%s%%%s", v6addr, c->ifname);
293 	sa_convert_str_to_sa(str_buf, (struct sockaddr *)&sin6);
294 
295 	struct sockaddr_dl ether;
296 	snprintf(str_buf, sizeof(str_buf), "%s%%%s", c->remote_lladdr, c->ifname);
297 	sa_convert_str_to_sa(str_buf, (struct sockaddr *)&ether);
298 
299 	prepare_route_message(rtm, RTM_ADD, (struct sockaddr *)&sin6, (struct sockaddr *)&ether);
300 
301 	rtsock_send_rtm(c->rtsock_fd, rtm);
302 
303 	/* Successfully added an entry, let's try to remove it. */
304 	prepare_route_message(rtm, RTM_DELETE, (struct sockaddr *)&sin6, (struct sockaddr *)&ether);
305 
306 	rtsock_send_rtm(c->rtsock_fd, rtm);
307 
308 	rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq);
309 
310 	RTSOCK_ATF_REQUIRE_MSG(rtm, rtm->rtm_type == RTM_DELETE, "rtm_type is not delete");
311 
312 	sa = rtsock_find_rtm_sa(rtm, RTA_DST);
313 	ret = sa_equal_msg(sa, (struct sockaddr *)&sin6, msg, sizeof(msg));
314 	RTSOCK_ATF_REQUIRE_MSG(rtm, ret != 0, "DST sa diff: %s", msg);
315 
316 	sa = rtsock_find_rtm_sa(rtm, RTA_GATEWAY);
317 	int sa_flags = SA_F_IGNORE_IFNAME | SA_F_IGNORE_IFTYPE | SA_F_IGNORE_MEMCMP;
318 	ret = sa_equal_msg_flags(sa, (struct sockaddr *)&ether, msg, sizeof(msg), sa_flags);
319 	RTSOCK_ATF_REQUIRE_MSG(rtm, ret != 0, "GATEWAY sa diff: %s", msg);
320 
321 	/*
322 	 * TODO: Currently kernel code does not set sdl_type on delete.
323 	 */
324 }
325 
326 ATF_TC_CLEANUP(rtm_del_v6_ll_lle_success, tc)
327 {
328 	CLEANUP_AFTER_TEST;
329 }
330 
331 ATF_TC_WITH_CLEANUP(rtm_del_v6_gu_lle_success);
332 ATF_TC_HEAD(rtm_del_v6_gu_lle_success, tc)
333 {
334 
335 	DESCRIBE_ROOT_TEST("Tests removal of global IPv6 ND entry");
336 }
337 
338 ATF_TC_BODY(rtm_del_v6_gu_lle_success, tc)
339 {
340 	DECLARE_TEST_VARS;
341 
342 	c = presetup_ipv6(tc);
343 
344 	char str_buf[128];
345 
346 	struct sockaddr_in6 sin6;
347 	sin6 = c->net6;
348 #define _s6_addr32 __u6_addr.__u6_addr32
349 	sin6.sin6_addr._s6_addr32[3] = htonl(0x42424242);
350 #undef _s6_addr32
351 
352 	struct sockaddr_dl ether;
353 	snprintf(str_buf, sizeof(str_buf), "%s%%%s", c->remote_lladdr, c->ifname);
354 	sa_convert_str_to_sa(str_buf, (struct sockaddr *)&ether);
355 
356 	prepare_route_message(rtm, RTM_ADD, (struct sockaddr *)&sin6, (struct sockaddr *)&ether);
357 
358 	len = rtsock_send_rtm(c->rtsock_fd, rtm);
359 
360 	/* Successfully added an entry, let's try to remove it. */
361 	prepare_route_message(rtm, RTM_DELETE, (struct sockaddr *)&sin6, (struct sockaddr *)&ether);
362 
363 	rtsock_send_rtm(c->rtsock_fd, rtm);
364 
365 	rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq);
366 
367 	RTSOCK_ATF_REQUIRE_MSG(rtm, rtm->rtm_type == RTM_DELETE, "rtm_type is not delete");
368 
369 	sa = rtsock_find_rtm_sa(rtm, RTA_DST);
370 	ret = sa_equal_msg(sa, (struct sockaddr *)&sin6, msg, sizeof(msg));
371 	RTSOCK_ATF_REQUIRE_MSG(rtm, ret != 0, "DST sa diff: %s", msg);
372 
373 	sa = rtsock_find_rtm_sa(rtm, RTA_GATEWAY);
374 	int sa_flags = SA_F_IGNORE_IFNAME | SA_F_IGNORE_IFTYPE | SA_F_IGNORE_MEMCMP;
375 	ret = sa_equal_msg_flags(sa, (struct sockaddr *)&ether, msg, sizeof(msg), sa_flags);
376 	RTSOCK_ATF_REQUIRE_MSG(rtm, ret != 0, "GATEWAY sa diff: %s", msg);
377 
378 	/*
379 	 * TODO: Currently kernel code does not set sdl_type on delete.
380 	 */
381 }
382 
383 ATF_TC_CLEANUP(rtm_del_v6_gu_lle_success, tc)
384 {
385 	CLEANUP_AFTER_TEST;
386 }
387 
388 ATF_TC_WITH_CLEANUP(rtm_del_v4_gu_lle_success);
389 ATF_TC_HEAD(rtm_del_v4_gu_lle_success, tc)
390 {
391 
392 	DESCRIBE_ROOT_TEST("Tests removal of IPv4 ARP entry");
393 }
394 
395 ATF_TC_BODY(rtm_del_v4_gu_lle_success, tc)
396 {
397 	DECLARE_TEST_VARS;
398 
399 	c = presetup_ipv4(tc);
400 
401 	char str_buf[128];
402 
403 	struct sockaddr_in sin;
404 	sin = c->addr4;
405 	/* Use the next IPv4 address after self */
406 	sin.sin_addr.s_addr = htonl(ntohl(sin.sin_addr.s_addr) + 1);
407 
408 	struct sockaddr_dl ether;
409 	snprintf(str_buf, sizeof(str_buf), "%s%%%s", c->remote_lladdr, c->ifname);
410 	sa_convert_str_to_sa(str_buf, (struct sockaddr *)&ether);
411 
412 	prepare_route_message(rtm, RTM_ADD, (struct sockaddr *)&sin, (struct sockaddr *)&ether);
413 
414 	rtsock_send_rtm(c->rtsock_fd, rtm);
415 
416 	rtsock_read_rtm(c->rtsock_fd, buffer, sizeof(buffer));
417 
418 	/* We successfully added an entry, let's try to remove it. */
419 	prepare_route_message(rtm, RTM_DELETE, (struct sockaddr *)&sin, (struct sockaddr *)&ether);
420 
421 	rtsock_send_rtm(c->rtsock_fd, rtm);
422 
423 	rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq);
424 
425 	RTSOCK_ATF_REQUIRE_MSG(rtm, rtm->rtm_type == RTM_DELETE, "rtm_type is not delete");
426 
427 	sa = rtsock_find_rtm_sa(rtm, RTA_DST);
428 	ret = sa_equal_msg(sa, (struct sockaddr *)&sin, msg, sizeof(msg));
429 	RTSOCK_ATF_REQUIRE_MSG(rtm, ret != 0, "DST sa diff: %s", msg);
430 
431 	sa = rtsock_find_rtm_sa(rtm, RTA_GATEWAY);
432 	int sa_flags = SA_F_IGNORE_IFNAME | SA_F_IGNORE_IFTYPE | SA_F_IGNORE_MEMCMP;
433 	ret = sa_equal_msg_flags(sa, (struct sockaddr *)&ether, msg, sizeof(msg), sa_flags);
434 	RTSOCK_ATF_REQUIRE_MSG(rtm, ret != 0, "GATEWAY sa diff: %s", msg);
435 
436 	/*
437 	 * TODO: Currently kernel code does not set sdl_type, contrary to IPv6.
438 	 */
439 }
440 
441 ATF_TC_CLEANUP(rtm_del_v4_gu_lle_success, tc)
442 {
443 	CLEANUP_AFTER_TEST;
444 }
445 
446 
447 ATF_TP_ADD_TCS(tp)
448 {
449 	ATF_TP_ADD_TC(tp, rtm_add_v6_ll_lle_success);
450 	ATF_TP_ADD_TC(tp, rtm_add_v6_gu_lle_success);
451 	ATF_TP_ADD_TC(tp, rtm_add_v4_gu_lle_success);
452 	ATF_TP_ADD_TC(tp, rtm_del_v6_ll_lle_success);
453 	ATF_TP_ADD_TC(tp, rtm_del_v6_gu_lle_success);
454 	ATF_TP_ADD_TC(tp, rtm_del_v4_gu_lle_success);
455 
456 	return (atf_no_error());
457 }
458 
459 
460