#!/bin/bash
# IBM(c) 2011EPL license http://www.eclipse.org/legal/epl-v10.html

#-------------------------------------------------------------------------------
#=head1  routeop
#=head2  routeop is called by makeroutes command and setuproutes postscript to
#        setup a route on a node.
#        The syntax is:
#          routeop add/delete net mask gateway ifname   #NOTE: the add/delete will be
#                 obsoleted, using 'replace' is recommended.
#          routeop replace net mask gateway ifname   #NOTE: it only works for sles so far
#                 net - IP of net like 192.168.1.0. The keyword
#                       'default' is used to set the default route.
#                 mask - The length of the netmask (CIDR) like 8,16,24 OR
#                       the dotted-decimal format like 255.255.0.0
#                 gateway - The next hop. It could be set to 0.0.0.0 for omitting
#                 ifname - The interface to route to the next hop
#=head3 example
#        routeop replace default 0 10.1.0.209 eth0
#        routeop replace 50.1.0.0 16 10.1.0.210 eth0
#        routeop replace 60.1.1.0 24 0.0.0.0 eth0
#        routeop replace 70.1.1.0 24 10.1.0.211    #NOTE: this is NOT supported for redhat
#=cut
#-------------------------------------------------------------------------------

if [ "$(uname -s|tr 'A-Z' 'a-z')" = "linux" ];then
   str_dir_name=`dirname $0`
   if [ -f $str_dir_name/xcatlib.sh ]; then
       . $str_dir_name/xcatlib.sh
   elif [ -f /install/postscripts/xcatlib.sh ]; then
       . /install/postscripts/xcatlib.sh
   elif [ -f /xcatpost/xcatlib.sh ]; then
       . /xcatpost/xcatlib.sh
   fi
fi
if [ -n "$LOGLABEL" ]; then
    log_label=$LOGLABEL
else
    log_label="xcat"
fi
op=$1

net=$2
mask=$3
gw=$4
if [ -n "$5" ]; then
    ifname=$5
fi

# use nummask to know whether the netmask format is 255.255.255.0 or CIDR (a number)
nummask=0
echo $mask | grep -E "^[.0123456789]+$" > /dev/null
if [ $? -ne 0 ]; then
    echo "Error: invalid format of netmask $mask."
    exit 1
else
    echo $mask | grep -E "^[0123456789]+$" > /dev/null
    if [ $? -eq 0 ]; then # only has digital
        nummask=1    # the netmask is the length of network mask.
        if [ $mask -ge 128 ]; then
            echo "Error: invalid format of netmask $mask."
            exit 1
        fi
    fi
fi



