chiark / gitweb /
sd-network: expose global operational state
authorTom Gundersen <teg@jklm.no>
Thu, 8 May 2014 15:21:37 +0000 (17:21 +0200)
committerTom Gundersen <teg@jklm.no>
Thu, 8 May 2014 15:21:37 +0000 (17:21 +0200)
src/network/networkd-link.c
src/network/networkd-manager.c
src/network/networkd.h
src/network/sd-network.c
src/systemd/sd-network.h

index 04b2265..ab31583 100644 (file)
@@ -1117,7 +1117,7 @@ static int link_acquire_conf(Link *link) {
         return 0;
 }
 
-static bool link_has_carrier(unsigned flags, uint8_t operstate) {
+bool link_has_carrier(unsigned flags, uint8_t operstate) {
         /* see Documentation/networking/operstates.txt in the kernel sources */
 
         if (operstate == IF_OPER_UP)
@@ -1689,6 +1689,11 @@ int link_save(Link *link) {
 
         assert(link);
         assert(link->state_file);
+        assert(link->manager);
+
+        r = manager_save(link->manager);
+        if (r < 0)
+                return r;
 
         admin_state = link_state_to_string(link->state);
         assert(admin_state);
@@ -1735,7 +1740,7 @@ int link_save(Link *link) {
 
 finish:
         if (r < 0)
-                log_error("Failed to save link data %s: %s", link->state_file, strerror(-r));
+                log_error("Failed to save link data to %s: %s", link->state_file, strerror(-r));
 
         return r;
 }
index 28de791..4b29553 100644 (file)
@@ -20,6 +20,7 @@
  ***/
 
 #include <resolv.h>
+#include <linux/if.h>
 
 #include "path-util.h"
 #include "networkd.h"
@@ -80,6 +81,10 @@ int manager_new(Manager **ret) {
         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;
@@ -135,6 +140,8 @@ void manager_free(Manager *m) {
         if (!m)
                 return;
 
+        free(m->state_file);
+
         udev_monitor_unref(m->udev_monitor);
         udev_unref(m->udev);
         sd_bus_unref(m->bus);
@@ -457,3 +464,55 @@ int manager_update_resolv_conf(Manager *m) {
 
         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;
+}
index d31844a..aebb285 100644 (file)
@@ -232,6 +232,8 @@ struct Manager {
         sd_event_source *sigterm_event_source;
         sd_event_source *sigint_event_source;
 
+        char *state_file;
+
         Hashmap *links;
         Hashmap *netdevs;
         LIST_HEAD(Network, networks);
@@ -256,6 +258,7 @@ int manager_udev_listen(Manager *m);
 int manager_bus_listen(Manager *m);
 
 int manager_update_resolv_conf(Manager *m);
+int manager_save(Manager *m);
 
 DEFINE_TRIVIAL_CLEANUP_FUNC(Manager*, manager_free);
 #define _cleanup_manager_free_ _cleanup_(manager_freep)
@@ -377,6 +380,8 @@ int link_initialized(Link *link, struct udev_device *device);
 
 int link_save(Link *link);
 
+bool link_has_carrier(unsigned flags, uint8_t operstate);
+
 const char* link_state_to_string(LinkState s) _const_;
 LinkState link_state_from_string(const char *s) _pure_;
 
index c867812..492e97c 100644 (file)
@@ -95,6 +95,27 @@ _public_ int sd_network_get_link_state(unsigned index, char **state) {
         return 0;
 }
 
+_public_ int sd_network_get_operational_state(char **state) {
+        _cleanup_free_ char *s = NULL;
+        int r;
+
+        assert_return(state, -EINVAL);
+
+        r = parse_env_file("/run/systemd/network/state", NEWLINE, "OPER_STATE",
+                           &s, NULL);
+        if (r == -ENOENT)
+                return -ENODATA;
+        else if (r < 0)
+                return r;
+        else if (!s)
+                return -EIO;
+
+        *state = s;
+        s = NULL;
+
+        return 0;
+}
+
 _public_ int sd_network_get_link_operational_state(unsigned index, char **state) {
         _cleanup_free_ char *s = NULL, *p = NULL;
         int r;
index 40bd75a..d0b2ea3 100644 (file)
@@ -67,6 +67,13 @@ int sd_network_get_link_state(unsigned index, char **state);
  */
 int sd_network_get_link_operational_state(unsigned index, char **state);
 
+/* Get overall opeartional state
+ * Possible states: unknown, dormant, carrier
+ * Possible return codes:
+ *   -ENODATA: networkd is not aware of any links
+ */
+int sd_network_get_operational_state(char **state);
+
 /* Returns true if link exists and is loopback, and false otherwise */
 int sd_network_link_is_loopback(unsigned index);