summaryrefslogtreecommitdiffstats
path: root/canohost.c
diff options
context:
space:
mode:
authorDamien Miller <djm@mindrot.org>2003-11-24 12:57:25 +1100
committerDamien Miller <djm@mindrot.org>2003-11-24 12:57:25 +1100
commit927f52783ea99ac9bfad4f65bc5b79ba6255cc8c (patch)
tree68a1833f9c9d635d4b407c77f54b7407b5726dc5 /canohost.c
parent5924ceb22d8eb5e03bad93b7c0b9c6e30ed0814b (diff)
- (djm) [canohost.c] Move IPv4inV6 mapped address normalisation to its own
function and call it unconditionally
Diffstat (limited to 'canohost.c')
-rw-r--r--canohost.c52
1 files changed, 29 insertions, 23 deletions
diff --git a/canohost.c b/canohost.c
index fca7134f..f5145922 100644
--- a/canohost.c
+++ b/canohost.c
@@ -20,6 +20,7 @@ RCSID("$OpenBSD: canohost.c,v 1.38 2003/09/23 20:17:11 markus Exp $");
#include "canohost.h"
static void check_ip_options(int, char *);
+static void ipv64_normalise_mapped(struct sockaddr_storage *, socklen_t *);
/*
* Return the canonical name of the host at the other end of the socket. The
@@ -42,29 +43,9 @@ get_remote_hostname(int socket, int use_dns)
debug("getpeername failed: %.100s", strerror(errno));
cleanup_exit(255);
}
-#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;
- }
- }
-#endif
+
+ ipv64_normalise_mapped(&from, &fromlen);
+
if (from.ss_family == AF_INET6)
fromlen = sizeof(struct sockaddr_in6);
@@ -185,6 +166,31 @@ check_ip_options(int socket, char *ipaddr)
#endif /* IP_OPTIONS */
}
+static void
+ipv64_normalise_mapped(struct sockaddr_storage *addr, socklen_t *len)
+{
+ struct sockaddr_in6 *a6 = (struct sockaddr_in6 *)addr;
+ struct sockaddr_in *a4 = (struct sockaddr_in *)addr;
+ struct in_addr inaddr;
+ u_int16_t port;
+
+ if (addr->ss_family != AF_INET6 ||
+ !IN6_IS_ADDR_V4MAPPED(&a6->sin6_addr))
+ return;
+
+ debug3("Normalising mapped IPv4 in IPv6 address");
+
+ memcpy(&inaddr, ((char *)&a6->sin6_addr) + 12, sizeof(inaddr));
+ port = a6->sin6_port;
+
+ memset(addr, 0, sizeof(*a4));
+
+ a4->sin_family = AF_INET;
+ *len = sizeof(*a4);
+ memcpy(&a4->sin_addr, &inaddr, sizeof(inaddr));
+ a4->sin_port = port;
+}
+
/*
* Return the canonical name of the host in the other side of the current
* connection. The host name is cached, so it is efficient to call this