Created
December 23, 2014 21:59
-
-
Save jeffskinnerbox/9277e3ee7961c47ec4c8 to your computer and use it in GitHub Desktop.
Simple script for wireless stations monitoring
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# | |
# WLAN Minitoring Script Version v2.0 | |
# OpenWrt Atheros wireless radio STA status monitor | |
# Developed by dir2cas <kalin.t.ivanov@gmail.com> | |
# | |
# Comments: | |
# Required packages: bash, iw, kmod- packages&drivers to get your wireless interface running | |
# Optional packages: | |
# install with $ opkg update; opkg install iw bash .... | |
# To check if it's installed on your OpenWrt box, try $ opkg list-installed | grep "iw", etc. | |
# It is also recommended to have bash shell installed on your OpenWrt router | |
# | |
# Generally, the script should work without modifying the source, but you are free to do it if satisfying your needs. | |
# | |
# The aim is to give us a live stats monitor of wireless stations' link quality | |
# and some additional useful information regarding the bit rate, Tx/Rx packets, | |
# wireless signal strength, etc. The other goal is to make the output a little | |
# more comprehensive, featured and easily to give you an idea of what is happening | |
# with the stations associated to your AP, as giving you their IPs | |
# and eventual hostnames (if DHCP associated) as an addition to the STA's MAC address. | |
# The other added functionality is the ability to monitor the stats only of a | |
# single wireless STA, by specifying its MAC, IP or hostname if present. | |
# | |
# Source: https://forum.openwrt.org/viewtopic.php?id=29075 | |
SCRIPTNAME="wlan-monitor" | |
################ SCRIPT GLOBAL VARIABLES ################ | |
# Defining varialbles (usually no need to modify) | |
DIR="/tmp/${SCRIPTNAME}" | |
FILE="${SCRIPTNAME}.log" | |
ARP_CACHE="/proc/net/arp" | |
######################################################### | |
function Usage() { | |
# Define the help/warning message: | |
echo -e "\tUsage: ./${SCRIPTNAME}.sh [OPTION 1] [ARG 1]...[OPTION n] [ARG n]\n\n\tList of available options:\n\t-i :\tscan intensity in seconds\n\t-d :\twireless device/interface to monitor on\n\t-t :\t[STA_MAC | STA_IP | STA_Hostname]\n\t-h, --help :\tshow this menu\n\tDefault is to monitor all stations associated\n\tusing wireless device ${WLAN_DEFAULT} and scan intensity ${MON_INTERVAL_DEFAULT} sec" | |
} | |
# Defining the Away() function to terminate the script | |
function Away() { | |
# Show the message sent to the terminating function, if any | |
echo -e >&2 "$@\n" | |
sleep 1 | |
#do some cleaning | |
rm -f ${DIR}/* > /dev/null | |
unset INTERFACE | |
unset DIR | |
unset FILE | |
unset CLIENTS | |
unset ARP_CACHE | |
unset HOST | |
unset WLAN_MON_CMD | |
unset sta_num | |
unset sta_list | |
unset sta_count | |
unset sta[@] | |
unset sta_ip[@] | |
unset sta_hostname[@] | |
unset sta_linenum[@] | |
unset sta_mac_arp | |
unset sta_mac | |
unset flag | |
sleep 1 | |
exit | |
} | |
# Defining the Scan() function to print the current status of the wireless clients to the temp file: | |
function Scan() { | |
#clear | |
local WLAN_MON_CMD="$1" | |
${WLAN_MON_CMD} > ${DIR}/${FILE} | |
} | |
# Defining the GetHosts() function to learn the IPs and Hostnames of the wireless clients' stations (STAs): | |
function GetHosts() { | |
local i=1 | |
sta_num=$(grep -c 'Station' ${DIR}/${FILE}) | |
# Check if there are STAs connected to the AP | |
if [ "${sta_num}" -eq "0" ]; then | |
#exiting | |
Away "NO Wireless STAs associated" | |
fi | |
# Get list with the associated STAs' MAC addresses | |
sta_list=$(cat ${DIR}/${FILE} | grep -e "Station" | cut -f 2 -d" ") | |
if [ -z "${sta_list}" ]; then # -n the argument is non empty, -z the argument is empty | |
#exiting | |
Away "NO Wireless STAs associated" | |
fi | |
# Check again the real scanned wireless STAs (MAC addresses in the array) | |
sta_count=$(echo ${sta_list} | wc -w) | |
# Get each STA its IP and Hostname | |
while [ "${i}" -le "${sta_count}" ] | |
do | |
sta[${i}]=$(echo ${sta_list} | awk -v num=$i '{print $num}') | |
#sta[${i}]=$(echo ${sta_list} | cut -f${i} -d" " | |
sta_ip[${i}]=$(cat ${CLIENTS} | grep "${sta[${i}]}" | awk '{print $3}') | |
if [ -z "${sta_ip[${i}]}" ]; then # -n the argument is non empty, -z the argument is empty | |
sta_ip[${i}]=$(grep -e "${sta[${i}]}" "${ARP_CACHE}" | awk '{print $1}') | |
fi | |
sta_hostname[${i}]=$(cat ${CLIENTS} | grep "${sta[${i}]}" | awk '{print $4}') | |
if [ -z "${sta_hostname[${i}]}" ] || [ "${sta_hostname[${i}]}" = "*" ]; then # fix * if hostname for the device is not set | |
sta_hostname[${i}]="noname" | |
fi | |
#identify the line number of the beginning of each entry | |
sta_linenum[${i}]=$(grep -n -E "${sta[${i}]}" ${DIR}/${FILE} | cut -f1 -d: ) | |
let "i += 1" | |
done | |
} | |
# Defining the Format() function to prepare the final output of the script | |
function Format() { | |
local i=1 | |
local divider="----------------------------------------------------------------------" | |
while [ "${i}" -le "${sta_count}" ] | |
do | |
line=$(grep -e "${sta[${i}]}" ${DIR}/${FILE}) | |
sed -i '/'"${sta[${i}]}"'/ s/.*/'"${line} => IP:${sta_ip[${i}]} | Host:${sta_hostname[${i}]}"'/g' ${DIR}/${FILE} | |
sed -i '/'"${sta[${i}]}"'/ i'"${divider}"'' ${DIR}/${FILE} | |
let "i += 1" | |
done | |
} | |
# Defining the STA_select() function to choose the correct STA, specified by the user with an IP or hostname | |
function STA_select() { | |
#Initialize the script argument | |
local ARG="$1" | |
local i=1 | |
#Get the probable STA MAC address from the arp cache (the STA may have a static IP, not found in the dhcp file) | |
#sta_mac_arp=$(arp | grep "${ARG}" | awk '{print $4}') #this method seems broken, if no arp binary | |
sta_mac_arp=$(grep -e "${ARG}" "${ARP_CACHE}" | awk '{print $4}') | |
#Loop to find the STA MAC address that corresponds to the given argument | |
while [ "${i}" -le "${sta_count}" ] | |
do | |
if [ "${ARG}" = "${sta_hostname[${i}]}" ] || [ "${ARG}" = "${sta_ip[${i}]}" ] || [ "${sta_mac_arp}" = "${sta[${i}]}" ] ; then | |
#if the corresponding MAC is found(confirmed by dhcp), parse it to a variable that will be returned | |
sta_mac=${sta[${i}]} | |
fi | |
let "i += 1" | |
done | |
if [ -n "${sta_mac}" ]; then # -n the argument is non empty, -z the argument is empty | |
return "1" | |
else | |
#the given IP or hosname may be of a device that is not a wireless STA, in this case, exiting | |
Away "The given IP/Hostname <${ARG}> is not a Wireless STA" | |
fi | |
} | |
# Defining the Main() function | |
function Main() { | |
#Define what to do when Ctrl-C is pressed - in this case - to terminate the script jumping to a terminating function | |
#trap '{ echo -e "\nControl-C trap caught, exiting"; Away; }' INT #traps Ctrl-C | |
#Run an initial scan for wireless clients first to get the information needed: | |
WLAN_MON_CMD="iw dev ${INTERFACE} station dump" | |
Scan "${WLAN_MON_CMD}" | |
GetHosts | |
#Check which mode of the script to be run: | |
if [ -z "${HOST}" ]; then # -n the argument is non empty, -z the argument is empty | |
#if no argument given, the script will monitor all STAs, default mode | |
WLAN_MON_CMD="iw dev ${INTERFACE} station dump" | |
else | |
STA_select "${HOST}" | |
WLAN_MON_CMD="iw dev ${INTERFACE} station get ${sta_mac}" | |
fi | |
# Start actual monitoring | |
while : | |
do | |
Scan "${WLAN_MON_CMD}" | |
GetHosts | |
Format | |
clear | |
printf "%s STA(s) associated\n" "${sta_num}" | |
cat ${DIR}/${FILE} | |
sleep ${MON_INTERVAL} | |
done | |
} | |
################################################################################################# | |
#MAIN | |
#echo "Script parameters are: $@ \nNumber of parameters in the Array: ${#ARGUMENTS[@]}" | |
declare -a ARGUMENTS=("$@") | |
# Global variables defaults | |
WLAN_DEFAULT="wlan0" | |
#Monitor interval in seconds | |
MON_INTERVAL_DEFAULT="3" | |
# Initialize script parameters and usage | |
if [ "$#" -gt "6" ]; then | |
#Usage | |
Away "Too many arguments provided\n" | |
fi | |
# Handling Script Arguments | |
for (( i=0;i<${#ARGUMENTS[@]};i++ )); do | |
case ${ARGUMENTS[${i}]} in | |
"-i" ) | |
if [ -z "${ARGUMENTS[$((${i}+1))]}" ] || [ "${ARGUMENTS[$((${i}+1))]}" = "-d" ] || [ "${ARGUMENTS[$((${i}+1))]}" = "-t" ]; then | |
Away "###WARNING###\n<${ARGUMENTS[${i}]}> monitoring intensity provided without argument" | |
fi | |
;; | |
"-d" ) | |
if [ -z "${ARGUMENTS[$((${i}+1))]}" ] || [ "${ARGUMENTS[$((${i}+1))]}" = "-i" ] || [ "${ARGUMENTS[$((${i}+1))]}" = "-t" ]; then | |
Away "###WARNING###\n<${ARGUMENTS[${i}]}> wireless device provided without argument" | |
fi | |
;; | |
"-t" ) | |
if [ -z "${ARGUMENTS[$((${i}+1))]}" ] || [ "${ARGUMENTS[$((${i}+1))]}" = "-i" ] || [ "${ARGUMENTS[$((${i}+1))]}" = "-d" ]; then | |
Away "###WARNING###\n<${ARGUMENTS[${i}]}> target station provided without argument" | |
fi | |
;; | |
*help|-h ) | |
Usage; exit 0; | |
;; | |
* ) | |
if [ "${ARGUMENTS[$((${i}-1))]}" = "-d" ]; then INTERFACE="${ARGUMENTS[${i}]}"; | |
elif [ "${ARGUMENTS[$((${i}-1))]}" = "-t" ]; then HOST="${ARGUMENTS[${i}]}"; | |
elif [ "${ARGUMENTS[$((${i}-1))]}" = "-i" ]; then MON_INTERVAL="${ARGUMENTS[${i}]}"; | |
else | |
Away "###WARNING###\n<${ARGUMENTS[${i}]}> is invalid script option\nCheck the help option for a list of available options" | |
fi | |
;; | |
esac | |
done | |
# Defining unspecified vital global parameters | |
if [ -z "${HOST}" ]; then echo -e "Force scanning of all associated STAs"; unset ${HOST}; fi | |
if [ -z "${INTERFACE}" ]; then echo -e "Force usage of default wireless interface ${WLAN_DEFAULT}"; INTERFACE="${WLAN_DEFAULT}"; fi | |
if [ -z "${MON_INTERVAL}" ]; then echo -e "Force usage of default scan intensity ${MON_INTERVAL_DEFAULT} seconds"; MON_INTERVAL="${MON_INTERVAL_DEFAULT}"; fi | |
CLIENTS=$(cat /etc/config/dhcp | grep "leasefile" | sed 's/.*leasefile//' | tr -d " '") >&- 2>&- | |
if [ -z "${CLIENTS}" ]; then # -n the argument is non empty, -z the argument is empty | |
CLIENTS="/tmp/dhcp.leases" | |
fi | |
# Check if the specified interface is a valid wireless device | |
CHECK_DEVICE=$(iwconfig ${INTERFACE} 2>&1) | |
echo ${CHECK_DEVICE} | grep -i "No such device" > /dev/null && { Away "<${INTERFACE}> is not a valid interface"; }; | |
echo ${CHECK_DEVICE} | grep -i "wireless extensions" > /dev/null && { Away "<${INTERFACE}> is not a wireless interface"; }; | |
sleep 1 | |
# Check for the script directory in /tmp (RAM): | |
if [ -d "${DIR}" ]; then | |
#echo "Directory exists" | |
rm -f ${DIR}/* > /dev/null | |
cd ${DIR} | |
Main | |
else | |
echo "Directory does not exists" | |
echo "Creating directory" | |
mkdir -p ${DIR} | |
cd ${DIR} | |
Main | |
fi |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment