#!/bin/bash
# Author:
# https://github.com/ltpitt
#
# Please check README.md for install / usage instructions

###
# Configuration variables, customize if needed
###

# Set gateway_ips to one or more ips that you want to check to declare network working or not.
# If any of the ips responds, the network is considered functional.
# A minimum of one ip is required, in the example below it shows how to check two different
# gateways using a space character as delimiter.
gateway_ips='1.1.1.1 8.8.8.8'
# Set nic to your Network card name, as seen in ip output.
# If you have multiple interfaces and are currently online, you can find which is in use with:
# ip route get 1.1.1.1 | head -n1 | cut -d' ' -f5
nic='wlan0'
# Set network_check_threshold to the maximum number of failed checks that must fail
# before declaring the network as non functional.
network_check_threshold=20
# Set reboot_server to true if you want to reboot the system as a last
# option to fix wifi in case the normal restore procedure fails.
reboot_server=false
# Set reboot_server to the desired amount of minutes, it is used to
# prevent reboot loops in case network is down for long time and reboot_server
# is enabled.
reboot_cycle=60
# Folder where this script is located
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
# Last boot file location, also used to prevent reboot loop.
last_bootfile=/${SCRIPT_DIR}/.last_net_autoboot
echo "last_net_autoboot location is: ${SCRIPT_DIR}"

###
# Script logic
###

# Initializing the network check counter to zero.
network_check_tries=0

# This function is a simple logger, just adding datetime to messages.
function date_log {
    echo "$(date +'%Y-%m-%d %T') $1"
}

# This function checks connectivity to gateway_ips
function check_gateways {
    for ip in $gateway_ips; do
        ping -c 1 $ip > /dev/null 2>&1
        # The $? variable always contains the return code of the previous command.
        # In BASH return code 0 usually means that everything executed successfully.
        # In the next if we are checking if the ping command execution was successful.
        if [[ $? == 0 ]]; then
            return 0
        fi
    done
    return 1
}


function restart_wlan {
    date_log "Network was not working for the previous $network_check_tries checks."
    date_log "Restarting $nic"
    # Trying wlan restart using ip command.
    /sbin/ip link set "$nic" down
    sleep 5
    /sbin/ip link set "$nic" up
    sleep 60

    # If the gateway checks are NOT successful.
    if ! check_gateways; then
        if [ "$reboot_server" = true ]; then
            # If there's no last boot file or it's older than reboot_cycle.
            if [[ ! -f $last_bootfile || $(find $last_bootfile -mmin +$reboot_cycle -print) ]]; then
                touch $last_bootfile
                date_log "Network is still not working, rebooting"
                /sbin/reboot
            else
                date_log "Last auto reboot was less than $reboot_cycle minutes old"
            fi
        fi
    fi
}

# This loop will run for network_check_tries times, in case there are
# network_check_threshold failures the network will be declared as
# not functional and the restart_wlan function will be triggered.
while [ $network_check_tries -lt $network_check_threshold ]; do
    # Increasing network_check_tries by 1
    network_check_tries=$((network_check_tries+1))

    # If the gateway checks are successful.
    if check_gateways; then
        # Network is up.
        date_log "Network is working correctly" && exit 0
    else
        # Network is down.
        date_log "Network is down, failed check number $network_check_tries of $network_check_threshold"
    fi

    # Once the network_check_threshold is reached call restart_wlan.
    if [ $network_check_tries -ge $network_check_threshold ]; then
        restart_wlan
    fi
    sleep 5
done
