#!/bin/sh
#
# openvpn       This shell script takes care of starting and stopping openvpn
#
# The init script does the following:
#
# - Starts an openvpn process for each .conf file it finds in
#   /etc/openvpn/work
#
# - If /etc/openvpn/work/xxx.sh exists for a xxx.conf file then it executes
#   it before starting openvpn (useful for doing openvpn --mktun...).

# Location of openvpn binary
openvpn=""
openvpn_locations="/sbin/openvpn /usr/sbin/openvpn /usr/local/sbin/openvpn"
for location in $openvpn_locations
do
  if [ -f "$location" ]
  then
    openvpn=$location
  fi
done

if [ ! -d /var/lock/subsys/ ]; then
  mkdir -p /var/lock/subsys > /dev/null 2>/dev/null
fi

# Lockfile
lock="/var/lock/subsys/openvpn"

# PID directory
piddir="/var/run/openvpn"

# Our working directory
work=/etc/openvpn/work
internal_config=$work/conf/internal.cfg

if [ ! -d $work/keys/client ]; then
  mkdir -p $work/keys/client > /dev/null 2>/dev/null
fi


# Source function library.
#. /etc/rc.d/init.d/functions

# Source networking configuration.
#. /etc/sysconfig/network

# Check that networking is up.
#if [ ${NETWORKING} = "no" ]
#then
#  echo "Networking is down"
#  exit 0
#fi

# Check that binary exists
if ! [ -f  $openvpn ] 
then
  echo "openvpn binary not found"
  exit 0
fi

. /etc/openvpn/work/vars
# create the crl.pem (Certificate Revocation List) file if does not exist or is empty
if [ ! -f ${KEY_DIR}/crl.pem ] || [ ! -s ${KEY_DIR}/crl.pem ]; then
. /etc/openvpn/work/vars && openssl ca -gencrl -out ${KEY_DIR}/crl.pem -config $KEY_CONFIG
fi

valid_ip()
{
    local  ip=$1
    if expr "$ip" : '[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*$' >/dev/null; then
	echo "0"
    else
	echo "1"
    fi	
}
calcnetaddress()
{
local IPAddress=$1
local netMask=$2

IFS=.
read -r i1 i2 i3 i4 << EOF
$IPAddress
EOF

IFS=.
read -r m1 m2 m3 m4 << EOF
$netMask
EOF

echo "$((i1 & m1))"."$((i2 & m2))"."$((i3 & m3))"."$((i4 & m4))"
}

regencrl()
{
exp_date=$(openssl crl -inform PEM -noout -nextupdate -in /etc/openvpn/work/keys/crl.pem | awk -F= '{print $2}' | sed 's/ GMT//g' | xargs -I{} date --date {} +%s)
diff=$(($(($exp_date - $(date -u +"%s")))/86400))
if [ $diff -lt 360 ]; then
  . /etc/openvpn/work/vars && $OPENSSL ca -gencrl -out "/etc/openvpn/work/keys/crl.pem" -config "$KEY_CONFIG"
fi
}

