1
1
mirror of https://github.com/systemd/systemd-stable.git synced 2024-12-24 21:34:08 +03:00

network: radv: make conf parsers not set values into sd_radv_prefix/sd_radv_route_prefix

Preparation for later commits.
This commit is contained in:
Yu Watanabe 2021-09-27 21:07:27 +09:00
parent 7ebb14313f
commit 2ac4167900
3 changed files with 168 additions and 179 deletions

View File

@ -342,11 +342,11 @@ IPv6SendRA.Domains, config_parse_radv_search_domains,
IPv6SendRA.DNSLifetimeSec, config_parse_sec, 0, offsetof(Network, router_dns_lifetime_usec)
IPv6SendRA.UplinkInterface, config_parse_uplink, 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.OnLink, config_parse_prefix_boolean, 0, 0
IPv6Prefix.AddressAutoconfiguration, config_parse_prefix_boolean, 0, 0
IPv6Prefix.ValidLifetimeSec, config_parse_prefix_lifetime, 0, 0
IPv6Prefix.PreferredLifetimeSec, config_parse_prefix_lifetime, 0, 0
IPv6Prefix.Assign, config_parse_prefix_assign, 0, 0
IPv6Prefix.Assign, config_parse_prefix_boolean, 0, 0
IPv6Prefix.RouteMetric, config_parse_prefix_metric, 0, 0
IPv6Prefix.Token, config_parse_prefix_token, 0, 0
IPv6RoutePrefix.Route, config_parse_route_prefix, 0, 0

View File

