The IFA_F_NOPREFIXROUTE flag prevents the kernel from creating new onlink prefixes when a DHCPv6 IPv6 address with a prefix length is set from user space. IPv6 routing will follow the onlink status from Router Advertisment Prefix Information options or any manually set route, which is the correct thing to do.
As this flag has a larger value than what fits into an unsigned char, update the flag attribute to an uint32_t and set it with an IFA_FLAGS attribute when writing netlink messages to the kernel. --- src/network/networkd-address.c | 20 ++++++++++++++++++-- src/network/networkd-dhcp6.c | 4 +++- src/network/networkd-link.c | 4 +++- src/network/networkd.h | 2 +- 4 files changed, 25 insertions(+), 5 deletions(-) diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c index 255ff77..85acc49 100644 --- a/src/network/networkd-address.c +++ b/src/network/networkd-address.c @@ -209,10 +209,18 @@ int address_update(Address *address, Link *link, if (r < 0) return log_error_errno(r, "Could not set prefixlen: %m"); - r = sd_rtnl_message_addr_set_flags(req, IFA_F_PERMANENT); + address->flags |= IFA_F_PERMANENT; + + r = sd_rtnl_message_addr_set_flags(req, address->flags & 0xff); if (r < 0) return log_error_errno(r, "Could not set flags: %m"); + if (address->flags & ~0xff) { + 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"); + } + r = sd_rtnl_message_addr_set_scope(req, address->scope); if (r < 0) return log_error_errno(r, "Could not set scope: %m"); @@ -335,10 +343,18 @@ int address_configure(Address *address, Link *link, if (r < 0) return log_error_errno(r, "Could not set prefixlen: %m"); - r = sd_rtnl_message_addr_set_flags(req, IFA_F_PERMANENT); + address->flags |= IFA_F_PERMANENT; + + r = sd_rtnl_message_addr_set_flags(req, (address->flags & 0xff)); if (r < 0) return log_error_errno(r, "Could not set flags: %m"); + if (address->flags & ~0xff) { + 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"); + } + r = sd_rtnl_message_addr_set_scope(req, address->scope); if (r < 0) return log_error_errno(r, "Could not set scope: %m"); diff --git a/src/network/networkd-dhcp6.c b/src/network/networkd-dhcp6.c index bcfad4c..283a7d6 100644 --- a/src/network/networkd-dhcp6.c +++ b/src/network/networkd-dhcp6.c @@ -65,7 +65,9 @@ static int dhcp6_address_update(Link *link, struct in6_addr *ip6_addr, addr->family = AF_INET6; memcpy(&addr->in_addr.in6, ip6_addr, sizeof(*ip6_addr)); - addr->prefixlen = prefixlen; + + addr->flags = IFA_F_NOPREFIXROUTE; + addr->prefixlen = 64; addr->cinfo.ifa_prefered = lifetime_preferred; addr->cinfo.ifa_valid = lifetime_valid; diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 842ca1c..437c598 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -1831,6 +1831,7 @@ int link_rtnl_process_address(sd_rtnl *rtnl, sd_rtnl_message *message, void *use Link *link = NULL; uint16_t type; _cleanup_address_free_ Address *address = NULL; + unsigned char flags; Address *existing; char buf[INET6_ADDRSTRLEN], valid_buf[FORMAT_TIMESPAN_MAX]; const char *valid_str = NULL; @@ -1894,11 +1895,12 @@ int link_rtnl_process_address(sd_rtnl *rtnl, sd_rtnl_message *message, void *use return 0; } - r = sd_rtnl_message_addr_get_flags(message, &address->flags); + r = sd_rtnl_message_addr_get_flags(message, &flags); if (r < 0) { log_link_warning(link, "rtnl: received address with invalid flags, ignoring"); return 0; } + address->flags = flags; switch (address->family) { case AF_INET: diff --git a/src/network/networkd.h b/src/network/networkd.h index 8bdc2be..c26d64e 100644 --- a/src/network/networkd.h +++ b/src/network/networkd.h @@ -173,7 +173,7 @@ struct Address { int family; unsigned char prefixlen; unsigned char scope; - unsigned char flags; + uint32_t flags; char *label; struct in_addr broadcast; -- 2.1.4 _______________________________________________ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel