Index: mozilla/nsprpub/pr/src/io/pripv6.c |
=================================================================== |
--- mozilla/nsprpub/pr/src/io/pripv6.c (revision 191424) |
+++ mozilla/nsprpub/pr/src/io/pripv6.c (working copy) |
@@ -1,364 +0,0 @@ |
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
-/* This Source Code Form is subject to the terms of the Mozilla Public |
- * License, v. 2.0. If a copy of the MPL was not distributed with this |
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
- |
-/* |
-** File: pripv6.c |
-** Description: Support for various functions unique to IPv6 |
-*/ |
-#include "primpl.h" |
-#include <string.h> |
- |
-#if !defined(_PR_INET6) || defined(_PR_INET6_PROBE) |
- |
-static PRIOMethods ipv6_to_v4_tcpMethods; |
-static PRIOMethods ipv6_to_v4_udpMethods; |
-static PRDescIdentity _pr_ipv6_to_ipv4_id; |
-extern PRBool IsValidNetAddr(const PRNetAddr *addr); |
-extern PRIPv6Addr _pr_in6addr_any; |
-extern PRIPv6Addr _pr_in6addr_loopback; |
- |
-/* |
- * convert an IPv4-mapped IPv6 addr to an IPv4 addr |
- */ |
-static void _PR_ConvertToIpv4NetAddr(const PRNetAddr *src_v6addr, |
- PRNetAddr *dst_v4addr) |
-{ |
-const PRUint8 *srcp; |
- |
- PR_ASSERT(PR_AF_INET6 == src_v6addr->ipv6.family); |
- |
- if (PR_IsNetAddrType(src_v6addr, PR_IpAddrV4Mapped)) { |
- srcp = src_v6addr->ipv6.ip.pr_s6_addr; |
- memcpy((char *) &dst_v4addr->inet.ip, srcp + 12, 4); |
- } else if (PR_IsNetAddrType(src_v6addr, PR_IpAddrAny)) { |
- dst_v4addr->inet.ip = htonl(INADDR_ANY); |
- } else if (PR_IsNetAddrType(src_v6addr, PR_IpAddrLoopback)) { |
- dst_v4addr->inet.ip = htonl(INADDR_LOOPBACK); |
- } |
- dst_v4addr->inet.family = PR_AF_INET; |
- dst_v4addr->inet.port = src_v6addr->ipv6.port; |
-} |
- |
-/* |
- * convert an IPv4 addr to an IPv4-mapped IPv6 addr |
- */ |
-static void _PR_ConvertToIpv6NetAddr(const PRNetAddr *src_v4addr, |
- PRNetAddr *dst_v6addr) |
-{ |
-PRUint8 *dstp; |
- |
- PR_ASSERT(PR_AF_INET == src_v4addr->inet.family); |
- dst_v6addr->ipv6.family = PR_AF_INET6; |
- dst_v6addr->ipv6.port = src_v4addr->inet.port; |
- |
- if (htonl(INADDR_ANY) == src_v4addr->inet.ip) { |
- dst_v6addr->ipv6.ip = _pr_in6addr_any; |
- } else { |
- dstp = dst_v6addr->ipv6.ip.pr_s6_addr; |
- memset(dstp, 0, 10); |
- memset(dstp + 10, 0xff, 2); |
- memcpy(dstp + 12,(char *) &src_v4addr->inet.ip, 4); |
- } |
-} |
- |
-static PRStatus PR_CALLBACK Ipv6ToIpv4SocketBind(PRFileDesc *fd, |
- const PRNetAddr *addr) |
-{ |
- PRNetAddr tmp_ipv4addr; |
- const PRNetAddr *tmp_addrp; |
- PRFileDesc *lo = fd->lower; |
- |
- if (PR_AF_INET6 != addr->raw.family) { |
- PR_SetError(PR_ADDRESS_NOT_SUPPORTED_ERROR, 0); |
- return PR_FAILURE; |
- } |
- if (PR_IsNetAddrType(addr, PR_IpAddrV4Mapped) || |
- PR_IsNetAddrType(addr, PR_IpAddrAny)) { |
- _PR_ConvertToIpv4NetAddr(addr, &tmp_ipv4addr); |
- tmp_addrp = &tmp_ipv4addr; |
- } else { |
- PR_SetError(PR_NETWORK_UNREACHABLE_ERROR, 0); |
- return PR_FAILURE; |
- } |
- return((lo->methods->bind)(lo,tmp_addrp)); |
-} |
- |
-static PRStatus PR_CALLBACK Ipv6ToIpv4SocketConnect( |
- PRFileDesc *fd, const PRNetAddr *addr, PRIntervalTime timeout) |
-{ |
- PRNetAddr tmp_ipv4addr; |
- const PRNetAddr *tmp_addrp; |
- |
- if (PR_AF_INET6 != addr->raw.family) { |
- PR_SetError(PR_ADDRESS_NOT_SUPPORTED_ERROR, 0); |
- return PR_FAILURE; |
- } |
- if (PR_IsNetAddrType(addr, PR_IpAddrV4Mapped) || |
- PR_IsNetAddrType(addr, PR_IpAddrLoopback)) { |
- _PR_ConvertToIpv4NetAddr(addr, &tmp_ipv4addr); |
- tmp_addrp = &tmp_ipv4addr; |
- } else { |
- PR_SetError(PR_NETWORK_UNREACHABLE_ERROR, 0); |
- return PR_FAILURE; |
- } |
- return (fd->lower->methods->connect)(fd->lower, tmp_addrp, timeout); |
-} |
- |
-static PRInt32 PR_CALLBACK Ipv6ToIpv4SocketSendTo( |
- PRFileDesc *fd, const void *buf, PRInt32 amount, |
- PRIntn flags, const PRNetAddr *addr, PRIntervalTime timeout) |
-{ |
- PRNetAddr tmp_ipv4addr; |
- const PRNetAddr *tmp_addrp; |
- |
- if (PR_AF_INET6 != addr->raw.family) { |
- PR_SetError(PR_ADDRESS_NOT_SUPPORTED_ERROR, 0); |
- return PR_FAILURE; |
- } |
- if (PR_IsNetAddrType(addr, PR_IpAddrV4Mapped) || |
- PR_IsNetAddrType(addr, PR_IpAddrLoopback)) { |
- _PR_ConvertToIpv4NetAddr(addr, &tmp_ipv4addr); |
- tmp_addrp = &tmp_ipv4addr; |
- } else { |
- PR_SetError(PR_NETWORK_UNREACHABLE_ERROR, 0); |
- return PR_FAILURE; |
- } |
- return (fd->lower->methods->sendto)( |
- fd->lower, buf, amount, flags, tmp_addrp, timeout); |
-} |
- |
-static PRFileDesc* PR_CALLBACK Ipv6ToIpv4SocketAccept ( |
- PRFileDesc *fd, PRNetAddr *addr, PRIntervalTime timeout) |
-{ |
- PRStatus rv; |
- PRFileDesc *newfd; |
- PRFileDesc *newstack; |
- PRNetAddr tmp_ipv4addr; |
- PRNetAddr *addrlower = NULL; |
- |
- PR_ASSERT(fd != NULL); |
- PR_ASSERT(fd->lower != NULL); |
- |
- newstack = PR_NEW(PRFileDesc); |
- if (NULL == newstack) |
- { |
- PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); |
- return NULL; |
- } |
- *newstack = *fd; /* make a copy of the accepting layer */ |
- |
- if (addr) |
- addrlower = &tmp_ipv4addr; |
- newfd = (fd->lower->methods->accept)(fd->lower, addrlower, timeout); |
- if (NULL == newfd) |
- { |
- PR_DELETE(newstack); |
- return NULL; |
- } |
- if (addr) |
- _PR_ConvertToIpv6NetAddr(&tmp_ipv4addr, addr); |
- |
- rv = PR_PushIOLayer(newfd, PR_TOP_IO_LAYER, newstack); |
- PR_ASSERT(PR_SUCCESS == rv); |
- return newfd; /* that's it */ |
-} |
- |
-static PRInt32 PR_CALLBACK Ipv6ToIpv4SocketAcceptRead(PRFileDesc *sd, |
- PRFileDesc **nd, PRNetAddr **ipv6_raddr, void *buf, PRInt32 amount, |
- PRIntervalTime timeout) |
-{ |
- PRInt32 nbytes; |
- PRStatus rv; |
- PRNetAddr tmp_ipv4addr; |
- PRFileDesc *newstack; |
- |
- PR_ASSERT(sd != NULL); |
- PR_ASSERT(sd->lower != NULL); |
- |
- newstack = PR_NEW(PRFileDesc); |
- if (NULL == newstack) |
- { |
- PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); |
- return -1; |
- } |
- *newstack = *sd; /* make a copy of the accepting layer */ |
- |
- nbytes = sd->lower->methods->acceptread( |
- sd->lower, nd, ipv6_raddr, buf, amount, timeout); |
- if (-1 == nbytes) |
- { |
- PR_DELETE(newstack); |
- return nbytes; |
- } |
- tmp_ipv4addr = **ipv6_raddr; /* copy */ |
- _PR_ConvertToIpv6NetAddr(&tmp_ipv4addr, *ipv6_raddr); |
- |
- /* this PR_PushIOLayer call cannot fail */ |
- rv = PR_PushIOLayer(*nd, PR_TOP_IO_LAYER, newstack); |
- PR_ASSERT(PR_SUCCESS == rv); |
- return nbytes; |
-} |
- |
-static PRStatus PR_CALLBACK Ipv6ToIpv4SocketGetName(PRFileDesc *fd, |
- PRNetAddr *ipv6addr) |
-{ |
- PRStatus result; |
- PRNetAddr tmp_ipv4addr; |
- |
- result = (fd->lower->methods->getsockname)(fd->lower, &tmp_ipv4addr); |
- if (PR_SUCCESS == result) { |
- _PR_ConvertToIpv6NetAddr(&tmp_ipv4addr, ipv6addr); |
- PR_ASSERT(IsValidNetAddr(ipv6addr) == PR_TRUE); |
- } |
- return result; |
-} |
- |
-static PRStatus PR_CALLBACK Ipv6ToIpv4SocketGetPeerName(PRFileDesc *fd, |
- PRNetAddr *ipv6addr) |
-{ |
- PRStatus result; |
- PRNetAddr tmp_ipv4addr; |
- |
- result = (fd->lower->methods->getpeername)(fd->lower, &tmp_ipv4addr); |
- if (PR_SUCCESS == result) { |
- _PR_ConvertToIpv6NetAddr(&tmp_ipv4addr, ipv6addr); |
- PR_ASSERT(IsValidNetAddr(ipv6addr) == PR_TRUE); |
- } |
- return result; |
-} |
- |
-static PRInt32 PR_CALLBACK Ipv6ToIpv4SocketRecvFrom(PRFileDesc *fd, void *buf, |
- PRInt32 amount, PRIntn flags, PRNetAddr *ipv6addr, |
- PRIntervalTime timeout) |
-{ |
- PRNetAddr tmp_ipv4addr; |
- PRInt32 result; |
- |
- result = (fd->lower->methods->recvfrom)( |
- fd->lower, buf, amount, flags, &tmp_ipv4addr, timeout); |
- if (-1 != result) { |
- _PR_ConvertToIpv6NetAddr(&tmp_ipv4addr, ipv6addr); |
- PR_ASSERT(IsValidNetAddr(ipv6addr) == PR_TRUE); |
- } |
- return result; |
-} |
- |
-#if defined(_PR_INET6_PROBE) |
-static PRBool ipv6_is_present; |
-extern PRBool _pr_test_ipv6_socket(void); |
- |
-#if !defined(_PR_INET6) && defined(_PR_HAVE_GETIPNODEBYNAME) |
-extern PRStatus _pr_find_getipnodebyname(void); |
-#endif |
- |
-#if !defined(_PR_INET6) && defined(_PR_HAVE_GETADDRINFO) |
-extern PRStatus _pr_find_getaddrinfo(void); |
-#endif |
- |
-static PRBool |
-_pr_probe_ipv6_presence(void) |
-{ |
-#if !defined(_PR_INET6) && defined(_PR_HAVE_GETIPNODEBYNAME) |
- if (_pr_find_getipnodebyname() != PR_SUCCESS) |
- return PR_FALSE; |
-#endif |
- |
-#if !defined(_PR_INET6) && defined(_PR_HAVE_GETADDRINFO) |
- if (_pr_find_getaddrinfo() != PR_SUCCESS) |
- return PR_FALSE; |
-#endif |
- |
- return _pr_test_ipv6_socket(); |
-} |
-#endif /* _PR_INET6_PROBE */ |
- |
-static PRCallOnceType _pr_init_ipv6_once; |
- |
-static PRStatus PR_CALLBACK _pr_init_ipv6(void) |
-{ |
- const PRIOMethods *stubMethods; |
- |
-#if defined(_PR_INET6_PROBE) |
- ipv6_is_present = _pr_probe_ipv6_presence(); |
- if (ipv6_is_present) |
- return PR_SUCCESS; |
-#endif |
- |
- _pr_ipv6_to_ipv4_id = PR_GetUniqueIdentity("Ipv6_to_Ipv4 layer"); |
- PR_ASSERT(PR_INVALID_IO_LAYER != _pr_ipv6_to_ipv4_id); |
- |
- stubMethods = PR_GetDefaultIOMethods(); |
- |
- ipv6_to_v4_tcpMethods = *stubMethods; /* first get the entire batch */ |
- /* then override the ones we care about */ |
- ipv6_to_v4_tcpMethods.connect = Ipv6ToIpv4SocketConnect; |
- ipv6_to_v4_tcpMethods.bind = Ipv6ToIpv4SocketBind; |
- ipv6_to_v4_tcpMethods.accept = Ipv6ToIpv4SocketAccept; |
- ipv6_to_v4_tcpMethods.acceptread = Ipv6ToIpv4SocketAcceptRead; |
- ipv6_to_v4_tcpMethods.getsockname = Ipv6ToIpv4SocketGetName; |
- ipv6_to_v4_tcpMethods.getpeername = Ipv6ToIpv4SocketGetPeerName; |
-/* |
- ipv6_to_v4_tcpMethods.getsocketoption = Ipv6ToIpv4GetSocketOption; |
- ipv6_to_v4_tcpMethods.setsocketoption = Ipv6ToIpv4SetSocketOption; |
-*/ |
- ipv6_to_v4_udpMethods = *stubMethods; /* first get the entire batch */ |
- /* then override the ones we care about */ |
- ipv6_to_v4_udpMethods.connect = Ipv6ToIpv4SocketConnect; |
- ipv6_to_v4_udpMethods.bind = Ipv6ToIpv4SocketBind; |
- ipv6_to_v4_udpMethods.sendto = Ipv6ToIpv4SocketSendTo; |
- ipv6_to_v4_udpMethods.recvfrom = Ipv6ToIpv4SocketRecvFrom; |
- ipv6_to_v4_udpMethods.getsockname = Ipv6ToIpv4SocketGetName; |
- ipv6_to_v4_udpMethods.getpeername = Ipv6ToIpv4SocketGetPeerName; |
-/* |
- ipv6_to_v4_udpMethods.getsocketoption = Ipv6ToIpv4GetSocketOption; |
- ipv6_to_v4_udpMethods.setsocketoption = Ipv6ToIpv4SetSocketOption; |
-*/ |
- return PR_SUCCESS; |
-} |
- |
-#if defined(_PR_INET6_PROBE) |
-PRBool _pr_ipv6_is_present(void) |
-{ |
- if (PR_CallOnce(&_pr_init_ipv6_once, _pr_init_ipv6) != PR_SUCCESS) |
- return PR_FALSE; |
- return ipv6_is_present; |
-} |
-#endif |
- |
-PR_IMPLEMENT(PRStatus) _pr_push_ipv6toipv4_layer(PRFileDesc *fd) |
-{ |
- PRFileDesc *ipv6_fd = NULL; |
- |
- if (PR_CallOnce(&_pr_init_ipv6_once, _pr_init_ipv6) != PR_SUCCESS) |
- return PR_FAILURE; |
- |
- /* |
- * For platforms with no support for IPv6 |
- * create layered socket for IPv4-mapped IPv6 addresses |
- */ |
- if (fd->methods->file_type == PR_DESC_SOCKET_TCP) |
- ipv6_fd = PR_CreateIOLayerStub(_pr_ipv6_to_ipv4_id, |
- &ipv6_to_v4_tcpMethods); |
- else |
- ipv6_fd = PR_CreateIOLayerStub(_pr_ipv6_to_ipv4_id, |
- &ipv6_to_v4_udpMethods); |
- if (NULL == ipv6_fd) { |
- goto errorExit; |
- } |
- ipv6_fd->secret = NULL; |
- |
- if (PR_PushIOLayer(fd, PR_TOP_IO_LAYER, ipv6_fd) == PR_FAILURE) { |
- goto errorExit; |
- } |
- |
- return PR_SUCCESS; |
-errorExit: |
- |
- if (ipv6_fd) |
- ipv6_fd->dtor(ipv6_fd); |
- return PR_FAILURE; |
-} |
- |
-#endif /* !defined(_PR_INET6) || defined(_PR_INET6_PROBE) */ |