From 58d97b5e271bc0d7507eab5b9bd2902181864e02 Mon Sep 17 00:00:00 2001 From: "Daniel F. Dickinson" Date: Fri, 3 Aug 2018 12:36:51 -0400 Subject: modules: Split luci-mod-full Move some common elements to luci-base, and otherwise make three packages out of status, system, and network. They were mostly separated already, but there were some shared elements between status and network that are now in luci-base. Signed-off-by: Daniel F. Dickinson --- modules/luci-mod-status/Makefile | 18 + .../htdocs/luci-static/resources/bandwidth.svg | 16 + .../htdocs/luci-static/resources/connections.svg | 17 + .../htdocs/luci-static/resources/load.svg | 17 + .../htdocs/luci-static/resources/wifirate.svg | 15 + .../htdocs/luci-static/resources/wireless.svg | 16 + .../luasrc/controller/admin/status.lua | 153 ++++ .../luasrc/model/cbi/admin_status/processes.lua | 34 + .../luasrc/view/admin_status/bandwidth.htm | 305 ++++++++ .../luasrc/view/admin_status/connections.htm | 376 ++++++++++ .../luasrc/view/admin_status/dmesg.htm | 12 + .../luasrc/view/admin_status/index.htm | 487 +++++++++++++ .../luasrc/view/admin_status/iptables.htm | 155 ++++ .../luasrc/view/admin_status/load.htm | 285 ++++++++ .../luasrc/view/admin_status/routes.htm | 156 +++++ .../luasrc/view/admin_status/syslog.htm | 12 + .../luasrc/view/admin_status/wireless.htm | 371 ++++++++++ modules/luci-mod-status/src/Makefile | 14 + modules/luci-mod-status/src/luci-bwc.c | 778 +++++++++++++++++++++ 19 files changed, 3237 insertions(+) create mode 100644 modules/luci-mod-status/Makefile create mode 100644 modules/luci-mod-status/htdocs/luci-static/resources/bandwidth.svg create mode 100644 modules/luci-mod-status/htdocs/luci-static/resources/connections.svg create mode 100644 modules/luci-mod-status/htdocs/luci-static/resources/load.svg create mode 100644 modules/luci-mod-status/htdocs/luci-static/resources/wifirate.svg create mode 100644 modules/luci-mod-status/htdocs/luci-static/resources/wireless.svg create mode 100644 modules/luci-mod-status/luasrc/controller/admin/status.lua create mode 100644 modules/luci-mod-status/luasrc/model/cbi/admin_status/processes.lua create mode 100644 modules/luci-mod-status/luasrc/view/admin_status/bandwidth.htm create mode 100644 modules/luci-mod-status/luasrc/view/admin_status/connections.htm create mode 100644 modules/luci-mod-status/luasrc/view/admin_status/dmesg.htm create mode 100644 modules/luci-mod-status/luasrc/view/admin_status/index.htm create mode 100644 modules/luci-mod-status/luasrc/view/admin_status/iptables.htm create mode 100644 modules/luci-mod-status/luasrc/view/admin_status/load.htm create mode 100644 modules/luci-mod-status/luasrc/view/admin_status/routes.htm create mode 100644 modules/luci-mod-status/luasrc/view/admin_status/syslog.htm create mode 100644 modules/luci-mod-status/luasrc/view/admin_status/wireless.htm create mode 100644 modules/luci-mod-status/src/Makefile create mode 100644 modules/luci-mod-status/src/luci-bwc.c (limited to 'modules/luci-mod-status') diff --git a/modules/luci-mod-status/Makefile b/modules/luci-mod-status/Makefile new file mode 100644 index 0000000000..cf8c8ddf83 --- /dev/null +++ b/modules/luci-mod-status/Makefile @@ -0,0 +1,18 @@ +# +# Copyright (C) 2008-2014 The LuCI Team +# +# This is free software, licensed under the Apache License, Version 2.0 . +# + +include $(TOPDIR)/rules.mk + +LUCI_TITLE:=LuCI Status Pages +LUCI_DEPENDS:=+luci-base +libiwinfo +libiwinfo-lua + +PKG_BUILD_DEPENDS:=iwinfo +PKG_LICENSE:=Apache-2.0 + +include ../../luci.mk + +# call BuildPackage - OpenWrt buildroot signature + diff --git a/modules/luci-mod-status/htdocs/luci-static/resources/bandwidth.svg b/modules/luci-mod-status/htdocs/luci-static/resources/bandwidth.svg new file mode 100644 index 0000000000..5a121b85c6 --- /dev/null +++ b/modules/luci-mod-status/htdocs/luci-static/resources/bandwidth.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/modules/luci-mod-status/htdocs/luci-static/resources/connections.svg b/modules/luci-mod-status/htdocs/luci-static/resources/connections.svg new file mode 100644 index 0000000000..5794e79426 --- /dev/null +++ b/modules/luci-mod-status/htdocs/luci-static/resources/connections.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/modules/luci-mod-status/htdocs/luci-static/resources/load.svg b/modules/luci-mod-status/htdocs/luci-static/resources/load.svg new file mode 100644 index 0000000000..716d37617f --- /dev/null +++ b/modules/luci-mod-status/htdocs/luci-static/resources/load.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/modules/luci-mod-status/htdocs/luci-static/resources/wifirate.svg b/modules/luci-mod-status/htdocs/luci-static/resources/wifirate.svg new file mode 100644 index 0000000000..e75ea614c9 --- /dev/null +++ b/modules/luci-mod-status/htdocs/luci-static/resources/wifirate.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/modules/luci-mod-status/htdocs/luci-static/resources/wireless.svg b/modules/luci-mod-status/htdocs/luci-static/resources/wireless.svg new file mode 100644 index 0000000000..00cc2a12f1 --- /dev/null +++ b/modules/luci-mod-status/htdocs/luci-static/resources/wireless.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/modules/luci-mod-status/luasrc/controller/admin/status.lua b/modules/luci-mod-status/luasrc/controller/admin/status.lua new file mode 100644 index 0000000000..4f04cce545 --- /dev/null +++ b/modules/luci-mod-status/luasrc/controller/admin/status.lua @@ -0,0 +1,153 @@ +-- Copyright 2008 Steven Barth +-- Copyright 2011 Jo-Philipp Wich +-- Licensed to the public under the Apache License 2.0. + +module("luci.controller.admin.status", package.seeall) + +function index() + entry({"admin", "status", "overview"}, template("admin_status/index"), _("Overview"), 1) + + entry({"admin", "status", "iptables"}, template("admin_status/iptables"), _("Firewall"), 2).leaf = true + entry({"admin", "status", "iptables_action"}, post("action_iptables")).leaf = true + + entry({"admin", "status", "routes"}, template("admin_status/routes"), _("Routes"), 3) + entry({"admin", "status", "syslog"}, call("action_syslog"), _("System Log"), 4) + entry({"admin", "status", "dmesg"}, call("action_dmesg"), _("Kernel Log"), 5) + entry({"admin", "status", "processes"}, form("admin_status/processes"), _("Processes"), 6) + + entry({"admin", "status", "realtime"}, alias("admin", "status", "realtime", "load"), _("Realtime Graphs"), 7) + + entry({"admin", "status", "realtime", "load"}, template("admin_status/load"), _("Load"), 1).leaf = true + entry({"admin", "status", "realtime", "load_status"}, call("action_load")).leaf = true + + entry({"admin", "status", "realtime", "bandwidth"}, template("admin_status/bandwidth"), _("Traffic"), 2).leaf = true + entry({"admin", "status", "realtime", "bandwidth_status"}, call("action_bandwidth")).leaf = true + + if nixio.fs.access("/etc/config/wireless") then + entry({"admin", "status", "realtime", "wireless"}, template("admin_status/wireless"), _("Wireless"), 3).leaf = true + entry({"admin", "status", "realtime", "wireless_status"}, call("action_wireless")).leaf = true + end + + entry({"admin", "status", "realtime", "connections"}, template("admin_status/connections"), _("Connections"), 4).leaf = true + entry({"admin", "status", "realtime", "connections_status"}, call("action_connections")).leaf = true + + entry({"admin", "status", "nameinfo"}, call("action_nameinfo")).leaf = true +end + +function action_syslog() + local syslog = luci.sys.syslog() + luci.template.render("admin_status/syslog", {syslog=syslog}) +end + +function action_dmesg() + local dmesg = luci.sys.dmesg() + luci.template.render("admin_status/dmesg", {dmesg=dmesg}) +end + +function action_iptables() + if luci.http.formvalue("zero") then + if luci.http.formvalue("family") == "6" then + luci.util.exec("/usr/sbin/ip6tables -Z") + else + luci.util.exec("/usr/sbin/iptables -Z") + end + elseif luci.http.formvalue("restart") then + luci.util.exec("/etc/init.d/firewall restart") + end + + luci.http.redirect(luci.dispatcher.build_url("admin/status/iptables")) +end + +function action_bandwidth(iface) + luci.http.prepare_content("application/json") + + local bwc = io.popen("luci-bwc -i %s 2>/dev/null" + % luci.util.shellquote(iface)) + + if bwc then + luci.http.write("[") + + while true do + local ln = bwc:read("*l") + if not ln then break end + luci.http.write(ln) + end + + luci.http.write("]") + bwc:close() + end +end + +function action_wireless(iface) + luci.http.prepare_content("application/json") + + local bwc = io.popen("luci-bwc -r %s 2>/dev/null" + % luci.util.shellquote(iface)) + + if bwc then + luci.http.write("[") + + while true do + local ln = bwc:read("*l") + if not ln then break end + luci.http.write(ln) + end + + luci.http.write("]") + bwc:close() + end +end + +function action_load() + luci.http.prepare_content("application/json") + + local bwc = io.popen("luci-bwc -l 2>/dev/null") + if bwc then + luci.http.write("[") + + while true do + local ln = bwc:read("*l") + if not ln then break end + luci.http.write(ln) + end + + luci.http.write("]") + bwc:close() + end +end + +function action_connections() + local sys = require "luci.sys" + + luci.http.prepare_content("application/json") + + luci.http.write('{ "connections": ') + luci.http.write_json(sys.net.conntrack()) + + local bwc = io.popen("luci-bwc -c 2>/dev/null") + if bwc then + luci.http.write(', "statistics": [') + + while true do + local ln = bwc:read("*l") + if not ln then break end + luci.http.write(ln) + end + + luci.http.write("]") + bwc:close() + end + + luci.http.write(" }") +end + +function action_nameinfo(...) + local util = require "luci.util" + + luci.http.prepare_content("application/json") + luci.http.write_json(util.ubus("network.rrdns", "lookup", { + addrs = { ... }, + timeout = 5000, + limit = 1000 + }) or { }) +end diff --git a/modules/luci-mod-status/luasrc/model/cbi/admin_status/processes.lua b/modules/luci-mod-status/luasrc/model/cbi/admin_status/processes.lua new file mode 100644 index 0000000000..0a6e48fd8e --- /dev/null +++ b/modules/luci-mod-status/luasrc/model/cbi/admin_status/processes.lua @@ -0,0 +1,34 @@ +-- Copyright 2008 Steven Barth +-- Copyright 2008 Jo-Philipp Wich +-- Licensed to the public under the Apache License 2.0. + +f = SimpleForm("processes", translate("Processes"), translate("This list gives an overview over currently running system processes and their status.")) +f.reset = false +f.submit = false + +t = f:section(Table, luci.sys.process.list()) +t:option(DummyValue, "PID", translate("PID")) +t:option(DummyValue, "USER", translate("Owner")) +t:option(DummyValue, "COMMAND", translate("Command")) +t:option(DummyValue, "%CPU", translate("CPU usage (%)")) +t:option(DummyValue, "%MEM", translate("Memory usage (%)")) + +hup = t:option(Button, "_hup", translate("Hang Up")) +hup.inputstyle = "reload" +function hup.write(self, section) + null, self.tag_error[section] = luci.sys.process.signal(section, 1) +end + +term = t:option(Button, "_term", translate("Terminate")) +term.inputstyle = "remove" +function term.write(self, section) + null, self.tag_error[section] = luci.sys.process.signal(section, 15) +end + +kill = t:option(Button, "_kill", translate("Kill")) +kill.inputstyle = "reset" +function kill.write(self, section) + null, self.tag_error[section] = luci.sys.process.signal(section, 9) +end + +return f \ No newline at end of file diff --git a/modules/luci-mod-status/luasrc/view/admin_status/bandwidth.htm b/modules/luci-mod-status/luasrc/view/admin_status/bandwidth.htm new file mode 100644 index 0000000000..3bb55f9054 --- /dev/null +++ b/modules/luci-mod-status/luasrc/view/admin_status/bandwidth.htm @@ -0,0 +1,305 @@ +<%# + Copyright 2010 Jo-Philipp Wich + Licensed to the public under the Apache License 2.0. +-%> + +<%- + local ntm = require "luci.model.network".init() + + local dev + local devices = { } + for _, dev in luci.util.vspairs(luci.sys.net.devices()) do + if dev ~= "lo" and not ntm:ignore_interface(dev) then + devices[#devices+1] = dev + end + end + + local curdev = luci.http.formvalue("dev") or devices[1] +-%> + +<%+header%> + + + +

