This patch fixes the handling of IPv6 mapped IPv4 addresses. This got broken by the TAHI patches, which change the addr_type() function to return IPV6_ADDR_MAPPED ORed with the scope, instead of just IPV6_ADDR_MAPPED. Patch courtesy David L Stevens of IBM Index: linux-2.6.7/net/ipv6/addrconf.c =================================================================== --- linux-2.6.7.orig/net/ipv6/addrconf.c 2004-08-04 15:28:05.640746399 +0200 +++ linux-2.6.7/net/ipv6/addrconf.c 2004-08-04 15:40:47.998823599 +0200 @@ -1145,18 +1145,18 @@ return 1; if (addr_type2 == IPV6_ADDR_ANY && - !(sk2_ipv6only && addr_type == IPV6_ADDR_MAPPED)) + !(sk2_ipv6only && (addr_type & IPV6_ADDR_MAPPED))) return 1; if (addr_type == IPV6_ADDR_ANY && - !(sk_ipv6only && addr_type2 == IPV6_ADDR_MAPPED)) + !(sk_ipv6only && (addr_type2 & IPV6_ADDR_MAPPED))) return 1; if (sk2_rcv_saddr6 && !ipv6_addr_cmp(sk_rcv_saddr6, sk2_rcv_saddr6)) return 1; - if (addr_type == IPV6_ADDR_MAPPED && + if ((addr_type & IPV6_ADDR_MAPPED) && !sk2_ipv6only && (!sk2_rcv_saddr || !sk_rcv_saddr || sk_rcv_saddr == sk2_rcv_saddr)) return 1; Index: linux-2.6.7/net/ipv6/af_inet6.c =================================================================== --- linux-2.6.7.orig/net/ipv6/af_inet6.c 2004-08-04 15:28:00.693226152 +0200 +++ linux-2.6.7/net/ipv6/af_inet6.c 2004-08-04 15:40:47.999823502 +0200 @@ -308,7 +308,7 @@ } /* Check if the address belongs to the host. */ - if (addr_type == IPV6_ADDR_MAPPED) { + if (addr_type & IPV6_ADDR_MAPPED) { v4addr = addr->sin6_addr.s6_addr32[3]; if (inet_addr_type(v4addr) != RTN_LOCAL) { err = -EADDRNOTAVAIL; Index: linux-2.6.7/net/ipv6/raw.c =================================================================== --- linux-2.6.7.orig/net/ipv6/raw.c 2004-08-04 15:28:00.884207633 +0200 +++ linux-2.6.7/net/ipv6/raw.c 2004-08-04 15:40:48.000823405 +0200 @@ -190,7 +190,7 @@ addr_type = ipv6_addr_type(&addr->sin6_addr); /* Raw sockets are IPv6 only */ - if (addr_type == IPV6_ADDR_MAPPED) + if (addr_type & IPV6_ADDR_MAPPED) return(-EADDRNOTAVAIL); lock_sock(sk); Index: linux-2.6.7/net/ipv6/tcp_ipv6.c =================================================================== --- linux-2.6.7.orig/net/ipv6/tcp_ipv6.c 2004-08-04 15:28:00.892206857 +0200 +++ linux-2.6.7/net/ipv6/tcp_ipv6.c 2004-08-04 15:40:48.002823211 +0200 @@ -620,7 +620,7 @@ * TCP over IPv4 */ - if (addr_type == IPV6_ADDR_MAPPED) { + if (addr_type & IPV6_ADDR_MAPPED) { u32 exthdrlen = tp->ext_header_len; struct sockaddr_in sin; Index: linux-2.6.7/net/ipv6/udp.c =================================================================== --- linux-2.6.7.orig/net/ipv6/udp.c 2004-08-04 15:28:05.639746000 +0200 +++ linux-2.6.7/net/ipv6/udp.c 2004-08-04 15:40:48.004823017 +0200 @@ -667,7 +667,7 @@ daddr = NULL; if (daddr) { - if (ipv6_addr_type(daddr) == IPV6_ADDR_MAPPED) { + if (ipv6_addr_type(daddr) & IPV6_ADDR_MAPPED) { struct sockaddr_in sin; sin.sin_family = AF_INET; sin.sin_port = sin6 ? sin6->sin6_port : inet->dport; Index: linux-2.6.7/net/sctp/ipv6.c =================================================================== --- linux-2.6.7.orig/net/sctp/ipv6.c 2004-08-04 15:28:01.229174182 +0200 +++ linux-2.6.7/net/sctp/ipv6.c 2004-08-04 15:40:48.006822823 +0200 @@ -445,7 +445,7 @@ if (addr1->sa.sa_family != addr2->sa.sa_family) { if (addr1->sa.sa_family == AF_INET && addr2->sa.sa_family == AF_INET6 && - IPV6_ADDR_MAPPED == ipv6_addr_type(&addr2->v6.sin6_addr)) { + IPV6_ADDR_MAPPED & ipv6_addr_type(&addr2->v6.sin6_addr)) { if (addr2->v6.sin6_port == addr1->v4.sin_port && addr2->v6.sin6_addr.s6_addr32[3] == addr1->v4.sin_addr.s_addr) @@ -453,7 +453,7 @@ } if (addr2->sa.sa_family == AF_INET && addr1->sa.sa_family == AF_INET6 && - IPV6_ADDR_MAPPED == ipv6_addr_type(&addr1->v6.sin6_addr)) { + IPV6_ADDR_MAPPED & ipv6_addr_type(&addr1->v6.sin6_addr)) { if (addr1->v6.sin6_port == addr2->v4.sin_port && addr1->v6.sin6_addr.s6_addr32[3] == addr2->v4.sin_addr.s_addr) @@ -499,7 +499,7 @@ type = ipv6_addr_type(in6); if (IPV6_ADDR_ANY == type) return 1; - if (type == IPV6_ADDR_MAPPED) { + if (type & IPV6_ADDR_MAPPED) { if (sp && !sp->v4mapped) return 0; if (sp && ipv6_only_sock(sctp_opt2sk(sp))) @@ -525,7 +525,7 @@ int ret = ipv6_addr_type(&addr->v6.sin6_addr); /* Support v4-mapped-v6 address. */ - if (ret == IPV6_ADDR_MAPPED) { + if (ret & IPV6_ADDR_MAPPED) { /* Note: This routine is used in input, so v4-mapped-v6 * are disallowed here when there is no sctp_opt. */