Forwarding this to usagi due to underwhelming response from netdev.
The following scenario fails in most known ipv6 linuxes
All within a single node.
Host has two IPv6 addresses: dead:dead:dead:dead::1/128 dead:dead:dead:dead::2/128
Application A creates two listening sockets: dead:dead:dead:dead::1 49997 dead:dead:dead:dead::2 49997
Application B creates a TCP-connection: from dead:dead:dead:dead::1 49998 to dead:dead:dead:dead::2 49997
Application C creates a TCP-connection: from dead:dead:dead:dead::2 49998 to dead:dead:dead:dead::1 49997
However, the latter operation fails, and connect() returns EADDRNOTAVAILABLE. Meaning that the host already has such a connection and the new one cannot be created. Clearly there is no identical connection used (different ports), thus connect() misbehaves.
All sockets use SO_REUSEADDR-option, and all sockets bind() their source address and source ports before the attempted connect().
While the above may be somewhat contrived, the code is wrong by inspection. The check for the established connections interates on sk2, while the macro argument for TCP_IPV6_MATCH is sk. Thus the check result is invarient over the loop.
A proposed patch for 2.6.6 is attached. A similar patch is required for 2.4 kernels, and is also attached.
Mark Huth
Attachment:
tcp_ipv6_check_est-2.6.6.patch
Description: Binary data
Attachment:
tcp_ipv6_check_est-2.4.20.patch
Description: Binary data