+static char *
+get_remote_hostname(int socket, int reverse_mapping_check)
+{
+ struct sockaddr_storage from;
+ int i;
+ socklen_t fromlen;
+ struct addrinfo hints, *ai, *aitop;
+ char name[NI_MAXHOST], ntop[NI_MAXHOST], ntop2[NI_MAXHOST];
+
+ /* Get IP address of client. */
+ fromlen = sizeof(from);
+ memset(&from, 0, sizeof(from));
+ if (getpeername(socket, (struct sockaddr *) &from, &fromlen) < 0) {
+ 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 (from.ss_family == AF_INET)
+ check_ip_options(socket, ntop);
+
+ if (getnameinfo((struct sockaddr *)&from, fromlen, ntop, sizeof(ntop),
+ NULL, 0, NI_NUMERICHOST) != 0)
+ fatal("get_remote_hostname: getnameinfo NI_NUMERICHOST failed");
+
+ debug3("Trying to reverse map address %.100s.", ntop);
+ /* Map the IP address to a host name. */
+ if (getnameinfo((struct sockaddr *)&from, fromlen, name, sizeof(name),
+ NULL, 0, NI_NAMEREQD) != 0) {
+ /* Host name not found. Use ip address. */
+ log("Could not reverse map address %.100s.", ntop);
+ return xstrdup(ntop);
+ }