#!/bin/bash
### This script runs as a service. It starts the VPN connection to the CS.
### Then it checks periodically the status of the network connection.
### In case that the network is disconnected and then connected again,
### it tries to start the VPN connection to CS again.
###
### It can be installed as a service with a command like this:
###
### $ cygrunsrv --install cs_vpn_connection --disp "ShrewVPN Connection to CS." \
###             --path "/cygdrive/c/Tools/vpn_connect_cs.sh" --args "-r CS -a"  \
###             --desc "Opens the VPN connection to the CS."                    \
###             --dep ipsecd --dep iked --dep dtpd --dep netman                 \
###             --preshutdown --user Administrator
###
### The logs of the service can be checked at '/var/log/cs_vpn_connection.log'.
### The amount of the info that is outputed on the log is defined by the log_level. 

### log_level can be: normal or debug
log_level='debug'

### output the given messages
### only if the log_level is debug
function debug
{
  if [ "$log_level" = 'debug' ]; then echo -e "$@"; fi
}

### ping the given IP; if we get any Reply
### then return 1, else return 0
function check_connection
{
  ip=$1  ## get the IP from the first parameter
  ping_output=$(ping $ip -w 3000)
  debug "$ping_output"
  
  ### check for any reply and return connection status
  reply=$(echo $ping_output | grep Reply)
  if [ "$reply" = '' ]
  then return 0  ## disconnected
  else return 1  ## connected
  fi
}

### when the VPN connection state is changed, report it on the log
old_vpn_state='disconnected'
current_vpn_state='connected'
function report_vpn_state
{
  vpn_status=$1
  
  old_vpn_state=$current_vpn_state
  if [ $vpn_status -eq 1 ]
  then
    current_vpn_state='connected'
  else
    current_vpn_state='disconnected'
  fi
  
  ### if there is a change in the VPN connection state, report it on the log
  if [ "$old_vpn_state" != "$current_vpn_state" ]
  then
    echo "$(date) -- VPN is $current_vpn_state"
  fi
}

### paths of the tools (programs)
ipsecc="/cygdrive/c/Program Files/ShrewSoft/VPN Client/ipsecc.exe"
devcon="/cygdrive/c/Tools/devcon.exe"

### get the IP of the gateway and of the VPN DNS
gateway=$(netsh interface ip show address | grep 'Default Gateway' | gawk '{print $3}')
vpn_dns=$(reg query "HKEY_CURRENT_USER\Software\ShrewSoft\vpn\site\CS" | grep client-dns-addr | gawk '{print $3}')

### output some startup debug messages
debug_msg="
==== Starting Service cs_vpn_connection == $(date) ====
ipsecc=$ipsecc
devcon=$devcon
gateway=$gateway
vpn_dns=$vpn_dns
"
debug "$debug_msg"


### start an endless loop of sleeping, checking 
### and trying to re-establish the VPN connection
wait_time=1
while true
do
  ### wait for the given number of seconds
  sleep $wait_time
  debug "\n----- Check again -- $(date) -----"

  ### check the VPN connection
  check_connection $vpn_dns;  status=$?
  report_vpn_state $status
  
  ### if VPN is connected, no need to do anything, 
  ### just skip and wait about 10 min to check again
  if [ $status -eq 1 ]
  then
    debug "===> VPN is connected, no need to do anything, just sleep about 10 min"
    wait_time=600
    continue
  fi
  
  ### else, VPN is disconnected
  debug "===> VPN disconnected"
  
  ### since the VPN is disconnected, close the ipsecc program
  debug "taskkill /F /IM ipsecc.exe"
  msg=$(taskkill /F /IM ipsecc.exe 2>/dev/null)
  debug "$msg";  sleep 1
  
  ### try to re-initialize the network device
  ### by disabling and then enabling it again
  debug "devcon disable 'PCI\VEN_11AB'"
  msg=$($devcon disable 'PCI\VEN_11AB')
  debug "$msg";  sleep 1
  debug "devcon enable 'PCI\VEN_11AB'"
  msg=$($devcon enable 'PCI\VEN_11AB')
  debug "$msg";  sleep 1
  
  ### check the gateway connection
  check_connection $gateway;  status=$?
  
  ### if the gateway is disconnected, there is nothing we can do, 
  ### just skip and wait about 1 min to try again
  if [ $status -eq 0 ]
  then
    debug "===> Gateway not reachable, nothing we can do, wait 1 min and try again"
    wait_time=60
    continue
  fi

  ### else, local gateway is reachable, try to re-establish the VPN connection

  ### now we have the local gateway connected, but the VPN is disconnected,
  ### so, we try to open again the VPN connection  
  debug "===> Gateway is reachable, trying to re-establish the VPN connection"
  debug "$ipsecc -r CS -a"
  "$ipsecc" -r CS -a &     ## try to start the VPN connection
  debug "$(date) --- wait about 2 min before checking again"
  wait_time=60
done
