Hi,

From: Markus Stumpf <[EMAIL PROTECTED]>

> I am trying to get dnscache running with IPv6 patches.
> dnscache binds to the IPv6 unqualified address "::". This works fine
> and I get (from netstat)
>     udp46      0      0  *.53                   *.*
> As the sending address the IPv6 unqualified address "::" is used, also.
> 
> As long as I only send queries via either IPv6 or IPv4 all works well, but 
> all subsequent queries via IPv6 after one or more queries via
> IPv4 fail. The queries arrive properly, but sending the answer fails.
> 
> >From truss I can see for that IPv6 answers:
>     sendto(0x3,0x80f34e0,0x55,0x0,0xbfbffbd0,0x1c)   ERR#65 'No route to host'
> for all queries via IPv6, queries via IPv4 still work without problems.
> It doesn't matter if I use different source hosts for the queries via IPv6,
> it fails for all of them.

This is a cached route problem.  struct inpcb has a route entry for
cached route.  Since inpcb is shared by both IPv4 and IPv6, the cached
route entry is also shared by them.  4.5-STABLE doesn't check the
protocol family of the cached route when using it.  Therefore, once a
IPv4 route is cached, ip6_output mistakingly use it as a cached route
for IPv6 destination.

Please try attached patches.

---
Keiichi SHIMA
IIJ Research Laboratory  <[EMAIL PROTECTED]>
KAME Project <[EMAIL PROTECTED]>

--- ip_output.c.orig    Wed Mar 27 14:29:43 2002
+++ ip_output.c Wed Mar 27 13:54:40 2002
@@ -219,6 +219,7 @@
         * and is still up.  If not, free it and try again.
         */
        if (ro->ro_rt && ((ro->ro_rt->rt_flags & RTF_UP) == 0 ||
+          dst->sin_family != AF_INET ||
           dst->sin_addr.s_addr != ip->ip_dst.s_addr)) {
                RTFREE(ro->ro_rt);
                ro->ro_rt = (struct rtentry *)0;
--- ip6_output.c.orig   Wed Mar 27 14:23:54 2002
+++ ip6_output.c        Wed Mar 27 14:08:22 2002
@@ -461,6 +461,7 @@
         * and is still up. If not, free it and try again.
         */
        if (ro->ro_rt && ((ro->ro_rt->rt_flags & RTF_UP) == 0 ||
+                        dst->sin6_family != AF_INET6 ||
                         !IN6_ARE_ADDR_EQUAL(&dst->sin6_addr, &ip6->ip6_dst))) {
                RTFREE(ro->ro_rt);
                ro->ro_rt = (struct rtentry *)0;
--- in6_src.c.orig      Wed Mar 27 14:24:28 2002
+++ in6_src.c   Wed Mar 27 14:47:31 2002
@@ -239,7 +239,9 @@
         */
        if (ro) {
                if (ro->ro_rt &&
-                   !IN6_ARE_ADDR_EQUAL(&satosin6(&ro->ro_dst)->sin6_addr, dst)) {
+                   (!(ro->ro_rt->rt_flags & RTF_UP) ||
+                    ro->ro_dst.sin6_family != AF_INET6 ||
+                    !IN6_ARE_ADDR_EQUAL(&satosin6(&ro->ro_dst)->sin6_addr, dst))) {
                        RTFREE(ro->ro_rt);
                        ro->ro_rt = (struct rtentry *)0;
                }

Reply via email to