luci-mod-network: add admin/network/remote_addr endpoint
authorJo-Philipp Wich <jo@mein.io>
Sun, 3 Nov 2019 16:26:22 +0000 (17:26 +0100)
committerJo-Philipp Wich <jo@mein.io>
Sun, 3 Nov 2019 16:56:58 +0000 (17:56 +0100)
The remote_addr endpoint allows clients to query their external IP address
as seen by the device as well as the inbound network devices and logical
interfaces on the router.

Signed-off-by: Jo-Philipp Wich <jo@mein.io>
modules/luci-mod-network/luasrc/controller/admin/network.lua

index 9f6a568b07a1d18e5dd601075b7483269828edb7..1d99564631a831dad216bb770ae42ac263eb90a1 100644 (file)
@@ -18,6 +18,9 @@ function index()
                page = entry({"admin", "network", "iface_down"}, post("iface_down"), nil)
                page.leaf = true
 
+               page = entry({"admin", "network", "remote_addr"}, call("remote_addr"), nil)
+               page.leaf = true
+
                page = entry({"admin", "network", "network"}, view("network/interfaces"), _("Interfaces"), 10)
                page.leaf   = true
                page.subindex = true
@@ -117,6 +120,60 @@ function iface_down(iface, force)
        luci.http.status(404, "No such interface")
 end
 
+function remote_addr()
+       local uci    = require "luci.model.uci"
+       local peer   = luci.http.getenv("REMOTE_ADDR")
+       local serv   = luci.http.getenv("SERVER_ADDR")
+       local device = addr2dev(peer, serv)
+       local ifaces = luci.util.ubus("network.interface", "dump")
+       local indevs = {}
+       local inifs  = {}
+
+       local result = {
+               remote_addr        = peer,
+               server_addr        = serv,
+               inbound_devices    = {},
+               inbound_interfaces = {}
+       }
+
+       if type(ifaces) == "table" and type(ifaces.interface) == "table" then
+               for _, iface in ipairs(ifaces.interface) do
+                       if type(iface) == "table" then
+                               if iface.device == device or iface.l3_device == device then
+                                       inifs[iface.interface] = true
+                                       indevs[device] = true
+                               end
+
+                               local peeraddr = uci:get("network", iface.interface, "peeraddr")
+                               for _, ai in ipairs(peeraddr and nixio.getaddrinfo(peeraddr) or {}) do
+                                       local peerdev = addr2dev(ai.address)
+                                       if peerdev then
+                                               for _, iface in ipairs(ifaces.interface) do
+                                                       if type(iface) == "table" and
+                                                          (iface.device == peerdev or iface.l3_device == peerdev)
+                                                       then
+                                                               inifs[iface.interface] = true
+                                                               indevs[peerdev] = true
+                                                       end
+                                               end
+                                       end
+                               end
+                       end
+               end
+       end
+
+       for k in pairs(inifs) do
+               result.inbound_interfaces[#result.inbound_interfaces + 1] = k
+       end
+
+       for k in pairs(indevs) do
+               result.inbound_devices[#result.inbound_devices + 1] = k
+       end
+
+       luci.http.prepare_content("application/json")
+       luci.http.write_json(result)
+end
+
 function diag_command(cmd, addr)
        if addr and addr:match("^[a-zA-Z0-9%-%.:_]+$") then
                luci.http.prepare_content("text/plain")