Intro
A long and lingering issue with wireless 802.11 work in a UNIX context is filtering AP scans into a meaningful form such that the important bits (BSSID, ESSID, channel) can be used by shell scripts, PHP, etc.
This is something grappled by many with ‘iwlist’, but as it is now legacy (along with ‘iwconfig’) across Linux distributions, a migration of scripts to ‘iw’ is required to ensure portability.
Here is a short script that will take the output of a scan and place it into a formatted CSV with fields on a single line, like so:
BSSID, freq (MHz), RSSI (dBms), ESSID, channel
24:65:12:85:3a:45,2412,-76.00,FRITZ!Box 7312,1
00:90:3c:c0:01:01,2457,-48.00,noonicorn,10
c0:15:02:c7:d6:45,2412,-86.00,FRITZ!Box Fon WLAN 71,1
74:3b:70:6b:22:4c,2422,-79.00,Don’t Menschen IT,3
e8:9c:a6:3d:c6:1a,2412,-71.00,Superglue-c81a-rescue,1
00:25:fe:a7:af:1c,2417,-84.00,Funkwrecker,2
71:32:71:e7:25:bf,2417,-79.00,WLAN-E72519,2
It takes care of ESSIDs with awkward characters, such as ‘!’ and whitespace.
#!/bin/bash
# Scan APs with 'iw' and output to single-line.
# CSV is in the format:
# BSSID, freq (MHz), RSSI (dBms), ESSID, channel)
# Tested with iw version 3.15 on OpenWrt and 3.4 on Debian GNU/Linux
DATA=/path/to/data
NIC=$(iw dev | grep Interface | awk '{ print $2 }')
TMPFILE=/tmp/scan.log
SCAN=$DATA/networks
S=1;E=5;
# Scrape 'iw' scan output and write to temporary file
iw dev $NIC scan | grep -E '^BSS|SSID|DS Parameter set: channel|signal:|freq:'\
| sed -e 's/BSS\ //' -e 's/(on.*$//' -e 's/DS Parameter\ set:\ channel\ // ' \
-e 's/SSID:\ //' -e 's/freq://' -e 's/signal: //' -e 's/dBm//'\
> $TMPFILE && LEN=$(cat $TMPFILE | wc -l)
# Count lines in 5's
for i in $(seq 1 $((LEN/5)))
do
LINES=$(sed -n "$S,$E p;$E q" $TMPFILE)
# Test for hidden ESSIDs. Allow for ESSIDs with spaces
if [ $(echo $LINES | awk '{print substr($0, index($0,$4))}' | sed \
's/\(.*\)[[:space:]].*/\1/' | wc -c ) -gt 1 ]
then
# Replace all whitespace with commas except whitespace in
# ESSID field
echo $LINES | awk -F ' ' -v OFS=',' '{print $1, $2, $3, \
substr($0, index($0,$4))}' | sed 's/\(.*\)[[:space:]]/\1,/'
fi
# Increment
((S+=5))
((E+=5))
done > $SCAN
rm $TMPFILE
Save it out as scan.sh then:
$ chmod +x scan.sh
$ sudo ./scan.sh && cat /path/to/data/networks
Output can be read straight into variables in a script, like so:
#!/bin/bash
...
while IFS=, read BSSID FREQ RSSI ESSID CHANNEL
do
# Do something with these variables here.
done < /path/to/data/networks