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