#!/usr/bin/env bash
#
# add_ips.sh - Linux 多发行版 IP 地址配置工具_by豆芽
#
# 支持发行版: CentOS 7/8/9, Rocky Linux 8/9, AlmaLinux 8/9,
#              Ubuntu 16.04/18.04/20.04/22.04/24.04,
#              Debian 10/11/12/13
#
# 功能:
#   - 为当前服务器添加多个附加 IPv4 / IPv6 地址
#   - IPv4: 支持单个 IP、多个 IP(空格分隔)、IP 范围(如 192.168.2.2-254)
#   - IPv6: 支持单个或多个 IPv6 地址(空格分隔)，默认前缀 /64，可选网关
#   - 添加 IPv6 前自动检查并启用系统 IPv6 支持
#   - 智能识别主网卡和已有网络配置
#   - 支持 CIDR 掩码位(/24) 和完整掩码格式(255.255.255.0)，默认 /24
#   - 自动备份原网络配置文件
#

set -euo pipefail

# ========================= 颜色定义 =========================
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
NC='\033[0m' # No Color

# 显示欢迎信息
show_welcome() {
    echo "================================================================="
    echo "               Linux多发行版IP地址配置工具 - By豆芽             "
    echo "================================================================="
    echo "功能说明:"
    echo "1. 支持为当前服务器批量添加附加IP地址"
    echo "2. 支持多种Linux发行版:"
    echo "   - CentOS 7/8/9, Rocky Linux 8/9"
    echo "   - Ubuntu 16.04/18.04/20.04/22.04/24.04"
    echo "   - Debian 10/11/12/13"
    echo "3. 智能识别主网卡和网络配置"
    echo "4. 自动检测已存在子网卡，智能分配新子网卡编号"
    echo "5. 支持批量输入IP地址，格式: 192.168.1.2 192.168.1.3"
    echo "6. 不输入掩码位则默认使用 /24"
    echo "7. 自动备份原配置文件"
    echo "================================================================="
    echo
}

# ========================= 全局变量 =========================
BACKUP_DIR="/root/network_backup/$(date +%Y%m%d_%H%M%S)"
LOG_FILE="/var/log/add_ips_$(date +%Y%m%d_%H%M%S).log"
DISTRO=""
DISTRO_VERSION=""
DISTRO_MAJOR=""
NET_MANAGER=""    # networkd / NetworkManager / ifupdown / network-scripts
PRIMARY_IFACE=""
GATEWAY=""
DNS_SERVERS=""

# IPv6 全局变量
IPV6_MODE=false
IPV6_GATEWAY=""

# ========================= 日志函数 =========================
log() {
    local msg="[$(date '+%Y-%m-%d %H:%M:%S')] $*"
    echo "$msg" >> "$LOG_FILE" 2>/dev/null || true
}

info() {
    echo -e "${GREEN}[INFO]${NC} $*"
    log "INFO: $*"
}

warn() {
    echo -e "${YELLOW}[WARN]${NC} $*"
    log "WARN: $*"
}

error() {
    echo -e "${RED}[ERROR]${NC} $*" >&2
    log "ERROR: $*"
}

die() {
    error "$@"
    exit 1
}

# ========================= 权限检查 =========================
check_root() {
    if [[ $EUID -ne 0 ]]; then
        die "此脚本需要 root 权限运行，请使用 sudo 或切换到 root 用户"
    fi
}

# ========================= 发行版检测 =========================
detect_distro() {
    if [[ ! -f /etc/os-release ]]; then
        die "无法检测发行版: /etc/os-release 不存在"
    fi

    source /etc/os-release

    local id="${ID,,}"
    local version="${VERSION_ID:-}"

    case "$id" in
        centos)
            DISTRO="centos"
            ;;
        rocky)
            DISTRO="rocky"
            ;;
        almalinux)
            DISTRO="almalinux"
            ;;
        rhel)
            DISTRO="rhel"
            ;;
        ubuntu)
            DISTRO="ubuntu"
            ;;
        debian)
            DISTRO="debian"
            ;;
        *)
            # 检查 ID_LIKE 字段
            local id_like="${ID_LIKE:-}"
            if [[ "$id_like" == *"rhel"* ]] || [[ "$id_like" == *"centos"* ]] || [[ "$id_like" == *"fedora"* ]]; then
                DISTRO="rhel_like"
            elif [[ "$id_like" == *"ubuntu"* ]] || [[ "$id_like" == *"debian"* ]]; then
                DISTRO="debian_like"
            else
                die "不支持的发行版: $id (ID_LIKE: $id_like)"
            fi
            ;;
    esac

    DISTRO_VERSION="$version"
    DISTRO_MAJOR="${version%%.*}"

    info "检测到发行版: ${PRETTY_NAME:-$id $version}"
}

