Merge 7e6b0fda73
into c0b4fb54a4
This commit is contained in:
commit
f555f59c0c
38
package/ffnw-hoods/Makefile
Normal file
38
package/ffnw-hoods/Makefile
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
include $(TOPDIR)/rules.mk
|
||||||
|
|
||||||
|
PKG_NAME:=ffnw-hoods
|
||||||
|
PKG_VERSION:=1
|
||||||
|
PKG_RELEASE:=1
|
||||||
|
|
||||||
|
PKG_BUILD_DEPENDS := luci-base/host lua-cjson/host
|
||||||
|
|
||||||
|
PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)
|
||||||
|
|
||||||
|
include $(GLUONDIR)/include/package.mk
|
||||||
|
|
||||||
|
define Package/ffnw-hoods
|
||||||
|
SECTION:=networke
|
||||||
|
CATEGORY:=Freifunk Nordwest
|
||||||
|
TITLE:=Hoodjson file
|
||||||
|
endef
|
||||||
|
|
||||||
|
define Package/ffnw-hoods/description
|
||||||
|
Hoodjson file for defined hoods
|
||||||
|
endef
|
||||||
|
|
||||||
|
define Build/Prepare
|
||||||
|
mkdir -p $(PKG_BUILD_DIR)
|
||||||
|
endef
|
||||||
|
|
||||||
|
define Build/Configure
|
||||||
|
endef
|
||||||
|
|
||||||
|
define Build/Compile
|
||||||
|
endef
|
||||||
|
|
||||||
|
define Package/ffnw-hoods/install
|
||||||
|
$(INSTALL_DIR) $(1)/lib/ffnw/hoods
|
||||||
|
lua -e 'local cjson = require("cjson"); print(cjson.encode(cjson.decode(assert(io.open("./files/lib/ffnw/hoods/hoods.json"):read("*a")))))' > $(1)/lib/ffnw/hoods/hoods.json
|
||||||
|
endef
|
||||||
|
|
||||||
|
$(eval $(call BuildPackage,ffnw-hoods))
|
64
package/ffnw-hoods/files/lib/ffnw/hoods/hoods.json
Normal file
64
package/ffnw-hoods/files/lib/ffnw/hoods/hoods.json
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"name": "default",
|
||||||
|
"bssid": "02:CA:FF:AA:BA:BF",
|
||||||
|
"defaulthood": true,
|
||||||
|
"servers": [
|
||||||
|
{
|
||||||
|
"host": "default02.entenhausen.de",
|
||||||
|
"port": "11111",
|
||||||
|
"publickey": "32a02dd5e6b9454734tt3r3ad30bcf269564546ewtrew5442533tgr258cb"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"host": "default03.entenhausen.de",
|
||||||
|
"port": "11111",
|
||||||
|
"publickey": "973732543523frea17cfa53d2b9e025202trwrtefacf9503737tf5a23204"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"host": "default04.entenhausen.de",
|
||||||
|
"port": "11111",
|
||||||
|
"publickey": "432534t2ewe9a10620d09402ca2frewfwdf364e6fwqfer4re669a2eb5e6f"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"host": "default05.entenhausen.de",
|
||||||
|
"port": "11111",
|
||||||
|
"publickey": "34rfewf4754tg3f54538236bae815ef2r4245f20c63aeregt452b183045d"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"host": "default06.entenhausen.de",
|
||||||
|
"port": "11111",
|
||||||
|
"publickey": "2245t42gvre0ff93a0rewferewfrewb00dd215arefewf4355e5eb16f0b69"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"boxes": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "quackenbruek",
|
||||||
|
"bssid": "02:AA:0A:12:80:43",
|
||||||
|
"defaulthood": false,
|
||||||
|
"servers": [
|
||||||
|
{
|
||||||
|
"host": "quackenbruek01.sn.entenhausen.de",
|
||||||
|
"port": "10000",
|
||||||
|
"publickey": "c6485dsaqdwe33dbebdbweqrfqca4aewfc3453453224532434fr4f3d629d"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"host": "quackenbruek02.sn.entenhausen.de",
|
||||||
|
"port": "10001",
|
||||||
|
"publickey": "887c6c4e1ff435t4t42gt4aac03cd9494bd13d1221ea6cewqdq3431r4194"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"boxes": [
|
||||||
|
[
|
||||||
|
[
|
||||||
|
52.18,
|
||||||
|
7.41
|
||||||
|
],
|
||||||
|
[
|
||||||
|
52.35,
|
||||||
|
7.9
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
45
package/ffnw-hoodselector/Makefile
Normal file
45
package/ffnw-hoodselector/Makefile
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
include $(TOPDIR)/rules.mk
|
||||||
|
|
||||||
|
PKG_NAME:=ffnw-hoodselector
|
||||||
|
PKG_VERSION:=1
|
||||||
|
PKG_RELEASE:=1
|
||||||
|
|
||||||
|
PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)
|
||||||
|
PKG_BUILD_DEPENDS := lua/host luci-base/host respondd
|
||||||
|
|
||||||
|
include $(GLUONDIR)/include/package.mk
|
||||||
|
|
||||||
|
|
||||||
|
define Package/ffnw-hoodselector
|
||||||
|
SECTION:=networke
|
||||||
|
CATEGORY:=Freifunk Nordwest
|
||||||
|
TITLE:=Select the hoods depending on the geo coordinate
|
||||||
|
DEPENDS:=+ffnw-hoods +luci-lib-jsonc gluon-mesh-batman-adv-15 +gluon-mesh-vpn-fastd +respondd
|
||||||
|
endef
|
||||||
|
|
||||||
|
define Package/ffnw-hoodselector/description
|
||||||
|
Select the hoods depending on the geo coordinates
|
||||||
|
endef
|
||||||
|
|
||||||
|
define Build/Prepare
|
||||||
|
mkdir -p $(PKG_BUILD_DIR)
|
||||||
|
$(CP) ./src/* $(PKG_BUILD_DIR)/
|
||||||
|
endef
|
||||||
|
|
||||||
|
define Build/Configure
|
||||||
|
endef
|
||||||
|
|
||||||
|
define Build/Compile
|
||||||
|
$(call Build/Compile/Default)
|
||||||
|
$(call GluonSrcDiet,./luasrc,$(PKG_BUILD_DIR)/luadest/)
|
||||||
|
endef
|
||||||
|
|
||||||
|
define Package/ffnw-hoodselector/install
|
||||||
|
$(CP) ./files/* $(1)/
|
||||||
|
$(INSTALL_DIR) $(1)/usr/sbin
|
||||||
|
$(CP) $(PKG_BUILD_DIR)/luadest/hoodselector $(1)/usr/sbin/hoodselector
|
||||||
|
$(INSTALL_DIR) $(1)/lib/gluon/respondd
|
||||||
|
$(CP) $(PKG_BUILD_DIR)/respondd.so $(1)/lib/gluon/respondd/hoodselector.so
|
||||||
|
endef
|
||||||
|
|
||||||
|
$(eval $(call BuildPackage,ffnw-hoodselector))
|
@ -0,0 +1 @@
|
|||||||
|
*/2 * * * * /usr/sbin/hoodselector
|
722
package/ffnw-hoodselector/luasrc/hoodselector
Executable file
722
package/ffnw-hoodselector/luasrc/hoodselector
Executable file
@ -0,0 +1,722 @@
|
|||||||
|
#!/usr/bin/lua
|
||||||
|
|
||||||
|
-- This is the hoodselector. The hoodselector is one of the main components for
|
||||||
|
-- splitting a layer 2 mesh network into seperated network segments (hoods).
|
||||||
|
-- The job of the hoodselector is to automatically detect in which hood
|
||||||
|
-- the router is located based on geo settings or by scanning its environment.
|
||||||
|
-- Based on these informations the hoodselector should select a hood from a
|
||||||
|
-- list of known hoods (hoodlist) and adjust vpn, wireless and mesh on lan
|
||||||
|
-- configuration based on the settings given for the selected hood.
|
||||||
|
--
|
||||||
|
-- The hoodlist containing all hood settings is located in a seperate hoodfile
|
||||||
|
-- in the hoods package.
|
||||||
|
--
|
||||||
|
-- The hoodselector depends on the folowing additional software:
|
||||||
|
-- * fastd (vpn configuration) see getCurrentPeers(), setHoodVPN()
|
||||||
|
-- * iw (wireless network scanning) see getNeigbourBssid()
|
||||||
|
-- * batman-adv (mesh protocol) see directVPN(), getGwRange()
|
||||||
|
-- * respondd (molwm) see molwm()
|
||||||
|
--
|
||||||
|
-- To detect the current hood the hoodselector knows 2 modes containing
|
||||||
|
-- * 1. Default mode (VPN Router)
|
||||||
|
-- - set real hood dependent on geo position.
|
||||||
|
-- - set default hood dependent on geo position.
|
||||||
|
-- * 2. Scan modes
|
||||||
|
-- - Set wifi conf on scanned BSSID
|
||||||
|
-- - Set vpn conf getting by BSSID (if no VPN conf exsist disable fastd)
|
||||||
|
-- When selecting a hood, the hoodselector has the following priorities:
|
||||||
|
-- 1. Selecting a hood by geo position depending on direct VPN connection.
|
||||||
|
-- 2. force creating one mesh cloud with neigbour mesh routers
|
||||||
|
-- 3. if routers had only mesh setting vpn config depends on the BSSID
|
||||||
|
--
|
||||||
|
-- Resources
|
||||||
|
-- * https://wireless.wiki.kernel.org/en/users/documentation/iw
|
||||||
|
|
||||||
|
-- MOLWM respondd file
|
||||||
|
local molwmFile="/tmp/.hoodselector"
|
||||||
|
|
||||||
|
local molwmtable = {}
|
||||||
|
molwmtable["md5hash"] = ""
|
||||||
|
molwmtable["vpnrouter"] = ""
|
||||||
|
molwmtable["hoodname"] = ""
|
||||||
|
|
||||||
|
-- PID file to ensure the hoodselector isn't running parallel
|
||||||
|
local pidPath="/var/run/hoodselector.pid"
|
||||||
|
|
||||||
|
if io.open(pidPath, "r") ~=nil then
|
||||||
|
io.stderr:write("The hoodselector is still running.\n")
|
||||||
|
os.exit(1)
|
||||||
|
else
|
||||||
|
io.close(io.open(pidPath, "w"))
|
||||||
|
end
|
||||||
|
|
||||||
|
local json = require ("luci.jsonc")
|
||||||
|
local uci = require('luci.model.uci').cursor()
|
||||||
|
local file = '/lib/ffnw/hoods/hoods.json'
|
||||||
|
-- initialization done
|
||||||
|
|
||||||
|
-- Read the full hoodfile. Return nil for wrong format or no such file
|
||||||
|
local function readHoodfile(file)
|
||||||
|
local jhood = io.open(file, 'r')
|
||||||
|
if not jhood then return nil end
|
||||||
|
local obj, pos, err = json.parse (jhood:read('*a'), 1, nil)
|
||||||
|
if err then
|
||||||
|
return nil
|
||||||
|
else
|
||||||
|
return obj
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function mesh_on_wan_disable()
|
||||||
|
os.execute('ifdown mesh_wan')
|
||||||
|
io.stderr:write('Interface mesh_wan disabled.\n')
|
||||||
|
end
|
||||||
|
|
||||||
|
local function mesh_on_wan_enable()
|
||||||
|
os.execute('ifup mesh_wan')
|
||||||
|
io.stderr:write('Interface mesh_wan enabled.\n')
|
||||||
|
end
|
||||||
|
|
||||||
|
local function mesh_on_lan_disable()
|
||||||
|
os.execute('ifdown mesh_lan')
|
||||||
|
io.stderr:write('Interface mesh_lan disabled.\n')
|
||||||
|
end
|
||||||
|
|
||||||
|
local function mesh_on_lan_enable()
|
||||||
|
os.execute('ifup mesh_lan')
|
||||||
|
io.stderr:write('Interface mesh_lan enabled.\n')
|
||||||
|
end
|
||||||
|
|
||||||
|
local function molwm()
|
||||||
|
local mesh_en = true
|
||||||
|
local respondd = string.format("gluon-neighbour-info -i bat0 -p 1001 -d ff02::2 -r hoodselector -t 0.5")
|
||||||
|
for line in io.popen(respondd, 'r'):lines() do
|
||||||
|
local obj, pos, err = json.parse (line, 1, nil)
|
||||||
|
if err then
|
||||||
|
io.stderr:write("json parse error!\n")
|
||||||
|
mesh_en = false
|
||||||
|
break
|
||||||
|
else
|
||||||
|
if obj["hoodinfo"] ~= nil then
|
||||||
|
if not ( obj["hoodinfo"]["md5hash"] == molwmtable["md5hash"]:gsub('\"', '') ) then
|
||||||
|
io.stderr:write("hashes are not equals!\n")
|
||||||
|
mesh_en = false
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if uci:get('network', 'mesh_wan') and not mesh_en then
|
||||||
|
mesh_on_wan_disable()
|
||||||
|
end
|
||||||
|
if uci:get('network', 'mesh_lan') and not mesh_en then
|
||||||
|
mesh_on_lan_disable()
|
||||||
|
end
|
||||||
|
if uci:get('network', 'mesh_wan') and mesh_en then
|
||||||
|
mesh_on_wan_enable()
|
||||||
|
end
|
||||||
|
if uci:get('network', 'mesh_lan') and mesh_en then
|
||||||
|
mesh_on_lan_enable()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Create md5 hash from currend hood
|
||||||
|
local function molwm_md5hash(hood)
|
||||||
|
local file = io.open("/tmp/.hoodhash", "w")
|
||||||
|
if not file then
|
||||||
|
io.stderr:write('\"/tmp/.hoodhash\" can not created\n')
|
||||||
|
else
|
||||||
|
file:write(json.stringify(hood, { indent = true }))
|
||||||
|
file:close()
|
||||||
|
--part to create md5 hash of this file
|
||||||
|
for line in io.popen(string.format( "md5sum /tmp/.hoodhash")):lines() do
|
||||||
|
for i in string.gmatch(line, "%S+") do
|
||||||
|
if (string.len(i) == 32) then
|
||||||
|
molwmtable["md5hash"] = "\"" .. string.format(i) .. "\""
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
os.remove("/tmp/.hoodhash")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Write MOLWM content into file
|
||||||
|
local function write_molwm(hood)
|
||||||
|
if hood ~= nil then
|
||||||
|
molwm_md5hash(hood)
|
||||||
|
molwmtable["hoodname"] = "\"" .. hood["name"] .. "\""
|
||||||
|
end
|
||||||
|
molwm()
|
||||||
|
local file = io.open(molwmFile, "w")
|
||||||
|
if not file then
|
||||||
|
io.stderr:write(molwmFile ..' not found or not createble!\n')
|
||||||
|
else
|
||||||
|
file:write("\"md5hash\": " .. molwmtable["md5hash"] .. "\n")
|
||||||
|
file:write("\"vpnrouter\": " .. molwmtable["vpnrouter"] .. "\n")
|
||||||
|
file:write("\"hoodname\": " .. molwmtable["hoodname"] .. "\n")
|
||||||
|
file:close()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Program terminating function including removing of PID file
|
||||||
|
local function exit()
|
||||||
|
if io.open(pidPath, "r") ~=nil then
|
||||||
|
os.remove(pidPath)
|
||||||
|
end
|
||||||
|
os.exit(0)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function trim(s)
|
||||||
|
-- from PiL2 20.4
|
||||||
|
return (s:gsub("^%s*(.-)%s*$", "%1"))
|
||||||
|
end
|
||||||
|
|
||||||
|
local function sleep(n)
|
||||||
|
os.execute("sleep " .. tonumber(n))
|
||||||
|
end
|
||||||
|
|
||||||
|
local function brclient_restart()
|
||||||
|
os.execute('ifconfig br-client down')
|
||||||
|
os.execute('ifconfig br-client up')
|
||||||
|
io.stderr:write('Interface br-client restarted.\n')
|
||||||
|
end
|
||||||
|
|
||||||
|
local function vpn_stop()
|
||||||
|
os.execute('/etc/init.d/fastd stop')
|
||||||
|
io.stderr:write('VPN stopped.\n')
|
||||||
|
end
|
||||||
|
|
||||||
|
local function vpn_start()
|
||||||
|
os.execute('/etc/init.d/fastd start')
|
||||||
|
io.stderr:write('VPN started.\n')
|
||||||
|
brclient_restart()
|
||||||
|
end
|
||||||
|
|
||||||
|
local function vpn_disable()
|
||||||
|
-- disable VPN if not already disabled
|
||||||
|
os.execute('/etc/init.d/fastd disable')
|
||||||
|
io.stderr:write('VPN disabled.\n')
|
||||||
|
end
|
||||||
|
|
||||||
|
local function vpn_enable()
|
||||||
|
-- enable VPN if not already enabled
|
||||||
|
os.execute('/etc/init.d/fastd enable')
|
||||||
|
io.stderr:write('VPN enable.\n')
|
||||||
|
end
|
||||||
|
|
||||||
|
local function wireless_restart()
|
||||||
|
os.execute('wifi')
|
||||||
|
io.stderr:write('Wireless restarted.\n')
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Get a list of wifi devices return an emty table for no divices
|
||||||
|
local function getWifiDevices()
|
||||||
|
local radios = {}
|
||||||
|
uci:foreach('wireless', 'wifi-device',
|
||||||
|
function(s)
|
||||||
|
table.insert(radios, s['.name'])
|
||||||
|
end
|
||||||
|
)
|
||||||
|
return radios
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Scans for wireless networks and returns a two dimensional array containing
|
||||||
|
-- wireless mesh neigbour networks and their properties.
|
||||||
|
-- The array is sorted descending by signal strength (strongest signal
|
||||||
|
-- first, usually the local signal of the wireless chip of the router)
|
||||||
|
local function wlan_list_sorted(radios)
|
||||||
|
local networks = {}
|
||||||
|
for index, radio in ipairs(radios) do
|
||||||
|
local ifname = uci:get('wireless', 'ibss_' .. radio, 'ifname')
|
||||||
|
local ssid = uci:get('wireless', 'ibss_' .. radio, 'ssid')
|
||||||
|
if (ifname ~= nil and ssid ~= nil) then
|
||||||
|
local wireless_scan = string.format( "iw %s scan", ifname)
|
||||||
|
local row = {}
|
||||||
|
row["radio"] = radio
|
||||||
|
-- loop through each line in the output of iw
|
||||||
|
for wifiscan in io.popen(wireless_scan, 'r'):lines() do
|
||||||
|
-- the following line matches a new network in the output of iw
|
||||||
|
if wifiscan:match("BSS (%w+:%w+:%w+:%w+:%w+:%w+)") then
|
||||||
|
if(row["bssid"] ~= nil and row["quality"] ~= nil
|
||||||
|
and row["ssid"] == ssid) then
|
||||||
|
table.insert(networks, row)
|
||||||
|
row = {}
|
||||||
|
row["radio"] = radio
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- get ssid
|
||||||
|
if wifiscan:match("SSID:") then
|
||||||
|
row["ssid"] = wifiscan:split(":")
|
||||||
|
row["ssid"] = row["ssid"][2]
|
||||||
|
if(row["ssid"] ~= nil) then
|
||||||
|
row["ssid"] = trim(row["ssid"])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- get frequency
|
||||||
|
if wifiscan:match("freq:") then
|
||||||
|
row["frequency"] = wifiscan:split(":")
|
||||||
|
row["frequency"] = row["frequency"][2]
|
||||||
|
if(row["frequency"] ~= nil) then
|
||||||
|
row["frequency"] = trim(row["frequency"])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- get bssid
|
||||||
|
if wifiscan:match("(%w+:%w+:%w+:%w+:%w+:%w+)") then
|
||||||
|
row["bssid"] = wifiscan:match("(%w+:%w+:%w+:%w+:%w+:%w+)"):upper()
|
||||||
|
end
|
||||||
|
|
||||||
|
-- get signal strength
|
||||||
|
if wifiscan:match("signal:") then
|
||||||
|
row["quality"] = wifiscan:split(" ")
|
||||||
|
row["quality"] = row["quality"][2]:split(".")
|
||||||
|
if row["quality"][1]:match("-") then
|
||||||
|
row["quality"] = row["quality"][1]:split("-")
|
||||||
|
end
|
||||||
|
row["quality"] = tonumber(row["quality"][2]:match("(%d%d)"))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
io.stderr:write("wireless uci config broken! abort...\n")
|
||||||
|
exit();
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
table.sort(networks, function(a,b) return a["quality"] < b["quality"] end)
|
||||||
|
return networks
|
||||||
|
end
|
||||||
|
|
||||||
|
-- this method removes the wireless network of the router itself
|
||||||
|
-- from the wlan_list
|
||||||
|
local function filter_my_wlan_network(wlan_list)
|
||||||
|
local filtered_wlan_list = {}
|
||||||
|
|
||||||
|
for n,wlan in pairs(wlan_list) do
|
||||||
|
if(wlan.quality ~= 0) then
|
||||||
|
table.insert(filtered_wlan_list, wlan)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return filtered_wlan_list
|
||||||
|
end
|
||||||
|
|
||||||
|
local function filter_default_hood_wlan_networks(default_hood, wlan_list)
|
||||||
|
local filtered_wlan_list = {}
|
||||||
|
|
||||||
|
for n,wlan in pairs(wlan_list) do
|
||||||
|
if(default_hood.bssid ~= wlan.bssid) then
|
||||||
|
table.insert(filtered_wlan_list, wlan)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return filtered_wlan_list
|
||||||
|
end
|
||||||
|
|
||||||
|
-- bool if direct VPN. The detection is realaise by searching the fastd network interface inside the originator table
|
||||||
|
local function directVPN()
|
||||||
|
-- escape special chars "[]-"
|
||||||
|
for outgoingIF in io.open("/sys/kernel/debug/batman_adv/bat0/originators", 'r'):lines() do
|
||||||
|
local vpnIface = uci:get('fastd', 'mesh_vpn_backbone', 'net')
|
||||||
|
if not vpnIface then
|
||||||
|
io.stderr:write("fastd uci config broken! abort...\n")
|
||||||
|
exit()
|
||||||
|
end
|
||||||
|
if outgoingIF:match(string.gsub("%[ " .. vpnIface .. "%]","%_",'-'):gsub("%-", "%%-")) then
|
||||||
|
molwmtable["vpnrouter"] = "\"true\""
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
molwmtable["vpnrouter"] = "\"false\""
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Retun a table of current peers from /etc/config/fastd
|
||||||
|
local function getCurrentPeers()
|
||||||
|
local configPeers = {}
|
||||||
|
local err = uci:foreach('fastd', 'peer',
|
||||||
|
function(s)
|
||||||
|
if s['.name'] then
|
||||||
|
for prefix,peer in pairs(s) do
|
||||||
|
local tmpPeer = {}
|
||||||
|
if prefix:match(".name") then
|
||||||
|
if peer:match("mesh_vpn_backbone_peer_") then
|
||||||
|
-- val tmpRemote does not need uci exception check because its already include by "uci:foreach"
|
||||||
|
local tmpRemote = uci:get('fastd', peer, 'remote')
|
||||||
|
tmpRemote = tmpRemote[1]:split(" ")
|
||||||
|
local remote = {}
|
||||||
|
remote['host'] = tmpRemote[1]
|
||||||
|
remote[tmpRemote[2]] = tmpRemote[3]
|
||||||
|
-- uci:get does not need uci exception check because its already include by "uci:foreach"
|
||||||
|
tmpPeer['key'] = tostring(uci:get('fastd', peer, 'key'))
|
||||||
|
tmpPeer['remote'] = remote
|
||||||
|
configPeers[peer] = tmpPeer
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
)
|
||||||
|
if not err then
|
||||||
|
io.stderr:write("fastd uci config broken! abort...\n")
|
||||||
|
exit()
|
||||||
|
end
|
||||||
|
return configPeers
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
-- Get Geoposition. Return nil for no position
|
||||||
|
local function getGeolocation()
|
||||||
|
local ret = {}
|
||||||
|
table.insert(ret, tonumber(uci:get('gluon-node-info', uci:get_first('gluon-node-info', 'location'), 'latitude')))
|
||||||
|
table.insert(ret, tonumber(uci:get('gluon-node-info', uci:get_first('gluon-node-info', 'location'), 'longitude')))
|
||||||
|
return ret
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Return hood from the hood file based on geo position or nil, no real hood could be determined
|
||||||
|
local function getHoodByGeo(jhood,geo)
|
||||||
|
for n, h in pairs(jhood) do
|
||||||
|
for n, box in pairs(h.boxes) do
|
||||||
|
if ( geo[1] >= box[1][1] and geo[1] < box[2][1] and geo[2] >= box[1][2] and geo[2] < box[2][2] ) then
|
||||||
|
return h
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
-- This method checks if the VPN configuration needs to be rewritten from the
|
||||||
|
-- hoodfile. Therefore the method performs 3 checks and returns false if all
|
||||||
|
-- checks fail. If one of the checks results to true the method returns true:
|
||||||
|
-- 1. Check if the local VPN configuratin has a server that does not exist
|
||||||
|
-- in the hoodfile.
|
||||||
|
-- 2. Check if a server that does exist in the local VPN configuration AND
|
||||||
|
-- in the hoodfile has a configuration change.
|
||||||
|
-- 3. Check if the hoodfile contains a server that does not exist in the
|
||||||
|
-- local VPN configuration.
|
||||||
|
local function vpn_reconfiguration_needed(hood_serverlist,local_serverlist)
|
||||||
|
-- Checks 1. and 2.
|
||||||
|
for local_server_config_name, local_server in pairs(local_serverlist) do
|
||||||
|
local local_server_exists_in_hoodfile = false
|
||||||
|
for hood_server_index,hood_server in pairs(hood_serverlist) do
|
||||||
|
if (local_server_config_name == 'mesh_vpn_backbone_peer_'.. hood_server["host"]:split('.')[1]:gsub("%-", "%_")) then
|
||||||
|
local_server_exists_in_hoodfile = true
|
||||||
|
if ( local_server.key ~= hood_server['publickey'] ) then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
if ( local_server.remote.host ~= '\"'..hood_server["host"]..'\"' ) then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
if ( local_server.remote.port ~= hood_server['port'] ) then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if not(local_server_exists_in_hoodfile) then return true end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Check 3.
|
||||||
|
for hood_server_index,hood_server in pairs(hood_serverlist) do
|
||||||
|
local hood_server_exists_locally = false
|
||||||
|
for local_server_config_name, local_server in pairs(local_serverlist) do
|
||||||
|
if (local_server_config_name == 'mesh_vpn_backbone_peer_'.. hood_server["host"]:split('.')[1]:gsub("%-", "%_")) then
|
||||||
|
hood_server_exists_locally = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if not(hood_server_exists_locally) then return true end
|
||||||
|
end
|
||||||
|
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Reconfigure fastd
|
||||||
|
local function vpn_reconfigure(hood_serverlist,local_serverlist)
|
||||||
|
-- remove all servers
|
||||||
|
for config_index, local_server in pairs(local_serverlist) do
|
||||||
|
uci:delete('fastd',config_index)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- add servers from hoodfile
|
||||||
|
local group = 'mesh_vpn_backbone'
|
||||||
|
for i,hood_server in pairs(hood_serverlist) do
|
||||||
|
uci:section('fastd', 'peer', group .. '_peer_' .. hood_server.host:split('.')[1]:gsub("%-", "%_"),
|
||||||
|
{
|
||||||
|
enabled = 1,
|
||||||
|
net = 'mesh_vpn',
|
||||||
|
group = group,
|
||||||
|
key = hood_server.publickey,
|
||||||
|
remote = {'\"'..hood_server.host..'\"'..' port '..hood_server.port}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
uci:save('fastd')
|
||||||
|
uci:commit('fastd')
|
||||||
|
io.stderr:write('Fastd needed reconfiguration. Stopped and applied new settings.\n')
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Checks if wireless needs a reconfiguration. Returns true if any of the checks
|
||||||
|
-- passes. Otherwise the method returns false.
|
||||||
|
local function wireless_reconfiguration_needed(radios, hood_bssid)
|
||||||
|
for index, radio in ipairs(radios) do
|
||||||
|
if ( uci:get('wireless', 'ibss_' .. radio, 'bssid') ~= hood_bssid ) then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Reconfigure wireless
|
||||||
|
local function wireless_reconfigure(radios, hood_bssid)
|
||||||
|
for index, radio in ipairs(radios) do
|
||||||
|
if not ( uci:get('wireless', 'ibss_' .. radio, 'bssid') == hood_bssid ) then
|
||||||
|
uci:section('wireless', 'wifi-iface', 'ibss_' .. radio, {
|
||||||
|
bssid = hood_bssid
|
||||||
|
})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
uci:save('wireless')
|
||||||
|
uci:commit('wireless')
|
||||||
|
end
|
||||||
|
|
||||||
|
-- This method sets a new hoodconfig and takes care that services are only
|
||||||
|
-- stopped or restarted if reconfiguration is needed.
|
||||||
|
-- Process:
|
||||||
|
-- * Check if wireless needs reconfiguration and prepare reconfiguration
|
||||||
|
-- * Check if fastd needs reconfiguration and prepare reconfiguration
|
||||||
|
-- * If fastd needs reconfiguration, stop fastd and apply new settings but
|
||||||
|
-- dont restart it before wireless has been reconfigured
|
||||||
|
-- * If wireless needs reconfiguration apply new settings and restart wireless
|
||||||
|
-- * If fastd needed reconfiguration start fastd now
|
||||||
|
local function set_hoodconfig(hood, radios)
|
||||||
|
local local_serverlist = getCurrentPeers()
|
||||||
|
-- Check if VPN needs reconfiguration because in case of reconfiguration we
|
||||||
|
-- need to stop VPN before we can reconfigure any other connection.
|
||||||
|
local vpn_reconfiguration_needed = vpn_reconfiguration_needed(hood["servers"],local_serverlist);
|
||||||
|
if(vpn_reconfiguration_needed) then
|
||||||
|
vpn_stop()
|
||||||
|
end
|
||||||
|
|
||||||
|
-- reconfigure wireless
|
||||||
|
if(wireless_reconfiguration_needed(radios, hood["bssid"])) then
|
||||||
|
wireless_reconfigure(radios, hood["bssid"])
|
||||||
|
wireless_restart()
|
||||||
|
io.stderr:write('Wireless needed reconfiguration. Applied new settings and restarted.\n')
|
||||||
|
end
|
||||||
|
|
||||||
|
-- reconfigure fastd
|
||||||
|
if (vpn_reconfiguration_needed) then
|
||||||
|
vpn_reconfigure(hood["servers"],local_serverlist)
|
||||||
|
-- scan mode can disable VPN so we need to make shure that VPN is enabled
|
||||||
|
-- if the router selects a hood
|
||||||
|
vpn_enable()
|
||||||
|
vpn_start()
|
||||||
|
io.stderr:write('VPN needed reconfiguration. Applied new settings and restarted.\n')
|
||||||
|
end
|
||||||
|
io.stderr:write("Set hood \""..hood["name"].."\"\n")
|
||||||
|
molwmtable["hoodname"] = "\"" .. hood["name"] .. "\""
|
||||||
|
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Return the default hood in the hood list.
|
||||||
|
-- This method can return the following data:
|
||||||
|
-- * default hood
|
||||||
|
-- * nil if no default hood has been defined
|
||||||
|
local function getDefaultHood(jhood)
|
||||||
|
for n, h in pairs(jhood) do
|
||||||
|
if h.defaulthood then
|
||||||
|
return h
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
-- boolean check if batman-adv has gateways
|
||||||
|
local function batmanHasGateway()
|
||||||
|
for gw in io.open("/sys/kernel/debug/batman_adv/bat0/gateways", 'r'):lines() do
|
||||||
|
if gw:match("Bit") then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Return hood from the hood file based on a given BSSID. nil if no matching hood could be found
|
||||||
|
local function gethoodByBssid(jhood, scan_bssid)
|
||||||
|
for n, h in pairs(jhood) do
|
||||||
|
if scan_bssid:match(h.bssid) then
|
||||||
|
return h
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Return hood from hood file based on a peer address. nil if no matching hood could be found
|
||||||
|
local function getCurrentHood(jhood)
|
||||||
|
for local_server_config_name, local_server in pairs(getCurrentPeers()) do
|
||||||
|
for n, h in pairs(jhood) do
|
||||||
|
for n, peer in pairs(h.servers) do
|
||||||
|
if ( peer["host"] == local_server.remote.host:gsub("\"", "") ) then
|
||||||
|
return h
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
local function get_batman_mesh_network(sorted_wlan_list, defaultHood)
|
||||||
|
io.stderr:write('Testing neighboring adhoc networks for batman advanced gw connection.\n')
|
||||||
|
io.stderr:write('The following wireless networks have been found:\n')
|
||||||
|
for n, network in pairs(sorted_wlan_list) do
|
||||||
|
print(network["quality"].."\t"..network["frequency"].."\t"..network["bssid"].."\t"..network["ssid"])
|
||||||
|
end
|
||||||
|
|
||||||
|
-- we dont want to get tricked by our signal
|
||||||
|
sorted_wlan_list = filter_my_wlan_network(sorted_wlan_list)
|
||||||
|
-- we dont want to test the default hood because if there is no other
|
||||||
|
-- hood present we will connect to the default hood anyway
|
||||||
|
sorted_wlan_list = filter_default_hood_wlan_networks(defaultHood, sorted_wlan_list)
|
||||||
|
|
||||||
|
io.stderr:write('After filtering we will test the following wireless networks:\n')
|
||||||
|
for n, network in pairs(sorted_wlan_list) do
|
||||||
|
print(network["quality"].."\t"..network["frequency"].."\t"..network["bssid"].."\t"..network["ssid"])
|
||||||
|
end
|
||||||
|
|
||||||
|
local bssid = nil
|
||||||
|
if(next(sorted_wlan_list)) then
|
||||||
|
io.stderr:write("Prepare configuration for testing wireless networks...\n")
|
||||||
|
-- Notice:
|
||||||
|
-- we will use iw for testing the wireless networks because using iw does
|
||||||
|
-- not need any changes inside the uci config. This approach allows the
|
||||||
|
-- router to automatically reset to previous configuration in case
|
||||||
|
-- someone disconnects the router from power during test.
|
||||||
|
|
||||||
|
-- stop vpn to prevent two hoods from beeing connected in case
|
||||||
|
-- the router gets internet unexpectedly during test.
|
||||||
|
vpn_stop()
|
||||||
|
-- remove the ap network because we cannot change
|
||||||
|
-- the settings of the adhoc network if the ap network is still operating
|
||||||
|
os.execute("iw dev client0 del")
|
||||||
|
for n, wireless in pairs(sorted_wlan_list) do
|
||||||
|
io.stderr:write("Testing "..wireless["bssid"].."...")
|
||||||
|
-- leave the current adhoc network
|
||||||
|
os.execute("iw dev ibss0 ibss leave")
|
||||||
|
-- setup the adhoc network we want to test
|
||||||
|
os.execute("iw dev ibss0 ibss join "..wireless["ssid"].." "..wireless["frequency"].." "..wireless["bssid"])
|
||||||
|
-- sleep 30 seconds till the connection is fully setup
|
||||||
|
sleep(30)
|
||||||
|
|
||||||
|
if batmanHasGateway() then
|
||||||
|
bssid = wireless["bssid"]
|
||||||
|
break;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
vpn_start()
|
||||||
|
wireless_restart()
|
||||||
|
io.stderr:write("Finished testing wireless networks, restored previous configuration\n")
|
||||||
|
end
|
||||||
|
|
||||||
|
return bssid
|
||||||
|
end
|
||||||
|
|
||||||
|
-- INITIALIZE AND PREPARE DATA --
|
||||||
|
-- read hoodfile, exit if reading the hoodfile fails
|
||||||
|
local jhood = readHoodfile(file)
|
||||||
|
if jhood == nil then
|
||||||
|
io.stderr:write('There seems to have gone something wrong while reading hoodfile from ' .. file .. '\n')
|
||||||
|
exit()
|
||||||
|
end
|
||||||
|
|
||||||
|
-- check if a default hood has been defined and exit if none has been defined
|
||||||
|
local defaultHood = getDefaultHood(jhood)
|
||||||
|
if defaultHood == nil then
|
||||||
|
io.stderr:write('No defaulthood defined.\n')
|
||||||
|
exit()
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Get list of wifi devices
|
||||||
|
local radios = getWifiDevices()
|
||||||
|
|
||||||
|
-- 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 fallback to scan mode.
|
||||||
|
if directVPN() then
|
||||||
|
io.stderr:write('VPN connection found.\n')
|
||||||
|
local geo = getGeolocation()
|
||||||
|
if geo[1] ~= nil and geo[2] ~= nil then
|
||||||
|
io.stderr:write('Position found.\n')
|
||||||
|
local geoHood = getHoodByGeo(jhood, geo)
|
||||||
|
if geoHood ~= nil then
|
||||||
|
set_hoodconfig(geoHood, radios)
|
||||||
|
io.stderr:write('Hood set by VPN mode.\n')
|
||||||
|
write_molwm(geoHood)
|
||||||
|
exit()
|
||||||
|
end
|
||||||
|
io.stderr:write('No hood has been defined for current position.\n')
|
||||||
|
set_hoodconfig(defaultHood, radios)
|
||||||
|
io.stderr:write('Defaulthood set.\n')
|
||||||
|
write_molwm(defaultHood)
|
||||||
|
exit()
|
||||||
|
end
|
||||||
|
io.stderr:write('No position found\n')
|
||||||
|
else
|
||||||
|
io.stderr:write('No VPN connection found\n')
|
||||||
|
end
|
||||||
|
|
||||||
|
if batmanHasGateway() then
|
||||||
|
io.stderr:write('Batman gateways found, everything seems to be ok - doing nothing\n')
|
||||||
|
local currendHood = getCurrentHood(jhood)
|
||||||
|
if currendHood ~= nil then
|
||||||
|
write_molwm(currendHood)
|
||||||
|
end
|
||||||
|
exit()
|
||||||
|
end
|
||||||
|
|
||||||
|
-- SCAN MODE
|
||||||
|
if next(radios) then
|
||||||
|
-- check if there exist a neighboring freifunk batman advanced mesh
|
||||||
|
-- network with an active connection to a batman advanced gateway
|
||||||
|
local sortedWlanList = wlan_list_sorted(radios)
|
||||||
|
local meshBSSID = get_batman_mesh_network(sortedWlanList, defaultHood)
|
||||||
|
if meshBSSID ~= nil then
|
||||||
|
io.stderr:write("Neighoring freifunk batman advanced mesh with BSSID "..meshBSSID.." found\n")
|
||||||
|
local bssidHood = gethoodByBssid(jhood, meshBSSID)
|
||||||
|
if bssidHood ~= nil then
|
||||||
|
set_hoodconfig(bssidHood, radios)
|
||||||
|
io.stderr:write('Hood set by scan mode\n')
|
||||||
|
write_molwm(bssidHood)
|
||||||
|
exit()
|
||||||
|
end
|
||||||
|
|
||||||
|
-- if the bssid does not corespond to any hood, we disable vpn and
|
||||||
|
-- just establish a wireless connection to the mesh without any vpn or
|
||||||
|
-- mesh on lan (TODO) connectivity
|
||||||
|
vpn_stop()
|
||||||
|
vpn_disable()
|
||||||
|
wireless_reconfigure(radios, meshBSSID)
|
||||||
|
wireless_restart()
|
||||||
|
io.stderr:write('Could not select a hood but established a connection via wireless mesh.\n')
|
||||||
|
io.stderr:write('Disabled all connections except connections via wireless mesh.\n')
|
||||||
|
local currendHood = getCurrentHood(jhood)
|
||||||
|
if currendHood ~= nil then
|
||||||
|
write_molwm(currendHood)
|
||||||
|
end
|
||||||
|
exit()
|
||||||
|
end
|
||||||
|
io.stderr:write('No neighboring freifunk batman advanced mesh found.\n')
|
||||||
|
end
|
||||||
|
|
||||||
|
-- DEFAULT-HOOD MODE
|
||||||
|
-- If we do NOT have a VPN connection AND found no freifunk mesh network while
|
||||||
|
-- scanning then we set the default hood
|
||||||
|
set_hoodconfig(defaultHood, radios)
|
||||||
|
io.stderr:write('Set defaulthood.\n')
|
||||||
|
write_molwm(defaultHood)
|
||||||
|
exit()
|
6
package/ffnw-hoodselector/src/Makefile
Normal file
6
package/ffnw-hoodselector/src/Makefile
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
all: respondd.so
|
||||||
|
|
||||||
|
CFLAGS += -Wall
|
||||||
|
|
||||||
|
respondd.so: respondd.c
|
||||||
|
$(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -shared -fPIC -D_GNU_SOURCE -o $@ $^ $(LDLIBS) -lgluonutil -luci
|
119
package/ffnw-hoodselector/src/respondd.c
Normal file
119
package/ffnw-hoodselector/src/respondd.c
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
#include <respondd.h>
|
||||||
|
#include <json-c/json.h>
|
||||||
|
#include <libgluonutil.h>
|
||||||
|
#include <uci.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <net/if.h>
|
||||||
|
|
||||||
|
#define _STRINGIFY(s) #s
|
||||||
|
#define STRINGIFY(s) _STRINGIFY(s)
|
||||||
|
|
||||||
|
bool strstw(const char *pre, const char *str) {
|
||||||
|
size_t lenpre = strlen(pre);
|
||||||
|
return strlen(str) < lenpre ? false : strncmp(pre, str, lenpre) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool strrmbs(char *line, int begin, int end) { // <- ist es hier sinvoller pointer auf die ints zu setzen??
|
||||||
|
size_t len = strlen(line);
|
||||||
|
if (len < begin)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
memmove(line, line+begin, len - begin + 1);
|
||||||
|
if (len < end)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
line[len-end] = 0; //remove val of end characters on the end
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// extract hood informations
|
||||||
|
static struct json_object * get_hoodselector(void) {
|
||||||
|
FILE *f = fopen("/tmp/.hoodselector", "r");
|
||||||
|
if (!f)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
struct json_object *ret = json_object_new_object();
|
||||||
|
char *line = NULL;
|
||||||
|
size_t len = 0;
|
||||||
|
while (getline(&line, &len, f) >= 0) {
|
||||||
|
//1. Get md5 hash from current selected hood.
|
||||||
|
if (strstw("\"md5hash\": ",line)) {
|
||||||
|
if (!strrmbs(line, 12, 14))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
json_object_object_add(ret, "md5hash", gluonutil_wrap_string(line));
|
||||||
|
}
|
||||||
|
//2. Get true or false string for VPN Router.
|
||||||
|
if (strstw("\"vpnrouter\": ",line)) {
|
||||||
|
if (!strrmbs(line, 14, 16))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
json_object_object_add(ret, "vpnrouter", gluonutil_wrap_string(line));
|
||||||
|
}
|
||||||
|
//3. Get hoodname
|
||||||
|
if (strstw("\"hoodname\": ",line)) {
|
||||||
|
if (!strrmbs(line, 13, 15))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
json_object_object_add(ret, "hoodname", gluonutil_wrap_string(line));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(line);
|
||||||
|
fclose(f);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Get currend selected BSSID
|
||||||
|
static struct json_object * get_current_selected_bssid(void){
|
||||||
|
struct uci_context *ctx = uci_alloc_context();
|
||||||
|
ctx->flags &= ~UCI_FLAG_STRICT;
|
||||||
|
struct uci_package *p;
|
||||||
|
|
||||||
|
if (uci_load(ctx, "wireless", &p))
|
||||||
|
goto end;
|
||||||
|
|
||||||
|
struct uci_element *e;
|
||||||
|
uci_foreach_element(&p->sections, e) {
|
||||||
|
struct uci_section *s = uci_to_section(e);
|
||||||
|
if (strcmp(s->type, "wifi-iface"))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (strncmp(e->name, "ibss_", 5))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
const char *bssid = uci_lookup_option_string(ctx, s, "bssid");
|
||||||
|
if (!bssid)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
struct json_object *ret = json_object_new_object();
|
||||||
|
json_object_object_add(ret, "bssid", gluonutil_wrap_string(bssid));
|
||||||
|
free(bssid);
|
||||||
|
uci_free_context(ctx);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
end:
|
||||||
|
uci_free_context(ctx);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// create final obj with logical structure
|
||||||
|
static struct json_object * respondd_provider_hoodselector(void) {
|
||||||
|
struct json_object *ret = json_object_new_object();
|
||||||
|
|
||||||
|
struct json_object *hoodinfo = get_hoodselector();
|
||||||
|
if(hoodinfo)
|
||||||
|
json_object_object_add(ret, "hoodinfo", hoodinfo);
|
||||||
|
|
||||||
|
struct json_object *selectedbssid = get_current_selected_bssid();
|
||||||
|
if(selectedbssid)
|
||||||
|
json_object_object_add(ret, "selectedbssid", selectedbssid);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// related to respondd_provider_hoodselector
|
||||||
|
const struct respondd_provider_info respondd_providers[] = {
|
||||||
|
{"hoodselector", respondd_provider_hoodselector},
|
||||||
|
{}
|
||||||
|
};
|
Loading…
Reference in New Issue
Block a user