From a693f5b3da5fa6a81c5415fa38b079f016c407d1 Mon Sep 17 00:00:00 2001 From: "wtc%netscape.com" Date: Thu, 16 Jan 2003 16:16:34 +0000 Subject: [PATCH] Bug 168228: added IPv6 support for Darwin (Mac OS X). Added two new feature macros _PR_HAVE_INET_NTOP and _PR_GHBA_DISALLOW_V4MAPPED to handle the differences of Darwin's IPv6 sockets implementation and other platforms' implementations. Modified files: _aix.h _bsdi.h _darwin.h _freebsd.h _irix.h _linux.h _netbsd.h _openvms.h _osf1.h _solaris.h prnetdb.c --- nsprpub/pr/include/md/_aix.h | 1 + nsprpub/pr/include/md/_bsdi.h | 1 + nsprpub/pr/include/md/_darwin.h | 21 ++++++++ nsprpub/pr/include/md/_freebsd.h | 1 + nsprpub/pr/include/md/_irix.h | 1 + nsprpub/pr/include/md/_linux.h | 1 + nsprpub/pr/include/md/_netbsd.h | 1 + nsprpub/pr/include/md/_openvms.h | 4 +- nsprpub/pr/include/md/_osf1.h | 4 +- nsprpub/pr/include/md/_solaris.h | 4 +- nsprpub/pr/src/misc/prnetdb.c | 93 +++++++++++++++++++++++++++++--- 11 files changed, 121 insertions(+), 11 deletions(-) diff --git a/nsprpub/pr/include/md/_aix.h b/nsprpub/pr/include/md/_aix.h index 5bf1a335b17..2ef0fc1d718 100644 --- a/nsprpub/pr/include/md/_aix.h +++ b/nsprpub/pr/include/md/_aix.h @@ -72,6 +72,7 @@ #define _PR_USE_POLL #define _PR_STAT_HAS_ONLY_ST_ATIME #ifdef _PR_INET6 +#define _PR_HAVE_INET_NTOP #define _PR_HAVE_GETHOSTBYNAME2 #endif #define _PR_HAVE_SYSV_SEMAPHORES diff --git a/nsprpub/pr/include/md/_bsdi.h b/nsprpub/pr/include/md/_bsdi.h index 3ecddde4529..346f1049058 100644 --- a/nsprpub/pr/include/md/_bsdi.h +++ b/nsprpub/pr/include/md/_bsdi.h @@ -66,6 +66,7 @@ /* BSD/OS 4.3 and newer all have IPv6 support */ #if _BSDI_VERSION >= 200105 #define _PR_INET6 +#define _PR_HAVE_INET_NTOP #define _PR_HAVE_GETIPNODEBYNAME #define _PR_HAVE_GETIPNODEBYADDR #define _PR_INET6_PROBE diff --git a/nsprpub/pr/include/md/_darwin.h b/nsprpub/pr/include/md/_darwin.h index d262849cbb3..e3046801142 100644 --- a/nsprpub/pr/include/md/_darwin.h +++ b/nsprpub/pr/include/md/_darwin.h @@ -61,6 +61,27 @@ #define _PR_NO_LARGE_FILES #define PR_HAVE_SYSV_NAMED_SHARED_MEMORY +#define _PR_INET6 +/* + * I'd prefer to use getipnodebyname and getipnodebyaddr but the + * getipnodebyname(3) man page on Mac OS X 10.2 says they are not + * thread-safe. AI_V4MAPPED|AI_ADDRCONFIG doesn't work either. + */ +#define _PR_HAVE_GETHOSTBYNAME2 +/* + * On Mac OS X 10.2, gethostbyaddr fails with h_errno=NO_RECOVERY + * if you pass an IPv4-mapped IPv6 address to it. + */ +#define _PR_GHBA_DISALLOW_V4MAPPED +/* socket(AF_INET6) fails with EPROTONOSUPPORT on Mac OS X 10.1. */ +#if MACOS_DEPLOYMENT_TARGET < 100200 +#define _PR_INET6_PROBE +#endif +/* Mac OS X 10.2 has inet_ntop and inet_pton. */ +#if MACOS_DEPLOYMENT_TARGET >= 100200 +#define _PR_HAVE_INET_NTOP +#endif + #define USE_SETJMP #if !defined(_PR_PTHREADS) diff --git a/nsprpub/pr/include/md/_freebsd.h b/nsprpub/pr/include/md/_freebsd.h index 844980c1ef6..68542336479 100644 --- a/nsprpub/pr/include/md/_freebsd.h +++ b/nsprpub/pr/include/md/_freebsd.h @@ -90,6 +90,7 @@ #if __FreeBSD_version >= 400014 #define _PR_INET6 +#define _PR_HAVE_INET_NTOP #define _PR_HAVE_GETHOSTBYNAME2 #define _PR_INET6_PROBE #endif diff --git a/nsprpub/pr/include/md/_irix.h b/nsprpub/pr/include/md/_irix.h index e81ee5ad0fe..5e7b624ca15 100644 --- a/nsprpub/pr/include/md/_irix.h +++ b/nsprpub/pr/include/md/_irix.h @@ -79,6 +79,7 @@ #define _PR_ACCEPT_INHERIT_NONBLOCK #ifdef _PR_INET6 +#define _PR_HAVE_INET_NTOP #define _PR_HAVE_GETIPNODEBYNAME #define _PR_HAVE_GETIPNODEBYADDR #endif diff --git a/nsprpub/pr/include/md/_linux.h b/nsprpub/pr/include/md/_linux.h index 3f4b6735afb..04b2ea74458 100644 --- a/nsprpub/pr/include/md/_linux.h +++ b/nsprpub/pr/include/md/_linux.h @@ -118,6 +118,7 @@ extern PRInt32 _PR_ia64_AtomicSet(PRInt32 *val, PRInt32 newval); #endif #if (__GLIBC__ > 2) || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 1) #define _PR_INET6 +#define _PR_HAVE_INET_NTOP #define _PR_HAVE_GETHOSTBYNAME2 #define _PR_INET6_PROBE #endif diff --git a/nsprpub/pr/include/md/_netbsd.h b/nsprpub/pr/include/md/_netbsd.h index 1e70994d2e0..0ccc2399e82 100644 --- a/nsprpub/pr/include/md/_netbsd.h +++ b/nsprpub/pr/include/md/_netbsd.h @@ -80,6 +80,7 @@ #if __NetBSD_Version__ >= 105000000 #define _PR_INET6 +#define _PR_HAVE_INET_NTOP #define _PR_HAVE_GETHOSTBYNAME2 #define _PR_INET6_PROBE #endif diff --git a/nsprpub/pr/include/md/_openvms.h b/nsprpub/pr/include/md/_openvms.h index abf438f1818..4b3fb92a5ee 100644 --- a/nsprpub/pr/include/md/_openvms.h +++ b/nsprpub/pr/include/md/_openvms.h @@ -106,7 +106,9 @@ struct ip_mreq { #define _PR_HAVE_GETIPNODEBYNAME #define _PR_HAVE_GETIPNODEBYADDR #define _PR_INET6_PROBE -#ifndef _PR_INET6 +#ifdef _PR_INET6 +#define _PR_HAVE_INET_NTOP +#else #define AF_INET6 26 #define AI_V4MAPPED 0x00000010 #define AI_ALL 0x00000008 diff --git a/nsprpub/pr/include/md/_osf1.h b/nsprpub/pr/include/md/_osf1.h index edf2fa3da4a..33c44da66a7 100644 --- a/nsprpub/pr/include/md/_osf1.h +++ b/nsprpub/pr/include/md/_osf1.h @@ -72,7 +72,9 @@ #define _PR_HAVE_GETIPNODEBYNAME #define _PR_HAVE_GETIPNODEBYADDR #define _PR_INET6_PROBE -#ifndef _PR_INET6 +#ifdef _PR_INET6 +#define _PR_HAVE_INET_NTOP +#else #define AF_INET6 26 #define AI_V4MAPPED 0x00000010 #define AI_ALL 0x00000008 diff --git a/nsprpub/pr/include/md/_solaris.h b/nsprpub/pr/include/md/_solaris.h index 3efb498d2ba..01b5fed4de3 100644 --- a/nsprpub/pr/include/md/_solaris.h +++ b/nsprpub/pr/include/md/_solaris.h @@ -111,7 +111,9 @@ #define _PR_HAVE_GETIPNODEBYADDR #define _PR_INET6_PROBE #define _PR_ACCEPT_INHERIT_NONBLOCK -#ifndef _PR_INET6 +#ifdef _PR_INET6 +#define _PR_HAVE_INET_NTOP +#else #define AF_INET6 26 #define AI_V4MAPPED 0x0001 #define AI_ALL 0x0002 diff --git a/nsprpub/pr/src/misc/prnetdb.c b/nsprpub/pr/src/misc/prnetdb.c index 207a6c1eb22..f6699422798 100644 --- a/nsprpub/pr/src/misc/prnetdb.c +++ b/nsprpub/pr/src/misc/prnetdb.c @@ -182,7 +182,10 @@ static PRBool _pr_have_inet6_if = PR_FALSE; #undef DEBUG_QUERY_IFS -#if defined(AIX) +#if defined(AIX) \ + || (defined(DARWIN) && (!defined(HAVE_GETIFADDRS) \ + || (defined(MACOS_DEPLOYMENT_TARGET) \ + && MACOS_DEPLOYMENT_TARGET < 100200))) /* * Use SIOCGIFCONF ioctl on platforms that don't have routing @@ -288,7 +291,8 @@ _pr_QueryNetIfs(void) } } else if (sa->sa_family == AF_INET6) { struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) sa; - if (!IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr)) { + if (!IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr) + && !IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) { _pr_have_inet6_if = PR_TRUE; } } @@ -315,6 +319,75 @@ _pr_QueryNetIfs(void) PR_Free(buf); } +#elif (defined(DARWIN) && defined(HAVE_GETIFADDRS)) + +/* + * Use the BSD getifaddrs function. + */ + +#include +#include +#include +#include + +#ifdef DEBUG_QUERY_IFS +static void +_pr_PrintIfaddrs(struct ifaddrs *ifa) +{ + struct sockaddr *sa; + const char* family; + void *addrp; + char addrstr[64]; + + sa = ifa->ifa_addr; + if (sa->sa_family == AF_INET) { + struct sockaddr_in *sin = (struct sockaddr_in *)sa; + family = "inet"; + addrp = &sin->sin_addr; + } else if (sa->sa_family == AF_INET6) { + struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa; + family = "inet6"; + addrp = &sin6->sin6_addr; + } else { + return; /* skip if not AF_INET or AF_INET6 */ + } + inet_ntop(sa->sa_family, addrp, addrstr, sizeof(addrstr)); + printf("%s: %s %s\n", ifa->ifa_name, family, addrstr); +} +#endif + +static void +_pr_QueryNetIfs(void) +{ + struct ifaddrs *ifp; + struct ifaddrs *ifa; + + if (getifaddrs(&ifp) == -1) { + return; + } + for (ifa = ifp; ifa; ifa = ifa->ifa_next) { + struct sockaddr *sa; + +#ifdef DEBUG_QUERY_IFS + _pr_PrintIfaddrs(ifa); +#endif + sa = ifa->ifa_addr; + if (sa->sa_family == AF_INET) { + struct sockaddr_in *sin = (struct sockaddr_in *) sa; + if (sin->sin_addr.s_addr != htonl(INADDR_LOOPBACK)) { + _pr_have_inet_if = 1; + } + } else if (sa->sa_family == AF_INET6) { + struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) sa; + if (!IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr) + && !IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) { + _pr_have_inet6_if = 1; + } + } + } + freeifaddrs(ifp); +} + #else /* default */ /* @@ -886,6 +959,10 @@ PR_IMPLEMENT(PRStatus) PR_GetHostByAddr( af = AF_INET6; #else af = AF_INET; +#endif +#if defined(_PR_GHBA_DISALLOW_V4MAPPED) + if (_PR_IN6_IS_ADDR_V4MAPPED(&hostaddr->ipv6.ip)) + af = AF_INET; #endif } else @@ -1370,7 +1447,7 @@ PR_IsNetAddrType(const PRNetAddr *addr, PRNetAddrValue val) return PR_FALSE; } -#ifndef _PR_INET6 +#ifndef _PR_HAVE_INET_NTOP #define XX 127 static const unsigned char index_hex[256] = { XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, @@ -1610,14 +1687,14 @@ static const char *V6AddrToString( #undef STUFF } -#endif /* !_PR_INET6 */ +#endif /* !_PR_HAVE_INET_NTOP */ PR_IMPLEMENT(PRStatus) PR_StringToNetAddr(const char *string, PRNetAddr *addr) { PRStatus status = PR_SUCCESS; PRIntn rv; -#if defined(_PR_INET6) +#if defined(_PR_HAVE_INET_NTOP) rv = inet_pton(AF_INET6, string, &addr->ipv6.ip); if (1 == rv) { @@ -1640,7 +1717,7 @@ PR_IMPLEMENT(PRStatus) PR_StringToNetAddr(const char *string, PRNetAddr *addr) status = PR_FAILURE; } } -#else /* _PR_INET6 */ +#else /* _PR_HAVE_INET_NTOP */ rv = StringToV6Addr(string, &addr->ipv6.ip); if (1 == rv) { addr->raw.family = PR_AF_INET6; @@ -1664,7 +1741,7 @@ PR_IMPLEMENT(PRStatus) PR_StringToNetAddr(const char *string, PRNetAddr *addr) PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); status = PR_FAILURE; } -#endif /* _PR_INET6 */ +#endif /* _PR_HAVE_INET_NTOP */ return status; } @@ -1674,7 +1751,7 @@ PR_IMPLEMENT(PRStatus) PR_NetAddrToString( { if (PR_AF_INET6 == addr->raw.family) { -#if defined(_PR_INET6) +#if defined(_PR_HAVE_INET_NTOP) if (NULL == inet_ntop(AF_INET6, &addr->ipv6.ip, string, size)) #else if (NULL == V6AddrToString(&addr->ipv6.ip, string, size))