]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libsystemd-network/test-dhcp6-client.c
fd-uitl: rename PIPE_EBADF → EBADF_PAIR, and add EBADF_TRIPLET
[thirdparty/systemd.git] / src / libsystemd-network / test-dhcp6-client.c
CommitLineData
db9ecf05 1/* SPDX-License-Identifier: LGPL-2.1-or-later */
813e3a6f 2/***
810adae9 3 Copyright © 2014 Intel Corporation. All rights reserved.
813e3a6f
PF
4***/
5
07630cea 6#include <net/ethernet.h>
8f815e8b 7#include <net/if_arp.h>
813e3a6f
PF
8#include <stdbool.h>
9#include <stdio.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
8d71f2b3 16#include "dhcp-identifier.h"
f12ed3bf 17#include "dhcp6-internal.h"
859cca44 18#include "dhcp6-lease-internal.h"
07630cea 19#include "dhcp6-protocol.h"
3ffd4af2 20#include "fd-util.h"
07630cea 21#include "macro.h"
0a970718 22#include "memory-util.h"
07630cea 23#include "socket-util.h"
c43eea9f
BG
24#include "string-util.h"
25#include "strv.h"
6d7c4033 26#include "tests.h"
0a970718 27#include "time-util.h"
813e3a6f 28
1f280191
YW
29#define DHCP6_CLIENT_EVENT_TEST_ADVERTISED 77
30#define IA_ID_BYTES \
31 0x0e, 0xcf, 0xa3, 0x7d
32#define IA_NA_ADDRESS1_BYTES \
33 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef, 0x78, 0xee, 0x1c, 0xf3, 0x09, 0x3c, 0x55, 0xad
34#define IA_NA_ADDRESS2_BYTES \
35 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef, 0x78, 0xee, 0x1c, 0xf3, 0x09, 0x3c, 0x55, 0xae
36#define IA_PD_PREFIX1_BYTES \
37 0x2a, 0x02, 0x81, 0x0d, 0x98, 0x80, 0x37, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
38#define IA_PD_PREFIX2_BYTES \
39 0x2a, 0x02, 0x81, 0x0d, 0x98, 0x80, 0x37, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
40#define DNS1_BYTES \
41 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01
42#define DNS2_BYTES \
43 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02
44#define SNTP1_BYTES \
45 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03
46#define SNTP2_BYTES \
47 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04
48#define NTP1_BYTES \
49 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05
50#define NTP2_BYTES \
51 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06
52#define CLIENT_ID_BYTES \
53 0x00, 0x02, 0x00, 0x00, 0xab, 0x11, 0x61, 0x77, 0x40, 0xde, 0x13, 0x42, 0xc3, 0xa2
54#define SERVER_ID_BYTES \
55 0x00, 0x01, 0x00, 0x01, 0x19, 0x40, 0x5c, 0x53, 0x78, 0x2b, 0xcb, 0xb3, 0x6d, 0x53
56
57static const struct in6_addr local_address =
58 { { { 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, } } };
59static const struct in6_addr mcast_address =
60 IN6ADDR_ALL_DHCP6_RELAY_AGENTS_AND_SERVERS_INIT;
61static const struct in6_addr ia_na_address1 = { { { IA_NA_ADDRESS1_BYTES } } };
62static const struct in6_addr ia_na_address2 = { { { IA_NA_ADDRESS2_BYTES } } };
63static const struct in6_addr ia_pd_prefix1 = { { { IA_PD_PREFIX1_BYTES } } };
64static const struct in6_addr ia_pd_prefix2 = { { { IA_PD_PREFIX2_BYTES } } };
65static const struct in6_addr dns1 = { { { DNS1_BYTES } } };
66static const struct in6_addr dns2 = { { { DNS2_BYTES } } };
67static const struct in6_addr sntp1 = { { { SNTP1_BYTES } } };
68static const struct in6_addr sntp2 = { { { SNTP2_BYTES } } };
69static const struct in6_addr ntp1 = { { { NTP1_BYTES } } };
70static const struct in6_addr ntp2 = { { { NTP2_BYTES } } };
71static const uint8_t client_id[] = { CLIENT_ID_BYTES };
72static const uint8_t server_id[] = { SERVER_ID_BYTES };
73static const struct ether_addr mac = {
74 .ether_addr_octet = { 'A', 'B', 'C', '1', '2', '3' },
813e3a6f 75};
71136404 76static int test_fd[2] = EBADF_PAIR;
1a6c9136 77static int test_ifindex = 42;
1f280191
YW
78static unsigned test_client_sent_message_count = 0;
79static sd_dhcp6_client *client_ref = NULL;
80
68da8adf 81TEST(client_basic) {
1f280191 82 _cleanup_(sd_dhcp6_client_unrefp) sd_dhcp6_client *client = NULL;
7776f2ae 83 int v;
813e3a6f 84
813e3a6f
PF
85 assert_se(sd_dhcp6_client_new(&client) >= 0);
86 assert_se(client);
87
2f8e7633 88 assert_se(sd_dhcp6_client_set_ifindex(client, 15) == 0);
2f8e7633 89 assert_se(sd_dhcp6_client_set_ifindex(client, 42) >= 0);
813e3a6f 90
1f280191 91 assert_se(sd_dhcp6_client_set_mac(client, mac.ether_addr_octet, sizeof(mac), ARPHRD_ETHER) >= 0);
813e3a6f 92
8006aa32
SA
93 assert_se(sd_dhcp6_client_set_fqdn(client, "host") == 1);
94 assert_se(sd_dhcp6_client_set_fqdn(client, "host.domain") == 1);
95 assert_se(sd_dhcp6_client_set_fqdn(client, NULL) == 1);
96 assert_se(sd_dhcp6_client_set_fqdn(client, "~host") == -EINVAL);
97 assert_se(sd_dhcp6_client_set_fqdn(client, "~host.domain") == -EINVAL);
98
fea8c180 99 assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_CLIENTID) == -EINVAL);
612caa26
YW
100 assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_DNS_SERVER) >= 0);
101 assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_NTP_SERVER) >= 0);
102 assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_SNTP_SERVER) >= 0);
103 assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_DOMAIN) >= 0);
fea8c180 104 assert_se(sd_dhcp6_client_set_request_option(client, 10) == -EINVAL);
612caa26
YW
105 assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_NIS_SERVER) >= 0);
106 assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_NISP_SERVER) >= 0);
f697ab35
YW
107 assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_NIS_SERVER) == -EEXIST);
108 assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_NISP_SERVER) == -EEXIST);
da6fe470 109
7776f2ae
PF
110 assert_se(sd_dhcp6_client_set_information_request(client, 1) >= 0);
111 v = 0;
112 assert_se(sd_dhcp6_client_get_information_request(client, &v) >= 0);
113 assert_se(v);
114 assert_se(sd_dhcp6_client_set_information_request(client, 0) >= 0);
115 v = 42;
116 assert_se(sd_dhcp6_client_get_information_request(client, &v) >= 0);
117 assert_se(v == 0);
118
119 v = 0;
120 assert_se(sd_dhcp6_client_get_address_request(client, &v) >= 0);
121 assert_se(v);
122 v = 0;
123 assert_se(sd_dhcp6_client_set_address_request(client, 1) >= 0);
124 assert_se(sd_dhcp6_client_get_address_request(client, &v) >= 0);
125 assert_se(v);
126 v = 42;
127 assert_se(sd_dhcp6_client_set_address_request(client, 1) >= 0);
128 assert_se(sd_dhcp6_client_get_address_request(client, &v) >= 0);
129 assert_se(v);
130
131 assert_se(sd_dhcp6_client_set_address_request(client, 1) >= 0);
132 assert_se(sd_dhcp6_client_set_prefix_delegation(client, 1) >= 0);
133 v = 0;
134 assert_se(sd_dhcp6_client_get_address_request(client, &v) >= 0);
135 assert_se(v);
136 v = 0;
137 assert_se(sd_dhcp6_client_get_prefix_delegation(client, &v) >= 0);
138 assert_se(v);
139
813e3a6f
PF
140 assert_se(sd_dhcp6_client_set_callback(client, NULL, NULL) >= 0);
141
142 assert_se(sd_dhcp6_client_detach_event(client) >= 0);
813e3a6f
PF
143}
144
68da8adf 145TEST(parse_domain) {
1f280191
YW
146 _cleanup_free_ char *domain = NULL;
147 _cleanup_strv_free_ char **list = NULL;
c43eea9f 148 uint8_t *data;
c43eea9f 149
c43eea9f 150 data = (uint8_t []) { 7, 'e', 'x', 'a', 'm', 'p', 'l', 'e', 3, 'c', 'o', 'm', 0 };
1f280191 151 assert_se(dhcp6_option_parse_domainname(data, 13, &domain) >= 0);
c43eea9f
BG
152 assert_se(domain);
153 assert_se(streq(domain, "example.com"));
1f280191 154 domain = mfree(domain);
c43eea9f
BG
155
156 data = (uint8_t []) { 4, 't', 'e', 's', 't' };
1f280191 157 assert_se(dhcp6_option_parse_domainname(data, 5, &domain) >= 0);
c43eea9f
BG
158 assert_se(domain);
159 assert_se(streq(domain, "test"));
1f280191 160 domain = mfree(domain);
c43eea9f
BG
161
162 data = (uint8_t []) { 0 };
1f280191 163 assert_se(dhcp6_option_parse_domainname(data, 1, &domain) < 0);
c43eea9f
BG
164
165 data = (uint8_t []) { 7, 'e', 'x', 'a', 'm', 'p', 'l', 'e', 3, 'c', 'o', 'm', 0,
166 6, 'f', 'o', 'o', 'b', 'a', 'r', 0 };
1f280191 167 assert_se(dhcp6_option_parse_domainname_list(data, 21, &list) >= 0);
c43eea9f
BG
168 assert_se(list);
169 assert_se(streq(list[0], "example.com"));
170 assert_se(streq(list[1], "foobar"));
1f280191
YW
171 assert_se(!list[2]);
172 list = strv_free(list);
c43eea9f
BG
173
174 data = (uint8_t []) { 1, 'a', 0, 20, 'b', 'c' };
1f280191 175 assert_se(dhcp6_option_parse_domainname_list(data, 6, &list) < 0);
c43eea9f
BG
176
177 data = (uint8_t []) { 0 , 0 };
1f280191 178 assert_se(dhcp6_option_parse_domainname_list(data, 2, &list) < 0);
c43eea9f
BG
179}
180
68da8adf 181TEST(option) {
9d2d346a 182 static const uint8_t packet[] = {
e6201049 183 'F', 'O', 'O', 'H', 'O', 'G', 'E',
2c1ab8ca 184 0x00, SD_DHCP6_OPTION_ORO, 0x00, 0x07,
f12ed3bf 185 'A', 'B', 'C', 'D', 'E', 'F', 'G',
2c1ab8ca 186 0x00, SD_DHCP6_OPTION_VENDOR_CLASS, 0x00, 0x09,
f12ed3bf
PF
187 '1', '2', '3', '4', '5', '6', '7', '8', '9',
188 'B', 'A', 'R',
189 };
9d2d346a 190 static const uint8_t result[] = {
e6201049 191 'F', 'O', 'O', 'H', 'O', 'G', 'E',
f12ed3bf
PF
192 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
193 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
194 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
195 'B', 'A', 'R',
196 };
e6201049 197 _cleanup_free_ uint8_t *buf = NULL;
9d2d346a 198 size_t offset, pos, optlen;
b89a3758 199 const uint8_t *optval;
f12ed3bf 200 uint16_t optcode;
f12ed3bf 201
b89a3758 202 assert_se(sizeof(packet) == sizeof(result));
f12ed3bf 203
b89a3758
YW
204 offset = 0;
205 assert_se(dhcp6_option_parse(packet, 0, &offset, &optcode, &optlen, &optval) == -EBADMSG);
f12ed3bf 206
b89a3758
YW
207 offset = 3;
208 assert_se(dhcp6_option_parse(packet, 0, &offset, &optcode, &optlen, &optval) == -EBADMSG);
209
e6201049
YW
210 /* Tests for reading unaligned data. */
211 assert_se(buf = new(uint8_t, sizeof(packet)));
212 for (size_t i = 0; i <= 7; i++) {
213 memcpy(buf, packet + i, sizeof(packet) - i);
214 offset = 7 - i;
215 assert_se(dhcp6_option_parse(buf, sizeof(packet), &offset, &optcode, &optlen, &optval) >= 0);
216
217 assert_se(optcode == SD_DHCP6_OPTION_ORO);
218 assert_se(optlen == 7);
219 assert_se(optval == buf + 11 - i);
220 }
221
222 offset = 7;
b89a3758 223 assert_se(dhcp6_option_parse(packet, sizeof(packet), &offset, &optcode, &optlen, &optval) >= 0);
f12ed3bf 224
2c1ab8ca 225 assert_se(optcode == SD_DHCP6_OPTION_ORO);
f12ed3bf 226 assert_se(optlen == 7);
e6201049 227 assert_se(optval == packet + 11);
b89a3758 228
9d2d346a
YW
229 free(buf);
230 assert_se(buf = memdup(result, sizeof(result)));
e6201049 231 pos = 7;
9d2d346a 232 assert_se(dhcp6_option_append(&buf, &pos, optcode, optlen, optval) >= 0);
f12ed3bf 233
b89a3758
YW
234 assert_se(dhcp6_option_parse(packet, sizeof(packet), &offset, &optcode, &optlen, &optval) >= 0);
235
2c1ab8ca 236 assert_se(optcode == SD_DHCP6_OPTION_VENDOR_CLASS);
f12ed3bf 237 assert_se(optlen == 9);
e6201049 238 assert_se(optval == packet + 22);
b89a3758 239
9d2d346a 240 assert_se(dhcp6_option_append(&buf, &pos, optcode, optlen, optval) >= 0);
f12ed3bf 241
9d2d346a 242 assert_se(memcmp(packet, buf, sizeof(packet)) == 0);
f12ed3bf
PF
243}
244
68da8adf 245TEST(option_status) {
df296124
PF
246 uint8_t option1[] = {
247 /* IA NA */
248 0x00, 0x03, 0x00, 0x12, 0x1a, 0x1d, 0x1a, 0x1d,
249 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x02,
250 /* status option */
251 0x00, 0x0d, 0x00, 0x02, 0x00, 0x01,
252 };
253 static const uint8_t option2[] = {
254 /* IA NA */
255 0x00, 0x03, 0x00, 0x2e, 0x1a, 0x1d, 0x1a, 0x1d,
256 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x02,
257 /* IA Addr */
258 0x00, 0x05, 0x00, 0x1e,
259 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
260 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
261 0x01, 0x02, 0x03, 0x04, 0x0a, 0x0b, 0x0c, 0x0d,
4af39cb8 262 /* IA address status option */
df296124
PF
263 0x00, 0x0d, 0x00, 0x02, 0x00, 0x01,
264 };
265 static const uint8_t option3[] = {
266 /* IA NA */
267 0x00, 0x03, 0x00, 0x34, 0x1a, 0x1d, 0x1a, 0x1d,
268 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x02,
269 /* IA Addr */
270 0x00, 0x05, 0x00, 0x24,
271 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
272 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
273 0x01, 0x02, 0x03, 0x04, 0x0a, 0x0b, 0x0c, 0x0d,
4af39cb8 274 /* IA address status option */
df296124
PF
275 0x00, 0x0d, 0x00, 0x08, 0x00, 0x00, 'f', 'o',
276 'o', 'b', 'a', 'r',
277 };
819c56f6
PF
278 static const uint8_t option4[] = {
279 /* IA PD */
280 0x00, 0x19, 0x00, 0x2f, 0x1a, 0x1d, 0x1a, 0x1d,
281 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x02,
282 /* IA PD Prefix */
283 0x00, 0x1a, 0x00, 0x1f,
284 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
285 0x80, 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe,
286 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
287 0x00,
4af39cb8 288 /* PD prefix status option */
819c56f6
PF
289 0x00, 0x0d, 0x00, 0x02, 0x00, 0x00,
290 };
291 static const uint8_t option5[] = {
292 /* IA PD */
293 0x00, 0x19, 0x00, 0x52, 0x1a, 0x1d, 0x1a, 0x1d,
294 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x02,
295 /* IA PD Prefix #1 */
296 0x00, 0x1a, 0x00, 0x1f,
297 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
298 0x80, 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe,
299 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
300 0x00,
4af39cb8 301 /* PD prefix status option */
819c56f6
PF
302 0x00, 0x0d, 0x00, 0x02, 0x00, 0x00,
303 /* IA PD Prefix #2 */
304 0x00, 0x1a, 0x00, 0x1f,
305 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
306 0x80, 0x20, 0x01, 0x0d, 0xb8, 0xc0, 0x0l, 0xd0,
307 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
308 0x00,
4af39cb8 309 /* PD prefix status option */
819c56f6
PF
310 0x00, 0x0d, 0x00, 0x02, 0x00, 0x00,
311 };
e5b0b87f 312 _cleanup_(dhcp6_ia_freep) DHCP6IA *ia = NULL;
df296124 313 DHCP6Option *option;
469fd57f 314 be32_t iaid;
e5b0b87f 315 int r;
df296124 316
469fd57f
YW
317 memcpy(&iaid, option1 + 4, sizeof(iaid));
318
4af39cb8 319 option = (DHCP6Option*) option1;
df296124
PF
320 assert_se(sizeof(option1) == sizeof(DHCP6Option) + be16toh(option->len));
321
8a895550 322 r = dhcp6_option_parse_ia(NULL, 0, be16toh(option->code), be16toh(option->len), option->data, &ia);
469fd57f
YW
323 assert_se(r == -ENOANO);
324
8a895550
YW
325 r = dhcp6_option_parse_ia(NULL, iaid, be16toh(option->code), be16toh(option->len), option->data, &ia);
326 assert_se(r == -EINVAL);
df296124
PF
327
328 option->len = htobe16(17);
8a895550
YW
329 r = dhcp6_option_parse_ia(NULL, iaid, be16toh(option->code), be16toh(option->len), option->data, &ia);
330 assert_se(r == -EBADMSG);
df296124
PF
331
332 option->len = htobe16(sizeof(DHCP6Option));
8a895550
YW
333 r = dhcp6_option_parse_ia(NULL, iaid, be16toh(option->code), be16toh(option->len), option->data, &ia);
334 assert_se(r == -EBADMSG);
df296124 335
4af39cb8 336 option = (DHCP6Option*) option2;
df296124 337 assert_se(sizeof(option2) == sizeof(DHCP6Option) + be16toh(option->len));
8a895550
YW
338 r = dhcp6_option_parse_ia(NULL, iaid, be16toh(option->code), be16toh(option->len), option->data, &ia);
339 assert_se(r == -ENODATA);
df296124 340
4af39cb8 341 option = (DHCP6Option*) option3;
df296124 342 assert_se(sizeof(option3) == sizeof(DHCP6Option) + be16toh(option->len));
8a895550
YW
343 r = dhcp6_option_parse_ia(NULL, iaid, be16toh(option->code), be16toh(option->len), option->data, &ia);
344 assert_se(r >= 0);
e5b0b87f
YW
345 assert_se(ia);
346 assert_se(ia->addresses);
347 ia = dhcp6_ia_free(ia);
df296124 348
4af39cb8 349 option = (DHCP6Option*) option4;
819c56f6 350 assert_se(sizeof(option4) == sizeof(DHCP6Option) + be16toh(option->len));
e5b0b87f 351 r = dhcp6_option_parse_ia(NULL, iaid, be16toh(option->code), be16toh(option->len), option->data, &ia);
8a895550 352 assert_se(r >= 0);
e5b0b87f
YW
353 assert_se(ia);
354 assert_se(ia->addresses);
355 assert_se(memcmp(&ia->header.id, &option4[4], 4) == 0);
356 assert_se(memcmp(&ia->header.lifetime_t1, &option4[8], 4) == 0);
357 assert_se(memcmp(&ia->header.lifetime_t2, &option4[12], 4) == 0);
358 ia = dhcp6_ia_free(ia);
819c56f6 359
4af39cb8 360 option = (DHCP6Option*) option5;
819c56f6 361 assert_se(sizeof(option5) == sizeof(DHCP6Option) + be16toh(option->len));
e5b0b87f 362 r = dhcp6_option_parse_ia(NULL, iaid, be16toh(option->code), be16toh(option->len), option->data, &ia);
8a895550 363 assert_se(r >= 0);
e5b0b87f
YW
364 assert_se(ia);
365 assert_se(ia->addresses);
366 ia = dhcp6_ia_free(ia);
df296124
PF
367}
368
68da8adf 369TEST(client_parse_message_issue_22099) {
95c514e9 370 static const uint8_t msg[] = {
1f280191
YW
371 /* Message type */
372 DHCP6_MESSAGE_REPLY,
373 /* Transaction ID */
374 0x7c, 0x4c, 0x16,
375 /* Rapid commit */
376 0x00, SD_DHCP6_OPTION_RAPID_COMMIT, 0x00, 0x00,
377 /* NTP servers */
378 0x00, SD_DHCP6_OPTION_NTP_SERVER, 0x00, 0x14,
379 /* NTP server (broken sub option and sub option length) */
380 0x01, 0x00, 0x10, 0x00,
381 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xde, 0x15, 0xc8, 0xff, 0xfe, 0xef, 0x1e, 0x4e,
382 /* Client ID */
383 0x00, SD_DHCP6_OPTION_CLIENTID, 0x00, 0x0e,
384 0x00, 0x02, /* DUID-EN */
385 0x00, 0x00, 0xab, 0x11, /* pen */
386 0x5c, 0x6b, 0x90, 0xec, 0xda, 0x95, 0x15, 0x45, /* id */
387 /* Server ID */
388 0x00, SD_DHCP6_OPTION_SERVERID, 0x00, 0x0a,
389 0x00, 0x03, /* DUID-LL */
390 0x00, 0x01, /* htype */
391 0xdc, 0x15, 0xc8, 0xef, 0x1e, 0x4e, /* haddr */
95c514e9 392 /* preference */
1f280191
YW
393 0x00, SD_DHCP6_OPTION_PREFERENCE, 0x00, 0x01,
394 0x00,
95c514e9 395 /* DNS servers */
f697ab35 396 0x00, SD_DHCP6_OPTION_DNS_SERVER, 0x00, 0x10,
1f280191 397 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xde, 0x15, 0xc8, 0xff, 0xfe, 0xef, 0x1e, 0x4e,
95c514e9 398 /* v6 pcp server */
1f280191
YW
399 0x00, SD_DHCP6_OPTION_V6_PCP_SERVER, 0x00, 0x10,
400 0x2a, 0x02, 0x81, 0x0d, 0x98, 0x80, 0x37, 0x00, 0xde, 0x15, 0xc8, 0xff, 0xfe, 0xef, 0x1e, 0x4e,
95c514e9 401 /* IA_NA */
1f280191
YW
402 0x00, SD_DHCP6_OPTION_IA_NA, 0x00, 0x28,
403 0xcc, 0x59, 0x11, 0x7b, /* iaid */
404 0x00, 0x00, 0x07, 0x08, /* lifetime T1 */
405 0x00, 0x00, 0x0b, 0x40, /* lifetime T2 */
406 /* IA_NA (iaaddr suboption) */
407 0x00, SD_DHCP6_OPTION_IAADDR, 0x00, 0x18,
408 0x2a, 0x02, 0x81, 0x0d, 0x98, 0x80, 0x37, 0x00, 0x6a, 0x05, 0xca, 0xff, 0xfe, 0xf1, 0x51, 0x53, /* address */
409 0x00, 0x00, 0x0e, 0x10, /* preferred lifetime */
410 0x00, 0x00, 0x1c, 0x20, /* valid lifetime */
95c514e9 411 /* IA_PD */
1f280191
YW
412 0x00, SD_DHCP6_OPTION_IA_PD, 0x00, 0x29,
413 0xcc, 0x59, 0x11, 0x7b, /* iaid */
414 0x00, 0x00, 0x07, 0x08, /* lifetime T1 */
415 0x00, 0x00, 0x0b, 0x40, /* lifetime T2 */
416 /* IA_PD (iaprefix suboption) */
417 0x00, SD_DHCP6_OPTION_IA_PD_PREFIX, 0x00, 0x19,
418 0x00, 0x00, 0x0e, 0x10, /* preferred lifetime */
419 0x00, 0x00, 0x1c, 0x20, /* valid lifetime */
420 0x3a, /* prefixlen */
421 0x2a, 0x02, 0x81, 0x0d, 0x98, 0x80, 0x37, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* prefix */
95c514e9
YW
422 };
423 static const uint8_t duid[] = {
424 0x00, 0x00, 0xab, 0x11, 0x5c, 0x6b, 0x90, 0xec, 0xda, 0x95, 0x15, 0x45,
425 };
426 _cleanup_(sd_dhcp6_client_unrefp) sd_dhcp6_client *client = NULL;
427 _cleanup_(sd_dhcp6_lease_unrefp) sd_dhcp6_lease *lease = NULL;
428
95c514e9
YW
429 assert_se(sd_dhcp6_client_new(&client) >= 0);
430 assert_se(sd_dhcp6_client_set_iaid(client, 0xcc59117b) >= 0);
53488ea3 431 assert_se(sd_dhcp6_client_set_duid_raw(client, 2, duid, sizeof(duid)) >= 0);
95c514e9 432
65ece4c8 433 assert_se(dhcp6_lease_new_from_message(client, (const DHCP6Message*) msg, sizeof(msg), NULL, NULL, &lease) >= 0);
95c514e9
YW
434}
435
68870a46
YW
436TEST(client_parse_message_issue_24002) {
437 static const uint8_t msg[] = {
438 /* Message Type */
439 0x07,
440 /* Transaction ID */
441 0x0e, 0xa5, 0x7c,
442 /* Client ID */
443 0x00, SD_DHCP6_OPTION_CLIENTID, 0x00, 0x0e,
444 0x00, 0x02, /* DUID-EN */
445 0x00, 0x00, 0xab, 0x11, /* pen */
446 0x5c, 0x6b, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, /* id */
447 /* Server ID */
448 0x00, 0x02, 0x00, 0x1a,
449 0x00, 0x02, 0x00, 0x00, 0x05, 0x83, 0x30, 0x63, 0x3a, 0x38, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55,
450 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
451 /* IA_PD */
452 0x00, 0x19, 0x00, 0x29,
453 0xaa, 0xbb, 0xcc, 0xdd, /* iaid */
454 0x00, 0x00, 0x03, 0x84, /* lifetime (T1) */
455 0x00, 0x00, 0x05, 0xa0, /* lifetime (T2) */
456 /* IA_PD (iaprefix suboption) */
457 0x00, 0x1a, 0x00, 0x19,
458 0x00, 0x00, 0x07, 0x08, /* preferred lifetime */
459 0x00, 0x00, 0x38, 0x40, /* valid lifetime */
460 0x38, /* prefixlen */
461 0x20, 0x03, 0x00, 0xff, 0xaa, 0xbb, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* prefix */
462 /* Rapid commit */
463 0x00, 0x0e, 0x00, 0x00,
894f4417
YW
464 /* Trailing invalid byte at the end. See issue #28183. */
465 00,
68870a46
YW
466 };
467 static const uint8_t duid[] = {
468 0x00, 0x00, 0xab, 0x11, 0x5c, 0x6b, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
469 };
470 _cleanup_(sd_dhcp6_client_unrefp) sd_dhcp6_client *client = NULL;
471 _cleanup_(sd_dhcp6_lease_unrefp) sd_dhcp6_lease *lease = NULL;
472
473 assert_se(sd_dhcp6_client_new(&client) >= 0);
474 assert_se(sd_dhcp6_client_set_iaid(client, 0xaabbccdd) >= 0);
53488ea3 475 assert_se(sd_dhcp6_client_set_duid_raw(client, 2, duid, sizeof(duid)) >= 0);
68870a46
YW
476
477 assert_se(dhcp6_lease_new_from_message(client, (const DHCP6Message*) msg, sizeof(msg), NULL, NULL, &lease) >= 0);
478}
479
1f280191
YW
480static const uint8_t msg_information_request[] = {
481 /* Message type */
482 DHCP6_MESSAGE_INFORMATION_REQUEST,
483 /* Transaction ID */
484 0x0f, 0xb4, 0xe5,
485 /* MUD URL */
486 /* ORO */
822883b3 487 0x00, SD_DHCP6_OPTION_ORO, 0x00, 0x0c,
f697ab35
YW
488 0x00, SD_DHCP6_OPTION_DNS_SERVER,
489 0x00, SD_DHCP6_OPTION_DOMAIN,
490 0x00, SD_DHCP6_OPTION_SNTP_SERVER,
822883b3 491 0x00, SD_DHCP6_OPTION_INFORMATION_REFRESH_TIME,
0e0c4dae 492 0x00, SD_DHCP6_OPTION_NTP_SERVER,
822883b3 493 0x00, SD_DHCP6_OPTION_INF_MAX_RT,
1f280191
YW
494 /* Client ID */
495 0x00, SD_DHCP6_OPTION_CLIENTID, 0x00, 0x0e,
496 CLIENT_ID_BYTES,
497 /* Extra options */
498 /* Elapsed time */
499 0x00, SD_DHCP6_OPTION_ELAPSED_TIME, 0x00, 0x02,
500 0x00, 0x00,
859cca44
PF
501};
502
1f280191
YW
503static const uint8_t msg_solicit[] = {
504 /* Message type */
505 DHCP6_MESSAGE_SOLICIT,
506 /* Transaction ID */
507 0x0f, 0xb4, 0xe5,
508 /* Rapid commit */
509 0x00, SD_DHCP6_OPTION_RAPID_COMMIT, 0x00, 0x00,
510 /* IA_NA */
511 0x00, SD_DHCP6_OPTION_IA_NA, 0x00, 0x0c,
512 IA_ID_BYTES,
513 0x00, 0x00, 0x00, 0x00, /* lifetime T1 */
514 0x00, 0x00, 0x00, 0x00, /* lifetime T2 */
515 /* IA_PD */
516 0x00, SD_DHCP6_OPTION_IA_PD, 0x00, 0x0c,
517 IA_ID_BYTES,
518 0x00, 0x00, 0x00, 0x00, /* lifetime T1 */
519 0x00, 0x00, 0x00, 0x00, /* lifetime T2 */
520 /* Client FQDN */
521 0x00, SD_DHCP6_OPTION_CLIENT_FQDN, 0x00, 0x11,
522 DHCP6_FQDN_FLAG_S,
523 0x04, 'h', 'o', 's', 't', 0x03, 'l', 'a', 'b', 0x05, 'i', 'n', 't', 'r', 'a', 0x00,
524 /* User Class */
525 /* Vendor Class */
526 /* Vendor Options */
527 /* MUD URL */
528 /* ORO */
822883b3 529 0x00, SD_DHCP6_OPTION_ORO, 0x00, 0x0a,
f697ab35
YW
530 0x00, SD_DHCP6_OPTION_DNS_SERVER,
531 0x00, SD_DHCP6_OPTION_DOMAIN,
532 0x00, SD_DHCP6_OPTION_SNTP_SERVER,
0e0c4dae 533 0x00, SD_DHCP6_OPTION_NTP_SERVER,
822883b3 534 0x00, SD_DHCP6_OPTION_SOL_MAX_RT,
1f280191
YW
535 /* Client ID */
536 0x00, SD_DHCP6_OPTION_CLIENTID, 0x00, 0x0e,
537 CLIENT_ID_BYTES,
538 /* Extra options */
539 /* Elapsed time */
540 0x00, SD_DHCP6_OPTION_ELAPSED_TIME, 0x00, 0x02,
541 0x00, 0x00,
947527f8
PF
542};
543
1f280191
YW
544static const uint8_t msg_request[] = {
545 /* Message type */
546 DHCP6_MESSAGE_REQUEST,
547 /* Transaction ID */
548 0x00, 0x00, 0x00,
549 /* Server ID */
550 0x00, SD_DHCP6_OPTION_SERVERID, 0x00, 0x0e,
551 SERVER_ID_BYTES,
552 /* IA_NA */
553 0x00, SD_DHCP6_OPTION_IA_NA, 0x00, 0x44,
554 IA_ID_BYTES,
555 0x00, 0x00, 0x00, 0x00, /* lifetime T1 */
556 0x00, 0x00, 0x00, 0x00, /* lifetime T2 */
557 /* IA_NA (IAADDR suboption) */
558 0x00, SD_DHCP6_OPTION_IAADDR, 0x00, 0x18,
559 IA_NA_ADDRESS1_BYTES,
560 0x00, 0x00, 0x00, 0x00, /* preferred lifetime */
561 0x00, 0x00, 0x00, 0x00, /* valid lifetime */
562 /* IA_NA (IAADDR suboption) */
563 0x00, SD_DHCP6_OPTION_IAADDR, 0x00, 0x18,
564 IA_NA_ADDRESS2_BYTES,
565 0x00, 0x00, 0x00, 0x00, /* preferred lifetime */
566 0x00, 0x00, 0x00, 0x00, /* valid lifetime */
567 /* IA_PD */
568 0x00, SD_DHCP6_OPTION_IA_PD, 0x00, 0x46,
569 IA_ID_BYTES,
570 0x00, 0x00, 0x00, 0x00, /* lifetime T1 */
571 0x00, 0x00, 0x00, 0x00, /* lifetime T2 */
572 /* IA_PD (IA_PD_PREFIX suboption) */
573 0x00, SD_DHCP6_OPTION_IA_PD_PREFIX, 0x00, 0x19,
574 0x00, 0x00, 0x00, 0x00, /* preferred lifetime */
575 0x00, 0x00, 0x00, 0x00, /* valid lifetime */
576 0x40, /* prefixlen */
577 IA_PD_PREFIX1_BYTES,
578 /* IA_PD (IA_PD_PREFIX suboption) */
579 0x00, SD_DHCP6_OPTION_IA_PD_PREFIX, 0x00, 0x19,
580 0x00, 0x00, 0x00, 0x00, /* preferred lifetime */
581 0x00, 0x00, 0x00, 0x00, /* valid lifetime */
582 0x40, /* prefixlen */
583 IA_PD_PREFIX2_BYTES,
584 /* Client FQDN */
585 0x00, SD_DHCP6_OPTION_CLIENT_FQDN, 0x00, 0x11,
586 DHCP6_FQDN_FLAG_S,
587 0x04, 'h', 'o', 's', 't', 0x03, 'l', 'a', 'b', 0x05, 'i', 'n', 't', 'r', 'a', 0x00,
588 /* User Class */
589 /* Vendor Class */
590 /* Vendor Options */
591 /* MUD URL */
592 /* ORO */
593 0x00, SD_DHCP6_OPTION_ORO, 0x00, 0x08,
f697ab35
YW
594 0x00, SD_DHCP6_OPTION_DNS_SERVER,
595 0x00, SD_DHCP6_OPTION_DOMAIN,
596 0x00, SD_DHCP6_OPTION_SNTP_SERVER,
0e0c4dae 597 0x00, SD_DHCP6_OPTION_NTP_SERVER,
1f280191
YW
598 /* Client ID */
599 0x00, SD_DHCP6_OPTION_CLIENTID, 0x00, 0x0e,
600 CLIENT_ID_BYTES,
601 /* Extra options */
602 /* Elapsed time */
603 0x00, SD_DHCP6_OPTION_ELAPSED_TIME, 0x00, 0x02,
604 0x00, 0x00,
8006aa32
SA
605};
606
b895aa5f 607/* RFC 3315 section 18.1.6. The DHCP6 Release message must include:
608 - transaction id
609 - server identifier
610 - client identifier
611 - all released IA with addresses included
612 - elapsed time (required for all messages).
613 All other options aren't required. */
614static const uint8_t msg_release[] = {
615 /* Message type */
616 DHCP6_MESSAGE_RELEASE,
617 /* Transaction ID */
618 0x00, 0x00, 0x00,
619 /* Server ID */
620 0x00, SD_DHCP6_OPTION_SERVERID, 0x00, 0x0e,
621 SERVER_ID_BYTES,
622 /* IA_NA */
623 0x00, SD_DHCP6_OPTION_IA_NA, 0x00, 0x44,
624 IA_ID_BYTES,
625 0x00, 0x00, 0x00, 0x00, /* lifetime T1 */
626 0x00, 0x00, 0x00, 0x00, /* lifetime T2 */
627 /* IA_NA (IAADDR suboption) */
628 0x00, SD_DHCP6_OPTION_IAADDR, 0x00, 0x18,
629 IA_NA_ADDRESS1_BYTES,
630 0x00, 0x00, 0x00, 0x00, /* preferred lifetime */
631 0x00, 0x00, 0x00, 0x00, /* valid lifetime */
632 /* IA_NA (IAADDR suboption) */
633 0x00, SD_DHCP6_OPTION_IAADDR, 0x00, 0x18,
634 IA_NA_ADDRESS2_BYTES,
635 0x00, 0x00, 0x00, 0x00, /* preferred lifetime */
636 0x00, 0x00, 0x00, 0x00, /* valid lifetime */
637 /* IA_PD */
638 0x00, SD_DHCP6_OPTION_IA_PD, 0x00, 0x46,
639 IA_ID_BYTES,
640 0x00, 0x00, 0x00, 0x00, /* lifetime T1 */
641 0x00, 0x00, 0x00, 0x00, /* lifetime T2 */
642 /* IA_PD (IA_PD_PREFIX suboption) */
643 0x00, SD_DHCP6_OPTION_IA_PD_PREFIX, 0x00, 0x19,
644 0x00, 0x00, 0x00, 0x00, /* preferred lifetime */
645 0x00, 0x00, 0x00, 0x00, /* valid lifetime */
646 0x40, /* prefixlen */
647 IA_PD_PREFIX1_BYTES,
648 /* IA_PD (IA_PD_PREFIX suboption) */
649 0x00, SD_DHCP6_OPTION_IA_PD_PREFIX, 0x00, 0x19,
650 0x00, 0x00, 0x00, 0x00, /* preferred lifetime */
651 0x00, 0x00, 0x00, 0x00, /* valid lifetime */
652 0x40, /* prefixlen */
653 IA_PD_PREFIX2_BYTES,
654 /* Client ID */
655 0x00, SD_DHCP6_OPTION_CLIENTID, 0x00, 0x0e,
656 CLIENT_ID_BYTES,
657 /* Extra options */
658 /* Elapsed time */
659 0x00, SD_DHCP6_OPTION_ELAPSED_TIME, 0x00, 0x02,
660 0x00, 0x00,
661};
662
1f280191
YW
663static const uint8_t msg_reply[] = {
664 /* Message type */
665 DHCP6_MESSAGE_REPLY,
666 /* Transaction ID */
667 0x0f, 0xb4, 0xe5,
668 /* Client ID */
669 0x00, SD_DHCP6_OPTION_CLIENTID, 0x00, 0x0e,
670 CLIENT_ID_BYTES,
671 /* Server ID */
672 0x00, SD_DHCP6_OPTION_SERVERID, 0x00, 0x0e,
673 SERVER_ID_BYTES,
674 /* Rapid commit */
675 0x00, SD_DHCP6_OPTION_RAPID_COMMIT, 0x00, 0x01,
676 0x00,
677 /* IA_NA */
678 0x00, SD_DHCP6_OPTION_IA_NA, 0x00, 0x66,
679 IA_ID_BYTES,
680 0x00, 0x00, 0x00, 0x50, /* lifetime T1 */
681 0x00, 0x00, 0x00, 0x78, /* lifetime T2 */
682 /* IA_NA (IAADDR suboption) */
683 0x00, SD_DHCP6_OPTION_IAADDR, 0x00, 0x18,
684 IA_NA_ADDRESS2_BYTES,
685 0x00, 0x00, 0x00, 0x96, /* preferred lifetime */
686 0x00, 0x00, 0x00, 0xb4, /* valid lifetime */
687 /* IA_NA (IAADDR suboption) */
688 0x00, SD_DHCP6_OPTION_IAADDR, 0x00, 0x18,
689 IA_NA_ADDRESS1_BYTES,
690 0x00, 0x00, 0x00, 0x96, /* preferred lifetime */
691 0x00, 0x00, 0x00, 0xb4, /* valid lifetime */
692 /* IA_NA (status code suboption) */
693 0x00, SD_DHCP6_OPTION_STATUS_CODE, 0x00, 0x1e,
694 0x00, 0x00, /* status code */
695 0x41, 0x6c, 0x6c, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x20, 0x77, 0x65,
696 0x72, 0x65, 0x20, 0x61, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x2e, /* status message */
697 /* IA_PD */
698 0x00, SD_DHCP6_OPTION_IA_PD, 0x00, 0x46,
699 IA_ID_BYTES,
700 0x00, 0x00, 0x00, 0x50, /* lifetime T1 */
701 0x00, 0x00, 0x00, 0x78, /* lifetime T2 */
702 /* IA_PD (IA_PD_PREFIX suboption) */
703 0x00, SD_DHCP6_OPTION_IA_PD_PREFIX, 0x00, 0x19,
704 0x00, 0x00, 0x00, 0x96, /* preferred lifetime */
705 0x00, 0x00, 0x00, 0xb4, /* valid lifetime */
706 0x40, /* prefixlen */
707 IA_PD_PREFIX2_BYTES,
708 /* IA_PD (IA_PD_PREFIX suboption) */
709 0x00, SD_DHCP6_OPTION_IA_PD_PREFIX, 0x00, 0x19,
710 0x00, 0x00, 0x00, 0x96, /* preferred lifetime */
711 0x00, 0x00, 0x00, 0xb4, /* valid lifetime */
712 0x40, /* prefixlen */
713 IA_PD_PREFIX1_BYTES,
714 /* DNS servers */
f697ab35 715 0x00, SD_DHCP6_OPTION_DNS_SERVER, 0x00, 0x20,
1f280191
YW
716 DNS1_BYTES,
717 DNS2_BYTES,
718 /* SNTP servers */
f697ab35 719 0x00, SD_DHCP6_OPTION_SNTP_SERVER, 0x00, 0x20,
1f280191
YW
720 SNTP1_BYTES,
721 SNTP2_BYTES,
722 /* NTP servers */
723 0x00, SD_DHCP6_OPTION_NTP_SERVER, 0x00, 0x37,
724 /* NTP server (address suboption) */
725 0x00, DHCP6_NTP_SUBOPTION_SRV_ADDR, 0x00, 0x10,
726 NTP1_BYTES,
727 /* NTP server (address suboption) */
728 0x00, DHCP6_NTP_SUBOPTION_SRV_ADDR, 0x00, 0x10,
729 NTP2_BYTES,
730 /* NTP server (fqdn suboption) */
731 0x00, DHCP6_NTP_SUBOPTION_SRV_FQDN, 0x00, 0x0b,
732 0x03, 'n', 't', 'p', 0x05, 'i', 'n', 't', 'r', 'a', 0x00,
733 /* Domain list */
f697ab35 734 0x00, SD_DHCP6_OPTION_DOMAIN, 0x00, 0x0b,
1f280191
YW
735 0x03, 'l', 'a', 'b', 0x05, 'i', 'n', 't', 'r', 'a', 0x00,
736 /* Client FQDN */
737 0x00, SD_DHCP6_OPTION_CLIENT_FQDN, 0x00, 0x12,
738 0x01, 0x06, 'c', 'l', 'i', 'e', 'n', 't', 0x03, 'l', 'a', 'b', 0x05, 'i', 'n', 't', 'r', 'a',
739};
859cca44 740
1f280191
YW
741static const uint8_t msg_advertise[] = {
742 /* Message type */
743 DHCP6_MESSAGE_ADVERTISE,
744 /* Transaction ID */
745 0x0f, 0xb4, 0xe5,
746 /* Client ID */
747 0x00, SD_DHCP6_OPTION_CLIENTID, 0x00, 0x0e,
748 CLIENT_ID_BYTES,
749 /* Server ID */
750 0x00, SD_DHCP6_OPTION_SERVERID, 0x00, 0x0e,
751 SERVER_ID_BYTES,
752 /* Preference */
753 0x00, SD_DHCP6_OPTION_PREFERENCE, 0x00, 0x01,
754 0xff,
755 /* IA_NA */
756 0x00, SD_DHCP6_OPTION_IA_NA, 0x00, 0x7a,
757 IA_ID_BYTES,
758 0x00, 0x00, 0x00, 0x50, /* lifetime T1 */
759 0x00, 0x00, 0x00, 0x78, /* lifetime T2 */
760 /* IA_NA (IAADDR suboption) */
761 0x00, SD_DHCP6_OPTION_IAADDR, 0x00, 0x18,
762 IA_NA_ADDRESS2_BYTES, /* address */
763 0x00, 0x00, 0x00, 0x96, /* preferred lifetime */
764 0x00, 0x00, 0x00, 0xb4, /* valid lifetime */
765 /* IA_NA (IAADDR suboption) */
766 0x00, SD_DHCP6_OPTION_IAADDR, 0x00, 0x18,
767 IA_NA_ADDRESS1_BYTES, /* address */
768 0x00, 0x00, 0x00, 0x96, /* preferred lifetime */
769 0x00, 0x00, 0x00, 0xb4, /* valid lifetime */
770 /* IA_NA (status code suboption) */
771 0x00, SD_DHCP6_OPTION_STATUS_CODE, 0x00, 0x32,
772 0x00, 0x00, /* status code */
773 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x28, 0x65, 0x73, 0x29, 0x20, 0x72, 0x65, 0x6e, 0x65,
774 0x77, 0x65, 0x64, 0x2e, 0x20, 0x47, 0x72, 0x65, 0x65, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x20, 0x66,
775 0x72, 0x6f, 0x6d, 0x20, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x74, 0x20, 0x45, 0x61, 0x72, 0x74, 0x68, /* status message */
776 /* IA_PD */
777 0x00, SD_DHCP6_OPTION_IA_PD, 0x00, 0x46,
778 IA_ID_BYTES,
779 0x00, 0x00, 0x00, 0x50, /* lifetime T1 */
780 0x00, 0x00, 0x00, 0x78, /* lifetime T2 */
781 /* IA_PD (IA_PD_PREFIX suboption) */
782 0x00, SD_DHCP6_OPTION_IA_PD_PREFIX, 0x00, 0x19,
783 0x00, 0x00, 0x00, 0x96, /* preferred lifetime */
784 0x00, 0x00, 0x00, 0xb4, /* valid lifetime */
785 0x40, /* prefixlen */
786 IA_PD_PREFIX2_BYTES,
787 /* IA_PD (IA_PD_PREFIX suboption) */
788 0x00, SD_DHCP6_OPTION_IA_PD_PREFIX, 0x00, 0x19,
789 0x00, 0x00, 0x00, 0x96, /* preferred lifetime */
790 0x00, 0x00, 0x00, 0xb4, /* valid lifetime */
791 0x40, /* prefixlen */
792 IA_PD_PREFIX1_BYTES,
793 /* DNS servers */
f697ab35 794 0x00, SD_DHCP6_OPTION_DNS_SERVER, 0x00, 0x20,
1f280191
YW
795 DNS1_BYTES,
796 DNS2_BYTES,
797 /* SNTP servers */
f697ab35 798 0x00, SD_DHCP6_OPTION_SNTP_SERVER, 0x00, 0x20,
1f280191
YW
799 SNTP1_BYTES,
800 SNTP2_BYTES,
801 /* NTP servers */
802 0x00, SD_DHCP6_OPTION_NTP_SERVER, 0x00, 0x37,
803 /* NTP server (address suboption) */
804 0x00, DHCP6_NTP_SUBOPTION_SRV_ADDR, 0x00, 0x10,
805 NTP1_BYTES,
806 /* NTP server (address suboption) */
807 0x00, DHCP6_NTP_SUBOPTION_SRV_ADDR, 0x00, 0x10,
808 NTP2_BYTES,
809 /* NTP server (fqdn suboption) */
810 0x00, DHCP6_NTP_SUBOPTION_SRV_FQDN, 0x00, 0x0b,
811 0x03, 'n', 't', 'p', 0x05, 'i', 'n', 't', 'r', 'a', 0x00,
812 /* Domain list */
f697ab35 813 0x00, SD_DHCP6_OPTION_DOMAIN, 0x00, 0x0b,
1f280191
YW
814 0x03, 'l', 'a', 'b', 0x05, 'i', 'n', 't', 'r', 'a', 0x00,
815 /* Client FQDN */
816 0x00, SD_DHCP6_OPTION_CLIENT_FQDN, 0x00, 0x12,
817 0x01, 0x06, 'c', 'l', 'i', 'e', 'n', 't', 0x03, 'l', 'a', 'b', 0x05, 'i', 'n', 't', 'r', 'a',
818};
859cca44 819
1f280191
YW
820static void test_client_verify_information_request(const DHCP6Message *msg, size_t len) {
821 log_debug("/* %s */", __func__);
469fd57f 822
1f280191
YW
823 assert_se(len == sizeof(msg_information_request));
824 /* The elapsed time value is not deterministic. Skip it. */
825 assert_se(memcmp(msg, msg_information_request, len - sizeof(be16_t)) == 0);
826}
859cca44 827
1f280191
YW
828static void test_client_verify_solicit(const DHCP6Message *msg, size_t len) {
829 log_debug("/* %s */", __func__);
859cca44 830
1f280191
YW
831 assert_se(len == sizeof(msg_solicit));
832 /* The elapsed time value is not deterministic. Skip it. */
833 assert_se(memcmp(msg, msg_solicit, len - sizeof(be16_t)) == 0);
834}
859cca44 835
b895aa5f 836static void test_client_verify_release(const DHCP6Message *msg, size_t len) {
837 log_debug("/* %s */", __func__);
838
839 assert_se(len == sizeof(msg_release));
840 assert_se(msg->type == DHCP6_MESSAGE_RELEASE);
841 /* The transaction ID and elapsed time value are not deterministic. Skip them. */
842 assert_se(memcmp(msg->options, msg_release + offsetof(DHCP6Message, options),
843 len - offsetof(DHCP6Message, options) - sizeof(be16_t)) == 0);
844}
845
1f280191
YW
846static void test_client_verify_request(const DHCP6Message *msg, size_t len) {
847 log_debug("/* %s */", __func__);
859cca44 848
1f280191
YW
849 assert_se(len == sizeof(msg_request));
850 assert_se(msg->type == DHCP6_MESSAGE_REQUEST);
851 /* The transaction ID and elapsed time value are not deterministic. Skip them. */
b895aa5f 852 assert_se(memcmp(msg->options, msg_request + offsetof(DHCP6Message, options),
853 len - offsetof(DHCP6Message, options) - sizeof(be16_t)) == 0);
1f280191 854}
859cca44 855
1f280191
YW
856static void test_lease_common(sd_dhcp6_client *client) {
857 sd_dhcp6_lease *lease;
858 const struct in6_addr *addrs;
859 const char *str;
860 char **strv;
861 uint8_t *id;
862 size_t len;
859cca44 863
1f280191 864 assert_se(sd_dhcp6_client_get_lease(client, &lease) >= 0);
859cca44 865
1f280191
YW
866 assert_se(dhcp6_lease_get_clientid(lease, &id, &len) >= 0);
867 assert_se(memcmp_nn(id, len, client_id, sizeof(client_id)) == 0);
859cca44 868
1f280191
YW
869 assert_se(sd_dhcp6_lease_get_domains(lease, &strv) == 1);
870 assert_se(streq(strv[0], "lab.intra"));
871 assert_se(!strv[1]);
859cca44 872
1f280191
YW
873 assert_se(sd_dhcp6_lease_get_fqdn(lease, &str) >= 0);
874 assert_se(streq(str, "client.lab.intra"));
d63be95a 875
1f280191
YW
876 assert_se(sd_dhcp6_lease_get_dns(lease, &addrs) == 2);
877 assert_se(in6_addr_equal(&addrs[0], &dns1));
878 assert_se(in6_addr_equal(&addrs[1], &dns2));
d63be95a 879
1f280191
YW
880 assert_se(sd_dhcp6_lease_get_ntp_addrs(lease, &addrs) == 2);
881 assert_se(in6_addr_equal(&addrs[0], &ntp1));
882 assert_se(in6_addr_equal(&addrs[1], &ntp2));
bc152ff8 883
1f280191
YW
884 assert_se(sd_dhcp6_lease_get_ntp_fqdn(lease, &strv) == 1);
885 assert_se(streq(strv[0], "ntp.intra"));
886 assert_se(!strv[1]);
bc152ff8 887
1f280191
YW
888 assert_se(lease->sntp_count == 2);
889 assert_se(in6_addr_equal(&lease->sntp[0], &sntp1));
890 assert_se(in6_addr_equal(&lease->sntp[1], &sntp2));
891}
bc152ff8 892
1f280191
YW
893static void test_lease_managed(sd_dhcp6_client *client) {
894 sd_dhcp6_lease *lease;
895 struct in6_addr addr;
d8ec95c7 896 usec_t lt_pref, lt_valid;
1f280191
YW
897 uint8_t *id, prefixlen;
898 size_t len;
859cca44 899
1f280191 900 assert_se(sd_dhcp6_client_get_lease(client, &lease) >= 0);
859cca44 901
1f280191
YW
902 assert_se(dhcp6_lease_get_serverid(lease, &id, &len) >= 0);
903 assert_se(memcmp_nn(id, len, server_id, sizeof(server_id)) == 0);
859cca44 904
fb70992d
YW
905 assert_se(sd_dhcp6_lease_has_address(lease));
906 assert_se(sd_dhcp6_lease_has_pd_prefix(lease));
907
d8ec95c7
YW
908 for (unsigned i = 0; i < 2; i++) {
909 assert_se(sd_dhcp6_lease_address_iterator_reset(lease));
910 assert_se(sd_dhcp6_lease_get_address(lease, &addr) >= 0);
911 assert_se(sd_dhcp6_lease_get_address_lifetime(lease, &lt_pref, &lt_valid) >= 0);
912 assert_se(in6_addr_equal(&addr, &ia_na_address1));
913 assert_se(lt_pref == 150 * USEC_PER_SEC);
914 assert_se(lt_valid == 180 * USEC_PER_SEC);
915 assert_se(sd_dhcp6_lease_address_iterator_next(lease));
916 assert_se(sd_dhcp6_lease_get_address(lease, &addr) >= 0);
917 assert_se(sd_dhcp6_lease_get_address_lifetime(lease, &lt_pref, &lt_valid) >= 0);
918 assert_se(in6_addr_equal(&addr, &ia_na_address2));
919 assert_se(lt_pref == 150 * USEC_PER_SEC);
920 assert_se(lt_valid == 180 * USEC_PER_SEC);
921 assert_se(!sd_dhcp6_lease_address_iterator_next(lease));
922
923 assert_se(sd_dhcp6_lease_pd_iterator_reset(lease));
924 assert_se(sd_dhcp6_lease_get_pd_prefix(lease, &addr, &prefixlen) >= 0);
925 assert_se(sd_dhcp6_lease_get_pd_lifetime(lease, &lt_pref, &lt_valid) >= 0);
926 assert_se(in6_addr_equal(&addr, &ia_pd_prefix1));
927 assert_se(prefixlen == 64);
928 assert_se(lt_pref == 150 * USEC_PER_SEC);
929 assert_se(lt_valid == 180 * USEC_PER_SEC);
930 assert_se(sd_dhcp6_lease_pd_iterator_next(lease));
931 assert_se(sd_dhcp6_lease_get_pd_prefix(lease, &addr, &prefixlen) >= 0);
932 assert_se(sd_dhcp6_lease_get_pd_lifetime(lease, &lt_pref, &lt_valid) >= 0);
933 assert_se(in6_addr_equal(&addr, &ia_pd_prefix2));
934 assert_se(prefixlen == 64);
935 assert_se(lt_pref == 150 * USEC_PER_SEC);
936 assert_se(lt_valid == 180 * USEC_PER_SEC);
937 assert_se(!sd_dhcp6_lease_pd_iterator_next(lease));
938 }
5e256ea7 939
1f280191 940 test_lease_common(client);
5e256ea7
PF
941}
942
1f280191
YW
943static void test_client_callback(sd_dhcp6_client *client, int event, void *userdata) {
944 switch (event) {
945 case SD_DHCP6_CLIENT_EVENT_STOP:
946 log_debug("/* %s (event=stop) */", __func__);
947 return;
2ea8857e 948
1f280191
YW
949 case SD_DHCP6_CLIENT_EVENT_INFORMATION_REQUEST:
950 log_debug("/* %s (event=information-request) */", __func__);
3bc424a3 951
1f280191 952 assert_se(test_client_sent_message_count == 1);
3bc424a3 953
1f280191 954 test_lease_common(client);
2ea8857e 955
1f280191
YW
956 assert_se(sd_dhcp6_client_set_information_request(client, false) >= 0);
957 assert_se(sd_dhcp6_client_start(client) >= 0);
958 assert_se(dhcp6_client_set_transaction_id(client, ((const DHCP6Message*) msg_advertise)->transaction_id) >= 0);
959 break;
2ea8857e 960
1f280191
YW
961 case SD_DHCP6_CLIENT_EVENT_IP_ACQUIRE:
962 log_debug("/* %s (event=ip-acquire) */", __func__);
2ea8857e 963
b895aa5f 964 assert_se(IN_SET(test_client_sent_message_count, 3, 5));
2ea8857e 965
1f280191 966 test_lease_managed(client);
2ea8857e 967
119c00c1
YW
968 switch (test_client_sent_message_count) {
969 case 3:
970 assert_se(sd_dhcp6_client_stop(client) >= 0);
971 assert_se(sd_dhcp6_client_start(client) >= 0);
972 assert_se(dhcp6_client_set_transaction_id(client, ((const DHCP6Message*) msg_reply)->transaction_id) >= 0);
973 break;
974
b895aa5f 975 case 5:
119c00c1
YW
976 assert_se(sd_event_exit(sd_dhcp6_client_get_event(client), 0) >= 0);
977 break;
978
979 default:
980 assert_not_reached();
981 }
982
1f280191 983 break;
5e256ea7 984
1f280191
YW
985 case DHCP6_CLIENT_EVENT_TEST_ADVERTISED: {
986 sd_dhcp6_lease *lease;
987 uint8_t preference;
d63be95a 988
1f280191 989 log_debug("/* %s (event=test-advertised) */", __func__);
d63be95a 990
1f280191 991 assert_se(test_client_sent_message_count == 2);
d63be95a 992
1f280191 993 test_lease_managed(client);
8006aa32 994
1f280191
YW
995 assert_se(sd_dhcp6_client_get_lease(client, &lease) >= 0);
996 assert_se(dhcp6_lease_get_preference(lease, &preference) >= 0);
997 assert_se(preference == 0xff);
8006aa32 998
1f280191
YW
999 assert_se(dhcp6_client_set_transaction_id(client, ((const DHCP6Message*) msg_reply)->transaction_id) >= 0);
1000 break;
2ea8857e 1001 }
1f280191
YW
1002 default:
1003 assert_not_reached();
c4e8cedd 1004 }
c4e8cedd
PF
1005}
1006
1f280191
YW
1007int dhcp6_network_send_udp_socket(int s, struct in6_addr *a, const void *packet, size_t len) {
1008 log_debug("/* %s(count=%u) */", __func__, test_client_sent_message_count);
2ea8857e 1009
1f280191
YW
1010 assert_se(a);
1011 assert_se(in6_addr_equal(a, &mcast_address));
2ea8857e 1012 assert_se(packet);
1f280191
YW
1013 assert_se(len >= sizeof(DHCP6Message));
1014
1015 switch (test_client_sent_message_count) {
1016 case 0:
1017 test_client_verify_information_request(packet, len);
1018 assert_se(write(test_fd[1], msg_reply, sizeof(msg_reply)) == sizeof(msg_reply));
1019 break;
1020
1021 case 1:
1022 test_client_verify_solicit(packet, len);
1023 assert_se(write(test_fd[1], msg_advertise, sizeof(msg_advertise)) == sizeof(msg_advertise));
1024 break;
1025
1026 case 2:
1027 test_client_callback(client_ref, DHCP6_CLIENT_EVENT_TEST_ADVERTISED, NULL);
1028 test_client_verify_request(packet, len);
1029 assert_se(write(test_fd[1], msg_reply, sizeof(msg_reply)) == sizeof(msg_reply));
1030 break;
1031
119c00c1 1032 case 3:
b895aa5f 1033 test_client_verify_release(packet, len);
1034 /* when stopping, dhcp6 client doesn't wait for release server reply */
1035 assert_se(write(test_fd[1], msg_reply, sizeof(msg_reply)) == sizeof(msg_reply));
1036 break;
1037
1038 case 4:
119c00c1
YW
1039 test_client_verify_solicit(packet, len);
1040 assert_se(write(test_fd[1], msg_reply, sizeof(msg_reply)) == sizeof(msg_reply));
1041 break;
1042
1f280191
YW
1043 default:
1044 assert_not_reached();
5e256ea7 1045 }
2ea8857e 1046
1f280191 1047 test_client_sent_message_count++;
2ea8857e
PF
1048 return len;
1049}
1050
1f280191 1051int dhcp6_network_bind_udp_socket(int ifindex, struct in6_addr *a) {
1a6c9136 1052 assert_se(ifindex == test_ifindex);
1f280191
YW
1053 assert_se(a);
1054 assert_se(in6_addr_equal(a, &local_address));
da6fe470 1055
1f280191
YW
1056 assert_se(socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0, test_fd) >= 0);
1057 return TAKE_FD(test_fd[0]);
2ea8857e
PF
1058}
1059
68da8adf 1060TEST(dhcp6_client) {
1f280191
YW
1061 _cleanup_(sd_dhcp6_client_unrefp) sd_dhcp6_client *client = NULL;
1062 _cleanup_(sd_event_unrefp) sd_event *e = NULL;
2ea8857e 1063
1f280191 1064 assert_se(sd_event_new(&e) >= 0);
ba4e0427 1065 assert_se(sd_event_add_time_relative(e, NULL, CLOCK_BOOTTIME,
1f280191 1066 2 * USEC_PER_SEC, 0,
2e37084f 1067 NULL, INT_TO_PTR(-ETIMEDOUT)) >= 0);
2ea8857e 1068
1f280191 1069 assert_se(sd_dhcp6_client_new(&client) >= 0);
2ea8857e 1070 assert_se(sd_dhcp6_client_attach_event(client, e, 0) >= 0);
1a6c9136 1071 assert_se(sd_dhcp6_client_set_ifindex(client, test_ifindex) == 0);
1f280191
YW
1072 assert_se(sd_dhcp6_client_set_local_address(client, &local_address) >= 0);
1073 assert_se(sd_dhcp6_client_set_fqdn(client, "host.lab.intra") >= 0);
1074 assert_se(sd_dhcp6_client_set_iaid(client, unaligned_read_be32((uint8_t[]) { IA_ID_BYTES })) >= 0);
b895aa5f 1075 assert_se(sd_dhcp6_client_set_send_release(client, true) >= 0);
2ea8857e 1076
612caa26
YW
1077 assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_DNS_SERVER) >= 0);
1078 assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_DOMAIN) >= 0);
1079 assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_NTP_SERVER) >= 0);
1080 assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_SNTP_SERVER) >= 0);
1081
1f280191
YW
1082 assert_se(sd_dhcp6_client_set_information_request(client, true) >= 0);
1083 assert_se(sd_dhcp6_client_set_callback(client, test_client_callback, NULL) >= 0);
c601ebf7 1084
2ea8857e
PF
1085 assert_se(sd_dhcp6_client_start(client) >= 0);
1086
1f280191
YW
1087 assert_se(dhcp6_client_set_transaction_id(client, ((const DHCP6Message*) msg_reply)->transaction_id) >= 0);
1088
1089 assert_se(client_ref = sd_dhcp6_client_ref(client));
2ea8857e 1090
1f280191 1091 assert_se(sd_event_loop(e) >= 0);
2ea8857e 1092
b895aa5f 1093 assert_se(test_client_sent_message_count == 5);
2ea8857e 1094
8306912b 1095 assert_se(!sd_dhcp6_client_unref(client_ref));
1f280191 1096 test_fd[1] = safe_close(test_fd[1]);
2ea8857e
PF
1097}
1098
8b50b319
YW
1099static int intro(void) {
1100 assert_se(setenv("SYSTEMD_NETWORK_TEST_MODE", "1", 1) >= 0);
1101 return 0;
1102}
1103
1104DEFINE_TEST_MAIN_WITH_INTRO(LOG_DEBUG, intro);