apr-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Colm MacCarthaigh <c...@stdlib.net>
Subject Re: unrecognized getnameinfo() bugs dealing with IPv4-mapped addresses
Date Thu, 20 May 2004 12:12:00 GMT
On Thu, May 20, 2004 at 07:37:00AM -0400, Jeff Trawick wrote:
> updated patch attached to remove configure-time logic and protect 
> references to IPv6 goodies with APR_HAVE_IPV6...
> 
> any comments from the crowd before I commit to both branches?

> ? build-outputs.mk.python
> ? build-outputs.mk.tmp
> ? build.conf.headers
> ? build.conf.paths
> ? build.conf.platform_dirs
> ? gen-build.sh
> ? out
> ? stderr
> ? test.tar
> Index: build/apr_network.m4
> ===================================================================
> RCS file: /home/cvs/apr/build/apr_network.m4,v
> retrieving revision 1.30
> diff -u -r1.30 apr_network.m4
> --- build/apr_network.m4	23 Dec 2003 14:54:55 -0000	1.30
> +++ build/apr_network.m4	20 May 2004 11:33:55 -0000
> @@ -175,80 +175,6 @@
>  ])
>  
>  dnl
> -dnl check for getnameinfo() that properly resolves IPv4-mapped IPv6 addresses
> -dnl
> -dnl Darwin is known not to map them correctly
> -dnl
> -AC_DEFUN(APR_CHECK_GETNAMEINFO_IPV4_MAPPED,[
> -  AC_CACHE_CHECK(whether getnameinfo resolves IPv4-mapped IPv6 addresses,
> -                 ac_cv_getnameinfo_ipv4_mapped,[
> -  AC_TRY_RUN( [
> -#ifdef HAVE_NETDB_H
> -#include <netdb.h>
> -#endif
> -#ifdef HAVE_STRING_H
> -#include <string.h>
> -#endif
> -#ifdef HAVE_SYS_TYPES_H
> -#include <sys/types.h>
> -#endif
> -#ifdef HAVE_SYS_SOCKET_H
> -#include <sys/socket.h>
> -#endif
> -#ifdef HAVE_NETINET_IN_H
> -#include <netinet/in.h>
> -#endif
> -#ifdef HAVE_ARPA_INET_H
> -#include <arpa/inet.h>
> -#endif
> -
> -void main(void) {
> -    struct sockaddr_in6 sa = {0};
> -    struct in_addr ipv4;
> -#if defined(NI_MAXHOST)
> -    char hbuf[NI_MAXHOST];
> -#else
> -    char hbuf[256];
> -#endif
> -    unsigned int *addr32;
> -    int error;
> -
> -    ipv4.s_addr = inet_addr("127.0.0.1");
> -
> -    sa.sin6_family = AF_INET6;
> -    sa.sin6_port = 0;
> -
> -    addr32 = (unsigned int *)&sa.sin6_addr;
> -    addr32[2] = htonl(0x0000FFFF);
> -    addr32[3] = ipv4.s_addr;
> -
> -#ifdef SIN6_LEN
> -    sa.sin6_len = sizeof(sa);
> -#endif
> -
> -    error = getnameinfo((const struct sockaddr *)&sa, sizeof(sa),
> -                        hbuf, sizeof(hbuf), NULL, 0,
> -                        NI_NAMEREQD);
> -    if (error) {
> -        exit(1);
> -    } else {
> -        exit(0);
> -    }
> -}
> -],[
> -  ac_cv_getnameinfo_ipv4_mapped="yes"
> -],[
> -  ac_cv_getnameinfo_ipv4_mapped="no"
> -],[
> -  ac_cv_getnameinfo_ipv4_mapped="yes"
> -])])
> -if test "$ac_cv_getnameinfo_ipv4_mapped" = "no"; then
> -  AC_DEFINE(GETNAMEINFO_IPV4_MAPPED_FAILS, 1,
> -            [Define if getnameinfo does not map IPv4 address correctly])
> -fi
> -])
> -
> -dnl
>  dnl Checks the definition of gethostbyname_r and gethostbyaddr_r
>  dnl which are different for glibc, solaris and assorted other operating
>  dnl systems
> Index: network_io/unix/sockaddr.c
> ===================================================================
> RCS file: /home/cvs/apr/network_io/unix/sockaddr.c,v
> retrieving revision 1.49
> diff -u -r1.49 sockaddr.c
> --- network_io/unix/sockaddr.c	4 Mar 2004 16:17:25 -0000	1.49
> +++ network_io/unix/sockaddr.c	20 May 2004 11:33:56 -0000
> @@ -575,27 +575,26 @@
>       * a numeric address string if it fails to resolve the host name;
>       * that is *not* what we want here
>       *
> -     * Additionally, if we know getnameinfo() doesn't handle IPv4-mapped
> -     * IPv6 addresses correctly, drop down to IPv4 before calling
> -     * getnameinfo().
> +     * For IPv4-mapped IPv6 addresses, drop down to IPv4 before calling
> +     * getnameinfo() to avoid getnameinfo bugs (MacOS X, glibc).
>       */
> -#ifdef GETNAMEINFO_IPV4_MAPPED_FAILS
> +#if APR_HAVE_IPV6
>      if (sockaddr->family == AF_INET6 &&
>          IN6_IS_ADDR_V4MAPPED(&sockaddr->sa.sin6.sin6_addr)) {
> -        struct apr_sockaddr_t tmpsa;
> -        tmpsa.sa.sin.sin_family = AF_INET;
> -        tmpsa.sa.sin.sin_addr.s_addr = ((uint32_t *)sockaddr->ipaddr_ptr)[3];
> +        struct sockaddr_in tmpsa;
> +        tmpsa.sin_family = AF_INET;
> +        tmpsa.sin_addr.s_addr = sockaddr->sa.sin6.sin6_addr.s6_addr[3];

I don't think that's correct, s6_addr is only 8-bits wide, but we need
32 bits here.  sockaddr->sa.sin6.sin6_addr.s6_addr[3] will get you bits
24 through 32 when we want 96 through 128 :)

We can't use the s6_addr32 because it's non-standard (and depends on
_KERNEL on the BSD's I think - though havn't checked recently). I knew
there was some reason I used the ipaddr_ptr the first time ;p

-- 
Colm MacCárthaigh                        Public Key: colm+pgp@stdlib.net

Mime
View raw message