<%:Realtime Traffic%>

+ + + + +
-
+
+ +
+
+
<%:Inbound:%>
+
0 <%:kbit/s%>
(0 <%:kB/s%>)
+ +
<%:Average:%>
+
0 <%:kbit/s%>
(0 <%:kB/s%>)
+ +
<%:Peak:%>
+
0 <%:kbit/s%>
(0 <%:kB/s%>)
+
+
+
<%:Outbound:%>
+
0 <%:kbit/s%>
(0 <%:kB/s%>)
+ +
<%:Average:%>
+
0 <%:kbit/s%>
(0 <%:kB/s%>)
+ +
<%:Peak:%>
+
0 <%:kbit/s%>
(0 <%:kB/s%>)
+
+
+ +<%+footer%> diff --git a/modules/luci-mod-status/luasrc/view/admin_status/connections.htm b/modules/luci-mod-status/luasrc/view/admin_status/connections.htm new file mode 100644 index 0000000000..0a0db3be78 --- /dev/null +++ b/modules/luci-mod-status/luasrc/view/admin_status/connections.htm @@ -0,0 +1,376 @@ +<%# + Copyright 2010 Jo-Philipp Wich + Licensed to the public under the Apache License 2.0. +-%> + +<%+header%> + + + +

<%:Realtime Connections%>

