Use getaddrinfo() to figure out if a numeric address is IPv4 or IPv6.
diff --git a/clientname.c b/clientname.c
index 02846b3..4f85dcf 100644
--- a/clientname.c
+++ b/clientname.c
@@ -55,8 +55,7 @@
 
 	initialised = 1;
 
-	if (am_server) {
-		/* daemon over --rsh mode */
+	if (am_server) {	/* daemon over --rsh mode */
 		strcpy(addr_buf, "0.0.0.0");
 		if ((ssh_client = getenv("SSH_CLIENT")) != NULL) {
 			/* truncate SSH_CLIENT to just IP address */
@@ -101,11 +100,7 @@
 	static char name_buf[100];
 	static char port_buf[100];
 	static int initialised;
-	struct sockaddr_storage ss, *ssp;
-	struct sockaddr_in sin;
-#ifdef INET6
-	struct sockaddr_in6 sin6;
-#endif
+	struct sockaddr_storage ss;
 	socklen_t ss_len;
 
 	if (initialised)
@@ -114,43 +109,45 @@
 	strcpy(name_buf, default_name);
 	initialised = 1;
 
+	memset(&ss, 0, sizeof ss);
+
 	if (am_server) {	/* daemon over --rsh mode */
 		char *addr = client_addr(fd);
+		struct addrinfo hint, *answer;
+		int err;
+
+		memset(&hint, 0, sizeof hint);
+
+		hint.ai_flags = AI_NUMERICHOST;
+		hint.ai_socktype = SOCK_STREAM;
+
+		if ((err = getaddrinfo(addr, NULL, &hint, &answer)) != 0) {
+			rprintf(FERROR, RSYNC_NAME ": malformed address %s: %s\n",
+			        addr, gai_strerror(err));
+			return name_buf;
+		}
+
+		switch (answer->ai_family) {
+		case AF_INET:
+			ss_len = sizeof (struct sockaddr_in);
+			memcpy(&ss, answer->ai_addr, ss_len);
+			break;
 #ifdef INET6
-		int dots = 0;
-		char *p;
-
-		for (p = addr; *p && (dots <= 3); p++) {
-			if (*p == '.')
-				dots++;
-		}
-		if (dots > 3) {
-			/* more than 4 parts to IP address, must be ipv6 */
-			ssp = (struct sockaddr_storage *) &sin6;
-			ss_len = sizeof sin6;
-			memset(ssp, 0, ss_len);
-			inet_pton(AF_INET6, addr, &sin6.sin6_addr);
-			sin6.sin6_family = AF_INET6;
-		} else
+		case AF_INET6:
+			ss_len = sizeof (struct sockaddr_in6);
+			memcpy(&ss, answer->ai_addr, ss_len);
+			break;
 #endif
-		{
-			ssp = (struct sockaddr_storage *) &sin;
-			ss_len = sizeof sin;
-			memset(ssp, 0, ss_len);
-			inet_pton(AF_INET, addr, &sin.sin_addr);
-			sin.sin_family = AF_INET;
 		}
-
+		freeaddrinfo(answer);
 	} else {
 		ss_len = sizeof ss;
-		ssp = &ss;
-
 		client_sockaddr(fd, &ss, &ss_len);
 	}
 
-	if (!lookup_name(fd, ssp, ss_len, name_buf, sizeof name_buf,
+	if (!lookup_name(fd, &ss, ss_len, name_buf, sizeof name_buf,
 			port_buf, sizeof port_buf))
-		check_name(fd, ssp, name_buf);
+		check_name(fd, &ss, name_buf);
 
 	return name_buf;
 }