Closed Bug 23815 Opened 25 years ago Closed 25 years ago

PR_OpenTCPSocket(PR_AF_INET6) fails on linux

Categories

(NSPR :: NSPR, defect, P1)

x86
Linux
defect

Tracking

(Not tracked)

RESOLVED FIXED

People

(Reporter: jgmyers, Assigned: srinivas)

References

Details

Attachments

(3 files)

On linux RedHat 6.1, stock kernel

PR_OpenTCPSocket(PR_AF_INET6) fails with the error
PR_ADDRESS_NOT_SUPPROTED_ERROR.
Blocks: 23811
Priority: P3 → P1
This makes NSPR's IPv6 support almost useless.  NSPR's job is to deal with
platform issues such as lack of native support for the IPv6 socket API.
Status: NEW → ASSIGNED
Should the lack of a definition for PRIPv6Addr and PR_AF_INET6 on
non-IPv6-native platforms be included in this bug, or filed as a separate bug?
Here is a proposal to add NSPR support for IPv6 API on platforms with no native 
support for Ipv6:

1. Define PR_AF_INET6 for all platforms, independent of the definition of 
platform-specific AF_INET6.
2. Redefine PRNetAddr to include ipv6 addresses for all platforms. This will 
change the size of PRNetAddr for all non-Unix platforms when compared to NSPR 
3.x releases.
3. A layered socket is implemented when PR_OpenTCPSocket(PR_AF_INET6) is called 
on on-Ipv6 platforms.
4. The bind, connect and sendto operations accept both ipv4 and ipv6 (mapped) 
addresses for PR_AF_INET6 sockets on non-ipv6 platforms.
5. Modify PR_GetIPNodeByName(PR_AF_INET6) to return ipv4-mapped ipv6 addresses 
on non-ipv6 platforms.
6. NSPR interfaces to accept and return PR_AF_INET6, and not AF_INET6, for 
specifying Ipv6 address family. Internally, NSPR converts PR_AF_INET6 to 
AF_INET6 for ipv6 platforms, and AF_INET for non-ipv6 platforms.
I also propose removing PR_SetIpv6Enable.
The socket I/O methods that fill in a user-provided PRNetAddr
need to map an IPv4 address to an IPv4-mapped IPv6 address.
These are: accept, recvfrom, getsockname, and getpeername.
Also, the multicast-related socket option data also contain
a PRNetAddr, so getsocketoption and setsocketoption methods
may also to perform address mapping.
The mapping connect and sendto routines should check for IPv6 addresses that are 
not IPv4-mapped, returning a "network unreachable" error in such cases.  They 
should not use the lower 4 bytes of an non-IPv4-mapped IPv6 address as an IPv4 
address.
Linux has IPv6 support as a Kernel compile-time option, defaulting off.  We will 
want Linux to first try probing for IPv6 support with a socket(AF_INET6) call, 
setting a global which causes it to fall back to the v6-to-v4 layered mapping 
layer if the socket() call returns a "protocol not supported" error.

This should be a separate feature request, but it might be a good thing to keep 
in mind when designing the mapping layer.
Strictly speaking, the functions that return a PRNetAddr to the user need not 
make the conversion to Ipv4-mapped Ipv6 addresses. But, one reason to make the 
conversion is for similarity with the native functions on Ipv6 platforms.
srinivas@netscape.com wrotes:
> Strictly speaking, the functions that return a PRNetAddr to the user need not 
> make the conversion to Ipv4-mapped Ipv6 addresses.

I understand that the user can check the raw.family field
of PRNetAddr to determine what kind of address is returned,
but this will force users of our IPv6 API to be aware of IPv4
addresses, which are what this API is trying to hide.

RFC 2553 says:
    The system will use the sockaddr_in6 address structure
    to return addresses to application that are using PF_INET6
    sockets.  The functions that return an address from the
    system to an application are:
      accept()
      recvfrom()
      recvmsg()
      getpeername()
      getsockname()

The behavior of our IPv6 sockets should stay as close to
RFC 2553 as possible.
Checked in the modifications on the NSPRPUB_RELEASE_4_0_BRANCH branch. The 
socket functions accept and return only Ipv4-mapped Ipv6 addresses for 
PR_AF_INET6 sockets.

Files modified:

