[Olsr-dev] FreeBSD and multiple interfaces on the same subnet
John Hay
(spam-protected)
Sat Sep 29 13:53:45 CEST 2007
Hi,
This patch do two things. The first is to make it possible to run more
than one interface in the same IPv6 subnet on FreeBSD. I had kernel mods
to FreeBSD to achieve the same, but it had other negative side effects
and it looks like that is going to take a long time to sort out.
The second part is to catch the case where a route already exist in the
kernel routing table. Delete that route and then retry the add.
John
--
John Hay -- (spam-protected) / (spam-protected)
--- src/bsd/kernel_routes.c.orig 2007-09-06 09:55:25.000000000 +0200
+++ src/bsd/kernel_routes.c 2007-09-19 09:42:30.000000000 +0200
@@ -223,6 +223,14 @@
{
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;
+#ifdef __KAME__
+ *(u_int16_t *)&sin6.sin6_addr.s6_addr[2] = htons(sin6.sin6_scope_id);
+ sin6.sin6_scope_id = 0;
+#endif
memcpy(walker, &sin6, sizeof (sin6));
walker += step;
}
@@ -231,19 +239,19 @@
else
{
- // Sven-Ola: This looks really ugly (please compar to IPv4 above)
- struct interface* iface = if_ifwithindex(nexthop->iif_index);
- if (NULL == iface)
- {
- fprintf(stderr, "interface %s not found\n", if_ifwithindex_name(nexthop->iif_index));
- return -1;
- }
- memcpy(&sin6.sin6_addr.s6_addr, &iface->int6_addr.sin6_addr.s6_addr,
- sizeof(struct in6_addr));
+ 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
memcpy(walker, &sin6, sizeof (sin6));
walker += step;
- rtm->rtm_flags |= RTF_LLINFO;
+ rtm->rtm_flags |= RTF_GATEWAY;
}
if ((rtm->rtm_flags & RTF_HOST) == 0)
@@ -254,22 +262,41 @@
rtm->rtm_addrs |= RTA_NETMASK;
}
- if ((rtm->rtm_flags & RTF_GATEWAY) != 0)
- {
- strcpy(&sdl.sdl_data[0], if_ifwithindex_name(nexthop->iif_index));
- sdl.sdl_nlen = (u_char)strlen((char*)&sdl.sdl_data[0]);
- memcpy(walker, &sdl, sizeof (sdl));
- walker += step_dl;
- rtm->rtm_addrs |= RTA_IFP;
- }
-
rtm->rtm_msglen = (unsigned short)(walker - buff);
len = write(olsr_cnf->rts, buff, rtm->rtm_msglen);
-
- if (len < rtm->rtm_msglen)
+ if (len < 0 && !(errno == EEXIST || errno == ESRCH))
fprintf(stderr, "cannot write to routing socket: %s\n", strerror(errno));
+ /* If we get an EEXIST error while adding, delete and retry. */
+ if (len < 0 && errno == EEXIST && rtm->rtm_type == RTM_ADD) {
+ struct rt_msghdr *drtm;
+ unsigned char dbuff[512];
+
+ memset(dbuff, 0, sizeof (dbuff));
+ drtm = (struct rt_msghdr *)dbuff;
+ drtm->rtm_version = RTM_VERSION;
+ drtm->rtm_type = RTM_DELETE;
+ drtm->rtm_addrs = RTA_DST;
+ drtm->rtm_index = 0;
+ drtm->rtm_flags = olsr_rt_flags(rt);
+ drtm->rtm_seq = ++seq;
+
+ walker = dbuff + sizeof (struct rt_msghdr);
+ memcpy(&sin6.sin6_addr.s6_addr, &rt->rt_dst.prefix.v6,
+ sizeof(struct in6_addr));
+ memcpy(walker, &sin6, sizeof (sin6));
+ walker += step;
+ drtm->rtm_msglen = (unsigned short)(walker - dbuff);
+ len = write(olsr_cnf->rts, dbuff, drtm->rtm_msglen);
+ if (len < 0)
+ fprintf(stderr, "cannot delete route: %s\n", strerror(errno));
+ rtm->rtm_seq = ++seq;
+ len = write(olsr_cnf->rts, buff, rtm->rtm_msglen);
+ if (len < 0)
+ fprintf(stderr, "still cannot add route: %s\n", strerror(errno));
+ }
+
return 0;
}
More information about the Olsr-dev
mailing list