#!/bin/bash #version 0.96-N/HS-I #You may share this script on the condition a reference to RaspberryConnect.com #must be included in copies or derivatives of this script. #Network Wifi & Hotspot with Internet #A script to switch between a wifi network and an Internet routed Hotspot #A Raspberry Pi with a network port required for Internet in hotspot mode. #Works at startup or with a seperate timer or manually without a reboot #Other setup required find out more at #http://www.raspberryconnect.com wifidev="wlan0" #device name to use. Default is wlan0. ethdev="eth0" #Ethernet port to use with IP tables #use the command: iw dev ,to see wifi interface name IFSdef=$IFS cnt=0 #These four lines capture the wifi networks the RPi is setup to use wpassid=$(awk '/ssid="/{ print $0 }' /etc/wpa_supplicant/wpa_supplicant.conf | awk -F'ssid=' '{ print $2 }' ORS=',' | sed 's/\"/''/g' | sed 's/,$//') wpassid=$(echo "${wpassid//[$'\r\n']}") IFS="," ssids=($wpassid) IFS=$IFSdef #reset back to defaults #Note:If you only want to check for certain SSIDs #Remove the # in in front of ssids=('mySSID1'.... below and put a # infront of all four lines above # separated by a space, eg ('mySSID1' 'mySSID2') #ssids=('mySSID1' 'mySSID2' 'mySSID3') #Enter the Routers Mac Addresses for hidden SSIDs, seperated by spaces ie #( '11:22:33:44:55:66' 'aa:bb:cc:dd:ee:ff' ) mac=() ssidsmac=("${ssids[@]}" "${mac[@]}") #combines ssid and MAC for checking createAdHocNetwork() { echo "Creating Hotspot" ip link set dev "$wifidev" down ip a add 192.168.4.1/24 brd + dev "$wifidev" ip link set dev "$wifidev" up dhcpcd -k "$wifidev" >/dev/null 2>&1 iptables -t nat -A POSTROUTING -o "$ethdev" -j MASQUERADE iptables -A FORWARD -i "$ethdev" -o "$wifidev" -m state --state RELATED,ESTABLISHED -j ACCEPT iptables -A FORWARD -i "$wifidev" -o "$ethdev" -j ACCEPT systemctl start dnsmasq systemctl start hostapd echo 1 > /proc/sys/net/ipv4/ip_forward } KillHotspot() { echo "Shutting Down Hotspot" ip link set dev "$wifidev" down systemctl stop hostapd systemctl stop dnsmasq iptables -D FORWARD -i "$ethdev" -o "$wifidev" -m state --state RELATED,ESTABLISHED -j ACCEPT iptables -D FORWARD -i "$wifidev" -o "$ethdev" -j ACCEPT echo 0 > /proc/sys/net/ipv4/ip_forward ip addr flush dev "$wifidev" ip link set dev "$wifidev" up dhcpcd -n "$wifidev" >/dev/null 2>&1 } ChkWifiUp() { echo "Checking WiFi connection ok" sleep 20 #give time for connection to be completed to router if ! wpa_cli -i "$wifidev" status | grep 'ip_address' >/dev/null 2>&1 then #Failed to connect to wifi (check your wifi settings, password etc) echo 'Wifi failed to connect, falling back to Hotspot.' wpa_cli terminate "$wifidev" >/dev/null 2>&1 createAdHocNetwork fi } chksys() { #After some system updates hostapd gets masked using Raspbian Buster, and above. This checks and fixes #the issue and also checks dnsmasq is ok so the hotspot can be generated. #Check Hostapd is unmasked and disabled if systemctl -all list-unit-files hostapd.service | grep "hostapd.service masked" >/dev/null 2>&1 ;then systemctl unmask hostapd.service >/dev/null 2>&1 fi if systemctl -all list-unit-files hostapd.service | grep "hostapd.service enabled" >/dev/null 2>&1 ;then systemctl disable hostapd.service >/dev/null 2>&1 systemctl stop hostapd >/dev/null 2>&1 fi #Check dnsmasq is disabled if systemctl -all list-unit-files dnsmasq.service | grep "dnsmasq.service masked" >/dev/null 2>&1 ;then systemctl unmask dnsmasq >/dev/null 2>&1 fi if systemctl -all list-unit-files dnsmasq.service | grep "dnsmasq.service enabled" >/dev/null 2>&1 ;then systemctl disable dnsmasq >/dev/null 2>&1 systemctl stop dnsmasq >/dev/null 2>&1 fi } FindSSID() { #Check to see what SSID's and MAC addresses are in range ssidChk=('NoSSid') i=0; j=0 until [ $i -eq 1 ] #wait for wifi if busy, usb wifi is slower. do ssidreply=$((iw dev "$wifidev" scan ap-force | egrep "^BSS|SSID:") 2>&1) >/dev/null 2>&1 #echo "SSid's in range: " $ssidreply printf '%s\n' "${ssidreply[@]}" echo "Device Available Check try " $j if (($j >= 10)); then #if busy 10 times goto hotspot echo "Device busy or unavailable 10 times, going to Hotspot" ssidreply="" i=1 elif echo "$ssidreply" | grep "No such device (-19)" >/dev/null 2>&1; then echo "No Device Reported, try " $j NoDevice elif echo "$ssidreply" | grep "Network is down (-100)" >/dev/null 2>&1 ; then echo "Network Not available, trying again" $j j=$((j + 1)) sleep 2 elif echo "$ssidreply" | grep "Read-only file system (-30)" >/dev/null 2>&1 ; then echo "Temporary Read only file system, trying again" j=$((j + 1)) sleep 2 elif echo "$ssidreply" | grep "Invalid exchange (-52)" >/dev/null 2>&1 ; then echo "Temporary unavailable, trying again" j=$((j + 1)) sleep 2 elif echo "$ssidreply" | grep -v "resource busy (-16)" >/dev/null 2>&1 ; then echo "Device Available, checking SSid Results" i=1 else #see if device not busy in 2 seconds echo "Device unavailable checking again, try " $j j=$((j + 1)) sleep 2 fi done for ssid in "${ssidsmac[@]}" do if (echo "$ssidreply" | grep "$ssid") >/dev/null 2>&1 then #Valid SSid found, passing to script echo "Valid SSID Detected, assesing Wifi status" ssidChk=$ssid return 0 else #No Network found, NoSSid issued" echo "No SSid found, assessing WiFi status" ssidChk='NoSSid' fi done } NoDevice() { #if no wifi device,ie usb wifi removed, activate wifi so when it is #reconnected wifi to a router will be available echo "No wifi device connected" wpa_supplicant -B -i "$wifidev" -c /etc/wpa_supplicant/wpa_supplicant.conf >/dev/null 2>&1 exit 1 } chksys FindSSID #Create Hotspot or connect to valid wifi networks if [ "$ssidChk" != "NoSSid" ] then echo 0 > /proc/sys/net/ipv4/ip_forward #deactivate ip forwarding if systemctl status hostapd | grep "(running)" >/dev/null 2>&1 then #hotspot running and ssid in range KillHotspot echo "Hotspot Deactivated, Bringing Wifi Up" wpa_supplicant -B -i "$wifidev" -c /etc/wpa_supplicant/wpa_supplicant.conf >/dev/null 2>&1 ChkWifiUp elif { wpa_cli -i "$wifidev" status | grep 'ip_address'; } >/dev/null 2>&1 then #Already connected echo "Wifi already connected to a network" else #ssid exists and no hotspot running connect to wifi network echo "Connecting to the WiFi Network" wpa_supplicant -B -i "$wifidev" -c /etc/wpa_supplicant/wpa_supplicant.conf >/dev/null 2>&1 ChkWifiUp fi else #ssid or MAC address not in range if systemctl status hostapd | grep "(running)" >/dev/null 2>&1 then echo "Hostspot already active" elif { wpa_cli status | grep "$wifidev"; } >/dev/null 2>&1 then echo "Cleaning wifi files and Activating Hotspot" wpa_cli terminate >/dev/null 2>&1 ip addr flush "$wifidev" ip link set dev "$wifidev" down rm -r /var/run/wpa_supplicant >/dev/null 2>&1 createAdHocNetwork else #"No SSID, activating Hotspot" createAdHocNetwork fi fi