zones.lua 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. -- Copyright 2018 Eric Luehrsen <ericluehrsen@gmail.com>
  2. -- Licensed to the public under the Apache License 2.0.
  3. local m5, s5
  4. local ztype, zones, servers, fallback, enabled
  5. local fs = require "nixio.fs"
  6. local ut = require "luci.util"
  7. local sy = require "luci.sys"
  8. local ds = require "luci.dispatcher"
  9. local resolvfile = "/tmp/resolv.conf.auto"
  10. local logerr = ut.exec("logread -e 'unbound.*error.*ssl library'")
  11. m5 = Map("unbound")
  12. s5 = m5:section(TypedSection, "zone", "Zones",
  13. translatef("Organize directed forward, stub, and authoritative zones"
  14. .. " <a href=\"%s\" target=\"_blank\">(help)</a>.",
  15. "https://www.unbound.net/",
  16. "https://github.com/openwrt/packages/blob/master/net/unbound/files/README.md"))
  17. s5.addremove = true
  18. s5.anonymous = true
  19. s5.sortable = true
  20. s5.template = "cbi/tblsection"
  21. s5.extedit = ds.build_url("admin/services/unbound/zones/%s")
  22. ztype = s5:option(DummyValue, "DummyType", translate("Type"))
  23. ztype.rawhtml = true
  24. zones = s5:option(DummyValue, "DummyZones", translate("Zones"))
  25. zones.rawhtml = true
  26. servers = s5:option(DummyValue, "DummyServers", translate("Servers"))
  27. servers.rawhtml = true
  28. fallback = s5:option(Flag, "fallback", translate("Fallback"))
  29. fallback.rmempty = false
  30. enabled = s5:option(Flag, "enabled", translate("Enable"))
  31. enabled.rmempty = false
  32. if logerr and (#logerr > 0) then
  33. logerr = logerr:sub((1 + #logerr - math.min(#logerr, 250)), #logerr)
  34. m5.message = translatef( "Note: SSL/TLS library is missing an API. "
  35. .. "Please review syslog. >> logread ... " .. logerr )
  36. end
  37. function s5.create(self, section)
  38. created = TypedSection.create(self, section)
  39. end
  40. function s5.parse(self, ...)
  41. TypedSection.parse(self, ...)
  42. end
  43. function ztype.cfgvalue(self, s)
  44. -- Format a meaningful tile for the Zone Type column
  45. local itxt = self.map:get(s, "zone_type")
  46. local itls = self.map:get(s, "tls_upstream")
  47. if itxt and itxt:match("forward") then
  48. if itls and (itls == "1") then
  49. return translate("Forward TLS")
  50. else
  51. return translate("Forward")
  52. end
  53. elseif itxt and itxt:match("stub") then
  54. return translate("Recurse")
  55. elseif itxt and itxt:match("auth") then
  56. return translate("AXFR")
  57. else
  58. return translate("Undefined")
  59. end
  60. end
  61. function zones.cfgvalue(self, s)
  62. -- Format a meaningful sentence for the Zones viewed column
  63. local xtxt, otxt
  64. local itxt = self.map:get(s, "zone_name")
  65. local itype = self.map:get(s, "zone_type")
  66. for xtxt in ut.imatch(itxt) do
  67. if (xtxt == ".") then
  68. -- zone_name lists
  69. xtxt = translate("(root)")
  70. end
  71. if otxt and (#otxt > 0) then
  72. otxt = otxt .. ", <var>%s</var>" % xtxt
  73. else
  74. otxt = "<var>%s</var>" % xtxt
  75. end
  76. end
  77. if otxt and (#otxt > 0) then
  78. if itype and itype:match("forward") then
  79. -- from zone_type create a readable hint for the action
  80. otxt = translate("accept upstream results for ") .. otxt
  81. elseif itype and itype:match("stub") then
  82. otxt = translate("select recursion for ") .. otxt
  83. elseif itype and itype:match("auth") then
  84. otxt = translate("prefetch zone files for ") .. otxt
  85. else
  86. otxt = translate("unknown action for ") .. otxt
  87. end
  88. return otxt
  89. else
  90. return "(empty)"
  91. end
  92. end
  93. function servers.cfgvalue(self, s)
  94. -- Format a meaningful sentence for the Servers (and URL) column
  95. local xtxt, otxt, rtxt, found
  96. local itxt = self.map:get(s, "server")
  97. local iurl = self.map:get(s, "url_dir")
  98. local itype = self.map:get(s, "zone_type")
  99. local itls = self.map:get(s, "tls_upstream")
  100. local iidx = self.map:get(s, "tls_index")
  101. local irslv = self.map:get(s, "resolv_conf")
  102. for xtxt in ut.imatch(itxt) do
  103. if otxt and (#otxt > 0) then
  104. -- bundle and make pretty the server list
  105. otxt = otxt .. ", <var>%s</var>" % xtxt
  106. else
  107. otxt = "<var>%s</var>" % xtxt
  108. end
  109. end
  110. if otxt and (#otxt > 0) then
  111. otxt = translate("use nameservers ") .. otxt
  112. end
  113. if otxt and (#otxt > 0)
  114. and itls and (itls == "1")
  115. and iidx and (#iidx > 0) then
  116. -- show TLS certificate name index if provided
  117. otxt = otxt .. translatef(
  118. " with default certificate for <var>%s</var>", iidx)
  119. end
  120. if iurl and (#iurl > 0) and itype and itype:match("auth") then
  121. if otxt and (#otxt > 0) then
  122. -- include optional URL filed for auth-zone: type
  123. otxt = otxt .. translatef(", and try <var>%s</var>", iurl)
  124. else
  125. otxt = translatef("download from <var>%s</var>", iurl)
  126. end
  127. end
  128. if irslv and (irslv == "1") and itype and itype:match("forward") then
  129. for xtxt in ut.imatch(fs.readfile(resolvfile)) do
  130. if xtxt:match("nameserver") then
  131. found = true
  132. elseif (found == true) then
  133. if rtxt and (#rtxt > 0) then
  134. -- fetch name servers from resolv.conf
  135. rtxt = rtxt .. ", <var>%s</var>" % xtxt
  136. else
  137. rtxt = "<var>%s</var>" % xtxt
  138. end
  139. found = false
  140. end
  141. end
  142. if otxt and (#otxt > 0) and rtxt and (#rtxt > 0) then
  143. otxt = otxt .. translatef(
  144. ", and <var>%s</var> entries ", resolvfile) .. rtxt
  145. elseif rtxt and (#rtxt > 0) then
  146. otxt = translatef(
  147. "use <var>%s</var> nameservers ", resolvfile) .. rtxt
  148. end
  149. end
  150. if otxt and (#otxt > 0) then
  151. return otxt
  152. else
  153. return "(empty)"
  154. end
  155. end
  156. function m5.on_commit(self)
  157. if sy.init.enabled("unbound") then
  158. -- Restart Unbound with configuration
  159. sy.call("/etc/init.d/unbound restart >/dev/null 2>&1")
  160. else
  161. sy.call("/etc/init.d/unbound stop >/dev/null 2>&1")
  162. end
  163. end
  164. return m5