mirror of
https://github.com/systemd/systemd-stable.git
synced 2024-12-22 13:33:56 +03:00
Merge pull request #5275 from ssahani/fix-dropin-net-section
networkd: fix drop-in conf directory configs overwriting each other
This commit is contained in:
commit
c5d3ee266b
@ -53,15 +53,21 @@ int address_new(Address **ret) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int address_new_static(Network *network, unsigned section, Address **ret) {
|
||||
int address_new_static(Network *network, const char *filename, unsigned section_line, Address **ret) {
|
||||
_cleanup_network_config_section_free_ NetworkConfigSection *n = NULL;
|
||||
_cleanup_address_free_ Address *address = NULL;
|
||||
int r;
|
||||
|
||||
assert(network);
|
||||
assert(ret);
|
||||
assert(!!filename == (section_line > 0));
|
||||
|
||||
if (section) {
|
||||
address = hashmap_get(network->addresses_by_section, UINT_TO_PTR(section));
|
||||
if (filename) {
|
||||
r = network_config_section_new(filename, section_line, &n);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
address = hashmap_get(network->addresses_by_section, n);
|
||||
if (address) {
|
||||
*ret = address;
|
||||
address = NULL;
|
||||
@ -77,9 +83,9 @@ int address_new_static(Network *network, unsigned section, Address **ret) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (section) {
|
||||
address->section = section;
|
||||
hashmap_put(network->addresses_by_section, UINT_TO_PTR(address->section), address);
|
||||
if (filename) {
|
||||
address->section = n;
|
||||
hashmap_put(network->addresses_by_section, n, address);
|
||||
}
|
||||
|
||||
address->network = network;
|
||||
@ -88,6 +94,7 @@ int address_new_static(Network *network, unsigned section, Address **ret) {
|
||||
|
||||
*ret = address;
|
||||
address = NULL;
|
||||
n = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -101,8 +108,10 @@ void address_free(Address *address) {
|
||||
assert(address->network->n_static_addresses > 0);
|
||||
address->network->n_static_addresses--;
|
||||
|
||||
if (address->section)
|
||||
hashmap_remove(address->network->addresses_by_section, UINT_TO_PTR(address->section));
|
||||
if (address->section) {
|
||||
hashmap_remove(address->network->addresses_by_section, address->section);
|
||||
network_config_section_free(address->section);
|
||||
}
|
||||
}
|
||||
|
||||
if (address->link) {
|
||||
@ -676,7 +685,7 @@ int config_parse_broadcast(
|
||||
assert(rvalue);
|
||||
assert(data);
|
||||
|
||||
r = address_new_static(network, section_line, &n);
|
||||
r = address_new_static(network, filename, section_line, &n);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -723,10 +732,10 @@ int config_parse_address(const char *unit,
|
||||
if (streq(section, "Network")) {
|
||||
/* we are not in an Address section, so treat
|
||||
* this as the special '0' section */
|
||||
section_line = 0;
|
||||
}
|
||||
r = address_new_static(network, NULL, 0, &n);
|
||||
} else
|
||||
r = address_new_static(network, filename, section_line, &n);
|
||||
|
||||
r = address_new_static(network, section_line, &n);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -805,7 +814,7 @@ int config_parse_label(
|
||||
assert(rvalue);
|
||||
assert(data);
|
||||
|
||||
r = address_new_static(network, section_line, &n);
|
||||
r = address_new_static(network, filename, section_line, &n);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -844,7 +853,7 @@ int config_parse_lifetime(const char *unit,
|
||||
assert(rvalue);
|
||||
assert(data);
|
||||
|
||||
r = address_new_static(network, section_line, &n);
|
||||
r = address_new_static(network, filename, section_line, &n);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -891,7 +900,7 @@ int config_parse_address_flags(const char *unit,
|
||||
assert(rvalue);
|
||||
assert(data);
|
||||
|
||||
r = address_new_static(network, section_line, &n);
|
||||
r = address_new_static(network, filename, section_line, &n);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
|
@ -33,10 +33,11 @@ typedef struct Address Address;
|
||||
|
||||
typedef struct Network Network;
|
||||
typedef struct Link Link;
|
||||
typedef struct NetworkConfigSection NetworkConfigSection;
|
||||
|
||||
struct Address {
|
||||
Network *network;
|
||||
unsigned section;
|
||||
NetworkConfigSection *section;
|
||||
|
||||
Link *link;
|
||||
|
||||
@ -62,7 +63,7 @@ struct Address {
|
||||
LIST_FIELDS(Address, addresses);
|
||||
};
|
||||
|
||||
int address_new_static(Network *network, unsigned section, Address **ret);
|
||||
int address_new_static(Network *network, const char *filename, unsigned section, Address **ret);
|
||||
int address_new(Address **ret);
|
||||
void address_free(Address *address);
|
||||
int address_add_foreign(Link *link, int family, const union in_addr_union *in_addr, unsigned char prefixlen, Address **ret);
|
||||
|
@ -36,6 +36,49 @@
|
||||
#include "string-util.h"
|
||||
#include "util.h"
|
||||
|
||||
static void network_config_hash_func(const void *p, struct siphash *state) {
|
||||
const NetworkConfigSection *c = p;
|
||||
|
||||
siphash24_compress(c->filename, strlen(c->filename), state);
|
||||
siphash24_compress(&c->line, sizeof(c->line), state);
|
||||
}
|
||||
|
||||
static int network_config_compare_func(const void *a, const void *b) {
|
||||
const NetworkConfigSection *x = a, *y = b;
|
||||
int r;
|
||||
|
||||
r = strcmp(x->filename, y->filename);
|
||||
if (r != 0)
|
||||
return r;
|
||||
|
||||
return y->line - x->line;
|
||||
}
|
||||
|
||||
const struct hash_ops network_config_hash_ops = {
|
||||
.hash = network_config_hash_func,
|
||||
.compare = network_config_compare_func,
|
||||
};
|
||||
|
||||
int network_config_section_new(const char *filename, unsigned line, NetworkConfigSection **s) {
|
||||
NetworkConfigSection *cs;
|
||||
|
||||
cs = malloc0(offsetof(NetworkConfigSection, filename) + strlen(filename) + 1);
|
||||
if (!cs)
|
||||
return -ENOMEM;
|
||||
|
||||
strcpy(cs->filename, filename);
|
||||
cs->line = line;
|
||||
|
||||
*s = cs;
|
||||
cs = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void network_config_section_free(NetworkConfigSection *cs) {
|
||||
free(cs);
|
||||
}
|
||||
|
||||
static int network_load_one(Manager *manager, const char *filename) {
|
||||
_cleanup_network_free_ Network *network = NULL;
|
||||
_cleanup_fclose_ FILE *file = NULL;
|
||||
@ -76,11 +119,11 @@ static int network_load_one(Manager *manager, const char *filename) {
|
||||
if (!network->stacked_netdevs)
|
||||
return log_oom();
|
||||
|
||||
network->addresses_by_section = hashmap_new(NULL);
|
||||
network->addresses_by_section = hashmap_new(&network_config_hash_ops);
|
||||
if (!network->addresses_by_section)
|
||||
return log_oom();
|
||||
|
||||
network->routes_by_section = hashmap_new(NULL);
|
||||
network->routes_by_section = hashmap_new(&network_config_hash_ops);
|
||||
if (!network->routes_by_section)
|
||||
return log_oom();
|
||||
|
||||
@ -385,7 +428,7 @@ int network_apply(Network *network, Link *link) {
|
||||
if (network->ipv4ll_route) {
|
||||
Route *route;
|
||||
|
||||
r = route_new_static(network, 0, &route);
|
||||
r = route_new_static(network, "Network", 0, &route);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
|
@ -82,6 +82,17 @@ typedef struct DUID {
|
||||
uint8_t raw_data[MAX_DUID_LEN];
|
||||
} DUID;
|
||||
|
||||
typedef struct NetworkConfigSection {
|
||||
unsigned line;
|
||||
char filename[];
|
||||
} NetworkConfigSection;
|
||||
|
||||
int network_config_section_new(const char *filename, unsigned line, NetworkConfigSection **s);
|
||||
void network_config_section_free(NetworkConfigSection *network);
|
||||
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(NetworkConfigSection*, network_config_section_free);
|
||||
#define _cleanup_network_config_section_free_ _cleanup_(network_config_section_freep)
|
||||
|
||||
typedef struct Manager Manager;
|
||||
|
||||
struct Network {
|
||||
|
@ -77,15 +77,21 @@ int route_new(Route **ret) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int route_new_static(Network *network, unsigned section, Route **ret) {
|
||||
int route_new_static(Network *network, const char *filename, unsigned section_line, Route **ret) {
|
||||
_cleanup_network_config_section_free_ NetworkConfigSection *n = NULL;
|
||||
_cleanup_route_free_ Route *route = NULL;
|
||||
int r;
|
||||
|
||||
assert(network);
|
||||
assert(ret);
|
||||
assert(!!filename == (section_line > 0));
|
||||
|
||||
if (section) {
|
||||
route = hashmap_get(network->routes_by_section, UINT_TO_PTR(section));
|
||||
if (filename) {
|
||||
r = network_config_section_new(filename, section_line, &n);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
route = hashmap_get(network->routes_by_section, n);
|
||||
if (route) {
|
||||
*ret = route;
|
||||
route = NULL;
|
||||
@ -103,10 +109,11 @@ int route_new_static(Network *network, unsigned section, Route **ret) {
|
||||
|
||||
route->protocol = RTPROT_STATIC;
|
||||
|
||||
if (section) {
|
||||
route->section = section;
|
||||
if (filename) {
|
||||
route->section = n;
|
||||
n = NULL;
|
||||
|
||||
r = hashmap_put(network->routes_by_section, UINT_TO_PTR(route->section), route);
|
||||
r = hashmap_put(network->routes_by_section, n, route);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
@ -132,9 +139,11 @@ void route_free(Route *route) {
|
||||
route->network->n_static_routes--;
|
||||
|
||||
if (route->section)
|
||||
hashmap_remove(route->network->routes_by_section, UINT_TO_PTR(route->section));
|
||||
hashmap_remove(route->network->routes_by_section, route->section);
|
||||
}
|
||||
|
||||
network_config_section_free(route->section);
|
||||
|
||||
if (route->link) {
|
||||
set_remove(route->link->routes, route);
|
||||
set_remove(route->link->routes_foreign, route);
|
||||
@ -673,10 +682,10 @@ int config_parse_gateway(const char *unit,
|
||||
if (streq(section, "Network")) {
|
||||
/* we are not in an Route section, so treat
|
||||
* this as the special '0' section */
|
||||
section_line = 0;
|
||||
}
|
||||
r = route_new_static(network, NULL, 0, &n);
|
||||
} else
|
||||
r = route_new_static(network, filename, section_line, &n);
|
||||
|
||||
r = route_new_static(network, section_line, &n);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -715,7 +724,7 @@ int config_parse_preferred_src(const char *unit,
|
||||
assert(rvalue);
|
||||
assert(data);
|
||||
|
||||
r = route_new_static(network, section_line, &n);
|
||||
r = route_new_static(network, filename, section_line, &n);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -757,7 +766,7 @@ int config_parse_destination(const char *unit,
|
||||
assert(rvalue);
|
||||
assert(data);
|
||||
|
||||
r = route_new_static(network, section_line, &n);
|
||||
r = route_new_static(network, filename, section_line, &n);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -835,7 +844,7 @@ int config_parse_route_priority(const char *unit,
|
||||
assert(rvalue);
|
||||
assert(data);
|
||||
|
||||
r = route_new_static(network, section_line, &n);
|
||||
r = route_new_static(network, filename, section_line, &n);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -872,7 +881,7 @@ int config_parse_route_scope(const char *unit,
|
||||
assert(rvalue);
|
||||
assert(data);
|
||||
|
||||
r = route_new_static(network, section_line, &n);
|
||||
r = route_new_static(network, filename, section_line, &n);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -913,7 +922,7 @@ int config_parse_route_table(const char *unit,
|
||||
assert(rvalue);
|
||||
assert(data);
|
||||
|
||||
r = route_new_static(network, section_line, &n);
|
||||
r = route_new_static(network, filename, section_line, &n);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
|
@ -20,12 +20,13 @@
|
||||
***/
|
||||
|
||||
typedef struct Route Route;
|
||||
typedef struct NetworkConfigSection NetworkConfigSection;
|
||||
|
||||
#include "networkd-network.h"
|
||||
|
||||
struct Route {
|
||||
Network *network;
|
||||
unsigned section;
|
||||
NetworkConfigSection *section;
|
||||
|
||||
Link *link;
|
||||
|
||||
@ -52,7 +53,7 @@ struct Route {
|
||||
LIST_FIELDS(Route, routes);
|
||||
};
|
||||
|
||||
int route_new_static(Network *network, unsigned section, Route **ret);
|
||||
int route_new_static(Network *network, const char *filename, unsigned section_line, Route **ret);
|
||||
int route_new(Route **ret);
|
||||
void route_free(Route *route);
|
||||
int route_configure(Route *route, Link *link, sd_netlink_message_handler_t callback);
|
||||
|
Loading…
Reference in New Issue
Block a user