If the kernel is configured to handle RAs (accept_ra=1, e.g. implied by 
forwarding=0)
then this work is mainly duplicated by netifd and odhcp6c.
I don't think it's a good thing if kernel and userspace applications try to do 
the same
in parallel.

Another side effect I noticed: If the kernel takes care of temporary addresses 
then netifd
in case of "link down" deletes the global address leaving orphaned temporary 
addresses.

IMHO odhcp6c should not duplicate work the kernel does already. Therefore check 
and respect
kernel configuration for the respective device when processing RAs.

Signed-off-by: Heiner Kallweit <heiner.kallw...@web.de>
---
 src/ra.c | 77 ++++++++++++++++++++++++++++++++++++++++++++--------------------
 1 file changed, 53 insertions(+), 24 deletions(-)

diff --git a/src/ra.c b/src/ra.c
index 3e36f94..c9d6847 100644
--- a/src/ra.c
+++ b/src/ra.c
@@ -15,6 +15,7 @@
 #include <fcntl.h>
 #include <ifaddrs.h>
 #include <stdio.h>
+#include <stdlib.h>
 #include <signal.h>
 #include <string.h>
 #include <stddef.h>
@@ -57,6 +58,28 @@ static struct in6_addr lladdr = IN6ADDR_ANY_INIT;
 
 static void ra_send_rs(int signal __attribute__((unused)));
 
+static bool get_if_kernel_config(const char *paramname)
+{
+        char buf[128];
+        int len;
+        FILE *f;
+
+        snprintf(buf, sizeof(buf), "/proc/sys/net/ipv6/conf/%s/%s", if_name, 
paramname);
+        f = fopen(buf,"r");
+        if (!f)
+                return false;
+
+        len = fread(buf, sizeof(char), sizeof(buf)-1, f);
+        fclose(f);
+
+        if (len<=0)
+                return false;
+
+        buf[len] = '\0';
+        return strtoul(buf, NULL, 0) == 1;
+}
+
+
 int ra_init(const char *ifname, const struct in6_addr *ifid)
 {
        const pid_t ourpid = getpid();
@@ -232,6 +255,9 @@ bool ra_process(void)
        struct nd_router_advert *adv = (struct nd_router_advert*)buf;
        struct odhcp6c_entry entry = {IN6ADDR_ANY_INIT, 0, 0, IN6ADDR_ANY_INIT, 
0, 0, 0, 0, 0, 0};
        const struct in6_addr any = IN6ADDR_ANY_INIT;
+       bool kernel_accept_ra = get_if_kernel_config("accept_ra");
+       bool kernel_accept_ra_defrtr = get_if_kernel_config("accept_ra_defrtr");
+       bool kernel_accept_ra_pinfo = get_if_kernel_config("accept_ra_pinfo") 
&& get_if_kernel_config("autoconf");
 
        if (!has_lladdr) {
                // Autodetect interface-id if not specified
@@ -295,39 +321,42 @@ bool ra_process(void)
                }
                uint32_t router_valid = ntohs(adv->nd_ra_router_lifetime);
 
-               // Parse default route
-               entry.target = any;
-               entry.length = 0;
-               entry.router = from.sin6_addr;
-               entry.priority = pref_to_priority(adv->nd_ra_flags_reserved);
-               if (entry.priority < 0)
-                       entry.priority = pref_to_priority(0);
-               entry.valid = router_valid;
-               entry.preferred = entry.valid;
-               changed |= odhcp6c_update_entry(STATE_RA_ROUTE, &entry);
-
-               // Parse hoplimit
-               if (adv->nd_ra_curhoplimit)
-                       update_proc("conf", "hop_limit", 
adv->nd_ra_curhoplimit);
+               if (!kernel_accept_ra_defrtr) {
+                       // Parse default route
+                       entry.target = any;
+                       entry.length = 0;
+                       entry.router = from.sin6_addr;
+                       entry.priority = 
pref_to_priority(adv->nd_ra_flags_reserved);
+                       if (entry.priority < 0)
+                               entry.priority = pref_to_priority(0);
+                       entry.valid = router_valid;
+                       entry.preferred = entry.valid;
+                       changed |= odhcp6c_update_entry(STATE_RA_ROUTE, &entry);
+               }
 
-               // Parse ND parameters
-               uint32_t reachable = ntohl(adv->nd_ra_reachable);
-               if (reachable > 0 && reachable <= 3600000)
-                       update_proc("neigh", "base_reachable_time_ms", 
reachable);
+               if (!kernel_accept_ra) {
+                       // Parse hoplimit
+                       if (adv->nd_ra_curhoplimit)
+                               update_proc("conf", "hop_limit", 
adv->nd_ra_curhoplimit);
 
-               uint32_t retransmit = ntohl(adv->nd_ra_retransmit);
-               if (retransmit > 0 && retransmit <= 60000)
-                       update_proc("neigh", "retrans_time_ms", retransmit);
+                       // Parse ND parameters
+                       uint32_t reachable = ntohl(adv->nd_ra_reachable);
+                       if (reachable > 0 && reachable <= 3600000)
+                               update_proc("neigh", "base_reachable_time_ms", 
reachable);
 
+                       uint32_t retransmit = ntohl(adv->nd_ra_retransmit);
+                       if (retransmit > 0 && retransmit <= 60000)
+                               update_proc("neigh", "retrans_time_ms", 
retransmit);
+               }
 
                // Evaluate options
                struct icmpv6_opt *opt;
                icmpv6_for_each_option(opt, &adv[1], &buf[len]) {
-                       if (opt->type == ND_OPT_MTU) {
+                       if (!kernel_accept_ra && opt->type == ND_OPT_MTU) {
                                uint32_t *mtu = (uint32_t*)&opt->data[2];
                                if (ntohl(*mtu) >= 1280 && ntohl(*mtu) <= 65535)
                                        update_proc("conf", "mtu", ntohl(*mtu));
-                       } else if (opt->type == ND_OPT_ROUTE_INFORMATION && 
opt->len <= 3) {
+                       } else if (!kernel_accept_ra && opt->type == 
ND_OPT_ROUTE_INFORMATION && opt->len <= 3) {
                                entry.router = from.sin6_addr;
                                entry.target = any;
                                entry.priority = pref_to_priority(opt->data[1]);
@@ -343,7 +372,7 @@ bool ra_process(void)
 
                                if (entry.priority > 0)
                                        changed |= 
odhcp6c_update_entry(STATE_RA_ROUTE, &entry);
-                       } else if (opt->type == ND_OPT_PREFIX_INFORMATION && 
opt->len == 4) {
+                       } else if (!kernel_accept_ra_pinfo && opt->type == 
ND_OPT_PREFIX_INFORMATION && opt->len == 4) {
                                struct nd_opt_prefix_info *pinfo = (struct 
nd_opt_prefix_info*)opt;
                                entry.router = any;
                                entry.target = pinfo->nd_opt_pi_prefix;
-- 
1.9.1.315.g3f09db0.dirty
_______________________________________________
openwrt-devel mailing list
openwrt-devel@lists.openwrt.org
https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel

Reply via email to