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.
if (r < 0)
return log_error_errno(r, "Could not set prefixlen: %m");
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 (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");
r = sd_rtnl_message_addr_set_scope(req, address->scope);
if (r < 0)
return log_error_errno(r, "Could not set scope: %m");
if (r < 0)
return log_error_errno(r, "Could not set prefixlen: %m");
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 (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");
r = sd_rtnl_message_addr_set_scope(req, address->scope);
if (r < 0)
return log_error_errno(r, "Could not set scope: %m");
addr->family = AF_INET6;
memcpy(&addr->in_addr.in6, ip6_addr, sizeof(*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;
addr->cinfo.ifa_prefered = lifetime_preferred;
addr->cinfo.ifa_valid = lifetime_valid;
Link *link = NULL;
uint16_t type;
_cleanup_address_free_ Address *address = NULL;
Link *link = NULL;
uint16_t type;
_cleanup_address_free_ Address *address = NULL;
Address *existing;
char buf[INET6_ADDRSTRLEN], valid_buf[FORMAT_TIMESPAN_MAX];
const char *valid_str = NULL;
Address *existing;
char buf[INET6_ADDRSTRLEN], valid_buf[FORMAT_TIMESPAN_MAX];
const char *valid_str = NULL;
- 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;
}
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:
switch (address->family) {
case AF_INET:
int family;
unsigned char prefixlen;
unsigned char scope;
int family;
unsigned char prefixlen;
unsigned char scope;
char *label;
struct in_addr broadcast;
char *label;
struct in_addr broadcast;