2 LuCI - Lua Configuration Interface
4 Copyright 2008 Steven Barth <steven@midlink.org>
5 Copyright 2008 Jo-Philipp Wich <xm@leipzig.freifunk.net>
6 Copyright 2014 Christian Schoenebeck <christian dot schoenebeck at gmail dot com>
8 Licensed under the Apache License, Version 2.0 (the "License");
9 you may not use this file except in compliance with the License.
10 You may obtain a copy of the License at
12 http://www.apache.org/licenses/LICENSE-2.0
17 module("luci.controller.ddns", package.seeall)
23 require "luci.model.uci"
24 require "luci.dispatcher"
25 require "luci.tools.ddns"
28 -- no configuration file, don't start
29 if not nixio.fs.access("/etc/config/ddns") then
32 -- ddns-scripts 1.0.0 installed, run old luci app
33 if not nixio.fs.access("/usr/lib/ddns/services_ipv6")
34 or nixio.fs.access("/usr/lib/ddns/url_escape.sed") then
36 page = entry({"admin", "services", "ddns"}, cbi("ddns/ddns"), _("Dynamic DNS"), 60)
38 page = entry({"mini", "network", "ddns"}, cbi("ddns/ddns", {autoapply=true}), _("Dynamic DNS"), 60)
40 -- it looks like ddns-scripts 2.x.x are installed
42 entry( {"admin", "services", "ddns"}, cbi("ddns/overview"), _("Dynamic DNS"), 59)
43 entry( {"admin", "services", "ddns", "detail"}, cbi("ddns/detail"), nil ).leaf = true
44 entry( {"admin", "services", "ddns", "hints"}, cbi("ddns/hints",
45 {hideapplybtn=true, hidesavebtn=true, hideresetbtn=true}), nil ).leaf = true
46 entry( {"admin", "services", "ddns", "logview"}, call("logread") ).leaf = true
47 entry( {"admin", "services", "ddns", "status"}, call("status") ).leaf = true
48 entry( {"admin", "services", "ddns", "startstop"}, call("startstop") ).leaf = true
52 -- function to read all sections status and return data array
53 function _get_status()
54 local uci = luci.model.uci.cursor()
55 local service = luci.sys.init.enabled("ddns") and 1 or 0
56 local url_start = luci.dispatcher.build_url("admin", "system", "startup")
57 local data = {} -- Array to transfer data to javascript
59 -- read application settings
60 local date_format = uci:get("ddns", "global", "date_format") or "%F %R"
61 local run_dir = uci:get("ddns", "global", "run_dir") or "/var/run/ddns"
64 enabled = service, -- service enabled
65 url_up = url_start -- link to enable DDS (System-Startup)
68 uci:foreach("ddns", "service", function (s)
70 -- Get section we are looking at
72 local section = s[".name"]
73 local enabled = tonumber(s["enabled"]) or 0
74 local datelast = "_empty_" -- formated date of last update
75 local datenext = "_empty_" -- formated date of next update
78 local force_seconds = luci.tools.ddns.calc_seconds(
79 tonumber(s["force_interval"]) or 72 ,
80 s["force_unit"] or "hours" )
81 -- get/validate pid and last update
82 local pid = luci.tools.ddns.get_pid(section, run_dir)
83 local uptime = luci.sys.uptime()
84 local lasttime = tonumber(nixio.fs.readfile("%s/%s.update" % { run_dir, section } ) or 0 )
85 if lasttime > uptime then -- /var might not be linked to /tmp
86 lasttime = 0 -- and/or not cleared on reboot
89 -- no last update happen
93 -- we read last update
96 -- sys.epoch - sys uptime + lastupdate(uptime)
97 local epoch = os.time() - uptime + lasttime
98 -- use linux date to convert epoch
99 datelast = luci.sys.exec([[/bin/date -d @]] .. epoch .. [[ +']] .. date_format .. [[']])
100 -- calc and fill next update
101 datenext = luci.sys.exec([[/bin/date -d @]] .. (epoch + force_seconds) ..
102 [[ +']] .. date_format .. [[']])
105 -- process running but update needs to happen
106 -- problems it force_seconds > uptime
107 force_seconds = (force_seconds > uptime) and uptime or force_seconds
108 if pid > 0 and ( lasttime + force_seconds - uptime ) <= 0 then
109 datenext = "_verify_"
112 elseif force_seconds == 0 then
113 datenext = "_runonce_"
115 -- no process running and NOT enabled
116 elseif pid == 0 and enabled == 0 then
117 datenext = "_disabled_"
119 -- no process running and NOT
120 elseif pid == 0 and enabled ~= 0 then
121 datenext = "_stopped_"
124 -- get/set monitored interface and IP version
125 local iface = s["interface"] or "_nonet_"
126 local use_ipv6 = tonumber(s["use_ipv6"]) or 0
127 if iface ~= "_nonet_" then
128 local ipv = (use_ipv6 == 1) and "IPv6" or "IPv4"
129 iface = ipv .. " / " .. iface
132 -- try to get registered IP
133 local domain = s["domain"] or "_nodomain_"
134 local dnsserver = s["dns_server"] or ""
135 local force_ipversion = tonumber(s["force_ipversion"] or 0)
136 local force_dnstcp = tonumber(s["force_dnstcp"] or 0)
137 local command = [[/usr/lib/ddns/dynamic_dns_lucihelper.sh]]
138 command = command .. [[ get_registered_ip ]] .. domain .. [[ ]] .. use_ipv6 ..
139 [[ ]] .. force_ipversion .. [[ ]] .. force_dnstcp .. [[ ]] .. dnsserver
140 local reg_ip = luci.sys.exec(command)
145 -- fill transfer array
163 -- called by XHR.get from detail_logview.htm
164 function logread(section)
165 -- read application settings
166 local uci = luci.model.uci.cursor()
167 local log_dir = uci:get("ddns", "global", "log_dir") or "/var/log/ddns"
168 local lfile=log_dir .. "/" .. section .. ".log"
170 local ldata=nixio.fs.readfile(lfile)
171 if not ldata or #ldata == 0 then
174 luci.http.write(ldata)
177 -- called by XHR.get from overview_status.htm
178 function startstop(section, enabled)
179 -- Array to transfer data to javascript
181 -- read application settings
182 local uci = luci.model.uci.cursor()
183 local run_dir = uci:get("ddns", "global", "run_dir") or "/var/run/ddns"
185 -- if process running we want to stop and return
186 local pid = luci.tools.ddns.get_pid(section, run_dir)
188 os.execute ([[kill -9 %s]] % pid)
189 nixio.nanosleep(2) -- 2 second "show time"
190 -- status changed so return full status
192 luci.http.prepare_content("application/json")
193 luci.http.write_json(data)
197 -- read uncommited changes
198 -- we don't save and commit data from other section or other options
199 -- only enabled will be done
201 local changed = uci:changes("ddns")
202 for k_config, v_section in pairs(changed) do
203 -- security check because uci.changes only gets our config
204 if k_config ~= "ddns" then
208 for k_section, v_option in pairs(v_section) do
209 -- check if only section of button was changed
210 if k_section ~= section then
214 for k_option, v_value in pairs(v_option) do
215 -- check if only enabled was changed
216 if k_option ~= "enabled" then
225 -- we can not execute because other
226 -- uncommited changes pending, so exit here
228 luci.http.write("_uncommited_")
233 uci:set("ddns", section, "enabled", ( (enabled == "true") and "1" or "0") )
238 -- start dynamic_dns_updater.sh script
239 os.execute ([[/usr/lib/ddns/dynamic_dns_updater.sh %s 0 > /dev/null 2>&1 &]] % section)
240 nixio.nanosleep(3) -- 3 seconds "show time"
242 -- status changed so return full status
244 luci.http.prepare_content("application/json")
245 luci.http.write_json(data)
248 -- called by XHR.poll from overview_status.htm
250 local data = _get_status()
251 luci.http.prepare_content("application/json")
252 luci.http.write_json(data)