+ +
<%:This page gives an overview over currently active network connections.%>
+ +
+ <%:Active Connections%> + + +
-
+
+ +
+
+
<%:UDP:%>
+
0
+ +
<%:Average:%>
+
0
+ +
<%:Peak:%>
+
0
+
+
+
<%:TCP:%>
+
0
+ +
<%:Average:%>
+
0
+ +
<%:Peak:%>
+
0
+
+
+
<%:Other:%>
+
0
+ +
<%:Average:%>
+
0
+ +
<%:Peak:%>
+
0
+
+
+
+ +
+
+
+
<%:Network%>
+
<%:Protocol%>
+
<%:Source%>
+
<%:Destination%>
+
<%:Transfer%>
+
+ +
+
+ <%:Collecting data...%> +
+
+
+
+
+ +<%+footer%> diff --git a/modules/luci-mod-status/luasrc/view/admin_status/dmesg.htm b/modules/luci-mod-status/luasrc/view/admin_status/dmesg.htm new file mode 100644 index 0000000000..1a8770ef88 --- /dev/null +++ b/modules/luci-mod-status/luasrc/view/admin_status/dmesg.htm @@ -0,0 +1,12 @@ +<%# + Copyright 2008 Steven Barth + Copyright 2008 Jo-Philipp Wich + Licensed to the public under the Apache License 2.0. +-%> + +<%+header%> +

<%:Kernel Log%>

+
+ +
+<%+footer%> diff --git a/modules/luci-mod-status/luasrc/view/admin_status/index.htm b/modules/luci-mod-status/luasrc/view/admin_status/index.htm new file mode 100644 index 0000000000..3edfd92047 --- /dev/null +++ b/modules/luci-mod-status/luasrc/view/admin_status/index.htm @@ -0,0 +1,487 @@ +<%# + Copyright 2008 Steven Barth + Copyright 2008-2011 Jo-Philipp Wich + Licensed to the public under the Apache License 2.0. +-%> + +<% + local fs = require "nixio.fs" + local ipc = require "luci.ip" + local util = require "luci.util" + local stat = require "luci.tools.status" + local ver = require "luci.version" + + local has_ipv6 = fs.access("/proc/net/ipv6_route") + local has_dhcp = fs.access("/etc/config/dhcp") + local has_wifi = ((fs.stat("/etc/config/wireless", "size") or 0) > 0) + + local sysinfo = luci.util.ubus("system", "info") or { } + local boardinfo = luci.util.ubus("system", "board") or { } + local unameinfo = nixio.uname() or { } + + local meminfo = sysinfo.memory or { + total = 0, + free = 0, + buffered = 0, + shared = 0 + } + + local swapinfo = sysinfo.swap or { + total = 0, + free = 0 + } + + local has_dsl = fs.access("/etc/init.d/dsl_control") + + if luci.http.formvalue("status") == "1" then + local ntm = require "luci.model.network".init() + local wan_nets = ntm:get_wan_networks() + local wan6_nets = ntm:get_wan6_networks() + + local conn_count = tonumber( + fs.readfile("/proc/sys/net/netfilter/nf_conntrack_count") or "") or 0 + + local conn_max = tonumber(luci.sys.exec( + "sysctl -n -e net.nf_conntrack_max net.ipv4.netfilter.ip_conntrack_max" + ):match("%d+")) or 4096 + + local rv = { + uptime = sysinfo.uptime or 0, + localtime = os.date(), + loadavg = sysinfo.load or { 0, 0, 0 }, + memory = meminfo, + swap = swapinfo, + connmax = conn_max, + conncount = conn_count, + wifinets = stat.wifi_networks() + } + + if #wan_nets > 0 then + local k, v + + rv.wan = { } + + for k, v in pairs(wan_nets) do + local dev = v:get_interface() + local link = dev and ipc.link(dev:name()) + + local wan_info = { + ipaddr = v:ipaddr(), + gwaddr = v:gwaddr(), + netmask = v:netmask(), + dns = v:dnsaddrs(), + expires = v:expires(), + uptime = v:uptime(), + proto = v:proto(), + i18n = v:get_i18n(), + ifname = v:ifname(), + link = v:adminlink(), + mac = dev and dev:mac(), + type = dev and dev:type(), + name = dev and dev:get_i18n(), + ether = link and link.type == 1 + } + + rv.wan[#rv.wan+1] = wan_info + end + end + + if #wan6_nets > 0 then + local k, v + + rv.wan6 = { } + + for k, v in pairs(wan6_nets) do + local dev = v:get_interface() + local link = dev and ipc.link(dev:name()) + local wan6_info = { + ip6addr = v:ip6addr(), + gw6addr = v:gw6addr(), + dns = v:dns6addrs(), + ip6prefix = v:ip6prefix(), + uptime = v:uptime(), + proto = v:proto(), + i18n = v:get_i18n(), + ifname = v:ifname(), + link = v:adminlink(), + mac = dev and dev:mac(), + type = dev and dev:type(), + name = dev and dev:get_i18n(), + ether = link and link.type == 1 + } + + rv.wan6[#rv.wan6+1] = wan6_info + end + end + + if has_dsl then + local dsl_stat = luci.sys.exec("/etc/init.d/dsl_control lucistat") + local dsl_func = loadstring(dsl_stat) + if dsl_func then + rv.dsl = dsl_func() + end + end + + luci.http.prepare_content("application/json") + luci.http.write_json(rv) + + return + end +-%> + +<%+header%> + + + +

