diff --git a/src/etc/inc/interfaces.inc b/src/etc/inc/interfaces.inc index 401fe993a..f2c064940 100644 --- a/src/etc/inc/interfaces.inc +++ b/src/etc/inc/interfaces.inc @@ -2363,6 +2363,9 @@ function interface_configure($verbose = false, $interface = 'wan', $reload = fal /* XXX bridges can only load if all interfaces are there */ } + /* XXX may be called twice since also tied to dhcp configure */ + interfaces_staticarp_configure($interface, $ifconfig_details); + if ($verbose) { echo "done.\n"; } @@ -2377,8 +2380,6 @@ function interface_configure($verbose = false, $interface = 'wan', $reload = fal configdp_run('rfc2136 reload', array($interface)); } - interfaces_staticarp_configure($interface); - return $loaded; } @@ -3807,7 +3808,7 @@ function get_vip_descr($ipaddress) return ''; } -function interfaces_staticarp_configure($if) +function interfaces_staticarp_configure($if, $ifconfig_details = null) { global $config; @@ -3816,22 +3817,31 @@ function interfaces_staticarp_configure($if) return; } - mwexecf('/sbin/ifconfig %s %sstaticarp', [$ifcfg['if'], isset($config['dhcpd'][$if]['staticarp']) ? '' : '-']); + if (empty($ifconfig_details)) { + $ifconfig_details = legacy_interfaces_details($ifcfg['if']); + } - if (!file_exists('/var/run/booting')) { - // XXX: arp is really slow when there are many interfaces, while booting -d -a shouldn't be needed anyway + if (empty($ifconfig_details[$ifcfg['if']])) { + return; + } + + $have = in_array('staticarp', $ifconfig_details[$ifcfg['if']]['flags']); + $want = isset($config['dhcpd'][$if]['staticarp']); + + if ($have !== $want) { + mwexecf('/sbin/ifconfig %s %sstaticarp', [$ifcfg['if'], $want ? '' : '-']); mwexecf('/usr/sbin/arp -d -i %s -a', [$ifcfg['if']]); } if (isset($config['dhcpd'][$if]['staticmap'])) { foreach ($config['dhcpd'][$if]['staticmap'] as $arpent) { - if (!isset($config['dhcpd'][$if]['staticarp']) && !isset($arpent['arp_table_static_entry'])) { + if (!$want && !isset($arpent['arp_table_static_entry'])) { continue; } if (!isset($arpent['ipaddr'])) { continue; } - mwexecf( '/usr/sbin/arp -s %s %s', [$arpent['ipaddr'], $arpent['mac']]); + mwexecf('/usr/sbin/arp -s %s %s', [$arpent['ipaddr'], $arpent['mac']]); } } } diff --git a/src/etc/inc/plugins.inc.d/dhcpd.inc b/src/etc/inc/plugins.inc.d/dhcpd.inc index f9fb2787b..2681dfdfe 100644 --- a/src/etc/inc/plugins.inc.d/dhcpd.inc +++ b/src/etc/inc/plugins.inc.d/dhcpd.inc @@ -633,7 +633,8 @@ EOD; * to setup failover peer "bleh" entries */ foreach ($config['dhcpd'] as $dhcpif => $dhcpifconf) { - interfaces_staticarp_configure($dhcpif); + /* certainly odd but documented and side effect populates ARP table */ + interfaces_staticarp_configure($dhcpif, $ifconfig_details); if (!isset($dhcpifconf['enable'])) { continue; diff --git a/src/opnsense/service/conf/actions.d/actions_interface.conf b/src/opnsense/service/conf/actions.d/actions_interface.conf index 62cf22c04..96fe80e6c 100644 --- a/src/opnsense/service/conf/actions.d/actions_interface.conf +++ b/src/opnsense/service/conf/actions.d/actions_interface.conf @@ -47,6 +47,12 @@ parameters: %s type:script_output message:request arp table +[remove.arp] +command:/usr/sbin/arp -d +parameters:%s 2> /dev/null; exit 0 +type:script +message:remove arp entry for %s + [flush.arp] command:arp -da parameters: diff --git a/src/www/services_dhcp.php b/src/www/services_dhcp.php index 39de82b70..a456c0fb4 100644 --- a/src/www/services_dhcp.php +++ b/src/www/services_dhcp.php @@ -435,6 +435,11 @@ if ($_SERVER['REQUEST_METHOD'] === 'GET') { exit; } elseif ($act == "del") { if (!empty($config['dhcpd'][$if]['staticmap'][$_POST['id']])) { + if (isset($config['dhcpd'][$if]['staticmap'][$_POST['id']]['ipaddr'])) { + configdp_run('interface remove arp', [ + $config['dhcpd'][$if]['staticmap'][$_POST['id']]['ipaddr'] + ]); + } unset($config['dhcpd'][$if]['staticmap'][$_POST['id']]); write_config(); if (isset($config['dhcpd'][$if]['enable'])) {