summaryrefslogtreecommitdiff
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 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
22static void check_ip_options(int, char *); 22static void check_ip_options(int, char *);
23static 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
169static void
170ipv64_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