<%:Status%>

+ +
+

<%:System%>

+ +
+
<%:Hostname%>
<%=luci.sys.hostname() or "?"%>
+
<%:Model%>
<%=pcdata(boardinfo.model or "?")%>
+
<%:Architecture%>
<%=pcdata(boardinfo.system or "?")%>
+
<%:Firmware Version%>
+ <%=pcdata(ver.distname)%> <%=pcdata(ver.distversion)%> / + <%=pcdata(ver.luciname)%> (<%=pcdata(ver.luciversion)%>) +
+
<%:Kernel Version%>
<%=unameinfo.release or "?"%>
+
<%:Local Time%>
-
+
<%:Uptime%>
-
+
<%:Load Average%>
-
+
+
+ +
+

<%:Memory%>

+ +
+
<%:Total Available%>
-
+
<%:Free%>
-
+
<%:Buffered%>
-
+
+
+ +<% if swapinfo.total > 0 then %> +
+

<%:Swap%>

+ +
+
<%:Total Available%>
-
+
<%:Free%>
-
+
+
+<% end %> + +
+

<%:Network%>

+ +
+

<%:Collecting data...%>

+
+ +
+
<%:Active Connections%>
-
+
+
+ +<% + if has_dhcp then + include("lease_status") + end +%> + +<% if has_dsl then %> +
+

<%:DSL%>

+ +
+

<%:Collecting data...%>

+
+
+<% end %> + +<% if has_wifi then %> +
+

<%:Wireless%>

+ +
+

<%:Collecting data...%>

+
+
+ +
+

<%:Associated Stations%>

+ + <%+wifi_assoclist%> +
+<% end %> + +<%- + local incdir = util.libpath() .. "/view/admin_status/index/" + if fs.access(incdir) then + local inc + for inc in fs.dir(incdir) do + if inc:match("%.htm$") then + include("admin_status/index/" .. inc:gsub("%.htm$", "")) + end + end + end +-%> + +<%+footer%> diff --git a/modules/luci-mod-status/luasrc/view/admin_status/iptables.htm b/modules/luci-mod-status/luasrc/view/admin_status/iptables.htm new file mode 100644 index 0000000000..51e428e40e --- /dev/null +++ b/modules/luci-mod-status/luasrc/view/admin_status/iptables.htm @@ -0,0 +1,155 @@ +<%# + Copyright 2008-2009 Steven Barth + Copyright 2008-2015 Jo-Philipp Wich + Licensed to the public under the Apache License 2.0. +-%> + +<%- + + require "luci.sys.iptparser" + local wba = require "luci.tools.webadmin" + local fs = require "nixio.fs" + local io = require "io" + + local has_ip6tables = fs.access("/usr/sbin/ip6tables") + local mode = 4 + + if has_ip6tables then + mode = luci.dispatcher.context.requestpath + mode = tonumber(mode[#mode] ~= "iptables" and mode[#mode]) or 4 + end + + local ipt = luci.sys.iptparser.IptParser(mode) + + local rowcnt = 1 + function rowstyle() + rowcnt = rowcnt + 1 + return (rowcnt % 2) + 1 + end + + function link_target(t,c) + if ipt:is_custom_target(c) then + return '%s' %{ t:lower(), c, c } + end + return c + end + + function link_iface(i) + local net = wba.iface_get_network(i) + if net and i ~= "lo" then + return '%s' %{ + url("admin/network/network", net), i + } + + end + return i + end + + local tables = { "Filter", "NAT", "Mangle", "Raw" } + if mode == 6 then + tables = { "Filter", "Mangle", "Raw" } + local ok, lines = pcall(io.lines, "/proc/net/ip6_tables_names") + if ok and lines then + local line + for line in lines do + if line == "nat" then + tables = { "Filter", "NAT", "Mangle", "Raw" } + end + end + end + end +-%> + +<%+header%> + + + +

<%:Firewall Status%>

+ +<% if has_ip6tables then %> + +<% end %> + +
+ +
" style="position: absolute; right: 0"> + + + + +
+ +
+ + <% for _, tbl in ipairs(tables) do chaincnt = 0 %> +

<%:Table%>: <%=tbl%>

+ + <% for _, chain in ipairs(ipt:chains(tbl)) do + rowcnt = 0 + chaincnt = chaincnt + 1 + chaininfo = ipt:chain(tbl, chain) + %> +

+ <%:Chain%> <%=chain%> + (<%- if chaininfo.policy then -%> + <%:Policy%>: <%=chaininfo.policy%>, <%:Packets%>: <%=chaininfo.packets%>, <%:Traffic%>: <%=wba.byte_format(chaininfo.bytes)-%> + <%- else -%> + <%:References%>: <%=chaininfo.references-%> + <%- end -%>) +

+ +
+
+
+
<%:Pkts.%>
+
<%:Traffic%>
+
<%:Target%>
+
<%:Prot.%>
+
<%:In%>
+
<%:Out%>
+
<%:Source%>
+
<%:Destination%>
+
<%:Options%>
+
+ + <% for _, rule in ipairs(ipt:find({table=tbl, chain=chain})) do %> +
+
<%=rule.packets%>
+
<%=wba.byte_format(rule.bytes)%>
+
<%=rule.target and link_target(tbl, rule.target) or "-"%>
+
<%=rule.protocol%>
+
<%=link_iface(rule.inputif)%>
+
<%=link_iface(rule.outputif)%>
+
<%=rule.source%>
+
<%=rule.destination%>
+
<%=#rule.options > 0 and luci.util.pcdata(table.concat(rule.options, " ")) or "-"%>
+
+ <% end %> + + <% if rowcnt == 1 then %> +
+
<%:No rules in this chain%>
+
+ <% end %> +
+
+ <% end %> + + <% if chaincnt == 0 then %> + <%:No chains in this table%> + <% end %> + +

