- IPv6 workarounds from Hideaki YOSHIFUJI <yoshfuji@ecei.tohoku.ac.jp>
diff --git a/CREDITS b/CREDITS
index 50a0447..43f1c1a 100644
--- a/CREDITS
+++ b/CREDITS
@@ -19,6 +19,7 @@
 David Rankin <drankin@bohemians.lexington.ky.us> - libwrap, AIX, NetBSD fixes
 Gary E. Miller <gem@rellim.com> - SCO support
 HARUYAMA Seigo <haruyama@nt.phys.s.u-tokyo.ac.jp> - Translations & doc fixes
+Hideaki YOSHIFUJI <yoshfuji@ecei.tohoku.ac.jp> - IPv6 fixes
 Hiroshi Takekawa <takekawa@sr3.t.u-tokyo.ac.jp> - Configure fixes
 Holger Trapp <Holger.Trapp@Informatik.TU-Chemnitz.DE> - KRB4/AFS config patch
 Jani Hakala <jahakala@cc.jyu.fi> - Patches
diff --git a/ChangeLog b/ChangeLog
index eba385a..04fef5e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -4,6 +4,7 @@
    [sshd.c]
     - disallow guessing of root password
  - More configure fixes
+ - IPv6 workarounds from Hideaki YOSHIFUJI <yoshfuji@ecei.tohoku.ac.jp>
 
 20000309
  - OpenBSD CVS updates to v1.2.3
diff --git a/acconfig.h b/acconfig.h
index 7f51937..ee3be6e 100644
--- a/acconfig.h
+++ b/acconfig.h
@@ -153,6 +153,12 @@
 /* getaddrinfo is broken (if present) */
 #undef BROKEN_GETADDRINFO
 
+/* Workaround more Linux IPv6 bugs */
+#undef DONT_TRY_OTHER_AF
+
+/* Detect IPv4 in IPv6 mapped addresses and treat as IPv4 */
+#undef IPV4_IN_IPV6
+
 @BOTTOM@
 
 /* ******************* Shouldn't need to edit below this line ************** */
diff --git a/canohost.c b/canohost.c
index 9a6d8b7..a11d663 100644
--- a/canohost.c
+++ b/canohost.c
@@ -14,7 +14,7 @@
  */
 
 #include "includes.h"
-RCSID("$Id: canohost.c,v 1.7 2000/01/14 04:45:48 damien Exp $");
+RCSID("$Id: canohost.c,v 1.8 2000/03/11 09:45:41 damien Exp $");
 
 #include "packet.h"
 #include "xmalloc.h"
@@ -42,6 +42,30 @@
 		debug("getpeername failed: %.100s", strerror(errno));
 		fatal_cleanup();
 	}
+
+#ifdef IPV4_IN_IPV6
+	if (from.ss_family == AF_INET6) {
+		struct sockaddr_in6 *from6 = (struct sockaddr_in6 *)&from;
+
+		/* Detect IPv4 in IPv6 mapped address and convert it to */
+		/* plain (AF_INET) IPv4 address */
+		if (IN6_IS_ADDR_V4MAPPED(&from6->sin6_addr)) {
+			struct sockaddr_in *from4 = (struct sockaddr_in *)&from;
+			struct in_addr addr;
+			u_int16_t port;
+
+			memcpy(&addr, ((char *)&from6->sin6_addr) + 12, sizeof(addr));
+			port = from6->sin6_port;
+
+			memset(&from, 0, sizeof(from));
+			
+			from4->sin_family = AF_INET;
+			memcpy(&from4->sin_addr, &addr, sizeof(addr));
+			from4->sin_port = port;
+		}
+	}
+#endif
+
 	if (getnameinfo((struct sockaddr *)&from, fromlen, ntop, sizeof(ntop),
 	     NULL, 0, NI_NUMERICHOST) != 0)
 		fatal("get_remote_hostname: getnameinfo NI_NUMERICHOST failed");
diff --git a/channels.c b/channels.c
index 7d5e9a1..090cbf0 100644
--- a/channels.c
+++ b/channels.c
@@ -16,7 +16,7 @@
  */
 
 #include "includes.h"
-RCSID("$Id: channels.c,v 1.17 2000/03/03 11:35:33 damien Exp $");
+RCSID("$Id: channels.c,v 1.18 2000/03/11 09:45:41 damien Exp $");
 
 #include "ssh.h"
 #include "packet.h"
@@ -1215,8 +1215,12 @@
 				break;
 			}
 			socks[num_socks++] = sock;
+#ifndef DONT_TRY_OTHER_AF
 			if (num_socks == NUM_SOCKS)
 				break;
+#else
+			break;
+#endif
 		}
 		if (num_socks > 0)
 			break;
diff --git a/configure.in b/configure.in
index 90aadd9..4f1e479 100644
--- a/configure.in
+++ b/configure.in
@@ -55,6 +55,8 @@
 	;;
 *-*-linux*)
 	no_dev_ptmx=1
+	AC_DEFINE(DONT_TRY_OTHER_AF)
+	inet6_default_4in6=yes
 	;;
 *-*-netbsd*)
 	need_dash_r=1
@@ -788,6 +790,26 @@
 	]
 )
 
+AC_MSG_CHECKING([to convert IPv4 in IPv6-mapped addresses])
+AC_ARG_WITH(4in6,
+	[  --with-4in6             Check for and convert IPv4 in IPv6 mapped addresses],
+	[
+		if test "x$withval" != "xno" ; then
+			AC_MSG_RESULT(yes)
+			AC_DEFINE(IPV4_IN_IPV6)
+		else
+			AC_MSG_RESULT(no)
+		fi
+	],[
+		if test "x$inet6_default_4in6" = "xyes"; then
+			AC_MSG_RESULT([yes (default)])
+			AC_DEFINE(IPV4_IN_IPV6)
+		else
+			AC_MSG_RESULT([no (default)])
+		fi
+	]
+)
+
 # Where to place sshd.pid
 piddir=/var/run
 AC_ARG_WITH(pid-dir,