/cvsroot/mozilla/nsprpub/pr/include/prio.h
new revision: 3.19.4.2; previous revision: 3.19.4.1
/cvsroot/mozilla/nsprpub/pr/include/prnetdb.h
new revision: 3.4.4.1; previous revision: 3.4
/cvsroot/mozilla/nsprpub/pr/src/Makefile
new revision: 3.29.2.2; previous revision: 3.29.2.1
/cvsroot/mozilla/nsprpub/pr/src/io/Makefile
new revision: 3.5.6.1; previous revision: 3.5
/cvsroot/mozilla/nsprpub/pr/src/io/pripv6.c
new revision: 3.2.58.1; previous revision: 3.2
/cvsroot/mozilla/nsprpub/pr/src/io/prsocket.c
new revision: 3.27.4.1; previous revision: 3.27
/cvsroot/mozilla/nsprpub/pr/src/misc/prnetdb.c
new revision: 3.11.4.1; previous revision: 3.11
/cvsroot/mozilla/nsprpub/pr/src/pthreads/ptio.c
new revision: 3.42.4.4; previous revision: 3.42.4.3
/cvsroot/mozilla/nsprpub/pr/tests/cltsrv.c
new revision: 3.8.8.1; previous revision: 3.8
/cvsroot/mozilla/nsprpub/pr/tests/gethost.c
new revision: 3.1.18.1; previous revision: 3.1
I don't understand why you have the #if defined(AIX) around the definition of 
_PR_IN6_IS_ADDR_V4MAPPED() in the case of _PR_INET6.
Removed the "#if defined(AIX)" declaration.
Deleted PR_SetIPv6Enable() and PR_FamilyInet().

Files modified:

/cvsroot/mozilla/nsprpub/pr/include/private/primpl.h
new revision: 3.34.4.3; previous revision: 3.34.4.2
/cvsroot/mozilla/nsprpub/pr/include/prnetdb.h
new revision: 3.4.4.3; previous revision: 3.4.4.2
/cvsroot/mozilla/nsprpub/pr/src/io/prsocket.c
new revision: 3.27.4.2; previous revision: 3.27.4.1
/cvsroot/mozilla/nsprpub/pr/src/md/windows/ntio.c
new revision: 3.20.4.2; previous revision: 3.20.4.1
/cvsroot/mozilla/nsprpub/pr/src/misc/prnetdb.c
new revision: 3.11.4.3; previous revision: 3.11.4.2
/cvsroot/mozilla/nsprpub/pr/src/pthreads/ptio.c
new revision: 3.42.4.5; previous revision: 3.42.4.4
/cvsroot/mozilla/nsprpub/pr/tests/cltsrv.c
new revision: 3.8.8.2; previous revision: 3.8.8.1
/cvsroot/mozilla/nsprpub/pr/tests/gethost.c
new revision: 3.1.18.2; previous revision: 3.1.18.1
/cvsroot/mozilla/nsprpub/pr/tests/ipv6.c
new revision: 3.7.4.1; previous revision: 3.7
/cvsroot/mozilla/nsprpub/pr/tests/provider.c
new revision: 3.6.14.1; previous revision: 3.6
/cvsroot/mozilla/nsprpub/pr/tests/thruput.c
new revision: 3.4.58.1; previous revision: 3.4
/cvsroot/mozilla/nsprpub/pr/tests/tmoacc.c
new revision: 3.4.4.1; previous revision: 3.4
/cvsroot/mozilla/nsprpub/pr/tests/tmocon.c
new revision: 3.7.18.1; previous revision: 3.7
If it wasn't clear from my previous comment, I think Ipv6ToIpv4SocketConnect() 
does the wrong thing if given an AF_INET address.

The ConvertTo*() functions in pripv6.c need to either be static or be prefixed 
with "_pr_".
I think the patch in attachment 4569 [details] doesn't work correctly.
RFC 2553 says,

"Once the application has created a PF_INET6 socket, it must use the 
sockaddr_in6 address structure when passing addresses in to the system."

Ipv6ToIpv4SocketConnect() must fail, when an AF_INET addressed is specified. 
Because only PR_AF_INET6 addresses are passed to ConvertToIpv4NetAddr, 
Ipv4-mapped addresses are not converted to ipv4 addresses.

I will modify ConvertToIpv4NetAddr to process loopback and unspecified 
addresses correctly and modify ConvertToIpv6NetAddr to return Ipv6 addresses 
when the Ipv4 address is a loopback or unspecified value.
AF_INET addresses should not fail with PR_NETWORK_UNREACHABLE_ERROR.  If nothing 
else, that is the wrong error code.

