Revision 09a0164d
src/etc/inc/interfaces.inc | ||
---|---|---|
7593 | 7593 |
} |
7594 | 7594 |
|
7595 | 7595 |
if ($v6addrs) { |
7596 |
// use the first IPv6 GUA address if one exists, otherwise the first address |
|
7597 |
$v6addr = $v6addrs[array_key_first($v6addrs)]; |
|
7596 |
// Group IPv6 addresses by their flags |
|
7597 |
$address_flags = [ |
|
7598 |
'linklocal' => [], |
|
7599 |
'anycast' => [], |
|
7600 |
'tentative' => [], |
|
7601 |
'duplicated' => [], |
|
7602 |
'detached' => [], |
|
7603 |
'deprecated' => [], |
|
7604 |
'autoconf' => [], |
|
7605 |
'temporary' => [], |
|
7606 |
'prefer_source' => [], |
|
7607 |
'no_flag' => [] |
|
7608 |
]; |
|
7609 |
foreach ($v6addrs as $addrs) { |
|
7610 |
$has_flag = false; |
|
7611 |
foreach (array_keys($addrs) as $key) { |
|
7612 |
if (isset($address_flags[$key])) { |
|
7613 |
$has_flag = true; |
|
7614 |
$address_flags[$key][] = $addrs['addr']; |
|
7615 |
} |
|
7616 |
} |
|
7617 |
if (!$has_flag) { |
|
7618 |
$address_flags['no_flag'][] = $addrs['addr']; |
|
7619 |
} |
|
7620 |
} |
|
7621 |
|
|
7622 |
/** |
|
7623 |
* Create a list of IPv6 addresses that prioritizes the most |
|
7624 |
* "valid" source address. Each key in the array references a |
|
7625 |
* group of IPv6 addresses. Each key is assigned the first GUA of |
|
7626 |
* the respective group. If a GUA for the group does not exist, |
|
7627 |
* then the first IPv6 address of the group is assigned. |
|
7628 |
* |
|
7629 |
* A "preferred" address has the prefer_source flag and does not |
|
7630 |
* have any flags considered "invalid". |
|
7631 |
* |
|
7632 |
* A "manual" address does not have any flags. |
|
7633 |
* |
|
7634 |
* A "valid" address does not have any flags considered "invalid". |
|
7635 |
* |
|
7636 |
* An "invalid" address must have any of the following flags: |
|
7637 |
* deprecated, duplicated, tentative, or detached. It may have |
|
7638 |
* additional flags that need to be considered. The selected |
|
7639 |
* address is based on the following flag order: |
|
7640 |
* prefer_source, temporary, anycast, autoconf, deprecated, duplicated |
|
7641 |
* tentative, and lastly detached. |
|
7642 |
* |
|
7643 |
* A "linklocal" address has the linklocal flag. |
|
7644 |
*/ |
|
7645 |
$address_priority_list = [ |
|
7646 |
'preferred' => null, |
|
7647 |
'manual' => null, |
|
7648 |
'valid' => null, |
|
7649 |
'invalid' => null, |
|
7650 |
'linklocal' => null |
|
7651 |
]; |
|
7652 |
// The merge/intersect/diff order here is important. |
|
7653 |
$candidate_addresses = array_unique(array_merge($address_flags['prefer_source'], $address_flags['no_flag'], $address_flags['temporary'], $address_flags['anycast'], $address_flags['autoconf'])); |
|
7654 |
$invalid_addresses = array_unique(array_merge($address_flags['deprecated'], $address_flags['duplicated'], $address_flags['tentative'], $address_flags['detached'])); |
|
7655 |
$invalid_addresses = array_unique(array_merge(array_intersect($candidate_addresses, $invalid_addresses), $invalid_addresses)); |
|
7656 |
$valid_addresses = array_diff($candidate_addresses, $invalid_addresses); |
|
7657 |
|
|
7658 |
// Get a preferred address. |
|
7659 |
$temp_list = []; |
|
7660 |
foreach ($address_flags['prefer_source'] as $address) { |
|
7661 |
if (in_array($address, $valid_addresses)) { |
|
7662 |
if (is_v6gua($address)) { |
|
7663 |
$temp_list = [$address]; |
|
7664 |
break; |
|
7665 |
} else { |
|
7666 |
$temp_list[] = $address; |
|
7667 |
} |
|
7668 |
} |
|
7669 |
} |
|
7670 |
if (!empty($temp_list)) { |
|
7671 |
$address_priority_list['preferred'] = $temp_list[array_key_first($temp_list)]; |
|
7672 |
} |
|
7673 |
|
|
7674 |
// Get a manual address. |
|
7675 |
$temp_list = []; |
|
7676 |
foreach ($address_flags['no_flag'] as $address) { |
|
7677 |
if (is_v6gua($address)) { |
|
7678 |
$temp_list = [$address]; |
|
7679 |
break; |
|
7680 |
} else { |
|
7681 |
$temp_list[] = $address; |
|
7682 |
} |
|
7683 |
} |
|
7684 |
if (!empty($temp_list)) { |
|
7685 |
$address_priority_list['manual'] = $temp_list[array_key_first($temp_list)]; |
|
7686 |
} |
|
7687 |
|
|
7688 |
// Get a valid address. |
|
7689 |
$temp_list = []; |
|
7690 |
foreach ($valid_addresses as $address) { |
|
7691 |
if (is_v6gua($address)) { |
|
7692 |
$temp_list = [$address]; |
|
7693 |
break; |
|
7694 |
} else { |
|
7695 |
$temp_list[] = $address; |
|
7696 |
} |
|
7697 |
} |
|
7698 |
if (!empty($temp_list)) { |
|
7699 |
$address_priority_list['valid'] = $temp_list[array_key_first($temp_list)]; |
|
7700 |
} |
|
7701 |
|
|
7702 |
// Get an invalid address. |
|
7703 |
$temp_list = []; |
|
7704 |
foreach ($invalid_addresses as $address) { |
|
7705 |
if (is_v6gua($address)) { |
|
7706 |
$temp_list = [$address]; |
|
7707 |
break; |
|
7708 |
} else { |
|
7709 |
$temp_list[] = $address; |
|
7710 |
} |
|
7711 |
} |
|
7712 |
if (!empty($temp_list)) { |
|
7713 |
$address_priority_list['invalid'] = $temp_list[array_key_first($temp_list)]; |
|
7714 |
} |
|
7715 |
|
|
7716 |
// Get a link-local address |
|
7717 |
if (!empty($address_flags['linklocal'])) { |
|
7718 |
$address_priority_list['linklocal'] = $address_flags[array_key_first($address_flags['linklocal'])]; |
|
7719 |
} |
|
7720 |
|
|
7721 |
$selected_address = null; |
|
7722 |
if (isset($address_priority_list['preferred']) && is_v6gua($address_priority_list['preferred'])) { |
|
7723 |
$selected_address = $address_priority_list['preferred']; |
|
7724 |
} elseif (isset($address_priority_list['manual']) && is_v6gua($address_priority_list['manual'])) { |
|
7725 |
$selected_address = $address_priority_list['manual']; |
|
7726 |
} elseif (isset($address_priority_list['valid']) && is_v6gua($address_priority_list['valid'])) { |
|
7727 |
$selected_address = $address_priority_list['valid']; |
|
7728 |
} elseif (isset($address_priority_list['preferred'])) { |
|
7729 |
$selected_address = $address_priority_list['preferred']; |
|
7730 |
} elseif (isset($address_priority_list['manual'])) { |
|
7731 |
$selected_address = $address_priority_list['manual']; |
|
7732 |
} elseif (isset($address_priority_list['valid'])) { |
|
7733 |
$selected_address = $address_priority_list['valid']; |
|
7734 |
} elseif (isset($address_priority_list['invalid'])) { |
|
7735 |
$selected_address = $address_priority_list['invalid']; |
|
7736 |
} elseif (isset($address_priority_list['linklocal'])) { |
|
7737 |
$selected_address = $address_priority_list['linklocal']; |
|
7738 |
} else { |
|
7739 |
// Unexpected condition |
|
7740 |
$v6addr = $v6addrs[array_key_first($v6addrs)]; |
|
7741 |
} |
|
7742 |
|
|
7598 | 7743 |
foreach ($v6addrs as $addr) { |
7599 |
if (is_v6gua($addr['addr'])) {
|
|
7744 |
if ($addr['addr'] == $selected_address) {
|
|
7600 | 7745 |
$v6addr = $addr; |
7601 | 7746 |
break; |
7602 | 7747 |
} |
Also available in: Unified diff
Select an interface IPv6 address based on priority