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=<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
This commit is contained in:
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user