mirror of
https://github.com/systemd/systemd.git
synced 2025-01-26 14:04:03 +03:00
network: make resolving NetDev names delayed and moved to network_verify()
And before resolving NetDev names, check conditions in .network, and if they do not match the system environment, drop the network unit earlier. Fixes #4211.
This commit is contained in:
parent
a6779fecd9
commit
cebe12571d
@ -47,6 +47,7 @@ typedef enum NetDevKind {
|
|||||||
NETDEV_KIND_FOU,
|
NETDEV_KIND_FOU,
|
||||||
NETDEV_KIND_ERSPAN,
|
NETDEV_KIND_ERSPAN,
|
||||||
_NETDEV_KIND_MAX,
|
_NETDEV_KIND_MAX,
|
||||||
|
_NETDEV_KIND_TUNNEL, /* Used by config_parse_stacked_netdev() */
|
||||||
_NETDEV_KIND_INVALID = -1
|
_NETDEV_KIND_INVALID = -1
|
||||||
} NetDevKind;
|
} NetDevKind;
|
||||||
|
|
||||||
|
@ -38,15 +38,15 @@ Link.AllMulticast, config_parse_tristate,
|
|||||||
Link.Unmanaged, config_parse_bool, 0, offsetof(Network, unmanaged)
|
Link.Unmanaged, config_parse_bool, 0, offsetof(Network, unmanaged)
|
||||||
Link.RequiredForOnline, config_parse_bool, 0, offsetof(Network, required_for_online)
|
Link.RequiredForOnline, config_parse_bool, 0, offsetof(Network, required_for_online)
|
||||||
Network.Description, config_parse_string, 0, offsetof(Network, description)
|
Network.Description, config_parse_string, 0, offsetof(Network, description)
|
||||||
Network.Bridge, config_parse_netdev, 0, 0
|
Network.Bridge, config_parse_ifname, 0, offsetof(Network, bridge_name)
|
||||||
Network.Bond, config_parse_netdev, 0, 0
|
Network.Bond, config_parse_ifname, 0, offsetof(Network, bond_name)
|
||||||
Network.VLAN, config_parse_netdev, 0, 0
|
Network.VLAN, config_parse_stacked_netdev, 0, offsetof(Network, stacked_netdev_names)
|
||||||
Network.MACVLAN, config_parse_netdev, 0, 0
|
Network.MACVLAN, config_parse_stacked_netdev, 0, offsetof(Network, stacked_netdev_names)
|
||||||
Network.MACVTAP, config_parse_netdev, 0, 0
|
Network.MACVTAP, config_parse_stacked_netdev, 0, offsetof(Network, stacked_netdev_names)
|
||||||
Network.IPVLAN, config_parse_netdev, 0, 0
|
Network.IPVLAN, config_parse_stacked_netdev, 0, offsetof(Network, stacked_netdev_names)
|
||||||
Network.VXLAN, config_parse_netdev, 0, 0
|
Network.VXLAN, config_parse_stacked_netdev, 0, offsetof(Network, stacked_netdev_names)
|
||||||
Network.Tunnel, config_parse_tunnel, 0, 0
|
Network.Tunnel, config_parse_stacked_netdev, _NETDEV_KIND_TUNNEL, offsetof(Network, stacked_netdev_names)
|
||||||
Network.VRF, config_parse_netdev, 0, 0
|
Network.VRF, config_parse_ifname, 0, offsetof(Network, vrf_name)
|
||||||
Network.DHCP, config_parse_dhcp, 0, offsetof(Network, dhcp)
|
Network.DHCP, config_parse_dhcp, 0, offsetof(Network, dhcp)
|
||||||
Network.DHCPServer, config_parse_bool, 0, offsetof(Network, dhcp_server)
|
Network.DHCPServer, config_parse_bool, 0, offsetof(Network, dhcp_server)
|
||||||
Network.LinkLocalAddressing, config_parse_address_family_boolean, 0, offsetof(Network, link_local)
|
Network.LinkLocalAddressing, config_parse_address_family_boolean, 0, offsetof(Network, link_local)
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
#include "networkd-network.h"
|
#include "networkd-network.h"
|
||||||
#include "parse-util.h"
|
#include "parse-util.h"
|
||||||
#include "set.h"
|
#include "set.h"
|
||||||
|
#include "socket-util.h"
|
||||||
#include "stat-util.h"
|
#include "stat-util.h"
|
||||||
#include "string-table.h"
|
#include "string-table.h"
|
||||||
#include "string-util.h"
|
#include "string-util.h"
|
||||||
@ -97,6 +98,82 @@ void network_apply_anonymize_if_set(Network *network) {
|
|||||||
network->dhcp_use_timezone = false;
|
network->dhcp_use_timezone = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int network_resolve_netdev_one(Network *network, const char *name, NetDevKind kind, NetDev **ret_netdev) {
|
||||||
|
const char *kind_string;
|
||||||
|
NetDev *netdev;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
assert(network);
|
||||||
|
assert(network->manager);
|
||||||
|
assert(network->filename);
|
||||||
|
assert(ret_netdev);
|
||||||
|
|
||||||
|
if (!name)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (kind == _NETDEV_KIND_TUNNEL)
|
||||||
|
kind_string = "tunnel";
|
||||||
|
else {
|
||||||
|
kind_string = netdev_kind_to_string(kind);
|
||||||
|
if (!kind_string)
|
||||||
|
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||||
|
"%s: Invalid NetDev kind of %s, ignoring assignment.",
|
||||||
|
network->filename, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
r = netdev_get(network->manager, name, &netdev);
|
||||||
|
if (r < 0)
|
||||||
|
return log_error_errno(r, "%s: %s NetDev could not be found, ignoring assignment.",
|
||||||
|
network->filename, name);
|
||||||
|
|
||||||
|
if (netdev->kind != kind && !(kind == _NETDEV_KIND_TUNNEL &&
|
||||||
|
IN_SET(netdev->kind,
|
||||||
|
NETDEV_KIND_IPIP,
|
||||||
|
NETDEV_KIND_SIT,
|
||||||
|
NETDEV_KIND_GRE,
|
||||||
|
NETDEV_KIND_GRETAP,
|
||||||
|
NETDEV_KIND_IP6GRE,
|
||||||
|
NETDEV_KIND_IP6GRETAP,
|
||||||
|
NETDEV_KIND_VTI,
|
||||||
|
NETDEV_KIND_VTI6,
|
||||||
|
NETDEV_KIND_IP6TNL)))
|
||||||
|
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||||
|
"%s: NetDev %s is not a %s, ignoring assignment",
|
||||||
|
network->filename, name, kind_string);
|
||||||
|
|
||||||
|
*ret_netdev = netdev_ref(netdev);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int network_resolve_stacked_netdevs(Network *network) {
|
||||||
|
void *name, *kind;
|
||||||
|
Iterator i;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
assert(network);
|
||||||
|
|
||||||
|
HASHMAP_FOREACH_KEY(kind, name, network->stacked_netdev_names, i) {
|
||||||
|
_cleanup_(netdev_unrefp) NetDev *netdev = NULL;
|
||||||
|
|
||||||
|
r = network_resolve_netdev_one(network, name, PTR_TO_INT(kind), &netdev);
|
||||||
|
if (r <= 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
r = hashmap_ensure_allocated(&network->stacked_netdevs, &string_hash_ops);
|
||||||
|
if (r < 0)
|
||||||
|
return log_oom();
|
||||||
|
|
||||||
|
r = hashmap_put(network->stacked_netdevs, netdev->ifname, netdev);
|
||||||
|
if (r < 0)
|
||||||
|
return log_error_errno(r, "%s: Failed to add NetDev '%s' to network: %m",
|
||||||
|
network->filename, (const char *) name);
|
||||||
|
|
||||||
|
netdev = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int network_verify(Network *network) {
|
static int network_verify(Network *network) {
|
||||||
Address *address;
|
Address *address;
|
||||||
Route *route;
|
Route *route;
|
||||||
@ -104,6 +181,25 @@ static int network_verify(Network *network) {
|
|||||||
assert(network);
|
assert(network);
|
||||||
assert(network->filename);
|
assert(network->filename);
|
||||||
|
|
||||||
|
/* skip out early if configuration does not match the environment */
|
||||||
|
if (!net_match_config(NULL, NULL, NULL, NULL, NULL,
|
||||||
|
network->match_host, network->match_virt, network->match_kernel_cmdline,
|
||||||
|
network->match_kernel_version, network->match_arch,
|
||||||
|
NULL, NULL, NULL, NULL, NULL))
|
||||||
|
return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||||
|
"%s: Conditions in the file do not match the system environment, skipping.", network->filename);
|
||||||
|
|
||||||
|
(void) network_resolve_netdev_one(network, network->bond_name, NETDEV_KIND_BOND, &network->bond);
|
||||||
|
(void) network_resolve_netdev_one(network, network->bridge_name, NETDEV_KIND_BRIDGE, &network->bridge);
|
||||||
|
(void) network_resolve_netdev_one(network, network->vrf_name, NETDEV_KIND_VRF, &network->vrf);
|
||||||
|
(void) network_resolve_stacked_netdevs(network);
|
||||||
|
|
||||||
|
/* Free unnecessary entries. */
|
||||||
|
network->bond_name = mfree(network->bond_name);
|
||||||
|
network->bridge_name = mfree(network->bridge_name);
|
||||||
|
network->vrf_name = mfree(network->vrf_name);
|
||||||
|
network->stacked_netdev_names = hashmap_free_free_key(network->stacked_netdev_names);
|
||||||
|
|
||||||
if (network->bond) {
|
if (network->bond) {
|
||||||
/* Bonding slave does not support addressing. */
|
/* Bonding slave does not support addressing. */
|
||||||
if (network->ipv6_accept_ra > 0) {
|
if (network->ipv6_accept_ra > 0) {
|
||||||
@ -395,10 +491,13 @@ void network_free(Network *network) {
|
|||||||
ordered_set_free_free(network->router_search_domains);
|
ordered_set_free_free(network->router_search_domains);
|
||||||
free(network->router_dns);
|
free(network->router_dns);
|
||||||
|
|
||||||
|
free(network->bridge_name);
|
||||||
|
free(network->bond_name);
|
||||||
|
free(network->vrf_name);
|
||||||
|
hashmap_free_free_key(network->stacked_netdev_names);
|
||||||
netdev_unref(network->bridge);
|
netdev_unref(network->bridge);
|
||||||
netdev_unref(network->bond);
|
netdev_unref(network->bond);
|
||||||
netdev_unref(network->vrf);
|
netdev_unref(network->vrf);
|
||||||
|
|
||||||
hashmap_free_with_destructor(network->stacked_netdevs, netdev_unref);
|
hashmap_free_with_destructor(network->stacked_netdevs, netdev_unref);
|
||||||
|
|
||||||
while ((route = network->static_routes))
|
while ((route = network->static_routes))
|
||||||
@ -576,7 +675,7 @@ bool network_has_static_ipv6_addresses(Network *network) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int config_parse_netdev(const char *unit,
|
int config_parse_stacked_netdev(const char *unit,
|
||||||
const char *filename,
|
const char *filename,
|
||||||
unsigned line,
|
unsigned line,
|
||||||
const char *section,
|
const char *section,
|
||||||
@ -586,11 +685,10 @@ int config_parse_netdev(const char *unit,
|
|||||||
const char *rvalue,
|
const char *rvalue,
|
||||||
void *data,
|
void *data,
|
||||||
void *userdata) {
|
void *userdata) {
|
||||||
Network *network = userdata;
|
_cleanup_free_ char *kind_string = NULL, *name = NULL;
|
||||||
_cleanup_free_ char *kind_string = NULL;
|
Hashmap **h = data;
|
||||||
char *p;
|
|
||||||
NetDev *netdev;
|
|
||||||
NetDevKind kind;
|
NetDevKind kind;
|
||||||
|
char *p;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(filename);
|
assert(filename);
|
||||||
@ -598,72 +696,45 @@ int config_parse_netdev(const char *unit,
|
|||||||
assert(rvalue);
|
assert(rvalue);
|
||||||
assert(data);
|
assert(data);
|
||||||
|
|
||||||
kind_string = strdup(lvalue);
|
if (ltype == _NETDEV_KIND_TUNNEL)
|
||||||
if (!kind_string)
|
kind = _NETDEV_KIND_TUNNEL;
|
||||||
return log_oom();
|
else {
|
||||||
|
kind_string = strdup(lvalue);
|
||||||
/* the keys are CamelCase versions of the kind */
|
if (!kind_string)
|
||||||
for (p = kind_string; *p; p++)
|
|
||||||
*p = tolower(*p);
|
|
||||||
|
|
||||||
kind = netdev_kind_from_string(kind_string);
|
|
||||||
if (kind == _NETDEV_KIND_INVALID) {
|
|
||||||
log_syntax(unit, LOG_ERR, filename, line, 0,
|
|
||||||
"Invalid NetDev kind: %s", lvalue);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
r = netdev_get(network->manager, rvalue, &netdev);
|
|
||||||
if (r < 0) {
|
|
||||||
log_syntax(unit, LOG_ERR, filename, line, r,
|
|
||||||
"%s could not be found, ignoring assignment: %s", lvalue, rvalue);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (netdev->kind != kind) {
|
|
||||||
log_syntax(unit, LOG_ERR, filename, line, 0,
|
|
||||||
"NetDev is not a %s, ignoring assignment: %s", lvalue, rvalue);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (kind) {
|
|
||||||
case NETDEV_KIND_BRIDGE:
|
|
||||||
network->bridge = netdev_unref(network->bridge);
|
|
||||||
network->bridge = netdev;
|
|
||||||
|
|
||||||
break;
|
|
||||||
case NETDEV_KIND_BOND:
|
|
||||||
network->bond = netdev_unref(network->bond);
|
|
||||||
network->bond = netdev;
|
|
||||||
|
|
||||||
break;
|
|
||||||
case NETDEV_KIND_VRF:
|
|
||||||
network->vrf = netdev_unref(network->vrf);
|
|
||||||
network->vrf = netdev;
|
|
||||||
|
|
||||||
break;
|
|
||||||
case NETDEV_KIND_VLAN:
|
|
||||||
case NETDEV_KIND_MACVLAN:
|
|
||||||
case NETDEV_KIND_MACVTAP:
|
|
||||||
case NETDEV_KIND_IPVLAN:
|
|
||||||
case NETDEV_KIND_VXLAN:
|
|
||||||
case NETDEV_KIND_VCAN:
|
|
||||||
r = hashmap_ensure_allocated(&network->stacked_netdevs, &string_hash_ops);
|
|
||||||
if (r < 0)
|
|
||||||
return log_oom();
|
return log_oom();
|
||||||
|
|
||||||
r = hashmap_put(network->stacked_netdevs, netdev->ifname, netdev);
|
/* the keys are CamelCase versions of the kind */
|
||||||
if (r < 0) {
|
for (p = kind_string; *p; p++)
|
||||||
log_syntax(unit, LOG_ERR, filename, line, r, "Cannot add NetDev '%s' to network: %m", rvalue);
|
*p = tolower(*p);
|
||||||
|
|
||||||
|
kind = netdev_kind_from_string(kind_string);
|
||||||
|
if (kind < 0 || IN_SET(kind, NETDEV_KIND_BRIDGE, NETDEV_KIND_BOND, NETDEV_KIND_VRF)) {
|
||||||
|
log_syntax(unit, LOG_ERR, filename, line, 0,
|
||||||
|
"Invalid NetDev kind: %s", lvalue);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
assert_not_reached("Cannot parse NetDev");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
netdev_ref(netdev);
|
if (!ifname_valid(rvalue)) {
|
||||||
|
log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid netdev name in %s=, ignoring assignment: %s", lvalue, rvalue);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
name = strdup(rvalue);
|
||||||
|
if (!name)
|
||||||
|
return log_oom();
|
||||||
|
|
||||||
|
r = hashmap_ensure_allocated(h, &string_hash_ops);
|
||||||
|
if (r < 0)
|
||||||
|
return log_oom();
|
||||||
|
|
||||||
|
r = hashmap_put(*h, name, INT_TO_PTR(kind));
|
||||||
|
if (r < 0) {
|
||||||
|
log_syntax(unit, LOG_ERR, filename, line, r, "Cannot add NetDev '%s' to network, ignoring assignment: %m", rvalue);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
name = NULL;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -749,63 +820,6 @@ int config_parse_domains(
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int config_parse_tunnel(const char *unit,
|
|
||||||
const char *filename,
|
|
||||||
unsigned line,
|
|
||||||
const char *section,
|
|
||||||
unsigned section_line,
|
|
||||||
const char *lvalue,
|
|
||||||
int ltype,
|
|
||||||
const char *rvalue,
|
|
||||||
void *data,
|
|
||||||
void *userdata) {
|
|
||||||
Network *network = userdata;
|
|
||||||
NetDev *netdev;
|
|
||||||
int r;
|
|
||||||
|
|
||||||
assert(filename);
|
|
||||||
assert(lvalue);
|
|
||||||
assert(rvalue);
|
|
||||||
assert(data);
|
|
||||||
|
|
||||||
r = netdev_get(network->manager, rvalue, &netdev);
|
|
||||||
if (r < 0) {
|
|
||||||
log_syntax(unit, LOG_ERR, filename, line, r,
|
|
||||||
"Tunnel is invalid, ignoring assignment: %s", rvalue);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!IN_SET(netdev->kind,
|
|
||||||
NETDEV_KIND_IPIP,
|
|
||||||
NETDEV_KIND_SIT,
|
|
||||||
NETDEV_KIND_GRE,
|
|
||||||
NETDEV_KIND_GRETAP,
|
|
||||||
NETDEV_KIND_IP6GRE,
|
|
||||||
NETDEV_KIND_IP6GRETAP,
|
|
||||||
NETDEV_KIND_VTI,
|
|
||||||
NETDEV_KIND_VTI6,
|
|
||||||
NETDEV_KIND_IP6TNL)) {
|
|
||||||
log_syntax(unit, LOG_ERR, filename, line, 0,
|
|
||||||
"NetDev is not a tunnel, ignoring assignment: %s", rvalue);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
r = hashmap_ensure_allocated(&network->stacked_netdevs, &string_hash_ops);
|
|
||||||
if (r < 0)
|
|
||||||
return log_oom();
|
|
||||||
|
|
||||||
r = hashmap_put(network->stacked_netdevs, netdev->ifname, netdev);
|
|
||||||
if (r < 0) {
|
|
||||||
log_syntax(unit, LOG_ERR, filename, line, r,
|
|
||||||
"Cannot add VLAN '%s' to network, ignoring: %m", rvalue);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
netdev_ref(netdev);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int config_parse_ipv4ll(
|
int config_parse_ipv4ll(
|
||||||
const char* unit,
|
const char* unit,
|
||||||
const char *filename,
|
const char *filename,
|
||||||
|
@ -120,6 +120,10 @@ struct Network {
|
|||||||
NetDev *bond;
|
NetDev *bond;
|
||||||
NetDev *vrf;
|
NetDev *vrf;
|
||||||
Hashmap *stacked_netdevs;
|
Hashmap *stacked_netdevs;
|
||||||
|
char *bridge_name;
|
||||||
|
char *bond_name;
|
||||||
|
char *vrf_name;
|
||||||
|
Hashmap *stacked_netdev_names;
|
||||||
|
|
||||||
/* DHCP Client Support */
|
/* DHCP Client Support */
|
||||||
AddressFamilyBoolean dhcp;
|
AddressFamilyBoolean dhcp;
|
||||||
@ -297,7 +301,7 @@ void network_apply_anonymize_if_set(Network *network);
|
|||||||
|
|
||||||
bool network_has_static_ipv6_addresses(Network *network);
|
bool network_has_static_ipv6_addresses(Network *network);
|
||||||
|
|
||||||
CONFIG_PARSER_PROTOTYPE(config_parse_netdev);
|
CONFIG_PARSER_PROTOTYPE(config_parse_stacked_netdev);
|
||||||
CONFIG_PARSER_PROTOTYPE(config_parse_domains);
|
CONFIG_PARSER_PROTOTYPE(config_parse_domains);
|
||||||
CONFIG_PARSER_PROTOTYPE(config_parse_tunnel);
|
CONFIG_PARSER_PROTOTYPE(config_parse_tunnel);
|
||||||
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp);
|
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user