291 lines
11 KiB
Lua
Executable File
291 lines
11 KiB
Lua
Executable File
#!/usr/bin/lua
|
|
|
|
-- PID file to ensure the hoodselector isn't running parallel
|
|
local pidPath="/var/run/hoodselector.pid"
|
|
|
|
local uci = require('simple-uci').cursor()
|
|
local hoodutil = require("hoodselector.util")
|
|
local hash = require("hash")
|
|
|
|
if io.open(pidPath, "r") ~=nil then
|
|
hoodutil.log("The hoodselector is still running.")
|
|
os.exit(1)
|
|
else
|
|
if io.open(pidPath, "w") ==nil then
|
|
hoodutil.log("Can`t create pid file on "..pidPath)
|
|
os.exit(1)
|
|
end
|
|
end
|
|
|
|
-- Program terminating function including removing of PID file
|
|
local function exit(exc)
|
|
if io.open(pidPath, "r") ~=nil then
|
|
os.remove(pidPath)
|
|
end
|
|
os.exit(tonumber(exc))
|
|
end
|
|
|
|
-- initialization done
|
|
|
|
local function get_mesh_vpn_interface()
|
|
local ret = {}
|
|
if hoodutil.fastd_installed() then
|
|
local vpnifac = uci:get('fastd', 'mesh_vpn_backbone', 'net')
|
|
if vpnifac ~= nil then
|
|
vpnifac = vpnifac:gsub("%_",'-')
|
|
table.insert(ret,vpnifac)
|
|
else
|
|
hoodutil.log("fastd uci config broken! abort...")
|
|
exit(1)
|
|
end
|
|
end
|
|
if hoodutil.tunneldigger_installed() then
|
|
local vpnifac = uci:get('tunneldigger', 'mesh_vpn', 'interface')
|
|
if vpnifac ~= nil then
|
|
table.insert(ret,vpnifac)
|
|
else
|
|
hoodutil.log("tunneldigger uci config broken! abort...")
|
|
exit(1)
|
|
end
|
|
end
|
|
return ret
|
|
end
|
|
|
|
function table.val_to_str ( v )
|
|
if "string" == type( v ) then
|
|
v = string.gsub( v, "\n", "\\n" )
|
|
if string.match( string.gsub(v,"[^'\"]",""), '^"+$' ) then
|
|
return "'" .. v .. "'"
|
|
end
|
|
return '"' .. string.gsub(v,'"', '\\"' ) .. '"'
|
|
else
|
|
return "table" == type( v ) and table.tostring( v ) or tostring( v )
|
|
end
|
|
end
|
|
|
|
function table.key_to_str ( k )
|
|
if "string" == type( k ) and string.match( k, "^[_%a][_%a%d]*$" ) then
|
|
return k
|
|
else
|
|
return "[" .. table.val_to_str( k ) .. "]"
|
|
end
|
|
end
|
|
|
|
function table.tostring( tbl )
|
|
local result, done = {}, {}
|
|
for k, v in ipairs( tbl ) do
|
|
table.insert( result, table.val_to_str( v ) )
|
|
done[ k ] = true
|
|
end
|
|
for k, v in pairs( tbl ) do
|
|
if not done[ k ] then
|
|
table.insert( result, table.key_to_str( k ) .. "=" .. table.val_to_str( v ) )
|
|
end
|
|
end
|
|
return "{" .. table.concat( result, "," ) .. "}"
|
|
end
|
|
|
|
|
|
-- INITIALIZE AND PREPARE DATA --
|
|
-- read hoodfile...
|
|
local jhood = hoodutil.get_domains()
|
|
|
|
-- get defaul hood
|
|
local defaultHood = hoodutil.getDefaultHood(jhood)
|
|
|
|
-- VPN MODE
|
|
-- If we have a VPN connection then we will try to get the routers location and
|
|
-- select the hood coresponding to our location.
|
|
-- If no hood for the location has been defined, we will select
|
|
-- the default hood.
|
|
-- If we can not get our routers location, we will continure to next mode.
|
|
if hoodutil.directVPN(get_mesh_vpn_interface()) then
|
|
io.stdout:write('VPN connection found.\n')
|
|
local geo = hoodutil.getGeolocation()
|
|
if geo.lat ~= nil and geo.lon ~= nil then
|
|
io.stdout:write('Position found.\n')
|
|
local geoHood = hoodutil.getHoodByGeo(jhood, geo)
|
|
if geoHood ~= nil then
|
|
if hoodutil.set_hoodconfig(geoHood) then
|
|
hoodutil.restart_services() -- TMP solution
|
|
io.stdout:write('Hood set by VPN mode.\n')
|
|
end
|
|
exit(0)
|
|
end
|
|
io.stdout:write('No hood has been defined for current position.\n')
|
|
if hoodutil.set_hoodconfig(defaultHood) then
|
|
hoodutil.restart_services() -- TMP solution
|
|
io.stdout:write('Hood set by VPN mode.\n')
|
|
end
|
|
exit(0)
|
|
else
|
|
-- The hoodselector should continure with next states because thier can be other
|
|
-- VPN routers in the local mesh network which provides a possition and therfore
|
|
-- have set a geo base hood.
|
|
io.stdout:write('No position found\n')
|
|
end
|
|
else
|
|
io.stdout:write('No VPN connection found\n')
|
|
end
|
|
|
|
--[[
|
|
-- GATEWAY MODE
|
|
-- If a node have batman-adv GWs ensure config is validate to current hood.
|
|
-- Furthermore is a node is connected to a neigbour hood check if its geo base hood avalable.
|
|
local gw_intf = hoodutil.get_batman_GW_interface()
|
|
if gw_intf ~= nil then
|
|
io.stdout:write('Batman gateways found\n')
|
|
-- We have to verify if the currend applyed setting
|
|
-- return currend applyed hood if source gw_intf a wifi interface
|
|
-- we have to check the hood explecit bw wifi source besause the
|
|
-- scan mode can apply an unknown hood by adapting the mesh id or
|
|
-- bssid with deaktivated VPNs(in case if a router will get a VPN
|
|
-- connection afterwards).
|
|
local currentHood = hoodutil.getHoodByRadio(gw_intf, jhood)
|
|
if currentHood ~= nil then
|
|
print("DEBUG: currentHood ~= nil")
|
|
-- Now we need check if the current seclected hood our geo base hood, otherwise search for
|
|
-- our geo base hood in the local network ENV
|
|
--check if hood inside geo pos
|
|
local geo = hoodutil.getGeolocation()
|
|
if geo.lat ~= nil and geo.lon ~= nil then
|
|
io.stdout:write('Position found.\n')
|
|
local geoHood = hoodutil.getHoodByGeo(jhood, geo)
|
|
if geoHood ~= nil then
|
|
print("DEBUG: geoHood ~= nil")
|
|
if string.format(hash.md5(table.tostring(currentHood))) ~=
|
|
string.format(hash.md5(table.tostring(geoHood))) then
|
|
io.stdout:write('Geo hood and current applyed hood are not equal, do wifi scan...\n')
|
|
local sortedWlanList = hoodutil.wlan_list_sorted()
|
|
for i=#sortedWlanList,1,-1 do
|
|
-- Filter all wifis whicht does not match the geo base hood
|
|
-- if h.domain.wifi24 ~= nil then
|
|
-- if h.domain.wifi24.ibss ~= nil then
|
|
print("foo")
|
|
-- end
|
|
-- end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
454 if geoHood ~= nil then
|
|
455 if string.format(hash.md5(table.tostring(bssidHood))) ~=
|
|
string.format(hash.md5(table.tostring(geoHood))) then
|
|
456 io.stdout:write('Geo hood and bssid hood are not equal, do wifi scan...\n')
|
|
457 local sortedWlanList = hoodutil.wlan_list_sorted(radios, mesh_prefix)
|
|
458 for i=#sortedWlanList,1,-1 do
|
|
459 if(string.lower(geoHood.bssid) ~= string.lower(sortedWlanList[i].bssid)) then
|
|
460 table.remove(sortedWlanList, i)
|
|
461 end
|
|
462 end
|
|
463 if next(sortedWlanList) then
|
|
464 io.stdout:write('Try to switch back in our real hood!\n')
|
|
465 io.stdout:write('After filtering we will test the following wireless networks:\n')
|
|
466 for _, network in pairs(sortedWlanList) do
|
|
467 print(network["quality"].."\t"..network["frequency"].."\t"..network["bssid"].."\t"..network["ssid"])
|
|
468 end
|
|
469 io.stdout:write("Prepare configuration for testing wireless networks...\n")
|
|
470 local bssid = hoodutil.test_batman_mesh_networks(sortedWlanList, mesh_prefix)
|
|
471 hoodutil.wireless_restart()
|
|
472 io.stdout:write("Finished testing wireless networks, restored previous configuration\n")
|
|
473 if bssid ~= nil then
|
|
474 set_hoodconfig(geoHood, mesh_prefix, radios)
|
|
475 hoodutil.vpn_enable()
|
|
476 hoodutil.vpn_start()
|
|
477 io.stdout:write('Set Geo Hood by Gateway mode\n')
|
|
478 write_molwm(geoHood, radios)
|
|
479 exit(0)
|
|
480 else
|
|
481 io.stdout:write('No neighboring freifunk batman advanced mesh found.\n')
|
|
482 end
|
|
483 else
|
|
484 io.stdout:write('No networks left after filtering!\n')
|
|
485 end --end next(sortedWlanList)
|
|
486 else
|
|
487 io.stdout:write('Geo hood are equal to bssid hood no wifi scan necessary.\n')
|
|
488 end --end bssidHood ~= geoHood
|
|
489 else
|
|
490 io.stdout:write('No hood has been defined for current position.\n')
|
|
491 end --end geoHood ~= nil
|
|
492 else
|
|
493 io.stdout:write('No position found.\n')
|
|
494 end --end geo.lat ~= nil and geo.lon ~= nil
|
|
495 set_hoodconfig(bssidHood, mesh_prefix, radios)
|
|
496 io.stdout:write('Hood set by batmanHasGateway mode, GW source is wifi\n')
|
|
497 write_molwm(bssidHood,radios)
|
|
498 exit(0)
|
|
499 end --end bssidHood ~= nil
|
|
500
|
|
501 -- mesh lan or wan interface
|
|
502 if hoodutil.mesh_lan_wan(gw_intf[1]) then
|
|
503 -- if mesh_lan/wan try to get hood by selected bssid of neightbour vpnRouters
|
|
504 local neighbourBssid = hoodutil.molw_get_bssid(gw_intf)
|
|
505 if neighbourBssid ~= nil then
|
|
506 bssidHood = hoodutil.gethoodByBssid(jhood, neighbourBssid)
|
|
507 if bssidHood ~= nil then
|
|
508 set_hoodconfig(bssidHood, mesh_prefix, radios)
|
|
509 io.stdout:write('Hood set by batmanHasGateway mode, GW source is mesh on lan/wan\n')
|
|
510 molwmtable["md5hash"] = "\"" .. string.format(hash.md5(table.tostring(bssidHood))) .. "\""
|
|
511 molwmtable["hoodname"] = "\"" .. bssidHood["name"] .. "\""
|
|
512 molwmtable["bssid"] = "\"" .. bssidHood["bssid"] .. "\""
|
|
513 molwm_to_file()
|
|
514 exit(0)
|
|
515 end
|
|
516 end
|
|
517 end]]
|
|
--end -- end gw_intf
|
|
|
|
-- SCAN MODE
|
|
if next(hoodutil.getWifiDevices()) then
|
|
print("Entering SCAN MODE ...")
|
|
-- check if there exist a neighbouring freifunk batman advanced mesh
|
|
-- network with an active connection to a batman advanced gateway
|
|
local sortedWlanList = hoodutil.wlan_list_sorted()
|
|
if next(sortedWlanList) then
|
|
local ID = hoodutil.get_batman_mesh_network(sortedWlanList, defaultHood)
|
|
if ID ~= nil then
|
|
local scanHood = nil
|
|
if ID.method == "ibss" then
|
|
io.stdout:write("Neighoring freifunk batman advanced mesh with Bssid: "..ID.bssid.." found\n")
|
|
scanHood = hoodutil.gethoodByBssid(jhood, ID.bssid)
|
|
end
|
|
if ID.method == "11s" then
|
|
io.stdout:write("Neighoring freifunk batman advanced mesh with meshid: "..ID.meshid.." found\n")
|
|
scanHood = hoodutil.gethoodByMeshID(jhood, ID.meshid)
|
|
end
|
|
if scanHood ~= nil then
|
|
if hoodutil.set_hoodconfig(scanHood) then
|
|
hoodutil.restart_services() -- TMP solution
|
|
io.stdout:write('Hood set by scan mode\n')
|
|
end
|
|
exit(0)
|
|
end
|
|
|
|
-- if the wifi ID does not corespond to any hood, we disable all VPN and
|
|
-- just establish a wireless connection to the coresponding mesh. Furthermore
|
|
-- we set a unknown VXLAN ID to signalisize neibouring mesh on LAN/WAN nodes
|
|
-- that we have a gateway conection but does not know to which hood it is coresponding.
|
|
io.stdout:write("No hood has been found for this mesh ID\n")
|
|
--hoodutil.vpn_stop()
|
|
--hoodutil.vpn_disable()
|
|
--TBD
|
|
-- some idea was to collect neigbouhood informations like VXLAN ID over respondd
|
|
end
|
|
end
|
|
end
|
|
|
|
--Radio less mode
|
|
-- TBD
|
|
|
|
-- DEFAULT-HOOD MODE
|
|
-- If we do NOT have a VPN connection and no other freifunk mesh nodes found in our network ENV
|
|
-- then we set the default hood.
|
|
io.stdout:write("ENV does not give enough information\n")
|
|
if hoodutil.set_hoodconfig(defaultHood) then
|
|
hoodutil.restart_services() -- TMP solution
|
|
io.stdout:write('Hood set by default-hood mode.\n')
|
|
end
|
|
exit(0)
|