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