* Re: [Fwd: Problem with dual IPv4/IPv6 connect]
[not found] ` <Pine.LNX.4.61.0411190904580.6216@netcore.fi>
@ 2004-11-19 18:43 ` Tom Marshall
2004-11-19 18:57 ` YOSHIFUJI Hideaki / 吉藤英明
0 siblings, 1 reply; 2+ messages in thread
From: Tom Marshall @ 2004-11-19 18:43 UTC (permalink / raw)
To: Pekka Savola; +Cc: davem, yoshfuji, netdev
[-- Attachment #1.1: Type: text/plain, Size: 2352 bytes --]
> I'd suggest you resend it to netdev, but also attach a minimal,
> trivial test case .c file which allows anyone to easily experiment
> with the behaviour, test a fix, etc.
Recap of the issue:
s = socket(AF_INET6, SOCK_STREAM, 0)
connect(s, [fec0::203:baff:fe88:5a15]:1554) => EINPROGRESS
Put socket in select's write set
Kernel sends TCPv6 SYN
Kernel receives ICMPv6 Time Exceeded (routing error)
Socket becomes writable
getsockopt(s, SO_ERROR) => EHOSTUNREACH
connect(s, [:ffff:192.168.168.241]:1554) => ECONNABORTED
Okay I've attached a fairly small repro. Sorry it's not smaller but it
takes a few lines of code to do the required setup. The trickier part of
the setup is probably getting a ICMPv6 Time Exceeded error. My particular
setup was using vtun for an IPv6 route through a dumb switch and a bogus
route on the remote vtun endpoint, but there are surely other ways to get
this error.
The app expects you to specify an IPv6 address, an IPv4 address (glibc's
inet_pton requires it be in V4MAPPED form), a port, and a nonblocking value.
The addresses don't necessarily need to be for the same host.
Results for kernel 2.6.9 and 2.6.10-rc2 are the same, as follows:
$ gcc -Wall -o dualconnect dualconnect.c
$ ./dualconnect fec0::203:baff:fe88:5a15 ::ffff:192.168.168.241 22 1
async connect to fec0::203:baff:fe88:5a15 returned No route to host
sync connect to ::ffff:192.168.168.241 returned Software caused connection abort
async connect to ::ffff:192.168.168.241 returned Success
$ ./dualconnect fec0::203:baff:fe88:5a15 ::ffff:192.168.168.241 22 0
sync connect to fec0::203:baff:fe88:5a15 returned No route to host
sync connect to ::ffff:192.168.168.241 returned No route to host
sync connect to ::ffff:192.168.168.241 returned Transport endpoint is already connected
In the nonblocking case (which we use, and prompted the report), the socket
appears to correct its internal state and the second IPv4 connect succeeds.
In the blocking case, the socket appears to actually connect even though it
reports an error. I just discovered this today because I was hoping to get
a smaller repro by avoiding using select. :-/
--
Don't get suckered in by the comments -- they can be terribly misleading.
Debug only code.
-- Dave Storer
[-- Attachment #1.2: dualconnect.c --]
[-- Type: text/x-csrc, Size: 2189 bytes --]
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
int
do_connect(int s, const char* destaddr, unsigned short destport)
{
struct sockaddr_in6 sa;
socklen_t len;
int rc;
len = sizeof(struct sockaddr_in6);
memset(&sa, 0, len);
sa.sin6_family = AF_INET6;
if (inet_pton(AF_INET6, destaddr, &sa.sin6_addr) <= 0)
{
printf("inet_pton failed\n");
exit(1);
}
sa.sin6_port = htons(destport);
rc = connect(s, (struct sockaddr*)&sa, len);
if (rc == -1 && errno == EINPROGRESS)
{
fd_set fds;
FD_ZERO(&fds);
FD_SET(s, &fds);
do
{
rc = select(s+1, NULL, &fds, NULL, NULL);
}
while (rc == -1 && errno == EINTR);
if (rc != 1)
{
printf("select failed\n");
exit(1);
}
len = sizeof(rc);
if (getsockopt(s, SOL_SOCKET, SO_ERROR, &rc, &len) != 0)
{
printf("get SO_ERROR failed\n");
exit(1);
}
printf("async connect to %s returned %s\n", destaddr, strerror(rc));
return rc;
}
printf("sync connect to %s returned %s\n", destaddr, strerror(errno));
return errno;
}
int
main(int argc, char** argv)
{
int s;
int rc;
int tmp;
if (argc != 5)
{
printf("usage: %s <host6> <host4> <port> <NB>\n", argv[0]);
exit(1);
}
s = socket(AF_INET6, SOCK_STREAM, 0);
if (s == -1)
{
perror("socket");
exit(1);
}
tmp = atoi(argv[4]);
ioctl(s, FIONBIO, &tmp);
/* attempt v6 connect, verify EHOSTUNREACH */
rc = do_connect(s, argv[1], atoi(argv[3]));
if (rc == 0)
{
exit(1);
}
/* attempt v4 connect, 2.6.x returns ECONNABORTED */
rc = do_connect(s, argv[2], atoi(argv[3]));
if (rc == 0)
{
exit(1);
}
/* retry, verify success */
rc = do_connect(s, argv[2], atoi(argv[3]));
if (rc == 0)
{
exit(1);
}
close(s);
return 0;
}
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: [Fwd: Problem with dual IPv4/IPv6 connect]
2004-11-19 18:43 ` [Fwd: Problem with dual IPv4/IPv6 connect] Tom Marshall
@ 2004-11-19 18:57 ` YOSHIFUJI Hideaki / 吉藤英明
0 siblings, 0 replies; 2+ messages in thread
From: YOSHIFUJI Hideaki / 吉藤英明 @ 2004-11-19 18:57 UTC (permalink / raw)
To: tmarshall; +Cc: pekkas, davem, netdev, yoshfuji
In article <20041119184328.GB3396@real.com> (at Fri, 19 Nov 2004 10:43:29 -0800), Tom Marshall <tmarshall@real.com> says:
> > I'd suggest you resend it to netdev, but also attach a minimal,
> > trivial test case .c file which allows anyone to easily experiment
> > with the behaviour, test a fix, etc.
>
> Recap of the issue:
>
> s = socket(AF_INET6, SOCK_STREAM, 0)
> connect(s, [fec0::203:baff:fe88:5a15]:1554) => EINPROGRESS
> Put socket in select's write set
> Kernel sends TCPv6 SYN
> Kernel receives ICMPv6 Time Exceeded (routing error)
> Socket becomes writable
> getsockopt(s, SO_ERROR) => EHOSTUNREACH
(*)
> connect(s, [:ffff:192.168.168.241]:1554) => ECONNABORTED
At the point of (*), the state of socket if undefined.
you need to create another socket to connect another peer.
--yoshfuji
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2004-11-19 18:57 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <20041118184950.GB3972@real.com>
[not found] ` <Pine.LNX.4.61.0411190904580.6216@netcore.fi>
2004-11-19 18:43 ` [Fwd: Problem with dual IPv4/IPv6 connect] Tom Marshall
2004-11-19 18:57 ` YOSHIFUJI Hideaki / 吉藤英明
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).