diff options
author | Damien Miller <djm@mindrot.org> | 2003-11-24 12:57:25 +1100 |
---|---|---|
committer | Damien Miller <djm@mindrot.org> | 2003-11-24 12:57:25 +1100 |
commit | 927f52783ea99ac9bfad4f65bc5b79ba6255cc8c (patch) | |
tree | 68a1833f9c9d635d4b407c77f54b7407b5726dc5 /canohost.c | |
parent | 5924ceb22d8eb5e03bad93b7c0b9c6e30ed0814b (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.c | 52 |
1 files changed, 29 insertions, 23 deletions
diff --git a/canohost.c b/canohost.c index fca7134f9..f5145922e 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 $"); | |||
20 | #include "canohost.h" | 20 | #include "canohost.h" |
21 | 21 | ||
22 | static void check_ip_options(int, char *); | 22 | static void check_ip_options(int, char *); |
23 | static void ipv64_normalise_mapped(struct sockaddr_storage *, socklen_t *); | ||
23 | 24 | ||
24 | /* | 25 | /* |
25 | * Return the canonical name of the host at the other end of the socket. The | 26 | * 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) | |||
42 | debug("getpeername failed: %.100s", strerror(errno)); | 43 | debug("getpeername failed: %.100s", strerror(errno)); |
43 | cleanup_exit(255); | 44 | cleanup_exit(255); |
44 | } | 45 | } |
45 | #ifdef IPV4_IN_IPV6 | 46 | |
46 | if (from.ss_family == AF_INET6) { | 47 | ipv64_normalise_mapped(&from, &fromlen); |
47 | struct sockaddr_in6 *from6 = (struct sockaddr_in6 *)&from; | 48 | |
48 | |||
49 | /* Detect IPv4 in IPv6 mapped address and convert it to */ | ||
50 | /* plain (AF_INET) IPv4 address */ | ||
51 | if (IN6_IS_ADDR_V4MAPPED(&from6->sin6_addr)) { | ||
52 | struct sockaddr_in *from4 = (struct sockaddr_in *)&from; | ||
53 | struct in_addr addr; | ||
54 | u_int16_t port; | ||
55 | |||
56 | memcpy(&addr, ((char *)&from6->sin6_addr) + 12, sizeof(addr)); | ||
57 | port = from6->sin6_port; | ||
58 | |||
59 | memset(&from, 0, sizeof(from)); | ||
60 | |||
61 | from4->sin_family = AF_INET; | ||
62 | fromlen = sizeof(*from4); | ||
63 | memcpy(&from4->sin_addr, &addr, sizeof(addr)); | ||
64 | from4->sin_port = port; | ||
65 | } | ||
66 | } | ||
67 | #endif | ||
68 | if (from.ss_family == AF_INET6) | 49 | if (from.ss_family == AF_INET6) |
69 | fromlen = sizeof(struct sockaddr_in6); | 50 | fromlen = sizeof(struct sockaddr_in6); |
70 | 51 | ||
@@ -185,6 +166,31 @@ check_ip_options(int socket, char *ipaddr) | |||
185 | #endif /* IP_OPTIONS */ | 166 | #endif /* IP_OPTIONS */ |
186 | } | 167 | } |
187 | 168 | ||
169 | static void | ||
170 | ipv64_normalise_mapped(struct sockaddr_storage *addr, socklen_t *len) | ||
171 | { | ||
172 | struct sockaddr_in6 *a6 = (struct sockaddr_in6 *)addr; | ||
173 | struct sockaddr_in *a4 = (struct sockaddr_in *)addr; | ||
174 | struct in_addr inaddr; | ||
175 | u_int16_t port; | ||
176 | |||
177 | if (addr->ss_family != AF_INET6 || | ||
178 | !IN6_IS_ADDR_V4MAPPED(&a6->sin6_addr)) | ||
179 | return; | ||
180 | |||
181 | debug3("Normalising mapped IPv4 in IPv6 address"); | ||
182 | |||
183 | memcpy(&inaddr, ((char *)&a6->sin6_addr) + 12, sizeof(inaddr)); | ||
184 | port = a6->sin6_port; | ||
185 | |||
186 | memset(addr, 0, sizeof(*a4)); | ||
187 | |||
188 | a4->sin_family = AF_INET; | ||
189 | *len = sizeof(*a4); | ||
190 | memcpy(&a4->sin_addr, &inaddr, sizeof(inaddr)); | ||
191 | a4->sin_port = port; | ||
192 | } | ||
193 | |||
188 | /* | 194 | /* |
189 | * Return the canonical name of the host in the other side of the current | 195 | * Return the canonical name of the host in the other side of the current |
190 | * connection. The host name is cached, so it is efficient to call this | 196 | * connection. The host name is cached, so it is efficient to call this |