#!/bin/sh
|
|
##############################################################################
|
|
#
|
|
# This program is free software; you can redistribute it and/or modify
|
|
# it under the terms of the GNU General Public License version 2 as
|
|
# published by the Free Software Foundation.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
# Copyright (C) 2016 Eric Luehrsen
|
|
#
|
|
##############################################################################
|
|
#
|
|
# This crosses over to the dnsmasq UCI file "dhcp" and parses it for fields
|
|
# that will allow Unbound to request local host DNS of dnsmasq. We need to look
|
|
# at the interfaces in "dhcp" and get their subnets. The Unbound conf syntax
|
|
# makes this a little difficult. First in "server:" we need to create private
|
|
# zones for the domain and PTR records. Then we need to create numerous
|
|
# "forward:" clauses to forward those zones to dnsmasq.
|
|
#
|
|
##############################################################################
|
|
|
|
# while useful (sh)ellcheck is pedantic and noisy
|
|
# shellcheck disable=1091,2002,2004,2034,2039,2086,2094,2140,2154,2155
|
|
|
|
DM_D_WAN_FQDN=0
|
|
|
|
DM_LIST_KNOWN_ZONES="invalid"
|
|
DM_LIST_TRN_ZONES=""
|
|
DM_LIST_LOCAL_DATA=""
|
|
DM_LIST_LOCAL_PTR=""
|
|
DM_LIST_FWD_PORTS=""
|
|
DM_LIST_FWD_ZONES=""
|
|
|
|
##############################################################################
|
|
|
|
create_local_zone() {
|
|
local target="$1"
|
|
local partial domain found
|
|
|
|
case $DM_LIST_TRN_ZONES in
|
|
*"${target}"*)
|
|
found=1
|
|
;;
|
|
|
|
*)
|
|
case $target in
|
|
[A-Za-z0-9]*.[A-Za-z0-9]*)
|
|
found=0
|
|
;;
|
|
|
|
*) # no dots
|
|
found=1
|
|
;;
|
|
esac
|
|
esac
|
|
|
|
|
|
if [ $found -eq 0 ] ; then
|
|
# New Zone! Bundle local-zones: by first two name tiers "abcd.tld."
|
|
partial=$( echo "$target" | awk -F. '{ j=NF ; i=j-1; print $i"."$j }' )
|
|
DM_LIST_TRN_ZONES="$DM_LIST_TRN_ZONES $partial"
|
|
DM_LIST_KNOWN_ZONES="$DM_LIST_KNOWN_ZONES $partial"
|
|
fi
|
|
}
|
|
|
|
##############################################################################
|
|
|
|
create_host_record() {
|
|
local cfg="$1"
|
|
local ip name debug_ip
|
|
|
|
# basefiles dhcp "domain" clause which means host A, AAAA, and PRT record
|
|
config_get ip "$cfg" ip
|
|
config_get name "$cfg" name
|
|
|
|
|
|
if [ -n "$name" ] && [ -n "$ip" ] ; then
|
|
create_local_zone "$name"
|
|
|
|
|
|
case $ip in
|
|
fe[89ab][0-9a-f]:*|169.254.*)
|
|
debug_ip="$ip@$name"
|
|
;;
|
|
|
|
[1-9a-f]*:*[0-9a-f])
|
|
DM_LIST_LOCAL_DATA="$DM_LIST_LOCAL_DATA $name.@@300@@IN@@AAAA@@$ip"
|
|
DM_LIST_LOCAL_PTR="$DM_LIST_LOCAL_PTR $ip@@300@@$name"
|
|
;;
|
|
|
|
[1-9]*.*[0-9])
|
|
DM_LIST_LOCAL_DATA="$DM_LIST_LOCAL_DATA $name.@@300@@IN@@A@@$ip"
|
|
DM_LIST_LOCAL_PTR="$DM_LIST_LOCAL_PTR $ip@@300@@$name"
|
|
;;
|
|
esac
|
|
fi
|
|
}
|
|
|
|
##############################################################################
|
|
|
|
create_mx_record() {
|
|
local cfg="$1"
|
|
local domain relay pref record
|
|
|
|
# Insert a static MX record
|
|
config_get domain "$cfg" domain
|
|
config_get relay "$cfg" relay
|
|
config_get pref "$cfg" pref 10
|
|
|
|
|
|
if [ -n "$domain" ] && [ -n "$relay" ] ; then
|
|
create_local_zone "$domain"
|
|
record="$domain.@@300@@IN@@MX@@$pref@@$relay."
|
|
DM_LIST_LOCAL_DATA="$DM_LIST_LOCAL_DATA $record"
|
|
fi
|
|
}
|
|
|
|
##############################################################################
|
|
|
|
create_srv_record() {
|
|
local cfg="$1"
|
|
local srv target port class weight record
|
|
|
|
# Insert a static SRV record such as SIP server
|
|
config_get srv "$cfg" srv
|
|
config_get target "$cfg" target
|
|
config_get port "$cfg" port
|
|
config_get class "$cfg" class 10
|
|
config_get weight "$cfg" weight 10
|
|
|
|
|
|
if [ -n "$srv" ] && [ -n "$target" ] && [ -n "$port" ] ; then
|
|
create_local_zone "$srv"
|
|
record="$srv.@@300@@IN@@SRV@@$class@@$weight@@$port@@$target."
|
|
DM_LIST_LOCAL_DATA="$DM_LIST_LOCAL_DATA $record"
|
|
fi
|
|
}
|
|
|
|
##############################################################################
|
|
|
|
create_cname_record() {
|
|
local cfg="$1"
|
|
local cname target record
|
|
|
|
# Insert static CNAME record
|
|
config_get cname "$cfg" cname
|
|
config_get target "$cfg" target
|
|
|
|
|
|
if [ -n "$cname" ] && [ -n "$target" ] ; then
|
|
create_local_zone "$cname"
|
|
record="$cname.@@300@@IN@@CNAME@@$target."
|
|
DM_LIST_LOCAL_DATA="$DM_LIST_LOCAL_DATA $record"
|
|
fi
|
|
}
|
|
|
|
##############################################################################
|
|
|
|
dnsmasq_local_zone() {
|
|
local cfg="$1"
|
|
local fwd_port fwd_domain wan_fqdn
|
|
|
|
# dnsmasq domain and interface assignment settings will control config
|
|
config_get fwd_domain "$cfg" domain
|
|
config_get fwd_port "$cfg" port
|
|
config_get wan_fqdn "$cfg" add_wan_fqdn
|
|
|
|
|
|
if [ -n "$wan_fqdn" ] ; then
|
|
DM_D_WAN_FQDN=$wan_fqdn
|
|
fi
|
|
|
|
|
|
if [ -n "$fwd_domain" ] && [ -n "$fwd_port" ] \
|
|
&& [ ! ${fwd_port:-53} -eq 53 ] ; then
|
|
# dnsmasq localhost listening ports (possible multiple instances)
|
|
DM_LIST_FWD_PORTS="$DM_LIST_FWD_PORTS $fwd_port"
|
|
DM_LIST_FWD_ZONES="$DM_LIST_FWD_ZONES $fwd_domain"
|
|
fi
|
|
}
|
|
|
|
##############################################################################
|
|
|
|
dnsmasq_local_arpa() {
|
|
local ifarpa ifsubnet
|
|
|
|
|
|
if [ -n "$UB_LIST_NETW_LAN" ] ; then
|
|
for ifsubnet in $UB_LIST_NETW_LAN ; do
|
|
ifarpa=$( domain_ptr_any "${ifsubnet#*@}" )
|
|
DM_LIST_FWD_ZONES="$DM_LIST_FWD_ZONES $ifarpa"
|
|
done
|
|
fi
|
|
|
|
|
|
if [ -n "$UB_LIST_NETW_WAN" ] && [ $DM_D_WAN_FQDN -gt 0 ] ; then
|
|
for ifsubnet in $UB_LIST_NETW_WAN ; do
|
|
ifarpa=$( domain_ptr_any "${ifsubnet#*@}" )
|
|
DM_LIST_FWD_ZONES="$DM_LIST_FWD_ZONES $ifarpa"
|
|
done
|
|
fi
|
|
}
|
|
|
|
##############################################################################
|
|
|
|
dnsmasq_inactive() {
|
|
local record
|
|
|
|
|
|
if [ $UB_D_EXTRA_DNS -gt 0 ] ; then
|
|
# Parasite from the uci.dhcp.domain clauses
|
|
DM_LIST_KNOWN_ZONES="$DM_LIST_KNOWN_ZONES $UB_TXT_DOMAIN"
|
|
config_load dhcp
|
|
config_foreach create_host_record domain
|
|
|
|
|
|
if [ $UB_D_EXTRA_DNS -gt 1 ] ; then
|
|
config_foreach create_srv_record srvhost
|
|
config_foreach create_mx_record mxhost
|
|
fi
|
|
|
|
|
|
if [ $UB_D_EXTRA_DNS -gt 2 ] ; then
|
|
config_foreach create_cname_record cname
|
|
fi
|
|
|
|
|
|
{
|
|
echo "# $UB_SRVMASQ_CONF generated by UCI $( date -Is )"
|
|
if [ -n "$DM_LIST_TRN_ZONES" ] ; then
|
|
for record in $DM_LIST_TRN_ZONES ; do
|
|
echo " local-zone: $record transparent"
|
|
done
|
|
echo
|
|
fi
|
|
if [ -n "$DM_LIST_LOCAL_DATA" ] ; then
|
|
for record in $DM_LIST_LOCAL_DATA ; do
|
|
echo " local-data: \"${record//@@/ }\""
|
|
done
|
|
echo
|
|
fi
|
|
if [ -n "$DM_LIST_LOCAL_PTR" ] ; then
|
|
for record in $DM_LIST_LOCAL_PTR ; do
|
|
echo " local-data-ptr: \"${record//@@/ }\""
|
|
done
|
|
echo
|
|
fi
|
|
} > $UB_SRVMASQ_CONF
|
|
fi
|
|
}
|
|
|
|
##############################################################################
|
|
|
|
dnsmasq_active() {
|
|
# Look at dnsmasq settings
|
|
config_load dhcp
|
|
# Zone for DHCP / SLAAC-PING DOMAIN
|
|
config_foreach dnsmasq_local_zone dnsmasq
|
|
# Zone for DHCP / SLAAC-PING ARPA
|
|
dnsmasq_local_arpa
|
|
|
|
|
|
if [ -n "$DM_LIST_FWD_PORTS" ] && [ -n "$DM_LIST_FWD_ZONES" ] ; then
|
|
if [ $UB_B_DNS_ASSIST -lt 1 ] ; then
|
|
{
|
|
# Forward to dnsmasq on same host for DHCP lease hosts
|
|
echo "# $UB_SRVMASQ_CONF generated by UCI $( date -Is )"
|
|
echo " do-not-query-localhost: no"
|
|
echo
|
|
} > $UB_SRVMASQ_CONF
|
|
|
|
else
|
|
echo > $UB_SRVMASQ_CONF
|
|
fi
|
|
|
|
echo "# $UB_EXTMASQ_CONF generated by UCI $( date -Is )" > $UB_EXTMASQ_CONF
|
|
|
|
|
|
for fwd_domain in $DM_LIST_FWD_ZONES ; do
|
|
{
|
|
# This creates a domain with local privledges
|
|
echo " domain-insecure: $fwd_domain"
|
|
echo " private-domain: $fwd_domain"
|
|
echo " local-zone: $fwd_domain transparent"
|
|
echo
|
|
} >> $UB_SRVMASQ_CONF
|
|
|
|
{
|
|
# This is derived from dnsmasq local domain and dhcp service subnets
|
|
echo "forward-zone:"
|
|
echo " name: $fwd_domain"
|
|
echo " forward-first: no"
|
|
for port in $DM_LIST_FWD_PORTS ; do
|
|
echo " forward-addr: 127.0.0.1@$port"
|
|
done
|
|
echo
|
|
} >> $UB_EXTMASQ_CONF
|
|
done
|
|
fi
|
|
}
|
|
|
|
##############################################################################
|
|
|
|
dnsmasq_link() {
|
|
if [ "$UB_D_DHCP_LINK" = "dnsmasq" ] ; then
|
|
dnsmasq_active
|
|
|
|
else
|
|
dnsmasq_inactive
|
|
fi
|
|
}
|
|
|
|
##############################################################################
|
|
|