function debianpreconf(){
    #create the config sub dir
    if [ ! -d "/etc/network/interfaces.d" ];then
        mkdir -p "/etc/network/interfaces.d"
    fi
    #search xcat flag
    XCATFLAG=`grep "#XCAT_CONFIG" /etc/network/interfaces`
    if [ -n "$XCATFLAG" ];then
        return
    fi

    #back up the old interface configure
    if [ ! -e "/etc/network/interfaces.bak" ];then
        mv /etc/network/interfaces /etc/network/interfaces.bak
    fi

    #create the new config file
    echo "#XCAT_CONFIG" > /etc/network/interfaces
    echo "source /etc/network/interfaces.d/*" >> /etc/network/interfaces

    CONFFILE=''

    #read the backfile
    cat /etc/network/interfaces.bak | while read LINE
    do
        if [ ! "$LINE" ];then
            continue
        fi
        FIRSTCHAR=${LINE:0:1}
        if [ $FIRSTCHAR = '#' ];then
            continue
        fi

        CONFTYPE=`echo $LINE | cut -d" " -f1`
        if [ $CONFTYPE = 'auto' -o $CONFTYPE = 'allow-hotplug' ];then
            LINE=${LINE#$CONFTYPE}
            for NICNAME in $LINE; do
                echo "$CONFTYPE $NICNAME" > "/etc/network/interfaces.d/$NICNAME"
            done
        elif [ $CONFTYPE = 'iface' -o $CONFTYPE = 'mapping' ];then
            #find out the nic name, should think about the eth0:1
            NICNAME=`echo $LINE | cut -d" " -f 2 | cut -d":" -f 1`
            CONFFILE="/etc/network/interfaces.d/$NICNAME"
            if [ ! -e $CONFFILE ];then
                echo "auto $NICNAME" > $CONFFILE
            fi

            #write lines into the conffile
            echo $LINE >> $CONFFILE
        else
            echo $LINE >> $CONFFILE
        fi

    done
}

route_exists()
{
    local route_net=$1
    local route_mask=$2
    local route_gw=$3
    local route_ifname
    local ret=0
    local result
    local os_type

    if [ -n "$4" ]; then
        route_ifname=$4
    else
        route_ifname=$ifname
    fi

    os_type=$(uname -s)

    # ipv6
    if echo $route_net | grep : 2>&1 1>/dev/null
    then
        result=`ip -6 route show $route_net/$route_mask`
        if [ $? -ne 0 ] || [ -z "$result" ]
        then
            ret=0
        else
            ret=1
        fi
    else
        if [ "$os_type" = "Linux" ] && command -v ip >/dev/null 2>&1; then
            local route_prefix=$route_mask
            local line

            if ! echo "$route_prefix" | grep -E "^[0123456789]+$" >/dev/null 2>&1; then
                if type v4mask2prefix >/dev/null 2>&1; then
                    route_prefix=$(v4mask2prefix "$route_mask")
                fi
            fi

            if [ "$route_net" = "default" ]; then
                result=$(ip route show default 2>/dev/null)
            elif echo "$route_prefix" | grep -E "^[0123456789]+$" >/dev/null 2>&1; then
                result=$(ip route show "$route_net/$route_prefix" 2>/dev/null)
            else
                result=$(ip route show "$route_net" 2>/dev/null)
            fi

            while IFS= read -r line
            do
                [ -n "$line" ] || continue
                if [ -n "$route_gw" ] && [ "$route_gw" != "0.0.0.0" ]; then
                    case " $line " in
                        *" via $route_gw "*) ;;
                        *) continue ;;
                    esac
                fi
                if [ -n "$route_ifname" ]; then
                    case " $line " in
                        *" dev $route_ifname "*) ;;
                        *) continue ;;
                    esac
                fi
                ret=1
                break
            done <<< "$result"
        else
            result=`netstat -nr|grep $route_net`;
            if [ $? -eq 0 ] && [ -n "$result" ]; then
                for x in `echo "$result"|tr -s " " ","`
                    do
                if [ "$os_type" = "Linux" ]; then
                    net1=`echo $x|cut -d',' -f1`
                    gw1=`echo $x|cut -d',' -f2`
                    mask1=`echo $x|cut -d',' -f3`
                    ifname1=`echo $x|cut -d',' -f8`
                    if [ "$route_net" = "$net1" ] && [ "$route_mask" = "$mask1" ] && [ "$route_gw" = "$gw1" ] && [ "$route_ifname" = "$ifname1"  ]; then
                        ret=1
                        break
                    fi
                else
                    tmp1=`echo $x|cut -d',' -f1`
                    gw1=`echo $x|cut -d',' -f2`

                    n1=`echo $route_net |cut -d'.' -f1`
                    n2=`echo $route_net |cut -d'.' -f2`
                    n3=`echo $route_net |cut -d'.' -f3`
                    n4=`echo $route_net |cut -d'.' -f4`

                    netnum="$(( ($n1 << 24) + ($n2 << 16) + ($n3 << 8) + $n4 ))"
                    bits=32
                    while [ `expr $netnum % 2` -eq 0 ]
                    do
                        bits="$(( $bits - 1 ))"
                        netnum="$(( $netnum >> 1 ))"
                    done

                    tmp2="$route_net/$bits";
                    #echo "$tmp2=$tmp2"
                    if [ "$tmp1" = "$tmp2" ] && [ "$route_gw" = "$gw1" ]; then
                        ret=1
                        break
                    fi
                fi
                    done
            fi
        fi
    fi

    echo $ret
}

is_ipv6_route()
{
    case "$1" in
        *:*) return 0 ;;
        *) return 1 ;;
    esac
}

ipv4_route_prefix()
{
    local route_mask=$1

    if echo "$route_mask" | grep -E "^[0123456789]+$" >/dev/null 2>&1; then
        echo "$route_mask"
    elif type v4mask2prefix >/dev/null 2>&1; then
        v4mask2prefix "$route_mask"
    else
        echo "$route_mask"
    fi
}

ipv4_route_destination()
{
    local route_net=$1
    local route_mask=$2

    if [ "$route_net" = "default" ]; then
        echo "default"
    else
        echo "$route_net/$(ipv4_route_prefix "$route_mask")"
    fi
}

redhat_uses_nmcli_routes()
{
    [ "$OS_name" = "redhat" ] || return 1
    command -v nmcli >/dev/null 2>&1 || return 1

    if [[ "$OSVER" =~ ^(rhel|rhels|alma|almalinux|rocky|centos|ol)(9|1[0-9]) ]]; then
        return 0
    fi

    [ -r /etc/os-release ] || return 1
    local os_id
    local version_major
    os_id=$(sed -n 's/^ID=//p' /etc/os-release | head -1 | tr -d '"')
    version_major=$(sed -n 's/^VERSION_ID=//p' /etc/os-release | head -1 | tr -d '"' | cut -d. -f1)

    case "$os_id" in
        rhel|rocky|almalinux|centos|ol)
            case "$version_major" in
                ''|*[!0-9]*) return 1 ;;
            esac
            [ "$version_major" -ge 9 ]
            ;;
        *)
            return 1
            ;;
    esac
}

route_ifname()
{
    local route_net=$1
    local route_gw=$2
    local requested_ifname=$3

    if [ -n "$requested_ifname" ]; then
        echo "$requested_ifname"
        return 0
    fi

    if [ "$route_net" = "default" ]; then
        if is_ipv6_route "$route_gw"; then
            ip -6 route show default 2>/dev/null | awk '{for (i = 1; i <= NF; i++) if ($i == "dev") {print $(i + 1); exit}}'
        else
            ip route show default 2>/dev/null | awk '{for (i = 1; i <= NF; i++) if ($i == "dev") {print $(i + 1); exit}}'
        fi
    fi
}

