+ int name_err;
+
+#ifdef INET6
+ if (get_sockaddr_family(ss) == AF_INET6 &&
+ IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)ss)->sin6_addr)) {
+ /* OK, so ss is in the IPv6 family, but it is really
+ * an IPv4 address: something like
+ * "::ffff:10.130.1.2". If we use it as-is, then the
+ * reverse lookup might fail or perhaps something else
+ * bad might happen. So instead we convert it to an
+ * equivalent address in the IPv4 address family. */
+ struct sockaddr_in6 sin6;
+ struct sockaddr_in *sin;
+
+ memcpy(&sin6, ss, sizeof(sin6));
+ sin = (struct sockaddr_in *)ss;
+ memset(sin, 0, sizeof(*sin));
+ sin->sin_family = AF_INET;
+ ss_len = sizeof(struct sockaddr_in);
+#ifdef HAVE_SOCKADDR_LEN
+ sin->sin_len = ss_len;
+#endif
+ sin->sin_port = sin6.sin6_port;
+ /* FIXME: Isn't there a macro we can use here rather
+ * than grovelling through the struct? It might be
+ * wrong on some systems. */
+ memcpy(&sin->sin_addr, &sin6.sin6_addr.s6_addr[12],
+ sizeof(sin->sin_addr));
+ }
+#endif