]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
networkd: Add IPv6Prefix sections to the network configuration files
authorPatrik Flykt <patrik.flykt@linux.intel.com>
Fri, 12 May 2017 13:48:29 +0000 (16:48 +0300)
committerPatrik Flykt <patrik.flykt@linux.intel.com>
Mon, 15 May 2017 11:49:50 +0000 (14:49 +0300)
Support zero or more [IPv6Prefix] sections in the network configuration
files. Each section can have one Prefix=<subnet>[/<prefixlength>]
option, with the preferred and valid lifetimes specified by
ValidLifetimeSec and PreferredLifetimeSec measured in seconds, and
with onlink and address autoconfiguration booleans specified by
OnLink and AddressAutoconfiguration variables.

This adds a section like the following to .network configuration files:
[IPv6Prefix]
Prefix=2001:db8:dead:beef::/64
OnLink=true
AddressAutoconfiguration=true
ValidLifetimeSec=1500
PreferredLifetimeSec=1000

src/network/networkd-address.c
src/network/networkd-address.h
src/network/networkd-link.h
src/network/networkd-network-gperf.gperf
src/network/networkd-network.c

index dba394b5e690ee80e10e6e681020b7887c70d151..700ae2adda7d11a4e7f79980c90c4ddfa830ab19 100644 (file)
@@ -947,6 +947,8 @@ void prefix_free(Prefix *prefix) {
                                        prefix->section);
         }
 
+        prefix->radv_prefix = sd_radv_prefix_unref(prefix->radv_prefix);
+
         free(prefix);
 }
 