nm_connection_for_ifname()
{
    local dev=$1
    local con_name

    [ -n "$dev" ] || return 1

    con_name=$(nmcli -g GENERAL.CONNECTION device show "$dev" 2>/dev/null | head -1)
    if [ -n "$con_name" ] && [ "$con_name" != "--" ]; then
        echo "$con_name"
        return 0
    fi

    con_name=$(nmcli -g NAME,DEVICE connection show --active 2>/dev/null | awk -F: -v dev="$dev" '$2 == dev {print $1; exit}')
    if [ -n "$con_name" ]; then
        echo "$con_name"
        return 0
    fi

    if nmcli connection show "$dev" >/dev/null 2>&1; then
        echo "$dev"
        return 0
    fi

    return 1
}

nmcli_remove_routes_by_destination()
{
    local con_name=$1
    local family=$2
    local route_dest=$3
    local current_routes
    local current_route

    current_routes=$(nmcli -g "$family.routes" connection show "$con_name" 2>/dev/null | tr ',' '\n')
    while IFS= read -r current_route
    do
        current_route=$(echo "$current_route" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
        [ -n "$current_route" ] || continue
        case "$current_route" in
            "$route_dest"|"$route_dest "*)
                nmcli connection modify "$con_name" -"$family.routes" "$current_route" >/dev/null 2>&1
                ;;
        esac
    done <<< "$current_routes"
}

nmcli_persistent_route()
{
    local route_action=$1
    local route_net=$2
    local route_mask=$3
    local route_gw=$4
    local route_dev
    local con_name
    local family
    local route_dest
    local route_value
    local empty_gw
    local rc

    route_dev=$(route_ifname "$route_net" "$route_gw" "$5")
    if [ -z "$route_dev" ]; then
        echo "Error: the device name is necessary to configure a NetworkManager persistent route."
        return 1
    fi

    con_name=$(nm_connection_for_ifname "$route_dev")
    if [ -z "$con_name" ]; then
        echo "Error: unable to find a NetworkManager connection for $route_dev."
        return 1
    fi

    if is_ipv6_route "$route_net" || is_ipv6_route "$route_gw"; then
        family="ipv6"
        empty_gw="::"
    else
        family="ipv4"
        empty_gw="0.0.0.0"
    fi

    if [ "$route_net" = "default" ]; then
        if [ "$route_action" = "delete" ]; then
            nmcli connection modify "$con_name" "$family.gateway" ""
            rc=$?
            [ $rc -eq 0 ] && echo "Persistent default route removed from NetworkManager connection \"$con_name\"."
            return $rc
        elif [ -n "$route_gw" ] && [ "$route_gw" != "$empty_gw" ]; then
            nmcli connection modify "$con_name" "$family.gateway" "$route_gw" "$family.never-default" no
            rc=$?
            [ $rc -eq 0 ] && echo "Persistent default route via $route_gw added to NetworkManager connection \"$con_name\"."
            return $rc
        else
            if [ "$family" = "ipv6" ]; then
                route_value="::/0"
            else
                route_value="0.0.0.0/0"
            fi
            nmcli connection modify "$con_name" -"$family.routes" "$route_value" >/dev/null 2>&1
            nmcli connection modify "$con_name" +"$family.routes" "$route_value"
            rc=$?
            [ $rc -eq 0 ] && echo "Persistent default route for $route_dev added to NetworkManager connection \"$con_name\"."
            return $rc
        fi
    else
        if [ "$family" = "ipv4" ]; then
            route_dest=$(ipv4_route_destination "$route_net" "$route_mask")
        else
            route_dest="$route_net/$route_mask"
        fi
        route_value="$route_dest"
        if [ -n "$route_gw" ] && [ "$route_gw" != "$empty_gw" ]; then
            route_value="$route_value $route_gw"
        fi

        if [ "$route_action" = "delete" ]; then
            nmcli connection modify "$con_name" -"$family.routes" "$route_value"
            rc=$?
            [ $rc -eq 0 ] && echo "Persistent route \"$route_value\" removed from NetworkManager connection \"$con_name\"."
            return $rc
        else
            if [ "$route_action" = "replace" ]; then
                nmcli_remove_routes_by_destination "$con_name" "$family" "$route_dest"
            else
                nmcli connection modify "$con_name" -"$family.routes" "$route_value" >/dev/null 2>&1
            fi
            nmcli connection modify "$con_name" +"$family.routes" "$route_value"
            rc=$?
            [ $rc -eq 0 ] && echo "Persistent route \"$route_value\" added to NetworkManager connection \"$con_name\"."
            return $rc
        fi
    fi
}

