dhcp.lua 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307
  1. -- Copyright 2008 Steven Barth <steven@midlink.org>
  2. -- Licensed to the public under the Apache License 2.0.
  3. local ipc = require "luci.ip"
  4. local o
  5. require "luci.util"
  6. m = Map("dhcp", translate("DHCP and DNS"),
  7. translate("Dnsmasq is a combined <abbr title=\"Dynamic Host Configuration Protocol" ..
  8. "\">DHCP</abbr>-Server and <abbr title=\"Domain Name System\">DNS</abbr>-" ..
  9. "Forwarder for <abbr title=\"Network Address Translation\">NAT</abbr> " ..
  10. "firewalls"))
  11. s = m:section(TypedSection, "dnsmasq", translate("Server Settings"))
  12. s.anonymous = true
  13. s.addremove = false
  14. s:tab("general", translate("General Settings"))
  15. s:tab("files", translate("Resolv and Hosts Files"))
  16. s:tab("tftp", translate("TFTP Settings"))
  17. s:tab("advanced", translate("Advanced Settings"))
  18. s:taboption("general", Flag, "domainneeded",
  19. translate("Domain required"),
  20. translate("Don't forward <abbr title=\"Domain Name System\">DNS</abbr>-Requests without " ..
  21. "<abbr title=\"Domain Name System\">DNS</abbr>-Name"))
  22. s:taboption("general", Flag, "authoritative",
  23. translate("Authoritative"),
  24. translate("This is the only <abbr title=\"Dynamic Host Configuration Protocol\">DHCP</" ..
  25. "abbr> in the local network"))
  26. s:taboption("files", Flag, "readethers",
  27. translate("Use <code>/etc/ethers</code>"),
  28. translate("Read <code>/etc/ethers</code> to configure the <abbr title=\"Dynamic Host " ..
  29. "Configuration Protocol\">DHCP</abbr>-Server"))
  30. s:taboption("files", Value, "leasefile",
  31. translate("Leasefile"),
  32. translate("file where given <abbr title=\"Dynamic Host Configuration Protocol\">DHCP</" ..
  33. "abbr>-leases will be stored"))
  34. s:taboption("files", Flag, "noresolv",
  35. translate("Ignore resolve file")).optional = true
  36. rf = s:taboption("files", Value, "resolvfile",
  37. translate("Resolve file"),
  38. translate("local <abbr title=\"Domain Name System\">DNS</abbr> file"))
  39. rf:depends("noresolv", "")
  40. rf.optional = true
  41. s:taboption("files", Flag, "nohosts",
  42. translate("Ignore <code>/etc/hosts</code>")).optional = true
  43. s:taboption("files", DynamicList, "addnhosts",
  44. translate("Additional Hosts files")).optional = true
  45. qu = s:taboption("advanced", Flag, "quietdhcp",
  46. translate("Suppress logging"),
  47. translate("Suppress logging of the routine operation of these protocols"))
  48. qu.optional = true
  49. se = s:taboption("advanced", Flag, "sequential_ip",
  50. translate("Allocate IP sequentially"),
  51. translate("Allocate IP addresses sequentially, starting from the lowest available address"))
  52. se.optional = true
  53. s:taboption("advanced", Flag, "boguspriv",
  54. translate("Filter private"),
  55. translate("Do not forward reverse lookups for local networks"))
  56. s:taboption("advanced", Flag, "filterwin2k",
  57. translate("Filter useless"),
  58. translate("Do not forward requests that cannot be answered by public name servers"))
  59. s:taboption("advanced", Flag, "localise_queries",
  60. translate("Localise queries"),
  61. translate("Localise hostname depending on the requesting subnet if multiple IPs are available"))
  62. local have_dnssec_support = luci.util.checklib("/usr/sbin/dnsmasq", "libhogweed.so")
  63. if have_dnssec_support then
  64. o = s:taboption("advanced", Flag, "dnssec",
  65. translate("DNSSEC"))
  66. o.optional = true
  67. o = s:taboption("advanced", Flag, "dnsseccheckunsigned",
  68. translate("DNSSEC check unsigned"),
  69. translate("Requires upstream supports DNSSEC; verify unsigned domain responses really come from unsigned domains"))
  70. o.optional = true
  71. end
  72. s:taboption("general", Value, "local",
  73. translate("Local server"),
  74. translate("Local domain specification. Names matching this domain are never forwarded and are resolved from DHCP or hosts files only"))
  75. s:taboption("general", Value, "domain",
  76. translate("Local domain"),
  77. translate("Local domain suffix appended to DHCP names and hosts file entries"))
  78. s:taboption("advanced", Flag, "expandhosts",
  79. translate("Expand hosts"),
  80. translate("Add local domain suffix to names served from hosts files"))
  81. s:taboption("advanced", Flag, "nonegcache",
  82. translate("No negative cache"),
  83. translate("Do not cache negative replies, e.g. for not existing domains"))
  84. s:taboption("advanced", Value, "serversfile",
  85. translate("Additional servers file"),
  86. translate("This file may contain lines like 'server=/domain/1.2.3.4' or 'server=1.2.3.4' for"..
  87. "domain-specific or full upstream <abbr title=\"Domain Name System\">DNS</abbr> servers."))
  88. s:taboption("advanced", Flag, "strictorder",
  89. translate("Strict order"),
  90. translate("<abbr title=\"Domain Name System\">DNS</abbr> servers will be queried in the " ..
  91. "order of the resolvfile")).optional = true
  92. bn = s:taboption("advanced", DynamicList, "bogusnxdomain", translate("Bogus NX Domain Override"),
  93. translate("List of hosts that supply bogus NX domain results"))
  94. bn.optional = true
  95. bn.placeholder = "67.215.65.132"
  96. s:taboption("general", Flag, "logqueries",
  97. translate("Log queries"),
  98. translate("Write received DNS requests to syslog")).optional = true
  99. df = s:taboption("general", DynamicList, "server", translate("DNS forwardings"),
  100. translate("List of <abbr title=\"Domain Name System\">DNS</abbr> " ..
  101. "servers to forward requests to"))
  102. df.optional = true
  103. df.placeholder = "/example.org/10.1.2.3"
  104. rp = s:taboption("general", Flag, "rebind_protection",
  105. translate("Rebind protection"),
  106. translate("Discard upstream RFC1918 responses"))
  107. rp.rmempty = false
  108. rl = s:taboption("general", Flag, "rebind_localhost",
  109. translate("Allow localhost"),
  110. translate("Allow upstream responses in the 127.0.0.0/8 range, e.g. for RBL services"))
  111. rl:depends("rebind_protection", "1")
  112. rd = s:taboption("general", DynamicList, "rebind_domain",
  113. translate("Domain whitelist"),
  114. translate("List of domains to allow RFC1918 responses for"))
  115. rd.optional = true
  116. rd:depends("rebind_protection", "1")
  117. rd.datatype = "host(1)"
  118. rd.placeholder = "ihost.netflix.com"
  119. pt = s:taboption("advanced", Value, "port",
  120. translate("<abbr title=\"Domain Name System\">DNS</abbr> server port"),
  121. translate("Listening port for inbound DNS queries"))
  122. pt.optional = true
  123. pt.datatype = "port"
  124. pt.placeholder = 53
  125. qp = s:taboption("advanced", Value, "queryport",
  126. translate("<abbr title=\"Domain Name System\">DNS</abbr> query port"),
  127. translate("Fixed source port for outbound DNS queries"))
  128. qp.optional = true
  129. qp.datatype = "port"
  130. qp.placeholder = translate("any")
  131. lm = s:taboption("advanced", Value, "dhcpleasemax",
  132. translate("<abbr title=\"maximal\">Max.</abbr> <abbr title=\"Dynamic Host Configuration " ..
  133. "Protocol\">DHCP</abbr> leases"),
  134. translate("Maximum allowed number of active DHCP leases"))
  135. lm.optional = true
  136. lm.datatype = "uinteger"
  137. lm.placeholder = translate("unlimited")
  138. em = s:taboption("advanced", Value, "ednspacket_max",
  139. translate("<abbr title=\"maximal\">Max.</abbr> <abbr title=\"Extension Mechanisms for " ..
  140. "Domain Name System\">EDNS0</abbr> packet size"),
  141. translate("Maximum allowed size of EDNS.0 UDP packets"))
  142. em.optional = true
  143. em.datatype = "uinteger"
  144. em.placeholder = 1280
  145. cq = s:taboption("advanced", Value, "dnsforwardmax",
  146. translate("<abbr title=\"maximal\">Max.</abbr> concurrent queries"),
  147. translate("Maximum allowed number of concurrent DNS queries"))
  148. cq.optional = true
  149. cq.datatype = "uinteger"
  150. cq.placeholder = 150
  151. s:taboption("tftp", Flag, "enable_tftp",
  152. translate("Enable TFTP server")).optional = true
  153. tr = s:taboption("tftp", Value, "tftp_root",
  154. translate("TFTP server root"),
  155. translate("Root directory for files served via TFTP"))
  156. tr.optional = true
  157. tr:depends("enable_tftp", "1")
  158. tr.placeholder = "/"
  159. db = s:taboption("tftp", Value, "dhcp_boot",
  160. translate("Network boot image"),
  161. translate("Filename of the boot image advertised to clients"))
  162. db.optional = true
  163. db:depends("enable_tftp", "1")
  164. db.placeholder = "pxelinux.0"
  165. o = s:taboption("general", Flag, "localservice",
  166. translate("Local Service Only"),
  167. translate("Limit DNS service to subnets interfaces on which we are serving DNS."))
  168. o.optional = false
  169. o.rmempty = false
  170. o = s:taboption("general", Flag, "nonwildcard",
  171. translate("Non-wildcard"),
  172. translate("Bind only to specific interfaces rather than wildcard address."))
  173. o.optional = false
  174. o.rmempty = false
  175. o = s:taboption("general", DynamicList, "interface",
  176. translate("Listen Interfaces"),
  177. translate("Limit listening to these interfaces, and loopback."))
  178. o.optional = true
  179. o:depends("nonwildcard", true)
  180. o = s:taboption("general", DynamicList, "notinterface",
  181. translate("Exclude interfaces"),
  182. translate("Prevent listening on these interfaces."))
  183. o.optional = true
  184. o:depends("nonwildcard", true)
  185. m:section(SimpleSection).template = "admin_network/lease_status"
  186. s = m:section(TypedSection, "host", translate("Static Leases"),
  187. translate("Static leases are used to assign fixed IP addresses and symbolic hostnames to " ..
  188. "DHCP clients. They are also required for non-dynamic interface configurations where " ..
  189. "only hosts with a corresponding lease are served.") .. "<br />" ..
  190. translate("Use the <em>Add</em> Button to add a new lease entry. The <em>MAC-Address</em> " ..
  191. "indentifies the host, the <em>IPv4-Address</em> specifies to the fixed address to " ..
  192. "use and the <em>Hostname</em> is assigned as symbolic name to the requesting host. " ..
  193. "The optional <em>Lease time</em> can be used to set non-standard host-specific " ..
  194. "lease time, e.g. 12h, 3d or infinite."))
  195. s.addremove = true
  196. s.anonymous = true
  197. s.template = "cbi/tblsection"
  198. name = s:option(Value, "name", translate("Hostname"))
  199. name.datatype = "hostname"
  200. name.rmempty = true
  201. mac = s:option(Value, "mac", translate("<abbr title=\"Media Access Control\">MAC</abbr>-Address"))
  202. mac.datatype = "list(macaddr)"
  203. mac.rmempty = true
  204. ip = s:option(Value, "ip", translate("<abbr title=\"Internet Protocol Version 4\">IPv4</abbr>-Address"))
  205. ip.datatype = "or(ip4addr,'ignore')"
  206. time = s:option(Value, "leasetime", translate("Lease time"))
  207. time.rmempty = true
  208. hostid = s:option(Value, "hostid", translate("<abbr title=\"Internet Protocol Version 6\">IPv6</abbr>-Suffix (hex)"))
  209. ipc.neighbors({ family = 4 }, function(n)
  210. if n.mac and n.dest then
  211. ip:value(n.dest:string())
  212. mac:value(n.mac, "%s (%s)" %{ n.mac, n.dest:string() })
  213. end
  214. end)
  215. function ip.validate(self, value, section)
  216. local m = mac:formvalue(section) or ""
  217. local n = name:formvalue(section) or ""
  218. if value and #n == 0 and #m == 0 then
  219. return nil, translate("One of hostname or mac address must be specified!")
  220. end
  221. return Value.validate(self, value, section)
  222. end
  223. return m