@ -68,7 +68,6 @@ Prefix *prefix_free(Prefix *prefix) {
}
network_config_section_free(prefix->section);
sd_radv_prefix_unref(prefix->radv_prefix);
set_free(prefix->tokens);
return mfree(prefix);
@ -76,21 +75,6 @@ Prefix *prefix_free(Prefix *prefix) {
DEFINE_NETWORK_SECTION_FUNCTIONS(Prefix, prefix_free);
static int prefix_new(Prefix **ret) {
_cleanup_(prefix_freep) Prefix *prefix = NULL;
prefix = new0(Prefix, 1);
if (!prefix)
return -ENOMEM;
if (sd_radv_prefix_new(&prefix->radv_prefix) < 0)
return -ENOMEM;
*ret = TAKE_PTR(prefix);
return 0;
}
static int prefix_new_static(Network *network, const char *filename, unsigned section_line, Prefix **ret) {
_cleanup_(network_config_section_freep) NetworkConfigSection *n = NULL;
_cleanup_(prefix_freep) Prefix *prefix = NULL;
@ -111,19 +95,25 @@ static int prefix_new_static(Network *network, const char *filename, unsigned se
return 0;
}
r = prefix_new(&prefix);
if (r < 0)
return r;
prefix = new(Prefix, 1);
if (!prefix)
return -ENOMEM;
prefix->network = network;
prefix->section = TAKE_PTR(n);
*prefix = (Prefix) {
.network = network,
.section = TAKE_PTR(n),
.preferred_lifetime = 7 * USEC_PER_DAY,
.valid_lifetime = 30 * USEC_PER_DAY,
.onlink = true,
.address_auto_configuration = true,
};
r = hashmap_ensure_put(&network->prefixes_by_section, &network_config_hash_ops, prefix->section, prefix);
if (r < 0)
return r;
*ret = TAKE_PTR(prefix);
return 0;
}
@ -137,28 +127,12 @@ RoutePrefix *route_prefix_free(RoutePrefix *prefix) {
}
network_config_section_free(prefix->section);
sd_radv_route_prefix_unref(prefix->radv_route_prefix);
return mfree(prefix);
}
DEFINE_NETWORK_SECTION_FUNCTIONS(RoutePrefix, route_prefix_free);
static int route_prefix_new(RoutePrefix **ret) {
_cleanup_(route_prefix_freep) RoutePrefix *prefix = NULL;
prefix = new0(RoutePrefix, 1);
if (!prefix)
return -ENOMEM;
if (sd_radv_route_prefix_new(&prefix->radv_route_prefix) < 0)
return -ENOMEM;
*ret = TAKE_PTR(prefix);
return 0;
}
static int route_prefix_new_static(Network *network, const char *filename, unsigned section_line, RoutePrefix **ret) {
_cleanup_(network_config_section_freep) NetworkConfigSection *n = NULL;
_cleanup_(route_prefix_freep) RoutePrefix *prefix = NULL;
@ -179,19 +153,22 @@ static int route_prefix_new_static(Network *network, const char *filename, unsig
return 0;
}
r = route_prefix_new(&prefix);
if (r < 0)
return r;
prefix = new(RoutePrefix, 1);
if (!prefix)
return -ENOMEM;
prefix->network = network;
prefix->section = TAKE_PTR(n);
*prefix = (RoutePrefix) {
.network = network,
.section = TAKE_PTR(n),
.lifetime = 7 * USEC_PER_DAY,
};
r = hashmap_ensure_put(&network->route_prefixes_by_section, &network_config_hash_ops, prefix->section, prefix);
if (r < 0)
return r;
*ret = TAKE_PTR(prefix);
return 0;
}
@ -206,28 +183,23 @@ int link_request_radv_addresses(Link *link) {
HASHMAP_FOREACH(p, link->network->prefixes_by_section) {
_cleanup_set_free_ Set *addresses = NULL;
struct in6_addr prefix, *a;
uint8_t prefixlen;
struct in6_addr *a;
if (!p->assign)
continue;
r = sd_radv_prefix_get_prefix(p->radv_prefix, &prefix, &prefixlen);
if (r < 0)
return r;
/* radv_generate_addresses() below requires the prefix length <= 64. */
if (prefixlen > 64) {
if (p->prefixlen > 64) {
_cleanup_free_ char *str = NULL;
(void) in6_addr_prefix_to_string(&prefix, prefixlen, &str);
(void) in6_addr_prefix_to_string(&p->prefix, p->prefixlen, &str);
log_link_debug(link,
"Prefix is longer than 64, refusing to assign an address in %s.",
strna(str));
continue;
}
r = radv_generate_addresses(link, p->tokens, &prefix, prefixlen, &addresses);
r = radv_generate_addresses(link, p->tokens, &p->prefix, p->prefixlen, &addresses);
if (r < 0)
return r;
@ -241,7 +213,7 @@ int link_request_radv_addresses(Link *link) {
address->source = NETWORK_CONFIG_SOURCE_STATIC;
address->family = AF_INET6;
address->in_addr.in6 = *a;
address->prefixlen = prefixlen;
address->prefixlen = p->prefixlen;
address->route_metric = p->route_metric;
r = link_request_static_address(link, TAKE_PTR(address), true);
@ -253,6 +225,77 @@ int link_request_radv_addresses(Link *link) {
return 0;
}
static uint32_t usec_to_lifetime(usec_t usec) {
uint64_t t;
if (usec == USEC_INFINITY)
return UINT32_MAX;
t = DIV_ROUND_UP(usec, USEC_PER_SEC);
if (t >= UINT32_MAX)
return UINT32_MAX;
return (uint32_t) t;
}
static int radv_set_prefix(Link *link, Prefix *prefix) {
_cleanup_(sd_radv_prefix_unrefp) sd_radv_prefix *p = NULL;
int r;
assert(link);
assert(link->radv);
assert(prefix);
r = sd_radv_prefix_new(&p);
if (r < 0)
return r;
r = sd_radv_prefix_set_prefix(p, &prefix->prefix, prefix->prefixlen);
if (r < 0)
return r;
r = sd_radv_prefix_set_preferred_lifetime(p, usec_to_lifetime(prefix->preferred_lifetime));
if (r < 0)
return r;
r = sd_radv_prefix_set_valid_lifetime(p, usec_to_lifetime(prefix->valid_lifetime));
if (r < 0)
return r;
r = sd_radv_prefix_set_onlink(p, prefix->onlink);
if (r < 0)
return r;
r = sd_radv_prefix_set_address_autoconfiguration(p, prefix->address_auto_configuration);
if (r < 0)
return r;
return sd_radv_add_prefix(link->radv, p, false);
}
static int radv_set_route_prefix(Link *link, RoutePrefix *prefix) {
_cleanup_(sd_radv_route_prefix_unrefp) sd_radv_route_prefix *p = NULL;
int r;
assert(link);
assert(link->radv);
assert(prefix);
r = sd_radv_route_prefix_new(&p);
if (r < 0)
return r;
r = sd_radv_route_prefix_set_prefix(p, &prefix->prefix, prefix->prefixlen);
if (r < 0)
return r;
r = sd_radv_route_prefix_set_lifetime(p, usec_to_lifetime(prefix->lifetime));
if (r < 0)
return r;
return sd_radv_add_route_prefix(link->radv, p, false);
}
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;
@ -455,22 +498,14 @@ static int radv_configure(Link *link) {
}
HASHMAP_FOREACH(p, link->network->prefixes_by_section) {
r = sd_radv_add_prefix(link->radv, p->radv_prefix, false);
if (r == -EEXIST)
continue;
if (r == -ENOEXEC) {
log_link_warning_errno(link, r, "[IPv6Prefix] section configured without Prefix= setting, ignoring section.");
continue;
}
if (r < 0)
r = radv_set_prefix(link, p);
if (r < 0 && r != -EEXIST)
return r;
}
HASHMAP_FOREACH(q, link->network->route_prefixes_by_section) {
r = sd_radv_add_route_prefix(link->radv, q->radv_route_prefix, false);
if (r == -EEXIST)
continue;
if (r < 0)
r = radv_set_route_prefix(link, q);
if (r < 0 && r != -EEXIST)
return r;
}
@ -675,40 +710,34 @@ int config_parse_prefix(
void *data,
void *userdata) {
Network *network = userdata;
_cleanup_(prefix_free_or_set_invalidp) Prefix *p = NULL;
uint8_t prefixlen = 64;
union in_addr_union in6addr;
Network *network = userdata;
union in_addr_union a;
int r;
assert(filename);
assert(section);
assert(lvalue);
assert(rvalue);
assert(data);
assert(userdata);
r = prefix_new_static(network, filename, section_line, &p);
if (r < 0)
return log_oom();
r = in_addr_prefix_from_string(rvalue, AF_INET6, &in6addr, &prefixlen);
r = in_addr_prefix_from_string(rvalue, AF_INET6, &a, &p->prefixlen);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r, "Prefix is invalid, ignoring assignment: %s", rvalue);
log_syntax(unit, LOG_WARNING, filename, line, r,
"Prefix is invalid, ignoring assignment: %s", rvalue);
return 0;
}
p->prefix = a.in6;
r = sd_radv_prefix_set_prefix(p->radv_prefix, &in6addr.in6, prefixlen);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to set radv prefix, ignoring assignment: %s", rvalue);
return 0;
}
p = NULL;
TAKE_PTR(p);
return 0;
}
int config_parse_prefix_flags(
int config_parse_prefix_boolean(
const char *unit,
const char *filename,
unsigned line,
@ -720,15 +749,15 @@ int config_parse_prefix_flags(
void *data,
void *userdata) {
Network *network = userdata;
_cleanup_(prefix_free_or_set_invalidp) Prefix *p = NULL;
Network *network = userdata;
int r;
assert(filename);
assert(section);
assert(lvalue);
assert(rvalue);
assert(data);
assert(userdata);
r = prefix_new_static(network, filename, section_line, &p);
if (r < 0)
@ -736,21 +765,21 @@ int config_parse_prefix_flags(
r = parse_boolean(rvalue);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse %s=, ignoring assignment: %s", lvalue, rvalue);
log_syntax(unit, LOG_WARNING, filename, line, r,
"Failed to parse %s=, ignoring assignment: %s", lvalue, rvalue);
return 0;
}
if (streq(lvalue, "OnLink"))
r = sd_radv_prefix_set_onlink(p->radv_prefix, r);
p->onlink = r;
else if (streq(lvalue, "AddressAutoconfiguration"))
r = sd_radv_prefix_set_address_autoconfiguration(p->radv_prefix, r);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to set %s=, ignoring assignment: %m", lvalue);
return 0;
}
p = NULL;
p->address_auto_configuration = r;
else if (streq(lvalue, "Assign"))
p->assign = r;
else
assert_not_reached();
TAKE_PTR(p);
return 0;
}
@ -766,8 +795,8 @@ int config_parse_prefix_lifetime(
void *data,
void *userdata) {
Network *network = userdata;
_cleanup_(prefix_free_or_set_invalidp) Prefix *p = NULL;
Network *network = userdata;
usec_t usec;
int r;
@ -775,72 +804,33 @@ int config_parse_prefix_lifetime(
assert(section);
assert(lvalue);
assert(rvalue);
assert(data);
assert(userdata);
r = 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, "Lifetime is invalid, ignoring assignment: %s", rvalue);
return 0;
}
/* a value of 0xffffffff represents infinity */
if (streq(lvalue, "PreferredLifetimeSec"))
r = sd_radv_prefix_set_preferred_lifetime(p->radv_prefix,
DIV_ROUND_UP(usec, USEC_PER_SEC));
else if (streq(lvalue, "ValidLifetimeSec"))
r = sd_radv_prefix_set_valid_lifetime(p->radv_prefix,
DIV_ROUND_UP(usec, USEC_PER_SEC));
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to set %s=, ignoring assignment: %m", lvalue);
return 0;
}
p = NULL;
return 0;
}
int config_parse_prefix_assign(
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_or_set_invalidp) Prefix *p = NULL;
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 log_oom();
r = parse_boolean(rvalue);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Failed to parse %s=, ignoring assignment: %s",
lvalue, rvalue);
"Lifetime is invalid, ignoring assignment: %s", rvalue);
return 0;
}
p->assign = r;
p = NULL;
if (usec != USEC_INFINITY && DIV_ROUND_UP(usec, USEC_PER_SEC) >= UINT32_MAX) {
log_syntax(unit, LOG_WARNING, filename, line, 0,
"Lifetime is too long, ignoring assignment: %s", rvalue);
return 0;
}
if (streq(lvalue, "PreferredLifetimeSec"))
p->preferred_lifetime = usec;
else if (streq(lvalue, "ValidLifetimeSec"))
p->valid_lifetime = usec;
else
assert_not_reached();
TAKE_PTR(p);
return 0;
}
@ -856,15 +846,15 @@ int config_parse_prefix_metric(
void *data,
void *userdata) {
Network *network = userdata;
_cleanup_(prefix_free_or_set_invalidp) Prefix *p = NULL;
Network *network = userdata;
int r;
assert(filename);
assert(section);
assert(lvalue);
assert(rvalue);
assert(data);
assert(userdata);
r = prefix_new_static(network, filename, section_line, &p);
if (r < 0)
@ -879,7 +869,6 @@ int config_parse_prefix_metric(
}
TAKE_PTR(p);
return 0;
}
@ -930,36 +919,30 @@ int config_parse_route_prefix(
void *data,
void *userdata) {
Network *network = userdata;
_cleanup_(route_prefix_free_or_set_invalidp) RoutePrefix *p = NULL;
uint8_t prefixlen = 64;
union in_addr_union in6addr;
Network *network = userdata;
union in_addr_union a;
int r;
assert(filename);
assert(section);
assert(lvalue);
assert(rvalue);
assert(data);
assert(userdata);
r = route_prefix_new_static(network, filename, section_line, &p);
if (r < 0)
return log_oom();
r = in_addr_prefix_from_string(rvalue, AF_INET6, &in6addr, &prefixlen);
r = in_addr_prefix_from_string(rvalue, AF_INET6, &a, &p->prefixlen);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r, "Route prefix is invalid, ignoring assignment: %s", rvalue);
log_syntax(unit, LOG_WARNING, filename, line, r,
"Route prefix is invalid, ignoring assignment: %s", rvalue);
return 0;
}
p->prefix = a.in6;
r = sd_radv_route_prefix_set_prefix(p->radv_route_prefix, &in6addr.in6, prefixlen);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to set route prefix, ignoring assignment: %m");
return 0;
}
p = NULL;
TAKE_PTR(p);
return 0;
}
@ -975,8 +958,8 @@ int config_parse_route_prefix_lifetime(
void *data,
void *userdata) {
Network *network = userdata;
_cleanup_(route_prefix_free_or_set_invalidp) RoutePrefix *p = NULL;
Network *network = userdata;
usec_t usec;
int r;
@ -984,7 +967,7 @@ int config_parse_route_prefix_lifetime(
assert(section);
assert(lvalue);
assert(rvalue);
assert(data);
assert(userdata);
r = route_prefix_new_static(network, filename, section_line, &p);
if (r < 0)
@ -997,16 +980,15 @@ int config_parse_route_prefix_lifetime(
return 0;
}
/* a value of 0xffffffff represents infinity */
r = sd_radv_route_prefix_set_lifetime(p->radv_route_prefix, DIV_ROUND_UP(usec, USEC_PER_SEC));
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Failed to set route lifetime, ignoring assignment: %m");
if (usec != USEC_INFINITY && DIV_ROUND_UP(usec, USEC_PER_SEC) >= UINT32_MAX) {
log_syntax(unit, LOG_WARNING, filename, line, 0,
"Lifetime is too long, ignoring assignment: %s", rvalue);
return 0;
}
p = NULL;
p->lifetime = usec;
TAKE_PTR(p);
return 0;
}

View File

@ -31,7 +31,13 @@ typedef struct Prefix {
Network *network;
NetworkConfigSection *section;
sd_radv_prefix *radv_prefix;
struct in6_addr prefix;
uint8_t prefixlen;
usec_t preferred_lifetime;
usec_t valid_lifetime;
bool onlink;
bool address_auto_configuration;
bool assign;
uint32_t route_metric;
@ -42,7 +48,9 @@ typedef struct RoutePrefix {
Network *network;
NetworkConfigSection *section;
sd_radv_route_prefix *radv_route_prefix;
struct in6_addr prefix;
uint8_t prefixlen;
usec_t lifetime;
} RoutePrefix;
Prefix *prefix_free(Prefix *prefix);
@ -67,9 +75,8 @@ RADVPrefixDelegation radv_prefix_delegation_from_string(const char *s) _pure_;
CONFIG_PARSER_PROTOTYPE(config_parse_router_prefix_delegation);
CONFIG_PARSER_PROTOTYPE(config_parse_router_preference);
CONFIG_PARSER_PROTOTYPE(config_parse_prefix);
CONFIG_PARSER_PROTOTYPE(config_parse_prefix_flags);
CONFIG_PARSER_PROTOTYPE(config_parse_prefix_boolean);
CONFIG_PARSER_PROTOTYPE(config_parse_prefix_lifetime);
CONFIG_PARSER_PROTOTYPE(config_parse_prefix_assign);
CONFIG_PARSER_PROTOTYPE(config_parse_prefix_metric);
CONFIG_PARSER_PROTOTYPE(config_parse_prefix_token);
CONFIG_PARSER_PROTOTYPE(config_parse_radv_dns);