diff --git a/ffh-wifi-offline-ssid/Makefile b/ffh-wifi-offline-ssid/Makefile new file mode 100644 index 00000000..5ada518c --- /dev/null +++ b/ffh-wifi-offline-ssid/Makefile @@ -0,0 +1,22 @@ +include $(TOPDIR)/rules.mk + +PKG_NAME:=ffh-wifi-offline-ssid +PKG_VERSION:=1 +PKG_RELEASE:=1 + +include $(TOPDIR)/../package/gluon.mk + +define Package/$(PKG_NAME) + TITLE:=Changes the SSID to an Offline-SSID on disrupted internet connection + DEPENDS:=+gluon-core +ffh-check-connection +endef + +define Package/$(PKG_NAME)/description + Script to change the SSID to an Offline-SSID when there is no connection to + the internet. This SSID can be generated from the node's hostname with the + first and last part of the node's name or from the MAC address. + The script is being triggered by ffh-check-connection on connection status + changes. +endef + +$(eval $(call BuildPackageGluon,$(PKG_NAME))) diff --git a/ffh-wifi-offline-ssid/check_site.lua b/ffh-wifi-offline-ssid/check_site.lua new file mode 100644 index 00000000..ffc7fec3 --- /dev/null +++ b/ffh-wifi-offline-ssid/check_site.lua @@ -0,0 +1,5 @@ +need_boolean({'ffh_wifi_offline_ssid', 'disabled'}, false) +need_string({'ffh_wifi_offline_ssid', 'target_group'}, true) +need_number({'ffh_wifi_offline_ssid', 'threshold'}, false) +need_string({'ffh_wifi_offline_ssid', 'prefix'}, false) +need_one_of({'ffh_wifi_offline_ssid', 'suffix'}, {'hostname', 'mac', 'none'}, false) diff --git a/ffh-wifi-offline-ssid/files/etc/config/ffh-wifi-offline-ssid b/ffh-wifi-offline-ssid/files/etc/config/ffh-wifi-offline-ssid new file mode 100644 index 00000000..c488b640 --- /dev/null +++ b/ffh-wifi-offline-ssid/files/etc/config/ffh-wifi-offline-ssid @@ -0,0 +1 @@ +config settings 'settings' diff --git a/ffh-wifi-offline-ssid/luasrc/lib/gluon/upgrade/600-ffh-wifi-offline-ssid b/ffh-wifi-offline-ssid/luasrc/lib/gluon/upgrade/600-ffh-wifi-offline-ssid new file mode 100755 index 00000000..d387ff26 --- /dev/null +++ b/ffh-wifi-offline-ssid/luasrc/lib/gluon/upgrade/600-ffh-wifi-offline-ssid @@ -0,0 +1,36 @@ +#!/usr/bin/lua + +local site = require 'gluon.site' +local uci = require('simple-uci').cursor() + +if site.ffh_wifi_offline_ssid then + local site_disabled = site.ffh_wifi_offline_ssid.disabled() or '0' + + uci:section('ffh-wifi-offline-ssid', 'settings', 'settings', { + disabled = uci:get('ffh-wifi-offline-ssid', 'settings', 'disabled') or site_disabled, + threshold = site.ffh_wifi_offline_ssid.threshold() or 5, + prefix = site.ffh_wifi_offline_ssid.prefix() or 'Offline_', + suffix = site.ffh_wifi_offline_ssid.suffix() or 'hostname', + }) + + uci:save('ffh-wifi-offline-ssid') + + uci:section('ffh-check-connection', 'script', 'ffh_wifi_offline', { + enabled = true, + interval = 1, + command = 'ffh-wifi-offline-ssid offline', + groups = {site.ffh_wifi_offline_ssid.target_group(),}, + trigger = 'offline', + }) + + uci:section('ffh-check-connection', 'script', 'ffh_wifi_online', { + enabled = true, + interval = 1, + command = 'ffh-wifi-offline-ssid online', + groups = {site.ffh_wifi_offline_ssid.target_group(),}, + onchange = true, + trigger = 'online', + }) + + uci:save('ffh-check-connection') +end diff --git a/ffh-wifi-offline-ssid/luasrc/usr/sbin/ffh-wifi-offline-ssid b/ffh-wifi-offline-ssid/luasrc/usr/sbin/ffh-wifi-offline-ssid new file mode 100644 index 00000000..ca30ceda --- /dev/null +++ b/ffh-wifi-offline-ssid/luasrc/usr/sbin/ffh-wifi-offline-ssid @@ -0,0 +1,119 @@ +#!/usr/bin/lua + +local uci = require('simple-uci').cursor() +local unistd = require 'posix.unistd' +local util = require 'gluon.util' + +local prog_name = 'ffh-wifi-offline-ssid' +local offline_file = '/tmp/ffh-offline-ffh_wifi_offline' + +local disabled = uci:get('ffh-wifi-offline-ssid', 'settings', 'disabled') == '1' or false +if disabled then + print(prog_name .. " is disabled. Exiting...") + os.exit(0) +end + +local threshold_mins = uci:get(prog_name, 'settings', 'threshold') or 0 + +local uptime_mins = math.floor(util.get_uptime() / 60) +local offline_mins = uptime +if unistd.access(offline_file) then + offline_mins = uptime - (tonumber(util.readfile(offline_file)) or 0) +end + +if arg[1] == "offline" and offline_mins < switch_time then + print((threshold_mins - offline_mins) .. ' minutes remaining until the node is considered offline. Exiting...') + os.exit(0) +end + +local phys = {count = 0} +uci:foreach('wireless', 'wifi-device', function(config) + local phy = util.find_phy(config) + if phy then + phys[config['.name']] = phy + phys['count'] = phys['count'] + 1 + end +end) + +if phys['count'] == 0 then + print('No radios detected. Exiting...') + os.exit(0) +end + +local ssids = {} +uci:foreach('wireless', 'wifi-iface', function(config) + if config['mode'] == 'ap' and config['network'] == 'client' then + local ssid = config['ssid'] + if ssid then + table.insert(ssids, {ssid = ssid, phy = phys[config['device']]}) + end + end +end) + +if #ssids == 0 then + print('No client networks active. Exiting...') + os.exit(0) +end + +-- Use something short to leave space for the hostname +-- (no '~' allowed!) +local prefix = uci:get(prog_name, 'settings', 'prefix') or 'Offline_' + +-- Generate the SSID either with 'hostname', 'mac' or only using the prefix +local settings_suffix = uci:get(prog_name, 'settings', 'suffix') or 'hostname' + +local suffix = '' +if settings_suffix == 'hostname' then + local pretty_hostname = require 'pretty_hostname' + suffix = pretty_hostname.get(uci) + -- 32 would be possible as well + if (string.len(suffix) > 30 - string.len(prefix)) then + -- Calculate the length of the first part of the node identifier in the offline-ssid + local half = math.floor((28 - string.len(prefix)) / 2) + -- Jump to this character for the last part of the name + local skip = string.len(suffix) - half + -- Use the first and last part of the nodename for nodes with long name + suffix = string.sub(suffix, 0, half) .. '...' .. string.sub(suffix, skip) + end +elseif settings_suffix == 'mac' then + local sysconfig = require 'gluon.sysconfig' + suffix = sysconfig.primary_mac +end + +local offline_ssid = prefix .. suffix + +local hup_needed = 0 +local ssid_grep = 'grep "^ssid=' +for _, ssid in ipairs(ssids) do + local hostapd = '/var/run/hostapd-' .. ssid.phy .. '.conf' + + if arg[1] == "offline" then + old_ssid = ssid.ssid + new_ssid = offline_ssid + else + old_ssid = offline_ssid + new_ssid = ssid.ssid + end + + if os.execute(ssid_grep .. new_ssid .. '" ' .. hostapd) == 0 then + print('Current SSID "' .. new_ssid .. '" for ' .. ssid.phy .. ' is already correct. Skipping...') + break + end + + -- Confirm that old SSID was set + if os.execute(ssid_grep .. old_ssid .. '" ' .. hostapd) ~= 0 then + util.log(prog_name .. ': Warning: Neither found SSID "' .. ssid.ssid .. '" nor "' .. offline_ssid .. '" on ' .. ssid.phy .. '.') + end + + local current_ssid = util.trim(util.exec(ssid_grep .. '" ' .. hostapd .. ' | cut -d"=" -f2')) + + util.log(prog_name .. ': Current SSID is "' .. current_ssid .. '". Changing it to "' .. new_ssid .. '"...') + os.execute('sed -i "s~^ssid=' .. current_ssid .. '~ssid=' .. new_ssid .. '~" ' .. hostapd) + hup_needed = 1 +end + +-- Send hup to all hostapd instances to apply the new SSID +if hup_needed == 1 then + print("Applying new SSIDs...") + os.execute('killall -hup hostapd') +end