***/
#include <resolv.h>
+#include <linux/if.h>
#include "path-util.h"
#include "networkd.h"
if (!m)
return -ENOMEM;
+ m->state_file = strdup("/run/systemd/network/state");
+ if (!m->state_file)
+ return -ENOMEM;
+
r = sd_event_default(&m->event);
if (r < 0)
return r;
if (!m)
return;
+ free(m->state_file);
+
udev_monitor_unref(m->udev_monitor);
udev_unref(m->udev);
sd_bus_unref(m->bus);
sd_event_unref(m->event);
while ((link = hashmap_first(m->links)))
- link_free(link);
+ link_unref(link);
hashmap_free(m->links);
while ((network = m->networks))
network_free(network);
while ((netdev = hashmap_first(m->netdevs)))
- netdev_free(netdev);
+ netdev_unref(netdev);
hashmap_free(m->netdevs);
sd_rtnl_unref(m->rtnl);
static int manager_rtnl_process_link(sd_rtnl *rtnl, sd_rtnl_message *message, void *userdata) {
Manager *m = userdata;
Link *link = NULL;
+ NetDev *netdev = NULL;
+ uint16_t type;
char *name;
int r, ifindex;
assert(message);
assert(m);
+ r = sd_rtnl_message_get_type(message, &type);
+ if (r < 0) {
+ log_warning("rtnl: could not get message type");
+ return 0;
+ }
+
r = sd_rtnl_message_link_get_ifindex(message, &ifindex);
if (r < 0 || ifindex <= 0) {
log_warning("rtnl: received link message without valid ifindex");
return 0;
- }
-
- link_get(m, ifindex, &link);
- if (!link) {
- /* link is new, so add it */
- r = link_add(m, message, &link);
- if (r < 0) {
- log_debug("could not add new link");
- return 0;
- }
- }
+ } else
+ link_get(m, ifindex, &link);
r = sd_rtnl_message_read_string(message, IFLA_IFNAME, &name);
- if (r < 0)
+ if (r < 0 || !name) {
log_warning("rtnl: received link message without valid ifname");
- else {
- NetDev *netdev;
+ return 0;
+ } else
+ netdev_get(m, name, &netdev);
+
+ switch (type) {
+ case RTM_NEWLINK:
+ if (!link) {
+ /* link is new, so add it */
+ r = link_add(m, message, &link);
+ if (r < 0) {
+ log_debug("could not add new link");
+ return 0;
+ }
+ }
- r = netdev_get(m, name, &netdev);
- if (r >= 0) {
+ if (netdev) {
+ /* netdev exists, so make sure the ifindex matches */
r = netdev_set_ifindex(netdev, message);
if (r < 0) {
log_debug("could not set ifindex on netdev");
return 0;
}
}
- }
- r = link_update(link, message);
- if (r < 0)
- return 0;
+ r = link_update(link, message);
+ if (r < 0)
+ return 0;
+
+ break;
+
+ case RTM_DELLINK:
+ link_drop(link);
+ netdev_drop(netdev);
+
+ break;
+
+ default:
+ assert_not_reached("Received invalid RTNL message type.");
+ }
return 1;
}
if (r < 0)
return r;
+ r = sd_rtnl_add_match(m->rtnl, RTM_DELLINK, &manager_rtnl_process_link, m);
+ if (r < 0)
+ return r;
+
return 0;
}
return 0;
}
+
+int manager_save(Manager *m) {
+ Link *link;
+ Iterator i;
+ _cleanup_free_ char *temp_path = NULL;
+ _cleanup_fclose_ FILE *f = NULL;
+ const char *oper_state = "unknown";
+ bool dormant, carrier;
+ int r;
+
+ assert(m);
+ assert(m->state_file);
+
+ HASHMAP_FOREACH(link, m->links, i) {
+ if (link->flags & IFF_LOOPBACK)
+ continue;
+
+ if (link_has_carrier(link->flags, link->operstate))
+ carrier = true;
+ else if (link->operstate == IF_OPER_DORMANT)
+ dormant = true;
+ }
+
+ if (carrier)
+ oper_state = "carrier";
+ else if (dormant)
+ oper_state = "dormant";
+
+ r = fopen_temporary(m->state_file, &f, &temp_path);
+ if (r < 0)
+ goto finish;
+
+ fchmod(fileno(f), 0644);
+
+ fprintf(f,
+ "# This is private data. Do not parse.\n"
+ "OPER_STATE=%s\n", oper_state);
+
+ fflush(f);
+
+ if (ferror(f) || rename(temp_path, m->state_file) < 0) {
+ r = -errno;
+ unlink(m->state_file);
+ unlink(temp_path);
+ }
+
+finish:
+ if (r < 0)
+ log_error("Failed to save network state to %s: %s", m->state_file, strerror(-r));
+
+ return r;
+}