I believe the appropriate error code is
PR_SetError(PR_ADDRESS_NOT_SUPPORTED_ERROR, 0).
(equivalent to the Unix error code EAFNOSUPPORT)
This is fixed in patch 4616.
I'm wondering if we should also map FF02::1 to 255.255.255.255
Patch checked in.

Files modified:

/cvsroot/mozilla/nsprpub/pr/src/io/pripv6.c,v  <--  pripv6.c
new revision: 3.2.58.3; previous revision: 3.2.58.2

/cvsroot/mozilla/nsprpub/pr/src/misc/prnetdb.c,v  <--  prnetdb.c
new revision: 3.11.4.7; previous revision: 3.11.4.6
For non-IPv6 platforms, byte ordering of the loopback address is an issue as the 
PR_NetAddrToString() will incorrectly report _pr_in6addr_loopback as "::100"

The #ifdef _PR_INET6 in PR_SetNetAddr() is no longer needed.  PR_SetNetAddr() 
should probably initialize the flowinfo and scope_id fields to 0.
Yes, the byte-ordering for the loopback address is incorrect. Fixed checked in.
Also addednew function, PR_ConvertIpv4AddrToIpv6.

Files modified:

/cvsroot/mozilla/nsprpub/pr/include/prio.h, rev  3.19.4.5
/cvsroot/mozilla/nsprpub/pr/include/prnetdb.h, rev 3.4.4.5
/cvsroot/mozilla/nsprpub/pr/src/misc/prnetdb.c, rev 3.11.4.8
/cvsroot/mozilla/nsprpub/pr/tests/gethost.c, rev 3.1.18.4
I don't think we should convert 127.0.0.1 to ::1 when mapping from a V4 address 
to a V6 address.  IPv6 native implementations will report a v4 connection from 
the loopback address as ::ffff:127.0.0.1, the mapping layer should do the same.

I do agree with converting 0.0.0.0 to ::


I agree that the loopback addresses should be converted to ::ffff:127.0.0.1
Fix checked in.

Files modified:
/cvsroot/mozilla/nsprpub/pr/src/io/pripv6.c,v  <--  pripv6.c
new revision: 3.2.58.6; previous revision: 3.2.58.5
/cvsroot/mozilla/nsprpub/pr/src/misc/prnetdb.c,v  <--  prnetdb.c
new revision: 3.11.4.12; previous revision: 3.11.4.11
PR_Accept(fd, NULL, timeout) crashes on Linux
because _PR_INET6 is defined and pt_Accept()
dereferences a NULL 'addr' when mapping AF_INET6
to PR_AF_INET6.  I fixed this on NSPRPUB_RELEASE_4_0_BRANCH.

/cvsroot/mozilla/nsprpub/pr/src/pthreads/ptio.c, revision 3.42.4.12

pt_RecvFrom, pt_GetSockName, pt_GetPeerName may also need
to be fixed in the same way, especially pt_RecvFrom.
It doesn't make sense to pass a null 'addr' argument
to PR_GetSockName or PR_GetPeerName.  It may be legal
to pass a null 'addr' to PR_RecvFrom.
I added tests for a null 'addr' argument in the
various accept, acceptread, and recvfrom functions.
The 'addr' argument to these functions can be null.
For getsockname and getpeername, if a null 'addr' is
passed, the system call should fail with EFAULT, so
we don't need to test for that ourselves.

In prsocket.c, declare the local variable 'addrCopy'.

These fixes are checked in on NSPRPUB_RELEASE_4_0_BRANCH.
/cvsroot/mozilla/nsprpub/pr/src/io/prsocket.c, revision 3.27.4.6
/cvsroot/mozilla/nsprpub/pr/src/pthreads/ptio.c, revision 3.42.4.13
The macro PR_NetAddrInetPort needs to be modified to check for the PR_AF_INET6 
platforms on all platforms.

Fix checked in:

/cvsroot/mozilla/nsprpub/pr/include/prnetdb.h
new revision: 3.4.4.6; previous revision: 3.4.4.5

Marking the bug fixed.
Status: ASSIGNED → RESOLVED
Closed: 25 years ago
Resolution: --- → FIXED
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Creator:
Created:
Updated:
Size: