diff --git a/hoodselector-advanced/Makefile b/hoodselector-advanced/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..e026f05895b2892a4ed5b3a0a863311d771e1dcf --- /dev/null +++ b/hoodselector-advanced/Makefile @@ -0,0 +1,36 @@ +include $(TOPDIR)/rules.mk + +PKG_NAME:=ffnw-hoodselector-advanced +PKG_VERSION:=1 +PKG_RELEASE:=1 + +PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME) + +include $(INCLUDE_DIR)/package.mk + +define Package/$(PKG_NAME) + SECTION:=networke + CATEGORY:=Freifunk Nordwest + TITLE:=Select the hoods depending on the geo coordinate + DEPENDS:=+lwtrace +libwlocate +ffnw-hoods +dkjson +endef + +define Package/$(PKG_NAME)/description + Select the hoods depending on the geo coordinates +endef + +define Build/Prepare + mkdir -p $(PKG_BUILD_DIR) +endef + +define Build/Configure +endef + +define Build/Compile +endef + +define Package/$(PKG_NAME)/install + $(CP) ./files/* $(1)/ +endef + +$(eval $(call BuildPackage,$(PKG_NAME))) diff --git a/hoodselector-advanced/files/usr/lib/micron.d/hoodselector-advanced b/hoodselector-advanced/files/usr/lib/micron.d/hoodselector-advanced new file mode 100644 index 0000000000000000000000000000000000000000..989cf7c3a66d9d19b09c15f6a3c67ed64f868b90 --- /dev/null +++ b/hoodselector-advanced/files/usr/lib/micron.d/hoodselector-advanced @@ -0,0 +1 @@ +* * * * * /usr/sbin/hoodselector-advanced diff --git a/hoodselector-advanced/files/usr/sbin/hoodselector-advanced b/hoodselector-advanced/files/usr/sbin/hoodselector-advanced new file mode 100644 index 0000000000000000000000000000000000000000..f9a80303f603125296b508233fe4b77db7a3d3f4 --- /dev/null +++ b/hoodselector-advanced/files/usr/sbin/hoodselector-advanced @@ -0,0 +1,732 @@ +#!/usr/bin/lua + +-- This is the hoodselector-advanced. The hoodselector-advanced is one of the +-- main components for splitting a layer 2 mesh network into seperated network +-- segments (hoods). +-- The job of the hoodselector-advanced 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-advanced should select a hood +-- from a list of known hoods (hoodlist) and adjust vpn, wireless and mesh +-- on lan (TODO) 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-advanced depends on the folowing additional software: +-- * gluon (determing mesh ssid using site.json) see get_mesh_ssids() +-- * fastd (vpn configuration) see get_current_peers(), +-- fastd_remove_old_peers(), fastd_add_new_peers() and set_hoodconfig() +-- * iw (wireless network scanning) see wlan_list_sorted() +-- +-- To detect the current hood the hoodselector-advanced knows 3 modes containing +-- two submodes: +-- * 1. Standard mode +-- * 2. Scan modes +-- - 2.1. Real hood scan mode +-- - 2.2. Maintenance scan mode +-- * 3. Default hood mode +-- +-- When selecting a hood, the hoodselector-advanced has the following +-- priorities: +-- 1. Selecting a hood by geo position is always the best option. +-- 2. If selecting a hood by geo position is not possible then selecting +-- a known real hood from the hoodlist is always better than +-- selecting a default hood or switching into maintenance mode. +-- 3. Selecting a default hood is always better than switching into +-- maintenance mode. +-- 4. Maintenance mode is only used if the scanner detects a an unknown +-- adhoc mesh network without detecting a known real or default +-- hood +-- +-- References +-- * UCI API: https://htmlpreview.github.io/?https://github.com/openwrt/luci/blob/master/documentation/api/modules/luci.model.uci.html#Cursor.get + +-- check if hoodselector-advanced is still running +-- and initialize +local pidPath="/var/run/hoodselector-advanced.pid" + +if io.open(pidPath, "r") ~=nil then + io.stderr:write("The hoodselector-advanced is still running.\n") + os.exit(1) +else + io.close(io.open(pidPath, "w")) +end + +local json = require ("dkjson") +local hoodfile_src = '/lib/ffnw/hoods/hoods.json' +local uci = require('luci.model.uci').cursor() + +-- initialization done + + +function pid_clean() + if io.open(pidPath, "r") ~=nil then + os.remove(pidPath) + end +end + +function trim(s) + -- from PiL2 20.4 + return (s:gsub("^%s*(.-)%s*$", "%1")) +end + +function sleep(n) + os.execute("sleep " .. tonumber(n)) +end + +--- +-- Function to retrieve console output +-- +function os.capture(cmd, raw) + local handle = assert(io.popen(cmd, 'r')) + local output = assert(handle:read('*a')) + + handle:close() + + if raw then + return output + end + + output = string.gsub( + string.gsub( + string.gsub(output, '^%s+', ''), + '%s+$', + '' + ), + '[\n\r]+', + ' ' + ) + + return output +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') +end + +local function get_mesh_ssids() + local site_src = "/lib/gluon/site.json" + local site, pos, err = json.decode (io.popen(string.format("cat %s",site_src), 'r'):read('*a'), 1, nil) + if err then + io.stderr:write("Error reading file " .. site_src .. "\n") + io.stderr:write("Existing...\n") + exit() + end + + local ssids = {} + if(site.wifi24.ibss.ssid ~= nil) then + table.insert(ssids, site.wifi24.ibss.ssid) + end + + if(site.wifi5.ibss.ssid ~= nil) then + table.insert(ssids, site.wifi5.ibss.ssid) + end + + return ssids +end + +-- Read the full hoodfile. Return nil for wrong format or no such file +local function readhoodfile(file) + local obj, pos, err = json.decode (io.popen(string.format("cat %s",file), 'r'):read('*a'), 1, nil) + if err then + return nil + else + return obj + end +end + +-- Return a wifi device list +local function get_wifi_devices() + 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 4-dimensional +-- array containing quality, capability, bssid and ssid. +-- 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') + if(ifname ~= nil) then + local wireless_scan = string.format( "iw %s scan", ifname) + local row = {} + row["encryption"] = "open" + row["radio"] = radio + for wifiscan in io.popen(wireless_scan, 'r'):lines() do + -- the following matches a new network + if wifiscan:match("BSS (%w+:%w+:%w+:%w+:%w+:%w+)") then + if(row["bssid"] ~= nil and row["quality"] ~= nil + and row["ssid"] ~= nil and row["capability"] ~= nil) then + table.insert(networks, row) + row = {} + row["encryption"] = "open" + row["radio"] = radio + end + end + + -- get encryption + if wifiscan:match("WPA:") then + row["encryption"] = "WPA" + end + if wifiscan:match("WEP:") then + row["encryption"] = "WEP" + end + if wifiscan:match("RSN:") then + row["encryption"] = "RSN" + 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 client/adhoc mode + if wifiscan:match("capability:") then + row["capability"] = wifiscan:split(":") + row["capability"] = row["capability"][2] + if(row["capability"] ~= nil) then + row["capability"] = trim(row["capability"]) + 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 + end + end + + table.sort(networks, function(a,b) return a["quality"] < b["quality"] end) + return networks +end + +local function get_wlan_adhoc_networks(wlan_list) + local adhoc_wlan_list = {} + for n,wlan in pairs(wlan_list) do + if(string.match(wlan["capability"], "IBSS")) then + table.insert(adhoc_wlan_list, wlan) + end + end + + return adhoc_wlan_list +end + +local function get_wlan_ap_networks(wlan_list) + local filtered_wlan_list = {} + for n,wlan in pairs(wlan_list) do + if(string.match(wlan["capability"], "ESS")) then + table.insert(filtered_wlan_list, wlan) + end + end + + return filtered_wlan_list +end + +local function get_wlan_open_networks(wlan_list) + local filtered_wlan_list = {} + for n,wlan in pairs(wlan_list) do + if(string.match(wlan["encryption"], "open")) then + table.insert(filtered_wlan_list, wlan) + end + end + + return filtered_wlan_list +end + +local function get_wlan_mesh_networks(wlan_list) + local mesh_wlan_list = {} + local mesh_ssids = get_mesh_ssids() + + for n,wlan in pairs(wlan_list) do + for i,ssid in pairs(mesh_ssids) do + if(string.match(wlan["ssid"], ssid)) then + table.insert(mesh_wlan_list, wlan) + break + end + end + end + + return mesh_wlan_list +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 + +-- This method checks for every bssid in sorted_mesh_list if the bssid +-- coresponds to a hood in jhood. +-- If a bssid is found that does not coresponds to a hood in the hoodfile, +-- the method returns true. Otherwise the method returns false. +local function unknown_hood_in_range(jhood, sorted_mesh_list) + for j, mesh in pairs(sorted_mesh_list) do + local mesh_exists = false + for i, hood in pairs(jhood) do + if(mesh.bssid == hood.bssid) then + mesh_exists = true + break + end + end + if not (mesh_exists) then return true end + end + return false +end + +-- Get Geoposition if no static position present try lwtrace. +-- Return nil for no position +local function get_geolocation() + local lat = uci:get('gluon-node-info', uci:get_first('gluon-node-info', 'location'), 'latitude') + local lng = uci:get('gluon-node-info', uci:get_first('gluon-node-info', 'location'), 'longitude') + if ( lat == nil or lng == nil ) then + for scan in io.popen(string.format("lwtrace -t 2> /dev/null"), 'r'):lines() do + if string.find(scan,"(lat)") then + local last_val = nil + for geo in string.gmatch(scan,"[^%s]+") do + if geo == '(lat)' then + lat = last_val + end + if geo == '(lon)' then + lng = last_val + end + last_val = geo + end + end + end + end + local ret = {} + table.insert(ret, tonumber(lat)) + table.insert(ret, tonumber(lng)) + return ret +end + +-- Return hood from the hood file based on geo position. This method +-- can return the following data: +-- * real hood if a hood could be determined for the given position +-- * nil if no real hood could be determined +local function gethood_by_geo(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 + +-- Return hood from the hood file based on a list of wireless networks. +-- This method takes a sorted a list of scanned wireless networks sorted by +-- descending by signal quality and returns the first real hoot that matches +-- a bssid from the network list (first hood, best signal quality). +-- This method can return the following data: +-- * real hood if a real hood matches the given BSSID +-- * nil if no real hood could be found +local function gethood_by_wlan_list(hoodlist, sorted_adhoc_mesh_list) + -- Match wireless networks with hoods. Summary: first match best signal + for i,wlan in pairs(sorted_adhoc_mesh_list) do + for n, hood in pairs(hoodlist) do + if (not hood.defaulthood and hood.bssid == wlan.bssid) then + return hood + end + end + end + return nil +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 get_default_hood(jhood) + for n, h in pairs(jhood) do + if h.defaulthood then + return h + end + end + return nil +end + +-- This method will iterate through a list of wireless networks. +-- While iterating it will try to get a connection to the update server +-- by connecting to unencrypted networks in client mode. +-- TODO: this method is critical so we should do exception handing like +-- described here: https://www.lua.org/pil/8.4.html +local function maintenance_mode(sorted_wlan_list) + io.stderr:write('Maintenance Mode: TODO.\n') + sorted_open_ap_list = get_wlan_open_networks(sorted_wlan_list) + sorted_open_ap_list = get_wlan_ap_networks(sorted_open_ap_list) + if(next(sorted_open_ap_list)) then + -- stop VPN and change wireless mode to STA + vpn_stop() + os.execute("iw dev ibss0 del") + os.execute("iw dev client0 del") + os.execute("iw phy phy0 interface add sta0 type managed") + os.execute("ip link set sta0 up") + + -- connect to open wireless networks + local update_successfull = false + for i, wlan in pairs(sorted_open_ap_list) do + print("Connecting to open wireless network "..wlan["ssid"].." on "..wlan["radio"]) + local cmd_output = os.capture("iw dev sta0 connect -w \'"..wlan["ssid"].."\'") + local cmd_output = os.capture("iw sta0 link") + if cmd_output:match("Connected to (%w+:%w+:%w+:%w+:%w+:%w+)") then + print("Connected to "..wlan["ssid"]) + sleep(1) + local cmd_output = os.capture("udhcpc -i sta0 --foreground --quit --now") + if cmd_output:match("Lease of (%d+\.%d+\.%d+\.%d+) obtained") then + print("Obtained IPv4 address") + os.execute("route -n") + -- TODO + -- At this point we need to optain the new data. To achieve this + -- there exist two ideas: + -- 1. Fetch a new firmware via wget or autoupdater. Problem is + -- that this is not possible so easy because of + -- https://gluon.readthedocs.io/en/v2016.1.4/dev/wan.html#gluon-wan-dnsmasq + -- os.execute("start-stop-daemon -S -c root:gluon-fastd -x /ping.sh") + -- 2. Each freifunk router supplies its hoodfile via + -- respondd on the wireless ap network and we just + -- recieve this hoodfile and check if the provided hoodfile + -- is newer than ours. One could add a version string to the + -- hoodfile to achieve this quickly. + -- Problem: the hoodfile should be signed + -- and we need to check if the signature is valid. This would + -- be the best way but I dont know how to do it. + update_successfull = true + else + print("No IPv4 address obtained") + end + os.execute("iw dev sta0 disconnect") + if(update_successfull) then + break + end + else + print("Connection to "..wlan["ssid"].." failed") + end + end + + -- put WLAN and VPN back in original state + os.execute("iw dev sta0 del") + os.execute("wifi") + vpn_start() + end +end + +-- Retun a table of current peers from /etc/config/fastd +local function get_current_peers() + local config_peername = {} + uci:foreach('fastd', 'peer', + function(s) + if s['.name'] then + table.insert(config_peername,s) + end + end + ) + local config_peers = {} + for _,index in pairs(config_peername) do + for prafix,peer in pairs(index) do + local tmp_peer = {} + if prafix:match(".name") then + if peer:match("mesh_vpn_backbone_peer_") then + local tmpremote = uci:get('fastd', peer, 'remote') + tmpremote = tmpremote[1]:split(" ") + local remote = {} + remote['host'] = tmpremote[1] + remote[tmpremote[2]] = tmpremote[3] + tmp_peer['key'] = tostring(uci:get('fastd', peer, 'key')) + tmp_peer['remote'] = remote + config_peers[peer] = tmp_peer + end + end + end + end + return config_peers +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 local_serverlist = get_current_peers() + + -- 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]) then + local_server_exists_in_hoodfile = true + if ( local_server.key ~= hood_server['publickey'] ) then + return true + end + local hood_server_host = '\"'..hood_server["host"]..'\"' + 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]) 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) + -- remove all servers + local local_serverlist = get_current_peers() + 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], + { + 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) + -- Check if VPN needs reconfiguration because in case of reconfiguration we + -- need to stop it before we can reconfigure any other connection. + local vpn_reconfiguration_needed = vpn_reconfiguration_needed(hood["servers"]); + if(vpn_reconfiguration_needed) then + vpn_stop() + end + + -- reconfigure wireless + if(wireless_reconfiguration_needed(radios, hood["bssid"])) then + wireless_reconfigure(radios, hood["bssid"]) + os.execute('wifi') + io.stderr:write('Wireless needed reconfiguration. Applied new settings and restarted.\n') + end + + -- reconfigure fastd + if (vpn_reconfiguration_needed) then + vpn_reconfigure(hood["servers"]) + vpn_start() + io.stderr:write('VPN needed reconfiguration. Applied new settings and restarted.\n') + end + + return true +end + +function exit() + pid_clean() + os.exit(0) +end + +-- INITIALIZE AND PREPARE DATA -- +-- read hoodfile, exit if reading the hoodfile fails +local jhood = readhoodfile(hoodfile_src) +if jhood == nil then + io.stderr:write('There seems to have gone something wrong while reading hoodfile from ' .. hoodfile_src .. '\n') + exit() +end + +-- check if a default hood has been defined and exit if none has been defined +local default_hood = get_default_hood(jhood) +if default_hood == nil then + io.stderr:write('No defaulthood defined.\n') + exit() +end + +-- Get wifi devices and geolocation +-- You can set geo = {lat, lon} manually for debugging purposes +local radios = get_wifi_devices() +local geo = get_geolocation() + +-- scan for wireless networks (this is needed for some modes) +io.stderr:write('Scanning wireless environment.\n') +local sorted_wlan_list = nil +local sorted_mesh_list = nil +if next(radios) then + -- create list of wireless networks in range sorted + -- descending by signal quality. Drop our own network from the list. + sorted_wlan_list = wlan_list_sorted(radios) + sorted_wlan_list = filter_my_wlan_network(sorted_wlan_list) + -- create list of wireless mesh networks in range sorted + -- descending by signal quality + sorted_mesh_list = get_wlan_adhoc_networks(sorted_wlan_list) + sorted_mesh_list = get_wlan_mesh_networks(sorted_mesh_list) +end + +-- MAINTENANCE SCAN MODE +-- At first we check if our hoodfile is up to date. In order to do this we check +-- if a freifunk mesh network is in range which bssid does not corespond to any +-- hood in our hoodfile. If such a network is in range the reason for this +-- can be: +-- 1. Our hoodfile is outdated +-- 2. Someone installed a testsetup in range +-- 3. Someone tries to attack us +-- In case 1. we need to trigger an update. +-- In case 2. and 3. we need to trigger an update too because we cannot +-- distinguish between the cases 1. and 2. or 3.. But we need to prevent the +-- attack from swapping all over the network. Therefore we need to choose an +-- update method that does not trigger the maintenance mode of other nodes +-- in general. +if (unknown_hood_in_range(jhood, sorted_mesh_list)) then + io.stderr:write('Unknown hood found while scanning. We might have an old hoodfile!\n') + maintenance_mode(sorted_wlan_list) + exit() +else + io.stderr:write('No unknown hood found while scanning, everything seems up to date.\n') +end + +-- STANDARD MODE +-- If we do have a position (either by geolocator or if the user has forced a +-- position manually) we will use the coresponding hood or fallback to another +-- mode if no hood coresponds to the position +if (geo[1] ~= nil and geo[2] ~= nil) then + io.stderr:write('Position found.\n') + local hood = gethood_by_geo(jhood, geo) + if(hood ~= nil) then + set_hoodconfig(hood, radios) + io.stderr:write('Hood set by standard mode.\n') + exit() + else + io.stderr:write('No hood for found for position.\n') + end +else + io.stderr:write('No position found.\n') +end + +-- REAL HOOD SCAN MODE +-- If we do NOT have a position but found a knwon hood by scanning our +-- wireless environment we will use the coresponding hood +local real_hood_scan_mode_hood = nil +sorted_mesh_list = filter_default_hood_wlan_networks(default_hood, sorted_mesh_list) +real_hood_scan_mode_hood = gethood_by_wlan_list(jhood, sorted_wlan_list) +if ( (geo[1] == nil or geo[2] == nil) and real_hood_scan_mode_hood ~= nil) then + io.stderr:write('Hood by real hood scan mode found.\n') + set_hoodconfig(real_hood_scan_mode_hood, radios) + io.stderr:write('Hood set by real hood scan mode.\n') + exit() +else + io.stderr:write('Neither position given nor real hood found by scaning.\n') +end + +-- DEFAULT-HOOD MODE +-- If we do NOT have a position AND found no known hoods by scanning our +-- wireless environment AND found no freifunk mesh network that might +-- coresponds to an unknown hood then we use defaul hood mode. +set_hoodconfig(default_hood, radios) +io.stderr:write('Set defaulthood.\n') +exit()