#!/bin/bash # # open-wifi-auto-connect.sh: Auto connect open WIFI(s). # This script scanns for WIFIs and connects to the first open WIFI it can find # and which is really online, e. g. can send a ping to a root nameserver. # If no open and online WIFI could be connected or after a disconnect it # restarts with a new and fast scan for WIFIs, to make the PC nearly always # online. # To avoid problems with duplicate ESSIDs and hidden ESSIDs this script uses # MACs instead of ESSIDs. # # ---------------------------------------------------------------------------- # "THE BEERWARE LICENSE" (Revision 44): # Dr. Rolf Freitag (rolf dot freitag at email dot de) wrote this file. # As long as you retain this notice you can do whatever # the GPL (GNU Public License version 3) allows with this stuff. # If you think this stuff is worth it, you can send me money via # paypal, and get a contribution receipt if you wish, or if we met some day # you can buy me a beer in return. # ---------------------------------------------------------------------------- # # Version 2010-06-20 # # TODOs: # * sort the list of open WIFIs due to their quality to connect the best # * set a lockfile with the device name in the file name # set -u : Stop the script when a variable isn't set (add -x for debugging) set -u if [ $# -ne 1 ] then echo "Error: Not exact one parameter (the WIFI device); exiting." exit 1 fi # device used for wifi (usually wlan0): first argument DEVICE="$1" # Make sure the script is run as root. #if [ $EUID -ne 0 ]; then if [ $GROUPS -ne 0 ]; then echo "Error: This script must be run from group root, but your group is $GROUPS; exiting." exit 1 fi # kill other stuff which uses the device /etc/init.d/network-manager stop 2>&1 >/dev/null # if necessary bring the device up ifconfig "$DEVICE" 2>&1 > /dev/null if [ $? -ne 0 ] then ifconfig "$DEVICE" up fi # check if the device can now be used ifconfig "$DEVICE" 2>&1 > /dev/null if [ $? -ne 0 ]; then echo "Error: Device $DEVICE is not ready (ifconfig $DEVICE returned not zero); exiting." exit 1 fi # set the device offline for configuration ifconfig "$DEVICE" down # disable the ESSID checking (ESSID promiscuous), no key iwconfig "$DEVICE" channel auto iwconfig "$DEVICE" essid any iwconfig "$DEVICE" key off # set auto parameters with maximum speed of 1 Mbit/s (half duplex) # for maximum sensitivity, maximum range and maximum immunity to interference # because SNR and bit rate are complementary. iwconfig "$DEVICE" txpower auto #iwconfig "$DEVICE" commit # Set a trasmission power of 500 mW, which is ok e. g. in the USA and works # with many cards. The value set here should be (smaller than or) equal to the # maximum of your card. iwconfig "$DEVICE" txpower 500mW iwconfig "$DEVICE" power on iwconfig "$DEVICE" rate 1M auto iwconfig "$DEVICE" frag auto # set client mode iwconfig "$DEVICE" mode managed #iwconfig "$DEVICE" commit # create temporary working directory and change into that directory #TMPDIR0="/tmp/.$0.$$.$RANDOM.DIR1.if.txt" #mkdir "$TMPDIR0" TMPDIR0=`mktemp -d` cd "$TMPDIR0" # bash trap function for cleanup at exit (executed when CTRL-C is pressed) # Signals: 1/HUP, 2/INT, 3/QUIT, 9/KILL, 15/TERM, ERR trap bashtrap 2 9 15 bashtrap() { cd - rm -rf "$TMPDIR0" exit 0 } # create temporary files #TMPFILE0="$TMPDIR0/.$0.$$.$RANDOM.0.if.txt" #TMPFILE0=`tempfile -d "$TMPDIR0"` # tempfile is not part of the coreutils TMPFILE0=`mktemp --tmpdir="$TMPDIR0"` TMPFILE1=`mktemp --tmpdir="$TMPDIR0"` # variables for open WIFI count (0...), ... typeset -i OPENCOUNT=0 typeset -i CLOSEDCOUNT=0 typeset -i CELLCOUNT=0 typeset -i i=0 declare -a APMAC declare -a OPENCELLNUMBER declare -a CHANNEL declare -a ESSID typeset -i deadline_counter=0 typeset -i loop_counter=0 typeset -i connected=0 typeset -i flag=0 typeset -i SCANNUMBER=0 # start of the endless loop with scanning, looking for open WIFIs, testing/using while [ 1 = 1 ] do OPENCOUNT=0 # Change the MAC before every scan to a random and valid MAC by limiting the second byte to 5. # Because modern WIFI cards usually have higher bytes, this ensures another and random MAC. ran=$(head /dev/urandom | md5sum) MAC=00:0$[$RANDOM%6]:${ran:0:2}:${ran:3:2}:${ran:5:2}:${ran:7:2} echo "switching MAC to $MAC" ifconfig "$DEVICE" down ifconfig "$DEVICE" promisc ifconfig "$DEVICE" hw ether $MAC # clear the arp cache #ip neigh flush all 2>/dev/null ifconfig "$DEVICE" up # scan and get a list of (open) wifi points echo "Scan number $SCANNUMBER, scanning ..." SCANNUMBER=$[$SCANNUMBER +1] iwlist "$DEVICE" scanning > "$TMPFILE0" 2>/dev/null # remove the first line of the scan output (with "Scan completed") i=`wc -l < "$TMPFILE0"` i=$[$i -1] tail -n $i "$TMPFILE0" > "$TMPFILE1" # get the number of open WIFIs cat "$TMPFILE1" | grep "Encryption key:off" > "$TMPFILE0" OPENCOUNT=`wc -l < "$TMPFILE0"` # get the number of closed WIFIs cat "$TMPFILE1" | grep "Encryption key:on" > "$TMPFILE0" CLOSEDCOUNT=`wc -l < "$TMPFILE0"` echo "Found $OPENCOUNT open WIFI(s) and $CLOSEDCOUNT closed WIFI(s)." # get the total number of WIFIs (Cells) cat "$TMPFILE1" | grep "Encryption key:" > "$TMPFILE0" CELLCOUNT=`wc -l < "$TMPFILE0"` # Split the scan output into one file per cell; the files are xx1, xx2, ... csplit --digits=1 -k "$TMPFILE1" '/Cell/' {99} 2> /dev/null > /dev/null # print the ESSID(s) echo "List of WIFI(s) with Channel, Encryption, Quality, Signal Level, MAC, ESSID:" i=1 # number for the first open WIFI MAC for loop_counter in $(seq 1 $CELLCOUNT) do echo -n "`cat xx$loop_counter | awk '/Channel:/{ print $1 }'`" echo -n -e "\t`cat xx$loop_counter | awk '/Encryption/{ print $2 }'`" echo -n -e "\t`cat xx$loop_counter | awk '/Quality/{ print $1}'`" echo -n " `cat xx$loop_counter | awk '/Quality/{ print $3}'`" echo -n " `cat xx$loop_counter | awk '/Address/{ print $5 }'`" echo " `cat xx$loop_counter | awk '/ESSID/{ print $1 }'`" done # if no open WIFI found: continue (make a new scan) if [ $OPENCOUNT -eq 0 ] then continue fi # now we have at minimum one open WIFI # put the MACs of the open WIFIs into the array (APMAC) i=1 # number for the first open WIFI MAC for loop_counter in $(seq 1 $CELLCOUNT) do cat xx$loop_counter | grep "Encryption key:off" 2>&1 >/dev/null if [ $? -eq 0 ]; then APMAC[$i]=`cat xx$loop_counter | awk '/Address/{ print $5 }'` CHANNEL[$i]=`cat xx$loop_counter | awk '/Channel:/{ print $1 }' | cut -d ":" -f 2` foo=`cat xx$loop_counter | awk '/ESSID:/{ print $1 }' | cut -d ":" -f 2 | cut -c 2-128` ESSID[$i]=${foo%?} OPENCELLNUMBER[$i]=$loop_counter i=$[$i +1] fi done # now the MACs of the open WIFIs are at APMAC[1]...APMAC[$OPENCOUNT] # Check/use the list of open WIFI(s) for loop_counter in $(seq 1 $OPENCOUNT) do deadline_counter=0 connected=0 echo "Checking the open WIFI with MAC ${APMAC[$loop_counter]}, Channel ${CHANNEL[$loop_counter]}, ESSID ${ESSID[$loop_counter]}" while [ $deadline_counter -lt 2 ] # give a connection try at minimum two chances do if [ $connected -eq 0 ]; then # if not connected # kill the now outdated dhcpcd if [ -f /var/run/dhcpcd-"$DEVICE".pid ] then kill `cat /var/run/dhcpcd-"$DEVICE".pid` rm -f /var/run/dhcpcd-"$DEVICE".pid fi killall dhclient 2>&1 >/dev/null rm -f /var/run/dhclient.pid # Connect iwconfig "$DEVICE" mode managed ap "${APMAC[$loop_counter]}" channel "${CHANNEL[$loop_counter]}" essid ${ESSID[$loop_counter]} # iwconfig commit # DHCP configuration: use dhcpcd if availible, dhclient else # if command -s -v dhcpcd type -P dhcpcd if [ $? -eq 0 ] then dhcpcd "$DEVICE" else dhclient "$DEVICE" fi connected=1 # we should now be connected to the access point fi echo "Connectet" # check the internet connection (online test) by pinging # TODO: Add a httping test (with checking the content). flag=0; for HOST in 8.8.8.8 4.2.2.2 192.5.5.241 184.73.110.30 173.222.58.135; do { ping -M do -Q 0x02 -q -w 5 -W 5 -c 1 -s 24 -p 0f1e2d3c4b5a6978 -n $HOST &> /dev/null ; }&& flag=1 && break done # if no internet connection: increase deadline counter if [ $flag -eq 0 ]; then deadline_counter=$[$deadline_counter +1] else # we are connected; wait before the next check echo "Online!" sleep 10 fi done # the last open WIFI failed the online test two times; loop to the next deadline_counter=0 connected=0 echo "Not connectet" done # go to the next open WIFI (or make a new scan) done # while [ 1 = 1 ], end of the endless loop exit 0