1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
3 Copyright © 2014 Intel Corporation. All rights reserved.
6 #include <netinet/icmp6.h>
12 #include "alloc-util.h"
13 #include "hexdecoct.h"
14 #include "icmp6-util.h"
15 #include "socket-util.h"
17 #include "ndisc-internal.h"
20 static struct ether_addr mac_addr
= {
21 .ether_addr_octet
= {'A', 'B', 'C', '1', '2', '3'}
24 static bool verbose
= false;
25 static int test_fd
[2];
26 static sd_ndisc
*test_timeout_nd
;
28 typedef int (*send_ra_t
)(uint8_t flags
);
29 static send_ra_t send_ra_function
;
31 static void router_dump(sd_ndisc_router
*rt
) {
43 assert_se(sd_ndisc_router_get_address(rt
, &addr
) == -ENODATA
);
45 assert_se(sd_ndisc_router_get_timestamp(rt
, CLOCK_REALTIME
, &t
) >= 0);
46 log_info("Timestamp: %s", FORMAT_TIMESTAMP(t
));
48 assert_se(sd_ndisc_router_get_timestamp(rt
, CLOCK_MONOTONIC
, &t
) >= 0);
49 log_info("Monotonic: %" PRIu64
, t
);
51 if (sd_ndisc_router_get_hop_limit(rt
, &hop_limit
) < 0)
52 log_info("No hop limit set");
54 log_info("Hop limit: %u", hop_limit
);
56 assert_se(sd_ndisc_router_get_flags(rt
, &flags
) >= 0);
57 log_info("Flags: <%s|%s>",
58 flags
& ND_RA_FLAG_OTHER
? "OTHER" : "",
59 flags
& ND_RA_FLAG_MANAGED
? "MANAGED" : "");
61 assert_se(sd_ndisc_router_get_preference(rt
, &preference
) >= 0);
62 log_info("Preference: %s",
63 preference
== SD_NDISC_PREFERENCE_LOW
? "low" :
64 preference
== SD_NDISC_PREFERENCE_HIGH
? "high" : "medium");
66 assert_se(sd_ndisc_router_get_lifetime(rt
, &lifetime
) >= 0);
67 log_info("Lifetime: %" PRIu16
, lifetime
);
69 if (sd_ndisc_router_get_mtu(rt
, &mtu
) < 0)
70 log_info("No MTU set");
72 log_info("MTU: %" PRIu32
, mtu
);
74 r
= sd_ndisc_router_option_rewind(rt
);
83 assert_se(sd_ndisc_router_option_get_type(rt
, &type
) >= 0);
85 log_info(">> Option %u", type
);
89 case SD_NDISC_OPTION_SOURCE_LL_ADDRESS
:
90 case SD_NDISC_OPTION_TARGET_LL_ADDRESS
: {
91 _cleanup_free_
char *c
= NULL
;
95 assert_se(sd_ndisc_router_option_get_raw(rt
, &p
, &n
) >= 0);
97 assert_se(c
= hexmem((uint8_t*) p
+ 2, n
- 2));
99 log_info("Address: %s", c
);
103 case SD_NDISC_OPTION_PREFIX_INFORMATION
: {
104 uint32_t lifetime_valid
, lifetime_preferred
;
108 char buff
[INET6_ADDRSTRLEN
];
110 assert_se(sd_ndisc_router_prefix_get_valid_lifetime(rt
, &lifetime_valid
) >= 0);
111 log_info("Valid Lifetime: %" PRIu32
, lifetime_valid
);
113 assert_se(sd_ndisc_router_prefix_get_preferred_lifetime(rt
, &lifetime_preferred
) >= 0);
114 log_info("Preferred Lifetime: %" PRIu32
, lifetime_preferred
);
116 assert_se(sd_ndisc_router_prefix_get_flags(rt
, &pfl
) >= 0);
117 log_info("Flags: <%s|%s>",
118 pfl
& ND_OPT_PI_FLAG_ONLINK
? "ONLINK" : "",
119 pfl
& ND_OPT_PI_FLAG_AUTO
? "AUTO" : "");
121 assert_se(sd_ndisc_router_prefix_get_prefixlen(rt
, &prefix_len
) >= 0);
122 log_info("Prefix Length: %u", prefix_len
);
124 assert_se(sd_ndisc_router_prefix_get_address(rt
, &a
) >= 0);
125 log_info("Prefix: %s", inet_ntop(AF_INET6
, &a
, buff
, sizeof(buff
)));
130 case SD_NDISC_OPTION_RDNSS
: {
131 const struct in6_addr
*a
;
135 n
= sd_ndisc_router_rdnss_get_addresses(rt
, &a
);
138 for (i
= 0; i
< n
; i
++) {
139 char buff
[INET6_ADDRSTRLEN
];
140 log_info("DNS: %s", inet_ntop(AF_INET6
, a
+ i
, buff
, sizeof(buff
)));
143 assert_se(sd_ndisc_router_rdnss_get_lifetime(rt
, <
) >= 0);
144 log_info("Lifetime: %" PRIu32
, lt
);
148 case SD_NDISC_OPTION_DNSSL
: {
149 _cleanup_strv_free_
char **l
= NULL
;
153 n
= sd_ndisc_router_dnssl_get_domains(rt
, &l
);
156 for (i
= 0; i
< n
; i
++)
157 log_info("Domain: %s", l
[i
]);
159 assert_se(sd_ndisc_router_dnssl_get_lifetime(rt
, <
) >= 0);
160 log_info("Lifetime: %" PRIu32
, lt
);
164 r
= sd_ndisc_router_option_next(rt
);
168 int icmp6_bind_router_solicitation(int ifindex
) {
169 assert_se(ifindex
== 42);
171 if (socketpair(AF_UNIX
, SOCK_DGRAM
| SOCK_CLOEXEC
| SOCK_NONBLOCK
, 0, test_fd
) < 0)
177 int icmp6_bind_router_advertisement(int ifindex
) {
181 int icmp6_receive(int fd
, void *iov_base
, size_t iov_len
,
182 struct in6_addr
*dst
, triple_timestamp
*timestamp
) {
183 assert_se(read (fd
, iov_base
, iov_len
) == (ssize_t
)iov_len
);
186 triple_timestamp_get(timestamp
);
191 static int send_ra(uint8_t flags
) {
192 uint8_t advertisement
[] = {
193 0x86, 0x00, 0xde, 0x83, 0x40, 0xc0, 0x00, 0xb4,
194 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
195 0x03, 0x04, 0x40, 0xc0, 0x00, 0x00, 0x01, 0xf4,
196 0x00, 0x00, 0x01, 0xb8, 0x00, 0x00, 0x00, 0x00,
197 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef,
198 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
199 0x19, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c,
200 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef,
201 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
202 0x1f, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c,
203 0x03, 0x6c, 0x61, 0x62, 0x05, 0x69, 0x6e, 0x74,
204 0x72, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
205 0x01, 0x01, 0x78, 0x2b, 0xcb, 0xb3, 0x6d, 0x53,
208 advertisement
[5] = flags
;
210 assert_se(write(test_fd
[1], advertisement
, sizeof(advertisement
)) ==
211 sizeof(advertisement
));
214 printf(" sent RA with flag 0x%02x\n", flags
);
219 int icmp6_send_router_solicitation(int s
, const struct ether_addr
*ether_addr
) {
220 if (!send_ra_function
)
223 return send_ra_function(0);
226 static void test_callback(sd_ndisc
*nd
, sd_ndisc_event_t event
, sd_ndisc_router
*rt
, void *userdata
) {
227 sd_event
*e
= userdata
;
228 static unsigned idx
= 0;
229 uint64_t flags_array
[] = {
240 if (event
!= SD_NDISC_EVENT_ROUTER
)
245 assert_se(sd_ndisc_router_get_flags(rt
, &flags
) >= 0);
246 assert_se(flags
== flags_array
[idx
]);
250 printf(" got event 0x%02" PRIx64
"\n", flags
);
252 if (idx
< ELEMENTSOF(flags_array
)) {
253 send_ra(flags_array
[idx
]);
264 send_ra_function
= send_ra
;
266 assert_se(sd_event_new(&e
) >= 0);
268 assert_se(sd_ndisc_new(&nd
) >= 0);
271 assert_se(sd_ndisc_attach_event(nd
, e
, 0) >= 0);
273 assert_se(sd_ndisc_set_ifindex(nd
, 42) >= 0);
274 assert_se(sd_ndisc_set_mac(nd
, &mac_addr
) >= 0);
275 assert_se(sd_ndisc_set_callback(nd
, test_callback
, e
) >= 0);
277 assert_se(sd_event_add_time_relative(e
, NULL
, clock_boottime_or_monotonic(),
278 30 * USEC_PER_SEC
, 0,
279 NULL
, INT_TO_PTR(-ETIMEDOUT
)) >= 0);
281 assert_se(sd_ndisc_stop(nd
) >= 0);
282 assert_se(sd_ndisc_start(nd
) >= 0);
283 assert_se(sd_ndisc_start(nd
) >= 0);
284 assert_se(sd_ndisc_stop(nd
) >= 0);
286 assert_se(sd_ndisc_start(nd
) >= 0);
288 assert_se(sd_event_loop(e
) >= 0);
290 nd
= sd_ndisc_unref(nd
);
298 static int test_timeout_value(uint8_t flags
) {
299 static int count
= 0;
300 static usec_t last
= 0;
301 sd_ndisc
*nd
= test_timeout_nd
;
305 assert_se(nd
->event
);
308 sd_event_exit(nd
->event
, 0);
311 /* initial RT = IRT + RAND*IRT */
312 min
= NDISC_ROUTER_SOLICITATION_INTERVAL
-
313 NDISC_ROUTER_SOLICITATION_INTERVAL
/ 10;
314 max
= NDISC_ROUTER_SOLICITATION_INTERVAL
+
315 NDISC_ROUTER_SOLICITATION_INTERVAL
/ 10;
317 /* next RT = 2*RTprev + RAND*RTprev */
318 min
= 2 * last
- last
/ 10;
319 max
= 2 * last
+ last
/ 10;
323 if (last
* 2 > NDISC_MAX_ROUTER_SOLICITATION_INTERVAL
) {
324 min
= NDISC_MAX_ROUTER_SOLICITATION_INTERVAL
-
325 NDISC_MAX_ROUTER_SOLICITATION_INTERVAL
/ 10;
326 max
= NDISC_MAX_ROUTER_SOLICITATION_INTERVAL
+
327 NDISC_MAX_ROUTER_SOLICITATION_INTERVAL
/ 10;
330 log_info("backoff timeout interval %2d %s%s <= %s <= %s",
332 last
* 2 > NDISC_MAX_ROUTER_SOLICITATION_INTERVAL
? "(max) ": "",
333 FORMAT_TIMESPAN(min
, USEC_PER_MSEC
),
334 FORMAT_TIMESPAN(nd
->retransmit_time
, USEC_PER_MSEC
),
335 FORMAT_TIMESPAN(max
, USEC_PER_MSEC
));
337 assert_se(min
<= nd
->retransmit_time
);
338 assert_se(max
>= nd
->retransmit_time
);
340 last
= nd
->retransmit_time
;
342 assert_se(sd_event_source_set_time(nd
->timeout_event_source
, 0) >= 0);
351 send_ra_function
= test_timeout_value
;
353 assert_se(sd_event_new(&e
) >= 0);
355 assert_se(sd_ndisc_new(&nd
) >= 0);
358 test_timeout_nd
= nd
;
360 assert_se(sd_ndisc_attach_event(nd
, e
, 0) >= 0);
362 assert_se(sd_ndisc_set_ifindex(nd
, 42) >= 0);
363 assert_se(sd_ndisc_set_mac(nd
, &mac_addr
) >= 0);
365 assert_se(sd_event_add_time_relative(e
, NULL
, clock_boottime_or_monotonic(),
366 30 * USEC_PER_SEC
, 0,
367 NULL
, INT_TO_PTR(-ETIMEDOUT
)) >= 0);
369 assert_se(sd_ndisc_start(nd
) >= 0);
371 assert_se(sd_event_loop(e
) >= 0);
373 nd
= sd_ndisc_unref(nd
);
378 DEFINE_TEST_MAIN(LOG_DEBUG
);