ports/65043: [patch] net/rsync: problems in client name lookup
code
Alex Vasylenko
lxv at omut.org
Thu Apr 1 23:38:04 GMT 2004
Wayne,
I'm changing the subject and keeping your text in an attempt to get this
recorded in gnats.
Wayne Davison wrote:
> On Thu, Apr 01, 2004 at 11:31:00AM -0500, Alex Vasylenko wrote:
>
>> - detection of IPv6 via counting dots is plain silly and doesn't work;
>
>
> Thanks, I've tweaked your patch for this a little and checked it in.
> It's attached to this email.
>
>> - fails to set ss_len member of struct sockaddr_storage, which when
>> passed to getnameinfo causes the latter to fail;
>
>
> Not everyone has ss_len in sockaddr_storage, so this part of the patch
> doesn't work. It looked like the only place you set the value was after
> calling client_sockaddr() (though you only affected one of the two
> places it was called).
ss.ss_len is set correctly in the answer structure returned from
getnameinfo, so no need to set it explicitly there. Setting ss_len
inside "switch (answer->ai_family)" like you do is OK, as long as ss_len
must be passed as a parameter to lookup_name.
> So, might it be better to set the value inside
> the client_sockaddr() routine?
>
> Attached is my guess at how this might be fixed. This looks odd,
> though, so I think this is probably not the right fix. Can you (or
> anyone with access to a system that uses ss_len) let me know if this
> second patch is what we need, and if not, what the correct fix is.
I think your second patch is superfluous, as getpeername returns a
correctly formatted sockaddr (with _len set, if it's there), so it
should be sufficient to simply drop the "ss.ss_len = ss_len;" line from
my original patch
>
> ------------------------------------------------------------------------
>
> --- clientname.c 1 Apr 2004 21:08:24 -0000 1.20
> +++ clientname.c 1 Apr 2004 21:36:31 -0000
> @@ -100,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)
> @@ -113,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;
> +
> + memset(&hint, 0, sizeof hint);
>
> - for (p = addr; *p && (dots <= 3); p++) {
> - if (*p == '.')
> - dots++;
> + 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;
> }
>
>
> ------------------------------------------------------------------------
>
> --- clientname.c 1 Apr 2004 21:39:35 -0000 1.21
> +++ clientname.c 1 Apr 2004 22:00:22 -0000
> @@ -190,9 +190,6 @@ void client_sockaddr(int fd,
> memset(sin, 0, sizeof *sin);
> sin->sin_family = AF_INET;
> *ss_len = sizeof (struct sockaddr_in);
> -#if HAVE_SOCKADDR_IN_LEN
> - sin->sin_len = *ss_len;
> -#endif
> sin->sin_port = sin6.sin6_port;
>
> /* There is a macro to extract the mapped part
> @@ -201,6 +198,10 @@ void client_sockaddr(int fd,
> memcpy(&sin->sin_addr, &sin6.sin6_addr.s6_addr[12],
> sizeof sin->sin_addr);
> }
> +#endif /* INET6 */
> +
> +#if HAVE_SOCKADDR_IN_LEN
> + ss->ss_len = *ss_len;
> #endif
> }
>
--
Alex.
More information about the rsync
mailing list