Most recent edit on 2006-07-12 21:38:33 by FreekDijkstra
Additions:
Here is a short kernel patch, which makes a linux kernel broadcast ARP replies, if they concern link-local (zerconf IP addresses). The patch was written by David Daney for a 2.6.16.1 kernel, but also succesfully applied to a 2.6.8 and even a 2.4.27 kernel (apparently, the arp.c code doesn't change much these days). It was based on a earlier patch∞ by FreekDijkstra.
# apply using cd linux-2.6.16.1 ; patch -p0 < ipv4ll.patch
net/ipv4/arp.c.orig 2006-03-31 13:44:50.000000000 -0800
+ net/ipv4/arp.c 2006-04-05 13:33:19.000000000 -0700
-690,6 +690,11
void arp_send(int type, int ptype, u32 d
if (dev->flags&IFF_NOARP)
return;
+ /* If link local address (169.254.0.0/16) we must broadcast
+ * the ARP packet. See RFC 3927 section 2.5 for details. */
+ if ((src_ip & htonl(0xFFFF0000UL)) htonl(0xA9FE0000UL))
+ dest_hw = NULL;
+
skb = arp_create(type, ptype, dest_ip, dev, src_ip,
dest_hw, src_hw, target_hw);
if (skb
NULL)
This patch was extensively∞ discussed∞ on the netdev mailing list for network related Linux kernel development, but so far not picked up upstream.
Deletions:
Here is a short kernel patch, which makes a linux kernel broadcast ARP replies, if they concern link-local (zerconf IP addresses). The patch was written by FreekDijkstra for a 2.6.13 kernel, but also succesfully applied to a 2.6.8 and even a 2.4.27 kernel (apparently, the arp.c code doesn't change much these days):
# apply using cd linux-2.6.13 ; patch -p0 < ipv4ll.patch
net/ipv4/arp.c 2005-08-29 01:41:01.000000000 +0200
+ net/ipv4/arp.c.new 2005-09-13 09:48:23.000000000 +0200
-851,8 +851,18
static int arp_process(struct sk_buff *s
dont_send |= arp_ignore(in_dev,dev,sip,tip);
if (!dont_send && IN_DEV_ARPFILTER(in_dev))
dont_send |= arp_filter(sip,tip,dev);
- if (!dont_send)
- arp_send(ARPOP_REPLY,ETH_P_ARP,sip,dev,tip,sha,dev->dev_addr,sha);
+ if (!dont_send) {
+ /* special case: broadcast ARP replies when sender ip is a IPv4 link-local address (RFC3927) */
+ sourcec ip (sip) is in network byte order. make sure so is llprefix, so memcmp() works correctly.
+ u16 llprefix = htons(0xA9FE); 169.254.0.0/16
+ if (!memcmp(&sip, &llprefix, 2)) {
+ printk(KERN_INFO "arp: source IP 0x%X is link-local. broadcast arp reply\n", ntohl(sip));
+ arp_send(ARPOP_REPLY,ETH_P_ARP,sip,dev,tip,NULL,dev->dev_addr,NULL);
+ } else {
+ printk(KERN_INFO "arp: source IP 0x%X is not link-local. unicast arp reply\n", ntohl(sip));
+ arp_send(ARPOP_REPLY,ETH_P_ARP,sip,dev,tip,sha,dev->dev_addr,sha);
+ }
+ }
neigh_release(n);
}
I'm sure this code could be more efficient (you could probably do a bitshift and a simple comparison as well). However, I'm slightly more certain this code will work on all platforms (big-endian and little-endian), so I leave the optimization to someone else.
Edited on 2005-09-30 02:35:30 by FreekDijkstra
Additions:
Measurements
machines:
- Mac, OS 10.4
- Linux with patched kernel
Seperate network, give Mac same (fixed) IP as Linux. Join. Linux should reconfigure, but indeed the Mac complains and refuses to join the network.
Other problems include that computers are indeed reconfigured, but the reverse lookup still is to the older hosts, giving incorrect results from an end-user persepctive.
Edited on 2005-09-21 13:28:43 by FreekDijkstra
Additions:
I'm sure this code could be more efficient (you could probably do a bitshift and a simple comparison as well). However, I'm slightly more certain this code will work on all platforms (big-endian and little-endian), so I leave the optimization to someone else.
Edited on 2005-09-21 13:25:34 by FreekDijkstra
Additions:
Kernel Patch
Here is a short kernel patch, which makes a linux kernel broadcast ARP replies, if they concern link-local (zerconf IP addresses). The patch was written by FreekDijkstra for a 2.6.13 kernel, but also succesfully applied to a 2.6.8 and even a 2.4.27 kernel (apparently, the arp.c code doesn't change much these days):
# apply using cd linux-2.6.13 ; patch -p0 < ipv4ll.patch
--- net/ipv4/arp.c 2005-08-29 01:41:01.000000000 +0200
+++ net/ipv4/arp.c.new 2005-09-13 09:48:23.000000000 +0200
@@ -851,8 +851,18 @@ static int arp_process(struct sk_buff *s
dont_send |= arp_ignore(in_dev,dev,sip,tip);
if (!dont_send && IN_DEV_ARPFILTER(in_dev))
dont_send |= arp_filter(sip,tip,dev);
- if (!dont_send)
- arp_send(ARPOP_REPLY,ETH_P_ARP,sip,dev,tip,sha,dev->dev_addr,sha);
+ if (!dont_send) {
+ /* special case: broadcast ARP replies when sender ip is a IPv4 link-local address (RFC3927) */
+ // sourcec ip (sip) is in network byte order. make sure so is llprefix, so memcmp() works correctly.
+ u16 llprefix = htons(0xA9FE); // 169.254.0.0/16
+ if (!memcmp(&sip, &llprefix, 2)) {
+ // printk(KERN_INFO "arp: source IP 0x%X is link-local. broadcast arp reply\n", ntohl(sip));
+ arp_send(ARPOP_REPLY,ETH_P_ARP,sip,dev,tip,NULL,dev->dev_addr,NULL);
+ } else {
+ // printk(KERN_INFO "arp: source IP 0x%X is not link-local. unicast arp reply\n", ntohl(sip));
+ arp_send(ARPOP_REPLY,ETH_P_ARP,sip,dev,tip,sha,dev->dev_addr,sha);
+ }
+ }
neigh_release(n);
}
Edited on 2005-09-21 13:19:15 by FreekDijkstra
Additions:
Categories
CategoryZeroconf
Edited on 2005-06-09 16:48:55 by FreekDijkstra [results for 2.6 kernel]
Additions:
With statically configured link-local addresses: unicasted
Linux 2.6.6 and 2.6.8 kernels
With statically configured link-local addresses: unicasted
Deletions:
Linux 2.6 kernel
Edited on 2005-04-27 18:56:39 by FreekDijkstra [First results]
Additions:
Mac OS 10.3.9
Deletions:
Mac OS 10.3
Edited on 2005-04-27 18:56:20 by FreekDijkstra
Additions:
Setup
Take three nodes, and put them in a LAN, without external connectivity.
Configure either link-local (169.254/16) or private (10/8) IP addresses on the hosts.
Make sure the ARP cache is empty (for example do arp -d -a -n), check with arp -a -n (the -n makes sure no resolving is done, since that may generate an ARP request).
Do a single connection request, for example using ping -c 1 <IP of host 2> and check with ethereal or tcpdump arp if the ARP replies are unicasted or broadcasted. You can check by either decoding the ARP packet with ethereal or by just checking if host 3 sees the packet or not.
Linux 2.4.26 kernel
With private addresses: unicasted
With private addresses: unicasted
With statically configured link-local addresses: broadcasted
With bootpd automatically configured link-local addresses: broadcasted
Deletions:
Linux 2.4 kernel
Oldest known version of this page was edited on 2005-04-27 08:32:49 by FreekDijkstra [preliminary page]
Page view:
Link-Local ARP Measurements
RFC 3927∞ (
IPv4 Link-Local Adressing) specifies that not just ARP requests, but also ARP replies must be broadcasted. This helps in identifying duplicate IP addresses, which is particularly usefull in LAN which use link-local IP addresses (169.254/16). These test are meant to measure normal ARP behaviour, identify when that normal behaviour is indeed a problem, and which kernels support broadcasting ARP replies, and if they broadcast all ARP replies or just those with link-local IP addresses in the body.
Generic ARP Behaviour Tests
describe set-up (with three hosts)
Description of Problem Scenario's
Link-Local ARP Behaviour Tests
Linux 2.4 kernel
Linux 2.6 kernel
Mac OS 10.3