# See how we were called.
case "$1" in
  start)
	echo -n $"Starting openvpn: "
	
	regencrl
	
	/sbin/modprobe tun >/dev/null 2>&1

	# Run startup script, if defined
	if [ -f $work/openvpn-startup ]; then
	    $work/openvpn-startup
	fi

	if [ ! -d  $piddir ]; then
	    mkdir $piddir
	fi

	if [ -f $lock ]; then
	    # we were not shut down correctly
	    for pidf in `/bin/ls $piddir/*.pid 2>/dev/null`; do
	      if [ -s $pidf ]; then
		kill `cat $pidf` >/dev/null 2>&1
	      fi
	      rm -f $pidf
	    done
	    rm -f $lock
	    sleep 2
	fi

	rm -f $piddir/*.pid
	cd $work

	# Start every .conf in $work and run .sh if exists
	errors=0
	successes=0
	for c in `/bin/ls *.conf 2>/dev/null`; do
	    bn=${c%%.conf}
	    if [ -f "$bn.sh" ]; then
		. ./$bn.sh
	    fi
	    rm -f $piddir/$bn.pid
            # Handle backward compatibility, see Red Hat Bugzilla ID #458594
            script_security=''
            if [ -z "$( grep '^[[:space:]]*script-security[[:space:]]' $c )" ]; then
                script_security="--script-security 2"
            fi
	    
	    push_internal=''
		
		if [ -f $internal_config ]; then
			val=`cat $internal_config | grep push_internal`
			if [ "$val" = "push_internal=1" ] ; then
				if [ -f /etc/sysconfig/network-scripts/ifcfg-internal ]; then
					. /etc/sysconfig/network-scripts/ifcfg-internal
					INTERNAL_IP_ADDR=$IPADDR
					INTERNAL_IP_NETMASK=$NETMASK
					ipisvalid=$(valid_ip $INTERNAL_IP_ADDR)
					subnetisvalid=$(valid_ip $INTERNAL_IP_NETMASK)				
					if [ $ipisvalid = "0" ] && [ $subnetisvalid = "0" ]; then
						INTERNAL_IP_ADDR=$(calcnetaddress $INTERNAL_IP_ADDR $INTERNAL_IP_NETMASK)
						push_internal="--push "route $INTERNAL_IP_ADDR $INTERNAL_IP_NETMASK""
					fi
				fi
			fi
		fi
	    
	    $openvpn --daemon --writepid $piddir/$bn.pid --cd $work --config $c $push_internal $script_security  \
			--up /etc/openvpn/scripts/server/up.sh \
			--down /etc/openvpn/scripts/server/down.sh \
			--client-connect /etc/openvpn/scripts/server/client-connect.sh \
			--client-disconnect /etc/openvpn/scripts/server/client-disconnect.sh

	    if [ $? = 0 ]; then
		successes=1
	    else
		errors=1
	    fi
	done

	if [ $errors = 1 ]; then
	    #failure; echo
	    echo "Failure"
	else
	    #success; echo
	    echo "Success"
	fi

	if [ $successes = 1 ]; then
	    touch $lock
	fi
	;;
  stop)
	echo -n $"Shutting down openvpn: "
	for pidf in `/bin/ls $piddir/*.pid 2>/dev/null`; do
	  if [ -s $pidf ]; then
	    kill `cat $pidf` >/dev/null 2>&1
	  fi
	  rm -f $pidf
	done

	# Run shutdown script, if defined
	if [ -f $work/openvpn-shutdown ]; then
	    $work/openvpn-shutdown
	fi

	#success; echo
	echo "Success"
	rm -f $lock
	;;
  restart)
	$0 stop
	sleep 2
	$0 start
	;;
  reload)
	if [ -f $lock ]; then
	    for pidf in `/bin/ls $piddir/*.pid 2>/dev/null`; do
		if [ -s $pidf ]; then
		    kill -HUP `cat $pidf` >/dev/null 2>&1
		fi
	    done
	else
	    echo "openvpn: service not started"
	    exit 1
	fi
	;;
  reopen)
	if [ -f $lock ]; then
	    for pidf in `/bin/ls $piddir/*.pid 2>/dev/null`; do
		if [ -s $pidf ]; then
		    kill -USR1 `cat $pidf` >/dev/null 2>&1
		fi
	    done
	else
	    echo "openvpn: service not started"
	    exit 1
	fi
	;;
  condrestart)
	if [ -f $lock ]; then
	    $0 stop
	    # avoid race
	    sleep 2
	    $0 start
	fi
	;;
  status)
	if [ -f $lock ]; then
		OPENVPNSTATUS=0
	    for pidf in `/bin/ls $piddir/*.pid 2>/dev/null`; do
		if [ -s $pidf ]; then
		  kill -USR2 `cat $pidf` >/dev/null 2>&1
		  OPENVPNSTATUS=$?
		fi
	    done

		if [ "$OPENVPNSTATUS" == "0" ]; then
			echo "Status written to /tmp/logs/openvpn.log"
		else
			echo "openvpn: service not started"
			exit 1
		fi
	else
	    echo "openvpn: service not started"
	    exit 1
	fi
        ;;
  *)
	echo "Usage: openvpn {start|stop|restart|condrestart|reload|reopen|status}"
	exit 1
	;;
esac
exit 0
