chiark / gitweb /
networkd: don't do exit-on-idle if there is something wrong with the dbus connection
[elogind.git] / src / network / networkd-manager.c
index 4d27272b3be3b7e47907b3fc3fcabd860a94881f..ce97ac0778ca7e6a25698bd364ed301dd11ab9e5 100644 (file)
@@ -31,6 +31,8 @@
 #include "libudev-private.h"
 #include "udev-util.h"
 #include "rtnl-util.h"
+#include "bus-util.h"
+#include "def.h"
 #include "mkdir.h"
 #include "virt.h"
 
@@ -76,8 +78,6 @@ static int setup_default_address_pool(Manager *m) {
         return 0;
 }
 
-int manager_connect_bus(Manager *m);
-
 static int on_bus_retry(sd_event_source *s, usec_t usec, void *userdata) {
         Manager *m = userdata;
 
@@ -151,10 +151,6 @@ int manager_connect_bus(Manager *m) {
         } if (r < 0)
                 return r;
 
-        r = sd_bus_attach_event(m->bus, m->event, 0);
-        if (r < 0)
-                return r;
-
         r = sd_bus_add_match(m->bus, &m->prepare_for_sleep_slot,
                              "type='signal',"
                              "sender='org.freedesktop.login1',"
@@ -166,6 +162,34 @@ int manager_connect_bus(Manager *m) {
         if (r < 0)
                 return log_error_errno(r, "Failed to add match for PrepareForSleep: %m");
 
+        r = sd_bus_add_object_vtable(m->bus, NULL, "/org/freedesktop/network1", "org.freedesktop.network1.Manager", manager_vtable, m);
+        if (r < 0)
+                return log_error_errno(r, "Failed to add manager object vtable: %m");
+
+        r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/network1/link", "org.freedesktop.network1.Link", link_vtable, link_object_find, m);
+        if (r < 0)
+               return log_error_errno(r, "Failed to add link object vtable: %m");
+
+        r = sd_bus_add_node_enumerator(m->bus, NULL, "/org/freedesktop/network1/link", link_node_enumerator, m);
+        if (r < 0)
+                return log_error_errno(r, "Failed to add link enumerator: %m");
+
+        r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/network1/network", "org.freedesktop.network1.Network", network_vtable, network_object_find, m);
+        if (r < 0)
+               return log_error_errno(r, "Failed to add network object vtable: %m");
+
+        r = sd_bus_add_node_enumerator(m->bus, NULL, "/org/freedesktop/network1/network", network_node_enumerator, m);
+        if (r < 0)
+                return log_error_errno(r, "Failed to add network enumerator: %m");
+
+        r = sd_bus_request_name(m->bus, "org.freedesktop.network1", 0);
+        if (r < 0)
+                return log_error_errno(r, "Failed to register name: %m");
+
+        r = sd_bus_attach_event(m->bus, m->event, 0);
+        if (r < 0)
+                return log_error_errno(r, "Failed to attach bus to event loop: %m");
+
         return 0;
 }
 
@@ -419,10 +443,6 @@ int manager_new(Manager **ret) {
         if (r < 0)
                 return r;
 
-        r = manager_connect_bus(m);
-        if (r < 0)
-                return r;
-
         r = manager_connect_udev(m);
         if (r < 0)
                 return r;
@@ -469,6 +489,8 @@ void manager_free(Manager *m) {
         while ((network = m->networks))
                 network_free(network);
 
+        hashmap_free(m->networks_by_name);
+
         while ((netdev = hashmap_first(m->netdevs)))
                 netdev_unref(netdev);
         hashmap_free(m->netdevs);
@@ -481,6 +503,51 @@ void manager_free(Manager *m) {
         free(m);
 }
 
+static bool manager_check_idle(void *userdata) {
+        Manager *m = userdata;
+        Link *link;
+        Iterator i;
+
+        assert(m);
+
+        HASHMAP_FOREACH(link, m->links, i) {
+                /* we are not woken on udev activity, so let's just wait for the
+                 * pending udev event */
+                if (link->state == LINK_STATE_PENDING)
+                        return false;
+
+                if (!link->network)
+                        continue;
+
+                /* we are not woken on netork activity, so let's stay around */
+                if (link_lldp_enabled(link) ||
+                    link_ipv4ll_enabled(link) ||
+                    link_dhcp4_server_enabled(link) ||
+                    link_dhcp4_enabled(link) ||
+                    link_dhcp6_enabled(link))
+                        return false;
+        }
+
+        return true;
+}
+
+int manager_run(Manager *m) {
+        assert(m);
+
+        if (m->bus)
+                return bus_event_loop_with_idle(
+                                m->event,
+                                m->bus,
+                                "org.freedesktop.network1",
+                                DEFAULT_EXIT_USEC,
+                                manager_check_idle,
+                                m);
+        else
+                /* failed to connect to the bus, so we lose exit-on-idle logic,
+                   this should not happen except if dbus is not around at all */
+                return sd_event_loop(m->event);
+}
+
 int manager_load_config(Manager *m) {
         int r;
 
@@ -741,6 +808,13 @@ int manager_save(Manager *m) {
                 goto fail;
         }
 
+        if (m->operational_state != operstate) {
+                m->operational_state = operstate;
+                r = manager_send_changed(m, "OperationalState", NULL);
+                if (r < 0)
+                        log_error_errno(r, "Could not emit changed OperationalState: %m");
+        }
+
         return 0;
 
 fail: