Use getaddrinfo() to figure out if a numeric address is IPv4 or IPv6.
authorWayne Davison <wayned@samba.org>
Thu, 1 Apr 2004 21:39:35 +0000 (21:39 +0000)
committerWayne Davison <wayned@samba.org>
Thu, 1 Apr 2004 21:39:35 +0000 (21:39 +0000)
clientname.c

index 02846b3..4f85dcf 100644 (file)
@@ -55,8 +55,7 @@ char *client_addr(int fd)
 
        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 @@ char *client_name(int fd)
        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 @@ char *client_name(int fd)
        strcpy(name_buf, default_name);
        initialised = 1;
 
+       memset(&ss, 0, sizeof ss);
+
        if (am_server) {        /* daemon over --rsh mode */
                char *addr = client_addr(fd);
-#ifdef INET6
-               int dots = 0;
-               char *p;
+               struct addrinfo hint, *answer;
+               int err;
 
-               for (p = addr; *p && (dots <= 3); p++) {
-                       if (*p == '.')
-                               dots++;
+               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;
                }
-               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
+
+               switch (answer->ai_family) {
+               case AF_INET:
+                       ss_len = sizeof (struct sockaddr_in);
+                       memcpy(&ss, answer->ai_addr, ss_len);
+                       break;
+#ifdef INET6
+               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;
 }