interfaces: fix the intricate cleanup of link-local VIPs

The VIPs are bound to the scope so we need to add it to the
address lookup.  From the controller emit the same "@" usage
which is used to indicatge a scope, but not no a network
device.  If encountered translate the scope back to a network
device and use the proper "%" syntax.
This commit is contained in:
Franco Fichtner 2023-10-24 10:37:38 +02:00
parent ad2e5e7515
commit 16d0a071ad
2 changed files with 29 additions and 7 deletions

View File

@ -28,10 +28,11 @@
namespace OPNsense\Interfaces\Api;
use OPNsense\Base\ApiMutableModelControllerBase;
use OPNsense\Base\UserException;
use OPNsense\Core\Backend;
use OPNsense\Core\Config;
use OPNsense\Base\UserException;
use OPNsense\Base\ApiMutableModelControllerBase;
use OPNsense\Firewall\Util;
class VipSettingsController extends ApiMutableModelControllerBase
{
@ -149,7 +150,11 @@ class VipSettingsController extends ApiMutableModelControllerBase
}
}
if ($node != null && ($post_subnet != (string)$node->subnet || $post_interface != (string)$node->interface)) {
file_put_contents("/tmp/delete_vip_{$uuid}.todo", (string)$node->subnet . "\n", FILE_APPEND);
$addr = (string)$node->subnet;
if (Util::isLinkLocal($addr)) {
$addr .= "@{$node->interface}";
}
file_put_contents("/tmp/delete_vip_{$uuid}.todo", $addr . PHP_EOL, FILE_APPEND);
}
return $this->handleFormValidations($this->setBase('vip', 'vip', $uuid, $this->getVipOverlay()));
@ -184,7 +189,11 @@ class VipSettingsController extends ApiMutableModelControllerBase
}
$response = $this->delBase("vip", $uuid);
if (($response['result'] ?? '') == 'deleted') {
file_put_contents("/tmp/delete_vip_{$uuid}.todo", (string)$node->subnet . "\n", FILE_APPEND);
$addr = (string)$node->subnet;
if (Util::isLinkLocal($addr)) {
$addr .= "@{$node->interface}";
}
file_put_contents("/tmp/delete_vip_{$uuid}.todo", $addr . PHP_EOL, FILE_APPEND);
}
return $response;
}

View File

@ -38,7 +38,11 @@ foreach (legacy_interfaces_details() as $ifname => $ifcnf) {
foreach (['ipv4', 'ipv6'] as $proto) {
if (!empty($ifcnf[$proto])) {
foreach ($ifcnf[$proto] as $address) {
$addresses[$address['ipaddr']] = [
$key = $address['ipaddr'];
if ($proto == 'ipv6' && $address['link-local']) {
$key .= '%' . $ifname;
}
$addresses[$key] = [
'subnetbits' => $address['subnetbits'],
'if' => $ifname,
'vhid' => $address['vhid'] ?? '',
@ -48,8 +52,8 @@ foreach (legacy_interfaces_details() as $ifname => $ifcnf) {
if (!empty($address['vhid'])) {
foreach ($ifcnf['carp'] as $vhid) {
if ($vhid['vhid'] == $address['vhid']) {
$addresses[$address['ipaddr']]['advbase'] = $vhid['advbase'];
$addresses[$address['ipaddr']]['advskew'] = $vhid['advskew'];
$addresses[$key]['advbase'] = $vhid['advbase'];
$addresses[$key]['advskew'] = $vhid['advskew'];
}
}
}
@ -61,6 +65,12 @@ foreach (legacy_interfaces_details() as $ifname => $ifcnf) {
// remove deleted vips
foreach (glob("/tmp/delete_vip_*.todo") as $filename) {
foreach (array_unique(explode("\n", trim(file_get_contents($filename)))) as $address) {
/* '@' designates an IPv6 link-local scope, but not on network device */
if (strpos($address, '@') !== false) {
list($address, $interface) = explode('@', $address);
/* translate to what ifconfig will understand */
$address .= '%' . get_real_interface($interface, 'inet6');
}
if (isset($addresses[$address])) {
legacy_interface_deladdress($addresses[$address]['if'], $address, is_ipaddrv6($address) ? 6 : 4);
} else {
@ -83,6 +93,9 @@ if (!empty($config['virtualip']['vip'])) {
if (!empty($vipent['interface']) && !empty($interfaces[$vipent['interface']])) {
$if = $interfaces[$vipent['interface']];
$subnet = $vipent['subnet'];
if (is_linklocal($subnet)) {
$subnet .= '%' . get_real_interface($if, 'inet6');
}
$subnet_bits = $vipent['subnet_bits'];
$vhid = $vipent['vhid'] ?? '';
$advbase = !empty($vipent['vhid']) ? $vipent['advbase'] : '';