#! /bin/bash
### BEGIN INIT INFO
# Provides:          nperf-server
# Required-Start:    $all
# Required-Stop:
# Default-Start:     2 3 4 5
# Default-Stop:
# Short-Description: nPerfServer
### END INIT INFO
# Manages the services to run nPerfServer
# Script for Unix/Linux. Version : 2.1
# https://www.nperf.com/

OPT_ARGS=""
BIND_IP=""
IPTABLES_ARGS=""
IP6TABLES_ARGS=""
IPV6=""
NB_THREAD=""
DAEMON_START=""
PORT="8080"
TLS_PORT="8443"
REDIRECT_PORT_80=0
REDIRECT_PORT_443=0

set -e

. "/etc/nperf/nperf-server.conf"

test -x $DAEMON || exit 1
test -z $1 && arg="empty" || arg=$1

set -u
DESC="`basename $DAEMON` daemon"

DAEMON_START="$DAEMON_START -p $PORT -t $TLS_PORT --uuidfile=$UUID"
if [ -n "$OPT_ARGS" ]; then
    DAEMON_START="$DAEMON_START $OPT_ARGS"
fi

if [[ $BIND_IP = *":"* ]]; then
    IPV6=true
fi

if [ -n "$BIND_IP" ]; then
    DAEMON_START="$DAEMON_START -i $BIND_IP"
    if [ "$BIND_IP" != "::" ] && [ "$BIND_IP" != "0.0.0.0" ]; then
        if [ "$IPV6" = false ]; then
            IPTABLES_ARGS=" -d $BIND_IP/32"
        else
            IP6TABLES_ARGS=" -d $BIND_IP/128"
        fi
    fi
fi

status() {
        curl -s -m 5 -i localhost:${PORT} | grep "Server: nPerf" >/dev/null 2>&1 && return 0
        nc -z -w5 localhost $PORT && return 2
        return 1
}

case "$arg" in
  initnet)
        echo -n "Activating IPv4 Anti-DOS limitation..."
        CHECK_DOS_IPV4=$(/sbin/iptables-save | grep nPerfServer | grep "connlimit" | cat)
        if [ -z "$CHECK_DOS_IPV4" ]; then
            /sbin/iptables -A INPUT -p tcp --syn -m connlimit --connlimit-above 50 -j REJECT -m comment --comment nPerfServer
            echo " OK."
        else
            echo " Already set!"
        fi

        if [ "$IPV6" = true ]; then
            echo -n "Activating IPv6 Anti-DOS limitation..."
            CHECK_DOS_IPV6=$(/sbin/ip6tables-save | grep nPerfServer | grep "connlimit" | cat)
            if [ -z "$CHECK_DOS_IPV6" ]; then
                /sbin/ip6tables -A INPUT -p tcp --syn -m connlimit --connlimit-above 50 --connlimit-mask 64 -j REJECT -m comment --comment nPerfServer
                echo " OK."
            else
                echo " Already set!"
            fi
        fi

        if [ "$REDIRECT_PORT_80" -eq 1 ]; then
            echo -n "Activating IPv4 redirection from TCP port 80 to port $PORT..."
            /sbin/iptables-save | grep nPerfServer | grep "\--dport 80" | sed -r 's/-A/-D/' | while read line; do /sbin/iptables -t nat $line; done
            /sbin/iptables -t nat -A PREROUTING -p tcp $IPTABLES_ARGS --dport 80 -j REDIRECT --to $PORT -m comment --comment nPerfServer
            echo " OK."
            if [ "$IPV6" = true ]; then
                if [ -n "$(/usr/bin/which ip6tables)" ]; then
                    echo -n "Activating IPv6 redirection from TCP port 80 to port $PORT..."
                    /sbin/ip6tables-save | grep nPerfServer | grep "\--dport 80" | sed -r 's/-A/-D/' | while read line; do ip6tables -t nat $line; done
                    /sbin/ip6tables -t nat -A PREROUTING$IP6TABLES_ARGS -p tcp --dport 80 -j REDIRECT --to $PORT -m comment --comment nPerfServer
                    echo " OK."
                else
                    echo 1>&2 "Error: ip6tables is not available, please install ip6tables OR disable IPv6 for nPerfServer OR disable port redirection."
                    exit 1
                fi
            fi
        fi
        if [ "$REDIRECT_PORT_443" -eq 1 ]; then
            echo -n "Activating IPv4 redirection from TCP port 443 to port $TLS_PORT..."
            /sbin/iptables-save | grep nPerfServer | grep "\--dport 443" | sed -r 's/-A/-D/' | while read line; do /sbin/iptables -t nat $line; done
            /sbin/iptables -t nat -A PREROUTING -p tcp $IPTABLES_ARGS --dport 443 -j REDIRECT --to $TLS_PORT -m comment --comment nPerfServer
            echo " OK."
            if [ "$IPV6" = true ]; then
                if [ -n "$(/usr/bin/which ip6tables)" ]; then
                    echo -n "Activating IPv6 redirection from TCP port 443 to port $TLS_PORT..."
                    /sbin/ip6tables-save | grep nPerfServer | grep "\--dport 443" | sed -r 's/-A/-D/' | while read line; do ip6tables -t nat $line; done
                    /sbin/ip6tables -t nat -A PREROUTING -p tcp $IP6TABLES_ARGS --dport 443 -j REDIRECT --to $TLS_PORT -m comment --comment nPerfServer
                    echo " OK."
                else
                    echo 1>&2 "Error: ip6tables is not available, please install ip6tables OR disable IPv6 for nPerfServer OR disable port redirection."
                    exit 1
                fi
            fi
        fi
    ;;
  startcmd)
       if [ -n "$NB_THREAD" ]; then
           DAEMON_START="$DAEMON_START -w $NB_THREAD"
       fi
       echo "$DAEMON $DAEMON_START"
    ;;
  start-systemd)
        if [ -z "$NB_THREAD" ]; then
            echo -n "Starting $DESC ... "
        else
            echo -n "Starting $DESC with $NB_THREAD threads ... "
            DAEMON_START="$DAEMON_START -w $NB_THREAD"
        fi
        DAEMON_START="-x --pidfile=$PID $DAEMON_START"
        rm -f $PID
        set +e
        ${DAEMON} ${DAEMON_START}
        set -e
        exit $?
    ;;
  start)
        $0 initnet
        if [ -z "$NB_THREAD" ]; then
            echo -n "Starting $DESC ... "
        else
            echo -n "Starting $DESC with $NB_THREAD threads ... "
            DAEMON_START="$DAEMON_START -w $NB_THREAD"
        fi
        DAEMON_START="-x --pidfile=$PID $DAEMON_START"
        rm -f $PID
        set +e
        [ "`id -u`" -eq "0" ] && su $USER -s /bin/sh -c "${DAEMON} ${DAEMON_START}" >/dev/null
        [ "`id -u`" -eq "`id -u $USER`" ] && eval "${DAEMON} ${DAEMON_START}"
        set -e
        sleep 0.5 ; test -e $PID && echo "[ ok ]" || echo "[fail]"
    ;;
  stop)
    echo -n "Stopping $DESC : "
    pkill `basename $DAEMON` || true
    sleep 0.5 ; test -e $PID && echo "[fail]" || echo "[ ok ]"
    ;;
  status)
    status && echo "$DESC is running." || echo "$DESC is stopped."
    ;;
  version)
    $DAEMON -v || true
    ;;
  restart)
        $0 stop
        $0 start
        ;;
  *)
    echo "Usage: $0 {start|stop|restart|status|version}" >&2
        exit 1
        ;;
esac

exit 0
