I noticed the output of the live AP client screen on Luci is far from accurate, mostly not even useful.
So, to experiment with it, I wrote this shell script:
#!/bin/bash
declare -A IPHOST
declare -A IPDNSMAP
declare -a MACHOSTLIST
declare -A MACSTATIONSENDMAP
declare -A MACSTATIONRECEIVEMAP
declare -A MACSTATIONSIGNALMAP
INTERFACES=("wlan0" "wlan1")
#not used currently, only for documentation, values are hardcoded in code
DNS="10.0.0.5"
SUBNET="10.0.0."
ZONE="myzone\."
mkfifo /dev/shm/memorymap;
check_host() {
export=$(arping -f -w 5 -I br-lan 10.0.0.$1);
if [[ $? == 0 ]]; then
macaddr=$(echo $export | sed 's/.*10\.0\.0\.[0-9]\+\ \[\([0-9A-Fa-f:]\{17\}\)\]\ .*/\1/')
dnsaddr=$(kdig -t PTR -x 10.0.0.$1 @10.0.0.5 | grep -E "myzone\." | grep -v hostmaster | cut -f 5| cut -d'.' -f 1)
echo "$macaddr $1" > /dev/shm/memorymap
fi
return 0
}
check_station() {
data=($(iw dev $1 station dump | grep -E "($1)|(bitrate)|(signal:\ )" | sed 's/Station\ \([A-Za-z0-9:]\{17\}\)\ [(]on\ [a-zA-Z0-9\-]\+[)]/\1/;s/.*signal:.*\-\([0-9]\{2\}\)\ .*[\[].*dBm/\1/;s/.*tx\ bitrate:[\ \t]\+\([0-9\.]\+\)\ MBit.*/\1/;s/.*rx\ bitrate:[\ \t]\+\([0-9\.]\+\)\ MBit.*/\1/'))
total=${#data[@]}
for (( i=0; i<$total; i+=4 ));
do
identifier=${data[$i]}
MACHOSTLIST=($identifier $MACHOSTLIST)
MACSTATIONSIGNALMAP[$identifier]=${data[$i + 1]}
MACSTATIONSENDMAP[$identifier]=${data[$i + 2]}
MACSTATIONRECEIVEMAP[$identifier]=${data[$i + 3]}
done
}
for d in $(seq 80 82); do
check_host $d &
done
for a in ${INTERFACES[@]}; do
check_station $a
done
echo "waiting for processes to finish ..."
wait
echo "terminating EOF write buffer"
echo 'qi' > /dev/shm/memorymap
echo "running through processes"
while true
do
if read line < /dev/shm/memorymap; then
if [[ "$line" == 'qi' ]]; then
break
fi
echo "$line"
IPHOST[$(echo $line | cut -d' ' -f 1)]=$(echo $line | cut -d' ' -f 2)
IPDNSMAP[$(echo $line | cut -d' ' -f 1)]=$(echo $line | cut -d' ' -f 3)
fi
done
echo "removing pipe"
rm -rf /dev/shm/memorymap
echo "loop through results"
for i in $MACHOSTLIST; do
echo "$i : ${IPHOST[$i]}: ${IPDNSMAP[$i]} - Send: ${MACSTATIONSENDMAP[$i]} - Receive: ${MACSTATIONRECEIVEMAP[$i]} - quality: ${MACSTATIONSIGNALMAP[$i]} / 70"
done
# some formatting stuff ...
All subcommands seem to work perfectly, but this output comes out:
waiting for processes to finish ...
terminating EOF write buffer
... and that's it. It never gets past "echo 'qi' > /dev/shm/memorymap", even when playing around with seq to reduce the fifo input.
Your "wait" commands stops until all "check_host" children die, but all of them are waiting untill someone reads from the "memorymap" fifo, and your script will not read from that fifo until later.
Nobody is ... it's some sort of EOF line to tell the loop we're at the end of line.
Anyway, this one works better, though I do not know about the thread-safety: I'd like to know whether bash supports atomic writes to /dev/shm/memorymap, otherwise this is a rather dangerous construction:
#!/bin/bash
declare -A IPHOST
declare -A IPDNSMAP
declare -a MACHOSTLIST
declare -A MACSTATIONSENDMAP
declare -A MACSTATIONRECEIVEMAP
declare -A MACSTATIONSIGNALMAP
INTERFACES=("wlan0" "wlan1")
#not used currently, only for documentation, values are hardcoded in code
DNS="10.0.0.5"
SUBNET="10.0.0."
ZONE="myzone\."
touch /dev/shm/memorymap
check_host() {
export=$(arping -f -w 5 -I br-lan 10.0.0.$1);
if [[ $? == 0 ]]; then
macaddr=$(echo $export | sed 's/.*10\.0\.0\.[0-9]\+\ \[\([0-9A-Fa-f:]\{17\}\)\]\ .*/\1/')
dnsaddr=$(kdig -t PTR -x 10.0.0.$1 @10.0.0.5 | grep -E "myzone\." | grep -v hostmaster | cut -f 5| cut -d'.' -f 1)
echo "$macaddr $1 $dnsaddr" >> /dev/shm/memorymap
fi
return 0
}
check_station() {
data=($(iw dev $1 station dump | grep -E "($1)|(bitrate)|(signal:\ )" | sed 's/Station\ \([A-Za-z0-9:]\{17\}\)\ [(]on\ [a-zA-Z0-9\-]\+[)]/\1/;s/.*signal:.*\-\([0-9]\{2\}\)\ .*[\[].*dBm/\1/;s/.*tx\ bitrate:[\ \t]\+\([0-9\.]\+\)\ MBit.*/\1/;s/.*rx\ bitrate:[\ \t]\+\([0-9\.]\+\)\ MBit.*/\1/'))
total=${#data[@]}
for (( i=0; i<$total; i+=4 ));
do
identifier=${data[$i]^^}
MACHOSTLIST=($identifier $MACHOSTLIST)
MACSTATIONSIGNALMAP[$identifier]=${data[$i + 1]}
MACSTATIONSENDMAP[$identifier]=${data[$i + 2]}
MACSTATIONRECEIVEMAP[$identifier]=${data[$i + 3]}
done
}
for d in $(seq 90 190); do
check_host $d &
done
for a in ${INTERFACES[@]}; do
check_station $a
done
echo "waiting for processes to finish ..."
wait
echo "terminating EOF write buffer"
echo 'quit' >> /dev/shm/memorymap
chmod ago-w /dev/shm/memorymap
while read line;
do
if [[ "$line" == 'quit' ]]; then
break
fi
echo "$line"
IPHOST[$(echo $line | cut -d' ' -f 1)]="10.0.0.$(echo $line | cut -d' ' -f 2)"
IPDNSMAP[$(echo $line | cut -d' ' -f 1)]=$(echo $line | cut -d' ' -f 3)
done < /dev/shm/memorymap
echo "removing pipe"
rm -rf /dev/shm/memorymap
echo "loop through results"
for i in $MACHOSTLIST; do
echo "$i : ${IPHOST[$i]}: ${IPDNSMAP[$i]} - Send: ${MACSTATIONSENDMAP[$i]} - Receive: ${MACSTATIONRECEIVEMAP[$i]} - quality: ${MACSTATIONSIGNALMAP[$i]} / 70"
done
Data written to a fifo does not go anywhere, until another process reads from it, and viceversa. So, the "echo 'qi' > /dev/shm/memorymap" locks until the script reaches the "read line < /dev/shm/memorymap" command. I see you are using a normal file now.
I do not think there are atomic writes happening in your script, so the contents of the "memorymap" can get garbled.
Don't you trust it? I mean, I'd like to know if I'm learning it the wrong way... It's still reversible right now, but it may not be that easy in future versions
EDIT to give a feature whishlist:
use ARP cache to offload arping requests, and perform initial ipv6 mapping (ip neigh)
use NDP to further discover ipv6 (though not sure how to do that)
I haven't experimented or read about that to be one hundred percent sure that it will not fail... However, that explanation makes sense, and this is not a mission critical script, after all.