netdev
[Top] [All Lists]

tcp_ipv6_check_established

To: netdev@xxxxxxxxxxx
Subject: tcp_ipv6_check_established
From: Mark Huth <mhuth@xxxxxxxxxx>
Date: Tue, 11 May 2004 16:37:08 -0700
Sender: netdev-bounce@xxxxxxxxxxx
User-agent: Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.0.1) Gecko/20020823 Netscape/7.0
There appears to be a long-standing bug in tcp_ipv6_check_established that results in the return of EADDRNOTAVAILABLE from connect(). It can be demonstrated in the following scenario:

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

<Prev in Thread] Current Thread [Next in Thread>