# handle the route replace operation that adding the setting to configuration file
replace_persistent_route()
{
    net=$1;
    mask=$2;
    gw=$3;
    if [ -n "$4" ]; then
        ifname=$4
    fi

    if [ "$(uname -s)" = "Linux" ]; then
    #determine the os name
    OS_name="something"
    if [ -f /etc/redhat-release ]
    then
        OS_name="redhat"  #it can be RedHatFerdora or CentOS
    elif [ -f /etc/SuSE-release ] || [ -f /etc/SUSE-brand ]
    then
        OS_name="sles"
    else
        OS_name="debian"
    fi

    # set the destination of the route for searching in the route configuration file
    if [ "$net" = "default" ]; then
        routedest="default"
        routedest1="default"
    else
        routedest="$net/$mask"
        routedest1="$net\/$mask"
    fi

    case $OS_name in
        sles)
            filename="/etc/sysconfig/network/routes";
            if echo $net | grep : 2>&1 1>/dev/null
            then
                # for ipv6
                if [ "$gw" = "" -o "$gw" = "::" ] ; then
                    route="$net/$mask :: - $ifname"
                    route1="$net\/$mask :: - $ifname";
                else
                    route="$net/$mask $gw - -"
                    route1="$net\/$mask $gw - -";
                fi
            else
                # for ipv4
                if [ "$gw" = "" -o "$gw" = "0.0.0.0" ] ; then
                    if [ "$net" = "default" ]; then
                        route="default - - $ifname";
                        route1="default - - $ifname";
                    else
                        route="$net/$mask - - $ifname";
                        route1="$net\/$mask - - $ifname";
                    fi
                else
                    if [ "$net" = "default" ]; then
                        route="default $gw - $ifname";
                        route1="default $gw - $ifname";
                    else
                        route="$net/$mask $gw - $ifname";
                        route1="$net\/$mask $gw - $ifname";
                    fi
                fi
            fi
            if [ -f $filename ]; then
                grep -E "^$routedest" $filename 2>&1 1>/dev/null
                if [ $? -ne 0 ]; then #route does not exist
                    echo $route >> $filename
                    echo "Persistent route \"$route\" has been added in $filename."
                else
                    # replace it
                    sed -i -e "s/${routedest1}.*/$route1/g" $filename
                    echo "Persistent route \"$route\" has been replaced in $filename."
                fi
            else
                echo "$route" > $filename
                echo "Persistent route \"$route\" has been added in $filename."
            fi
        ;;

        redhat)
            #echo "rh/fedora/centos"
            if [ -z "$ifname" -a "$net" != "default" ]; then
                echo "Error: the device name is necessary to configure static route."
                return 1
            fi
            if redhat_uses_nmcli_routes; then
                nmcli_persistent_route replace "$net" "$mask" "$gw" "$ifname"
                return $?
            fi

            if echo $net | grep : 2>&1 1>/dev/null
            then
                # ipv6
                filename="/etc/sysconfig/network-scripts/route6-$ifname"
                if [ "$gw" = "" -o "$gw" = "::" ] ; then
                    route="$net/$mask dev $ifname"
                    route1="$net\/$mask dev $ifname"
                else
                    route="$net/$mask via $gw"
                    route1="$net\/$mask via $gw"
                fi
            else
                # ipv4
                filename="/etc/sysconfig/network-scripts/route-$ifname"
                if [ "$gw" = "" -o "$gw" = "0.0.0.0" ] ; then
                    route="$net/$mask dev $ifname"
                    route1="$net\/$mask dev $ifname"
                else
                    route="$net/$mask via $gw"
                    route1="$net\/$mask via $gw"
                fi
            fi
            # default route is handled separately
            if [ "$net" = "default" ]; then
                filename="/etc/sysconfig/network"
                route="GATEWAY=$gw"
                route1=$route
                routedest="GATEWAY="
                routedest1=$routedest
            fi
            if [ -f $filename ]; then
                grep -E "^$routedest" $filename 2>&1 1>/dev/null
                if [ $? -ne 0 ]; then #route does not exist
                    echo $route >> $filename
                    echo "Persistent route \"$route\" has been added in $filename."
                else
                    # replace it
                    sed -i -e "s/${routedest1}.*/$route1/g" $filename
                    echo "Persistent route \"$route\" has been replaced in $filename."
                fi
            else
                echo "$route" > $filename
                echo "Persistent route \"$route\" has been added in $filename."
            fi
        ;;

        debian)
            debianpreconf
            matchstr=""
            v6flag=0
            # on debian/ubuntu need the network device name
            if [ -z "$ifname" ]; then
                echo "Error: the device name is necessary to configure static route."
                return 1
            fi
            filename="/etc/network/interfaces.d/$ifname"

            if [ ! -f $filename ];then
                echo "auto $ifname" > $filename
                echo "iface $ifname inet dhcp" >> $filename
            fi

            # if the route entry for a target net has been added in the if cfg file, just replace it
            cmd="post-up $cmd"
            #cmd1=${cmd//\//\\\/}
            #sed -i -e "s/.*$routedest1.*/$cmd1/g" $filename

            # for the case to add a new cmd for certain interface
            foundflag=0
            setflag=0
            tempfile="/etc/network/interfaces.d/tmp"
            >$tempfile

            while read LINE
            do
                # replace the existed setting
                echo $LINE | grep "$routedest1" 2>&1 1>/dev/null
                if [ $? -eq 0 -a $foundflag -eq 1 ];then
                    LINE=$cmd
                    setflag=1
                fi

                echo $LINE | grep "iface" 2>&1 1>/dev/null
                if [ $? -eq 0 -a $foundflag -eq 1 -a $setflag -eq 0 ];then
                    foundflag=0
                    echo "$cmd" >> $tempfile
                fi
                echo $LINE | grep "iface $ifname " 2>&1 1>/dev/null
                #this is the last line of the device
                if [ $? -eq 0 ];then
                    foundflag=1
                fi

                echo $LINE >> $tempfile
            done < $filename

            #the insert place is the last line of the config file
            if [ $foundflag -eq 1 -a $setflag -eq 0 ];then
                echo "$cmd" >> $tempfile
            fi
            mv -f $tempfile $filename
            echo "Persistent route \"$cmd\" is added in $filename.;    "
        ;;

    esac
    else #AIX
    echo "Adding persistent route on AIX is not supported yet."
    fi
}