@@ -957,6 +959,9 @@ int prefix_new(Prefix **ret) {
         if (!prefix)
                 return -ENOMEM;
 
+        if (sd_radv_prefix_new(&prefix->radv_prefix) < 0)
+                return -ENOMEM;
+
         *ret = prefix;
         prefix = NULL;
 
@@ -1012,3 +1017,137 @@ int prefix_new_static(Network *network, const char *filename,
 
         return 0;
 }
+
+int config_parse_prefix(const char *unit,
+                const char *filename,
+                unsigned line,
+                const char *section,
+                unsigned section_line,
+                const char *lvalue,
+                int ltype,
+                const char *rvalue,
+                void *data,
+                void *userdata) {
+
+        Network *network = userdata;
+        _cleanup_prefix_free_ Prefix *p = NULL;
+        uint8_t prefixlen = 64;
+        union in_addr_union in6addr;
+        int r;
+
+        assert(filename);
+        assert(section);
+        assert(lvalue);
+        assert(rvalue);
+        assert(data);
+
+        r = prefix_new_static(network, filename, section_line, &p);
+        if (r < 0)
+                return r;
+
+        r = in_addr_prefix_from_string(rvalue, AF_INET6, &in6addr, &prefixlen);
+        if (r < 0) {
+                log_syntax(unit, LOG_ERR, filename, line, r, "Prefix is invalid, ignoring assignment: %s", rvalue);
+                return 0;
+        }
+
+        if (sd_radv_prefix_set_prefix(p->radv_prefix, &in6addr.in6, prefixlen) < 0)
+                return -EADDRNOTAVAIL;
+
+        log_syntax(unit, LOG_INFO, filename, line, r, "Found prefix %s", rvalue);
+
+        p = NULL;
+
+        return 0;
+}
+
+int config_parse_prefix_flags(const char *unit,
+                              const char *filename,
+                              unsigned line,
+                              const char *section,
+                              unsigned section_line,
+                              const char *lvalue,
+                              int ltype,
+                              const char *rvalue,
+                              void *data,
+                              void *userdata) {
+        Network *network = userdata;
+        _cleanup_prefix_free_ Prefix *p = NULL;
+        int r, val;
+
+        assert(filename);
+        assert(section);
+        assert(lvalue);
+        assert(rvalue);
+        assert(data);
+
+        r = prefix_new_static(network, filename, section_line, &p);
+        if (r < 0)
+                return r;
+
+        r = parse_boolean(rvalue);
+        if (r < 0) {
+                log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse address flag, ignoring: %s", rvalue);
+                return 0;
+        }
+
+        val = r;
+
+        if (streq(lvalue, "OnLink"))
+                r = sd_radv_prefix_set_onlink(p->radv_prefix, val);
+        else if (streq(lvalue, "AddressAutoconfiguration"))
+                r = sd_radv_prefix_set_address_autoconfiguration(p->radv_prefix, val);
+        if (r < 0)
+                return r;
+
+        p = NULL;
+
+        return 0;
+}
+
+int config_parse_prefix_lifetime(const char *unit,
+                                 const char *filename,
+                                 unsigned line,
+                                 const char *section,
+                                 unsigned section_line,
+                                 const char *lvalue,
+                                 int ltype,
+                                 const char *rvalue,
+                                 void *data,
+                                 void *userdata) {
+        Network *network = userdata;
+        _cleanup_prefix_free_ Prefix *p = NULL;
+        usec_t usec;
+        int r;
+
+        assert(filename);
+        assert(section);
+        assert(lvalue);
+        assert(rvalue);
+        assert(data);
+
+        r = prefix_new_static(network, filename, section_line, &p);
+        if (r < 0)
+                return r;
+
+        r = parse_sec(rvalue, &usec);
+        if (r < 0) {
+                log_syntax(unit, LOG_ERR, filename, line, r, "Lifetime is invalid, ignoring assignment: %s", rvalue);
+                return 0;
+        }
+
+        /* a value of 0xffffffff represents infinity, 0x0 means this host is
+           not a router */
+        if (streq(lvalue, "PreferredLifetimeSec"))
+                r = sd_radv_prefix_set_preferred_lifetime(p->radv_prefix,
+                                                          (usec + USEC_PER_SEC - 1) / USEC_PER_SEC);
+        else if (streq(lvalue, "ValidLifetimeSec"))
+                r = sd_radv_prefix_set_valid_lifetime(p->radv_prefix,
+                                                      (usec + USEC_PER_SEC - 1) / USEC_PER_SEC);
+        if (r < 0)
+                return r;
+
+        p = NULL;
+
+        return 0;
+};
index fb79f7a03af667b934512bb75691c3af48d725bf..d9be045302e4e19bd0b8677a8d8c99486e97bc74 100644 (file)
@@ -40,6 +40,8 @@ struct Prefix {
         Network *network;
         NetworkConfigSection *section;
 
+        sd_radv_prefix *radv_prefix;
+
         LIST_FIELDS(Prefix, prefixes);
 };
 
@@ -100,3 +102,6 @@ int config_parse_broadcast(const char *unit, const char *filename, unsigned line
 int config_parse_label(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
 int config_parse_lifetime(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
 int config_parse_address_flags(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+int config_parse_prefix(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+int config_parse_prefix_flags(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+int config_parse_prefix_lifetime(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
index be5c4f328425a240f86cdede2f9d177247d86763..4e53298cb49795ab08ba3f1b706632a1f89768a6 100644 (file)
@@ -28,6 +28,7 @@
 #include "sd-ipv4ll.h"
 #include "sd-lldp.h"
 #include "sd-ndisc.h"
+#include "sd-radv.h"
 #include "sd-netlink.h"
 
 #include "list.h"
index b2c585f8664d9f5cce9d109cc99425f949a72943..eb54a686295316a001203d2a23dca5cc34f5956a 100644 (file)
@@ -137,6 +137,11 @@ BridgeFDB.VLANId,                       config_parse_fdb_vlan_id,
 BridgeVLAN.PVID,                        config_parse_brvlan_pvid,                       0,                             0
 BridgeVLAN.VLAN,                        config_parse_brvlan_vlan,                       0,                             0
 BridgeVLAN.EgressUntagged,              config_parse_brvlan_untagged,                   0,                             0
+IPv6Prefix.Prefix,                      config_parse_prefix,                            0,                             0
+IPv6Prefix.OnLink,                      config_parse_prefix_flags,                      0,                             0
+IPv6Prefix.AddressAutoconfiguration,    config_parse_prefix_flags,                      0,                             0
+IPv6Prefix.ValidLifetimeSec,            config_parse_prefix_lifetime,                   0,                             0
+IPv6Prefix.PreferredLifetimeSec,        config_parse_prefix_lifetime,                   0,                             0
 /* backwards compatibility: do not add new entries to this section */
 Network.IPv4LL,                         config_parse_ipv4ll,                            0,                             offsetof(Network, link_local)
 DHCPv4.UseDNS,                          config_parse_bool,                              0,                             offsetof(Network, dhcp_use_dns)
index 43f62e2c9bc76910ff5fa0be39ba61cd4972bac4..f5d11d6b997c82bc40aa43b5ada08fb1cd223efc 100644 (file)
@@ -212,7 +212,8 @@ static int network_load_one(Manager *manager, const char *filename) {
                               "IPv6NDPProxyAddress\0"
                               "Bridge\0"
                               "BridgeFDB\0"
-                              "BridgeVLAN\0",
+                              "BridgeVLAN\0"
+                              "IPv6Prefix\0",
                               config_item_perf_lookup, network_network_gperf_lookup,
                               false, network);
         if (r < 0)