diff --git a/sbin/ifconfig/ifconfig.8 b/sbin/ifconfig/ifconfig.8 --- a/sbin/ifconfig/ifconfig.8 +++ b/sbin/ifconfig/ifconfig.8 @@ -28,7 +28,7 @@ .\" From: @(#)ifconfig.8 8.3 (Berkeley) 1/5/94 .\" $FreeBSD$ .\" -.Dd April 11, 2022 +.Dd May 26, 2022 .Dt IFCONFIG 8 .Os .Sh NAME @@ -419,6 +419,23 @@ If the Address Resolution Protocol is enabled, the host will perform normally, sending out requests and listening for replies. +.It Cm stickyarp +Enable so-called sticky ARP mode for the interface. +If this option is enabled on the given interface, any resolved address is +marked as a static one and never expires. This may be used to increase +security of the network by preventing ARP spoofing or to reduce latency for +high-performance Ethernet networks where the time needed for ARP resolution is +too high. Please note that a similar feature is also provided for bridges. See +the sticky option in the +.Sx Bridge Interface Parameters +section. Enabling this +option may impact techniques which rely on ARP expiration/overwriting feature +such as load-balancers or high-availabity solutions such as +.Xr carp 4 . +.It Fl stickyarp +Disable so-called sticky ARP mode for the interface (default). +Resolved addresses will expire normally respecting the kernel ARP +configuration. .It Cm broadcast (Inet only.) Specify the address to use to represent broadcasts to the diff --git a/sbin/ifconfig/ifconfig.c b/sbin/ifconfig/ifconfig.c --- a/sbin/ifconfig/ifconfig.c +++ b/sbin/ifconfig/ifconfig.c @@ -1407,7 +1407,7 @@ #define IFFBITS \ "\020\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5POINTOPOINT\7RUNNING" \ "\10NOARP\11PROMISC\12ALLMULTI\13OACTIVE\14SIMPLEX\15LINK0\16LINK1\17LINK2" \ -"\20MULTICAST\22PPROMISC\23MONITOR\24STATICARP" +"\20MULTICAST\22PPROMISC\23MONITOR\24STATICARP\25STICKYARP" #define IFCAPBITS \ "\020\1RXCSUM\2TXCSUM\3NETCONS\4VLAN_MTU\5VLAN_HWTAGGING\6JUMBO_MTU\7POLLING" \ @@ -1771,6 +1771,8 @@ DEF_CMD("-mextpg", -IFCAP_MEXTPG, setifcap), DEF_CMD("staticarp", IFF_STATICARP, setifflags), DEF_CMD("-staticarp", -IFF_STATICARP, setifflags), + DEF_CMD("stickyarp", IFF_STICKYARP, setifflags), + DEF_CMD("-stickyarp", -IFF_STICKYARP, setifflags), DEF_CMD("rxcsum6", IFCAP_RXCSUM_IPV6, setifcap), DEF_CMD("-rxcsum6", -IFCAP_RXCSUM_IPV6, setifcap), DEF_CMD("txcsum6", IFCAP_TXCSUM_IPV6, setifcap), diff --git a/sys/net/if.h b/sys/net/if.h --- a/sys/net/if.h +++ b/sys/net/if.h @@ -160,6 +160,7 @@ #define IFF_PPROMISC 0x20000 /* (n) user-requested promisc mode */ #define IFF_MONITOR 0x40000 /* (n) user-requested monitor mode */ #define IFF_STATICARP 0x80000 /* (n) static ARP */ +#define IFF_STICKYARP 0x100000 /* (n) sticky ARP */ #define IFF_DYING 0x200000 /* (n) interface is winding down */ #define IFF_RENAMING 0x400000 /* (n) interface is being renamed */ #define IFF_NOGROUP 0x800000 /* (n) interface is not part of any groups */ diff --git a/sys/netinet/if_ether.c b/sys/netinet/if_ether.c --- a/sys/netinet/if_ether.c +++ b/sys/netinet/if_ether.c @@ -186,7 +186,7 @@ static void arp_check_update_lle(struct arphdr *ah, struct in_addr isaddr, struct ifnet *ifp, int bridged, struct llentry *la); -static void arp_mark_lle_reachable(struct llentry *la); +static void arp_mark_lle_reachable(struct llentry *la, struct ifnet *ifp); static void arp_iflladdr(void *arg __unused, struct ifnet *ifp); static eventhandler_tag iflladdr_tag; @@ -999,7 +999,7 @@ IF_AFDATA_WUNLOCK(ifp); if (la_tmp == NULL) { - arp_mark_lle_reachable(la); + arp_mark_lle_reachable(la, ifp); LLE_WUNLOCK(la); } else { /* Free newly-create entry and handle packet */ @@ -1247,7 +1247,7 @@ llentry_mark_used(la); } - arp_mark_lle_reachable(la); + arp_mark_lle_reachable(la, ifp); /* * The packets are all freed within the call to the output @@ -1267,7 +1267,7 @@ } static void -arp_mark_lle_reachable(struct llentry *la) +arp_mark_lle_reachable(struct llentry *la, struct ifnet *ifp) { int canceled, wtime; @@ -1276,6 +1276,9 @@ la->ln_state = ARP_LLINFO_REACHABLE; EVENTHANDLER_INVOKE(lle_event, la, LLENTRY_RESOLVED); + if ((ifp->if_flags & IFF_STICKYARP) != 0) + la->la_flags |= LLE_STATIC; + if (!(la->la_flags & LLE_STATIC)) { LLE_ADDREF(la); la->la_expire = time_uptime + V_arpt_keep;