You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

309 lines
8.1 KiB

  1. #!/bin/sh
  2. ##############################################################################
  3. #
  4. # This program is free software; you can redistribute it and/or modify
  5. # it under the terms of the GNU General Public License version 2 as
  6. # published by the Free Software Foundation.
  7. #
  8. # This program is distributed in the hope that it will be useful,
  9. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. # GNU General Public License for more details.
  12. #
  13. # Copyright (C) 2016 Eric Luehrsen
  14. #
  15. ##############################################################################
  16. #
  17. # This crosses over to the dnsmasq UCI file "dhcp" and parses it for fields
  18. # that will allow Unbound to request local host DNS of dnsmasq. We need to look
  19. # at the interfaces in "dhcp" and get their subnets. The Unbound conf syntax
  20. # makes this a little difficult. First in "server:" we need to create private
  21. # zones for the domain and PTR records. Then we need to create numerous
  22. # "forward:" clauses to forward those zones to dnsmasq.
  23. #
  24. ##############################################################################
  25. DM_D_WAN_FQDN=0
  26. DM_LIST_KNOWN_ZONES="invalid"
  27. DM_LIST_TRN_ZONES=""
  28. DM_LIST_LOCAL_DATA=""
  29. DM_LIST_LOCAL_PTR=""
  30. DM_LIST_FWD_PORTS=""
  31. DM_LIST_FWD_ZONES=""
  32. ##############################################################################
  33. create_local_zone() {
  34. local target="$1"
  35. local partial domain found
  36. case $DM_LIST_TRN_ZONES in
  37. *"${target}"*)
  38. found=1
  39. ;;
  40. *)
  41. case $target in
  42. [A-Za-z0-9]*.[A-Za-z0-9]*)
  43. found=0
  44. ;;
  45. *) # no dots
  46. found=1
  47. ;;
  48. esac
  49. esac
  50. if [ $found -eq 0 ] ; then
  51. # New Zone! Bundle local-zones: by first two name tiers "abcd.tld."
  52. partial=$( echo "$target" | awk -F. '{ j=NF ; i=j-1; print $i"."$j }' )
  53. DM_LIST_TRN_ZONES="$DM_LIST_TRN_ZONES $partial"
  54. DM_LIST_KNOWN_ZONES="$DM_LIST_KNOWN_ZONES $partial"
  55. fi
  56. }
  57. ##############################################################################
  58. create_host_record() {
  59. local cfg="$1"
  60. local ip name debug_ip
  61. # basefiles dhcp "domain" clause which means host A, AAAA, and PRT record
  62. config_get ip "$cfg" ip
  63. config_get name "$cfg" name
  64. if [ -n "$name" -a -n "$ip" ] ; then
  65. create_local_zone "$name"
  66. case $ip in
  67. fe[89ab][0-9a-f]:*|169.254.*)
  68. debug_ip="$ip@$host"
  69. ;;
  70. [1-9a-f]*:*[0-9a-f])
  71. DM_LIST_LOCAL_DATA="$DM_LIST_LOCAL_DATA $name.@@300@@IN@@AAAA@@$ip"
  72. DM_LIST_LOCAL_PTR="$DM_LIST_LOCAL_PTR $ip@@300@@$name"
  73. ;;
  74. [1-9]*.*[0-9])
  75. DM_LIST_LOCAL_DATA="$DM_LIST_LOCAL_DATA $name.@@300@@IN@@A@@$ip"
  76. DM_LIST_LOCAL_PTR="$DM_LIST_LOCAL_PTR $ip@@300@@$name"
  77. ;;
  78. esac
  79. fi
  80. }
  81. ##############################################################################
  82. create_mx_record() {
  83. local cfg="$1"
  84. local domain relay pref record
  85. # Insert a static MX record
  86. config_get domain "$cfg" domain
  87. config_get relay "$cfg" relay
  88. config_get pref "$cfg" pref 10
  89. if [ -n "$domain" -a -n "$relay" ] ; then
  90. create_local_zone "$domain"
  91. record="$domain.@@300@@IN@@MX@@$pref@@$relay."
  92. DM_LIST_LOCAL_DATA="$DM_LIST_LOCAL_DATA $record"
  93. fi
  94. }
  95. ##############################################################################
  96. create_srv_record() {
  97. local cfg="$1"
  98. local srv target port class weight record
  99. # Insert a static SRV record such as SIP server
  100. config_get srv "$cfg" srv
  101. config_get target "$cfg" target
  102. config_get port "$cfg" port
  103. config_get class "$cfg" class 10
  104. config_get weight "$cfg" weight 10
  105. if [ -n "$srv" -a -n "$target" -a -n "$port" ] ; then
  106. create_local_zone "$srv"
  107. record="$srv.@@300@@IN@@SRV@@$class@@$weight@@$port@@$target."
  108. DM_LIST_LOCAL_DATA="$DM_LIST_LOCAL_DATA $record"
  109. fi
  110. }
  111. ##############################################################################
  112. create_cname_record() {
  113. local cfg="$1"
  114. local cname target record
  115. # Insert static CNAME record
  116. config_get cname "$cfg" cname
  117. config_get target "$cfg" target
  118. if [ -n "$cname" -a -n "$target" ] ; then
  119. create_local_zone "$cname"
  120. record="$cname.@@300@@IN@@CNAME@@$target."
  121. DM_LIST_LOCAL_DATA="$DM_LIST_LOCAL_DATA $record"
  122. fi
  123. }
  124. ##############################################################################
  125. dnsmasq_local_zone() {
  126. local cfg="$1"
  127. local fwd_port fwd_domain wan_fqdn
  128. # dnsmasq domain and interface assignment settings will control config
  129. config_get fwd_domain "$cfg" domain
  130. config_get fwd_port "$cfg" port
  131. config_get wan_fqdn "$cfg" add_wan_fqdn
  132. if [ -n "$wan_fqdn" ] ; then
  133. DM_D_WAN_FQDN=$wan_fqdn
  134. fi
  135. if [ -n "$fwd_domain" -a -n "$fwd_port" -a ! "${fwd_port:-53}" -eq 53 ] ; then
  136. # dnsmasq localhost listening ports (possible multiple instances)
  137. DM_LIST_FWD_PORTS="$DM_LIST_FWD_PORTS $fwd_port"
  138. DM_LIST_FWD_ZONES="$DM_LIST_FWD_ZONES $fwd_domain"
  139. fi
  140. }
  141. ##############################################################################
  142. dnsmasq_local_arpa() {
  143. local ifarpa ifsubnet
  144. if [ -n "$UB_LIST_NETW_LAN" ] ; then
  145. for ifsubnet in $UB_LIST_NETW_LAN ; do
  146. ifarpa=$( domain_ptr_any "${ifsubnet#*@}" )
  147. DM_LIST_FWD_ZONES="$DM_LIST_FWD_ZONES $ifarpa"
  148. done
  149. fi
  150. if [ -n "$UB_LIST_NETW_WAN" -a "$DM_D_WAN_FQDN" -gt 0 ] ; then
  151. for ifsubnet in $UB_LIST_NETW_WAN ; do
  152. ifarpa=$( domain_ptr_any "${ifsubnet#*@}" )
  153. DM_LIST_FWD_ZONES="$DM_LIST_FWD_ZONES $ifarpa"
  154. done
  155. fi
  156. }
  157. ##############################################################################
  158. dnsmasq_inactive() {
  159. local record
  160. if [ "$UB_D_EXTRA_DNS" -gt 0 ] ; then
  161. # Parasite from the uci.dhcp.domain clauses
  162. DM_LIST_KNOWN_ZONES="$DM_LIST_KNOWN_ZONES $UB_TXT_DOMAIN"
  163. config_load dhcp
  164. config_foreach create_host_record domain
  165. if [ "$UB_D_EXTRA_DNS" -gt 1 ] ; then
  166. config_foreach create_srv_record srvhost
  167. config_foreach create_mx_record mxhost
  168. fi
  169. if [ "$UB_D_EXTRA_DNS" -gt 2 ] ; then
  170. config_foreach create_cname_record cname
  171. fi
  172. {
  173. echo "# $UB_SRVMASQ_CONF generated by UCI $( date -Is )"
  174. if [ -n "$DM_LIST_TRN_ZONES" ] ; then
  175. for record in $DM_LIST_TRN_ZONES ; do
  176. echo " local-zone: $record transparent"
  177. done
  178. echo
  179. fi
  180. if [ -n "$DM_LIST_LOCAL_DATA" ] ; then
  181. for record in $DM_LIST_LOCAL_DATA ; do
  182. echo " local-data: \"${record//@@/ }\""
  183. done
  184. echo
  185. fi
  186. if [ -n "$DM_LIST_LOCAL_PTR" ] ; then
  187. for record in $DM_LIST_LOCAL_PTR ; do
  188. echo " local-data-ptr: \"${record//@@/ }\""
  189. done
  190. echo
  191. fi
  192. } > $UB_SRVMASQ_CONF
  193. fi
  194. }
  195. ##############################################################################
  196. dnsmasq_active() {
  197. # Look at dnsmasq settings
  198. config_load dhcp
  199. # Zone for DHCP / SLAAC-PING DOMAIN
  200. config_foreach dnsmasq_local_zone dnsmasq
  201. # Zone for DHCP / SLAAC-PING ARPA
  202. dnsmasq_local_arpa
  203. if [ -n "$DM_LIST_FWD_PORTS" -a -n "$DM_LIST_FWD_ZONES" ] ; then
  204. {
  205. # Forward to dnsmasq on same host for DHCP lease hosts
  206. echo "# $UB_SRVMASQ_CONF generated by UCI $( date -Is )"
  207. echo " do-not-query-localhost: no"
  208. echo
  209. } > $UB_SRVMASQ_CONF
  210. echo "# $UB_EXTMASQ_CONF generated by UCI $( date -Is )" > $UB_EXTMASQ_CONF
  211. for fwd_domain in $DM_LIST_FWD_ZONES ; do
  212. {
  213. # This creates a domain with local privledges
  214. echo " domain-insecure: $fwd_domain"
  215. echo " private-domain: $fwd_domain"
  216. echo " local-zone: $fwd_domain transparent"
  217. echo
  218. } >> $UB_SRVMASQ_CONF
  219. {
  220. # This is derived from dnsmasq local domain and dhcp service subnets
  221. echo "forward-zone:"
  222. echo " name: $fwd_domain"
  223. echo " forward-first: no"
  224. for port in $DM_LIST_FWD_PORTS ; do
  225. echo " forward-addr: 127.0.0.1@$port"
  226. done
  227. echo
  228. } >> $UB_EXTMASQ_CONF
  229. done
  230. fi
  231. }
  232. ##############################################################################
  233. dnsmasq_link() {
  234. if [ "$UB_D_DHCP_LINK" = "dnsmasq" ] ; then
  235. dnsmasq_active
  236. else
  237. dnsmasq_inactive
  238. fi
  239. }
  240. ##############################################################################