networkd: link - deserialize

For now only deserialize some basic state and the applied addresses.

When a link is added, try to deserialize it's state from /run. This
is relevant only when networkd is restarted at runtime.
This commit is contained in:
Tom Gundersen 2015-10-01 21:14:06 +02:00
parent c1eb9872f6
commit c4a03a5669
4 changed files with 111 additions and 19 deletions

View File

@ -271,7 +271,7 @@ int address_add_foreign(Link *link, int family, const union in_addr_union *in_ad
return address_add_internal(link, &link->addresses_foreign, family, in_addr, prefixlen, ret);
}
static int address_add(Link *link, int family, const union in_addr_union *in_addr, unsigned char prefixlen, Address **ret) {
int address_add(Link *link, int family, const union in_addr_union *in_addr, unsigned char prefixlen, Address **ret) {
Address *address;
int r;

View File

@ -62,6 +62,7 @@ int address_new_static(Network *network, 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);
int address_add(Link *link, int family, const union in_addr_union *in_addr, unsigned char prefixlen, Address **ret);
int address_get(Link *link, int family, const union in_addr_union *in_addr, unsigned char prefixlen, Address **ret);
int address_update(Address *address, unsigned char flags, unsigned char scope, struct ifa_cacheinfo *cinfo);
int address_drop(Address *address);

View File

@ -2057,29 +2057,31 @@ static int link_initialized_and_synced(sd_netlink *rtnl, sd_netlink_message *m,
if (r < 0)
return r;
r = network_get(link->manager, link->udev_device, link->ifname,
&link->mac, &network);
if (r == -ENOENT) {
link_enter_unmanaged(link);
return 1;
} else if (r < 0)
return r;
if (!link->network) {
r = network_get(link->manager, link->udev_device, link->ifname,
&link->mac, &network);
if (r == -ENOENT) {
link_enter_unmanaged(link);
return 1;
} else if (r < 0)
return r;
if (link->flags & IFF_LOOPBACK) {
if (network->link_local != ADDRESS_FAMILY_NO)
log_link_debug(link, "Ignoring link-local autoconfiguration for loopback link");
if (link->flags & IFF_LOOPBACK) {
if (network->link_local != ADDRESS_FAMILY_NO)
log_link_debug(link, "Ignoring link-local autoconfiguration for loopback link");
if (network->dhcp != ADDRESS_FAMILY_NO)
log_link_debug(link, "Ignoring DHCP clients for loopback link");
if (network->dhcp != ADDRESS_FAMILY_NO)
log_link_debug(link, "Ignoring DHCP clients for loopback link");
if (network->dhcp_server)
log_link_debug(link, "Ignoring DHCP server for loopback link");
if (network->dhcp_server)
log_link_debug(link, "Ignoring DHCP server for loopback link");
}
r = network_apply(link->manager, network, link);
if (r < 0)
return r;
}
r = network_apply(link->manager, network, link);
if (r < 0)
return r;
r = link_new_bound_to_list(link);
if (r < 0)
return r;
@ -2130,6 +2132,87 @@ int link_initialized(Link *link, struct udev_device *device) {
return 0;
}
static int link_load(Link *link) {
_cleanup_free_ char *network_file = NULL, *addresses = NULL;
int r;
assert(link);
r = parse_env_file(link->state_file, NEWLINE,
"NETWORK_FILE", &network_file,
"ADDRESSES", &addresses,
NULL);
if (r < 0 && r != -ENOENT)
return log_link_error_errno(link, r, "Failed to read %s: %m", link->state_file);
if (network_file) {
Network *network;
char *suffix;
/* drop suffix */
suffix = strrchr(network_file, '.');
if (!suffix) {
log_link_debug(link, "Failed to get network name from %s", network_file);
goto network_file_fail;
}
*suffix = '\0';
r = network_get_by_name(link->manager, basename(network_file), &network);
if (r < 0) {
log_link_debug_errno(link, r, "Failed to get network %s: %m", basename(network_file));
goto network_file_fail;
}
r = network_apply(link->manager, network, link);
if (r < 0)
return log_link_error_errno(link, r, "Failed to apply network %s: %m", basename(network_file));
}
network_file_fail:
if (addresses) {
_cleanup_strv_free_ char **addresses_strv = NULL;
char **address_str;
addresses_strv = strv_split(addresses, " ");
if (!addresses_strv)
return log_oom();
STRV_FOREACH(address_str, addresses_strv) {
char *prefixlen_str;
int family;
unsigned char prefixlen;
union in_addr_union address;
prefixlen_str = strchr(*address_str, '/');
if (!prefixlen_str) {
log_link_debug(link, "Failed to parse address and prefix length %s", *address_str);
continue;
}
*prefixlen_str ++ = '\0';
r = sscanf(prefixlen_str, "%hhu", &prefixlen);
if (r != 1) {
log_link_error(link, "Failed to parse prefixlen %s", prefixlen_str);
continue;
}
r = in_addr_from_string_auto(*address_str, &family, &address);
if (r < 0) {
log_link_debug_errno(link, r, "Failed to parse address %s: %m", *address_str);
continue;
}
r = address_add(link, family, &address, prefixlen, NULL);
if (r < 0)
return log_link_error_errno(link, r, "Failed to add address: %m");
}
}
return 0;
}
int link_add(Manager *m, sd_netlink_message *message, Link **ret) {
Link *link;
_cleanup_udev_device_unref_ struct udev_device *device = NULL;
@ -2149,6 +2232,10 @@ int link_add(Manager *m, sd_netlink_message *message, Link **ret) {
log_link_debug(link, "Link %d added", link->ifindex);
r = link_load(link);
if (r < 0)
return r;
if (detect_container() <= 0) {
/* not in a container, udev will be around */
sprintf(ifindex_str, "n%d", link->ifindex);

View File

@ -352,6 +352,10 @@ int network_get(Manager *manager, struct udev_device *device,
int network_apply(Manager *manager, Network *network, Link *link) {
int r;
assert(manager);
assert(network);
assert(link);
link->network = network;
if (network->ipv4ll_route) {