From f609e1ae48b25702b91f73d6ccb1cfefcf5a4d5f Mon Sep 17 00:00:00 2001 From: glebius Date: Fri, 9 Sep 2005 10:06:27 +0000 Subject: [PATCH] - Do not hold route entry lock, when calling arprequest(). One such call was introduced by me in 1.139, the other one was present before. - Do all manipulations with rtentry and la before dropping the lock. - Copy interface address from route into local variable before dropping the lock. Supply this copy as argument to arprequest() LORs fixed: http://sources.zabbadoz.net/freebsd/lor/003.html http://sources.zabbadoz.net/freebsd/lor/037.html http://sources.zabbadoz.net/freebsd/lor/061.html http://sources.zabbadoz.net/freebsd/lor/062.html http://sources.zabbadoz.net/freebsd/lor/064.html http://sources.zabbadoz.net/freebsd/lor/068.html http://sources.zabbadoz.net/freebsd/lor/071.html http://sources.zabbadoz.net/freebsd/lor/074.html http://sources.zabbadoz.net/freebsd/lor/077.html http://sources.zabbadoz.net/freebsd/lor/093.html http://sources.zabbadoz.net/freebsd/lor/135.html http://sources.zabbadoz.net/freebsd/lor/140.html http://sources.zabbadoz.net/freebsd/lor/142.html http://sources.zabbadoz.net/freebsd/lor/145.html http://sources.zabbadoz.net/freebsd/lor/152.html http://sources.zabbadoz.net/freebsd/lor/158.html --- sys/netinet/if_ether.c | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/sys/netinet/if_ether.c b/sys/netinet/if_ether.c index 63ea5457a31a..24c8b98ce01f 100644 --- a/sys/netinet/if_ether.c +++ b/sys/netinet/if_ether.c @@ -445,6 +445,9 @@ arpresolve(struct ifnet *ifp, struct rtentry *rt0, struct mbuf *m, */ if ((rt->rt_expire == 0 || rt->rt_expire > time_second) && sdl->sdl_family == AF_LINK && sdl->sdl_alen != 0) { + + bcopy(LLADDR(sdl), desten, sdl->sdl_alen); + /* * If entry has an expiry time and it is approaching, * see if we need to send an ARP request within this @@ -452,14 +455,16 @@ arpresolve(struct ifnet *ifp, struct rtentry *rt0, struct mbuf *m, */ if ((rt->rt_expire != 0) && (time_second + la->la_preempt > rt->rt_expire)) { - arprequest(ifp, - &SIN(rt->rt_ifa->ifa_addr)->sin_addr, - &SIN(dst)->sin_addr, - IF_LLADDR(ifp)); + struct in_addr sin = + SIN(rt->rt_ifa->ifa_addr)->sin_addr; + la->la_preempt--; + RT_UNLOCK(rt); + arprequest(ifp, &sin, &SIN(dst)->sin_addr, + IF_LLADDR(ifp)); + return (0); } - bcopy(LLADDR(sdl), desten, sdl->sdl_alen); RT_UNLOCK(rt); return (0); } @@ -487,10 +492,13 @@ arpresolve(struct ifnet *ifp, struct rtentry *rt0, struct mbuf *m, if (la->la_asked == 0 || rt->rt_expire != time_second) { rt->rt_expire = time_second; if (la->la_asked++ < arp_maxtries) { - arprequest(ifp, - &SIN(rt->rt_ifa->ifa_addr)->sin_addr, - &SIN(dst)->sin_addr, - IF_LLADDR(ifp)); + struct in_addr sin = + SIN(rt->rt_ifa->ifa_addr)->sin_addr; + + RT_UNLOCK(rt); + arprequest(ifp, &sin, &SIN(dst)->sin_addr, + IF_LLADDR(ifp)); + return (EWOULDBLOCK); } else { rt->rt_flags |= RTF_REJECT; rt->rt_expire += arpt_down;