interfaces: make link-local vips unique per interface #6775 (#6876)

This commit is contained in:
Franco Fichtner 2023-09-25 16:15:53 +02:00 committed by GitHub
parent 3a0b929386
commit 2bd3fb5d9f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 26 additions and 9 deletions

View File

@ -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;

View File

@ -21,12 +21,6 @@
</mode>
<subnet type=".\VipNetworkField">
<!-- required, but validated in model -->
<Constraints>
<check001>
<ValidationMessage>Address already assigned.</ValidationMessage>
<type>UniqueConstraint</type>
</check001>
</Constraints>
</subnet>
<subnet_bits type=".\VipNetworkField">
<!-- required, but validated in model -->