Merge pull request #19362 from yuwata/network-dhcp6-pd-log-19354
network: dhcp6: add logs about delegated prefix
This commit is contained in:
@@ -803,6 +803,9 @@ int in_addr_prefix_from_string_auto_internal(
|
||||
}
|
||||
|
||||
static void in_addr_data_hash_func(const struct in_addr_data *a, struct siphash *state) {
|
||||
assert(a);
|
||||
assert(state);
|
||||
|
||||
siphash24_compress(&a->family, sizeof(a->family), state);
|
||||
siphash24_compress(&a->address, FAMILY_ADDRESS_SIZE(a->family), state);
|
||||
}
|
||||
@@ -810,6 +813,9 @@ static void in_addr_data_hash_func(const struct in_addr_data *a, struct siphash
|
||||
static int in_addr_data_compare_func(const struct in_addr_data *x, const struct in_addr_data *y) {
|
||||
int r;
|
||||
|
||||
assert(x);
|
||||
assert(y);
|
||||
|
||||
r = CMP(x->family, y->family);
|
||||
if (r != 0)
|
||||
return r;
|
||||
@@ -819,13 +825,46 @@ static int in_addr_data_compare_func(const struct in_addr_data *x, const struct
|
||||
|
||||
DEFINE_HASH_OPS(in_addr_data_hash_ops, struct in_addr_data, in_addr_data_hash_func, in_addr_data_compare_func);
|
||||
|
||||
static void in_addr_prefix_hash_func(const struct in_addr_prefix *a, struct siphash *state) {
|
||||
assert(a);
|
||||
assert(state);
|
||||
|
||||
siphash24_compress(&a->family, sizeof(a->family), state);
|
||||
siphash24_compress(&a->prefixlen, sizeof(a->prefixlen), state);
|
||||
siphash24_compress(&a->address, FAMILY_ADDRESS_SIZE(a->family), state);
|
||||
}
|
||||
|
||||
static int in_addr_prefix_compare_func(const struct in_addr_prefix *x, const struct in_addr_prefix *y) {
|
||||
int r;
|
||||
|
||||
assert(x);
|
||||
assert(y);
|
||||
|
||||
r = CMP(x->family, y->family);
|
||||
if (r != 0)
|
||||
return r;
|
||||
|
||||
r = CMP(x->prefixlen, y->prefixlen);
|
||||
if (r != 0)
|
||||
return r;
|
||||
|
||||
return memcmp(&x->address, &y->address, FAMILY_ADDRESS_SIZE(x->family));
|
||||
}
|
||||
|
||||
DEFINE_HASH_OPS(in_addr_prefix_hash_ops, struct in_addr_prefix, in_addr_prefix_hash_func, in_addr_prefix_compare_func);
|
||||
DEFINE_HASH_OPS_WITH_KEY_DESTRUCTOR(in_addr_prefix_hash_ops_free, struct in_addr_prefix, in_addr_prefix_hash_func, in_addr_prefix_compare_func, free);
|
||||
|
||||
void in6_addr_hash_func(const struct in6_addr *addr, struct siphash *state) {
|
||||
assert(addr);
|
||||
assert(state);
|
||||
|
||||
siphash24_compress(addr, sizeof(*addr), state);
|
||||
}
|
||||
|
||||
int in6_addr_compare_func(const struct in6_addr *a, const struct in6_addr *b) {
|
||||
assert(a);
|
||||
assert(b);
|
||||
|
||||
return memcmp(a, b, sizeof(*a));
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,12 @@ struct in_addr_data {
|
||||
union in_addr_union address;
|
||||
};
|
||||
|
||||
struct in_addr_prefix {
|
||||
int family;
|
||||
uint8_t prefixlen;
|
||||
union in_addr_union address;
|
||||
};
|
||||
|
||||
bool in4_addr_is_null(const struct in_addr *a);
|
||||
static inline bool in4_addr_is_set(const struct in_addr *a) {
|
||||
return !in4_addr_is_null(a);
|
||||
@@ -111,4 +117,6 @@ void in6_addr_hash_func(const struct in6_addr *addr, struct siphash *state);
|
||||
int in6_addr_compare_func(const struct in6_addr *a, const struct in6_addr *b);
|
||||
|
||||
extern const struct hash_ops in_addr_data_hash_ops;
|
||||
extern const struct hash_ops in_addr_prefix_hash_ops;
|
||||
extern const struct hash_ops in_addr_prefix_hash_ops_free;
|
||||
extern const struct hash_ops in6_addr_hash_ops;
|
||||
|
||||
@@ -364,6 +364,33 @@ static int dhcp6_pd_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Lin
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void log_dhcp6_pd_address(Link *link, const Address *address) {
|
||||
char valid_buf[FORMAT_TIMESPAN_MAX], preferred_buf[FORMAT_TIMESPAN_MAX];
|
||||
const char *valid_str = NULL, *preferred_str = NULL;
|
||||
_cleanup_free_ char *buffer = NULL;
|
||||
int log_level;
|
||||
|
||||
log_level = address_get(link, address, NULL) >= 0 ? LOG_DEBUG : LOG_INFO;
|
||||
|
||||
if (log_level < log_get_max_level())
|
||||
return;
|
||||
|
||||
(void) in_addr_prefix_to_string(address->family, &address->in_addr, address->prefixlen, &buffer);
|
||||
if (address->cinfo.ifa_valid != CACHE_INFO_INFINITY_LIFE_TIME)
|
||||
valid_str = format_timespan(valid_buf, FORMAT_TIMESPAN_MAX,
|
||||
address->cinfo.ifa_valid * USEC_PER_SEC,
|
||||
USEC_PER_SEC);
|
||||
if (address->cinfo.ifa_prefered != CACHE_INFO_INFINITY_LIFE_TIME)
|
||||
preferred_str = format_timespan(preferred_buf, FORMAT_TIMESPAN_MAX,
|
||||
address->cinfo.ifa_prefered * USEC_PER_SEC,
|
||||
USEC_PER_SEC);
|
||||
|
||||
log_link_full(link, log_level, "DHCPv6-PD address %s (valid %s%s, preferred %s%s)",
|
||||
strna(buffer),
|
||||
valid_str ? "for " : "forever", strempty(valid_str),
|
||||
preferred_str ? "for " : "forever", strempty(preferred_str));
|
||||
}
|
||||
|
||||
static int dhcp6_set_pd_address(
|
||||
Link *link,
|
||||
const union in_addr_union *prefix,
|
||||
@@ -402,6 +429,7 @@ static int dhcp6_set_pd_address(
|
||||
SET_FLAG(address->flags, IFA_F_MANAGETEMPADDR, link->network->dhcp6_pd_manage_temporary_address);
|
||||
address->route_metric = link->network->dhcp6_pd_route_metric;
|
||||
|
||||
log_dhcp6_pd_address(link, address);
|
||||
r = address_configure(address, link, dhcp6_pd_address_handler, &ret);
|
||||
if (r < 0)
|
||||
return log_link_error_errno(link, r, "Failed to set DHCPv6 delegated prefix address: %m");
|
||||
@@ -654,6 +682,8 @@ static void dhcp6_pd_prefix_lost(Link *dhcp6_link) {
|
||||
if (r < 0)
|
||||
link_enter_failed(link);
|
||||
}
|
||||
|
||||
set_clear(dhcp6_link->dhcp6_pd_prefixes);
|
||||
}
|
||||
|
||||
static int dhcp6_remove_old(Link *link, bool force);
|
||||
@@ -796,20 +826,12 @@ static int dhcp6_set_unreachable_route(Link *link, const union in_addr_union *ad
|
||||
|
||||
(void) in_addr_prefix_to_string(AF_INET6, addr, prefixlen, &buf);
|
||||
|
||||
if (prefixlen > 64) {
|
||||
log_link_debug(link, "PD Prefix length > 64, ignoring prefix %s", strna(buf));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (prefixlen == 64) {
|
||||
log_link_debug(link, "Not adding a blocking route for DHCPv6 delegated subnet %s since distributed prefix is 64",
|
||||
strna(buf));
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (prefixlen < 48)
|
||||
log_link_warning(link, "PD Prefix length < 48, looks unusual: %s", strna(buf));
|
||||
|
||||
r = route_new(&route);
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
@@ -837,7 +859,45 @@ static int dhcp6_set_unreachable_route(Link *link, const union in_addr_union *ad
|
||||
|
||||
(void) set_remove(link->dhcp6_routes_old, ret);
|
||||
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dhcp6_pd_prefix_add(Link *link, const union in_addr_union *prefix, uint8_t prefixlen) {
|
||||
_cleanup_free_ struct in_addr_prefix *p = NULL;
|
||||
_cleanup_free_ char *buf = NULL;
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
assert(prefix);
|
||||
|
||||
p = new(struct in_addr_prefix, 1);
|
||||
if (!p)
|
||||
return log_oom();
|
||||
|
||||
*p = (struct in_addr_prefix) {
|
||||
.family = AF_INET6,
|
||||
.prefixlen = prefixlen,
|
||||
.address = *prefix,
|
||||
};
|
||||
|
||||
(void) in_addr_prefix_to_string(p->family, &p->address, p->prefixlen, &buf);
|
||||
|
||||
log_link_full(link,
|
||||
set_contains(link->dhcp6_pd_prefixes, p) ? LOG_DEBUG :
|
||||
prefixlen > 64 || prefixlen < 48 ? LOG_WARNING : LOG_INFO,
|
||||
"DHCP6: received PD Prefix %s%s",
|
||||
strna(buf),
|
||||
prefixlen > 64 ? " with prefix length > 64, ignoring." :
|
||||
prefixlen < 48 ? " with prefix lenght < 48, looks unusual.": "");
|
||||
|
||||
/* Store PD prefix even if prefixlen > 64, not to make logged at warning level so frequently. */
|
||||
r = set_ensure_put(&link->dhcp6_pd_prefixes, &in_addr_prefix_hash_ops_free, p);
|
||||
if (r < 0)
|
||||
return log_link_error_errno(link, r, "Failed to store DHCP6 PD prefix %s: %m", strna(buf));
|
||||
if (r > 0)
|
||||
TAKE_PTR(p);
|
||||
|
||||
return prefixlen <= 64;
|
||||
}
|
||||
|
||||
static int dhcp6_pd_prefix_acquired(Link *dhcp6_link) {
|
||||
@@ -866,12 +926,16 @@ static int dhcp6_pd_prefix_acquired(Link *dhcp6_link) {
|
||||
if (r < 0)
|
||||
break;
|
||||
|
||||
r = dhcp6_set_unreachable_route(dhcp6_link, &pd_prefix, pd_prefix_len);
|
||||
r = dhcp6_pd_prefix_add(dhcp6_link, &pd_prefix, pd_prefix_len);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
continue;
|
||||
|
||||
r = dhcp6_set_unreachable_route(dhcp6_link, &pd_prefix, pd_prefix_len);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
/* We are doing prefix allocation in two steps:
|
||||
* 1. all those links that have a preferred subnet id will be assigned their subnet
|
||||
* 2. all those links that remain will receive prefixes in sequential order. Prefixes
|
||||
|
||||
@@ -573,6 +573,8 @@ static Link *link_free(Link *link) {
|
||||
link->dhcp6_pd_addresses_old = set_free(link->dhcp6_pd_addresses_old);
|
||||
link->ndisc_addresses = set_free(link->ndisc_addresses);
|
||||
|
||||
link->dhcp6_pd_prefixes = set_free(link->dhcp6_pd_prefixes);
|
||||
|
||||
link_free_engines(link);
|
||||
|
||||
free(link->ifname);
|
||||
|
||||
@@ -151,6 +151,7 @@ typedef struct Link {
|
||||
sd_dhcp6_lease *dhcp6_lease;
|
||||
Set *dhcp6_addresses, *dhcp6_addresses_old;
|
||||
Set *dhcp6_routes, *dhcp6_routes_old;
|
||||
Set *dhcp6_pd_prefixes;
|
||||
Set *dhcp6_pd_addresses, *dhcp6_pd_addresses_old;
|
||||
Set *dhcp6_pd_routes, *dhcp6_pd_routes_old;
|
||||
unsigned dhcp6_address_messages;
|
||||
|
||||
Reference in New Issue
Block a user