fix: select correct primary IPv6 address whose subnet contains the gateway (#561)

* fix: select correct primary IPv6 address whose subnet contains the gateway

When a system has multiple IPv6 addresses with different prefix lengths
(e.g., /44 and /96), the script previously selected the first address
as primary regardless of whether its subnet contained the default gateway.
This caused the gateway to be unreachable after reinstallation.

This change:
- Adds pure shell expand_ipv6 and ip_addr_contains_gw functions to
  determine which IPv6 subnet contains the gateway (no python dependency)
- Modifies collect_netconf to select the correct primary IPv6 address
- Stores remaining addresses as ipv6_extra_addrs
- Adds extra IPv6 addresses via post-up in create_ifupdown_config

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: address review feedback for IPv6 extra addrs and edge cases

- Pass ipv6_extra_addrs through initrd-network.sh (receive as $7,
  add extra addresses in add_missing_ipv6_config, write to netconf)
  so that trans.sh can read them via get_netconf_to
- Fix cut -c1-0 error when prefix_len < 4 in ip_addr_contains_gw
- Use grep -Fxve for exact string matching instead of regex

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: use subshell for IFS modification to avoid leaking to outer scope

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: avoid global IFS modification when iterating extra IPv6 addresses

Replace subshell IFS trick with tr+while read to split comma-separated
ipv6_extra_addrs, avoiding any modification of the IFS variable.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: use ip route get instead of subnet matching for IPv6 primary address selection

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
kelryry
2026-03-08 22:17:59 +08:00
committed by GitHub
parent ecacaab103
commit 5b0d91c633
3 changed files with 45 additions and 4 deletions

View File

@ -2717,7 +2717,27 @@ collect_netconf() {
eval ipv${v}_ethx="$ethx" # can_use_cloud_kernel 要用
eval ipv${v}_mac="$(ip link show dev $ethx | grep link/ether | head -1 | awk '{print $2}')"
eval ipv${v}_gateway="$gateway"
eval ipv${v}_addr="$(ip -$v -o addr show scope global dev $ethx | grep -v temporary | head -1 | awk '{print $4}')"
# 获取所有全局地址
all_addrs=$(ip -$v -o addr show scope global dev $ethx | grep -v temporary | awk '{print $4}')
primary_addr=$(echo "$all_addrs" | head -1)
# IPv6: 用 ip route get 让内核返回正确的源 IP指定 dev 避免 tun/warp 干扰
if [ "$v" = 6 ] && [ -n "$primary_addr" ]; then
route_src=$(ip -6 route get 2001:4860:4860::8888 dev "$ethx" 2>/dev/null | grep -oP 'src \K[^ ]+')
if [ -n "$route_src" ]; then
for addr in $all_addrs; do
if [ "${addr%/*}" = "$route_src" ]; then
primary_addr=$addr
break
fi
done
fi
fi
eval ipv${v}_addr="$primary_addr"
# extra_addrs: 除主地址外的所有地址
eval ipv${v}_extra_addrs="$(echo "$all_addrs" | grep -Fxve "$primary_addr" | tr '\n' ',' | sed 's/,$//')"
fi
done
fi
@ -3607,13 +3627,13 @@ get_ip_conf_cmd() {
sh=/initrd-network.sh
if is_found_ipv4_netconf && is_found_ipv6_netconf && [ "$ipv4_mac" = "$ipv6_mac" ]; then
echo "'$sh' '$ipv4_mac' '$ipv4_addr' '$ipv4_gateway' '$ipv6_addr' '$ipv6_gateway' '$is_in_china'"
echo "'$sh' '$ipv4_mac' '$ipv4_addr' '$ipv4_gateway' '$ipv6_addr' '$ipv6_gateway' '$is_in_china' '$ipv6_extra_addrs'"
else
if is_found_ipv4_netconf; then
echo "'$sh' '$ipv4_mac' '$ipv4_addr' '$ipv4_gateway' '' '' '$is_in_china'"
echo "'$sh' '$ipv4_mac' '$ipv4_addr' '$ipv4_gateway' '' '' '$is_in_china' ''"
fi
if is_found_ipv6_netconf; then
echo "'$sh' '$ipv6_mac' '' '' '$ipv6_addr' '$ipv6_gateway' '$is_in_china'"
echo "'$sh' '$ipv6_mac' '' '' '$ipv6_addr' '$ipv6_gateway' '$is_in_china' '$ipv6_extra_addrs'"
fi
fi
}