interfaces: extend/modify IPv6 primary address behaviour

"primary" now works like its IPv4 counterpart not using tracking
interface addresses to suggest a different derived listening address.

OTOH "routed" and "scoped" variants are only relevant for services
listening on a particularly connected (functional) address.  Its use
is relatively low but better to have these variants than handroll each
required spot.
This commit is contained in:
Franco Fichtner 2023-05-17 09:29:51 +02:00
parent 227d092d23
commit 3e457864c7
6 changed files with 30 additions and 27 deletions

View File

@ -4339,6 +4339,7 @@ function interfaces_has_prefix_only($interface)
function interfaces_primary_address($interface, $ifconfig_details = null)
{
/* primary returns preferred local address according to configuration */
$ifcfgip = $network = $subnetbits = null;
foreach (interfaces_addresses($interface, false, $ifconfig_details) as $addr) {
@ -4362,56 +4363,58 @@ function interfaces_primary_address($interface, $ifconfig_details = null)
return [ $ifcfgip, $network, $subnetbits ];
}
/* XXX rename "primary" to "routed" as that is what it is */
function interfaces_primary_address6($interface, $ifconfig_details = null, $allow_track = true)
function _interfaces_primary_address6($interface, $ifconfig_details = null, $allow_track = true, $link_local = false)
{
$ifcfgipv6 = $networkv6 = $subnetbitsv6 = null;
if (interfaces_has_prefix_only($interface) && $allow_track) {
if ($allow_track && !$link_local && interfaces_has_prefix_only($interface)) {
/* extend the search scope for a non-NA mode to tracking interfaces */
$interface = array_merge([$interface], array_keys(link_interface_to_track6($interface)));
}
foreach (interfaces_addresses($interface, false, $ifconfig_details) as $addr) {
if ($addr['family'] != 'inet6' || $addr['deprecated'] || $addr['tentative'] || $addr['alias'] || $addr['scope']) {
if ($addr['family'] != 'inet6' || $addr['deprecated'] || $addr['tentative'] || $addr['alias']) {
continue;
}
if ($link_local && !$addr['scope']) {
continue;
} elseif (!$link_local && $addr['scope']) {
continue;
}
$networkv6 = gen_subnetv6($addr['address'], $addr['bits']) . "/{$addr['bits']}";
$subnetbitsv6 = $addr['bits'];
$ifcfgipv6 = $addr['address'];
if ($link_local) {
$ifcfgipv6 .= "%{$addr['name']}";
}
break; /* all done */
}
return [ $ifcfgipv6, $networkv6, $subnetbitsv6 ];
}
function interfaces_routed_address6($interface, $ifconfig_details = null)
{
/* "routed" returns a non-link-local address only, possiby derived from tracking interfaces */
return _interfaces_primary_address6($interface, $ifconfig_details, true, false);
}
function interfaces_scoped_address6($interface, $ifconfig_details = null)
{
$ifcfgipv6 = $networkv6 = $subnetbitsv6 = null;
foreach (interfaces_addresses($interface, false, $ifconfig_details) as $addr) {
if ($addr['family'] != 'inet6' || $addr['deprecated'] || $addr['tentative'] || $addr['alias'] || !$addr['scope']) {
continue;
}
$networkv6 = gen_subnetv6($addr['address'], $addr['bits']) . "/{$addr['bits']}";
$subnetbitsv6 = $addr['bits'];
$ifcfgipv6 = "{$addr['address']}%{$addr['name']}";
break; /* all done */
}
return [ $ifcfgipv6, $networkv6, $subnetbitsv6 ];
/* "scoped" returns own link-local address only */
return _interfaces_primary_address6($interface, $ifconfig_details, false, true);
}
/* XXX rename "prefix" to "primary" as that is what it is */
function interfaces_prefix_address6($interface, $ifconfig_details = null)
function interfaces_primary_address6($interface, $ifconfig_details = null)
{
/* primary returns preferred local address according to configuration */
$ifcfgipv6 = $networkv6 = $subnetbitsv6 = null;
if (interfaces_has_prefix_only($interface)) {
return interfaces_scoped_address6($interface, $ifconfig_details);
return _interfaces_primary_address6($interface, $ifconfig_details, false, true);
}
return interfaces_primary_address6($interface, $ifconfig_details, false);
return _interfaces_primary_address6($interface, $ifconfig_details, false, false);
}

View File

@ -220,7 +220,7 @@ function dpinger_configure_do($verbose = false, $gwname = null, $bootup = false)
/* link local monitor needs a link local address for the "src" part */
list ($gwifip) = interfaces_scoped_address6($gateway['interface'], $ifconfig_details);
} else {
list ($gwifip) = interfaces_primary_address6($gateway['interface'], $ifconfig_details);
list ($gwifip) = interfaces_routed_address6($gateway['interface'], $ifconfig_details);
}
if (empty($gwifip) && is_ipaddrv6($gateway['gateway'])) {

View File

@ -570,7 +570,7 @@ function ipsec_idinfo_to_cidr(&$idinfo, $addrbits = false, $mode = '')
$mode = $idinfo['mode'];
}
if ($mode == 'tunnel6') {
list (, $network) = interfaces_primary_address6($idinfo['type']);
list (, $network) = interfaces_routed_address6($idinfo['type']);
return $network;
} else {
list (, $network) = interfaces_primary_address($idinfo['type']);

View File

@ -419,7 +419,7 @@ function unbound_add_host_entries($ifconfig_details)
}
list ($laddr) = interfaces_primary_address($interface, $ifconfig_details);
list ($laddr6) = interfaces_primary_address6($interface, $ifconfig_details);
list ($laddr6) = interfaces_routed_address6($interface, $ifconfig_details);
foreach (['4' => $laddr, '6' => $laddr6] as $ip_version => $addr) {
if (empty($addr)) {

View File

@ -62,7 +62,7 @@ if (!isset($config['interfaces'][$interface]['enable'])) {
system_resolver_configure();
$interface_descr = convert_friendly_interface_to_friendly_descr($interface);
list ($ip) = interfaces_prefix_address6($interface);
list ($ip) = interfaces_primary_address6($interface);
if (!is_ipaddr($ip)) {
/* interface is not ready */

View File

@ -89,7 +89,7 @@ foreach ($iflist as $ifname => $ifcfg) {
list ($primary,, $bits) = interfaces_primary_address($ifname, $ifdetails);
$network = "{$primary}/{$bits}";
list ($primary6,, $bits6) = interfaces_prefix_address6($ifname, $ifdetails);
list ($primary6,, $bits6) = interfaces_primary_address6($ifname, $ifdetails);
$network6 = "{$primary6}/{$bits6}";
$tobanner = "{$ifcfg['descr']} ({$realif})";