+ <% end %> +
+
+ +<%+footer%> diff --git a/modules/luci-mod-status/luasrc/view/admin_status/load.htm b/modules/luci-mod-status/luasrc/view/admin_status/load.htm new file mode 100644 index 0000000000..bced06fa22 --- /dev/null +++ b/modules/luci-mod-status/luasrc/view/admin_status/load.htm @@ -0,0 +1,285 @@ +<%# + Copyright 2010 Jo-Philipp Wich + Licensed to the public under the Apache License 2.0. +-%> + +<%+header%> + + + +

<%:Realtime Load%>

+ + +
-
+
+ +
+
+
<%:1 Minute Load:%>
+
0
+ +
<%:Average:%>
+
0
+ +
<%:Peak:%>
+
0
+
+
+
<%:5 Minute Load:%>
+
0
+ +
<%:Average:%>
+
0
+ +
<%:Peak:%>
+
0
+
+
+
<%:15 Minute Load:%>
+
0
+ +
<%:Average:%>
+
0
+ +
<%:Peak:%>
+
0
+
+
+ +<%+footer%> diff --git a/modules/luci-mod-status/luasrc/view/admin_status/routes.htm b/modules/luci-mod-status/luasrc/view/admin_status/routes.htm new file mode 100644 index 0000000000..74779f6ad8 --- /dev/null +++ b/modules/luci-mod-status/luasrc/view/admin_status/routes.htm @@ -0,0 +1,156 @@ +<%# + Copyright 2008-2009 Steven Barth + Copyright 2008-2015 Jo-Philipp Wich + Licensed to the public under the Apache License 2.0. +-%> + +<%- + require "luci.tools.webadmin" + require "nixio.fs" + + local ip = require "luci.ip" + local style = true + local _, v + + local rtn = { + [255] = "local", + [254] = "main", + [253] = "default", + [0] = "unspec" + } + + if nixio.fs.access("/etc/iproute2/rt_tables") then + local ln + for ln in io.lines("/etc/iproute2/rt_tables") do + local i, n = ln:match("^(%d+)%s+(%S+)") + if i and n then + rtn[tonumber(i)] = n + end + end + end +-%> + +<%+header%> + + +
+

<%:Routes%>

+
<%:The following rules are currently active on this system.%>
+ +
+ ARP +
+
+
+
<%_IPv4-Address%>
+
<%_MAC-Address%>
+
<%:Interface%>
+
+ + <% + for _, v in ipairs(ip.neighbors({ family = 4 })) do + if v.mac then + %> +
+
<%=v.dest%>
+
<%=v.mac%>
+
<%=luci.tools.webadmin.iface_get_network(v.dev) or '(' .. v.dev .. ')'%>
+
+ <% + style = not style + end + end + %> +
+
+
+ +
+ <%_Active IPv4-Routes%> +
+
+
+
<%:Network%>
+
<%:Target%>
+
<%_IPv4-Gateway%>
+
<%:Metric%>
+
<%:Table%>
+
+ <% for _, v in ipairs(ip.routes({ family = 4, type = 1 })) do %> +
+
<%=luci.tools.webadmin.iface_get_network(v.dev) or v.dev%>
+
<%=v.dest%>
+
<%=v.gw or "-"%>
+
<%=v.metric or 0%>
+
<%=rtn[v.table] or v.table%>
+
+ <% style = not style end %> +
+
+
+ + <% + if nixio.fs.access("/proc/net/ipv6_route") then + style = true + %> +
+ <%_Active IPv6-Routes%> +
+
+
+
<%:Network%>
+
<%:Target%>
+
<%:Source%>
+
<%:Metric%>
+
<%:Table%>
+
+ <% + for _, v in ipairs(ip.routes({ family = 6, type = 1 })) do + if v.dest and not v.dest:is6linklocal() then + %> +
+
<%=luci.tools.webadmin.iface_get_network(v.dev) or '(' .. v.dev .. ')'%>
+
<%=v.dest%>
+
<%=v.from%>
+
<%=v.metric or 0%>
+
<%=rtn[v.table] or v.table%>
+
+ <% + style = not style + end + end + %> +
+
+
+ +
+ <%:IPv6 Neighbours%> +
+
+
+
<%:IPv6-Address%>
+
<%:MAC-Address%>
+
<%:Interface%>
+
+ <% + for _, v in ipairs(ip.neighbors({ family = 6 })) do + if v.dest and not v.dest:is6linklocal() and v.mac then + %> +
+
<%=v.dest%>
+
<%=v.mac%>
+
<%=luci.tools.webadmin.iface_get_network(v.dev) or '(' .. v.dev .. ')'%>
+
+ <% + style = not style + end + end + %> +
+
+
+ <% end %> +
+ +<%+footer%> diff --git a/modules/luci-mod-status/luasrc/view/admin_status/syslog.htm b/modules/luci-mod-status/luasrc/view/admin_status/syslog.htm new file mode 100644 index 0000000000..fb734a76d9 --- /dev/null +++ b/modules/luci-mod-status/luasrc/view/admin_status/syslog.htm @@ -0,0 +1,12 @@ +<%# + Copyright 2008 Steven Barth + Copyright 2008 Jo-Philipp Wich + Licensed to the public under the Apache License 2.0. +-%> + +<%+header%> +

<%:System Log%>

+
+ +
+<%+footer%> diff --git a/modules/luci-mod-status/luasrc/view/admin_status/wireless.htm b/modules/luci-mod-status/luasrc/view/admin_status/wireless.htm new file mode 100644 index 0000000000..8ec43cb0e6 --- /dev/null +++ b/modules/luci-mod-status/luasrc/view/admin_status/wireless.htm @@ -0,0 +1,371 @@ +<%# + Copyright 2011 Jo-Philipp Wich + Licensed to the public under the Apache License 2.0. +-%> + +<%- + local ntm = require "luci.model.network".init() + + local dev + local devices = { } + for _, dev in luci.util.vspairs(luci.sys.net.devices()) do + if dev:match("^wlan%d") or dev:match("^ath%d") or dev:match("^wl%d") then + devices[#devices+1] = dev + end + end + + local curdev = luci.http.formvalue("dev") or devices[1] +-%> + +<%+header%> + + + +

