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