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