diff --git a/src/opnsense/mvc/app/models/OPNsense/Interfaces/Vip.php b/src/opnsense/mvc/app/models/OPNsense/Interfaces/Vip.php
index 1aca7dc8b..25f5e8772 100644
--- a/src/opnsense/mvc/app/models/OPNsense/Interfaces/Vip.php
+++ b/src/opnsense/mvc/app/models/OPNsense/Interfaces/Vip.php
@@ -41,21 +41,33 @@ class Vip extends BaseModel
public function performValidation($validateFullModel = false)
{
$messages = parent::performValidation($validateFullModel);
- $vips = [];
+
+ $unqiue_addrs = [];
$carp_vhids = [];
+ $vips = [];
// collect changed VIP entries
$vip_fields = ['mode', 'subnet', 'subnet_bits', 'password', 'vhid', 'interface'];
foreach ($this->getFlatNodes() as $key => $node) {
$tagName = $node->getInternalXMLTagName();
$parentNode = $node->getParentNode();
+
if ($validateFullModel || $node->isFieldChanged()) {
if ($parentNode->getInternalXMLTagName() === 'vip' && in_array($tagName, $vip_fields)) {
- $parentKey = $parentNode->__reference;
- $vips[$parentKey] = $parentNode;
+ $vips[$parentNode->__reference] = $parentNode;
}
}
+
+ if ($parentNode->getInternalXMLTagName() === 'vip' && $tagName == 'subnet') {
+ $addr = (string)$parentNode->subnet;
+ if (Util::isLinkLocal($addr)) {
+ $addr .= '@' . (string)$parentNode->interface;
+ }
+ $unique_addrs[$parentNode->__reference] = $addr;
+ }
+
$vhid_key = sprintf("%s_%s", $parentNode->interface, $parentNode->vhid);
+
if ((string)$parentNode->mode == 'carp' && !isset($carp_vhids[$vhid_key])) {
$carp_vhids[$vhid_key] = $parentNode;
}
@@ -151,6 +163,17 @@ class Vip extends BaseModel
)
);
}
+
+ /* ensure address is unique; for link-local we test with scope attached */
+ $addr = (string)$node->subnet;
+ if (Util::isLinkLocal($addr)) {
+ $addr .= '@' . (string)$node->interface;
+ }
+ foreach ($unique_addrs as $refKey => $refAddr) {
+ if ($refKey != $key && $refAddr === $addr) {
+ $messages->appendMessage(new Message(gettext('Address already assigned.'), $key . '.subnet'));
+ }
+ }
}
return $messages;
diff --git a/src/opnsense/mvc/app/models/OPNsense/Interfaces/Vip.xml b/src/opnsense/mvc/app/models/OPNsense/Interfaces/Vip.xml
index 0c5a7ede0..d7e1a6e25 100644
--- a/src/opnsense/mvc/app/models/OPNsense/Interfaces/Vip.xml
+++ b/src/opnsense/mvc/app/models/OPNsense/Interfaces/Vip.xml
@@ -21,12 +21,6 @@
-
-
- Address already assigned.
- UniqueConstraint
-
-