diff options
author | Jo-Philipp Wich <jow@openwrt.org> | 2014-12-03 15:17:05 +0100 |
---|---|---|
committer | Jo-Philipp Wich <jow@openwrt.org> | 2015-01-08 16:26:20 +0100 |
commit | 1bb4822dca6113f73e3bc89e2acf15935e6f8e92 (patch) | |
tree | 35e16f100466e4e00657199b38bb3d87d52bf73f /applications/luci-app-olsr/luasrc | |
parent | 9edd0e46c3f880727738ce8ca6ff1c8b85f99ef4 (diff) |
Rework LuCI build system
* Rename subdirectories to their repective OpenWrt package names
* Make each LuCI module its own standalone package
* Deploy a shared luci.mk which is used by each module Makefile
Signed-off-by: Jo-Philipp Wich <jow@openwrt.org>
Diffstat (limited to 'applications/luci-app-olsr/luasrc')
24 files changed, 3485 insertions, 0 deletions
diff --git a/applications/luci-app-olsr/luasrc/controller/olsr.lua b/applications/luci-app-olsr/luasrc/controller/olsr.lua new file mode 100644 index 000000000..4573f690b --- /dev/null +++ b/applications/luci-app-olsr/luasrc/controller/olsr.lua @@ -0,0 +1,413 @@ +module("luci.controller.olsr", package.seeall) + +function index() + local ipv4,ipv6 + if nixio.fs.access("/etc/config/olsrd") then + ipv4 = 1 + end + if nixio.fs.access("/etc/config/olsrd6") then + ipv6 = 1 + end + if not ipv4 and not ipv6 then + return + end + + require("luci.model.uci") + local uci = luci.model.uci.cursor_state() + + uci:foreach("olsrd", "olsrd", function(s) + if s.SmartGateway and s.SmartGateway == "yes" then has_smartgw = true end + end) + + local page = node("admin", "status", "olsr") + page.target = template("status-olsr/overview") + page.title = _("OLSR") + page.subindex = true + + local page = node("admin", "status", "olsr", "json") + page.target = call("action_json") + page.title = nil + page.leaf = true + + local page = node("admin", "status", "olsr", "neighbors") + page.target = call("action_neigh") + page.title = _("Neighbours") + page.subindex = true + page.order = 5 + + local page = node("admin", "status", "olsr", "routes") + page.target = call("action_routes") + page.title = _("Routes") + page.order = 10 + + local page = node("admin", "status", "olsr", "topology") + page.target = call("action_topology") + page.title = _("Topology") + page.order = 20 + + local page = node("admin", "status", "olsr", "hna") + page.target = call("action_hna") + page.title = _("HNA") + page.order = 30 + + local page = node("admin", "status", "olsr", "mid") + page.target = call("action_mid") + page.title = _("MID") + page.order = 50 + + if has_smartgw then + local page = node("admin", "status", "olsr", "smartgw") + page.target = call("action_smartgw") + page.title = _("SmartGW") + page.order = 60 + end + + local page = node("admin", "status", "olsr", "interfaces") + page.target = call("action_interfaces") + page.title = _("Interfaces") + page.order = 70 + + odsp = entry( + {"admin", "services", "olsrd", "display"}, + cbi("olsr/olsrddisplay"), _("Display") + ) + +end + +function action_json() + local http = require "luci.http" + local utl = require "luci.util" + local uci = require "luci.model.uci".cursor_state() + local jsonreq4 + local jsonreq6 + + jsonreq4 = utl.exec("echo /status | nc 127.0.0.1 9090") + jsonreq6 = utl.exec("echo /status | nc ::1 9090") + http.prepare_content("application/json") + if not jsonreq4 or jsonreq4 == "" then + jsonreq4 = "{}" + end + if not jsonreq6 or jsonreq6 == "" then + jsonreq6 = "{}" + end + http.write('{"v4":' .. jsonreq4 .. ', "v6":' .. jsonreq6 .. '}') +end + +function action_neigh(json) + local data, has_v4, has_v6, error = fetch_jsoninfo('links') + + if error then + return + end + + local uci = require "luci.model.uci".cursor_state() + local resolve = uci:get("luci_olsr", "general", "resolve") + local ntm = require "luci.model.network".init() + local devices = ntm:get_wifidevs() + local sys = require "luci.sys" + local assoclist = {} + --local neightbl = require "neightbl" + local ipc = require "luci.ip" + + luci.sys.net.routes(function(r) + if r.dest:prefix() == 0 then + defaultgw = r.gateway:string() + end + end) + + local function compare(a,b) + if a.proto == b.proto then + return a.linkCost < b.linkCost + else + return a.proto < b.proto + end + end + + for _, dev in ipairs(devices) do + for _, net in ipairs(dev:get_wifinets()) do + assoclist[#assoclist+1] = {} + assoclist[#assoclist]['ifname'] = net.iwdata.ifname + assoclist[#assoclist]['network'] = net.iwdata.network + assoclist[#assoclist]['device'] = net.iwdata.device + assoclist[#assoclist]['list'] = net.iwinfo.assoclist + end + end + + for k, v in ipairs(data) do + local interface + local snr = 0 + local signal = 0 + local noise = 0 + local arptable = sys.net.arptable() + local mac = "" + local rmac = "" + local lmac = "" + local ip + local neihgt = {} + + if resolve == "1" then + hostname = nixio.getnameinfo(v.remoteIP, nil, 100) + if hostname then + v.hostname = hostname + end + end + if v.proto == '4' then + uci:foreach("network", "interface",function(vif) + if vif.ipaddr and vif.ipaddr == v.localIP then + interface = vif['.name'] or vif.interface + lmac = string.lower(vif.macaddr or "") + return + end + end) + for _, arpt in ipairs(arptable) do + ip = arpt['IP address'] + if ip == v.remoteIP then + rmac = string.lower(arpt['HW address'] or "") + end + end + elseif v.proto == '6' then + uci:foreach("network", "interface",function(vif) + local name = vif['.name'] + local net = ntm:get_network(name) + local device = net and net:get_interface() + local locip = ipc.IPv6(v.localIP) + if device and device:ip6addrs() and locip then + for _, a in ipairs(device:ip6addrs()) do + if not a:is6linklocal() then + if a:host() == locip:host() then + interface = name + --neihgt = neightbl.get(device.ifname) or {} + end + end + end + end + end) + --[[ + for ip,mac in pairs(neihgt) do + if ip == v.remoteIP then + rmac = mac + end + end + ]]-- + end + for _, val in ipairs(assoclist) do + if val.network == interface and val.list then + for assocmac, assot in pairs(val.list) do + assocmac = string.lower(assocmac or "") + if rmac == assocmac then + signal = tonumber(assot.signal) + noise = tonumber(assot.noise) + snr = (noise*-1) - (signal*-1) + end + end + end + end + if interface then + v.interface = interface + end + v.snr = snr + v.signal = signal + v.noise = noise + if rmac then + v.remoteMAC = rmac + end + if lmac then + v.localMAC = lmac + end + + if defaultgw == v.remoteIP then + v.defaultgw = 1 + end + end + + table.sort(data, compare) + luci.template.render("status-olsr/neighbors", {links=data, has_v4=has_v4, has_v6=has_v6}) +end + +function action_routes() + local data, has_v4, has_v6, error = fetch_jsoninfo('routes') + if error then + return + end + + local uci = require "luci.model.uci".cursor_state() + local resolve = uci:get("luci_olsr", "general", "resolve") + + for k, v in ipairs(data) do + if resolve == "1" then + local hostname = nixio.getnameinfo(v.gateway, nil, 100) + if hostname then + v.hostname = hostname + end + end + end + + local function compare(a,b) + if a.proto == b.proto then + return a.rtpMetricCost < b.rtpMetricCost + else + return a.proto < b.proto + end + end + + table.sort(data, compare) + luci.template.render("status-olsr/routes", {routes=data, has_v4=has_v4, has_v6=has_v6}) +end + +function action_topology() + local data, has_v4, has_v6, error = fetch_jsoninfo('topology') + if error then + return + end + + local function compare(a,b) + if a.proto == b.proto then + return a.tcEdgeCost < b.tcEdgeCost + else + return a.proto < b.proto + end + end + + table.sort(data, compare) + luci.template.render("status-olsr/topology", {routes=data, has_v4=has_v4, has_v6=has_v6}) +end + +function action_hna() + local data, has_v4, has_v6, error = fetch_jsoninfo('hna') + if error then + return + end + + local uci = require "luci.model.uci".cursor_state() + local resolve = uci:get("luci_olsr", "general", "resolve") + + local function compare(a,b) + if a.proto == b.proto then + return a.genmask < b.genmask + else + return a.proto < b.proto + end + end + + for k, v in ipairs(data) do + if resolve == "1" then + hostname = nixio.getnameinfo(v.gateway, nil, 100) + if hostname then + v.hostname = hostname + end + end + if v.validityTime then + v.validityTime = tonumber(string.format("%.0f", v.validityTime / 1000)) + end + end + + table.sort(data, compare) + luci.template.render("status-olsr/hna", {hna=data, has_v4=has_v4, has_v6=has_v6}) +end + +function action_mid() + local data, has_v4, has_v6, error = fetch_jsoninfo('mid') + if error then + return + end + + local function compare(a,b) + if a.proto == b.proto then + return a.ipAddress < b.ipAddress + else + return a.proto < b.proto + end + end + + table.sort(data, compare) + luci.template.render("status-olsr/mid", {mids=data, has_v4=has_v4, has_v6=has_v6}) +end + +function action_smartgw() + local data, has_v4, has_v6, error = fetch_jsoninfo('gateways') + if error then + return + end + + local function compare(a,b) + if a.proto == b.proto then + return a.tcPathCost < b.tcPathCost + else + return a.proto < b.proto + end + end + + table.sort(data, compare) + luci.template.render("status-olsr/smartgw", {gws=data, has_v4=has_v4, has_v6=has_v6}) +end + +function action_interfaces() + local data, has_v4, has_v6, error = fetch_jsoninfo('interfaces') + if error then + return + end + + local function compare(a,b) + return a.proto < b.proto + end + + table.sort(data, compare) + luci.template.render("status-olsr/interfaces", {iface=data, has_v4=has_v4, has_v6=has_v6}) +end + +-- Internal +function fetch_jsoninfo(otable) + local uci = require "luci.model.uci".cursor_state() + local utl = require "luci.util" + local json = require "luci.json" + local IpVersion = uci:get_first("olsrd", "olsrd","IpVersion") + local jsonreq4 = "" + local jsonreq6 = "" + jsonreq4 = utl.exec("echo /" .. otable .. " | nc 127.0.0.1 9090") + jsonreq6 = utl.exec("echo /" .. otable .. " | nc ::1 9090") + local jsondata4 = {} + local jsondata6 = {} + local data4 = {} + local data6 = {} + local has_v4 = False + local has_v6 = False + + if jsonreq4 == '' and jsonreq6 == '' then + luci.template.render("status-olsr/error_olsr") + return nil, 0, 0, true + end + + if jsonreq4 ~= "" then + has_v4 = 1 + jsondata4 = json.decode(jsonreq4) + if otable == 'status' then + data4 = jsondata4 or {} + else + data4 = jsondata4[otable] or {} + end + + for k, v in ipairs(data4) do + data4[k]['proto'] = '4' + end + + end + if jsonreq6 ~= "" then + has_v6 = 1 + jsondata6 = json.decode(jsonreq6) + if otable == 'status' then + data6 = jsondata6 or {} + else + data6 = jsondata6[otable] or {} + end + for k, v in ipairs(data6) do + data6[k]['proto'] = '6' + end + end + + for k, v in ipairs(data6) do + table.insert(data4, v) + end + + return data4, has_v4, has_v6, false +end + diff --git a/applications/luci-app-olsr/luasrc/controller/olsr4.lua b/applications/luci-app-olsr/luasrc/controller/olsr4.lua new file mode 100644 index 000000000..31a3101bc --- /dev/null +++ b/applications/luci-app-olsr/luasrc/controller/olsr4.lua @@ -0,0 +1,47 @@ +module("luci.controller.olsr4", package.seeall) + +function index() + if not nixio.fs.access("/etc/config/olsrd") then + return + end + + require("luci.model.uci") + local uci = luci.model.uci.cursor_state() + + local ol = entry( + {"admin", "services", "olsrd"}, + cbi("olsr/olsrd"), "OLSR IPv4" + ) + ol.subindex = true + + entry( + {"admin", "services", "olsrd", "iface"}, + cbi("olsr/olsrdiface") + ).leaf = true + + entry( + {"admin", "services", "olsrd", "hna"}, + cbi("olsr/olsrdhna"), _("HNA Announcements") + ) + + oplg = entry( + {"admin", "services", "olsrd", "plugins"}, + cbi("olsr/olsrdplugins"), _("Plugins") + ) + + oplg.leaf = true + oplg.subindex = true + + local uci = require("luci.model.uci").cursor() + uci:foreach("olsrd", "LoadPlugin", + function (section) + local lib = section.library + entry( + {"admin", "services", "olsrd", "plugins", lib }, + cbi("olsr/olsrdplugins"), + nil --'Plugin "%s"' % lib:gsub("^olsrd_",""):gsub("%.so.+$","") + ) + end + ) +end + diff --git a/applications/luci-app-olsr/luasrc/controller/olsr6.lua b/applications/luci-app-olsr/luasrc/controller/olsr6.lua new file mode 100644 index 000000000..9fbaa0427 --- /dev/null +++ b/applications/luci-app-olsr/luasrc/controller/olsr6.lua @@ -0,0 +1,47 @@ +module("luci.controller.olsr6", package.seeall) + +function index() + if not nixio.fs.access("/etc/config/olsrd6") then + return + end + + require("luci.model.uci") + local uci = luci.model.uci.cursor_state() + + local ol = entry( + {"admin", "services", "olsrd6"}, + cbi("olsr/olsrd6"), "OLSR IPv6" + ) + ol.subindex = true + + entry( + {"admin", "services", "olsrd6", "iface"}, + cbi("olsr/olsrdiface6") + ).leaf = true + + entry( + {"admin", "services", "olsrd6", "hna"}, + cbi("olsr/olsrdhna6"), _("HNA6 Announcements") + ) + + oplg = entry( + {"admin", "services", "olsrd6", "plugins"}, + cbi("olsr/olsrdplugins6"), _("Plugins") + ) + + oplg.leaf = true + oplg.subindex = true + + local uci = require("luci.model.uci").cursor() + uci:foreach("olsrd6", "LoadPlugin", + function (section) + local lib = section.library + entry( + {"admin", "services", "olsrd6", "plugins", lib }, + cbi("olsr/olsrdplugins6"), + nil --'Plugin "%s"' % lib:gsub("^olsrd_",""):gsub("%.so.+$","") + ) + end + ) +end + diff --git a/applications/luci-app-olsr/luasrc/model/cbi/olsr/olsrd.lua b/applications/luci-app-olsr/luasrc/model/cbi/olsr/olsrd.lua new file mode 100644 index 000000000..46121747d --- /dev/null +++ b/applications/luci-app-olsr/luasrc/model/cbi/olsr/olsrd.lua @@ -0,0 +1,420 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth <steven@midlink.org> +Copyright 2010 Jo-Philipp Wich <xm@subsignal.org> + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +$Id$ +]]-- + +require("luci.tools.webadmin") +local fs = require "nixio.fs" +local util = require "luci.util" +local ip = require "luci.ip" + +local has_ipip = fs.glob("/etc/modules.d/[0-9]*-ipip")() + +m = Map("olsrd", translate("OLSR Daemon"), + translate("The OLSR daemon is an implementation of the Optimized Link State Routing protocol. ".. + "As such it allows mesh routing for any network equipment. ".. + "It runs on any wifi card that supports ad-hoc mode and of course on any ethernet device. ".. + "Visit <a href='http://www.olsr.org'>olsrd.org</a> for help and documentation.")) + +function m.on_parse() + local has_defaults = false + + m.uci:foreach("olsrd", "InterfaceDefaults", + function(s) + has_defaults = true + return false + end) + + if not has_defaults then + m.uci:section("olsrd", "InterfaceDefaults") + end +end + +function write_float(self, section, value) + local n = tonumber(value) + if n ~= nil then + return Value.write(self, section, "%.1f" % n) + end +end + +s = m:section(TypedSection, "olsrd", translate("General settings")) +s.anonymous = true + +s:tab("general", translate("General Settings")) +s:tab("lquality", translate("Link Quality Settings")) +s:tab("smartgw", translate("SmartGW"), not has_ipip and translate("Warning: kmod-ipip is not installed. Without kmod-ipip SmartGateway will not work, please install it.")) +s:tab("advanced", translate("Advanced Settings")) + +ipv = s:taboption("general", ListValue, "IpVersion", translate("Internet protocol"), + translate("IP-version to use. If 6and4 is selected then one olsrd instance is started for each protocol.")) +ipv:value("4", "IPv4") +ipv:value("6and4", "6and4") + + +poll = s:taboption("advanced", Value, "Pollrate", translate("Pollrate"), + translate("Polling rate for OLSR sockets in seconds. Default is 0.05.")) +poll.optional = true +poll.datatype = "ufloat" +poll.placeholder = "0.05" + +nicc = s:taboption("advanced", Value, "NicChgsPollInt", translate("Nic changes poll interval"), + translate("Interval to poll network interfaces for configuration changes (in seconds). Default is \"2.5\".")) +nicc.optional = true +nicc.datatype = "ufloat" +nicc.placeholder = "2.5" + +tos = s:taboption("advanced", Value, "TosValue", translate("TOS value"), + translate("Type of service value for the IP header of control traffic. Default is \"16\".")) +tos.optional = true +tos.datatype = "uinteger" +tos.placeholder = "16" + +fib = s:taboption("general", ListValue, "FIBMetric", translate("FIB metric"), + translate ("FIBMetric controls the metric value of the host-routes OLSRd sets. ".. + "\"flat\" means that the metric value is always 2. This is the preferred value ".. + "because it helps the linux kernel routing to clean up older routes. ".. + "\"correct\" uses the hopcount as the metric value. ".. + "\"approx\" use the hopcount as the metric value too, but does only update the hopcount if the nexthop changes too. ".. + "Default is \"flat\".")) +fib:value("flat") +fib:value("correct") +fib:value("approx") + +lql = s:taboption("lquality", ListValue, "LinkQualityLevel", translate("LQ level"), + translate("Link quality level switch between hopcount and cost-based (mostly ETX) routing.<br />".. + "<b>0</b> = do not use link quality<br />".. + "<b>2</b> = use link quality for MPR selection and routing<br />".. + "Default is \"2\"")) +lql:value("2") +lql:value("0") + +lqage = s:taboption("lquality", Value, "LinkQualityAging", translate("LQ aging"), + translate("Link quality aging factor (only for lq level 2). Tuning parameter for etx_float and etx_fpm, smaller values ".. + "mean slower changes of ETX value. (allowed values are between 0.01 and 1.0)")) +lqage.optional = true +lqage:depends("LinkQualityLevel", "2") + +lqa = s:taboption("lquality", ListValue, "LinkQualityAlgorithm", translate("LQ algorithm"), + translate("Link quality algorithm (only for lq level 2).<br />".. + "<b>etx_float</b>: floating point ETX with exponential aging<br />".. + "<b>etx_fpm</b> : same as etx_float, but with integer arithmetic<br />".. + "<b>etx_ff</b> : ETX freifunk, an etx variant which use all OLSR traffic (instead of only hellos) for ETX calculation<br />".. + "<b>etx_ffeth</b>: incompatible variant of etx_ff that allows ethernet links with ETX 0.1.<br />".. + "Defaults to \"etx_ff\"")) +lqa.optional = true +lqa:value("etx_ff") +lqa:value("etx_fpm") +lqa:value("etx_float") +lqa:value("etx_ffeth") +lqa:depends("LinkQualityLevel", "2") +lqa.optional = true + +lqfish = s:taboption("lquality", Flag, "LinkQualityFishEye", translate("LQ fisheye"), + translate("Fisheye mechanism for TCs (checked means on). Default is \"on\"")) +lqfish.default = "1" +lqfish.optional = true + +hyst = s:taboption("lquality", Flag, "UseHysteresis", translate("Use hysteresis"), + translate("Hysteresis for link sensing (only for hopcount metric). Hysteresis adds more robustness to the link sensing ".. + "but delays neighbor registration. Defaults is \"yes\"")) +hyst.default = "yes" +hyst.enabled = "yes" +hyst.disabled = "no" +hyst:depends("LinkQualityLevel", "0") +hyst.optional = true +hyst.rmempty = true + +port = s:taboption("general", Value, "OlsrPort", translate("Port"), + translate("The port OLSR uses. This should usually stay at the IANA assigned port 698. It can have a value between 1 and 65535.")) +port.optional = true +port.default = "698" +port.rmempty = true + +mainip = s:taboption("general", Value, "MainIp", translate("Main IP"), + translate("Sets the main IP (originator ip) of the router. This IP will NEVER change during the uptime of olsrd. ".. + "Default is 0.0.0.0, which triggers usage of the IP of the first interface.")) +mainip.optional = true +mainip.rmempty = true +mainip.datatype = "ipaddr" +mainip.placeholder = "0.0.0.0" + +sgw = s:taboption("smartgw", Flag, "SmartGateway", translate("Enable"), translate("Enable SmartGateway. If it is disabled, then " .. + "all other SmartGateway parameters are ignored. Default is \"no\".")) +sgw.default="no" +sgw.enabled="yes" +sgw.disabled="no" +sgw.rmempty = true + +sgwnat = s:taboption("smartgw", Flag, "SmartGatewayAllowNAT", translate("Allow gateways with NAT"), translate("Allow the selection of an outgoing ipv4 gateway with NAT")) +sgwnat:depends("SmartGateway", "yes") +sgwnat.default="yes" +sgwnat.enabled="yes" +sgwnat.disabled="no" +sgwnat.optional = true +sgwnat.rmempty = true + +sgwuplink = s:taboption("smartgw", ListValue, "SmartGatewayUplink", translate("Announce uplink"), translate("Which kind of uplink is exported to the other mesh nodes. " .. + "An uplink is detected by looking for a local HNA of 0.0.0.0/0, ::ffff:0:0/96 or 2000::/3. Default setting is \"both\".")) +sgwuplink:value("none") +sgwuplink:value("ipv4") +sgwuplink:value("ipv6") +sgwuplink:value("both") +sgwuplink:depends("SmartGateway", "yes") +sgwuplink.default="both" +sgwuplink.optional = true +sgwuplink.rmempty = true + +sgwulnat = s:taboption("smartgw", Flag, "SmartGatewayUplinkNAT", translate("Uplink uses NAT"), translate("If this Node uses NAT for connections to the internet. " .. + "Default is \"yes\".")) +sgwulnat:depends("SmartGatewayUplink", "ipv4") +sgwulnat:depends("SmartGatewayUplink", "both") +sgwulnat.default="yes" +sgwulnat.enabled="yes" +sgwulnat.disabled="no" +sgwnat.optional = true +sgwnat.rmempty = true + +sgwspeed = s:taboption("smartgw", Value, "SmartGatewaySpeed", translate("Speed of the uplink"), translate("Specifies the speed of ".. + "the uplink in kilobits/s. First parameter is upstream, second parameter is downstream. Default is \"128 1024\".")) +sgwspeed:depends("SmartGatewayUplink", "ipv4") +sgwspeed:depends("SmartGatewayUplink", "ipv6") +sgwspeed:depends("SmartGatewayUplink", "both") +sgwspeed.optional = true +sgwspeed.rmempty = true + +sgwprefix = s:taboption("smartgw", Value, "SmartGatewayPrefix", translate("IPv6-Prefix of the uplink"), translate("This can be used " .. + "to signal the external IPv6 prefix of the uplink to the clients. This might allow a client to change it's local IPv6 address to " .. + "use the IPv6 gateway without any kind of address translation. The maximum prefix length is 64 bits. " .. + "Default is \"::/0\" (no prefix).")) +sgwprefix:depends("SmartGatewayUplink", "ipv6") +sgwprefix:depends("SmartGatewayUplink", "both") +sgwprefix.optional = true +sgwprefix.rmempty = true + +willingness = s:taboption("advanced", ListValue, "Willingness", translate("Willingness"), + translate("The fixed willingness to use. If not set willingness will be calculated dynamically based on battery/power status. Default is \"3\".")) +for i=0,7 do + willingness:value(i) +end +willingness.optional = true +willingness.default = "3" + +natthr = s:taboption("advanced", Value, "NatThreshold", translate("NAT threshold"), + translate("If the route to the current gateway is to be changed, the ETX value of this gateway is ".. + "multiplied with this value before it is compared to the new one. ".. + "The parameter can be a value between 0.1 and 1.0, but should be close to 1.0 if changed.<br />".. + "<b>WARNING:</b> This parameter should not be used together with the etx_ffeth metric!<br />".. + "Defaults to \"1.0\".")) +for i=1,0.1,-0.1 do + natthr:value(i) +end +natthr:depends("LinkQualityAlgorithm", "etx_ff") +natthr:depends("LinkQualityAlgorithm", "etx_float") +natthr:depends("LinkQualityAlgorithm", "etx_fpm") +natthr.default = "1.0" +natthr.optional = true +natthr.write = write_float + + +i = m:section(TypedSection, "InterfaceDefaults", translate("Interfaces Defaults")) +i.anonymous = true +i.addremove = false + +i:tab("general", translate("General Settings")) +i:tab("addrs", translate("IP Addresses")) +i:tab("timing", translate("Timing and Validity")) + +mode = i:taboption("general", ListValue, "Mode", translate("Mode"), + translate("Interface Mode is used to prevent unnecessary packet forwarding on switched ethernet interfaces. ".. + "valid Modes are \"mesh\" and \"ether\". Default is \"mesh\".")) +mode:value("mesh") +mode:value("ether") +mode.optional = true +mode.rmempty = true + + +weight = i:taboption("general", Value, "Weight", translate("Weight"), + translate("When multiple links exist between hosts the weight of interface is used to determine the link to use. ".. + "Normally the weight is automatically calculated by olsrd based on the characteristics of the interface, ".. + "but here you can specify a fixed value. Olsrd will choose links with the lowest value.<br />".. + "<b>Note:</b> Interface weight is used only when LinkQualityLevel is set to 0. ".. + "For any other value of LinkQualityLevel, the interface ETX value is used instead.")) +weight.optional = true +weight.datatype = "uinteger" +weight.placeholder = "0" + +lqmult = i:taboption("general", DynamicList, "LinkQualityMult", translate("LinkQuality Multiplicator"), + translate("Multiply routes with the factor given here. Allowed values are between 0.01 and 1.0. ".. + "It is only used when LQ-Level is greater than 0. Examples:<br />".. + "reduce LQ to 192.168.0.1 by half: 192.168.0.1 0.5<br />".. + "reduce LQ to all nodes on this interface by 20%: default 0.8")) +lqmult.optional = true +lqmult.rmempty = true +lqmult.cast = "table" +lqmult.placeholder = "default 1.0" + +function lqmult.validate(self, value) + for _, v in pairs(value) do + if v ~= "" then + local val = util.split(v, " ") + local host = val[1] + local mult = val[2] + if not host or not mult then + return nil, translate("LQMult requires two values (IP address or 'default' and multiplicator) seperated by space.") + end + if not (host == "default" or ip.IPv4(host) or ip.IPv6(host)) then + return nil, translate("Can only be a valid IPv4 or IPv6 address or 'default'") + end + if not tonumber(mult) or tonumber(mult) > 1 or tonumber(mult) < 0.01 then + return nil, translate("Invalid Value for LQMult-Value. Must be between 0.01 and 1.0.") + end + if not mult:match("[0-1]%.[0-9]+") then + return nil, translate("Invalid Value for LQMult-Value. You must use a decimal number between 0.01 and 1.0 here.") + end + end + end + return value +end + +ip4b = i:taboption("addrs", Value, "Ip4Broadcast", translate("IPv4 broadcast"), + translate("IPv4 broadcast address for outgoing OLSR packets. One useful example would be 255.255.255.255. ".. + "Default is \"0.0.0.0\", which triggers the usage of the interface broadcast IP.")) +ip4b.optional = true +ip4b.datatype = "ip4addr" +ip4b.placeholder = "0.0.0.0" + +ip6m = i:taboption("addrs", Value, "IPv6Multicast", translate("IPv6 multicast"), + translate("IPv6 multicast address. Default is \"FF02::6D\", the manet-router linklocal multicast.")) +ip6m.optional = true +ip6m.datatype = "ip6addr" +ip6m.placeholder = "FF02::6D" + +ip4s = i:taboption("addrs", Value, "IPv4Src", translate("IPv4 source"), + translate("IPv4 src address for outgoing OLSR packages. Default is \"0.0.0.0\", which triggers usage of the interface IP.")) +ip4s.optional = true +ip4s.datatype = "ip4addr" +ip4s.placeholder = "0.0.0.0" + +ip6s = i:taboption("addrs", Value, "IPv6Src", translate("IPv6 source"), + translate("IPv6 src prefix. OLSRd will choose one of the interface IPs which matches the prefix of this parameter. ".. + "Default is \"0::/0\", which triggers the usage of a not-linklocal interface IP.")) +ip6s.optional = true +ip6s.datatype = "ip6addr" +ip6s.placeholder = "0::/0" + + +hi = i:taboption("timing", Value, "HelloInterval", translate("Hello interval")) +hi.optional = true +hi.datatype = "ufloat" +hi.placeholder = "5.0" +hi.write = write_float + +hv = i:taboption("timing", Value, "HelloValidityTime", translate("Hello validity time")) +hv.optional = true +hv.datatype = "ufloat" +hv.placeholder = "40.0" +hv.write = write_float + +ti = i:taboption("timing", Value, "TcInterval", translate("TC interval")) +ti.optional = true +ti.datatype = "ufloat" +ti.placeholder = "2.0" +ti.write = write_float + +tv = i:taboption("timing", Value, "TcValidityTime", translate("TC validity time")) +tv.optional = true +tv.datatype = "ufloat" +tv.placeholder = "256.0" +tv.write = write_float + +mi = i:taboption("timing", Value, "MidInterval", translate("MID interval")) +mi.optional = true +mi.datatype = "ufloat" +mi.placeholder = "18.0" +mi.write = write_float + +mv = i:taboption("timing", Value, "MidValidityTime", translate("MID validity time")) +mv.optional = true +mv.datatype = "ufloat" +mv.placeholder = "324.0" +mv.write = write_float + +ai = i:taboption("timing", Value, "HnaInterval", translate("HNA interval")) +ai.optional = true +ai.datatype = "ufloat" +ai.placeholder = "18.0" +ai.write = write_float + +av = i:taboption("timing", Value, "HnaValidityTime", translate("HNA validity time")) +av.optional = true +av.datatype = "ufloat" +av.placeholder = "108.0" +av.write = write_float + + +ifs = m:section(TypedSection, "Interface", translate("Interfaces")) +ifs.addremove = true +ifs.anonymous = true +ifs.extedit = luci.dispatcher.build_url("admin/services/olsrd/iface/%s") +ifs.template = "cbi/tblsection" + +function ifs.create(...) + local sid = TypedSection.create(...) + luci.http.redirect(ifs.extedit % sid) +end + +ign = ifs:option(Flag, "ignore", translate("Enable")) +ign.enabled = "0" +ign.disabled = "1" +ign.rmempty = false +function ign.cfgvalue(self, section) + return Flag.cfgvalue(self, section) or "0" +end + +network = ifs:option(DummyValue, "interface", translate("Network")) +network.template = "cbi/network_netinfo" + +mode = ifs:option(DummyValue, "Mode", translate("Mode")) +function mode.cfgvalue(...) + return Value.cfgvalue(...) or m.uci:get_first("olsrd", "InterfaceDefaults", "Mode", "mesh") +end + +hello = ifs:option(DummyValue, "_hello", translate("Hello")) +function hello.cfgvalue(self, section) + local i = tonumber(m.uci:get("olsrd", section, "HelloInterval")) or tonumber(m.uci:get_first("olsrd", "InterfaceDefaults", "HelloInterval", 5)) + local v = tonumber(m.uci:get("olsrd", section, "HelloValidityTime")) or tonumber(m.uci:get_first("olsrd", "InterfaceDefaults", "HelloValidityTime", 40)) + return "%.01fs / %.01fs" %{ i, v } +end + +tc = ifs:option(DummyValue, "_tc", translate("TC")) +function tc.cfgvalue(self, section) + local i = tonumber(m.uci:get("olsrd", section, "TcInterval")) or tonumber(m.uci:get_first("olsrd", "InterfaceDefaults", "TcInterval", 2)) + local v = tonumber(m.uci:get("olsrd", section, "TcValidityTime")) or tonumber(m.uci:get_first("olsrd", "InterfaceDefaults", "TcValidityTime", 256)) + return "%.01fs / %.01fs" %{ i, v } +end + +mid = ifs:option(DummyValue, "_mid", translate("MID")) +function mid.cfgvalue(self, section) + local i = tonumber(m.uci:get("olsrd", section, "MidInterval")) or tonumber(m.uci:get_first("olsrd", "InterfaceDefaults", "MidInterval", 18)) + local v = tonumber(m.uci:get("olsrd", section, "MidValidityTime")) or tonumber(m.uci:get_first("olsrd", "InterfaceDefaults", "MidValidityTime", 324)) + return "%.01fs / %.01fs" %{ i, v } +end + +hna = ifs:option(DummyValue, "_hna", translate("HNA")) +function hna.cfgvalue(self, section) + local i = tonumber(m.uci:get("olsrd", section, "HnaInterval")) or tonumber(m.uci:get_first("olsrd", "InterfaceDefaults", "HnaInterval", 18)) + local v = tonumber(m.uci:get("olsrd", section, "HnaValidityTime")) or tonumber(m.uci:get_first("olsrd", "InterfaceDefaults", "HnaValidityTime", 108)) + return "%.01fs / %.01fs" %{ i, v } +end + +return m diff --git a/applications/luci-app-olsr/luasrc/model/cbi/olsr/olsrd6.lua b/applications/luci-app-olsr/luasrc/model/cbi/olsr/olsrd6.lua new file mode 100644 index 000000000..2b8d60cd1 --- /dev/null +++ b/applications/luci-app-olsr/luasrc/model/cbi/olsr/olsrd6.lua @@ -0,0 +1,401 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth <steven@midlink.org> +Copyright 2010 Jo-Philipp Wich <xm@subsignal.org> + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +$Id$ +]]-- + +require("luci.tools.webadmin") +local fs = require "nixio.fs" +local util = require "luci.util" +local ip = require "luci.ip" + +local has_ipip = fs.glob("/etc/modules.d/[0-9]*-ipip")() + +m = Map("olsrd6", translate("OLSR Daemon"), + translate("The OLSR daemon is an implementation of the Optimized Link State Routing protocol. ".. + "As such it allows mesh routing for any network equipment. ".. + "It runs on any wifi card that supports ad-hoc mode and of course on any ethernet device. ".. + "Visit <a href='http://www.olsr.org'>olsrd.org</a> for help and documentation.")) + +function m.on_parse() + local has_defaults = false + + m.uci:foreach("olsrd6", "InterfaceDefaults", + function(s) + has_defaults = true + return false + end) + + if not has_defaults then + m.uci:section("olsrd6", "InterfaceDefaults") + end +end + +function write_float(self, section, value) + local n = tonumber(value) + if n ~= nil then + return Value.write(self, section, "%.1f" % n) + end +end + +s = m:section(TypedSection, "olsrd6", translate("General settings")) +s.anonymous = true + +s:tab("general", translate("General Settings")) +s:tab("lquality", translate("Link Quality Settings")) +s:tab("smartgw", translate("SmartGW"), not has_ipip and translate("Warning: kmod-ipip is not installed. Without kmod-ipip SmartGateway will not work, please install it.")) +s:tab("advanced", translate("Advanced Settings")) + +poll = s:taboption("advanced", Value, "Pollrate", translate("Pollrate"), + translate("Polling rate for OLSR sockets in seconds. Default is 0.05.")) +poll.optional = true +poll.datatype = "ufloat" +poll.placeholder = "0.05" + +nicc = s:taboption("advanced", Value, "NicChgsPollInt", translate("Nic changes poll interval"), + translate("Interval to poll network interfaces for configuration changes (in seconds). Default is \"2.5\".")) +nicc.optional = true +nicc.datatype = "ufloat" +nicc.placeholder = "2.5" + +tos = s:taboption("advanced", Value, "TosValue", translate("TOS value"), + translate("Type of service value for the IP header of control traffic. Default is \"16\".")) +tos.optional = true +tos.datatype = "uinteger" +tos.placeholder = "16" + +fib = s:taboption("general", ListValue, "FIBMetric", translate("FIB metric"), + translate ("FIBMetric controls the metric value of the host-routes OLSRd sets. ".. + "\"flat\" means that the metric value is always 2. This is the preferred value ".. + "because it helps the linux kernel routing to clean up older routes. ".. + "\"correct\" uses the hopcount as the metric value. ".. + "\"approx\" use the hopcount as the metric value too, but does only update the hopcount if the nexthop changes too. ".. + "Default is \"flat\".")) +fib:value("flat") +fib:value("correct") +fib:value("approx") + +lql = s:taboption("lquality", ListValue, "LinkQualityLevel", translate("LQ level"), + translate("Link quality level switch between hopcount and cost-based (mostly ETX) routing.<br />".. + "<b>0</b> = do not use link quality<br />".. + "<b>2</b> = use link quality for MPR selection and routing<br />".. + "Default is \"2\"")) +lql:value("2") +lql:value("0") + +lqage = s:taboption("lquality", Value, "LinkQualityAging", translate("LQ aging"), + translate("Link quality aging factor (only for lq level 2). Tuning parameter for etx_float and etx_fpm, smaller values ".. + "mean slower changes of ETX value. (allowed values are between 0.01 and 1.0)")) +lqage.optional = true +lqage:depends("LinkQualityLevel", "2") + +lqa = s:taboption("lquality", ListValue, "LinkQualityAlgorithm", translate("LQ algorithm"), + translate("Link quality algorithm (only for lq level 2).<br />".. + "<b>etx_float</b>: floating point ETX with exponential aging<br />".. + "<b>etx_fpm</b> : same as etx_float, but with integer arithmetic<br />".. + "<b>etx_ff</b> : ETX freifunk, an etx variant which use all OLSR traffic (instead of only hellos) for ETX calculation<br />".. + "<b>etx_ffeth</b>: incompatible variant of etx_ff that allows ethernet links with ETX 0.1.<br />".. + "Defaults to \"etx_ff\"")) +lqa.optional = true +lqa:value("etx_ff") +lqa:value("etx_fpm") +lqa:value("etx_float") +lqa:value("etx_ffeth") +lqa:depends("LinkQualityLevel", "2") +lqa.optional = true + +lqfish = s:taboption("lquality", Flag, "LinkQualityFishEye", translate("LQ fisheye"), + translate("Fisheye mechanism for TCs (checked means on). Default is \"on\"")) +lqfish.default = "1" +lqfish.optional = true + +hyst = s:taboption("lquality", Flag, "UseHysteresis", translate("Use hysteresis"), + translate("Hysteresis for link sensing (only for hopcount metric). Hysteresis adds more robustness to the link sensing ".. + "but delays neighbor registration. Defaults is \"yes\"")) +hyst.default = "yes" +hyst.enabled = "yes" +hyst.disabled = "no" +hyst:depends("LinkQualityLevel", "0") +hyst.optional = true +hyst.rmempty = true + +port = s:taboption("general", Value, "OlsrPort", translate("Port"), + translate("The port OLSR uses. This should usually stay at the IANA assigned port 698. It can have a value between 1 and 65535.")) +port.optional = true +port.default = "698" +port.rmempty = true + +mainip = s:taboption("general", Value, "MainIp", translate("Main IP"), + translate("Sets the main IP (originator ip) of the router. This IP will NEVER change during the uptime of olsrd. ".. + "Default is ::, which triggers usage of the IP of the first interface.")) +mainip.optional = true +mainip.rmempty = true +mainip.datatype = "ipaddr" +mainip.placeholder = "::" + +sgw = s:taboption("smartgw", Flag, "SmartGateway", translate("Enable"), translate("Enable SmartGateway. If it is disabled, then " .. + "all other SmartGateway parameters are ignored. Default is \"no\".")) +sgw.default="no" +sgw.enabled="yes" +sgw.disabled="no" +sgw.rmempty = true + +sgwnat = s:taboption("smartgw", Flag, "SmartGatewayAllowNAT", translate("Allow gateways with NAT"), translate("Allow the selection of an outgoing ipv4 gateway with NAT")) +sgwnat:depends("SmartGateway", "yes") +sgwnat.default="yes" +sgwnat.enabled="yes" +sgwnat.disabled="no" +sgwnat.optional = true +sgwnat.rmempty = true + +sgwuplink = s:taboption("smartgw", ListValue, "SmartGatewayUplink", translate("Announce uplink"), translate("Which kind of uplink is exported to the other mesh nodes. " .. + "An uplink is detected by looking for a local HNA6 ::ffff:0:0/96 or 2000::/3. Default setting is \"both\".")) +sgwuplink:value("none") +sgwuplink:value("ipv4") +sgwuplink:value("ipv6") +sgwuplink:value("both") +sgwuplink:depends("SmartGateway", "yes") +sgwuplink.default="both" +sgwuplink.optional = true +sgwuplink.rmempty = true + +sgwulnat = s:taboption("smartgw", Flag, "SmartGatewayUplinkNAT", translate("Uplink uses NAT"), translate("If this Node uses NAT for connections to the internet. " .. + "Default is \"yes\".")) +sgwulnat:depends("SmartGatewayUplink", "ipv4") +sgwulnat:depends("SmartGatewayUplink", "both") +sgwulnat.default="yes" +sgwulnat.enabled="yes" +sgwulnat.disabled="no" +sgwnat.optional = true +sgwnat.rmempty = true + +sgwspeed = s:taboption("smartgw", Value, "SmartGatewaySpeed", translate("Speed of the uplink"), translate("Specifies the speed of ".. + "the uplink in kilobits/s. First parameter is upstream, second parameter is downstream. Default is \"128 1024\".")) +sgwspeed:depends("SmartGatewayUplink", "ipv4") +sgwspeed:depends("SmartGatewayUplink", "ipv6") +sgwspeed:depends("SmartGatewayUplink", "both") +sgwspeed.optional = true +sgwspeed.rmempty = true + +sgwprefix = s:taboption("smartgw", Value, "SmartGatewayPrefix", translate("IPv6-Prefix of the uplink"), translate("This can be used " .. + "to signal the external IPv6 prefix of the uplink to the clients. This might allow a client to change it's local IPv6 address to " .. + "use the IPv6 gateway without any kind of address translation. The maximum prefix length is 64 bits. " .. + "Default is \"::/0\" (no prefix).")) +sgwprefix:depends("SmartGatewayUplink", "ipv6") +sgwprefix:depends("SmartGatewayUplink", "both") +sgwprefix.optional = true +sgwprefix.rmempty = true + +willingness = s:taboption("advanced", ListValue, "Willingness", translate("Willingness"), + translate("The fixed willingness to use. If not set willingness will be calculated dynamically based on battery/power status. Default is \"3\".")) +for i=0,7 do + willingness:value(i) +end +willingness.optional = true +willingness.default = "3" + +natthr = s:taboption("advanced", Value, "NatThreshold", translate("NAT threshold"), + translate("If the route to the current gateway is to be changed, the ETX value of this gateway is ".. + "multiplied with this value before it is compared to the new one. ".. + "The parameter can be a value between 0.1 and 1.0, but should be close to 1.0 if changed.<br />".. + "<b>WARNING:</b> This parameter should not be used together with the etx_ffeth metric!<br />".. + "Defaults to \"1.0\".")) +for i=1,0.1,-0.1 do + natthr:value(i) +end +natthr:depends("LinkQualityAlgorithm", "etx_ff") +natthr:depends("LinkQualityAlgorithm", "etx_float") +natthr:depends("LinkQualityAlgorithm", "etx_fpm") +natthr.default = "1.0" +natthr.optional = true +natthr.write = write_float + + +i = m:section(TypedSection, "InterfaceDefaults", translate("Interfaces Defaults")) +i.anonymous = true +i.addremove = false + +i:tab("general", translate("General Settings")) +i:tab("addrs", translate("IP Addresses")) +i:tab("timing", translate("Timing and Validity")) + +mode = i:taboption("general", ListValue, "Mode", translate("Mode"), + translate("Interface Mode is used to prevent unnecessary packet forwarding on switched ethernet interfaces. ".. + "valid Modes are \"mesh\" and \"ether\". Default is \"mesh\".")) +mode:value("mesh") +mode:value("ether") +mode.optional = true +mode.rmempty = true + + +weight = i:taboption("general", Value, "Weight", translate("Weight"), + translate("When multiple links exist between hosts the weight of interface is used to determine the link to use. ".. + "Normally the weight is automatically calculated by olsrd based on the characteristics of the interface, ".. + "but here you can specify a fixed value. Olsrd will choose links with the lowest value.<br />".. + "<b>Note:</b> Interface weight is used only when LinkQualityLevel is set to 0. ".. + "For any other value of LinkQualityLevel, the interface ETX value is used instead.")) +weight.optional = true +weight.datatype = "uinteger" +weight.placeholder = "0" + +lqmult = i:taboption("general", DynamicList, "LinkQualityMult", translate("LinkQuality Multiplicator"), + translate("Multiply routes with the factor given here. Allowed values are between 0.01 and 1.0. ".. + "It is only used when LQ-Level is greater than 0. Examples:<br />".. + "reduce LQ to fd91:662e:3c58::1 by half: fd91:662e:3c58::1 0.5<br />".. + "reduce LQ to all nodes on this interface by 20%: default 0.8")) +lqmult.optional = true +lqmult.rmempty = true +lqmult.cast = "table" +lqmult.placeholder = "default 1.0" + +function lqmult.validate(self, value) + for _, v in pairs(value) do + if v ~= "" then + local val = util.split(v, " ") + local host = val[1] + local mult = val[2] + if not host or not mult then + return nil, translate("LQMult requires two values (IP address or 'default' and multiplicator) seperated by space.") + end + if not (host == "default" or ip.IPv6(host)) then + return nil, translate("Can only be a valid IPv6 address or 'default'") + end + if not tonumber(mult) or tonumber(mult) > 1 or tonumber(mult) < 0.01 then + return nil, translate("Invalid Value for LQMult-Value. Must be between 0.01 and 1.0.") + end + if not mult:match("[0-1]%.[0-9]+") then + return nil, translate("Invalid Value for LQMult-Value. You must use a decimal number between 0.01 and 1.0 here.") + end + end + end + return value +end + +ip6m = i:taboption("addrs", Value, "IPv6Multicast", translate("IPv6 multicast"), + translate("IPv6 multicast address. Default is \"FF02::6D\", the manet-router linklocal multicast.")) +ip6m.optional = true +ip6m.datatype = "ip6addr" +ip6m.placeholder = "FF02::6D" + +ip6s = i:taboption("addrs", Value, "IPv6Src", translate("IPv6 source"), + translate("IPv6 src prefix. OLSRd will choose one of the interface IPs which matches the prefix of this parameter. ".. + "Default is \"0::/0\", which triggers the usage of a not-linklocal interface IP.")) +ip6s.optional = true +ip6s.datatype = "ip6addr" +ip6s.placeholder = "0::/0" + + +hi = i:taboption("timing", Value, "HelloInterval", translate("Hello interval")) +hi.optional = true +hi.datatype = "ufloat" +hi.placeholder = "5.0" +hi.write = write_float + +hv = i:taboption("timing", Value, "HelloValidityTime", translate("Hello validity time")) +hv.optional = true +hv.datatype = "ufloat" +hv.placeholder = "40.0" +hv.write = write_float + +ti = i:taboption("timing", Value, "TcInterval", translate("TC interval")) +ti.optional = true +ti.datatype = "ufloat" +ti.placeholder = "2.0" +ti.write = write_float + +tv = i:taboption("timing", Value, "TcValidityTime", translate("TC validity time")) +tv.optional = true +tv.datatype = "ufloat" +tv.placeholder = "256.0" +tv.write = write_float + +mi = i:taboption("timing", Value, "MidInterval", translate("MID interval")) +mi.optional = true +mi.datatype = "ufloat" +mi.placeholder = "18.0" +mi.write = write_float + +mv = i:taboption("timing", Value, "MidValidityTime", translate("MID validity time")) +mv.optional = true +mv.datatype = "ufloat" +mv.placeholder = "324.0" +mv.write = write_float + +ai = i:taboption("timing", Value, "HnaInterval", translate("HNA interval")) +ai.optional = true +ai.datatype = "ufloat" +ai.placeholder = "18.0" +ai.write = write_float + +av = i:taboption("timing", Value, "HnaValidityTime", translate("HNA validity time")) +av.optional = true +av.datatype = "ufloat" +av.placeholder = "108.0" +av.write = write_float + + +ifs = m:section(TypedSection, "Interface", translate("Interfaces")) +ifs.addremove = true +ifs.anonymous = true +ifs.extedit = luci.dispatcher.build_url("admin/services/olsrd6/iface/%s") +ifs.template = "cbi/tblsection" + +function ifs.create(...) + local sid = TypedSection.create(...) + luci.http.redirect(ifs.extedit % sid) +end + +ign = ifs:option(Flag, "ignore", translate("Enable")) +ign.enabled = "0" +ign.disabled = "1" +ign.rmempty = false +function ign.cfgvalue(self, section) + return Flag.cfgvalue(self, section) or "0" +end + +network = ifs:option(DummyValue, "interface", translate("Network")) +network.template = "cbi/network_netinfo" + +mode = ifs:option(DummyValue, "Mode", translate("Mode")) +function mode.cfgvalue(...) + return Value.cfgvalue(...) or m.uci:get_first("olsrd6", "InterfaceDefaults", "Mode", "mesh") +end + +hello = ifs:option(DummyValue, "_hello", translate("Hello")) +function hello.cfgvalue(self, section) + local i = tonumber(m.uci:get("olsrd6", section, "HelloInterval")) or tonumber(m.uci:get_first("olsrd6", "InterfaceDefaults", "HelloInterval", 5)) + local v = tonumber(m.uci:get("olsrd6", section, "HelloValidityTime")) or tonumber(m.uci:get_first("olsrd6", "InterfaceDefaults", "HelloValidityTime", 40)) + return "%.01fs / %.01fs" %{ i, v } +end + +tc = ifs:option(DummyValue, "_tc", translate("TC")) +function tc.cfgvalue(self, section) + local i = tonumber(m.uci:get("olsrd6", section, "TcInterval")) or tonumber(m.uci:get_first("olsrd6", "InterfaceDefaults", "TcInterval", 2)) + local v = tonumber(m.uci:get("olsrd6", section, "TcValidityTime")) or tonumber(m.uci:get_first("olsrd6", "InterfaceDefaults", "TcValidityTime", 256)) + return "%.01fs / %.01fs" %{ i, v } +end + +mid = ifs:option(DummyValue, "_mid", translate("MID")) +function mid.cfgvalue(self, section) + local i = tonumber(m.uci:get("olsrd6", section, "MidInterval")) or tonumber(m.uci:get_first("olsrd6", "InterfaceDefaults", "MidInterval", 18)) + local v = tonumber(m.uci:get("olsrd6", section, "MidValidityTime")) or tonumber(m.uci:get_first("olsrd6", "InterfaceDefaults", "MidValidityTime", 324)) + return "%.01fs / %.01fs" %{ i, v } +end + +hna = ifs:option(DummyValue, "_hna", translate("HNA")) +function hna.cfgvalue(self, section) + local i = tonumber(m.uci:get("olsrd6", section, "HnaInterval")) or tonumber(m.uci:get_first("olsrd6", "InterfaceDefaults", "HnaInterval", 18)) + local v = tonumber(m.uci:get("olsrd6", section, "HnaValidityTime")) or tonumber(m.uci:get_first("olsrd6", "InterfaceDefaults", "HnaValidityTime", 108)) + return "%.01fs / %.01fs" %{ i, v } +end + +return m diff --git a/applications/luci-app-olsr/luasrc/model/cbi/olsr/olsrddisplay.lua b/applications/luci-app-olsr/luasrc/model/cbi/olsr/olsrddisplay.lua new file mode 100644 index 000000000..48dc965c7 --- /dev/null +++ b/applications/luci-app-olsr/luasrc/model/cbi/olsr/olsrddisplay.lua @@ -0,0 +1,23 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2011 Manuel Munz <freifunk at somakoma de> + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 +]]-- + +m = Map("luci_olsr", translate("OLSR - Display Options")) + +s = m:section(TypedSection, "olsr") +s.anonymous = true + +res = s:option(Flag, "resolve", translate("Resolve"), + translate("Resolve hostnames on status pages. It is generally safe to allow this, but if you use public IPs and have unstable DNS-Setup then those pages will load really slow. In this case disable it here.")) +res.default = "0" +res.optional = true + +return m diff --git a/applications/luci-app-olsr/luasrc/model/cbi/olsr/olsrdhna.lua b/applications/luci-app-olsr/luasrc/model/cbi/olsr/olsrdhna.lua new file mode 100644 index 000000000..d5ee79f24 --- /dev/null +++ b/applications/luci-app-olsr/luasrc/model/cbi/olsr/olsrdhna.lua @@ -0,0 +1,56 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth <steven@midlink.org> +Copyright 2011 Manuel Munz <freifunk at somakoma dot de> + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +$Id$ +]]-- + +local uci = require "luci.model.uci".cursor() +local ipv = uci:get_first("olsrd", "olsrd", "IpVersion", "4") + +mh = Map("olsrd", translate("OLSR - HNA-Announcements"), translate("Hosts in a OLSR routed network can announce connecitivity " .. + "to external networks using HNA messages.")) + +if ipv == "6and4" or ipv == "4" then + hna4 = mh:section(TypedSection, "Hna4", translate("Hna4"), translate("Both values must use the dotted decimal notation.")) + hna4.addremove = true + hna4.anonymous = true + hna4.template = "cbi/tblsection" + + net4 = hna4:option(Value, "netaddr", translate("Network address")) + net4.datatype = "ip4addr" + net4.placeholder = "10.11.12.13" + net4.default = "10.11.12.13" + msk4 = hna4:option(Value, "netmask", translate("Netmask")) + msk4.datatype = "ip4addr" + msk4.placeholder = "255.255.255.255" + msk4.default = "255.255.255.255" +end + +if ipv == "6and4" or ipv == "6" then + hna6 = mh:section(TypedSection, "Hna6", translate("Hna6"), translate("IPv6 network must be given in full notation, " .. + "prefix must be in CIDR notation.")) + hna6.addremove = true + hna6.anonymous = true + hna6.template = "cbi/tblsection" + + net6 = hna6:option(Value, "netaddr", translate("Network address")) + net6.datatype = "ip6addr" + net6.placeholder = "fec0:2200:106:0:0:0:0:0" + net6.default = "fec0:2200:106:0:0:0:0:0" + msk6 = hna6:option(Value, "prefix", translate("Prefix")) + msk6.datatype = "range(0,128)" + msk6.placeholder = "128" + msk6.default = "128" +end + +return mh + diff --git a/applications/luci-app-olsr/luasrc/model/cbi/olsr/olsrdhna6.lua b/applications/luci-app-olsr/luasrc/model/cbi/olsr/olsrdhna6.lua new file mode 100644 index 000000000..21b2ec867 --- /dev/null +++ b/applications/luci-app-olsr/luasrc/model/cbi/olsr/olsrdhna6.lua @@ -0,0 +1,36 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth <steven@midlink.org> +Copyright 2011 Manuel Munz <freifunk at somakoma dot de> + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +$Id$ +]]-- + +local uci = require "luci.model.uci".cursor() + +mh = Map("olsrd6", translate("OLSR - HNA6-Announcements"), translate("Hosts in a OLSR routed network can announce connecitivity " .. + "to external networks using HNA6 messages.")) + + hna6 = mh:section(TypedSection, "Hna6", translate("Hna6"), translate("IPv6 network must be given in full notation, " .. + "prefix must be in CIDR notation.")) + hna6.addremove = true + hna6.anonymous = true + hna6.template = "cbi/tblsection" + + net6 = hna6:option(Value, "netaddr", translate("Network address")) + net6.datatype = "ip6addr" + net6.placeholder = "fec0:2200:106:0:0:0:0:0" + net6.default = "fec0:2200:106:0:0:0:0:0" + msk6 = hna6:option(Value, "prefix", translate("Prefix")) + msk6.datatype = "range(0,128)" + msk6.placeholder = "128" + msk6.default = "128" +return mh + diff --git a/applications/luci-app-olsr/luasrc/model/cbi/olsr/olsrdiface.lua b/applications/luci-app-olsr/luasrc/model/cbi/olsr/olsrdiface.lua new file mode 100644 index 000000000..9673d9afc --- /dev/null +++ b/applications/luci-app-olsr/luasrc/model/cbi/olsr/olsrdiface.lua @@ -0,0 +1,189 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2010 Jo-Philipp Wich <xm@subsignal.org> + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +$Id$ + +]]-- + +local util = require "luci.util" +local ip = require "luci.ip" + +function write_float(self, section, value) + local n = tonumber(value) + if n ~= nil then + return Value.write(self, section, "%.1f" % n) + end +end + +m = Map("olsrd", translate("OLSR Daemon - Interface"), + translate("The OLSR daemon is an implementation of the Optimized Link State Routing protocol. ".. + "As such it allows mesh routing for any network equipment. ".. + "It runs on any wifi card that supports ad-hoc mode and of course on any ethernet device. ".. + "Visit <a href='http://www.olsr.org'>olsrd.org</a> for help and documentation.")) + +m.redirect = luci.dispatcher.build_url("admin/services/olsrd") + +if not arg[1] or m.uci:get("olsrd", arg[1]) ~= "Interface" then + luci.http.redirect(m.redirect) + return +end + +i = m:section(NamedSection, arg[1], "Interface", translate("Interface")) +i.anonymous = true +i.addremove = false + +i:tab("general", translate("General Settings")) +i:tab("addrs", translate("IP Addresses")) +i:tab("timing", translate("Timing and Validity")) + +ign = i:taboption("general", Flag, "ignore", translate("Enable"), + translate("Enable this interface.")) +ign.enabled = "0" +ign.disabled = "1" +ign.rmempty = false +function ign.cfgvalue(self, section) + return Flag.cfgvalue(self, section) or "0" +end + +network = i:taboption("general", Value, "interface", translate("Network"), + translate("The interface OLSRd should serve.")) + +network.template = "cbi/network_netlist" +network.widget = "radio" +network.nocreate = true + +mode = i:taboption("general", ListValue, "Mode", translate("Mode"), + translate("Interface Mode is used to prevent unnecessary packet forwarding on switched ethernet interfaces. ".. + "valid Modes are \"mesh\" and \"ether\". Default is \"mesh\".")) +mode:value("mesh") +mode:value("ether") +mode.optional = true +mode.rmempty = true + + +weight = i:taboption("general", Value, "Weight", translate("Weight"), + translate("When multiple links exist between hosts the weight of interface is used to determine the link to use. ".. + "Normally the weight is automatically calculated by olsrd based on the characteristics of the interface, ".. + "but here you can specify a fixed value. Olsrd will choose links with the lowest value.<br />".. + "<b>Note:</b> Interface weight is used only when LinkQualityLevel is set to 0. ".. + "For any other value of LinkQualityLevel, the interface ETX value is used instead.")) +weight.optional = true +weight.datatype = "uinteger" +weight.placeholder = "0" + +lqmult = i:taboption("general", DynamicList, "LinkQualityMult", translate("LinkQuality Multiplicator"), + translate("Multiply routes with the factor given here. Allowed values are between 0.01 and 1.0. ".. + "It is only used when LQ-Level is greater than 0. Examples:<br />".. + "reduce LQ to 192.168.0.1 by half: 192.168.0.1 0.5<br />".. + "reduce LQ to all nodes on this interface by 20%: default 0.8")) +lqmult.optional = true +lqmult.rmempty = true +lqmult.cast = "table" +lqmult.placeholder = "default 1.0" + +function lqmult.validate(self, value) + for _, v in pairs(value) do + if v ~= "" then + local val = util.split(v, " ") + local host = val[1] + local mult = val[2] + if not host or not mult then + return nil, translate("LQMult requires two values (IP address or 'default' and multiplicator) seperated by space.") + end + if not (host == "default" or ip.IPv4(host) or ip.IPv6(host)) then + return nil, translate("Can only be a valid IPv4 or IPv6 address or 'default'") + end + if not tonumber(mult) or tonumber(mult) > 1 or tonumber(mult) < 0.01 then + return nil, translate("Invalid Value for LQMult-Value. Must be between 0.01 and 1.0.") + end + if not mult:match("[0-1]%.[0-9]+") then + return nil, translate("Invalid Value for LQMult-Value. You must use a decimal number between 0.01 and 1.0 here.") + end + end + end + return value +end + +ip4b = i:taboption("addrs", Value, "Ip4Broadcast", translate("IPv4 broadcast"), + translate("IPv4 broadcast address for outgoing OLSR packets. One useful example would be 255.255.255.255. ".. + "Default is \"0.0.0.0\", which triggers the usage of the interface broadcast IP.")) +ip4b.optional = true +ip4b.datatype = "ip4addr" +ip4b.placeholder = "0.0.0.0" + +ip6m = i:taboption("addrs", Value, "IPv6Multicast", translate("IPv6 multicast"), + translate("IPv6 multicast address. Default is \"FF02::6D\", the manet-router linklocal multicast.")) +ip6m.optional = true +ip6m.datatype = "ip6addr" +ip6m.placeholder = "FF02::6D" + +ip4s = i:taboption("addrs", Value, "IPv4Src", translate("IPv4 source"), + translate("IPv4 src address for outgoing OLSR packages. Default is \"0.0.0.0\", which triggers usage of the interface IP.")) +ip4s.optional = true +ip4s.datatype = "ip4addr" +ip4s.placeholder = "0.0.0.0" + +ip6s = i:taboption("addrs", Value, "IPv6Src", translate("IPv6 source"), + translate("IPv6 src prefix. OLSRd will choose one of the interface IPs which matches the prefix of this parameter. ".. + "Default is \"0::/0\", which triggers the usage of a not-linklocal interface IP.")) +ip6s.optional = true +ip6s.datatype = "ip6addr" +ip6s.placeholder = "0::/0" + +hi = i:taboption("timing", Value, "HelloInterval", translate("Hello interval")) +hi.optional = true +hi.datatype = "ufloat" +hi.placeholder = "5.0" +hi.write = write_float + +hv = i:taboption("timing", Value, "HelloValidityTime", translate("Hello validity time")) +hv.optional = true +hv.datatype = "ufloat" +hv.placeholder = "40.0" +hv.write = write_float + +ti = i:taboption("timing", Value, "TcInterval", translate("TC interval")) +ti.optional = true +ti.datatype = "ufloat" +ti.placeholder = "2.0" +ti.write = write_float + +tv = i:taboption("timing", Value, "TcValidityTime", translate("TC validity time")) +tv.optional = true +tv.datatype = "ufloat" +tv.placeholder = "256.0" +tv.write = write_float + +mi = i:taboption("timing", Value, "MidInterval", translate("MID interval")) +mi.optional = true +mi.datatype = "ufloat" +mi.placeholder = "18.0" +mi.write = write_float + +mv = i:taboption("timing", Value, "MidValidityTime", translate("MID validity time")) +mv.optional = true +mv.datatype = "ufloat" +mv.placeholder = "324.0" +mv.write = write_float + +ai = i:taboption("timing", Value, "HnaInterval", translate("HNA interval")) +ai.optional = true +ai.datatype = "ufloat" +ai.placeholder = "18.0" +ai.write = write_float + +av = i:taboption("timing", Value, "HnaValidityTime", translate("HNA validity time")) +av.optional = true +av.datatype = "ufloat" +av.placeholder = "108.0" +av.write = write_float + +return m diff --git a/applications/luci-app-olsr/luasrc/model/cbi/olsr/olsrdiface6.lua b/applications/luci-app-olsr/luasrc/model/cbi/olsr/olsrdiface6.lua new file mode 100644 index 000000000..85818acb3 --- /dev/null +++ b/applications/luci-app-olsr/luasrc/model/cbi/olsr/olsrdiface6.lua @@ -0,0 +1,176 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2010 Jo-Philipp Wich <xm@subsignal.org> + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +$Id$ + +]]-- + +local util = require "luci.util" +local ip = require "luci.ip" + +function write_float(self, section, value) + local n = tonumber(value) + if n ~= nil then + return Value.write(self, section, "%.1f" % n) + end +end + +m = Map("olsrd6", translate("OLSR Daemon - Interface"), + translate("The OLSR daemon is an implementation of the Optimized Link State Routing protocol. ".. + "As such it allows mesh routing for any network equipment. ".. + "It runs on any wifi card that supports ad-hoc mode and of course on any ethernet device. ".. + "Visit <a href='http://www.olsr.org'>olsrd.org</a> for help and documentation.")) + +m.redirect = luci.dispatcher.build_url("admin/services/olsrd6") + +if not arg[1] or m.uci:get("olsrd6", arg[1]) ~= "Interface" then + luci.http.redirect(m.redirect) + return +end + +i = m:section(NamedSection, arg[1], "Interface", translate("Interface")) +i.anonymous = true +i.addremove = false + +i:tab("general", translate("General Settings")) +i:tab("addrs", translate("IP Addresses")) +i:tab("timing", translate("Timing and Validity")) + +ign = i:taboption("general", Flag, "ignore", translate("Enable"), + translate("Enable this interface.")) +ign.enabled = "0" +ign.disabled = "1" +ign.rmempty = false +function ign.cfgvalue(self, section) + return Flag.cfgvalue(self, section) or "0" +end + +network = i:taboption("general", Value, "interface", translate("Network"), + translate("The interface OLSRd should serve.")) + +network.template = "cbi/network_netlist" +network.widget = "radio" +network.nocreate = true + +mode = i:taboption("general", ListValue, "Mode", translate("Mode"), + translate("Interface Mode is used to prevent unnecessary packet forwarding on switched ethernet interfaces. ".. + "valid Modes are \"mesh\" and \"ether\". Default is \"mesh\".")) +mode:value("mesh") +mode:value("ether") +mode.optional = true +mode.rmempty = true + + +weight = i:taboption("general", Value, "Weight", translate("Weight"), + translate("When multiple links exist between hosts the weight of interface is used to determine the link to use. ".. + "Normally the weight is automatically calculated by olsrd based on the characteristics of the interface, ".. + "but here you can specify a fixed value. Olsrd will choose links with the lowest value.<br />".. + "<b>Note:</b> Interface weight is used only when LinkQualityLevel is set to 0. ".. + "For any other value of LinkQualityLevel, the interface ETX value is used instead.")) +weight.optional = true +weight.datatype = "uinteger" +weight.placeholder = "0" + +lqmult = i:taboption("general", DynamicList, "LinkQualityMult", translate("LinkQuality Multiplicator"), + translate("Multiply routes with the factor given here. Allowed values are between 0.01 and 1.0. ".. + "It is only used when LQ-Level is greater than 0. Examples:<br />".. + "reduce LQ to fd91:662e:3c58::1 by half: fd91:662e:3c58::1 0.5<br />".. + "reduce LQ to all nodes on this interface by 20%: default 0.8")) +lqmult.optional = true +lqmult.rmempty = true +lqmult.cast = "table" +lqmult.placeholder = "default 1.0" + +function lqmult.validate(self, value) + for _, v in pairs(value) do + if v ~= "" then + local val = util.split(v, " ") + local host = val[1] + local mult = val[2] + if not host or not mult then + return nil, translate("LQMult requires two values (IP address or 'default' and multiplicator) seperated by space.") + end + if not (host == "default" or ip.IPv6(host)) then + return nil, translate("Can only be a valid IPv6 address or 'default'") + end + if not tonumber(mult) or tonumber(mult) > 1 or tonumber(mult) < 0.01 then + return nil, translate("Invalid Value for LQMult-Value. Must be between 0.01 and 1.0.") + end + if not mult:match("[0-1]%.[0-9]+") then + return nil, translate("Invalid Value for LQMult-Value. You must use a decimal number between 0.01 and 1.0 here.") + end + end + end + return value +end + +ip6m = i:taboption("addrs", Value, "IPv6Multicast", translate("IPv6 multicast"), + translate("IPv6 multicast address. Default is \"FF02::6D\", the manet-router linklocal multicast.")) +ip6m.optional = true +ip6m.datatype = "ip6addr" +ip6m.placeholder = "FF02::6D" + +ip6s = i:taboption("addrs", Value, "IPv6Src", translate("IPv6 source"), + translate("IPv6 src prefix. OLSRd will choose one of the interface IPs which matches the prefix of this parameter. ".. + "Default is \"0::/0\", which triggers the usage of a not-linklocal interface IP.")) +ip6s.optional = true +ip6s.datatype = "ip6addr" +ip6s.placeholder = "0::/0" + +hi = i:taboption("timing", Value, "HelloInterval", translate("Hello interval")) +hi.optional = true +hi.datatype = "ufloat" +hi.placeholder = "5.0" +hi.write = write_float + +hv = i:taboption("timing", Value, "HelloValidityTime", translate("Hello validity time")) +hv.optional = true +hv.datatype = "ufloat" +hv.placeholder = "40.0" +hv.write = write_float + +ti = i:taboption("timing", Value, "TcInterval", translate("TC interval")) +ti.optional = true +ti.datatype = "ufloat" +ti.placeholder = "2.0" +ti.write = write_float + +tv = i:taboption("timing", Value, "TcValidityTime", translate("TC validity time")) +tv.optional = true +tv.datatype = "ufloat" +tv.placeholder = "256.0" +tv.write = write_float + +mi = i:taboption("timing", Value, "MidInterval", translate("MID interval")) +mi.optional = true +mi.datatype = "ufloat" +mi.placeholder = "18.0" +mi.write = write_float + +mv = i:taboption("timing", Value, "MidValidityTime", translate("MID validity time")) +mv.optional = true +mv.datatype = "ufloat" +mv.placeholder = "324.0" +mv.write = write_float + +ai = i:taboption("timing", Value, "HnaInterval", translate("HNA interval")) +ai.optional = true +ai.datatype = "ufloat" +ai.placeholder = "18.0" +ai.write = write_float + +av = i:taboption("timing", Value, "HnaValidityTime", translate("HNA validity time")) +av.optional = true +av.datatype = "ufloat" +av.placeholder = "108.0" +av.write = write_float + +return m diff --git a/applications/luci-app-olsr/luasrc/model/cbi/olsr/olsrdplugins.lua b/applications/luci-app-olsr/luasrc/model/cbi/olsr/olsrdplugins.lua new file mode 100644 index 000000000..bd72c56ad --- /dev/null +++ b/applications/luci-app-olsr/luasrc/model/cbi/olsr/olsrdplugins.lua @@ -0,0 +1,270 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth <steven@midlink.org> +Copyright 2009 Jo-Philipp Wich <xm@subsignal.org> + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +$Id$ +]]-- + +local ip = require "luci.ip" +local fs = require "nixio.fs" + +if arg[1] then + mp = Map("olsrd", translate("OLSR - Plugins")) + + p = mp:section(TypedSection, "LoadPlugin", translate("Plugin configuration")) + p:depends("library", arg[1]) + p.anonymous = true + + ign = p:option(Flag, "ignore", translate("Enable")) + ign.enabled = "0" + ign.disabled = "1" + ign.rmempty = false + function ign.cfgvalue(self, section) + return Flag.cfgvalue(self, section) or "0" + end + + lib = p:option(DummyValue, "library", translate("Library")) + lib.default = arg[1] + + local function Range(x,y) + local t = {} + for i = x, y do t[#t+1] = i end + return t + end + + local function Cidr2IpMask(val) + if val then + for i = 1, #val do + local cidr = ip.IPv4(val[i]) or ip.IPv6(val[i]) + if cidr then + val[i] = cidr:network():string() .. " " .. cidr:mask():string() + end + end + return val + end + end + + local function IpMask2Cidr(val) + if val then + for i = 1, #val do + local ip, mask = val[i]:gmatch("([^%s]+)%s+([^%s]+)")() + local cidr + if ip and mask and ip:match(":") then + cidr = ip.IPv6(ip, mask) + elseif ip and mask then + cidr = ip.IPv4(ip, mask) + end + + if cidr then + val[i] = cidr:string() + end + end + return val + end + end + + + local knownPlParams = { + ["olsrd_bmf.so.1.5.3"] = { + { Value, "BmfInterface", "bmf0" }, + { Value, "BmfInterfaceIp", "10.10.10.234/24" }, + { Flag, "DoLocalBroadcast", "no" }, + { Flag, "CapturePacketsOnOlsrInterfaces", "yes" }, + { ListValue, "BmfMechanism", { "UnicastPromiscuous", "Broadcast" } }, + { Value, "BroadcastRetransmitCount", "2" }, + { Value, "FanOutLimit", "4" }, + { DynamicList, "NonOlsrIf", "br-lan" } + }, + + ["olsrd_dyn_gw.so.0.4"] = { + { Value, "Interval", "40" }, + { DynamicList, "Ping", "141.1.1.1" }, + { DynamicList, "HNA", "192.168.80.0/24", IpMask2Cidr, Cidr2IpMask } + }, + + ["olsrd_httpinfo.so.0.1"] = { + { Value, "port", "80" }, + { DynamicList, "Host", "163.24.87.3" }, + { DynamicList, "Net", "0.0.0.0/0", Cidr2IpMask } + }, + + ["olsrd_nameservice.so.0.3"] = { + { DynamicList, "name", "my-name.mesh" }, + { DynamicList, "hosts", "1.2.3.4 name-for-other-interface.mesh" }, + { Value, "suffix", ".olsr" }, + { Value, "hosts_file", "/path/to/hosts_file" }, + { Value, "add_hosts", "/path/to/file" }, + { Value, "dns_server", "141.1.1.1" }, + { Value, "resolv_file", "/path/to/resolv.conf" }, + { Value, "interval", "120" }, + { Value, "timeout", "240" }, + { Value, "lat", "12.123" }, + { Value, "lon", "12.123" }, + { Value, "latlon_file", "/var/run/latlon.js" }, + { Value, "latlon_infile", "/var/run/gps.txt" }, + { Value, "sighup_pid_file", "/var/run/dnsmasq.pid" }, + { Value, "name_change_script", "/usr/local/bin/announce_new_hosts.sh" }, + { DynamicList, "service", "http://me.olsr:80|tcp|my little homepage" }, + { Value, "services_file", "/var/run/services_olsr" }, + { Value, "services_change_script", "/usr/local/bin/announce_new_services.sh" }, + { DynamicList, "mac", "xx:xx:xx:xx:xx:xx[,0-255]" }, + { Value, "macs_file", "/path/to/macs_file" }, + { Value, "macs_change_script", "/path/to/script" } + }, + + ["olsrd_quagga.so.0.2.2"] = { + { StaticList, "redistribute", { + "system", "kernel", "connect", "static", "rip", "ripng", "ospf", + "ospf6", "isis", "bgp", "hsls" + } }, + { ListValue, "ExportRoutes", { "only", "both" } }, + { Flag, "LocalPref", "true" }, + { Value, "Distance", Range(0,255) } + }, + + ["olsrd_secure.so.0.5"] = { + { Value, "Keyfile", "/etc/private-olsr.key" } + }, + + ["olsrd_txtinfo.so.0.1"] = { + { Value, "accept", "127.0.0.1" } + }, + + ["olsrd_jsoninfo.so.0.0"] = { + { Value, "accept", "127.0.0.1" }, + { Value, "port", "9090" }, + { Value, "UUIDFile", "/etc/olsrd/olsrd.uuid" }, + + }, + + ["olsrd_watchdog.so.0.1"] = { + { Value, "file", "/var/run/olsrd.watchdog" }, + { Value, "interval", "30" } + }, + + ["olsrd_mdns.so.1.0.0"] = { + { DynamicList, "NonOlsrIf", "lan" } + }, + + ["olsrd_p2pd.so.0.1.0"] = { + { DynamicList, "NonOlsrIf", "lan" }, + { Value, "P2pdTtl", "10" } + }, + + ["olsrd_arprefresh.so.0.1"] = {}, + ["olsrd_dot_draw.so.0.3"] = {}, + ["olsrd_dyn_gw_plain.so.0.4"] = {}, + ["olsrd_pgraph.so.1.1"] = {}, + ["olsrd_tas.so.0.1"] = {} + } + + + -- build plugin options with dependencies + if knownPlParams[arg[1]] then + for _, option in ipairs(knownPlParams[arg[1]]) do + local otype, name, default, uci2cbi, cbi2uci = unpack(option) + local values + + if type(default) == "table" then + values = default + default = default[1] + end + + if otype == Flag then + local bool = p:option( Flag, name, name ) + if default == "yes" or default == "no" then + bool.enabled = "yes" + bool.disabled = "no" + elseif default == "on" or default == "off" then + bool.enabled = "on" + bool.disabled = "off" + elseif default == "1" or default == "0" then + bool.enabled = "1" + bool.disabled = "0" + else + bool.enabled = "true" + bool.disabled = "false" + end + bool.optional = true + bool.default = default + bool:depends({ library = plugin }) + else + local field = p:option( otype, name, name ) + if values then + for _, value in ipairs(values) do + field:value( value ) + end + end + if type(uci2cbi) == "function" then + function field.cfgvalue(self, section) + return uci2cbi(otype.cfgvalue(self, section)) + end + end + if type(cbi2uci) == "function" then + function field.formvalue(self, section) + return cbi2uci(otype.formvalue(self, section)) + end + end + field.optional = true + field.default = default + --field:depends({ library = arg[1] }) + end + end + end + + return mp + +else + + mpi = Map("olsrd", translate("OLSR - Plugins")) + + local plugins = {} + mpi.uci:foreach("olsrd", "LoadPlugin", + function(section) + if section.library and not plugins[section.library] then + plugins[section.library] = true + end + end + ) + + -- create a loadplugin section for each found plugin + for v in fs.dir("/usr/lib") do + if v:sub(1, 6) == "olsrd_" then + if not plugins[v] then + mpi.uci:section( + "olsrd", "LoadPlugin", nil, + { library = v, ignore = 1 } + ) + end + end + end + + t = mpi:section( TypedSection, "LoadPlugin", translate("Plugins") ) + t.anonymous = true + t.template = "cbi/tblsection" + t.override_scheme = true + function t.extedit(self, section) + local lib = self.map:get(section, "library") or "" + return luci.dispatcher.build_url("admin", "services", "olsrd", "plugins") .. "/" .. lib + end + + ign = t:option( Flag, "ignore", translate("Enabled") ) + ign.enabled = "0" + ign.disabled = "1" + ign.rmempty = false + function ign.cfgvalue(self, section) + return Flag.cfgvalue(self, section) or "0" + end + + t:option( DummyValue, "library", translate("Library") ) + + return mpi +end diff --git a/applications/luci-app-olsr/luasrc/model/cbi/olsr/olsrdplugins6.lua b/applications/luci-app-olsr/luasrc/model/cbi/olsr/olsrdplugins6.lua new file mode 100644 index 000000000..221938e7a --- /dev/null +++ b/applications/luci-app-olsr/luasrc/model/cbi/olsr/olsrdplugins6.lua @@ -0,0 +1,270 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth <steven@midlink.org> +Copyright 2009 Jo-Philipp Wich <xm@subsignal.org> + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +$Id$ +]]-- + +local ip = require "luci.ip" +local fs = require "nixio.fs" + +if arg[1] then + mp = Map("olsrd6", translate("OLSR - Plugins")) + + p = mp:section(TypedSection, "LoadPlugin", translate("Plugin configuration")) + p:depends("library", arg[1]) + p.anonymous = true + + ign = p:option(Flag, "ignore", translate("Enable")) + ign.enabled = "0" + ign.disabled = "1" + ign.rmempty = false + function ign.cfgvalue(self, section) + return Flag.cfgvalue(self, section) or "0" + end + + lib = p:option(DummyValue, "library", translate("Library")) + lib.default = arg[1] + + local function Range(x,y) + local t = {} + for i = x, y do t[#t+1] = i end + return t + end + + local function Cidr2IpMask(val) + if val then + for i = 1, #val do + local cidr = ip.IPv4(val[i]) or ip.IPv6(val[i]) + if cidr then + val[i] = cidr:network():string() .. " " .. cidr:mask():string() + end + end + return val + end + end + + local function IpMask2Cidr(val) + if val then + for i = 1, #val do + local ip, mask = val[i]:gmatch("([^%s]+)%s+([^%s]+)")() + local cidr + if ip and mask and ip:match(":") then + cidr = ip.IPv6(ip, mask) + elseif ip and mask then + cidr = ip.IPv4(ip, mask) + end + + if cidr then + val[i] = cidr:string() + end + end + return val + end + end + + + local knownPlParams = { + ["olsrd_bmf.so.1.5.3"] = { + { Value, "BmfInterface", "bmf0" }, + { Value, "BmfInterfaceIp", "10.10.10.234/24" }, + { Flag, "DoLocalBroadcast", "no" }, + { Flag, "CapturePacketsOnOlsrInterfaces", "yes" }, + { ListValue, "BmfMechanism", { "UnicastPromiscuous", "Broadcast" } }, + { Value, "BroadcastRetransmitCount", "2" }, + { Value, "FanOutLimit", "4" }, + { DynamicList, "NonOlsrIf", "br-lan" } + }, + + ["olsrd_dyn_gw.so.0.4"] = { + { Value, "Interval", "40" }, + { DynamicList, "Ping", "141.1.1.1" }, + { DynamicList, "HNA", "192.168.80.0/24", IpMask2Cidr, Cidr2IpMask } + }, + + ["olsrd_httpinfo.so.0.1"] = { + { Value, "port", "80" }, + { DynamicList, "Host", "163.24.87.3" }, + { DynamicList, "Net", "0.0.0.0/0", Cidr2IpMask } + }, + + ["olsrd_nameservice.so.0.3"] = { + { DynamicList, "name", "my-name.mesh" }, + { DynamicList, "hosts", "1.2.3.4 name-for-other-interface.mesh" }, + { Value, "suffix", ".olsr" }, + { Value, "hosts_file", "/path/to/hosts_file" }, + { Value, "add_hosts", "/path/to/file" }, + { Value, "dns_server", "141.1.1.1" }, + { Value, "resolv_file", "/path/to/resolv.conf" }, + { Value, "interval", "120" }, + { Value, "timeout", "240" }, + { Value, "lat", "12.123" }, + { Value, "lon", "12.123" }, + { Value, "latlon_file", "/var/run/latlon.js.ipv6" }, + { Value, "latlon_infile", "/var/run/gps.txt" }, + { Value, "sighup_pid_file", "/var/run/dnsmasq.pid" }, + { Value, "name_change_script", "/usr/local/bin/announce_new_hosts.sh" }, + { DynamicList, "service", "http://me.olsr:80|tcp|my little homepage" }, + { Value, "services_file", "/var/run/services_olsr" }, + { Value, "services_change_script", "/usr/local/bin/announce_new_services.sh" }, + { DynamicList, "mac", "xx:xx:xx:xx:xx:xx[,0-255]" }, + { Value, "macs_file", "/path/to/macs_file" }, + { Value, "macs_change_script", "/path/to/script" } + }, + + ["olsrd_quagga.so.0.2.2"] = { + { StaticList, "redistribute", { + "system", "kernel", "connect", "static", "rip", "ripng", "ospf", + "ospf6", "isis", "bgp", "hsls" + } }, + { ListValue, "ExportRoutes", { "only", "both" } }, + { Flag, "LocalPref", "true" }, + { Value, "Distance", Range(0,255) } + }, + + ["olsrd_secure.so.0.5"] = { + { Value, "Keyfile", "/etc/private-olsr.key" } + }, + + ["olsrd_txtinfo.so.0.1"] = { + { Value, "accept", "::1/128" } + }, + + ["olsrd_jsoninfo.so.0.0"] = { + { Value, "accept", "::1/128" }, + { Value, "port", "9090" }, + { Value, "UUIDFile", "/etc/olsrd/olsrd.uuid.ipv6" }, + + }, + + ["olsrd_watchdog.so.0.1"] = { + { Value, "file", "/var/run/olsrd.watchdog.ipv6" }, + { Value, "interval", "30" } + }, + + ["olsrd_mdns.so.1.0.0"] = { + { DynamicList, "NonOlsrIf", "lan" } + }, + + ["olsrd_p2pd.so.0.1.0"] = { + { DynamicList, "NonOlsrIf", "lan" }, + { Value, "P2pdTtl", "10" } + }, + + ["olsrd_arprefresh.so.0.1"] = {}, + ["olsrd_dot_draw.so.0.3"] = {}, + ["olsrd_dyn_gw_plain.so.0.4"] = {}, + ["olsrd_pgraph.so.1.1"] = {}, + ["olsrd_tas.so.0.1"] = {} + } + + + -- build plugin options with dependencies + if knownPlParams[arg[1]] then + for _, option in ipairs(knownPlParams[arg[1]]) do + local otype, name, default, uci2cbi, cbi2uci = unpack(option) + local values + + if type(default) == "table" then + values = default + default = default[1] + end + + if otype == Flag then + local bool = p:option( Flag, name, name ) + if default == "yes" or default == "no" then + bool.enabled = "yes" + bool.disabled = "no" + elseif default == "on" or default == "off" then + bool.enabled = "on" + bool.disabled = "off" + elseif default == "1" or default == "0" then + bool.enabled = "1" + bool.disabled = "0" + else + bool.enabled = "true" + bool.disabled = "false" + end + bool.optional = true + bool.default = default + bool:depends({ library = plugin }) + else + local field = p:option( otype, name, name ) + if values then + for _, value in ipairs(values) do + field:value( value ) + end + end + if type(uci2cbi) == "function" then + function field.cfgvalue(self, section) + return uci2cbi(otype.cfgvalue(self, section)) + end + end + if type(cbi2uci) == "function" then + function field.formvalue(self, section) + return cbi2uci(otype.formvalue(self, section)) + end + end + field.optional = true + field.default = default + --field:depends({ library = arg[1] }) + end + end + end + + return mp + +else + + mpi = Map("olsrd6", translate("OLSR - Plugins")) + + local plugins = {} + mpi.uci:foreach("olsrd6", "LoadPlugin", + function(section) + if section.library and not plugins[section.library] then + plugins[section.library] = true + end + end + ) + + -- create a loadplugin section for each found plugin + for v in fs.dir("/usr/lib") do + if v:sub(1, 6) == "olsrd_" then + if not plugins[v] then + mpi.uci:section( + "olsrd6", "LoadPlugin", nil, + { library = v, ignore = 1 } + ) + end + end + end + + t = mpi:section( TypedSection, "LoadPlugin", translate("Plugins") ) + t.anonymous = true + t.template = "cbi/tblsection" + t.override_scheme = true + function t.extedit(self, section) + local lib = self.map:get(section, "library") or "" + return luci.dispatcher.build_url("admin", "services", "olsrd6", "plugins") .. "/" .. lib + end + + ign = t:option( Flag, "ignore", translate("Enabled") ) + ign.enabled = "0" + ign.disabled = "1" + ign.rmempty = false + function ign.cfgvalue(self, section) + return Flag.cfgvalue(self, section) or "0" + end + + t:option( DummyValue, "library", translate("Library") ) + + return mpi +end diff --git a/applications/luci-app-olsr/luasrc/tools/olsr.lua b/applications/luci-app-olsr/luasrc/tools/olsr.lua new file mode 100644 index 000000000..dfd8262f0 --- /dev/null +++ b/applications/luci-app-olsr/luasrc/tools/olsr.lua @@ -0,0 +1,42 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2011 Manuel Munz <freifunk at somakoma dot de> + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 +]]-- + +module("luci.tools.olsr", package.seeall) + +function etx_color(etx) + local color = "#bb3333" + if etx == 0 then + color = "#bb3333" + elseif etx < 2 then + color = "#00cc00" + elseif etx < 4 then + color = "#ffcb05" + elseif etx < 10 then + color = "#ff6600" + end + return color +end + +function snr_color(snr) + local color = "#bb3333" + if snr == 0 then + color = "#bb3333" + elseif snr > 30 then + color = "#00cc00" + elseif snr > 20 then + color = "#ffcb05" + elseif snr > 5 then + color = "#ff6600" + end + return color +end + diff --git a/applications/luci-app-olsr/luasrc/view/status-olsr/common_js.htm b/applications/luci-app-olsr/luasrc/view/status-olsr/common_js.htm new file mode 100644 index 000000000..1ee763e11 --- /dev/null +++ b/applications/luci-app-olsr/luasrc/view/status-olsr/common_js.htm @@ -0,0 +1,35 @@ +<% if has_v4 and has_v6 then %> +<script type="text/javascript">//<![CDATA[ + +function css(selector, property, value) { + for (var i=0; i<document.styleSheets.length;i++) { + try { document.styleSheets[i].insertRule(selector+ ' {'+property+':'+value+'}', document.styleSheets[i].cssRules.length); + } catch(err) {try { document.styleSheets[i].addRule(selector, property+':'+value);} catch(err) {}}//IE + } +} + +window.onload = function() { + buttons = '<input type="button" name="show-proto-4" id="show-proto-4" class="cbi-button cbi-button-apply" style="margin-right: 5px" value="<%:Hide IPv4%>">' + buttons += '<input type="button" name="show-proto-6" id="show-proto-6" class="cbi-button cbi-button-apply" value="<%:Hide IPv6%>">' + + document.getElementById('togglebuttons').innerHTML = buttons; + + var visible = true; + document.getElementById('show-proto-4').onclick = function() { + visible = !visible; + document.getElementById('show-proto-4').value = visible ? '<%:Hide IPv4%>' : '<%:Show IPv4%>'; + document.getElementById('show-proto-4').className = visible ? 'cbi-button cbi-button-apply' : 'cbi-button cbi-button-reset'; + css('.proto-4', 'display', visible ? 'table-row' : 'none') + }; + + var visible6 = true; + document.getElementById('show-proto-6').onclick = function() { + visible6 = !visible6; + document.getElementById('show-proto-6').value = visible6 ? '<%:Hide IPv6%>' : '<%:Show IPv6%>'; + document.getElementById('show-proto-6').className = visible6 ? 'cbi-button cbi-button-apply' : 'cbi-button cbi-button-reset'; + css('.proto-6', 'display', visible6 ? 'table-row' : 'none') + }; + +} +//]]></script> +<%end %> diff --git a/applications/luci-app-olsr/luasrc/view/status-olsr/error_olsr.htm b/applications/luci-app-olsr/luasrc/view/status-olsr/error_olsr.htm new file mode 100644 index 000000000..2c872fa5a --- /dev/null +++ b/applications/luci-app-olsr/luasrc/view/status-olsr/error_olsr.htm @@ -0,0 +1,17 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth <steven@midlink.org> +Copyright 2008 Jo-Philipp Wich <xm@leipzig.freifunk.net> + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +-%> +<%+header%> +<h2><a id="content" name="content"><%:OLSR Daemon%></a></h2> +<p class="error"><%:Unable to connect to the OLSR daemon!%></p> +<p><%:Make sure that OLSRd is running, the "jsoninfo" plugin is loaded, configured on port 9090 and accepts connections from "127.0.0.1".%></p> +<%+footer%> diff --git a/applications/luci-app-olsr/luasrc/view/status-olsr/hna.htm b/applications/luci-app-olsr/luasrc/view/status-olsr/hna.htm new file mode 100644 index 000000000..689bafdfa --- /dev/null +++ b/applications/luci-app-olsr/luasrc/view/status-olsr/hna.htm @@ -0,0 +1,129 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth <steven@midlink.org> +Copyright 2008 Jo-Philipp Wich <xm@leipzig.freifunk.net> +Copyright 2011 Manuel Munz <freifunk at somakoma dot de> + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +-%> + +<% +local i = 1 + +if luci.http.formvalue("status") == "1" then + local rv = {} + for k, hna in ipairs(hna) do + rv[#rv+1] = { + proto = hna["proto"], + destination = hna["destination"], + genmask = hna["genmask"], + gateway = hna["gateway"], + hostname = hna["hostname"], + validityTime = hna["validityTime"] + } + end + luci.http.prepare_content("application/json") + luci.http.write_json(rv) + return +end +%> + +<%+header%> + +<script type="text/javascript" src="<%=resource%>/cbi.js"></script> +<script type="text/javascript">//<![CDATA[ +XHR.poll(10, '<%=REQUEST_URI%>', { status: 1 }, + function(x, info) + { + var hnadiv = document.getElementById('olsrd_hna'); + if (hnadiv) + { + var s = ''; + for (var idx = 0; idx < info.length; idx++) + { + var hna = info[idx]; + var linkgw = '' + s += '<tr class="cbi-section-table-row cbi-rowstyle-'+(1 + (idx % 2))+' proto-' + hna.proto + '">' + if (hna.proto == '6') { + linkgw = '<a href="http://[' + hna.gateway + ']/cgi-bin-status.html">' + hna.gateway + '</a>' + } else { + linkgw = '<a href="http://' + hna.gateway + '/cgi-bin-status.html">' + hna.gateway + '</a>' + } + + if (hna.validityTime != undefined) { + validity = hna.validityTime + 's' + } else { + validity = '-' + } + + if (hna.hostname != undefined) { + hostname = ' / <a href="http://' + hna.hostname + '/cgi-bin-status.html">' + hna.hostname + '</a>' + } else { + hostname = '' + } + + s += String.format( + '<td class="cbi-section-table-cell">%s</td>' + + '<td class="cbi-section-table-cell">%s</td>' + + '<td class="cbi-section-table-cell">%s</td>', hna.destination + '/' + hna.genmask, linkgw + hostname, validity + ) + s += '</tr>' + } + hnadiv.innerHTML = s; + } +} +); +//]]></script> + +<h2><a id="content" name="content"><%:Active host net announcements%></a></h2> + +<div id="togglebuttons"></div> +<fieldset class="cbi-section"> + + <legend><%:Overview of currently active OLSR host net announcements%></legend> + <table class="cbi-section-table"> + <thead> + <tr class="cbi-section-table-titles"> + <th class="cbi-section-table-cell"><%:Announced network%></th> + <th class="cbi-section-table-cell"><%:OLSR gateway%></th> + <th class="cbi-section-table-cell"><%:Validity Time%></th> + </tr> + + </thead> + <tbody id="olsrd_hna"> + <% for k, route in ipairs(hna) do %> + + <tr class="cbi-section-table-row cbi-rowstyle-<%=i%> proto-<%=hna[k].proto%>"> + <td class="cbi-section-table-cell"><%=hna[k].destination%>/<%=hna[k].genmask%> </td> + <td class="cbi-section-table-cell"> + <% if hna[k].proto == '6' then %> + <a href="http://[<%=hna[k].gateway%>]/cgi-bin-status.html"><%=hna[k].gateway%></a> + <% else %> + <a href="http://<%=hna[k].gateway%>/cgi-bin-status.html"><%=hna[k].gateway%></a> + <% end %> + <% if hna[k].hostname then %> + / <a href="http://<%=hna[k].hostname%>/cgi-bin-status.html"><%=hna[k].hostname%></a> + <% end %> + </td> + <% if hna[k].validityTime then + validity = hna[k].validityTime .. 's' + else + validity = '-' + end %> + + <td class="cbi-section-table-cell"><%=validity%></td> + </tr> + + <% i = ((i % 2) + 1) + end %> + </tbody> + </table> +</fieldset> + +<%+status-olsr/common_js%> +<%+footer%> diff --git a/applications/luci-app-olsr/luasrc/view/status-olsr/interfaces.htm b/applications/luci-app-olsr/luasrc/view/status-olsr/interfaces.htm new file mode 100644 index 000000000..dd1a21ea6 --- /dev/null +++ b/applications/luci-app-olsr/luasrc/view/status-olsr/interfaces.htm @@ -0,0 +1,57 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth <steven@midlink.org> +Copyright 2008 Jo-Philipp Wich <xm@leipzig.freifunk.net> +Copyright 2011 Manuel Munz <freifunk at somakoma dot de> + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +-%> + +<% +local i = 1 +%> + +<%+header%> + +<h2><a id="content" name="content"><%:Interfaces%></a></h2> + +<div id="togglebuttons"></div> + +<fieldset class="cbi-section"> + <legend><%:Overview of interfaces where OLSR is running%></legend> + + <table class="cbi-section-table"> + <tr> + <th class="cbi-section-table-cell"><%:Interface%></th> + <th class="cbi-section-table-cell"><%:State%></th> + <th class="cbi-section-table-cell"><%:MTU%></th> + <th class="cbi-section-table-cell"><%:WLAN%></th> + <th class="cbi-section-table-cell"><%:Source address%></th> + <th class="cbi-section-table-cell"><%:Netmask%></th> + <th class="cbi-section-table-cell"><%:Broadcast address%></th> + </tr> + + <% for k, iface in ipairs(iface) do %> + + <tr class="cbi-section-table-row cbi-rowstyle-<%=i%> proto-<%=iface.proto%>"> + <td class="cbi-section-table-cell"><%=iface.name%></td> + <td class="cbi-section-table-cell"><%=iface.state%></td> + <td class="cbi-section-table-cell"><%=iface.olsrMTU%></td> + <td class="cbi-section-table-cell"><%=iface.wireless and luci.i18n.translate('yes') or luci.i18n.translate('no')%></td> + <td class="cbi-section-table-cell"><%=iface.ipv4Address or iface.ipv6Address%></td> + <td class="cbi-section-table-cell"><%=iface.netmask%></td> + <td class="cbi-section-table-cell"><%=iface.broadcast or iface.multicast%></td> + </tr> + <% i = ((i % 2) + 1) + end %> + </table> +</fieldset> +<%+status-olsr/common_js%> +<%+footer%> + + diff --git a/applications/luci-app-olsr/luasrc/view/status-olsr/legend.htm b/applications/luci-app-olsr/luasrc/view/status-olsr/legend.htm new file mode 100644 index 000000000..2f598489d --- /dev/null +++ b/applications/luci-app-olsr/luasrc/view/status-olsr/legend.htm @@ -0,0 +1,24 @@ +<h3><%:Legend%>:</h3> +<ul> + <li><strong>LQ: </strong><%:Success rate of packages received from the neighbour%></li> + <li><strong>NLQ: </strong><%:Success rate of packages sent to the neighbour%></li> + <li><strong>ETX: </strong><%:Expected retransmission count%></li> + <li style="list-style: none"> + <ul> + <li><strong><span style="color:#00cc00"><%:Green%></span></strong>:<%:Very good (ETX < 2)%></li> + <li><strong><span style="color:#ffcb05"><%:Yellow%></span></strong>:<%:Good (2 < ETX < 4)%></li> + <li><strong><span style="color:#ff6600"><%:Orange%></span></strong>:<%:Still usable (4 < ETX < 10)%></li> + <li><strong><span style="color:#bb3333"><%:Red%></span></strong>:<%:Bad (ETX > 10)%></li> + </ul> + </li> + <li><strong>SNR: </strong><%:Signal Noise Ratio in dB%></li> + <li style="list-style: none"> + <ul> + <li><strong><span style="color:#00cc00"><%:Green%></span></strong>:<%:Very good (SNR > 30)%></li> + <li><strong><span style="color:#ffcb05"><%:Yellow%></span></strong>:<%:Good (30 > SNR > 20)%></li> + <li><strong><span style="color:#ff6600"><%:Orange%></span></strong>:<%:Still usable (20 > SNR > 5)%></li> + <li><strong><span style="color:#bb3333"><%:Red%></span></strong>:<%:Bad (SNR < 5)%></li> + </ul> + </li> +</ul> + diff --git a/applications/luci-app-olsr/luasrc/view/status-olsr/mid.htm b/applications/luci-app-olsr/luasrc/view/status-olsr/mid.htm new file mode 100644 index 000000000..ec5caaa95 --- /dev/null +++ b/applications/luci-app-olsr/luasrc/view/status-olsr/mid.htm @@ -0,0 +1,58 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth <steven@midlink.org> +Copyright 2008 Jo-Philipp Wich <xm@leipzig.freifunk.net> +Copyright 2011 Manuel Munz <freifunk at somakoma dot de> + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +$Id$ + +-%> +<% +local i = 1 +%> + +<%+header%> +<h2><a id="content" name="content"><%:Active MID announcements%></a></h2> + +<div id="togglebuttons"></div> +<fieldset class="cbi-section"> + <legend><%:Overview of known multiple interface announcements%></legend> + <table class="cbi-section-table"> + <tr class="cbi-section-table-titles"> + <th class="cbi-section-table-cell"><%:OLSR node%></th> + <th class="cbi-section-table-cell" ><%:Secondary OLSR interfaces%></th> + </tr> + + <% for k, mid in ipairs(mids) do + local aliases = '' + for k,v in ipairs(mid.aliases) do + if aliases == '' then + sep = '' + else + sep = ', ' + end + aliases = v.ipAddress .. sep .. aliases + end + local host = mid.ipAddress + if mid.proto == '6' then + host = '[' .. mid.ipAddress .. ']' + end + %> + + <tr class="cbi-section-table-row cbi-rowstyle-<%=i%> proto-<%=mid.proto%>"> + <td class="cbi-section-table-cell"><a href="http://<%=host%>/cgi-bin-status.html"><%=mid.ipAddress%></a></td> + <td class="cbi-section-table-cell"><%=aliases%></td> + </tr> + + <% i = ((i % 2) + 1) + end %> + </table> +</fieldset> +<%+status-olsr/common_js%> +<%+footer%> diff --git a/applications/luci-app-olsr/luasrc/view/status-olsr/neighbors.htm b/applications/luci-app-olsr/luasrc/view/status-olsr/neighbors.htm new file mode 100644 index 000000000..daa52831f --- /dev/null +++ b/applications/luci-app-olsr/luasrc/view/status-olsr/neighbors.htm @@ -0,0 +1,181 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth <steven@midlink.org> +Copyright 2008 Jo-Philipp Wich <xm@leipzig.freifunk.net> +Copyright 2011 Manuel Munz <freifunk at somakoma dot de> + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +-%> + +<% +local olsrtools = require "luci.tools.olsr" +local i = 1 + +if luci.http.formvalue("status") == "1" then + local rv = {} + for k, link in ipairs(links) do + link.linkCost = tonumber(link.linkCost)/1024 or 0 + if link.linkCost == 4096 then + link.linkCost = 0 + end + local color = olsrtools.etx_color(link.linkCost) + local snr_color = olsrtools.snr_color(link.snr) + defaultgw_color = "" + if link.defaultgw == 1 then + defaultgw_color = "#ffff99" + end + + rv[#rv+1] = { + rip = link.remoteIP, + hn = link.hostname, + lip = link.localIP, + ifn = link.interface, + lq = string.format("%.3f", link.linkQuality), + nlq = string.format("%.3f",link.neighborLinkQuality), + cost = string.format("%.3f", link.linkCost), + snr = link.snr, + signal = link.signal, + noise = link.noise, + color = color, + snr_color = snr_color, + dfgcolor = defaultgw_color, + proto = link.proto + } + end + luci.http.prepare_content("application/json") + luci.http.write_json(rv) + return +end +%> + +<%+header%> + +<script type="text/javascript" src="<%=resource%>/cbi.js"></script> +<script type="text/javascript">//<![CDATA[ + + XHR.poll(10 , '<%=REQUEST_URI%>', { status: 1 }, + function(x, info) + { + var nt = document.getElementById('olsr_neigh_table'); + if (nt) + { + var s = ''; + for (var idx = 0; idx < info.length; idx++) + { + var neigh = info[idx]; + + if (neigh.proto == '6') { + s += String.format( + '<tr class="cbi-section-table-row cbi-rowstyle-'+(1 + (idx % 2))+' proto-%s">' + + '<td class="cbi-section-table-titles" style="background-color:%s"><a href="http://[%s]/cgi-bin-status.html">%s</a></td>', + neigh.proto, neigh.dfgcolor, neigh.rip, neigh.rip + ); + } else { + s += String.format( + '<tr class="cbi-section-table-row cbi-rowstyle-'+(1 + (idx % 2))+' proto-%s">' + + '<td class="cbi-section-table-titles" style="background-color:%s"><a href="http://%s/cgi-bin-status.html">%s</a></td>', + neigh.proto, neigh.dfgcolor, neigh.rip, neigh.rip + ); + } + if (neigh.hn) { + s += String.format( + '<td class="cbi-section-table-titles" style="background-color:%s"><a href="http://%s/cgi-bin-status.html">%s</a></td>', + neigh.dfgcolor, neigh.hn, neigh.hn + ); + } else { + s += String.format( + '<td class="cbi-section-table-titles" style="background-color:%s">?</td>', + neigh.dfgcolor + ); + } + s += String.format( + '<td class="cbi-section-table-titles" style="background-color:%s">%s</td>' + + '<td class="cbi-section-table-titles" style="background-color:%s">%s</td>' + + '<td class="cbi-section-table-titles" style="background-color:%s">%s</td>' + + '<td class="cbi-section-table-titles" style="background-color:%s">%s</td>' + + '<td class="cbi-section-table-titles" style="background-color:%s">%s</td>' + + '<td class="cbi-section-table-titles" style="background-color:%s" title="Signal: %s Noise: %s">%s</td>' + + '</tr>', + neigh.dfgcolor, neigh.ifn, neigh.dfgcolor, neigh.lip, neigh.dfgcolor, neigh.lq, neigh.dfgcolor, neigh.nlq, neigh.color, neigh.cost, neigh.snr_color, neigh.signal, neigh.noise, neigh.snr || '?' + ); + } + + nt.innerHTML = s; + } + } + ); +//]]></script> + + +<h2><a id="content" name="content"><%:OLSR connections%></a></h2> + +<div id="togglebuttons"></div> + +<fieldset class="cbi-section"> + <legend><%:Overview of currently established OLSR connections%></legend> + + <table class="cbi-section-table"> + <thead> + <tr class="cbi-section-table-titles"> + <th class="cbi-section-table-cell"><%:Neighbour IP%></th> + <th class="cbi-section-table-cell"><%:Hostname%></th> + <th class="cbi-section-table-cell"><%:Interface%></th> + <th class="cbi-section-table-cell"><%:Local interface IP%></th> + <th class="cbi-section-table-cell">LQ</th> + <th class="cbi-section-table-cell">NLQ</th> + <th class="cbi-section-table-cell">ETX</th> + <th class="cbi-section-table-cell">SNR</th> + </tr> + </thead> + + <tbody id="olsr_neigh_table"> + <% local i = 1 + for k, link in ipairs(links) do + link.linkCost = tonumber(link.linkCost)/1024 or 0 + if link.linkCost == 4096 then + link.linkCost = 0 + end + + color = olsrtools.etx_color(link.linkCost) + snr_color = olsrtools.snr_color(link.snr) + + if link.snr == 0 then + link.snr = '?' + end + + defaultgw_color = "" + if link.defaultgw == 1 then + defaultgw_color = "#ffff99" + end + %> + + <tr class="cbi-section-table-row cbi-rowstyle-<%=i%> proto-<%=link.proto%>"> + <% if link.proto == "6" then %> + <td class="cbi-section-table-titles" style="background-color:<%=defaultgw_color%>"><a href="http://[<%=link.remoteIP%>]/cgi-bin-status.html"><%=link.remoteIP%></a></td> + <% else %> + <td class="cbi-section-table-titles" style="background-color:<%=defaultgw_color%>"><a href="http://<%=link.remoteIP%>/cgi-bin-status.html"><%=link.remoteIP%></a></td> + <% end %> + <td class="cbi-section-table-titles" style="background-color:<%=defaultgw_color%>"><a href="http://<%=link.hostname%>/cgi-bin-status.html"><%=link.hostname%></a></td> + <td class="cbi-section-table-titles" style="background-color:<%=defaultgw_color%>"><%=link.interface%></td> + <td class="cbi-section-table-titles" style="background-color:<%=defaultgw_color%>"><%=link.localIP%></td> + <td class="cbi-section-table-titles" style="background-color:<%=defaultgw_color%>"><%=string.format("%.3f", link.linkQuality)%></td> + <td class="cbi-section-table-titles" style="background-color:<%=defaultgw_color%>"><%=string.format("%.3f", link.neighborLinkQuality)%></td> + <td class="cbi-section-table-titles" style="background-color:<%=color%>"><%=string.format("%.3f", link.linkCost)%></td> + <td class="cbi-section-table-titles" style="background-color:<%=snr_color%>" title="Signal: <%=link.signal%> Noise: <%=link.noise%>"><%=link.snr%></td> + </tr> + <% + i = ((i % 2) + 1) + end %> + </tbody> + </table> +<br /> + +<%+status-olsr/legend%> +</fieldset> +<%+status-olsr/common_js%> +<%+footer%> diff --git a/applications/luci-app-olsr/luasrc/view/status-olsr/overview.htm b/applications/luci-app-olsr/luasrc/view/status-olsr/overview.htm new file mode 100644 index 000000000..6d8eca874 --- /dev/null +++ b/applications/luci-app-olsr/luasrc/view/status-olsr/overview.htm @@ -0,0 +1,220 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth <steven@midlink.org> +Copyright 2008 Jo-Philipp Wich <xm@leipzig.freifunk.net> +Copyright 2011 Manuel Munz <freifunk at somakoma dot de> + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 +-%> + +<% +local ipv = luci.model.uci.cursor():get_first("olsrd", "olsrd", "IpVersion", "4") + +function write_conf(conf, file) + local fs = require "luci.fs" + if fs.access(conf) then + luci.http.header("Content-Disposition", "attachment; filename="..file) + luci.http.prepare_content("text/plain") + luci.http.write(fs.readfile(conf)) + end +end + +conf = luci.http.formvalue() + +if conf.openwrt then + write_conf("/etc/config/olsrd", "olsrd") + return false +end + +if conf.conf_v4 then + write_conf("/var/etc/olsrd.conf.ipv4", "olsrd.conf.ipv4") + return false +end + +if conf.conf_v6 then + write_conf("/var/etc/olsrd.conf.ipv6", "olsrd.conf.ipv6") + return false +end + +if conf.conf then + write_conf("/var/etc/olsrd.conf", "olsrd.conf") + return false +end + +%> + +<%+header%> + +<script type="text/javascript" src="<%=resource%>/cbi.js"></script> +<script type="text/javascript">//<![CDATA[ + +XHR.poll(10, '<%=REQUEST_URI%>/json', { }, + function(x, info) + { + var e; + + if (! info) { + document.getElementById('error').innerHTML = '<%:Could not get any data. Make sure the jsoninfo plugin is installed and allows connections from localhost.%>'; + return + } + document.getElementById('error').innerHTML = ''; + + if (e = document.getElementById('version')) + var version; + var date; + if (info.v4.config.olsrdVersion != undefined) { + version = info.v4.config.olsrdVersion + date = info.v4.config.olsrdBuildDate + } else if (info.v6.config.olsrdVersion != undefined) { + version = info.v6.config.olsrdVersion + date = info.v6.config.olsrdBuildDate + } else { + version = 'unknown' + date = 'unknown' + } + e.innerHTML = version + '<br />' + date; + + if (e = document.getElementById('nr_neigh')) + var neigh = 0; + if (info.v4.links != undefined) { + neigh = neigh + info.v4.links.length + } + if (info.v6.links != undefined) { + neigh = neigh + info.v6.links.length + } + e.innerHTML = neigh; + + + if (e = document.getElementById('nr_hna')) + var hna = 0; + if (info.v4.hna != undefined) { + hna = hna + info.v4.hna.length + } + if (info.v6.hna != undefined) { + hna = hna + info.v6.hna.length + } + e.innerHTML = hna; + + + if (e = document.getElementById('nr_ifaces')) + var nrint = 0 + if (info.v4.interfaces != undefined) { + nrint = nrint + info.v4.interfaces.length + } + if (info.v6.interfaces != undefined) { + nrint = nrint + info.v6.interfaces.length + } + e.innerHTML = nrint + + + if (e = document.getElementById('nr_topo')) + var topo = 0; + var nodes = []; + + Array.prototype.contains = function (element) { + for (var i = 0; i < this.length; i++) { + if (this[i] == element) { + return true; + } + } + return false; + } + + if (info.v4.topology != undefined) { + topo = topo + info.v4.topology.length; + for (var i = 0; i < info.v4.topology.length; i++) { + var destip = info.v4.topology[i].destinationIP + if (! nodes.contains(destip) ) { + nodes.push(destip) + } + } + } + + if (info.v6.topology != undefined) { + topo = topo + info.v6.topology.length + for (var i = 0; i < info.v6.topology.length; i++) { + var destip = info.v6.topology[i].destinationIP + if (! nodes.contains(destip) ) { + nodes.push(destip) + } + } + + } + e.innerHTML = topo; + + if (e = document.getElementById('nr_nodes')) + e.innerHTML = nodes.length; + + if (e = document.getElementById('meshfactor')) + var meshfactor = topo / nodes.length + e.innerHTML = meshfactor.toFixed(2) + } + ); +//]]></script> + + +<div id="error" class="error"></div> + +<h2><a id="content" name="content">OLSR <%:Overview%></a></h2> + +<fieldset class="cbi-section"> + <legend><%:Network%></legend> + + <table width="100%" cellspacing="10"> + <tr><td width="33%"><%:Interfaces%></td><td> + <a href="<%=REQUEST_URI%>/interfaces"> + <span id="nr_ifaces">-<span> + </a> + </td></tr> + <tr><td width="33%"><%:Neighbors%></td><td> + <a href="<%=REQUEST_URI%>/neighbors"> + <span id="nr_neigh">-</span> + </a> + </td></tr> + <tr><td width="33%"><%:Nodes%></td><td> + <a href="<%=REQUEST_URI%>/topology"> + <span id="nr_nodes">-</span> + </a> + </td></tr> + <tr><td width="33%"><%:HNA%></td><td> + <a href="<%=REQUEST_URI%>/hna"> + <span id="nr_hna">-</span> + </a> + </td></tr> + <tr><td width="33%"><%:Links total%></td><td> + <a href="<%=REQUEST_URI%>/topology"> + <span id="nr_topo">-</span> + </a> + </td></tr> + <tr><td width="33%"><%:Links per node (average)%></td><td> + <span id="meshfactor">-</span> + </td></tr> + + + </table> +</fieldset> + + +<fieldset class="cbi-section"> + <legend>OLSR <%:Configuration%></legend> + <table width="100%" cellspacing="10"> + <tr><td width="33%"><%:Version%></td><td> + <span id="version">-<span> + </td></tr> + <tr><td width="33%"><%:Download Config%></td><td> + <a href="<%=REQUEST_URI%>?openwrt">OpenWrt</a>, + <% if ipv == "6and4" then %> + <a href="<%=REQUEST_URI%>?conf_v4">OLSRD IPv4</a>, + <a href="<%=REQUEST_URI%>?conf_v6">OLSRD IPv6</a> + <% else %> + <a href="<%=REQUEST_URI%>?conf">OLSRD</a> + <% end %> + </td></tr> + </table> +</fieldset> + +<%+footer%> diff --git a/applications/luci-app-olsr/luasrc/view/status-olsr/routes.htm b/applications/luci-app-olsr/luasrc/view/status-olsr/routes.htm new file mode 100644 index 000000000..76e1b1078 --- /dev/null +++ b/applications/luci-app-olsr/luasrc/view/status-olsr/routes.htm @@ -0,0 +1,148 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth <steven@midlink.org> +Copyright 2008 Jo-Philipp Wich <xm@leipzig.freifunk.net> +Copyright 2011 Manuel Munz <freifunk at somakoma dot de> + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 +-%> + +<% + +local olsrtools = require "luci.tools.olsr" +local i = 1 + +if luci.http.formvalue("status") == "1" then + local rv = {} + for k, route in ipairs(routes) do + local ETX = string.format("%.3f", tonumber(route.rtpMetricCost)/1024 or 0) + rv[#rv+1] = { + hostname = route.hostname, + dest = route.destination, + genmask = route.genmask, + gw = route.gateway, + interface = route.networkInterface, + metric = route.metric, + etx = ETX, + color = olsrtools.etx_color(tonumber(ETX)) + } + end + luci.http.prepare_content("application/json") + luci.http.write_json(rv) + return +end + +%> + +<%+header%> + +<script type="text/javascript" src="<%=resource%>/cbi.js"></script> +<script type="text/javascript">//<![CDATA[ + +XHR.poll(20, '<%=REQUEST_URI%>', { status: 1 }, + function(x, info) + { + + var rt = document.getElementById('olsrd_routes'); + if (rt) + { + var s = ''; + for (var idx = 0; idx < info.length; idx++) + { + var route = info[idx]; + + s += String.format( + '<tr class="cbi-section-table-row cbi-rowstyle-'+(1 + (idx % 2))+' proto-%s">' + + '<td class="cbi-section-table-cell">%s/%s</td>' + + '<td class="cbi-section-table-cell">' + + '<a href="http://%s/cgi-bin-status.html">%s</a>', + route.proto, route.dest, route.genmask, route.gw, route.gw + ) + + if (route.hostname) { + if (hna.proto == '6') { + s += String.format( + ' / <a href="http://[%s]/cgi-bin-status.html">%s</a>', + route.hostname, route.hostname || '?' + ); + } else { + s += String.format( + ' / <a href="http://%s/cgi-bin-status.html">%s</a>', + route.hostname, route.hostname || '?' + ); + } + + } + s += String.format( + '</td>' + + '<td class="cbi-section-table-cell">%s</td>' + + '<td class="cbi-section-table-cell">%s</td>' + + '<td class="cbi-section-table-cell" style="background-color:%s">%s</td>' + + '</tr>', + route.interface, route.metric, route.color, route.etx || '?' + ); + } + } + rt.innerHTML = s; + + } + ); +//]]></script> + + + +<h2><a id="content" name="content"><%:Known OLSR routes%></a></h2> + +<div id="togglebuttons"></div> + +<fieldset class="cbi-section"> +<legend><%:Overview of currently known routes to other OLSR nodes%></legend> + +<table class="cbi-section-table"> + <thead> + <tr class="cbi-section-table-titles"> + <th class="cbi-section-table-cell"><%:Announced network%></th> + <th class="cbi-section-table-cell"><%:OLSR gateway%></th> + <th class="cbi-section-table-cell"><%:Interface%></th> + <th class="cbi-section-table-cell"><%:Metric%></th> + <th class="cbi-section-table-cell">ETX</th> + </tr> + </thead> + + <tbody id="olsrd_routes"> + + <% for k, route in ipairs(routes) do + ETX = tonumber(route.rtpMetricCost)/1024 or '0' + color = olsrtools.etx_color(ETX) + %> + + <tr class="cbi-section-table-row cbi-rowstyle-<%=i%> proto-<%=route.proto%>"> + <td class="cbi-section-table-cell"><%=route.destination%>/<%=route.genmask%></td> + <td class="cbi-section-table-cell"> + <% if route.proto == '6' then %> + <a href="http://[<%=route.gateway%>]/cgi-bin-status.html"><%=route.gateway%></a> + <% else %> + <a href="http://<%=route.gateway%>/cgi-bin-status.html"><%=route.gateway%></a> + <% end %> + <% if route.hostname then %> + / <a href="http://<%=route.Hostname%>/cgi-bin-status.html"><%=route.hostname%></a> + <% end %> + </td> + <td class="cbi-section-table-cell"><%=route.networkInterface%></td> + <td class="cbi-section-table-cell"><%=route.metric%></td> + <td class="cbi-section-table-cell" style="background-color:<%=color%>"><%=string.format("%.3f", ETX)%></td> + </tr> + <% + i = ((i % 2) + 1) + end %> + </tbody> +</table> + +<%+status-olsr/legend%> +</fieldset> +<%+status-olsr/common_js%> +<%+footer%> diff --git a/applications/luci-app-olsr/luasrc/view/status-olsr/smartgw.htm b/applications/luci-app-olsr/luasrc/view/status-olsr/smartgw.htm new file mode 100644 index 000000000..75d0c1c2f --- /dev/null +++ b/applications/luci-app-olsr/luasrc/view/status-olsr/smartgw.htm @@ -0,0 +1,158 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth <steven@midlink.org> +Copyright 2008 Jo-Philipp Wich <xm@leipzig.freifunk.net> +Copyright 2011 Manuel Munz <freifunk at somakoma dot de> + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 +-%> + +<% +local i = 1 +require("luci.model.uci") +local uci = luci.model.uci.cursor_state() + +uci:foreach("olsrd", "olsrd", function(s) + if s.SmartGateway and s.SmartGateway == "yes" then has_smartgw = true end +end) + + +if luci.http.formvalue("status") == "1" then + local rv = {} + for k, gw in ipairs(gws) do + gw.tcPathCost = tonumber(gw.tcPathCost)/1024 or 0 + if gw.tcPathCost == 4096 then + gw.tcPathCost = 0 + end + + rv[#rv+1] = { + proto = gw.proto, + ipAddress = gw.ipAddress, + status = gw.ipv4Status or gw.ipv6Status, + tcPathCost = string.format("%.3f", gw.tcPathCost), + hopCount = gw.hopCount, + uplinkSpeed = gw.uplinkSpeed, + downlinkSpeed = gw.downlinkSpeed, + v4 = gw.ipv4 and luci.i18n.translate('yes') or luci.i18n.translate('no'), + v6 = gw.ipv6 and luci.i18n.translate('yes') or luci.i18n.translate('no'), + externalPrefix = gw.externalPrefix + } + end + luci.http.prepare_content("application/json") + luci.http.write_json(rv) + return +end +%> + +<%+header%> + +<script type="text/javascript" src="<%=resource%>/cbi.js"></script> +<script type="text/javascript">//<![CDATA[ +XHR.poll(10, '<%=REQUEST_URI%>', { status: 1 }, + function(x, info) + { + var smartgwdiv = document.getElementById('olsrd_smartgw'); + if (smartgwdiv) + { + var s = ''; + for (var idx = 0; idx < info.length; idx++) + { + var smartgw = info[idx]; + s += '<tr class="cbi-section-table-row cbi-rowstyle-'+(1 + (idx % 2))+' proto-' + smartgw.proto + '">' + if (smartgw.proto == '6') { + linkgw = '<a href="http://[' + smartgw.ipAddress + ']/cgi-bin-status.html">' + smartgw.ipAddress + '</a>' + } else { + linkgw = '<a href="http://' + smartgw.ipAddress + '/cgi-bin-status.html">' + smartgw.ipAddress + '</a>' + } + + s += String.format( + '<td class="cbi-section-table-cell">%s</td>' + + '<td class="cbi-section-table-cell">%s</td>' + + '<td class="cbi-section-table-cell">%s</td>' + + '<td class="cbi-section-table-cell">%s</td>' + + '<td class="cbi-section-table-cell">%s</td>' + + '<td class="cbi-section-table-cell">%s</td>' + + '<td class="cbi-section-table-cell">%s</td>' + + '<td class="cbi-section-table-cell">%s</td>' + + '<td class="cbi-section-table-cell">%s</td>', + linkgw, smartgw.status, smartgw.tcPathCost, smartgw.hopCount, smartgw.uplinkSpeed, smartgw.downlinkSpeed, smartgw.v4, smartgw.v6, smartgw.externalPrefix + ) + s += '</tr>' + } + smartgwdiv.innerHTML = s; + } +} +); +//]]></script> + + +<%+header%> + +<h2><a id="content" name="content"><%:SmartGW announcements%></a></h2> + +<div id="togglebuttons"></div> + +<% if has_smartgw then %> + + <fieldset class="cbi-section"> + <legend><%:Overview of smart gateways in this network%></legend> + <table class="cbi-section-table"> + <thead> + <tr class="cbi-section-table-titles"> + <th class="cbi-section-table-cell"><%:Gateway%></th> + <th class="cbi-section-table-cell"><%:Status%></th> + <th class="cbi-section-table-cell"><%:ETX%></th> + <th class="cbi-section-table-cell"><%:Hops%></th> + <th class="cbi-section-table-cell"><%:Uplink%></th> + <th class="cbi-section-table-cell"><%:Downlink%></th> + <th class="cbi-section-table-cell"><%:IPv4%></th> + <th class="cbi-section-table-cell"><%:IPv6%></th> + <th class="cbi-section-table-cell"><%:Prefix%></th> + + </tr> + </thead> + + <tbody id="olsrd_smartgw"> + <% for k, gw in ipairs(gws) do + + gw.tcPathCost = tonumber(gw.tcPathCost)/1024 or 0 + if gw.tcPathCost == 4096 then + gw.tcPathCost = 0 + end + %> + + <tr class="cbi-section-table-row cbi-rowstyle-<%=i%> proto-<%=proto%>"> + <% if gw.proto == '6' then %> + <td class="cbi-section-table-cell"><a href="http://[<%=gw.ipAddress%>]/cgi-bin-status.html"><%=gw.ipAddress%></a></td> + <% else %> + <td class="cbi-section-table-cell"><a href="http://<%=gw.ipAddress%>/cgi-bin-status.html"><%=gw.ipAddress%></a></td> + <% end %> + + <td class="cbi-section-table-cell"><%=gw.ipv4Status or gw.ipv6Status or '-' %></td> + <td class="cbi-section-table-cell"><%=string.format("%.3f", gw.tcPathCost)%></td> + <td class="cbi-section-table-cell"><%=gw.hopCount%></td> + <td class="cbi-section-table-cell"><%=gw.uplinkSpeed%></td> + <td class="cbi-section-table-cell"><%=gw.downlinkSpeed%></td> + <td class="cbi-section-table-cell"><%=gw.ipv4 and luci.i18n.translate('yes') or luci.i18n.translate('no')%></td> + <td class="cbi-section-table-cell"><%=gw.ipv6 and luci.i18n.translate('yes') or luci.i18n.translate('no')%></td> + <td class="cbi-section-table-cell"><%=gw.externalPrefix%></td> + </tr> + + <% i = ((i % 2) + 1) + end %> + </tbody> + </table> + </fieldset> + +<% else %> + + <%:SmartGateway is not configured on this system.%> + +<% end %> + +<%+status-olsr/common_js%> +<%+footer%> diff --git a/applications/luci-app-olsr/luasrc/view/status-olsr/topology.htm b/applications/luci-app-olsr/luasrc/view/status-olsr/topology.htm new file mode 100644 index 000000000..eb3df5ff5 --- /dev/null +++ b/applications/luci-app-olsr/luasrc/view/status-olsr/topology.htm @@ -0,0 +1,68 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth <steven@midlink.org> +Copyright 2008 Jo-Philipp Wich <xm@leipzig.freifunk.net> +Copyright 2011 Manuel Munz <freifunk at somakoma dot de> + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +-%> +<% +local i = 1 +local olsrtools = require "luci.tools.olsr" +%> + +<%+header%> +<h2><a id="content" name="content"><%:Active OLSR nodes%></a></h2> + +<div id="togglebuttons"></div> + +<fieldset class="cbi-section"> + <legend><%:Overview of currently known OLSR nodes%></legend> + <table class="cbi-section-table"> + <tr class="cbi-section-table-titles"> + <th class="cbi-section-table-cell"><%:OLSR node%></th> + <th class="cbi-section-table-cell"><%:Last hop%></th> + <th class="cbi-section-table-cell"><%:LQ%></th> + <th class="cbi-section-table-cell"><%:NLQ%></th> + <th class="cbi-section-table-cell"><%:ETX%></th> + </tr> + + <% for k, route in ipairs(routes) do + local cost = string.format("%.3f", tonumber(route.tcEdgeCost/1024) or 0) + local color = olsrtools.etx_color(tonumber(cost)) + local lq = string.format("%.3f", tonumber(route.linkQuality) or 0) + local nlq = string.format("%.3f", tonumber(route.neighborLinkQuality) or 0) + %> + + <tr class="cbi-section-table-row cbi-rowstyle-<%=i%> proto-<%=route.proto%>"> + + <% if route.proto == "6" then %> + + <td class="cbi-section-table-cell"><a href="http://[<%=route.destinationIP%>]/cgi-bin-status.html"><%=route.destinationIP%></a></td> + <td class="cbi-section-table-cell"><a href="http://[<%=route.lastHopIP%>]/cgi-bin-status.html"><%=route.lastHopIP%></a></td> + + <% else %> + + <td class="cbi-section-table-cell"><a href="http://<%=route.destinationIP%>/cgi-bin-status.html"><%=route.destinationIP%></a></td> + <td class="cbi-section-table-cell"><a href="http://<%=route.lastHopIP%>/cgi-bin-status.html"><%=route.lastHopIP%></a></td> + + <%end%> + + <td class="cbi-section-table-cell"><%=lq%></td> + <td class="cbi-section-table-cell"><%=nlq%></td> + <td class="cbi-section-table-cell" style="background-color:<%=color%>"><%=cost%></td> + </tr> + + <% i = ((i % 2) + 1) + end %> + </table> +<%+status-olsr/legend%> +</fieldset> + +<%+status-olsr/common_js%> +<%+footer%> |