]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/libsystemd-network/test-ndisc-ra.c
analyze: fix typo
[thirdparty/systemd.git] / src / libsystemd-network / test-ndisc-ra.c
1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2 /***
3 Copyright © 2017 Intel Corporation. All rights reserved.
4 ***/
5
6 #include <net/ethernet.h>
7 #include <netinet/icmp6.h>
8 #include <unistd.h>
9
10 #include "sd-event.h"
11 #include "sd-ndisc-protocol.h"
12 #include "sd-radv.h"
13
14 #include "alloc-util.h"
15 #include "icmp6-test-util.h"
16 #include "in-addr-util.h"
17 #include "radv-internal.h"
18 #include "socket-util.h"
19 #include "tests.h"
20
21 static struct ether_addr mac_addr = {
22 .ether_addr_octet = { 0x78, 0x2b, 0xcb, 0xb3, 0x6d, 0x53 }
23 };
24
25 static bool test_stopped;
26 static struct {
27 struct in6_addr address;
28 unsigned char prefixlen;
29 uint32_t valid;
30 uint32_t preferred;
31 bool successful;
32 } prefix[] = {
33 { { { { 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef,
34 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, 64,
35 500, 440, true },
36 { { { { 0x20, 0x01, 0x0d, 0xb8, 0x0b, 0x16, 0xd0, 0x0d,
37 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, 64,
38 /* indicate default valid and preferred lifetimes for the test code */
39 0, 0, true },
40 { { { { 0x20, 0x01, 0x0d, 0xb8, 0x0b, 0x16, 0xd0, 0x0d,
41 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, 58,
42 0, 0,
43 /* indicate that this prefix already exists */
44 false },
45 { { { { 0x20, 0x01, 0x0d, 0xb8, 0x0b, 0x16, 0xd0, 0x0d,
46 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, 120,
47 0, 0,
48 /* indicate that this prefix already exists */
49 false },
50 { { { { 0x20, 0x01, 0x0d, 0xb8, 0x0b, 0x16, 0xd0, 0x0d,
51 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, 12,
52 0, 0,
53 /* indicate that this prefix already exists */
54 false },
55 { { { { 0x20, 0x01, 0x0d, 0xb8, 0xc0, 0x01, 0x0d, 0xad,
56 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, 48,
57 0, 0, true },
58 { { { { 0x20, 0x01, 0x0d, 0xb8, 0xc0, 0x01, 0x0d, 0xad,
59 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, 60,
60 0, 0,
61 /* indicate that this prefix already exists */
62 false },
63 };
64
65 static const struct in6_addr test_rdnss = { { { 0x20, 0x01, 0x0d, 0xb8,
66 0xde, 0xad, 0xbe, 0xef,
67 0x00, 0x00, 0x00, 0x00,
68 0x00, 0x00, 0x00, 0x01 } } };
69 static const char *test_dnssl[] = { "lab.intra",
70 NULL };
71
72 TEST(radv) {
73 sd_radv *ra;
74
75 assert_se(sd_radv_new(&ra) >= 0);
76 assert_se(ra);
77
78 ASSERT_RETURN_EXPECTED_SE(sd_radv_set_ifindex(NULL, 0) < 0);
79 ASSERT_RETURN_EXPECTED_SE(sd_radv_set_ifindex(ra, 0) < 0);
80 ASSERT_RETURN_EXPECTED_SE(sd_radv_set_ifindex(ra, -1) < 0);
81 ASSERT_RETURN_EXPECTED_SE(sd_radv_set_ifindex(ra, -2) < 0);
82 assert_se(sd_radv_set_ifindex(ra, 42) >= 0);
83
84 /* header */
85 ASSERT_RETURN_EXPECTED_SE(sd_radv_set_hop_limit(NULL, 0) < 0);
86 assert_se(sd_radv_set_hop_limit(ra, 0) >= 0);
87 assert_se(sd_radv_set_hop_limit(ra, ~0) >= 0);
88
89 ASSERT_RETURN_EXPECTED_SE(sd_radv_set_router_lifetime(NULL, 0) < 0);
90 assert_se(sd_radv_set_router_lifetime(ra, 0) >= 0);
91 assert_se(sd_radv_set_router_lifetime(ra, USEC_INFINITY) < 0);
92 assert_se(sd_radv_set_router_lifetime(ra, USEC_PER_YEAR) < 0);
93 assert_se(sd_radv_set_router_lifetime(ra, 300 * USEC_PER_SEC) >= 0);
94
95 ASSERT_RETURN_EXPECTED_SE(sd_radv_set_preference(NULL, 0) < 0);
96 assert_se(sd_radv_set_preference(ra, SD_NDISC_PREFERENCE_LOW) >= 0);
97 assert_se(sd_radv_set_preference(ra, SD_NDISC_PREFERENCE_MEDIUM) >= 0);
98 assert_se(sd_radv_set_preference(ra, SD_NDISC_PREFERENCE_HIGH) >= 0);
99 ASSERT_RETURN_EXPECTED_SE(sd_radv_set_preference(ra, ~0) < 0);
100
101 ASSERT_RETURN_EXPECTED_SE(sd_radv_set_managed_information(NULL, true) < 0);
102 assert_se(sd_radv_set_managed_information(ra, true) >= 0);
103 assert_se(sd_radv_set_managed_information(ra, false) >= 0);
104
105 ASSERT_RETURN_EXPECTED_SE(sd_radv_set_other_information(NULL, true) < 0);
106 assert_se(sd_radv_set_other_information(ra, true) >= 0);
107 assert_se(sd_radv_set_other_information(ra, false) >= 0);
108
109 ASSERT_RETURN_EXPECTED_SE(sd_radv_set_reachable_time(NULL, 10 * USEC_PER_MSEC) < 0);
110 assert_se(sd_radv_set_reachable_time(ra, 10 * USEC_PER_MSEC) >= 0);
111 assert_se(sd_radv_set_reachable_time(ra, 0) >= 0);
112 assert_se(sd_radv_set_reachable_time(ra, USEC_INFINITY) >= 0);
113
114 ASSERT_RETURN_EXPECTED_SE(sd_radv_set_retransmit(NULL, 10 * USEC_PER_MSEC) < 0);
115 assert_se(sd_radv_set_retransmit(ra, 10 * USEC_PER_MSEC) >= 0);
116 assert_se(sd_radv_set_retransmit(ra, 0) >= 0);
117 assert_se(sd_radv_set_retransmit(ra, USEC_INFINITY) >= 0);
118
119 /* options */
120 ASSERT_RETURN_EXPECTED_SE(sd_radv_set_mac(NULL, NULL) < 0);
121 ASSERT_RETURN_EXPECTED_SE(sd_radv_set_mac(ra, NULL) >= 0);
122 assert_se(sd_radv_set_mac(ra, &mac_addr) >= 0);
123 sd_radv_unset_mac(ra);
124
125 ASSERT_RETURN_EXPECTED_SE(sd_radv_set_mtu(NULL, 0) < 0);
126 ASSERT_RETURN_EXPECTED_SE(sd_radv_set_mtu(ra, 0) < 0);
127 ASSERT_RETURN_EXPECTED_SE(sd_radv_set_mtu(ra, 1279) < 0);
128 assert_se(sd_radv_set_mtu(ra, 1280) >= 0);
129 assert_se(sd_radv_set_mtu(ra, 9999) >= 0);
130 sd_radv_unset_mtu(ra);
131
132 ASSERT_RETURN_EXPECTED_SE(sd_radv_add_rdnss(NULL, 0, NULL, 0, 0) < 0);
133 ASSERT_RETURN_EXPECTED_SE(sd_radv_add_rdnss(ra, 0, NULL, 0, 0) < 0);
134 assert_se(sd_radv_add_rdnss(ra, 0, &test_rdnss, 600 * USEC_PER_SEC, USEC_INFINITY) < 0);
135 assert_se(sd_radv_add_rdnss(ra, 1, &test_rdnss, 600 * USEC_PER_SEC, USEC_INFINITY) >= 0);
136 assert_se(sd_radv_add_rdnss(ra, 1, &test_rdnss, 0, 0) >= 0);
137 sd_radv_clear_rdnss(ra);
138
139 ASSERT_RETURN_EXPECTED_SE(sd_radv_add_dnssl(NULL, NULL, 0, 0) < 0);
140 assert_se(sd_radv_add_dnssl(ra, NULL, 0, 0) < 0);
141 assert_se(sd_radv_add_dnssl(ra, NULL, 600 * USEC_PER_SEC, USEC_INFINITY) < 0);
142 assert_se(sd_radv_add_dnssl(ra, (char**) test_dnssl, 600 * USEC_PER_SEC, USEC_INFINITY) >= 0);
143 assert_se(sd_radv_add_dnssl(ra, (char**) test_dnssl, 0, 0) >= 0);
144 sd_radv_clear_dnssl(ra);
145
146 ASSERT_RETURN_EXPECTED_SE(sd_radv_set_home_agent(NULL, 0, 0, 0) < 0);
147 assert_se(sd_radv_set_home_agent(ra, 0, 0, 0) >= 0);
148 assert_se(sd_radv_set_home_agent(ra, 10, 300 * USEC_PER_SEC, USEC_INFINITY) >= 0);
149 sd_radv_unset_home_agent(ra);
150
151 ra = sd_radv_unref(ra);
152 assert_se(!ra);
153 }
154
155 static void dump_message(const uint8_t *buf, size_t len) {
156 assert(len >= sizeof(struct nd_router_advert));
157
158 printf("Received Router Advertisement with lifetime %i sec\n",
159 (buf[6] << 8) + buf[7]);
160
161 for (size_t i = 0; i < len; i++) {
162 if (!(i % 8))
163 printf("%3zu: ", i);
164
165 printf("0x%02x", buf[i]);
166
167 if ((i + 1) % 8)
168 printf(", ");
169 else
170 printf("\n");
171 }
172 }
173
174 static void verify_message(const uint8_t *buf, size_t len) {
175 static const uint8_t advertisement[] = {
176 /* ICMPv6 Router Advertisement, no checksum */
177 0x86, 0x00, 0x00, 0x00, 0x40, 0xc0, 0x00, 0xb4,
178 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
179 /* Source Link Layer Address Option */
180 0x01, 0x01, 0x78, 0x2b, 0xcb, 0xb3, 0x6d, 0x53,
181 /* Prefix Information Option */
182 0x03, 0x04, 0x30, 0xc0, 0x00, 0x00, 0x0e, 0x10,
183 0x00, 0x00, 0x07, 0x08, 0x00, 0x00, 0x00, 0x00,
184 0x20, 0x01, 0x0d, 0xb8, 0xc0, 0x01, 0x00, 0x00,
185 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
186 /* Prefix Information Option */
187 0x03, 0x04, 0x40, 0xc0, 0x00, 0x00, 0x0e, 0x10,
188 0x00, 0x00, 0x07, 0x08, 0x00, 0x00, 0x00, 0x00,
189 0x20, 0x01, 0x0d, 0xb8, 0x0b, 0x16, 0xd0, 0x0d,
190 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
191 /* Prefix Information Option */
192 0x03, 0x04, 0x40, 0xc0, 0x00, 0x00, 0x01, 0xf4,
193 0x00, 0x00, 0x01, 0xb8, 0x00, 0x00, 0x00, 0x00,
194 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef,
195 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
196 /* Recursive DNS Server Option */
197 0x19, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c,
198 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef,
199 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
200 /* DNS Search List Option */
201 0x1f, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c,
202 0x03, 0x6c, 0x61, 0x62, 0x05, 0x69, 0x6e, 0x74,
203 0x72, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
204 };
205
206 /* verify only up to known options, rest is not yet implemented */
207 for (size_t i = 0, m = MIN(len, sizeof(advertisement)); i < m; i++) {
208 if (test_stopped)
209 /* on stop, many header fields are zero */
210 switch (i) {
211 case 4: /* hop limit */
212 case 5: /* flags */
213 case 6 ... 7: /* router lifetime */
214 case 8 ... 11: /* reachable time */
215 case 12 ... 15: /* retrans timer */
216 assert_se(buf[i] == 0);
217 continue;
218 }
219
220 assert_se(buf[i] == advertisement[i]);
221 }
222 }
223
224 static int radv_recv(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
225 sd_radv *ra = ASSERT_PTR(userdata);
226 _cleanup_free_ uint8_t *buf = NULL;
227 ssize_t buflen;
228
229 buflen = next_datagram_size_fd(fd);
230 assert_se(buflen >= 0);
231 assert_se(buf = new0(uint8_t, buflen));
232
233 assert_se(read(fd, buf, buflen) == buflen);
234
235 dump_message(buf, buflen);
236 verify_message(buf, buflen);
237
238 if (test_stopped) {
239 assert_se(sd_event_exit(sd_radv_get_event(ra), 0) >= 0);
240 return 0;
241 }
242
243 assert_se(sd_radv_stop(ra) >= 0);
244 test_stopped = true;
245 return 0;
246 }
247
248 TEST(ra) {
249 _cleanup_(sd_event_unrefp) sd_event *e = NULL;
250 _cleanup_(sd_event_source_unrefp) sd_event_source *recv_router_advertisement = NULL;
251 _cleanup_(sd_radv_unrefp) sd_radv *ra = NULL;
252
253 assert_se(socketpair(AF_UNIX, SOCK_SEQPACKET | SOCK_CLOEXEC | SOCK_NONBLOCK, 0, test_fd) >= 0);
254
255 assert_se(sd_event_new(&e) >= 0);
256
257 assert_se(sd_radv_new(&ra) >= 0);
258 assert_se(ra);
259
260 assert_se(sd_radv_attach_event(ra, e, 0) >= 0);
261
262 assert_se(sd_radv_set_ifindex(ra, 42) >= 0);
263 assert_se(sd_radv_set_router_lifetime(ra, 180 * USEC_PER_SEC) >= 0);
264 assert_se(sd_radv_set_hop_limit(ra, 64) >= 0);
265 assert_se(sd_radv_set_managed_information(ra, true) >= 0);
266 assert_se(sd_radv_set_other_information(ra, true) >= 0);
267 assert_se(sd_radv_set_mac(ra, &mac_addr) >= 0);
268 assert_se(sd_radv_add_rdnss(ra, 1, &test_rdnss, 60 * USEC_PER_SEC, USEC_INFINITY) >= 0);
269 assert_se(sd_radv_add_dnssl(ra, (char**) test_dnssl, 60 * USEC_PER_SEC, USEC_INFINITY) >= 0);
270
271 FOREACH_ARRAY(p, prefix, ELEMENTSOF(prefix)) {
272 printf("Test prefix %s\n", IN6_ADDR_PREFIX_TO_STRING(&p->address, p->prefixlen));
273 assert_se((sd_radv_add_prefix(
274 ra,
275 &p->address,
276 p->prefixlen,
277 ND_OPT_PI_FLAG_ONLINK | ND_OPT_PI_FLAG_AUTO,
278 p->valid > 0 ? p->valid * USEC_PER_SEC : RADV_DEFAULT_VALID_LIFETIME_USEC,
279 p->preferred > 0 ? p->preferred * USEC_PER_SEC : RADV_DEFAULT_PREFERRED_LIFETIME_USEC,
280 USEC_INFINITY,
281 USEC_INFINITY) >= 0) == p->successful);
282 /* If the previous sd_radv_add_prefix() succeeds, then also the second call should also succeed. */
283 assert_se((sd_radv_add_prefix(
284 ra,
285 &p->address,
286 p->prefixlen,
287 ND_OPT_PI_FLAG_ONLINK | ND_OPT_PI_FLAG_AUTO,
288 p->valid > 0 ? p->valid * USEC_PER_SEC : RADV_DEFAULT_VALID_LIFETIME_USEC,
289 p->preferred > 0 ? p->preferred * USEC_PER_SEC : RADV_DEFAULT_PREFERRED_LIFETIME_USEC,
290 USEC_INFINITY,
291 USEC_INFINITY) >= 0) == p->successful);
292 }
293
294 assert_se(sd_event_add_io(e, &recv_router_advertisement, test_fd[0], EPOLLIN, radv_recv, ra) >= 0);
295 assert_se(sd_event_source_set_io_fd_own(recv_router_advertisement, true) >= 0);
296
297 assert_se(sd_event_add_time_relative(e, NULL, CLOCK_BOOTTIME,
298 30 * USEC_PER_SEC, 0,
299 NULL, INT_TO_PTR(-ETIMEDOUT)) >= 0);
300
301 assert_se(sd_radv_start(ra) >= 0);
302
303 assert_se(sd_event_loop(e) >= 0);
304 }
305
306 DEFINE_TEST_MAIN(LOG_DEBUG);