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