commit ca7bbadf2c3a0f0c965be60c5479a86a20208af3 Author: Christoph Date: Mon Feb 20 02:56:35 2017 +0100 Initial import diff --git a/INSTALL b/INSTALL new file mode 100644 index 0000000..5bffbea --- /dev/null +++ b/INSTALL @@ -0,0 +1,74 @@ + +# --- +# - Install scripts +# --- + +cp /usr/local/sbin/ +cp /usr/local/sbin/ + + + +# --- +# - Configuration +# --- + +mkdir -p /etc/check_net +cp /etc/check_net/check_net.conf + +# - Adjust /etc/check_net/check_net.conf +# - +vim /etc/check_net/check_net.conf + + + +# --- +# - systemd configuration for service "check_net" +# --- + +# - Create service "check_net" +# - +cat < /etc/systemd/system/check_net.service +[Unit] +Description=Configure Routing for Internet Connections; +After=network.target +After=rc-local.service + +[Service] +ExecStart=/usr/local/sbin/check_net.sh +ExecStartPre=rm -rf /tmp/check_net.sh.LOCK +ExecStopPost=rm -rf /tmp/check_net.sh.LOCK +KillMode=control-group +SendSIGKILL=yes +TimeoutStopSec=2 +Restart=on-failure + +[Install] +WantedBy=multi-user.target +EOF + + +# - Activate service check_net +# - +systemctl enable check_net.service + +systemctl daemon-reload + +systemctl start check_net + + +# --- +# - Configure lograotation for service "check_net" +# --- + +cat < /etc/logrotate.d/check_net +/var/log/check_net.log +{ + rotate 7 + daily + missingok + notifempty + copytruncate + delaycompress + compress +} +EOF diff --git a/check_net.conf.sample b/check_net.conf.sample new file mode 100644 index 0000000..8c81ce9 --- /dev/null +++ b/check_net.conf.sample @@ -0,0 +1,133 @@ +# - Configuration file for scrupts check_net.sh and netconfig.sh +# - + +LOGGING_CONSOLE=false +DEBUG=true + +# - Where are your scripts located? +# - +check_script=/usr/local/sbin/check_net.sh +netconfig_script=/usr/local/sbin/netconfig.sh + +log_file=/var/log/check_net.log + + +# - Put in your DSL devices (refers to your network configuration) +# - youe wish be congigured by that script +# - +# - Notice: +# - If not using multiple default gatways, declare the list in the order of your +# - preferred default gatway devices +# - +# - Example: +# - _INITIAL_DEVICE_LIST="eth0:192.168.63.254 ppp-light" +# - +_INITIAL_DEVICE_LIST="ppp-ckubu" + +# - Set to "false" uses "0.0.0.0" as remote gateway instead of the real address +# - +USE_REMOTE_GATEWAY_ADDRESS=true +#USE_REMOTE_GATEWAY_ADDRESS=false + +# - Set default gw (roundrobin) +# - +# - !! SET_MULTIPLE_DEFAULT_GW=true does not work for now.. +# - +SET_MULTIPLE_DEFAULT_GW=false +#SET_MULTIPLE_DEFAULT_GW=true + + +# - Set to false uses "0.0.0.0" as default gateway adress instaed of real remote address +# - +USE_DEFAULT_GW_ADDRESS=true +#USE_DEFAULT_GW_ADDRESS=false + + +# - Hostnames for ping test +# - +# - Note: The first two reachable hosts will be used for ping test. +# - +# - Space separated list +# - +PING_TEST_HOSTS="oopen.de google.com heise.de debian.org ubuntu.com" + + +admin_email=root +from_address="check-inet-devices@`hostname -f`" +company="CKUBU" +content_type='Content-Type: text/plain;\n charset="utf-8"' + + +# - rule_local_ips +# - +# - Add rule(s) for routing local ip-address(es) through a given extern interface +# - +# - Space separated list of entries ':' +# - rule_local_ips=": [:] [.." +# - +# - Example: +# - ======== +# - local ip 192.168.10.1 through extern interface ppp-st and +# - local ip 192.168.10.13 through extern interface ppp-surf1 +# - rule_local_ips="ppp-st:192.168.10.1 ppp-surf1:192.168.10.13" +# - +rule_local_ips="" + +# - rule_remote_ips +# - +# - Add rule(s) for routing remote ip-address(es) through a given extern interface +# - +# - Space separated list of entries ':' +# - rule_remote_ips=": [:] [.." +# - +# - Example: +# - ======== +# - route remote ip-address 141.1.1.1 through extern interface ppp-ckubu and +# - also route ip-address 8.8.8.8 through through extern interface ppp-ckubu +# - rule_remote_ips="ppp-ckubu:141.1.1.1 ppp-ckubu:8.8.8.8" +# - +rule_remote_ips="" + +# - rule_local_nets +# - +# - Add rule(s) for routing local networks through a given extern interface out +# - +# - Space separated list of entries ':' +# - rule_local_nets=": [:] [.." +# - +# - +# - Example: +# - ======== +# - rule_local_nets="ppp-st:192.168.11.0/25 ppp-surf1:192.168.11.128/25" +# - +rule_local_nets="" + + + +## ==================================== +## - Don't make changes after this Line +## ==================================== + +# --- +# - Add rule(s) for routing local ip-address(es) +# --- +declare -a rule_local_ip_arr +for _str in $rule_local_ips ; do + rule_local_ip_arr+=("$_str") +done + +# --- +# - Add rule(s) for routing remote ip-address(es) +# --- +declare -a rule_remote_ip_arr +for _str in $rule_remote_ips ; do + rule_remote_ip_arr+=("$_str") +done + +# --- +# - Add rule(s) for routing local networks +# --- +declare -a rule_local_net_arr +for _str in $rule_local_nets ; do + rule_local_net_arr+=("$_str") +done diff --git a/check_net.service.sample b/check_net.service.sample new file mode 100644 index 0000000..d1020a1 --- /dev/null +++ b/check_net.service.sample @@ -0,0 +1,16 @@ +[Unit] +Description=Configure Routing for Internet Connections; +After=network.target +After=rc-local.service + +[Service] +ExecStart=/root/bin/check_net/check_net.sh +ExecStartPre=rm -rf /tmp/check_net.sh.LOCK +ExecStopPost=rm -rf /tmp/check_net.sh.LOCK +KillMode=control-group +SendSIGKILL=yes +TimeoutStopSec=2 +Restart=on-failure + +[Install] +WantedBy=multi-user.target diff --git a/check_net.sh b/check_net.sh new file mode 100755 index 0000000..e1607fa --- /dev/null +++ b/check_net.sh @@ -0,0 +1,623 @@ +#!/usr/bin/env bash + +## ------------------------------------------------------------------- +## --- All Configurations ill be done in /etc/check_net/check_net.conf +## ------------------------------------------------------------------- + +## - Load Configuration +## - +source /etc/check_net/check_net.conf + + +## ------------------ +## --- Some functions +## ------------------ + +## - Check if a given array (parameter 2) contains a given string (parameter 1) +## - +fatal(){ + echo "" + echo -e "[ \033[31m\033[1mError\033[m ]: $*" + echo "" + echo -e "\t\033[31m\033[1mScript is canceled\033[m\033[m" + echo "" + + echo "" >> $log_file + echo "[ Error ]: $*" >> $log_file + echo "" >> $log_file + echo " Script is canceled." >> $log_file + echo "" >> $log_file + + exit 1 +} +containsElement () { + local e + for e in "${@:2}"; do [[ "$e" == "$1" ]] && return 0; done + return 1 +} +set_ping_addresses () { + + if $DEBUG ; then + echo "`date +'%Y-%m-%d %H:%M:%S'` [ Info ] Try to set IP-Address(es) for ping test. This may take some time.." >> $log_file + fi + + ping_test_ip="" + unset ping_ip_arr + declare -i i=0 + for _host in $PING_TEST_HOSTS ; do + while [ $i -lt 2 ]; do + if dig +short $_host > /dev/null 2>&1 ; then + ping_test_ip=`dig +short $_host | head -1` + if ping -q -c2 $ping_test_ip >/dev/null 2>&1 ; then + ping_ip_arr+=("$ping_test_ip") + let i++ + break + fi + fi + break + done + done + + if [ ${#ping_ip_arr[@]} -lt 1 ]; then + echo "`date +'%Y-%m-%d %H:%M:%S'` [ Error ] Setting IP-Address(es) for ping test FAILED!" >> $log_file + else + if $DEBUG ; then + echo "`date +'%Y-%m-%d %H:%M:%S'` [ Info ] IP-Addresses for ping tests set to ${ping_ip_arr[@]}" >> $log_file + fi + fi +} +usage() { + echo + [ -n "$1" ] && echo -e "[ \033[1;31mError\033[m ] : $1\n" + +echo -e " Usage:" +echo -e " \033[1m`basename $0` [OPTIONS] ..\033[m" +echo "" +echo -e " This script checks the status (online/offline) of the given devices. Afterward another" +echo " script called \033[1m`basename $netconfig_script`\033[m will be triggered to configure" +echo " the routing depending on the status of the devices." +echo "" +echo -e " It is strongly recommend to put \033[1mall devices, which should have a connection to" +echo -e " the internet\033[m, on the command line." +echo "" +echo -e " \033[1mNotice\033[m" +echo -e " On static line devices \033[1mappend \":\"\033[m. This is very important," +echo -e " otherwise this script will \033[1mNOT work as expected\033[m." +echo -e " Example:" +echo -e " \033[1m`basename $0` -l \"eth0 ppp-light\" eth0:172.16.0.1 ppp-light\033[m" +echo "" +echo -e " The declaration of the device(s) is mandatory." +echo "" +echo -e " Options:" +echo "" +echo -e " \033[1m-h\033[m" +echo -e " Prints this help\033[m" +echo "" +echo -e " \033[1m-l \033[m" +echo -e " List of all (internet) devices known as online." +echo "" + +exit 1 +} + + +if [[ $EUID -ne 0 ]]; then + fatal "This script must be run as root" 1>&2 +fi + +if [[ ! -f "$netconfig_script" ]]; then + fatal "Netconfig script \"$netconfig_script\" not found!" +fi + + +## ------------------------------------------------- +## --- If script is already running, stop execution +## ------------------------------------------------- + +LOCK_DIR=/tmp/`basename $0`.LOCK +if mkdir "$LOCK_DIR" 2> /dev/null ; then + + ## - Remove lockdir when the script finishes, or when it receives a signal + trap 'rm -rf "$LOCK_DIR"' 0 2 15 + +else + + datum=`date +"%d.%m.%Y"` + msg="[ Error ]: A previos instance of script \"`basename $0`\" seems already be running.\n\n Exiting now.." + echo -e "To:${admin_email}\n${content_type}\nSubject:DSL Script Error $company -- $datum\n\n${msg}\n" | /usr/sbin/sendmail -F "DSL Monitoring $company" -f $from_address $admin_email 2> /dev/null + + if $LOGGING_CONSOLE ; then + echo "" + echo "[ Error ]: A previos instance script \"`basename $0`\" seems already be running." + echo "" + echo " Exiting now.." + echo "" + fi + exit 1 + +fi + + +## ------------- +## --- Configure +## ------------- + +while getopts l:h opt ; do + case $opt in + h) usage ;; + l) ONLINE_DEVICE_LIST=$OPTARG + ;; + esac +done + +shift `expr $OPTIND - 1` + +INITIAL_DEVICE_LIST="$@" +if [[ -z "$INITIAL_DEVICE_LIST" ]]; then + INITIAL_DEVICE_LIST=$_INITIAL_DEVICE_LIST +fi + +[[ -z "$INITIAL_DEVICE_LIST" ]] && usage "No device list given" + + +## - Define (non associative) array +## - +declare -a inet_devices_arr +declare -a dsl_devices_arr +declare -a static_devices_arr +declare -a online_devices_arr +declare -A static_gw_arr +declare -A dsl_gw_available_arr + +for _device in $INITIAL_DEVICE_LIST ; do + if [[ "$_device" =~ : ]]; then + static_gateway="${_device##*:}" + _device="${_device%:*}" + static_gw_arr[$_device]="$static_gateway" + + static_devices_arr+=("$_device") + + else + dsl_devices_arr+=("$_device") + fi + inet_devices_arr+=("$_device") +done + +for _online_device in $ONLINE_DEVICE_LIST ; do + online_devices_arr+=("$_online_device") +done + +## - Define associative array +## - +declare -A remote_gw_arr +declare -A filetime_PID_arr +for inet_device in "${online_devices_arr[@]}" ; do + + if containsElement "$inet_device" "${dsl_devices_arr[@]}" ; then + remote_gw_address=`ifconfig $inet_device 2> /dev/null | grep "inet Adresse" | cut -d":" -f3 | cut -d" " -f1` + else + remote_gw_address=${static_gw_arr[$inet_device]} + fi + + remote_gw_arr[$inet_device]=$remote_gw_address + _pid_file=/var/run/${inet_device}.pid + if [ -f $_pid_file ]; then + filetime_PID_arr[$inet_device]=`stat -c %Y /var/run/${inet_device}.pid` + else + filetime_PID_arr[$inet_device]="NOT FOUND" + fi +done + +declare -a ping_ip_arr; + + +#echo "--" +#for _key in "${!filetime_PID_arr[@]}" ; do +# echo "filetime_PID_arr[$_key]: ${filetime_PID_arr[$_key]}" +#done +# +#for _key in "${!remote_gw_arr[@]}" ; do +# echo "remote_gw_arr[$_key]: ${remote_gw_arr[$_key]}" +#done +# +#for _device in ${online_devices_arr[@]} ; do +# echo "$_device is online" +#done +#echo "--" +#exit + +echo "" >> $log_file +echo "" >> $log_file +echo "`date +'%Y-%m-%d %H:%M:%S'` [ Info ] ## ---" >> $log_file +echo "`date +'%Y-%m-%d %H:%M:%S'` [ Info ] ## --- Starting script `basename $0`" >> $log_file +echo "`date +'%Y-%m-%d %H:%M:%S'` [ Info ] ## ---" >> $log_file +echo "" >> $log_file +echo "`date +'%Y-%m-%d %H:%M:%S'` [ Info ] Devices configured..: ${inet_devices_arr[@]}" >> $log_file +echo "`date +'%Y-%m-%d %H:%M:%S'` [ Info ] Devices Online......: ${online_devices_arr[@]}" >> $log_file +echo "`date +'%Y-%m-%d %H:%M:%S'` [ Info ] DSL Devices.........: ${dsl_devices_arr[@]}" >> $log_file +echo "`date +'%Y-%m-%d %H:%M:%S'` [ Info ] Static Devices......: ${static_devices_arr[@]}" >> $log_file +echo "`date +'%Y-%m-%d %H:%M:%S'` [ Info ] Remote Gateways.....: ${remote_gw_arr[@]}" >> $log_file +echo "`date +'%Y-%m-%d %H:%M:%S'` [ Info ] ## ---" >> $log_file + +echo "" >> $log_file +echo "`date +'%Y-%m-%d %H:%M:%S'` [ Info ] ## --- Initial Setup:" >> $log_file + +## - Initial: get ping addresses +## - +set_ping_addresses +echo "" >> $log_file + +while true ; do + + changed=false + + for inet_device in "${inet_devices_arr[@]}" ; do + + if $DEBUG ; then + echo "`date +'%Y-%m-%d %H:%M:%S'` [ Debug ] ## --- Device $inet_device" >> $log_file + fi + + ## - Set interface name, routing tables name and, if available, remote gateway. + ## - + if containsElement "$inet_device" "${dsl_devices_arr[@]}" ; then + + ## - Is remote a remote gateway for this device knpn? + ## - + remote_gw_address=`ifconfig $inet_device 2> /dev/null | grep "inet Adresse" | cut -d":" -f3 | cut -d" " -f1` + iface_name="dsl-`echo $inet_device | cut -d '-' -f2`" + rt_name="dsl_`echo $inet_device | cut -d '-' -f2`" + if [[ -n "$remote_gw_address" ]]; then + if $DEBUG ; then + echo "`date +'%Y-%m-%d %H:%M:%S'` [ Debug ] Add $remote_gw_address to array dsl_gw_available_arr for DSL line $inet_device" >> $log_file + fi + dsl_gw_available_arr[$inet_device]=$remote_gw_address + else + if $DEBUG ; then + echo "`date +'%Y-%m-%d %H:%M:%S'` [ Debug ] No remote gateway found for DSL line $inet_device" >> $log_file + fi + if [[ ${dsl_gw_available_arr[$inet_device]+_} ]]; then + if $DEBUG; then + echo "`date +'%Y-%m-%d %H:%M:%S'` [ Debug ] Unset dsl_gw_available_arr for DSL line $inet_device" >> $log_file + fi + unset ${dsl_gw_available_arr[$inet_device]} + fi + fi + else + remote_gw_address=${static_gw_arr[$inet_device]} + iface_name=$inet_device + rt_name="static_`echo $inet_device | cut -d '-' -f1`" + fi + + + ## --- + ## --- Check if routing through this connection works + ## --- + + ## - Notice: + ## - if no remote gateway is known (remote_gw_address is empty), then we don't + ## - need to test here. + ## - + device_is_online=false + if [[ -n "$remote_gw_address" ]]; then + + + ## - Check if routing through this dsl connection realy works + ## - + if [ ${#ping_ip_arr[@]} -lt 1 ]; then + echo "`date +'%Y-%m-%d %H:%M:%S'` [ Warn ] No ip-address for ping-test is set. Skipping test.." >> $log_file + else + failed=true + for _key in ${!ping_ip_arr[@]} ; do + /sbin/ip rule add to ${ping_ip_arr[$_key]} table $rt_name + if ping -q -c2 ${ping_ip_arr[$_key]} >/dev/null 2>&1 ; then + if $DEBUG ; then + _local_gw=`curl -4 https://meine-ip.oopen.de 2> /dev/null` + if [ -n "$_local_gw" ]; then + echo "`date +'%Y-%m-%d %H:%M:%S'` [ Debug ] Using local gateway \"$_local_gw\" for ping test" >> $log_file + fi + echo "`date +'%Y-%m-%d %H:%M:%S'` [ Debug ] Ping test (to ${ping_ip_arr[$_key]}) for device \"${inet_device}\" was successful." >> $log_file + fi + /sbin/ip rule del to ${ping_ip_arr[$_key]} table $rt_name + failed=false + device_is_online=true + break + fi + /sbin/ip rule del to ${ping_ip_arr[$_key]} table $rt_name + done + if $failed ; then + echo "`date +'%Y-%m-%d %H:%M:%S'` [ Error ] Ping test for device \"${inet_device}\" failed" >> $log_file + #echo "`date +'%Y-%m-%d %H:%M:%S'` [ Error ] Status Devices \"$inet_device\" changed" >> $log_file + #echo "`date +'%Y-%m-%d %H:%M:%S'` [ Error ] Devices \"$inet_device\" is now OFFLINE" >> $log_file + + ## - Remote gateway is not reachable. So empty variable "remote_gw_address" + #remote_gw_address= + + fi # End: if $failed + + fi # End: if [ ${#ping_ip_arr[@]} -lt 1 ]; then + + fi # End: if [[ -n "$remote_gw_address" ]] + + + ## --- + ## --- Now check, if something has changed + ## --- + + if $device_is_online; then + + if containsElement "$inet_device" ${online_devices_arr[@]} ; then + + ## - + ## - + ## - online online + if $DEBUG ; then + echo "`date +'%Y-%m-%d %H:%M:%S'` [ Debug ] $inet_device is still online" >> $log_file + fi + + ## - Check if remote gateway has changed + ## - + if [ "$remote_gw_address" != "${remote_gw_arr[$inet_device]}" ]; then + echo "`date +'%Y-%m-%d %H:%M:%S'` [ WARN ] Remote Gateway on device \"$inet_device\" has changed: ${remote_gw_arr[$inet_device]} --> $remote_gw_address" >> $log_file + remote_gw_arr[$inet_device]=$remote_gw_address + + _pid_file=/var/run/${inet_device}.pid + if [ -f $_pid_file ]; then + filetime_PID_arr[$inet_device]=`stat -c %Y $_pid_file` + fi + changed=true + else + if $DEBUG ; then + echo "`date +'%Y-%m-%d %H:%M:%S'` [ Debug ] Remote Gateway on device \"$inet_device\": still ${remote_gw_arr[$inet_device]}" >> $log_file + fi + + ## - Test if pid-file's modify time hs changed + ## - + ## - Notice: that happens if your provider forces a reconnect (mostly one time a day + ## - or in other words after 1440 minutes) + ## - + _pid_file=/var/run/${inet_device}.pid + if [ -f $_pid_file ]; then + if [ "`stat -c %Y $_pid_file`" != "${filetime_PID_arr[$inet_device]}" ]; then + echo "`date +'%Y-%m-%d %H:%M:%S'` [ Warn ] Modify time for pid-file \"${inet_device}.pid\" has changed" >> $log_file + filetime_PID_arr[$inet_device]=`stat -c %Y $_pid_file` + changed=true + fi + fi + + fi + + else + ## - + ## - + ## - offline online + echo "`date +'%Y-%m-%d %H:%M:%S'` [ Warn ] Status Devices \"$inet_device\" changed" >> $log_file + echo "`date +'%Y-%m-%d %H:%M:%S'` [ Warn ] Devices \"$inet_device\" is now online" >> $log_file + + ## - Add device to array online_devices_arr + ## - + online_devices_arr+=("$inet_device") + ## - Add device to array remote_gw_arr + ## - + remote_gw_arr[$inet_device]=$remote_gw_address + + _pid=/var/run/${inet_device}.pid + if [ -f "$_pid" ]; then + filetime_PID_arr[$inet_device]=`stat -c %Y /var/run/${inet_device}.pid` + fi + changed=true + fi # END: if containsElement "$inet_device" ${online_devices_arr[@]} + + else # ELSE: if $device_is_online; then + + if containsElement "$inet_device" ${online_devices_arr[@]} ; then + + ## - + ## - + ## - online offline + echo "`date +'%Y-%m-%d %H:%M:%S'` [ Error ] Status Devices \"$inet_device\" changed" >> $log_file + echo "`date +'%Y-%m-%d %H:%M:%S'` [ Error ] Devices \"$inet_device\" is now OFFLINE" >> $log_file + + ## - In case of DSL Device, have a look at the ppp deamon + ## - + if containsElement "$inet_device" "${dsl_devices_arr[@]}" ; then + if ps -x | grep -E "/usr/sbin/pppd\s+call\s+$iface_name" > /dev/null 2>&1 ; then + echo "`date +'%Y-%m-%d %H:%M:%S'` [ Warn ] pppd for \"$iface_name\" is running: Waiting another period" >> $log_file + else + echo "`date +'%Y-%m-%d %H:%M:%S'` [ Info ] Trying to start pppd for \"$inet_device\".." >> $log_file + /usr/sbin/pppd call $iface_name > /dev/null 2>&1 + fi + fi + + ## - Remove device from array online_devices_arr + ## - + for _index in ${!online_devices_arr[@]} ; do + if [ "${online_devices_arr[$_index]}" = "$inet_device" ]; then + unset online_devices_arr[$_index] + break + fi + done + ## - Also remove device from remote_gw_arr + ## - + unset remote_gw_arr[$inet_device] + + ## - In case of DSL Device, kill the concerning the ppp deamon + ## - + if containsElement "$inet_device" "${dsl_devices_arr[@]}" ; then + _pid=`ps -ax | grep -e "pppd call $iface_name" | grep -v grep | awk '{print$1}'` + echo "`date +'%Y-%m-%d %H:%M:%S'` [ Info ] Kill ppp-daemon for $iface_name (pid $_pid)" >> $log_file + + kill -9 $_pid + fi + + changed=true + else + ## - + ## - + ## - offline offline + if $DEBUG ; then + echo "`date +'%Y-%m-%d %H:%M:%S'` [ Debug ] $inet_device is still offline" >> $log_file + fi + + ## - In case of DSL Device, have a look at the ppp deamon + ## - + if containsElement "$inet_device" "${dsl_devices_arr[@]}" ; then + if ps -x | grep -E "/usr/sbin/pppd\s+call\s+$iface_name" > /dev/null 2>&1 ; then + echo "`date +'%Y-%m-%d %H:%M:%S'` [ Warn ] pppd for \"$iface_name\" is running: Waiting another period" >> $log_file + else + echo "`date +'%Y-%m-%d %H:%M:%S'` [ Info ] Trying to start pppd for \"$inet_device\".." >> $log_file + /usr/sbin/pppd call $iface_name > /dev/null 2>&1 + fi + fi + + fi # END: if containsElement "$inet_device" ${online_devices_arr[@]} + + fi # END: if $device_is_online; then + + done # End: for inet_device in "${inet_devices_arr[@]}" + + + if $changed ; then + echo "`date +'%Y-%m-%d %H:%M:%S'` [ Warn ] Status Online Devices changed" >> $log_file + echo "`date +'%Y-%m-%d %H:%M:%S'` [ Warn ] Online Devices: ${online_devices_arr[@]}" >> $log_file + echo "`date +'%Y-%m-%d %H:%M:%S'` [ Warn ] Reconfigure Routing: invoking script \"$netconfig_script\".." >> $log_file + if [[ -z "${online_devices_arr[@]}" ]]; then + if $DEBUG ; then + echo "`date +'%Y-%m-%d %H:%M:%S'` [ Debug ] $netconfig_script $INITIAL_DEVICE_LIST" >> $log_file + fi + + $netconfig_script $INITIAL_DEVICE_LIST > /dev/null 2>&1 + else + + _LIST= + for _device in ${online_devices_arr[@]} ; do + _LIST="$_LIST $_device" + done + _LIST=`echo "${_LIST}" | sed -e 's/^[ \t]*//'` + if $DEBUG ; then + echo "`date +'%Y-%m-%d %H:%M:%S'` [ Debug ] $netconfig_script -l \"$_LIST\" $INITIAL_DEVICE_LIST" >> $log_file + fi + $netconfig_script -l "$_LIST" $INITIAL_DEVICE_LIST > /dev/null 2>&1 + fi + + datum=`date +"%d.%m.%Y"` + msg="[ `date +\"%H:%M:%S\"` ]: Status Online Devices changed..\n Online Devices: ${online_devices_arr[@]}\n\n Script \"$netconfig_script\" was invoked to reconfigure routing." + echo -e "To:${admin_email}\n${content_type}\nSubject:DSL Status changed $company -- $datum\n\n${msg}\n" | /usr/sbin/sendmail -F "DSL Monitoring $company" -f $from_address $admin_email 2> /dev/null + fi # END if $changed + + + ## - Set IP-adresses for Ping-Test at next run + ## - + if [[ ${#online_devices_arr[@]} -gt 0 ]]; then + + ## - Try to set IP-Addresses for ping test + ## - + set_ping_addresses + + elif [[ ${#dsl_gw_available_arr[@]} -gt 0 ]]; then + + echo "`date +'%Y-%m-%d %H:%M:%S'` [ Info ] Try to set default gateway to an existing DSL line .." >> $log_file + + __set_default_gatway=false + default_gw_deleted=false + + for _device in "${dsl_devices_arr[@]}" ; do + + if $DEBUG ; then + echo "`date +'%Y-%m-%d %H:%M:%S'` [ Info ] Device: $_device - Gateway: ${dsl_gw_available_arr[$_device]}" >> $log_file + fi + + if [[ -n "${dsl_gw_available_arr[$_device]}" ]]; then + + ## - Delete old default route + ## - + if ! $default_gw_deleted ; then + if $DEBUG ; then + echo "`date +'%Y-%m-%d %H:%M:%S'` [ Info ] /sbin/ip route delete default" >> $log_file + /sbin/ip route delete default >> $log_file 2>&1 + else + /sbin/ip route delete default > /dev/null 2>&1 + fi + default_gw_deleted=true + fi + + ## - Try to set default gateway to this DSL connection + ## - + if $DEBUG ; then + echo "`date +'%Y-%m-%d %H:%M:%S'` [ Info ] /sbin/ip route add default via ${dsl_gw_available_arr[$_device]} dev $_device" >> $log_file + /sbin/ip route add default via ${dsl_gw_available_arr[$_device]} dev $_device >> $log_file 2>&1 + else + /sbin/ip route add default via ${dsl_gw_available_arr[$_device]} dev $_device > /dev/null 2>&1 + fi + if [[ "$?" == "0" ]]; then + __set_default_gatway=true + break + fi + fi + + done # END: for _device in "${inet_devices_arr[@]}" + + if ! $__set_default_gatway ; then + echo "`date +'%Y-%m-%d %H:%M:%S'` [ Error ] No default gateway (for DSL Device ${_device}) is set!" >> $log_file + else + echo "`date +'%Y-%m-%d %H:%M:%S'` [ Info ] Default gateway on DSL Device $_device is set to ${inet_devices_arr[$_device]}" >> $log_file + + + ## - Try to set IP-Addresses for ping test + ## - + set_ping_addresses + fi + + elif [[ ${#static_devices_arr[@]} -gt 0 ]]; then + + echo "`date +'%Y-%m-%d %H:%M:%S'` [ Info ] Try to set default gateway to an existing static line .." >> $log_file + + __set_default_gatway=false + default_gw_deleted=false + + for _device in "${static_devices_arr[@]}" ; do + + ## - Delete old default route + ## - + if ! $default_gw_deleted ; then + if $DEBUG ; then + echo "`date +'%Y-%m-%d %H:%M:%S'` [ Info ] /sbin/ip route delete default" >> $log_file + /sbin/ip route delete default >> $log_file 2>&1 + else + /sbin/ip route delete default > /dev/null 2>&1 + fi + default_gw_deleted=true + fi + + ## - Set new default route + ## - + if $DEBUG ; then + echo "`date +'%Y-%m-%d %H:%M:%S'` [ Info ] /sbin/ip route add default via ${static_gw_arr[$_device]} dev $_device" >> $log_file + /sbin/ip route add default via ${static_gw_arr[$_device]} dev $_device >> $log_file 2>&1 + else + /sbin/ip route add default via ${static_gw_arr[$_device]} dev $_device > /dev/null 2>&1 + fi + + if [[ "$?" == 0 ]] ; then + __set_default_gatway=true + break + fi + done + + if ! $__set_default_gatway ; then + echo "`date +'%Y-%m-%d %H:%M:%S'` [ Error ] No default gateway is set!" >> $log_file + else + echo "`date +'%Y-%m-%d %H:%M:%S'` [ Info ] Default gateway is set to ${static_gw_arr[$_device]}" >> $log_file + + ## - Try to set IP-Addresses for ping test + ## - + set_ping_addresses + + fi + + fi # if [[ ${#online_devices_arr[@]} -gt 0 ]] + + sleep 30 + +done + +exit 0 diff --git a/netconfig.sh b/netconfig.sh new file mode 100755 index 0000000..bce0dee --- /dev/null +++ b/netconfig.sh @@ -0,0 +1,993 @@ +#!/usr/bin/env bash + +## ------------------------------------------------------------------- +## --- All Configurations ill be done in /etc/check_net/check_net.conf +## ------------------------------------------------------------------- + +## - Load Configuration +## - +source /etc/check_net/check_net.conf + + +## ------------------ +## --- Some functions +## ------------------ + +## - Check if a given array (parameter 2) contains a given string (parameter 1) +## - +fatal(){ + echo "" + echo -e "[ \033[31m\033[1mError\033[m ]: $*" + echo "" + echo -e "\t\033[31m\033[1mScript is canceled\033[m\033[m" + echo "" + + echo "" >> $log_file + echo "[ Error ]: $*" >> $log_file + echo "" >> $log_file + echo " Script is canceled." >> $log_file + echo "" >> $log_file + + exit 1 +} +containsElement () { + local e + for e in "${@:2}"; do [[ "$e" == "$1" ]] && return 0; done + return 1 +} + +usage() { + echo + [ -n "$1" ] && echo -e "[ \033[1;31mError\033[m ] : $1\n" + +echo -e " Usage:" +echo -e " \033[1m`basename $0` [OPTIONS] ..\033[m" +echo "" +echo -e " This script configures the default route, especially if more than one" +echo -e " route to the internet exists. Also the routing tables are managed by this" +echo -e " script." +echo "" +echo -e " The Parameter \033[1mdevice list\033[m contains all network devices, which should have" +echo -e " a connection to the Internet. Tha can be DSL lines as well as static lines." +echo -e " The declaration of the device list is mandatory." +echo "" +echo -e " \033[1mNotice\033[m" +echo -e " Declare the device list in the order of your preferred default gatway devices." +echo "" +echo -e " \033[1mNotice\033[m" +echo -e " On static line devices \033[1mappend \":\033[m. This is very important," +echo -e " otherwise this script will \033[1mNOT work as expected\033[m." +echo "" +echo -e " If this script is invoked with option \033[1m-m\033[m, another script called \033[1m`basename $check_script`\033[m" +echo -e " will be triigered to monitor the devices and informs about changes (online/offline" +echo -e " status) of the given devices. If the status of a line has changed, this script" +echo -e " is reinvoked by the monitoring script \033[1m`basename $check_script`\033[m to reconfigure" +echo -e " the routing." +echo "" +echo -e " Options:" +echo "" +echo -e " \033[1m-h\033[m" +echo -e " Prints this help\033[m" +echo "" +echo -e " \033[1m-l \033[m" +echo -e " List of all (internet) devices known as online. Usually, this option will" +echo -e " be used by triggering this script from check script \033[1m`basename $check_script`\033[m." +echo "" +echo -e " \033[1m-m\033[m" +echo -e " Activates monitoring of the given network devices." +echo "" +echo -e " Example:" +echo -e " - Simply configure routing for devices \"$_INITIAL_DEVICE_LIST\"" +echo -e " \033[1m`basename $0` $_INITIAL_DEVICE_LIST\033[m" +echo "" +echo -e " - Configure routing for devices \"$_INITIAL_DEVICE_LIST\" and activate monitoring" +echo -e " \033[1m`basename $0` -m $_INITIAL_DEVICE_LIST\033[m" +echo "" + +exit 1 +} + +if [[ ! -f "$check_script" ]] ; then + fatal "Check script \033[1m$check_script\033[m not found!" +fi + +if [[ "`which sipcalc`" == "" ]]; then + fatal "\033[1msipcalc\033[m must be installed to run this script" +fi + +if [[ $EUID -ne 0 ]]; then + fatal "This script must be run as root" 1>&2 +fi + +## --- +## --- Configure +## --- + +_monitoring=false +ONLINE_DEVICE_LIST= +while getopts hl:m opt ; do + case $opt in + h) usage + ;; + l) ONLINE_DEVICE_LIST=$OPTARG + ;; + m) _monitoring=true + ;; + esac +done + +shift `expr $OPTIND - 1` + +INITIAL_DEVICE_LIST="$@" +if [[ -z "$INITIAL_DEVICE_LIST" ]]; then + INITIAL_DEVICE_LIST=$_INITIAL_DEVICE_LIST +fi + +[[ -z "$INITIAL_DEVICE_LIST" ]] && usage "No device list given" + +## - Define (non associative) array +## - +declare -a inet_devices_arr +declare -a dsl_devices_arr +declare -a static_devices_arr +declare -a online_devices_arr +declare -A static_gw_arr + +for _device in $INITIAL_DEVICE_LIST ; do + if [[ "$_device" =~ : ]]; then + static_gateway="${_device##*:}" + _device="${_device%:*}" + static_gw_arr[$_device]="$static_gateway" + + static_devices_arr+=("$_device") + + else + dsl_devices_arr+=("$_device") + fi + inet_devices_arr+=("$_device") +done + +for _online_device in $ONLINE_DEVICE_LIST ; do + online_devices_arr+=("$_online_device") +done + + +#echo "All Devices:" +#for _device in "${inet_devices_arr[@]}" ; do +# echo -e "\t$_device" +#done +#echo "Online Devices:" +#for _device in "${online_devices_arr[@]}" ; do +# echo -e "\t$_device" +#done +# +#for inet_device in "${inet_devices_arr[@]}" ; do +# if [ -n "$ONLINE_DEVICE_LIST" ]; then +# if ! containsElement "$inet_device" "${online_devices_arr[@]}" ; then +# echo "$inet_device is offline" +# continue +# fi +# fi +#done +# +#echo "" +#exit + + +## - Define associative arrays +## - +declare -A default_gw_arr +declare -A gw_connection_arr + +declare -i number_rt_table=0 + + +## --- +## --- Start +## --- + +#echo "" >> $log_file +#echo "" >> $log_file +#echo "#############################" >> $log_file +#echo "### ---" >> $log_file +#echo "### --- [ `date +'%Y-%m-%d %H:%M'` ]: Starting Script `basename $0`.." >> $log_file +#echo "### --- Devices all: $INITIAL_DEVICE_LIST" >> $log_file +#echo "### --- Devices online: $ONLINE_DEVICE_LIST" >> $log_file +#echo "### ---" >> $log_file +#echo "### ---" >> $log_file +#echo "#############################" >> $log_file + +echo "" >> $log_file +echo "`date +'%Y-%m-%d %H:%M:%S'` [ Info ] Starting Script `basename $0`.." >> $log_file +echo " Devices all: $INITIAL_DEVICE_LIST" >> $log_file +echo " Devices online: $ONLINE_DEVICE_LIST" >> $log_file + +configured=false +if $_monitoring ; then + max_attempts=20 +else + max_attempts=1 +fi +declare -i _try_number=0 +declare -i prio=0 + +while ! $configured && [ $_try_number -lt $max_attempts ] ; do + + let _try_number++ + + if [ $_try_number -gt 1 ]; then + echo "" >> $log_file + echo "# --- sleeping 2 seconds before attempt number $_try_number" >> $log_file + sleep 2 + fi + + number_rt_table=0 + + #for inet_device in "${dsl_devices_arr[@]}" ; do + for inet_device in "${inet_devices_arr[@]}" ; do + + ## - Create routing table name + ## - + if containsElement "$inet_device" "${dsl_devices_arr[@]}" ; then + __name=`echo $inet_device | cut -d '-' -f2` + rt_name="dsl_$__name" + else + __name=`echo $inet_device | cut -d '-' -f1` + rt_name="static_$__name" + fi + + if ! $_monitoring ; then + + ## - Check if device was reported (from check script) as offline + ## - + _offline=false + if [ -n "$ONLINE_DEVICE_LIST" ]; then + if ! containsElement "$inet_device" "${online_devices_arr[@]}" ; then + _offline=true + fi + else + _offline=true + fi + + ## - Cleanup routing tables + ## - + if $_offline ; then + + if $LOGGING_CONSOLE ; then + echo -e "\n\t[ Error ]: Connection at interface \"$inet_device\" was reported to be down !" + echo -e "\t So device \"$inet_device\" will be excluded from routing." + fi + + echo -e "\n\t[ Error ]: Connection at interface \"$inet_device\" was reported to be down !" >> $log_file + echo -e "\t So device \"$inet_device\" will be excluded from routing." >> $log_file + + ## - Delete all existing entries of this routing table + ## - + echo "" >> $log_file + echo "## - Delete all existing entries of routing table \"$rt_name\"" >> $log_file + echo "## -" >> $log_file + echo "/sbin/ip route flush table $rt_name" >> $log_file + /sbin/ip route flush table $rt_name >> $log_file 2>&1 + + if /sbin/ip rule | grep $rt_name > /dev/null 2>&1 ; then + ## - Delete all rules concerning table $rt_name + ## - + echo "" >> $log_file + echo "## - Delete all rules concerning routing table $rt_name" >> $log_file + echo "## -" >> $log_file + while read line ; do + direction=`echo $line | awk '{print$2}'` + ip=`echo $line | awk '{print$3}'` + echo "/sbin/ip rule delete $direction $ip table $rt_name" >> $log_file + /sbin/ip rule delete $direction $ip table $rt_name + done < <(/sbin/ip rule | grep $rt_name) + echo "" >> $log_file + fi # End: if /sbin/ip rule | grep $rt_name > /dev/null 2>&1 + + continue + + fi # End: if $_offline + fi # End: if ! $_monitoring ; then + + let number_rt_table="$number_rt_table+100" + prio=0 + + + ## - Add new routing table to /etc/iproute2/rt_tables + ## - if not yet exists + ## - + if ! grep $rt_name /etc/iproute2/rt_tables > /dev/null 2>&1 ; then + + echo "" >> $log_file + echo "## - Add new routing table to /etc/iproute2/rt_tables" >> $log_file + echo "## -" >> $log_file + echo "echo \"$number_rt_table $rt_name\" >> /etc/iproute2/rt_tables" >> $log_file + + echo -e "$number_rt_table\t$rt_name" >> /etc/iproute2/rt_tables + fi + + ## - Is the device present and has local Address ? + ## - + local_gw_address=`ifconfig $inet_device 2> /dev/null | grep "inet Adresse" | cut -d":" -f2 | cut -d" " -f1` + if [ -z $local_gw_address ]; then + if $LOGGING_CONSOLE ; then + echo -e "\n\t[ Error ]: Connection at interface \"$inet_device\" seems to be down !" + echo -e "\t No local address was found." + fi + + echo -e "\n\t[ Error ]: Connection at interface \"$inet_device\" seems to be down !" >> $log_file + echo -e "\t No local address was found." >> $log_file + + + ## - Cleanup routing tables + ## - + ## - Delete all existing entries of this routing table + ## - + echo "" >> $log_file + echo "## - Delete all existing entries of this routing table" >> $log_file + echo "## -" >> $log_file + echo "/sbin/ip route flush table $rt_name" >> $log_file + /sbin/ip route flush table $rt_name >> $log_file 2>&1 + + if /sbin/ip rule | grep $rt_name > /dev/null 2>&1 ; then + ## - Delete all rules concerning table $rt_name + ## - + echo "" >> $log_file + echo "## - Delete all rules concerning routing table $rt_name" >> $log_file + echo "## -" >> $log_file + while read line ; do + direction=`echo $line | awk '{print$2}'` + ip=`echo $line | awk '{print$3}'` + echo "/sbin/ip rule delete $direction $ip table $rt_name" >> $log_file + /sbin/ip rule delete $direction $ip table $rt_name + done < <(/sbin/ip rule | grep $rt_name) + echo "" >> $log_file + fi + + continue + fi # End: if [ -z $local_gw_address ] + + ## - Is the DSL-device known and has remote Address ? + ## - + if containsElement "$inet_device" "${dsl_devices_arr[@]}" ; then + remote_gw_address=`ifconfig $inet_device 2> /dev/null | grep "inet Adresse" | cut -d":" -f3 | cut -d" " -f1` + remote_gw_net="$remote_gw_address/32" + else + net_address=`sipcalc $inet_device 2> /dev/null | grep -i -e "^network\s*address\s*-" | awk '{print$4}'` + remote_gw_address=${static_gw_arr[$inet_device]} + _netmask_bits=`sipcalc $inet_device 2> /dev/null | grep -i -e "Network\s*mask\s*(bits)" | awk '{print$5}'` + remote_gw_net="${net_address}/$_netmask_bits" + fi + if [ -z $remote_gw_address ]; then + if $LOGGING_CONSOLE ; then + echo -e "\n\t[ Error ]: Connection at interface \"$inet_device\" seems to be down !" + echo -e "\t No remote gateway was found." + fi + + + echo -e "\n\t[ Error ]: Connection at interface \"$inet_device\" seems to be down !" >> $log_file + echo -e "\t No remote gateway was found." >> $log_file + + ## - Cleanup routing tables + ## - + ## - Delete all existing entries of this routing table + ## - + echo "" >> $log_file + echo "## - Delete all existing entries of this routing table" >> $log_file + echo "## -" >> $log_file + echo "/sbin/ip route flush table $rt_name" >> $log_file + /sbin/ip route flush table $rt_name >> $log_file 2>&1 + + if /sbin/ip rule | grep $rt_name > /dev/null 2>&1 ; then + ## - Delete all rules concerning table $rt_name + ## - + echo "" >> $log_file + echo "## - Delete all rules concerning routing table $rt_name" >> $log_file + echo "## -" >> $log_file + while read line ; do + direction=`echo $line | awk '{print$2}'` + ip=`echo $line | awk '{print$3}'` + echo "/sbin/ip rule delete $direction $ip table $rt_name" >> $log_file + /sbin/ip rule delete $direction $ip table $rt_name + done < <(/sbin/ip rule | grep $rt_name) + echo "" >> $log_file + fi + + continue + fi + + ## - Device already configured by that script? + ## - + if [ ${default_gw_arr[$inet_device]+_} ] ; then + continue + fi + + + # - + # - Ready to start configuration for that device + # - + echo "" >> $log_file + echo "# ---" >> $log_file + if containsElement "$inet_device" "${dsl_devices_arr[@]}" ; then + echo "# --- Routing Table for (DSL) network device \"$inet_device\" was created" >> $log_file + else + echo "# --- Routing Table for (static line) network device \"$inet_device\"" >> $log_file + fi + echo "# ---" >> $log_file + + if $LOGGING_CONSOLE ; then + echo + echo + if containsElement "$inet_device" "${dsl_devices_arr[@]}" ; then + echo -e "\t--- DSL Connection at interface $inet_device" + else + echo -e "\t--- Static Connection at interface $inet_device" + fi + echo -e "\t---" + echo -e "\tRouting Table Name..: $rt_name" + echo + echo -e "\tInterface...........: $inet_device" + echo + echo -e "\tLocal GW address....: $local_gw_address" + echo -e "\tRemote GW address...: $remote_gw_address" + echo -e "\tRemote network......: $remote_gw_net" + echo + fi + echo "# --- Routing Table Name..: $rt_name" >> $log_file + echo "# --- " >> $log_file + echo "# --- Interface...........: $inet_device" >> $log_file + echo "# --- " >> $log_file + echo "# --- Local GW address....: $local_gw_address" >> $log_file + echo "# --- Remote GW address...: $remote_gw_address" >> $log_file + echo "# --- Remote network......: $remote_gw_net" >> $log_file + echo "# --- " >> $log_file + + ## - Read routing table from output of "netstat -rn" + ## - + routing_table_main_arr=() + while read _destination _gateway _genmask _flags _mss _window _irtt _iface; do + if [ "$_destination" = "Destination" -o "$_destination" = "Kernel" \ + -o "$_destination" = "Ziel" -o "$_destination" = "Kernel-IP-Routentabelle" ]; then + continue + fi + routing_table_main_arr+=("$_destination $_gateway $_genmask $_iface") + done < <(netstat -rn) + + ## - First delete all existing entries of this routing table + ## - + echo "" >> $log_file + echo "## - First delete all existing entries of this routing table" >> $log_file + echo "## -" >> $log_file + echo "/sbin/ip route flush table $rt_name" >> $log_file + /sbin/ip route flush table $rt_name >> $log_file 2>&1 + + + ## - Add loopback device to routing table $rt_name + ## - + echo "" >> $log_file + echo "## - Add loopback device to routing table $rt_name " >> $log_file + echo "## -" >> $log_file + echo "/sbin/ip route add 127.0.0.0/8 dev lo table table $rt_name" >> $log_file + /sbin/ip route add 127.0.0.0/8 dev lo table $rt_name >> $log_file 2>&1 + + + ## - Add routing tables of all (local) network interfaces + ## - + echo "" >> $log_file + echo "## - Add routing tables of all (local) network interfaces" >> $log_file + echo "## -" >> $log_file + for _entry in "${routing_table_main_arr[@]}" ; do + dest=`echo $_entry | cut -d " " -f1` + gateway=`echo $_entry | cut -d " " -f2` + genmask=`echo $_entry | cut -d " " -f3` + iface=`echo $_entry | cut -d " " -f4` + + ## - We will set default route later.. + ## - + if [ "$dest" = "0.0.0.0" ]; then + continue + fi + + ## - Is this a "ppp"-device ? + ## - + if [[ "$iface" =~ "ppp" ]]; then + continue + fi + + if [ "$dest" = "$remote_gw_address" ]; then + continue + fi + + if [ "$gateway" = "0.0.0.0" ]; then + echo "/sbin/ip route add ${dest}/$genmask dev $iface table $rt_name" >> $log_file + /sbin/ip route add ${dest}/$genmask dev $iface table $rt_name >> $log_file 2>&1 + else + echo "/sbin/ip route add ${dest}/$genmask via $gateway table $rt_name" >> $log_file + /sbin/ip route add ${dest}/$genmask via $gateway table $rt_name >> $log_file 2>&1 + fi + done + + ## - Add this connection to the routing table + ## - + echo "" >> $log_file + echo "## - Add this connection to the routing table $rt_name" >> $log_file + echo "## -" >> $log_file + + if $USE_REMOTE_GATEWAY_ADDRESS ; then + ## - Remote Network: $remote_gw_net + ## - + echo "/sbin/ip route add $remote_gw_net dev $inet_device src $local_gw_address table $rt_name" >> $log_file + /sbin/ip route add $remote_gw_net dev $inet_device src $local_gw_address table $rt_name >> $log_file 2>&1 + else + ## - Remote Network: 0.0.0.0 + ## - + echo "/sbin/ip route add 0.0.0.0 dev $inet_device src $local_gw_address table $rt_name" >> $log_file + /sbin/ip route add 0.0.0.0 dev $inet_device src $local_gw_address table $rt_name >> $log_file 2>&1 + fi + + if $SET_MULTIPLE_DEFAULT_GW ; then + if /sbin/ip route show table main | grep -e "^$remote_gw_address" | grep $inet_device > /dev/null 2>&1 ; then + echo "" >> $log_file + echo "## - Delete route via (dsl remote) host $remote_gw_address" >> $log_file + echo "## -" + echo "/sbin/ip route delete $remote_gw_address dev $inet_device" >> $log_file + /sbin/ip route delete $remote_gw_address dev $inet_device >> $log_file 2>&1 + fi + + echo "" >> $log_file + echo "## - Add this connection also to the main routing table" >> $log_file + echo "## -" >> $log_file + echo "/sbin/ip route add $remote_gw_net dev $inet_device src $local_gw_address" >> $log_file + /sbin/ip route add $remote_gw_net dev $inet_device src $local_gw_address >> $log_file 2>&1 + fi + + ## - Remeber that route in order to add it to the routing table + ## - of other connections + ## - + gw_connection_arr[$inet_device]="$remote_gw_net $local_gw_address" + + + ## - Add the connections associated gateway as default gateway for this + ## - routing table + ## - + echo "" >> $log_file + echo "## - Add the connections associated gateway as default gateway for this" >> $log_file + echo "## - routing table" >> $log_file + echo "## -" >> $log_file + + if $USE_REMOTE_GATEWAY_ADDRESS ; then + ## - Default Gatway: $remote_gw_address + ## - + #echo "/sbin/ip route add default via $remote_gw_address dev $inet_device table $rt_name" >> $log_file + #/sbin/ip route add default via $remote_gw_address dev $inet_device table $rt_name >> $log_file 2>&1 + echo "/sbin/ip route add default via $remote_gw_address table $rt_name" >> $log_file + /sbin/ip route add default via $remote_gw_address table $rt_name >> $log_file 2>&1 + else + ## - Default Gatway: 0.0.0.0 + ## - + echo "/sbin/ip route add default via 0.0.0.0 dev $inet_device table $rt_name" >> $log_file + /sbin/ip route add default via 0.0.0.0 dev $inet_device table $rt_name >> $log_file 2>&1 + fi + + + ## - Make sure that a reply goes out over the same connection as came in + ## - + echo "" >> $log_file + echo "## - Make sure that a reply goes out over the same connection as came in" >> $log_file + echo "## -" >> $log_file + + if ! /sbin/ip rule | grep "from $local_gw_address" > /dev/null 2>&1 ; then + let prio="$number_rt_table" + echo "/sbin/ip rule add from $local_gw_address table $rt_name prio $prio" >> $log_file + /sbin/ip rule add from $local_gw_address table $rt_name prio $prio >> $log_file 2>&1 + #let prio="10+$prio" + #echo "/sbin/ip rule add to $local_gw_address table $rt_name prio $prio" >> $log_file + #/sbin/ip rule add to $local_gw_address table $rt_name prio $prio >> $log_file 2>&1 + else + let prio="1010+$number_rt_table" + echo -e "#\t[ info ]: Rule already exists.." >> $log_file + fi + + + ## --- + ## --- Special Routing (local) IP-Address OUT + ## --- + + if [[ ${#rule_local_ip_arr[@]} -gt 0 ]] ; then + + let prio="1000+${number_rt_table}+10" + + for _val in "${rule_local_ip_arr[@]}" ; do + + IFS=':' read -a _val_arr <<< "${_val}" + + if [[ "${_val_arr[0]}" = "$inet_device" ]]; then + + echo "" >> $log_file + echo "## - Rule ${prio}: from ${_val_arr[1]} through ${_val_arr[0]}" >> $log_file + echo "## -" >> $log_file + if ! /sbin/ip rule | grep "from ${_val_arr[1]} " > /dev/null 2>&1 ; then + echo "/sbin/ip rule add from ${_val_arr[1]} table $rt_name prio $prio" >> $log_file + /sbin/ip rule add from ${_val_arr[1]} table $rt_name prio $prio >> $log_file 2>&1 + else + echo "# Rule already exists" >> $log_file + fi + prio="10+$prio" + fi + done + fi + + + + ## --- + ## --- Special Routing (remote) Services + ## --- + + if [[ ${#rule_remote_ip_arr[@]} -gt 0 ]] ; then + + let prio="5000+${number_rt_table}+10" + + for _val in "${rule_remote_ip_arr[@]}" ; do + + IFS=':' read -a _val_arr <<< "${_val}" + + if [[ "${_val_arr[0]}" = "$inet_device" ]]; then + + echo "" >> $log_file + echo "## - Rule ${prio}: to ${_val_arr[1]} through ${_val_arr[0]}" >> $log_file + echo "## -" >> $log_file + if ! /sbin/ip rule | grep "to ${_val_arr[1]} " > /dev/null 2>&1 ; then + echo "/sbin/ip rule add to ${_val_arr[1]} table $rt_name prio $prio" >> $log_file + /sbin/ip rule add to ${_val_arr[1]} table $rt_name prio $prio >> $log_file 2>&1 + else + echo "# Rule already exists" >> $log_file + fi + prio="10+$prio" + fi + done + fi + + + ## --- + ## --- Special Routing Networks + ## --- + + if [[ ${#rule_local_net_arr[@]} -gt 0 ]] ; then + + let prio="10000+${number_rt_table}+10" + + for _val in "${rule_local_net_arr[@]}" ; do + + IFS=':' read -a _val_arr <<< "${_val}" + + if [[ "${_val_arr[0]}" = "$inet_device" ]]; then + + echo "" >> $log_file + echo "## - Rule ${prio}: from ${_val_arr[1]} through ${_val_arr[0]}" >> $log_file + echo "## -" >> $log_file + if ! /sbin/ip rule | grep "from ${_val_arr[1]} " > /dev/null 2>&1 ; then + echo "/sbin/ip rule add from ${_val_arr[1]} table $rt_name prio $prio" >> $log_file + /sbin/ip rule add from ${_val_arr[1]} table $rt_name prio $prio >> $log_file 2>&1 + else + echo "# Rule already exists" >> $log_file + fi + prio="10+$prio" + fi + done + fi + + + ## - Add this connection to the routing tables of other already configured dsl-connections + ## - + ## - Note: + ## - Connections which will be configured later at this loop will + ## - not have that connection in their routing tables. So you have + ## - to add missing routes at the end (after that loop has finisched). + ## - + ## - _key is eqal to the ppp-device + ## - + for _key in "${!gw_connection_arr[@]}"; do + + if containsElement "$_key" "${dsl_devices_arr[@]}" ; then + __name=`echo $_key | cut -d '-' -f2` + _rt_name="dsl_$__name" + else + __name=`echo $_key | cut -d '-' -f1` + _rt_name="static_$__name" + fi + if [[ "$_rt_name" == "$rt_name" ]]; then + continue + fi + + _local_gw_address=`echo ${gw_connection_arr[$_key]} | cut -d " " -f2` + _remote_gw_net=`echo ${gw_connection_arr[$_key]} | cut -d " " -f1` + echo "" >> $log_file + echo "## - Add this connection to the routing table \"$_rt_name\"" >> $log_file + echo "## -" >> $log_file + + if $USE_REMOTE_GATEWAY_ADDRESS ; then + ## - Remote Network: $_remote_gw_net + ## - + if ! /sbin/ip route show table $_rt_name | egrep "^$_remote_gw_net\s+dev\s+$_key" >/dev/null 2>&1 ; then + _remote_gw=`echo $_remote_gw_net | cut -d "/" -f1` + if ! /sbin/ip route show table $_rt_name | egrep "^$_remote_gw\s+dev\s+$_key" >/dev/null 2>&1 ; then + echo "/sbin/ip route add $_remote_gw_net dev $_key src $_local_gw_address table $_rt_name" >> $log_file + /sbin/ip route add $_remote_gw_net dev $_key src $_local_gw_address table $_rt_name >> $log_file 2>&1 + else + echo -e "#\t[ info ]: Connection through $_key is already part of table $_rt_name" >> $log_file + fi + fi + else + ## - Remote Network: 0.0.0.0 + ## - + if ! /sbin/ip route show table $_rt_name | egrep "^0.0.0.0\s+dev\s+$_key" >/dev/null 2>&1 ; then + _remote_gw=`echo $_remote_gw_net | cut -d "/" -f1` + if ! /sbin/ip route show table $_rt_name | egrep "^0.0.0.0\s+dev\s+$_key" >/dev/null 2>&1 ; then + echo "/sbin/ip route add 0.0.0.0 dev $_key src $_local_gw_address table $_rt_name" >> $log_file + /sbin/ip route add 0.0.0.0 dev $_key src $_local_gw_address table $_rt_name >> $log_file 2>&1 + else + echo -e "#\t[ info ]: Connection through $_key is already part of table $_rt_name" >> $log_file + fi + fi + fi + done + + + ## - Add this gateway data to the array concerning all outgoing gatways + ## - + #default_gw_arr[$inet_device]="$local_gw_address" + default_gw_arr[$inet_device]="$remote_gw_address" + + + if $SET_MULTIPLE_DEFAULT_GW ; then + + default_gw_arg="" + for _key in "${!default_gw_arr[@]}"; do + + if $USE_DEFAULT_GW_ADDRESS ; then + ## - Default Gateway: $remote_gw_address + ## - + default_gw_arg="$default_gw_arg nexthop via ${default_gw_arr[$_key]} dev $_key weight 1" + else + ## - Default Gateway: 0.0.0.0 + ## - + default_gw_arg="$default_gw_arg nexthop via 0.0.0.0 dev $_key weight 1" + fi + + done + if [ -n "$default_gw_arg" ] ; then + echo "" >> $log_file + echo "## - Add multiple default gateways" >> $log_file + echo "## -" >> $log_file + echo "/sbin/ip route delete default" >> $log_file + /sbin/ip route delete default >> $log_file 2>&1 + echo "/sbin/ip route add default scope global $default_gw_arg" >> $log_file + /sbin/ip route add default scope global $default_gw_arg >> $log_file 2>&1 + else + echo "" >> $log_file + echo "## -" >> $log_file + echo "## - [ Warning]: No default gateway found!" >> $log_file + echo "## -" >> $log_file + fi + + fi + + + + ## - Notice: + ## - It is possible to first make a number of changes and then flush + ## - the cache so that all of the changes will be implemented simultaneously. + ## - This is actually convenient when working on an active router. + ## - + echo "" >> $log_file + echo "## - Flush table cache" >> $log_file + echo "## -" >> $log_file + echo "/sbin/ip route flush table cache" >> $log_file + /sbin/ip route flush table cache >> $log_file 2>&1 + + echo "" >> $log_file + + if [ ${#default_gw_arr[@]} -eq ${#inet_devices_arr[@]} ]; then + configured=true + fi + + done + +done + + +## - Some dsl-connections maybe not known to all routing tables. So add +## - the missing routes to the appropriate tables.. +## - +echo "" >> $log_file +echo "" >> $log_file +echo "## - Some dsl-connections maybe not known to all routing tables. So add" >> $log_file +echo "## - the missing routes to the appropriate tables.." >> $log_file +echo "## -" >> $log_file +_changed=false + +if $USE_REMOTE_GATEWAY_ADDRESS ; then + ## - Remote Network: $_remote_gw_net + ## - + for _key in "${!gw_connection_arr[@]}"; do + + if containsElement "$_key" "${dsl_devices_arr[@]}" ; then + __name=`echo $_key | cut -d '-' -f2` + _rt_name="dsl_$__name" + else + __name=`echo $_key | cut -d '-' -f1` + _rt_name="static_$__name" + fi + + echo "# Routing Table \"$_rt_name\"" >> $log_file + for __key in "${!gw_connection_arr[@]}"; do + _local_gw_address=`echo ${gw_connection_arr[$__key]} | cut -d " " -f2` + _remote_gw_net=`echo ${gw_connection_arr[$__key]} | cut -d " " -f1` + if ! /sbin/ip route show table $_rt_name | egrep "^$_remote_gw_net\s+dev\s+$__key" >/dev/null 2>&1 ; then + _remote_gw=`echo $_remote_gw_net | cut -d "/" -f1` + if ! /sbin/ip route show table $_rt_name | egrep "^$_remote_gw\s+dev\s+$__key" >/dev/null 2>&1 ; then + #echo "/sbin/ip route add $_remote_gw_net dev $_key src $_local_gw_address table $_rt_name" >> $log_file + #/sbin/ip route add $_remote_gw_net dev $__key src $_local_gw_address table $_rt_name >> $log_file 2>&1 + echo "/sbin/ip route add $_remote_gw dev $__key table $_rt_name" >> $log_file + /sbin/ip route add $_remote_gw dev $__key table $_rt_name >> $log_file 2>&1 + _changed=true + else + echo -e "#\t[ info ]: Connection through $__key is already part of table $_rt_name" >> $log_file + fi + fi + done + done +else + ## - Remote Network: 0.0.0.0 + ## - + for _key in "${!gw_connection_arr[@]}"; do + + + if containsElement "$_key" "${dsl_devices_arr[@]}" ; then + __name=`echo $_key | cut -d '-' -f2` + _rt_name="dsl_$__name" + else + __name=`echo $_key | cut -d '-' -f1` + _rt_name="static_$__name" + fi + + echo "# Routing Table \"$_rt_name\"" >> $log_file + for __key in "${!gw_connection_arr[@]}"; do + _local_gw_address=`echo ${gw_connection_arr[$__key]} | cut -d " " -f2` + _remote_gw_net=`echo ${gw_connection_arr[$__key]} | cut -d " " -f1` + if ! /sbin/ip route show table $_rt_name | egrep "^0.0.0.0\s+dev\s+$__key" >/dev/null 2>&1 ; then + _remote_gw=`echo $_remote_gw_net | cut -d "/" -f1` + if ! /sbin/ip route show table $_rt_name | egrep "^0.0.0.0\s+dev\s+$__key" >/dev/null 2>&1 ; then + echo "/sbin/ip route add 0.0.0.0 dev $_key src $_local_gw_address table $_rt_name" >> $log_file + /sbin/ip route add 0.0.0.0 dev $__key src $_local_gw_address table $_rt_name >> $log_file 2>&1 + _changed=true + else + echo -e "#\t[ info ]: Connection through $__key is already part of table $_rt_name" >> $log_file + fi + fi + done + done +fi + + +## - If not using multiple default gatways, set the default gateway here +## - +if ! $SET_MULTIPLE_DEFAULT_GW ; then + + __set_default_gatway=false + + echo "" >> $log_file + echo "" >> $log_file + echo "## ---" >> $log_file + echo "## --- Add default gateway" >> $log_file + echo "## ---" >> $log_file + + ## - Note: the first online device will become default route + ## - + for _device in "${inet_devices_arr[@]}" ; do + ## - Device online ? + if [ -n "${default_gw_arr[$_device]}" ]; then + echo "/sbin/ip route delete default" >> $log_file + /sbin/ip route delete default >> $log_file 2>&1 + if $USE_REMOTE_GATEWAY_ADDRESS ; then + echo "/sbin/ip route add default via ${default_gw_arr[$_device]} dev $_device" >> $log_file + /sbin/ip route add default via ${default_gw_arr[$_device]} dev $_device >> $log_file 2>&1 + else + echo "/sbin/ip route add default via 0.0.0.0 dev $_device" >> $log_file + /sbin/ip route add default via 0.0.0.0 dev $_device >> $log_file 2>&1 + fi + __set_default_gatway=true + _changed=true + break + else + echo "" >> $log_file + echo -e "\t[ Warning ]: $_device is OFFLINE ! Trying next.." >> $log_file + fi + done + if ! $__set_default_gatway ; then + + echo "" >> $log_file + echo -e "\t[ Error ]: No connection is online!" >> $log_file + echo -e "\t Try to set default gateway from an existing static line .." >> $log_file + + ## - Notice: + ## - + ## - If no connection is available (the machine is fully offline), the check script will not + ## - recognize, if the static line becomes online. A way to handle this is to let the + ## - default gateway active. + ## - + default_gw_deleted=false + for _device in "${inet_devices_arr[@]}" ; do + if containsElement "$_device" "${static_devices_arr[@]}" ; then + + ## - Delete old default route + ## - + if ! $default_gw_deleted ; then + echo "" >> $log_file + echo "## - Delete existing default gatewy" >> $log_file + echo "## - " >> $log_file + echo "/sbin/ip route delete default" >> $log_file + /sbin/ip route delete default >> $log_file 2>&1 + default_gw_deleted=true + fi + + ## - Set new default route + ## - + + echo "" >> $log_file + echo "## - Try to set default gateway to ${static_gw_arr[$_device]}.." >> $log_file + echo "## - " >> $log_file + echo "/sbin/ip route add default via ${static_gw_arr[$_device]} dev $_device" >> $log_file + /sbin/ip route add default via ${static_gw_arr[$_device]} dev $_device >> $log_file 2>&1 + + if [[ "$?" == 0 ]] ; then + __set_default_gatway=true + break + fi + fi + done + + if ! $__set_default_gatway ; then + echo "" >> $log_file + echo -e "\t[ Error ]: No default gateway is set!" >> $log_file + fi + fi +fi + +## - Flush the routing tables cache if somethimg has changed +## - +if $_changed ; then + echo "" >> $log_file + echo "" >> $log_file + echo "## - Some Routing tables has changed, so flush table cache" >> $log_file + echo "## -" >> $log_file + echo "/sbin/ip route flush table cache" >> $log_file + /sbin/ip route flush table cache >> $log_file 2>&1 +fi + +if $_monitoring ; then + echo "" >> $log_file + echo "" >> $log_file + echo "## - Starting monitoring script to check dsl connections.." >> $log_file + echo "## -" >> $log_file + + if [[ -z "${!default_gw_arr[@]}" ]] ; then + echo "$check_script $INITIAL_DEVICE_LIST &" >> $log_file 2>&1 + $check_script $INITIAL_DEVICE_LIST & + else + + _LIST= + for _device in ${!default_gw_arr[@]} ; do + _LIST="$_LIST $_device" + done + _LIST=`echo "${_LIST}" | sed -e 's/^[ \t]*//'` + + echo "$check_script -l \"$_LIST\" $INITIAL_DEVICE_LIST &" >> $log_file 2>&1 + $check_script -l "$_LIST" $INITIAL_DEVICE_LIST & + fi +fi + +echo "" >> $log_file +echo "### -------------------------" >> $log_file + +exit 0