]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/libsystemd-network/test-ndisc-rs.c
sd-ndisc: notify user on STOP
[thirdparty/systemd.git] / src / libsystemd-network / test-ndisc-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 "sd-ndisc.h"
25
26 #include "icmp6-util.h"
27 #include "socket-util.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 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(uint8_t flags) {
57 uint8_t advertisement[] = {
58 0x86, 0x00, 0xde, 0x83, 0x40, 0xc0, 0x00, 0xb4,
59 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
60 0x03, 0x04, 0x40, 0xc0, 0x00, 0x00, 0x01, 0xf4,
61 0x00, 0x00, 0x01, 0xb8, 0x00, 0x00, 0x00, 0x00,
62 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef,
63 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
64 0x19, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c,
65 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef,
66 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
67 0x1f, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c,
68 0x03, 0x6c, 0x61, 0x62, 0x05, 0x69, 0x6e, 0x74,
69 0x72, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
70 0x01, 0x01, 0x78, 0x2b, 0xcb, 0xb3, 0x6d, 0x53,
71 };
72
73 advertisement[5] = flags;
74
75 assert_se(write(test_fd[1], advertisement, sizeof(advertisement)) ==
76 sizeof(advertisement));
77
78 if (verbose)
79 printf(" sent RA with flag 0x%02x\n", flags);
80
81 return 0;
82 }
83
84 int icmp6_send_router_solicitation(int s, const struct ether_addr *ether_addr) {
85 return send_ra_function(0);
86 }
87
88 static void test_rs_done(sd_ndisc *nd, int event, void *userdata) {
89 sd_event *e = userdata;
90 static unsigned idx = 0;
91 struct {
92 uint8_t flag;
93 int event;
94 } flag_event[] = {
95 { 0, SD_NDISC_EVENT_STOP },
96 { 0, SD_NDISC_EVENT_STOP },
97 { 0, SD_NDISC_EVENT_ROUTER_ADVERTISMENT_NONE },
98 { ND_RA_FLAG_OTHER, SD_NDISC_EVENT_ROUTER_ADVERTISMENT_OTHER },
99 { ND_RA_FLAG_MANAGED, SD_NDISC_EVENT_ROUTER_ADVERTISMENT_MANAGED }
100 };
101 uint32_t mtu;
102
103 assert_se(nd);
104
105 assert_se(event == flag_event[idx].event);
106 idx++;
107
108 if (verbose)
109 printf(" got event %d\n", event);
110
111 if (idx < ELEMENTSOF(flag_event)) {
112 send_ra(flag_event[idx].flag);
113 return;
114 }
115
116 assert_se(sd_ndisc_get_mtu(nd, &mtu) == -ENOMSG);
117
118 sd_event_exit(e, 0);
119 }
120
121 static void test_rs(void) {
122 sd_event *e;
123 sd_ndisc *nd;
124 usec_t time_now = now(clock_boottime_or_monotonic());
125
126 if (verbose)
127 printf("* %s\n", __FUNCTION__);
128
129 send_ra_function = send_ra;
130
131 assert_se(sd_event_new(&e) >= 0);
132
133 assert_se(sd_ndisc_new(&nd) >= 0);
134 assert_se(nd);
135
136 assert_se(sd_ndisc_attach_event(nd, e, 0) >= 0);
137
138 assert_se(sd_ndisc_set_index(nd, 42) >= 0);
139 assert_se(sd_ndisc_set_mac(nd, &mac_addr) >= 0);
140 assert_se(sd_ndisc_set_callback(nd, test_rs_done, e) >= 0);
141
142 assert_se(sd_event_add_time(e, &test_hangcheck, clock_boottime_or_monotonic(),
143 time_now + 2 *USEC_PER_SEC, 0,
144 test_rs_hangcheck, NULL) >= 0);
145
146 assert_se(sd_ndisc_stop(nd) >= 0);
147 assert_se(sd_ndisc_router_discovery_start(nd) >= 0);
148 assert_se(sd_ndisc_stop(nd) >= 0);
149
150 assert_se(sd_ndisc_router_discovery_start(nd) >= 0);
151
152 sd_event_loop(e);
153
154 test_hangcheck = sd_event_source_unref(test_hangcheck);
155
156 nd = sd_ndisc_unref(nd);
157 assert_se(!nd);
158
159 close(test_fd[1]);
160
161 sd_event_unref(e);
162 }
163
164 int main(int argc, char *argv[]) {
165
166 log_set_max_level(LOG_DEBUG);
167 log_parse_environment();
168 log_open();
169
170 test_rs();
171
172 return 0;
173 }