diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/network/networkd-address.c | 2 | ||||
-rw-r--r-- | src/network/networkd-dhcp6.c | 66 | ||||
-rw-r--r-- | src/network/networkd-link.c | 1 | ||||
-rw-r--r-- | src/network/networkd-link.h | 1 |
4 files changed, 67 insertions, 3 deletions
diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c index a3aa1f7fdb..069ba3eccb 100644 --- a/src/network/networkd-address.c +++ b/src/network/networkd-address.c @@ -215,7 +215,7 @@ int address_update(Address *address, Link *link, if (r < 0) return log_error_errno(r, "Could not set flags: %m"); - if (address->flags & ~0xff) { + if (address->flags & ~0xff && link->rtnl_extended_attrs) { r = sd_rtnl_message_append_u32(req, IFA_FLAGS, address->flags); if (r < 0) return log_error_errno(r, "Could not set extended flags: %m"); diff --git a/src/network/networkd-dhcp6.c b/src/network/networkd-dhcp6.c index e863f4b347..5668fdf16c 100644 --- a/src/network/networkd-dhcp6.c +++ b/src/network/networkd-dhcp6.c @@ -28,6 +28,8 @@ #include "sd-icmp6-nd.h" #include "sd-dhcp6-client.h" +static int dhcp6_lease_address_acquired(sd_dhcp6_client *client, Link *link); + static int dhcp6_lease_information_acquired(sd_dhcp6_client *client, Link *link) { return 0; @@ -42,6 +44,15 @@ static int dhcp6_address_handler(sd_rtnl *rtnl, sd_rtnl_message *m, r = sd_rtnl_message_get_errno(m); if (r < 0 && r != -EEXIST) { + if (link->rtnl_extended_attrs) { + log_link_warning(link, "Could not set extended netlink attributes, reverting to fallback mechanism"); + + link->rtnl_extended_attrs = false; + dhcp6_lease_address_acquired(link->dhcp6_client, link); + + return 1; + } + log_link_error(link, "Could not set DHCPv6 address: %s", strerror(-r)); @@ -67,7 +78,7 @@ static int dhcp6_address_update(Link *link, struct in6_addr *ip6_addr, memcpy(&addr->in_addr.in6, ip6_addr, sizeof(*ip6_addr)); addr->flags = IFA_F_NOPREFIXROUTE; - addr->prefixlen = 64; + addr->prefixlen = prefixlen; addr->cinfo.ifa_prefered = lifetime_preferred; addr->cinfo.ifa_valid = lifetime_valid; @@ -262,6 +273,52 @@ static int dhcp6_configure(Link *link, int event) { return r; } +static int dhcp6_prefix_expired(Link *link) { + int r; + sd_dhcp6_lease *lease; + struct in6_addr *expired_prefix, ip6_addr; + uint8_t expired_prefixlen; + uint32_t lifetime_preferred, lifetime_valid; + + r = sd_icmp6_ra_get_expired_prefix(link->icmp6_router_discovery, + &expired_prefix, &expired_prefixlen); + if (r < 0) + return r; + + r = sd_dhcp6_client_get_lease(link->dhcp6_client, &lease); + if (r < 0) + return r; + + log_link_struct(link, LOG_INFO, + "MESSAGE=%-*s: IPv6 prefix "SD_ICMP6_ADDRESS_FORMAT_STR"/%d expired", + IFNAMSIZ, link->ifname, + SD_ICMP6_ADDRESS_FORMAT_VAL(*expired_prefix), + expired_prefixlen, NULL); + + sd_dhcp6_lease_reset_address_iter(lease); + + while (sd_dhcp6_lease_get_address(lease, &ip6_addr, + &lifetime_preferred, + &lifetime_valid) >= 0) { + + r = sd_icmp6_prefix_match(expired_prefix, expired_prefixlen, + &ip6_addr); + if (r < 0) + continue; + + log_link_struct(link, LOG_INFO, + "MESSAGE=%-*s: IPv6 prefix length updated "SD_ICMP6_ADDRESS_FORMAT_STR"/%d", + IFNAMSIZ, link->ifname, + SD_ICMP6_ADDRESS_FORMAT_VAL(ip6_addr), 128, + NULL); + + dhcp6_address_update(link, &ip6_addr, 128, lifetime_preferred, + lifetime_valid); + } + + return 0; +} + static void icmp6_router_handler(sd_icmp6_nd *nd, int event, void *userdata) { Link *link = userdata; @@ -274,7 +331,6 @@ static void icmp6_router_handler(sd_icmp6_nd *nd, int event, void *userdata) { switch(event) { case ICMP6_EVENT_ROUTER_ADVERTISMENT_NONE: - case ICMP6_EVENT_ROUTER_ADVERTISMENT_PREFIX_EXPIRED: return; case ICMP6_EVENT_ROUTER_ADVERTISMENT_TIMEOUT: @@ -284,6 +340,12 @@ static void icmp6_router_handler(sd_icmp6_nd *nd, int event, void *userdata) { break; + case ICMP6_EVENT_ROUTER_ADVERTISMENT_PREFIX_EXPIRED: + if (!link->rtnl_extended_attrs) + dhcp6_prefix_expired(link); + + break; + default: if (event < 0) log_link_warning(link, "ICMPv6 error: %s", diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 0f9a1cd6d1..0c6bb658e6 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -225,6 +225,7 @@ static int link_new(Manager *manager, sd_rtnl_message *message, Link **ret) { link->n_ref = 1; link->manager = manager; link->state = LINK_STATE_PENDING; + link->rtnl_extended_attrs = true; link->ifindex = ifindex; link->ifname = strdup(ifname); if (!link->ifname) diff --git a/src/network/networkd-link.h b/src/network/networkd-link.h index 479098cb2b..c3bc1b907b 100644 --- a/src/network/networkd-link.h +++ b/src/network/networkd-link.h @@ -82,6 +82,7 @@ struct Link { sd_icmp6_nd *icmp6_router_discovery; sd_dhcp6_client *dhcp6_client; + bool rtnl_extended_attrs; sd_lldp *lldp; char *lldp_file; |