<%:Realtime Wireless%>

+ + + + +
-
+
+ +
+
+
<%:Signal:%>
+
0 <%:dBm%>
+ +
<%:Average:%>
+
0 <%:dBm%>
+ +
<%:Peak:%>
+
0 <%:dBm%>
+
+
+
<%:Noise:%>
+
0 <%:dBm%>
+ +
<%:Average:%>
+
0 <%:dBm%>
+ +
<%:Peak:%>
+
0 <%:dBm%>
+
+
+ +
+ + +
-
+
+ +
+
+
<%:Phy Rate:%>
+
0 MBit/s
+ +
<%:Average:%>
+
0 MBit/s
+ +
<%:Peak:%>
+
0 MBit/s
+
+
+ +<%+footer%> diff --git a/modules/luci-mod-status/src/Makefile b/modules/luci-mod-status/src/Makefile new file mode 100644 index 0000000000..d6ed8c6e46 --- /dev/null +++ b/modules/luci-mod-status/src/Makefile @@ -0,0 +1,14 @@ +%.o: %.c + $(CC) $(CPPFLAGS) $(CFLAGS) $(FPIC) -c -o $@ $< + +clean: + rm -f luci-bwc *.o + +luci-bwc: luci-bwc.o + $(CC) $(LDFLAGS) -o $@ $^ -ldl + +compile: luci-bwc + +install: compile + mkdir -p $(DESTDIR)/usr/bin + cp luci-bwc $(DESTDIR)/usr/bin/luci-bwc diff --git a/modules/luci-mod-status/src/luci-bwc.c b/modules/luci-mod-status/src/luci-bwc.c new file mode 100644 index 0000000000..8ddd91727a --- /dev/null +++ b/modules/luci-mod-status/src/luci-bwc.c @@ -0,0 +1,778 @@ +/* + * luci-bwc - Very simple bandwidth collector cache for LuCI realtime graphs + * + * Copyright (C) 2010 Jo-Philipp Wich + * + * 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 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#define STEP_COUNT 60 +#define STEP_TIME 1 +#define TIMEOUT 10 + +#define PID_PATH "/var/run/luci-bwc.pid" + +#define DB_PATH "/var/lib/luci-bwc" +#define DB_IF_FILE DB_PATH "/if/%s" +#define DB_RD_FILE DB_PATH "/radio/%s" +#define DB_CN_FILE DB_PATH "/connections" +#define DB_LD_FILE DB_PATH "/load" + +#define IF_SCAN_PATTERN \ + " %[^ :]:%u %u" \ + " %*d %*d %*d %*d %*d %*d" \ + " %u %u" + +#define LD_SCAN_PATTERN \ + "%f %f %f" + + +struct file_map { + int fd; + int size; + char *mmap; +}; + +struct traffic_entry { + uint32_t time; + uint32_t rxb; + uint32_t rxp; + uint32_t txb; + uint32_t txp; +}; + +struct conn_entry { + uint32_t time; + uint32_t udp; + uint32_t tcp; + uint32_t other; +}; + +struct load_entry { + uint32_t time; + uint16_t load1; + uint16_t load5; + uint16_t load15; +}; + +struct radio_entry { + uint32_t time; + uint16_t rate; + uint8_t rssi; + uint8_t noise; +}; + +static int readpid(void) +{ + int fd; + int pid = -1; + char buf[9] = { 0 }; + + if ((fd = open(PID_PATH, O_RDONLY)) > -1) + { + if (read(fd, buf, sizeof(buf))) + { + buf[8] = 0; + pid = atoi(buf); + } + + close(fd); + } + + return pid; +} + +static int writepid(void) +{ + int fd; + int wlen; + char buf[9] = { 0 }; + + if ((fd = open(PID_PATH, O_WRONLY | O_CREAT | O_TRUNC, 0600)) > -1) + { + wlen = snprintf(buf, sizeof(buf), "%i", getpid()); + write(fd, buf, wlen); + close(fd); + + return 0; + } + + return -1; +} + +static int timeout = TIMEOUT; +static int countdown = -1; + +static void reset_countdown(int sig) +{ + countdown = timeout; + +} + + +static char *progname; +static int prognamelen; + +static struct iwinfo_ops *backend = NULL; + + +static int init_directory(char *path) +{ + char *p = path; + + for (p = &path[1]; *p; p++) + { + if (*p == '/') + { + *p = 0; + + if (mkdir(path, 0700) && (errno != EEXIST)) + return -1; + + *p = '/'; + } + } + + return 0; +} + +static int init_file(char *path, int esize) +{ + int i, file; + char buf[sizeof(struct traffic_entry)] = { 0 }; + + if (init_directory(path)) + return -1; + + if ((file = open(path, O_WRONLY | O_CREAT, 0600)) >= 0) + { + for (i = 0; i < STEP_COUNT; i++) + { + if (write(file, buf, esize) < 0) + break; + } + + close(file); + + return 0; + } + + return -1; +} + +static inline uint32_t timeof(void *entry) +{ + return ntohl(((struct traffic_entry *)entry)->time); +} + +static int update_file(const char *path, void *entry, int esize) +{ + int rv = -1; + int file; + char *map; + + if ((file = open(path, O_RDWR)) >= 0) + { + map = mmap(NULL, esize * STEP_COUNT, PROT_READ | PROT_WRITE, + MAP_SHARED | MAP_LOCKED, file, 0); + + if ((map != NULL) && (map != MAP_FAILED)) + { + if (timeof(entry) > timeof(map + esize * (STEP_COUNT-1))) + { + memmove(map, map + esize, esize * (STEP_COUNT-1)); + memcpy(map + esize * (STEP_COUNT-1), entry, esize); + } + + munmap(map, esize * STEP_COUNT); + + rv = 0; + } + + close(file); + } + + return rv; +} + +static int mmap_file(const char *path, int esize, struct file_map *m) +{ + m->fd = -1; + m->size = -1; + m->mmap = NULL; + + if ((m->fd = open(path, O_RDONLY)) >= 0) + { + m->size = STEP_COUNT * esize; + m->mmap = mmap(NULL, m->size, PROT_READ, + MAP_SHARED | MAP_LOCKED, m->fd, 0); + + if ((m->mmap != NULL) && (m->mmap != MAP_FAILED)) + return 0; + } + + return -1; +} + +static void umap_file(struct file_map *m) +{ + if ((m->mmap != NULL) && (m->mmap != MAP_FAILED)) + munmap(m->mmap, m->size); + + if (m->fd > -1) + close(m->fd); +} + +static void * iw_open(void) +{ + return dlopen("/usr/lib/libiwinfo.so", RTLD_LAZY); +} + +static int iw_update( + void *iw, const char *ifname, uint16_t *rate, uint8_t *rssi, uint8_t *noise +) { + struct iwinfo_ops *(*probe)(const char *); + int val; + + if (!backend) + { + probe = dlsym(iw, "iwinfo_backend"); + + if (!probe) + return 0; + + backend = probe(ifname); + + if (!backend) + return 0; + } + + *rate = (backend->bitrate && !backend->bitrate(ifname, &val)) ? val : 0; + *rssi = (backend->signal && !backend->signal(ifname, &val)) ? val : 0; + *noise = (backend->noise && !backend->noise(ifname, &val)) ? val : 0; + + return 1; +} + +static void iw_close(void *iw) +{ + void (*finish)(void); + + finish = dlsym(iw, "iwinfo_finish"); + + if (finish) + finish(); + + dlclose(iw); +} + + +static int update_ifstat( + const char *ifname, uint32_t rxb, uint32_t rxp, uint32_t txb, uint32_t txp +) { + char path[1024]; + + struct stat s; + struct traffic_entry e; + + snprintf(path, sizeof(path), DB_IF_FILE, ifname); + + if (stat(path, &s)) + { + if (init_file(path, sizeof(struct traffic_entry))) + { + fprintf(stderr, "Failed to init %s: %s\n", + path, strerror(errno)); + + return -1; + } + } + + e.time = htonl(time(NULL)); + e.rxb = htonl(rxb); + e.rxp = htonl(rxp); + e.txb = htonl(txb); + e.txp = htonl(txp); + + return update_file(path, &e, sizeof(struct traffic_entry)); +} + +static int update_radiostat( + const char *ifname, uint16_t rate, uint8_t rssi, uint8_t noise +) { + char path[1024]; + + struct stat s; + struct radio_entry e; + + snprintf(path, sizeof(path), DB_RD_FILE, ifname); + + if (stat(path, &s)) + { + if (init_file(path, sizeof(struct radio_entry))) + { + fprintf(stderr, "Failed to init %s: %s\n", + path, strerror(errno)); + + return -1; + } + } + + e.time = htonl(time(NULL)); + e.rate = htons(rate); + e.rssi = rssi; + e.noise = noise; + + return update_file(path, &e, sizeof(struct radio_entry)); +} + +static int update_cnstat(uint32_t udp, uint32_t tcp, uint32_t other) +{ + char path[1024]; + + struct stat s; + struct conn_entry e; + + snprintf(path, sizeof(path), DB_CN_FILE); + + if (stat(path, &s)) + { + if (init_file(path, sizeof(struct conn_entry))) + { + fprintf(stderr, "Failed to init %s: %s\n", + path, strerror(errno)); + + return -1; + } + } + + e.time = htonl(time(NULL)); + e.udp = htonl(udp); + e.tcp = htonl(tcp); + e.other = htonl(other); + + return update_file(path, &e, sizeof(struct conn_entry)); +} + +static int update_ldstat(uint16_t load1, uint16_t load5, uint16_t load15) +{ + char path[1024]; + + struct stat s; + struct load_entry e; + + snprintf(path, sizeof(path), DB_LD_FILE); + + if (stat(path, &s)) + { + if (init_file(path, sizeof(struct load_entry))) + { + fprintf(stderr, "Failed to init %s: %s\n", + path, strerror(errno)); + + return -1; + } + } + + e.time = htonl(time(NULL)); + e.load1 = htons(load1); + e.load5 = htons(load5); + e.load15 = htons(load15); + + return update_file(path, &e, sizeof(struct load_entry)); +} + +static int run_daemon(void) +{ + FILE *info; + uint32_t rxb, txb, rxp, txp; + uint32_t udp, tcp, other; + uint16_t rate; + uint8_t rssi, noise; + float lf1, lf5, lf15; + char line[1024]; + char ifname[16]; + int i; + void *iw; + struct sigaction sa; + + struct stat s; + const char *ipc = stat("/proc/net/nf_conntrack", &s) + ? "/proc/net/ip_conntrack" : "/proc/net/nf_conntrack"; + + switch (fork()) + { + case -1: + perror("fork()"); + return -1; + + case 0: + if (chdir("/") < 0) + { + perror("chdir()"); + exit(1); + } + + close(0); + close(1); + close(2); + break; + + default: + return 0; + } + + /* setup USR1 signal handler to reset timer */ + sa.sa_handler = reset_countdown; + sa.sa_flags = SA_RESTART; + sigemptyset(&sa.sa_mask); + sigaction(SIGUSR1, &sa, NULL); + + /* write pid */ + if (writepid()) + { + fprintf(stderr, "Failed to write pid file: %s\n", strerror(errno)); + return 1; + } + + /* initialize iwinfo */ + iw = iw_open(); + + /* go */ + for (reset_countdown(0); countdown >= 0; countdown--) + { + /* alter progname for ps, top */ + memset(progname, 0, prognamelen); + snprintf(progname, prognamelen, "luci-bwc %d", countdown); + + if ((info = fopen("/proc/net/dev", "r")) != NULL) + { + while (fgets(line, sizeof(line), info)) + { + if (strchr(line, '|')) + continue; + + if (sscanf(line, IF_SCAN_PATTERN, ifname, &rxb, &rxp, &txb, &txp)) + { + if (strncmp(ifname, "lo", sizeof(ifname))) + update_ifstat(ifname, rxb, rxp, txb, txp); + } + } + + fclose(info); + } + + if (iw) + { + for (i = 0; i < 5; i++) + { +#define iw_checkif(pattern) \ + do { \ + snprintf(ifname, sizeof(ifname), pattern, i); \ + if (iw_update(iw, ifname, &rate, &rssi, &noise)) \ + { \ + update_radiostat(ifname, rate, rssi, noise); \ + continue; \ + } \ + } while(0) + + iw_checkif("wlan%d"); + iw_checkif("ath%d"); + iw_checkif("wl%d"); + } + } + + if ((info = fopen(ipc, "r")) != NULL) + { + udp = 0; + tcp = 0; + other = 0; + + while (fgets(line, sizeof(line), info)) + { + if (strstr(line, "TIME_WAIT")) + continue; + + if ((strstr(line, "src=127.0.0.1 ") && strstr(line, "dst=127.0.0.1 ")) + || (strstr(line, "src=::1 ") && strstr(line, "dst=::1 "))) + continue; + + if (sscanf(line, "%*s %*d %s", ifname) || sscanf(line, "%s %*d", ifname)) + { + if (!strcmp(ifname, "tcp")) + tcp++; + else if (!strcmp(ifname, "udp")) + udp++; + else + other++; + } + } + + update_cnstat(udp, tcp, other); + + fclose(info); + } + + if ((info = fopen("/proc/loadavg", "r")) != NULL) + { + if (fscanf(info, LD_SCAN_PATTERN, &lf1, &lf5, &lf15)) + { + update_ldstat((uint16_t)(lf1 * 100), + (uint16_t)(lf5 * 100), + (uint16_t)(lf15 * 100)); + } + + fclose(info); + } + + sleep(STEP_TIME); + } + + unlink(PID_PATH); + + if (iw) + iw_close(iw); + + return 0; +} + +static void check_daemon(void) +{ + int pid; + + if ((pid = readpid()) < 0 || kill(pid, 0) < 0) + { + /* daemon ping failed, try to start it up */ + if (run_daemon()) + { + fprintf(stderr, + "Failed to ping daemon and unable to start it up: %s\n", + strerror(errno)); + + exit(1); + } + } + else if (kill(pid, SIGUSR1)) + { + fprintf(stderr, "Failed to send signal: %s\n", strerror(errno)); + exit(2); + } +} + +static int run_dump_ifname(const char *ifname) +{ + int i; + char path[1024]; + struct file_map m; + struct traffic_entry *e; + + check_daemon(); + snprintf(path, sizeof(path), DB_IF_FILE, ifname); + + if (mmap_file(path, sizeof(struct traffic_entry), &m)) + { + fprintf(stderr, "Failed to open %s: %s\n", path, strerror(errno)); + return 1; + } + + for (i = 0; i < m.size; i += sizeof(struct traffic_entry)) + { + e = (struct traffic_entry *) &m.mmap[i]; + + if (!e->time) + continue; + + printf("[ %u, %u, %" PRIu32 + ", %u, %u ]%s\n", + ntohl(e->time), + ntohl(e->rxb), ntohl(e->rxp), + ntohl(e->txb), ntohl(e->txp), + ((i + sizeof(struct traffic_entry)) < m.size) ? "," : ""); + } + + umap_file(&m); + + return 0; +} + +static int run_dump_radio(const char *ifname) +{ + int i; + char path[1024]; + struct file_map m; + struct radio_entry *e; + + check_daemon(); + snprintf(path, sizeof(path), DB_RD_FILE, ifname); + + if (mmap_file(path, sizeof(struct radio_entry), &m)) + { + fprintf(stderr, "Failed to open %s: %s\n", path, strerror(errno)); + return 1; + } + + for (i = 0; i < m.size; i += sizeof(struct radio_entry)) + { + e = (struct radio_entry *) &m.mmap[i]; + + if (!e->time) + continue; + + printf("[ %u, %d, %d, %d ]%s\n", + ntohl(e->time), + e->rate, e->rssi, e->noise, + ((i + sizeof(struct radio_entry)) < m.size) ? "," : ""); + } + + umap_file(&m); + + return 0; +} + +static int run_dump_conns(void) +{ + int i; + char path[1024]; + struct file_map m; + struct conn_entry *e; + + check_daemon(); + snprintf(path, sizeof(path), DB_CN_FILE); + + if (mmap_file(path, sizeof(struct conn_entry), &m)) + { + fprintf(stderr, "Failed to open %s: %s\n", path, strerror(errno)); + return 1; + } + + for (i = 0; i < m.size; i += sizeof(struct conn_entry)) + { + e = (struct conn_entry *) &m.mmap[i]; + + if (!e->time) + continue; + + printf("[ %u, %u, %u, %u ]%s\n", + ntohl(e->time), ntohl(e->udp), + ntohl(e->tcp), ntohl(e->other), + ((i + sizeof(struct conn_entry)) < m.size) ? "," : ""); + } + + umap_file(&m); + + return 0; +} + +static int run_dump_load(void) +{ + int i; + char path[1024]; + struct file_map m; + struct load_entry *e; + + check_daemon(); + snprintf(path, sizeof(path), DB_LD_FILE); + + if (mmap_file(path, sizeof(struct load_entry), &m)) + { + fprintf(stderr, "Failed to open %s: %s\n", path, strerror(errno)); + return 1; + } + + for (i = 0; i < m.size; i += sizeof(struct load_entry)) + { + e = (struct load_entry *) &m.mmap[i]; + + if (!e->time) + continue; + + printf("[ %u, %u, %u, %u ]%s\n", + ntohl(e->time), + ntohs(e->load1), ntohs(e->load5), ntohs(e->load15), + ((i + sizeof(struct load_entry)) < m.size) ? "," : ""); + } + + umap_file(&m); + + return 0; +} + + +int main(int argc, char *argv[]) +{ + int opt; + + progname = argv[0]; + prognamelen = -1; + + for (opt = 0; opt < argc; opt++) + prognamelen += 1 + strlen(argv[opt]); + + while ((opt = getopt(argc, argv, "t:i:r:cl")) > -1) + { + switch (opt) + { + case 't': + timeout = atoi(optarg); + break; + + case 'i': + if (optarg) + return run_dump_ifname(optarg); + break; + + case 'r': + if (optarg) + return run_dump_radio(optarg); + break; + + case 'c': + return run_dump_conns(); + + case 'l': + return run_dump_load(); + + default: + break; + } + } + + fprintf(stderr, + "Usage:\n" + " %s [-t timeout] -i ifname\n" + " %s [-t timeout] -r radiodev\n" + " %s [-t timeout] -c\n" + " %s [-t timeout] -l\n", + argv[0], argv[0], argv[0], argv[0] + ); + + return 1; +} -- cgit v1.2.3