chiark / gitweb /
network-address,test-network: avoid undefined behaviour
[elogind.git] / src / network / networkd-manager.c
index 6aab42756441a51fa6a1e69c8d1c24d8c0e78475..ac207851cbb5b46ac5d2414fffefc79a3baec4fc 100644 (file)
@@ -35,6 +35,7 @@
 #include "virt.h"
 
 #include "sd-rtnl.h"
+#include "sd-daemon.h"
 
 /* use 8 MB for receive socket kernel queue. */
 #define RCVBUF_SIZE    (8*1024*1024)
@@ -75,9 +76,28 @@ static int setup_default_address_pool(Manager *m) {
         return 0;
 }
 
+static int systemd_netlink_fd(void) {
+        int n, fd, rtnl_fd = -EINVAL;
+
+        n = sd_listen_fds(true);
+        if (n <= 0)
+                return -EINVAL;
+
+        for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++) {
+                if (sd_is_socket(fd, AF_NETLINK, SOCK_RAW, -1) > 0) {
+                        if (rtnl_fd >= 0)
+                                return -EINVAL;
+
+                        rtnl_fd = fd;
+                }
+        }
+
+        return rtnl_fd;
+}
+
 int manager_new(Manager **ret) {
         _cleanup_manager_free_ Manager *m = NULL;
-        int r;
+        int r, fd;
 
         m = new0(Manager, 1);
         if (!m)
@@ -96,8 +116,11 @@ int manager_new(Manager **ret) {
         sd_event_add_signal(m->event, NULL, SIGTERM, NULL, NULL);
         sd_event_add_signal(m->event, NULL, SIGINT, NULL, NULL);
 
-        r = sd_rtnl_open(&m->rtnl, 3, RTNLGRP_LINK, RTNLGRP_IPV4_IFADDR,
-                         RTNLGRP_IPV6_IFADDR);
+        fd = systemd_netlink_fd();
+        if (fd < 0)
+                r = sd_rtnl_open(&m->rtnl, 3, RTNLGRP_LINK, RTNLGRP_IPV4_IFADDR, RTNLGRP_IPV6_IFADDR);
+        else
+                r = sd_rtnl_new_from_netlink(&m->rtnl, fd);
         if (r < 0)
                 return r;
 
@@ -654,3 +677,37 @@ int manager_address_pool_acquire(Manager *m, int family, unsigned prefixlen, uni
 
         return 0;
 }
+
+const char *address_family_boolean_to_string(AddressFamilyBoolean b) {
+        if (b == ADDRESS_FAMILY_YES ||
+            b == ADDRESS_FAMILY_NO)
+                return yes_no(b == ADDRESS_FAMILY_YES);
+
+        if (b == ADDRESS_FAMILY_IPV4)
+                return "ipv4";
+        if (b == ADDRESS_FAMILY_IPV6)
+                return "ipv6";
+
+        return NULL;
+}
+
+AddressFamilyBoolean address_family_boolean_from_string(const char *s) {
+        int r;
+
+        /* Make this a true superset of a boolean */
+
+        r = parse_boolean(s);
+        if (r > 0)
+                return ADDRESS_FAMILY_YES;
+        if (r == 0)
+                return ADDRESS_FAMILY_NO;
+
+        if (streq(s, "ipv4"))
+                return ADDRESS_FAMILY_IPV4;
+        if (streq(s, "ipv6"))
+                return ADDRESS_FAMILY_IPV6;
+
+        return _ADDRESS_FAMILY_BOOLEAN_INVALID;
+}
+
+DEFINE_CONFIG_PARSE_ENUM(config_parse_address_family_boolean, address_family_boolean, AddressFamilyBoolean, "Failed to parse option");