#!/bin/bash


checkip(){
        regex="\b(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[1-9])\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[1-9])\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[1-9])\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[1-9])\b"
        if ! echo $1 | egrep ${regex} >/dev/null; then
                echo "$1 地址不规范"
                exit
        fi
}

cidr_to_mask(){
        set -- $(( 5 - ($1 / 8) )) 255 255 255 255 $(( (255 << (8 - ($1 % 8))) & 255 )) 0 0 0
        [ $1 -gt 1 ] && shift $1 || shift
        echo ${1-0}.${2-0}.${3-0}.${4-0}
}

mask_to_cidr(){
        local x=${1##*255.}
        set -- 0^^^128^192^224^240^248^252^254^ $(( (${#1} - ${#x})*2 )) ${x%%.*}
        x=${1%%$3*}
        echo $(( $2 + (${#x}/4) ))
}

interface_del_ip_range(){
        net_config_line=$(wc -l /etc/network/interfaces | awk '{print$1}')
        for((i=${del_ip_line};i>=1;i--));do
                if sed -n ${i}p /etc/network/interfaces | grep auto > /dev/null;then
                        del_start_line=${i}
                        break
                fi
        done
        for((n=${del_ip_line};n<=${net_config_line};n++));do
                if sed -n ${n}p /etc/network/interfaces | grep auto > /dev/null;then
                        let del_end_line=${n}-1
                        break
                fi
        done
        if [ -z ${del_end_line} ];then
                del_end_line=${net_config_line}
        fi
}


interface_del_ip(){
        nic=$1
        ip_info=$2
        ip=$(echo ${ip_info} | awk -F"/" '{print$1}')
        del_ip_line=$(grep -n " ${ip}$" /etc/network/interfaces | awk -F":" '{print$1}')
        interface_del_ip_range
        if sed -n "${del_start_line},${del_end_line}"p /etc/network/interfaces | grep gateway > /dev/null;then
                default_gateway=$(sed -n "${del_start_line},${del_end_line}"p /etc/network/interfaces | awk '/gateway/{print$2}')
                ifname=$(sed -n "${del_start_line},${del_end_line}"p /etc/network/interfaces | awk '/auto/{print$2}')
                sed -i "${del_start_line},${del_end_line}d" /etc/network/interfaces
                new_gw_ifname=$(grep "auto" /etc/network/interfaces | awk '{print$2}' | grep ${nic} | head -n 1)
                new_gw_ifname_line=$(grep -n "${new_gw_ifname}[ ]\{0,\}$" /etc/network/interfaces | awk -F":" '{print$1}')
                net_config_line=$(wc -l /etc/network/interfaces | awk '{print$1}')
                for((n=${new_gw_ifname_line};n<=${net_config_line};n++));do
                        if sed -n ${n}p /etc/network/interfaces | grep netmask > /dev/null;then
                                add_line=${n}
                                break
                        fi
                done
                sed -i "${add_line} a      gateway ${default_gateway}" /etc/network/interfaces
                ip addr del ${ip_info} dev ${nic};systemctl restart networking.service
        else
                ifname=$(sed -n ${del_start_line},${del_end_line}p /etc/network/interfaces | awk '/auto/{print$2}')
                ifdown ${ifname}
                sed -i "${del_start_line},${del_end_line}d" /etc/network/interfaces
        fi
}

interface_add_ip(){
        nic=$1
        ip_info=$2
        ip=$(echo ${ip_info} | awk -F"/" '{print$1}')
        cidr=$(echo ${ip_info} | awk -F"/" '{print$2}')
        mask=$(cidr_to_mask ${cidr})
        if grep ${nic} /etc/network/interfaces > /dev/null;then
                if_id_range=($(grep "auto" /etc/network/interfaces | awk -F[\ :] '/'${nic}:'/{print$3}'  | grep -v "^$"))
                for ((n=1;n<=300;n++));do
                        if ! echo ${if_id_range[@]} | grep -w ${n} > /dev/null;then
                                if_id=${n}
                                break
                        fi
                done
                cat >> /etc/network/interfaces << EOF
auto ${nic}:${if_id}
iface ${nic}:${if_id} inet static
    address ${ip}
    netmask ${mask}
EOF
        ifup ${nic}:${if_id}
        else
                cat >> /etc/network/interfaces << EOF
auto ${nic}:1
iface ${nic}:1 inet static
    address ${ip}
    netmask ${mask}
EOF
        ifup ${nic}:1
        fi
}

interface_change_default_gw(){
        nic=$1
        ip_info=$2
        sed -i "s/gateway .*/gateway ${ip_info}/" /etc/network/interfaces
}


netplan_add_ip(){
        nic=$1
        ip_info=$2
        net_conf_file=$(ls /etc/netplan/*.yaml)
        yq -i '.network.ethernets.'${nic}'.addresses += ["'${ip_info}'"]' ${net_conf_file}
        netplan apply
}

netplan_del_ip(){
        nic=$1
        ip_info=$2
        net_conf_file=$(ls /etc/netplan/*.yaml)
        yq -i 'del(.network.ethernets.'${nic}'.addresses[] | select(. == "'${ip_info}'"))' ${net_conf_file}
        netplan apply
}

netplan_change_default_gw(){
        nic=$1
        default_gateway=$2
        net_conf_file=$(ls /etc/netplan/*.yaml)
        yq -i '.network.ethernets.'${nic}'.gateway4 = "'${default_gateway}'"' ${net_conf_file}
        netplan apply
}

nmcli_add_ip(){
        nic=$1
        ip_info=$2
        # 获取网卡对应的连接名称
        conn_name=$(nmcli -t -f DEVICE,NAME connection show --active | grep "^${nic}:" | cut -d: -f2)
        
        if [ -n "${conn_name}" ];then
                # 连接存在，直接添加IP
                nmcli connection modify "${conn_name}" +ipv4.addresses ${ip_info} ipv4.method manual ipv6.method link-local
                nmcli connection up "${conn_name}"
        else
                # 连接不存在，创建新连接
                nmcli con add con-name ${nic} autoconnect yes type ethernet ifname ${nic} ipv4.method manual ipv6.method link-local +ipv4.addresses ${ip_info}
                nmcli connection up ${nic}
        fi
}

nmcli_del_ip(){
        nic=$1
        ip_info=$2
        # 获取网卡对应的连接名称
        conn_name=$(nmcli -t -f DEVICE,NAME connection show --active | grep "^${nic}:" | cut -d: -f2)
        
        if [ -z "${conn_name}" ];then
                echo "未找到网卡 ${nic} 的连接"
                exit 1
        fi
        
        ip_num=$(ip addr show ${nic} | grep -c "inet ")
        if [ ${ip_num} -eq 1 ];then
                nmcli connection modify "${conn_name}" -ipv4.addresses ${ip_info} ipv4.method disabled ipv6.method link-local 
                nmcli connection up "${conn_name}"
        else
                nmcli connection modify "${conn_name}" -ipv4.addresses ${ip_info} ipv6.method link-local
                nmcli connection up "${conn_name}"
        fi
}

nmcli_change_default_gw(){
        nic=$1
        default_gateway=$2
        # 获取网卡对应的连接名称
        conn_name=$(nmcli -t -f DEVICE,NAME connection show --active | grep "^${nic}:" | cut -d: -f2)
        
        if [ -z "${conn_name}" ];then
                echo "未找到网卡 ${nic} 的连接"
                exit 1
        fi
        
        nmcli connection modify "${conn_name}" ipv4.gateway ${default_gateway}
        nmcli connection up "${conn_name}"
}

change_ssh_port(){
        ssh_port=$1
        sed -i "/Port /s/.*/Port ${ssh_port}/" /etc/ssh/sshd_config
        systemctl restart sshd
}

change_hostname(){
        hostname=$1
        echo ${hostname} > /etc/hostname
        hostname ${hostname}
}



system_version(){
        operate=$1
        nic=$2
        ip_info=$3
        if grep "CentOS" /etc/redhat-release > /dev/null 2>&1 || grep "Rocky" /etc/redhat-release > /dev/null 2>&1 || grep "AlmaLinux" /etc/redhat-release > /dev/null 2>&1; then
                if [ ${operate} == "ip_add" ];then
                        nmcli_add_ip ${nic} ${ip_info}
                elif [ ${operate} == "ip_del" ];then
                        nmcli_del_ip ${nic} ${ip_info}
                elif [ ${operate} == "change_gw" ];then
                        nmcli_change_default_gw ${public_nic} ${gw_ip}
                fi
        elif egrep "ubuntu1~14|Ubuntu 16|ubuntu1~16" /proc/version > /dev/null 2>&1; then
                if [ ${operate} == "ip_add" ];then
                        interface_add_ip ${nic} ${ip_info}
                elif [ ${operate} == "ip_del" ];then
                        interface_del_ip ${nic} ${ip_info}
                elif [ ${operate} == "change_gw" ];then
                        interface_change_default_gw ${public_nic} ${gw_ip}
                fi
        elif egrep "Ubuntu 18|Ubuntu 20|Ubuntu 22|Ubuntu 24" /etc/issue > /dev/null 2>&1; then
                if [ ! -f /usr/local/bin/yq ];then
                        wget http://154.213.178.175/Tools/yq_linux_amd64 -O /usr/local/bin/yq > /dev/null 2>&1
                        chmod +x /usr/local/bin/yq
                fi
                if [ ! -f /usr/local/bin/yq ];then
                        exit 1
                fi
                if [ ${operate} == "ip_add" ];then
                        netplan_add_ip ${nic} ${ip_info}
                elif [ ${operate} == "ip_del" ];then
                        netplan_del_ip ${nic} ${ip_info}
                elif [ ${operate} == "change_gw" ];then
                        netplan_change_default_gw ${public_nic} ${gw_ip}
                fi
        elif egrep "Debian" /proc/version > /dev/null 2>&1; then

                if [ ${operate} == "ip_add" ];then
                        interface_add_ip ${nic} ${ip_info}
                elif [ ${operate} == "ip_del" ];then
                        interface_del_ip ${nic} ${ip_info}
                elif [ ${operate} == "change_gw" ];then
                        interface_change_default_gw ${public_nic} ${gw_ip}
                fi
        fi
}

cat << EOF
1) 增加IP地址
2) 移除IP地址
3) 更换默认网关
4) 修改ssh端口
5) 修改主机名
EOF

check_id(){
        input_id=$1
        max_id=$2
        text=$3
        # 检查是否为空或非数字
        if [ -z "${input_id}" ] || ! [[ "${input_id}" =~ ^[0-9]+$ ]]; then
                echo "${text}"
                exit 1
        fi
        # 检查范围
        if [ ${input_id} -lt 1 ] || [ ${input_id} -gt ${max_id} ]; then
                echo "${text}"
                exit 1
        fi
}

read -p "输入以上功能的序号[1-5]: " input
check_id ${input} 5 "输入序号不在范围内"
if [ ${input} -eq 1 ];then
        ip link show | awk -F[\ \:] '/mtu/{print$3}' | grep -v lo | sort | awk '{print NR") "$1}'
        ip route show | head -n 1| awk '/default/{print"当前公网网卡是: "$5}'
        nic_num=$(ip link show | awk -F[\ \:] '/mtu/{print$3}' | grep -v lo | wc -l)
        read -p "输入需要新增的IP的网卡: " nic_id
        check_id ${nic_id} ${nic_num} "序号不在范围内"
        nic=$(ip link show | awk -F[\ \:] '/mtu/{print$3}' | grep -v lo | sort | sed -n ${nic_id}p)
        read -p "输入需要新增的IP地址: " new_ip
        checkip ${new_ip}
        read -p "输入需要新增的IP的掩码位: " new_dir
        check_id ${new_dir} 32 "掩码位格式不对"
        ip_info="${new_ip}/${new_dir}"
        ip addr show dev ${nic} | awk '/inet /{print$2}' | grep "${ip_info}/" > /dev/null && echo "IP地址已存在" && exit 1
        system_version ip_add ${nic} ${ip_info}
elif [ ${input} -eq 2 ];then
        ip link show | awk -F[\ \:] '/mtu/{print$3}' | grep -v lo | sort | awk '{print NR") "$1}'
        public_nic=$(ip route show | head -n 1| awk '/default/{print$5}')
        echo "当前公网网卡是: ${public_nic}"
        nic_num=$(ip link show | awk -F[\ \:] '/mtu/{print$3}' | grep -v lo | wc -l)
        read -p "输入需要移除IP的网卡: " nic_id
        check_id ${nic_id} ${nic_num} "序号不在范围内"
        nic=$(ip link show | awk -F[\ \:] '/mtu/{print$3}' | grep -v lo | sort | sed -n ${nic_id}p)
        ip_num=$(ip addr show dev ${nic} | awk '/inet /{print$2}'| wc -l)
        if [ ${nic} == ${public_nic} ];then
                if [ ${ip_num} -eq 1 ];then
                        echo "公网网卡只有一个IP不能移除"
                        exit 1
                fi
        fi
        ip addr show dev ${nic} | awk '/inet /{print$2}' | awk '{print NR") "$1}'
        read -p "输入需要移除IP的序号: " del_ip_id
        check_id ${del_ip_id} ${ip_num} "序号不在范围内"
        ip_info=$(ip addr show dev ${nic} | awk '/inet /{print$2}' | sed -n ${del_ip_id}p)
        system_version ip_del ${nic} ${ip_info}
elif [ ${input} -eq 3 ];then
        public_nic=$(ip route show | awk '/default/{print$5}' | head -n 1)
        read -p "输入需要更新的网关地址: " gw_ip
        checkip ${gw_ip}
        system_version change_gw
elif [ ${input} -eq 4 ];then
        read -p "输入需要更换的SSH端口[1-65535]: " ssh_port
        check_id ${ssh_port} 65535 "输入端口不在范围内"
        change_ssh_port ${ssh_port}
elif [ ${input} -eq 5 ];then
        read -p "输入需要更换的主机名: " hostname
        if [ -z ${hostname} ];then
                echo "输入为空"
                exit 1
        fi
        change_hostname ${hostname}
fi
