diff options
author | qingli <qingli@FreeBSD.org> | 2008-12-19 11:07:34 +0000 |
---|---|---|
committer | qingli <qingli@FreeBSD.org> | 2008-12-19 11:07:34 +0000 |
commit | e1a252e123d00883dfdada1b4a1567a5fbb1414f (patch) | |
tree | ee357c191fa777901e4866e2c359cbba69c5bb80 /sys/netinet/if_ether.c | |
parent | 468571c1c0a807043a39f0cd88fa41b543e03e9f (diff) | |
download | FreeBSD-src-e1a252e123d00883dfdada1b4a1567a5fbb1414f.zip FreeBSD-src-e1a252e123d00883dfdada1b4a1567a5fbb1414f.tar.gz |
The proxy-arp code was broken and responds to ARP
requests for addresses that are not proxied locally.
Diffstat (limited to 'sys/netinet/if_ether.c')
-rw-r--r-- | sys/netinet/if_ether.c | 109 |
1 files changed, 52 insertions, 57 deletions
diff --git a/sys/netinet/if_ether.c b/sys/netinet/if_ether.c index 7bea5aa..1b03fb3 100644 --- a/sys/netinet/if_ether.c +++ b/sys/netinet/if_ether.c @@ -660,69 +660,64 @@ reply: (void)memcpy(ar_tha(ah), ar_sha(ah), ah->ar_hln); (void)memcpy(ar_sha(ah), enaddr, ah->ar_hln); } else { - if (la == NULL) { - if (!V_arp_proxyall) - goto drop; - - sin.sin_addr = itaddr; - /* XXX MRT use table 0 for arp reply */ - rt = in_rtalloc1((struct sockaddr *)&sin, 0, 0UL, 0); - if (!rt) - goto drop; - /* - * Don't send proxies for nodes on the same interface - * as this one came out of, or we'll get into a fight - * over who claims what Ether address. - */ - if (rt->rt_ifp == ifp) { - RTFREE_LOCKED(rt); - goto drop; - } - (void)memcpy(ar_tha(ah), ar_sha(ah), ah->ar_hln); - (void)memcpy(ar_sha(ah), enaddr, ah->ar_hln); + struct llentry *lle = NULL; + + if (!V_arp_proxyall) + goto drop; + + sin.sin_addr = itaddr; + /* XXX MRT use table 0 for arp reply */ + rt = in_rtalloc1((struct sockaddr *)&sin, 0, 0UL, 0); + if (!rt) + goto drop; + + /* + * Don't send proxies for nodes on the same interface + * as this one came out of, or we'll get into a fight + * over who claims what Ether address. + */ + if (!rt->rt_ifp || rt->rt_ifp == ifp) { RTFREE_LOCKED(rt); + goto drop; + } + IF_AFDATA_LOCK(rt->rt_ifp); + lle = lla_lookup(LLTABLE(rt->rt_ifp), 0, (struct sockaddr *)&sin); + IF_AFDATA_UNLOCK(rt->rt_ifp); + RTFREE_LOCKED(rt); - /* - * Also check that the node which sent the ARP packet - * is on the the interface we expect it to be on. This - * avoids ARP chaos if an interface is connected to the - * wrong network. - */ - sin.sin_addr = isaddr; - - /* XXX MRT use table 0 for arp checks */ - rt = in_rtalloc1((struct sockaddr *)&sin, 0, 0UL, 0); - if (!rt) - goto drop; - if (rt->rt_ifp != ifp) { - log(LOG_INFO, "arp_proxy: ignoring request" - " from %s via %s, expecting %s\n", - inet_ntoa(isaddr), ifp->if_xname, - rt->rt_ifp->if_xname); - RTFREE_LOCKED(rt); - goto drop; - } + if (lle != NULL) { + (void)memcpy(ar_tha(ah), ar_sha(ah), ah->ar_hln); + (void)memcpy(ar_sha(ah), &lle->ll_addr, ah->ar_hln); + LLE_RUNLOCK(lle); + } else + goto drop; + + /* + * Also check that the node which sent the ARP packet + * is on the the interface we expect it to be on. This + * avoids ARP chaos if an interface is connected to the + * wrong network. + */ + sin.sin_addr = isaddr; + + /* XXX MRT use table 0 for arp checks */ + rt = in_rtalloc1((struct sockaddr *)&sin, 0, 0UL, 0); + if (!rt) + goto drop; + if (rt->rt_ifp != ifp) { + log(LOG_INFO, "arp_proxy: ignoring request" + " from %s via %s, expecting %s\n", + inet_ntoa(isaddr), ifp->if_xname, + rt->rt_ifp->if_xname); RTFREE_LOCKED(rt); + goto drop; + } + RTFREE_LOCKED(rt); #ifdef DEBUG_PROXY - printf("arp: proxying for %s\n", - inet_ntoa(itaddr)); + printf("arp: proxying for %s\n", + inet_ntoa(itaddr)); #endif - } else { - /* - * Return proxied ARP replies only on the interface - * or bridge cluster where this network resides. - * Otherwise we may conflict with the host we are - * proxying for. - */ - if (la->lle_tbl->llt_ifp != ifp && - (la->lle_tbl->llt_ifp->if_bridge != ifp->if_bridge || - ifp->if_bridge == NULL)) { - goto drop; - } - (void)memcpy(ar_tha(ah), ar_sha(ah), ah->ar_hln); - (void)memcpy(ar_sha(ah), &la->ll_addr, ah->ar_hln); - } } if (la != NULL) |