Fix adding IPv6 routes on BSD. 31/head
authorStefan Sperling <stsp@stsp.name>
Thu, 22 Jun 2017 16:18:26 +0000 (18:18 +0200)
committerStefan Sperling <stsp@stsp.name>
Fri, 23 Jun 2017 08:46:47 +0000 (10:46 +0200)
The KAME hack (storing the interface index inside the prefix) is only used
for link-local addresses. So only apply it in case the gateway is link-local.

For gateway routes (reachable on-link), install a cloning route which tells
the kernel to perform NDP address resolution to find the gateway.

The previous code was installing a bogus route to fe:80::1 for any destination.
I don't see how this could ever have worked.

Tested in Berlin's Freifunk mesh.

Signed-off-by: Stefan Sperling <stsp@stsp.name>
src/bsd/kernel_routes.c

index 45daed6..66866db 100644 (file)
@@ -322,13 +322,15 @@ add_del_route6(const struct rt_entry *rt, int add)
   nexthop = olsr_get_nh(rt);
   if (0 != (rtm->rtm_flags & RTF_GATEWAY)) {
     memcpy(&sin6.sin6_addr.s6_addr, &nexthop->gateway.v6, sizeof(struct in6_addr));
-    memset(&sin6.sin6_addr.s6_addr, 0, 8);
-    sin6.sin6_addr.s6_addr[0] = 0xfe;
-    sin6.sin6_addr.s6_addr[1] = 0x80;
-    sin6.sin6_scope_id = nexthop->iif_index;
+    if (IN6_IS_ADDR_LINKLOCAL(&sin6.sin6_addr))
+      sin6.sin6_scope_id = nexthop->iif_index;
 #ifdef __KAME__
-    *(u_int16_t *) & sin6.sin6_addr.s6_addr[2] = htons(sin6.sin6_scope_id);
-    sin6.sin6_scope_id = 0;
+  if (IN6_IS_ADDR_LINKLOCAL(&sin6.sin6_addr))
+    {
+      uint16_t tmp16 = htons(sin6.sin6_scope_id);
+      memcpy(&sin6.sin6_addr.s6_addr[2], &tmp16, sizeof(uint16_t));
+      sin6.sin6_scope_id = 0;
+    }
 #endif /* __KAME__ */
     memcpy(walker, &sin6, sizeof(sin6));
     walker += sin_size;
@@ -336,22 +338,14 @@ add_del_route6(const struct rt_entry *rt, int add)
   }
   else {
     /*
-     * Host is directly reachable, so add
-     * the output interface MAC address.
+     * Host is directly reachable, add a cloning route.
      */
-    memcpy(&sin6.sin6_addr.s6_addr, &rt->rt_dst.prefix.v6, sizeof(struct in6_addr));
-    memset(&sin6.sin6_addr.s6_addr, 0, 8);
-    sin6.sin6_addr.s6_addr[0] = 0xfe;
-    sin6.sin6_addr.s6_addr[1] = 0x80;
-    sin6.sin6_scope_id = nexthop->iif_index;
-#ifdef __KAME__
-    *(u_int16_t *) & sin6.sin6_addr.s6_addr[2] = htons(sin6.sin6_scope_id);
-    sin6.sin6_scope_id = 0;
-#endif /* __KAME__ */
-    memcpy(walker, &sin6, sizeof(sin6));
-    walker += sin_size;
+    sdl.sdl_index = nexthop->iif_index;
+    memcpy(walker, &sdl, sizeof(sdl));
+    walker += sdl_size;
     rtm->rtm_addrs |= RTA_GATEWAY;
-    rtm->rtm_flags |= RTF_GATEWAY;
+    rtm->rtm_flags |= RTF_CLONING;
+    rtm->rtm_flags &= ~RTF_GATEWAY;
   }
 
   /**********************************************************************