# handle the route add operation that adding the setting to configuration file
add_persistent_route()
{
    net=$1;
    mask=$2;
    gw=$3;
    if [ -n "$4" ]; then
        ifname=$4
    fi

    xcat_config_start="# xCAT_CONFIG_START";
    xcat_config_end="# xCAT_CONFIG_END";

    if [ "$(uname -s)" = "Linux" ]; then
    #determine the os name
    OS_name="something"
    if [ -f /etc/redhat-release ]
    then
        OS_name="redhat"  #it can be RedHatFerdora or CentOS
    elif [ -f /etc/SuSE-release ] || [ -f /etc/SUSE-brand ]
    then
        OS_name="sles"
    else
        OS_name="debian"
    fi

    # The replace operation does not support redhat and debain so far
    if [ "$op" = "replace" ]; then
        if [ "$OS_name" = "redhat" -o "$OS_name" = "debain" ]; then
            echo "Warning: replace operation only supports to add persistent route for sles by now."
            return
        fi
    fi

    case $OS_name in
        sles)
        #echo "sles"
        # ipv6 net
        filename="/etc/sysconfig/network/routes";
        if echo $net | grep : 2>&1 1>/dev/null
        then
            if [ "$gw" = "" -o "$gw" = "::" ] ; then
                route="$net/$mask :: - $ifname"
                route1="$net\/$mask :: - $ifname";
            else
                route="$net/$mask $gw - -"
                route1="$net\/$mask $gw - -";
            fi
        else
            if [ "$gw" = "" -o "$gw" = "0.0.0.0" ] ; then
                if [ $nummask -eq 1 ]; then
                    if [ "$net" = "default" ]; then
                        route="default - - $ifname";
                        route1="default - - $ifname";
                    else
                        route="$net/$mask - - $ifname";
                        route1="$net\/$mask - - $ifname";
                    fi
                else
                    route="$net 0.0.0.0 $mask $ifname";
                    route1="$net 0.0.0.0 $mask $ifname";
                fi
            else
                if [ $nummask -eq 1 ]; then
                    if [ "$net" = "default" ]; then
                        route="default $gw - $ifname";
                        route1="default $gw - $ifname";
                    else
                        route="$net/$mask $gw - $ifname";
                        route1="$net\/$mask $gw - $ifname";
                    fi
                else
                    route="$net $gw $mask $ifname";
                    route1="$net $gw $mask $ifname";
                fi
            fi
        fi
        if [ -f $filename ]; then
            grep "$route" $filename 2>&1 1>/dev/null
            if [ $? -ne 0 ]; then #route does not exist
                grep "$xcat_config_start" $filename 2>&1 1>/dev/null
                if [ $? -ne 0 ]; then #no xCAT section
                    echo $xcat_config_start >> $filename
                    echo $route >> $filename
                    echo $xcat_config_end >> $filename
                else
                    sed -i -e s/"$xcat_config_end"/"$route1\n$xcat_config_end"/g $filename
                fi
                echo "Persistent route \"$route\" added in $filename."
            else
                echo "Persistent route \"$route\" already exists in $filename."
            fi
        else
            #echo "got here"
            echo "$xcat_config_start" > $filename
            echo "$route" >> $filename
            echo "$xcat_config_end" >> $filename
            echo "Route \"$route\" added in $filename."
        fi

        ;;
        debian)
            debianpreconf
            matchstr=""
            v6flag=0
            #on debian/ubuntu need the network device name
            if [ ! $ifname ];then
                ifname=`netstat -nr | grep "$net" | awk '{print $8}' | head -1`
            fi
            filename="/etc/network/interfaces.d/$ifname"

            if [ ! -f $filename ];then
                echo "auto $ifname" > $filename
                echo "iface $ifname inet dhcp" >> $filename
            fi
            echo $net | grep : 2>&1 1>/dev/null
            #ipv6
            if [ $? -eq 0 ];then
        if [ "$gw" = "" -o "$gw" = "::" ] ; then
                    matchstr="$net/$mask dev $ifname"
        else
                    matchstr="$net/$mask gw $gw"
                fi
                v6flag=1
            else
        if [ "$gw" = "" -o "$gw" = "0.0.0.0" ] ; then
                    matchstr="net $net netmask $mask dev $ifname"
        else
                    matchstr="net $net netmask $mask gw $gw"
        fi
            fi

            grep "$matchstr" $filename 2>&1 1>/dev/null
            if [ $? -ne 0 ];then
                foundflag=0
                tempfile="/etc/network/interfaces.d/tmp"
                while read LINE
                do
                    echo $LINE | grep "iface" 2>&1 1>/dev/null
                    if [ $? -eq 0 -a $foundflag -eq 1 ];then
                        foundflag=0
                        if [ $v6flag -eq 1 ];then
                    if [ "$gw" = "" -o "$gw" = "::" ] ; then
                                echo "  up route -A inet6 add $net/$mask dev $ifname" >> $tempfile
                                echo "  down route -A inet6 del $net/$mask dev $ifname" >> $tempfile
                else
                                echo "  up route -A inet6 add $net/$mask gw $gw" >> $tempfile
                                echo "  down route -A inet6 del $net/$mask gw $gw" >> $tempfile
                    fi
                        else
                    if [ "$gw" = "" -o "$gw" = "0.0.0.0" ] ; then
                    echo "  up route add -net $net netmask $mask dev $ifname" >> $tempfile
                    echo "  down route del -net $net netmask $mask dev $ifname" >> $tempfile
                else
                                echo "  up route add -net $net netmask $mask gw $gw" >> $tempfile
                                echo "  down route del -net $net netmask $mask gw $gw" >> $tempfile
                fi
                        fi
                    fi
                    echo $LINE | grep "iface $ifname " 2>&1 1>/dev/null
                    #this is the last line of the device
                    if [ $? -eq 0 ];then
                        foundflag=1
                    fi

                    echo $LINE >> $tempfile
                done < $filename
                #the insert place is the last line of the config file
                if [ $foundflag -eq 1 ];then
                    if [ $v6flag -eq 1 ];then
                if [ "$gw" = "" -o "$gw" = "::" ] ; then
                            echo "  up route -A inet6 add $net/$mask dev $ifname" >> $tempfile
                            echo "  down route -A inet6 del $net/$mask dev $ifname" >> $tempfile
            else
                            echo "  up route -A inet6 add $net/$mask gw $gw" >> $tempfile
                            echo "  down route -A inet6 del $net/$mask gw $gw" >> $tempfile
            fi
                    else
                if [ "$gw" = "" -o "$gw" = "0.0.0.0" ] ; then
                echo "  up route add -net $net netmask $mask dev $ifname" >> $tempfile
                echo "  down route del -net $net netmask $mask dev $ifname" >> $tempfile
            else
                            echo "  up route add -net $net netmask $mask gw $gw" >> $tempfile
                            echo "  down route del -net $net netmask $mask gw $gw" >> $tempfile
            fi
                    fi
                fi
                mv -f $tempfile $filename
                echo "Persistent route \"$matchstr\" added in $filename."
            else
                echo "Persisten route \"$match\" already exists in $filename"
            fi
        ;;
        redhat)
        #echo "rh/fedora/centos"
        if redhat_uses_nmcli_routes; then
            nmcli_persistent_route add "$net" "$mask" "$gw" "$ifname"
            return $?
        fi
        # ipv6 net
        if echo $net | grep : 2>&1 1>/dev/null
        then
            if [ "$gw" = "" ] ; then
            $gw = "::";
            fi
            filename="/etc/sysconfig/static-routes-ipv6";
            route="$ifname $net/$mask $gw";
            # $net/mask does not work with sed cmd
            route1="$ifname $net\/$mask $gw";
        else
            filename="/etc/sysconfig/static-routes";
            if [ "$gw" = "" -o "$gw" = "0.0.0.0" ] ; then
               route="any net $net netmask $mask dev $ifname";
               route1="any net $net netmask $mask dev $ifname";
        else
               route="any net $net netmask $mask gw $gw $ifname";
               route1="any net $net netmask $mask gw $gw $ifname";
        fi
        fi
        if [ -f $filename ]; then
            grep "$route" $filename 2>&1 1>/dev/null
            if [ $? -ne 0 ]; then #route does not exist
                grep "$xcat_config_start" $filename 2>&1 1>/dev/null
                if [ $? -ne 0 ]; then #no xCAT section
                    echo $xcat_config_start >> $filename
                    echo $route >> $filename
                    echo $xcat_config_end >> $filename
                else
                    sed -i -e s/"$xcat_config_end"/"$route1\n$xcat_config_end"/g $filename
                fi
                echo "Persistent route \"$route\" added in $filename."
            else
                echo "Persistent route \"$route\" already exists in $filename."
            fi
        else
                #echo "got here"
                echo "$xcat_config_start" > $filename
                echo "$route" >> $filename
                echo "$xcat_config_end" >> $filename
                echo "Persistent route \"$route\" added in $filename."
       fi
      ;;
    esac
    else #AIX
    echo "Adding persistent route on AIX is not supported yet."
    fi
}

