- struct sockaddr_in from;
- int fromlen, i;
- struct hostent *hp;
- char name[MAXHOSTNAMELEN];
-
- /* Get IP address of client. */
- fromlen = sizeof(from);
- memset(&from, 0, sizeof(from));
- if (getpeername(socket, (struct sockaddr *)&from, &fromlen) < 0)
- {
- error("getpeername failed: %.100s", strerror(errno));
- strlcpy(name, "UNKNOWN", sizeof name);
- goto check_ip_options;
- }
-
- /* Map the IP address to a host name. */
- hp = gethostbyaddr((char *)&from.sin_addr, sizeof(struct in_addr),
- from.sin_family);
- if (hp)
- {
- /* Got host name, find canonic host name. */
- if (strchr(hp->h_name, '.') != 0)
- strlcpy(name, hp->h_name, sizeof(name));
- else if (hp->h_aliases != 0
- && hp->h_aliases[0] != 0
- && strchr(hp->h_aliases[0], '.') != 0)
- strlcpy(name, hp->h_aliases[0], sizeof(name));
- else
- strlcpy(name, hp->h_name, sizeof(name));
-
- /* Convert it to all lowercase (which is expected by the rest of this
- software). */
- for (i = 0; name[i]; i++)
- if (isupper(name[i]))
- name[i] = tolower(name[i]);
-
- /* Map it back to an IP address and check that the given address actually
- is an address of this host. This is necessary because anyone with
- access to a name server can define arbitrary names for an IP address.
- Mapping from name to IP address can be trusted better (but can still
- be fooled if the intruder has access to the name server of the
- domain). */
- hp = gethostbyname(name);
- if (!hp)
- {
- log("reverse mapping checking gethostbyname for %.700s failed - POSSIBLE BREAKIN ATTEMPT!", name);
- strlcpy(name, inet_ntoa(from.sin_addr), sizeof name);
- goto check_ip_options;
+ 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;
+ }