1
1
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:
Lennart Poettering 2017-02-17 18:03:04 +01:00 committed by GitHub
commit c5d3ee266b
6 changed files with 111 additions and 37 deletions

View File

@ -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;

View File

@ -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);

View File

@ -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;

View File

@ -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 {

View File

@ -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;

View File

@ -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);