Skip to content

Commit

Permalink
ffh-wifi-offline-ssid: initial commit
Browse files Browse the repository at this point in the history
This commit adds a package to change the SSID if no internet connection is
available. It depends on ffh-check-connection.

This is based on freifunk-gluon/gluon#1649
  • Loading branch information
CodeFetch committed Jun 8, 2021
1 parent 3fa4b74 commit bb5b1d0
Show file tree
Hide file tree
Showing 7 changed files with 249 additions and 0 deletions.
23 changes: 23 additions & 0 deletions ffh-wifi-offline-ssid/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
Copyright (c) 2021, Freifunk Hannover <[email protected]>
Copyright (c) 2013-2021, Project Gluon
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
22 changes: 22 additions & 0 deletions ffh-wifi-offline-ssid/Makefile
Original file line number Diff line number Diff line change
@@ -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)))
46 changes: 46 additions & 0 deletions ffh-wifi-offline-ssid/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
ffh-wifi-offline-ssid
=====================

This package adds a script which changes the WLAN SSID on loss of
internet connectivity. It depends on and is being called by
*ffh-check-connection*.

This ``offline SSID`` can be generated from the node's hostname
with the first and last part of the node name or the MAC address.

After the connection has been lost for a certain ``threshold`` of
minutes it is being changed to the offline SSID.
Once the connectivity is established it will be changed back to
the default SSID again.

domain.conf
-----------

Adapt and add this block to your ``domain.conf``:

::

ffh_wifi_offline_ssid = {
disabled = false,
target_group = 'targets_global', -- the ffh-check-connection target group to perform tests on
threshold = 5, -- the number of minutes after which connectivity is considered lost
prefix = 'Offline_', -- use something short to leave space for the hostname (no '~' allowed!)
suffix = 'hostname', -- generate the SSID with either 'hostname', 'mac' or only the prefix: 'none'
},


Configuration via UCI
---------------------

You can configure the offline SSID on the command line with ``uci``.
E.g. disable it with:

::

uci set ffh-wifi-offline-ssid.settings.disabled='1'

Or set the threshold to three minutes with

::

uci set ffh-wifi-offline-ssid.settings.threshold='3'
5 changes: 5 additions & 0 deletions ffh-wifi-offline-ssid/check_site.lua
Original file line number Diff line number Diff line change
@@ -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)
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
config settings 'settings'
Original file line number Diff line number Diff line change
@@ -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
116 changes: 116 additions & 0 deletions ffh-wifi-offline-ssid/luasrc/usr/sbin/ffh-wifi-offline-ssid
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
#!/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') or false
if disabled then
print(prog_name .. " is disabled. Exiting...")
os.exit(0)
end

local threshold_mins = tonumber(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 < threshold_mins 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' and config['ssid'] then
table.insert(ssids, {ssid = config['ssid'], phy = phys[config['device']]})
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 the 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(s)
if hup_needed == 1 then
print("Applying new SSIDs...")
os.execute('killall -hup hostapd')
end

0 comments on commit bb5b1d0

Please sign in to comment.