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