]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libsystemd-network/test-ndisc-ra.c
tree-wide: make use of new relative time events in sd-event.h
[thirdparty/systemd.git] / src / libsystemd-network / test-ndisc-ra.c
CommitLineData
53e1b683 1/* SPDX-License-Identifier: LGPL-2.1+ */
24852172 2/***
810adae9 3 Copyright © 2017 Intel Corporation. All rights reserved.
24852172
PF
4***/
5
6#include <netinet/icmp6.h>
7#include <arpa/inet.h>
ca78ad1d 8#include <unistd.h>
24852172
PF
9
10#include "sd-radv.h"
11
12#include "alloc-util.h"
13#include "hexdecoct.h"
14#include "icmp6-util.h"
15#include "socket-util.h"
16#include "strv.h"
6d7c4033 17#include "tests.h"
24852172
PF
18
19static struct ether_addr mac_addr = {
20 .ether_addr_octet = { 0x78, 0x2b, 0xcb, 0xb3, 0x6d, 0x53 }
21};
22
23static uint8_t advertisement[] = {
24 /* ICMPv6 Router Advertisement, no checksum */
25 0x86, 0x00, 0x00, 0x00, 0x40, 0xc0, 0x00, 0xb4,
26 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
27 /* Source Link Layer Address Option */
28 0x01, 0x01, 0x78, 0x2b, 0xcb, 0xb3, 0x6d, 0x53,
29 /* Prefix Information Option */
30 0x03, 0x04, 0x40, 0xc0, 0x00, 0x00, 0x01, 0xf4,
31 0x00, 0x00, 0x01, 0xb8, 0x00, 0x00, 0x00, 0x00,
32 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef,
33 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34 /* Prefix Information Option */
35 0x03, 0x04, 0x40, 0xc0, 0x00, 0x27, 0x8d, 0x00,
36 0x00, 0x09, 0x3a, 0x80, 0x00, 0x00, 0x00, 0x00,
37 0x20, 0x01, 0x0d, 0xb8, 0x0b, 0x16, 0xd0, 0x0d,
38 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
39 /* Prefix Information Option */
40 0x03, 0x04, 0x30, 0xc0, 0x00, 0x27, 0x8d, 0x00,
41 0x00, 0x09, 0x3a, 0x80, 0x00, 0x00, 0x00, 0x00,
42 0x20, 0x01, 0x0d, 0xb8, 0xc0, 0x01, 0x0d, 0xad,
43 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
06e6c805 44 /* Recursive DNS Server Option */
24852172
PF
45 0x19, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c,
46 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef,
47 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
fa178dd2 48 /* DNS Search List Option */
24852172
PF
49 0x1f, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c,
50 0x03, 0x6c, 0x61, 0x62, 0x05, 0x69, 0x6e, 0x74,
51 0x72, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
52};
53
54static sd_event_source *test_hangcheck;
55static bool test_stopped;
56static int test_fd[2];
57static sd_event_source *recv_router_advertisement;
58static struct {
59 struct in6_addr address;
60 unsigned char prefixlen;
61 uint32_t valid;
62 uint32_t preferred;
5238e957 63 bool successful;
24852172
PF
64} prefix[] = {
65 { { { { 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef,
66 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, 64,
67 500, 440, true },
68 { { { { 0x20, 0x01, 0x0d, 0xb8, 0x0b, 0x16, 0xd0, 0x0d,
69 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, 64,
70 /* indicate default valid and preferred lifetimes for the test code */
71 0, 0, true },
72 { { { { 0x20, 0x01, 0x0d, 0xb8, 0x0b, 0x16, 0xd0, 0x0d,
73 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, 58,
74 0, 0,
75 /* indicate that this prefix already exists */
76 false },
77 { { { { 0x20, 0x01, 0x0d, 0xb8, 0x0b, 0x16, 0xd0, 0x0d,
78 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, 120,
79 0, 0,
80 /* indicate that this prefix already exists */
81 false },
82 { { { { 0x20, 0x01, 0x0d, 0xb8, 0x0b, 0x16, 0xd0, 0x0d,
83 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, 12,
84 0, 0,
85 /* indicate that this prefix already exists */
86 false },
87 { { { { 0x20, 0x01, 0x0d, 0xb8, 0xc0, 0x01, 0x0d, 0xad,
88 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, 48,
89 0, 0, true },
90 { { { { 0x20, 0x01, 0x0d, 0xb8, 0xc0, 0x01, 0x0d, 0xad,
91 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, 60,
92 0, 0,
93 /* indicate that this prefix already exists */
94 false },
95};
96
06e6c805
PF
97static const struct in6_addr test_rdnss = { { { 0x20, 0x01, 0x0d, 0xb8,
98 0xde, 0xad, 0xbe, 0xef,
99 0x00, 0x00, 0x00, 0x00,
100 0x00, 0x00, 0x00, 0x01 } } };
fa178dd2
PF
101static const char *test_dnssl[] = { "lab.intra",
102 NULL };
06e6c805 103
24852172
PF
104static int test_rs_hangcheck(sd_event_source *s, uint64_t usec,
105 void *userdata) {
106 assert_se(false);
107
108 return 0;
109}
110
111static void test_radv_prefix(void) {
112 sd_radv_prefix *p;
113
114 printf("* %s\n", __FUNCTION__);
115
116 assert_se(sd_radv_prefix_new(&p) >= 0);
117
118 assert_se(sd_radv_prefix_set_onlink(NULL, true) < 0);
119 assert_se(sd_radv_prefix_set_onlink(p, true) >= 0);
120 assert_se(sd_radv_prefix_set_onlink(p, false) >= 0);
121
122 assert_se(sd_radv_prefix_set_address_autoconfiguration(NULL, true) < 0);
123 assert_se(sd_radv_prefix_set_address_autoconfiguration(p, true) >= 0);
124 assert_se(sd_radv_prefix_set_address_autoconfiguration(p, false) >= 0);
125
126 assert_se(sd_radv_prefix_set_valid_lifetime(NULL, true) < 0);
127 assert_se(sd_radv_prefix_set_valid_lifetime(p, ~0) >= 0);
128 assert_se(sd_radv_prefix_set_valid_lifetime(p, 42) >= 0);
129 assert_se(sd_radv_prefix_set_valid_lifetime(p, 0) >= 0);
130
131 assert_se(sd_radv_prefix_set_preferred_lifetime(NULL, true) < 0);
132 assert_se(sd_radv_prefix_set_preferred_lifetime(p, ~0) >= 0);
133 assert_se(sd_radv_prefix_set_preferred_lifetime(p, 42) >= 0);
134 assert_se(sd_radv_prefix_set_preferred_lifetime(p, 0) >= 0);
135
136 assert_se(sd_radv_prefix_set_prefix(NULL, NULL, 0) < 0);
137 assert_se(sd_radv_prefix_set_prefix(p, NULL, 0) < 0);
138
139 assert_se(sd_radv_prefix_set_prefix(p, &prefix[0].address, 64) >= 0);
140 assert_se(sd_radv_prefix_set_prefix(p, &prefix[0].address, 0) < 0);
141 assert_se(sd_radv_prefix_set_prefix(p, &prefix[0].address, 1) < 0);
142 assert_se(sd_radv_prefix_set_prefix(p, &prefix[0].address, 2) < 0);
143 assert_se(sd_radv_prefix_set_prefix(p, &prefix[0].address, 3) >= 0);
144 assert_se(sd_radv_prefix_set_prefix(p, &prefix[0].address, 125) >= 0);
145 assert_se(sd_radv_prefix_set_prefix(p, &prefix[0].address, 128) >= 0);
146 assert_se(sd_radv_prefix_set_prefix(p, &prefix[0].address, 129) < 0);
147 assert_se(sd_radv_prefix_set_prefix(p, &prefix[0].address, 255) < 0);
148
149 p = sd_radv_prefix_unref(p);
150 assert_se(!p);
151}
152
153static void test_radv(void) {
154 sd_radv *ra;
155
156 printf("* %s\n", __FUNCTION__);
157
158 assert_se(sd_radv_new(&ra) >= 0);
159 assert_se(ra);
160
161 assert_se(sd_radv_set_ifindex(NULL, 0) < 0);
7fa69c0a
YW
162 assert_se(sd_radv_set_ifindex(ra, 0) < 0);
163 assert_se(sd_radv_set_ifindex(ra, -1) < 0);
24852172
PF
164 assert_se(sd_radv_set_ifindex(ra, -2) < 0);
165 assert_se(sd_radv_set_ifindex(ra, 42) >= 0);
166
167 assert_se(sd_radv_set_mac(NULL, NULL) < 0);
168 assert_se(sd_radv_set_mac(ra, NULL) >= 0);
169 assert_se(sd_radv_set_mac(ra, &mac_addr) >= 0);
170
171 assert_se(sd_radv_set_mtu(NULL, 0) < 0);
172 assert_se(sd_radv_set_mtu(ra, 0) < 0);
173 assert_se(sd_radv_set_mtu(ra, 1279) < 0);
174 assert_se(sd_radv_set_mtu(ra, 1280) >= 0);
175 assert_se(sd_radv_set_mtu(ra, ~0) >= 0);
176
177 assert_se(sd_radv_set_hop_limit(NULL, 0) < 0);
178 assert_se(sd_radv_set_hop_limit(ra, 0) >= 0);
179 assert_se(sd_radv_set_hop_limit(ra, ~0) >= 0);
180
181 assert_se(sd_radv_set_router_lifetime(NULL, 0) < 0);
182 assert_se(sd_radv_set_router_lifetime(ra, 0) >= 0);
183 assert_se(sd_radv_set_router_lifetime(ra, ~0) >= 0);
184
185 assert_se(sd_radv_set_preference(NULL, 0) < 0);
186 assert_se(sd_radv_set_preference(ra, SD_NDISC_PREFERENCE_LOW) >= 0);
187 assert_se(sd_radv_set_preference(ra, SD_NDISC_PREFERENCE_MEDIUM) >= 0);
188 assert_se(sd_radv_set_preference(ra, SD_NDISC_PREFERENCE_HIGH) >= 0);
189 assert_se(sd_radv_set_preference(ra, ~0) < 0);
190
191 assert_se(sd_radv_set_preference(ra, SD_NDISC_PREFERENCE_HIGH) >= 0);
192 assert_se(sd_radv_set_router_lifetime(ra, 42000) >= 0);
193 assert_se(sd_radv_set_router_lifetime(ra, 0) < 0);
194 assert_se(sd_radv_set_preference(ra, SD_NDISC_PREFERENCE_MEDIUM) >= 0);
195 assert_se(sd_radv_set_router_lifetime(ra, 0) >= 0);
196
197 assert_se(sd_radv_set_managed_information(NULL, true) < 0);
198 assert_se(sd_radv_set_managed_information(ra, true) >= 0);
199 assert_se(sd_radv_set_managed_information(ra, false) >= 0);
200
201 assert_se(sd_radv_set_other_information(NULL, true) < 0);
202 assert_se(sd_radv_set_other_information(ra, true) >= 0);
203 assert_se(sd_radv_set_other_information(ra, false) >= 0);
204
06e6c805
PF
205 assert_se(sd_radv_set_rdnss(NULL, 0, NULL, 0) < 0);
206 assert_se(sd_radv_set_rdnss(ra, 0, NULL, 0) >= 0);
207 assert_se(sd_radv_set_rdnss(ra, 0, NULL, 128) < 0);
208 assert_se(sd_radv_set_rdnss(ra, 600, &test_rdnss, 0) >= 0);
209 assert_se(sd_radv_set_rdnss(ra, 600, &test_rdnss, 1) >= 0);
210 assert_se(sd_radv_set_rdnss(ra, 0, &test_rdnss, 1) >= 0);
211 assert_se(sd_radv_set_rdnss(ra, 0, NULL, 0) >= 0);
212
fa178dd2
PF
213 assert_se(sd_radv_set_dnssl(ra, 0, NULL) >= 0);
214 assert_se(sd_radv_set_dnssl(ra, 600, NULL) >= 0);
215 assert_se(sd_radv_set_dnssl(ra, 0, (char **)test_dnssl) >= 0);
216 assert_se(sd_radv_set_dnssl(ra, 600, (char **)test_dnssl) >= 0);
217
24852172
PF
218 ra = sd_radv_unref(ra);
219 assert_se(!ra);
220}
221
1a6c9136 222int icmp6_bind_router_solicitation(int ifindex) {
24852172
PF
223 return -ENOSYS;
224}
225
1a6c9136
YW
226int icmp6_bind_router_advertisement(int ifindex) {
227 assert_se(ifindex == 42);
24852172
PF
228
229 return test_fd[1];
230}
231
232int icmp6_send_router_solicitation(int s, const struct ether_addr *ether_addr) {
233
234 return 0;
235}
236
237int icmp6_receive(int fd, void *iov_base, size_t iov_len,
238 struct in6_addr *dst, triple_timestamp *timestamp) {
239 assert_se(read (fd, iov_base, iov_len) == (ssize_t)iov_len);
240
241 if (timestamp)
242 triple_timestamp_get(timestamp);
243
244 return 0;
245}
246
247static int radv_recv(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
248 sd_radv *ra = userdata;
fa178dd2 249 unsigned char buf[168];
24852172
PF
250 size_t i;
251
ef51180b 252 assert_se(read(test_fd[0], &buf, sizeof(buf)) == sizeof(buf));
24852172
PF
253
254 /* router lifetime must be zero when test is stopped */
255 if (test_stopped) {
256 advertisement[6] = 0x00;
257 advertisement[7] = 0x00;
258 }
259
260 printf ("Received Router Advertisement with lifetime %u\n",
261 (advertisement[6] << 8) + advertisement[7]);
262
263 /* test only up to buf size, rest is not yet implemented */
264 for (i = 0; i < sizeof(buf); i++) {
06e6c805
PF
265 if (!(i % 8))
266 printf("%3zd: ", i);
267
24852172
PF
268 printf("0x%02x", buf[i]);
269
270 assert_se(buf[i] == advertisement[i]);
271
272 if ((i + 1) % 8)
273 printf(", ");
274 else
275 printf("\n");
276 }
277
278 if (test_stopped) {
279 sd_event *e;
280
281 e = sd_radv_get_event(ra);
282 sd_event_exit(e, 0);
283
284 return 0;
285 }
286
290696e5 287 assert_se(sd_radv_stop(ra) >= 0);
24852172
PF
288 test_stopped = true;
289
290 return 0;
291}
292
293static void test_ra(void) {
294 sd_event *e;
295 sd_radv *ra;
14cb109d 296 unsigned i;
24852172
PF
297
298 printf("* %s\n", __FUNCTION__);
299
3e29b889 300 assert_se(socketpair(AF_UNIX, SOCK_SEQPACKET | SOCK_CLOEXEC | SOCK_NONBLOCK, 0, test_fd) >= 0);
24852172
PF
301
302 assert_se(sd_event_new(&e) >= 0);
303
304 assert_se(sd_radv_new(&ra) >= 0);
305 assert_se(ra);
306
307 assert_se(sd_radv_attach_event(ra, e, 0) >= 0);
308
309 assert_se(sd_radv_set_ifindex(ra, 42) >= 0);
310 assert_se(sd_radv_set_mac(ra, &mac_addr) >= 0);
311 assert_se(sd_radv_set_router_lifetime(ra, 180) >= 0);
312 assert_se(sd_radv_set_hop_limit(ra, 64) >= 0);
313 assert_se(sd_radv_set_managed_information(ra, true) >= 0);
314 assert_se(sd_radv_set_other_information(ra, true) >= 0);
06e6c805 315 assert_se(sd_radv_set_rdnss(ra, 60, &test_rdnss, 1) >= 0);
fa178dd2 316 assert_se(sd_radv_set_dnssl(ra, 60, (char **)test_dnssl) >= 0);
24852172
PF
317
318 for (i = 0; i < ELEMENTSOF(prefix); i++) {
319 sd_radv_prefix *p;
320
321 printf("Test prefix %u\n", i);
322 assert_se(sd_radv_prefix_new(&p) >= 0);
323
324 assert_se(sd_radv_prefix_set_prefix(p, &prefix[i].address,
325 prefix[i].prefixlen) >= 0);
326 if (prefix[i].valid)
327 assert_se(sd_radv_prefix_set_valid_lifetime(p, prefix[i].valid) >= 0);
328 if (prefix[i].preferred)
329 assert_se(sd_radv_prefix_set_preferred_lifetime(p, prefix[i].preferred) >= 0);
330
5238e957 331 assert_se((sd_radv_add_prefix(ra, p, false) >= 0) == prefix[i].successful);
d601b566 332 assert_se(sd_radv_add_prefix(ra, p, false) < 0);
24852172
PF
333
334 p = sd_radv_prefix_unref(p);
335 assert_se(!p);
336 }
337
338 assert_se(sd_event_add_io(e, &recv_router_advertisement, test_fd[0],
339 EPOLLIN, radv_recv, ra) >= 0);
340
39cf0351
LP
341 assert_se(sd_event_add_time_relative(
342 e, &test_hangcheck, clock_boottime_or_monotonic(),
343 2 *USEC_PER_SEC, 0,
344 test_rs_hangcheck, NULL) >= 0);
24852172
PF
345
346 assert_se(sd_radv_start(ra) >= 0);
347
348 sd_event_loop(e);
349
350 test_hangcheck = sd_event_source_unref(test_hangcheck);
351
352 ra = sd_radv_unref(ra);
353 assert_se(!ra);
354
355 close(test_fd[0]);
356
357 sd_event_unref(e);
358}
359
360int main(int argc, char *argv[]) {
361
6d7c4033 362 test_setup_logging(LOG_DEBUG);
24852172
PF
363
364 test_radv_prefix();
365 test_radv();
366 test_ra();
367
368 printf("* done\n");
369 return 0;
370}