summaryrefslogtreecommitdiff
path: root/src/libsystemd-network
diff options
context:
space:
mode:
authorSusant Sahani <ssahani@vmware.com>2019-09-25 05:14:12 +0200
committerYu Watanabe <watanabe.yu+github@gmail.com>2019-10-01 23:52:40 +0900
commit2805536bff6de4001255a3f93b558a1242df0114 (patch)
tree2308627ef978dacd0a9245e933c01370598785be /src/libsystemd-network
parentd90874b4e26c406f264d5fafad8ea2072be88046 (diff)
downloadsystemd-2805536bff6de4001255a3f93b558a1242df0114.tar.gz
network: DHCPv6 client add support for prefix delegation hint
Add support for prefix hint lenth and prefix hint address ``` Frame 43: 177 bytes on wire (1416 bits), 177 bytes captured (1416 bits) on interface 0 Ethernet II, Src: f6:c1:08:4d:45:f1 (f6:c1:08:4d:45:f1), Dst: IPv6mcast_01:00:02 (33:33:00:01:00:02) Internet Protocol Version 6, Src: fe80::d250:c82:7f6e:28d6, Dst: ff02::1:2 User Datagram Protocol, Src Port: 546, Dst Port: 547 DHCPv6 Message type: Solicit (1) Transaction ID: 0x5c7902 Rapid Commit Identity Association for Non-temporary Address Fully Qualified Domain Name Identity Association for Prefix Delegation Option: Identity Association for Prefix Delegation (25) Length: 41 Value: 1b97b1690000000000000000001a0019ffffffffffffffff… IAID: 1b97b169 T1: 0 T2: 0 IA Prefix Option: IA Prefix (26) Length: 25 Value: ffffffffffffffff3c000000000000000000000000000000… Preferred lifetime: infinity Valid lifetime: infinity Prefix length: 60 Prefix address: :: Option Request Client Identifier Elapsed time ```
Diffstat (limited to 'src/libsystemd-network')
-rw-r--r--src/libsystemd-network/dhcp6-internal.h2
-rw-r--r--src/libsystemd-network/dhcp6-option.c20
-rw-r--r--src/libsystemd-network/sd-dhcp6-client.c25
3 files changed, 37 insertions, 10 deletions
diff --git a/src/libsystemd-network/dhcp6-internal.h b/src/libsystemd-network/dhcp6-internal.h
index f28ba68dd1..517e357d3d 100644
--- a/src/libsystemd-network/dhcp6-internal.h
+++ b/src/libsystemd-network/dhcp6-internal.h
@@ -85,7 +85,7 @@ typedef struct DHCP6IA DHCP6IA;
int dhcp6_option_append(uint8_t **buf, size_t *buflen, uint16_t code,
size_t optlen, const void *optval);
int dhcp6_option_append_ia(uint8_t **buf, size_t *buflen, const DHCP6IA *ia);
-int dhcp6_option_append_pd(uint8_t *buf, size_t len, const DHCP6IA *pd);
+int dhcp6_option_append_pd(uint8_t *buf, size_t len, const DHCP6IA *pd, DHCP6Address *hint_pd_prefix);
int dhcp6_option_append_fqdn(uint8_t **buf, size_t *buflen, const char *fqdn);
int dhcp6_option_parse(uint8_t **buf, size_t *buflen, uint16_t *optcode,
size_t *optlen, uint8_t **optvalue);
diff --git a/src/libsystemd-network/dhcp6-option.c b/src/libsystemd-network/dhcp6-option.c
index 017402c53b..ca67559e6f 100644
--- a/src/libsystemd-network/dhcp6-option.c
+++ b/src/libsystemd-network/dhcp6-option.c
@@ -168,9 +168,10 @@ int dhcp6_option_append_fqdn(uint8_t **buf, size_t *buflen, const char *fqdn) {
return r;
}
-int dhcp6_option_append_pd(uint8_t *buf, size_t len, const DHCP6IA *pd) {
+int dhcp6_option_append_pd(uint8_t *buf, size_t len, const DHCP6IA *pd, DHCP6Address *hint_pd_prefix) {
DHCP6Option *option = (DHCP6Option *)buf;
size_t i = sizeof(*option) + sizeof(pd->ia_pd);
+ DHCP6PDPrefixOption *prefix_opt;
DHCP6Address *prefix;
assert_return(buf, -EINVAL);
@@ -183,10 +184,7 @@ int dhcp6_option_append_pd(uint8_t *buf, size_t len, const DHCP6IA *pd) {
option->code = htobe16(SD_DHCP6_OPTION_IA_PD);
memcpy(&option->data, &pd->ia_pd, sizeof(pd->ia_pd));
-
LIST_FOREACH(addresses, prefix, pd->addresses) {
- DHCP6PDPrefixOption *prefix_opt;
-
if (len < i + sizeof(*prefix_opt))
return -ENOBUFS;
@@ -194,9 +192,19 @@ int dhcp6_option_append_pd(uint8_t *buf, size_t len, const DHCP6IA *pd) {
prefix_opt->option.code = htobe16(SD_DHCP6_OPTION_IA_PD_PREFIX);
prefix_opt->option.len = htobe16(sizeof(prefix_opt->iapdprefix));
- memcpy(&prefix_opt->iapdprefix, &prefix->iapdprefix,
- sizeof(struct iapdprefix));
+ memcpy(&prefix_opt->iapdprefix, &prefix->iapdprefix, sizeof(struct iapdprefix));
+ i += sizeof(*prefix_opt);
+ }
+
+ if (hint_pd_prefix && hint_pd_prefix->iapdprefix.prefixlen > 0) {
+ if (len < i + sizeof(*prefix_opt))
+ return -ENOBUFS;
+
+ prefix_opt = (DHCP6PDPrefixOption *)&buf[i];
+ prefix_opt->option.code = htobe16(SD_DHCP6_OPTION_IA_PD_PREFIX);
+ prefix_opt->option.len = htobe16(sizeof(prefix_opt->iapdprefix));
+ memcpy(&prefix_opt->iapdprefix, &hint_pd_prefix->iapdprefix, sizeof(struct iapdprefix));
i += sizeof(*prefix_opt);
}
diff --git a/src/libsystemd-network/sd-dhcp6-client.c b/src/libsystemd-network/sd-dhcp6-client.c
index 9773a067d5..33420fd4c0 100644
--- a/src/libsystemd-network/sd-dhcp6-client.c
+++ b/src/libsystemd-network/sd-dhcp6-client.c
@@ -46,6 +46,7 @@ struct sd_dhcp6_client {
sd_event *event;
int event_priority;
int ifindex;
+ DHCP6Address hint_pd_prefix;
struct in6_addr local_address;
uint8_t mac_addr[MAX_MAC_ADDR_LEN];
size_t mac_addr_len;
@@ -187,6 +188,22 @@ int sd_dhcp6_client_set_mac(
return 0;
}
+int sd_dhcp6_client_set_prefix_delegation_hint(
+ sd_dhcp6_client *client,
+ uint8_t prefixlen,
+ const struct in6_addr *pd_address) {
+
+ assert_return(client, -EINVAL);
+ assert_return(pd_address, -EINVAL);
+
+ assert_return(IN_SET(client->state, DHCP6_STATE_STOPPED), -EBUSY);
+
+ client->hint_pd_prefix.iapdprefix.address = *pd_address;
+ client->hint_pd_prefix.iapdprefix.prefixlen = prefixlen;
+
+ return 0;
+}
+
static int client_ensure_duid(sd_dhcp6_client *client) {
if (client->duid_len != 0)
return 0;
@@ -492,7 +509,7 @@ static int client_send_message(sd_dhcp6_client *client, usec_t time_now) {
}
if (FLAGS_SET(client->request, DHCP6_REQUEST_IA_PD)) {
- r = dhcp6_option_append_pd(opt, optlen, &client->ia_pd);
+ r = dhcp6_option_append_pd(opt, optlen, &client->ia_pd, &client->hint_pd_prefix);
if (r < 0)
return r;
@@ -530,7 +547,7 @@ static int client_send_message(sd_dhcp6_client *client, usec_t time_now) {
}
if (FLAGS_SET(client->request, DHCP6_REQUEST_IA_PD)) {
- r = dhcp6_option_append_pd(opt, optlen, &client->lease->pd);
+ r = dhcp6_option_append_pd(opt, optlen, &client->lease->pd, NULL);
if (r < 0)
return r;
@@ -556,7 +573,7 @@ static int client_send_message(sd_dhcp6_client *client, usec_t time_now) {
}
if (FLAGS_SET(client->request, DHCP6_REQUEST_IA_PD)) {
- r = dhcp6_option_append_pd(opt, optlen, &client->lease->pd);
+ r = dhcp6_option_append_pd(opt, optlen, &client->lease->pd, NULL);
if (r < 0)
return r;
@@ -1537,6 +1554,8 @@ int sd_dhcp6_client_new(sd_dhcp6_client **ret) {
.request = DHCP6_REQUEST_IA_NA,
.fd = -1,
.req_opts_len = ELEMENTSOF(default_req_opts),
+ .hint_pd_prefix.iapdprefix.lifetime_preferred = (be32_t) -1,
+ .hint_pd_prefix.iapdprefix.lifetime_valid = (be32_t) -1,
.req_opts = TAKE_PTR(req_opts),
};