1 /* SPDX-License-Identifier: LGPL-2.1+ */
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 sd_event_source
*test_hangcheck
;
26 static int test_fd
[2];
27 static sd_ndisc
*test_timeout_nd
;
29 typedef int (*send_ra_t
)(uint8_t flags
);
30 static send_ra_t send_ra_function
;
32 static void router_dump(sd_ndisc_router
*rt
) {
34 char buf
[FORMAT_TIMESTAMP_MAX
];
45 assert_se(sd_ndisc_router_get_address(rt
, &addr
) == -ENODATA
);
47 assert_se(sd_ndisc_router_get_timestamp(rt
, CLOCK_REALTIME
, &t
) >= 0);
48 log_info("Timestamp: %s", format_timestamp(buf
, sizeof(buf
), t
));
50 assert_se(sd_ndisc_router_get_timestamp(rt
, CLOCK_MONOTONIC
, &t
) >= 0);
51 log_info("Monotonic: %" PRIu64
, t
);
53 if (sd_ndisc_router_get_hop_limit(rt
, &hop_limit
) < 0)
54 log_info("No hop limit set");
56 log_info("Hop limit: %u", hop_limit
);
58 assert_se(sd_ndisc_router_get_flags(rt
, &flags
) >= 0);
59 log_info("Flags: <%s|%s>",
60 flags
& ND_RA_FLAG_OTHER
? "OTHER" : "",
61 flags
& ND_RA_FLAG_MANAGED
? "MANAGED" : "");
63 assert_se(sd_ndisc_router_get_preference(rt
, &preference
) >= 0);
64 log_info("Preference: %s",
65 preference
== SD_NDISC_PREFERENCE_LOW
? "low" :
66 preference
== SD_NDISC_PREFERENCE_HIGH
? "high" : "medium");
68 assert_se(sd_ndisc_router_get_lifetime(rt
, &lifetime
) >= 0);
69 log_info("Lifetime: %" PRIu16
, lifetime
);
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
: {
106 uint32_t lifetime_valid
, lifetime_preferred
;
110 char buff
[INET6_ADDRSTRLEN
];
112 assert_se(sd_ndisc_router_prefix_get_valid_lifetime(rt
, &lifetime_valid
) >= 0);
113 log_info("Valid Lifetime: %" PRIu32
, lifetime_valid
);
115 assert_se(sd_ndisc_router_prefix_get_preferred_lifetime(rt
, &lifetime_preferred
) >= 0);
116 log_info("Preferred Lifetime: %" PRIu32
, lifetime_preferred
);
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", inet_ntop(AF_INET6
, &a
, buff
, sizeof(buff
)));
132 case SD_NDISC_OPTION_RDNSS
: {
133 const struct in6_addr
*a
;
137 n
= sd_ndisc_router_rdnss_get_addresses(rt
, &a
);
140 for (i
= 0; i
< n
; i
++) {
141 char buff
[INET6_ADDRSTRLEN
];
142 log_info("DNS: %s", inet_ntop(AF_INET6
, a
+ i
, buff
, sizeof(buff
)));
145 assert_se(sd_ndisc_router_rdnss_get_lifetime(rt
, <
) >= 0);
146 log_info("Lifetime: %" PRIu32
, lt
);
150 case SD_NDISC_OPTION_DNSSL
: {
151 _cleanup_strv_free_
char **l
= NULL
;
155 n
= sd_ndisc_router_dnssl_get_domains(rt
, &l
);
158 for (i
= 0; i
< n
; i
++)
159 log_info("Domain: %s", l
[i
]);
161 assert_se(sd_ndisc_router_dnssl_get_lifetime(rt
, <
) >= 0);
162 log_info("Lifetime: %" PRIu32
, lt
);
166 r
= sd_ndisc_router_option_next(rt
);
170 static int test_rs_hangcheck(sd_event_source
*s
, uint64_t usec
,
177 int icmp6_bind_router_solicitation(int index
) {
178 assert_se(index
== 42);
180 if (socketpair(AF_UNIX
, SOCK_DGRAM
| SOCK_CLOEXEC
| SOCK_NONBLOCK
, 0, test_fd
) < 0)
186 int icmp6_bind_router_advertisement(int index
) {
191 int icmp6_receive(int fd
, void *iov_base
, size_t iov_len
,
192 struct in6_addr
*dst
, triple_timestamp
*timestamp
) {
193 assert_se(read (fd
, iov_base
, iov_len
) == (ssize_t
)iov_len
);
196 triple_timestamp_get(timestamp
);
201 static int send_ra(uint8_t flags
) {
202 uint8_t advertisement
[] = {
203 0x86, 0x00, 0xde, 0x83, 0x40, 0xc0, 0x00, 0xb4,
204 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
205 0x03, 0x04, 0x40, 0xc0, 0x00, 0x00, 0x01, 0xf4,
206 0x00, 0x00, 0x01, 0xb8, 0x00, 0x00, 0x00, 0x00,
207 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef,
208 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
209 0x19, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c,
210 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef,
211 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
212 0x1f, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c,
213 0x03, 0x6c, 0x61, 0x62, 0x05, 0x69, 0x6e, 0x74,
214 0x72, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
215 0x01, 0x01, 0x78, 0x2b, 0xcb, 0xb3, 0x6d, 0x53,
218 advertisement
[5] = flags
;
220 assert_se(write(test_fd
[1], advertisement
, sizeof(advertisement
)) ==
221 sizeof(advertisement
));
224 printf(" sent RA with flag 0x%02x\n", flags
);
229 int icmp6_send_router_solicitation(int s
, const struct ether_addr
*ether_addr
) {
230 if (!send_ra_function
)
233 return send_ra_function(0);
236 static void test_callback(sd_ndisc
*nd
, sd_ndisc_event event
, sd_ndisc_router
*rt
, void *userdata
) {
237 sd_event
*e
= userdata
;
238 static unsigned idx
= 0;
239 uint64_t flags_array
[] = {
251 if (event
!= SD_NDISC_EVENT_ROUTER
)
256 assert_se(sd_ndisc_router_get_flags(rt
, &flags
) >= 0);
257 assert_se(flags
== flags_array
[idx
]);
261 printf(" got event 0x%02" PRIx64
"\n", flags
);
263 if (idx
< ELEMENTSOF(flags_array
)) {
264 send_ra(flags_array
[idx
]);
268 assert_se(sd_ndisc_get_mtu(nd
, &mtu
) == -ENODATA
);
273 static void test_rs(void) {
276 usec_t time_now
= now(clock_boottime_or_monotonic());
279 printf("* %s\n", __FUNCTION__
);
281 send_ra_function
= send_ra
;
283 assert_se(sd_event_new(&e
) >= 0);
285 assert_se(sd_ndisc_new(&nd
) >= 0);
288 assert_se(sd_ndisc_attach_event(nd
, e
, 0) >= 0);
290 assert_se(sd_ndisc_set_ifindex(nd
, 42) >= 0);
291 assert_se(sd_ndisc_set_mac(nd
, &mac_addr
) >= 0);
292 assert_se(sd_ndisc_set_callback(nd
, test_callback
, e
) >= 0);
294 assert_se(sd_event_add_time(e
, &test_hangcheck
, clock_boottime_or_monotonic(),
295 time_now
+ 2 *USEC_PER_SEC
, 0,
296 test_rs_hangcheck
, NULL
) >= 0);
298 assert_se(sd_ndisc_stop(nd
) >= 0);
299 assert_se(sd_ndisc_start(nd
) >= 0);
300 assert_se(sd_ndisc_stop(nd
) >= 0);
302 assert_se(sd_ndisc_start(nd
) >= 0);
306 test_hangcheck
= sd_event_source_unref(test_hangcheck
);
308 nd
= sd_ndisc_unref(nd
);
316 static int test_timeout_value(uint8_t flags
) {
317 static int count
= 0;
318 static usec_t last
= 0;
319 sd_ndisc
*nd
= test_timeout_nd
;
321 char time_string_min
[FORMAT_TIMESPAN_MAX
];
322 char time_string_nd
[FORMAT_TIMESPAN_MAX
];
323 char time_string_max
[FORMAT_TIMESPAN_MAX
];
326 assert_se(nd
->event
);
329 sd_event_exit(nd
->event
, 0);
332 /* initial RT = IRT + RAND*IRT */
333 min
= NDISC_ROUTER_SOLICITATION_INTERVAL
-
334 NDISC_ROUTER_SOLICITATION_INTERVAL
/ 10;
335 max
= NDISC_ROUTER_SOLICITATION_INTERVAL
+
336 NDISC_ROUTER_SOLICITATION_INTERVAL
/ 10;
338 /* next RT = 2*RTprev + RAND*RTprev */
339 min
= 2 * last
- last
/ 10;
340 max
= 2 * last
+ last
/ 10;
344 if (last
* 2 > NDISC_MAX_ROUTER_SOLICITATION_INTERVAL
) {
345 min
= NDISC_MAX_ROUTER_SOLICITATION_INTERVAL
-
346 NDISC_MAX_ROUTER_SOLICITATION_INTERVAL
/ 10;
347 max
= NDISC_MAX_ROUTER_SOLICITATION_INTERVAL
+
348 NDISC_MAX_ROUTER_SOLICITATION_INTERVAL
/ 10;
351 format_timespan(time_string_min
, FORMAT_TIMESPAN_MAX
,
353 format_timespan(time_string_nd
, FORMAT_TIMESPAN_MAX
,
354 nd
->retransmit_time
, USEC_PER_MSEC
);
355 format_timespan(time_string_max
, FORMAT_TIMESPAN_MAX
,
358 log_info("backoff timeout interval %2d %s%s <= %s <= %s",
360 (last
* 2 > NDISC_MAX_ROUTER_SOLICITATION_INTERVAL
)? "(max) ": "",
361 time_string_min
, time_string_nd
, time_string_max
);
363 assert_se(min
<= nd
->retransmit_time
);
364 assert_se(max
>= nd
->retransmit_time
);
366 last
= nd
->retransmit_time
;
368 assert_se(sd_event_source_set_time(nd
->timeout_event_source
, 0) >= 0);
373 static void test_timeout(void) {
376 usec_t time_now
= now(clock_boottime_or_monotonic());
379 printf("* %s\n", __FUNCTION__
);
381 send_ra_function
= test_timeout_value
;
383 assert_se(sd_event_new(&e
) >= 0);
385 assert_se(sd_ndisc_new(&nd
) >= 0);
388 test_timeout_nd
= nd
;
390 assert_se(sd_ndisc_attach_event(nd
, e
, 0) >= 0);
392 assert_se(sd_ndisc_set_ifindex(nd
, 42) >= 0);
393 assert_se(sd_ndisc_set_mac(nd
, &mac_addr
) >= 0);
395 assert_se(sd_event_add_time(e
, &test_hangcheck
, clock_boottime_or_monotonic(),
396 time_now
+ 2U * USEC_PER_SEC
, 0,
397 test_rs_hangcheck
, NULL
) >= 0);
399 assert_se(sd_ndisc_start(nd
) >= 0);
403 test_hangcheck
= sd_event_source_unref(test_hangcheck
);
405 nd
= sd_ndisc_unref(nd
);
410 int main(int argc
, char *argv
[]) {
412 test_setup_logging(LOG_DEBUG
);