mirror of
https://github.com/systemd/systemd.git
synced 2025-02-25 21:57:32 +03:00
network: sd-radv - Introduce pref64 support (RFC8781)
Implements: https://datatracker.ietf.org/doc/html/rfc8781 ``` [IPv6PREF64Prefix] Prefix=2003:da8:1:0::/64 ValidLifetimeSec=30m Frame 16: 126 bytes on wire (1008 bits), 126 bytes captured (1008 bits) on interface veth99, id 0 Ethernet II, Src: 06:c7:41:95:1d:7f (06:c7:41:95:1d:7f), Dst: IPv6mcast_01 (33:33:00:00:00:01) Internet Protocol Version 6, Src: fe80::4c7:41ff:fe95:1d7f, Dst: ff02::1 Internet Control Message Protocol v6 Type: Router Advertisement (134) Code: 0 Checksum: 0x0ca0 [correct] [Checksum Status: Good] Cur hop limit: 0 Flags: 0x00, Prf (Default Router Preference): Medium Router lifetime (s): 1800 Reachable time (ms): 0 Retrans timer (ms): 0 ICMPv6 Option (Source link-layer address : 06:c7:41:95:1d:7f) ICMPv6 Option (Prefix information : 2002:da8:1::/64) ICMPv6 Option (PREF64 Option) Type: PREF64 Option (38) Length: 2 (16 bytes) 0000 0111 0000 1... = Scaled Lifetime: 225 .... .... .... .001 = PLC (Prefix Length Code): 64 bits prefix length (0x1) Prefix: 64:ff9b:: ```
This commit is contained in:
parent
ebbc92405b
commit
1925f829ab
@ -3249,6 +3249,31 @@ Token=prefixstable:2002:da8:1::</programlisting></para>
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>[IPv6PREF64Prefix] Section Options</title>
|
||||
<para>One or more [IPv6PREF64Prefix] sections contain the IPv6 PREF64 (or NAT64) prefixes that are announced via Router
|
||||
Advertisements. See <ulink url="https://tools.ietf.org/html/rfc8781">RFC 8781</ulink> for further
|
||||
details.</para>
|
||||
|
||||
<variablelist class='network-directives'>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>Prefix=</varname></term>
|
||||
|
||||
<listitem><para>The IPv6 PREF64 (or NAT64) prefix that is to be distributed to hosts. The setting holds
|
||||
an IPv6 prefix that should be set up for NAT64 translation (PLAT) to allow 464XLAT on the network segment.
|
||||
Use multiple [IPv6PREF64Prefix] sections to configure multiple IPv6 prefixes since prefix lifetime may differ
|
||||
from one prefix to another. The prefix is an address with a prefix length, separated by a slash
|
||||
<literal>/</literal> character. Valid NAT64 prefix length are 96, 64, 56, 48, 40, and 32 bits.</para></listitem></varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>LifetimeSec=</varname></term>
|
||||
<listitem><para>Lifetime for the prefix measured in seconds. Should be greater than or equal to <varname>RouterLifetimeSec=</varname>.
|
||||
<varname>LifetimeSec=</varname> defaults to 1800 seconds.</para></listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>[Bridge] Section Options</title>
|
||||
<para>The [Bridge] section accepts the following keys:</para>
|
||||
|
@ -55,10 +55,15 @@
|
||||
#define RADV_MAX_FINAL_RTR_ADVERTISEMENTS 3
|
||||
#define RADV_MIN_DELAY_BETWEEN_RAS 3
|
||||
#define RADV_MAX_RA_DELAY_TIME_USEC (500 * USEC_PER_MSEC)
|
||||
/* From RFC 8781 section 4.1
|
||||
* By default, the value of the Scaled Lifetime field SHOULD be set to the lesser of 3 x MaxRtrAdvInterval */
|
||||
#define RADV_DEFAULT_PRE64_LIFETIME_USEC (3 * RADV_DEFAULT_MAX_TIMEOUT_USEC)
|
||||
|
||||
#define RADV_OPT_ROUTE_INFORMATION 24
|
||||
#define RADV_OPT_RDNSS 25
|
||||
#define RADV_OPT_DNSSL 31
|
||||
/* Pref64 option type (RFC8781, section 4) */
|
||||
#define RADV_OPT_PREF64 38
|
||||
|
||||
enum RAdvState {
|
||||
RADV_STATE_IDLE = 0,
|
||||
@ -101,6 +106,9 @@ struct sd_radv {
|
||||
unsigned n_route_prefixes;
|
||||
LIST_HEAD(sd_radv_route_prefix, route_prefixes);
|
||||
|
||||
unsigned n_pref64_prefixes;
|
||||
LIST_HEAD(sd_radv_pref64_prefix, pref64_prefixes);
|
||||
|
||||
size_t n_rdnss;
|
||||
struct sd_radv_opt_dns *rdnss;
|
||||
struct sd_radv_opt_dns *dnssl;
|
||||
@ -172,6 +180,32 @@ struct sd_radv_route_prefix {
|
||||
usec_t valid_until;
|
||||
};
|
||||
|
||||
/* rfc8781: section 4 - Scaled Lifetime: 13-bit unsigned integer. PLC (Prefix Length Code): 3-bit unsigned integer */
|
||||
#define radv_pref64_prefix_opt__contents { \
|
||||
uint8_t type; \
|
||||
uint8_t length; \
|
||||
uint16_t lifetime_and_plc; \
|
||||
uint8_t prefix[12]; \
|
||||
}
|
||||
|
||||
struct radv_pref64_prefix_opt radv_pref64_prefix_opt__contents;
|
||||
|
||||
struct radv_pref64_prefix_opt__packed radv_pref64_prefix_opt__contents _packed_;
|
||||
assert_cc(sizeof(struct radv_pref64_prefix_opt) == sizeof(struct radv_pref64_prefix_opt__packed));
|
||||
|
||||
struct sd_radv_pref64_prefix {
|
||||
unsigned n_ref;
|
||||
|
||||
struct radv_pref64_prefix_opt opt;
|
||||
|
||||
struct in6_addr in6_addr;
|
||||
uint8_t prefixlen;
|
||||
|
||||
usec_t lifetime_usec;
|
||||
|
||||
LIST_FIELDS(struct sd_radv_pref64_prefix, prefix);
|
||||
};
|
||||
|
||||
#define log_radv_errno(radv, error, fmt, ...) \
|
||||
log_interface_prefix_full_errno( \
|
||||
"RADV: ", \
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include "socket-util.h"
|
||||
#include "string-util.h"
|
||||
#include "strv.h"
|
||||
#include "unaligned.h"
|
||||
|
||||
int sd_radv_new(sd_radv **ret) {
|
||||
_cleanup_(sd_radv_unrefp) sd_radv *ra = NULL;
|
||||
@ -220,6 +221,9 @@ static int radv_send(sd_radv *ra, const struct in6_addr *dst, usec_t lifetime_us
|
||||
iov[msg.msg_iovlen++] = IOVEC_MAKE(&rt->opt, sizeof(rt->opt));
|
||||
}
|
||||
|
||||
LIST_FOREACH(prefix, p, ra->pref64_prefixes)
|
||||
iov[msg.msg_iovlen++] = IOVEC_MAKE(&p->opt, sizeof(p->opt));
|
||||
|
||||
if (ra->rdnss)
|
||||
iov[msg.msg_iovlen++] = IOVEC_MAKE(ra->rdnss, ra->rdnss->length * 8);
|
||||
|
||||
@ -738,6 +742,78 @@ int sd_radv_add_route_prefix(sd_radv *ra, sd_radv_route_prefix *p) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sd_radv_add_pref64_prefix(sd_radv *ra, sd_radv_pref64_prefix *p) {
|
||||
sd_radv_pref64_prefix *found = NULL;
|
||||
int r;
|
||||
|
||||
assert_return(ra, -EINVAL);
|
||||
assert_return(p, -EINVAL);
|
||||
|
||||
const char *addr_p = IN6_ADDR_PREFIX_TO_STRING(&p->in6_addr, p->prefixlen);
|
||||
|
||||
LIST_FOREACH(prefix, cur, ra->pref64_prefixes) {
|
||||
r = in_addr_prefix_intersect(AF_INET6,
|
||||
(const union in_addr_union*) &cur->in6_addr,
|
||||
cur->prefixlen,
|
||||
(const union in_addr_union*) &p->in6_addr,
|
||||
p->prefixlen);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
continue;
|
||||
|
||||
if (cur->prefixlen == p->prefixlen) {
|
||||
found = cur;
|
||||
break;
|
||||
}
|
||||
|
||||
return log_radv_errno(ra, SYNTHETIC_ERRNO(EEXIST),
|
||||
"IPv6 PREF64 prefix %s conflicts with %s, ignoring.",
|
||||
addr_p,
|
||||
IN6_ADDR_PREFIX_TO_STRING(&cur->in6_addr, cur->prefixlen));
|
||||
}
|
||||
|
||||
if (found) {
|
||||
/* p and cur may be equivalent. First increment the reference counter. */
|
||||
sd_radv_pref64_prefix_ref(p);
|
||||
|
||||
/* Then, remove the old entry. */
|
||||
LIST_REMOVE(prefix, ra->pref64_prefixes, found);
|
||||
sd_radv_pref64_prefix_unref(found);
|
||||
|
||||
/* Finally, add the new entry. */
|
||||
LIST_APPEND(prefix, ra->pref64_prefixes, p);
|
||||
|
||||
log_radv(ra, "Updated/replaced IPv6 PREF64 prefix %s (lifetime: %s)",
|
||||
strna(addr_p),
|
||||
FORMAT_TIMESPAN(p->lifetime_usec, USEC_PER_SEC));
|
||||
} else {
|
||||
/* The route prefix is new. Let's simply add it. */
|
||||
|
||||
sd_radv_pref64_prefix_ref(p);
|
||||
LIST_APPEND(prefix, ra->pref64_prefixes, p);
|
||||
ra->n_pref64_prefixes++;
|
||||
|
||||
log_radv(ra, "Added PREF64 prefix %s", strna(addr_p));
|
||||
}
|
||||
|
||||
if (ra->state == RADV_STATE_IDLE)
|
||||
return 0;
|
||||
|
||||
if (ra->ra_sent == 0)
|
||||
return 0;
|
||||
|
||||
/* If RAs have already been sent, send an RA immediately to announce the newly-added route prefix */
|
||||
r = radv_send(ra, NULL, ra->lifetime_usec);
|
||||
if (r < 0)
|
||||
log_radv_errno(ra, r, "Unable to send Router Advertisement for added PREF64 prefix %s, ignoring: %m",
|
||||
strna(addr_p));
|
||||
else
|
||||
log_radv(ra, "Sent Router Advertisement for added PREF64 prefix %s.", strna(addr_p));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sd_radv_set_rdnss(
|
||||
sd_radv *ra,
|
||||
uint32_t lifetime,
|
||||
@ -983,3 +1059,77 @@ int sd_radv_route_prefix_set_lifetime(sd_radv_route_prefix *p, uint64_t lifetime
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sd_radv_pref64_prefix_new(sd_radv_pref64_prefix **ret) {
|
||||
sd_radv_pref64_prefix *p;
|
||||
|
||||
assert_return(ret, -EINVAL);
|
||||
|
||||
p = new(sd_radv_pref64_prefix, 1);
|
||||
if (!p)
|
||||
return -ENOMEM;
|
||||
|
||||
*p = (sd_radv_pref64_prefix) {
|
||||
.n_ref = 1,
|
||||
|
||||
.opt.type = RADV_OPT_PREF64,
|
||||
.opt.length = 2,
|
||||
};
|
||||
|
||||
*ret = p;
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_radv_pref64_prefix, sd_radv_pref64_prefix, mfree);
|
||||
|
||||
int sd_radv_pref64_prefix_set_prefix(
|
||||
sd_radv_pref64_prefix *p,
|
||||
const struct in6_addr *prefix,
|
||||
uint8_t prefixlen,
|
||||
uint64_t lifetime_usec) {
|
||||
|
||||
uint16_t pref64_lifetime;
|
||||
uint8_t prefixlen_code;
|
||||
|
||||
assert_return(p, -EINVAL);
|
||||
assert_return(prefix, -EINVAL);
|
||||
|
||||
switch (prefixlen) {
|
||||
case 96:
|
||||
prefixlen_code = 0;
|
||||
break;
|
||||
case 64:
|
||||
prefixlen_code = 1;
|
||||
break;
|
||||
case 56:
|
||||
prefixlen_code = 2;
|
||||
break;
|
||||
case 48:
|
||||
prefixlen_code = 3;
|
||||
break;
|
||||
case 40:
|
||||
prefixlen_code = 4;
|
||||
break;
|
||||
case 32:
|
||||
prefixlen_code = 5;
|
||||
break;
|
||||
default:
|
||||
log_radv(NULL, "Unsupported PREF64 prefix length %u. Valid lengths are 32, 40, 48, 56, 64 and 96", prefixlen);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (lifetime_usec == USEC_INFINITY || DIV_ROUND_UP(lifetime_usec, 8 * USEC_PER_SEC) >= UINT64_C(1) << 13)
|
||||
return -EINVAL;
|
||||
|
||||
/* RFC 8781 - 4.1 rounding up lifetime to multiply of 8 */
|
||||
pref64_lifetime = DIV_ROUND_UP(lifetime_usec, 8 * USEC_PER_SEC) << 3;
|
||||
pref64_lifetime |= prefixlen_code;
|
||||
|
||||
unaligned_write_be16(&p->opt.lifetime_and_plc, pref64_lifetime);
|
||||
memcpy(&p->opt.prefix, prefix, sizeof(p->opt.prefix));
|
||||
|
||||
p->in6_addr = *prefix;
|
||||
p->prefixlen = prefixlen;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -389,6 +389,8 @@ IPv6Prefix.RouteMetric, config_parse_prefix_metric,
|
||||
IPv6Prefix.Token, config_parse_prefix_token, 0, 0
|
||||
IPv6RoutePrefix.Route, config_parse_route_prefix, 0, 0
|
||||
IPv6RoutePrefix.LifetimeSec, config_parse_route_prefix_lifetime, 0, 0
|
||||
IPv6PREF64Prefix.Prefix, config_parse_pref64_prefix, 0, 0
|
||||
IPv6PREF64Prefix.LifetimeSec, config_parse_pref64_prefix_lifetime, 0, 0
|
||||
LLDP.MUDURL, config_parse_mud_url, 0, offsetof(Network, lldp_mudurl)
|
||||
CAN.BitRate, config_parse_can_bitrate, 0, offsetof(Network, can_bitrate)
|
||||
CAN.SamplePoint, config_parse_permille, 0, offsetof(Network, can_sample_point)
|
||||
|
@ -529,6 +529,7 @@ int network_load_one(Manager *manager, OrderedHashmap **networks, const char *fi
|
||||
"IPv6PrefixDelegation\0"
|
||||
"IPv6Prefix\0"
|
||||
"IPv6RoutePrefix\0"
|
||||
"IPv6PREF64Prefix\0"
|
||||
"LLDP\0"
|
||||
"TrafficControlQueueingDiscipline\0"
|
||||
"CAN\0"
|
||||
@ -779,6 +780,7 @@ static Network *network_free(Network *network) {
|
||||
hashmap_free_with_destructor(network->address_labels_by_section, address_label_free);
|
||||
hashmap_free_with_destructor(network->prefixes_by_section, prefix_free);
|
||||
hashmap_free_with_destructor(network->route_prefixes_by_section, route_prefix_free);
|
||||
hashmap_free_with_destructor(network->pref64_prefixes_by_section, pref64_prefix_free);
|
||||
hashmap_free_with_destructor(network->rules_by_section, routing_policy_rule_free);
|
||||
hashmap_free_with_destructor(network->dhcp_static_leases_by_section, dhcp_static_lease_free);
|
||||
ordered_hashmap_free_with_destructor(network->sr_iov_by_section, sr_iov_free);
|
||||
@ -844,6 +846,9 @@ bool network_has_static_ipv6_configurations(Network *network) {
|
||||
if (!hashmap_isempty(network->route_prefixes_by_section))
|
||||
return true;
|
||||
|
||||
if (!hashmap_isempty(network->pref64_prefixes_by_section))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -358,6 +358,7 @@ struct Network {
|
||||
Hashmap *address_labels_by_section;
|
||||
Hashmap *prefixes_by_section;
|
||||
Hashmap *route_prefixes_by_section;
|
||||
Hashmap *pref64_prefixes_by_section;
|
||||
Hashmap *rules_by_section;
|
||||
Hashmap *dhcp_static_leases_by_section;
|
||||
Hashmap *qdiscs_by_section;
|
||||
|
@ -48,6 +48,7 @@ void network_adjust_radv(Network *network) {
|
||||
if (!FLAGS_SET(network->router_prefix_delegation, RADV_PREFIX_DELEGATION_STATIC)) {
|
||||
network->prefixes_by_section = hashmap_free_with_destructor(network->prefixes_by_section, prefix_free);
|
||||
network->route_prefixes_by_section = hashmap_free_with_destructor(network->route_prefixes_by_section, route_prefix_free);
|
||||
network->pref64_prefixes_by_section = hashmap_free_with_destructor(network->pref64_prefixes_by_section, pref64_prefix_free);
|
||||
}
|
||||
}
|
||||
|
||||
@ -177,6 +178,61 @@ static int route_prefix_new_static(Network *network, const char *filename, unsig
|
||||
return 0;
|
||||
}
|
||||
|
||||
pref64Prefix *pref64_prefix_free(pref64Prefix *prefix) {
|
||||
if (!prefix)
|
||||
return NULL;
|
||||
|
||||
if (prefix->network) {
|
||||
assert(prefix->section);
|
||||
hashmap_remove(prefix->network->pref64_prefixes_by_section, prefix->section);
|
||||
}
|
||||
|
||||
config_section_free(prefix->section);
|
||||
|
||||
return mfree(prefix);
|
||||
}
|
||||
|
||||
DEFINE_SECTION_CLEANUP_FUNCTIONS(pref64Prefix, pref64_prefix_free);
|
||||
|
||||
static int pref64_prefix_new_static(Network *network, const char *filename, unsigned section_line, pref64Prefix **ret) {
|
||||
_cleanup_(config_section_freep) ConfigSection *n = NULL;
|
||||
_cleanup_(pref64_prefix_freep) pref64Prefix *prefix = NULL;
|
||||
int r;
|
||||
|
||||
assert(network);
|
||||
assert(ret);
|
||||
assert(filename);
|
||||
assert(section_line > 0);
|
||||
|
||||
r = config_section_new(filename, section_line, &n);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
prefix = hashmap_get(network->pref64_prefixes_by_section, n);
|
||||
if (prefix) {
|
||||
*ret = TAKE_PTR(prefix);
|
||||
return 0;
|
||||
}
|
||||
|
||||
prefix = new(pref64Prefix, 1);
|
||||
if (!prefix)
|
||||
return -ENOMEM;
|
||||
|
||||
*prefix = (pref64Prefix) {
|
||||
.network = network,
|
||||
.section = TAKE_PTR(n),
|
||||
|
||||
.lifetime = RADV_DEFAULT_PRE64_LIFETIME_USEC,
|
||||
};
|
||||
|
||||
r = hashmap_ensure_put(&network->pref64_prefixes_by_section, &config_section_hash_ops, prefix->section, prefix);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
*ret = TAKE_PTR(prefix);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int link_request_radv_addresses(Link *link) {
|
||||
Prefix *p;
|
||||
int r;
|
||||
@ -294,6 +350,25 @@ static int radv_set_route_prefix(Link *link, RoutePrefix *prefix) {
|
||||
return sd_radv_add_route_prefix(link->radv, p);
|
||||
}
|
||||
|
||||
static int radv_set_pref64_prefix(Link *link, pref64Prefix *prefix) {
|
||||
_cleanup_(sd_radv_pref64_prefix_unrefp) sd_radv_pref64_prefix *p = NULL;
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
assert(link->radv);
|
||||
assert(prefix);
|
||||
|
||||
r = sd_radv_pref64_prefix_new(&p);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_radv_pref64_prefix_set_prefix(p, &prefix->prefix, prefix->prefixlen, prefix->lifetime);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return sd_radv_add_pref64_prefix(link->radv, p);
|
||||
}
|
||||
|
||||
static int network_get_ipv6_dns(Network *network, struct in6_addr **ret_addresses, size_t *ret_size) {
|
||||
_cleanup_free_ struct in6_addr *addresses = NULL;
|
||||
size_t n_addresses = 0;
|
||||
@ -441,6 +516,7 @@ static int radv_find_uplink(Link *link, Link **ret) {
|
||||
static int radv_configure(Link *link) {
|
||||
Link *uplink = NULL;
|
||||
RoutePrefix *q;
|
||||
pref64Prefix *n;
|
||||
Prefix *p;
|
||||
int r;
|
||||
|
||||
@ -508,6 +584,12 @@ static int radv_configure(Link *link) {
|
||||
return r;
|
||||
}
|
||||
|
||||
HASHMAP_FOREACH(n, link->network->pref64_prefixes_by_section) {
|
||||
r = radv_set_pref64_prefix(link, n);
|
||||
if (r < 0 && r != -EEXIST)
|
||||
return r;
|
||||
}
|
||||
|
||||
(void) radv_find_uplink(link, &uplink);
|
||||
|
||||
r = radv_set_dns(link, uplink);
|
||||
@ -792,6 +874,16 @@ void network_drop_invalid_route_prefixes(Network *network) {
|
||||
route_prefix_free(p);
|
||||
}
|
||||
|
||||
void network_drop_invalid_pref64_prefixes(Network *network) {
|
||||
pref64Prefix *p;
|
||||
|
||||
assert(network);
|
||||
|
||||
HASHMAP_FOREACH(p, network->pref64_prefixes_by_section)
|
||||
if (section_is_invalid(p->section))
|
||||
pref64_prefix_free(p);
|
||||
}
|
||||
|
||||
int config_parse_prefix(
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
@ -1083,6 +1175,99 @@ int config_parse_route_prefix_lifetime(
|
||||
return 0;
|
||||
}
|
||||
|
||||
int config_parse_pref64_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) {
|
||||
|
||||
_cleanup_(pref64_prefix_free_or_set_invalidp) pref64Prefix *p = NULL;
|
||||
Network *network = ASSERT_PTR(userdata);
|
||||
union in_addr_union a;
|
||||
uint8_t prefixlen;
|
||||
int r;
|
||||
|
||||
assert(filename);
|
||||
assert(section);
|
||||
assert(lvalue);
|
||||
assert(rvalue);
|
||||
|
||||
r = pref64_prefix_new_static(network, filename, section_line, &p);
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
|
||||
r = in_addr_prefix_from_string(rvalue, AF_INET6, &a, &prefixlen);
|
||||
if (r < 0) {
|
||||
log_syntax(unit, LOG_WARNING, filename, line, r,
|
||||
"PREF64 prefix is invalid, ignoring assignment: %s", rvalue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!IN_SET(prefixlen, 96, 64, 56, 48, 40, 32)) {
|
||||
log_syntax(unit, LOG_WARNING, filename, line, 0,
|
||||
"PREF64 prefixlen is invalid, ignoring assignment: %s", rvalue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
(void) in6_addr_mask(&a.in6,prefixlen);
|
||||
p->prefix = a.in6;
|
||||
p->prefixlen = prefixlen;
|
||||
|
||||
TAKE_PTR(p);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int config_parse_pref64_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) {
|
||||
|
||||
_cleanup_(pref64_prefix_free_or_set_invalidp) pref64Prefix *p = NULL;
|
||||
Network *network = ASSERT_PTR(userdata);
|
||||
usec_t usec;
|
||||
int r;
|
||||
|
||||
assert(filename);
|
||||
assert(section);
|
||||
assert(lvalue);
|
||||
assert(rvalue);
|
||||
|
||||
r = pref64_prefix_new_static(network, filename, section_line, &p);
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
|
||||
r = parse_sec(rvalue, &usec);
|
||||
if (r < 0) {
|
||||
log_syntax(unit, LOG_WARNING, filename, line, r,
|
||||
"PREF64 lifetime is invalid, ignoring assignment: %s", rvalue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (usec == USEC_INFINITY || DIV_ROUND_UP(usec, 8 * USEC_PER_SEC) >= UINT64_C(1) << 13) {
|
||||
log_syntax(unit, LOG_WARNING, filename, line, 0,
|
||||
"PREF64 lifetime is too long, ignoring assignment: %s", rvalue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
p->lifetime = usec;
|
||||
|
||||
TAKE_PTR(p);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int config_parse_radv_dns(
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
|
@ -52,11 +52,22 @@ typedef struct RoutePrefix {
|
||||
usec_t lifetime;
|
||||
} RoutePrefix;
|
||||
|
||||
typedef struct pref64Prefix {
|
||||
Network *network;
|
||||
ConfigSection *section;
|
||||
|
||||
struct in6_addr prefix;
|
||||
uint8_t prefixlen;
|
||||
usec_t lifetime;
|
||||
} pref64Prefix;
|
||||
|
||||
Prefix *prefix_free(Prefix *prefix);
|
||||
RoutePrefix *route_prefix_free(RoutePrefix *prefix);
|
||||
pref64Prefix *pref64_prefix_free(pref64Prefix *prefix);
|
||||
|
||||
void network_drop_invalid_prefixes(Network *network);
|
||||
void network_drop_invalid_route_prefixes(Network *network);
|
||||
void network_drop_invalid_pref64_prefixes(Network *network);
|
||||
void network_adjust_radv(Network *network);
|
||||
|
||||
int link_request_radv_addresses(Link *link);
|
||||
@ -85,3 +96,5 @@ CONFIG_PARSER_PROTOTYPE(config_parse_radv_dns);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_radv_search_domains);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_route_prefix);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_route_prefix_lifetime);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_pref64_prefix);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_pref64_prefix_lifetime);
|
||||
|
@ -33,6 +33,7 @@ _SD_BEGIN_DECLARATIONS;
|
||||
typedef struct sd_radv sd_radv;
|
||||
typedef struct sd_radv_prefix sd_radv_prefix;
|
||||
typedef struct sd_radv_route_prefix sd_radv_route_prefix;
|
||||
typedef struct sd_radv_pref64_prefix sd_radv_pref64_prefix;
|
||||
|
||||
/* Router Advertisement */
|
||||
int sd_radv_new(sd_radv **ret);
|
||||
@ -60,6 +61,7 @@ int sd_radv_set_other_information(sd_radv *ra, int other);
|
||||
int sd_radv_set_preference(sd_radv *ra, unsigned preference);
|
||||
int sd_radv_add_prefix(sd_radv *ra, sd_radv_prefix *p);
|
||||
int sd_radv_add_route_prefix(sd_radv *ra, sd_radv_route_prefix *p);
|
||||
int sd_radv_add_pref64_prefix(sd_radv *ra, sd_radv_pref64_prefix *p);
|
||||
void sd_radv_remove_prefix(sd_radv *ra, const struct in6_addr *prefix, unsigned char prefixlen);
|
||||
int sd_radv_set_rdnss(sd_radv *ra, uint32_t lifetime,
|
||||
const struct in6_addr *dns, size_t n_dns);
|
||||
@ -87,9 +89,16 @@ sd_radv_route_prefix *sd_radv_route_prefix_unref(sd_radv_route_prefix *ra);
|
||||
int sd_radv_route_prefix_set_prefix(sd_radv_route_prefix *p, const struct in6_addr *in6_addr, unsigned char prefixlen);
|
||||
int sd_radv_route_prefix_set_lifetime(sd_radv_route_prefix *p, uint64_t lifetime_usec, uint64_t valid_until);
|
||||
|
||||
int sd_radv_pref64_prefix_new(sd_radv_pref64_prefix **ret);
|
||||
int sd_radv_pref64_prefix_set_prefix(sd_radv_pref64_prefix *p, const struct in6_addr *prefix,
|
||||
uint8_t prefixlen, uint64_t lifetime_usec);
|
||||
sd_radv_pref64_prefix *sd_radv_pref64_prefix_ref(sd_radv_pref64_prefix *ra);
|
||||
sd_radv_pref64_prefix *sd_radv_pref64_prefix_unref(sd_radv_pref64_prefix *ra);
|
||||
|
||||
_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_radv, sd_radv_unref);
|
||||
_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_radv_prefix, sd_radv_prefix_unref);
|
||||
_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_radv_route_prefix, sd_radv_route_prefix_unref);
|
||||
_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_radv_pref64_prefix, sd_radv_pref64_prefix_unref);
|
||||
|
||||
_SD_END_DECLARATIONS;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user