Merge pull request #32424 from yuwata/network-radv-cleanups
network/radv: further cleanups
This commit is contained in:
+51
-40
@@ -194,6 +194,52 @@ int in_addr_equal(int family, const union in_addr_union *a, const union in_addr_
|
||||
return -EAFNOSUPPORT;
|
||||
}
|
||||
|
||||
bool in4_addr_prefix_intersect(
|
||||
const struct in_addr *a,
|
||||
unsigned aprefixlen,
|
||||
const struct in_addr *b,
|
||||
unsigned bprefixlen) {
|
||||
|
||||
assert(a);
|
||||
assert(b);
|
||||
|
||||
unsigned m = MIN3(aprefixlen, bprefixlen, (unsigned) (sizeof(struct in_addr) * 8));
|
||||
if (m == 0)
|
||||
return true; /* Let's return earlier, to avoid shift by 32. */
|
||||
|
||||
uint32_t x = be32toh(a->s_addr ^ b->s_addr);
|
||||
uint32_t n = 0xFFFFFFFFUL << (32 - m);
|
||||
return (x & n) == 0;
|
||||
}
|
||||
|
||||
bool in6_addr_prefix_intersect(
|
||||
const struct in6_addr *a,
|
||||
unsigned aprefixlen,
|
||||
const struct in6_addr *b,
|
||||
unsigned bprefixlen) {
|
||||
|
||||
assert(a);
|
||||
assert(b);
|
||||
|
||||
unsigned m = MIN3(aprefixlen, bprefixlen, (unsigned) (sizeof(struct in6_addr) * 8));
|
||||
if (m == 0)
|
||||
return true;
|
||||
|
||||
for (size_t i = 0; i < sizeof(struct in6_addr); i++) {
|
||||
uint8_t x = a->s6_addr[i] ^ b->s6_addr[i];
|
||||
uint8_t n = m < 8 ? (0xFF << (8 - m)) : 0xFF;
|
||||
if ((x & n) != 0)
|
||||
return false;
|
||||
|
||||
if (m <= 8)
|
||||
break;
|
||||
|
||||
m -= 8;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int in_addr_prefix_intersect(
|
||||
int family,
|
||||
const union in_addr_union *a,
|
||||
@@ -201,51 +247,16 @@ int in_addr_prefix_intersect(
|
||||
const union in_addr_union *b,
|
||||
unsigned bprefixlen) {
|
||||
|
||||
unsigned m;
|
||||
|
||||
assert(a);
|
||||
assert(b);
|
||||
|
||||
/* Checks whether there are any addresses that are in both networks */
|
||||
/* Checks whether there are any addresses that are in both networks. */
|
||||
|
||||
m = MIN(aprefixlen, bprefixlen);
|
||||
if (family == AF_INET)
|
||||
return in4_addr_prefix_intersect(&a->in, aprefixlen, &b->in, bprefixlen);
|
||||
|
||||
if (family == AF_INET) {
|
||||
uint32_t x, nm;
|
||||
|
||||
x = be32toh(a->in.s_addr ^ b->in.s_addr);
|
||||
nm = m == 0 ? 0 : 0xFFFFFFFFUL << (32 - m);
|
||||
|
||||
return (x & nm) == 0;
|
||||
}
|
||||
|
||||
if (family == AF_INET6) {
|
||||
unsigned i;
|
||||
|
||||
if (m > 128)
|
||||
m = 128;
|
||||
|
||||
for (i = 0; i < 16; i++) {
|
||||
uint8_t x, nm;
|
||||
|
||||
x = a->in6.s6_addr[i] ^ b->in6.s6_addr[i];
|
||||
|
||||
if (m < 8)
|
||||
nm = 0xFF << (8 - m);
|
||||
else
|
||||
nm = 0xFF;
|
||||
|
||||
if ((x & nm) != 0)
|
||||
return 0;
|
||||
|
||||
if (m > 8)
|
||||
m -= 8;
|
||||
else
|
||||
m = 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
if (family == AF_INET6)
|
||||
return in6_addr_prefix_intersect(&a->in6, aprefixlen, &b->in6, bprefixlen);
|
||||
|
||||
return -EAFNOSUPPORT;
|
||||
}
|
||||
|
||||
@@ -61,7 +61,22 @@ bool in6_addr_is_ipv4_mapped_address(const struct in6_addr *a);
|
||||
bool in4_addr_equal(const struct in_addr *a, const struct in_addr *b);
|
||||
bool in6_addr_equal(const struct in6_addr *a, const struct in6_addr *b);
|
||||
int in_addr_equal(int family, const union in_addr_union *a, const union in_addr_union *b);
|
||||
int in_addr_prefix_intersect(int family, const union in_addr_union *a, unsigned aprefixlen, const union in_addr_union *b, unsigned bprefixlen);
|
||||
bool in4_addr_prefix_intersect(
|
||||
const struct in_addr *a,
|
||||
unsigned aprefixlen,
|
||||
const struct in_addr *b,
|
||||
unsigned bprefixlen);
|
||||
bool in6_addr_prefix_intersect(
|
||||
const struct in6_addr *a,
|
||||
unsigned aprefixlen,
|
||||
const struct in6_addr *b,
|
||||
unsigned bprefixlen);
|
||||
int in_addr_prefix_intersect(
|
||||
int family,
|
||||
const union in_addr_union *a,
|
||||
unsigned aprefixlen,
|
||||
const union in_addr_union *b,
|
||||
unsigned bprefixlen);
|
||||
int in_addr_prefix_next(int family, union in_addr_union *u, unsigned prefixlen);
|
||||
int in_addr_prefix_nth(int family, union in_addr_union *u, unsigned prefixlen, uint64_t nth);
|
||||
int in_addr_random_prefix(int family, union in_addr_union *u, unsigned prefixlen_fixed_part, unsigned prefixlen);
|
||||
|
||||
@@ -626,19 +626,16 @@ int sd_radv_add_prefix(sd_radv *ra, sd_radv_prefix *p) {
|
||||
const char *addr_p = IN6_ADDR_PREFIX_TO_STRING(&p->opt.in6_addr, p->opt.prefixlen);
|
||||
|
||||
LIST_FOREACH(prefix, cur, ra->prefixes) {
|
||||
r = in_addr_prefix_intersect(AF_INET6,
|
||||
(const union in_addr_union*) &cur->opt.in6_addr,
|
||||
cur->opt.prefixlen,
|
||||
(const union in_addr_union*) &p->opt.in6_addr,
|
||||
p->opt.prefixlen);
|
||||
r = in6_addr_prefix_intersect(&cur->opt.in6_addr, cur->opt.prefixlen,
|
||||
&p->opt.in6_addr, p->opt.prefixlen);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
continue;
|
||||
continue; /* no intersection */
|
||||
|
||||
if (cur->opt.prefixlen == p->opt.prefixlen) {
|
||||
found = cur;
|
||||
break;
|
||||
break; /* same prefix */
|
||||
}
|
||||
|
||||
return log_radv_errno(ra, SYNTHETIC_ERRNO(EEXIST),
|
||||
@@ -672,19 +669,6 @@ int sd_radv_add_prefix(sd_radv *ra, sd_radv_prefix *p) {
|
||||
log_radv(ra, "Added prefix %s", addr_p);
|
||||
}
|
||||
|
||||
if (!sd_radv_is_running(ra))
|
||||
return 0;
|
||||
|
||||
if (ra->ra_sent == 0)
|
||||
return 0;
|
||||
|
||||
/* If RAs have already been sent, send an RA immediately to announce the newly-added prefix */
|
||||
r = radv_send_router(ra, NULL);
|
||||
if (r < 0)
|
||||
log_radv_errno(ra, r, "Unable to send Router Advertisement for added prefix %s, ignoring: %m", addr_p);
|
||||
else
|
||||
log_radv(ra, "Sent Router Advertisement for added/updated prefix %s.", addr_p);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -715,35 +699,17 @@ void sd_radv_remove_prefix(
|
||||
|
||||
int sd_radv_add_route_prefix(sd_radv *ra, sd_radv_route_prefix *p) {
|
||||
sd_radv_route_prefix *found = NULL;
|
||||
int r;
|
||||
|
||||
assert_return(ra, -EINVAL);
|
||||
assert_return(p, -EINVAL);
|
||||
|
||||
const char *addr_p = IN6_ADDR_PREFIX_TO_STRING(&p->opt.in6_addr, p->opt.prefixlen);
|
||||
|
||||
LIST_FOREACH(prefix, cur, ra->route_prefixes) {
|
||||
r = in_addr_prefix_intersect(AF_INET6,
|
||||
(const union in_addr_union*) &cur->opt.in6_addr,
|
||||
cur->opt.prefixlen,
|
||||
(const union in_addr_union*) &p->opt.in6_addr,
|
||||
p->opt.prefixlen);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
continue;
|
||||
|
||||
if (cur->opt.prefixlen == p->opt.prefixlen) {
|
||||
LIST_FOREACH(prefix, cur, ra->route_prefixes)
|
||||
if (cur->opt.prefixlen == p->opt.prefixlen &&
|
||||
in6_addr_equal(&cur->opt.in6_addr, &p->opt.in6_addr)) {
|
||||
found = cur;
|
||||
break;
|
||||
}
|
||||
|
||||
return log_radv_errno(ra, SYNTHETIC_ERRNO(EEXIST),
|
||||
"IPv6 route prefix %s conflicts with %s, ignoring.",
|
||||
addr_p,
|
||||
IN6_ADDR_PREFIX_TO_STRING(&cur->opt.in6_addr, cur->opt.prefixlen));
|
||||
}
|
||||
|
||||
if (found) {
|
||||
/* p and cur may be equivalent. First increment the reference counter. */
|
||||
sd_radv_route_prefix_ref(p);
|
||||
@@ -756,7 +722,7 @@ int sd_radv_add_route_prefix(sd_radv *ra, sd_radv_route_prefix *p) {
|
||||
LIST_APPEND(prefix, ra->route_prefixes, p);
|
||||
|
||||
log_radv(ra, "Updated/replaced IPv6 route prefix %s (lifetime: %s)",
|
||||
strna(addr_p),
|
||||
IN6_ADDR_PREFIX_TO_STRING(&p->opt.in6_addr, p->opt.prefixlen),
|
||||
FORMAT_TIMESPAN(p->lifetime_usec, USEC_PER_SEC));
|
||||
} else {
|
||||
/* The route prefix is new. Let's simply add it. */
|
||||
@@ -765,57 +731,26 @@ int sd_radv_add_route_prefix(sd_radv *ra, sd_radv_route_prefix *p) {
|
||||
LIST_APPEND(prefix, ra->route_prefixes, p);
|
||||
ra->n_route_prefixes++;
|
||||
|
||||
log_radv(ra, "Added route prefix %s", strna(addr_p));
|
||||
log_radv(ra, "Added route prefix %s",
|
||||
IN6_ADDR_PREFIX_TO_STRING(&p->opt.in6_addr, p->opt.prefixlen));
|
||||
}
|
||||
|
||||
if (!sd_radv_is_running(ra))
|
||||
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_router(ra, NULL);
|
||||
if (r < 0)
|
||||
log_radv_errno(ra, r, "Unable to send Router Advertisement for added route prefix %s, ignoring: %m",
|
||||
strna(addr_p));
|
||||
else
|
||||
log_radv(ra, "Sent Router Advertisement for added route prefix %s.", strna(addr_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) {
|
||||
LIST_FOREACH(prefix, cur, ra->pref64_prefixes)
|
||||
if (cur->prefixlen == p->prefixlen &&
|
||||
in6_addr_equal(&cur->in6_addr, &p->in6_addr)) {
|
||||
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);
|
||||
@@ -828,7 +763,7 @@ int sd_radv_add_pref64_prefix(sd_radv *ra, sd_radv_pref64_prefix *p) {
|
||||
LIST_APPEND(prefix, ra->pref64_prefixes, p);
|
||||
|
||||
log_radv(ra, "Updated/replaced IPv6 PREF64 prefix %s (lifetime: %s)",
|
||||
strna(addr_p),
|
||||
IN6_ADDR_PREFIX_TO_STRING(&p->in6_addr, p->prefixlen),
|
||||
FORMAT_TIMESPAN(p->lifetime_usec, USEC_PER_SEC));
|
||||
} else {
|
||||
/* The route prefix is new. Let's simply add it. */
|
||||
@@ -837,23 +772,10 @@ int sd_radv_add_pref64_prefix(sd_radv *ra, sd_radv_pref64_prefix *p) {
|
||||
LIST_APPEND(prefix, ra->pref64_prefixes, p);
|
||||
ra->n_pref64_prefixes++;
|
||||
|
||||
log_radv(ra, "Added PREF64 prefix %s", strna(addr_p));
|
||||
log_radv(ra, "Added PREF64 prefix %s",
|
||||
IN6_ADDR_PREFIX_TO_STRING(&p->in6_addr, p->prefixlen));
|
||||
}
|
||||
|
||||
if (!sd_radv_is_running(ra))
|
||||
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_router(ra, NULL);
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,9 @@
|
||||
#if __GNUC__ >= 7
|
||||
_Pragma("GCC diagnostic ignored \"-Wimplicit-fallthrough\"")
|
||||
#endif
|
||||
#include <netinet/icmp6.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include "conf-parser.h"
|
||||
#include "in-addr-prefix-util.h"
|
||||
#include "netem.h"
|
||||
@@ -409,8 +411,8 @@ IPv6SendRA.HomeAgent, config_parse_bool,
|
||||
IPv6SendRA.HomeAgentLifetimeSec, config_parse_router_home_agent_lifetime, 0, offsetof(Network, home_agent_lifetime_usec)
|
||||
IPv6SendRA.HomeAgentPreference, config_parse_uint16, 0, offsetof(Network, router_home_agent_preference)
|
||||
IPv6Prefix.Prefix, config_parse_prefix, 0, 0
|
||||
IPv6Prefix.OnLink, config_parse_prefix_boolean, 0, 0
|
||||
IPv6Prefix.AddressAutoconfiguration, config_parse_prefix_boolean, 0, 0
|
||||
IPv6Prefix.OnLink, config_parse_prefix_boolean, ND_OPT_PI_FLAG_ONLINK, 0
|
||||
IPv6Prefix.AddressAutoconfiguration, config_parse_prefix_boolean, ND_OPT_PI_FLAG_AUTO, 0
|
||||
IPv6Prefix.ValidLifetimeSec, config_parse_prefix_lifetime, 0, 0
|
||||
IPv6Prefix.PreferredLifetimeSec, config_parse_prefix_lifetime, 0, 0
|
||||
IPv6Prefix.Assign, config_parse_prefix_boolean, 0, 0
|
||||
|
||||
+18
-12
@@ -80,10 +80,9 @@ static int prefix_new_static(Network *network, const char *filename, unsigned se
|
||||
.network = network,
|
||||
.section = TAKE_PTR(n),
|
||||
|
||||
.flags = ND_OPT_PI_FLAG_ONLINK | ND_OPT_PI_FLAG_AUTO,
|
||||
.preferred_lifetime = RADV_DEFAULT_PREFERRED_LIFETIME_USEC,
|
||||
.valid_lifetime = RADV_DEFAULT_VALID_LIFETIME_USEC,
|
||||
.onlink = true,
|
||||
.address_auto_configuration = true,
|
||||
};
|
||||
|
||||
r = hashmap_ensure_put(&network->prefixes_by_section, &config_section_hash_ops, prefix->section, prefix);
|
||||
@@ -298,11 +297,11 @@ static int radv_set_prefix(Link *link, Prefix *prefix) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_radv_prefix_set_onlink(p, prefix->onlink);
|
||||
r = sd_radv_prefix_set_onlink(p, FLAGS_SET(prefix->flags, ND_OPT_PI_FLAG_ONLINK));
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_radv_prefix_set_address_autoconfiguration(p, prefix->address_auto_configuration);
|
||||
r = sd_radv_prefix_set_address_autoconfiguration(p, FLAGS_SET(prefix->flags, ND_OPT_PI_FLAG_AUTO));
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@@ -761,9 +760,18 @@ int radv_add_prefix(
|
||||
return r;
|
||||
|
||||
r = sd_radv_add_prefix(link->radv, p);
|
||||
if (r < 0 && r != -EEXIST)
|
||||
if (r == -EEXIST)
|
||||
return 0;
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (sd_radv_is_running(link->radv)) {
|
||||
/* Announce updated prefixe now. */
|
||||
r = sd_radv_send(link->radv);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -953,14 +961,12 @@ int config_parse_prefix_boolean(
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (streq(lvalue, "OnLink"))
|
||||
p->onlink = r;
|
||||
else if (streq(lvalue, "AddressAutoconfiguration"))
|
||||
p->address_auto_configuration = r;
|
||||
else if (streq(lvalue, "Assign"))
|
||||
if (ltype != 0)
|
||||
SET_FLAG(p->flags, ltype, r);
|
||||
else {
|
||||
assert(streq(lvalue, "Assign"));
|
||||
p->assign = r;
|
||||
else
|
||||
assert_not_reached();
|
||||
}
|
||||
|
||||
TAKE_PTR(p);
|
||||
return 0;
|
||||
|
||||
@@ -30,14 +30,12 @@ typedef struct Prefix {
|
||||
Network *network;
|
||||
ConfigSection *section;
|
||||
|
||||
struct in6_addr prefix;
|
||||
uint8_t flags;
|
||||
uint8_t prefixlen;
|
||||
struct in6_addr prefix;
|
||||
usec_t preferred_lifetime;
|
||||
usec_t valid_lifetime;
|
||||
|
||||
bool onlink;
|
||||
bool address_auto_configuration;
|
||||
|
||||
bool assign;
|
||||
uint32_t route_metric;
|
||||
Set *tokens;
|
||||
|
||||
Reference in New Issue
Block a user