#!/bin/bash
# ECS Utils IPv6 - sles

#LABEL_FOR_BUILD


##################################global define##################################
g_util_name=ecs-utils-ipv6
g_util_desc="ECS Utils IPv6"
g_gen_desc="#GENERATED BY $g_util_desc"
g_util_version=1.0.2
g_ret=0
g_need_reboot=0
g_need_restart_network=0

# const
G_ACTION_DISABLE=Disable

# log
g_log_dir=/var/log/"$g_util_name"
mkdir -p "$g_log_dir"
g_begin_day=$(date +"%Y%m%d")
g_log_file=${g_log_dir}/"${g_util_name}_${g_begin_day}.log"

function global::print_version() {
    cat <<EOF
$g_util_desc $g_util_version.
EOF
}

function global::print_usage() {
    cat <<EOF
$g_util_desc $g_util_version.
Usage: $(basename "$g_util_name") [OPTION...]
Examples:
  $g_util_name --help                                   # show usage
  $g_util_name --version                                # show version
  $g_util_name                                          # auto config all dev ipv6
  $g_util_name --static [dev] [ip6s] [prefix_len] [gw6] # config dev static ipv6
  e.g. $g_util_name --static eth0
       $g_util_name --static eth0 xxx::x1 64 xxx::x0
       $g_util_name --static eth0 "xxx::x1 xxx:x2 xxx:x3" 64 xxx::x0
  $g_util_name --enable                                 # enable ipv6
  $g_util_name --disable                                # disable ipv6
EOF
}

##################################common util##################################
function common::get_datetime() {
    date +"%Y-%m-%d %H:%M:%S.%3N"
}

function common::log() {
    local log_msg=$1
    local log_level=$2
    if [ "$log_level" == "" ]; then
        log_level="Info"
    fi
    log_info="[$log_level]\t$log_msg"
    log_info_time="$(common::get_datetime) $log_info"
    echo -e "$log_info_time" >>"$g_log_file"
    if [ "$log_level" != "Debug" ]; then
        echo -e "$log_info"
    fi
}

function common::log_function() {
    local log_msg="Function: ${FUNCNAME[1]} $*"
    common::log "$log_msg" "Debug"
}

function common::ret_log_var() {
    if [ -z "$2" ]; then
        common::log "var $1 is empty" "Error"
        exit 1
    fi
}

function common::log_empty_var() {
    if [ -z "$2" ]; then
        common::log "var $1 is empty" "Debug"
        return 0
    else
        common::log "var $1 is $2" "Debug"
        return 1
    fi
}

function common::ret_log() {
    if [ "$g_ret" -eq 0 ]; then
        log_msg="$1    OK"
        common::log "$log_msg" "Debug"
    else
        log_msg="$1    Failed"
        common::log "$log_msg" "Error"
        exit 1
    fi
}

