summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Gundersen <teg@jklm.no>2015-10-01 21:14:06 +0200
committerTom Gundersen <teg@jklm.no>2015-10-30 12:32:49 +0100
commitc4a03a5669af8abd752bff9084c29683ae78e11e (patch)
treed7437b9285d09c000161d7ad0f76cddd6f9ea7c1
parentc1eb9872f6d21e04c361a44987f36451e80ac126 (diff)
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.
-rw-r--r--src/network/networkd-address.c2
-rw-r--r--src/network/networkd-address.h1
-rw-r--r--src/network/networkd-link.c123
-rw-r--r--src/network/networkd-network.c4
4 files changed, 111 insertions, 19 deletions
diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c
index 5b5492e02e..8b6acf2e1d 100644
--- a/src/network/networkd-address.c
+++ b/src/network/networkd-address.c
@@ -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;
diff --git a/src/network/networkd-address.h b/src/network/networkd-address.h
index fd309bebb6..0b1f3b688b 100644
--- a/src/network/networkd-address.h
+++ b/src/network/networkd-address.h
@@ -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);
diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c
index c5be599ecd..4243f8cba9 100644
--- a/src/network/networkd-link.c
+++ b/src/network/networkd-link.c
@@ -2057,28 +2057,30 @@ 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)
@@ -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);
diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c
index 14c201e9a5..0188cb6fe5 100644
--- a/src/network/networkd-network.c
+++ b/src/network/networkd-network.c
@@ -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) {