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