diff --git a/src/etc/inc/interfaces.inc b/src/etc/inc/interfaces.inc index d92d8c9f6..407be955c 100644 --- a/src/etc/inc/interfaces.inc +++ b/src/etc/inc/interfaces.inc @@ -3950,17 +3950,6 @@ function find_interface_networkv6($realif, $subnet = true, $ifconfig_details = n return "{$addr}/${net}"; } -function find_interface_ipv6_ll($realif, $ifconfig_details = null) -{ - $ifinfo = legacy_get_interface_addresses($realif, $ifconfig_details); - - if (!isset($ifinfo['ipaddr6_ll'])) { - return null; - } - - return $ifinfo['ipaddr6_ll']; -} - function ip_in_interface_alias_subnet($interface, $ipalias) { global $config; @@ -4571,7 +4560,42 @@ function interfaces_addresses($interfaces, $as_subnet = false, $ifconfig_details return $result; } -function interfaces_primary_address6($interface, $realif = null, $ifconfig_details = null) +function interfaces_primary_address($interface, $realif = null, $ifconfig_details = null) +{ + $ifcfgip = $network = $subnetbits = null; + + if ($realif === null) { + $realif = get_real_interface($interface); + } + + $interfaces_a = config_read_array('interfaces'); + + foreach (interfaces_addresses($realif, true, $ifconfig_details) as $tmpaddr => $info) { + if ($info['family'] != 'inet') { + continue; + } + + $addrparts = explode('/', $tmpaddr); + + foreach (config_read_array('virtualip', 'vip') as $vip) { + if ($vip['interface'] == $interface && $vip['mode'] == 'ipalias' && strpos($vip['subnet'], ':') === false) { + /* matching alias cannot be primary address */ + if ($vip['subnet'] == $addrparts[0]) { + continue 2; + } + } + } + + $network = gen_subnet($addrparts[0], $addrparts[1]) . "/{$addrparts[1]}"; + $subnetbits = $addrparts[1]; + $ifcfgip = $addrparts[0]; + break; /* all done */ + } + + return [ $ifcfgip, $network, $subnetbits ]; +} + +function interfaces_primary_address6($interface, $realif = null, $ifconfig_details = null, $linklocal = false) { $ifcfgipv6 = $networkv6 = $subnetbitsv6 = null; @@ -4586,7 +4610,7 @@ function interfaces_primary_address6($interface, $realif = null, $ifconfig_detai continue; } - if (!isset($interfaces_a[$interface]['dhcp6prefixonly'])) { + if (!isset($interfaces_a[$interface]['dhcp6prefixonly']) && !$linklocal) { if ($info['scope']) { continue; } @@ -4614,8 +4638,16 @@ function interfaces_primary_address6($interface, $realif = null, $ifconfig_detai $networkv6 = gen_subnetv6($addrparts[0], $addrparts[1]) . "/{$addrparts[1]}"; $subnetbitsv6 = $addrparts[1]; $ifcfgipv6 = $addrparts[0]; + if ($linklocal) { + $ifcfgipv6 .= "%{$realif}"; + } break; /* all done */ } return [ $ifcfgipv6, $networkv6, $subnetbitsv6 ]; } + +function interfaces_linklocal_address6($interface, $realif = null, $ifconfig_details = null) +{ + return interfaces_primary_address6($interface, $realif, $ifconfig_details, true); +} diff --git a/src/etc/inc/plugins.inc.d/dpinger.inc b/src/etc/inc/plugins.inc.d/dpinger.inc index 3f151d64c..3575f8d42 100644 --- a/src/etc/inc/plugins.inc.d/dpinger.inc +++ b/src/etc/inc/plugins.inc.d/dpinger.inc @@ -175,14 +175,13 @@ function dpinger_configure_do($verbose = false, $gwname = null) } elseif ($gateway['ipprotocol'] == "inet6") { // This is an IPv6 gateway... if (is_linklocal($gateway['monitor'])) { /* link local monitor needs a link local address for the "src" part */ - $gwifip = find_interface_ipv6_ll($gateway['if'], $ifconfig_details); + $gwifip = interfaces_linklocal_address6($gateway['if'], null, $ifconfig_details); } else { - /* monitor is a routable address, so use a routable address for the "src" part */ - $gwifip = find_interface_ipv6($gateway['if'], $ifconfig_details); + $gwifip = interfaces_primary_address6($gateway['if'], null, $ifconfig_details); } - if (!is_ipaddrv6($gwifip)) { - log_error(sprintf('The %s IPv6 gateway address is invalid, skipping.', $name)); + if (empty($gwifip)) { + log_error(sprintf('The %s IPv6 gateway address could not be found, skipping.', $name)); continue; } @@ -196,9 +195,6 @@ function dpinger_configure_do($verbose = false, $gwname = null) if (is_linklocal($gateway['gateway']) && strpos($gateway['gateway'], '%') === false) { $gateway['gateway'] .= "%{$gateway['if']}"; } - if (is_linklocal($gwifip) && strpos($gwifip, '%') === false) { - $gwifip .= "%{$gateway['if']}"; - } /* flush the monitor unconditionally */ if (is_ipaddrv6($gateway['gateway']) && $gateway['monitor'] != $gateway['gateway']) { diff --git a/src/etc/inc/plugins.inc.d/unbound.inc b/src/etc/inc/plugins.inc.d/unbound.inc index d9144fe6d..0ffe07f23 100644 --- a/src/etc/inc/plugins.inc.d/unbound.inc +++ b/src/etc/inc/plugins.inc.d/unbound.inc @@ -513,11 +513,8 @@ function unbound_add_host_entries($ifconfig_details = null) continue; } - $realifv4 = get_real_interface($interface); - $realifv6 = get_real_interface($interface, 'inet6'); - - $laddr = find_interface_ip($realifv4, $ifconfig_details); - if (is_ipaddrv4($laddr)) { + list ($laddr) = interfaces_primary_address($interface, null, $ifconfig_details); + if (!empty($laddr)) { $domain = $config['system']['domain']; if (isset($config['dhcpd'][$interface]['enable']) && !empty($config['dhcpd'][$interface]['domain'])) { $domain = $config['dhcpd'][$interface]['domain']; @@ -526,8 +523,8 @@ function unbound_add_host_entries($ifconfig_details = null) $unbound_entries .= "local-data: \"{$config['system']['hostname']}.{$domain} A {$laddr}\"\n"; $unbound_entries .= "local-data: \"{$config['system']['hostname']} A {$laddr}\"\n"; } - $laddr6 = find_interface_ipv6($realifv6, $ifconfig_details); - if (is_ipaddrv6($laddr6)) { + list ($laddr6) = interfaces_primary_address6($interface, null, $ifconfig_details); + if (!empty($laddr6)) { $domain = $config['system']['domain']; if (isset($config['dhcpdv6'][$interface]['enable']) && !empty($config['dhcpdv6'][$interface]['domain'])) { $domain = $config['dhcpdv6'][$interface]['domain']; @@ -537,8 +534,10 @@ function unbound_add_host_entries($ifconfig_details = null) $unbound_entries .= "local-data: \"{$config['system']['hostname']} AAAA {$laddr6}\"\n"; } if (empty($config['unbound']['noreglladdr6'])) { - $lladdr6 = find_interface_ipv6_ll($realifv6, $ifconfig_details); - if (is_ipaddrv6($lladdr6)) { + list ($lladdr6) = interfaces_linklocal_address6($interface, null, $ifconfig_details); + if (!empty($lladdr6)) { + /* cannot embed scope */ + $lladdr6 = explode('%', $lladdr6)[0]; $domain = $config['system']['domain']; if (isset($config['dhcpdv6'][$interface]['enable']) && !empty($config['dhcpdv6'][$interface]['domain'])) { $domain = $config['dhcpdv6'][$interface]['domain']; diff --git a/src/etc/rc.filter_synchronize b/src/etc/rc.filter_synchronize index bd3f38f67..323b86890 100755 --- a/src/etc/rc.filter_synchronize +++ b/src/etc/rc.filter_synchronize @@ -2,35 +2,35 @@ - Copyright (C) 2005 Bill Marquette - Copyright (C) 2006 Peter Allgeyer - Copyright (C) 2008 Ermal Luçi - Copyright (C) 2003-2004 Manuel Kasper - 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. -*/ + * Copyright (C) 2016 Deciso B.V. + * Copyright (C) 2004-2006 Scott Ullrich + * Copyright (C) 2005 Bill Marquette + * Copyright (C) 2006 Peter Allgeyer + * Copyright (C) 2008 Ermal Luçi + * Copyright (C) 2003-2004 Manuel Kasper + * 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. + */ require_once("config.inc"); require_once("filter.inc"); @@ -187,7 +187,7 @@ function carp_sync_xml($url, $username, $password, $sections, $debug) foreach($transport_data['dhcpd'] as $dhcpif => $dhcpifconf) { if (isset($dhcpifconf['failover_peerip']) && $dhcpifconf['failover_peerip'] != '') { $int = guess_interface_from_ip($dhcpifconf['failover_peerip']); - $intip = find_interface_ip($int); + $intip = interfaces_primary_address($int); $transport_data['dhcpd'][$dhcpif]['failover_peerip'] = $intip; } } diff --git a/src/www/diag_ping.php b/src/www/diag_ping.php index 1e015a8f2..7a00f4ef1 100644 --- a/src/www/diag_ping.php +++ b/src/www/diag_ping.php @@ -58,11 +58,10 @@ if ($_SERVER['REQUEST_METHOD'] === 'GET') { break; case 'ipv6-ll': $command .= '6'; - $realif = get_real_interface($pconfig['interface'], 'inet6'); - $ifaddr = find_interface_ipv6_ll($realif) . "%{$realif}"; + list ($ifaddr) = interfaces_linklocal_address6($pconfig['interface']); break; default: - $ifaddr = find_interface_ip(get_real_interface($pconfig['interface'])); + list ($ifaddr) = interfaces_primary_address($pconfig['interface']); break; } $srcip = ''; diff --git a/src/www/diag_testport.php b/src/www/diag_testport.php index 984adb306..b04491279 100644 --- a/src/www/diag_testport.php +++ b/src/www/diag_testport.php @@ -75,16 +75,15 @@ if ($_SERVER['REQUEST_METHOD'] === 'GET') { switch ($pconfig['ipprotocol']) { case 'ipv6': list ($ifaddr) = interfaces_primary_address6($pconfig['interface']); - $nc_args .= " -6"; + $nc_args .= ' -6'; break; case 'ipv6-ll': - $realif = get_real_interface($pconfig['interface'], 'inet6'); - $ifaddr = find_interface_ipv6_ll($realif) . "%{$realif}"; - $nc_args .= " -6"; + list ($ifaddr) = interfaces_linklocal_address6($pconfig['interface']); + $nc_args .= ' -6'; break; default: - $ifaddr = find_interface_ip(get_real_interface($pconfig['interface'])); - $nc_args .= " -4"; + list ($ifaddr) = interfaces_primary_address($pconfig['interface']); + $nc_args .= ' -4'; break; } @@ -92,7 +91,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'GET') { $nc_args .= exec_safe(' -s %s ', $ifaddr); } - $cmd_action = exec_safe("/usr/bin/nc {$nc_args} %s %s", array($pconfig['host'], $pconfig['port'])); + $cmd_action = "/usr/bin/nc {$nc_args} " . exec_safe('%s %s', [$pconfig['host'], $pconfig['port']]); $process = proc_open($cmd_action, array(array("pipe", "r"), array("pipe", "w"), array("pipe", "w")), $pipes); if (is_resource($process)) { $cmd_output = "# $cmd_action\n"; diff --git a/src/www/diag_traceroute.php b/src/www/diag_traceroute.php index 097bb5b42..26818e619 100644 --- a/src/www/diag_traceroute.php +++ b/src/www/diag_traceroute.php @@ -77,7 +77,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'GET') { list ($ifaddr) = interfaces_primary_address6($pconfig['interface']); $command .= '6'; } else { - $ifaddr = find_interface_ip(get_real_interface($pconfig['interface'])); + list ($ifaddr) = interfaces_primary_address($pconfig['interface']); } if (is_ipaddr($ifaddr) && (is_ipaddr($host) || is_hostname($host))) {