rm_persistent_route()
{
    net=$1;
    mask=$2;
    gw=$3;
    if [ -n "$4" ]; then
        ifname=$4
    fi

    if [ "$(uname -s)" = "Linux" ]; then
    #determine the os name
    OS_name="something"
    if [ -f /etc/redhat-release ]
    then
        OS_name="redhat"  #it can be RedHatFerdora or CentOS
    elif [ -f /etc/SuSE-release ] || [ -f /etc/SUSE-brand ]
    then
        OS_name="sles"
    else
        OS_name="debian"
    fi

    case $OS_name in
        sles)
        #echo "sles"
        filename="/etc/sysconfig/network/routes";
        # ipv6 net
        if echo $net | grep : 2>&1 1>/dev/null
        then
        if [ $gw = "" -o $gw = "::" ] ; then
                route="$net/$mask :: - $ifname";
                route1="$net\/$mask :: - $ifname";
        else
                route="$net/$mask $gw - -";
                route1="$net\/$mask $gw - -";
        fi
        else
        if [ $gw = "" ] ; then
            $gw = "0.0.0.0";
            fi
            if [ -n "$ifname" ]; then
                route="$net $gw $mask $ifname";
                route1="$net $gw $mask $ifname";
            else
                route="$net $gw $mask -";
                route1="$net $gw $mask -";
            fi
        fi
        if [ -f $filename ]; then
            grep "$route" $filename 2>&1 1>/dev/null
            if [ $? -ne 0 ]; then # Does not exist in file
                echo "Persistent route \"$route\" does not exist in $filename."
            else
                sed -i -e s/"$route1"//g $filename
                echo "Persistent route \"$route\" removed from $filename."
            fi
        else
            echo "Persistent route file $filename does not exist."
        fi
        ;;
        debian)
            debianpreconf
            matchstr=""
            v6flag=0
            #on debian/ubuntu need the network device name
            if [ ! $ifname ];then
                ifname=`netstat -nr | grep "$net" | awk '{print $8}'`
            fi
            filename="/etc/network/interfaces.d/$ifname"

            echo $net | grep : 2>&1 1>/dev/null
            #ipv6
            if [ $? -eq 0 ];then
            if [ $gw = "" -o $gw = "::" ] ; then
                    matchstr="$net/$mask dev $ifname"
        else
                    matchstr="$net/$mask gw $gw"
        fi
                v6flag=1
            else
            if [ $gw = "" -o $gw = "0.0.0.0" ] ; then
                    matchstr="net $net netmask $mask dev $ifname"
        else
                    matchstr="net $net netmask $mask gw $gw"
        fi
            fi

            grep "$matchstr" $filename
            if [ $? -eq 0 ];then
                sed -i -e "/$matchstr/d" $filename
                echo "Persistent route \"$matchstr\" removed from $filename."
            else
                echo "Persistent route \"$matchstr\" does not exist in $filename."
            fi
        ;;
        redhat)
        #echo "rh/fedora/centos"
        if redhat_uses_nmcli_routes; then
            nmcli_persistent_route delete "$net" "$mask" "$gw" "$ifname"
            return $?
        fi
        #ipv6
        if echo $net | grep : 2>&1 1>/dev/null
        then
            filename="/etc/sysconfig/static-routes-ipv6";
            # $net/$mask does not work with sed
            if [ "$gw" = "" -o "$gw" = "::" ] ; then
                route="$ifname $net\/$mask ::"
                route1="$ifname $net/$mask ::"
        else
                route="$ifname $net\/$mask $gw"
                route1="$ifname $net/$mask $gw"
        fi
        else
            filename="/etc/sysconfig/static-routes";
            if [ "$gw" = "" -o "$gw" = "0.0.0.0" ] ; then
               route="any net $net netmask $mask dev $ifname";
               route1="any net $net netmask $mask dev $ifname";
            else
               route="any net $net netmask $mask gw $gw $ifname";
               route1="any net $net netmask $mask gw $gw $ifname";
            fi
        fi
        if [ -f $filename ]; then
            grep "$route" $filename 2>&1 1>/dev/null
            if [ $? -ne 0 ]; then # Does not exist in file
                echo "Persistent route \"$route1\" does not exist in $filename."
            else
                sed -i -e s/"$route"//g $filename
                echo "Persistent route \"$route1\" removed from $filename."
            fi
        else
            echo "Persistent route file $filename does not exist."
        fi
        filename="/etc/sysconfig/network";
        if [ "$net" = "default" -a -f $filename ]; then
            grep "GATEWAY=$gw" $filename >/dev/null 2>&1
            if [ $? -eq 0 ]; then
                sed -i '/GATEWAY=/d' $filename
                echo "Persistent GATEWAY=$gw removed from $filename."
            fi
        fi
        ;;
    esac
    else #AIX
    echo "Removing persistent route on AIX is not supported yet."
    fi
}



