From 90f0ce3c7c48aafe82406e9599620c5338f11a45 Mon Sep 17 00:00:00 2001 From: Alexander Kolenaty Date: Tue, 12 May 2026 16:31:49 +0200 Subject: [PATCH] interfaces: do not drop VIP alias on description-only set_item --- .../Interfaces/Api/VipSettingsController.php | 21 +++++++++++++------ .../scripts/interfaces/reconfigure_vips.php | 2 ++ 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/src/opnsense/mvc/app/controllers/OPNsense/Interfaces/Api/VipSettingsController.php b/src/opnsense/mvc/app/controllers/OPNsense/Interfaces/Api/VipSettingsController.php index d08f4dc0e3..22b2fe789f 100644 --- a/src/opnsense/mvc/app/controllers/OPNsense/Interfaces/Api/VipSettingsController.php +++ b/src/opnsense/mvc/app/controllers/OPNsense/Interfaces/Api/VipSettingsController.php @@ -120,14 +120,23 @@ class VipSettingsController extends ApiMutableModelControllerBase Config::getInstance()->lock(); $node = $this->getModel()->getNodeByReference('vip.' . $uuid); $validations = []; - $post_subnet = ''; - $post_interface = ''; + $post_subnet = null; + $post_interface = null; if (isset($_POST['vip'])) { - $post_subnet = !empty($_POST['vip']['network']) ? explode('/', $_POST['vip']['network'])[0] : ''; - $post_interface = !empty($_POST['vip']['interface']) ? $_POST['vip']['interface'] : ''; + if (!empty($_POST['vip']['network'])) { + $post_subnet = explode('/', $_POST['vip']['network'])[0]; + } elseif (isset($_POST['vip']['subnet'])) { + $post_subnet = $_POST['vip']['subnet']; + } + if (isset($_POST['vip']['interface'])) { + $post_interface = $_POST['vip']['interface']; + } } - if ($node != null && $post_subnet != (string)$node->subnet) { + $subnet_changed = $post_subnet !== null && $post_subnet != (string)$node?->subnet; + $interface_changed = $post_interface !== null && $post_interface != (string)$node?->interface; + + if ($node != null && $subnet_changed) { $validations = $this->getModel()->whereUsed((string)$node->subnet); if (!empty($validations)) { // XXX a bit unpractical, but we can not validate previous values from the model so @@ -140,7 +149,7 @@ class VipSettingsController extends ApiMutableModelControllerBase ]; } } - if ($node != null && ($post_subnet != (string)$node->subnet || $post_interface != (string)$node->interface)) { + if ($node != null && ($subnet_changed || $interface_changed)) { $addr = (string)$node->subnet; if (Util::isLinkLocal($addr)) { $addr .= "@{$node->interface}"; diff --git a/src/opnsense/scripts/interfaces/reconfigure_vips.php b/src/opnsense/scripts/interfaces/reconfigure_vips.php index 8c52b70d7e..9e4f271009 100755 --- a/src/opnsense/scripts/interfaces/reconfigure_vips.php +++ b/src/opnsense/scripts/interfaces/reconfigure_vips.php @@ -78,6 +78,8 @@ foreach (glob("/tmp/delete_vip_*.todo") as $filename) { } if (isset($addresses[$address])) { legacy_interface_deladdress($addresses[$address]['if'], $address, is_ipaddrv6($address) ? 6 : 4); + // keep snapshot in sync so the re-add loop below sees the address as missing + unset($addresses[$address]); } else { // not found, likely proxy arp $proxyarp = true;