From: Yu Watanabe Date: Tue, 23 Apr 2024 04:09:52 +0000 (+0900) Subject: sd-radv: allow to send multiple routes or prefix64 that have intersection with others X-Git-Tag: v256-rc1~34^2~3 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=9dc25035394d2da5d1612062c1ce153e33afb0d0;p=thirdparty%2Fsystemd.git sd-radv: allow to send multiple routes or prefix64 that have intersection with others I cannot find any RFC that states we should not send multiple route prefix or pref64 options that have intersection with others. Moreover, each route prefix option has preference field, thus, user may want to send e.g. a prefix with the normal preference, and another sub prefix with the high preference. Previously, such configuration was prohibited. Let's allow that now. --- diff --git a/src/libsystemd-network/sd-radv.c b/src/libsystemd-network/sd-radv.c index fa15f96336e..6dc4f9be29b 100644 --- a/src/libsystemd-network/sd-radv.c +++ b/src/libsystemd-network/sd-radv.c @@ -702,35 +702,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); @@ -743,7 +725,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. */ @@ -752,7 +734,8 @@ 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)); } return 0; @@ -760,35 +743,17 @@ 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) { 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); @@ -801,7 +766,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. */ @@ -810,7 +775,8 @@ 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)); } return 0;