From db60e8f5879985fb9cee89e4eafb76a1214dc838 Mon Sep 17 00:00:00 2001 From: Chris Fiege Date: Sun, 4 Aug 2024 14:36:43 +0200 Subject: [PATCH] Add ffbs-debugbathosts This package provides means to map MAC addresses to names for `batctl`. This is done with two components: * `/etc/bat-hosts` is a mapping file consumed by `batctl`. It is delivered empty and only contains help for the user. It is mostly intended as a reminder that this functions exists at all. * `update-bat-hosts` is a lua-script that loads a `nodes.json` from a given URL and populates `/etc/bat-hosts` with the nodes found. The script `update-bat-hosts` is only intended to be run by an experienced user by hand to ease debugging. The result is directly written into to `/etc/` and thus, usually, into flash memory. The number of write/erase cycles caused by this should be negligible. --- ffbs-debugbathosts/Makefile | 23 +++++ ffbs-debugbathosts/README.md | 12 +++ ffbs-debugbathosts/files/etc/bat-hosts | 9 ++ .../files/usr/sbin/update-bat-hosts | 95 +++++++++++++++++++ 4 files changed, 139 insertions(+) create mode 100644 ffbs-debugbathosts/Makefile create mode 100644 ffbs-debugbathosts/README.md create mode 100644 ffbs-debugbathosts/files/etc/bat-hosts create mode 100755 ffbs-debugbathosts/files/usr/sbin/update-bat-hosts diff --git a/ffbs-debugbathosts/Makefile b/ffbs-debugbathosts/Makefile new file mode 100644 index 00000000..a0ab5a17 --- /dev/null +++ b/ffbs-debugbathosts/Makefile @@ -0,0 +1,23 @@ +include $(TOPDIR)/rules.mk + +PKG_NAME:=ffbs-debugbathosts +PKG_VERSION:=1 +PKG_RELEASE:=1 + +PKG_MAINTAINER:=Chris Fiege +PKG_LICENSE:=MIT + +include $(TOPDIR)/../package/gluon.mk + +define Package/$(PKG_NAME) + TITLE:=Provide /etc/bat-hosts. +endef + +define Package/$(PKG_NAME)/description + This package provides an empty /etc/bat-hosts file and the script + update-bat-hosts that populates /etc/bat-hosts with entries from + a given nodes.json. +endef + +$(eval $(call BuildPackageGluon,$(PKG_NAME))) + diff --git a/ffbs-debugbathosts/README.md b/ffbs-debugbathosts/README.md new file mode 100644 index 00000000..565945fd --- /dev/null +++ b/ffbs-debugbathosts/README.md @@ -0,0 +1,12 @@ +ffbs-debugbathosts +================== + +This script provides means to map MAC addresses to names for `batctl`. + +This is done with two components: + +* `/etc/bat-hosts` is a mapping file consumed by `batctl`. + It is delivered empty and only contains help for the user. + It is mostly intended as a reminder that this functions exists at all. +* `update-bat-hosts` is a lua-script that loads a `nodes.json` from a given URL + and populates `/etc/bat-hosts` with the nodes found. diff --git a/ffbs-debugbathosts/files/etc/bat-hosts b/ffbs-debugbathosts/files/etc/bat-hosts new file mode 100644 index 00000000..f8cca58a --- /dev/null +++ b/ffbs-debugbathosts/files/etc/bat-hosts @@ -0,0 +1,9 @@ +# Map mac addresses to names for batctl +# Format: +# +# +# For your convenience the following script populates this file for you: +# $ update-bat-hosts [--gw] + +# example: +00:1f:16:12:8f:ae chrissi-korolev-eth diff --git a/ffbs-debugbathosts/files/usr/sbin/update-bat-hosts b/ffbs-debugbathosts/files/usr/sbin/update-bat-hosts new file mode 100755 index 00000000..4225afff --- /dev/null +++ b/ffbs-debugbathosts/files/usr/sbin/update-bat-hosts @@ -0,0 +1,95 @@ +#!/usr/bin/lua +-- SPDX-FileCopyrightText: Florian Maurer +-- SPDX-License-Identifier: MIT + +local jsonc = require("jsonc") + +local function truncate_hostname(hostname, max_length) + -- If the hostname is already within the maximum length, return it as is + if #hostname <= max_length then + return hostname + end + + -- Define the number of characters to keep at the start and end + local keep_start = math.floor((max_length - 3) / 2) + local keep_end = max_length - 3 - keep_start + + -- Concatenate the start, ellipses, and end of the hostname + return hostname:sub(1, keep_start) .. "..." .. hostname:sub(-keep_end) +end + +-- Function to fetch JSON data using wget +local function fetch_json_from_url(url) + local tmpfile = "/tmp/nodes.json" -- Temporary file to store the downloaded JSON data + local success = os.execute("wget -q -O " .. tmpfile .. " " .. url) + if success > 0 then + error("Failed to download JSON file from " .. url) + end + local file = io.open(tmpfile, "r") + if not file then + error("Failed to open the downloaded JSON file") + end + + local json_data = file:read("*all") + file:close() + + return json_data +end + +-- Function to parse the JSON data and output MAC addresses with hostnames +local function parse_and_print_mac_addresses(json_data, gateway_only) + local data = jsonc.parse(json_data) + if not data then + error("Failed to parse JSON data") + end + local seen_hostnames = {} -- Table to keep track of seen hostnames + + local file = io.open("/tmp/bat-hosts", "w") + if not file then + error("Failed to open /tmp/bat-hosts") + end + + file:write("# map mac addresses to names for batctl\n") + file:write("# format:\n") + file:write("# \n") + file:write("#\n") + file:write("# For your convenience the following script populates this file for you:\n") + file:write("# $ update-bat-hosts [--gw]\n\n") + + -- Iterate over nodes and extract MAC addresses with corresponding hostnames + for _, node in ipairs(data.nodes) do + local hostname = truncate_hostname(node.nodeinfo.hostname:gsub("%s", "-"), 30) + local mesh = node.nodeinfo.network.mesh + + -- only parse if gateway filter is off or is gateway + -- and if mesh info exists and host was not seen yet (otherwise this would give warnings) + if (not gateway_only or node.flags.gateway) and mesh and not seen_hostnames[hostname] then + seen_hostnames[hostname] = true + for _, mesh_interface in pairs(mesh) do + local interfaces = mesh_interface.interfaces + -- Loop through wireless, other, and tunnel interfaces + for iface, mac_list in pairs(interfaces) do + for idx, mac in ipairs(mac_list) do + file:write(mac .. " " .. hostname .. "-" .. iface .. "" .. idx .. "\n") + end + end + end + end + end +end + +if #arg == 0 then + print("Useage: update-bat-hosts [--gw]") + os.exit(1) +end + +local url = arg[1] + +local gateway_only = false +if #arg == 2 and arg[2] == '--gw' then + gateway_only = true +end + +local json_data = fetch_json_from_url(url) +parse_and_print_mac_addresses(json_data, gateway_only) +os.execute("mv /tmp/bat-hosts /etc/bat-hosts")