router: fix Lan host reachibility due to identical RIO and PIO prefixes (FS#3056)
authorHans Dedecker <dedeckeh@gmail.com>
Sun, 3 May 2020 19:17:53 +0000 (21:17 +0200)
committerHans Dedecker <dedeckeh@gmail.com>
Sun, 3 May 2020 20:06:08 +0000 (22:06 +0200)
odhcpd includes RIO RA options according to requirement L3 in RFC7084.
However if the delegated prefix length received on the wan is equal to the
downstream delegated prefix length on the Lan this may pollute the
routing table of type C hosts as the RIO routing entry can take
precedence of the PIO routing entry meaning all traffic for the on link
hosts will go via the router iso direct on link communication.
If the traffic is dropped in the router hosts are unreachable; therefore
don't include RIO options with prefixes and prefix length identical to
those in a PIO RA option

Signed-off-by: Hans Dedecker <dedeckeh@gmail.com>
src/router.c

index 295bdfbb11fa363af7a223a5c329472f9d57825e..7198ee97cb357cf09624c427b40a0b74638f1c72 100644 (file)
@@ -659,12 +659,22 @@ static int send_router_advert(struct interface *iface, const struct in6_addr *fr
        iov[IOV_RA_SEARCH].iov_base = (char *)search;
        iov[IOV_RA_SEARCH].iov_len = search_sz;
 
+       /*
+        * RFC7084 ยง 4.3 :
+        *    L-3:   An IPv6 CE router MUST advertise itself as a router for the
+        *           delegated prefix(es) (and ULA prefix if configured to provide
+        *           ULA addressing) using the "Route Information Option" specified
+        *           in Section 2.3 of [RFC4191].  This advertisement is
+        *           independent of having or not having IPv6 connectivity on the
+        *           WAN interface.
+        */
+
        for (ssize_t i = 0; i < addr_cnt; ++i) {
                struct odhcpd_ipaddr *addr = &addrs[i];
                struct nd_opt_route_info *tmp;
                uint32_t valid;
 
-               if (addr->dprefix > 64 || addr->dprefix == 0 || addr->valid <= (uint32_t)now) {
+               if (addr->dprefix >= 64 || addr->dprefix == 0 || addr->valid <= (uint32_t)now) {
                        syslog(LOG_INFO, "Address %s (dprefix %d, valid %u) not suitable as RA route on %s",
                                inet_ntop(AF_INET6, &addr->addr.in6, buf, sizeof(buf)),
                                addr->dprefix, addr->valid, iface->name);