*/
#include "includes.h"
-RCSID("$OpenBSD: canohost.c,v 1.37 2003/06/02 09:17:34 markus Exp $");
+RCSID("$OpenBSD: canohost.c,v 1.40 2004/06/21 17:36:31 avsm Exp $");
#include "packet.h"
#include "xmalloc.h"
#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
*/
static char *
-get_remote_hostname(int socket, int use_dns)
+get_remote_hostname(int sock, int use_dns)
{
struct sockaddr_storage from;
int i;
/* Get IP address of client. */
fromlen = sizeof(from);
memset(&from, 0, sizeof(from));
- if (getpeername(socket, (struct sockaddr *)&from, &fromlen) < 0) {
+ if (getpeername(sock, (struct sockaddr *)&from, &fromlen) < 0) {
debug("getpeername failed: %.100s", strerror(errno));
- fatal_cleanup();
+ 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
+
+ if (from.ss_family == AF_INET)
+ check_ip_options(sock, ntop);
+
+ ipv64_normalise_mapped(&from, &fromlen);
+
if (from.ss_family == AF_INET6)
fromlen = sizeof(struct sockaddr_in6);
if (!use_dns)
return xstrdup(ntop);
- if (from.ss_family == AF_INET)
- check_ip_options(socket, ntop);
-
debug3("Trying to reverse map address %.100s.", ntop);
/* Map the IP address to a host name. */
if (getnameinfo((struct sockaddr *)&from, fromlen, name, sizeof(name),
*/
memset(&hints, 0, sizeof(hints));
hints.ai_socktype = SOCK_DGRAM; /*dummy*/
- hints.ai_flags = NI_NUMERICHOST;
+ hints.ai_flags = AI_NUMERICHOST;
if (getaddrinfo(name, "0", &hints, &ai) == 0) {
logit("Nasty PTR record \"%s\" is set up for %s, ignoring",
name, ntop);
*/
/* IPv4 only */
static void
-check_ip_options(int socket, char *ipaddr)
+check_ip_options(int sock, char *ipaddr)
{
+#ifdef IP_OPTIONS
u_char options[200];
char text[sizeof(options) * 3 + 1];
socklen_t option_size;
else
ipproto = IPPROTO_IP;
option_size = sizeof(options);
- if (getsockopt(socket, ipproto, IP_OPTIONS, options,
+ if (getsockopt(sock, ipproto, IP_OPTIONS, options,
&option_size) >= 0 && option_size != 0) {
text[0] = '\0';
for (i = 0; i < option_size; i++)
packet_disconnect("Connection from %.100s with IP options:%.800s",
ipaddr, text);
}
+#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;
}
/*
* The returned string must be freed.
*/
static char *
-get_socket_address(int socket, int remote, int flags)
+get_socket_address(int sock, int remote, int flags)
{
struct sockaddr_storage addr;
socklen_t addrlen;
memset(&addr, 0, sizeof(addr));
if (remote) {
- if (getpeername(socket, (struct sockaddr *)&addr, &addrlen)
+ if (getpeername(sock, (struct sockaddr *)&addr, &addrlen)
< 0)
return NULL;
} else {
- if (getsockname(socket, (struct sockaddr *)&addr, &addrlen)
+ if (getsockname(sock, (struct sockaddr *)&addr, &addrlen)
< 0)
return NULL;
}
}
char *
-get_peer_ipaddr(int socket)
+get_peer_ipaddr(int sock)
{
char *p;
- if ((p = get_socket_address(socket, 1, NI_NUMERICHOST)) != NULL)
+ if ((p = get_socket_address(sock, 1, NI_NUMERICHOST)) != NULL)
return p;
return xstrdup("UNKNOWN");
}
char *
-get_local_ipaddr(int socket)
+get_local_ipaddr(int sock)
{
char *p;
- if ((p = get_socket_address(socket, 0, NI_NUMERICHOST)) != NULL)
+ if ((p = get_socket_address(sock, 0, NI_NUMERICHOST)) != NULL)
return p;
return xstrdup("UNKNOWN");
}
char *
-get_local_name(int socket)
+get_local_name(int sock)
{
- return get_socket_address(socket, 0, NI_NAMEREQD);
+ return get_socket_address(sock, 0, NI_NAMEREQD);
}
/*
canonical_host_ip =
get_peer_ipaddr(packet_get_connection_in());
if (canonical_host_ip == NULL)
- fatal_cleanup();
+ cleanup_exit(255);
} else {
/* If not on socket, return UNKNOWN. */
canonical_host_ip = xstrdup("UNKNOWN");
} else {
if (getpeername(sock, (struct sockaddr *)&from, &fromlen) < 0) {
debug("getpeername failed: %.100s", strerror(errno));
- fatal_cleanup();
+ cleanup_exit(255);
}
}