mirror of
https://github.com/systemd/systemd.git
synced 2025-01-03 05:18:09 +03:00
Merge pull request #16532 from yuwata/network-sync-state-file
network: sync link state file on dbus call, and ndisc cleanups
This commit is contained in:
commit
01b92946c5
@ -108,11 +108,7 @@ int in_addr_equal(int family, const union in_addr_union *a, const union in_addr_
|
||||
return in4_addr_equal(&a->in, &b->in);
|
||||
|
||||
if (family == AF_INET6)
|
||||
return
|
||||
a->in6.s6_addr32[0] == b->in6.s6_addr32[0] &&
|
||||
a->in6.s6_addr32[1] == b->in6.s6_addr32[1] &&
|
||||
a->in6.s6_addr32[2] == b->in6.s6_addr32[2] &&
|
||||
a->in6.s6_addr32[3] == b->in6.s6_addr32[3];
|
||||
return IN6_ARE_ADDR_EQUAL(&a->in6, &b->in6);
|
||||
|
||||
return -EAFNOSUPPORT;
|
||||
}
|
||||
|
@ -151,12 +151,6 @@ void siphash24_compress(const void *_in, size_t inlen, struct siphash *state) {
|
||||
}
|
||||
}
|
||||
|
||||
void siphash24_compress_boolean(bool in, struct siphash *state) {
|
||||
int i = in;
|
||||
|
||||
siphash24_compress(&i, sizeof i, state);
|
||||
}
|
||||
|
||||
uint64_t siphash24_finalize(struct siphash *state) {
|
||||
uint64_t b;
|
||||
|
||||
|
@ -17,9 +17,21 @@ struct siphash {
|
||||
|
||||
void siphash24_init(struct siphash *state, const uint8_t k[static 16]);
|
||||
void siphash24_compress(const void *in, size_t inlen, struct siphash *state);
|
||||
void siphash24_compress_boolean(bool in, struct siphash *state);
|
||||
#define siphash24_compress_byte(byte, state) siphash24_compress((const uint8_t[]) { (byte) }, 1, (state))
|
||||
|
||||
static inline void siphash24_compress_boolean(bool in, struct siphash *state) {
|
||||
uint8_t i = in;
|
||||
|
||||
siphash24_compress(&i, sizeof i, state);
|
||||
}
|
||||
|
||||
static inline void siphash24_compress_string(const char *in, struct siphash *state) {
|
||||
if (!in)
|
||||
return;
|
||||
|
||||
siphash24_compress(in, strlen(in), state);
|
||||
}
|
||||
|
||||
uint64_t siphash24_finalize(struct siphash *state);
|
||||
|
||||
uint64_t siphash24(const void *in, size_t inlen, const uint8_t k[static 16]);
|
||||
|
@ -55,7 +55,7 @@ typedef struct CatalogItem {
|
||||
|
||||
static void catalog_hash_func(const CatalogItem *i, struct siphash *state) {
|
||||
siphash24_compress(&i->id, sizeof(i->id), state);
|
||||
siphash24_compress(i->language, strlen(i->language), state);
|
||||
siphash24_compress_string(i->language, state);
|
||||
}
|
||||
|
||||
static int catalog_compare_func(const CatalogItem *a, const CatalogItem *b) {
|
||||
|
@ -110,7 +110,10 @@ int bus_link_method_set_ntp_servers(sd_bus_message *message, void *userdata, sd_
|
||||
|
||||
strv_free_and_replace(l->ntp, ntp);
|
||||
|
||||
(void) link_dirty(l);
|
||||
link_dirty(l);
|
||||
r = link_save_and_clean(l);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return sd_bus_reply_method_return(message, NULL);
|
||||
}
|
||||
@ -150,7 +153,10 @@ static int bus_link_method_set_dns_servers_internal(sd_bus_message *message, voi
|
||||
free_and_replace(l->dns, dns);
|
||||
l->n_dns = n;
|
||||
|
||||
(void) link_dirty(l);
|
||||
link_dirty(l);
|
||||
r = link_save_and_clean(l);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return sd_bus_reply_method_return(message, NULL);
|
||||
|
||||
@ -240,7 +246,10 @@ int bus_link_method_set_domains(sd_bus_message *message, void *userdata, sd_bus_
|
||||
l->search_domains = TAKE_PTR(search_domains);
|
||||
l->route_domains = TAKE_PTR(route_domains);
|
||||
|
||||
(void) link_dirty(l);
|
||||
link_dirty(l);
|
||||
r = link_save_and_clean(l);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return sd_bus_reply_method_return(message, NULL);
|
||||
}
|
||||
@ -271,7 +280,11 @@ int bus_link_method_set_default_route(sd_bus_message *message, void *userdata, s
|
||||
|
||||
if (l->dns_default_route != b) {
|
||||
l->dns_default_route = b;
|
||||
(void) link_dirty(l);
|
||||
|
||||
link_dirty(l);
|
||||
r = link_save_and_clean(l);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
return sd_bus_reply_method_return(message, NULL);
|
||||
@ -313,7 +326,11 @@ int bus_link_method_set_llmnr(sd_bus_message *message, void *userdata, sd_bus_er
|
||||
|
||||
if (l->llmnr != mode) {
|
||||
l->llmnr = mode;
|
||||
(void) link_dirty(l);
|
||||
|
||||
link_dirty(l);
|
||||
r = link_save_and_clean(l);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
return sd_bus_reply_method_return(message, NULL);
|
||||
@ -355,7 +372,11 @@ int bus_link_method_set_mdns(sd_bus_message *message, void *userdata, sd_bus_err
|
||||
|
||||
if (l->mdns != mode) {
|
||||
l->mdns = mode;
|
||||
(void) link_dirty(l);
|
||||
|
||||
link_dirty(l);
|
||||
r = link_save_and_clean(l);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
return sd_bus_reply_method_return(message, NULL);
|
||||
@ -397,7 +418,11 @@ int bus_link_method_set_dns_over_tls(sd_bus_message *message, void *userdata, sd
|
||||
|
||||
if (l->dns_over_tls_mode != mode) {
|
||||
l->dns_over_tls_mode = mode;
|
||||
(void) link_dirty(l);
|
||||
|
||||
link_dirty(l);
|
||||
r = link_save_and_clean(l);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
return sd_bus_reply_method_return(message, NULL);
|
||||
@ -439,7 +464,11 @@ int bus_link_method_set_dnssec(sd_bus_message *message, void *userdata, sd_bus_e
|
||||
|
||||
if (l->dnssec_mode != mode) {
|
||||
l->dnssec_mode = mode;
|
||||
(void) link_dirty(l);
|
||||
|
||||
link_dirty(l);
|
||||
r = link_save_and_clean(l);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
return sd_bus_reply_method_return(message, NULL);
|
||||
@ -493,7 +522,10 @@ int bus_link_method_set_dnssec_negative_trust_anchors(sd_bus_message *message, v
|
||||
set_free_free(l->dnssec_negative_trust_anchors);
|
||||
l->dnssec_negative_trust_anchors = TAKE_PTR(ns);
|
||||
|
||||
(void) link_dirty(l);
|
||||
link_dirty(l);
|
||||
r = link_save_and_clean(l);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return sd_bus_reply_method_return(message, NULL);
|
||||
}
|
||||
@ -519,7 +551,11 @@ int bus_link_method_revert_ntp(sd_bus_message *message, void *userdata, sd_bus_e
|
||||
return 1; /* Polkit will call us back */
|
||||
|
||||
link_ntp_settings_clear(l);
|
||||
(void) link_dirty(l);
|
||||
|
||||
link_dirty(l);
|
||||
r = link_save_and_clean(l);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return sd_bus_reply_method_return(message, NULL);
|
||||
}
|
||||
@ -545,7 +581,11 @@ int bus_link_method_revert_dns(sd_bus_message *message, void *userdata, sd_bus_e
|
||||
return 1; /* Polkit will call us back */
|
||||
|
||||
link_dns_settings_clear(l);
|
||||
(void) link_dirty(l);
|
||||
|
||||
link_dirty(l);
|
||||
r = link_save_and_clean(l);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return sd_bus_reply_method_return(message, NULL);
|
||||
}
|
||||
@ -629,10 +669,9 @@ int bus_link_method_reconfigure(sd_bus_message *message, void *userdata, sd_bus_
|
||||
return r;
|
||||
|
||||
link_set_state(l, LINK_STATE_INITIALIZED);
|
||||
r = link_save(l);
|
||||
r = link_save_and_clean(l);
|
||||
if (r < 0)
|
||||
return r;
|
||||
link_clean(l);
|
||||
|
||||
return sd_bus_reply_method_return(message, NULL);
|
||||
}
|
||||
|
@ -4525,6 +4525,17 @@ void link_clean(Link *link) {
|
||||
link_unref(set_remove(link->manager->dirty_links, link));
|
||||
}
|
||||
|
||||
int link_save_and_clean(Link *link) {
|
||||
int r;
|
||||
|
||||
r = link_save(link);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
link_clean(link);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char* const link_state_table[_LINK_STATE_MAX] = {
|
||||
[LINK_STATE_PENDING] = "pending",
|
||||
[LINK_STATE_INITIALIZED] = "initialized",
|
||||
|
@ -208,6 +208,7 @@ int link_update(Link *link, sd_netlink_message *message);
|
||||
void link_dirty(Link *link);
|
||||
void link_clean(Link *link);
|
||||
int link_save(Link *link);
|
||||
int link_save_and_clean(Link *link);
|
||||
|
||||
int link_carrier_reset(Link *link);
|
||||
bool link_has_carrier(Link *link);
|
||||
|
@ -1727,8 +1727,7 @@ static int manager_dirty_handler(sd_event_source *s, void *userdata) {
|
||||
manager_save(m);
|
||||
|
||||
SET_FOREACH(link, m->dirty_links, i)
|
||||
if (link_save(link) >= 0)
|
||||
link_clean(link);
|
||||
(void) link_save_and_clean(link);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -1899,7 +1898,7 @@ int manager_start(Manager *m) {
|
||||
manager_save(m);
|
||||
|
||||
HASHMAP_FOREACH(link, m->links, i)
|
||||
link_save(link);
|
||||
(void) link_save(link);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -35,53 +35,6 @@
|
||||
|
||||
#define NDISC_APP_ID SD_ID128_MAKE(13,ac,81,a7,d5,3f,49,78,92,79,5d,0c,29,3a,bc,7e)
|
||||
|
||||
static bool stableprivate_address_is_valid(const struct in6_addr *addr) {
|
||||
assert(addr);
|
||||
|
||||
/* According to rfc4291, generated address should not be in the following ranges. */
|
||||
|
||||
if (memcmp(addr, &SUBNET_ROUTER_ANYCAST_ADDRESS_RFC4291, SUBNET_ROUTER_ANYCAST_PREFIXLEN) == 0)
|
||||
return false;
|
||||
|
||||
if (memcmp(addr, &RESERVED_IPV6_INTERFACE_IDENTIFIERS_ADDRESS_RFC4291, RESERVED_IPV6_INTERFACE_IDENTIFIERS_PREFIXLEN) == 0)
|
||||
return false;
|
||||
|
||||
if (memcmp(addr, &RESERVED_SUBNET_ANYCAST_ADDRESSES_RFC4291, RESERVED_SUBNET_ANYCAST_PREFIXLEN) == 0)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static int make_stableprivate_address(Link *link, const struct in6_addr *prefix, uint8_t prefix_len, uint8_t dad_counter, struct in6_addr *addr) {
|
||||
sd_id128_t secret_key;
|
||||
struct siphash state;
|
||||
uint64_t rid;
|
||||
size_t l;
|
||||
int r;
|
||||
|
||||
/* According to rfc7217 section 5.1
|
||||
* RID = F(Prefix, Net_Iface, Network_ID, DAD_Counter, secret_key) */
|
||||
|
||||
r = sd_id128_get_machine_app_specific(NDISC_APP_ID, &secret_key);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to generate key: %m");
|
||||
|
||||
siphash24_init(&state, secret_key.bytes);
|
||||
|
||||
l = MAX(DIV_ROUND_UP(prefix_len, 8), 8);
|
||||
siphash24_compress(prefix, l, &state);
|
||||
siphash24_compress(link->ifname, strlen(link->ifname), &state);
|
||||
siphash24_compress(&link->mac, sizeof(struct ether_addr), &state);
|
||||
siphash24_compress(&dad_counter, sizeof(uint8_t), &state);
|
||||
|
||||
rid = htole64(siphash24_finalize(&state));
|
||||
|
||||
memcpy(addr->s6_addr, prefix->s6_addr, l);
|
||||
memcpy(addr->s6_addr + l, &rid, 16 - l);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ndisc_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
|
||||
int r;
|
||||
|
||||
@ -228,9 +181,66 @@ static int ndisc_router_process_default(Link *link, sd_ndisc_router *rt) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ndisc_router_generate_addresses(Link *link, unsigned prefixlen, uint32_t lifetime_preferred, Address *address, Set **ret) {
|
||||
static bool stableprivate_address_is_valid(const struct in6_addr *addr) {
|
||||
assert(addr);
|
||||
|
||||
/* According to rfc4291, generated address should not be in the following ranges. */
|
||||
|
||||
if (memcmp(addr, &SUBNET_ROUTER_ANYCAST_ADDRESS_RFC4291, SUBNET_ROUTER_ANYCAST_PREFIXLEN) == 0)
|
||||
return false;
|
||||
|
||||
if (memcmp(addr, &RESERVED_IPV6_INTERFACE_IDENTIFIERS_ADDRESS_RFC4291, RESERVED_IPV6_INTERFACE_IDENTIFIERS_PREFIXLEN) == 0)
|
||||
return false;
|
||||
|
||||
if (memcmp(addr, &RESERVED_SUBNET_ANYCAST_ADDRESSES_RFC4291, RESERVED_SUBNET_ANYCAST_PREFIXLEN) == 0)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static int make_stableprivate_address(Link *link, const struct in6_addr *prefix, uint8_t prefix_len, uint8_t dad_counter, struct in6_addr **ret) {
|
||||
_cleanup_free_ struct in6_addr *addr = NULL;
|
||||
sd_id128_t secret_key;
|
||||
struct siphash state;
|
||||
uint64_t rid;
|
||||
size_t l;
|
||||
int r;
|
||||
|
||||
/* According to rfc7217 section 5.1
|
||||
* RID = F(Prefix, Net_Iface, Network_ID, DAD_Counter, secret_key) */
|
||||
|
||||
r = sd_id128_get_machine_app_specific(NDISC_APP_ID, &secret_key);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to generate key: %m");
|
||||
|
||||
siphash24_init(&state, secret_key.bytes);
|
||||
|
||||
l = MAX(DIV_ROUND_UP(prefix_len, 8), 8);
|
||||
siphash24_compress(prefix, l, &state);
|
||||
siphash24_compress_string(link->ifname, &state);
|
||||
siphash24_compress(&link->mac, sizeof(struct ether_addr), &state);
|
||||
siphash24_compress(&dad_counter, sizeof(uint8_t), &state);
|
||||
|
||||
rid = htole64(siphash24_finalize(&state));
|
||||
|
||||
addr = new(struct in6_addr, 1);
|
||||
if (!addr)
|
||||
return log_oom();
|
||||
|
||||
memcpy(addr->s6_addr, prefix->s6_addr, l);
|
||||
memcpy(addr->s6_addr + l, &rid, 16 - l);
|
||||
|
||||
if (!stableprivate_address_is_valid(addr)) {
|
||||
*ret = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
*ret = TAKE_PTR(addr);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int ndisc_router_generate_addresses(Link *link, struct in6_addr *address, uint8_t prefixlen, Set **ret) {
|
||||
_cleanup_set_free_free_ Set *addresses = NULL;
|
||||
struct in6_addr addr;
|
||||
IPv6Token *j;
|
||||
Iterator i;
|
||||
int r;
|
||||
@ -239,76 +249,63 @@ static int ndisc_router_generate_addresses(Link *link, unsigned prefixlen, uint3
|
||||
assert(address);
|
||||
assert(ret);
|
||||
|
||||
addresses = set_new(&address_hash_ops);
|
||||
addresses = set_new(&in6_addr_hash_ops);
|
||||
if (!addresses)
|
||||
return log_oom();
|
||||
|
||||
addr = address->in_addr.in6;
|
||||
ORDERED_HASHMAP_FOREACH(j, link->network->ipv6_tokens, i) {
|
||||
bool have_address = false;
|
||||
_cleanup_(address_freep) Address *new_address = NULL;
|
||||
|
||||
r = address_new(&new_address);
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
|
||||
*new_address = *address;
|
||||
ORDERED_SET_FOREACH(j, link->network->ipv6_tokens, i) {
|
||||
_cleanup_free_ struct in6_addr *new_address = NULL;
|
||||
|
||||
if (j->address_generation_type == IPV6_TOKEN_ADDRESS_GENERATION_PREFIXSTABLE
|
||||
&& memcmp(&j->prefix, &addr, FAMILY_ADDRESS_SIZE(address->family)) == 0) {
|
||||
&& IN6_ARE_ADDR_EQUAL(&j->prefix, address)) {
|
||||
/* While this loop uses dad_counter and a retry limit as specified in RFC 7217, the loop
|
||||
does not actually attempt Duplicate Address Detection; the counter will be incremented
|
||||
only when the address generation algorithm produces an invalid address, and the loop
|
||||
may exit with an address which ends up being unusable due to duplication on the link.
|
||||
*/
|
||||
for (; j->dad_counter < DAD_CONFLICTS_IDGEN_RETRIES_RFC7217; j->dad_counter++) {
|
||||
r = make_stableprivate_address(link, &j->prefix, prefixlen, j->dad_counter, &new_address->in_addr.in6);
|
||||
r = make_stableprivate_address(link, &j->prefix, prefixlen, j->dad_counter, &new_address);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r > 0)
|
||||
break;
|
||||
|
||||
if (stableprivate_address_is_valid(&new_address->in_addr.in6)) {
|
||||
have_address = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (j->address_generation_type == IPV6_TOKEN_ADDRESS_GENERATION_STATIC) {
|
||||
memcpy(new_address->in_addr.in6.s6_addr + 8, j->prefix.s6_addr + 8, 8);
|
||||
have_address = true;
|
||||
new_address = new(struct in6_addr, 1);
|
||||
if (!new_address)
|
||||
return log_oom();
|
||||
|
||||
memcpy(new_address->s6_addr, address->s6_addr, 8);
|
||||
memcpy(new_address->s6_addr + 8, j->prefix.s6_addr + 8, 8);
|
||||
}
|
||||
|
||||
if (have_address) {
|
||||
new_address->prefixlen = prefixlen;
|
||||
new_address->flags = IFA_F_NOPREFIXROUTE|IFA_F_MANAGETEMPADDR;
|
||||
new_address->cinfo.ifa_prefered = lifetime_preferred;
|
||||
|
||||
if (new_address) {
|
||||
r = set_put(addresses, new_address);
|
||||
if (r < 0)
|
||||
return log_link_error_errno(link, r, "Failed to store SLAAC address: %m");
|
||||
TAKE_PTR(new_address);
|
||||
else if (r == 0)
|
||||
log_link_debug_errno(link, r, "Generated SLAAC address is duplicated, ignoring.");
|
||||
else
|
||||
TAKE_PTR(new_address);
|
||||
}
|
||||
}
|
||||
|
||||
/* fall back to EUI-64 if no tokens provided addresses */
|
||||
if (set_isempty(addresses)) {
|
||||
_cleanup_(address_freep) Address *new_address = NULL;
|
||||
_cleanup_free_ struct in6_addr *new_address = NULL;
|
||||
|
||||
r = address_new(&new_address);
|
||||
if (r < 0)
|
||||
new_address = newdup(struct in6_addr, address, 1);
|
||||
if (!new_address)
|
||||
return log_oom();
|
||||
|
||||
*new_address = *address;
|
||||
|
||||
r = generate_ipv6_eui_64_address(link, &new_address->in_addr.in6);
|
||||
r = generate_ipv6_eui_64_address(link, new_address);
|
||||
if (r < 0)
|
||||
return log_link_error_errno(link, r, "Failed to generate EUI64 address: %m");
|
||||
|
||||
new_address->prefixlen = prefixlen;
|
||||
new_address->flags = IFA_F_NOPREFIXROUTE|IFA_F_MANAGETEMPADDR;
|
||||
new_address->cinfo.ifa_prefered = lifetime_preferred;
|
||||
|
||||
r = set_put(addresses, new_address);
|
||||
if (r < 0)
|
||||
return log_link_error_errno(link, r, "Failed to store SLAAC address: %m");
|
||||
|
||||
TAKE_PTR(new_address);
|
||||
}
|
||||
|
||||
@ -321,9 +318,9 @@ static int ndisc_router_process_autonomous_prefix(Link *link, sd_ndisc_router *r
|
||||
uint32_t lifetime_valid, lifetime_preferred, lifetime_remaining;
|
||||
_cleanup_set_free_free_ Set *addresses = NULL;
|
||||
_cleanup_(address_freep) Address *address = NULL;
|
||||
struct in6_addr addr, *a;
|
||||
unsigned prefixlen;
|
||||
usec_t time_now;
|
||||
Address *a;
|
||||
Iterator i;
|
||||
int r;
|
||||
|
||||
@ -350,41 +347,47 @@ static int ndisc_router_process_autonomous_prefix(Link *link, sd_ndisc_router *r
|
||||
if (lifetime_preferred > lifetime_valid)
|
||||
return 0;
|
||||
|
||||
r = sd_ndisc_router_prefix_get_address(rt, &addr);
|
||||
if (r < 0)
|
||||
return log_link_error_errno(link, r, "Failed to get prefix address: %m");
|
||||
|
||||
r = ndisc_router_generate_addresses(link, &addr, prefixlen, &addresses);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = address_new(&address);
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
|
||||
address->family = AF_INET6;
|
||||
r = sd_ndisc_router_prefix_get_address(rt, &address->in_addr.in6);
|
||||
if (r < 0)
|
||||
return log_link_error_errno(link, r, "Failed to get prefix address: %m");
|
||||
|
||||
r = ndisc_router_generate_addresses(link, prefixlen, lifetime_preferred, address, &addresses);
|
||||
if (r < 0)
|
||||
return r;
|
||||
address->prefixlen = prefixlen;
|
||||
address->flags = IFA_F_NOPREFIXROUTE|IFA_F_MANAGETEMPADDR;
|
||||
address->cinfo.ifa_prefered = lifetime_preferred;
|
||||
|
||||
SET_FOREACH(a, addresses, i) {
|
||||
Address *existing_address;
|
||||
|
||||
/* see RFC4862 section 5.5.3.e */
|
||||
r = address_get(link, a->family, &a->in_addr, a->prefixlen, &existing_address);
|
||||
r = address_get(link, AF_INET6, (union in_addr_union *) a, prefixlen, &existing_address);
|
||||
if (r > 0) {
|
||||
lifetime_remaining = existing_address->cinfo.tstamp / 100 + existing_address->cinfo.ifa_valid - time_now / USEC_PER_SEC;
|
||||
if (lifetime_valid > NDISC_PREFIX_LFT_MIN || lifetime_valid > lifetime_remaining)
|
||||
a->cinfo.ifa_valid = lifetime_valid;
|
||||
address->cinfo.ifa_valid = lifetime_valid;
|
||||
else if (lifetime_remaining <= NDISC_PREFIX_LFT_MIN)
|
||||
a->cinfo.ifa_valid = lifetime_remaining;
|
||||
address->cinfo.ifa_valid = lifetime_remaining;
|
||||
else
|
||||
a->cinfo.ifa_valid = NDISC_PREFIX_LFT_MIN;
|
||||
address->cinfo.ifa_valid = NDISC_PREFIX_LFT_MIN;
|
||||
} else if (lifetime_valid > 0)
|
||||
a->cinfo.ifa_valid = lifetime_valid;
|
||||
address->cinfo.ifa_valid = lifetime_valid;
|
||||
else
|
||||
continue; /* see RFC4862 section 5.5.3.d */
|
||||
|
||||
if (a->cinfo.ifa_valid == 0)
|
||||
if (address->cinfo.ifa_valid == 0)
|
||||
continue;
|
||||
|
||||
r = address_configure(a, link, ndisc_address_handler, true);
|
||||
address->in_addr.in6 = *a;
|
||||
|
||||
r = address_configure(address, link, ndisc_address_handler, true);
|
||||
if (r < 0)
|
||||
return log_link_error_errno(link, r, "Could not set SLAAC address: %m");
|
||||
if (r > 0)
|
||||
@ -577,7 +580,7 @@ static int ndisc_router_process_rdnss(Link *link, sd_ndisc_router *rt) {
|
||||
}
|
||||
|
||||
static void ndisc_dnssl_hash_func(const NDiscDNSSL *x, struct siphash *state) {
|
||||
siphash24_compress(NDISC_DNSSL_DOMAIN(x), strlen(NDISC_DNSSL_DOMAIN(x)), state);
|
||||
siphash24_compress_string(NDISC_DNSSL_DOMAIN(x), state);
|
||||
}
|
||||
|
||||
static int ndisc_dnssl_compare_func(const NDiscDNSSL *a, const NDiscDNSSL *b) {
|
||||
@ -904,12 +907,26 @@ int ipv6token_new(IPv6Token **ret) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_HASH_OPS_WITH_VALUE_DESTRUCTOR(
|
||||
static void ipv6_token_hash_func(const IPv6Token *p, struct siphash *state) {
|
||||
siphash24_compress(&p->address_generation_type, sizeof(p->address_generation_type), state);
|
||||
siphash24_compress(&p->prefix, sizeof(p->prefix), state);
|
||||
}
|
||||
|
||||
static int ipv6_token_compare_func(const IPv6Token *a, const IPv6Token *b) {
|
||||
int r;
|
||||
|
||||
r = CMP(a->address_generation_type, b->address_generation_type);
|
||||
if (r != 0)
|
||||
return r;
|
||||
|
||||
return memcmp(&a->prefix, &b->prefix, sizeof(struct in6_addr));
|
||||
}
|
||||
|
||||
DEFINE_HASH_OPS_WITH_KEY_DESTRUCTOR(
|
||||
ipv6_token_hash_ops,
|
||||
void,
|
||||
trivial_hash_func,
|
||||
trivial_compare_func,
|
||||
IPv6Token,
|
||||
ipv6_token_hash_func,
|
||||
ipv6_token_compare_func,
|
||||
free);
|
||||
|
||||
int config_parse_ndisc_deny_listed_prefix(
|
||||
@ -999,7 +1016,7 @@ int config_parse_address_generation_type(
|
||||
assert(data);
|
||||
|
||||
if (isempty(rvalue)) {
|
||||
network->ipv6_tokens = ordered_hashmap_free(network->ipv6_tokens);
|
||||
network->ipv6_tokens = ordered_set_free(network->ipv6_tokens);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1031,18 +1048,19 @@ int config_parse_address_generation_type(
|
||||
|
||||
token->prefix = buffer.in6;
|
||||
|
||||
r = ordered_hashmap_ensure_allocated(&network->ipv6_tokens, &ipv6_token_hash_ops);
|
||||
r = ordered_set_ensure_allocated(&network->ipv6_tokens, &ipv6_token_hash_ops);
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
|
||||
r = ordered_hashmap_put(network->ipv6_tokens, &token->prefix, token);
|
||||
if (r < 0) {
|
||||
r = ordered_set_put(network->ipv6_tokens, token);
|
||||
if (r == -EEXIST)
|
||||
log_syntax(unit, LOG_DEBUG, filename, line, r,
|
||||
"IPv6 token '%s' is duplicated, ignoring: %m", rvalue);
|
||||
else if (r < 0)
|
||||
log_syntax(unit, LOG_WARNING, filename, line, r,
|
||||
"Failed to store IPv6 token '%s'", rvalue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
TAKE_PTR(token);
|
||||
"Failed to store IPv6 token '%s', ignoring: %m", rvalue);
|
||||
else
|
||||
TAKE_PTR(token);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -763,7 +763,7 @@ static Network *network_free(Network *network) {
|
||||
ordered_hashmap_free(network->dhcp_client_send_vendor_options);
|
||||
ordered_hashmap_free(network->dhcp_server_send_options);
|
||||
ordered_hashmap_free(network->dhcp_server_send_vendor_options);
|
||||
ordered_hashmap_free(network->ipv6_tokens);
|
||||
ordered_set_free(network->ipv6_tokens);
|
||||
ordered_hashmap_free(network->dhcp6_client_send_options);
|
||||
ordered_hashmap_free(network->dhcp6_client_send_vendor_options);
|
||||
|
||||
|
@ -255,7 +255,7 @@ struct Network {
|
||||
IPv6AcceptRAStartDHCP6Client ipv6_accept_ra_start_dhcp6_client;
|
||||
uint32_t ipv6_accept_ra_route_table;
|
||||
Set *ndisc_deny_listed_prefix;
|
||||
OrderedHashmap *ipv6_tokens;
|
||||
OrderedSet *ipv6_tokens;
|
||||
|
||||
IPv6PrivacyExtensions ipv6_privacy_extensions;
|
||||
|
||||
|
@ -132,11 +132,8 @@ static void routing_policy_rule_hash_func(const RoutingPolicyRule *rule, struct
|
||||
siphash24_compress(&rule->dport, sizeof(rule->dport), state);
|
||||
siphash24_compress(&rule->uid_range, sizeof(rule->uid_range), state);
|
||||
|
||||
if (rule->iif)
|
||||
siphash24_compress(rule->iif, strlen(rule->iif), state);
|
||||
|
||||
if (rule->oif)
|
||||
siphash24_compress(rule->oif, strlen(rule->oif), state);
|
||||
siphash24_compress_string(rule->iif, state);
|
||||
siphash24_compress_string(rule->oif, state);
|
||||
|
||||
break;
|
||||
default:
|
||||
|
@ -117,7 +117,7 @@ int kernel_route_expiration_supported(void) {
|
||||
}
|
||||
|
||||
static void network_config_hash_func(const NetworkConfigSection *c, struct siphash *state) {
|
||||
siphash24_compress(c->filename, strlen(c->filename), state);
|
||||
siphash24_compress_string(c->filename, state);
|
||||
siphash24_compress(&c->line, sizeof(c->line), state);
|
||||
}
|
||||
|
||||
|
@ -627,8 +627,7 @@ static void dns_server_hash_func(const DnsServer *s, struct siphash *state) {
|
||||
siphash24_compress(&s->address, FAMILY_ADDRESS_SIZE(s->family), state);
|
||||
siphash24_compress(&s->port, sizeof(s->port), state);
|
||||
siphash24_compress(&s->ifindex, sizeof(s->ifindex), state);
|
||||
if (s->server_name)
|
||||
siphash24_compress(s->server_name, strlen(s->server_name), state);
|
||||
siphash24_compress_string(s->server_name, state);
|
||||
}
|
||||
|
||||
static int dns_server_compare_func(const DnsServer *x, const DnsServer *y) {
|
||||
|
@ -4,4 +4,6 @@ Name=veth99
|
||||
[Network]
|
||||
IPv6AcceptRA=true
|
||||
IPv6Token=::1a:2b:3c:4d
|
||||
IPv6Token=::1a:2b:3c:4d
|
||||
IPv6Token=::1a:2b:3c:4d
|
||||
IPv6Token=::fa:de:ca:fe
|
||||
|
@ -2592,7 +2592,9 @@ class NetworkdStateFileTests(unittest.TestCase, Utilities):
|
||||
|
||||
path = os.path.join('/run/systemd/netif/links/', ifindex)
|
||||
self.assertTrue(os.path.exists(path))
|
||||
time.sleep(2)
|
||||
|
||||
# make link state file updated
|
||||
check_output(*resolvectl_cmd, 'revert', 'dummy98', env=env)
|
||||
|
||||
with open(path) as f:
|
||||
data = f.read()
|
||||
@ -2616,7 +2618,6 @@ class NetworkdStateFileTests(unittest.TestCase, Utilities):
|
||||
check_output(*resolvectl_cmd, 'mdns', 'dummy98', 'no', env=env)
|
||||
check_output(*resolvectl_cmd, 'dnssec', 'dummy98', 'yes', env=env)
|
||||
check_output(*timedatectl_cmd, 'ntp-servers', 'dummy98', '2.fedora.pool.ntp.org', '3.fedora.pool.ntp.org', env=env)
|
||||
time.sleep(2)
|
||||
|
||||
with open(path) as f:
|
||||
data = f.read()
|
||||
@ -2629,7 +2630,6 @@ class NetworkdStateFileTests(unittest.TestCase, Utilities):
|
||||
self.assertRegex(data, r'DNSSEC=yes')
|
||||
|
||||
check_output(*timedatectl_cmd, 'revert', 'dummy98', env=env)
|
||||
time.sleep(2)
|
||||
|
||||
with open(path) as f:
|
||||
data = f.read()
|
||||
@ -2642,7 +2642,6 @@ class NetworkdStateFileTests(unittest.TestCase, Utilities):
|
||||
self.assertRegex(data, r'DNSSEC=yes')
|
||||
|
||||
check_output(*resolvectl_cmd, 'revert', 'dummy98', env=env)
|
||||
time.sleep(2)
|
||||
|
||||
with open(path) as f:
|
||||
data = f.read()
|
||||
|
Loading…
Reference in New Issue
Block a user