diff --git a/man/systemd.network.xml b/man/systemd.network.xml index 77ed77918c..abd0abbf9b 100644 --- a/man/systemd.network.xml +++ b/man/systemd.network.xml @@ -2676,9 +2676,9 @@ Token=prefixstable:2002:da8:1:: DNSLifetimeSec= - Lifetime in seconds for the DNS server addresses listed - in DNS= and search domains listed in - Domains=. + Lifetime in seconds for the DNS server addresses listed in + DNS= and search domains listed in Domains=. Defaults to + 604800 seconds (one week). diff --git a/src/libsystemd-network/sd-radv.c b/src/libsystemd-network/sd-radv.c index ae33894302..2d91a406f8 100644 --- a/src/libsystemd-network/sd-radv.c +++ b/src/libsystemd-network/sd-radv.c @@ -936,7 +936,7 @@ _public_ int sd_radv_route_prefix_new(sd_radv_route_prefix **ret) { DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_radv_route_prefix, sd_radv_route_prefix, mfree); -_public_ int sd_radv_prefix_set_route_prefix(sd_radv_route_prefix *p, const struct in6_addr *in6_addr, +_public_ int sd_radv_route_prefix_set_prefix(sd_radv_route_prefix *p, const struct in6_addr *in6_addr, unsigned char prefixlen) { assert_return(p, -EINVAL); assert_return(in6_addr, -EINVAL); diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf index b670038d2a..a207e374d5 100644 --- a/src/network/networkd-network-gperf.gperf +++ b/src/network/networkd-network-gperf.gperf @@ -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 diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index afbb9d61db..c3b408c4e9 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -420,6 +420,7 @@ int network_load_one(Manager *manager, OrderedHashmap **networks, const char *fi .dhcp_server_emit_timezone = true, .router_lifetime_usec = 30 * USEC_PER_MINUTE, + .router_dns_lifetime_usec = 7 * USEC_PER_DAY, .router_emit_dns = true, .router_emit_domains = true, diff --git a/src/network/networkd-radv.c b/src/network/networkd-radv.c index 34e6a41c34..73e9bce52a 100644 --- a/src/network/networkd-radv.c +++ b/src/network/networkd-radv.c @@ -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,16 @@ 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) { - _cleanup_free_ char *str = NULL; - - (void) in6_addr_prefix_to_string(&prefix, prefixlen, &str); - log_link_debug(link, - "Prefix is longer than 64, refusing to assign an address in %s.", - strna(str)); + if (p->prefixlen > 64) 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 +206,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 +218,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; @@ -288,7 +324,6 @@ static int network_get_ipv6_dns(Network *network, struct in6_addr **ret_addresse static int radv_set_dns(Link *link, Link *uplink) { _cleanup_free_ struct in6_addr *dns = NULL; - usec_t lifetime_usec; size_t n_dns; int r; @@ -311,13 +346,10 @@ static int radv_set_dns(Link *link, Link *uplink) { *(p++) = link->network->router_dns[i]; n_dns = p - dns; - lifetime_usec = link->network->router_dns_lifetime_usec; goto set_dns; } - lifetime_usec = SD_RADV_DEFAULT_DNS_LIFETIME_USEC; - r = network_get_ipv6_dns(link->network, &dns, &n_dns); if (r > 0) goto set_dns; @@ -334,26 +366,22 @@ static int radv_set_dns(Link *link, Link *uplink) { set_dns: return sd_radv_set_rdnss(link->radv, - DIV_ROUND_UP(lifetime_usec, USEC_PER_SEC), + usec_to_lifetime(link->network->router_dns_lifetime_usec), dns, n_dns); } static int radv_set_domains(Link *link, Link *uplink) { - OrderedSet *search_domains; - usec_t lifetime_usec; _cleanup_free_ char **s = NULL; /* just free() because the strings are owned by the set */ + OrderedSet *search_domains; if (!link->network->router_emit_domains) return 0; search_domains = link->network->router_search_domains; - lifetime_usec = link->network->router_dns_lifetime_usec; if (search_domains) goto set_domains; - lifetime_usec = SD_RADV_DEFAULT_DNS_LIFETIME_USEC; - search_domains = link->network->search_domains; if (search_domains) goto set_domains; @@ -374,7 +402,7 @@ set_domains: return log_oom(); return sd_radv_set_dnssl(link->radv, - DIV_ROUND_UP(lifetime_usec, USEC_PER_SEC), + usec_to_lifetime(link->network->router_dns_lifetime_usec), s); } @@ -455,22 +483,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; } @@ -643,24 +663,94 @@ int radv_add_prefix( return 0; } +static int prefix_section_verify(Prefix *p) { + assert(p); + + if (section_is_invalid(p->section)) + return -EINVAL; + + if (in6_addr_is_null(&p->prefix)) + return log_warning_errno(SYNTHETIC_ERRNO(EINVAL), + "%s: [IPv6Prefix] section without Prefix= field configured, " + "or specified prefix is the null address. " + "Ignoring [IPv6Prefix] section from line %u.", + p->section->filename, p->section->line); + + if (p->prefixlen < 3 || p->prefixlen > 128) + return log_warning_errno(SYNTHETIC_ERRNO(EINVAL), + "%s: Invalid prefix length %u is specified in [IPv6Prefix] section. " + "Valid range is 3…128. Ignoring [IPv6Prefix] section from line %u.", + p->section->filename, p->prefixlen, p->section->line); + + if (p->prefixlen > 64) { + _cleanup_free_ char *str = NULL; + + if (p->assign) + (void) in6_addr_prefix_to_string(&p->prefix, p->prefixlen, &str); + + log_info("%s: Unusual prefix length %u (> 64) is specified in [IPv6Prefix] section from line %u%s%s.", + p->section->filename, p->prefixlen, p->section->line, + p->assign ? ", refusing to assign an address in " : "", + p->assign ? strna(str) : ""); + + p->assign = false; + } + + if (p->valid_lifetime == 0) + return log_warning_errno(SYNTHETIC_ERRNO(EINVAL), + "%s: The valid lifetime of prefix cannot be zero. " + "Ignoring [IPv6Prefix] section from line %u.", + p->section->filename, p->section->line); + + if (p->preferred_lifetime > p->valid_lifetime) + return log_warning_errno(SYNTHETIC_ERRNO(EINVAL), + "%s: The preferred lifetime %s is longer than the valid lifetime %s. " + "Ignoring [IPv6Prefix] section from line %u.", + p->section->filename, + FORMAT_TIMESPAN(p->preferred_lifetime, USEC_PER_SEC), + FORMAT_TIMESPAN(p->valid_lifetime, USEC_PER_SEC), + p->section->line); + + return 0; +} + void network_drop_invalid_prefixes(Network *network) { - Prefix *prefix; + Prefix *p; assert(network); - HASHMAP_FOREACH(prefix, network->prefixes_by_section) - if (section_is_invalid(prefix->section)) - prefix_free(prefix); + HASHMAP_FOREACH(p, network->prefixes_by_section) + if (prefix_section_verify(p) < 0) + prefix_free(p); +} + +static int route_prefix_section_verify(RoutePrefix *p) { + if (section_is_invalid(p->section)) + return -EINVAL; + + if (p->prefixlen > 128) + return log_warning_errno(SYNTHETIC_ERRNO(EINVAL), + "%s: Invalid prefix length %u is specified in [IPv6RoutePrefix] section. " + "Valid range is 0…128. Ignoring [IPv6RoutePrefix] section from line %u.", + p->section->filename, p->prefixlen, p->section->line); + + if (p->lifetime == 0) + return log_warning_errno(SYNTHETIC_ERRNO(EINVAL), + "%s: The lifetime of route cannot be zero. " + "Ignoring [IPv6RoutePrefix] section from line %u.", + p->section->filename, p->section->line); + + return 0; } void network_drop_invalid_route_prefixes(Network *network) { - RoutePrefix *prefix; + RoutePrefix *p; assert(network); - HASHMAP_FOREACH(prefix, network->route_prefixes_by_section) - if (section_is_invalid(prefix->section)) - route_prefix_free(prefix); + HASHMAP_FOREACH(p, network->route_prefixes_by_section) + if (route_prefix_section_verify(p) < 0) + route_prefix_free(p); } int config_parse_prefix( @@ -675,40 +765,36 @@ 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; } - 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; + (void) in6_addr_mask(&a.in6, p->prefixlen); + p->prefix = a.in6; + 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 +806,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 +822,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 +852,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 +861,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 +903,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 +926,6 @@ int config_parse_prefix_metric( } TAKE_PTR(p); - return 0; } @@ -930,36 +976,32 @@ 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; } - r = sd_radv_prefix_set_route_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; + (void) in6_addr_mask(&a.in6, p->prefixlen); + p->prefix = a.in6; + TAKE_PTR(p); return 0; } @@ -975,8 +1017,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 +1026,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 +1039,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; } diff --git a/src/network/networkd-radv.h b/src/network/networkd-radv.h index 5c869d8623..d51fe323dc 100644 --- a/src/network/networkd-radv.h +++ b/src/network/networkd-radv.h @@ -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); diff --git a/src/systemd/sd-radv.h b/src/systemd/sd-radv.h index 6bf56def40..f597c2c33d 100644 --- a/src/systemd/sd-radv.h +++ b/src/systemd/sd-radv.h @@ -91,7 +91,7 @@ int sd_radv_route_prefix_new(sd_radv_route_prefix **ret); sd_radv_route_prefix *sd_radv_route_prefix_ref(sd_radv_route_prefix *ra); sd_radv_route_prefix *sd_radv_route_prefix_unref(sd_radv_route_prefix *ra); -int sd_radv_prefix_set_route_prefix(sd_radv_route_prefix *p, const struct in6_addr *in6_addr, unsigned char prefixlen); +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, uint32_t valid_lifetime); _SD_DEFINE_POINTER_CLEANUP_FUNC(sd_radv, sd_radv_unref);