librecmc : Bump to v1.5.15
[librecmc/librecmc.git] / package / network / services / unbound / files / dnsmasq.sh
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
26 DM_D_WAN_FQDN=0
27
28 DM_LIST_KNOWN_ZONES="invalid"
29 DM_LIST_TRN_ZONES=""
30 DM_LIST_LOCAL_DATA=""
31 DM_LIST_LOCAL_PTR=""
32 DM_LIST_FWD_PORTS=""
33 DM_LIST_FWD_ZONES=""
34
35 ##############################################################################
36
37 create_local_zone() {
38   local target="$1"
39   local partial domain found
40
41   case $DM_LIST_TRN_ZONES in
42     *"${target}"*)
43       found=1
44       ;;
45
46     *)
47       case $target in
48         [A-Za-z0-9]*.[A-Za-z0-9]*)
49           found=0
50           ;;
51
52         *) # no dots
53           found=1
54           ;;
55       esac
56   esac
57
58
59   if [ $found -eq 0 ] ; then
60     # New Zone! Bundle local-zones: by first two name tiers "abcd.tld."
61     partial=$( echo "$target" | awk -F. '{ j=NF ; i=j-1; print $i"."$j }' )
62     DM_LIST_TRN_ZONES="$DM_LIST_TRN_ZONES $partial"
63     DM_LIST_KNOWN_ZONES="$DM_LIST_KNOWN_ZONES $partial"
64   fi
65 }
66
67 ##############################################################################
68
69 create_host_record() {
70   local cfg="$1"
71   local ip name debug_ip
72
73   # basefiles dhcp "domain" clause which means host A, AAAA, and PRT record
74   config_get ip   "$cfg" ip
75   config_get name "$cfg" name
76
77
78   if [ -n "$name" ] && [ -n "$ip" ] ; then
79     create_local_zone "$name"
80
81
82     case $ip in
83       fe[89ab][0-9a-f]:*|169.254.*)
84         debug_ip="$ip@$name"
85         ;;
86
87       [1-9a-f]*:*[0-9a-f])
88         DM_LIST_LOCAL_DATA="$DM_LIST_LOCAL_DATA $name.@@300@@IN@@AAAA@@$ip"
89         DM_LIST_LOCAL_PTR="$DM_LIST_LOCAL_PTR $ip@@300@@$name"
90         ;;
91
92       [1-9]*.*[0-9])
93         DM_LIST_LOCAL_DATA="$DM_LIST_LOCAL_DATA $name.@@300@@IN@@A@@$ip"
94         DM_LIST_LOCAL_PTR="$DM_LIST_LOCAL_PTR $ip@@300@@$name"
95         ;;
96     esac
97   fi
98 }
99
100 ##############################################################################
101
102 create_mx_record() {
103   local cfg="$1"
104   local domain relay pref record
105
106   # Insert a static MX record
107   config_get domain "$cfg" domain
108   config_get relay  "$cfg" relay
109   config_get pref   "$cfg" pref 10
110
111
112   if [ -n "$domain" ] && [ -n "$relay" ] ; then
113     create_local_zone "$domain"
114     record="$domain.@@300@@IN@@MX@@$pref@@$relay."
115     DM_LIST_LOCAL_DATA="$DM_LIST_LOCAL_DATA $record"
116   fi
117 }
118
119 ##############################################################################
120
121 create_srv_record() {
122   local cfg="$1"
123   local srv target port class weight record
124
125   # Insert a static SRV record such as SIP server
126   config_get srv    "$cfg" srv
127   config_get target "$cfg" target
128   config_get port   "$cfg" port
129   config_get class  "$cfg" class 10
130   config_get weight "$cfg" weight 10
131
132
133   if [ -n "$srv" ] && [ -n "$target" ] && [ -n "$port" ] ; then
134     create_local_zone "$srv"
135     record="$srv.@@300@@IN@@SRV@@$class@@$weight@@$port@@$target."
136     DM_LIST_LOCAL_DATA="$DM_LIST_LOCAL_DATA $record"
137   fi
138 }
139
140 ##############################################################################
141
142 create_cname_record() {
143   local cfg="$1"
144   local cname target record
145
146   # Insert static CNAME record
147   config_get cname  "$cfg" cname
148   config_get target "$cfg" target
149
150
151   if [ -n "$cname" ] && [ -n "$target" ] ; then
152     create_local_zone "$cname"
153     record="$cname.@@300@@IN@@CNAME@@$target."
154     DM_LIST_LOCAL_DATA="$DM_LIST_LOCAL_DATA $record"
155   fi
156 }
157
158 ##############################################################################
159
160 dnsmasq_local_zone() {
161   local cfg="$1"
162   local fwd_port fwd_domain wan_fqdn
163
164   # dnsmasq domain and interface assignment settings will control config
165   config_get fwd_domain "$cfg" domain
166   config_get fwd_port "$cfg" port
167   config_get wan_fqdn "$cfg" add_wan_fqdn
168
169
170   if [ -n "$wan_fqdn" ] ; then
171     DM_D_WAN_FQDN=$wan_fqdn
172   fi
173
174
175   if [ -n "$fwd_domain" ] && [ -n "$fwd_port" ] \
176   && [ ! "${fwd_port:-53}" -eq 53 ] ; then
177     # dnsmasq localhost listening ports (possible multiple instances)
178     DM_LIST_FWD_PORTS="$DM_LIST_FWD_PORTS $fwd_port"
179     DM_LIST_FWD_ZONES="$DM_LIST_FWD_ZONES $fwd_domain"
180   fi
181 }
182
183 ##############################################################################
184
185 dnsmasq_local_arpa() {
186   local ifarpa ifsubnet
187
188
189   if [ -n "$UB_LIST_NETW_LAN" ] ; then
190     for ifsubnet in $UB_LIST_NETW_LAN ; do
191       ifarpa=$( domain_ptr_any "${ifsubnet#*@}" )
192       DM_LIST_FWD_ZONES="$DM_LIST_FWD_ZONES $ifarpa"
193     done
194   fi
195
196
197   if [ -n "$UB_LIST_NETW_WAN" ] && [ "$DM_D_WAN_FQDN" -gt 0 ] ; then
198     for ifsubnet in $UB_LIST_NETW_WAN ; do
199       ifarpa=$( domain_ptr_any "${ifsubnet#*@}" )
200       DM_LIST_FWD_ZONES="$DM_LIST_FWD_ZONES $ifarpa"
201     done
202   fi
203 }
204
205 ##############################################################################
206
207 dnsmasq_inactive() {
208   local record
209
210
211   if [ "$UB_D_EXTRA_DNS" -gt 0 ] ; then
212     # Parasite from the uci.dhcp.domain clauses
213     DM_LIST_KNOWN_ZONES="$DM_LIST_KNOWN_ZONES $UB_TXT_DOMAIN"
214     config_load dhcp
215     config_foreach create_host_record domain
216
217
218     if [ "$UB_D_EXTRA_DNS" -gt 1 ] ; then
219       config_foreach create_srv_record srvhost
220       config_foreach create_mx_record mxhost
221     fi
222
223
224     if [ "$UB_D_EXTRA_DNS" -gt 2 ] ; then
225       config_foreach create_cname_record cname
226     fi
227
228
229     {
230       echo "# $UB_SRVMASQ_CONF generated by UCI $( date -Is )"
231       if [ -n "$DM_LIST_TRN_ZONES" ] ; then
232         for record in $DM_LIST_TRN_ZONES ; do
233           echo "  local-zone: $record transparent"
234         done
235         echo
236       fi
237       if [ -n "$DM_LIST_LOCAL_DATA" ] ; then
238         for record in $DM_LIST_LOCAL_DATA ; do
239           echo "  local-data: \"${record//@@/ }\""
240         done
241         echo
242       fi
243       if [ -n "$DM_LIST_LOCAL_PTR" ] ; then
244         for record in $DM_LIST_LOCAL_PTR ; do
245           echo "  local-data-ptr: \"${record//@@/ }\""
246         done
247         echo
248       fi
249     } > $UB_SRVMASQ_CONF
250   fi
251 }
252
253 ##############################################################################
254
255 dnsmasq_active() {
256   # Look at dnsmasq settings
257   config_load dhcp
258   # Zone for DHCP / SLAAC-PING DOMAIN
259   config_foreach dnsmasq_local_zone dnsmasq
260   # Zone for DHCP / SLAAC-PING ARPA
261   dnsmasq_local_arpa
262
263
264   if [ -n "$DM_LIST_FWD_PORTS" ] && [ -n "$DM_LIST_FWD_ZONES" ] ; then
265     {
266       # Forward to dnsmasq on same host for DHCP lease hosts
267       echo "# $UB_SRVMASQ_CONF generated by UCI $( date -Is )"
268       echo "  do-not-query-localhost: no"
269       echo
270     } > $UB_SRVMASQ_CONF
271
272     echo "# $UB_EXTMASQ_CONF generated by UCI $( date -Is )" > $UB_EXTMASQ_CONF
273
274
275     for fwd_domain in $DM_LIST_FWD_ZONES ; do
276       {
277         # This creates a domain with local privledges
278         echo "  domain-insecure: $fwd_domain"
279         echo "  private-domain: $fwd_domain"
280         echo "  local-zone: $fwd_domain transparent"
281         echo
282       } >> $UB_SRVMASQ_CONF
283
284       {
285         # This is derived from dnsmasq local domain and dhcp service subnets
286         echo "forward-zone:"
287         echo "  name: $fwd_domain"
288         echo "  forward-first: no"
289         for port in $DM_LIST_FWD_PORTS ; do
290           echo "  forward-addr: 127.0.0.1@$port"
291         done
292         echo
293       } >> $UB_EXTMASQ_CONF
294     done
295   fi
296 }
297
298 ##############################################################################
299
300 dnsmasq_link() {
301   if [ "$UB_D_DHCP_LINK" = "dnsmasq" ] ; then
302     dnsmasq_active
303
304   else
305     dnsmasq_inactive
306   fi
307 }
308
309 ##############################################################################
310