diff -urNb src/sbin/ifconfig/ifconfig.c src-proxyarp/sbin/ifconfig/ifconfig.c --- src/sbin/ifconfig/ifconfig.c 2006-03-19 02:59:22.000000000 +0500 +++ src-proxyarp/sbin/ifconfig/ifconfig.c 2007-08-21 21:40:26.000000000 +0600 @@ -812,7 +812,7 @@ #define IFFBITS \ "\020\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5POINTOPOINT\6SMART\7RUNNING" \ "\10NOARP\11PROMISC\12ALLMULTI\13OACTIVE\14SIMPLEX\15LINK0\16LINK1\17LINK2" \ -"\20MULTICAST\22PPROMISC\23MONITOR\24STATICARP\25NEEDSGIANT" +"\20MULTICAST\22PPROMISC\23MONITOR\24STATICARP\25NEEDSGIANT\26PROXYARP" #define IFCAPBITS \ "\020\1RXCSUM\2TXCSUM\3NETCONS\4VLAN_MTU\5VLAN_HWTAGGING\6JUMBO_MTU\7POLLING" @@ -1050,6 +1050,8 @@ DEF_CMD("noicmp", IFF_LINK1, setifflags), DEF_CMD_ARG("mtu", setifmtu), DEF_CMD_ARG("name", setifname), + DEF_CMD("proxyarp", IFF_PROXYARP, setifflags), + DEF_CMD("-proxyarp", -IFF_PROXYARP, setifflags), }; static __constructor void diff -urNb src/sys/net/if.h src-proxyarp/sys/net/if.h --- src/sys/net/if.h 2006-02-15 08:37:15.000000000 +0500 +++ src-proxyarp/sys/net/if.h 2007-08-21 21:40:26.000000000 +0600 @@ -153,6 +153,7 @@ #define IFF_MONITOR 0x40000 /* (n) user-requested monitor mode */ #define IFF_STATICARP 0x80000 /* (n) static ARP */ #define IFF_NEEDSGIANT 0x100000 /* (i) hold Giant over if_start calls */ +#define IFF_PROXYARP 0x200000 /* (n) enable "local-proxy-arp" mode */ /* * Old names for driver flags so that user space tools can continue to use diff -urNb src/sys/netinet/if_ether.c src-proxyarp/sys/netinet/if_ether.c --- src/sys/netinet/if_ether.c 2007-03-14 02:59:20.000000000 +0500 +++ src-proxyarp/sys/netinet/if_ether.c 2007-08-22 01:23:19.000000000 +0600 @@ -105,6 +105,7 @@ static int arp_maxtries = 5; static int useloopback = 1; /* use loopback interface for local traffic */ static int arp_proxyall = 0; +static int localproxyarp_delay = 0; static struct callout arp_callout; SYSCTL_INT(_net_link_ether_inet, OID_AUTO, maxtries, CTLFLAG_RW, @@ -113,6 +114,8 @@ &useloopback, 0, ""); SYSCTL_INT(_net_link_ether_inet, OID_AUTO, proxyall, CTLFLAG_RW, &arp_proxyall, 0, ""); +SYSCTL_INT(_net_link_ether_inet, OID_AUTO, local_proxyarp_delay, CTLFLAG_RW, + &localproxyarp_delay, 0, "Local Proxy ARP delay (microseconds), may help to win the race"); static void arp_init(void); static void arp_rtrequest(int, struct rtentry *, struct rt_addrinfo *); @@ -814,7 +817,7 @@ if (rt == NULL) { struct sockaddr_in sin; - if (!arp_proxyall) + if (!arp_proxyall && !(ifp->if_flags & IFF_PROXYARP)) goto drop; bzero(&sin, sizeof sin); @@ -830,10 +833,26 @@ * as this one came out of, or we'll get into a fight * over who claims what Ether address. */ - if (rt->rt_ifp == ifp) { + if ((rt->rt_ifp == ifp) && \ + !(ifp->if_flags & IFF_PROXYARP)) { rtfree(rt); goto drop; } + + /* + * PROXYARP: Windows workaround + */ + + if ((ifp->if_flags & IFF_PROXYARP) && \ + (isaddr.s_addr == itaddr.s_addr)) { + rtfree(rt); + goto drop; + } + + /* PROXYARP: Delay sending reply for specified time */ + if (ifp->if_flags & IFF_PROXYARP) + DELAY(localproxyarp_delay); + (void)memcpy(ar_tha(ah), ar_sha(ah), ah->ar_hln); (void)memcpy(ar_sha(ah), enaddr, ah->ar_hln); rtfree(rt);