- /* 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;
- }
- /* Look for the address from the list of addresses. */
- for (i = 0; hp->h_addr_list[i]; i++)
- if (memcmp(hp->h_addr_list[i], &from.sin_addr, sizeof(from.sin_addr))
- == 0)
- break;
- /*
- * If we reached the end of the list, the address was not
- * there.
- */
- if (!hp->h_addr_list[i]) {
- /* Address not found for the host name. */
- log("Address %.100s maps to %.600s, but this does not map back to the address - POSSIBLE BREAKIN ATTEMPT!",
- inet_ntoa(from.sin_addr), name);
- strlcpy(name, inet_ntoa(from.sin_addr), sizeof name);
- goto check_ip_options;
+#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;
+ fromlen = sizeof(*from4);
+ memcpy(&from4->sin_addr, &addr, sizeof(addr));
+ from4->sin_port = port;