-#!/bin/sh
-#
-# IPFire script - vpn-watch
-#
-# This code is distributed under the terms of the GPL
-#
-# (c) Daniel Berlin <daniel berlin_itechnology de> - Check for
-# remote peer with dynamic IPs and restart when change
-# is detected. Works with DPD which is not perfect!
-#
-# 2006: Franck - adapted original script to fit in IPCop 1.4
-# 2007: Michael Tremer - mitch@ipfire.org - Merged into IPFire
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2, or (at your option)
-# any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-
-#
-# Configuration
-#
-
-VPN_CONFIG='/var/ipfire/vpn/config' # Location of IPFire's vpn configuration file
-SETTINGS='/var/ipfire/vpn/settings' # and settings
-
-CHECK_INTERVAL='60' # Check this often (in seconds)
-DNS_RESOLVE_TRIES='4' # Try to resolve IPs this often (each try takes max. 2 seconds)
-NICENESS='+5' # Adjust niceness of child processes: '-20' ... '+19'; '0' is default
-case "$1" in
- 'start' | '--start')
- eval $(/usr/local/bin/readhash $SETTINGS)
- test "${VPN_WATCH}" != "on" && exit 1 # not activated, cannot start!
-
- if test ! -r "$VPN_CONFIG"; then
- echo 'Error: cannot read IPFire VPN configuration file; exit.' >&2
- exit 1
- fi
-
- if /usr/bin/test -p /var/run/$(basename $0); then
- if ps --no-heading axw | grep -v 'grep' | grep -q "$(basename $0) conn: "; then
- echo "Error: use '$(basename $0) stop' please; exit." >&2
- exit 1
- else
- rm /var/run/$(basename $0) # pipe was left alone, correct error condition
- fi
- fi
-
- # the pipe serves for "-status" but is not used yet
- /bin/mknod -m 0660 "/var/run/$(basename $0)" p >/dev/null 2>&1 # Create pipe for status-information
-
- #
- # Read VPN configuration and fork a child process for each VPN connection active, net-to-net & RED
- #
- while read line; do
- VPN=($(echo $line | cut --delimiter=',' --output-delimiter=' ' -f2,3,5,12,28 )) # Activated, Name, Host/Net-to-net, Remote, ITF.
- test "${VPN[0]}" != "on" && continue # Ignore: deactivated connections
- test "${VPN[2]}" = "host" && continue # Ignore: roadwarriors
- ## test "${VPN[4]}" != "RED" && continue # Ignore: local vpns needed or not ?
- echo -n "${VPN[3]}" | grep -q '^[[:digit:]\.]\+$' && continue #If fixed remote IP, no need to watch!
- $0 'conn:' "${VPN[1]}" "${VPN[3]}">/dev/null 2>&1 & #Fork child process (parameters: "conn: NAME RIGHT")
- done < "$VPN_CONFIG"
- exit 0 # Parent dies here... RIP
- ;;
-
- 'stop' | '--stop')
- # Terminate processes
- for proc in $(pidof -x -o %PPID $(basename $0)); do
- kill -s SIGTERM -- "$proc"
- done
- sleep 1
-
- # Kill remaining processes
- for proc in $(/bin/pidof -x -o %PPID $(basename $0)); do
- kill -s SIGKILL -- "$proc"
- done
- rm -f "/var/run/$(basename $0)" # Remove pipe
- exit 0
- ;;
-
- #'status' | '--status')
- # echo "VPN-Watch"
- # if ps --no-heading axw | grep -v 'grep' | grep -q "$(basename $0) conn: "; then
- # trap '' USR1
- # killall -q -g -s USR1 -- $(basename $0)
- # sleep 1
- # cat "/var/run/$(basename $0)" | sort # Read children's info from pipe
- # else
- # echo ' no instance running.'
- # fi
- # exit 0
- # ;;
-
- 'conn:')
- # Children proceed here...
- renice ${NICENESS:-0} -p $$ >/dev/null 2>&1 # Adjust niceness
- shift # Remove the first positional parameter ("conn:"), as we don't need it anymore
- ;;
- *)
- /bin/echo "Usage: $0 { start | stop }" >&2
- exit 1
- ;;
-esac
-
-# Logging, signal handlers
-alias log="logger -t vpn-watch \'${1}\':"
-
-trap 'log "terminated after ${RESTART_COUNT} restarts."' EXIT
-#trap 'echo "connection \"${1}\" restarted ${RESTART_COUNT} times" >>/var/run/$(basename $0)' USR1
-
-#
-# Get IP of a FQDN... using 'host' command. Everything is ok when dns server responds.
-# If no response,
-# -maybe RED is down. The script can terminate. It will restart with rc.updatered.
-# or
-# -the dns server is down. In this case, terminate the script is not a good idea...
-# Thus 4 retries before returning response 'stop'
-#
-function get_ip () {
- local RESULT=''
- # delay divided by two for each loop
- delay=8
- for ((i=1; ${i} <= ${DNS_RESOLVE_TRIES}; i++)); do
-
- # extract IP address
- RESULT=$(/usr/bin/host "$1" 2>/dev/null| awk '{ print $4 }')
- if echo -n $RESULT | /bin/grep -q '^[[:digit:]\.]\+$' ; then
- echo -n $RESULT
- return
- fi
-
- sleep $delay
- delay=$((delay>>1))
- done
- # Change 'stop' to something else to let the script running
- echo -n "stop" # stop: the script will terminate
-
+#!/usr/bin/perl
+##################################################
+##### VPN-Watch.pl Version 0.4c #####
+##################################################
+# #
+# VPN-Watch is part of the IPFire Firewall #
+# #
+##################################################
+
+use strict;
+
+require '/var/ipfire/general-functions.pl';
+my @vpnsettings;
+my $i = 0;
+my $file = "/var/run/vpn-watch.pid";
+my $debug = 0;
+
+if ( -e $file ){
+ logger("There my be another vpn-watch runnning because $file exists, vpn-watch will try kill the process.");
+ open(FILE, "<$file");
+ my $PID = <FILE>;
+ close(FILE);
+ system("kill -9 $PID");
+ }
+
+system("echo $$ > $file");
+
+while ( $i == 0){
+ if ($debug){logger("We will wait 60 seconds before next action.");}
+ sleep(60);
+
+ if (open(FILE, "<${General::swroot}/vpn/config")) {
+ @vpnsettings = <FILE>;
+ close(FILE);
+ unless(@vpnsettings) {exit 1;}
+ }
+
+my $status = `ipsec whack --status`;
+foreach (@vpnsettings){
+ my @settings = split(/,/,$_);
+
+ if ($settings[27] ne 'RED'){next;}
+ if ($settings[4] ne 'net'){next;}
+ if ($settings[1] ne 'on'){next;}chomp($settings[29]);
+ if ($settings[29] ne 'on'){next;}
+
+ my $remotehostname = $settings[11];
+
+ if ($debug){logger("Checking connection to $remotehostname.");}
+
+ my $remoteip = `/usr/bin/ping -c 1 $remotehostname 2>/dev/null | head -n1 | awk '{print \$3}' | tr -d '()' | tr -d ':'`;chomp($remoteip);
+ if ($remoteip eq ""){next;if ($debug){logger("Unable to resolve $remotehostname.");}}
+ my $ipmatch= `echo "$status" | grep $remoteip | grep $settings[2]`;
+
+ if ( $ipmatch eq '' ){
+ logger("Remote IP for host $remotehostname-$remoteip has changed, restarting ipsec.");
+ system("/usr/local/bin/ipsecctrl S");
+ last; #all connections will reloaded
+ }
+ }
+ if ($debug){logger("All connections may be fine nothing was done.");}