if [ "$op" = "add" ]; then
    result=$(route_exists $net $mask $gw)
    if [ "$result" = "0" ]; then
        #ipv6
        if echo $net | grep : 2>&1 1>/dev/null
        then
            if [ "$(uname -s)" = "Linux" ]; then
            if [ "$gw" = "" -o "$gw" = "::" ] ; then
                    cmd="ip -6 route add $net/$mask dev $ifname"
        else
                    cmd="ip -6 route add $net/$mask via $gw"
        fi
            else
                # AIX TODO
                cmd="ip -6 route add $net/$mask via $gw"
            fi
        else
        if [ "$(uname -s)" = "Linux" ]; then
            if command -v ip >/dev/null 2>&1; then
                route_dest=$(ipv4_route_destination "$net" "$mask")
                if [ "$gw" = "" -o "$gw" = "0.0.0.0" ] ; then
                    cmd="ip route add $route_dest dev $ifname"
                else
                    cmd="ip route add $route_dest via $gw"
                fi
            elif [ "$gw" = "" -o "$gw" = "0.0.0.0" ] ; then
                    cmd="route add -net $net netmask $mask dev $ifname"
            else
                    cmd="route add -net $net netmask $mask gw $gw"
            fi
            else
                cmd="route add -net $net -netmask $mask $gw"
            fi
        fi
        echo "Adding temporary route: $cmd"
        result=`$cmd 2>&1`
        code=$?
        if [ $code -ne 0 ]; then
            logger -t $log_label -p local4.err "$cmd\nerror code=$code, result=$result."
            echo "  error code=$code, result=$result."
            if [ -f "/etc/debian_version" ];then
                exit 1;
            fi
        fi
    else
        #ipv6
        if echo $net | grep : 2>&1 1>/dev/null
        then
            echo "The temporary route ($net/$mask $gw) already exists."
        else
            echo "The temporary route ($net $mask $gw) already exists."
        fi
    fi

    #add persistent route
    add_persistent_route $net $mask $gw $ifname
