#!/bin/bash
# 23/10/2013
# This script attempts to semi-automate / automate the wifi connection
# process from the command line.
# It is intended to be used on a headless machine without the
# requirement of typing several commands for a connection.
# The script stores previous connection credentials in PLAINTEXT as
# *.wpa files in the executed directory and in /etc/wpasupplicant.conf.
# These .wpa files are used to connect to several different AP using
# previously stored info.
# Probably a good idea to stop and other network managing software while
# running this script, also in testing wpa_supplicant does a pretty good
# job of re-connecting a disassociated link automatically.
#
# Mainly created from a combination of scripts taken from theses two
# sources:
# http://www.backtrack-linux.org/forums/archive/index.php/t-3367.html
# AND
# http://www.linuxquestions.org/questions/linux-general-1/wifi-connect\\
# -script-tested-in-ubuntu-772646/
#
# old version 1 http://pastebin.com/Pa90HBiU 01/06/2013
# very simple first version
# old version 2 http://pastebin.com/FzJnv5Nk 02/06/2013
# minor additions
# old version 3 http://pastebin.com/3mu1XT5Y 08/06/2013
# included ability to call up previous saved files from
# command line. Some checking of command line parameters and
# checking for empty saved files
# old version 4
# Added exit return values
# Current version 5
# Removal of cleanslate function. Capitalising of function names.
# Renaming of some function names.
# Addition of random_config to randomly select a previously saved
# config files, check for internet access and keep trying another
# connections if internet access is not made. Can be used in
# conjunction with -f to initially select a conf_file of your choice.
# Improved program feedback and internet access checking.
#
# This script uses the following commands: find, printf, iwlist, awk,
# cat, kill, ps, grep, xargs, iwconfig, dhclient, wpa_supplicant, curl.
#
# Copy, Distribute and Modify Freely.
#
########################################################################
######################## FUNCTIONS #####################################
function HELP (){
HELP_MESSAGE="$1"
if [ "$HELP_MESSAGE" ]; then
printf "$HELP_MESSAGE"
fi
printf "Usage: $0 -i [INTERFACE] OR AND -f [CONF_FILE.wpa] -r (RANDOM_CONF_MODE)\\n"
}
function CHECK_ARGS () {
#
# Define Globals
#
INET_AVAIL=0
RANDOM_CONF_MODE=0
RANDOM_FIRST_RUN=0
CONF_FILE=""
INT=""
if [ -z "$1" ]; then
HELP
exit 1
fi
while getopts "i:f:r" opt
do
case $opt in
i ) INT=${OPTARG};;
f ) CONF_FILE=${OPTARG};;
r ) RANDOM_CONF_MODE=1;;
\\?) HELP
exit 1;;
* ) HELP
exit 1;;
esac
done
#
# check if root
#
if [ "$(id -u)" != "0" ]; then
HELP "This script must be run as root\\n"
exit 1
fi
#
# check if interface is entered as command line argument
#
if [ -z "$INT" ]; then
HELP
exit 1
fi
#
# Check if interface entered exists
#
if [ ! -e /sys/class/net/$INT ]; then
HELP "Network Interface $INT does not exist\\n"
exit 1
fi
#
# If random mode selected, check if wpa files are available
#
if [ $RANDOM_CONF_MODE -eq 1 ]; then
local WPA_FILES=$(find . -type f -name "*.wpa" | wc -l)
if [ "$WPA_FILES" -eq 0 ]; then
HELP "No *.wpa files exist for RANDOM_CONF_MODE\\n"
exit 1
fi
fi
}
function PINGCHECK (){
#
# Check for an internet connection using curl to download from a
# FQDN. 5 Second timeout.
# Ref: superuser.com/questions/545865/how-to-check-if-internet-\\
# connection-is-available-via-terminal/625888
#
printf "Checking for internet access...\\n"
curl --interface $INT -o /dev/null -m 5 -s http://www.google.com
if [[ $? == 0 ]]; then
INET_AVAIL=1
else
#
# Check again for internet access
#
printf "Rechecking for internet access...\\n"
curl --interface $INT -o /dev/null -m 5 -s http://www.google.com
if [[ $? == 0 ]]; then
INET_AVAIL=1
else
INET_AVAIL=0
fi
fi
}
function READ_SAVED (){
#
# Accepts a filename argument to read a saved file. Also can search
# or use previous saved
# wpa configuration files. Will automatically bypass new config
# prompting if RANDOM_CONF_MODE
# is being used.
# Filename checking involves testing file is greater than zero
# length and exists
# before writing the configuration to wpa_supplicant.conf
#
local CONF_FILE=$1
if [ $RANDOM_CONF_MODE -eq 0 ]; then
if [ -n "$CONF_FILE" ]; then
if [ -s "$CONF_FILE" ]; then
printf "File $CONF_FILE exists, proceeding to connect\\n"
WRITE_CONF "$CONF_FILE"
exit 0
else
printf "File $CONF_FILE is invalid or does not exist\\n"
CONF_CREATE
exit 0
fi
fi
else
if [ -n "$CONF_FILE" ]; then
if [ -s "$CONF_FILE" ]; then
WRITE_CONF "$CONF_FILE"
exit 1
else
printf "File $CONF_FILE is invalid or does not exist\\n"
RANDOM_CONF
exit 1
fi
else
RANDOM_CONF
exit 1
fi
fi
#
# Save and change IFS so spaces in file names are not interpreted as
# separate lines in the array
#
OLDIFS=$IFS
IFS=$\'\\n\'
#
# Read all file names into an array
# ref:http://www.cyberciti.biz/tips/handling-filenames-with-spaces-\\
# in-bash.html
#
# " -printf \'%f\\n\' " removes path info from outputs
#
# ref:http://serverfault.com/questions/354403/remove-path-from-find\\
# -command-output
#
SAVED_LIST=($(find . -type f -name "*.wpa" -printf \'%f\\n\'))
#
# restore ifs
#
IFS=$OLDIFS
#
# Tests for number of saved wifi connections, if none exit
#
if [ -z "${SAVED_LIST[0]}" ]; then
printf "There are no previous saved wifi connections\\n"
#
# Create new connection
#
CONF_CREATE
exit 0
fi
#
#PS3 Sets the prompt for the select statement below
#
PS3="Choose a previously saved wifi connection or \'s\' to skip: "
#
# Select one of the previous saved configurations to connect with or
# quit
#
select CONF_FILE in "${SAVED_LIST[@]}"; do
#
# Quit if selected number does not exist
#
if [ -z "$CONF_FILE" ] ; then
printf "Skipping\\n\\n"
PS3=""
CONF_CREATE
exit 0
fi
#
# Quick check if file is greater than zero length and exists
#
if [ -s "$CONF_FILE" ]; then
printf "File $CONF_FILE exists, proceeding to connect\\n"
PS3=""
WRITE_CONF "$CONF_FILE"
exit 0
else
printf "File $CONF_FILE is invalid or does not exist, proceeding to create a new configuration\\n"
PS3=""
CONF_CREATE
exit 0
fi
done
}
function RANDOM_CONF (){
#
# This function randomly select a previously saved config files,
# check for internet access and keep trying another
# connections if internet access is not made. If and internet
# connection is not found, it tries another
# connection. Could be used as a faiover by specifying -f as your
# initial preferred network.
#
local CONF_FILE=$1
#
# Test to check if RANDOM_FIRST_RUN is 1. If so then proceed to
# connect using the config file specified first.
#
if [ $RANDOM_FIRST_RUN -eq 1 ]; then
RANDOM_FIRST_RUN=0
READ_SAVED "$CONF_FILE"
fi
#
# Test if INET_AVAIL is 1, initial value is 0 and if connection is
# good then it is 1. Used to loop and recheck for
# a internet connection. If there is no connection then it go to
# the random config selection.
#
if [ $INET_AVAIL -eq 1 ]; then
#
# Sleep for a random period of 600 to 900 seconds
#
sleep $(((RANDOM % 300)+600))
PINGCHECK
RANDOM_CONF
else
OLDIFS=$IFS
IFS=$\'\\n\'
CONF_FILE=($(find . -type f -name "*.wpa" -printf \'%f\\n\'|sort -R |tail -1))
IFS=$OLDIFS
READ_SAVED "$CONF_FILE"
fi
exit 1
}
function CONF_CREATE (){
#
# This is a user entry prompt function, used to create new config
# files.
#
#
# Scans for wifi connections & isolates wifi AP name
#
eval LIST=( $(iwlist $INT scan 2>/dev/null | awk -F":" \'/ESSID/{print $2}\') )
#
#PS3 Sets the prompt for the select statement below
#
PS3="Choose a new ESSID to create a connection or \'q\' to quit: "
#
# Tests for number of wifi connections, exits if none
#
if [ -z "${LIST[0]}" ]; then
printf "No available wifi connection using $INT\\n"
exit 1
fi
#
# Select from a LIST of scanned connections
#
select CONF_FILE in "${LIST[@]}"; do
#
# Quit if selected number does not exist or alpha in entered
#
if [ -z "$CONF_FILE" ] ; then
printf "Exiting\\n"
exit 0
fi
#
# Get user input for passphrase no need to escape spaces
#
printf "Enter the passphrase for $CONF_FILE?\\n"
read "PASSPHRASE"
#
# Append the CONF_FILE variable (ESSID) to .wpa to make a
# filename for saved configs
#
FILENAME=$CONF_FILE".wpa"
#
# Run wpa_passphrase to generate a file for wpa_supplicant to
# use, store it locally and in etc/wpa_supplicant.conf
#
printf "Running wpa_passphrase\\n"
wpa_passphrase "$CONF_FILE" "$PASSPHRASE" > "$FILENAME" | xargs
#
# Jump to WRITE_CONF function, append configuration filename
# to CONF_FILE variable
#
PS3=""
WRITE_CONF "$FILENAME"
exit 1
done
}
function WRITE_CONF (){
local CONF_FILE=$1
#
# Copy local wpa_supplicant file to etc/wpa_supplicant.conf
#
printf "Writing new configuration file using $CONF_FILE\\n"
cat "$CONF_FILE">/etc/wpa_supplicant.conf | xargs
#
# Jump to connect function, pass on the ESSID variable for connection
#
CONNECT "$CONF_FILE"
exit 1
}
function CONNECT (){
#
# Capture first incoming argument as SSID
#
local ESSID=$1
#
# Kill previous instances of wpa_supplicant to stop other instances
# wpa_supplicant fighting several different AP\'s
# Kill based on
# ref: http://thegeekstuff.com/2011/10/grep-or-and-not-operators
# and
# http://stackoverflow.com/questions/3510673/find-and-kill-a-\\
# process-in-one-line-using-bash-and-regex
#
# Release dhcp ip\'s and bring down the interface
#
kill $(ps aux | grep -E \'[w]pa_supplicant.*\\\'$INT\'\' | awk \'{print $2}\') 2>/dev/null | xargs
dhclient $INT -r
ifconfig $INT down
#
# Assign new credentials to config file
#
iwconfig $INT mode managed essid "$ESSID"
printf "Configured interface $INT; Config file is $ESSID\\n"
ifconfig $INT up
printf "Interface $INT is up\\n"
wpa_supplicant -B -Dwext -i$INT -c/etc/wpa_supplicant.conf 2>/dev/null | xargs
printf "wpa_supplicant running, sleeping for 15...\\n"
#
# Wait to connect before asking for a ip address
#
sleep 15
printf "Running dhclient\\n"
dhclient $INT
#
# Print current ip for interface to screen
#
ifconfig $INT | grep inet
#
# Check if internet is available and print status to screen
#
sleep 5
PINGCHECK
if [ $INET_AVAIL -eq 1 ]; then
printf "Internet is available on this connection\\n"
else
printf "Internet is unavailable on this connection\\n"
fi
if [ $RANDOM_CONF_MODE -eq 1 ]; then
RANDOM_CONF
fi
exit 0
}
########################################################################
######################## START HERE ####################################
#
# Call check args function to check the command line argument supplied are valid.
#
CHECK_ARGS "$@"
#
# Check if RANDOM_CONF_MODE is selected and/or config file specified,
# routes to correct function set
# with file name arguments or no arguments depending on what is specified.
#
if [ $RANDOM_CONF_MODE -eq 1 ]; then
if [ "$CONF_FILE" ]; then
RANDOM_FIRST_RUN=1
RANDOM_CONF "$CONF_FILE"
else
RANDOM_CONF
fi
else
if [ "$CONF_FILE" ]; then
READ_SAVED "$CONF_FILE"
else
READ_SAVED
fi
fi
exit 0