From 2e0e24a9926db31147ca750d698a6484c60c16a9 Mon Sep 17 00:00:00 2001
From: Nils Schneider <nils@nilsschneider.net>
Date: Thu, 11 Sep 2014 15:14:20 +0200
Subject: [PATCH] announce neighbours using alfred/gluon-announce

This adds a new announce.d datum "neighbours" (alfred 160) containing
information about mesh neighbours. It's intended to be an replacement
for batadv-vis.

In addition to the data already provided by batadv-vis it'll also
provide information about direct wifi neighbours.

Unlike batadv-vis, no data about clients is transmitted.

Sample data:

    {
      "wifi": {
        "90:f6:52:82:06:02": {
          "neighbours": {
            "f8:d1:11:2c:a7:d2": {
              "noise": -95,
              "inactive": 0,
              "signal": 0
            },
            "96:f6:52:ff:cd:6f": {
              "noise": -95,
              "inactive": 0,
              "signal": -37
            }
          }
        }
      },
      "batadv": {
        "90:f6:52:82:06:02": {
          "neighbours": {
            "96:f6:52:ff:cd:6f": {
              "lastseen": 2.8500000000000001,
              "tq": 177
            }
          }
        },
        "90:f6:52:82:06:03": {
          "neighbours": {
            "f8:d1:11:2c:a7:d3": {
              "lastseen": 2.3500000000000001,
              "tq": 206
            }
          }
        }
      },
      "node_id": "90f652820602"
    }
---
 .../gluon-alfred/files/lib/gluon/cron/alfred  |  2 +-
 .../lib/gluon/announce/neighbours.d/node_id   |  1 +
 package/gluon-mesh-batman-adv-core/Makefile   |  2 +-
 .../lib/gluon/announce/neighbours.d/batadv    | 41 +++++++++++++++++++
 .../lib/gluon/announce/neighbours.d/wifi      | 41 +++++++++++++++++++
 5 files changed, 85 insertions(+), 2 deletions(-)
 create mode 100644 package/gluon-announce/files/lib/gluon/announce/neighbours.d/node_id
 create mode 100644 package/gluon-mesh-batman-adv-core/files/lib/gluon/announce/neighbours.d/batadv
 create mode 100644 package/gluon-mesh-batman-adv-core/files/lib/gluon/announce/neighbours.d/wifi

diff --git a/package/gluon-alfred/files/lib/gluon/cron/alfred b/package/gluon-alfred/files/lib/gluon/cron/alfred
index adab7322c..9f79bc640 100644
--- a/package/gluon-alfred/files/lib/gluon/cron/alfred
+++ b/package/gluon-alfred/files/lib/gluon/cron/alfred
@@ -1 +1 @@
-* * * * * /lib/gluon/announce/collect.lua nodeinfo | gzip | alfred -s 158; /lib/gluon/announce/collect.lua statistics | gzip | alfred -s 159
+* * * * * /lib/gluon/announce/collect.lua nodeinfo | gzip | alfred -s 158; /lib/gluon/announce/collect.lua statistics | gzip | alfred -s 159; /lib/gluon/announce/collect.lua neighbours | gzip | alfred -s 160
diff --git a/package/gluon-announce/files/lib/gluon/announce/neighbours.d/node_id b/package/gluon-announce/files/lib/gluon/announce/neighbours.d/node_id
new file mode 100644
index 000000000..66303f4c7
--- /dev/null
+++ b/package/gluon-announce/files/lib/gluon/announce/neighbours.d/node_id
@@ -0,0 +1 @@
+return require('gluon.util').node_id()
diff --git a/package/gluon-mesh-batman-adv-core/Makefile b/package/gluon-mesh-batman-adv-core/Makefile
index 93191348e..fc4bc2248 100644
--- a/package/gluon-mesh-batman-adv-core/Makefile
+++ b/package/gluon-mesh-batman-adv-core/Makefile
@@ -11,7 +11,7 @@ define Package/gluon-mesh-batman-adv-core
   SECTION:=gluon
   CATEGORY:=Gluon
   TITLE:=Support for batman-adv meshing (core)
-  DEPENDS:=+gluon-core +firewall +kmod-ipt-nathelper
+  DEPENDS:=+gluon-core +firewall +kmod-ipt-nathelper +libiwinfo-lua
 endef
 
 define Build/Prepare
diff --git a/package/gluon-mesh-batman-adv-core/files/lib/gluon/announce/neighbours.d/batadv b/package/gluon-mesh-batman-adv-core/files/lib/gluon/announce/neighbours.d/batadv
new file mode 100644
index 000000000..f93a11f9c
--- /dev/null
+++ b/package/gluon-mesh-batman-adv-core/files/lib/gluon/announce/neighbours.d/batadv
@@ -0,0 +1,41 @@
+local json = require 'luci.json'
+local util = require 'luci.util'
+local fs = require 'nixio.fs'
+
+local ifname_address_cache = {}
+
+function ifname2address(ifname)
+  local ifaddress
+  if ifname_address_cache[ifname] ~= nil then
+    ifaddress = ifname_address_cache[ifname]
+  else
+    ifaddress = util.trim(fs.readfile("/sys/class/net/" .. ifname .. "/address"))
+    ifname_address_cache[ifname] = ifaddress
+  end
+
+  return ifaddress
+end
+
+function batadv()
+  local interfaces = {}
+  local list = io.lines("/sys/kernel/debug/batman_adv/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 = {} }
+      end
+
+      interfaces[ifaddress].neighbours[mac1] = { tq = tonumber(tq)
+                                               , lastseen = tonumber(lastseen)
+                                               }
+    end
+  end
+
+  return interfaces
+end
+
+return batadv()
diff --git a/package/gluon-mesh-batman-adv-core/files/lib/gluon/announce/neighbours.d/wifi b/package/gluon-mesh-batman-adv-core/files/lib/gluon/announce/neighbours.d/wifi
new file mode 100644
index 000000000..d37542223
--- /dev/null
+++ b/package/gluon-mesh-batman-adv-core/files/lib/gluon/announce/neighbours.d/wifi
@@ -0,0 +1,41 @@
+local json = require 'luci.json'
+local util = require 'luci.util'
+local fs = require 'nixio.fs'
+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
+
+  return stations
+end
+
+function interfaces()
+  local interfaces = {}
+  for _, line in ipairs(util.split(util.exec('batctl if'))) do
+    ifname = line:match('^(.-): active')
+    if ifname ~= nil then
+      pcall(function()
+        local address = util.trim(fs.readfile('/sys/class/net/' .. ifname .. '/address'))
+        local wifitype = iwinfo.type(ifname)
+        if wifitype ~= nil then
+          interfaces[address] = { ifname = ifname, iw = iwinfo[wifitype] }
+        end
+      end)
+    end
+  end
+
+  return interfaces
+end
+
+local wifi = {}
+for address, iface in pairs(interfaces()) do
+  wifi[address] = { neighbours = neighbours(iface) }
+end
+
+return wifi
-- 
GitLab