zcip, link-local ARP responses
Sebastian Fett
db_extern at gmx.de
Wed Aug 12 07:01:59 UTC 2015
Am 04.08.2015 um 14:36 schrieb Denys Vlasenko:
> On Tue, Aug 4, 2015 at 12:00 PM, Sebastian Fett <db_extern at gmx.de> wrote:
>>> On Tue, Jul 21, 2015 at 2:03 PM, dbextern <db_extern at gmx.de> wrote:
>>>> For our link local functionality I'm using udhcpc together with zcip out
>>>> of busybox on a Blackfin BF-537 CPU without MMU.
>>>>
>>>> The base functionality is there.
>>>> But when I connect two networks with stable IP addresses, and both
>>>> networks had the same IP(s) in them, the conflict stays unresolved.
>>>> My setup is one master PC or MAC and several embedded boards.
>>>>
>>>> What I would expect (following RFC3927
>>>> https://tools.ietf.org/html/rfc3927#page-10[https://3c.gmx.net/mail/client/dereferrer?redirectUrl=https%3A%2F%2Ftools.ietf.org%2Fhtml%2Frfc3927%23page-10];
>>>> chapter 2.x and 4) is that after a while the ARP messages will resolve the
>>>> problem because the still running zcip sees ARP responses on it's own IP and
>>>> reacts accordingly.
>>>> What really happens is:
>>>> * Windows only sends broadcast ARP requests as long as it never got an
>>>> answer. After that there is only unicast. And the requested device answers
>>>> with a unicast as well.
>>>> * the MAC always sends broadcasts. And both embedded devices with the
>>>> conflicting IP answer. But with a unicast ARP reply to the MAC.
>>>>
>>>> As I understand the specification (last paragraph in chapter 2.5) then
>>>> all ARP messages between devices with link local addresses should be link
>>>> layer broadcasts.
>>>> Did I get that right? And if yes, why does zcip not follow that rule?
>>>
>>>
>>> zcip does use bcast for all packets it sends:
>>>
>>> # tcpdump -nliwlan0 -s0 -vv -e arp
>>> tcpdump: listening on wlan0, link-type EN10MB (Ethernet), capture size
>>> 65535 bytes
>>> <zcip runs>
>>> 02:49:51.078369 00:04:e2:64:23:c2 > ff:ff:ff:ff:ff:ff, ethertype ARP
>>> (0x0806), length 42: arp who-has 169.254.194.171 tell 0.0.0.0
>>> 02:49:52.391711 00:04:e2:64:23:c2 > ff:ff:ff:ff:ff:ff, ethertype ARP
>>> (0x0806), length 42: arp who-has 169.254.194.171 tell 0.0.0.0
>>> 02:49:54.254628 00:04:e2:64:23:c2 > ff:ff:ff:ff:ff:ff, ethertype ARP
>>> (0x0806), length 42: arp who-has 169.254.194.171 tell 0.0.0.0
>>> 02:49:55.305731 00:04:e2:64:23:c2 > ff:ff:ff:ff:ff:ff, ethertype ARP
>>> (0x0806), length 42: arp who-has 169.254.194.171 (00:04:e2:64:23:c2)
>>> tell 169.254.194.171
>>> 02:49:57.307788 00:04:e2:64:23:c2 > ff:ff:ff:ff:ff:ff, ethertype ARP
>>> (0x0806), length 42: arp who-has 169.254.194.171 (00:04:e2:64:23:c2)
>>> tell 169.254.194.171
>>> 02:49:59.309844 00:04:e2:64:23:c2 > ff:ff:ff:ff:ff:ff, ethertype ARP
>>> (0x0806), length 42: arp who-has 169.254.194.171 (00:04:e2:64:23:c2)
>>> tell 169.254.194.171
>>
>>
>> Thanks for looking into that.
>>
>> These are the probing and announcement messages from zcip. They need to be
>> and are bcasts.
>> What it does not do is answer normal ARP requests with a broadcast. Which is
>> specified in RCF3927 as the right thing to do.
>
> Looking at the code, it should answer to them:
>
> // packets arriving, or link went down
> case 1:
> ...
> switch (state) {
> ... case MONITOR:
> // If a conflict, we try to defend
> with a single ARP probe.
> if (source_ip_conflict) {
> VDBG("monitor conflict -- defending\n");
> state = DEFEND;
> timeout_ms = DEFEND_INTERVAL * 1000;
> arp(/* ARPOP_REQUEST, */
> /* ð_addr, */ ip,
> ð_addr, ip);
> }
> break;
>
> The call to arp() in the code snippet above should send a broadcast
> ARP probe.
>
That was my first thought, too. But this only resolves the problem when
another device does it's probing.
What I needed was a bcast answer to a general ARP request.
This is the patch I use. It's not tidy and the comments are in german,
sorry.
And the result of this ist that the devices answers to an ARP request
twice. A bcast from zcip and a unicast from the kernel. Not really nice,
but acceptable in my usecase.
--- a/networking/zcip.c 2015-07-21 15:10:45.047362400 +0200
+++ c/networking/zcip.c 2015-07-22 14:44:13.280779500 +0200
@@ -117,12 +117,12 @@
* Broadcast an ARP packet.
*/
static void arp(
- /* int op, - always ARPOP_REQUEST */
+ int op, /*- always ARPOP_REQUEST */
/* const struct ether_addr *source_eth, - always ð_addr */
struct in_addr source_ip,
const struct ether_addr *target_eth, struct in_addr target_ip)
{
- enum { op = ARPOP_REQUEST };
+// enum { op = ARPOP_REQUEST }; //wir uebergeben wieder von aussen
#define source_eth (ð_addr)
struct arp_packet p;
@@ -348,6 +348,7 @@
struct arp_packet p;
int source_ip_conflict;
int target_ip_conflict;
+ int bcast_arp_response;
fds[0].fd = sock_fd;
fds[0].events = POLLIN;
@@ -385,7 +386,7 @@
nprobes, argv_intf, inet_ntoa(ip));
timeout_ms = PROBE_MIN * 1000;
timeout_ms += random_delay_ms(PROBE_MAX - PROBE_MIN);
- arp(/* ARPOP_REQUEST, */
+ arp( ARPOP_REQUEST, /**/
/* ð_addr, */ null_ip,
&null_addr, ip);
}
@@ -396,7 +397,7 @@
VDBG("announce/%u %s@%s\n",
nclaims, argv_intf, inet_ntoa(ip));
timeout_ms = ANNOUNCE_INTERVAL * 1000;
- arp(/* ARPOP_REQUEST, */
+ arp(ARPOP_REQUEST, /* */
/* ð_addr, */ ip,
ð_addr, ip);
}
@@ -409,7 +410,7 @@
VDBG("announce/%u %s@%s\n",
nclaims, argv_intf, inet_ntoa(ip));
timeout_ms = ANNOUNCE_INTERVAL * 1000;
- arp(/* ARPOP_REQUEST, */
+ arp( ARPOP_REQUEST, /**/
/* ð_addr, */ ip,
ð_addr, ip);
break;
@@ -421,7 +422,7 @@
VDBG("announce/%u %s@%s\n",
nclaims, argv_intf, inet_ntoa(ip));
timeout_ms = ANNOUNCE_INTERVAL * 1000;
- arp(/* ARPOP_REQUEST, */
+ arp( ARPOP_REQUEST, /**/
/* ð_addr, */ ip,
ð_addr, ip);
}
@@ -519,6 +520,7 @@
source_ip_conflict = 0;
target_ip_conflict = 0;
+ bcast_arp_response = 0;
if (memcmp(&p.arp.arp_sha, ð_addr, ETH_ALEN) != 0) {
if (memcmp(p.arp.arp_spa, &ip.s_addr, sizeof(struct in_addr)) == 0) {
@@ -526,13 +528,20 @@
source_ip_conflict = 1;
}
if (p.arp.arp_op == htons(ARPOP_REQUEST)
- && memcmp(p.arp.arp_spa, &null_ip, sizeof(struct in_addr)) == 0
&& memcmp(p.arp.arp_tpa, &ip.s_addr, sizeof(struct in_addr)) == 0
) {
- /* A probe with source_ip == 0.0.0.0, target_ip == chosen ip:
- * another host trying to claim this ip!
- */
- target_ip_conflict = 1;
+
+ if ( memcmp(p.arp.arp_spa, &null_ip, sizeof(struct in_addr)) == 0
) //Probe eines anders LL Geraetes
+ {
+ /* A probe with source_ip == 0.0.0.0, target_ip == chosen ip:
+ * another host trying to claim this ip!
+ */
+ target_ip_conflict = 1;
+ }
+ else //normaler ARP Request an meine Adresse, wir Antworten mit
BCast ARP Response
+ {
+ bcast_arp_response = 1;
+ }
}
}
@@ -564,7 +573,13 @@
VDBG("monitor conflict -- defending\n");
state = DEFEND;
timeout_ms = DEFEND_INTERVAL * 1000;
- arp(/* ARPOP_REQUEST, */
+ arp( ARPOP_REQUEST, /**/
+ /* ð_addr, */ ip,
+ ð_addr, ip);
+ }
+ else if (bcast_arp_response)//no conflict --> send broadcast arp
response
+ {
+ arp( ARPOP_REPLY, /**/
/* ð_addr, */ ip,
ð_addr, ip);
}
More information about the busybox
mailing list