From 9d5d0090cae80e705c61e3fad49b5ca728e1479b Mon Sep 17 00:00:00 2001 From: Patrik Flykt Date: Fri, 12 May 2017 16:48:29 +0300 Subject: [PATCH] networkd: Add IPv6Prefix sections to the network configuration files Support zero or more [IPv6Prefix] sections in the network configuration files. Each section can have one Prefix=[/] 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 | 139 +++++++++++++++++++++++++++++++ src/network/networkd-address.h | 5 ++ src/network/networkd-link.h | 1 + src/network/networkd-network-gperf.gperf | 5 ++ src/network/networkd-network.c | 3 +- 5 files changed, 152 insertions(+), 1 deletion(-) diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c index dba394b..700ae2a 100644 --- a/src/network/networkd-address.c +++ b/src/network/networkd-address.c @@ -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; +}; diff --git a/src/network/networkd-address.h b/src/network/networkd-address.h index fb79f7a..d9be045 100644 --- a/src/network/networkd-address.h +++ b/src/network/networkd-address.h @@ -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); diff --git a/src/network/networkd-link.h b/src/network/networkd-link.h index be5c4f3..4e53298 100644 --- a/src/network/networkd-link.h +++ b/src/network/networkd-link.h @@ -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" diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf index b2c585f..eb54a68 100644 --- a/src/network/networkd-network-gperf.gperf +++ b/src/network/networkd-network-gperf.gperf @@ -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) diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index 43f62e2..f5d11d6 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -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) -- 2.7.4