# ========================= 网络管理器检测 =========================
detect_net_manager() {
    case "$DISTRO" in
        centos|rhel|rhel_like)
            if [[ "$DISTRO_MAJOR" -le 7 ]]; then
                NET_MANAGER="network-scripts"
            else
                # CentOS/RHEL 8+: 优先检查是否存在 network-scripts 配置文件
                # 虽然使用 NetworkManager 服务，但配置可能仍存储在 network-scripts 目录
                if [[ -d /etc/sysconfig/network-scripts ]] && \
                   ls /etc/sysconfig/network-scripts/ifcfg-* &>/dev/null; then
                    NET_MANAGER="network-scripts"
                elif systemctl is-active --quiet NetworkManager 2>/dev/null; then
                    NET_MANAGER="NetworkManager"
                else
                    NET_MANAGER="network-scripts"
                fi
            fi
            ;;
        rocky|almalinux)
            # Rocky/AlmaLinux 8+: 优先检查是否存在 network-scripts 配置文件
            if [[ -d /etc/sysconfig/network-scripts ]] && \
               ls /etc/sysconfig/network-scripts/ifcfg-* &>/dev/null; then
                NET_MANAGER="network-scripts"
            elif systemctl is-active --quiet NetworkManager 2>/dev/null; then
                NET_MANAGER="NetworkManager"
            else
                NET_MANAGER="network-scripts"
            fi
            ;;
        ubuntu)
            if [[ -d /etc/netplan ]] && ls /etc/netplan/*.yaml &>/dev/null; then
                NET_MANAGER="netplan"
            elif systemctl is-active --quiet NetworkManager 2>/dev/null; then
                NET_MANAGER="NetworkManager"
            elif [[ -f /etc/network/interfaces ]]; then
                NET_MANAGER="ifupdown"
            else
                NET_MANAGER="netplan"
            fi
            ;;
        debian|debian_like)
            # Debian 网络管理器检测说明:
            # - Debian 10+ 默认使用 netplan，但某些安装(如最小化安装、从旧版本升级)可能仍使用 ifupdown
            # - 优先检测 netplan: 检查 /etc/netplan 目录是否存在且包含 .yaml 配置文件
            # - 其次检测 NetworkManager: 检查服务是否运行
            # - 最后回退到 ifupdown: 检查 /etc/network/interfaces 文件是否存在
            if [[ -d /etc/netplan ]] && ls /etc/netplan/*.yaml &>/dev/null; then
                NET_MANAGER="netplan"
            elif systemctl is-active --quiet NetworkManager 2>/dev/null; then
                NET_MANAGER="NetworkManager"
            elif [[ -f /etc/network/interfaces ]]; then
                NET_MANAGER="ifupdown"
            else
                # 默认回退到 ifupdown
                NET_MANAGER="ifupdown"
            fi
            ;;
    esac

    info "网络管理器: $NET_MANAGER"
}

# ========================= 主网卡检测 =========================
detect_primary_iface() {
    # 方法1: 通过默认路由获取
    PRIMARY_IFACE=$(ip route show default 2>/dev/null | awk '/default/ {print $5; exit}')

    # 方法2: 获取第一个非 lo 的 UP 状态接口
    if [[ -z "$PRIMARY_IFACE" ]]; then
        PRIMARY_IFACE=$(ip -o link show up 2>/dev/null | awk -F': ' '!/lo/{print $2; exit}')
    fi

    # 方法3: 从 /sys/class/net 获取
    if [[ -z "$PRIMARY_IFACE" ]]; then
        for iface in /sys/class/net/*; do
            local name
            name=$(basename "$iface")
            if [[ "$name" != "lo" ]] && [[ "$(cat "$iface/operstate" 2>/dev/null)" == "up" ]]; then
                PRIMARY_IFACE="$name"
                break
            fi
        done
    fi

    if [[ -z "$PRIMARY_IFACE" ]]; then
        die "无法自动检测主网卡，请检查网络配置"
    fi

    # 获取网关信息
    GATEWAY=$(ip route show default 2>/dev/null | awk '/default/ {print $3; exit}')

    # 获取 DNS 信息
    if [[ -f /etc/resolv.conf ]]; then
        DNS_SERVERS=$(awk '/^nameserver/ {print $2}' /etc/resolv.conf | head -3 | tr '\n' ',' | sed 's/,$//')
    fi

    local current_ips
    current_ips=$(ip -4 addr show dev "$PRIMARY_IFACE" 2>/dev/null | awk '/inet / {print $2}')

    info "主网卡: $PRIMARY_IFACE"
    info "网关: ${GATEWAY:-未检测到}"
    [[ -n "$DNS_SERVERS" ]] && info "DNS: $DNS_SERVERS"
    info "当前 IP 地址:"
    while IFS= read -r ip; do
        [[ -n "$ip" ]] && info "  $ip"
    done <<< "$current_ips"
}

# ========================= IP 地址验证 =========================
validate_ip() {
    local ip="$1"
    local IFS='.'
    read -ra octets <<< "$ip"

    if [[ ${#octets[@]} -ne 4 ]]; then
        return 1
    fi

    for octet in "${octets[@]}"; do
        if ! [[ "$octet" =~ ^[0-9]+$ ]] || [[ "$octet" -lt 0 ]] || [[ "$octet" -gt 255 ]]; then
            return 1
        fi
    done
    return 0
}

# ========================= IPv6 地址验证 =========================
validate_ipv6() {
    local ip="$1"

    # 基本检查
    if [[ -z "$ip" ]] || [[ "$ip" != *":"* ]]; then
        return 1
    fi

    # 优先使用 Python 进行精确验证
    if command -v python3 &>/dev/null; then
        python3 -c "import ipaddress; ipaddress.IPv6Address('$ip')" 2>/dev/null
        return $?
    fi

    # 简化验证：只允许合法的 IPv6 字符
    if [[ ! "$ip" =~ ^[0-9a-fA-F:]+$ ]]; then
        return 1
    fi

    # 检查 :: 只能出现一次或零次
    local compress_count
    compress_count=$(echo "$ip" | grep -o '::' | wc -l)
    if [[ "$compress_count" -gt 1 ]]; then
        return 1
    fi

    # 统计段数（通过 : 分割）
    local segment_count
    segment_count=$(echo "$ip" | grep -o ':' | wc -l)

    # 最多 7 个冒号（8段），加上 :: 的情况
    if [[ "$compress_count" -eq 0 ]] && [[ "$segment_count" -ne 7 ]]; then
        return 1
    fi

    if [[ "$segment_count" -gt 8 ]]; then
        return 1
    fi

    # 检查每段长度不超过 4 个十六进制字符
    local IFS=':'
    read -ra segments <<< "$ip"
    for seg in "${segments[@]}"; do
        if [[ "${#seg}" -gt 4 ]]; then
            return 1
        fi
    done

    return 0
}

# ========================= IPv6 前缀解析 =========================
parse_ipv6_prefix() {
    local input="$1"

    # 空输入默认 /64
    if [[ -z "$input" ]]; then
        echo "64"
        return 0
    fi

    # 去掉前导 /
    input="${input#/}"

    # 纯数字（CIDR）
    if [[ "$input" =~ ^[0-9]+$ ]]; then
        if [[ "$input" -ge 1 ]] && [[ "$input" -le 128 ]]; then
            echo "$input"
            return 0
        else
            error "无效的 IPv6 前缀长度: /$input (有效范围: 1-128)"
            return 1
        fi
    fi

    error "无法识别的 IPv6 前缀格式: $input"
    return 1
}

# ========================= 解析 IPv6 输入 =========================
# 使用全局变量 PARSE_IP_RESULT 返回结果
parse_ipv6_input() {
    local input="$1"
    PARSE_IP_RESULT=()

    # 支持空格、逗号、分号分隔
    local cleaned
    cleaned=$(echo "$input" | tr ';' ' ' | tr ',' ' ')

    read -ra segments <<< "$cleaned"

    for segment in "${segments[@]}"; do
        segment=$(echo "$segment" | xargs) # trim 空白
        [[ -z "$segment" ]] && continue

        if validate_ipv6 "$segment"; then
            PARSE_IP_RESULT+=("$segment")
        else
            error "无效的 IPv6 地址: $segment"
            return 1
        fi
    done

    if [[ ${#PARSE_IP_RESULT[@]} -eq 0 ]]; then
        error "未解析到任何有效 IPv6 地址"
        return 1
    fi

    return 0
}

# ========================= 检查并启用 IPv6 支持 =========================
check_and_enable_ipv6() {
    info "检查系统 IPv6 支持状态..."

    # 检查当前 IPv6 是否已启用
    local ipv6_disabled=1
    if [[ -f /proc/sys/net/ipv6/conf/all/disable_ipv6 ]]; then
        ipv6_disabled=$(cat /proc/sys/net/ipv6/conf/all/disable_ipv6 2>/dev/null || echo "1")
    fi

    if [[ "$ipv6_disabled" == "0" ]]; then
        info "系统 IPv6 已启用"
        return 0
    fi

    warn "系统 IPv6 未启用，正在尝试启用..."

    case "$DISTRO" in
        centos|rhel)
            if [[ "$DISTRO_MAJOR" -le 7 ]]; then
                # CentOS 7 / RHEL 7
                info "为 CentOS 7 / RHEL 7 启用 IPv6..."

                # 修改 /etc/sysctl.conf
                if ! grep -q '^net.ipv6.conf.all.disable_ipv6=0' /etc/sysctl.conf 2>/dev/null; then
                    # 移除旧的 disable 配置
                    sed -i '/net.ipv6.conf.all.disable_ipv6/d' /etc/sysctl.conf 2>/dev/null || true
                    echo "net.ipv6.conf.all.disable_ipv6=0" >> /etc/sysctl.conf
                    info "已设置 /etc/sysctl.conf: net.ipv6.conf.all.disable_ipv6=0"
                fi
                if ! grep -q '^net.ipv6.conf.default.disable_ipv6=0' /etc/sysctl.conf 2>/dev/null; then
                    sed -i '/net.ipv6.conf.default.disable_ipv6/d' /etc/sysctl.conf 2>/dev/null || true
                    echo "net.ipv6.conf.default.disable_ipv6=0" >> /etc/sysctl.conf
                    info "已设置 /etc/sysctl.conf: net.ipv6.conf.default.disable_ipv6=0"
                fi

                # 修改 /etc/sysconfig/network
                if [[ -f /etc/sysconfig/network ]]; then
                    if ! grep -q '^NETWORKING_IPV6=yes' /etc/sysconfig/network 2>/dev/null; then
                        sed -i '/NETWORKING_IPV6/d' /etc/sysconfig/network 2>/dev/null || true
                        echo "NETWORKING_IPV6=yes" >> /etc/sysconfig/network
                        info "已设置 /etc/sysconfig/network: NETWORKING_IPV6=yes"
                    fi
                    if ! grep -q '^IPV6INIT=yes' /etc/sysconfig/network 2>/dev/null; then
                        sed -i '/IPV6INIT/d' /etc/sysconfig/network 2>/dev/null || true
                        echo "IPV6INIT=yes" >> /etc/sysconfig/network
                        info "已设置 /etc/sysconfig/network: IPV6INIT=yes"
                    fi
                else
                    echo -e "NETWORKING_IPV6=yes\nIPV6INIT=yes" > /etc/sysconfig/network
                    info "已创建 /etc/sysconfig/network 并启用 IPv6"
                fi

                sysctl -p 2>/dev/null || true
            else
                # CentOS 8+ / RHEL 8+
                info "为 CentOS 8+ / RHEL 8+ 启用 IPv6..."
                echo 0 | tee /proc/sys/net/ipv6/conf/all/disable_ipv6 2>/dev/null || true
                echo 0 | tee /proc/sys/net/ipv6/conf/default/disable_ipv6 2>/dev/null || true

                # 永久生效
                if ! grep -q '^net.ipv6.conf.all.disable_ipv6=0' /etc/sysctl.conf 2>/dev/null; then
                    sed -i '/net.ipv6.conf.all.disable_ipv6/d' /etc/sysctl.conf 2>/dev/null || true
                    echo "net.ipv6.conf.all.disable_ipv6=0" >> /etc/sysctl.conf
                fi
                if ! grep -q '^net.ipv6.conf.default.disable_ipv6=0' /etc/sysctl.conf 2>/dev/null; then
                    sed -i '/net.ipv6.conf.default.disable_ipv6/d' /etc/sysctl.conf 2>/dev/null || true
                    echo "net.ipv6.conf.default.disable_ipv6=0" >> /etc/sysctl.conf
                fi
                sysctl -p 2>/dev/null || true
            fi
            ;;
        rocky|almalinux)
            # Rocky Linux / AlmaLinux 8+
            info "为 Rocky Linux / AlmaLinux 启用 IPv6..."
            echo 0 | tee /proc/sys/net/ipv6/conf/all/disable_ipv6 2>/dev/null || true
            echo 0 | tee /proc/sys/net/ipv6/conf/default/disable_ipv6 2>/dev/null || true

            if ! grep -q '^net.ipv6.conf.all.disable_ipv6=0' /etc/sysctl.conf 2>/dev/null; then
                sed -i '/net.ipv6.conf.all.disable_ipv6/d' /etc/sysctl.conf 2>/dev/null || true
                echo "net.ipv6.conf.all.disable_ipv6=0" >> /etc/sysctl.conf
            fi
            if ! grep -q '^net.ipv6.conf.default.disable_ipv6=0' /etc/sysctl.conf 2>/dev/null; then
                sed -i '/net.ipv6.conf.default.disable_ipv6/d' /etc/sysctl.conf 2>/dev/null || true
                echo "net.ipv6.conf.default.disable_ipv6=0" >> /etc/sysctl.conf
            fi
            sysctl -p 2>/dev/null || true
            ;;
        ubuntu|debian|debian_like)
            info "为 Ubuntu/Debian 启用 IPv6..."
            echo 0 | tee /proc/sys/net/ipv6/conf/all/disable_ipv6 2>/dev/null || true
            echo 0 | tee /proc/sys/net/ipv6/conf/default/disable_ipv6 2>/dev/null || true

            if ! grep -q '^net.ipv6.conf.all.disable_ipv6=0' /etc/sysctl.conf 2>/dev/null; then
                sed -i '/net.ipv6.conf.all.disable_ipv6/d' /etc/sysctl.conf 2>/dev/null || true
                echo "net.ipv6.conf.all.disable_ipv6=0" | tee -a /etc/sysctl.conf >/dev/null
            fi
            if ! grep -q '^net.ipv6.conf.default.disable_ipv6=0' /etc/sysctl.conf 2>/dev/null; then
                sed -i '/net.ipv6.conf.default.disable_ipv6/d' /etc/sysctl.conf 2>/dev/null || true
                echo "net.ipv6.conf.default.disable_ipv6=0" | tee -a /etc/sysctl.conf >/dev/null
            fi
            sysctl -p 2>/dev/null || true
            ;;
        rhel_like)
            info "为 RHEL-like 发行版启用 IPv6..."
            echo 0 | tee /proc/sys/net/ipv6/conf/all/disable_ipv6 2>/dev/null || true
            echo 0 | tee /proc/sys/net/ipv6/conf/default/disable_ipv6 2>/dev/null || true

            if ! grep -q '^net.ipv6.conf.all.disable_ipv6=0' /etc/sysctl.conf 2>/dev/null; then
                sed -i '/net.ipv6.conf.all.disable_ipv6/d' /etc/sysctl.conf 2>/dev/null || true
                echo "net.ipv6.conf.all.disable_ipv6=0" >> /etc/sysctl.conf
            fi
            if ! grep -q '^net.ipv6.conf.default.disable_ipv6=0' /etc/sysctl.conf 2>/dev/null; then
                sed -i '/net.ipv6.conf.default.disable_ipv6/d' /etc/sysctl.conf 2>/dev/null || true
                echo "net.ipv6.conf.default.disable_ipv6=0" >> /etc/sysctl.conf
            fi
            sysctl -p 2>/dev/null || true
            ;;
        *)
            warn "未识别的发行版，尝试通用方式启用 IPv6..."
            echo 0 | tee /proc/sys/net/ipv6/conf/all/disable_ipv6 2>/dev/null || true
            echo 0 | tee /proc/sys/net/ipv6/conf/default/disable_ipv6 2>/dev/null || true

            if ! grep -q '^net.ipv6.conf.all.disable_ipv6=0' /etc/sysctl.conf 2>/dev/null; then
                echo "net.ipv6.conf.all.disable_ipv6=0" >> /etc/sysctl.conf 2>/dev/null || true
            fi
            if ! grep -q '^net.ipv6.conf.default.disable_ipv6=0' /etc/sysctl.conf 2>/dev/null; then
                echo "net.ipv6.conf.default.disable_ipv6=0" >> /etc/sysctl.conf 2>/dev/null || true
            fi
            sysctl -p 2>/dev/null || true
            ;;
    esac

    # 重新检查
    local ipv6_disabled_after
    ipv6_disabled_after=$(cat /proc/sys/net/ipv6/conf/all/disable_ipv6 2>/dev/null || echo "1")
    if [[ "$ipv6_disabled_after" != "0" ]]; then
        die "无法启用 IPv6 支持，请手动检查系统配置"
    fi

    info "IPv6 支持已成功启用"
}

# ========================= 掩码转换 =========================
# 完整掩码转 CIDR
mask_to_cidr() {
    local mask="$1"
    local cidr=0
    local IFS='.'
    read -ra octets <<< "$mask"

    for octet in "${octets[@]}"; do
        case $octet in
            255) cidr=$((cidr + 8)) ;;
            254) cidr=$((cidr + 7)) ;;
            252) cidr=$((cidr + 6)) ;;
            248) cidr=$((cidr + 5)) ;;
            240) cidr=$((cidr + 4)) ;;
            224) cidr=$((cidr + 3)) ;;
            192) cidr=$((cidr + 2)) ;;
            128) cidr=$((cidr + 1)) ;;
            0) ;;
            *) echo ""; return 1 ;;
        esac
    done
    echo "$cidr"
}

# CIDR 转完整掩码
cidr_to_mask() {
    local cidr="$1"
    local mask=""
    local full_octets=$((cidr / 8))
    local partial=$((cidr % 8))

    for ((i = 0; i < 4; i++)); do
        if [[ $i -lt $full_octets ]]; then
            mask+="255"
        elif [[ $i -eq $full_octets ]]; then
            mask+="$((256 - (1 << (8 - partial))))"
        else
            mask+="0"
        fi
        [[ $i -lt 3 ]] && mask+="."
    done
    echo "$mask"
}

# ========================= 解析掩码输入 =========================
parse_mask() {
    local input="$1"

    # 空输入默认 /24
    if [[ -z "$input" ]]; then
        echo "24"
        return 0
    fi

    # 去掉前导 /
    input="${input#/}"

    # 如果是纯数字(CIDR)
    if [[ "$input" =~ ^[0-9]+$ ]]; then
        if [[ "$input" -ge 1 ]] && [[ "$input" -le 32 ]]; then
            echo "$input"
            return 0
        else
            error "无效的 CIDR 掩码位: /$input (有效范围: 1-32)"
            return 1
        fi
    fi

    # 如果是完整掩码格式
    if [[ "$input" =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
        local cidr
        cidr=$(mask_to_cidr "$input")
        if [[ -n "$cidr" ]]; then
            echo "$cidr"
            return 0
        else
            error "无效的子网掩码: $input"
            return 1
        fi
    fi

    error "无法识别的掩码格式: $input"
    return 1
}

# ========================= 解析 IP 输入 =========================
# 使用全局变量 PARSE_IP_RESULT 返回结果（兼容 Bash 4.2）
parse_ip_input() {
    local input="$1"
    PARSE_IP_RESULT=()

    # 支持空格、逗号、分号分隔
    local cleaned
    cleaned=$(echo "$input" | tr ';' ' ' | tr ',' ' ')

    read -ra segments <<< "$cleaned"

    for segment in "${segments[@]}"; do
        segment=$(echo "$segment" | xargs) # trim 空白
        [[ -z "$segment" ]] && continue

        # 检查是否是 IP 范围格式: 192.168.2.2-254
        if [[ "$segment" =~ ^([0-9]+\.[0-9]+\.[0-9]+\.)([0-9]+)-([0-9]+)$ ]]; then
            local prefix="${BASH_REMATCH[1]}"
            local start="${BASH_REMATCH[2]}"
            local end="${BASH_REMATCH[3]}"

            if [[ "$start" -gt "$end" ]]; then
                error "IP 范围起始值($start)大于结束值($end): $segment"
                return 1
            fi

            if [[ "$start" -lt 1 ]] || [[ "$end" -gt 254 ]]; then
                error "IP 范围超出有效主机地址范围(1-254): $segment"
                return 1
            fi

            for ((i = start; i <= end; i++)); do
                local ip="${prefix}${i}"
                if validate_ip "$ip"; then
                    PARSE_IP_RESULT+=("$ip")
                else
                    error "生成的 IP 地址无效: $ip"
                    return 1
                fi
            done

        # 完整范围格式: 192.168.2.2-192.168.2.254
        elif [[ "$segment" =~ ^([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)-([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)$ ]]; then
            local start_ip="${BASH_REMATCH[1]}"
            local end_ip="${BASH_REMATCH[2]}"

            if ! validate_ip "$start_ip" || ! validate_ip "$end_ip"; then
                error "IP 范围中包含无效地址: $segment"
                return 1
            fi

            # 确保前三段一致
            local start_prefix end_prefix
            start_prefix=$(echo "$start_ip" | cut -d. -f1-3)
            end_prefix=$(echo "$end_ip" | cut -d. -f1-3)

            if [[ "$start_prefix" != "$end_prefix" ]]; then
                error "IP 范围必须在同一个 /24 网段内: $segment"
                return 1
            fi

            local start_last end_last
            start_last=$(echo "$start_ip" | cut -d. -f4)
            end_last=$(echo "$end_ip" | cut -d. -f4)

            if [[ "$start_last" -gt "$end_last" ]]; then
                error "IP 范围起始地址大于结束地址: $segment"
                return 1
            fi

            for ((i = start_last; i <= end_last; i++)); do
                PARSE_IP_RESULT+=("${start_prefix}.${i}")
            done

        # 单个 IP
        elif validate_ip "$segment"; then
            PARSE_IP_RESULT+=("$segment")
        else
            error "无效的 IP 地址或范围: $segment"
            return 1
        fi
    done

    if [[ ${#PARSE_IP_RESULT[@]} -eq 0 ]]; then
        error "未解析到任何有效 IP 地址"
        return 1
    fi

    return 0
}

# ========================= 检查 IP 冲突 =========================
# 使用全局变量 CHECK_IPS_INPUT 传入 IP 列表（兼容 Bash 4.2）
check_ip_conflicts() {
    local cidr="$1"
    local conflicts=()

    # 获取当前系统上所有已配置的 IP
    local existing_ips
    existing_ips=$(ip -4 addr show 2>/dev/null | awk '/inet / {split($2,a,"/"); print a[1]}')

    for ip in "${CHECK_IPS_INPUT[@]}"; do
        # 检查是否已经配置在本机
        if echo "$existing_ips" | grep -qx "$ip"; then
            conflicts+=("$ip (已在本机配置)")
            continue
        fi

        # 使用 arping 检测(如果可用)
        if command -v arping &>/dev/null; then
            if arping -c 1 -w 1 -I "$PRIMARY_IFACE" "$ip" &>/dev/null; then
                conflicts+=("$ip (网络中已存在)")
            fi
        fi
    done

    if [[ ${#conflicts[@]} -gt 0 ]]; then
        warn "发现以下 IP 冲突:"
        for c in "${conflicts[@]}"; do
            warn "  - $c"
        done
        return 1
    fi

    return 0
}

# ========================= 查找主网卡配置文件 =========================
# 返回主网卡对应的配置文件路径(仅此一个文件用于备份)
find_primary_iface_config() {
    case "$NET_MANAGER" in
        network-scripts)
            local cfg="/etc/sysconfig/network-scripts/ifcfg-${PRIMARY_IFACE}"
            [[ -f "$cfg" ]] && echo "$cfg"
            ;;
        NetworkManager)
            # 优先查找 keyfile 格式: /etc/NetworkManager/system-connections/
            local nm_dir="/etc/NetworkManager/system-connections"
            if [[ -d "$nm_dir" ]]; then
                # 按文件名匹配网卡名
                for f in "$nm_dir"/${PRIMARY_IFACE}.nmconnection "$nm_dir"/${PRIMARY_IFACE}; do
                    [[ -f "$f" ]] && echo "$f" && return
                done
                # 按文件内容匹配 interface-name
                for f in "$nm_dir"/*; do
                    [[ -f "$f" ]] || continue
                    if grep -q "interface-name=${PRIMARY_IFACE}" "$f" 2>/dev/null; then
                        echo "$f"
                        return
                    fi
                done
            fi
            # 回退到 ifcfg 格式
            local cfg="/etc/sysconfig/network-scripts/ifcfg-${PRIMARY_IFACE}"
            [[ -f "$cfg" ]] && echo "$cfg"
            ;;
        netplan)
            # 找包含主网卡名的 yaml 文件
            for f in /etc/netplan/*.yaml; do
                [[ -f "$f" ]] || continue
                if grep -q "${PRIMARY_IFACE}" "$f" 2>/dev/null; then
                    echo "$f"
                    return
                fi
            done
            # 未匹配则返回第一个 yaml
            local first
            first=$(ls /etc/netplan/*.yaml 2>/dev/null | head -1)
            [[ -n "$first" ]] && echo "$first"
            ;;
        ifupdown)
            echo "/etc/network/interfaces"
            ;;
    esac
}

# ========================= 备份函数 =========================
backup_configs() {
    mkdir -p "$BACKUP_DIR"
    info "备份目录: $BACKUP_DIR"

    local cfg_file
    cfg_file=$(find_primary_iface_config)

    if [[ -n "$cfg_file" ]] && [[ -f "$cfg_file" ]]; then
        cp -a "$cfg_file" "$BACKUP_DIR/"
        info "已备份主网卡配置: $cfg_file"
    else
        warn "未找到主网卡 ${PRIMARY_IFACE} 的配置文件，跳过备份"
    fi

    info "网络配置备份完成"
}

# ========================= CentOS 7 / network-scripts 配置 =========================
# 使用全局变量 APPLY_IPS_INPUT 传入 IP 列表（兼容 Bash 4.2）
apply_network_scripts() {
    local cidr="$1"
    local mask
    mask=$(cidr_to_mask "$cidr")
    local base_dir="/etc/sysconfig/network-scripts"

    # 找到当前最大的别名编号
    local max_alias=0
    for f in "$base_dir"/ifcfg-${PRIMARY_IFACE}:*; do
        if [[ -f "$f" ]]; then
            local num
            num=$(basename "$f" | sed "s/ifcfg-${PRIMARY_IFACE}://")
            if [[ "$num" =~ ^[0-9]+$ ]] && [[ "$num" -gt "$max_alias" ]]; then
                max_alias="$num"
            fi
        fi
    done

    # 收集所有已配置的 IP 地址（从配置文件和当前系统）
    local -A existing_ips_map
    local all_existing_ips=""
    
    # 从已有的配置文件中读取 IP
    for f in "$base_dir"/ifcfg-${PRIMARY_IFACE}:*; do
        if [[ -f "$f" ]]; then
            local existing_ip
            existing_ip=$(grep -oP '^IPADDR=\K[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+' "$f" 2>/dev/null || true)
            if [[ -n "$existing_ip" ]]; then
                all_existing_ips+="$existing_ip "
            fi
        fi
    done
    
    # 从当前系统接口读取已有 IP
    all_existing_ips+=$(ip -4 addr show dev "$PRIMARY_IFACE" 2>/dev/null | awk '/inet / {split($2,a,"/"); print a[1]}' || true)
    
    # 构建已存在 IP 的哈希表
    for existing_ip in $all_existing_ips; do
        existing_ips_map["$existing_ip"]=1
    done

    local idx=$((max_alias + 1))
    local count=0

    for ip in "${APPLY_IPS_INPUT[@]}"; do
        # 检查 IP 是否已存在于配置中
        if [[ -n "${existing_ips_map[$ip]:-}" ]]; then
            warn "跳过已存在的 IP: $ip"
            continue
        fi
        
        local cfg_file="$base_dir/ifcfg-${PRIMARY_IFACE}:${idx}"
        cat > "$cfg_file" <<EOF
# 由 add_ips.sh 自动生成 - $(date '+%Y-%m-%d %H:%M:%S')
DEVICE=${PRIMARY_IFACE}:${idx}
TYPE=Ethernet
BOOTPROTO=static
ONBOOT=yes
IPADDR=${ip}
NETMASK=${mask}
EOF
        info "已创建: $cfg_file (${ip}/${cidr})"
        # 将新 IP 加入已存在列表，防止同批次重复
        existing_ips_map["$ip"]=1
        idx=$((idx + 1))
        count=$((count + 1))
    done
    
    # 如果没有新 IP 需要添加
    if [[ $count -eq 0 ]]; then
        info "所有 IP 已存在，无需添加"
        return 0
    fi

    # 启用接口
    info "正在激活网络配置..."
    if systemctl is-active --quiet network 2>/dev/null; then
        systemctl restart network
    else
        # 逐个激活别名接口
        idx=$((max_alias + 1))
        for ip in "${APPLY_IPS_INPUT[@]}"; do
            # 跳过已存在的 IP（已在上面标记）
            if [[ -z "${existing_ips_map[$ip]:-}" ]]; then
                continue
            fi
            # 检查是否已激活（避免重复激活）
            if ! ip -4 addr show dev "$PRIMARY_IFACE" 2>/dev/null | grep -q "inet ${ip}/"; then
                ifup "${PRIMARY_IFACE}:${idx}" 2>/dev/null || \
                    ip addr add "${ip}/${cidr}" dev "$PRIMARY_IFACE" 2>/dev/null || true
            fi
            idx=$((idx + 1))
        done
    fi

    info "通过 network-scripts 成功添加 $count 个 IP 地址"
}

# ========================= CentOS 7 / network-scripts IPv6 配置 =========================
apply_ipv6_network_scripts() {
    local prefix="$1"
    local base_dir="/etc/sysconfig/network-scripts"
    local cfg_file="$base_dir/ifcfg-${PRIMARY_IFACE}"

    if [[ ! -f "$cfg_file" ]]; then
        die "找不到主网卡配置文件: $cfg_file"
    fi

    # 确保 IPv6 初始化启用
    if ! grep -q '^IPV6INIT=yes' "$cfg_file" 2>/dev/null; then
        sed -i '/IPV6INIT/d' "$cfg_file" 2>/dev/null || true
        echo "IPV6INIT=yes" >> "$cfg_file"
        info "已启用 IPV6INIT=yes"
    fi

    # 收集已有 IPv6 地址
    local existing_ips=""
    if grep -q '^IPV6ADDR=' "$cfg_file" 2>/dev/null; then
        existing_ips+=$(grep '^IPV6ADDR=' "$cfg_file" | cut -d= -f2 | cut -d/ -f1)" "
    fi
    if grep -q '^IPV6ADDR_SECONDARIES=' "$cfg_file" 2>/dev/null; then
        local sec
        sec=$(grep '^IPV6ADDR_SECONDARIES=' "$cfg_file" | sed 's/IPV6ADDR_SECONDARIES=//' | tr -d '"')
        for addr in $sec; do
            existing_ips+=$(echo "$addr" | cut -d/ -f1)" "
        done
    fi

    # 从当前系统读取已有 IPv6（排除 link-local）
    existing_ips+=$(ip -6 addr show dev "$PRIMARY_IFACE" 2>/dev/null | awk '/inet6 / && !/fe80::/ {split($2,a,"/"); print a[1]}' || true)

    local -A existing_ips_map
    for eip in $existing_ips; do
        [[ -n "$eip" ]] && existing_ips_map["$eip"]=1
    done

    local secondaries=""
    local count=0

    for ip in "${APPLY_IPS_INPUT[@]}"; do
        if [[ -n "${existing_ips_map[$ip]:-}" ]]; then
            warn "跳过已存在的 IPv6: $ip"
            continue
        fi
        if [[ -n "$secondaries" ]]; then
            secondaries+=" "
        fi
        secondaries+="${ip}/${prefix}"
        existing_ips_map["$ip"]=1
        count=$((count + 1))
    done

    # 更新或添加 IPV6ADDR_SECONDARIES
    if [[ $count -gt 0 ]]; then
        if grep -q '^IPV6ADDR_SECONDARIES=' "$cfg_file" 2>/dev/null; then
            local old_sec
            old_sec=$(grep '^IPV6ADDR_SECONDARIES=' "$cfg_file" | sed 's/IPV6ADDR_SECONDARIES=//' | tr -d '"')
            if [[ -n "$old_sec" ]]; then
                secondaries="${old_sec} ${secondaries}"
            fi
            sed -i "s|^IPV6ADDR_SECONDARIES=.*|IPV6ADDR_SECONDARIES=\"${secondaries}\"|" "$cfg_file"
        else
            echo "IPV6ADDR_SECONDARIES=\"${secondaries}\"" >> "$cfg_file"
        fi
        info "已添加 $count 个 IPv6 地址到 $cfg_file"
    fi

    # 配置 IPv6 默认网关到配置文件
    if [[ -n "$IPV6_GATEWAY" ]]; then
        if grep -q "^IPV6_DEFAULTGW=${IPV6_GATEWAY}" "$cfg_file" 2>/dev/null; then
            info "IPv6 默认网关已存在于配置文件中，跳过"
        else
            # 删除旧的 IPV6_DEFAULTGW 配置
            sed -i '/^IPV6_DEFAULTGW=/d' "$cfg_file" 2>/dev/null || true
            echo "IPV6_DEFAULTGW=${IPV6_GATEWAY}" >> "$cfg_file"
            info "已写入 IPv6 默认网关到配置文件: $IPV6_GATEWAY"
        fi
    fi

    # 激活
    if [[ $count -gt 0 ]]; then
        if systemctl is-active --quiet network 2>/dev/null; then
            systemctl restart network
        else
            for ip in "${APPLY_IPS_INPUT[@]}"; do
                if ! ip -6 addr show dev "$PRIMARY_IFACE" 2>/dev/null | grep -q "inet6 ${ip}/"; then
                    ip -6 addr add "${ip}/${prefix}" dev "$PRIMARY_IFACE" 2>/dev/null || true
                fi
            done
        fi
    fi

    # 临时添加默认路由（如果配置文件方式未生效）
    if [[ -n "$IPV6_GATEWAY" ]]; then
        if ! ip -6 route show default | grep -q "$IPV6_GATEWAY"; then
            ip -6 route add default via "$IPV6_GATEWAY" dev "$PRIMARY_IFACE" 2>/dev/null || true
            info "已添加 IPv6 默认路由: $IPV6_GATEWAY"
        fi
    fi

    if [[ $count -gt 0 ]]; then
        info "通过 network-scripts 成功添加 $count 个 IPv6 地址"
    else
        info "所有 IPv6 地址已存在，无需添加"
    fi
}

# ========================= NetworkManager keyfile 配置 =========================
# 直接写入 /etc/NetworkManager/system-connections/ 下的连接配置文件的 [ipv4] 段
# 适用于 Rocky Linux 8/9, CentOS 8/9, AlmaLinux 8/9, RHEL 8/9 等
# 使用全局变量 APPLY_IPS_INPUT 传入 IP 列表（兼容 Bash 4.2）
apply_networkmanager() {
    local cidr="$1"

    local nm_dir="/etc/NetworkManager/system-connections"
    local conn_file=""

    # 查找主网卡对应的连接配置文件
    if [[ -d "$nm_dir" ]]; then
        # 按文件名匹配
        for f in "$nm_dir"/${PRIMARY_IFACE}.nmconnection "$nm_dir"/${PRIMARY_IFACE}; do
            if [[ -f "$f" ]]; then
                conn_file="$f"
                break
            fi
        done
        # 按文件内容中的 interface-name 匹配
        if [[ -z "$conn_file" ]]; then
            for f in "$nm_dir"/*; do
                [[ -f "$f" ]] || continue
                if grep -q "interface-name=${PRIMARY_IFACE}" "$f" 2>/dev/null; then
                    conn_file="$f"
                    break
                fi
            done
        fi
    fi

    if [[ -z "$conn_file" ]]; then
        die "无法找到 $PRIMARY_IFACE 对应的 NetworkManager 连接配置文件 (查找路径: $nm_dir)"
    fi

    info "连接配置文件: $conn_file"

    # 读取 [ipv4] 段中现有的 address 条目，找到最大编号
    local max_idx=0
    local -A existing_ips_map=()

    while IFS='=' read -r key val; do
        key=$(echo "$key" | xargs)  # trim
        val=$(echo "$val" | xargs)
        if [[ "$key" =~ ^address([0-9]+)$ ]]; then
            local idx="${BASH_REMATCH[1]}"
            if [[ "$idx" -gt "$max_idx" ]]; then
                max_idx="$idx"
            fi
            # 记录已有的 IP
            local existing_ip="${val%%/*}"
            existing_ips_map["$existing_ip"]=1
        fi
    done < <(sed -n '/^\[ipv4\]/,/^\[/p' "$conn_file" 2>/dev/null)
    
    # 同时检查当前系统接口中已存在的 IP
    local active_ips
    active_ips=$(ip -4 addr show dev "$PRIMARY_IFACE" 2>/dev/null | awk '/inet / {split($2,a,"/"); print a[1]}' || true)
    for ip in $active_ips; do
        existing_ips_map["$ip"]=1
    done

    # 确保 [ipv4] 段存在
    if ! grep -q '^\[ipv4\]' "$conn_file" 2>/dev/null; then
        printf '\n[ipv4]\nmethod=manual\n' >> "$conn_file"
        info "已添加 [ipv4] 段"
    else
        # 确保 method=manual
        if grep -q '^method=auto' "$conn_file" 2>/dev/null; then
            sed -i '/^\[ipv4\]/,/^\[/{s/^method=auto/method=manual/}' "$conn_file"
            info "已将 ipv4.method 从 auto 改为 manual"
        fi
    fi

    # 构建要插入的 address 行
    local new_lines=""
    local count=0
    local next_idx=$((max_idx + 1))

    for ip in "${APPLY_IPS_INPUT[@]}"; do
        if [[ -n "${existing_ips_map[$ip]:-}" ]]; then
            warn "跳过已存在的 IP: $ip"
            continue
        fi
        new_lines+="address${next_idx}=${ip}/${cidr}"$'\n'
        info "写入: address${next_idx}=${ip}/${cidr}"
        # 将新 IP 加入已存在列表，防止同批次重复
        existing_ips_map["$ip"]=1
        next_idx=$((next_idx + 1))
        count=$((count + 1))
    done

    if [[ $count -eq 0 ]]; then
        warn "没有新的 IP 需要添加(全部已存在)"
        return 0
    fi

    # 将新 address 行插入 [ipv4] 段末尾
    local temp_file
    temp_file=$(mktemp)
    local in_ipv4=false
    local inserted=false

    while IFS= read -r line; do
        if [[ "$line" == "[ipv4]" ]]; then
            in_ipv4=true
            echo "$line" >> "$temp_file"
            continue
        fi

        # 遇到下一个段头 [xxx]，先插入新地址行
        if [[ "$in_ipv4" == true ]] && [[ "$line" =~ ^\[.+\] ]]; then
            printf '%s' "$new_lines" >> "$temp_file"
            inserted=true
            in_ipv4=false
        fi

        echo "$line" >> "$temp_file"
    done < "$conn_file"

    # 如果 [ipv4] 是文件最后一个段，追加到文件末尾
    if [[ "$in_ipv4" == true ]] && [[ "$inserted" == false ]]; then
        printf '%s' "$new_lines" >> "$temp_file"
    fi

    # 替换原文件，保持权限
    local orig_perm
    orig_perm=$(stat -c '%a' "$conn_file" 2>/dev/null || echo "600")
    cp "$temp_file" "$conn_file"
    chmod "$orig_perm" "$conn_file"
    rm -f "$temp_file"

    info "已写入 $count 个 IP 到 $conn_file"

    # 重新加载 NetworkManager 配置使其生效
    info "正在重新加载 NetworkManager 配置..."
    nmcli con reload 2>/dev/null

    local conn_name
    conn_name=$(nmcli -t -f NAME,DEVICE con show 2>/dev/null | awk -F: -v dev="$PRIMARY_IFACE" '$2==dev {print $1; exit}')

    if [[ -n "$conn_name" ]]; then
        info "正在重新激活连接: $conn_name"
        if ! nmcli con up "$conn_name" 2>/dev/null; then
            warn "nmcli con up 失败，尝试使用 ip 命令临时添加..."
            for ip in "${APPLY_IPS_INPUT[@]}"; do
                # 跳过已存在的 IP
                if [[ -n "${existing_ips_map[$ip]:-}" ]] && [[ "${existing_ips_map[$ip]}" == "2" ]]; then
                    continue
                fi
                # 检查是否已激活
                if ! ip -4 addr show dev "$PRIMARY_IFACE" 2>/dev/null | grep -q "inet ${ip}/"; then
                    ip addr add "${ip}/${cidr}" dev "$PRIMARY_IFACE" 2>/dev/null || true
                fi
            done
        fi
    else
        warn "无法获取连接名称，尝试重启 NetworkManager..."
        systemctl restart NetworkManager 2>/dev/null || true
    fi

    info "通过 NetworkManager keyfile 成功添加 $count 个 IP 地址"
}

# ========================= NetworkManager keyfile IPv6 配置 =========================
apply_ipv6_networkmanager() {
    local prefix="$1"

    local nm_dir="/etc/NetworkManager/system-connections"
    local conn_file=""

    # 查找主网卡对应的连接配置文件
    if [[ -d "$nm_dir" ]]; then
        for f in "$nm_dir"/${PRIMARY_IFACE}.nmconnection "$nm_dir"/${PRIMARY_IFACE}; do
            if [[ -f "$f" ]]; then
                conn_file="$f"
                break
            fi
        done
        if [[ -z "$conn_file" ]]; then
            for f in "$nm_dir"/*; do
                [[ -f "$f" ]] || continue
                if grep -q "interface-name=${PRIMARY_IFACE}" "$f" 2>/dev/null; then
                    conn_file="$f"
                    break
                fi
            done
        fi
    fi

    if [[ -z "$conn_file" ]]; then
        die "无法找到 $PRIMARY_IFACE 对应的 NetworkManager 连接配置文件 (查找路径: $nm_dir)"
    fi

    info "连接配置文件: $conn_file"

    # 读取 [ipv6] 段中现有的 address 条目
    local max_idx=0
    local -A existing_ips_map=()

    while IFS='=' read -r key val; do
        key=$(echo "$key" | xargs)
        val=$(echo "$val" | xargs)
        if [[ "$key" =~ ^address([0-9]+)$ ]]; then
            local idx="${BASH_REMATCH[1]}"
            if [[ "$idx" -gt "$max_idx" ]]; then
                max_idx="$idx"
            fi
            local existing_ip="${val%%/*}"
            existing_ips_map["$existing_ip"]=1
        fi
    done < <(sed -n '/^\[ipv6\]/,/^\[/p' "$conn_file" 2>/dev/null)

    # 同时检查当前系统接口中已存在的 IPv6（排除 link-local）
    local active_ips
    active_ips=$(ip -6 addr show dev "$PRIMARY_IFACE" 2>/dev/null | awk '/inet6 / && !/fe80::/ {split($2,a,"/"); print a[1]}' || true)
    for ip in $active_ips; do
        existing_ips_map["$ip"]=1
    done

    # 确保 [ipv6] 段存在
    if ! grep -q '^\[ipv6\]' "$conn_file" 2>/dev/null; then
        printf '\n[ipv6]\nmethod=manual\n' >> "$conn_file"
        info "已添加 [ipv6] 段"
    else
        if grep -q '^method=auto' "$conn_file" 2>/dev/null; then
            sed -i '/^\[ipv6\]/,/^\[/{s/^method=auto/method=manual/}' "$conn_file"
            info "已将 ipv6.method 从 auto 改为 manual"
        fi
    fi

    # 构建要插入的 address 行
    local new_lines=""
    local count=0
    local next_idx=$((max_idx + 1))

    for ip in "${APPLY_IPS_INPUT[@]}"; do
        if [[ -n "${existing_ips_map[$ip]:-}" ]]; then
            warn "跳过已存在的 IPv6: $ip"
            continue
        fi
        new_lines+="address${next_idx}=${ip}/${prefix}"$'\n'
        info "写入: address${next_idx}=${ip}/${prefix}"
        existing_ips_map["$ip"]=1
        next_idx=$((next_idx + 1))
        count=$((count + 1))
    done

    # 配置 IPv6 默认网关到配置文件
    local gw_written=false
    if [[ -n "$IPV6_GATEWAY" ]]; then
        if grep -q "^gateway=${IPV6_GATEWAY}" "$conn_file" 2>/dev/null; then
            info "IPv6 默认网关已存在于配置文件中，跳过"
        else
            # 删除旧的 gateway 行
            sed -i '/^\[ipv6\]/,/^\[/ { /^gateway=/d }' "$conn_file" 2>/dev/null || true
            new_lines+="gateway=${IPV6_GATEWAY}"$'\n'
            info "写入: gateway=${IPV6_GATEWAY}"
            gw_written=true
        fi
    fi

    if [[ $count -eq 0 ]] && [[ "$gw_written" != true ]]; then
        warn "没有新的 IPv6 地址需要添加(全部已存在)，且网关无需更新"
        return 0
    fi

    # 将新 address/gateway 行插入 [ipv6] 段末尾
    local temp_file
    temp_file=$(mktemp)
    local in_ipv6=false
    local inserted=false

    while IFS= read -r line; do
        if [[ "$line" == "[ipv6]" ]]; then
            in_ipv6=true
            echo "$line" >> "$temp_file"
            continue
        fi

        if [[ "$in_ipv6" == true ]] && [[ "$line" =~ ^\[.+\] ]]; then
            printf '%s' "$new_lines" >> "$temp_file"
            inserted=true
            in_ipv6=false
        fi

        echo "$line" >> "$temp_file"
    done < "$conn_file"

    if [[ "$in_ipv6" == true ]] && [[ "$inserted" == false ]]; then
        printf '%s' "$new_lines" >> "$temp_file"
    fi

    local orig_perm
    orig_perm=$(stat -c '%a' "$conn_file" 2>/dev/null || echo "600")
    cp "$temp_file" "$conn_file"
    chmod "$orig_perm" "$conn_file"
    rm -f "$temp_file"

    if [[ $count -gt 0 ]]; then
        info "已写入 $count 个 IPv6 地址到 $conn_file"
    fi

    # 重新加载 NetworkManager 配置
    info "正在重新加载 NetworkManager 配置..."
    nmcli con reload 2>/dev/null

    local conn_name
    conn_name=$(nmcli -t -f NAME,DEVICE con show 2>/dev/null | awk -F: -v dev="$PRIMARY_IFACE" '$2==dev {print $1; exit}')

    if [[ -n "$conn_name" ]]; then
        info "正在重新激活连接: $conn_name"
        if ! nmcli con up "$conn_name" 2>/dev/null; then
            warn "nmcli con up 失败，尝试使用 ip 命令临时添加..."
            for ip in "${APPLY_IPS_INPUT[@]}"; do
                if ! ip -6 addr show dev "$PRIMARY_IFACE" 2>/dev/null | grep -q "inet6 ${ip}/"; then
                    ip -6 addr add "${ip}/${prefix}" dev "$PRIMARY_IFACE" 2>/dev/null || true
                fi
            done
        fi
    else
        warn "无法获取连接名称，尝试重启 NetworkManager..."
        systemctl restart NetworkManager 2>/dev/null || true
    fi

    # 临时添加默认路由（如果配置文件方式未生效）
    if [[ -n "$IPV6_GATEWAY" ]]; then
        if ! ip -6 route show default | grep -q "$IPV6_GATEWAY"; then
            ip -6 route add default via "$IPV6_GATEWAY" dev "$PRIMARY_IFACE" 2>/dev/null || true
            info "已添加 IPv6 默认路由: $IPV6_GATEWAY"
        fi
    fi

    if [[ $count -gt 0 ]]; then
        info "通过 NetworkManager keyfile 成功添加 $count 个 IPv6 地址"
    fi
}

# ========================= Netplan 配置 =========================
# 使用全局变量 APPLY_IPS_INPUT 传入 IP 列表（兼容 Bash 4.2）
apply_netplan() {
    local cidr="$1"

    # 找到主配置文件
    local netplan_file
    netplan_file=$(ls /etc/netplan/*.yaml 2>/dev/null | head -1)

    if [[ -z "$netplan_file" ]]; then
        # 如果不存在，创建新的配置文件
        netplan_file="/etc/netplan/01-netcfg.yaml"
        info "未找到 netplan 配置文件，将创建: $netplan_file"

        local primary_ip
        primary_ip=$(ip -4 addr show dev "$PRIMARY_IFACE" | awk '/inet / {print $2; exit}')

        cat > "$netplan_file" <<EOF
# 由 add_ips.sh 自动生成 - $(date '+%Y-%m-%d %H:%M:%S')
network:
  version: 2
  ethernets:
    ${PRIMARY_IFACE}:
      addresses:
        - ${primary_ip}
EOF
        if [[ -n "$GATEWAY" ]]; then
            cat >> "$netplan_file" <<EOF
      routes:
        - to: default
          via: ${GATEWAY}
EOF
        fi

        if [[ -n "$DNS_SERVERS" ]]; then
            echo "      nameservers:" >> "$netplan_file"
            echo "        addresses: [${DNS_SERVERS}]" >> "$netplan_file"
        fi
    fi

    info "Netplan 配置文件: $netplan_file"

    # 读取现有配置，检查 addresses 部分是否存在
    if grep -q "addresses:" "$netplan_file" 2>/dev/null; then
        # 找到接口配置中的 addresses 部分并追加 IP
        local temp_file
        temp_file=$(mktemp)

        # 使用 Python(如果可用)来安全地修改 YAML
        if command -v python3 &>/dev/null; then
            python3 - "$netplan_file" "$PRIMARY_IFACE" "$cidr" "${APPLY_IPS_INPUT[@]}" <<'PYEOF'
import sys
import yaml

netplan_file = sys.argv[1]
iface = sys.argv[2]
cidr = sys.argv[3]
new_ips = sys.argv[4:]

with open(netplan_file, 'r') as f:
    config = yaml.safe_load(f) or {}

network = config.get('network', {})
ethernets = network.get('ethernets', {})

if iface not in ethernets:
    # 查找任意已有的接口
    for key in ethernets:
        if key != 'renderer':
            iface = key
            break

if iface in ethernets:
    iface_config = ethernets[iface]
    if 'addresses' not in iface_config:
        iface_config['addresses'] = []
    existing = [str(a).split('/')[0] for a in iface_config['addresses']]
    for ip in new_ips:
        if ip not in existing:
            iface_config['addresses'].append(f"{ip}/{cidr}")

with open(netplan_file, 'w') as f:
    yaml.dump(config, f, default_flow_style=False, allow_unicode=True)

print(f"OK: Added {len(new_ips)} IPs")
PYEOF
        else
            # 无 Python 时使用 sed 方式追加
            # 找到 addresses: 块的最后一行，在其后追加新 IP
            local addresses_done=false
            local in_iface=false
            local in_addresses=false
            local last_addr_line=0
            local line_num=0

            while IFS= read -r line; do
                line_num=$((line_num + 1))
                if [[ "$line" =~ ^[[:space:]]+${PRIMARY_IFACE}: ]]; then
                    in_iface=true
                elif [[ "$in_iface" == true ]] && [[ "$line" =~ ^[[:space:]]+addresses: ]]; then
                    in_addresses=true
                elif [[ "$in_addresses" == true ]]; then
                    if [[ "$line" =~ ^[[:space:]]+-[[:space:]] ]]; then
                        last_addr_line=$line_num
                    else
                        in_addresses=false
                    fi
                fi
            done < "$netplan_file"

            if [[ $last_addr_line -gt 0 ]]; then
                # 在最后一个地址行后插入新 IP
                local insert_text=""
                for ip in "${APPLY_IPS_INPUT[@]}"; do
                    insert_text="${insert_text}        - ${ip}/${cidr}\n"
                done
                sed -i "${last_addr_line}a\\${insert_text}" "$netplan_file"
            else
                # 直接在接口段下添加 addresses
                warn "无法精确定位 addresses 块，将在接口段末尾追加"
                local insert_text="      addresses:"
                for ip in "${APPLY_IPS_INPUT[@]}"; do
                    insert_text="${insert_text}\n        - ${ip}/${cidr}"
                done
                sed -i "/^[[:space:]]*${PRIMARY_IFACE}:/a\\${insert_text}" "$netplan_file"
            fi
        fi
    else
        # 配置文件存在但没有 addresses 段 — 在接口下添加
        if command -v python3 &>/dev/null; then
            python3 - "$netplan_file" "$PRIMARY_IFACE" "$cidr" "${APPLY_IPS_INPUT[@]}" <<'PYEOF'
import sys
import yaml

netplan_file = sys.argv[1]
iface = sys.argv[2]
cidr = sys.argv[3]
new_ips = sys.argv[4:]

with open(netplan_file, 'r') as f:
    config = yaml.safe_load(f) or {}

network = config.setdefault('network', {})
network.setdefault('version', 2)
ethernets = network.setdefault('ethernets', {})
iface_config = ethernets.setdefault(iface, {})
iface_config.setdefault('addresses', [])

for ip in new_ips:
    iface_config['addresses'].append(f"{ip}/{cidr}")

with open(netplan_file, 'w') as f:
    yaml.dump(config, f, default_flow_style=False, allow_unicode=True)

print(f"OK: Added {len(new_ips)} IPs")
PYEOF
        else
            # 手动追加
            local insert_text="      addresses:"
            for ip in "${APPLY_IPS_INPUT[@]}"; do
                insert_text="${insert_text}\n        - ${ip}/${cidr}"
            done
            sed -i "/^[[:space:]]*${PRIMARY_IFACE}:/a\\${insert_text}" "$netplan_file"
        fi
    fi

    # 设置正确的文件权限 (netplan 要求 600)
    chmod 600 "$netplan_file"
    info "已设置配置文件权限为 600"

    # 应用配置
    info "正在应用 netplan 配置..."
    if netplan apply 2>&1; then
        info "Netplan 配置已成功应用"
    else
        warn "netplan apply 失败，尝试使用 ip 命令直接添加..."
        for ip in "${APPLY_IPS_INPUT[@]}"; do
            ip addr add "${ip}/${cidr}" dev "$PRIMARY_IFACE" 2>/dev/null || true
        done
    fi

    # 等待 IP 生效 (netplan apply 是异步的)
    info "等待网络配置生效..."
    local wait_count=0
    local max_wait=10
    while [[ $wait_count -lt $max_wait ]]; do
        sleep 1
        local all_ips_ready=true
        for ip in "${APPLY_IPS_INPUT[@]}"; do
            if ! ip -4 addr show dev "$PRIMARY_IFACE" 2>/dev/null | grep -q "inet ${ip}/"; then
                all_ips_ready=false
                break
            fi
        done
        if [[ "$all_ips_ready" == true ]]; then
            break
        fi
        wait_count=$((wait_count + 1))
    done

    info "通过 Netplan 成功添加 ${#APPLY_IPS_INPUT[@]} 个 IP 地址"
}

# ========================= Netplan IPv6 配置 =========================
apply_ipv6_netplan() {
    local prefix="$1"

    local netplan_file
    netplan_file=$(ls /etc/netplan/*.yaml 2>/dev/null | head -1)

    if [[ -z "$netplan_file" ]]; then
        netplan_file="/etc/netplan/01-netcfg.yaml"
        info "未找到 netplan 配置文件，将创建: $netplan_file"

        local primary_ip4
        primary_ip4=$(ip -4 addr show dev "$PRIMARY_IFACE" 2>/dev/null | awk '/inet / {print $2; exit}')
        local primary_ip6
        primary_ip6=$(ip -6 addr show dev "$PRIMARY_IFACE" 2>/dev/null | awk '/inet6 / && !/fe80::/ {print $2; exit}')

        cat > "$netplan_file" <<EOF
# 由 add_ips.sh 自动生成 - $(date '+%Y-%m-%d %H:%M:%S')
network:
  version: 2
  ethernets:
    ${PRIMARY_IFACE}:
      addresses:
        - ${primary_ip4:-}
EOF
        if [[ -n "$primary_ip6" ]]; then
            echo "        - ${primary_ip6}" >> "$netplan_file"
        fi
        if [[ -n "$GATEWAY" ]]; then
            cat >> "$netplan_file" <<EOF
      routes:
        - to: default
          via: ${GATEWAY}
EOF
        fi
        if [[ -n "$DNS_SERVERS" ]]; then
            echo "      nameservers:" >> "$netplan_file"
            echo "        addresses: [${DNS_SERVERS}]" >> "$netplan_file"
        fi
    fi

    info "Netplan 配置文件: $netplan_file"

    # 读取现有配置，检查 addresses 部分
    if grep -q "addresses:" "$netplan_file" 2>/dev/null; then
        if command -v python3 &>/dev/null; then
            python3 - "$netplan_file" "$PRIMARY_IFACE" "$prefix" "${APPLY_IPS_INPUT[@]}" <<'PYEOF'
import sys
import yaml

netplan_file = sys.argv[1]
iface = sys.argv[2]
prefix = sys.argv[3]
new_ips = sys.argv[4:]

with open(netplan_file, 'r') as f:
    config = yaml.safe_load(f) or {}

network = config.get('network', {})
ethernets = network.get('ethernets', {})

if iface not in ethernets:
    for key in ethernets:
        if key != 'renderer':
            iface = key
            break

if iface in ethernets:
    iface_config = ethernets[iface]
    if 'addresses' not in iface_config:
        iface_config['addresses'] = []
    existing = [str(a).split('/')[0] for a in iface_config['addresses']]
    for ip in new_ips:
        if ip not in existing:
            iface_config['addresses'].append(f"{ip}/{prefix}")

    # 添加 IPv6 网关路由
    if len(sys.argv) > 4 and 'routes' not in iface_config:
        pass  # 路由单独处理

with open(netplan_file, 'w') as f:
    yaml.dump(config, f, default_flow_style=False, allow_unicode=True)

print(f"OK: Added {len(new_ips)} IPv6 IPs")
PYEOF
        else
            local temp_file
            temp_file=$(mktemp)
            local in_iface=false
            local in_addresses=false
            local last_addr_line=0
            local line_num=0

            while IFS= read -r line; do
                line_num=$((line_num + 1))
                if [[ "$line" =~ ^[[:space:]]+${PRIMARY_IFACE}: ]]; then
                    in_iface=true
                elif [[ "$in_iface" == true ]] && [[ "$line" =~ ^[[:space:]]+addresses: ]]; then
                    in_addresses=true
                elif [[ "$in_addresses" == true ]]; then
                    if [[ "$line" =~ ^[[:space:]]+-[[:space:]] ]]; then
                        last_addr_line=$line_num
                    else
                        in_addresses=false
                    fi
                fi
            done < "$netplan_file"

            if [[ $last_addr_line -gt 0 ]]; then
                local insert_text=""
                for ip in "${APPLY_IPS_INPUT[@]}"; do
                    insert_text="${insert_text}        - ${ip}/${prefix}\n"
                done
                sed -i "${last_addr_line}a\\${insert_text}" "$netplan_file"
            else
                local insert_text="      addresses:"
                for ip in "${APPLY_IPS_INPUT[@]}"; do
                    insert_text="${insert_text}\n        - ${ip}/${prefix}"
                done
                sed -i "/^[[:space:]]*${PRIMARY_IFACE}:/a\\${insert_text}" "$netplan_file"
            fi
        fi
    else
        if command -v python3 &>/dev/null; then
            python3 - "$netplan_file" "$PRIMARY_IFACE" "$prefix" "${APPLY_IPS_INPUT[@]}" <<'PYEOF'
import sys
import yaml

netplan_file = sys.argv[1]
iface = sys.argv[2]
prefix = sys.argv[3]
new_ips = sys.argv[4:]

with open(netplan_file, 'r') as f:
    config = yaml.safe_load(f) or {}

network = config.setdefault('network', {})
network.setdefault('version', 2)
ethernets = network.setdefault('ethernets', {})
iface_config = ethernets.setdefault(iface, {})
iface_config.setdefault('addresses', [])

for ip in new_ips:
    iface_config['addresses'].append(f"{ip}/{prefix}")

with open(netplan_file, 'w') as f:
    yaml.dump(config, f, default_flow_style=False, allow_unicode=True)

print(f"OK: Added {len(new_ips)} IPv6 IPs")
PYEOF
        else
            local insert_text="      addresses:"
            for ip in "${APPLY_IPS_INPUT[@]}"; do
                insert_text="${insert_text}\n        - ${ip}/${prefix}"
            done
            sed -i "/^[[:space:]]*${PRIMARY_IFACE}:/a\\${insert_text}" "$netplan_file"
        fi
    fi

    # 如果有 IPv6 网关，添加路由配置
    if [[ -n "$IPV6_GATEWAY" ]]; then
        if command -v python3 &>/dev/null; then
            python3 - "$netplan_file" "$PRIMARY_IFACE" "$IPV6_GATEWAY" <<'PYEOF'
import sys
import yaml

netplan_file = sys.argv[1]
iface = sys.argv[2]
gateway = sys.argv[3]

with open(netplan_file, 'r') as f:
    config = yaml.safe_load(f) or {}

network = config.get('network', {})
ethernets = network.get('ethernets', {})

if iface in ethernets:
    iface_config = ethernets[iface]
    if 'routes' not in iface_config:
        iface_config['routes'] = []
    # 检查是否已有默认 IPv6 路由（匹配指定网关）
    has_default_v6 = False
    for route in iface_config['routes']:
        if route.get('to') == 'default' and route.get('via') == gateway:
            has_default_v6 = True
            break
    if not has_default_v6:
        iface_config['routes'].append({'to': 'default', 'via': gateway})

with open(netplan_file, 'w') as f:
    yaml.dump(config, f, default_flow_style=False, allow_unicode=True)
PYEOF
            info "已写入 IPv6 默认网关到 netplan 配置: $IPV6_GATEWAY"
        else
            # 无 Python 时，使用 sed 检查并追加路由
            if grep -q "via: ${IPV6_GATEWAY}" "$netplan_file" 2>/dev/null; then
                info "IPv6 默认网关已存在于 netplan 配置中，跳过"
            else
                local gw_route_text="      routes:\n        - to: default\n          via: ${IPV6_GATEWAY}"
                sed -i "/^[[:space:]]*${PRIMARY_IFACE}:/a\\${gw_route_text}" "$netplan_file"
                info "已写入 IPv6 默认网关到 netplan 配置: $IPV6_GATEWAY"
            fi
        fi
    fi

    chmod 600 "$netplan_file"
    info "已设置配置文件权限为 600"

    info "正在应用 netplan 配置..."
    if netplan apply 2>&1; then
        info "Netplan 配置已成功应用"
    else
        warn "netplan apply 失败，尝试使用 ip 命令直接添加..."
        for ip in "${APPLY_IPS_INPUT[@]}"; do
            ip -6 addr add "${ip}/${prefix}" dev "$PRIMARY_IFACE" 2>/dev/null || true
        done
    fi

    info "等待网络配置生效..."
    local wait_count=0
    local max_wait=10
    while [[ $wait_count -lt $max_wait ]]; do
        sleep 1
        local all_ips_ready=true
        for ip in "${APPLY_IPS_INPUT[@]}"; do
            if ! ip -6 addr show dev "$PRIMARY_IFACE" 2>/dev/null | grep -q "inet6 ${ip}/"; then
                all_ips_ready=false
                break
            fi
        done
        if [[ "$all_ips_ready" == true ]]; then
            break
        fi
        wait_count=$((wait_count + 1))
    done

    # 如果有网关，添加默认路由（临时）
    if [[ -n "$IPV6_GATEWAY" ]]; then
        if ! ip -6 route show default | grep -q "$IPV6_GATEWAY"; then
            ip -6 route add default via "$IPV6_GATEWAY" dev "$PRIMARY_IFACE" 2>/dev/null || true
            info "已添加 IPv6 默认网关: $IPV6_GATEWAY"
        fi
    fi

    info "通过 Netplan 成功添加 ${#APPLY_IPS_INPUT[@]} 个 IPv6 地址"
}

# ========================= ifupdown 配置 =========================
# 使用全局变量 APPLY_IPS_INPUT 传入 IP 列表（兼容 Bash 4.2）
apply_ifupdown() {
    local cidr="$1"
    local mask
    mask=$(cidr_to_mask "$cidr")

    local config_file="/etc/network/interfaces"
    local extra_dir="/etc/network/interfaces.d"

    # 优先使用 interfaces.d 目录
    local target_file
    if [[ -d "$extra_dir" ]]; then
        target_file="${extra_dir}/${PRIMARY_IFACE}-extra-ips.cfg"
    else
        target_file="$config_file"
    fi

    # 找到当前最大的别名编号
    # 优先从配置文件中读取已有的别名编号
    local max_alias=0
    local config_nums=""
    local extra_nums=""
    
    if [[ -f "$config_file" ]]; then
        config_nums=$(grep -oP "${PRIMARY_IFACE}:\K[0-9]+" "$config_file" 2>/dev/null || true)
    fi
    if [[ -d "$extra_dir" ]]; then
        extra_nums=$(grep -roP "${PRIMARY_IFACE}:\K[0-9]+" "$extra_dir" 2>/dev/null || true)
    fi
    
    for num in $config_nums $extra_nums; do
        if [[ "$num" =~ ^[0-9]+$ ]] && [[ "$num" -gt "$max_alias" ]]; then
            max_alias="$num"
        fi
    done
    
    # 同时检查当前系统中已激活的别名接口
    local active_aliases
    active_aliases=$(ip -4 addr show dev "$PRIMARY_IFACE" 2>/dev/null | grep -oP "${PRIMARY_IFACE}:\K[0-9]+" || true)
    for num in $active_aliases; do
        if [[ "$num" =~ ^[0-9]+$ ]] && [[ "$num" -gt "$max_alias" ]]; then
            max_alias="$num"
        fi
    done

    local idx=$((max_alias + 1))
    local count=0

    # 收集所有已配置的 IP 地址（从配置文件和当前系统）
    local -A existing_ips_map
    local all_existing_ips=""
    
    # 从主配置文件中读取已有 IP
    if [[ -f "$config_file" ]]; then
        all_existing_ips+=$(grep -oP 'address\s+\K[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+' "$config_file" 2>/dev/null || true)
        all_existing_ips+=" "
    fi
    
    # 从扩展目录读取已有 IP
    if [[ -d "$extra_dir" ]]; then
        all_existing_ips+=$(grep -roP 'address\s+\K[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+' "$extra_dir" 2>/dev/null || true)
        all_existing_ips+=" "
    fi
    
    # 从当前系统接口读取已有 IP
    all_existing_ips+=$(ip -4 addr show dev "$PRIMARY_IFACE" 2>/dev/null | awk '/inet / {split($2,a,"/"); print a[1]}' || true)
    
    # 构建已存在 IP 的哈希表
    for existing_ip in $all_existing_ips; do
        existing_ips_map["$existing_ip"]=1
    done

    # 生成配置内容
    local config_content
    config_content="# 由 add_ips.sh 自动生成 - $(date '+%Y-%m-%d %H:%M:%S')"$'\n'

    for ip in "${APPLY_IPS_INPUT[@]}"; do
        # 检查 IP 是否已存在于配置中
        if [[ -n "${existing_ips_map[$ip]:-}" ]]; then
            warn "跳过已存在的 IP: $ip"
            continue
        fi
        
        config_content+="
auto ${PRIMARY_IFACE}:${idx}
iface ${PRIMARY_IFACE}:${idx} inet static
    address ${ip}
    netmask ${mask}
"
        # 将新 IP 加入已存在列表，防止同批次重复
        existing_ips_map["$ip"]=1
        idx=$((idx + 1))
        count=$((count + 1))
    done
    
    # 如果没有新 IP 需要添加
    if [[ $count -eq 0 ]]; then
        info "所有 IP 已存在，无需添加"
        return 0
    fi

    if [[ "$target_file" == "$config_file" ]]; then
        # 追加到主配置文件
        echo "$config_content" >> "$config_file"
        info "已追加配置到 $config_file"
    else
        # 追加到独立文件（保留已有配置）
        echo "$config_content" >> "$target_file"
        if [[ -f "$target_file" ]]; then
            info "已追加配置到: $target_file"
        else
            info "已创建配置文件: $target_file"
        fi

        # 确保主配置文件包含 source 指令
        if ! grep -q "source.*interfaces.d" "$config_file" 2>/dev/null; then
            echo "" >> "$config_file"
            echo "source /etc/network/interfaces.d/*" >> "$config_file"
            info "已添加 source 指令到 $config_file"
        fi
    fi

    # 激活接口
    info "正在激活网络配置..."
    if command -v ifup &>/dev/null; then
        idx=$((max_alias + 1))
        for ip in "${APPLY_IPS_INPUT[@]}"; do
            ifup "${PRIMARY_IFACE}:${idx}" 2>/dev/null || \
                ip addr add "${ip}/${cidr}" dev "$PRIMARY_IFACE" 2>/dev/null || true
            idx=$((idx + 1))
        done
    else
        # 直接用 ip 命令
        for ip in "${APPLY_IPS_INPUT[@]}"; do
            ip addr add "${ip}/${cidr}" dev "$PRIMARY_IFACE" 2>/dev/null || true
        done
    fi

    if systemctl is-active --quiet networking 2>/dev/null; then
        systemctl restart networking 2>/dev/null || true
    fi

    info "通过 ifupdown 成功添加 $count 个 IP 地址"
}

# ========================= ifupdown IPv6 配置 =========================
apply_ipv6_ifupdown() {
    local prefix="$1"

    local config_file="/etc/network/interfaces"
    local extra_dir="/etc/network/interfaces.d"

    # 优先使用 interfaces.d 目录
    local target_file
    if [[ -d "$extra_dir" ]]; then
        target_file="${extra_dir}/${PRIMARY_IFACE}-ipv6.cfg"
    else
        target_file="$config_file"
    fi

    # 收集已有 IPv6 地址（从 address 行、up 命令和当前系统）
    local all_ips=()
    local -A all_ips_map

    # 从主配置文件的 address 行读取已有 IPv6（必须包含 : 以排除 IPv4）
    if [[ -f "$config_file" ]]; then
        local addr_lines
        addr_lines=$(grep -oP 'address\s+\K[0-9a-fA-F]*:[0-9a-fA-F:]+(/[0-9]+)?' "$config_file" 2>/dev/null || true)
        for line in $addr_lines; do
            local addr="${line%%/*}"
            [[ -n "$addr" ]] && [[ -z "${all_ips_map[$addr]:-}" ]] && { all_ips_map["$addr"]=1; all_ips+=("$addr"); }
        done
    fi

    # 从扩展目录的 address 行读取已有 IPv6（必须包含 : 以排除 IPv4）
    if [[ -d "$extra_dir" ]]; then
        local addr_lines_extra
        addr_lines_extra=$(grep -roP 'address\s+\K[0-9a-fA-F]*:[0-9a-fA-F:]+(/[0-9]+)?' "$extra_dir" 2>/dev/null || true)
        for line in $addr_lines_extra; do
            local addr="${line%%/*}"
            [[ -n "$addr" ]] && [[ -z "${all_ips_map[$addr]:-}" ]] && { all_ips_map["$addr"]=1; all_ips+=("$addr"); }
        done
    fi

    # 从 up 命令中读取已有 IPv6
    local up_ips=""
    if [[ -f "$config_file" ]]; then
        up_ips+=$(grep -oP 'up\s+ip\s+-6\s+addr\s+add\s+\K[0-9a-fA-F:]+' "$config_file" 2>/dev/null || true)
        up_ips+=" "
    fi
    if [[ -d "$extra_dir" ]]; then
        up_ips+=$(grep -roP 'up\s+ip\s+-6\s+addr\s+add\s+\K[0-9a-fA-F:]+' "$extra_dir" 2>/dev/null || true)
        up_ips+=" "
    fi
    for addr in $up_ips; do
        [[ -n "$addr" ]] && [[ -z "${all_ips_map[$addr]:-}" ]] && { all_ips_map["$addr"]=1; all_ips+=("$addr"); }
    done

    # 从当前系统读取已有 IPv6（排除 link-local）
    local sys_ips
    sys_ips=$(ip -6 addr show dev "$PRIMARY_IFACE" 2>/dev/null | awk '/inet6 / && !/fe80::/ {split($2,a,"/"); print a[1]}' || true)
    for addr in $sys_ips; do
        [[ -n "$addr" ]] && [[ -z "${all_ips_map[$addr]:-}" ]] && { all_ips_map["$addr"]=1; all_ips+=("$addr"); }
    done

    # 合并新的 IP
    local new_count=0
    for ip in "${APPLY_IPS_INPUT[@]}"; do
        if [[ -n "${all_ips_map[$ip]:-}" ]]; then
            warn "跳过已存在的 IPv6: $ip"
            continue
        fi
        all_ips+=("$ip")
        all_ips_map["$ip"]=1
        new_count=$((new_count + 1))
    done

    if [[ ${#all_ips[@]} -eq 0 ]] && [[ -z "$IPV6_GATEWAY" ]]; then
        info "没有 IPv6 地址需要配置"
        return 0
    fi

    # 如果未指定网关，尝试从现有配置中保留已有网关
    local effective_gateway="$IPV6_GATEWAY"
    if [[ -z "$effective_gateway" ]]; then
        local existing_gw
        existing_gw=$(grep -m1 -oP '^\s+gateway\s+\K[0-9a-fA-F:]+' "$target_file" 2>/dev/null || true)
        if [[ -n "$existing_gw" ]]; then
            effective_gateway="$existing_gw"
            info "保留现有 IPv6 网关: $effective_gateway"
        fi
    fi

    if [[ $new_count -eq 0 ]] && [[ -z "$effective_gateway" ]]; then
        info "所有 IPv6 地址已存在，无需添加"
        return 0
    fi

    # 生成配置内容：使用标准的 iface inet6 static 格式
    local config_content
    config_content="# 由 add_ips.sh 自动生成 - IPv6 - $(date '+%Y-%m-%d %H:%M:%S')"$'\n'
    config_content+="iface ${PRIMARY_IFACE} inet6 static"$'\n'

    # 第一个地址使用标准 address 行
    if [[ ${#all_ips[@]} -gt 0 ]]; then
        config_content+="    address ${all_ips[0]}/${prefix}"$'\n'
    fi

    # 网关使用标准 gateway 行
    if [[ -n "$effective_gateway" ]]; then
        config_content+="    gateway ${effective_gateway}"$'\n'
    fi

    # 其余地址使用 up/down 命令
    if [[ ${#all_ips[@]} -gt 1 ]]; then
        for ((i=1; i<${#all_ips[@]}; i++)); do
            config_content+="    up ip -6 addr add ${all_ips[$i]}/${prefix} dev ${PRIMARY_IFACE}"$'\n'
            config_content+="    down ip -6 addr del ${all_ips[$i]}/${prefix} dev ${PRIMARY_IFACE}"$'\n'
        done
    fi

    # 写入配置文件
    if [[ "$target_file" == "$config_file" ]]; then
        # 主配置文件只能追加，删除旧段比较复杂
        echo "$config_content" >> "$config_file"
        info "已追加 IPv6 配置到 $config_file"
    else
        # 独立文件直接覆盖，确保只有一个 iface 段
        echo "$config_content" > "$target_file"
        info "已更新 IPv6 配置文件: $target_file"

        # 确保主配置文件包含 source 指令
        if ! grep -q "source.*interfaces.d" "$config_file" 2>/dev/null; then
            echo "" >> "$config_file"
            echo "source /etc/network/interfaces.d/*" >> "$config_file"
            info "已添加 source 指令到 $config_file"
        fi
    fi

    # 激活接口
    info "正在激活 IPv6 网络配置..."
    for ip in "${all_ips[@]}"; do
        if ! ip -6 addr show dev "$PRIMARY_IFACE" 2>/dev/null | grep -q "inet6 ${ip}/"; then
            ip -6 addr add "${ip}/${prefix}" dev "$PRIMARY_IFACE" 2>/dev/null || true
        fi
    done

    # 临时添加默认路由（如果配置文件方式未生效）
    if [[ -n "$IPV6_GATEWAY" ]]; then
        if ! ip -6 route show default | grep -q "$IPV6_GATEWAY"; then
            ip -6 route add default via "$IPV6_GATEWAY" dev "$PRIMARY_IFACE" 2>/dev/null || true
            info "已添加 IPv6 默认路由: $IPV6_GATEWAY"
        fi
    fi

    if systemctl is-active --quiet networking 2>/dev/null; then
        systemctl restart networking 2>/dev/null || true
    fi

    if [[ $new_count -gt 0 ]]; then
        info "通过 ifupdown 成功添加 $new_count 个 IPv6 地址"
    fi
}

# ========================= 应用配置 =========================
# 使用全局变量 APPLY_IPS_INPUT 传递 IP 列表（兼容 Bash 4.2）
apply_ips() {
    local cidr="$1"

    if [[ "$IPV6_MODE" == true ]]; then
        apply_ipv6_ips "$cidr"
    else
        case "$NET_MANAGER" in
            network-scripts)
                apply_network_scripts "$cidr"
                ;;
            NetworkManager)
                apply_networkmanager "$cidr"
                ;;
            netplan)
                apply_netplan "$cidr"
                ;;
            ifupdown)
                apply_ifupdown "$cidr"
                ;;
            *)
                die "不支持的网络管理器: $NET_MANAGER"
                ;;
        esac
    fi
}

# ========================= IPv6 应用配置总控 =========================
apply_ipv6_ips() {
    local prefix="$1"

    case "$NET_MANAGER" in
        network-scripts)
            apply_ipv6_network_scripts "$prefix"
            ;;
        NetworkManager)
            apply_ipv6_networkmanager "$prefix"
            ;;
        netplan)
            apply_ipv6_netplan "$prefix"
            ;;
        ifupdown)
            apply_ipv6_ifupdown "$prefix"
            ;;
        *)
            die "不支持的网络管理器: $NET_MANAGER"
            ;;
    esac
}

# ========================= 验证结果 =========================
# 使用全局变量 VERIFY_IPS_INPUT 传入 IP 列表（兼容 Bash 4.2）
verify_ips() {
    local success=0
    local fail=0

    echo ""
    if [[ "$IPV6_MODE" == true ]]; then
        echo -e "${CYAN}========== IPv6 验证结果 ==========${NC}"
        for ip in "${VERIFY_IPS_INPUT[@]}"; do
            if ip -6 addr show dev "$PRIMARY_IFACE" 2>/dev/null | grep -q "inet6 ${ip}/"; then
                echo -e "  ${GREEN}[OK]${NC} ${ip}"
                success=$((success + 1))
            else
                echo -e "  ${RED}[FAIL]${NC} ${ip}"
                fail=$((fail + 1))
            fi
        done
    else
        echo -e "${CYAN}========== 验证结果 ==========${NC}"
        for ip in "${VERIFY_IPS_INPUT[@]}"; do
            if ip -4 addr show dev "$PRIMARY_IFACE" 2>/dev/null | grep -q "inet ${ip}/"; then
                echo -e "  ${GREEN}[OK]${NC} ${ip}"
                success=$((success + 1))
            else
                echo -e "  ${RED}[FAIL]${NC} ${ip}"
                fail=$((fail + 1))
            fi
        done
    fi

    echo -e "${CYAN}================================${NC}"
    echo -e "  成功: ${GREEN}${success}${NC}  失败: ${RED}${fail}${NC}  总计: $((success + fail))"
    echo ""

    if [[ $fail -gt 0 ]]; then
        warn "部分 IP 未能成功添加，请检查日志: $LOG_FILE"
    fi
}

# ========================= 显示帮助 =========================
show_help() {
    cat <<'HELP'
用法: add_ips.sh [选项]

Linux 多发行版 IP 地址配置工具_by豆芽
选项:
  -i, --ips <IPs>       要添加的 IP 地址
                         支持格式:
                           单个 IP:     192.168.1.100
                           多个 IP:     "192.168.1.100 192.168.1.101 192.168.1.102"
                           IP 范围:     192.168.1.100-200
                           完整范围:    192.168.1.100-192.168.1.200
                           混合格式:    "192.168.1.100 192.168.2.10-20"

  -m, --mask <掩码>     子网掩码 (默认: IPv4 /24, IPv6 /64)
                         支持格式:
                           CIDR:        24 或 /24
                           完整掩码:    255.255.255.0

  -d, --iface <网卡>    指定网卡名 (默认: 自动检测)

  -6, --ipv6            启用 IPv6 模式（添加 IPv6 地址）

  -g, --gateway <网关>  指定网关地址 (IPv4/IPv6)

  -y, --yes             跳过确认提示，自动执行

  -h, --help            显示此帮助信息

示例:
  # 添加单个 IPv4
  add_ips.sh -i 192.168.1.100

  # 添加多个 IPv4，指定掩码
  add_ips.sh -i "192.168.1.100 192.168.1.101" -m 255.255.255.0

  # 添加 IP 范围
  add_ips.sh -i 192.168.1.100-200 -m /24

  # 添加 IPv6 地址
  add_ips.sh -6 -i "2001:db8::1 2001:db8::2" -m /64

  # 添加 IPv6 地址并指定网关
  add_ips.sh -6 -i "2001:db8::1" -g "2001:db8::fe"

  # 交互模式
  add_ips.sh

HELP
}

# ========================= 交互模式 =========================
interactive_mode() {
    show_welcome
    
    detect_distro
    detect_net_manager
    detect_primary_iface

    # 选择 IP 协议版本
    echo ""
    echo -e "${BLUE}--- 选择要添加的 IP 协议版本 ---${NC}"
    echo "  1) IPv4 (默认)"
    echo "  2) IPv6"
    echo ""
    read -rp "请选择 [1/2] (直接回车默认 IPv4): " ip_version_choice

    if [[ "$ip_version_choice" == "2" ]]; then
        IPV6_MODE=true
        check_and_enable_ipv6
    fi

    echo ""
    echo -e "${BLUE}--- 输入要添加的 IP 地址 ---${NC}"
    if [[ "$IPV6_MODE" == true ]]; then
        echo "支持格式:"
        echo "  单个 IPv6:   2001:db8::1"
        echo "  多个 IPv6:   2001:db8::1 2001:db8::2"
        echo ""
        read -rp "请输入 IPv6 地址: " ip_input

        if [[ -z "$ip_input" ]]; then
            die "未输入任何 IPv6 地址"
        fi

        echo ""
        read -rp "请输入前缀长度 (直接回车默认 /64): " mask_input

        local prefix
        prefix=$(parse_ipv6_prefix "$mask_input") || exit 1

        echo ""
        read -rp "请输入 IPv6 网关 (直接回车跳过): " gw_input
        if [[ -n "$gw_input" ]]; then
            IPV6_GATEWAY="$gw_input"
        fi

        # 解析 IPv6 输入
        parse_ipv6_input "$ip_input" || exit 1

        # 去重
        local -a ip_list=()
        local -A seen=()
        for ip in "${PARSE_IP_RESULT[@]}"; do
            if [[ -z "${seen[$ip]:-}" ]]; then
                seen[$ip]=1
                ip_list+=("$ip")
            fi
        done

        echo ""
        echo -e "${CYAN}========== IPv6 配置摘要 ==========${NC}"
        echo -e "  发行版:   ${PRETTY_NAME:-$DISTRO $DISTRO_VERSION}"
        echo -e "  网络管理: $NET_MANAGER"
        echo -e "  网卡:     $PRIMARY_IFACE"
        echo -e "  前缀长度: /${prefix}"
        echo -e "  IPv6 网关: ${IPV6_GATEWAY:-未指定}"
        echo -e "  IP 数量:  ${#ip_list[@]}"
        echo ""
        echo -e "  将添加以下 IPv6 地址:"
        for ip in "${ip_list[@]}"; do
            echo -e "    - ${ip}/${prefix}"
        done
        echo -e "${CYAN}====================================${NC}"
        echo ""

        read -rp "确认执行以上配置? (y/N): " confirm
        if [[ "${confirm,,}" != "y" ]]; then
            info "已取消操作"
            exit 0
        fi

        echo ""
        backup_configs
        echo ""
        APPLY_IPS_INPUT=("${ip_list[@]}")
        apply_ips "$prefix"
        echo ""
        VERIFY_IPS_INPUT=("${ip_list[@]}")
        verify_ips
    else
        echo "支持格式:"
        echo "  单个 IP:   192.168.1.100"
        echo "  多个 IP:   192.168.1.100 192.168.1.101"
        echo "  IP 范围:   192.168.1.100-200"
        echo "  完整范围:  192.168.1.100-192.168.1.200"
        echo "  混合:      192.168.1.100 192.168.2.10-20"
        echo ""
        read -rp "请输入 IP 地址: " ip_input

        if [[ -z "$ip_input" ]]; then
            die "未输入任何 IP 地址"
        fi

        echo ""
        read -rp "请输入子网掩码 (直接回车默认 /24): " mask_input

        local cidr
        cidr=$(parse_mask "$mask_input") || exit 1
        local full_mask
        full_mask=$(cidr_to_mask "$cidr")

        # 解析 IP 输入（结果存入全局变量 PARSE_IP_RESULT）
        parse_ip_input "$ip_input" || exit 1

        # 去重
        local -a ip_list=()
        local -A seen=()
        for ip in "${PARSE_IP_RESULT[@]}"; do
            if [[ -z "${seen[$ip]:-}" ]]; then
                seen[$ip]=1
                ip_list+=("$ip")
            fi
        done

        echo ""
        echo -e "${CYAN}========== 配置摘要 ==========${NC}"
        echo -e "  发行版:   ${PRETTY_NAME:-$DISTRO $DISTRO_VERSION}"
        echo -e "  网络管理: $NET_MANAGER"
        echo -e "  网卡:     $PRIMARY_IFACE"
        echo -e "  子网掩码: /${cidr} (${full_mask})"
        echo -e "  IP 数量:  ${#ip_list[@]}"
        echo ""
        echo -e "  将添加以下 IP 地址:"
        for ip in "${ip_list[@]}"; do
            echo -e "    - ${ip}/${cidr}"
        done
        echo -e "${CYAN}===============================${NC}"
        echo ""

        # 检查冲突（使用全局变量 CHECK_IPS_INPUT）
        CHECK_IPS_INPUT=("${ip_list[@]}")
        if ! check_ip_conflicts "$cidr"; then
            echo ""
            read -rp "存在 IP 冲突，是否跳过冲突IP继续? (y/N): " confirm
            if [[ "${confirm,,}" != "y" ]]; then
                info "已取消操作"
                exit 0
            fi
        fi

        read -rp "确认执行以上配置? (y/N): " confirm
        if [[ "${confirm,,}" != "y" ]]; then
            info "已取消操作"
            exit 0
        fi

        echo ""
        backup_configs
        echo ""
        # 使用全局变量 APPLY_IPS_INPUT 传递 IP 列表
        APPLY_IPS_INPUT=("${ip_list[@]}")
        apply_ips "$cidr"
        echo ""
        # 使用全局变量 VERIFY_IPS_INPUT 传递 IP 列表
        VERIFY_IPS_INPUT=("${ip_list[@]}")
        verify_ips
    fi

    echo ""
    info "操作完成! 备份保存在: $BACKUP_DIR"
    info "日志文件: $LOG_FILE"
}

# ========================= 主入口 =========================
main() {
    check_root

    # 初始化日志文件
    mkdir -p "$(dirname "$LOG_FILE")" 2>/dev/null || LOG_FILE="/tmp/add_ips_$(date +%Y%m%d_%H%M%S).log"
    touch "$LOG_FILE" 2>/dev/null || LOG_FILE="/tmp/add_ips_$(date +%Y%m%d_%H%M%S).log"
    log "========== 脚本启动 =========="

    local ip_input=""
    local mask_input=""
    local auto_confirm=false
    local custom_iface=""

    # 解析命令行参数
    while [[ $# -gt 0 ]]; do
        case "$1" in
            -i|--ips)
                ip_input="$2"
                shift 2
                ;;
            -m|--mask)
                mask_input="$2"
                shift 2
                ;;
            -d|--iface)
                custom_iface="$2"
                shift 2
                ;;
            -6|--ipv6)
                IPV6_MODE=true
                shift
                ;;
            -g|--gateway)
                IPV6_GATEWAY="$2"
                shift 2
                ;;
            -y|--yes)
                auto_confirm=true
                shift
                ;;
            -h|--help)
                show_help
                exit 0
                ;;
            *)
                error "未知参数: $1"
                show_help
                exit 1
                ;;
        esac
    done

    # 如果没有提供 IP 参数，进入交互模式
    if [[ -z "$ip_input" ]]; then
        interactive_mode
        exit 0
    fi

    # 命令行模式
    detect_distro
    detect_net_manager

    if [[ -n "$custom_iface" ]]; then
        # 验证自定义网卡是否存在
        if ! ip link show "$custom_iface" &>/dev/null; then
            die "指定的网卡不存在: $custom_iface"
        fi
        PRIMARY_IFACE="$custom_iface"
        GATEWAY=$(ip route show default dev "$custom_iface" 2>/dev/null | awk '/default/ {print $3; exit}')
        info "使用指定网卡: $PRIMARY_IFACE"
    else
        detect_primary_iface
    fi

    if [[ "$IPV6_MODE" == true ]]; then
        # IPv6 模式
        check_and_enable_ipv6

        local prefix
        prefix=$(parse_ipv6_prefix "$mask_input") || exit 1

        # 解析 IPv6 输入
        parse_ipv6_input "$ip_input" || exit 1

        # 去重
        local -a ip_list=()
        local -A seen=()
        for ip in "${PARSE_IP_RESULT[@]}"; do
            if [[ -z "${seen[$ip]:-}" ]]; then
                seen[$ip]=1
                ip_list+=("$ip")
            fi
        done

        echo ""
        echo -e "${CYAN}========== IPv6 配置摘要 ==========${NC}"
        echo -e "  发行版:   ${PRETTY_NAME:-$DISTRO $DISTRO_VERSION}"
        echo -e "  网络管理: $NET_MANAGER"
        echo -e "  网卡:     $PRIMARY_IFACE"
        echo -e "  前缀长度: /${prefix}"
        echo -e "  IPv6 网关: ${IPV6_GATEWAY:-未指定}"
        echo -e "  IP 数量:  ${#ip_list[@]}"
        echo ""
        echo -e "  将添加以下 IPv6 地址:"
        for ip in "${ip_list[@]}"; do
            echo -e "    - ${ip}/${prefix}"
        done
        echo -e "${CYAN}====================================${NC}"
        echo ""

        if [[ "$auto_confirm" != true ]]; then
            read -rp "确认执行以上配置? (y/N): " confirm
            if [[ "${confirm,,}" != "y" ]]; then
                info "已取消操作"
                exit 0
            fi
        fi

        echo ""
        backup_configs
        echo ""
        APPLY_IPS_INPUT=("${ip_list[@]}")
        apply_ips "$prefix"
        echo ""
        VERIFY_IPS_INPUT=("${ip_list[@]}")
        verify_ips
    else
        # IPv4 模式
        local cidr
        cidr=$(parse_mask "$mask_input") || exit 1
        local full_mask
        full_mask=$(cidr_to_mask "$cidr")

        # 解析 IP 输入（结果存入全局变量 PARSE_IP_RESULT）
        parse_ip_input "$ip_input" || exit 1

        # 去重
        local -a ip_list=()
        local -A seen=()
        for ip in "${PARSE_IP_RESULT[@]}"; do
            if [[ -z "${seen[$ip]:-}" ]]; then
                seen[$ip]=1
                ip_list+=("$ip")
            fi
        done

        echo ""
        echo -e "${CYAN}========== 配置摘要 ==========${NC}"
        echo -e "  发行版:   ${PRETTY_NAME:-$DISTRO $DISTRO_VERSION}"
        echo -e "  网络管理: $NET_MANAGER"
        echo -e "  网卡:     $PRIMARY_IFACE"
        echo -e "  子网掩码: /${cidr} (${full_mask})"
        echo -e "  IP 数量:  ${#ip_list[@]}"
        echo ""
        echo -e "  将添加以下 IP 地址:"
        for ip in "${ip_list[@]}"; do
            echo -e "    - ${ip}/${cidr}"
        done
        echo -e "${CYAN}===============================${NC}"
        echo ""

        # 检查冲突（使用全局变量 CHECK_IPS_INPUT）
        CHECK_IPS_INPUT=("${ip_list[@]}")
        if ! check_ip_conflicts "$cidr"; then
            if [[ "$auto_confirm" != true ]]; then
                echo ""
                read -rp "存在 IP 冲突，是否跳过冲突IP继续? (y/N): " confirm
                if [[ "${confirm,,}" != "y" ]]; then
                    info "已取消操作"
                    exit 0
                fi
            else
                warn "存在 IP 冲突，由于指定了 -y 参数，继续执行"
            fi
        fi

        if [[ "$auto_confirm" != true ]]; then
            read -rp "确认执行以上配置? (y/N): " confirm
            if [[ "${confirm,,}" != "y" ]]; then
                info "已取消操作"
                exit 0
            fi
        fi

        echo ""
        backup_configs
        echo ""
        # 使用全局变量 APPLY_IPS_INPUT 传递 IP 列表
        APPLY_IPS_INPUT=("${ip_list[@]}")
        apply_ips "$cidr"
        echo ""
        # 使用全局变量 VERIFY_IPS_INPUT 传递 IP 列表
        VERIFY_IPS_INPUT=("${ip_list[@]}")
        verify_ips
    fi

    echo ""
    info "操作完成! 备份保存在: $BACKUP_DIR"
    info "日志文件: $LOG_FILE"
}

main "$@"
