network: drop sections contain invalid settings in network_verify()

If e.g., an [Address] section has an invalid setting, then
previously assigned settings in the section is freed, and
only later settings are stored. That may cause partially broken
section stored in Network object.

This makes if an invalid setting is found, then set 'invalid' flag
instead of freeing it. And invalid sections are dropped later by
network_verify().
This commit is contained in:
Yu Watanabe 2019-03-01 13:27:47 +09:00
parent 9560e5b323
commit fcbf4cb727
18 changed files with 149 additions and 73 deletions

View File

@ -159,7 +159,7 @@ int config_parse_address_label_prefix(const char *unit,
void *data,
void *userdata) {
_cleanup_(address_label_freep) AddressLabel *n = NULL;
_cleanup_(address_label_free_or_set_invalidp) AddressLabel *n = NULL;
Network *network = userdata;
int r;
@ -196,7 +196,7 @@ int config_parse_address_label(
void *data,
void *userdata) {
_cleanup_(address_label_freep) AddressLabel *n = NULL;
_cleanup_(address_label_free_or_set_invalidp) AddressLabel *n = NULL;
Network *network = userdata;
uint32_t k;
int r;

View File

@ -11,6 +11,7 @@ typedef struct AddressLabel AddressLabel;
#include "networkd-link.h"
#include "networkd-network.h"
#include "networkd-util.h"
typedef struct Network Network;
typedef struct Link Link;
@ -30,7 +31,7 @@ struct AddressLabel {
void address_label_free(AddressLabel *label);
DEFINE_TRIVIAL_CLEANUP_FUNC(AddressLabel*, address_label_free);
DEFINE_NETWORK_SECTION_FUNCTIONS(AddressLabel, address_label_free);
int address_label_configure(AddressLabel *address, Link *link, link_netlink_message_handler_t callback, bool update);

View File

@ -681,7 +681,7 @@ int config_parse_broadcast(
void *userdata) {
Network *network = userdata;
_cleanup_(address_freep) Address *n = NULL;
_cleanup_(address_free_or_set_invalidp) Address *n = NULL;
int r;
assert(filename);
@ -725,7 +725,7 @@ int config_parse_address(const char *unit,
void *userdata) {
Network *network = userdata;
_cleanup_(address_freep) Address *n = NULL;
_cleanup_(address_free_or_set_invalidp) Address *n = NULL;
union in_addr_union buffer;
unsigned char prefixlen;
int r, f;
@ -807,7 +807,7 @@ int config_parse_label(
void *data,
void *userdata) {
_cleanup_(address_freep) Address *n = NULL;
_cleanup_(address_free_or_set_invalidp) Address *n = NULL;
Network *network = userdata;
int r;
@ -846,7 +846,7 @@ int config_parse_lifetime(const char *unit,
void *data,
void *userdata) {
Network *network = userdata;
_cleanup_(address_freep) Address *n = NULL;
_cleanup_(address_free_or_set_invalidp) Address *n = NULL;
unsigned k;
int r;
@ -888,7 +888,7 @@ int config_parse_address_flags(const char *unit,
void *data,
void *userdata) {
Network *network = userdata;
_cleanup_(address_freep) Address *n = NULL;
_cleanup_(address_free_or_set_invalidp) Address *n = NULL;
int r;
assert(filename);
@ -936,7 +936,7 @@ int config_parse_address_scope(const char *unit,
void *data,
void *userdata) {
Network *network = userdata;
_cleanup_(address_freep) Address *n = NULL;
_cleanup_(address_free_or_set_invalidp) Address *n = NULL;
int r;
assert(filename);
@ -976,3 +976,19 @@ bool address_is_ready(const Address *a) {
else
return !(a->flags & (IFA_F_TENTATIVE | IFA_F_DEPRECATED));
}
int address_section_verify(Address *address) {
if (section_is_invalid(address->section))
return -EINVAL;
if (address->family == AF_UNSPEC) {
assert(address->section);
return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
"%s: Address section without Address= field configured. "
"Ignoring [Address] section from line %u.",
address->section->filename, address->section->line);
}
return 0;
}

View File

@ -11,6 +11,7 @@ typedef struct Address Address;
#include "networkd-link.h"
#include "networkd-network.h"
#include "networkd-util.h"
#define CACHE_INFO_INFINITY_LIFE_TIME 0xFFFFFFFFU
@ -57,8 +58,9 @@ int address_configure(Address *address, Link *link, link_netlink_message_handler
int address_remove(Address *address, Link *link, link_netlink_message_handler_t callback);
bool address_equal(Address *a1, Address *a2);
bool address_is_ready(const Address *a);
int address_section_verify(Address *a);
DEFINE_TRIVIAL_CLEANUP_FUNC(Address*, address_free);
DEFINE_NETWORK_SECTION_FUNCTIONS(Address, address_free);
CONFIG_PARSER_PROTOTYPE(config_parse_address);
CONFIG_PARSER_PROTOTYPE(config_parse_broadcast);

View File

@ -189,7 +189,7 @@ int config_parse_fdb_hwaddr(
void *userdata) {
Network *network = userdata;
_cleanup_(fdb_entry_freep) FdbEntry *fdb_entry = NULL;
_cleanup_(fdb_entry_free_or_set_invalidp) FdbEntry *fdb_entry = NULL;
int r;
assert(filename);
@ -235,7 +235,7 @@ int config_parse_fdb_vlan_id(
void *userdata) {
Network *network = userdata;
_cleanup_(fdb_entry_freep) FdbEntry *fdb_entry = NULL;
_cleanup_(fdb_entry_free_or_set_invalidp) FdbEntry *fdb_entry = NULL;
int r;
assert(filename);

View File

@ -8,6 +8,7 @@
#include "conf-parser.h"
#include "list.h"
#include "macro.h"
#include "networkd-util.h"
typedef struct Network Network;
typedef struct FdbEntry FdbEntry;
@ -27,7 +28,7 @@ struct FdbEntry {
void fdb_entry_free(FdbEntry *fdb_entry);
int fdb_entry_configure(Link *link, FdbEntry *fdb_entry);
DEFINE_TRIVIAL_CLEANUP_FUNC(FdbEntry*, fdb_entry_free);
DEFINE_NETWORK_SECTION_FUNCTIONS(FdbEntry, fdb_entry_free);
CONFIG_PARSER_PROTOTYPE(config_parse_fdb_hwaddr);
CONFIG_PARSER_PROTOTYPE(config_parse_fdb_vlan_id);

View File

@ -10,10 +10,10 @@ typedef struct IPv6ProxyNDPAddress IPv6ProxyNDPAddress;
typedef struct Link Link;
struct IPv6ProxyNDPAddress {
Network *network;
struct in6_addr in_addr;
Network *network;
struct in6_addr in_addr;
LIST_FIELDS(IPv6ProxyNDPAddress, ipv6_proxy_ndp_addresses);
LIST_FIELDS(IPv6ProxyNDPAddress, ipv6_proxy_ndp_addresses);
};
void ipv6_proxy_ndp_address_free(IPv6ProxyNDPAddress *ipv6_proxy_ndp_address);

View File

@ -164,7 +164,7 @@ int config_parse_neighbor_address(const char *unit,
void *userdata) {
Network *network = userdata;
_cleanup_(neighbor_freep) Neighbor *n = NULL;
_cleanup_(neighbor_free_or_set_invalidp) Neighbor *n = NULL;
int r;
assert(filename);
@ -200,7 +200,7 @@ int config_parse_neighbor_hwaddr(const char *unit,
void *userdata) {
Network *network = userdata;
_cleanup_(neighbor_freep) Neighbor *n = NULL;
_cleanup_(neighbor_free_or_set_invalidp) Neighbor *n = NULL;
int r;
assert(filename);

View File

@ -13,6 +13,7 @@ typedef struct Neighbor Neighbor;
#include "networkd-link.h"
#include "networkd-network.h"
#include "networkd-util.h"
struct Neighbor {
Network *network;
@ -29,7 +30,7 @@ struct Neighbor {
void neighbor_free(Neighbor *neighbor);
DEFINE_TRIVIAL_CLEANUP_FUNC(Neighbor*, neighbor_free);
DEFINE_NETWORK_SECTION_FUNCTIONS(Neighbor, neighbor_free);
int neighbor_configure(Neighbor *neighbor, Link *link, link_netlink_message_handler_t callback);

View File

@ -162,6 +162,11 @@ static uint32_t network_get_stacked_netdevs_mtu(Network *network) {
static int network_verify(Network *network) {
Address *address, *address_next;
Route *route, *route_next;
FdbEntry *fdb, *fdb_next;
Neighbor *neighbor, *neighbor_next;
AddressLabel *label, *label_next;
Prefix *prefix, *prefix_next;
RoutingPolicyRule *rule, *rule_next;
uint32_t mtu;
assert(network);
@ -249,34 +254,32 @@ static int network_verify(Network *network) {
}
LIST_FOREACH_SAFE(addresses, address, address_next, network->static_addresses)
if (address->family == AF_UNSPEC) {
log_warning("%s: Address section without Address= field configured. "
"Ignoring [Address] section from line %u.",
network->filename, address->section->line);
if (address_section_verify(address) < 0)
address_free(address);
}
LIST_FOREACH_SAFE(routes, route, route_next, network->static_routes) {
if (route->family == AF_UNSPEC) {
log_warning("%s: Route section without Gateway=, Destination=, Source=, "
"or PreferredSource= field configured. "
"Ignoring [Route] section from line %u.",
network->filename, route->section->line);
LIST_FOREACH_SAFE(routes, route, route_next, network->static_routes)
if (route_section_verify(route, network) < 0)
route_free(route);
continue;
}
if (network->n_static_addresses == 0 &&
in_addr_is_null(route->family, &route->gw) == 0 &&
route->gateway_onlink < 0) {
log_warning("%s: Gateway= without static address configured. "
"Enabling GatewayOnLink= option.",
network->filename);
route->gateway_onlink = true;
}
}
LIST_FOREACH_SAFE(static_fdb_entries, fdb, fdb_next, network->static_fdb_entries)
if (section_is_invalid(fdb->section))
fdb_entry_free(fdb);
LIST_FOREACH_SAFE(neighbors, neighbor, neighbor_next, network->neighbors)
if (section_is_invalid(neighbor->section))
neighbor_free(neighbor);
LIST_FOREACH_SAFE(labels, label, label_next, network->address_labels)
if (section_is_invalid(label->section))
address_label_free(label);
LIST_FOREACH_SAFE(prefixes, prefix, prefix_next, network->static_prefixes)
if (section_is_invalid(prefix->section))
prefix_free(prefix);
LIST_FOREACH_SAFE(rules, rule, rule_next, network->rules)
if (section_is_invalid(rule->section))
routing_policy_rule_free(rule);
return 0;
}

View File

@ -186,7 +186,7 @@ int config_parse_prefix(const char *unit,
void *userdata) {
Network *network = userdata;
_cleanup_(prefix_freep) Prefix *p = NULL;
_cleanup_(prefix_free_or_set_invalidp) Prefix *p = NULL;
uint8_t prefixlen = 64;
union in_addr_union in6addr;
int r;
@ -228,7 +228,7 @@ int config_parse_prefix_flags(const char *unit,
void *data,
void *userdata) {
Network *network = userdata;
_cleanup_(prefix_freep) Prefix *p = NULL;
_cleanup_(prefix_free_or_set_invalidp) Prefix *p = NULL;
int r, val;
assert(filename);
@ -272,7 +272,7 @@ int config_parse_prefix_lifetime(const char *unit,
void *data,
void *userdata) {
Network *network = userdata;
_cleanup_(prefix_freep) Prefix *p = NULL;
_cleanup_(prefix_free_or_set_invalidp) Prefix *p = NULL;
usec_t usec;
int r;

View File

@ -8,6 +8,7 @@
#include "conf-parser.h"
#include "networkd-address.h"
#include "networkd-link.h"
#include "networkd-util.h"
typedef struct Prefix Prefix;
@ -23,7 +24,7 @@ struct Prefix {
int prefix_new(Prefix **ret);
void prefix_free(Prefix *prefix);
DEFINE_TRIVIAL_CLEANUP_FUNC(Prefix*, prefix_free);
DEFINE_NETWORK_SECTION_FUNCTIONS(Prefix, prefix_free);
CONFIG_PARSER_PROTOTYPE(config_parse_router_prefix_delegation);
CONFIG_PARSER_PROTOTYPE(config_parse_router_preference);

View File

@ -678,7 +678,7 @@ int route_configure(
}
int network_add_ipv4ll_route(Network *network) {
_cleanup_(route_freep) Route *n = NULL;
_cleanup_(route_free_or_set_invalidp) Route *n = NULL;
int r;
assert(network);
@ -718,7 +718,7 @@ int config_parse_gateway(
void *userdata) {
Network *network = userdata;
_cleanup_(route_freep) Route *n = NULL;
_cleanup_(route_free_or_set_invalidp) Route *n = NULL;
int r;
assert(filename);
@ -763,7 +763,7 @@ int config_parse_preferred_src(
void *userdata) {
Network *network = userdata;
_cleanup_(route_freep) Route *n = NULL;
_cleanup_(route_free_or_set_invalidp) Route *n = NULL;
int r;
assert(filename);
@ -803,7 +803,7 @@ int config_parse_destination(
void *userdata) {
Network *network = userdata;
_cleanup_(route_freep) Route *n = NULL;
_cleanup_(route_free_or_set_invalidp) Route *n = NULL;
union in_addr_union *buffer;
unsigned char *prefixlen;
int r;
@ -854,7 +854,7 @@ int config_parse_route_priority(
void *userdata) {
Network *network = userdata;
_cleanup_(route_freep) Route *n = NULL;
_cleanup_(route_free_or_set_invalidp) Route *n = NULL;
int r;
assert(filename);
@ -891,7 +891,7 @@ int config_parse_route_scope(
void *userdata) {
Network *network = userdata;
_cleanup_(route_freep) Route *n = NULL;
_cleanup_(route_free_or_set_invalidp) Route *n = NULL;
int r;
assert(filename);
@ -931,7 +931,7 @@ int config_parse_route_table(
void *data,
void *userdata) {
_cleanup_(route_freep) Route *n = NULL;
_cleanup_(route_free_or_set_invalidp) Route *n = NULL;
Network *network = userdata;
int r;
@ -969,7 +969,7 @@ int config_parse_gateway_onlink(
void *userdata) {
Network *network = userdata;
_cleanup_(route_freep) Route *n = NULL;
_cleanup_(route_free_or_set_invalidp) Route *n = NULL;
int r;
assert(filename);
@ -1008,7 +1008,7 @@ int config_parse_ipv6_route_preference(
void *userdata) {
Network *network = userdata;
_cleanup_(route_freep) Route *n = NULL;
_cleanup_(route_free_or_set_invalidp) Route *n = NULL;
int r;
r = route_new_static(network, filename, section_line, &n);
@ -1043,7 +1043,7 @@ int config_parse_route_protocol(
void *userdata) {
Network *network = userdata;
_cleanup_(route_freep) Route *n = NULL;
_cleanup_(route_free_or_set_invalidp) Route *n = NULL;
int r;
r = route_new_static(network, filename, section_line, &n);
@ -1082,7 +1082,7 @@ int config_parse_route_type(
void *userdata) {
Network *network = userdata;
_cleanup_(route_freep) Route *n = NULL;
_cleanup_(route_free_or_set_invalidp) Route *n = NULL;
int r;
r = route_new_static(network, filename, section_line, &n);
@ -1121,7 +1121,7 @@ int config_parse_tcp_window(
void *data,
void *userdata) {
_cleanup_(route_freep) Route *n = NULL;
_cleanup_(route_free_or_set_invalidp) Route *n = NULL;
Network *network = userdata;
uint64_t k;
int r;
@ -1171,7 +1171,7 @@ int config_parse_quickack(
void *data,
void *userdata) {
_cleanup_(route_freep) Route *n = NULL;
_cleanup_(route_free_or_set_invalidp) Route *n = NULL;
Network *network = userdata;
int k, r;
@ -1210,7 +1210,7 @@ int config_parse_route_mtu(
void *userdata) {
Network *network = userdata;
_cleanup_(route_freep) Route *n = NULL;
_cleanup_(route_free_or_set_invalidp) Route *n = NULL;
int r;
assert(filename);
@ -1230,3 +1230,29 @@ int config_parse_route_mtu(
TAKE_PTR(n);
return 0;
}
int route_section_verify(Route *route, Network *network) {
if (section_is_invalid(route->section))
return -EINVAL;
if (route->family == AF_UNSPEC) {
assert(route->section);
return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
"%s: Route section without Gateway=, Destination=, Source=, "
"or PreferredSource= field configured. "
"Ignoring [Route] section from line %u.",
route->section->filename, route->section->line);
}
if (network->n_static_addresses == 0 &&
in_addr_is_null(route->family, &route->gw) == 0 &&
route->gateway_onlink < 0) {
log_warning("%s: Gateway= without static address configured. "
"Enabling GatewayOnLink= option.",
network->filename);
route->gateway_onlink = true;
}
return 0;
}

View File

@ -7,6 +7,7 @@ typedef struct Route Route;
typedef struct NetworkConfigSection NetworkConfigSection;
#include "networkd-network.h"
#include "networkd-util.h"
struct Route {
Network *network;
@ -55,8 +56,9 @@ void route_update(Route *route, const union in_addr_union *src, unsigned char sr
bool route_equal(Route *r1, Route *r2);
int route_expire_handler(sd_event_source *s, uint64_t usec, void *userdata);
int route_section_verify(Route *route, Network *network);
DEFINE_TRIVIAL_CLEANUP_FUNC(Route*, route_free);
DEFINE_NETWORK_SECTION_FUNCTIONS(Route, route_free);
int network_add_ipv4ll_route(Network *network);

View File

@ -636,7 +636,7 @@ int config_parse_routing_policy_rule_tos(
void *data,
void *userdata) {
_cleanup_(routing_policy_rule_freep) RoutingPolicyRule *n = NULL;
_cleanup_(routing_policy_rule_free_or_set_invalidp) RoutingPolicyRule *n = NULL;
Network *network = userdata;
int r;
@ -673,7 +673,7 @@ int config_parse_routing_policy_rule_priority(
void *data,
void *userdata) {
_cleanup_(routing_policy_rule_freep) RoutingPolicyRule *n = NULL;
_cleanup_(routing_policy_rule_free_or_set_invalidp) RoutingPolicyRule *n = NULL;
Network *network = userdata;
int r;
@ -710,7 +710,7 @@ int config_parse_routing_policy_rule_table(
void *data,
void *userdata) {
_cleanup_(routing_policy_rule_freep) RoutingPolicyRule *n = NULL;
_cleanup_(routing_policy_rule_free_or_set_invalidp) RoutingPolicyRule *n = NULL;
Network *network = userdata;
int r;
@ -747,7 +747,7 @@ int config_parse_routing_policy_rule_fwmark_mask(
void *data,
void *userdata) {
_cleanup_(routing_policy_rule_freep) RoutingPolicyRule *n = NULL;
_cleanup_(routing_policy_rule_free_or_set_invalidp) RoutingPolicyRule *n = NULL;
Network *network = userdata;
int r;
@ -784,7 +784,7 @@ int config_parse_routing_policy_rule_prefix(
void *data,
void *userdata) {
_cleanup_(routing_policy_rule_freep) RoutingPolicyRule *n = NULL;
_cleanup_(routing_policy_rule_free_or_set_invalidp) RoutingPolicyRule *n = NULL;
Network *network = userdata;
union in_addr_union *buffer;
uint8_t *prefixlen;
@ -831,7 +831,7 @@ int config_parse_routing_policy_rule_device(
void *data,
void *userdata) {
_cleanup_(routing_policy_rule_freep) RoutingPolicyRule *n = NULL;
_cleanup_(routing_policy_rule_free_or_set_invalidp) RoutingPolicyRule *n = NULL;
Network *network = userdata;
int r;
@ -876,7 +876,7 @@ int config_parse_routing_policy_rule_port_range(
const char *rvalue,
void *data,
void *userdata) {
_cleanup_(routing_policy_rule_freep) RoutingPolicyRule *n = NULL;
_cleanup_(routing_policy_rule_free_or_set_invalidp) RoutingPolicyRule *n = NULL;
Network *network = userdata;
uint16_t low, high;
int r;
@ -922,7 +922,7 @@ int config_parse_routing_policy_rule_ip_protocol(
void *data,
void *userdata) {
_cleanup_(routing_policy_rule_freep) RoutingPolicyRule *n = NULL;
_cleanup_(routing_policy_rule_free_or_set_invalidp) RoutingPolicyRule *n = NULL;
Network *network = userdata;
int r;
@ -961,7 +961,7 @@ int config_parse_routing_policy_rule_invert(
void *data,
void *userdata) {
_cleanup_(routing_policy_rule_freep) RoutingPolicyRule *n = NULL;
_cleanup_(routing_policy_rule_free_or_set_invalidp) RoutingPolicyRule *n = NULL;
Network *network = userdata;
int r;

View File

@ -13,6 +13,7 @@ typedef struct RoutingPolicyRule RoutingPolicyRule;
#include "networkd-link.h"
#include "networkd-network.h"
#include "networkd-util.h"
typedef struct Network Network;
typedef struct Link Link;
@ -54,7 +55,7 @@ struct RoutingPolicyRule {
int routing_policy_rule_new(RoutingPolicyRule **ret);
void routing_policy_rule_free(RoutingPolicyRule *rule);
DEFINE_TRIVIAL_CLEANUP_FUNC(RoutingPolicyRule*, routing_policy_rule_free);
DEFINE_NETWORK_SECTION_FUNCTIONS(RoutingPolicyRule, routing_policy_rule_free);
int routing_policy_rule_configure(RoutingPolicyRule *address, Link *link, link_netlink_message_handler_t callback, bool update);
int routing_policy_rule_remove(RoutingPolicyRule *routing_policy_rule, Link *link, link_netlink_message_handler_t callback);

View File

@ -17,6 +17,7 @@ typedef enum AddressFamilyBoolean {
typedef struct NetworkConfigSection {
unsigned line;
bool invalid;
char filename[];
} NetworkConfigSection;
@ -32,3 +33,24 @@ int network_config_section_new(const char *filename, unsigned line, NetworkConfi
void network_config_section_free(NetworkConfigSection *network);
DEFINE_TRIVIAL_CLEANUP_FUNC(NetworkConfigSection*, network_config_section_free);
extern const struct hash_ops network_config_hash_ops;
static inline bool section_is_invalid(NetworkConfigSection *section) {
/* If this retuns false, then it does _not_ mean the section is valid. */
if (!section)
return false;
return section->invalid;
}
#define DEFINE_NETWORK_SECTION_FUNCTIONS(type, free_func) \
static inline void free_func##_or_set_invalid(type *p) { \
assert(p); \
\
if (p->section) \
p->section->invalid = true; \
else \
free_func(p); \
} \
DEFINE_TRIVIAL_CLEANUP_FUNC(type*, free_func); \
DEFINE_TRIVIAL_CLEANUP_FUNC(type*, free_func##_or_set_invalid);

View File

@ -173,7 +173,7 @@ static void test_config_parse_address_one(const char *rvalue, int family, unsign
assert_se(network = new0(Network, 1));
assert_se(config_parse_address("network", "filename", 1, "section", 1, "Address", 0, rvalue, network, network) == 0);
assert_se(network->n_static_addresses == n_addresses);
assert_se(network->n_static_addresses == 1);
if (n_addresses > 0) {
assert_se(network->static_addresses);
assert_se(network->static_addresses->prefixlen == prefixlen);