Skip to content
Snippets Groups Projects
Commit 9004028c authored by Matthias Schiffer's avatar Matthias Schiffer
Browse files

Convert gluon-announce Lua code to C modules, rename to gluon-respondd

gluon-announced and gluon-announce are merged to gluon-respondd.
parent 840d07dd
No related branches found
No related tags found
No related merge requests found
Showing
with 100 additions and 383 deletions
return tonumber(util.readline(io.open('/proc/uptime')):match('^([^ ]+) '))
#!/usr/bin/lua
module('gluon.announce', package.seeall)
fs = require 'nixio.fs'
util = require 'gluon.util'
model_uci = require 'luci.model.uci'
local collect_dir
local function collect_entry(entry)
if fs.stat(entry, 'type') == 'dir' then
return collect_dir(entry)
else
return loadfile(entry)
end
end
function collect_dir(dir)
local fns = {}
for entry in fs.dir(dir) do
if entry:sub(1, 1) ~= '.' then
collectgarbage()
local fn, err = collect_entry(dir .. '/' .. entry)
if fn then
fns[entry] = fn
else
io.stderr:write(err, '\n')
end
end
end
return function ()
local ret = { [{}] = true }
for k, v in pairs(fns) do
collectgarbage()
local ok, val = pcall(setfenv(v, _M))
if ok then
ret[k] = val
else
io.stderr:write(val, '\n')
end
end
collectgarbage()
return ret
end
end
function collect(dir)
local f = collect_dir(dir)
return function ()
_M.uci = model_uci.cursor()
ret = f()
_M.uci = nil
collectgarbage()
return ret
end
end
local announce = require 'gluon.announce'
local deflate = require 'deflate'
local json = require 'luci.jsonc'
local util = require 'luci.util'
local nixio = require 'nixio'
local fs = require 'nixio.fs'
local memoize = {}
nixio.chdir('/lib/gluon/announce/')
for dir in fs.glob('*.d') do
local name = dir:sub(1, -3)
memoize[name] = {
collect = announce.collect(dir),
-- tonumber will return 0 for invalid inputs
cache_time = tonumber(util.trim(fs.readfile(name .. '.cache') or ''))
}
end
local function collect(type, timestamp)
local c = memoize[type]
if not c then
return nil
end
if c.cache_timeout and timestamp < c.cache_timeout then
return c.cache
else
local ret = c.collect()
if c.cache_time then
c.cache = ret
c.cache_timeout = timestamp + c.cache_time
end
return ret
end
end
module('gluon.announced', package.seeall)
function handle_request(query, timestamp)
collectgarbage()
local m = query:match('^GET ([a-z ]+)$')
local ret
if m then
local data = {}
for q in m:gmatch('([a-z]+)') do
local ok, val = pcall(collect, q, timestamp)
if ok then
data[q] = val
end
end
if next(data) then
ret = deflate.compress(json.stringify(data))
end
elseif query:match('^[a-z]+$') then
local ok, data = pcall(collect, query, timestamp)
if ok then
ret = json.stringify(data)
end
end
collectgarbage()
return ret
end
...@@ -5,29 +5,28 @@ PKG_VERSION:=4 ...@@ -5,29 +5,28 @@ PKG_VERSION:=4
PKG_RELEASE:=$(GLUON_BRANCH) PKG_RELEASE:=$(GLUON_BRANCH)
PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME) PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)
PKG_BUILD_DEPENDS := respondd
include $(GLUONDIR)/include/package.mk include $(GLUONDIR)/include/package.mk
define Package/gluon-autoupdater define Package/gluon-autoupdater
SECTION:=gluon SECTION:=gluon
CATEGORY:=Gluon CATEGORY:=Gluon
DEPENDS:=+gluon-core +micrond +autoupdater DEPENDS:=+gluon-core +libgluonutil +micrond +autoupdater
TITLE:=Automatically update firmware TITLE:=Automatically update firmware
endef endef
define Build/Prepare define Build/Prepare
mkdir -p $(PKG_BUILD_DIR) mkdir -p $(PKG_BUILD_DIR)
endef $(CP) ./src/* $(PKG_BUILD_DIR)/
define Build/Configure
endef
define Build/Compile
endef endef
define Package/gluon-autoupdater/install define Package/gluon-autoupdater/install
$(CP) ./files/* $(1)/ $(CP) ./files/* $(1)/
$(INSTALL_DIR) $(1)/lib/gluon/respondd
$(CP) $(PKG_BUILD_DIR)/respondd.so $(1)/lib/gluon/respondd/autoupdater.so
if [ '$(GLUON_BRANCH)' ]; then \ if [ '$(GLUON_BRANCH)' ]; then \
$(INSTALL_DIR) $(1)/lib/gluon/autoupdater; \ $(INSTALL_DIR) $(1)/lib/gluon/autoupdater; \
echo '$(GLUON_BRANCH)' > $(1)/lib/gluon/autoupdater/default_branch; \ echo '$(GLUON_BRANCH)' > $(1)/lib/gluon/autoupdater/default_branch; \
......
local autoupdater = uci:get_all('autoupdater', 'settings')
if autoupdater then
return {
branch = autoupdater['branch'],
enabled = uci:get_bool('autoupdater', 'settings', 'enabled'),
}
end
all: respondd.so
CFLAGS += -Wall
respondd.so: respondd.c
$(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -shared -fPIC -D_GNU_SOURCE -o $@ $^ $(LDLIBS) -lgluonutil -luci
/*
Copyright (c) 2016, Matthias Schiffer <mschiffer@universe-factory.net>
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.
*/
#include <respondd.h>
#include <json-c/json.h>
#include <libgluonutil.h>
#include <uci.h>
#include <string.h>
static struct json_object * get_autoupdater(void) {
struct uci_context *ctx = uci_alloc_context();
ctx->flags &= ~UCI_FLAG_STRICT;
struct uci_package *p;
if (uci_load(ctx, "autoupdater", &p))
goto error;
struct uci_section *s = uci_lookup_section(ctx, p, "settings");
if (!s)
goto error;
struct json_object *ret = json_object_new_object();
json_object_object_add(ret, "branch", gluonutil_wrap_string(uci_lookup_option_string(ctx, s, "branch")));
const char *enabled = uci_lookup_option_string(ctx, s, "enabled");
json_object_object_add(ret, "enabled", json_object_new_boolean(enabled && !strcmp(enabled, "1")));
uci_free_context(ctx);
return ret;
error:
uci_free_context(ctx);
return NULL;
}
static struct json_object * respondd_provider_nodeinfo(void) {
struct json_object *ret = json_object_new_object();
struct json_object *software = json_object_new_object();
json_object_object_add(software, "autoupdater", get_autoupdater());
json_object_object_add(ret, "software", software);
return ret;
}
const struct respondd_provider_info respondd_providers[] = {
{"nodeinfo", respondd_provider_nodeinfo},
{}
};
...@@ -12,7 +12,7 @@ define Package/gluon-core ...@@ -12,7 +12,7 @@ define Package/gluon-core
SECTION:=gluon SECTION:=gluon
CATEGORY:=Gluon CATEGORY:=Gluon
TITLE:=Base files of Gluon TITLE:=Base files of Gluon
DEPENDS:=+gluon-site +lua-platform-info +luci-base +luci-lib-jsonc +odhcp6c +firewall DEPENDS:=+gluon-site +libgluonutil +lua-platform-info +luci-base +luci-lib-jsonc +odhcp6c +firewall
endef endef
......
14
15
...@@ -4,6 +4,7 @@ PKG_NAME:=gluon-mesh-batman-adv-core ...@@ -4,6 +4,7 @@ PKG_NAME:=gluon-mesh-batman-adv-core
PKG_VERSION:=1 PKG_VERSION:=1
PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME) PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)
PKG_BUILD_DEPENDS := respondd
include $(GLUONDIR)/include/package.mk include $(GLUONDIR)/include/package.mk
...@@ -11,21 +12,19 @@ define Package/gluon-mesh-batman-adv-core ...@@ -11,21 +12,19 @@ define Package/gluon-mesh-batman-adv-core
SECTION:=gluon SECTION:=gluon
CATEGORY:=Gluon CATEGORY:=Gluon
TITLE:=Support for batman-adv meshing (core) TITLE:=Support for batman-adv meshing (core)
DEPENDS:=+gluon-core +gluon-client-bridge +firewall +libiwinfo-lua +batman-adv-visdata DEPENDS:=+gluon-core +libgluonutil +gluon-client-bridge +firewall +libiwinfo +batman-adv-visdata
endef endef
define Build/Prepare define Build/Prepare
mkdir -p $(PKG_BUILD_DIR) mkdir -p $(PKG_BUILD_DIR)
endef $(CP) ./src/* $(PKG_BUILD_DIR)/
define Build/Configure
endef
define Build/Compile
endef endef
define Package/gluon-mesh-batman-adv-core/install define Package/gluon-mesh-batman-adv-core/install
$(CP) ./files/* $(1)/ $(CP) ./files/* $(1)/
$(INSTALL_DIR) $(1)/lib/gluon/respondd
$(CP) $(PKG_BUILD_DIR)/respondd.so $(1)/lib/gluon/respondd/mesh-batman-adv-core.so
endef endef
define Package/gluon-mesh-batman-adv-core/postinst define Package/gluon-mesh-batman-adv-core/postinst
......
local ifname_address_cache = {}
function ifname2address(ifname)
local ifaddress
if ifname_address_cache[ifname] ~= nil then
ifaddress = ifname_address_cache[ifname]
else
ifaddress = util.readline(io.open("/sys/class/net/" .. ifname .. "/address"))
ifname_address_cache[ifname] = ifaddress
end
return ifaddress
end
function batadv()
local interfaces = {}
local list = io.lines("/tmp/batman-adv-visdata/bat0/originators")
for line in list do
local mac1, lastseen, tq, mac2, ifname =
line:match("^([0-9a-f:]+) +(%d+%.%d+)s +%( *(%d+)%) +([0-9a-f:]+) +%[ *(.-)%]")
if mac1 ~= nil and mac1 == mac2 then
ifaddress = ifname2address(ifname)
if interfaces[ifaddress] == nil then
interfaces[ifaddress] = { neighbours = { [{}] = true } }
end
interfaces[ifaddress].neighbours[mac1] = { tq = tonumber(tq)
, lastseen = tonumber(lastseen)
}
end
end
if next(interfaces) then
return interfaces
end
end
return batadv()
local batman_adv = require 'gluon.batman_adv'
local iwinfo = require 'iwinfo'
function neighbours(iface)
local stations = {}
for k, v in pairs(iface.iw.assoclist(iface.ifname)) do
stations[k:lower()] = { signal = v.signal
, noise = v.noise
, inactive = v.inactive
}
end
if next(stations) then
return stations
end
end
function interfaces()
local interfaces = {}
for ifname in batman_adv.interfaces('bat0') do
pcall(function()
local address = util.readline(io.open('/sys/class/net/' .. ifname .. '/address'))
local wifitype = iwinfo.type(ifname)
if wifitype ~= nil then
interfaces[address] = { ifname = ifname, iw = iwinfo[wifitype] }
end
end)
end
return interfaces
end
local wifi = {}
for address, iface in pairs(interfaces()) do
wifi[address] = { [{}] = true, neighbours = neighbours(iface) }
end
if next(wifi) then
return wifi
end
local ip = require 'luci.ip'
local bit = require 'nixio'.bit
local addresses = {}
for line in io.lines('/proc/net/if_inet6') do
local matches = { line:match('^' .. string.rep('(%x%x%x%x)', 8) .. string.rep(' %x%x', 3) .. ' (%x%x)%s+([^%s]+)$') }
-- exclude wrong interfaces and deprecated as well as tentative addresses
-- (see /include/uapi/linux/if_addr.h in linux source for flags)
if matches[10] == 'br-client' and bit.band(tonumber(matches[9], 16), 0x60) == 0 then
table.insert(addresses, ip.IPv6(string.format('%s:%s:%s:%s:%s:%s:%s:%s', unpack(matches))):string():lower())
end
end
return addresses
local batman_adv = require 'gluon.batman_adv'
local wireless = {}
local tunnel = {}
local other = {}
local function get_address(t, ifname)
pcall(
function()
table.insert(t, util.readline(io.open('/sys/class/net/' .. ifname .. '/address')))
end
)
end
local function file_exists(filename)
local f = io.open(filename)
if f == nil then
return false
else
f:close()
return true
end
end
local function is_wireless(ifname)
return file_exists('/sys/class/net/' .. ifname .. '/wireless')
end
local function is_tuntap(ifname)
return file_exists('/sys/class/net/' .. ifname .. '/tun_flags')
end
local function nil_table(t)
if next(t) ~= nil then
return t
else
return nil
end
end
for ifname in batman_adv.interfaces('bat0') do
if is_wireless(ifname) then
get_address(wireless, ifname)
elseif is_tuntap(ifname) then
get_address(tunnel, ifname)
else
get_address(other, ifname)
end
end
return {
wireless = nil_table(wireless),
tunnel = nil_table(tunnel),
other = nil_table(other),
[{}] = true
}
local batman_adv = require 'gluon.batman_adv'
local interfaces = {}
for ifname in batman_adv.interfaces('bat0') do
pcall(
function()
table.insert(interfaces, util.readline(io.open('/sys/class/net/' .. ifname .. '/address')))
end
)
end
return interfaces
return util.readline(io.open('/sys/module/batman_adv/version'))
local iwinfo = require 'iwinfo'
local counts = { total = 0
, wifi = 0
, wifi24 = 0
, wifi5 = 0
}
local list = io.lines("/sys/kernel/debug/batman_adv/bat0/transtable_local")
local clients = {}
for line in list do
local mac, _, flags, lastseen = line:match("^ %* ([0-9a-f:]+) *(.- )%[(.-)%] +(%d+%.%d+)")
if mac then
if not flags:match('P') then
counts.total = counts.total + 1
clients[mac:lower()] = true
if flags:match('W') then
counts.wifi = counts.wifi +1
end
end
end
end
function count_iface_stations(iface)
local wifitype = iwinfo.type(iface)
if wifitype == nil then
return
end
local freq = iwinfo[wifitype].frequency(iface)
local key
if freq >= 2400 and freq < 2500 then
key = "wifi24"
elseif freq >= 5000 and freq < 6000 then
key = "wifi5"
else
return
end
for k, v in pairs(iwinfo[wifitype].assoclist(iface)) do
if clients[k:lower()] then
counts[key] = counts[key] + 1
end
end
end
local ifaces = {}
uci:foreach("wireless", "wifi-iface", function(s)
if s.network == "client" and s.mode == "ap" then
count_iface_stations(s.ifname)
end
end)
return counts
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment