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"
14 #include "hexdecoct.h"
15 #include "icmp6-util-unix.h"
16 #include "socket-util.h"
18 #include "ndisc-internal.h"
21 static struct ether_addr mac_addr
= {
22 .ether_addr_octet
= {'A', 'B', 'C', '1', '2', '3'}
25 static bool verbose
= false;
26 static sd_ndisc
*test_timeout_nd
;
28 static void router_dump(sd_ndisc_router
*rt
) {
31 usec_t t
, lifetime
, retrans_time
;
40 assert_se(sd_ndisc_router_get_address(rt
, &addr
) >= 0);
41 log_info("Sender: %s", IN6_ADDR_TO_STRING(&addr
));
43 assert_se(sd_ndisc_router_get_timestamp(rt
, CLOCK_REALTIME
, &t
) >= 0);
44 log_info("Timestamp: %s", FORMAT_TIMESTAMP(t
));
46 assert_se(sd_ndisc_router_get_timestamp(rt
, CLOCK_MONOTONIC
, &t
) >= 0);
47 log_info("Monotonic: %" PRIu64
, t
);
49 if (sd_ndisc_router_get_hop_limit(rt
, &hop_limit
) < 0)
50 log_info("No hop limit set");
52 log_info("Hop limit: %u", hop_limit
);
54 assert_se(sd_ndisc_router_get_flags(rt
, &flags
) >= 0);
55 log_info("Flags: <%s|%s>",
56 flags
& ND_RA_FLAG_OTHER
? "OTHER" : "",
57 flags
& ND_RA_FLAG_MANAGED
? "MANAGED" : "");
59 assert_se(sd_ndisc_router_get_preference(rt
, &preference
) >= 0);
60 log_info("Preference: %s",
61 preference
== SD_NDISC_PREFERENCE_LOW
? "low" :
62 preference
== SD_NDISC_PREFERENCE_HIGH
? "high" : "medium");
64 assert_se(sd_ndisc_router_get_lifetime(rt
, &lifetime
) >= 0);
65 assert_se(sd_ndisc_router_get_lifetime_timestamp(rt
, CLOCK_REALTIME
, &t
) >= 0);
66 log_info("Lifetime: %s (%s)", FORMAT_TIMESPAN(lifetime
, USEC_PER_SEC
), FORMAT_TIMESTAMP(t
));
68 assert_se(sd_ndisc_router_get_retransmission_time(rt
, &retrans_time
) >= 0);
69 log_info("Retransmission Time: %s", FORMAT_TIMESPAN(retrans_time
, USEC_PER_SEC
));
71 if (sd_ndisc_router_get_mtu(rt
, &mtu
) < 0)
72 log_info("No MTU set");
74 log_info("MTU: %" PRIu32
, mtu
);
76 r
= sd_ndisc_router_option_rewind(rt
);
85 assert_se(sd_ndisc_router_option_get_type(rt
, &type
) >= 0);
87 log_info(">> Option %u", type
);
91 case SD_NDISC_OPTION_SOURCE_LL_ADDRESS
:
92 case SD_NDISC_OPTION_TARGET_LL_ADDRESS
: {
93 _cleanup_free_
char *c
= NULL
;
97 assert_se(sd_ndisc_router_option_get_raw(rt
, &p
, &n
) >= 0);
99 assert_se(c
= hexmem((uint8_t*) p
+ 2, n
- 2));
101 log_info("Address: %s", c
);
105 case SD_NDISC_OPTION_PREFIX_INFORMATION
: {
110 assert_se(sd_ndisc_router_prefix_get_valid_lifetime(rt
, &lifetime
) >= 0);
111 assert_se(sd_ndisc_router_prefix_get_valid_lifetime_timestamp(rt
, CLOCK_REALTIME
, &t
) >= 0);
112 log_info("Valid Lifetime: %s (%s)", FORMAT_TIMESPAN(lifetime
, USEC_PER_SEC
), FORMAT_TIMESTAMP(t
));
114 assert_se(sd_ndisc_router_prefix_get_preferred_lifetime(rt
, &lifetime
) >= 0);
115 assert_se(sd_ndisc_router_prefix_get_preferred_lifetime_timestamp(rt
, CLOCK_REALTIME
, &t
) >= 0);
116 log_info("Preferred Lifetime: %s (%s)", FORMAT_TIMESPAN(lifetime
, USEC_PER_SEC
), FORMAT_TIMESTAMP(t
));
118 assert_se(sd_ndisc_router_prefix_get_flags(rt
, &pfl
) >= 0);
119 log_info("Flags: <%s|%s>",
120 pfl
& ND_OPT_PI_FLAG_ONLINK
? "ONLINK" : "",
121 pfl
& ND_OPT_PI_FLAG_AUTO
? "AUTO" : "");
123 assert_se(sd_ndisc_router_prefix_get_prefixlen(rt
, &prefix_len
) >= 0);
124 log_info("Prefix Length: %u", prefix_len
);
126 assert_se(sd_ndisc_router_prefix_get_address(rt
, &a
) >= 0);
127 log_info("Prefix: %s", IN6_ADDR_TO_STRING(&a
));
132 case SD_NDISC_OPTION_RDNSS
: {
133 const struct in6_addr
*a
;
136 n
= sd_ndisc_router_rdnss_get_addresses(rt
, &a
);
139 for (i
= 0; i
< n
; i
++)
140 log_info("DNS: %s", IN6_ADDR_TO_STRING(a
+ i
));
142 assert_se(sd_ndisc_router_rdnss_get_lifetime(rt
, &lifetime
) >= 0);
143 assert_se(sd_ndisc_router_rdnss_get_lifetime_timestamp(rt
, CLOCK_REALTIME
, &t
) >= 0);
144 log_info("Lifetime: %s (%s)", FORMAT_TIMESPAN(lifetime
, USEC_PER_SEC
), FORMAT_TIMESTAMP(t
));
148 case SD_NDISC_OPTION_DNSSL
: {
149 _cleanup_strv_free_
char **l
= NULL
;
152 n
= sd_ndisc_router_dnssl_get_domains(rt
, &l
);
155 for (i
= 0; i
< n
; i
++)
156 log_info("Domain: %s", l
[i
]);
158 assert_se(sd_ndisc_router_dnssl_get_lifetime(rt
, &lifetime
) >= 0);
159 assert_se(sd_ndisc_router_dnssl_get_lifetime_timestamp(rt
, CLOCK_REALTIME
, &t
) >= 0);
160 log_info("Lifetime: %s (%s)", FORMAT_TIMESPAN(lifetime
, USEC_PER_SEC
), FORMAT_TIMESTAMP(t
));
164 r
= sd_ndisc_router_option_next(rt
);
168 static int send_ra(uint8_t flags
) {
169 uint8_t advertisement
[] = {
170 0x86, 0x00, 0xde, 0x83, 0x40, 0xc0, 0x00, 0xb4,
171 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
172 0x03, 0x04, 0x40, 0xc0, 0x00, 0x00, 0x01, 0xf4,
173 0x00, 0x00, 0x01, 0xb8, 0x00, 0x00, 0x00, 0x00,
174 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef,
175 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
176 0x19, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c,
177 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef,
178 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
179 0x1f, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c,
180 0x03, 0x6c, 0x61, 0x62, 0x05, 0x69, 0x6e, 0x74,
181 0x72, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
182 0x01, 0x01, 0x78, 0x2b, 0xcb, 0xb3, 0x6d, 0x53,
185 advertisement
[5] = flags
;
187 assert_se(write(test_fd
[1], advertisement
, sizeof(advertisement
)) ==
188 sizeof(advertisement
));
191 printf(" sent RA with flag 0x%02x\n", flags
);
196 static void test_callback(sd_ndisc
*nd
, sd_ndisc_event_t event
, sd_ndisc_router
*rt
, void *userdata
) {
197 sd_event
*e
= userdata
;
198 static unsigned idx
= 0;
199 uint64_t flags_array
[] = {
210 if (event
!= SD_NDISC_EVENT_ROUTER
)
215 assert_se(sd_ndisc_router_get_flags(rt
, &flags
) >= 0);
216 assert_se(flags
== flags_array
[idx
]);
220 printf(" got event 0x%02" PRIx64
"\n", flags
);
222 if (idx
< ELEMENTSOF(flags_array
)) {
223 send_ra(flags_array
[idx
]);
231 _cleanup_(sd_event_unrefp
) sd_event
*e
= NULL
;
232 _cleanup_(sd_ndisc_unrefp
) sd_ndisc
*nd
= NULL
;
234 send_ra_function
= send_ra
;
236 assert_se(sd_event_new(&e
) >= 0);
238 assert_se(sd_ndisc_new(&nd
) >= 0);
241 assert_se(sd_ndisc_attach_event(nd
, e
, 0) >= 0);
243 assert_se(sd_ndisc_set_ifindex(nd
, 42) >= 0);
244 assert_se(sd_ndisc_set_mac(nd
, &mac_addr
) >= 0);
245 assert_se(sd_ndisc_set_callback(nd
, test_callback
, e
) >= 0);
247 assert_se(sd_event_add_time_relative(e
, NULL
, CLOCK_BOOTTIME
,
248 30 * USEC_PER_SEC
, 0,
249 NULL
, INT_TO_PTR(-ETIMEDOUT
)) >= 0);
251 assert_se(sd_ndisc_stop(nd
) >= 0);
252 assert_se(sd_ndisc_start(nd
) >= 0);
253 assert_se(sd_ndisc_start(nd
) >= 0);
254 assert_se(sd_ndisc_stop(nd
) >= 0);
255 test_fd
[1] = safe_close(test_fd
[1]);
257 assert_se(sd_ndisc_start(nd
) >= 0);
259 assert_se(sd_event_loop(e
) >= 0);
261 test_fd
[1] = safe_close(test_fd
[1]);
264 static int test_timeout_value(uint8_t flags
) {
265 static int count
= 0;
266 static usec_t last
= 0;
267 sd_ndisc
*nd
= test_timeout_nd
;
271 assert_se(nd
->event
);
274 sd_event_exit(nd
->event
, 0);
277 /* initial RT = IRT + RAND*IRT */
278 min
= NDISC_ROUTER_SOLICITATION_INTERVAL
-
279 NDISC_ROUTER_SOLICITATION_INTERVAL
/ 10;
280 max
= NDISC_ROUTER_SOLICITATION_INTERVAL
+
281 NDISC_ROUTER_SOLICITATION_INTERVAL
/ 10;
283 /* next RT = 2*RTprev + RAND*RTprev */
284 min
= 2 * last
- last
/ 10;
285 max
= 2 * last
+ last
/ 10;
289 if (last
* 2 > NDISC_MAX_ROUTER_SOLICITATION_INTERVAL
) {
290 min
= NDISC_MAX_ROUTER_SOLICITATION_INTERVAL
-
291 NDISC_MAX_ROUTER_SOLICITATION_INTERVAL
/ 10;
292 max
= NDISC_MAX_ROUTER_SOLICITATION_INTERVAL
+
293 NDISC_MAX_ROUTER_SOLICITATION_INTERVAL
/ 10;
296 log_info("backoff timeout interval %2d %s%s <= %s <= %s",
298 last
* 2 > NDISC_MAX_ROUTER_SOLICITATION_INTERVAL
? "(max) ": "",
299 FORMAT_TIMESPAN(min
, USEC_PER_MSEC
),
300 FORMAT_TIMESPAN(nd
->retransmit_time
, USEC_PER_MSEC
),
301 FORMAT_TIMESPAN(max
, USEC_PER_MSEC
));
303 assert_se(min
<= nd
->retransmit_time
);
304 assert_se(max
>= nd
->retransmit_time
);
306 last
= nd
->retransmit_time
;
308 assert_se(sd_event_source_set_time(nd
->timeout_event_source
, 0) >= 0);
314 _cleanup_(sd_event_unrefp
) sd_event
*e
= NULL
;
315 _cleanup_(sd_ndisc_unrefp
) sd_ndisc
*nd
= NULL
;
317 send_ra_function
= test_timeout_value
;
319 assert_se(sd_event_new(&e
) >= 0);
321 assert_se(sd_ndisc_new(&nd
) >= 0);
324 test_timeout_nd
= nd
;
326 assert_se(sd_ndisc_attach_event(nd
, e
, 0) >= 0);
328 assert_se(sd_ndisc_set_ifindex(nd
, 42) >= 0);
329 assert_se(sd_ndisc_set_mac(nd
, &mac_addr
) >= 0);
331 assert_se(sd_event_add_time_relative(e
, NULL
, CLOCK_BOOTTIME
,
332 30 * USEC_PER_SEC
, 0,
333 NULL
, INT_TO_PTR(-ETIMEDOUT
)) >= 0);
335 assert_se(sd_ndisc_start(nd
) >= 0);
337 assert_se(sd_event_loop(e
) >= 0);
339 test_fd
[1] = safe_close(test_fd
[1]);
342 DEFINE_TEST_MAIN(LOG_DEBUG
);