2023-03-30 12:36:31 -06:00
|
|
|
--[[
|
|
|
|
|
|
|
|
Part of AREDN -- Used for creating Amateur Radio Emergency Data Networks
|
|
|
|
Copyright (C) 2023 Tim Wilkinson
|
|
|
|
See Contributors file for additional contributors
|
|
|
|
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
the Free Software Foundation version 3 of the License.
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
|
|
|
Additional Terms:
|
|
|
|
|
|
|
|
Additional use restrictions exist on the AREDN(TM) trademark and logo.
|
|
|
|
See AREDNLicense.txt for more info.
|
|
|
|
|
|
|
|
Attributions to the AREDN Project must be retained in the source code.
|
|
|
|
If importing this code into a new or existing project attribution
|
|
|
|
to the AREDN project must be added to the source code.
|
|
|
|
|
|
|
|
You must not misrepresent the origin of the material contained within.
|
|
|
|
|
|
|
|
Modified versions must be modified to attribute to the original source
|
|
|
|
and be marked in reasonable ways as differentiate it from the original
|
|
|
|
version
|
|
|
|
|
|
|
|
--]]
|
|
|
|
|
2023-04-02 02:29:46 -06:00
|
|
|
local unresponsive_max = 3
|
|
|
|
local last = {}
|
2023-03-30 12:36:31 -06:00
|
|
|
local wifiiface
|
2023-04-02 02:29:46 -06:00
|
|
|
local frequency
|
|
|
|
local ssid
|
2023-03-30 12:36:31 -06:00
|
|
|
|
|
|
|
local IW = "/usr/sbin/iw"
|
|
|
|
local ARPING = "/usr/sbin/arping"
|
|
|
|
|
2023-04-02 02:29:46 -06:00
|
|
|
local logfile = "/tmp/station_monitor.log"
|
|
|
|
if not file_exists(logfile) then
|
|
|
|
io.open(logfile, "w+"):close()
|
|
|
|
end
|
|
|
|
local log = aredn.log.open(logfile, 8000)
|
|
|
|
|
|
|
|
function rejoin_network()
|
|
|
|
os.execute(IW .. " " .. wifiiface .. " ibss leave")
|
|
|
|
nixio.nanosleep(1, 0)
|
|
|
|
os.execute(IW .. " " .. wifiiface .. " ibss join " .. ssid .. " " .. frequency .. " fixed-freq")
|
|
|
|
log:write("Rejoining network")
|
|
|
|
log:flush()
|
|
|
|
end
|
|
|
|
|
2023-03-30 12:36:31 -06:00
|
|
|
function station_monitor()
|
|
|
|
if not string.match(get_ifname("wifi"), "^wlan") then
|
|
|
|
exit_app()
|
|
|
|
else
|
|
|
|
wait_for_ticks(math.max(1, 120 - nixio.sysinfo().uptime))
|
|
|
|
|
|
|
|
wifiiface = get_ifname("wifi")
|
2023-04-02 02:29:46 -06:00
|
|
|
frequency = iwinfo.nl80211.frequency(wifiiface)
|
|
|
|
ssid = iwinfo.nl80211.ssid(wifiiface)
|
|
|
|
|
|
|
|
-- Mikrotik AC hardware has some startup issues which we try to resolve
|
|
|
|
-- by leaving and rejoining the network
|
|
|
|
local boardid = aredn.hardware.get_board_id():lower()
|
|
|
|
if boardid:match("mikrotik") and boardid:match("ac") then
|
|
|
|
rejoin_network()
|
|
|
|
end
|
2023-03-30 12:36:31 -06:00
|
|
|
|
|
|
|
while true
|
|
|
|
do
|
|
|
|
run_station_monitor()
|
2023-04-02 02:29:46 -06:00
|
|
|
wait_for_ticks(60) -- 1 minute
|
2023-03-30 12:36:31 -06:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
function run_station_monitor()
|
|
|
|
|
|
|
|
-- Check each station to make sure we can broadcast and unicast to them
|
2023-04-02 02:29:46 -06:00
|
|
|
local total = 0
|
|
|
|
local old = last
|
|
|
|
last = {}
|
2023-03-30 12:36:31 -06:00
|
|
|
arptable(
|
|
|
|
function (entry)
|
|
|
|
if entry.Device == wifiiface then
|
|
|
|
local ip = entry["IP address"]
|
|
|
|
local mac = entry["HW address"]
|
|
|
|
if entry["Flags"] ~= "0x0" and ip and mac then
|
|
|
|
-- Two arp pings - the first is broadcast, the second unicast
|
|
|
|
for line in io.popen(ARPING .. " -c 2 -I " .. wifiiface .. " " .. ip):lines()
|
|
|
|
do
|
|
|
|
-- If we see exactly one response then we neeed to force the station to reassociate
|
|
|
|
-- This indicates that broadcasts work, but unicasts dont
|
|
|
|
if line:match("Received 1 response") then
|
2023-04-02 02:29:46 -06:00
|
|
|
local val = (old[ip] or 0) + 1
|
|
|
|
last[ip] = val
|
|
|
|
if val > 1 then
|
|
|
|
log:write("Possible unresponsive node: " .. ip .. " [" .. mac .. "]")
|
|
|
|
log:flush()
|
|
|
|
if val > total then
|
|
|
|
total = val
|
|
|
|
end
|
|
|
|
end
|
2023-03-30 12:36:31 -06:00
|
|
|
break
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
)
|
2023-04-02 02:29:46 -06:00
|
|
|
|
|
|
|
-- If we find unresponsive nodes too often then we leave and rejoin the network
|
|
|
|
-- to reset everything
|
|
|
|
if total >= unresponsive_max then
|
|
|
|
last = {}
|
|
|
|
rejoin_network()
|
|
|
|
end
|
2023-03-30 12:36:31 -06:00
|
|
|
end
|
|
|
|
|
|
|
|
return station_monitor
|