From 8943c1d65247d74a8b5ddc11a887a6811ead4237 Mon Sep 17 00:00:00 2001 From: Daniel Barlow Date: Sun, 3 Apr 2022 12:41:15 +0100 Subject: [PATCH] add wlan quality and ssid --- blinkenlicht/default.nix | 3 ++ blinkenlicht/nl.fnl | 73 ++++++++++++++++++++++++++++++++-------- 2 files changed, 62 insertions(+), 14 deletions(-) diff --git a/blinkenlicht/default.nix b/blinkenlicht/default.nix index 6b6dbfc..60fd7c4 100644 --- a/blinkenlicht/default.nix +++ b/blinkenlicht/default.nix @@ -20,11 +20,14 @@ let hash = "sha256:1nha32yilzagfwrs44hc763jgwxd700kaik1is7x7lsjjvkgapw7"; }; + netlink = lua53Packages.callPackage ./netlink.nix {}; + lua = lua5_3.withPackages (ps: with ps; [ lgi luafilesystem luaposix readline + netlink ]); in stdenv.mkDerivation { diff --git a/blinkenlicht/nl.fnl b/blinkenlicht/nl.fnl index 6be61c0..fb60e20 100644 --- a/blinkenlicht/nl.fnl +++ b/blinkenlicht/nl.fnl @@ -4,19 +4,61 @@ (table.concat (nl.groups) ", "))) (local nls (nl.socket)) -;; when we have a default route, we get the ifname - ;; $ grep DEVTYPE /sys/class/net/*/uevent ;; /sys/class/net/docker0/uevent:DEVTYPE=bridge ;; /sys/class/net/wlp4s0/uevent:DEVTYPE=wlan ;; /sys/class/net/wwp0s20f0u2i12/uevent:DEVTYPE=wwan ;; (ethernet and loopback devices don't have DEVTYPE) +(fn devtype [ifname] + (with-open [f (io.open (.. "/sys/class/net/" ifname "/uevent") :r)] + (accumulate [dtype nil + line #(f:read "*l") + :until dtype] + (let [(name value) (line:match "([^=]+)=(.+)")] + (if (= name "DEVTYPE") value dtype))))) + ;; if the type is wlan, we can get a signal strength indicator ;; from the "quality - link" column of /proc/net/wireless -;; for wwan, need to determine how to get strength and carrier name +(fn wlan-link-quality [ifname] + (with-open [f (io.open "/proc/net/wireless" :r)] + (accumulate [strength nil + line #(f:read "*l") + :until strength] + ;; "%6s: %04x %3d%c %3d%c %3d%c %6d %6d %6d " + ;; "%6d %6d %6d\n", + ;; https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/wireless/wext-proc.c#n49 + (let [(name status link level) + (line:match "(.-): +(%x+) +(%S-)[ .] +(%S-)[ .]")] + (if (= name ifname) + (tonumber level) + strength))))) + +(fn wlan-link-ssid [ifname] + ;; could do this directly using an ioctl + ;; http://papermint-designs.com/dmo-blog/2016-08-how-to-get-the-essid-of-the-wifi-network-you-are-connected-to-# + (with-open [f (io.popen (.. "iwgetid " ifname " --raw") :r)] + (f:read "*l"))) + +(fn get-network-info [event] + ;; augments a newlink event with relevant information, if it's + ;; sufficiently well-configured to have any + + ;; "up" => administratively up + ;; "running" => can actually exchange packets + (when (= event.running "yes") + (let [dtype (devtype event.name)] + (tset event :devtype dtype) + (when (= dtype "wlan") + (if (not event.ssid) + (tset event :ssid (wlan-link-ssid event.name))) + (tset event :quality (wlan-link-quality event.name))) + (when (= dtype "wwan") + ;; for wwan, need to determine how to get strength and carrier name + ))) + event) (fn netlunk [] @@ -25,15 +67,13 @@ (fn handle-event [event] (match event {:event :newlink} - (match event.up - "yes" (tset links event.index event) - "no" (tset links event.index nil)) + (tset links event.index + (match event.up + "yes" (get-network-info event) + "no" event)) {:event :newroute} - (tset routes (or event.dst "default") - (if (. links event.index) - event - nil)) + (tset routes (or event.dst "default") event) {} (print :unhandled event.event) )) @@ -44,7 +84,12 @@ :refresh #(each [_ event (ipairs (nls:event))] (handle-event event)) :fd (nls:fd) - :uplink (fn [self] routes.default) + :uplink (fn [self] + (let [defaultroute routes.default + interface (and defaultroute + (. links defaultroute.index))] + (and interface (= interface.running "yes") + (get-network-info interface)))) :wait #(nls:poll 1000) :interface (fn [self ifnum] (. links ifnum)) } @@ -54,9 +99,9 @@ (while (or (nl:wait) true) (nl:refresh) (match (nl:uplink) - {:index ifnum} - (print "default route through " (. (nl:interface ifnum) :name)) - {} + interface + (print "default route through " (view interface)) + nil (print "no default route") )))