proxy-arp & mpd

Damien Deville damien.deville at netasq.com
Wed Jul 23 15:29:55 UTC 2008


Hi,

after some more tests here is what i came to (patch provided is for 
freebsd 6.3 but can be adapted for other versions): it is a dirty hack 
and might not be the right solution but it is working in the case i 
described earlier and i hope it will help discussing the issue.

It seems that the process that block read all entries available in the 
PF_ROUTE socket, do not find the one it is looking for and ends blocked 
on the PF_ROUTE socket as no more entries are available after reading 
and entry with rtm->rtm_pid == 0 and rtm->rtm_seq == 0.

Damien

Oleksandr Samoylyk wrote:
> Damien Deville wrote:
>> Hi,
>>
>> we are facing a similar issue with arp blocked in sbwait state.
>>
>> Here is a way to reproduce it:
>> - add a bunch of arp entries in your arp table (best is around 255 
>> entries).
>> - launch two arp -a -d in parallel ('arp -a -d & arp -a -d &')
>>
>> Both processes will be in concurence to access the table. One process 
>> will successfully nuke all entries of the arp table, the other one 
>> will be blocked in rtmsg function on the read while executing a 
>> RTM_GET or RTM_DELETE command after some time. By instrumenting arp we 
>> noticed that it happened when both process access to the same entry.
>>
>> Here is a backtrace of the blocked arp on FreeBSD 7.0
>>
>> (gdb) bt
>> #0  0x28158f81 in read () from /lib/libc.so.7
>> #1  0x08049091 in rtmsg ()
>> #2  0x08049b44 in delete ()
>> #3  0x0804a1fd in nuke_entry ()
>> #4  0x08049a77 in search ()
>> #5  0x08049e75 in main ()
>>
>> I can reproduce this on FreeBSD 4.11, 6.2 and 6.3, and FreeBSD 7.0.
> 
> Any workaround so far?
> 

-- 
Damien Deville
R&D engineer
damien.deville at netasq.com
http://www.netasq.com

NETASQ - We secure IT
-------------- next part --------------
--- arp.c.orig	2006-10-21 07:43:29.000000000 +0200
+++ arp.c	2008-07-23 10:41:44.000000000 +0200
@@ -706,17 +706,28 @@
 	l = rtm->rtm_msglen;
 	rtm->rtm_seq = ++seq;
 	rtm->rtm_type = cmd;
 	if ((rlen = write(s, (char *)&m_rtmsg, l)) < 0) {
 		if (errno != ESRCH || cmd != RTM_DELETE) {
 			warn("writing to routing socket");
 			return (NULL);
 		}
 	}
 	do {
 		l = read(s, (char *)&m_rtmsg, sizeof(m_rtmsg));
+		if ( l > 0 && rtm->rtm_seq == 0 && rtm->rtm_pid == 0 )
+			return (NULL); /* something weird happened */
 	} while (l > 0 && (rtm->rtm_seq != seq || rtm->rtm_pid != pid));
 	if (l < 0)
 		warn("read from routing socket");
 	return (rtm);
 }
 


More information about the freebsd-net mailing list