chiark / gitweb /
Add missing includes in header files
[elogind.git] / src / libsystemd-network / test-icmp6-rs.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4   This file is part of systemd.
5
6   Copyright (C) 2014 Intel Corporation. All rights reserved.
7
8   systemd is free software; you can redistribute it and/or modify it
9   under the terms of the GNU Lesser General Public License as published by
10   the Free Software Foundation; either version 2.1 of the License, or
11   (at your option) any later version.
12
13   systemd is distributed in the hope that it will be useful, but
14   WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16   Lesser General Public License for more details.
17
18   You should have received a copy of the GNU Lesser General Public License
19   along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include <netinet/icmp6.h>
23
24 #include "socket-util.h"
25
26 #include "dhcp6-internal.h"
27 #include "sd-icmp6-nd.h"
28
29 static struct ether_addr mac_addr = {
30         .ether_addr_octet = {'A', 'B', 'C', '1', '2', '3'}
31 };
32
33 static bool verbose = false;
34 static sd_event_source *test_hangcheck;
35 static int test_fd[2];
36
37 typedef int (*send_ra_t)(uint8_t flags);
38 static send_ra_t send_ra_function;
39
40 static int test_rs_hangcheck(sd_event_source *s, uint64_t usec,
41                              void *userdata) {
42         assert_se(false);
43
44         return 0;
45 }
46
47 int dhcp_network_icmp6_bind_router_solicitation(int index) {
48         assert_se(index == 42);
49
50         if (socketpair(AF_UNIX, SOCK_DGRAM, 0, test_fd) < 0)
51                 return -errno;
52
53         return test_fd[0];
54 }
55
56 static int send_ra_short_prefix(uint8_t flags) {
57         uint8_t advertisement[] = {
58                 0x86, 0x00, 0xbe, 0xd7, 0x40, 0xc0, 0x00, 0xb4,
59                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
60
61                 0x03, 0x04, 0x34, 0xc0, 0x00, 0x00, 0x01, 0xf4,
62                 0x00, 0x00, 0x01, 0xb8, 0x00, 0x00, 0x00, 0x00,
63                 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef,
64                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
65         };
66
67         assert_se(write(test_fd[1], advertisement, sizeof(advertisement)) ==
68                sizeof(advertisement));
69
70         return 0;
71 }
72
73 static void test_short_prefix_cb(sd_icmp6_nd *nd, int event, void *userdata) {
74         sd_event *e = userdata;
75         struct {
76                 struct in6_addr addr;
77                 uint8_t prefixlen;
78                 bool success;
79         } addrs[] = {
80                 { { { { 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef,
81                         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
82                   52, true },
83                 { { { { 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0x0d, 0xad,
84                         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
85                   64, false },
86                 { { { { 0x20, 0x01, 0x0d, 0xb8, 0x0b, 0x16, 0xd0, 0x0d,
87                         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
88                   60, true },
89                 { { { { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x9d, 0xab, 0xcd,
90                         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
91                   64, true },
92                 { { { { 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xed,
93                         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } } },
94                   52, true },
95         };
96         uint8_t prefixlen;
97         unsigned int i;
98
99         for (i = 0; i < ELEMENTSOF(addrs); i++) {
100                 printf("  %s prefix %02x%02x:%02x%02x:%02x%02x:%02x%02x",
101                         __FUNCTION__,
102                         addrs[i].addr.s6_addr[0], addrs[i].addr.s6_addr[1],
103                         addrs[i].addr.s6_addr[2], addrs[i].addr.s6_addr[3],
104                         addrs[i].addr.s6_addr[4], addrs[i].addr.s6_addr[5],
105                         addrs[i].addr.s6_addr[6], addrs[i].addr.s6_addr[7]);
106
107                 if (addrs[i].success) {
108                         assert_se(sd_icmp6_ra_get_prefixlen(nd, &addrs[i].addr,
109                                                                 &prefixlen) >= 0);
110                         assert_se(addrs[i].prefixlen == prefixlen);
111                         printf("/%d onlink\n", prefixlen);
112                 } else {
113                         assert_se(sd_icmp6_ra_get_prefixlen(nd, &addrs[i].addr,
114                                                                 &prefixlen) == -EADDRNOTAVAIL);
115                         printf("/128 offlink\n");
116                 }
117         }
118
119         sd_event_exit(e, 0);
120 }
121
122 static int send_ra_prefixes(uint8_t flags) {
123         uint8_t advertisement[] = {
124                 0x86, 0x00, 0xbe, 0xd7, 0x40, 0xc0, 0x00, 0xb4,
125                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
126                 0x03, 0x04, 0x3f, 0xc0, 0x00, 0x00, 0x01, 0xf4,
127                 0x00, 0x00, 0x01, 0xb8, 0x00, 0x00, 0x00, 0x00,
128                 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef,
129                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
130                 0x03, 0x04, 0x40, 0x00, 0x00, 0x00, 0x02, 0x58,
131                 0x00, 0x00, 0x02, 0x1c, 0x00, 0x00, 0x00, 0x00,
132                 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0x0d, 0xad,
133                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
134                 0x03, 0x04, 0x3c, 0x80, 0x00, 0x00, 0x03, 0x84,
135                 0x00, 0x00, 0x03, 0x20, 0x00, 0x00, 0x00, 0x00,
136                 0x20, 0x01, 0x0d, 0xb8, 0x0b, 0x16, 0xd0, 0x0d,
137                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
138                 0x03, 0x04, 0x40, 0xc0, 0x00, 0x00, 0x03, 0x84,
139                 0x00, 0x00, 0x03, 0x20, 0x00, 0x00, 0x00, 0x00,
140                 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x9d, 0xab, 0xcd,
141                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
142                 0x19, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c,
143                 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef,
144                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
145                 0x1f, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c,
146                 0x03, 0x6c, 0x61, 0x62, 0x05, 0x69, 0x6e, 0x74,
147                 0x72, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
148                 0x01, 0x01, 0x78, 0x2b, 0xcb, 0xb3, 0x6d, 0x53
149         };
150
151         assert_se(write(test_fd[1], advertisement, sizeof(advertisement)) ==
152                sizeof(advertisement));
153
154         return 0;
155 }
156
157 static void test_prefixes_cb(sd_icmp6_nd *nd, int event, void *userdata) {
158         sd_event *e = userdata;
159         struct {
160                 struct in6_addr addr;
161                 uint8_t prefixlen;
162                 bool success;
163         } addrs[] = {
164                 { { { { 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef,
165                         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
166                   63, true },
167                 { { { { 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0x0d, 0xad,
168                         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
169                   64, false },
170                 { { { { 0x20, 0x01, 0x0d, 0xb8, 0x0b, 0x16, 0xd0, 0x0d,
171                         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
172                   60, true },
173                 { { { { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x9d, 0xab, 0xcd,
174                         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
175                   64, true },
176                 { { { { 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xed,
177                         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } } },
178                   63, false },
179         };
180         uint8_t prefixlen;
181         unsigned int i;
182
183         for (i = 0; i < ELEMENTSOF(addrs); i++) {
184                 printf("  %s prefix %02x%02x:%02x%02x:%02x%02x:%02x%02x",
185                         __FUNCTION__,
186                         addrs[i].addr.s6_addr[0], addrs[i].addr.s6_addr[1],
187                         addrs[i].addr.s6_addr[2], addrs[i].addr.s6_addr[3],
188                         addrs[i].addr.s6_addr[4], addrs[i].addr.s6_addr[5],
189                         addrs[i].addr.s6_addr[6], addrs[i].addr.s6_addr[7]);
190
191                 if (addrs[i].success) {
192                         assert_se(sd_icmp6_ra_get_prefixlen(nd, &addrs[i].addr,
193                                                                 &prefixlen) >= 0);
194                         assert_se(addrs[i].prefixlen == prefixlen);
195                         printf("/%d onlink\n", prefixlen);
196                 } else {
197                         assert_se(sd_icmp6_ra_get_prefixlen(nd, &addrs[i].addr,
198                                                                 &prefixlen) == -EADDRNOTAVAIL);
199                         printf("/128 offlink\n");
200                 }
201         }
202
203         send_ra_function = send_ra_short_prefix;
204         assert_se(sd_icmp6_nd_set_callback(nd, test_short_prefix_cb, e) >= 0);
205         assert_se(sd_icmp6_nd_stop(nd) >= 0);
206         assert_se(sd_icmp6_router_solicitation_start(nd) >= 0);
207 }
208
209 static void test_prefixes(void) {
210         sd_event *e;
211         sd_icmp6_nd *nd;
212
213         if (verbose)
214                 printf("* %s\n", __FUNCTION__);
215
216         send_ra_function = send_ra_prefixes;
217
218         assert_se(sd_event_new(&e) >= 0);
219
220         assert_se(sd_icmp6_nd_new(&nd) >= 0);
221         assert_se(nd);
222
223         assert_se(sd_icmp6_nd_attach_event(nd, e, 0) >= 0);
224
225         assert_se(sd_icmp6_nd_set_index(nd, 42) >= 0);
226         assert_se(sd_icmp6_nd_set_mac(nd, &mac_addr) >= 0);
227         assert_se(sd_icmp6_nd_set_callback(nd, test_prefixes_cb, e) >= 0);
228
229         assert_se(sd_icmp6_router_solicitation_start(nd) >= 0);
230
231         sd_event_loop(e);
232
233         nd = sd_icmp6_nd_unref(nd);
234         assert_se(!nd);
235
236         close(test_fd[1]);
237
238         sd_event_unref(e);
239 }
240
241 static int send_ra(uint8_t flags) {
242         uint8_t advertisement[] = {
243                 0x86, 0x00, 0xde, 0x83, 0x40, 0xc0, 0x00, 0xb4,
244                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
245                 0x03, 0x04, 0x40, 0xc0, 0x00, 0x00, 0x01, 0xf4,
246                 0x00, 0x00, 0x01, 0xb8, 0x00, 0x00, 0x00, 0x00,
247                 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef,
248                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
249                 0x19, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c,
250                 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef,
251                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
252                 0x1f, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c,
253                 0x03, 0x6c, 0x61, 0x62, 0x05, 0x69, 0x6e, 0x74,
254                 0x72, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
255                 0x01, 0x01, 0x78, 0x2b, 0xcb, 0xb3, 0x6d, 0x53,
256         };
257
258         advertisement[5] = flags;
259
260         assert_se(write(test_fd[1], advertisement, sizeof(advertisement)) ==
261                sizeof(advertisement));
262
263         if (verbose)
264                 printf("  sent RA with flag 0x%02x\n", flags);
265
266         return 0;
267 }
268
269 int dhcp_network_icmp6_send_router_solicitation(int s, const struct ether_addr *ether_addr) {
270         return send_ra_function(0);
271 }
272
273 static void test_rs_done(sd_icmp6_nd *nd, int event, void *userdata) {
274         sd_event *e = userdata;
275         static int idx = 0;
276         struct {
277                 uint8_t flag;
278                 int event;
279         } flag_event[] = {
280                 { 0, ICMP6_EVENT_ROUTER_ADVERTISMENT_NONE },
281                 { ND_RA_FLAG_OTHER, ICMP6_EVENT_ROUTER_ADVERTISMENT_OTHER },
282                 { ND_RA_FLAG_MANAGED, ICMP6_EVENT_ROUTER_ADVERTISMENT_MANAGED }
283         };
284         uint32_t mtu;
285
286         assert_se(nd);
287
288         assert_se(event == flag_event[idx].event);
289         idx++;
290
291         if (verbose)
292                 printf("  got event %d\n", event);
293
294         if (idx < 3) {
295                 send_ra(flag_event[idx].flag);
296                 return;
297         }
298
299         assert_se(sd_icmp6_ra_get_mtu(nd, &mtu) == -ENOMSG);
300
301         sd_event_exit(e, 0);
302 }
303
304 static void test_rs(void) {
305         sd_event *e;
306         sd_icmp6_nd *nd;
307         usec_t time_now = now(clock_boottime_or_monotonic());
308
309         if (verbose)
310                 printf("* %s\n", __FUNCTION__);
311
312         send_ra_function = send_ra;
313
314         assert_se(sd_event_new(&e) >= 0);
315
316         assert_se(sd_icmp6_nd_new(&nd) >= 0);
317         assert_se(nd);
318
319         assert_se(sd_icmp6_nd_attach_event(nd, e, 0) >= 0);
320
321         assert_se(sd_icmp6_nd_set_index(nd, 42) >= 0);
322         assert_se(sd_icmp6_nd_set_mac(nd, &mac_addr) >= 0);
323         assert_se(sd_icmp6_nd_set_callback(nd, test_rs_done, e) >= 0);
324
325         assert_se(sd_event_add_time(e, &test_hangcheck, clock_boottime_or_monotonic(),
326                                  time_now + 2 *USEC_PER_SEC, 0,
327                                  test_rs_hangcheck, NULL) >= 0);
328
329         assert_se(sd_icmp6_nd_stop(nd) >= 0);
330         assert_se(sd_icmp6_router_solicitation_start(nd) >= 0);
331         assert_se(sd_icmp6_nd_stop(nd) >= 0);
332
333         assert_se(sd_icmp6_router_solicitation_start(nd) >= 0);
334
335         sd_event_loop(e);
336
337         test_hangcheck = sd_event_source_unref(test_hangcheck);
338
339         nd = sd_icmp6_nd_unref(nd);
340         assert_se(!nd);
341
342         close(test_fd[1]);
343
344         sd_event_unref(e);
345 }
346
347 int main(int argc, char *argv[]) {
348
349         log_set_max_level(LOG_DEBUG);
350         log_parse_environment();
351         log_open();
352
353         test_rs();
354         test_prefixes();
355
356         return 0;
357 }