mirror of
https://github.com/opnsense/core.git
synced 2026-06-09 00:42:36 -04:00
mvc: Fix idassoc.php converting already decimal stored prefix_id via hexdec(), add unit test for idassoc.php (#10389)
--------- Co-authored-by: Franco Fichtner <franco@opnsense.org>
This commit is contained in:
parent
9a702a6a6a
commit
b0e8dfcc54
3 changed files with 157 additions and 2 deletions
1
plist
1
plist
|
|
@ -1083,6 +1083,7 @@
|
|||
/usr/local/opnsense/mvc/tests/app/library/OPNsense/Firewall/FilterRuleTest/testDirection.conf
|
||||
/usr/local/opnsense/mvc/tests/app/library/OPNsense/Firewall/FilterRuleTest/testIcmp.conf
|
||||
/usr/local/opnsense/mvc/tests/app/library/OPNsense/Firewall/FilterRuleTest/testProtocol.conf
|
||||
/usr/local/opnsense/mvc/tests/app/library/OPNsense/Interface/IdassocTest.php
|
||||
/usr/local/opnsense/mvc/tests/app/models/OPNsense/ACL/AclConfig/config.xml
|
||||
/usr/local/opnsense/mvc/tests/app/models/OPNsense/ACL/AclTest.php
|
||||
/usr/local/opnsense/mvc/tests/app/models/OPNsense/Base/BaseModel/Migrations/M0_0_1.php
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ class Idassoc extends Autoconf
|
|||
$bytes = array_values(unpack('C*', inet_pton($address)));
|
||||
|
||||
$source_prefix_len = (int)$source_prefix_len;
|
||||
$prefix_id = hexdec((string)$prefix_id);
|
||||
$prefix_id = (int)$prefix_id;
|
||||
$id_bits = 64 - $source_prefix_len;
|
||||
|
||||
for ($i = 0; $i < $id_bits; $i++) {
|
||||
|
|
@ -69,7 +69,7 @@ class Idassoc extends Autoconf
|
|||
private static function calculateUsablePrefixLength($source_prefix_len, $track6_prefix_id, $track6_prefix_range = ''): int
|
||||
{
|
||||
$source_prefix_len = (int)$source_prefix_len;
|
||||
$track6_prefix_id = hexdec((string)$track6_prefix_id);
|
||||
$track6_prefix_id = (int)$track6_prefix_id;
|
||||
$track6_prefix_range = (string)$track6_prefix_range !== '' ? (int)$track6_prefix_range : 1;
|
||||
|
||||
$associated_size = 1 << (64 - $source_prefix_len);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,154 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Copyright (C) 2026 Deciso B.V.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
|
||||
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
namespace tests\OPNsense\Interface;
|
||||
|
||||
use OPNsense\Interface\Idassoc;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/*
|
||||
* Test value mapping:
|
||||
*
|
||||
* $track6_interface_prefix:
|
||||
* Runtime IPv6 prefix associated with the source interface selected by:
|
||||
* interfaces.<ifname>.track6-interface
|
||||
* Format: IPv6 CIDR prefix, for example "2001:db8:1234:ab00::/56"
|
||||
*
|
||||
* $track6_interface_prefix_len:
|
||||
* Prefix length extracted from $track6_interface_prefix.
|
||||
* Format: decimal integer, for example 56
|
||||
*
|
||||
* $track6_prefix_id:
|
||||
* Configuration value:
|
||||
* interfaces.<ifname>.track6-prefix-id
|
||||
* Format: decimal string, for example "0", "10", "16", "255"
|
||||
* The prefix ID is stored as decimal string in the config, even though the GUI overlays it as hex.
|
||||
* https://github.com/opnsense/core/blob/fb514217bae6525f36834ebd7279a02ad8626f0f/src/www/interfaces.php#L327
|
||||
*
|
||||
* $track6_prefix_range:
|
||||
* Configuration value:
|
||||
* interfaces.<ifname>.track6_prefix_range
|
||||
* Format: decimal string, interpreted as number of /64 slots,
|
||||
* for example "1", "2", "4", "16"
|
||||
*
|
||||
* $expected:
|
||||
* Calculated output value consumed by services:
|
||||
* prefix_on_link or prefix_allocated
|
||||
* Format: IPv6 CIDR prefix, for example "2001:db8:1234:ab10::/64"
|
||||
*/
|
||||
class IdassocTest extends TestCase
|
||||
{
|
||||
private function callPrivateStatic(string $method, array $args = [])
|
||||
{
|
||||
$reflection = new \ReflectionClass(Idassoc::class);
|
||||
$method = $reflection->getMethod($method);
|
||||
$method->setAccessible(true);
|
||||
|
||||
return $method->invokeArgs(null, $args);
|
||||
}
|
||||
|
||||
private function assertCalculatedPrefix(
|
||||
string $track6_interface_prefix,
|
||||
string $track6_prefix_id,
|
||||
string $expected
|
||||
) {
|
||||
$this->assertEquals(
|
||||
$expected,
|
||||
$this->callPrivateStatic('calculatePrefix', [$track6_interface_prefix, $track6_prefix_id]),
|
||||
sprintf(
|
||||
'track6_interface_prefix=%s track6_prefix_id=%s',
|
||||
$track6_interface_prefix,
|
||||
$track6_prefix_id
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
private function assertUsablePrefixLength(
|
||||
int $track6_interface_prefix_len,
|
||||
string $track6_prefix_id,
|
||||
string $track6_prefix_range,
|
||||
int $expected
|
||||
) {
|
||||
$this->assertEquals(
|
||||
$expected,
|
||||
$this->callPrivateStatic(
|
||||
'calculateUsablePrefixLength',
|
||||
[$track6_interface_prefix_len, $track6_prefix_id, $track6_prefix_range]
|
||||
),
|
||||
sprintf(
|
||||
'track6_interface_prefix_len=%s track6_prefix_id=%s track6_prefix_range=%s',
|
||||
$track6_interface_prefix_len,
|
||||
$track6_prefix_id,
|
||||
$track6_prefix_range
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public function testPrefixId()
|
||||
{
|
||||
$track6_interface_prefix = '2001:db8:1234:ab00::/56';
|
||||
|
||||
$this->assertCalculatedPrefix($track6_interface_prefix, '0', '2001:db8:1234:ab00::/64');
|
||||
$this->assertCalculatedPrefix($track6_interface_prefix, '1', '2001:db8:1234:ab01::/64');
|
||||
$this->assertCalculatedPrefix($track6_interface_prefix, '10', '2001:db8:1234:ab0a::/64');
|
||||
$this->assertCalculatedPrefix($track6_interface_prefix, '15', '2001:db8:1234:ab0f::/64');
|
||||
|
||||
// Configuration stores decimal 16; GUI may display this as hexadecimal "10".
|
||||
$this->assertCalculatedPrefix($track6_interface_prefix, '16', '2001:db8:1234:ab10::/64');
|
||||
|
||||
$this->assertCalculatedPrefix($track6_interface_prefix, '255', '2001:db8:1234:abff::/64');
|
||||
}
|
||||
|
||||
public function testDelegationSize()
|
||||
{
|
||||
// /52 leaves 12 bits for the subnet ID until /64.
|
||||
$this->assertCalculatedPrefix('2001:db8:1234:a000::/52', '16', '2001:db8:1234:a010::/64');
|
||||
|
||||
// /48 leaves 16 bits for the subnet ID until /64.
|
||||
$this->assertCalculatedPrefix('2001:db8:1234::/48', '16', '2001:db8:1234:10::/64');
|
||||
$this->assertCalculatedPrefix('2001:db8:1234::/48', '48879', '2001:db8:1234:beef::/64');
|
||||
}
|
||||
|
||||
public function testPrefixLength()
|
||||
{
|
||||
// Empty range or 1 means a single /64 slot.
|
||||
$this->assertUsablePrefixLength(56, '0', '', 64);
|
||||
$this->assertUsablePrefixLength(56, '0', '1', 64);
|
||||
|
||||
// Larger ranges can be aggregated when starting at an aligned prefix ID.
|
||||
$this->assertUsablePrefixLength(56, '0', '2', 63);
|
||||
$this->assertUsablePrefixLength(56, '0', '4', 62);
|
||||
$this->assertUsablePrefixLength(56, '0', '16', 60);
|
||||
|
||||
// Configuration stores decimal 16; GUI displays this as hexadecimal 10.
|
||||
$this->assertUsablePrefixLength(56, '16', '16', 60);
|
||||
|
||||
// Decimal 10 is hexadecimal 0x0a and only aligned to 2 slots.
|
||||
$this->assertUsablePrefixLength(56, '10', '16', 63);
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue