diff --git a/luci-app-openmptcprouter/Makefile b/luci-app-openmptcprouter/Makefile index 9ff51ec70..4f768cfbb 100644 --- a/luci-app-openmptcprouter/Makefile +++ b/luci-app-openmptcprouter/Makefile @@ -6,7 +6,7 @@ include $(TOPDIR)/rules.mk LUCI_TITLE:=LuCI Support for OpenMPTCProuter - +LUCI_DEPENDS:=+luci-lib-json PKG_LICENSE:=Apache-2.0 include ../luci/luci.mk diff --git a/luci-app-openmptcprouter/htdocs/luci-static/resources/computer.png b/luci-app-openmptcprouter/htdocs/luci-static/resources/computer.png new file mode 100644 index 000000000..4598c7cb6 Binary files /dev/null and b/luci-app-openmptcprouter/htdocs/luci-static/resources/computer.png differ diff --git a/luci-app-openmptcprouter/htdocs/luci-static/resources/modem.svg b/luci-app-openmptcprouter/htdocs/luci-static/resources/modem.svg new file mode 100644 index 000000000..338d44192 --- /dev/null +++ b/luci-app-openmptcprouter/htdocs/luci-static/resources/modem.svg @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/luci-app-openmptcprouter/htdocs/luci-static/resources/openmptcprouter/css/wanstatus.css b/luci-app-openmptcprouter/htdocs/luci-static/resources/openmptcprouter/css/wanstatus.css new file mode 100644 index 000000000..fbddd23be --- /dev/null +++ b/luci-app-openmptcprouter/htdocs/luci-static/resources/openmptcprouter/css/wanstatus.css @@ -0,0 +1,304 @@ +.container { + /* container for entire page. fixes bootstrap theme's ridiculously small page width */ + max-width: 1044px; +} +#interface_field { + padding: 12px 20px 20px 20px; +} +#mwan_status_text { + display: table; + font-size: 14px; + margin: auto; + max-width: 1044px; + min-width: 246px; + width: 100%; +} +.wanon { + background-color: #1cc82c; +} +.wanoff { + background-color: #e55712; +} +.wanon, +.wanoff { + border-radius: 60px; + box-shadow: 0px 2px 5px -3px; + float: left; + margin: 8px 3px 0px 3px; + min-height: 30px; + min-width: 235px; + padding: 5px 10px 8px 10px; + text-align: center; +} +/* Mwan3 ligthed CSS */ +.container { + /* container for entire page. fixes bootstrap theme's ridiculously small page width */ + max-width: 1044px; +} +#interface_field { + padding: 0px; +} +#interface_field td { + padding: 0px; +} +#interface_status_text { + display: table; + font-size: 14px; + margin: auto; + max-width: 1044px; + min-width: 246px; + width: 100%; +} +ul { + margin: 0px; +} +/*Now the CSS*/ +.tree ul { + position: relative; + float: left; + transition: all 0.5s; + -webkit-transition: all 0.5s; + -moz-transition: all 0.5s; +} +.tree li { + float: left; + text-align: left; + list-style-type: none; + position: relative; + padding: 5px 0px 5px 85px; + transition: all 0.5s; + -webkit-transition: all 0.5s; + -moz-transition: all 0.5s; +} +.tree ul ul { + padding-left: 85px; + position: relative; +} +.tree > ul > li:first-child { + position: relative; + padding-left: 0px; +} +.tree > ul > li#first-child > a { + position: relative; + top: 50%; +} +/*We will use ::before and ::after to draw the connectors + Before: Bottom part of the element + After: Top part of the element +*/ +.tree ul ul li::before, +.tree ul ul li::after { + content: ''; + position: absolute; + top: 50%; + left: 0; + border-left: 2px solid black; + width: 85px; + height: 50%; + float: left; + z-index: -10; + /* + position: absolute; + top: 0; + right: 50%; + border-top: 2px solid black; + width: 50%; + height: 20px; + background-color: red; +*/ +} +.tree ul ul li::after { + top: auto; + bottom: 50%; + border-left: 2px solid black; + border-bottom: 2px solid black; +} +.tree li:first-child { + position: relative; + top: 50%; +} +/*We need to remove first top and the last bottom border */ +.tree li:only-child::after { + display: none; +} +/*Remove space from the top of single children*/ +.tree li:only-child { + padding-top: 0; +} +/*Remove left connector from first child and +right connector from last child*/ +.tree li:first-child::after, +.tree li:last-child::before { + border-left: 0px; +} +/*Adding back the vertical connector to the last nodes*/ +/* +.tree li:last-child::before{ + //border-top: 2px solid black; + border-radius: 0 5px 0 0; + -webkit-border-radius: 0 5px 0 0; + -moz-border-radius: 0 5px 0 0; +} +.tree li:first-child::after{ + border-radius: 5px 0 0 0; + -webkit-border-radius: 5px 0 0 0; + -moz-border-radius: 5px 0 0 0; +} +*/ +/*Time to add right connectors from parents*/ +.tree ul ul::before { + content: ''; + position: absolute; + top: 50%; + left: 0; + border-top: 2px solid black; + width: 85px; + height: 100%; +} +.tree li a { + display: inline-block; + background-color: #f3f3f3; + text-decoration: none; + /* + border: 1px solid @color-bg-gray; + padding: 5px 10px; + + font-family: arial, verdana, tahoma; + font-size: 11px; + + border-radius: 5px; + -webkit-border-radius: 5px; + -moz-border-radius: 5px; + + transition: all 0.5s; + -webkit-transition: all 0.5s; + -moz-transition: all 0.5s; + */ +} +/*Exception*/ +.tree li.remote-from-lease { + padding-bottom: 0px; +} +.tree li.remote-from-lease::before, +.tree li#networkRootNode::before { + display: none; +} +.tree li#networkRootNode::after { + border: none; +} +.tree li.remote-from-lease::after { + content: ''; + position: absolute; + left: 50%; + top: 83px; + border-left: 2px solid black; + border-bottom: none; + width: 2px; + height: 30px; + z-index: -10; +} +.tree li#networkRootNode { + padding: 25px 0 0 0; +} +.tree li.subnode-only-child::before { + content: ''; + position: absolute; + top: 50%; + left: 0; + border-top: 2px solid black; + width: 85px; + height: 0; +} +.tree ul li#networkRootNode:not(:first-child) td::before { + content: ''; + position: absolute; + top: 0; + border-left: 2px solid black; + border-bottom: none; + width: 2px; + height: 50%; + left: 200px; + z-index: -10; +} +/*Time for some hover effects*/ +/*We will apply the hover effect the the lineage of the element also*/ +/* +.tree li a:hover, .tree li a:hover+ul li a { + background: #c8e4f8; color: #000; border: 1px solid #94a0b4; +} +.tree li a:hover+ul li::after, +.tree li a:hover+ul li::before, +.tree li a:hover+ul::before, +.tree li a:hover+ul ul::before{ + border-color: #94a0b4; +} +*/ +/*Thats all. I hope you enjoyed it. +Thanks :)*/ +.network-node { + position: relative; + background-color: #f3f3f3; + padding: 12px; + width: 400px; + max-width: 400px; + box-sizing: border-box; +} +.network-node .equipment-icon { + position: relative; + float: left; + width: 64px; + max-width: 64px; + box-sizing: border-box; +} +.network-node .equipment-icon emded, +.network-node .equipment-icon img { + width: 64px; + max-width: 64px; +} +.network-node .equipment-icon img { + position: relative; + top: 10px; +} +.network-node .status-icon { + position: relative; + float: left; + width: 30px; + max-width: 30px; + margin-left: 24px; + margin-rigth: 8px; + top: 20px; + box-sizing: border-box; +} +.network-node .status-icon img { + max-width: 30px; + width: 30px; +} +.network-node .info { + position: relative; + float: right; + width: 250px; + text-align: left; + font-size: 12px; + color: #757575; +} +.network-node .info .title { + display: block; + font-size: 17px; + font-weight: 700; + color: #333333; +} +.network-node .info .status-message { + display: block; +} +.network-node .info .status-message.error { + color: #e55712; +} +.network-node .info .status-message.warning { + color: #eb9e10; +} +.network-node .info .content { + display: block; +} +#networkRootNode table td { + border-top: 0px; +} \ No newline at end of file diff --git a/luci-app-openmptcprouter/htdocs/luci-static/resources/openmptcprouter/images/status-doing.png b/luci-app-openmptcprouter/htdocs/luci-static/resources/openmptcprouter/images/status-doing.png new file mode 100644 index 000000000..e71747272 Binary files /dev/null and b/luci-app-openmptcprouter/htdocs/luci-static/resources/openmptcprouter/images/status-doing.png differ diff --git a/luci-app-openmptcprouter/htdocs/luci-static/resources/openmptcprouter/images/status-done.png b/luci-app-openmptcprouter/htdocs/luci-static/resources/openmptcprouter/images/status-done.png new file mode 100644 index 000000000..bb6265c98 Binary files /dev/null and b/luci-app-openmptcprouter/htdocs/luci-static/resources/openmptcprouter/images/status-done.png differ diff --git a/luci-app-openmptcprouter/htdocs/luci-static/resources/openmptcprouter/images/status-error.png b/luci-app-openmptcprouter/htdocs/luci-static/resources/openmptcprouter/images/status-error.png new file mode 100644 index 000000000..4d2cf17ea Binary files /dev/null and b/luci-app-openmptcprouter/htdocs/luci-static/resources/openmptcprouter/images/status-error.png differ diff --git a/luci-app-openmptcprouter/htdocs/luci-static/resources/openmptcprouter/images/status-todo.png b/luci-app-openmptcprouter/htdocs/luci-static/resources/openmptcprouter/images/status-todo.png new file mode 100644 index 000000000..e71747272 Binary files /dev/null and b/luci-app-openmptcprouter/htdocs/luci-static/resources/openmptcprouter/images/status-todo.png differ diff --git a/luci-app-openmptcprouter/htdocs/luci-static/resources/openmptcprouter/images/status-warn.png b/luci-app-openmptcprouter/htdocs/luci-static/resources/openmptcprouter/images/status-warn.png new file mode 100644 index 000000000..9194825fb Binary files /dev/null and b/luci-app-openmptcprouter/htdocs/luci-static/resources/openmptcprouter/images/status-warn.png differ diff --git a/luci-app-openmptcprouter/htdocs/luci-static/resources/openmptcprouter/images/statusError.png b/luci-app-openmptcprouter/htdocs/luci-static/resources/openmptcprouter/images/statusError.png new file mode 100644 index 000000000..d22c0de55 Binary files /dev/null and b/luci-app-openmptcprouter/htdocs/luci-static/resources/openmptcprouter/images/statusError.png differ diff --git a/luci-app-openmptcprouter/htdocs/luci-static/resources/openmptcprouter/images/statusOK.png b/luci-app-openmptcprouter/htdocs/luci-static/resources/openmptcprouter/images/statusOK.png new file mode 100644 index 000000000..7a40c9758 Binary files /dev/null and b/luci-app-openmptcprouter/htdocs/luci-static/resources/openmptcprouter/images/statusOK.png differ diff --git a/luci-app-openmptcprouter/htdocs/luci-static/resources/openmptcprouter/images/statusWarning.png b/luci-app-openmptcprouter/htdocs/luci-static/resources/openmptcprouter/images/statusWarning.png new file mode 100644 index 000000000..29ee04f01 Binary files /dev/null and b/luci-app-openmptcprouter/htdocs/luci-static/resources/openmptcprouter/images/statusWarning.png differ diff --git a/luci-app-openmptcprouter/htdocs/luci-static/resources/overthebox.png b/luci-app-openmptcprouter/htdocs/luci-static/resources/overthebox.png new file mode 100644 index 000000000..7b578c01f Binary files /dev/null and b/luci-app-openmptcprouter/htdocs/luci-static/resources/overthebox.png differ diff --git a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua index 8b40669dd..1d589bc82 100644 --- a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua +++ b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua @@ -1,3 +1,6 @@ +local tools = require "luci.tools.status" +local sys = require "luci.sys" +local json = require("luci.json") local ucic = uci.cursor() module("luci.controller.openmptcprouter", package.seeall) @@ -5,8 +8,11 @@ function index() -- entry({"admin", "openmptcprouter"}, firstchild(), _("OpenMPTCProuter"), 19).index = true -- entry({"admin", "openmptcprouter", "wizard"}, template("openmptcprouter/wizard"), _("Wizard"), 1).leaf = true -- entry({"admin", "openmptcprouter", "wizard_add"}, post("wizard_add")).leaf = true - entry({"admin", "system", "openmptcprouter"}, template("openmptcprouter/wizard"), _("Settings Wizard"), 1) + entry({"admin", "system", "openmptcprouter"}, alias("admin", "system", "openmptcprouter", "wizard"), _("OpenMPTCProuter")) + entry({"admin", "system", "openmptcprouter", "wizard"}, template("openmptcprouter/wizard"), _("Settings Wizard"), 1) entry({"admin", "system", "openmptcprouter", "wizard_add"}, post("wizard_add")) + entry({"admin", "system", "openmptcprouter", "status"}, template("openmptcprouter/wanstatus"), _("Status"), 2).leaf = true + entry({"admin", "system", "openmptcprouter", "interfaces_status"}, call("interfaces_status")).leaf = true end function wizard_add() @@ -47,6 +53,144 @@ function wizard_add() ucic:commit("network") luci.sys.call("(env -i /bin/ubus call network reload) >/dev/null 2>/dev/null") luci.sys.call("/etc/init.d/glorytun restart >/dev/null 2>/dev/null") - luci.http.redirect(luci.dispatcher.build_url("admin/network/network")) + luci.http.redirect(luci.dispatcher.build_url("admin/system/openmptcprouter/status")) return +end + +-- This function come from OverTheBox by OVH with very small changes +function interfaces_status() + local ut = require "luci.util" + local ntm = require "luci.model.network".init() + local uci = require "luci.model.uci".cursor() + + local mArray = {} + + -- OpenMPTCProuter info + mArray.openmptcprouter = {} + mArray.openmptcprouter["version"] = ut.trim(sys.exec("cat /etc/os-release | grep VERSION= | sed -e 's:VERSION=::'")) + -- Check that requester is in same network + mArray.openmptcprouter["service_addr"] = uci:get("shadowsocks", "proxy", "server") or "0.0.0.0" + mArray.openmptcprouter["local_addr"] = uci:get("network", "lan", "ipaddr") + mArray.openmptcprouter["wan_addr"] = "0.0.0.0" + + -- wanaddr + mArray.openmptcprouter["wan_addr"] = sys.exec("wget -4 -qO- -T 1 http://ip.openmptcprouter.com") + + mArray.openmptcprouter["remote_addr"] = luci.http.getenv("REMOTE_ADDR") or "" + mArray.openmptcprouter["remote_from_lease"] = false + local leases=tools.dhcp_leases() + for _, value in pairs(leases) do + if value["ipaddr"] == mArray.openmptcprouter["remote_addr"] then + mArray.openmptcprouter["remote_from_lease"] = true + mArray.openmptcprouter["remote_hostname"] = value["hostname"] + end + end + + -- Check openmptcprouter service are running + mArray.openmptcprouter["tun_service"] = false + if string.find(sys.exec("/usr/bin/pgrep '^(/usr/sbin/)?glorytun(-udp)?$'"), "%d+") then + mArray.openmptcprouter["tun_service"] = true + end + mArray.openmptcprouter["socks_service"] = false + if string.find(sys.exec("/usr/bin/pgrep ss-redir"), "%d+") then + mArray.openmptcprouter["socks_service"] = true + end + + -- Add DHCP infos by parsing dnsmasq config file + mArray.openmptcprouter.dhcpd = {} + dnsmasq = ut.trim(sys.exec("cat /var/etc/dnsmasq.conf*")) + for itf, range_start, range_end, mask, leasetime in dnsmasq:gmatch("range=[%w,!:-]*set:(%w+),(%d+\.%d+\.%d+\.%d+),(%d+\.%d+\.%d+\.%d+),(%d+\.%d+\.%d+\.%d+),(%w+)") do + mArray.openmptcprouter.dhcpd[itf] = {} + mArray.openmptcprouter.dhcpd[itf].interface = itf + mArray.openmptcprouter.dhcpd[itf].range_start = range_start + mArray.openmptcprouter.dhcpd[itf].range_end = range_end + mArray.openmptcprouter.dhcpd[itf].netmask = mask + mArray.openmptcprouter.dhcpd[itf].leasetime = leasetime + mArray.openmptcprouter.dhcpd[itf].router = mArray.openmptcprouter["local_addr"] + mArray.openmptcprouter.dhcpd[itf].dns = mArray.openmptcprouter["local_addr"] + end + for itf, option, value in dnsmasq:gmatch("option=(%w+),([%w:-]+),(%d+\.%d+\.%d+\.%d+)") do + if mArray.openmptcprouter.dhcpd[itf] then + if option == "option:router" or option == "6" then + mArray.openmptcprouter.dhcpd[itf].router = value + end + if option == "option:dns-server" or option == "" then + mArray.openmptcprouter.dhcpd[itf].dns = value + end + end + end + -- Parse mptcp kernel info + local mptcp = {} + local fullmesh = ut.trim(sys.exec("cat /proc/net/mptcp_fullmesh")) + for ind, addressId, backup, ipaddr in fullmesh:gmatch("(%d+), (%d+), (%d+), (%d+\.%d+\.%d+\.%d+)") do + mptcp[ipaddr] = {} + mptcp[ipaddr].index = ind + mptcp[ipaddr].id = addressId + mptcp[ipaddr].backup= backup + mptcp[ipaddr].ipaddr= ipaddr + end + + -- retrieve core temperature + --mArray.openmptcprouter["core_temp"] = sys.exec("cat /sys/devices/platform/coretemp.0/hwmon/hwmon0/temp2_input 2>/dev/null"):match("%d+") + mArray.openmptcprouter["loadavg"] = sys.exec("cat /proc/loadavg 2>/dev/null"):match("[%d%.]+ [%d%.]+ [%d%.]+") + mArray.openmptcprouter["uptime"] = sys.exec("cat /proc/uptime 2>/dev/null"):match("[%d%.]+") + + -- overview status + mArray.wans = {} + mArray.tunnels = {} + + uci:foreach("network", "interface", function (section) + local interface = section[".name"] + local net = ntm:get_network(interface) + local ipaddr = net:ipaddr() + local gateway = section['gateway'] + local multipath = section['multipath'] + + --if not ipaddr or not gateway then return end + -- Don't show if0 in the overview + --if interface == "lo" then return end + + local ifname = section['ifname'] + if multipath == "off" and not ifname:match("^tun.*") then return end + + local asn + + local connectivity + local multipath_state = ut.trim(sys.exec("multipath " .. ifname .. " | grep deactivated")) + if multipath_state == "" then + connectivity = 'OK' + else + connectivity = 'ERROR' + end + + local publicIP = "-" + + local latency = "-" + + local data = { + label = section['label'] or interface, + name = interface, + link = net:adminlink(), + ifname = ifname, + ipaddr = ipaddr, + gateway = gateway, + multipath = section['multipath'], + status = connectivity, + wanip = publicIP, + latency = latency, + whois = asn and asn.as_description or "unknown", + qos = section['trafficcontrol'], + download = section['download'], + upload = section['upload'], + } + + if ifname:match("^tun.*") then + table.insert(mArray.tunnels, data); + else + table.insert(mArray.wans, data); + end + end) + + luci.http.prepare_content("application/json") + luci.http.write_json(mArray) end \ No newline at end of file diff --git a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm new file mode 100644 index 000000000..a71b6c242 --- /dev/null +++ b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm @@ -0,0 +1,284 @@ +<% +-- Copyright 2015 OVH (OverTheBox@ovh.net) +-- Simon Lelievre (simon.lelievre@corp.ovh.com) +-- Sebastien Duponcheel (sebastien.duponcheel@ovh.net) +-- +-- This file is part of OverTheBox for OpenWrt. +-- +-- OverTheBox is free software: you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation, either version 3 of the License, or +-- (at your option) any later version. +-- +-- OverTheBox is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with OverTheBox. If not, see (http://www.gnu.org/licenses/) +-%> +<% +-- Copyright 2018 Ycarus (Yannick Chabanois) ycarus@zugaina.org +-- +-- Small changes to make this work with OpenMPTCProuter +-%> +<%+header%> + + + + + +

<%:Network overview%>

+
+ +
+
+<%+footer%> \ No newline at end of file