Bug#17885: DHCP breaks other interfaces

Phil Karn (karn@ka9q.ampr.org)
Thu, 5 Feb 1998 23:15:24 -0800 (PST)


Package: kernel-source-2.0.32
Version: 2.0.32-1

The symptom:

On a machine with multiple interfaces, starting a DHCP client on one
interface breaks all other interfaces until the DHCP client
successfully binds to an address.

On further investigation, I noticed that the other interfaces weren't
actually disabled. But while the DHCP client was negotiating an
address, all packets leaving the other interfaces have the originating
interface's Ethernet address in the *destination* field -- so the
hosts they're intended for never see them.

The bug:

The problem is an unintended consequence of code in
net/ipv4/devinet.c, function ip_chk_addr, lines 120-126. This function
ordinarily takes an IP address and returns IS_BROADCAST, IS_MYADDR or
0. But when an interface (any interface) is configured to IP address
0.0.0.0 (as it is during DHCP resolution), this function returns
IS_MYADDR instead of 0 for any arbitrary non-broadcast address. This
is intended to cause the calls to ip_chk_addr on line 437 and 439 of
net/ipv4/ip_input.c to return IS_MYADDR during DHCP resolution so that
the response packets from the DHCP server will be accepted regardless
of their IP destination address.

But this code has an unintended side effect. It causes the ARP
machinery to resolve *all* outbound packets (regardless of interface)
to the local Ethernet address instead of the correct one. This is what
breaks the other interfaces.

The fix:

Remove lines 120-126 of net/ipv4/devinet.c.

Change lines 437 and 439 of net/ipv4/ip_input.c as follows to accept
any destination address in an incoming packet as being directed to us
whenever the IP address configured for the receiving interface is
0.0.0.0:

if ( iph->daddr == skb->dev->pa_addr || skb->redirport || dev->pa_addr == 0 || (brd = ip_chk_addr(iph->daddr)) != 0 || ip_chksock(skb))
#else
if ( iph->daddr == skb->dev->pa_addr || dev->pa_addr == 0 || (brd = ip_chk_addr(iph->daddr)) != 0)

Discussion:

This is arguably the right thing to do. This code treats an interface
IP address of 0.0.0.0 as "promiscuous" for the purposes of DHCP without
affecting the operation of any other interface on the machine.

Phil

----- End of forwarded message from Phil Karn -----

-- 
Debian GNU/Linux 1.3 is out! ( http://www.debian.org/ )
Email:  Herbert Xu ~{PmV>HI~} <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu