• Simon Kelley's avatar
    [NEIGH]: Fix IP-over-ATM and ARP interaction. · bd89efc5
    Simon Kelley authored
    The classical IP over ATM code maintains its own IPv4 <-> <ATM stuff>
    ARP table, using the standard neighbour-table code. The
    neigh_table_init function adds this neighbour table to a linked list
    of all neighbor tables which is used by the functions neigh_delete()
    neigh_add() and neightbl_set(), all called by the netlink code.
    
    Once the ATM neighbour table is added to the list, there are two
    tables with family == AF_INET there, and ARP entries sent via netlink
    go into the first table with matching family. This is indeterminate
    and often wrong.
    
    To see the bug, on a kernel with CLIP enabled, create a standard IPv4
    ARP entry by pinging an unused address on a local subnet. Then attempt
    to complete that entry by doing
    
    ip neigh replace <ip address> lladdr <some mac address> nud reachable
    
    Looking at the ARP tables by using 
    
    ip neigh show
    
    will reveal two ARP entries for the same address. One of these can be
    found in /proc/net/arp, and the other in /proc/net/atm/arp.
    
    This patch adds a new function, neigh_table_init_no_netlink() which
    does everything the neigh_table_init() does, except add the table to
    the netlink all-arp-tables chain. In addition neigh_table_init() has a
    check that all tables on the chain have a distinct address family.
    The init call in clip.c is changed to call
    neigh_table_init_no_netlink().
    
    Since ATM ARP tables are rather more complicated than can currently be
    handled by the available rtattrs in the netlink protocol, no
    functionality is lost by this patch, and non-ATM ARP manipulation via
    netlink is rescued. A more complete solution would involve a rtattr
    for ATM ARP entries and some way for the netlink code to give
    neigh_add and friends more information than just address family with
    which to find the correct ARP table.
    
    [ I've changed the assertion checking in neigh_table_init() to not
      use BUG_ON() while holding neigh_tbl_lock.  Instead we remember that
      we found an existing tbl with the same family, and after dropping
      the lock we'll give a diagnostic kernel log message and a stack dump.
      -DaveM ]
    Signed-off-by: default avatarSimon Kelley <simon@thekelleys.org.uk>
    Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
    bd89efc5
clip.c 24.7 KB