Merge pull request #1735 from sumpfralle/olsr-jsoninfo-parser-handle-empty-result
[oweals/luci.git] / applications / luci-app-unbound / luasrc / model / cbi / unbound / configure.lua
1 -- Copyright 2008 Steven Barth <steven@midlink.org>
2 -- Copyright 2016 Eric Luehrsen <ericluehrsen@gmail.com>
3 -- Copyright 2016 Dan Luedtke <mail@danrl.com>
4 -- Licensed to the public under the Apache License 2.0.
5
6 local m1, s1
7 local ena, mcf, lci, lsv
8 local rlh, rpv, vld, nvd, eds, prt, tlm
9 local ctl, dlk, dom, dty, lfq, wfq, exa
10 local dp6, d64, pfx, qry, qrs
11 local pro, tgr, rsc, rsn, ag2, stt
12 local rpn, din, ath
13
14 local ut = require "luci.util"
15 local sy = require "luci.sys"
16 local ht = require "luci.http"
17 local ds = require "luci.dispatcher"
18 local ucl = luci.model.uci.cursor()
19 local valman = ucl:get_first("unbound", "unbound", "manual_conf")
20 local dhcplk = ucl:get_first("unbound", "unbound", "dhcp_link")
21 local lstrig = ucl:get_first("dhcp", "odhcpd", "leasetrigger")
22
23 m1 = Map("unbound")
24 s1 = m1:section(TypedSection, "unbound", translate("Recursive DNS"),
25     translatef("Unbound <a href=\"%s\" target=\"_blank\">(NLnet Labs)</a>"
26     .. " is a validating, recursive, and caching DNS resolver"
27     .. " <a href=\"%s\" target=\"_blank\">(help)</a>.",
28     "https://www.unbound.net/",
29     "https://github.com/openwrt/packages/blob/master/net/unbound/files/README.md"))
30
31 s1.addremove = false
32 s1.anonymous = true
33
34 if (valman == "0") and (dhcplk == "odhcpd") and (lstrig ~= "/usr/lib/unbound/odhcpd.sh") then
35     m1.message = translatef( "Note: local DNS is configured to look at odhpcd, "
36     .. "but odhpcd UCI lease trigger is incorrectly set: ")
37     .. "dhcp.odhcpd.leasetrigger='" .. lstrig .. "'"
38 end
39
40 --LuCI, Unbound, or Not
41 s1:tab("basic", translate("Basic"))
42
43
44 if (valman == "0") then
45     -- Not in manual configuration mode; show UCI
46     s1:tab("advanced", translate("Advanced"))
47     s1:tab("DHCP", translate("DHCP"))
48     s1:tab("resource", translate("Resource"))
49 end
50
51
52 --Basic Tab, unconditional pieces
53 ena = s1:taboption("basic", Flag, "enabled", translate("Enable Unbound"),
54     translate("Enable the initialization scripts for Unbound"))
55 ena.rmempty = false
56
57 mcf = s1:taboption("basic", Flag, "manual_conf", translate("Manual Conf"),
58     translate("Skip UCI and use /etc/unbound/unbound.conf"))
59 mcf.rmempty = false
60
61
62 if (valman == "0") then
63     -- Not in manual configuration mode; show UCI
64     --Basic Tab
65     lsv = s1:taboption("basic", Flag, "localservice",
66         translate("Local Service"),
67         translate("Accept queries only from local subnets"))
68     lsv.rmempty = false
69
70     vld = s1:taboption("basic", Flag, "validator",
71         translate("Enable DNSSEC"),
72         translate("Enable the DNSSEC validator module"))
73     vld.rmempty = false
74
75     nvd = s1:taboption("basic", Flag, "validator_ntp",
76         translate("DNSSEC NTP Fix"),
77         translate("Break the loop where DNSSEC needs NTP and NTP needs DNS"))
78     nvd.optional = true
79     nvd:depends("validator", true)
80
81     prt = s1:taboption("basic", Value, "listen_port",
82         translate("Listening Port"),
83         translate("Choose Unbounds listening port"))
84     prt.datatype = "port"
85     prt.placeholder = "53"
86
87     --Avanced Tab
88     rlh = s1:taboption("advanced", Flag, "rebind_localhost",
89         translate("Filter Localhost Rebind"),
90         translate("Protect against upstream response of 127.0.0.0/8"))
91     rlh.rmempty = false
92
93     rpv = s1:taboption("advanced", ListValue, "rebind_protection",
94         translate("Filter Private Rebind"),
95         translate("Protect against upstream responses within local subnets"))
96     rpv:value("0", translate("No Filter"))
97     rpv:value("1", translate("Filter Private Address"))
98     rpv:value("2", translate("Filter Entire Subnet"))
99     rpv.rmempty = false
100
101     d64 = s1:taboption("advanced", Flag, "dns64", translate("Enable DNS64"),
102         translate("Enable the DNS64 module"))
103     d64.rmempty = false
104
105     pfx = s1:taboption("advanced", Value, "dns64_prefix",
106         translate("DNS64 Prefix"),
107         translate("Prefix for generated DNS64 addresses"))
108     pfx.datatype = "ip6addr"
109     pfx.placeholder = "64:ff9b::/96"
110     pfx.optional = true
111     pfx:depends("dns64", true)
112
113     din = s1:taboption("advanced", DynamicList, "domain_insecure",
114         translate("Domain Insecure"),
115         translate("List domains to bypass checks of DNSSEC"))
116     din:depends("validator", true)
117
118     ag2 = s1:taboption("advanced", Value, "root_age",
119         translate("Root DSKEY Age"),
120         translate("Limit days between RFC5011 copies to reduce flash writes"))
121     ag2.datatype = "and(uinteger,min(1),max(99))"
122     ag2:value("3", "3")
123     ag2:value("9", "9 ("..translate("default")..")")
124     ag2:value("12", "12")
125     ag2:value("24", "24")
126     ag2:value("99", "99 ("..translate("never")..")")
127
128     tgr = s1:taboption("advanced", Value, "trigger_interface",
129         translate("Trigger Networks"),
130         translate("Networks that may trigger Unbound to reload (avoid wan6)"))
131     tgr.template = "cbi/network_netlist"
132     tgr.widget = "checkbox"
133     tgr.rmempty = true
134     tgr.cast = "string"
135     tgr.nocreate = true
136
137     --DHCP Tab
138     dlk = s1:taboption("DHCP", ListValue, "dhcp_link",
139         translate("DHCP Link"),
140         translate("Link to supported programs to load DHCP into DNS"))
141     dlk:value("none", translate("No Link"))
142     dlk:value("dnsmasq", "dnsmasq")
143     dlk:value("odhcpd", "odhcpd")
144     dlk.rmempty = false
145
146     dp6 = s1:taboption("DHCP", Flag, "dhcp4_slaac6",
147         translate("DHCPv4 to SLAAC"),
148         translate("Use DHCPv4 MAC to discover IP6 hosts SLAAC (EUI64)"))
149     dp6.optional = true
150     dp6:depends("dhcp_link", "odhcpd")
151
152     dom = s1:taboption("DHCP", Value, "domain",
153         translate("Local Domain"),
154         translate("Domain suffix for this router and DHCP clients"))
155     dom.placeholder = "lan"
156     dom.optional = true
157     dom:depends("dhcp_link", "none")
158     dom:depends("dhcp_link", "odhcpd")
159
160     dty = s1:taboption("DHCP", ListValue, "domain_type",
161         translate("Local Domain Type"),
162         translate("How to treat queries of this local domain"))
163     dty.optional = true
164     dty:value("deny", translate("Denied (nxdomain)"))
165     dty:value("refuse", translate("Refused"))
166     dty:value("static", translate("Static (local only)"))
167     dty:value("transparent", translate("Transparent (local/global)"))
168     dty:depends("dhcp_link", "none")
169     dty:depends("dhcp_link", "odhcpd")
170
171     lfq = s1:taboption("DHCP", ListValue, "add_local_fqdn",
172         translate("LAN DNS"),
173         translate("How to enter the LAN or local network router in DNS"))
174     lfq.optional = true
175     lfq:value("0", translate("No Entry"))
176     lfq:value("1", translate("Hostname, Primary Address"))
177     lfq:value("2", translate("Hostname, All Addresses"))
178     lfq:value("3", translate("Host FQDN, All Addresses"))
179     lfq:value("4", translate("Interface FQDN, All Addresses"))
180     lfq:depends("dhcp_link", "none")
181     lfq:depends("dhcp_link", "odhcpd")
182
183     wfq = s1:taboption("DHCP", ListValue, "add_wan_fqdn",
184         translate("WAN DNS"),
185         translate("Override the WAN side router entry in DNS"))
186     wfq.optional = true
187     wfq:value("0", translate("Use Upstream"))
188     wfq:value("1", translate("Hostname, Primary Address"))
189     wfq:value("2", translate("Hostname, All Addresses"))
190     wfq:value("3", translate("Host FQDN, All Addresses"))
191     wfq:value("4", translate("Interface FQDN, All Addresses"))
192     wfq:depends("dhcp_link", "none")
193     wfq:depends("dhcp_link", "odhcpd")
194
195     exa = s1:taboption("DHCP", ListValue, "add_extra_dns",
196         translate("Extra DNS"),
197         translate("Use extra DNS entries found in /etc/config/dhcp"))
198     exa.optional = true
199     exa:value("0", translate("Ignore"))
200     exa:value("1", translate("Host Records"))
201     exa:value("2", translate("Host/MX/SRV RR"))
202     exa:value("3", translate("Host/MX/SRV/CNAME RR"))
203     exa:depends("dhcp_link", "none")
204     exa:depends("dhcp_link", "odhcpd")
205
206     --TODO: dnsmasq needs to not reference resolve-file and get off port 53.
207
208     --Resource Tuning Tab
209     ctl = s1:taboption("resource", ListValue, "unbound_control",
210         translate("Unbound Control App"),
211         translate("Enable access for unbound-control"))
212     ctl.rmempty = false
213     ctl:value("0", translate("No Remote Control"))
214     ctl:value("1", translate("Local Host, No Encryption"))
215     ctl:value("2", translate("Local Host, Encrypted"))
216     ctl:value("3", translate("Local Subnet, Encrypted"))
217     ctl:value("4", translate("Local Subnet, Static Encryption"))
218
219     pro = s1:taboption("resource", ListValue, "protocol",
220         translate("Recursion Protocol"),
221         translate("Chose the IP versions used upstream and downstream"))
222     pro:value("default", translate("Default"))
223     pro:value("ip4_only", translate("IP4 Only"))
224     pro:value("ip6_local", translate("IP4 All and IP6 Local"))
225     pro:value("ip6_only", translate("IP6 Only*"))
226     pro:value("ip6_prefer", translate("IP6 Preferred"))
227     pro:value("mixed", translate("IP4 and IP6"))
228     pro.rmempty = false
229
230     rsc = s1:taboption("resource", ListValue, "resource",
231         translate("Memory Resource"),
232         translate("Use menu System/Processes to observe any memory growth"))
233     rsc:value("default", translate("Default"))
234     rsc:value("tiny", translate("Tiny"))
235     rsc:value("small", translate("Small"))
236     rsc:value("medium", translate("Medium"))
237     rsc:value("large", translate("Large"))
238     rsc.rmempty = false
239
240     rsn = s1:taboption("resource", ListValue, "recursion",
241         translate("Recursion Strength"),
242         translate("Recursion activity affects memory growth and CPU load"))
243     rsn:value("default", translate("Default"))
244     rsn:value("passive", translate("Passive"))
245     rsn:value("aggressive", translate("Aggressive"))
246     rsn.rmempty = false
247
248     qry = s1:taboption("resource", Flag, "query_minimize",
249         translate("Query Minimize"),
250         translate("Break down query components for limited added privacy"))
251     qry.optional = true
252     qry:depends("recursion", "passive")
253     qry:depends("recursion", "aggressive")
254
255     qrs = s1:taboption("resource", Flag, "query_min_strict",
256         translate("Strict Minimize"),
257         translate("Strict version of 'query minimize' but it can break DNS"))
258     qrs.optional = true
259     qrs:depends("query_minimize", true)
260
261     eds = s1:taboption("resource", Value, "edns_size",
262         translate("EDNS Size"),
263         translate("Limit extended DNS packet size"))
264     eds.datatype = "and(uinteger,min(512),max(4096))"
265     eds.placeholder = "1280"
266
267     tlm = s1:taboption("resource", Value, "ttl_min",
268         translate("TTL Minimum"),
269         translate("Prevent excessively short cache periods"))
270     tlm.datatype = "and(uinteger,min(0),max(1200))"
271     tlm.placeholder = "120"
272
273     stt = s1:taboption("resource", Flag, "extended_stats",
274         translate("Extended Statistics"),
275         translate("Extended statistics are printed from unbound-control"))
276     stt.rmempty = false
277
278 else
279     ag2 = s1:taboption("basic", Value, "root_age",
280         translate("Root DSKEY Age"),
281         translate("Limit days between RFC5011 copies to reduce flash writes"))
282     ag2.datatype = "and(uinteger,min(1),max(99))"
283     ag2:value("3", "3")
284     ag2:value("9", "9 ("..translate("default")..")")
285     ag2:value("12", "12")
286     ag2:value("24", "24")
287     ag2:value("99", "99 ("..translate("never")..")")
288
289     tgr = s1:taboption("basic", Value, "trigger_interface",
290         translate("Trigger Networks"),
291         translate("Networks that may trigger Unbound to reload (avoid wan6)"))
292     tgr.template = "cbi/network_netlist"
293     tgr.widget = "checkbox"
294     tgr.rmempty = true
295     tgr.cast = "string"
296     tgr.nocreate = true
297 end
298
299
300 function ena.cfgvalue(self, section)
301     return sy.init.enabled("unbound") and self.enabled or self.disabled
302 end
303
304
305 function ena.write(self, section, value)
306     if (value == "1") then
307         sy.init.enable("unbound")
308         sy.call("/etc/init.d/unbound start >/dev/null 2>&1")
309
310     else
311         sy.call("/etc/init.d/unbound stop >/dev/null 2>&1")
312         sy.init.disable("unbound")
313     end
314
315
316     return Flag.write(self, section, value)
317 end
318
319
320 function m1.on_commit(self)
321     if sy.init.enabled("unbound") then
322         -- Restart Unbound with configuration
323         sy.call("/etc/init.d/unbound restart >/dev/null 2>&1")
324
325     else
326         sy.call("/etc/init.d/unbound stop >/dev/null 2>&1")
327     end
328 end
329
330
331 function m1.on_apply(self)
332     -- reload the page because some options hide
333     ht.redirect(ds.build_url("admin", "services", "unbound", "configure"))
334 end
335
336
337 return m1
338