diff --git a/luci-app-olsrd2/Makefile b/luci-app-olsrd2/Makefile new file mode 100644 index 0000000..6725067 --- /dev/null +++ b/luci-app-olsrd2/Makefile @@ -0,0 +1,57 @@ +# call BuildPackage - OpenWrt buildroot signature +include $(TOPDIR)/rules.mk + +PKG_NAME:=luci-app-olsrd2 +PKG_VERSION:=0.2.6 +PKG_RELEASE:=14 +PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION) + +include $(INCLUDE_DIR)/package.mk + +define Package/luci-app-olsrd2 + SECTION:=luci + CATEGORY:=LuCI + SUBMENU:=3. Applications + TITLE:=OLSR2 configuration and status module + MAINTAINER:=Patrick Grimm + EXTRA_DEPENDS:=oonf-olsrd2, luci-mod-admin-full + PKGARCH:=all +endef + +define Build/Prepare +endef + +define Build/Configure +endef + +define Build/Compile +endef + +define Package/$(PKG_NAME)/postinst +#!/bin/sh +if [ -z $${IPKG_INSTROOT} ] ; then + rm -f /tmp/luci-indexcache + rm -rf /tmp/luci-modulecache/ + killall -HUP rpcd 2>/dev/null +fi +endef + +define Package/$(PKG_NAME)/install + $(INSTALL_DIR) $(1)/www/luci-static/resources/view/olsrd2 + $(INSTALL_DATA) ./htdocs/cgi-bin-olsrd2-neigh.html $(1)/www + $(INSTALL_DATA) ./htdocs/luci-static/resources/view/olsrd2/* $(1)/www/luci-static/resources/view/olsrd2 + $(INSTALL_DIR) $(1)/etc/config + $(INSTALL_DATA) ./root/etc/config/* $(1)/etc/config + $(INSTALL_DIR) $(1)/etc/uci-defaults + $(INSTALL_DATA) ./root/etc/uci-defaults/* $(1)/etc/uci-defaults + $(INSTALL_DIR) $(1)/usr/libexec/rpcd + $(INSTALL_BIN) ./root/usr/libexec/rpcd/status.olsrd2 $(1)/usr/libexec/rpcd/status.olsrd2 + $(INSTALL_DIR) $(1)/usr/share/luci/menu.d + $(INSTALL_DATA) ./root/usr/share/luci/menu.d/* $(1)/usr/share/luci/menu.d + $(INSTALL_DIR) $(1)/usr/share/rpcd/acl.d + $(INSTALL_DATA) ./root/usr/share/rpcd/acl.d/* $(1)/usr/share/rpcd/acl.d + $(INSTALL_DIR) $(1)/lib/functions + $(INSTALL_DATA) ./root/lib/functions/* $(1)/lib/functions +endef + +$(eval $(call BuildPackage,luci-app-olsrd2)) diff --git a/luci-app-olsrd2/htdocs/cgi-bin-olsrd2-neigh.html b/luci-app-olsrd2/htdocs/cgi-bin-olsrd2-neigh.html new file mode 100644 index 0000000..849f55e --- /dev/null +++ b/luci-app-olsrd2/htdocs/cgi-bin-olsrd2-neigh.html @@ -0,0 +1,10 @@ + + + + + + + +LuCI - Lua Configuration Interface + + diff --git a/luci-app-olsrd2/htdocs/luci-static/resources/view/olsrd2/attachednetwork.js b/luci-app-olsrd2/htdocs/luci-static/resources/view/olsrd2/attachednetwork.js new file mode 100644 index 0000000..af4703b --- /dev/null +++ b/luci-app-olsrd2/htdocs/luci-static/resources/view/olsrd2/attachednetwork.js @@ -0,0 +1,51 @@ +'use strict'; +'require view'; +'require ui'; +'require rpc'; +'require poll'; + +var callgetData = rpc.declare({ + object: 'status.olsrd2', + method: 'getAttached_network' +}); + +function createTable(data) { + let tableData = []; + data.attached_network.forEach(row => { + let node = E('a',{ 'href': 'https://' + row.node + '/cgi-bin-olsrd2-neigh.html'},row.node); + tableData.push([ + node, + row.attached_net, + row.attached_net_src, + row.domain_metric_out + ]) + }); + return tableData; +} + +return view.extend({ + title: _('OLSRD2 networks'), + handleSaveApply: null, + handleSave: null, + handleReset: null, + + render: function(data) { + + var tr = E('table', { 'class': 'table' }); + tr.appendChild(E('div', { 'class': 'tr cbi-section-table-titles' }, [ + E('th', { 'class': 'th left' }, [ 'IP address' ]), + E('th', { 'class': 'th left' }, [ 'Network' ]), + E('th', { 'class': 'th left' }, [ 'Source' ]), + E('th', { 'class': 'th left' }, [ 'Metric' ]) + ])); + poll.add(() => { + Promise.all([ + callgetData() + ]).then((results) => { + cbi_update_table(tr, createTable(results[0])); + }) + }, 30); + return tr + } + +}); diff --git a/luci-app-olsrd2/htdocs/luci-static/resources/view/olsrd2/domain.js b/luci-app-olsrd2/htdocs/luci-static/resources/view/olsrd2/domain.js new file mode 100644 index 0000000..ea9597b --- /dev/null +++ b/luci-app-olsrd2/htdocs/luci-static/resources/view/olsrd2/domain.js @@ -0,0 +1,32 @@ +'use strict'; +'require view'; +'require form'; + +return view.extend({ + render: function() { + var m, s, o; + + m = new form.Map('olsrd2', 'OLSRD2 Daemon'); + + s = m.section(form.TypedSection, 'domain', _('domain configuration section')); + s.anonymous = true; + s.addremove = false; + o = s.option(form.Value, "table", _("table defines the routing table for the local routing entries."), "0-254"); + o.optional = true; + o.placeholder = 254; + o.datatype = "range(0,254)"; + o = s.option(form.Value, "protocol", _("protocol defines the protocol number for the local routing entries."), "0-254"); + o.optional = true; + o.placeholder = 100; + o.datatype = "range(0,254)"; + o = s.option(form.Value, "distance", _("distance defines the 'metric' (hopcount) of the local routing entries."), "0-254"); + o.optional = true; + o.placeholder = 2; + o.datatype = "range(0,254)"; + o = s.option(form.Flag, "srcip_routes", _("srcip_routes defines if the router sets the originator address as the source-ip entry into the local routing entries."), ""); + o.optional = true; + o.datatype = "bool"; + + return m.render(); + } +}); diff --git a/luci-app-olsrd2/htdocs/luci-static/resources/view/olsrd2/global.js b/luci-app-olsrd2/htdocs/luci-static/resources/view/olsrd2/global.js new file mode 100644 index 0000000..d3a9e27 --- /dev/null +++ b/luci-app-olsrd2/htdocs/luci-static/resources/view/olsrd2/global.js @@ -0,0 +1,32 @@ +'use strict'; +'require view'; +'require form'; + +return view.extend({ + render: function() { + var m, s, o; + + m = new form.Map('olsrd2', 'OLSRD2 Daemon'); + + s = m.section(form.TypedSection, 'global', _('It controls the basic behavior of the OONF core.')); + s.anonymous = true; + s.addremove = false; + + o = s.option(form.Flag, "failfast", _("failfast is another boolean setting which can activate an error during startup if a requested plugin does not load or an unknown configuration variable is set."), ""); + o.optional = true; + o.rmempty = true; + o.datatype = 'bool'; + o = s.option(form.Value, "pidfile", _("pidfile is used together with the fork option to store the pid of the background process in a file."), "Filename"); + o.optional = true; + o.rmempty = true; + o.placeholder = '/var/run/olsrd2.pid'; + o.datatype = 'string'; + o = s.option(form.Value, "lockfile", _("lockfile creates a file on disk and keeps a lock on it as long as the OONF application is running to prevent the application from running multiple times at once."), "Filename"); + o.rmempty = false; + o.optional = true; + o.placeholder = "/var/lock/olsrd2"; + o.datatype = "string"; + + return m.render(); + } +}); diff --git a/luci-app-olsrd2/htdocs/luci-static/resources/view/olsrd2/interface.js b/luci-app-olsrd2/htdocs/luci-static/resources/view/olsrd2/interface.js new file mode 100644 index 0000000..26e0a89 --- /dev/null +++ b/luci-app-olsrd2/htdocs/luci-static/resources/view/olsrd2/interface.js @@ -0,0 +1,103 @@ +'use strict'; +'require view'; +'require form'; +'require tools.widgets as widgets'; + +return view.extend({ + render: function() { + var m, s, o; + + m = new form.Map('olsrd2', 'OLSRD2 Daemon'); + m.tabbed = true; + s = m.section(form.GridSection, 'interface', _('interface configuration section')); + s.anonymous = true; + s.addremove = true; + s.addbtntitle = _('Add new interface...'); + s.tab('general', _('General Settings')); + s.tab('oonf', _('OONF RFC5444 Plugin')); + s.tab('nhdp', _('NHDP Plugin')); + s.tab('link', _('Link Config Plugin')); + s.modaltitle = function(section_id) { + return _('Interfaces') + ' ยป ' + section_id.toUpperCase(); + }; + + o = s.taboption("general", form.Flag, "ignore", _("Enabled")); + o.enabled = "0"; + o.disabled = "1"; + o.rmempty = false; + o = s.taboption("general", form.Value, "ifname", _("Network"), _("The interface OLSR2 should serve.")); + o.datatype = "string"; + o = s.taboption("oonf", form.DynamicList, "acl", _("acl defines the IP addresses that are allowed to use the RFC5444 socket."), _("ip6prefix, ip4prefix, default_accept, default_reject")); + o.datatype = "string"; + o.optional = true; + o.modalonly = true; + o = s.taboption("oonf", form.DynamicList, "bindto", _("bindto defines the IP addresses which the RFC5444 socket will be bound to."), _("ip6prefix, ip4prefix, default_accept, default_reject")); + o.datatype = "string"; + o.optional = true; + o.modalonly = true; + o = s.taboption("oonf", form.Value, "multicast_v4", _("multicast_v4 defines the IPv4 multicast address used for RFC5444 packets."), _("ip4addr")); + o.datatype = "ip4addr"; + o.placeholder = "224.0.0.109"; + o.optional = true; + o.modalonly = true; + o = s.taboption("oonf", form.Value, "multicast_v6", _("multicast_v6 defines the IPv6 multicast address used for RFC5444 packets."), _("ip6addr")); + o.datatype = "ip6addr"; + o.placeholder = "ff02::6d"; + o.optional = true; + o.modalonly = true; + o = s.taboption("oonf", form.Value, "dscp", _("dscp defines the DSCP value set for each outgoing RFC5444 packet. The value must be between 0 and 252 without fractional digits. The value should be a multiple of 4."), _("0-255")); + o.optional = true; + o.placeholder = 192; + o.datatype = "range(0,255)"; + o.modalonly = true; + o = s.taboption("oonf", form.Value, "rawip", _("rawip defines if the interface should put RFC5444 packets directly into IP headers (skipping the UDP header)."), _("bool")); + o.optional = true; + o.rmempty = true; + o.datatype = "bool"; + o.modalonly = true; + o = s.taboption("nhdp", form.DynamicList, "ifaddr_filter", _("ifaddr_filter defines the IP addresses that are allowed to NHDP interface addresses."), _("ip6prefix, ip4prefix, default_accept, default_reject")); + o.datatype = "string"; + o.optional = true; + o.modalonly = true; + o = s.taboption("nhdp", form.Value, "hello_validity", _("hello_validity defines the time the local HELLO messages will be valid for the neighbors."), _(">0.1 s")); + o.optional = true; + o.placeholder = 20.0; + o.datatype = "and(min(0.1), ufloat)"; + o.modalonly = true; + o = s.taboption("nhdp", form.Value, "hello_interval", _("hello_interval defines the time between two HELLO messages on the interface."), _(">0.1 s")); + o.optional = true; + o.placeholder = 2.0; + o.datatype = "and(min(0.1), ufloat)"; + o.modalonly = true; + o = s.taboption("link", form.Value, "rx_bitrate", _("rx_bitrate")); + o.optional = true; + o.rmempty = false; + o.placeholder = "1G"; + o.datatype = "string"; + o = s.taboption("link", form.Value, "tx_bitrate", _("tx_bitrate")); + o.optional = true; + o.rmempty = false; + o.placeholder = "1G"; + o.datatype = "string"; + o = s.taboption("link", form.Value, "rx_max_bitrate", _("rx_max_bitrate")); + o.optional = true; + o.rmempty = false; + o.placeholder = "1G"; + o.datatype = "string"; + o.modalonly = true; + o = s.taboption("link", form.Value, "tx_max_bitrate", _("tx_max_bitrate")); + o.optional = true; + o.rmempty = false; + o.placeholder = "1G"; + o.datatype = "string"; + o.modalonly = true; + o = s.taboption("link", form.Value, "rx_signal", _("rx_signal")); + o.optional = true; + o.rmempty = false; + o.placeholder = "1G"; + o.datatype = "string"; + o.modalonly = true; + + return m.render(); + } +}); diff --git a/luci-app-olsrd2/htdocs/luci-static/resources/view/olsrd2/lan_import.js b/luci-app-olsrd2/htdocs/luci-static/resources/view/olsrd2/lan_import.js new file mode 100644 index 0000000..3839f7b --- /dev/null +++ b/luci-app-olsrd2/htdocs/luci-static/resources/view/olsrd2/lan_import.js @@ -0,0 +1,25 @@ +'use strict'; +'require view'; +'require form'; + +return view.extend({ + render: function() { + var m, s, o; + + m = new form.Map('olsrd2', 'OLSRD2 Daemon'); + + s = m.section(form.TypedSection, 'lan_import', _('Automatic import of routing tables as locally attached networks.')); + s.anonymous = true; + s.addremove = true; + o = s.option(form.Value, "name", _("Name"), "Text"); + o.datatype = "string"; + o = s.option(form.Value, "interface", _("Interface"), "Name Interface"); + o.datatype = "string"; + o = s.option(form.Value, "table", _("IP Table"), "1-255"); + o.datatype = "range(1,255)"; + o = s.option(form.Value, "protocol", _("IP protocol"), "1-255"); + o.datatype = "range(1,255)"; + + return m.render(); + } +}); diff --git a/luci-app-olsrd2/htdocs/luci-static/resources/view/olsrd2/log.js b/luci-app-olsrd2/htdocs/luci-static/resources/view/olsrd2/log.js new file mode 100644 index 0000000..f8fe2b5 --- /dev/null +++ b/luci-app-olsrd2/htdocs/luci-static/resources/view/olsrd2/log.js @@ -0,0 +1,37 @@ +'use strict'; +'require view'; +'require form'; + +return view.extend({ + render: function() { + var m, s, o; + + m = new form.Map('olsrd2', 'OLSRD2 Daemon'); + + s = m.section(form.TypedSection, 'log', _('OONF Logging')); + s.anonymous = true; + s.addremove = false; + + o = s.option(form.Flag, "syslog", _("syslog are boolean options that activate or deactivate the syslog Logging Target."), ""); + o.optional = true; + o.datatype = "bool"; + o = s.option(form.Flag, "stderr", _("stderr are boolean options that activate or deactivate the stderr Logging Target."), ""); + o.optional = true; + o.datatype = "bool"; + o = s.option(form.Value, "file", _("file asks for a filename for logging output"),"Filename"); + o.rmempty = false; + o.optional = true; + o.placeholder = "/tmp/olsrd2.log"; + o.datatype = "string"; + o = s.option(form.Value, "debug", _("debug ask for a list of Logging Sources that will be logged by the OONF Core Logging Targets.")); + o.rmempty = false; + o.optional = true; + o.datatype = "string"; + o = s.option(form.Value, "info", _("info ask for a list of Logging Sources that will be logged by the OONF Core Logging Targets.")); + o.rmempty = false; + o.optional = true; + o.datatype = "string"; + + return m.render(); + } +}); diff --git a/luci-app-olsrd2/htdocs/luci-static/resources/view/olsrd2/luci.js b/luci-app-olsrd2/htdocs/luci-static/resources/view/olsrd2/luci.js new file mode 100644 index 0000000..7348040 --- /dev/null +++ b/luci-app-olsrd2/htdocs/luci-static/resources/view/olsrd2/luci.js @@ -0,0 +1,22 @@ +'use strict'; +'require view'; +'require form'; + +return view.extend({ + render: function() { + var m, s, o; + + m = new form.Map('luci_olsrd2', 'Luci options'); + + s = m.section(form.TypedSection, 'olsrd2', _('LUCI')); + s.anonymous = true; + s.addremove = false; + + o = s.option(form.Flag, "resolve", _("do Hostname lookup"), ""); + o.datatype = "bool"; + o = s.option(form.Value, "domain", _("optional Public domain forwarding with dnsmasq-full (auth-zone=example.com) on the internetgateway "), "default is olsr"); + o.datatype = "string"; + + return m.render(); + } +}); diff --git a/luci-app-olsrd2/htdocs/luci-static/resources/view/olsrd2/mesh.js b/luci-app-olsrd2/htdocs/luci-static/resources/view/olsrd2/mesh.js new file mode 100644 index 0000000..763068b --- /dev/null +++ b/luci-app-olsrd2/htdocs/luci-static/resources/view/olsrd2/mesh.js @@ -0,0 +1,29 @@ +'use strict'; +'require view'; +'require form'; + +return view.extend({ + render: function() { + var m, s, o; + + m = new form.Map('olsrd2', 'OLSRD2 Daemon'); + + s = m.section(form.TypedSection, 'mesh', _('mesh configuration section')); + s.anonymous = true; + s.addremove = false; + o = s.option(form.Value, "port", _("port defines the UDP port number of the RFC5444 socket."), "1-65535"); + o.optional = true; + o.placeholder = 269; + o.datatype = "range(1,65535)"; + o = s.option(form.Value, "ip_proto", _("ip_proto defines the IP protocol number that can be used for RFC5444 communication."), "1-255"); + o.optional = true; + o.placeholder = 138; + o.datatype = "range(1,255)"; + o = s.option(form.Value, "aggregation_interval", _("aggregation_interval defines the time the local RFC5444 implementation will keep messages to aggregate them before creating a new RFC5444 packet to forward them."), ">0.1 s"); + o.optional = true; + o.placeholder = 1.0; + o.datatype = "and(min(0.1), ufloat)"; + + return m.render(); + } +}); diff --git a/luci-app-olsrd2/htdocs/luci-static/resources/view/olsrd2/neighbors.js b/luci-app-olsrd2/htdocs/luci-static/resources/view/olsrd2/neighbors.js new file mode 100644 index 0000000..e38af4a --- /dev/null +++ b/luci-app-olsrd2/htdocs/luci-static/resources/view/olsrd2/neighbors.js @@ -0,0 +1,58 @@ +'use strict'; +'require view'; +'require ui'; +'require rpc'; +'require poll'; + +var callgetData = rpc.declare({ + object: 'status.olsrd2', + method: 'getNeighbors' +}); + +function createTable(data) { + let tableData = []; + data.neighbors.forEach(row => { + let hostname = E('a',{ 'href': 'https://' + row.hostname + '/cgi-bin-olsrd2-neigh.html'},row.hostname); + let orginator = E('a',{ 'href': 'https://[' + row.originator + ']/cgi-bin-olsrd2-neigh.html'},row.originator); + tableData.push([ + hostname, + orginator, + row.lladdr, + row.interface, + row.metric_in, + row.metric_in_raw + ]) + }); + return tableData; +}; + +return view.extend({ + title: _('OLSRD2 mesh neighbors'), + handleSaveApply: null, + handleSave: null, + handleReset: null, + + + render: function(data) { + + var tr = E('table', { 'class': 'table' }); + tr.appendChild(E('tr', { 'class': 'tr cbi-section-table-titles' }, [ + E('th', { 'class': 'th left' }, [ 'Hostname' ]), + E('th', { 'class': 'th left' }, [ 'Orginator' ]), + E('th', { 'class': 'th left' }, [ 'MAC' ]), + E('th', { 'class': 'th left' }, [ 'Interface' ]), + E('th', { 'class': 'th left' }, [ 'Metric' ]), + E('th', { 'class': 'th left' }, [ 'raw' ]) + ])); + poll.add(() => { + Promise.all([ + callgetData() + ]).then((results) => { + cbi_update_table(tr, createTable(results[0])); + }) + }, 30); + return tr + + } + +}); diff --git a/luci-app-olsrd2/htdocs/luci-static/resources/view/olsrd2/node.js b/luci-app-olsrd2/htdocs/luci-static/resources/view/olsrd2/node.js new file mode 100644 index 0000000..982d5a5 --- /dev/null +++ b/luci-app-olsrd2/htdocs/luci-static/resources/view/olsrd2/node.js @@ -0,0 +1,46 @@ +'use strict'; +'require view'; +'require ui'; +'require rpc'; +'require poll'; + +var callgetData = rpc.declare({ + object: 'status.olsrd2', + method: 'getNode' +}); + +function createTable(data) { + let tableData = []; + data.node.forEach(row => { + let node = E('a',{ 'href': 'https://' + row.node + '/cgi-bin-olsrd2-neigh.html'},row.node); + tableData.push([ + node + ]) + }); + return tableData; +}; + +return view.extend({ + title: _('OLSRD2 mesh nodes'), + handleSaveApply: null, + handleSave: null, + handleReset: null, + + render: function(data) { + + var tr = E('table', { 'class': 'table' }); + tr.appendChild(E('tr', { 'class': 'tr cbi-section-table-titles' }, [ + E('th', { 'class': 'th left' }, [ 'IP Address' ]) + ])); + poll.add(() => { + Promise.all([ + callgetData() + ]).then((results) => { + cbi_update_table(tr, createTable(results[0])); + }) + }, 30); + + return tr; + } + +}); diff --git a/luci-app-olsrd2/htdocs/luci-static/resources/view/olsrd2/olsrv2.js b/luci-app-olsrd2/htdocs/luci-static/resources/view/olsrd2/olsrv2.js new file mode 100644 index 0000000..ae12e33 --- /dev/null +++ b/luci-app-olsrd2/htdocs/luci-static/resources/view/olsrd2/olsrv2.js @@ -0,0 +1,60 @@ +'use strict'; +'require view'; +'require form'; + +return view.extend({ + render: function() { + var m, s, o; + + m = new form.Map('olsrd2', 'OLSRD2 Daemon'); + + s = m.section(form.TypedSection, 'olsrv2', _('the OLSRv2 implementation including the OLSRv2 API for other plugins.')); + s.anonymous = true; + s.addremove = false; + + o = s.option(form.Value, "tc_interval", _("defines the time between two TC messages."), "s"); + o.optional = true; + o.placeholder = 5.0; + o.datatype = "ufloat"; + o = s.option(form.Value, "tc_validity", _("tc_validity defines the validity time of the TC messages."), "s"); + o.optional = true; + o.placeholder = 300.0; + o.datatype = "ufloat"; + o = s.option(form.Value, "forward_hold_time", _("forward_hold_time defines the time until the router will forget an entry in its forwarding duplicate database."), "s"); + o.optional = true; + o.placeholder = 300.0; + o.datatype = "ufloat"; + o = s.option(form.Value, "processing_hold_time", _("processing_hold_time defines the time until the router will forget an entry in its processing duplicate database."), "s"); + o.optional = true; + o.placeholder = 300.0; + o.datatype = "ufloat"; + o = s.option(form.DynamicList, "routable", _("routable defines the ACL which declares an IP address routable. Other IP addresses will not be included in TC messages."), "ip6prefix, ip4prefix, default_accept, default_reject"); + o.datatype = "string"; +//TODO +//svc.datatype = "or(negm(ip6addr), negm(ip4addr), 'default_accept', 'default_reject')" +//modules/luci-base/htdocs/luci-static/resources/cbi.js:545 +// negm: function() { +// return this.apply('or', this.value.replace(/^[ \t]*-[ \t]*/, ''), arguments); +// }, + //modules/luci-base/luasrc/cbi/datatypes.lua:51 +//function negm(v, ...) +// return _M['or'](v:gsub("^%s*-%s*", ""), ...) +//end + o.optional = true; + o = s.option(form.DynamicList, "originator", _("originator defines the ACL which declares a valid originator IP address for the router."), "ip6prefix, ip4prefix, default_accept, default_reject"); + o.datatype = "string"; +//TODO +//svc.datatype = "or(negm(ip6addr), negm(ip4addr), 'default_accept', 'default_reject')" +//modules/luci-base/htdocs/luci-static/resources/cbi.js:545 +// negm: function() { +// return this.apply('or', this.value.replace(/^[ \t]*-[ \t]*/, ''), arguments); +// }, + //modules/luci-base/luasrc/cbi/datatypes.lua:51 +//function negm(v, ...) +// return _M['or'](v:gsub("^%s*-%s*", ""), ...) +//end + o.optional = true; + + return m.render(); + } +}); diff --git a/luci-app-olsrd2/htdocs/luci-static/resources/view/olsrd2/olsrv2_lan.js b/luci-app-olsrd2/htdocs/luci-static/resources/view/olsrd2/olsrv2_lan.js new file mode 100644 index 0000000..f846c77 --- /dev/null +++ b/luci-app-olsrd2/htdocs/luci-static/resources/view/olsrd2/olsrv2_lan.js @@ -0,0 +1,32 @@ +'use strict'; +'require view'; +'require form'; + +return view.extend({ + render: function() { + var m, s, o; + + m = new form.Map('olsrd2', 'OLSRD2 Daemon'); + + s = m.section(form.TypedSection, 'olsrv2_lan', _('Prefix configuration section')); + s.anonymous = true; + s.addremove = true; + o = s.option(form.Value, "name", _("Name"), "Text"); + o.datatype = "string"; + o = s.option(form.Value, "prefix", _("locally attached network prefix"), ""); + o.datatype = "string"; + o = s.option(form.Value, "domain", _("domain for this LAN entry, -1 for all domains"), "-1-254"); + o.optional = true; + o.placeholder = -1; + o.datatype = "range(-1,254)"; + o = s.option(form.Value, "metric", _("metric value for this LAN entry"), "0-254"); + o.optional = true; + o.placeholder = 2; + o.datatype = "range(0,254)"; + o = s.option(form.Flag, "source_prefix", _("source prefix for lan (source specific routing)"), ""); + o.optional = true; + o.datatype = "bool"; + + return m.render(); + } +}); diff --git a/luci-app-olsrd2/htdocs/luci-static/resources/view/olsrd2/overview.js b/luci-app-olsrd2/htdocs/luci-static/resources/view/olsrd2/overview.js new file mode 100644 index 0000000..29500e1 --- /dev/null +++ b/luci-app-olsrd2/htdocs/luci-static/resources/view/olsrd2/overview.js @@ -0,0 +1,74 @@ +'use strict'; +'require view'; +'require ui'; +'require rpc'; +'require poll'; + +var callgetVersion = rpc.declare({ + object: 'status.olsrd2', + method: 'getVersion' +}); +var callgetLan = rpc.declare({ + object: 'status.olsrd2', + method: 'getLan' +}); + +function createTable(data) { + let tableData = []; + if ( data && data[0] && data[0].version && data[0].version[0] ) { + if ( data[0].version[0].version_text != undefined ) { + tableData.push([_('Version'),data[0].version[0].version_text]); + } + if ( data[0].version[0].version_commit != undefined) { + tableData.push([_('GIT commit'),data[0].version[0].version_commit]); + } + } + if ( data && data[1] && data[1].lan && data[1].lan[0] ) { + if ( data[1].lan[0].lan != undefined ) { + tableData.push([_('LAN IP'),data[1].lan[0].lan]); + } + if ( data[1].lan[0].domain != undefined) { + tableData.push([_('Domain'),data[1].lan[0].domain]); + } + if ( data[1].lan[0].domain_metric != undefined) { + tableData.push([_('Domain metric'),data[1].lan[0].domain_metric]); + } + if ( data[1].lan[0].domain_metric_out != undefined) { + tableData.push([_('Domain metric outgoing'),data[1].lan[0].domain_metric_out]); + } + if ( data[1].lan[0].domain_metric_out_raw != undefined) { + tableData.push([_('domain_metric_out_raw'),data[1].lan[0].domain_metric_out_raw]); + } + if ( data[1].lan[0].domain_distance != undefined) { + tableData.push([_('Domain distance'),data[1].lan[0].domain_distance]); + } + } + return tableData; +} + +return view.extend({ + title: _('Version'), + handleSaveApply: null, + handleSave: null, + handleReset: null, + + render: function() { + + var tr = E('table',{ 'class': 'table'}); + tr.appendChild(E('tr', { 'class': 'tr cbi-section-table-titles' }, [ + E('th', { 'class': 'th left' }), + E('th', { 'class': 'th left' }) + ])); + poll.add(() => { + Promise.all([ + callgetVersion(), + callgetLan() + ]).then((results) => { + cbi_update_table(tr, createTable(results)); + }) + }, 30); + + return tr; + } + +}); diff --git a/luci-app-olsrd2/root/etc/config/luci_olsrd2 b/luci-app-olsrd2/root/etc/config/luci_olsrd2 new file mode 100644 index 0000000..9935410 --- /dev/null +++ b/luci-app-olsrd2/root/etc/config/luci_olsrd2 @@ -0,0 +1,3 @@ +config 'olsrd2' 'general' + option 'resolve' '1' + option 'domain' 'olsr' diff --git a/luci-app-olsrd2/root/etc/uci-defaults/41_luci-olsrd2 b/luci-app-olsrd2/root/etc/uci-defaults/41_luci-olsrd2 new file mode 100755 index 0000000..094970a --- /dev/null +++ b/luci-app-olsrd2/root/etc/uci-defaults/41_luci-olsrd2 @@ -0,0 +1,13 @@ +#!/bin/sh + +uci -q batch <<-EOF >/dev/null + delete ucitrack.@olsrd2[-1] + add ucitrack olsrd2 + set ucitrack.@olsrd2[-1].init=olsrd2 + commit ucitrack +EOF + +rm -f /tmp/luci-indexcache +rm -f /tmp/luci-modulecache/* + +exit 0 diff --git a/luci-app-olsrd2/root/lib/functions/olsrd2.sh b/luci-app-olsrd2/root/lib/functions/olsrd2.sh new file mode 100644 index 0000000..b998073 --- /dev/null +++ b/luci-app-olsrd2/root/lib/functions/olsrd2.sh @@ -0,0 +1,61 @@ +# 1: destination variable +# 2: interface +# 3: path +# 4: separator +# 5: limit +__network_ifstatus() { + local __tmp + + [ -z "$__NETWORK_CACHE" ] && { + __tmp="$(ubus call network.interface dump 2>&1)" + case "$?" in + 4) : ;; + 0) export __NETWORK_CACHE="$__tmp" ;; + *) echo "$__tmp" >&2 ;; + esac + } + + __tmp="$(jsonfilter ${4:+-F "$4"} ${5:+-l "$5"} -s "${__NETWORK_CACHE:-{}}" -e "$1=@.interface${2:+[@.interface='$2']}$3")" + + [ -z "$__tmp" ] && \ + unset "$1" && \ + return 1 + + eval "$__tmp" +} + +# 1: addr +# 2: export var neighbour dev lladdr +network_get_neighbour_by_ip() +{ + local __tmp + neighbour='' + dev='' + lladdr='' + local ipaddr="$1" + hostname=$(nslookup "$ipaddr" "$ipaddr" | grep name | cut -d " " -f 3 | cut -d '.' -f -1) + [ -z "$__NEIGH_CACHE" ] && { + __tmp="$(ip -6 neigh)" + export __NEIGH_CACHE="$__tmp" + } + [ -z "$__ROUTE_CACHE" ] && { + __tmp="$(ip -6 route)" + export __ROUTE_CACHE="$__tmp" + } + local gwaddr=$(echo "$__ROUTE_CACHE" | grep "^$ipaddr" | cut -d ' ' -f 3) + [ -z "$gwaddr" ] && return + local neigh=$(echo "$__NEIGH_CACHE" | grep "$gwaddr") + [ -z "$neigh" ] && return + set -- $neigh + eval "neighbour=$1;dev=$3;lladdr=$5" +} + +# 1: destination variable +# 2: addr +network_get_name_by_device() +{ + __network_ifstatus "$1" "" \ + "[@.device='$2' && !@.table].interface" "" 1 && \ + return 0 +} + diff --git a/luci-app-olsrd2/root/usr/libexec/rpcd/status.olsrd2 b/luci-app-olsrd2/root/usr/libexec/rpcd/status.olsrd2 new file mode 100644 index 0000000..fa4d668 --- /dev/null +++ b/luci-app-olsrd2/root/usr/libexec/rpcd/status.olsrd2 @@ -0,0 +1,91 @@ +#!/bin/sh +# Copyright (C) 2016 OpenWrt.org + +. /lib/functions.sh +. /usr/share/libubox/jshn.sh +. /lib/functions/olsrd2.sh + +case "$1" in + list) + json_init + + json_add_object "getVersion" + json_close_object + json_add_object "getLan" + json_close_object + json_add_object "getNode" + json_close_object + json_add_object "getNeighbors" + json_close_object + json_add_object "getAttached_network" + json_close_object + json_add_object "getRoute" + json_close_object + json_add_object "getGraph" + json_close_object + json_add_object "getDomain" + json_close_object + + json_dump + ;; + call) + case "$2" in + getVersion) + echo '/systeminfo json version /quit' | nc ::1 2009 2>/dev/null + ;; + getLan) + echo '/olsrv2info json lan /quit' | nc ::1 2009 2>/dev/null + ;; + getNode) + echo '/olsrv2info json node /quit' | nc ::1 2009 2>/dev/null + ;; + getNeighbors) + domain="$(uci_get luci_olsr2 general domain)" + [ -z "$domain" ] || domain=".$domain" + json_init + json_add_array "neighbors" + OLDIFS="$IFS" + IFS=$'\n' + neighbor_status="$(echo '/nhdpinfo neighbor /quit' | nc ::1 2009 | cut -f 1,9,10,11,12)" + for neighbor in $neighbor_status; do + json_add_object 0 + IFS="$OLDIFS" + i=1 + for value in $neighbor ; do + case $i in + 1) json_add_string "originator" "${value}" + network_get_neighbour_by_ip "${value}" + json_add_string "lladdr" "${lladdr}" + json_add_string "hostname" "${hostname}${domain}" + network_get_name_by_device interface $dev + json_add_string "interface" "${interface}" + ;; + 2) json_add_string "metric_in" "${value}";; + 3) json_add_string "metric_in_raw" "${value}";; + 4) json_add_string "metric_out" "${value}";; + 5) json_add_string "metric_out_raw" "${value}";; + esac + i=$(( i + 1 )) + done + IFS=$'\n' + json_close_object + done + IFS="$OLDIFS" + json_close_array + json_dump + ;; + getAttached_network) + echo '/olsrv2info json attached_network /quit' | nc ::1 2009 2>/dev/null + ;; + getRoute) + echo '/netjsoninfo filter route ipv6_0' | nc ::1 2009 2>/dev/null + ;; + getGraph) + echo '/netjsoninfo filter graph ipv6_0' | nc ::1 2009 2>/dev/null + ;; + getDomain) + echo '/netjsoninfo domain' | nc ::1 2009 2>/dev/null + ;; + esac + ;; +esac diff --git a/luci-app-olsrd2/root/usr/share/luci/menu.d/luci-app-olsrd2.json b/luci-app-olsrd2/root/usr/share/luci/menu.d/luci-app-olsrd2.json new file mode 100644 index 0000000..ab45e72 --- /dev/null +++ b/luci-app-olsrd2/root/usr/share/luci/menu.d/luci-app-olsrd2.json @@ -0,0 +1,171 @@ +{ + "admin/services/olsrd2": { + "title": "OLSRD2", + "action": { + "type": "firstchild" + }, + "depends": { + "acl": [ "luci-app-olsrd2" ] + } + }, + "admin/services/olsrd2/global": { + "title": "Global", + "order": 1, + "action": { + "type": "view", + "path": "olsrd2/global" + } + }, + "admin/services/olsrd2/log": { + "title": "Logging", + "order": 2, + "action": { + "type": "view", + "path": "olsrd2/log" + } + }, + "admin/services/olsrd2/olsrv2": { + "title": "Daemon", + "order": 3, + "action": { + "type": "view", + "path": "olsrd2/olsrv2" + } + }, + "admin/services/olsrd2/olsrv2_lan": { + "title": "Prefix", + "order": 4, + "action": { + "type": "view", + "path": "olsrd2/olsrv2_lan" + } + }, + "admin/services/olsrd2/domain": { + "title": "Domain", + "order": 5, + "action": { + "type": "view", + "path": "olsrd2/domain" + } + }, + "admin/services/olsrd2/mesh": { + "title": "Mesh", + "order": 6, + "action": { + "type": "view", + "path": "olsrd2/mesh" + } + }, + "admin/services/olsrd2/lan_import": { + "title": "LAN Import", + "order": 7, + "action": { + "type": "view", + "path": "olsrd2/lan_import" + } + }, + "admin/services/olsrd2/interface": { + "title": "Interface", + "order": 8, + "action": { + "type": "view", + "path": "olsrd2/interface" + } + }, + "admin/services/olsrd2/luci": { + "title": "LUCI", + "order": 8, + "action": { + "type": "view", + "path": "olsrd2/luci" + } + }, + "admin/status/olsrd2": { + "title": "OLSRD2", + "action": { + "type": "firstchild" + } + }, + "admin/status/olsrd2/overview": { + "title": "Overview", + "order": 1, + "action": { + "type": "view", + "path": "olsrd2/overview" + } + }, + "admin/status/olsrd2/node": { + "title": "Nodes", + "order": 2, + "action": { + "type": "view", + "path": "olsrd2/node" + } + }, + "admin/status/olsrd2/attachednetwork": { + "title": "Attachednetwork", + "order": 3, + "action": { + "type": "view", + "path": "olsrd2/attachednetwork" + } + }, + "admin/status/olsrd2/neighbors": { + "title": "Neighbors", + "order": 4, + "action": { + "type": "view", + "path": "olsrd2/neighbors" + } + }, + "public/status": { + "title": "Status", + "order": 10, + "action": { + "type": "firstchild", + "recurse": true + }, + "auth": {} + }, + "public/status/olsrd2": { + "title": "OLSRD2", + "order": 20, + "action": { + "type": "firstchild", + "recurse": true + }, + "auth": {} + }, + "public/status/olsrd2/overview": { + "title": "Overview", + "order": 4, + "action": { + "type": "view", + "path": "olsrd2/overview" + } + }, + "public/status/olsrd2/node": { + "title": "Nodes", + "order": 2, + "action": { + "type": "view", + "path": "olsrd2/node" + } + }, + "public/status/olsrd2/attachednetwork": { + "title": "Attachednetwork", + "order": 3, + "action": { + "type": "view", + "path": "olsrd2/attachednetwork" + } + }, + "public/status/olsrd2/neighbors": { + "title": "Neighbors", + "order": 1, + "action": { + "type": "view", + "path": "olsrd2/neighbors" + } + } +} diff --git a/luci-app-olsrd2/root/usr/share/rpcd/acl.d/luci-app-olsrd2.json b/luci-app-olsrd2/root/usr/share/rpcd/acl.d/luci-app-olsrd2.json new file mode 100644 index 0000000..61e8691 --- /dev/null +++ b/luci-app-olsrd2/root/usr/share/rpcd/acl.d/luci-app-olsrd2.json @@ -0,0 +1,27 @@ +{ + "unauthenticated": { + "description": "Allow system feature probing", + "read": { + "file": { + "/www/luci-static/resources/view/olsrd2": [ "list" ] + }, + "ubus": { + "status.olsrd2": [ "getVersion", "getLan", "getNode", "getNeighbors", "getAttached_network" ], + "file": [ "list" ] + + } + } + }, + "luci-app-olsrd2": { + "description": "Grant UCI access for luci-app-olsrd2", + "read": { + "uci": [ "olsrd2" ], + "ubus": { + "status.olsrd2": [ "getVersion", "getLan", "getNode", "getNeighbors", "getAttached_network" ] + } + }, + "write": { + "uci": [ "olsrd2" ] + } + } +}