add wlan quality and ssid

phoen
Daniel Barlow 2022-04-03 12:41:15 +01:00
parent 7ae4284dc0
commit 8943c1d652
2 changed files with 62 additions and 14 deletions

View File

@ -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 {

View File

@ -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")
)))