elif [ "$op" = "delete" ]; then
    result=$(route_exists $net $mask $gw)
    if [ "$result" = "1" ]; then
        # ipv6
        if echo $net | grep : 2>&1 1>/dev/null
        then
            if [ "$(uname -s)" = "Linux" ]; then
            if [ "$gw" = "" -o "$gw" = "::" ] ; then
                    cmd="ip -6 route delete $net/$mask dev $ifname"
        else
                    cmd="ip -6 route delete $net/$mask via $gw"
        fi
            else
                # AIX TODO
                cmd="ip -6 route delete $net/$mask via $gw"
            fi
        else
        if [ "$(uname -s)" = "Linux" ]; then
            if command -v ip >/dev/null 2>&1; then
                route_dest=$(ipv4_route_destination "$net" "$mask")
                if [ "$gw" = "" -o "$gw" = "0.0.0.0" ] ; then
                    cmd="ip route delete $route_dest dev $ifname"
                else
                    cmd="ip route delete $route_dest via $gw"
                fi
            elif [ "$gw" = "" -o "$gw" = "0.0.0.0" ] ; then
                    cmd="route delete -net $net netmask $mask dev $ifname"
            else
                    cmd="route delete -net $net netmask $mask gw $gw"
            fi
            else
                cmd="route delete -net $net -netmask $mask $gw"
            fi
        fi

        echo "Removing temporary route: $cmd"
        result=`$cmd 2>&1`
        code=$?
        if [ $code -ne 0 ]; then
            logger -t $log_label  -p local4.err "$cmd\nerror code=$code, result=$result."
            echo "  error code=$code, result=$result."
        fi
    else
        echo "The temporary route ($net $mask $gw) does not exist."
    fi

    #remove the persistent route
    rm_persistent_route $net $mask $gw $ifname
elif [ "$op" = "replace" ]; then
    if [ $nummask -ne 1 ]; then
        mask=$(v4mask2prefix $mask)
    fi

    if echo $net | grep : 2>&1 1>/dev/null
    then # ipv6
        if [ "$(uname -s)" = "Linux" ]; then
            if [ "$gw" = "" -o "$gw" = "::" ] ; then
                if [ "$net" = "default" ]; then
                    cmd="ip -6 route replace default dev $ifname"
                else
                    cmd="ip -6 route replace $net/$mask dev $ifname"
                fi
            else
                if [ "$net" = "default" ]; then
                    cmd="ip -6 route replace default via $gw"
                else
                    cmd="ip -6 route replace $net/$mask via $gw"
                fi
            fi
        fi
    else #ipv4
        if [ "$(uname -s)" = "Linux" ]; then
            if [ "$gw" = "" -o "$gw" = "0.0.0.0" ] ; then
                if [ "$net" = "default" ]; then
                    cmd="ip route replace default dev $ifname"
                else
                    cmd="ip route replace $net/$mask dev $ifname"
                fi
            else
                if [ "$net" = "default" ]; then
                    cmd="ip route replace default via $gw"
                else
                    cmd="ip route replace $net/$mask via $gw"
                fi
            fi
        fi
    fi

    echo "Adding temporary route: $cmd;    "
    result=`$cmd 2>&1`
    code=$?
    if [ $code -ne 0 ]; then
        logger -t $log_label -p local4.err "Error: $cmd [error code=$code, result=$result]"
        echo "Error: $cmd [error code=$code, result=$result]"
        exit 1;
    fi

    #replace the persistent route
    # the $cmd param is used for Ubuntu since it needs to run the specific cmd to enable
    # the route during the up of the device
    replace_persistent_route $net $mask $gw $ifname
    if [ $? -ne 0 ]; then
        exit 1
    fi
fi

exit 0
