diff --git a/src/opnsense/mvc/app/models/OPNsense/DHCRelay/DHCRelay.php b/src/opnsense/mvc/app/models/OPNsense/DHCRelay/DHCRelay.php index bddfd02c7..b7f719ab4 100644 --- a/src/opnsense/mvc/app/models/OPNsense/DHCRelay/DHCRelay.php +++ b/src/opnsense/mvc/app/models/OPNsense/DHCRelay/DHCRelay.php @@ -1,7 +1,7 @@ destinations->getFlatNodes() as $key => $node) { - $tagName = $node->getInternalXMLTagName(); - $parentNode = $node->getParentNode(); + if ($node->getInternalXMLTagName() != 'server') { + continue; + } + + /* single pass lookup for each special IP delimiter beats looping over entries */ + $v4 = strpos((string)$node, '.') !== false; + $v6 = strpos((string)$node, ':') !== false; if ($validateFullModel || $node->isFieldChanged()) { - $destinations[$parentNode->__reference] = $parentNode; - } - } - - // validate all changed destinations - foreach ($destinations as $key => $node) { - $v4 = $v6 = false; - - foreach (explode(',', (string)$node->server) as $server) { - if (strpos($server, '.') !== false) { - $v4 = true; - } else { - $v6 = true; + if ($v4 && $v6) { + $messages->appendMessage(new Message(gettext('You cannot mix address families for destinations.'), $key)); } } - if ($v4 && $v6) { - $messages->appendMessage( - new Message(gettext('You cannot mix address families for destinations.'), "{$key}.server") - ); + $uuid = $node->getParentNode()->getAttribute('uuid'); + + if ($v4) { + $dst4[$uuid] = true; + } elseif ($v6) { + $dst6[$uuid] = true; + } + } + + foreach ($this->relays->getFlatNodes() as $key => $node) { + if ($node->getInternalXMLTagName() == 'interface' && ($validateFullModel || $node->isFieldChanged())) { + /* collect changed interfaces first to confirm their association afterwards */ + $ints[$node->getParentNode()->__reference] = (string)$node; + } + } + + foreach ($ints as $intkey => $int) { + $has_v4 = $has_v6 = 0; + + foreach ($this->relays->iterateItems() as $key => $node) { + if ((string)$node->interface == $int) { + if (array_key_exists((string)$node->destination, $dst4)) { + $has_v4 += 1; + } + if (array_key_exists((string)$node->destination, $dst6)) { + $has_v6 += 1; + } + } + } + + if ($has_v4 > 1) { + $messages->appendMessage(new Message(gettext('An IPv4 destination for this relay is already set.'), "{$intkey}.destination")); + } elseif ($has_v6 > 1) { + $messages->appendMessage(new Message(gettext('An IPv6 destination for this relay is already set.'), "{$intkey}.destination")); } } diff --git a/src/opnsense/mvc/app/models/OPNsense/DHCRelay/DHCRelay.xml b/src/opnsense/mvc/app/models/OPNsense/DHCRelay/DHCRelay.xml index 02481086e..66fe05641 100644 --- a/src/opnsense/mvc/app/models/OPNsense/DHCRelay/DHCRelay.xml +++ b/src/opnsense/mvc/app/models/OPNsense/DHCRelay/DHCRelay.xml @@ -9,12 +9,6 @@ Y - - - A relay for this interface already exists. - UniqueConstraint - -