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