diff -urNbp src/sbin/ifconfig/ifconfig.c src-proxyarp/sbin/ifconfig/ifconfig.c --- src/sbin/ifconfig/ifconfig.c 2010-03-23 00:50:33.000000000 +0500 +++ src-proxyarp/sbin/ifconfig/ifconfig.c 2012-06-22 16:13:39.000000000 +0600 @@ -773,7 +773,7 @@ setifname(const char *val, int dummy __u #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\30PROXYARP" #define IFCAPBITS \ "\020\1RXCSUM\2TXCSUM\3NETCONS\4VLAN_MTU\5VLAN_HWTAGGING\6JUMBO_MTU\7POLLING" \ @@ -1037,6 +1037,8 @@ static struct cmd basic_cmds[] = { 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 -urNbp src/sys/net/if.h src-proxyarp/sys/net/if.h --- src/sys/net/if.h 2012-05-19 20:38:14.000000000 +0600 +++ src-proxyarp/sys/net/if.h 2012-06-22 16:13:39.000000000 +0600 @@ -151,6 +151,7 @@ struct if_data { #define IFF_STATICARP 0x80000 /* (n) static ARP */ #define IFF_NEEDSGIANT 0x100000 /* (i) hold Giant over if_start calls */ #define IFF_RENAMING 0x400000 /* (n) interface is being renamed */ +#define IFF_PROXYARP 0x800000 /* (n) enable "local-proxy-arp" mode */ /* * Old names for driver flags so that user space tools can continue to use diff -urNbp src/sys/netinet/if_ether.c src-proxyarp/sys/netinet/if_ether.c --- src/sys/netinet/if_ether.c 2011-08-03 10:28:16.000000000 +0600 +++ src-proxyarp/sys/netinet/if_ether.c 2012-06-22 16:16:51.000000000 +0600 @@ -891,7 +891,7 @@ reply: /* Nope, only intersted now if proxying everything. */ struct sockaddr_in sin; - if (!arp_proxyall) + if (!arp_proxyall && !(ifp->if_flags & IFF_PROXYARP)) goto drop; bzero(&sin, sizeof sin); @@ -908,10 +908,23 @@ reply: * 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_LOCKED(rt); goto drop; } + + /* + * PROXYARP: Windows workaround + */ + + if ((ifp->if_flags & IFF_PROXYARP) && \ + (isaddr.s_addr == itaddr.s_addr)) { + 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); RTFREE_LOCKED(rt);