function common::key_value_editer() {
    common::log_function "$*"
    local file=$1
    local key=$2
    local value=$3

    if ! grep -i "^${key}[[:space:]]*=" "$file" &>/dev/null; then
        echo "$key=$value" >> "$file"
    else
        value=${value//\//\\/}
        sed -i "s/^${key}[[:space:]]*=.*/$key=$value/" "$file"
    fi
}

function common::key_editer() {
    common::log_function "$*"
    local file=$1
    local key=$2
    local option=$3

    [[ ! -f $file ]] && return

    if [[ "$option" == "add" ]]; then
        if ! grep -i "^$key" "$file" &>/dev/null; then
            echo "$key" >> "$file"
        else
            sed -i "s/^$key.*/$key/" "$file"
        fi
    elif [[ "$option" == "del" ]]; then
        if grep -i "^$key" "$file" &>/dev/null; then
            sed -i "/^$key.*/d" "$file"
        fi
    fi
}

function common::key_value_deletor() {
    common::log_function "$*"
    local file=$1
    local key=$2

    if grep -i "^${key}[[:space:]]*=" "$file" &>/dev/null; then
        sed -i "/^${key}[[:space:]]*=.*/d" "$file"
    fi
}

function common::get_interfaces() {
    common::log_function
    local interfaces=""
    if [ ! -d /sys/class/net/ ];then
        echo ""
        return
    fi
    interfaces=$(ls /sys/class/net/ | grep 'eth[0-9]\+$')
    echo "$interfaces"
}



##################################metadata util##################################
s_metadata_url="100.100.100.200/latest/meta-data/network/interfaces/macs"
function metadata::get_interface_data() {
    common::log_function "$*"
    local mac=$1
    local data_key=$2
    if [ -z "$mac" ]; then
      echo ""
      return
    fi
    local data=""
    data=$(curl -L -s "$s_metadata_url/$mac/$data_key")
    local ret=$?
    if [ $ret -ne 0 ];then
      echo ""
      return
    fi
    if echo "$data" | grep -q "404 - Not Found";then
      echo ""
      return
    fi
    echo "$data"
}

function metadata::get_interface_array() {
    common::log_function "$*"
    local array=""
    array=$(metadata::get_interface_data "$1" "$2")
    if [ -z "$array" ];then
      echo ""
      return
    fi
    local array_len=${#array}
    local datas=""
    datas=${array:(-$array_len+1):($array_len-2)}
    echo "$datas"
}

function metadata::get_interface_array_data0() {
    common::log_function "$*"
    local datas=""
    datas=$(get_interface_array "$1" "$2")
    if [ -z "$datas" ];then
      echo ""
      return
    fi
    local data=""
    data=$(echo "$datas" | awk -F',' '{ printf $1}')
    echo "$data"
}

function metadata::get_ipv6_prefix_len() {
    common::log_function "$*"
    local vswitch_cidr_block=""
    vswitch_cidr_block=$(metadata::get_interface_data "$1" "vswitch-ipv6-cidr-block")
    if [ -z "$vswitch_cidr_block" ];then
      echo ""
      return
    fi
    local prefix_len=""
    prefix_len=${vswitch_cidr_block##*/}
	echo "$prefix_len"
}

function metadata::get_ipv6s() {
    common::log_function "$*"
    local ipv6s=""
    ipv6s=$(metadata::get_interface_array "$1" "ipv6s")
    if [ -z "$ipv6s" ];then
      echo ""
      return
    fi

    local ipv6_array=""
    ipv6_array=${ipv6s//,/ }
    echo "$ipv6_array"
}

function metadata::get_ipv6_gateway() {
    common::log_function "$*"
    metadata::get_interface_data "$1" "ipv6-gateway"
}


# base functions - sles
function base::restart_network () {
    common::log_function
    if which systemctl > /dev/null 2>&1; then
        systemctl restart network >> "$g_log_file" 2>&1
    else
        service network restart >> "$g_log_file" 2>&1
    fi
}

function base::enable_ipv6() {
    common::log_function
    # check /etc/modprobe.d/50-ipv6.conf
    ipv6::disable_modprobed_50_ipv6

    # check /etc/sysctl.conf
    ipv6::enable_sysctl_conf
}

function base::disable_ipv6 () {
    common::log_function
    # check /etc/sysctl.conf
    ipv6::disable_sysctl_conf
}

##################################grub util##################################
function grub::do_config_default_grub() {
    common::log_function "$*"
    local boot_params=$1
    local config_option=$2

    local default_grub_file=/etc/default/grub
    [[ ! -f $default_grub_file ]] && return

    if [[ "$config_option" == "add" ]]; then
        if ! grep -q 'GRUB_CMDLINE_LINUX=' $default_grub_file; then
            echo "GRUB_CMDLINE_LINUX=\" $boot_params\"" >> $default_grub_file
        else
            if ! grep -q "GRUB_CMDLINE_LINUX=\".*$boot_params" $default_grub_file; then
                sed -i "/GRUB_CMDLINE_LINUX=\"/s/\"$/ $boot_params\"/" $default_grub_file
            fi
        fi
    elif [[ "$config_option" == "del" ]]; then
        if grep -q "GRUB_CMDLINE_LINUX=\".*$boot_params" $default_grub_file; then
            sed -i "/GRUB_CMDLINE_LINUX=/s/$boot_params//" $default_grub_file
        fi
    fi
}

function grub::do_config_grub_legacy() {
    common::log_function "$*"
    local grub_cfg_file=$1
    local boot_params=$2
    local config_option=$3

    grep -n -E 'kernel*[[:space:]]+(/boot)?/vmlinuz-.*root=.*' "$grub_cfg_file" | \
    while read line ; do
        if [[ "$config_option" == "add" ]]; then
            if ! echo "$line" | grep -q "$boot_params"; then
                line_no=${line%%:*}
                chmod 600 "$grub_cfg_file"
                sed -i "$line_no s/$/ $boot_params/" "$grub_cfg_file"
            fi
        elif [[ "$config_option" == "del" ]]; then
            if  echo "$line" | grep -q "$boot_params"; then
                line_no=${line%%:*}
                chmod 600 "$grub_cfg_file"
                sed -i "$line_no s/$boot_params//" "$grub_cfg_file"
            fi
        fi
    done
}

function grub::do_config_grub_v2() {
    common::log_function "$*"
    local grub_cfg_file=$1
    local boot_params=$2
    local config_option=$3

    grep -n -E 'linux[16]*[[:space:]]+(/boot)?/vmlinuz-.*root=.*' "$grub_cfg_file" | \
    while read line; do
        if [[ "$config_option" == "add" ]]; then
            if ! echo "$line" | grep -q "$boot_params"; then
                line_no=${line%%:*}
                chmod 600 "$grub_cfg_file"
                sed -i "$line_no s/$/ $boot_params/" "$grub_cfg_file"
            fi
        elif [[ "$config_option" == "del" ]]; then
            if echo "$line" | grep -q "$boot_params"; then
                line_no=${line%%:*}
                chmod 600 "$grub_cfg_file"
                sed -i "$line_no s/$boot_params//" "$grub_cfg_file"
            fi
        fi
    done
}

function grub::do_config_grub_oem() {
    common::log_function "$*"
    local grub_cfg_file=$1
    local boot_params=$2
    local config_option=$3

    if [[ "$config_option" == "add" ]]; then
        if ! grep -q 'set linux_append=' "$grub_cfg_file"; then
            echo "set linux_append=\" $boot_params\"" >> "$grub_cfg_file"
        else
            if ! grep -q "set linux_append=\".*$boot_params" "$grub_cfg_file"; then
                sed -i "/set linux_append=\"/s/\"$/ $boot_params\"/" "$grub_cfg_file"
            fi
        fi
    elif [[ "$config_option" == "del" ]]; then
        if grep -q "set linux_append=\".*$boot_params" "$grub_cfg_file"; then
            sed -i "/set linux_append=/s/$boot_params//" "$grub_cfg_file"
        fi
    fi
}

function grub::do_config_grub_cfg() {
    common::log_function "$*"
    local boot_params=$1
    local config_option=$2

    if [[ -f /boot/grub/grub.cfg ]]; then
        grub::do_config_grub_v2 /boot/grub/grub.cfg "$boot_params" "$config_option"
    fi

    if [[ -f /boot/grub2/grub.cfg ]]; then
        grub::do_config_grub_v2 /boot/grub2/grub.cfg "$boot_params" "$config_option"
    fi

    if [[ -f /usr/share/oem/grub.cfg ]]; then
        grub::do_config_grub_oem /usr/share/oem/grub.cfg "$boot_params" "$config_option"
    fi

    if [[ -f /boot/grub/grub.conf ]]; then
        grub::do_config_grub_legacy /boot/grub/grub.conf "$boot_params" "$config_option"
    fi

    if [[ -f /boot/grub/menu.lst ]]; then
        grub::do_config_grub_legacy /boot/grub/menu.lst "$boot_params" "$config_option"
    fi
}

function grub::do_config_grub_entry() {
    common::log_function "$*"
    grub::do_config_default_grub "$1" "$2"
    grub::do_config_grub_cfg "$1" "$2"
}

function grub::config_grub() {
    common::log_function "$*"
    for i in "$@" ; do
        grub::do_config_grub_entry "$i" add
    done
}

function grub::del_params_grub() {
    common::log_function "$*"
    for i in "$@" ; do
        grub::do_config_grub_entry "$i" del
    done
}

function grub::del_grub_ipv6_disable() {
    common::log_function "$*"
    local ipv6_disable='ipv6.disable=1'
    grub::del_params_grub $ipv6_disable
}


##################################ipv6_util##################################
function ipv6::is_grub_ipv6_disabled() {
    common::log_function
    # check if need to del grub ipv6 disable
    if grep -q "ipv6.disable=1" /proc/cmdline; then
        echo "1"
    else
        echo "0"
    fi
}

function ipv6::del_grub_ipv6_disable() {
    common::log_function
    # check if need to del grub ipv6 disable
    local is_disabled=""
    is_disabled=$(ipv6::is_grub_ipv6_disabled)
    if [ "$is_disabled" == "1" ]; then
        grub::del_grub_ipv6_disable
        g_ret=$?
        g_need_reboot=1
        common::ret_log "delete grub ipv6 disable"
    fi
}

function ipv6::enable_sysctl_conf() {
    common::log_function
    # check /etc/sysctl.conf
    local sysctl_conf_file=/etc/sysctl.conf
    common::key_value_editer "$sysctl_conf_file" net.ipv6.conf.all.disable_ipv6 0
    g_ret=$?
    common::ret_log "check $sysctl_conf_file net.ipv6.conf.all.disable_ipv6"
    common::key_value_editer "$sysctl_conf_file" net.ipv6.conf.default.disable_ipv6 0
    g_ret=$?
    common::ret_log "check $sysctl_conf_file net.ipv6.conf.default.disable_ipv6"
    common::key_value_editer "$sysctl_conf_file" net.ipv6.conf.lo.disable_ipv6 0
    g_ret=$?
    common::ret_log "check $sysctl_conf_file net.ipv6.conf.lo.disable_ipv6"
    common::key_value_editer "$sysctl_conf_file" net.ipv6.conf.eth0.disable_ipv6 0
    g_ret=$?
    common::ret_log "check $sysctl_conf_file net.ipv6.conf.eth0.disable_ipv6"
    # update /etc/sysctl.conf
    if [[ g_need_reboot -eq 0 ]]; then
        sysctl -p > /dev/null 2>&1
        g_ret=$?
        common::ret_log "update $sysctl_conf_file"
    fi
}

function ipv6::disable_sysctl_conf() {
    common::log_function
    # check /etc/sysctl.conf
    local sysctl_conf_file=/etc/sysctl.conf
    common::key_value_editer "$sysctl_conf_file" net.ipv6.conf.all.disable_ipv6 1
    g_ret=$?
    common::ret_log "check $sysctl_conf_file net.ipv6.conf.all.disable_ipv6"
    common::key_value_editer "$sysctl_conf_file" net.ipv6.conf.default.disable_ipv6 1
    g_ret=$?
    common::ret_log "check $sysctl_conf_file net.ipv6.conf.default.disable_ipv6"
    common::key_value_editer "$sysctl_conf_file" net.ipv6.conf.lo.disable_ipv6 1
    g_ret=$?
    common::ret_log "check $sysctl_conf_file net.ipv6.conf.lo.disable_ipv6"
    common::key_value_editer "$sysctl_conf_file" net.ipv6.conf.eth0.disable_ipv6 1
    g_ret=$?
    common::ret_log "check $sysctl_conf_file net.ipv6.conf.eth0.disable_ipv6"
}

function ipv6::enable_modprobed_disable_conf() {
    common::log_function
    local disable_ipv6_file=/etc/modprobe.d/disable_ipv6.conf
    common::key_value_editer "$disable_ipv6_file" "options ipv6 disable" 0
    g_ret=$?
    common::ret_log "check $disable_ipv6_file"
}

function ipv6::disable_modprobed_disable_conf() {
    common::log_function
    local disable_ipv6_file=/etc/modprobe.d/disable_ipv6.conf
    common::key_value_editer "$disable_ipv6_file" "options ipv6 disable" 1
    g_ret=$?
    common::ret_log "check $disable_ipv6_file"
}

function ipv6::enable_sysconfig_network() {
    common::log_function
    local sysconfig_network_file=/etc/sysconfig/network
    common::key_value_editer "$sysconfig_network_file" NETWORKING_IPV6 yes
    g_ret=$?
    common::ret_log "check $sysconfig_network_file"
}

function ipv6::check_ipv6_module() {
    common::log_function
    if [[ g_need_reboot -eq 0 ]]; then
        if grep -q "CONFIG_IPV6=m" /boot/config-"$(uname -r)"; then
            # reload ipv6 module
            modprobe -r ipv6 > /dev/null 2>&1
            modprobe ipv6 > /dev/null 2>&1
            ipv6_module_arg=$(lsmod | grep ipv6 | awk '{print $3}')
            # check if ipv6 module arg is invalid
            if [[ "$ipv6_module_arg" -eq 0 ]]; then
                g_ret=1
            fi
            common::ret_log "check ipv6 modules"
        fi
    fi
}

function ipv6::disable_sysconfig_network() {
    common::log_function
    local sysconfig_network_file=/etc/sysconfig/network
    common::key_value_editer "$sysconfig_network_file" NETWORKING_IPV6 no
    g_ret=$?
    common::ret_log "check $sysconfig_network_file"
}

function ipv6::disable_modprobed_50_ipv6() {
    common::log_function
    local modprobed_50_ipv6_file=/etc/modprobe.d/50-ipv6.conf
    common::key_value_editer "$modprobed_50_ipv6_file" NETWORKING_IPV6 no
    g_ret=$?
    common::ret_log "check $modprobed_50_ipv6_file"
}

function ipv6::check_inet6() {
    common::log_function
    if ! ip addr | grep -q inet6; then
        g_ret=1
    fi
    common::ret_log "check inet6"
}

function ipv6::begin_ipv6() {
    common::log_function
    common::log "ECS Utils IPv6 $g_util_version." "Info"
    common::log "IPv6 $1 Begin..." "Info"
}

function ipv6::config_dev_ipv6_by_metadata() {
    common::log_function "$*"
    # config ipv6
    local dev=$1
    if [[ -z "$dev" ]]; then
        common::log "paramter [dev] is empty." "Error"
        exit 1
    fi
    local ip6s=$2
    local prefix_len=$3
    local gw6=$4
    if [[ -n "$ip6s" ]] && [[ -n "$gw6" ]] && [[ -n "$prefix_len" ]]; then
        config_dev_ipv6 "$dev" "$ip6s" "$prefix_len" "$gw6"
    else
        # parse dev ipv6 metadata
        local mac=""
        mac=$(cat /sys/class/net/"$dev"/address)
        ip6s=$(metadata::get_ipv6s "$mac")
        if [ -z "$ip6s" ]; then
            common::log "get [$mac] ipv6 metadata null" "Warn"
        fi
        prefix_len=$(metadata::get_ipv6_prefix_len "$mac")
        if [ -z "$prefix_len" ];then
            common::log "get [$mac] prefix len metadata null" "Warn"
        fi
        gw6=$(metadata::get_ipv6_gateway "$mac")
        if [ -z "$gw6" ]; then
            common::log "get [$mac] ipv6 gateway metadata null" "Warn"
        fi
        config_dev_ipv6 "$dev" "$ip6s" "$prefix_len" "$gw6" 
    fi
}

function ipv6::config_ipv6() {
    common::log_function "$*"
    local dev=$1
    local ip6s=$2
    local prefix_len=$3
    local gw6=$4
    if [[ -n "$dev" ]]; then
        # config dev ipv6
        ipv6::config_dev_ipv6_by_metadata "$dev" "$ip6s" "$prefix_len" "$gw6"
    else
        # config all dev ipv6
        local interfaces=""
        interfaces=$(common::get_interfaces)
        if [ -z "$interfaces" ];then
            g_ret=1
        fi
        common::ret_log "get interfaces"
        for interface in $interfaces
        do
            ipv6::config_dev_ipv6_by_metadata "$interface" "" "" ""
        done
    fi
}

function ipv6::enable_ipv6() {
    common::log_function
    # check if need to del grub ipv6 disable
    ipv6::del_grub_ipv6_disable

    base::enable_ipv6

    if [[ g_need_reboot -eq 0 ]]; then
        # check inet6
        ipv6::check_inet6
    fi
}

function ipv6::disable_ipv6() {
    common::log_function
    # check inet6
    local ip_addr_inet6=""
    ip_addr_inet6=$(ip addr | grep inet6)
    if [ -n "$ip_addr_inet6" ]; then
        # check if any global ipv6s are configed
        if echo "$ip_addr_inet6" | grep -q global; then
            g_need_restart_network=1
        fi
    fi

    base::disable_ipv6

    # config all dev ipv6 disable
    local interfaces=""
    interfaces=$(common::get_interfaces)
    for interface in $interfaces
    do
        clean_ipv6_conf "$interface"
    done
    g_need_restart_network=1
}

function ipv6::finish_ipv6() {
    common::log_function "$*"
    if [[ g_need_restart_network -eq 1 ]]; then
        #restart $dev
        base::restart_network "$1"
        g_ret=$?
        common::ret_log "restart $dev"
        # if inet6 exsits after disabled ipv6, need to reboot.
        if [ "$1" == "Disable" ]; then
            if ip addr | grep -q inet6; then
                g_need_reboot=1
            fi
        fi
    fi
    # check if need to reboot
    if [[ g_need_reboot -eq 1 ]]; then
        common::log "IPv6 $1 Finished, Need To Reboot." "Done"
    else
        common::log "IPv6 $1 Finished." "Done"
    fi
}

function ipv6::get_first_ipv6() {
    common::log_function "$*"
    local ip6s=$1
    local first_ip6=""
    for ip6_elem in $ip6s; do
        first_ip6=$ip6_elem
        break
    done
    echo "$first_ip6"
}

function ipv6::get_second_ipv6s() {
    common::log_function "$*"
    local ip6s=$1
    local second_ipv6s=""
    local prefix_len=""
    second_ipv6s=${ip6s#* }
    if [ "$second_ipv6s" == "$ip6s" ]; then
        echo ""
        return
    fi
    echo "$second_ipv6s"
}

function ipv6::main_entry() {
    common::log_function "$*"
    local action=$1
    if [ "$action" == '--version' ]; then
        global::print_version
    elif [ "$action" == '--help' ]; then
        global::print_usage
    elif [ "$action" == '--enable' ]; then
        ipv6::begin_ipv6 "Enable"
        ipv6::enable_ipv6
        ipv6::finish_ipv6 "Enable"
    elif [ "$action" == '--disable' ]; then
        ipv6::begin_ipv6 "$G_ACTION_DISABLE"
        ipv6::disable_ipv6
        ipv6::finish_ipv6 "$G_ACTION_DISABLE"
    elif [ "$action" == '--static' ]; then
        local dev_arg=$2
        if [ -z "$dev_arg" ]; then
            common::log "static paramer [dev] is empty." "Error"
            exit 1
        fi
        # check /sys/class/net/$dev
        local sys_net_dir="/sys/class/net/$dev_arg"
        if [ ! -d "$sys_net_dir" ]; then
            common::log "$sys_net_dir is not exist." "Error"
            exit 1
        fi

        local ip6s_arg=$3
        local prefix_len_arg=$4
        local gw6_arg=$5
        if [ -z "$ip6s_arg" ] || [ -z "$prefix_len_arg" ] || [ -z "$gw6_arg" ]; then
            common::log "config paramer [ip6s] or [prefix_len]  or [gw6] is empty." "Error"
            exit 1
        fi

        ipv6::begin_ipv6 "Config"
        ipv6::enable_ipv6
        ipv6::config_ipv6 "$dev_arg" "$ip6s_arg" "$prefix_len_arg" "$gw6_arg"
        ipv6::finish_ipv6 "Config"
    elif [ -z "$action" ]; then
        ipv6::begin_ipv6 "Auto Config"
        ipv6::enable_ipv6
        ipv6::config_ipv6
        ipv6::finish_ipv6 "Auto Config"
    else 
        echo "Invalid option: [$action]"
        global::print_usage
        exit 1
    fi

    exit 0
}



clean_ipv6_conf() {
    common::log_function "$*"
    # clean interface config
    local dev=$1
    local ifcfg_file="/etc/sysconfig/network/ifcfg-$dev"
    if [ -f "$ifcfg_file" ]; then
        sed -i "/^IPADDR_[0-9]\+[[:space:]]*=.*:.*'$/d" "$ifcfg_file"
        sed -i "/^PREFIXLEN_[0-9]\+[[:space:]]*='[0-9]\+'$/d" "$ifcfg_file"
    else
        common::log "$ifcfg_file is not exist." "Warn"
        return
    fi

    # clean gateway
    local routes_file=/etc/sysconfig/network/routes
    if [ -f "$routes_file" ]; then
        sed -i "/^default[[:space:]]\+.*:.*/d" "$routes_file"
    fi
}

config_one_ipv6() {
    common::log_function "$*"
    local ifcfg_file=$1
    local index=$2
    local ip6=$3
    local prefix_len=$4

    echo -e "\nIPADDR_$index='$ip6'\nPREFIXLEN_$index='$prefix_len'" >> "$ifcfg_file"
    g_ret=$?
    common::ret_log "config $ifcfg_file ipv6 $index"
}

config_gw6() {
    common::log_function "$*"
    local gw6=$1
    local routes_file=/etc/sysconfig/network/routes
    echo "default $gw6 - -" >> "$routes_file"
}

config_dev_ipv6() {
    common::log_function "$*"
    # config dev ipv6
    local dev=$1
    local ip6s=$2
    local prefix_len=$3
    local gw6=$4
    common::log "Config $dev..." "Info"

    local ifcfg_file="/etc/sysconfig/network/ifcfg-$dev"
    if [ ! -f "$ifcfg_file" ]; then
        touch "$ifcfg_file"
    fi
    if [ -n "$ip6s" ] && [ -n "$prefix_len" ] && [ -n "$gw6" ]; then
        # clean ipv6 conf
        clean_ipv6_conf "$dev"

        # then append ipv6 conf
        # config first ipv6
        local first_ipv6=""
        first_ipv6=$(ipv6::get_first_ipv6 "$ip6s")
        if [ -z "$first_ipv6" ]; then
            g_ret=1
        fi
        common::ret_log "get first ipv6"
        config_one_ipv6 "$ifcfg_file" "0" "$first_ipv6" "$prefix_len"
        g_ret=$?
        common::ret_log "config $ifcfg_file first ipv6"

        # config second ipv6s
        local second_ipv6s=""
        local second_ipv6_count=0
        second_ipv6s=$(ipv6::get_second_ipv6s "$ip6s")
        if [ -n "$second_ipv6s" ]; then
            for second_ipv6 in $second_ipv6s
            do
                if [ -z "$second_ipv6" ]; then
                    continue
                fi
                second_ipv6_count=$(( second_ipv6_count + 1 ))
                config_one_ipv6 "$ifcfg_file" "$second_ipv6_count" "$second_ipv6" "$prefix_len"
                g_ret=$?
                common::ret_log "config $ifcfg_file second ipv6s"
            done
        fi

        # config default gw6
        config_gw6 "$gw6"
        g_ret=$?
        common::ret_log "config gw6"
    else
        clean_ipv6_conf "$dev"
    fi

    g_need_restart_network=1
}

ipv6::main_entry "$@"
