Merge pull request #9981 from pfl/dhcp6_pd_other_information_quirk

DHCPv6 PD other information quirk
This commit is contained in:
Zbigniew Jędrzejewski-Szmek
2018-09-24 13:02:24 +02:00
committed by GitHub
12 changed files with 355 additions and 135 deletions
-2
View File
@@ -73,8 +73,6 @@ struct DHCP6IA {
struct ia_pd ia_pd;
struct ia_ta ia_ta;
};
sd_event_source *timeout_t1;
sd_event_source *timeout_t2;
LIST_HEAD(DHCP6Address, addresses);
};
@@ -37,7 +37,6 @@ struct sd_dhcp6_lease {
size_t ntp_fqdn_count;
};
int dhcp6_lease_clear_timers(DHCP6IA *ia);
int dhcp6_lease_ia_rebind_expire(const DHCP6IA *ia, uint32_t *expire);
DHCP6IA *dhcp6_lease_free_ia(DHCP6IA *ia);
@@ -50,6 +49,7 @@ int dhcp6_lease_set_rapid_commit(sd_dhcp6_lease *lease);
int dhcp6_lease_get_rapid_commit(sd_dhcp6_lease *lease, bool *rapid_commit);
int dhcp6_lease_get_iaid(sd_dhcp6_lease *lease, be32_t *iaid);
int dhcp6_lease_get_pd_iaid(sd_dhcp6_lease *lease, be32_t *iaid);
int dhcp6_lease_set_dns(sd_dhcp6_lease *lease, uint8_t *optval, size_t optlen);
int dhcp6_lease_set_domains(sd_dhcp6_lease *lease, uint8_t *optval,
+105 -43
View File
@@ -27,6 +27,13 @@
#define MAX_MAC_ADDR_LEN INFINIBAND_ALEN
/* what to request from the server, addresses (IA_NA) and/or prefixes (IA_PD) */
enum {
DHCP6_REQUEST_IA_NA = 1,
DHCP6_REQUEST_IA_TA = 2, /* currently not used */
DHCP6_REQUEST_IA_PD = 4,
};
struct sd_dhcp6_client {
unsigned n_ref;
@@ -40,7 +47,9 @@ struct sd_dhcp6_client {
uint16_t arp_type;
DHCP6IA ia_na;
DHCP6IA ia_pd;
bool prefix_delegation;
sd_event_source *timeout_t1;
sd_event_source *timeout_t2;
int request;
be32_t transaction_id;
usec_t transaction_start;
struct sd_dhcp6_lease *lease;
@@ -325,10 +334,36 @@ int sd_dhcp6_client_set_request_option(sd_dhcp6_client *client, uint16_t option)
return 0;
}
int sd_dhcp6_client_set_prefix_delegation(sd_dhcp6_client *client, bool delegation) {
int sd_dhcp6_client_get_prefix_delegation(sd_dhcp6_client *client, int *delegation) {
assert_return(client, -EINVAL);
assert_return(delegation, -EINVAL);
*delegation = FLAGS_SET(client->request, DHCP6_REQUEST_IA_PD);
return 0;
}
int sd_dhcp6_client_set_prefix_delegation(sd_dhcp6_client *client, int delegation) {
assert_return(client, -EINVAL);
client->prefix_delegation = delegation;
SET_FLAG(client->request, DHCP6_REQUEST_IA_PD, delegation);
return 0;
}
int sd_dhcp6_client_get_address_request(sd_dhcp6_client *client, int *request) {
assert_return(client, -EINVAL);
assert_return(request, -EINVAL);
*request = FLAGS_SET(client->request, DHCP6_REQUEST_IA_NA);
return 0;
}
int sd_dhcp6_client_set_address_request(sd_dhcp6_client *client, int request) {
assert_return(client, -EINVAL);
SET_FLAG(client->request, DHCP6_REQUEST_IA_NA, request);
return 0;
}
@@ -355,12 +390,8 @@ static void client_notify(sd_dhcp6_client *client, int event) {
static void client_set_lease(sd_dhcp6_client *client, sd_dhcp6_lease *lease) {
assert(client);
if (client->lease) {
dhcp6_lease_clear_timers(&client->lease->ia);
sd_dhcp6_lease_unref(client->lease);
}
client->lease = lease;
(void) sd_dhcp6_lease_unref(client->lease);
client->lease = sd_dhcp6_lease_ref(lease);
}
static int client_reset(sd_dhcp6_client *client) {
@@ -374,11 +405,6 @@ static int client_reset(sd_dhcp6_client *client) {
client->transaction_id = 0;
client->transaction_start = 0;
client->ia_na.timeout_t1 =
sd_event_source_unref(client->ia_na.timeout_t1);
client->ia_na.timeout_t2 =
sd_event_source_unref(client->ia_na.timeout_t2);
client->retransmit_time = 0;
client->retransmit_count = 0;
client->timeout_resend = sd_event_source_unref(client->timeout_resend);
@@ -436,9 +462,12 @@ static int client_send_message(sd_dhcp6_client *client, usec_t time_now) {
if (r < 0)
return r;
r = dhcp6_option_append_ia(&opt, &optlen, &client->ia_na);
if (r < 0)
return r;
if (FLAGS_SET(client->request, DHCP6_REQUEST_IA_NA)) {
r = dhcp6_option_append_ia(&opt, &optlen,
&client->ia_na);
if (r < 0)
return r;
}
if (client->fqdn) {
r = dhcp6_option_append_fqdn(&opt, &optlen, client->fqdn);
@@ -446,7 +475,7 @@ static int client_send_message(sd_dhcp6_client *client, usec_t time_now) {
return r;
}
if (client->prefix_delegation) {
if (FLAGS_SET(client->request, DHCP6_REQUEST_IA_PD)) {
r = dhcp6_option_append_pd(opt, optlen, &client->ia_pd);
if (r < 0)
return r;
@@ -471,9 +500,12 @@ static int client_send_message(sd_dhcp6_client *client, usec_t time_now) {
if (r < 0)
return r;
r = dhcp6_option_append_ia(&opt, &optlen, &client->lease->ia);
if (r < 0)
return r;
if (FLAGS_SET(client->request, DHCP6_REQUEST_IA_NA)) {
r = dhcp6_option_append_ia(&opt, &optlen,
&client->lease->ia);
if (r < 0)
return r;
}
if (client->fqdn) {
r = dhcp6_option_append_fqdn(&opt, &optlen, client->fqdn);
@@ -481,7 +513,7 @@ static int client_send_message(sd_dhcp6_client *client, usec_t time_now) {
return r;
}
if (client->prefix_delegation) {
if (FLAGS_SET(client->request, DHCP6_REQUEST_IA_PD)) {
r = dhcp6_option_append_pd(opt, optlen, &client->lease->pd);
if (r < 0)
return r;
@@ -495,9 +527,11 @@ static int client_send_message(sd_dhcp6_client *client, usec_t time_now) {
case DHCP6_STATE_REBIND:
message->type = DHCP6_REBIND;
r = dhcp6_option_append_ia(&opt, &optlen, &client->lease->ia);
if (r < 0)
return r;
if (FLAGS_SET(client->request, DHCP6_REQUEST_IA_NA)) {
r = dhcp6_option_append_ia(&opt, &optlen, &client->lease->ia);
if (r < 0)
return r;
}
if (client->fqdn) {
r = dhcp6_option_append_fqdn(&opt, &optlen, client->fqdn);
@@ -505,7 +539,7 @@ static int client_send_message(sd_dhcp6_client *client, usec_t time_now) {
return r;
}
if (client->prefix_delegation) {
if (FLAGS_SET(client->request, DHCP6_REQUEST_IA_PD)) {
r = dhcp6_option_append_pd(opt, optlen, &client->lease->pd);
if (r < 0)
return r;
@@ -562,8 +596,8 @@ static int client_timeout_t2(sd_event_source *s, uint64_t usec, void *userdata)
assert(client);
assert(client->lease);
client->lease->ia.timeout_t2 =
sd_event_source_unref(client->lease->ia.timeout_t2);
client->timeout_t2 =
sd_event_source_unref(client->timeout_t2);
log_dhcp6_client(client, "Timeout T2");
@@ -579,8 +613,8 @@ static int client_timeout_t1(sd_event_source *s, uint64_t usec, void *userdata)
assert(client);
assert(client->lease);
client->lease->ia.timeout_t1 =
sd_event_source_unref(client->lease->ia.timeout_t1);
client->timeout_t1 =
sd_event_source_unref(client->timeout_t1);
log_dhcp6_client(client, "Timeout T1");
@@ -914,7 +948,7 @@ static int client_parse_message(
if (r < 0 && r != -ENOMSG)
return r;
r = dhcp6_lease_get_iaid(lease, &iaid_lease);
r = dhcp6_lease_get_pd_iaid(lease, &iaid_lease);
if (r < 0)
return r;
@@ -1188,10 +1222,33 @@ static int client_receive_message(
return 0;
}
static int client_get_lifetime(sd_dhcp6_client *client, uint32_t *lifetime_t1,
uint32_t *lifetime_t2) {
assert_return(client, -EINVAL);
assert_return(client->lease, -EINVAL);
if (FLAGS_SET(client->request, DHCP6_REQUEST_IA_NA) && client->lease->ia.addresses) {
*lifetime_t1 = be32toh(client->lease->ia.ia_na.lifetime_t1);
*lifetime_t2 = be32toh(client->lease->ia.ia_na.lifetime_t2);
return 0;
}
if (FLAGS_SET(client->request, DHCP6_REQUEST_IA_PD) && client->lease->pd.addresses) {
*lifetime_t1 = be32toh(client->lease->pd.ia_pd.lifetime_t1);
*lifetime_t2 = be32toh(client->lease->pd.ia_pd.lifetime_t2);
return 0;
}
return -ENOMSG;
}
static int client_start(sd_dhcp6_client *client, enum DHCP6State state) {
int r;
usec_t timeout, time_now;
char time_string[FORMAT_TIMESPAN_MAX];
uint32_t lifetime_t1, lifetime_t2;
assert_return(client, -EINVAL);
assert_return(client->event, -EINVAL);
@@ -1251,57 +1308,58 @@ static int client_start(sd_dhcp6_client *client, enum DHCP6State state) {
case DHCP6_STATE_BOUND:
if (client->lease->ia.ia_na.lifetime_t1 == 0xffffffff ||
client->lease->ia.ia_na.lifetime_t2 == 0xffffffff) {
r = client_get_lifetime(client, &lifetime_t1, &lifetime_t2);
if (r < 0)
goto error;
if (lifetime_t1 == 0xffffffff || lifetime_t2 == 0xffffffff) {
log_dhcp6_client(client, "Infinite T1 0x%08x or T2 0x%08x",
be32toh(client->lease->ia.ia_na.lifetime_t1),
be32toh(client->lease->ia.ia_na.lifetime_t2));
lifetime_t1, lifetime_t2);
return 0;
}
timeout = client_timeout_compute_random(be32toh(client->lease->ia.ia_na.lifetime_t1) * USEC_PER_SEC);
timeout = client_timeout_compute_random(lifetime_t1 * USEC_PER_SEC);
log_dhcp6_client(client, "T1 expires in %s",
format_timespan(time_string, FORMAT_TIMESPAN_MAX, timeout, USEC_PER_SEC));
r = sd_event_add_time(client->event,
&client->lease->ia.timeout_t1,
&client->timeout_t1,
clock_boottime_or_monotonic(), time_now + timeout,
10 * USEC_PER_SEC, client_timeout_t1,
client);
if (r < 0)
goto error;
r = sd_event_source_set_priority(client->lease->ia.timeout_t1,
r = sd_event_source_set_priority(client->timeout_t1,
client->event_priority);
if (r < 0)
goto error;
r = sd_event_source_set_description(client->lease->ia.timeout_t1, "dhcp6-t1-timeout");
r = sd_event_source_set_description(client->timeout_t1, "dhcp6-t1-timeout");
if (r < 0)
goto error;
timeout = client_timeout_compute_random(be32toh(client->lease->ia.ia_na.lifetime_t2) * USEC_PER_SEC);
timeout = client_timeout_compute_random(lifetime_t2 * USEC_PER_SEC);
log_dhcp6_client(client, "T2 expires in %s",
format_timespan(time_string, FORMAT_TIMESPAN_MAX, timeout, USEC_PER_SEC));
r = sd_event_add_time(client->event,
&client->lease->ia.timeout_t2,
&client->timeout_t2,
clock_boottime_or_monotonic(), time_now + timeout,
10 * USEC_PER_SEC, client_timeout_t2,
client);
if (r < 0)
goto error;
r = sd_event_source_set_priority(client->lease->ia.timeout_t2,
r = sd_event_source_set_priority(client->timeout_t2,
client->event_priority);
if (r < 0)
goto error;
r = sd_event_source_set_description(client->lease->ia.timeout_t2, "dhcp6-t2-timeout");
r = sd_event_source_set_description(client->timeout_t2, "dhcp6-t2-timeout");
if (r < 0)
goto error;
@@ -1363,6 +1421,9 @@ int sd_dhcp6_client_start(sd_dhcp6_client *client) {
if (!IN_SET(client->state, DHCP6_STATE_STOPPED))
return -EBUSY;
if (!client->information_request && !client->request)
return -EINVAL;
r = client_reset(client);
if (r < 0)
return r;
@@ -1461,6 +1522,7 @@ int sd_dhcp6_client_new(sd_dhcp6_client **ret) {
client->ia_na.type = SD_DHCP6_OPTION_IA_NA;
client->ia_pd.type = SD_DHCP6_OPTION_IA_PD;
client->ifindex = -1;
client->request = DHCP6_REQUEST_IA_NA;
client->fd = -1;
client->req_opts_len = ELEMENTSOF(default_req_opts);
+9 -11
View File
@@ -11,15 +11,6 @@
#include "strv.h"
#include "util.h"
int dhcp6_lease_clear_timers(DHCP6IA *ia) {
assert_return(ia, -EINVAL);
ia->timeout_t1 = sd_event_source_unref(ia->timeout_t1);
ia->timeout_t2 = sd_event_source_unref(ia->timeout_t2);
return 0;
}
int dhcp6_lease_ia_rebind_expire(const DHCP6IA *ia, uint32_t *expire) {
DHCP6Address *addr;
uint32_t valid = 0, t;
@@ -48,8 +39,6 @@ DHCP6IA *dhcp6_lease_free_ia(DHCP6IA *ia) {
if (!ia)
return NULL;
dhcp6_lease_clear_timers(ia);
while (ia->addresses) {
address = ia->addresses;
@@ -136,6 +125,15 @@ int dhcp6_lease_get_iaid(sd_dhcp6_lease *lease, be32_t *iaid) {
return 0;
}
int dhcp6_lease_get_pd_iaid(sd_dhcp6_lease *lease, be32_t *iaid) {
assert_return(lease, -EINVAL);
assert_return(iaid, -EINVAL);
*iaid = lease->pd.ia_pd.id;
return 0;
}
int sd_dhcp6_lease_get_address(sd_dhcp6_lease *lease, struct in6_addr *addr,
uint32_t *lifetime_preferred,
uint32_t *lifetime_valid) {
+35 -4
View File
@@ -37,6 +37,7 @@ static uint8_t test_duid[14] = { };
static int test_client_basic(sd_event *e) {
sd_dhcp6_client *client;
int v;
if (verbose)
printf("* %s\n", __FUNCTION__);
@@ -68,6 +69,36 @@ static int test_client_basic(sd_event *e) {
assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_DOMAIN_LIST) == -EEXIST);
assert_se(sd_dhcp6_client_set_request_option(client, 10) == -EINVAL);
assert_se(sd_dhcp6_client_set_information_request(client, 1) >= 0);
v = 0;
assert_se(sd_dhcp6_client_get_information_request(client, &v) >= 0);
assert_se(v);
assert_se(sd_dhcp6_client_set_information_request(client, 0) >= 0);
v = 42;
assert_se(sd_dhcp6_client_get_information_request(client, &v) >= 0);
assert_se(v == 0);
v = 0;
assert_se(sd_dhcp6_client_get_address_request(client, &v) >= 0);
assert_se(v);
v = 0;
assert_se(sd_dhcp6_client_set_address_request(client, 1) >= 0);
assert_se(sd_dhcp6_client_get_address_request(client, &v) >= 0);
assert_se(v);
v = 42;
assert_se(sd_dhcp6_client_set_address_request(client, 1) >= 0);
assert_se(sd_dhcp6_client_get_address_request(client, &v) >= 0);
assert_se(v);
assert_se(sd_dhcp6_client_set_address_request(client, 1) >= 0);
assert_se(sd_dhcp6_client_set_prefix_delegation(client, 1) >= 0);
v = 0;
assert_se(sd_dhcp6_client_get_address_request(client, &v) >= 0);
assert_se(v);
v = 0;
assert_se(sd_dhcp6_client_get_prefix_delegation(client, &v) >= 0);
assert_se(v);
assert_se(sd_dhcp6_client_set_callback(client, NULL, NULL) >= 0);
assert_se(sd_dhcp6_client_detach_event(client) >= 0);
@@ -862,7 +893,7 @@ static int test_client_solicit(sd_event *e) {
sd_dhcp6_client *client;
usec_t time_now = now(clock_boottime_or_monotonic());
struct in6_addr address = { { { 0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x01 } } };
int val = true;
int val;
if (verbose)
printf("* %s\n", __FUNCTION__);
@@ -879,10 +910,10 @@ static int test_client_solicit(sd_event *e) {
assert_se(sd_dhcp6_client_set_fqdn(client, "host.lab.intra") == 1);
assert_se(sd_dhcp6_client_get_information_request(client, &val) >= 0);
assert_se(val == false);
assert_se(sd_dhcp6_client_set_information_request(client, true) >= 0);
assert_se(val == 0);
assert_se(sd_dhcp6_client_set_information_request(client, 42) >= 0);
assert_se(sd_dhcp6_client_get_information_request(client, &val) >= 0);
assert_se(val == true);
assert_se(val);
assert_se(sd_dhcp6_client_set_callback(client,
test_client_information_cb, e) >= 0);
+145 -39
View File
@@ -103,12 +103,77 @@ static int dhcp6_pd_prefix_assign(Link *link, struct in6_addr *prefix,
return sd_radv_start(radv);
}
static Network *dhcp6_reset_pd_prefix_network(Link *link) {
assert(link);
assert(link->manager);
assert(link->manager->networks);
static int dhcp6_route_remove_cb(sd_netlink *nl, sd_netlink_message *m,
void *userdata) {
Link *l = userdata;
int r;
return link->manager->networks;
r = sd_netlink_message_get_errno(m);
if (r < 0)
log_link_debug_errno(l, r, "Received error on unreachable route removal for DHCPv6 delegated subnetl: %m");
l = link_unref(l);
return 0;
}
int dhcp6_lease_pd_prefix_lost(sd_dhcp6_client *client, Link* link) {
int r;
sd_dhcp6_lease *lease;
union in_addr_union pd_prefix;
uint8_t pd_prefix_len;
uint32_t lifetime_preferred, lifetime_valid;
r = sd_dhcp6_client_get_lease(client, &lease);
if (r < 0)
return r;
sd_dhcp6_lease_reset_pd_prefix_iter(lease);
while (sd_dhcp6_lease_get_pd(lease, &pd_prefix.in6, &pd_prefix_len,
&lifetime_preferred,
&lifetime_valid) >= 0) {
_cleanup_free_ char *buf = NULL;
_cleanup_free_ Route *route;
if (pd_prefix_len > 64)
continue;
(void) in_addr_to_string(AF_INET6, &pd_prefix, &buf);
if (pd_prefix_len < 64) {
r = route_new(&route);
if (r < 0) {
log_link_warning_errno(link, r, "Cannot create unreachable route to delete for DHCPv6 delegated subnet %s/%u: %m",
strnull(buf),
pd_prefix_len);
continue;
}
route_add(link, AF_INET6, &pd_prefix, pd_prefix_len,
0, 0, 0, &route);
route_update(route, NULL, 0, NULL, NULL, 0, 0,
RTN_UNREACHABLE);
r = route_remove(route, link, dhcp6_route_remove_cb);
if (r < 0) {
(void) in_addr_to_string(AF_INET6,
&pd_prefix, &buf);
log_link_warning_errno(link, r, "Cannot delete unreachable route for DHCPv6 delegated subnet %s/%u: %m",
strnull(buf),
pd_prefix_len);
route_free(route);
continue;
}
link = link_ref(link);
log_link_debug(link, "Removing unreachable route %s/%u",
strnull(buf), pd_prefix_len);
}
}
return 0;
}
static int dhcp6_pd_prefix_distribute(Link *dhcp6_link, Iterator *i,
@@ -184,39 +249,28 @@ static int dhcp6_pd_prefix_distribute(Link *dhcp6_link, Iterator *i,
return r;
}
if (n_used < n_prefixes) {
Route *route;
uint64_t n = n_used;
r = route_new(&route);
if (r < 0)
return r;
route->family = AF_INET6;
while (n < n_prefixes) {
route_update(route, &prefix, pd_prefix_len, NULL, NULL,
0, 0, RTN_UNREACHABLE);
r = route_configure(route, dhcp6_link, NULL);
if (r < 0) {
route_free(route);
return r;
}
r = in_addr_prefix_next(AF_INET6, &prefix, pd_prefix_len);
if (r < 0)
return r;
}
}
return n_used;
return 0;
}
static int dhcp6_route_add_cb(sd_netlink *nl, sd_netlink_message *m,
void *userdata) {
Link *l = userdata;
int r;
r = sd_netlink_message_get_errno(m);
if (r < 0 && r != -EEXIST)
log_link_debug_errno(l, r, "Received error when adding unreachable route for DHCPv6 delegated subnet: %m");
l = link_unref(l);
return 0;
}
static int dhcp6_lease_pd_prefix_acquired(sd_dhcp6_client *client, Link *link) {
int r;
sd_dhcp6_lease *lease;
struct in6_addr pd_prefix;
union in_addr_union pd_prefix;
uint8_t pd_prefix_len;
uint32_t lifetime_preferred, lifetime_valid;
_cleanup_free_ char *buf = NULL;
@@ -226,27 +280,62 @@ static int dhcp6_lease_pd_prefix_acquired(sd_dhcp6_client *client, Link *link) {
if (r < 0)
return r;
dhcp6_reset_pd_prefix_network(link);
sd_dhcp6_lease_reset_pd_prefix_iter(lease);
while (sd_dhcp6_lease_get_pd(lease, &pd_prefix, &pd_prefix_len,
while (sd_dhcp6_lease_get_pd(lease, &pd_prefix.in6, &pd_prefix_len,
&lifetime_preferred,
&lifetime_valid) >= 0) {
if (pd_prefix_len > 64) {
(void) in_addr_to_string(AF_INET6, (union in_addr_union*) &pd_prefix, &buf);
(void) in_addr_to_string(AF_INET6, &pd_prefix, &buf);
log_link_debug(link, "PD Prefix length > 64, ignoring prefix %s/%u",
strnull(buf), pd_prefix_len);
continue;
}
if (pd_prefix_len < 48) {
(void) in_addr_to_string(AF_INET6, (union in_addr_union*) &pd_prefix, &buf);
(void) in_addr_to_string(AF_INET6, &pd_prefix, &buf);
log_link_warning(link, "PD Prefix length < 48, looks unusual %s/%u",
strnull(buf), pd_prefix_len);
}
r = dhcp6_pd_prefix_distribute(link, &i, &pd_prefix,
if (pd_prefix_len < 64) {
Route *route = NULL;
(void) in_addr_to_string(AF_INET6, &pd_prefix, &buf);
r = route_new(&route);
if (r < 0) {
log_link_warning_errno(link, r, "Cannot create unreachable route for DHCPv6 delegated subnet %s/%u: %m",
strnull(buf),
pd_prefix_len);
continue;
}
route_add(link, AF_INET6, &pd_prefix, pd_prefix_len,
0, 0, 0, &route);
route_update(route, NULL, 0, NULL, NULL, 0, 0,
RTN_UNREACHABLE);
r = route_configure(route, link, dhcp6_route_add_cb);
if (r < 0) {
log_link_warning_errno(link, r, "Cannot configure unreachable route for delegated subnet %s/%u: %m",
strnull(buf),
pd_prefix_len);
route_free(route);
continue;
}
link = link_ref(link);
route_free(route);
log_link_debug(link, "Configuring unreachable route for %s/%u",
strnull(buf), pd_prefix_len);
} else
log_link_debug(link, "Not adding a blocking route since distributed prefix is /64");
r = dhcp6_pd_prefix_distribute(link, &i, &pd_prefix.in6,
pd_prefix_len,
lifetime_preferred,
lifetime_valid);
@@ -364,6 +453,7 @@ static void dhcp6_handler(sd_dhcp6_client *client, int event, void *userdata) {
if (sd_dhcp6_client_get_lease(client, NULL) >= 0)
log_link_warning(link, "DHCPv6 lease lost");
(void) dhcp6_lease_pd_prefix_lost(client, link);
(void) manager_dhcp6_prefix_remove_all(link->manager, link);
link->dhcp6_configured = false;
@@ -403,11 +493,12 @@ static void dhcp6_handler(sd_dhcp6_client *client, int event, void *userdata) {
}
int dhcp6_request_address(Link *link, int ir) {
int r, inf_req;
int r, inf_req, pd;
bool running;
assert(link);
assert(link->dhcp6_client);
assert(link->network);
assert(in_addr_is_link_local(AF_INET6, (const union in_addr_union*)&link->ipv6ll_address) > 0);
r = sd_dhcp6_client_is_running(link->dhcp6_client);
@@ -416,6 +507,21 @@ int dhcp6_request_address(Link *link, int ir) {
else
running = r;
r = sd_dhcp6_client_get_prefix_delegation(link->dhcp6_client, &pd);
if (r < 0)
return r;
if (pd && ir && link->network->dhcp6_force_pd_other_information) {
log_link_debug(link, "Enabling managed mode to request DHCPv6 PD with 'Other Information' set");
r = sd_dhcp6_client_set_address_request(link->dhcp6_client,
false);
if (r < 0 )
return r;
ir = false;
}
if (running) {
r = sd_dhcp6_client_get_information_request(link->dhcp6_client, &inf_req);
if (r < 0)
+1
View File
@@ -165,6 +165,7 @@ int dhcp4_set_client_identifier(Link *link);
int dhcp4_set_promote_secondaries(Link *link);
int dhcp6_configure(Link *link);
int dhcp6_request_address(Link *link, int ir);
int dhcp6_lease_pd_prefix_lost(sd_dhcp6_client *client, Link* link);
const char* link_state_to_string(LinkState s) _const_;
LinkState link_state_from_string(const char *s) _pure_;
+32 -33
View File
@@ -1240,27 +1240,15 @@ Link *manager_dhcp6_prefix_get(Manager *m, struct in6_addr *addr) {
}
static int dhcp6_route_add_callback(sd_netlink *nl, sd_netlink_message *m,
void *userdata) {
void *userdata) {
Link *l = userdata;
int r;
union in_addr_union prefix;
_cleanup_free_ char *buf = NULL;
r = sd_netlink_message_get_errno(m);
if (r != 0) {
if (r < 0 && r != -EEXIST)
log_link_debug_errno(l, r, "Received error adding DHCPv6 Prefix Delegation route: %m");
return 0;
}
r = sd_netlink_message_read_in6_addr(m, RTA_DST, &prefix.in6);
if (r < 0) {
log_link_debug_errno(l, r, "Could not read IPv6 address from DHCPv6 Prefix Delegation while adding route: %m");
return 0;
}
(void) in_addr_to_string(AF_INET6, &prefix, &buf);
log_link_debug(l, "Added DHCPv6 Prefix Deleagtion route %s/64",
strnull(buf));
l = link_unref(l);
return 0;
}
@@ -1268,6 +1256,7 @@ static int dhcp6_route_add_callback(sd_netlink *nl, sd_netlink_message *m,
int manager_dhcp6_prefix_add(Manager *m, struct in6_addr *addr, Link *link) {
int r;
Route *route;
_cleanup_free_ char *buf = NULL;
assert_return(m, -EINVAL);
assert_return(m->dhcp6_prefixes, -ENODATA);
@@ -1282,6 +1271,11 @@ int manager_dhcp6_prefix_add(Manager *m, struct in6_addr *addr, Link *link) {
if (r < 0)
return r;
(void) in_addr_to_string(AF_INET6, (union in_addr_union *) addr, &buf);
log_link_debug(link, "Adding prefix route %s/64", strnull(buf));
link = link_ref(link);
return hashmap_put(m->dhcp6_prefixes, addr, link);
}
@@ -1289,24 +1283,12 @@ static int dhcp6_route_remove_callback(sd_netlink *nl, sd_netlink_message *m,
void *userdata) {
Link *l = userdata;
int r;
union in_addr_union prefix;
_cleanup_free_ char *buf = NULL;
r = sd_netlink_message_get_errno(m);
if (r != 0) {
if (r < 0)
log_link_debug_errno(l, r, "Received error on DHCPv6 Prefix Delegation route removal: %m");
return 0;
}
r = sd_netlink_message_read_in6_addr(m, RTA_DST, &prefix.in6);
if (r < 0) {
log_link_debug_errno(l, r, "Could not read IPv6 address from DHCPv6 Prefix Delegation while removing route: %m");
return 0;
}
(void) in_addr_to_string(AF_INET6, &prefix, &buf);
log_link_debug(l, "Removed DHCPv6 Prefix Delegation route %s/64",
strnull(buf));
l = link_unref(l);
return 0;
}
@@ -1315,6 +1297,7 @@ int manager_dhcp6_prefix_remove(Manager *m, struct in6_addr *addr) {
Link *l;
int r;
Route *route;
_cleanup_free_ char *buf = NULL;
assert_return(m, -EINVAL);
assert_return(m->dhcp6_prefixes, -ENODATA);
@@ -1327,8 +1310,17 @@ int manager_dhcp6_prefix_remove(Manager *m, struct in6_addr *addr) {
(void) sd_radv_remove_prefix(l->radv, addr, 64);
r = route_get(l, AF_INET6, (union in_addr_union *) addr, 64,
0, 0, 0, &route);
if (r >= 0)
(void) route_remove(route, l, dhcp6_route_remove_callback);
if (r < 0)
return r;
r = route_remove(route, l, dhcp6_route_remove_callback);
if (r < 0)
return r;
(void) in_addr_to_string(AF_INET6, (union in_addr_union *) addr, &buf);
log_link_debug(l, "Removing prefix route %s/64", strnull(buf));
l = link_ref(l);
return 0;
}
@@ -1452,11 +1444,18 @@ void manager_free(Manager *m) {
network_free(network);
while ((link = hashmap_first(m->dhcp6_prefixes)))
link_unref(link);
manager_dhcp6_prefix_remove_all(m, link);
hashmap_free(m->dhcp6_prefixes);
while ((link = hashmap_first(m->links)))
while ((link = hashmap_first(m->links))) {
if (link->dhcp6_client)
(void) dhcp6_lease_pd_prefix_lost(link->dhcp6_client,
link);
hashmap_remove(m->links, INT_TO_PTR(link->ifindex));
link_unref(link);
}
hashmap_free(m->links);
set_free(m->links_requesting_uuid);
+1
View File
@@ -138,6 +138,7 @@ DHCP.UseTimezone, config_parse_bool,
DHCP.IAID, config_parse_iaid, 0, offsetof(Network, iaid)
DHCP.ListenPort, config_parse_uint16, 0, offsetof(Network, dhcp_client_port)
DHCP.RapidCommit, config_parse_bool, 0, offsetof(Network, rapid_commit)
DHCP.ForceDHCPv6PDOtherInformation, config_parse_bool, 0, offsetof(Network, dhcp6_force_pd_other_information)
IPv6AcceptRA.UseDNS, config_parse_bool, 0, offsetof(Network, ipv6_accept_ra_use_dns)
IPv6AcceptRA.UseDomains, config_parse_dhcp_use_domains, 0, offsetof(Network, ipv6_accept_ra_use_domains)
IPv6AcceptRA.RouteTable, config_parse_uint32, 0, offsetof(Network, ipv6_accept_ra_route_table)
+3
View File
@@ -171,6 +171,9 @@ struct Network {
struct in6_addr *router_dns;
unsigned n_router_dns;
char **router_search_domains;
bool dhcp6_force_pd_other_information; /* Start DHCPv6 PD also when 'O'
RA flag is set, see RFC 7084,
WPD-4 */
/* Bridge Support */
int use_bpdu;
+7 -2
View File
@@ -21,7 +21,6 @@
#include <inttypes.h>
#include <net/ethernet.h>
#include <stdbool.h>
#include <sys/types.h>
#include "sd-dhcp6-lease.h"
@@ -120,8 +119,14 @@ int sd_dhcp6_client_get_information_request(
int sd_dhcp6_client_set_request_option(
sd_dhcp6_client *client,
uint16_t option);
int sd_dhcp6_client_get_prefix_delegation(sd_dhcp6_client *client,
int *delegation);
int sd_dhcp6_client_set_prefix_delegation(sd_dhcp6_client *client,
bool delegation);
int delegation);
int sd_dhcp6_client_get_address_request(sd_dhcp6_client *client,
int *request);
int sd_dhcp6_client_set_address_request(sd_dhcp6_client *client,
int request);
int sd_dhcp6_client_get_lease(
sd_dhcp6_client *client,