Improved the build rule for getfsdev and added getfsdev.o to the
[rsync/rsync.git] / clientname.c
index 02846b3..60e8af0 100644 (file)
@@ -43,29 +43,26 @@ extern int am_server;
  **/
 char *client_addr(int fd)
 {
-       struct sockaddr_storage ss;
-       socklen_t length = sizeof ss;
-       char *ssh_client, *p;
-       int len;
        static char addr_buf[100];
        static int initialised;
+       struct sockaddr_storage ss;
+       socklen_t length = sizeof ss;
+       char *ssh_info, *p;
 
        if (initialised)
                return addr_buf;
 
        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 */
-                       if ((p = strchr(ssh_client, ' ')) != NULL) {
-                               len = MIN((unsigned int) (p - ssh_client),
-                                   sizeof addr_buf - 1);
-                               strncpy(addr_buf, ssh_client, len);
-                               *(addr_buf + len) = '\0';
-                       }
+               if ((ssh_info = getenv("SSH_CONNECTION")) != NULL
+                   || (ssh_info = getenv("SSH_CLIENT")) != NULL
+                   || (ssh_info = getenv("SSH2_CLIENT")) != NULL) {
+                       strlcpy(addr_buf, ssh_info, sizeof addr_buf);
+                       /* Truncate the value to just the IP address. */
+                       if ((p = strchr(addr_buf, ' ')) != NULL)
+                               *p = '\0';
                }
        } else {
                client_sockaddr(fd, &ss, &length);
@@ -101,11 +98,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 +107,47 @@ 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++;
-               }
-               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
+               memset(&hint, 0, sizeof hint);
+
+#ifdef AI_NUMERICHOST
+               hint.ai_flags = AI_NUMERICHOST;
 #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;
+               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
+               case AF_INET6:
+                       ss_len = sizeof (struct sockaddr_in6);
+                       memcpy(&ss, answer->ai_addr, ss_len);
+                       break;
+#endif
+               }
+               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;
 }
@@ -171,8 +168,7 @@ void client_sockaddr(int fd,
 
        if (getpeername(fd, (struct sockaddr *) ss, ss_len)) {
                /* FIXME: Can we really not continue? */
-               rprintf(FERROR, RSYNC_NAME ": getpeername on fd%d failed: %s\n",
-                       fd, strerror(errno));
+               rsyserr(FERROR, errno, "getpeername on fd%d failed", fd);
                exit_cleanup(RERR_SOCKETIO);
        }