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