]>
Commit | Line | Data |
---|---|---|
53e1b683 | 1 | /* SPDX-License-Identifier: LGPL-2.1+ */ |
813e3a6f | 2 | /*** |
810adae9 | 3 | Copyright © 2014 Intel Corporation. All rights reserved. |
813e3a6f PF |
4 | ***/ |
5 | ||
07630cea | 6 | #include <net/ethernet.h> |
813e3a6f PF |
7 | #include <stdbool.h> |
8 | #include <stdio.h> | |
2ea8857e | 9 | #include <sys/socket.h> |
07630cea | 10 | #include <sys/types.h> |
2ea8857e | 11 | #include <unistd.h> |
813e3a6f | 12 | |
07630cea | 13 | #include "sd-dhcp6-client.h" |
813e3a6f | 14 | #include "sd-event.h" |
813e3a6f | 15 | |
f12ed3bf | 16 | #include "dhcp6-internal.h" |
859cca44 | 17 | #include "dhcp6-lease-internal.h" |
07630cea | 18 | #include "dhcp6-protocol.h" |
3ffd4af2 | 19 | #include "fd-util.h" |
07630cea LP |
20 | #include "macro.h" |
21 | #include "socket-util.h" | |
6d7c4033 | 22 | #include "tests.h" |
07630cea | 23 | #include "virt.h" |
813e3a6f PF |
24 | |
25 | static struct ether_addr mac_addr = { | |
26 | .ether_addr_octet = {'A', 'B', 'C', '1', '2', '3'} | |
27 | }; | |
28 | ||
2ea8857e PF |
29 | static sd_event_source *hangcheck; |
30 | static int test_dhcp_fd[2]; | |
31 | static int test_index = 42; | |
5e256ea7 PF |
32 | static int test_client_message_num; |
33 | static be32_t test_iaid = 0; | |
34 | static uint8_t test_duid[14] = { }; | |
2ea8857e | 35 | |
813e3a6f PF |
36 | static int test_client_basic(sd_event *e) { |
37 | sd_dhcp6_client *client; | |
7776f2ae | 38 | int v; |
813e3a6f | 39 | |
9a254164 | 40 | log_debug("/* %s */", __func__); |
813e3a6f PF |
41 | |
42 | assert_se(sd_dhcp6_client_new(&client) >= 0); | |
43 | assert_se(client); | |
44 | ||
45 | assert_se(sd_dhcp6_client_attach_event(client, e, 0) >= 0); | |
46 | ||
2f8e7633 LP |
47 | assert_se(sd_dhcp6_client_set_ifindex(client, 15) == 0); |
48 | assert_se(sd_dhcp6_client_set_ifindex(client, -42) == -EINVAL); | |
49 | assert_se(sd_dhcp6_client_set_ifindex(client, -1) == 0); | |
50 | assert_se(sd_dhcp6_client_set_ifindex(client, 42) >= 0); | |
813e3a6f | 51 | |
76253e73 DW |
52 | assert_se(sd_dhcp6_client_set_mac(client, (const uint8_t *) &mac_addr, |
53 | sizeof (mac_addr), | |
54 | ARPHRD_ETHER) >= 0); | |
813e3a6f | 55 | |
8006aa32 SA |
56 | assert_se(sd_dhcp6_client_set_fqdn(client, "host") == 1); |
57 | assert_se(sd_dhcp6_client_set_fqdn(client, "host.domain") == 1); | |
58 | assert_se(sd_dhcp6_client_set_fqdn(client, NULL) == 1); | |
59 | assert_se(sd_dhcp6_client_set_fqdn(client, "~host") == -EINVAL); | |
60 | assert_se(sd_dhcp6_client_set_fqdn(client, "~host.domain") == -EINVAL); | |
61 | ||
2c1ab8ca BG |
62 | assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_CLIENTID) == -EINVAL); |
63 | assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_DNS_SERVERS) == -EEXIST); | |
64 | assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_NTP_SERVER) == -EEXIST); | |
65 | assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_SNTP_SERVERS) == -EEXIST); | |
66 | assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_DOMAIN_LIST) == -EEXIST); | |
da6fe470 PF |
67 | assert_se(sd_dhcp6_client_set_request_option(client, 10) == -EINVAL); |
68 | ||
7776f2ae PF |
69 | assert_se(sd_dhcp6_client_set_information_request(client, 1) >= 0); |
70 | v = 0; | |
71 | assert_se(sd_dhcp6_client_get_information_request(client, &v) >= 0); | |
72 | assert_se(v); | |
73 | assert_se(sd_dhcp6_client_set_information_request(client, 0) >= 0); | |
74 | v = 42; | |
75 | assert_se(sd_dhcp6_client_get_information_request(client, &v) >= 0); | |
76 | assert_se(v == 0); | |
77 | ||
78 | v = 0; | |
79 | assert_se(sd_dhcp6_client_get_address_request(client, &v) >= 0); | |
80 | assert_se(v); | |
81 | v = 0; | |
82 | assert_se(sd_dhcp6_client_set_address_request(client, 1) >= 0); | |
83 | assert_se(sd_dhcp6_client_get_address_request(client, &v) >= 0); | |
84 | assert_se(v); | |
85 | v = 42; | |
86 | assert_se(sd_dhcp6_client_set_address_request(client, 1) >= 0); | |
87 | assert_se(sd_dhcp6_client_get_address_request(client, &v) >= 0); | |
88 | assert_se(v); | |
89 | ||
90 | assert_se(sd_dhcp6_client_set_address_request(client, 1) >= 0); | |
91 | assert_se(sd_dhcp6_client_set_prefix_delegation(client, 1) >= 0); | |
92 | v = 0; | |
93 | assert_se(sd_dhcp6_client_get_address_request(client, &v) >= 0); | |
94 | assert_se(v); | |
95 | v = 0; | |
96 | assert_se(sd_dhcp6_client_get_prefix_delegation(client, &v) >= 0); | |
97 | assert_se(v); | |
98 | ||
813e3a6f PF |
99 | assert_se(sd_dhcp6_client_set_callback(client, NULL, NULL) >= 0); |
100 | ||
101 | assert_se(sd_dhcp6_client_detach_event(client) >= 0); | |
102 | assert_se(!sd_dhcp6_client_unref(client)); | |
103 | ||
104 | return 0; | |
105 | } | |
106 | ||
f12ed3bf PF |
107 | static int test_option(sd_event *e) { |
108 | uint8_t packet[] = { | |
109 | 'F', 'O', 'O', | |
2c1ab8ca | 110 | 0x00, SD_DHCP6_OPTION_ORO, 0x00, 0x07, |
f12ed3bf | 111 | 'A', 'B', 'C', 'D', 'E', 'F', 'G', |
2c1ab8ca | 112 | 0x00, SD_DHCP6_OPTION_VENDOR_CLASS, 0x00, 0x09, |
f12ed3bf PF |
113 | '1', '2', '3', '4', '5', '6', '7', '8', '9', |
114 | 'B', 'A', 'R', | |
115 | }; | |
116 | uint8_t result[] = { | |
117 | 'F', 'O', 'O', | |
118 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
119 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
120 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
121 | 'B', 'A', 'R', | |
122 | }; | |
123 | uint16_t optcode; | |
124 | size_t optlen; | |
125 | uint8_t *optval, *buf, *out; | |
126 | size_t zero = 0, pos = 3; | |
127 | size_t buflen = sizeof(packet), outlen = sizeof(result); | |
128 | ||
9a254164 | 129 | log_debug("/* %s */", __func__); |
f12ed3bf PF |
130 | |
131 | assert_se(buflen == outlen); | |
132 | ||
133 | assert_se(dhcp6_option_parse(&buf, &zero, &optcode, &optlen, | |
134 | &optval) == -ENOMSG); | |
135 | ||
136 | buflen -= 3; | |
137 | buf = &packet[3]; | |
138 | outlen -= 3; | |
139 | out = &result[3]; | |
140 | ||
141 | assert_se(dhcp6_option_parse(&buf, &buflen, &optcode, &optlen, | |
142 | &optval) >= 0); | |
143 | pos += 4 + optlen; | |
144 | assert_se(buf == &packet[pos]); | |
2c1ab8ca | 145 | assert_se(optcode == SD_DHCP6_OPTION_ORO); |
f12ed3bf PF |
146 | assert_se(optlen == 7); |
147 | assert_se(buflen + pos == sizeof(packet)); | |
148 | ||
149 | assert_se(dhcp6_option_append(&out, &outlen, optcode, optlen, | |
150 | optval) >= 0); | |
151 | assert_se(out == &result[pos]); | |
152 | assert_se(*out == 0x00); | |
153 | ||
154 | assert_se(dhcp6_option_parse(&buf, &buflen, &optcode, &optlen, | |
155 | &optval) >= 0); | |
156 | pos += 4 + optlen; | |
157 | assert_se(buf == &packet[pos]); | |
2c1ab8ca | 158 | assert_se(optcode == SD_DHCP6_OPTION_VENDOR_CLASS); |
f12ed3bf PF |
159 | assert_se(optlen == 9); |
160 | assert_se(buflen + pos == sizeof(packet)); | |
161 | ||
162 | assert_se(dhcp6_option_append(&out, &outlen, optcode, optlen, | |
163 | optval) >= 0); | |
164 | assert_se(out == &result[pos]); | |
165 | assert_se(*out == 'B'); | |
166 | ||
167 | assert_se(memcmp(packet, result, sizeof(packet)) == 0); | |
168 | ||
169 | return 0; | |
170 | } | |
171 | ||
df296124 PF |
172 | static int test_option_status(sd_event *e) { |
173 | uint8_t option1[] = { | |
174 | /* IA NA */ | |
175 | 0x00, 0x03, 0x00, 0x12, 0x1a, 0x1d, 0x1a, 0x1d, | |
176 | 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x02, | |
177 | /* status option */ | |
178 | 0x00, 0x0d, 0x00, 0x02, 0x00, 0x01, | |
179 | }; | |
180 | static const uint8_t option2[] = { | |
181 | /* IA NA */ | |
182 | 0x00, 0x03, 0x00, 0x2e, 0x1a, 0x1d, 0x1a, 0x1d, | |
183 | 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x02, | |
184 | /* IA Addr */ | |
185 | 0x00, 0x05, 0x00, 0x1e, | |
186 | 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, | |
187 | 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, | |
188 | 0x01, 0x02, 0x03, 0x04, 0x0a, 0x0b, 0x0c, 0x0d, | |
189 | /* status option */ | |
190 | 0x00, 0x0d, 0x00, 0x02, 0x00, 0x01, | |
191 | }; | |
192 | static const uint8_t option3[] = { | |
193 | /* IA NA */ | |
194 | 0x00, 0x03, 0x00, 0x34, 0x1a, 0x1d, 0x1a, 0x1d, | |
195 | 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x02, | |
196 | /* IA Addr */ | |
197 | 0x00, 0x05, 0x00, 0x24, | |
198 | 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, | |
199 | 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, | |
200 | 0x01, 0x02, 0x03, 0x04, 0x0a, 0x0b, 0x0c, 0x0d, | |
201 | /* status option */ | |
202 | 0x00, 0x0d, 0x00, 0x08, 0x00, 0x00, 'f', 'o', | |
203 | 'o', 'b', 'a', 'r', | |
204 | }; | |
819c56f6 PF |
205 | static const uint8_t option4[] = { |
206 | /* IA PD */ | |
207 | 0x00, 0x19, 0x00, 0x2f, 0x1a, 0x1d, 0x1a, 0x1d, | |
208 | 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x02, | |
209 | /* IA PD Prefix */ | |
210 | 0x00, 0x1a, 0x00, 0x1f, | |
211 | 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, | |
212 | 0x80, 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, | |
213 | 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
214 | 0x00, | |
215 | /* status option */ | |
216 | 0x00, 0x0d, 0x00, 0x02, 0x00, 0x00, | |
217 | }; | |
218 | static const uint8_t option5[] = { | |
219 | /* IA PD */ | |
220 | 0x00, 0x19, 0x00, 0x52, 0x1a, 0x1d, 0x1a, 0x1d, | |
221 | 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x02, | |
222 | /* IA PD Prefix #1 */ | |
223 | 0x00, 0x1a, 0x00, 0x1f, | |
224 | 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, | |
225 | 0x80, 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, | |
226 | 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
227 | 0x00, | |
228 | /* status option */ | |
229 | 0x00, 0x0d, 0x00, 0x02, 0x00, 0x00, | |
230 | /* IA PD Prefix #2 */ | |
231 | 0x00, 0x1a, 0x00, 0x1f, | |
232 | 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, | |
233 | 0x80, 0x20, 0x01, 0x0d, 0xb8, 0xc0, 0x0l, 0xd0, | |
234 | 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
235 | 0x00, | |
236 | 0x00, 0x0d, 0x00, 0x02, 0x00, 0x00, | |
237 | }; | |
df296124 | 238 | DHCP6Option *option; |
819c56f6 | 239 | DHCP6IA ia, pd; |
df296124 PF |
240 | int r = 0; |
241 | ||
9a254164 | 242 | log_debug("/* %s */", __func__); |
df296124 PF |
243 | |
244 | zero(ia); | |
245 | option = (DHCP6Option *)option1; | |
246 | assert_se(sizeof(option1) == sizeof(DHCP6Option) + be16toh(option->len)); | |
247 | ||
248 | r = dhcp6_option_parse_ia(option, &ia); | |
249 | assert_se(r == -EINVAL); | |
250 | assert_se(ia.addresses == NULL); | |
251 | ||
252 | option->len = htobe16(17); | |
253 | r = dhcp6_option_parse_ia(option, &ia); | |
254 | assert_se(r == -ENOBUFS); | |
255 | assert_se(ia.addresses == NULL); | |
256 | ||
257 | option->len = htobe16(sizeof(DHCP6Option)); | |
258 | r = dhcp6_option_parse_ia(option, &ia); | |
259 | assert_se(r == -ENOBUFS); | |
260 | assert_se(ia.addresses == NULL); | |
261 | ||
262 | zero(ia); | |
263 | option = (DHCP6Option *)option2; | |
264 | assert_se(sizeof(option2) == sizeof(DHCP6Option) + be16toh(option->len)); | |
265 | ||
266 | r = dhcp6_option_parse_ia(option, &ia); | |
267 | assert_se(r >= 0); | |
268 | assert_se(ia.addresses == NULL); | |
269 | ||
270 | zero(ia); | |
271 | option = (DHCP6Option *)option3; | |
272 | assert_se(sizeof(option3) == sizeof(DHCP6Option) + be16toh(option->len)); | |
273 | ||
274 | r = dhcp6_option_parse_ia(option, &ia); | |
275 | assert_se(r >= 0); | |
276 | assert_se(ia.addresses != NULL); | |
5a45fde5 | 277 | dhcp6_lease_free_ia(&ia); |
df296124 | 278 | |
819c56f6 PF |
279 | zero(pd); |
280 | option = (DHCP6Option *)option4; | |
281 | assert_se(sizeof(option4) == sizeof(DHCP6Option) + be16toh(option->len)); | |
282 | ||
283 | r = dhcp6_option_parse_ia(option, &pd); | |
284 | assert_se(r == 0); | |
285 | assert_se(pd.addresses != NULL); | |
286 | assert_se(memcmp(&pd.ia_pd.id, &option4[4], 4) == 0); | |
287 | assert_se(memcmp(&pd.ia_pd.lifetime_t1, &option4[8], 4) == 0); | |
288 | assert_se(memcmp(&pd.ia_pd.lifetime_t2, &option4[12], 4) == 0); | |
5a45fde5 | 289 | dhcp6_lease_free_ia(&pd); |
819c56f6 PF |
290 | |
291 | zero(pd); | |
292 | option = (DHCP6Option *)option5; | |
293 | assert_se(sizeof(option5) == sizeof(DHCP6Option) + be16toh(option->len)); | |
294 | ||
295 | r = dhcp6_option_parse_ia(option, &pd); | |
296 | assert_se(r == 0); | |
297 | assert_se(pd.addresses != NULL); | |
5a45fde5 | 298 | dhcp6_lease_free_ia(&pd); |
819c56f6 | 299 | |
df296124 PF |
300 | return 0; |
301 | } | |
302 | ||
859cca44 PF |
303 | static uint8_t msg_advertise[198] = { |
304 | 0x02, 0x0f, 0xb4, 0xe5, 0x00, 0x01, 0x00, 0x0e, | |
305 | 0x00, 0x01, 0x00, 0x01, 0x1a, 0x6b, 0xf3, 0x30, | |
306 | 0x3c, 0x97, 0x0e, 0xcf, 0xa3, 0x7d, 0x00, 0x03, | |
307 | 0x00, 0x5e, 0x0e, 0xcf, 0xa3, 0x7d, 0x00, 0x00, | |
308 | 0x00, 0x50, 0x00, 0x00, 0x00, 0x78, 0x00, 0x05, | |
309 | 0x00, 0x18, 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, | |
310 | 0xbe, 0xef, 0x78, 0xee, 0x1c, 0xf3, 0x09, 0x3c, | |
311 | 0x55, 0xad, 0x00, 0x00, 0x00, 0x96, 0x00, 0x00, | |
312 | 0x00, 0xb4, 0x00, 0x0d, 0x00, 0x32, 0x00, 0x00, | |
313 | 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x28, | |
314 | 0x65, 0x73, 0x29, 0x20, 0x72, 0x65, 0x6e, 0x65, | |
315 | 0x77, 0x65, 0x64, 0x2e, 0x20, 0x47, 0x72, 0x65, | |
316 | 0x65, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x20, 0x66, | |
317 | 0x72, 0x6f, 0x6d, 0x20, 0x70, 0x6c, 0x61, 0x6e, | |
318 | 0x65, 0x74, 0x20, 0x45, 0x61, 0x72, 0x74, 0x68, | |
319 | 0x00, 0x17, 0x00, 0x10, 0x20, 0x01, 0x0d, 0xb8, | |
320 | 0xde, 0xad, 0xbe, 0xef, 0x00, 0x00, 0x00, 0x00, | |
321 | 0x00, 0x00, 0x00, 0x01, 0x00, 0x18, 0x00, 0x0b, | |
322 | 0x03, 0x6c, 0x61, 0x62, 0x05, 0x69, 0x6e, 0x74, | |
323 | 0x72, 0x61, 0x00, 0x00, 0x1f, 0x00, 0x10, 0x20, | |
324 | 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef, 0x00, | |
325 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, | |
326 | 0x02, 0x00, 0x0e, 0x00, 0x01, 0x00, 0x01, 0x19, | |
327 | 0x40, 0x5c, 0x53, 0x78, 0x2b, 0xcb, 0xb3, 0x6d, | |
328 | 0x53, 0x00, 0x07, 0x00, 0x01, 0x00 | |
329 | }; | |
330 | ||
947527f8 PF |
331 | static uint8_t msg_reply[173] = { |
332 | 0x07, 0xf7, 0x4e, 0x57, 0x00, 0x02, 0x00, 0x0e, | |
333 | 0x00, 0x01, 0x00, 0x01, 0x19, 0x40, 0x5c, 0x53, | |
334 | 0x78, 0x2b, 0xcb, 0xb3, 0x6d, 0x53, 0x00, 0x01, | |
335 | 0x00, 0x0e, 0x00, 0x01, 0x00, 0x01, 0x1a, 0x6b, | |
336 | 0xf3, 0x30, 0x3c, 0x97, 0x0e, 0xcf, 0xa3, 0x7d, | |
337 | 0x00, 0x03, 0x00, 0x4a, 0x0e, 0xcf, 0xa3, 0x7d, | |
338 | 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x78, | |
339 | 0x00, 0x05, 0x00, 0x18, 0x20, 0x01, 0x0d, 0xb8, | |
340 | 0xde, 0xad, 0xbe, 0xef, 0x78, 0xee, 0x1c, 0xf3, | |
341 | 0x09, 0x3c, 0x55, 0xad, 0x00, 0x00, 0x00, 0x96, | |
342 | 0x00, 0x00, 0x00, 0xb4, 0x00, 0x0d, 0x00, 0x1e, | |
343 | 0x00, 0x00, 0x41, 0x6c, 0x6c, 0x20, 0x61, 0x64, | |
344 | 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x20, | |
345 | 0x77, 0x65, 0x72, 0x65, 0x20, 0x61, 0x73, 0x73, | |
346 | 0x69, 0x67, 0x6e, 0x65, 0x64, 0x2e, 0x00, 0x17, | |
347 | 0x00, 0x10, 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, | |
348 | 0xbe, 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
349 | 0x00, 0x01, 0x00, 0x18, 0x00, 0x0b, 0x03, 0x6c, | |
350 | 0x61, 0x62, 0x05, 0x69, 0x6e, 0x74, 0x72, 0x61, | |
351 | 0x00, 0x00, 0x1f, 0x00, 0x10, 0x20, 0x01, 0x0d, | |
352 | 0xb8, 0xde, 0xad, 0xbe, 0xef, 0x00, 0x00, 0x00, | |
353 | 0x00, 0x00, 0x00, 0x00, 0x01 | |
354 | }; | |
355 | ||
8006aa32 SA |
356 | static uint8_t fqdn_wire[16] = { |
357 | 0x04, 'h', 'o', 's', 't', 0x03, 'l', 'a', 'b', | |
358 | 0x05, 'i', 'n', 't', 'r', 'a', 0x00 | |
359 | }; | |
360 | ||
859cca44 | 361 | static int test_advertise_option(sd_event *e) { |
4afd3348 | 362 | _cleanup_(sd_dhcp6_lease_unrefp) sd_dhcp6_lease *lease = NULL; |
859cca44 | 363 | DHCP6Message *advertise = (DHCP6Message *)msg_advertise; |
3bc424a3 | 364 | size_t len = sizeof(msg_advertise) - sizeof(DHCP6Message), pos = 0; |
859cca44 PF |
365 | be32_t val; |
366 | uint8_t preference = 255; | |
367 | struct in6_addr addr; | |
368 | uint32_t lt_pref, lt_valid; | |
369 | int r; | |
3bc424a3 | 370 | uint8_t *opt; |
859cca44 | 371 | bool opt_clientid = false; |
bc152ff8 PF |
372 | struct in6_addr *addrs; |
373 | char **domains; | |
859cca44 | 374 | |
9a254164 | 375 | log_debug("/* %s */", __func__); |
859cca44 | 376 | |
3bc424a3 PF |
377 | assert_se(len >= sizeof(DHCP6Message)); |
378 | ||
859cca44 PF |
379 | assert_se(dhcp6_lease_new(&lease) >= 0); |
380 | ||
381 | assert_se(advertise->type == DHCP6_ADVERTISE); | |
382 | assert_se((be32toh(advertise->transaction_id) & 0x00ffffff) == | |
383 | 0x0fb4e5); | |
384 | ||
3bc424a3 PF |
385 | while (pos < len) { |
386 | DHCP6Option *option = (DHCP6Option *)&advertise->options[pos]; | |
387 | const uint16_t optcode = be16toh(option->code); | |
388 | const uint16_t optlen = be16toh(option->len); | |
389 | uint8_t *optval = option->data; | |
859cca44 PF |
390 | |
391 | switch(optcode) { | |
2c1ab8ca | 392 | case SD_DHCP6_OPTION_CLIENTID: |
859cca44 PF |
393 | assert_se(optlen == 14); |
394 | ||
395 | opt_clientid = true; | |
396 | break; | |
397 | ||
2c1ab8ca | 398 | case SD_DHCP6_OPTION_IA_NA: |
859cca44 PF |
399 | assert_se(optlen == 94); |
400 | assert_se(!memcmp(optval, &msg_advertise[26], optlen)); | |
401 | ||
402 | val = htobe32(0x0ecfa37d); | |
403 | assert_se(!memcmp(optval, &val, sizeof(val))); | |
404 | ||
405 | val = htobe32(80); | |
406 | assert_se(!memcmp(optval + 4, &val, sizeof(val))); | |
407 | ||
408 | val = htobe32(120); | |
409 | assert_se(!memcmp(optval + 8, &val, sizeof(val))); | |
410 | ||
3bc424a3 | 411 | assert_se(dhcp6_option_parse_ia(option, &lease->ia) >= 0); |
859cca44 PF |
412 | |
413 | break; | |
414 | ||
2c1ab8ca | 415 | case SD_DHCP6_OPTION_SERVERID: |
859cca44 PF |
416 | assert_se(optlen == 14); |
417 | assert_se(!memcmp(optval, &msg_advertise[179], optlen)); | |
418 | ||
419 | assert_se(dhcp6_lease_set_serverid(lease, optval, | |
420 | optlen) >= 0); | |
421 | break; | |
422 | ||
2c1ab8ca | 423 | case SD_DHCP6_OPTION_PREFERENCE: |
859cca44 PF |
424 | assert_se(optlen == 1); |
425 | assert_se(!*optval); | |
426 | ||
427 | assert_se(dhcp6_lease_set_preference(lease, | |
428 | *optval) >= 0); | |
429 | break; | |
430 | ||
2c1ab8ca | 431 | case SD_DHCP6_OPTION_ELAPSED_TIME: |
d63be95a PF |
432 | assert_se(optlen == 2); |
433 | ||
434 | break; | |
435 | ||
2c1ab8ca | 436 | case SD_DHCP6_OPTION_DNS_SERVERS: |
bc152ff8 PF |
437 | assert_se(optlen == 16); |
438 | assert_se(dhcp6_lease_set_dns(lease, optval, | |
439 | optlen) >= 0); | |
440 | break; | |
441 | ||
2c1ab8ca | 442 | case SD_DHCP6_OPTION_DOMAIN_LIST: |
bc152ff8 PF |
443 | assert_se(optlen == 11); |
444 | assert_se(dhcp6_lease_set_domains(lease, optval, | |
445 | optlen) >= 0); | |
446 | break; | |
447 | ||
2c1ab8ca | 448 | case SD_DHCP6_OPTION_SNTP_SERVERS: |
bc152ff8 PF |
449 | assert_se(optlen == 16); |
450 | assert_se(dhcp6_lease_set_sntp(lease, optval, | |
451 | optlen) >= 0); | |
452 | break; | |
453 | ||
859cca44 PF |
454 | default: |
455 | break; | |
456 | } | |
859cca44 | 457 | |
3bc424a3 PF |
458 | pos += sizeof(*option) + optlen; |
459 | } | |
859cca44 | 460 | |
3bc424a3 | 461 | assert_se(pos == len); |
859cca44 PF |
462 | assert_se(opt_clientid); |
463 | ||
e7504d95 PF |
464 | sd_dhcp6_lease_reset_address_iter(lease); |
465 | assert_se(sd_dhcp6_lease_get_address(lease, &addr, <_pref, | |
466 | <_valid) >= 0); | |
859cca44 PF |
467 | assert_se(!memcmp(&addr, &msg_advertise[42], sizeof(addr))); |
468 | assert_se(lt_pref == 150); | |
469 | assert_se(lt_valid == 180); | |
e7504d95 PF |
470 | assert_se(sd_dhcp6_lease_get_address(lease, &addr, <_pref, |
471 | <_valid) == -ENOMSG); | |
859cca44 | 472 | |
e7504d95 PF |
473 | sd_dhcp6_lease_reset_address_iter(lease); |
474 | assert_se(sd_dhcp6_lease_get_address(lease, &addr, <_pref, | |
475 | <_valid) >= 0); | |
859cca44 | 476 | assert_se(!memcmp(&addr, &msg_advertise[42], sizeof(addr))); |
e7504d95 PF |
477 | assert_se(sd_dhcp6_lease_get_address(lease, &addr, <_pref, |
478 | <_valid) == -ENOMSG); | |
479 | sd_dhcp6_lease_reset_address_iter(lease); | |
480 | assert_se(sd_dhcp6_lease_get_address(lease, &addr, <_pref, | |
481 | <_valid) >= 0); | |
859cca44 | 482 | assert_se(!memcmp(&addr, &msg_advertise[42], sizeof(addr))); |
e7504d95 PF |
483 | assert_se(sd_dhcp6_lease_get_address(lease, &addr, <_pref, |
484 | <_valid) == -ENOMSG); | |
859cca44 PF |
485 | |
486 | assert_se(dhcp6_lease_get_serverid(lease, &opt, &len) >= 0); | |
487 | assert_se(len == 14); | |
488 | assert_se(!memcmp(opt, &msg_advertise[179], len)); | |
489 | ||
490 | assert_se(dhcp6_lease_get_preference(lease, &preference) >= 0); | |
491 | assert_se(preference == 0); | |
492 | ||
bc152ff8 PF |
493 | r = sd_dhcp6_lease_get_dns(lease, &addrs); |
494 | assert_se(r == 1); | |
495 | assert_se(!memcmp(addrs, &msg_advertise[124], r * 16)); | |
496 | ||
497 | r = sd_dhcp6_lease_get_domains(lease, &domains); | |
498 | assert_se(r == 1); | |
499 | assert_se(!strcmp("lab.intra", domains[0])); | |
500 | assert_se(domains[1] == NULL); | |
501 | ||
502 | r = sd_dhcp6_lease_get_ntp_addrs(lease, &addrs); | |
503 | assert_se(r == 1); | |
504 | assert_se(!memcmp(addrs, &msg_advertise[159], r * 16)); | |
505 | ||
859cca44 PF |
506 | return 0; |
507 | } | |
508 | ||
2ea8857e PF |
509 | static int test_hangcheck(sd_event_source *s, uint64_t usec, void *userdata) { |
510 | assert_not_reached("Test case should have completed in 2 seconds"); | |
511 | ||
512 | return 0; | |
513 | } | |
514 | ||
c4e8cedd PF |
515 | static void test_client_solicit_cb(sd_dhcp6_client *client, int event, |
516 | void *userdata) { | |
517 | sd_event *e = userdata; | |
bc152ff8 PF |
518 | sd_dhcp6_lease *lease; |
519 | struct in6_addr *addrs; | |
520 | char **domains; | |
2ea8857e | 521 | |
9a254164 YW |
522 | log_debug("/* %s */", __func__); |
523 | ||
c4e8cedd | 524 | assert_se(e); |
10c9ce61 | 525 | assert_se(event == SD_DHCP6_CLIENT_EVENT_IP_ACQUIRE); |
2ea8857e | 526 | |
bc152ff8 PF |
527 | assert_se(sd_dhcp6_client_get_lease(client, &lease) >= 0); |
528 | ||
529 | assert_se(sd_dhcp6_lease_get_domains(lease, &domains) == 1); | |
530 | assert_se(!strcmp("lab.intra", domains[0])); | |
531 | assert_se(domains[1] == NULL); | |
532 | ||
533 | assert_se(sd_dhcp6_lease_get_dns(lease, &addrs) == 1); | |
534 | assert_se(!memcmp(addrs, &msg_advertise[124], 16)); | |
535 | ||
536 | assert_se(sd_dhcp6_lease_get_ntp_addrs(lease, &addrs) == 1); | |
537 | assert_se(!memcmp(addrs, &msg_advertise[159], 16)); | |
538 | ||
2c1ab8ca | 539 | assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_DNS_SERVERS) == -EBUSY); |
c4e8cedd | 540 | |
c4e8cedd | 541 | sd_event_exit(e, 0); |
2ea8857e PF |
542 | } |
543 | ||
5e256ea7 | 544 | static int test_client_send_reply(DHCP6Message *request) { |
947527f8 PF |
545 | DHCP6Message reply; |
546 | ||
547 | reply.transaction_id = request->transaction_id; | |
548 | reply.type = DHCP6_REPLY; | |
549 | ||
550 | memcpy(msg_reply, &reply.transaction_id, 4); | |
551 | ||
552 | memcpy(&msg_reply[26], test_duid, sizeof(test_duid)); | |
553 | ||
554 | memcpy(&msg_reply[44], &test_iaid, sizeof(test_iaid)); | |
555 | ||
556 | assert_se(write(test_dhcp_fd[1], msg_reply, sizeof(msg_reply)) | |
557 | == sizeof(msg_reply)); | |
558 | ||
5e256ea7 PF |
559 | return 0; |
560 | } | |
561 | ||
3bc424a3 | 562 | static int test_client_verify_request(DHCP6Message *request, size_t len) { |
4afd3348 | 563 | _cleanup_(sd_dhcp6_lease_unrefp) sd_dhcp6_lease *lease = NULL; |
3bc424a3 | 564 | size_t pos = 0; |
d63be95a | 565 | bool found_clientid = false, found_iana = false, found_serverid = false, |
8006aa32 | 566 | found_elapsed_time = false, found_fqdn = false; |
5e256ea7 PF |
567 | struct in6_addr addr; |
568 | be32_t val; | |
569 | uint32_t lt_pref, lt_valid; | |
570 | ||
9a254164 | 571 | log_debug("/* %s */", __func__); |
5e256ea7 | 572 | |
9a254164 | 573 | assert_se(request->type == DHCP6_REQUEST); |
5e256ea7 PF |
574 | assert_se(dhcp6_lease_new(&lease) >= 0); |
575 | ||
3bc424a3 PF |
576 | len -= sizeof(DHCP6Message); |
577 | ||
578 | while (pos < len) { | |
579 | DHCP6Option *option = (DHCP6Option *)&request->options[pos]; | |
580 | uint16_t optcode = be16toh(option->code); | |
581 | uint16_t optlen = be16toh(option->len); | |
582 | uint8_t *optval = option->data; | |
583 | ||
5e256ea7 | 584 | switch(optcode) { |
2c1ab8ca | 585 | case SD_DHCP6_OPTION_CLIENTID: |
5e256ea7 PF |
586 | assert_se(!found_clientid); |
587 | found_clientid = true; | |
588 | ||
589 | assert_se(!memcmp(optval, &test_duid, | |
590 | sizeof(test_duid))); | |
591 | ||
592 | break; | |
593 | ||
2c1ab8ca | 594 | case SD_DHCP6_OPTION_IA_NA: |
5e256ea7 PF |
595 | assert_se(!found_iana); |
596 | found_iana = true; | |
597 | ||
5e256ea7 PF |
598 | assert_se(optlen == 40); |
599 | assert_se(!memcmp(optval, &test_iaid, sizeof(test_iaid))); | |
600 | ||
601 | val = htobe32(80); | |
602 | assert_se(!memcmp(optval + 4, &val, sizeof(val))); | |
603 | ||
604 | val = htobe32(120); | |
605 | assert_se(!memcmp(optval + 8, &val, sizeof(val))); | |
606 | ||
3bc424a3 | 607 | assert_se(!dhcp6_option_parse_ia(option, &lease->ia)); |
5e256ea7 PF |
608 | |
609 | break; | |
610 | ||
2c1ab8ca | 611 | case SD_DHCP6_OPTION_SERVERID: |
5e256ea7 PF |
612 | assert_se(!found_serverid); |
613 | found_serverid = true; | |
614 | ||
615 | assert_se(optlen == 14); | |
616 | assert_se(!memcmp(&msg_advertise[179], optval, optlen)); | |
617 | ||
d63be95a PF |
618 | break; |
619 | ||
2c1ab8ca | 620 | case SD_DHCP6_OPTION_ELAPSED_TIME: |
d63be95a PF |
621 | assert_se(!found_elapsed_time); |
622 | found_elapsed_time = true; | |
623 | ||
624 | assert_se(optlen == 2); | |
625 | ||
8006aa32 SA |
626 | break; |
627 | case SD_DHCP6_OPTION_FQDN: | |
628 | assert_se(!found_fqdn); | |
629 | found_fqdn = true; | |
630 | ||
631 | assert_se(optlen == 17); | |
632 | ||
633 | assert_se(optval[0] == 0x01); | |
634 | assert_se(!memcmp(optval + 1, fqdn_wire, sizeof(fqdn_wire))); | |
5e256ea7 PF |
635 | break; |
636 | } | |
3bc424a3 PF |
637 | |
638 | pos += sizeof(*option) + optlen; | |
5e256ea7 PF |
639 | } |
640 | ||
d63be95a PF |
641 | assert_se(found_clientid && found_iana && found_serverid && |
642 | found_elapsed_time); | |
5e256ea7 | 643 | |
e7504d95 PF |
644 | sd_dhcp6_lease_reset_address_iter(lease); |
645 | assert_se(sd_dhcp6_lease_get_address(lease, &addr, <_pref, | |
646 | <_valid) >= 0); | |
5e256ea7 PF |
647 | assert_se(!memcmp(&addr, &msg_advertise[42], sizeof(addr))); |
648 | assert_se(lt_pref == 150); | |
649 | assert_se(lt_valid == 180); | |
650 | ||
e7504d95 PF |
651 | assert_se(sd_dhcp6_lease_get_address(lease, &addr, <_pref, |
652 | <_valid) == -ENOMSG); | |
5e256ea7 | 653 | |
5e256ea7 PF |
654 | return 0; |
655 | } | |
656 | ||
52efd56a | 657 | static int test_client_send_advertise(DHCP6Message *solicit) { |
5e256ea7 PF |
658 | DHCP6Message advertise; |
659 | ||
660 | advertise.transaction_id = solicit->transaction_id; | |
661 | advertise.type = DHCP6_ADVERTISE; | |
662 | ||
663 | memcpy(msg_advertise, &advertise.transaction_id, 4); | |
664 | ||
665 | memcpy(&msg_advertise[8], test_duid, sizeof(test_duid)); | |
666 | ||
667 | memcpy(&msg_advertise[26], &test_iaid, sizeof(test_iaid)); | |
668 | ||
669 | assert_se(write(test_dhcp_fd[1], msg_advertise, sizeof(msg_advertise)) | |
670 | == sizeof(msg_advertise)); | |
671 | ||
672 | return 0; | |
673 | } | |
674 | ||
3bc424a3 | 675 | static int test_client_verify_solicit(DHCP6Message *solicit, size_t len) { |
d63be95a | 676 | bool found_clientid = false, found_iana = false, |
8006aa32 | 677 | found_elapsed_time = false, found_fqdn = false; |
3bc424a3 | 678 | size_t pos = 0; |
2ea8857e | 679 | |
9a254164 YW |
680 | log_debug("/* %s */", __func__); |
681 | ||
2ea8857e PF |
682 | assert_se(solicit->type == DHCP6_SOLICIT); |
683 | ||
3bc424a3 PF |
684 | len -= sizeof(DHCP6Message); |
685 | ||
686 | while (pos < len) { | |
687 | DHCP6Option *option = (DHCP6Option *)&solicit->options[pos]; | |
688 | uint16_t optcode = be16toh(option->code); | |
689 | uint16_t optlen = be16toh(option->len); | |
690 | uint8_t *optval = option->data; | |
691 | ||
2ea8857e | 692 | switch(optcode) { |
2c1ab8ca | 693 | case SD_DHCP6_OPTION_CLIENTID: |
2ea8857e PF |
694 | assert_se(!found_clientid); |
695 | found_clientid = true; | |
696 | ||
5e256ea7 PF |
697 | assert_se(optlen == sizeof(test_duid)); |
698 | memcpy(&test_duid, optval, sizeof(test_duid)); | |
2ea8857e PF |
699 | |
700 | break; | |
701 | ||
2c1ab8ca | 702 | case SD_DHCP6_OPTION_IA_NA: |
2ea8857e PF |
703 | assert_se(!found_iana); |
704 | found_iana = true; | |
705 | ||
706 | assert_se(optlen == 12); | |
707 | ||
5e256ea7 PF |
708 | memcpy(&test_iaid, optval, sizeof(test_iaid)); |
709 | ||
d63be95a PF |
710 | break; |
711 | ||
2c1ab8ca | 712 | case SD_DHCP6_OPTION_ELAPSED_TIME: |
d63be95a PF |
713 | assert_se(!found_elapsed_time); |
714 | found_elapsed_time = true; | |
715 | ||
716 | assert_se(optlen == 2); | |
717 | ||
8006aa32 SA |
718 | break; |
719 | ||
720 | case SD_DHCP6_OPTION_FQDN: | |
721 | assert_se(!found_fqdn); | |
722 | found_fqdn = true; | |
723 | ||
724 | assert_se(optlen == 17); | |
725 | ||
726 | assert_se(optval[0] == 0x01); | |
727 | assert_se(!memcmp(optval + 1, fqdn_wire, sizeof(fqdn_wire))); | |
728 | ||
2ea8857e PF |
729 | break; |
730 | } | |
3bc424a3 PF |
731 | |
732 | pos += sizeof(*option) + optlen; | |
2ea8857e PF |
733 | } |
734 | ||
3bc424a3 | 735 | assert_se(pos == len); |
d63be95a | 736 | assert_se(found_clientid && found_iana && found_elapsed_time); |
2ea8857e | 737 | |
2ea8857e PF |
738 | return 0; |
739 | } | |
740 | ||
c4e8cedd PF |
741 | static void test_client_information_cb(sd_dhcp6_client *client, int event, |
742 | void *userdata) { | |
743 | sd_event *e = userdata; | |
bc152ff8 PF |
744 | sd_dhcp6_lease *lease; |
745 | struct in6_addr *addrs; | |
c601ebf7 | 746 | struct in6_addr address = { { { 0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x01 } } }; |
bc152ff8 | 747 | char **domains; |
c4e8cedd | 748 | |
9a254164 YW |
749 | log_debug("/* %s */", __func__); |
750 | ||
c4e8cedd | 751 | assert_se(e); |
10c9ce61 | 752 | assert_se(event == SD_DHCP6_CLIENT_EVENT_INFORMATION_REQUEST); |
c4e8cedd | 753 | |
bc152ff8 PF |
754 | assert_se(sd_dhcp6_client_get_lease(client, &lease) >= 0); |
755 | ||
756 | assert_se(sd_dhcp6_lease_get_domains(lease, &domains) == 1); | |
757 | assert_se(!strcmp("lab.intra", domains[0])); | |
758 | assert_se(domains[1] == NULL); | |
759 | ||
760 | assert_se(sd_dhcp6_lease_get_dns(lease, &addrs) == 1); | |
761 | assert_se(!memcmp(addrs, &msg_advertise[124], 16)); | |
762 | ||
763 | assert_se(sd_dhcp6_lease_get_ntp_addrs(lease, &addrs) == 1); | |
764 | assert_se(!memcmp(addrs, &msg_advertise[159], 16)); | |
765 | ||
44598572 PF |
766 | assert_se(sd_dhcp6_client_set_information_request(client, false) == -EBUSY); |
767 | assert_se(sd_dhcp6_client_set_callback(client, NULL, e) >= 0); | |
768 | assert_se(sd_dhcp6_client_stop(client) >= 0); | |
c4e8cedd | 769 | assert_se(sd_dhcp6_client_set_information_request(client, false) >= 0); |
44598572 | 770 | |
c4e8cedd PF |
771 | assert_se(sd_dhcp6_client_set_callback(client, |
772 | test_client_solicit_cb, e) >= 0); | |
773 | ||
c601ebf7 TG |
774 | assert_se(sd_dhcp6_client_set_local_address(client, &address) >= 0); |
775 | ||
c4e8cedd | 776 | assert_se(sd_dhcp6_client_start(client) >= 0); |
3bc424a3 | 777 | |
c4e8cedd PF |
778 | } |
779 | ||
780 | static int test_client_verify_information_request(DHCP6Message *information_request, | |
3bc424a3 | 781 | size_t len) { |
c4e8cedd | 782 | |
4afd3348 | 783 | _cleanup_(sd_dhcp6_lease_unrefp) sd_dhcp6_lease *lease = NULL; |
3bc424a3 | 784 | size_t pos = 0; |
c4e8cedd | 785 | bool found_clientid = false, found_elapsed_time = false; |
c4e8cedd PF |
786 | struct in6_addr addr; |
787 | uint32_t lt_pref, lt_valid; | |
788 | ||
9a254164 | 789 | log_debug("/* %s */", __func__); |
c4e8cedd | 790 | |
9a254164 | 791 | assert_se(information_request->type == DHCP6_INFORMATION_REQUEST); |
c4e8cedd PF |
792 | assert_se(dhcp6_lease_new(&lease) >= 0); |
793 | ||
3bc424a3 PF |
794 | len -= sizeof(DHCP6Message); |
795 | ||
796 | while (pos < len) { | |
797 | DHCP6Option *option = (DHCP6Option *)&information_request->options[pos]; | |
798 | uint16_t optcode = be16toh(option->code); | |
799 | uint16_t optlen = be16toh(option->len); | |
800 | uint8_t *optval = option->data; | |
801 | ||
c4e8cedd | 802 | switch(optcode) { |
2c1ab8ca | 803 | case SD_DHCP6_OPTION_CLIENTID: |
c4e8cedd PF |
804 | assert_se(!found_clientid); |
805 | found_clientid = true; | |
806 | ||
807 | assert_se(optlen == sizeof(test_duid)); | |
808 | memcpy(&test_duid, optval, sizeof(test_duid)); | |
809 | ||
810 | break; | |
811 | ||
2c1ab8ca | 812 | case SD_DHCP6_OPTION_IA_NA: |
c4e8cedd PF |
813 | assert_not_reached("IA TA option must not be present"); |
814 | ||
815 | break; | |
816 | ||
2c1ab8ca | 817 | case SD_DHCP6_OPTION_SERVERID: |
c4e8cedd PF |
818 | assert_not_reached("Server ID option must not be present"); |
819 | ||
820 | break; | |
821 | ||
2c1ab8ca | 822 | case SD_DHCP6_OPTION_ELAPSED_TIME: |
c4e8cedd PF |
823 | assert_se(!found_elapsed_time); |
824 | found_elapsed_time = true; | |
825 | ||
826 | assert_se(optlen == 2); | |
827 | ||
828 | break; | |
829 | } | |
3bc424a3 PF |
830 | |
831 | pos += sizeof(*option) + optlen; | |
c4e8cedd PF |
832 | } |
833 | ||
3bc424a3 | 834 | assert_se(pos == len); |
c4e8cedd PF |
835 | assert_se(found_clientid && found_elapsed_time); |
836 | ||
e7504d95 | 837 | sd_dhcp6_lease_reset_address_iter(lease); |
c4e8cedd | 838 | |
e7504d95 PF |
839 | assert_se(sd_dhcp6_lease_get_address(lease, &addr, <_pref, |
840 | <_valid) == -ENOMSG); | |
c4e8cedd PF |
841 | |
842 | return 0; | |
843 | } | |
844 | ||
2ea8857e PF |
845 | int dhcp6_network_send_udp_socket(int s, struct in6_addr *server_address, |
846 | const void *packet, size_t len) { | |
847 | struct in6_addr mcast = | |
848 | IN6ADDR_ALL_DHCP6_RELAY_AGENTS_AND_SERVERS_INIT; | |
849 | DHCP6Message *message; | |
2ea8857e PF |
850 | |
851 | assert_se(s == test_dhcp_fd[0]); | |
852 | assert_se(server_address); | |
853 | assert_se(packet); | |
854 | assert_se(len > sizeof(DHCP6Message) + 4); | |
2ea8857e PF |
855 | assert_se(IN6_ARE_ADDR_EQUAL(server_address, &mcast)); |
856 | ||
857 | message = (DHCP6Message *)packet; | |
2ea8857e PF |
858 | |
859 | assert_se(message->transaction_id & 0x00ffffff); | |
860 | ||
5e256ea7 | 861 | if (test_client_message_num == 0) { |
3bc424a3 | 862 | test_client_verify_information_request(message, len); |
c4e8cedd PF |
863 | test_client_send_reply(message); |
864 | test_client_message_num++; | |
865 | } else if (test_client_message_num == 1) { | |
3bc424a3 | 866 | test_client_verify_solicit(message, len); |
5e256ea7 PF |
867 | test_client_send_advertise(message); |
868 | test_client_message_num++; | |
c4e8cedd | 869 | } else if (test_client_message_num == 2) { |
3bc424a3 | 870 | test_client_verify_request(message, len); |
5e256ea7 PF |
871 | test_client_send_reply(message); |
872 | test_client_message_num++; | |
873 | } | |
2ea8857e PF |
874 | |
875 | return len; | |
876 | } | |
877 | ||
c4e8cedd PF |
878 | int dhcp6_network_bind_udp_socket(int index, struct in6_addr *local_address) { |
879 | assert_se(index == test_index); | |
da6fe470 | 880 | |
3e29b889 | 881 | if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0, test_dhcp_fd) < 0) |
c4e8cedd | 882 | return -errno; |
2ea8857e | 883 | |
c4e8cedd | 884 | return test_dhcp_fd[0]; |
2ea8857e PF |
885 | } |
886 | ||
887 | static int test_client_solicit(sd_event *e) { | |
888 | sd_dhcp6_client *client; | |
fa94c34b | 889 | usec_t time_now = now(clock_boottime_or_monotonic()); |
c601ebf7 | 890 | struct in6_addr address = { { { 0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x01 } } }; |
7776f2ae | 891 | int val; |
2ea8857e | 892 | |
9a254164 | 893 | log_debug("/* %s */", __func__); |
2ea8857e PF |
894 | |
895 | assert_se(sd_dhcp6_client_new(&client) >= 0); | |
896 | assert_se(client); | |
897 | ||
898 | assert_se(sd_dhcp6_client_attach_event(client, e, 0) >= 0); | |
899 | ||
2f8e7633 | 900 | assert_se(sd_dhcp6_client_set_ifindex(client, test_index) == 0); |
76253e73 DW |
901 | assert_se(sd_dhcp6_client_set_mac(client, (const uint8_t *) &mac_addr, |
902 | sizeof (mac_addr), | |
903 | ARPHRD_ETHER) >= 0); | |
8006aa32 | 904 | assert_se(sd_dhcp6_client_set_fqdn(client, "host.lab.intra") == 1); |
2ea8857e | 905 | |
c4e8cedd | 906 | assert_se(sd_dhcp6_client_get_information_request(client, &val) >= 0); |
7776f2ae PF |
907 | assert_se(val == 0); |
908 | assert_se(sd_dhcp6_client_set_information_request(client, 42) >= 0); | |
c4e8cedd | 909 | assert_se(sd_dhcp6_client_get_information_request(client, &val) >= 0); |
7776f2ae | 910 | assert_se(val); |
c4e8cedd | 911 | |
2ea8857e | 912 | assert_se(sd_dhcp6_client_set_callback(client, |
c4e8cedd | 913 | test_client_information_cb, e) >= 0); |
2ea8857e | 914 | |
fa94c34b | 915 | assert_se(sd_event_add_time(e, &hangcheck, clock_boottime_or_monotonic(), |
2ea8857e PF |
916 | time_now + 2 * USEC_PER_SEC, 0, |
917 | test_hangcheck, NULL) >= 0); | |
918 | ||
c601ebf7 TG |
919 | assert_se(sd_dhcp6_client_set_local_address(client, &address) >= 0); |
920 | ||
2ea8857e PF |
921 | assert_se(sd_dhcp6_client_start(client) >= 0); |
922 | ||
923 | sd_event_loop(e); | |
924 | ||
925 | hangcheck = sd_event_source_unref(hangcheck); | |
926 | ||
927 | assert_se(!sd_dhcp6_client_unref(client)); | |
928 | ||
929 | test_dhcp_fd[1] = safe_close(test_dhcp_fd[1]); | |
930 | ||
931 | return 0; | |
932 | } | |
933 | ||
813e3a6f | 934 | int main(int argc, char *argv[]) { |
4afd3348 | 935 | _cleanup_(sd_event_unrefp) sd_event *e; |
813e3a6f PF |
936 | |
937 | assert_se(sd_event_new(&e) >= 0); | |
938 | ||
6d7c4033 | 939 | test_setup_logging(LOG_DEBUG); |
813e3a6f PF |
940 | |
941 | test_client_basic(e); | |
f12ed3bf | 942 | test_option(e); |
df296124 | 943 | test_option_status(e); |
859cca44 | 944 | test_advertise_option(e); |
2ea8857e | 945 | test_client_solicit(e); |
f12ed3bf | 946 | |
813e3a6f PF |
947 | return 0; |
948 | } |