]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libsystemd-network/test-ndisc-rs.c
tree-wide: make use of new relative time events in sd-event.h
[thirdparty/systemd.git] / src / libsystemd-network / test-ndisc-rs.c
CommitLineData
53e1b683 1/* SPDX-License-Identifier: LGPL-2.1+ */
f20a35cc 2/***
810adae9 3 Copyright © 2014 Intel Corporation. All rights reserved.
f20a35cc
PF
4***/
5
6#include <netinet/icmp6.h>
1e7a0e21 7#include <arpa/inet.h>
ca78ad1d 8#include <unistd.h>
f20a35cc 9
07630cea 10#include "sd-ndisc.h"
f20a35cc 11
1e7a0e21
LP
12#include "alloc-util.h"
13#include "hexdecoct.h"
940367a0 14#include "icmp6-util.h"
07630cea 15#include "socket-util.h"
1e7a0e21 16#include "strv.h"
5a67ed24 17#include "ndisc-internal.h"
6d7c4033 18#include "tests.h"
f20a35cc
PF
19
20static struct ether_addr mac_addr = {
21 .ether_addr_octet = {'A', 'B', 'C', '1', '2', '3'}
22};
23
24static bool verbose = false;
25static sd_event_source *test_hangcheck;
26static int test_fd[2];
5a67ed24 27static sd_ndisc *test_timeout_nd;
f20a35cc 28
99af546d
PF
29typedef int (*send_ra_t)(uint8_t flags);
30static send_ra_t send_ra_function;
31
1e7a0e21
LP
32static void router_dump(sd_ndisc_router *rt) {
33 struct in6_addr addr;
34 char buf[FORMAT_TIMESTAMP_MAX];
35 uint8_t hop_limit;
36 uint64_t t, flags;
37 uint32_t mtu;
38 uint16_t lifetime;
39 unsigned preference;
40 int r;
41
42 assert_se(rt);
43
44 log_info("--");
45 assert_se(sd_ndisc_router_get_address(rt, &addr) == -ENODATA);
46
47 assert_se(sd_ndisc_router_get_timestamp(rt, CLOCK_REALTIME, &t) >= 0);
48 log_info("Timestamp: %s", format_timestamp(buf, sizeof(buf), t));
49
50 assert_se(sd_ndisc_router_get_timestamp(rt, CLOCK_MONOTONIC, &t) >= 0);
51 log_info("Monotonic: %" PRIu64, t);
52
53 if (sd_ndisc_router_get_hop_limit(rt, &hop_limit) < 0)
54 log_info("No hop limit set");
55 else
56 log_info("Hop limit: %u", hop_limit);
57
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" : "");
62
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");
67
68 assert_se(sd_ndisc_router_get_lifetime(rt, &lifetime) >= 0);
69 log_info("Lifetime: %" PRIu16, lifetime);
70
71 if (sd_ndisc_router_get_mtu(rt, &mtu) < 0)
72 log_info("No MTU set");
73 else
74 log_info("MTU: %" PRIu32, mtu);
75
76 r = sd_ndisc_router_option_rewind(rt);
77 for (;;) {
78 uint8_t type;
79
80 assert_se(r >= 0);
81
82 if (r == 0)
83 break;
84
85 assert_se(sd_ndisc_router_option_get_type(rt, &type) >= 0);
86
87 log_info(">> Option %u", type);
88
89 switch (type) {
90
91 case SD_NDISC_OPTION_SOURCE_LL_ADDRESS:
92 case SD_NDISC_OPTION_TARGET_LL_ADDRESS: {
93 _cleanup_free_ char *c = NULL;
94 const void *p;
95 size_t n;
96
97 assert_se(sd_ndisc_router_option_get_raw(rt, &p, &n) >= 0);
98 assert_se(n > 2);
99 assert_se(c = hexmem((uint8_t*) p + 2, n - 2));
100
101 log_info("Address: %s", c);
102 break;
103 }
104
105 case SD_NDISC_OPTION_PREFIX_INFORMATION: {
106 uint32_t lifetime_valid, lifetime_preferred;
107 unsigned prefix_len;
108 uint8_t pfl;
109 struct in6_addr a;
110 char buff[INET6_ADDRSTRLEN];
111
112 assert_se(sd_ndisc_router_prefix_get_valid_lifetime(rt, &lifetime_valid) >= 0);
113 log_info("Valid Lifetime: %" PRIu32, lifetime_valid);
114
115 assert_se(sd_ndisc_router_prefix_get_preferred_lifetime(rt, &lifetime_preferred) >= 0);
116 log_info("Preferred Lifetime: %" PRIu32, lifetime_preferred);
117
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" : "");
122
123 assert_se(sd_ndisc_router_prefix_get_prefixlen(rt, &prefix_len) >= 0);
124 log_info("Prefix Length: %u", prefix_len);
125
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)));
128
129 break;
130 }
131
132 case SD_NDISC_OPTION_RDNSS: {
133 const struct in6_addr *a;
134 uint32_t lt;
135 int n, i;
136
137 n = sd_ndisc_router_rdnss_get_addresses(rt, &a);
138 assert_se(n > 0);
139
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)));
143 }
144
145 assert_se(sd_ndisc_router_rdnss_get_lifetime(rt, &lt) >= 0);
146 log_info("Lifetime: %" PRIu32, lt);
147 break;
148 }
149
150 case SD_NDISC_OPTION_DNSSL: {
151 _cleanup_strv_free_ char **l = NULL;
152 uint32_t lt;
153 int n, i;
154
155 n = sd_ndisc_router_dnssl_get_domains(rt, &l);
156 assert_se(n > 0);
157
158 for (i = 0; i < n; i++)
159 log_info("Domain: %s", l[i]);
160
161 assert_se(sd_ndisc_router_dnssl_get_lifetime(rt, &lt) >= 0);
162 log_info("Lifetime: %" PRIu32, lt);
163 break;
164 }}
165
166 r = sd_ndisc_router_option_next(rt);
167 }
168}
169
f20a35cc
PF
170static int test_rs_hangcheck(sd_event_source *s, uint64_t usec,
171 void *userdata) {
787784c4 172 assert_se(false);
f20a35cc
PF
173
174 return 0;
175}
176
1a6c9136
YW
177int icmp6_bind_router_solicitation(int ifindex) {
178 assert_se(ifindex == 42);
f20a35cc 179
3e29b889 180 if (socketpair(AF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0, test_fd) < 0)
f20a35cc
PF
181 return -errno;
182
183 return test_fd[0];
184}
185
1a6c9136 186int icmp6_bind_router_advertisement(int ifindex) {
6142bb37
PF
187 return -ENOSYS;
188}
189
88d5a3db
PF
190int icmp6_receive(int fd, void *iov_base, size_t iov_len,
191 struct in6_addr *dst, triple_timestamp *timestamp) {
19500112 192 assert_se(read (fd, iov_base, iov_len) == (ssize_t)iov_len);
88d5a3db
PF
193
194 if (timestamp)
195 triple_timestamp_get(timestamp);
196
197 return 0;
198}
199
f20a35cc
PF
200static int send_ra(uint8_t flags) {
201 uint8_t advertisement[] = {
202 0x86, 0x00, 0xde, 0x83, 0x40, 0xc0, 0x00, 0xb4,
203 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
204 0x03, 0x04, 0x40, 0xc0, 0x00, 0x00, 0x01, 0xf4,
205 0x00, 0x00, 0x01, 0xb8, 0x00, 0x00, 0x00, 0x00,
206 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef,
207 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
208 0x19, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c,
209 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef,
210 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
211 0x1f, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c,
212 0x03, 0x6c, 0x61, 0x62, 0x05, 0x69, 0x6e, 0x74,
213 0x72, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
214 0x01, 0x01, 0x78, 0x2b, 0xcb, 0xb3, 0x6d, 0x53,
215 };
216
217 advertisement[5] = flags;
218
787784c4 219 assert_se(write(test_fd[1], advertisement, sizeof(advertisement)) ==
f20a35cc
PF
220 sizeof(advertisement));
221
222 if (verbose)
223 printf(" sent RA with flag 0x%02x\n", flags);
224
225 return 0;
226}
227
940367a0 228int icmp6_send_router_solicitation(int s, const struct ether_addr *ether_addr) {
5a67ed24
PF
229 if (!send_ra_function)
230 return 0;
231
99af546d 232 return send_ra_function(0);
f20a35cc
PF
233}
234
1e7a0e21 235static void test_callback(sd_ndisc *nd, sd_ndisc_event event, sd_ndisc_router *rt, void *userdata) {
f20a35cc 236 sd_event *e = userdata;
cb53894d 237 static unsigned idx = 0;
1e7a0e21 238 uint64_t flags_array[] = {
9d96e6c3
TG
239 0,
240 0,
241 0,
242 ND_RA_FLAG_OTHER,
243 ND_RA_FLAG_MANAGED
f20a35cc 244 };
1e7a0e21 245 uint64_t flags;
8d7f2c6a
PF
246 uint32_t mtu;
247
787784c4 248 assert_se(nd);
f20a35cc 249
1e7a0e21
LP
250 if (event != SD_NDISC_EVENT_ROUTER)
251 return;
252
253 router_dump(rt);
254
255 assert_se(sd_ndisc_router_get_flags(rt, &flags) >= 0);
9d96e6c3 256 assert_se(flags == flags_array[idx]);
f20a35cc
PF
257 idx++;
258
259 if (verbose)
1e7a0e21 260 printf(" got event 0x%02" PRIx64 "\n", flags);
f20a35cc 261
9d96e6c3
TG
262 if (idx < ELEMENTSOF(flags_array)) {
263 send_ra(flags_array[idx]);
8d7f2c6a
PF
264 return;
265 }
266
1e7a0e21 267 assert_se(sd_ndisc_get_mtu(nd, &mtu) == -ENODATA);
8d7f2c6a
PF
268
269 sd_event_exit(e, 0);
f20a35cc
PF
270}
271
99af546d
PF
272static void test_rs(void) {
273 sd_event *e;
4d7b83da 274 sd_ndisc *nd;
f20a35cc
PF
275
276 if (verbose)
277 printf("* %s\n", __FUNCTION__);
278
99af546d
PF
279 send_ra_function = send_ra;
280
281 assert_se(sd_event_new(&e) >= 0);
282
4d7b83da 283 assert_se(sd_ndisc_new(&nd) >= 0);
787784c4 284 assert_se(nd);
f20a35cc 285
4d7b83da 286 assert_se(sd_ndisc_attach_event(nd, e, 0) >= 0);
f20a35cc 287
2f8e7633 288 assert_se(sd_ndisc_set_ifindex(nd, 42) >= 0);
4d7b83da 289 assert_se(sd_ndisc_set_mac(nd, &mac_addr) >= 0);
1e7a0e21 290 assert_se(sd_ndisc_set_callback(nd, test_callback, e) >= 0);
f20a35cc 291
39cf0351
LP
292 assert_se(sd_event_add_time_relative(
293 e, &test_hangcheck, clock_boottime_or_monotonic(),
294 2 *USEC_PER_SEC, 0,
295 test_rs_hangcheck, NULL) >= 0);
f20a35cc 296
4d7b83da 297 assert_se(sd_ndisc_stop(nd) >= 0);
1e7a0e21 298 assert_se(sd_ndisc_start(nd) >= 0);
6b8a1aa6 299 assert_se(sd_ndisc_start(nd) >= 0);
4d7b83da 300 assert_se(sd_ndisc_stop(nd) >= 0);
836cf090 301
1e7a0e21 302 assert_se(sd_ndisc_start(nd) >= 0);
f20a35cc
PF
303
304 sd_event_loop(e);
305
306 test_hangcheck = sd_event_source_unref(test_hangcheck);
307
4d7b83da 308 nd = sd_ndisc_unref(nd);
787784c4 309 assert_se(!nd);
f20a35cc 310
f20a35cc 311 close(test_fd[1]);
99af546d
PF
312
313 sd_event_unref(e);
f20a35cc
PF
314}
315
5a67ed24
PF
316static 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;
320 usec_t min, max;
321 char time_string_min[FORMAT_TIMESPAN_MAX];
322 char time_string_nd[FORMAT_TIMESPAN_MAX];
323 char time_string_max[FORMAT_TIMESPAN_MAX];
324
325 assert_se(nd);
326 assert_se(nd->event);
327
328 if (++count >= 20)
329 sd_event_exit(nd->event, 0);
330
331 if (last == 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;
337 } else {
338 /* next RT = 2*RTprev + RAND*RTprev */
339 min = 2 * last - last / 10;
340 max = 2 * last + last / 10;
341 }
342
343 /* final RT > MRT */
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;
349 }
350
351 format_timespan(time_string_min, FORMAT_TIMESPAN_MAX,
352 min, USEC_PER_MSEC);
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,
356 max, USEC_PER_MSEC);
357
358 log_info("backoff timeout interval %2d %s%s <= %s <= %s",
359 count,
360 (last * 2 > NDISC_MAX_ROUTER_SOLICITATION_INTERVAL)? "(max) ": "",
361 time_string_min, time_string_nd, time_string_max);
362
363 assert_se(min <= nd->retransmit_time);
364 assert_se(max >= nd->retransmit_time);
365
366 last = nd->retransmit_time;
367
368 assert_se(sd_event_source_set_time(nd->timeout_event_source, 0) >= 0);
369
370 return 0;
371}
372
373static void test_timeout(void) {
374 sd_event *e;
375 sd_ndisc *nd;
5a67ed24
PF
376
377 if (verbose)
378 printf("* %s\n", __FUNCTION__);
379
380 send_ra_function = test_timeout_value;
381
382 assert_se(sd_event_new(&e) >= 0);
383
384 assert_se(sd_ndisc_new(&nd) >= 0);
385 assert_se(nd);
386
387 test_timeout_nd = nd;
388
389 assert_se(sd_ndisc_attach_event(nd, e, 0) >= 0);
390
391 assert_se(sd_ndisc_set_ifindex(nd, 42) >= 0);
392 assert_se(sd_ndisc_set_mac(nd, &mac_addr) >= 0);
393
39cf0351
LP
394 assert_se(sd_event_add_time_relative(
395 e, &test_hangcheck, clock_boottime_or_monotonic(),
396 2U * USEC_PER_SEC, 0,
397 test_rs_hangcheck, NULL) >= 0);
5a67ed24
PF
398
399 assert_se(sd_ndisc_start(nd) >= 0);
400
401 sd_event_loop(e);
402
403 test_hangcheck = sd_event_source_unref(test_hangcheck);
404
405 nd = sd_ndisc_unref(nd);
406
407 sd_event_unref(e);
408}
409
f20a35cc 410int main(int argc, char *argv[]) {
f20a35cc 411
6d7c4033 412 test_setup_logging(LOG_DEBUG);
f20a35cc 413
99af546d 414 test_rs();
5a67ed24 415 test_timeout();
f20a35cc
PF
416
417 return 0;
418}