3 local json = require "luci.jsonc"
4 local fs = require "nixio.fs"
6 local function readfile(path)
7 local s = fs.readfile(path)
8 return s and (s:gsub("^%s+", ""):gsub("%s+$", ""))
13 args = { name = "name" },
15 local sys = require "luci.sys"
16 local _, name, scripts = nil, nil, {}
17 for _, name in ipairs(args.name and { args.name } or sys.init.names()) do
18 local index = sys.init.index(name)
20 scripts[name] = { index = index, enabled = sys.init.enabled(name) }
22 return { error = "No such init script" }
25 return { result = scripts }
30 args = { name = "name", action = "action" },
32 local sys = require "luci.sys"
33 if type(sys.init[args.action]) ~= "function" then
34 return { error = "Invalid action" }
36 return { result = sys.init[args.action](args.name) }
42 return { localtime = os.time() }
47 args = { localtime = 0 },
49 local sys = require "luci.sys"
50 local date = os.date("*t", args.localtime)
52 sys.call("date -s '%04d-%02d-%02d %02d:%02d:%02d' >/dev/null" %{ date.year, date.month, date.day, date.hour, date.min, date.sec })
53 sys.call("/etc/init.d/sysfixtime restart >/dev/null")
55 return { localtime = args.localtime }
61 local util = require "luci.util"
62 local zones = require "luci.sys.zoneinfo"
64 local tz = readfile("/etc/TZ")
65 local res = util.ubus("uci", "get", {
67 section = "@system[0]",
73 for _, zone in ipairs(zones.TZ) do
76 active = (res and res.value == zone[1]) and true or nil
79 return { result = result }
85 local iter = fs.dir("/sys/class/leds")
93 result[led] = { triggers = {} }
95 s = readfile("/sys/class/leds/"..led.."/trigger")
96 for s in (s or ""):gmatch("%S+") do
97 m = s:match("^%[(.+)%]$")
98 result[led].triggers[#result[led].triggers+1] = m or s
99 result[led].active_trigger = m or result[led].active_trigger
102 s = readfile("/sys/class/leds/"..led.."/brightness")
104 result[led].brightness = tonumber(s)
107 s = readfile("/sys/class/leds/"..led.."/max_brightness")
109 result[led].max_brightness = tonumber(s)
120 local fs = require "nixio.fs"
121 local iter = fs.glob("/sys/bus/usb/devices/[0-9]*/manufacturer")
129 local id = p:match("%d+-%d+")
131 result.devices[#result.devices+1] = {
133 vid = readfile("/sys/bus/usb/devices/"..id.."/idVendor"),
134 pid = readfile("/sys/bus/usb/devices/"..id.."/idProduct"),
135 vendor = readfile("/sys/bus/usb/devices/"..id.."/manufacturer"),
136 product = readfile("/sys/bus/usb/devices/"..id.."/product"),
137 speed = tonumber((readfile("/sys/bus/usb/devices/"..id.."/product")))
142 iter = fs.glob("/sys/bus/usb/devices/*/usb[0-9]*-port[0-9]*")
149 local bus, port = p:match("usb(%d+)-port(%d+)")
151 result.ports[#result.ports+1] = {
153 port = tonumber(port)
164 return { result = nixio.getifaddrs() }
170 local sys = require "luci.sys"
171 return sys.net.host_hints()
177 local fp = io.open('/var/hosts/odhcpd')
180 for line in fp:lines() do
181 local dev, duid, name = string.match(line, '# (%S+)%s+(%S+)%s+%d+%s+(%S+)')
182 if dev and duid and name then
184 name = (name ~= "-") and name or nil,
196 args = { family = 0 },
197 call = function(args)
198 local s = require "luci.tools.status"
200 if args.family == 4 then
201 return { dhcp_leases = s.dhcp_leases() }
202 elseif args.family == 6 then
203 return { dhcp6_leases = s.dhcp6_leases() }
206 dhcp_leases = s.dhcp_leases(),
207 dhcp6_leases = s.dhcp6_leases()
214 call = function(args)
215 local dir = fs.dir("/sys/class/net")
220 if not result[dev] then
221 result[dev] = { name = dev }
224 if fs.access("/sys/class/net/"..dev.."/master") then
225 local brname = fs.basename(fs.readlink("/sys/class/net/"..dev.."/master"))
226 if not result[brname] then
227 result[brname] = { name = brname }
230 if not result[brname].ports then
231 result[brname].ports = { }
234 result[brname].ports[#result[brname].ports+1] = dev
235 elseif fs.access("/sys/class/net/"..dev.."/bridge") then
236 if not result[dev].ports then
237 result[dev].ports = { }
240 result[dev].id = readfile("/sys/class/net/"..dev.."/bridge/bridge_id")
241 result[dev].stp = (readfile("/sys/class/net/"..dev.."/bridge/stp_state") ~= "0")
242 result[dev].bridge = true
245 local opr = readfile("/sys/class/net/"..dev.."/operstate")
247 result[dev].up = (opr == "up" or opr == "unknown")
248 result[dev].type = tonumber(readfile("/sys/class/net/"..dev.."/type"))
249 result[dev].name = dev
251 local mtu = tonumber(readfile("/sys/class/net/"..dev.."/mtu"))
252 if mtu and mtu > 0 then
253 result[dev].mtu = mtu
256 local qlen = tonumber(readfile("/sys/class/net/"..dev.."/tx_queue_len"))
257 if qlen and qlen > 0 then
258 result[dev].qlen = qlen
261 local master = fs.readlink("/sys/class/net/"..dev.."/master")
263 result[dev].master = fs.basename(master)
266 local mac = readfile("/sys/class/net/"..dev.."/address")
267 if mac and #mac == 17 then
268 result[dev].mac = mac
277 call = function(args)
278 local jsc = require "luci.jsonc"
279 return jsc.parse(fs.readfile("/etc/board.json") or "")
285 local fs = require "nixio.fs"
286 return { offload_support = not not fs.access("/sys/module/xt_FLOWOFFLOAD/refcnt") }
290 conntrack_helpers = {
292 local fd = io.open("/usr/share/fw3/helpers.conf", "r")
302 if line:match("^%s*config%s") then
308 local opt, val = line:match("^%s*option%s+(%S+)%s+(%S.*)$")
310 opt = opt:gsub("^'(.+)'$", "%1"):gsub('^"(.+)"$', "%1")
311 val = val:gsub("^'(.+)'$", "%1"):gsub('^"(.+)"$', "%1")
321 return { helpers = rv }
326 local function parseInput()
327 local parse = json.new()
331 local chunk = io.read(4096)
334 elseif not done and not err then
335 done, err = parse:parse(chunk)
340 print(json.stringify({ error = err or "Incomplete input" }))
347 local function validateArgs(func, uargs)
348 local method = methods[func]
350 print(json.stringify({ error = "Method not found" }))
354 if type(uargs) ~= "table" then
355 print(json.stringify({ error = "Invalid arguments" }))
359 uargs.ubus_rpc_session = nil
362 local margs = method.args or {}
363 for k, v in pairs(uargs) do
364 if margs[k] == nil or
365 (v ~= nil and type(v) ~= type(margs[k]))
367 print(json.stringify({ error = "Invalid arguments" }))
375 if arg[1] == "list" then
376 local _, method, rv = nil, nil, {}
377 for _, method in pairs(methods) do rv[_] = method.args or {} end
378 print((json.stringify(rv):gsub(":%[%]", ":{}")))
379 elseif arg[1] == "call" then
380 local args = parseInput()
381 local method = validateArgs(arg[2], args)
382 local result, code = method.call(args)
383 print((json.stringify(result):gsub("^%[%]$", "{}")))