Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/tests/sys/net/routing/test_rtsock_lladdr.c
39604 views
1
/*-
2
* SPDX-License-Identifier: BSD-2-Clause
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
28
#include "rtsock_common.h"
29
#include "rtsock_config.h"
30
31
static void
32
jump_vnet(struct rtsock_test_config *c, const atf_tc_t *tc)
33
{
34
char vnet_name[512];
35
36
snprintf(vnet_name, sizeof(vnet_name), "vt-%s", atf_tc_get_ident(tc));
37
RLOG("jumping to %s", vnet_name);
38
39
vnet_switch_one(vnet_name, c->ifname);
40
41
/* Update ifindex cache */
42
c->ifindex = if_nametoindex(c->ifname);
43
}
44
45
static inline struct rtsock_test_config *
46
presetup_ipv6(const atf_tc_t *tc)
47
{
48
struct rtsock_test_config *c;
49
int ret;
50
51
c = config_setup(tc, NULL);
52
53
jump_vnet(c, tc);
54
55
ret = iface_turn_up(c->ifname);
56
ATF_REQUIRE_MSG(ret == 0, "Unable to turn up %s", c->ifname);
57
ret = iface_enable_ipv6(c->ifname);
58
ATF_REQUIRE_MSG(ret == 0, "Unable to enable IPv6 on %s", c->ifname);
59
60
c->rtsock_fd = rtsock_setup_socket();
61
62
return (c);
63
}
64
65
static inline struct rtsock_test_config *
66
presetup_ipv4(const atf_tc_t *tc)
67
{
68
struct rtsock_test_config *c;
69
int ret;
70
71
c = config_setup(tc, NULL);
72
73
jump_vnet(c, tc);
74
75
/* assumes ifconfig doing IFF_UP */
76
ret = iface_setup_addr(c->ifname, c->addr4_str, c->plen4);
77
ATF_REQUIRE_MSG(ret == 0, "ifconfig failed");
78
79
c->rtsock_fd = rtsock_setup_socket();
80
81
return (c);
82
}
83
84
static void
85
prepare_route_message(struct rt_msghdr *rtm, int cmd, struct sockaddr *dst,
86
struct sockaddr *gw)
87
{
88
89
rtsock_prepare_route_message(rtm, cmd, dst, NULL, gw);
90
91
rtm->rtm_flags |= (RTF_HOST | RTF_STATIC | RTF_LLDATA);
92
}
93
94
/* TESTS */
95
#define DECLARE_TEST_VARS \
96
char buffer[2048], msg[512]; \
97
ssize_t len; \
98
int ret; \
99
struct rtsock_test_config *c; \
100
struct rt_msghdr *rtm = (struct rt_msghdr *)buffer; \
101
struct sockaddr *sa; \
102
\
103
104
#define DECLARE_CLEANUP_VARS \
105
struct rtsock_test_config *c = config_setup(tc); \
106
\
107
108
#define DESCRIBE_ROOT_TEST(_msg) config_describe_root_test(tc, _msg)
109
#define CLEANUP_AFTER_TEST config_generic_cleanup(tc)
110
111
#define RTM_DECLARE_ROOT_TEST(_name, _descr) \
112
ATF_TC_WITH_CLEANUP(_name); \
113
ATF_TC_HEAD(_name, tc) \
114
{ \
115
DESCRIBE_ROOT_TEST(_descr); \
116
} \
117
ATF_TC_CLEANUP(_name, tc) \
118
{ \
119
CLEANUP_AFTER_TEST; \
120
}
121
122
RTM_DECLARE_ROOT_TEST(rtm_add_v6_ll_lle_success, "Tests addition of link-local IPv6 ND entry");
123
ATF_TC_BODY(rtm_add_v6_ll_lle_success, tc)
124
{
125
DECLARE_TEST_VARS;
126
127
c = presetup_ipv6(tc);
128
129
char str_buf[128];
130
struct sockaddr_in6 sin6;
131
/* Interface here is optional. XXX: verify kernel side. */
132
char *v6addr = "fe80::4242:4242";
133
snprintf(str_buf, sizeof(str_buf), "%s%%%s", v6addr, c->ifname);
134
sa_convert_str_to_sa(str_buf, (struct sockaddr *)&sin6);
135
136
struct sockaddr_dl ether;
137
snprintf(str_buf, sizeof(str_buf), "%s%%%s", c->remote_lladdr, c->ifname);
138
sa_convert_str_to_sa(str_buf, (struct sockaddr *)&ether);
139
140
prepare_route_message(rtm, RTM_ADD, (struct sockaddr *)&sin6, (struct sockaddr *)&ether);
141
rtsock_send_rtm(c->rtsock_fd, rtm);
142
143
/*
144
* Got message of size 240 on 2019-12-17 15:06:51
145
* RTM_ADD: Add Route: len 240, pid: 0, seq 0, errno 0, flags: <UP,HOST,DONE,LLINFO>
146
* sockaddrs: 0x3 <DST,GATEWAY>
147
* af=inet6 len=28 addr=fe80::4242:4242 scope_id=3 if_name=tap4242
148
* af=link len=54 sdl_index=3 if_name=tap4242 addr=52:54:00:14:E3:10
149
*/
150
151
rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq);
152
153
sa = rtsock_find_rtm_sa(rtm, RTA_DST);
154
ret = sa_equal_msg(sa, (struct sockaddr *)&sin6, msg, sizeof(msg));
155
RTSOCK_ATF_REQUIRE_MSG(rtm, ret != 0, "DST sa diff: %s", msg);
156
157
sa = rtsock_find_rtm_sa(rtm, RTA_GATEWAY);
158
int sa_flags = SA_F_IGNORE_IFNAME | SA_F_IGNORE_IFTYPE | SA_F_IGNORE_MEMCMP;
159
ret = sa_equal_msg_flags(sa, (struct sockaddr *)&ether, msg, sizeof(msg), sa_flags);
160
RTSOCK_ATF_REQUIRE_MSG(rtm, ret != 0, "GATEWAY sa diff: %s", msg);
161
162
#if 0
163
/* Disable the check until https://reviews.freebsd.org/D22003 merge */
164
/* Some additional checks to verify kernel has filled in interface data */
165
struct sockaddr_dl *sdl = (struct sockaddr_dl *)sa;
166
RTSOCK_ATF_REQUIRE_MSG(rtm, sdl->sdl_type > 0, "sdl_type not set");
167
#endif
168
}
169
170
RTM_DECLARE_ROOT_TEST(rtm_add_v6_gu_lle_success, "Tests addition of global IPv6 ND entry");
171
ATF_TC_BODY(rtm_add_v6_gu_lle_success, tc)
172
{
173
DECLARE_TEST_VARS;
174
175
c = presetup_ipv6(tc);
176
177
char str_buf[128];
178
179
struct sockaddr_in6 sin6;
180
sin6 = c->net6;
181
#define _s6_addr32 __u6_addr.__u6_addr32
182
sin6.sin6_addr._s6_addr32[3] = htonl(0x42424242);
183
#undef _s6_addr32
184
185
struct sockaddr_dl ether;
186
snprintf(str_buf, sizeof(str_buf), "%s%%%s", c->remote_lladdr, c->ifname);
187
sa_convert_str_to_sa(str_buf, (struct sockaddr *)&ether);
188
189
prepare_route_message(rtm, RTM_ADD, (struct sockaddr *)&sin6, (struct sockaddr *)&ether);
190
191
rtsock_send_rtm(c->rtsock_fd, rtm);
192
193
/*
194
* Got message of size 240 on 2019-12-17 14:56:43
195
* RTM_ADD: Add Route: len 240, pid: 0, seq 0, errno 0, flags: <UP,HOST,DONE,LLINFO>
196
* sockaddrs: 0x3 <DST,GATEWAY>
197
* af=inet6 len=28 addr=2001:db8::4242:4242
198
* af=link len=54 sdl_index=3 if_name=tap4242 addr=52:54:00:14:E3:10
199
*/
200
201
/* XXX: where is uRPF?! this should fail */
202
203
rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq);
204
205
sa = rtsock_find_rtm_sa(rtm, RTA_DST);
206
ret = sa_equal_msg(sa, (struct sockaddr *)&sin6, msg, sizeof(msg));
207
RTSOCK_ATF_REQUIRE_MSG(rtm, ret != 0, "DST sa diff: %s", msg);
208
209
sa = rtsock_find_rtm_sa(rtm, RTA_GATEWAY);
210
int sa_flags = SA_F_IGNORE_IFNAME | SA_F_IGNORE_IFTYPE | SA_F_IGNORE_MEMCMP;
211
ret = sa_equal_msg_flags(sa, (struct sockaddr *)&ether, msg, sizeof(msg), sa_flags);
212
RTSOCK_ATF_REQUIRE_MSG(rtm, ret != 0, "GATEWAY sa diff: %s", msg);
213
214
#if 0
215
/* Disable the check until https://reviews.freebsd.org/D22003 merge */
216
/* Some additional checks to verify kernel has filled in interface data */
217
struct sockaddr_dl *sdl = (struct sockaddr_dl *)sa;
218
RTSOCK_ATF_REQUIRE_MSG(rtm, sdl->sdl_type > 0, "sdl_type not set");
219
#endif
220
}
221
222
RTM_DECLARE_ROOT_TEST(rtm_add_v4_gu_lle_success, "Tests addition of IPv4 ARP entry");
223
ATF_TC_BODY(rtm_add_v4_gu_lle_success, tc)
224
{
225
DECLARE_TEST_VARS;
226
227
c = presetup_ipv4(tc);
228
229
char str_buf[128];
230
231
struct sockaddr_in sin;
232
sin = c->addr4;
233
/* Use the next IPv4 address after self */
234
sin.sin_addr.s_addr = htonl(ntohl(sin.sin_addr.s_addr) + 1);
235
236
struct sockaddr_dl ether;
237
snprintf(str_buf, sizeof(str_buf), "%s%%%s", c->remote_lladdr, c->ifname);
238
sa_convert_str_to_sa(str_buf, (struct sockaddr *)&ether);
239
240
prepare_route_message(rtm, RTM_ADD, (struct sockaddr *)&sin, (struct sockaddr *)&ether);
241
242
len = rtsock_send_rtm(c->rtsock_fd, rtm);
243
244
/*
245
* RTM_ADD: Add Route: len 224, pid: 43131, seq 42, errno 0, flags: <HOST,DONE,LLINFO,STATIC>
246
* sockaddrs: 0x3 <DST,GATEWAY>
247
* af=inet len=16 addr=192.0.2.2
248
* af=link len=54 sdl_index=3 if_name=tap4242 addr=52:54:00:14:E3:10
249
*/
250
251
rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq);
252
253
sa = rtsock_find_rtm_sa(rtm, RTA_DST);
254
ret = sa_equal_msg(sa, (struct sockaddr *)&sin, msg, sizeof(msg));
255
RTSOCK_ATF_REQUIRE_MSG(rtm, ret != 0, "DST sa diff: %s", msg);
256
257
sa = rtsock_find_rtm_sa(rtm, RTA_GATEWAY);
258
int sa_flags = SA_F_IGNORE_IFNAME | SA_F_IGNORE_IFTYPE | SA_F_IGNORE_MEMCMP;
259
ret = sa_equal_msg_flags(sa, (struct sockaddr *)&ether, msg, sizeof(msg), sa_flags);
260
RTSOCK_ATF_REQUIRE_MSG(rtm, ret != 0, "GATEWAY sa diff: %s", msg);
261
262
/*
263
* TODO: Currently kernel code does not set sdl_type, contrary to IPv6.
264
*/
265
}
266
267
RTM_DECLARE_ROOT_TEST(rtm_del_v6_ll_lle_success, "Tests removal of link-local IPv6 ND entry");
268
ATF_TC_BODY(rtm_del_v6_ll_lle_success, tc)
269
{
270
DECLARE_TEST_VARS;
271
272
c = presetup_ipv6(tc);
273
274
char str_buf[128];
275
276
struct sockaddr_in6 sin6;
277
/* Interface here is optional. XXX: verify kernel side. */
278
char *v6addr = "fe80::4242:4242";
279
snprintf(str_buf, sizeof(str_buf), "%s%%%s", v6addr, c->ifname);
280
sa_convert_str_to_sa(str_buf, (struct sockaddr *)&sin6);
281
282
struct sockaddr_dl ether;
283
snprintf(str_buf, sizeof(str_buf), "%s%%%s", c->remote_lladdr, c->ifname);
284
sa_convert_str_to_sa(str_buf, (struct sockaddr *)&ether);
285
286
prepare_route_message(rtm, RTM_ADD, (struct sockaddr *)&sin6, (struct sockaddr *)&ether);
287
288
rtsock_send_rtm(c->rtsock_fd, rtm);
289
290
/* Successfully added an entry, let's try to remove it. */
291
prepare_route_message(rtm, RTM_DELETE, (struct sockaddr *)&sin6, (struct sockaddr *)&ether);
292
293
rtsock_send_rtm(c->rtsock_fd, rtm);
294
295
rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq);
296
297
RTSOCK_ATF_REQUIRE_MSG(rtm, rtm->rtm_type == RTM_DELETE, "rtm_type is not delete");
298
299
sa = rtsock_find_rtm_sa(rtm, RTA_DST);
300
ret = sa_equal_msg(sa, (struct sockaddr *)&sin6, msg, sizeof(msg));
301
RTSOCK_ATF_REQUIRE_MSG(rtm, ret != 0, "DST sa diff: %s", msg);
302
303
sa = rtsock_find_rtm_sa(rtm, RTA_GATEWAY);
304
int sa_flags = SA_F_IGNORE_IFNAME | SA_F_IGNORE_IFTYPE | SA_F_IGNORE_MEMCMP;
305
ret = sa_equal_msg_flags(sa, (struct sockaddr *)&ether, msg, sizeof(msg), sa_flags);
306
RTSOCK_ATF_REQUIRE_MSG(rtm, ret != 0, "GATEWAY sa diff: %s", msg);
307
308
/*
309
* TODO: Currently kernel code does not set sdl_type on delete.
310
*/
311
}
312
313
RTM_DECLARE_ROOT_TEST(rtm_del_v6_gu_lle_success, "Tests removal of global IPv6 ND entry");
314
ATF_TC_BODY(rtm_del_v6_gu_lle_success, tc)
315
{
316
DECLARE_TEST_VARS;
317
318
c = presetup_ipv6(tc);
319
320
char str_buf[128];
321
322
struct sockaddr_in6 sin6;
323
sin6 = c->net6;
324
#define _s6_addr32 __u6_addr.__u6_addr32
325
sin6.sin6_addr._s6_addr32[3] = htonl(0x42424242);
326
#undef _s6_addr32
327
328
struct sockaddr_dl ether;
329
snprintf(str_buf, sizeof(str_buf), "%s%%%s", c->remote_lladdr, c->ifname);
330
sa_convert_str_to_sa(str_buf, (struct sockaddr *)&ether);
331
332
prepare_route_message(rtm, RTM_ADD, (struct sockaddr *)&sin6, (struct sockaddr *)&ether);
333
334
len = rtsock_send_rtm(c->rtsock_fd, rtm);
335
336
/* Successfully added an entry, let's try to remove it. */
337
prepare_route_message(rtm, RTM_DELETE, (struct sockaddr *)&sin6, (struct sockaddr *)&ether);
338
339
rtsock_send_rtm(c->rtsock_fd, rtm);
340
341
rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq);
342
343
RTSOCK_ATF_REQUIRE_MSG(rtm, rtm->rtm_type == RTM_DELETE, "rtm_type is not delete");
344
345
sa = rtsock_find_rtm_sa(rtm, RTA_DST);
346
ret = sa_equal_msg(sa, (struct sockaddr *)&sin6, msg, sizeof(msg));
347
RTSOCK_ATF_REQUIRE_MSG(rtm, ret != 0, "DST sa diff: %s", msg);
348
349
sa = rtsock_find_rtm_sa(rtm, RTA_GATEWAY);
350
int sa_flags = SA_F_IGNORE_IFNAME | SA_F_IGNORE_IFTYPE | SA_F_IGNORE_MEMCMP;
351
ret = sa_equal_msg_flags(sa, (struct sockaddr *)&ether, msg, sizeof(msg), sa_flags);
352
RTSOCK_ATF_REQUIRE_MSG(rtm, ret != 0, "GATEWAY sa diff: %s", msg);
353
354
/*
355
* TODO: Currently kernel code does not set sdl_type on delete.
356
*/
357
}
358
359
RTM_DECLARE_ROOT_TEST(rtm_del_v4_gu_lle_success, "Tests removal of IPv4 ARP entry");
360
ATF_TC_BODY(rtm_del_v4_gu_lle_success, tc)
361
{
362
DECLARE_TEST_VARS;
363
364
c = presetup_ipv4(tc);
365
366
char str_buf[128];
367
368
struct sockaddr_in sin;
369
sin = c->addr4;
370
/* Use the next IPv4 address after self */
371
sin.sin_addr.s_addr = htonl(ntohl(sin.sin_addr.s_addr) + 1);
372
373
struct sockaddr_dl ether;
374
snprintf(str_buf, sizeof(str_buf), "%s%%%s", c->remote_lladdr, c->ifname);
375
sa_convert_str_to_sa(str_buf, (struct sockaddr *)&ether);
376
377
prepare_route_message(rtm, RTM_ADD, (struct sockaddr *)&sin, (struct sockaddr *)&ether);
378
379
rtsock_send_rtm(c->rtsock_fd, rtm);
380
381
/* We successfully added an entry, let's try to remove it. */
382
prepare_route_message(rtm, RTM_DELETE, (struct sockaddr *)&sin, (struct sockaddr *)&ether);
383
384
rtsock_send_rtm(c->rtsock_fd, rtm);
385
386
rtm = rtsock_read_rtm_reply(c->rtsock_fd, buffer, sizeof(buffer), rtm->rtm_seq);
387
388
RTSOCK_ATF_REQUIRE_MSG(rtm, rtm->rtm_type == RTM_DELETE, "rtm_type is not delete");
389
390
sa = rtsock_find_rtm_sa(rtm, RTA_DST);
391
ret = sa_equal_msg(sa, (struct sockaddr *)&sin, msg, sizeof(msg));
392
RTSOCK_ATF_REQUIRE_MSG(rtm, ret != 0, "DST sa diff: %s", msg);
393
394
sa = rtsock_find_rtm_sa(rtm, RTA_GATEWAY);
395
int sa_flags = SA_F_IGNORE_IFNAME | SA_F_IGNORE_IFTYPE | SA_F_IGNORE_MEMCMP;
396
ret = sa_equal_msg_flags(sa, (struct sockaddr *)&ether, msg, sizeof(msg), sa_flags);
397
RTSOCK_ATF_REQUIRE_MSG(rtm, ret != 0, "GATEWAY sa diff: %s", msg);
398
399
/*
400
* TODO: Currently kernel code does not set sdl_type, contrary to IPv6.
401
*/
402
}
403
404
ATF_TP_ADD_TCS(tp)
405
{
406
ATF_TP_ADD_TC(tp, rtm_add_v6_ll_lle_success);
407
ATF_TP_ADD_TC(tp, rtm_add_v6_gu_lle_success);
408
ATF_TP_ADD_TC(tp, rtm_add_v4_gu_lle_success);
409
ATF_TP_ADD_TC(tp, rtm_del_v6_ll_lle_success);
410
ATF_TP_ADD_TC(tp, rtm_del_v6_gu_lle_success);
411
ATF_TP_ADD_TC(tp, rtm_del_v4_gu_lle_success);
412
413
return (atf_no_error());
414
}
415
416
417
418