summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorYu Watanabe <watanabe.yu+github@gmail.com>2021-10-01 09:22:18 +0900
committerYu Watanabe <watanabe.yu+github@gmail.com>2021-10-04 18:17:38 +0900
commit50783f91d44b1978c0e4ba62283131fac75d3745 (patch)
tree8be16d173c3cdce0a208425d453591cce6d2ea4e /src
parent5b43c2c84312d399784b61fd44a00dc8d987f248 (diff)
downloadsystemd-50783f91d44b1978c0e4ba62283131fac75d3745.tar.gz
network: drop and warn duplicated Address= settings
Fixes #20891.
Diffstat (limited to 'src')
-rw-r--r--src/network/networkd-address.c43
-rw-r--r--src/network/networkd-address.h2
-rw-r--r--src/network/networkd-network.c6
3 files changed, 46 insertions, 5 deletions
diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c
index f162fd5334..002827eb78 100644
--- a/src/network/networkd-address.c
+++ b/src/network/networkd-address.c
@@ -314,6 +314,12 @@ int address_compare_func(const Address *a1, const Address *a2) {
}
}
+DEFINE_PRIVATE_HASH_OPS(
+ address_hash_ops,
+ Address,
+ address_hash_func,
+ address_compare_func);
+
DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR(
address_hash_ops_free,
Address,
@@ -1910,12 +1916,43 @@ static int address_section_verify(Address *address) {
return 0;
}
-void network_drop_invalid_addresses(Network *network) {
+int network_drop_invalid_addresses(Network *network) {
+ _cleanup_set_free_ Set *addresses = NULL;
Address *address;
+ int r;
assert(network);
- ORDERED_HASHMAP_FOREACH(address, network->addresses_by_section)
- if (address_section_verify(address) < 0)
+ ORDERED_HASHMAP_FOREACH(address, network->addresses_by_section) {
+ Address *dup;
+
+ if (address_section_verify(address) < 0) {
+ /* Drop invalid [Address] sections or Address= settings in [Network].
+ * Note that address_free() will drop the address from addresses_by_section. */
address_free(address);
+ continue;
+ }
+
+ /* Always use the setting specified later. So, remove the previously assigned setting. */
+ dup = set_remove(addresses, address);
+ if (dup) {
+ _cleanup_free_ char *buf = NULL;
+
+ (void) in_addr_prefix_to_string(address->family, &address->in_addr, address->prefixlen, &buf);
+ log_warning("%s: Duplicated address %s is specified at line %u and %u, "
+ "dropping the address setting specified at line %u.",
+ dup->section->filename, strna(buf), address->section->line,
+ dup->section->line, dup->section->line);
+ /* address_free() will drop the address from addresses_by_section. */
+ address_free(dup);
+ }
+
+ /* Do not use address_hash_ops_free here. Otherwise, all address settings will be freed. */
+ r = set_ensure_put(&addresses, &address_hash_ops, address);
+ if (r < 0)
+ return log_oom();
+ assert(r > 0);
+ }
+
+ return 0;
}
diff --git a/src/network/networkd-address.h b/src/network/networkd-address.h
index 80ceda9427..0fd3163fc4 100644
--- a/src/network/networkd-address.h
+++ b/src/network/networkd-address.h
@@ -93,7 +93,7 @@ int request_process_address(Request *req);
int manager_rtnl_process_address(sd_netlink *nl, sd_netlink_message *message, Manager *m);
-void network_drop_invalid_addresses(Network *network);
+int network_drop_invalid_addresses(Network *network);
void address_hash_func(const Address *a, struct siphash *state);
int address_compare_func(const Address *a1, const Address *a2);
diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c
index 9c01d1cb89..bb7c1defe7 100644
--- a/src/network/networkd-network.c
+++ b/src/network/networkd-network.c
@@ -121,6 +121,8 @@ static int network_resolve_stacked_netdevs(Network *network) {
}
int network_verify(Network *network) {
+ int r;
+
assert(network);
assert(network->filename);
@@ -299,7 +301,9 @@ int network_verify(Network *network) {
network->ipv6_proxy_ndp_addresses = set_free_free(network->ipv6_proxy_ndp_addresses);
}
- network_drop_invalid_addresses(network);
+ r = network_drop_invalid_addresses(network);
+ if (r < 0)
+ return r;
network_drop_invalid_routes(network);
network_drop_invalid_nexthops(network);
network_drop_invalid_bridge_fdb_entries(network);