pymumu / smartdns

A local DNS server to obtain the fastest website IP for the best Internet experience, support DoT, DoH. 一个本地DNS服务器,获取最快的网站IP,获得最佳上网体验,支持DoH,DoT。
https://pymumu.github.io/smartdns/
GNU General Public License v3.0
8.32k stars 1.07k forks source link

smartdns设置为53端口时,服务无法启动。 #1045

Closed Misaka299 closed 2 years ago

Misaka299 commented 2 years ago

问题现象
smartdns设置为53端口时,服务无法启动。

运行环境 网上找的openwrt镜像,一个插件很多的镜像包。 跑在exsi,64位下。

smartdns是在release页面下载的。 image image 根据上图下载了 luci-app-smartdns.1.2022.08.28-1734.all-luci-all.ipksmartdns.1.2022.08.28-1734.x86_64-openwrt-all.ipk。 重启过后菜单里也没有smartdns一栏。然后卸载重装,把luci的包换成了 luci-app-smartdns.1.2022.08.28-1734.all-luci-compat-all.ipk

[2022-08-31 23:51:07,293][ERROR][     dns_server.c:5038] bind service [::]:53 failed, Address in use
[2022-08-31 23:51:07,293][ERROR][     dns_server.c:5283] create server socket failed.
[2022-08-31 23:51:07,293][ERROR][     dns_server.c:312 ] epoll ctl failed, fd = 6, Invalid argument
[2022-08-31 23:51:07,293][ERROR][       smartdns.c:374 ] start dns server failed.
[2022-08-31 23:51:09,215][ERROR][     dns_server.c:5038] bind service [::]:53 failed, Address in use
[2022-08-31 23:51:09,216][ERROR][     dns_server.c:5283] create server socket failed.
[2022-08-31 23:51:09,216][ERROR][     dns_server.c:312 ] epoll ctl failed, fd = 6, Invalid argument
[2022-08-31 23:51:09,216][ERROR][       smartdns.c:374 ] start dns server failed.
[2022-08-31 23:51:14,319][ERROR][     dns_server.c:5038] bind service [::]:53 failed, Address in use
[2022-08-31 23:51:14,319][ERROR][     dns_server.c:5283] create server socket failed.
[2022-08-31 23:51:14,319][ERROR][     dns_server.c:312 ] epoll ctl failed, fd = 6, Invalid argument
[2022-08-31 23:51:14,319][ERROR][       smartdns.c:374 ] start dns server failed.
[2022-08-31 23:51:19,423][ERROR][     dns_server.c:5038] bind service [::]:53 failed, Address in use
[2022-08-31 23:51:19,423][ERROR][     dns_server.c:5283] create server socket failed.
[2022-08-31 23:51:19,423][ERROR][     dns_server.c:312 ] epoll ctl failed, fd = 6, Invalid argument
[2022-08-31 23:51:19,423][ERROR][       smartdns.c:374 ] start dns server failed.
[2022-08-31 23:51:19,449][ERROR][     dns_server.c:5038] bind service [::]:53 failed, Address in use
[2022-08-31 23:51:19,449][ERROR][     dns_server.c:5283] create server socket failed.
[2022-08-31 23:51:19,449][ERROR][     dns_server.c:312 ] epoll ctl failed, fd = 6, Invalid argument
[2022-08-31 23:51:19,449][ERROR][       smartdns.c:374 ] start dns server failed.
[2022-08-31 23:51:24,553][ERROR][     dns_server.c:5038] bind service [::]:53 failed, Address in use
[2022-08-31 23:51:24,553][ERROR][     dns_server.c:5283] create server socket failed.
[2022-08-31 23:51:24,553][ERROR][     dns_server.c:312 ] epoll ctl failed, fd = 6, Invalid argument
[2022-08-31 23:51:24,553][ERROR][       smartdns.c:374 ] start dns server failed.
[2022-08-31 23:51:27,738][ERROR][      fast_ping.c:461 ] sendto 2001::, id 1, Permission denied
[2022-08-31 23:51:41,143][ERROR][      fast_ping.c:461 ] sendto 2001::, id 1, Permission denied
[2022-08-31 23:52:02,550][ERROR][      fast_ping.c:461 ] sendto 2001::, id 1, Permission denied
[2022-08-31 23:55:09,561][ERROR][     dns_server.c:5038] bind service [::]:53 failed, Address in use
[2022-08-31 23:55:09,561][ERROR][     dns_server.c:5283] create server socket failed.
[2022-08-31 23:55:09,561][ERROR][     dns_server.c:312 ] epoll ctl failed, fd = 6, Invalid argument
[2022-08-31 23:55:09,561][ERROR][       smartdns.c:374 ] start dns server failed.
[2022-08-31 23:55:14,665][ERROR][     dns_server.c:5038] bind service [::]:53 failed, Address in use
[2022-08-31 23:55:14,665][ERROR][     dns_server.c:5283] create server socket failed.
[2022-08-31 23:55:14,665][ERROR][     dns_server.c:312 ] epoll ctl failed, fd = 6, Invalid argument
[2022-08-31 23:55:14,665][ERROR][       smartdns.c:374 ] start dns server failed.
[2022-08-31 23:55:19,769][ERROR][     dns_server.c:5038] bind service [::]:53 failed, Address in use
[2022-08-31 23:55:19,769][ERROR][     dns_server.c:5283] create server socket failed.
[2022-08-31 23:55:19,769][ERROR][     dns_server.c:312 ] epoll ctl failed, fd = 6, Invalid argument
[2022-08-31 23:55:19,769][ERROR][       smartdns.c:374 ] start dns server failed.
[2022-08-31 23:55:24,873][ERROR][     dns_server.c:5038] bind service [::]:53 failed, Address in use
[2022-08-31 23:55:24,873][ERROR][     dns_server.c:5283] create server socket failed.
[2022-08-31 23:55:24,873][ERROR][     dns_server.c:312 ] epoll ctl failed, fd = 6, Invalid argument
[2022-08-31 23:55:24,873][ERROR][       smartdns.c:374 ] start dns server failed.
[2022-08-31 23:55:29,975][ERROR][     dns_server.c:5038] bind service [::]:53 failed, Address in use
[2022-08-31 23:55:29,975][ERROR][     dns_server.c:5283] create server socket failed.
[2022-08-31 23:55:29,975][ERROR][     dns_server.c:312 ] epoll ctl failed, fd = 6, Invalid argument
[2022-08-31 23:55:29,975][ERROR][       smartdns.c:374 ] start dns server failed.
[2022-08-31 23:55:35,081][ERROR][     dns_server.c:5038] bind service [::]:53 failed, Address in use
[2022-08-31 23:55:35,081][ERROR][     dns_server.c:5283] create server socket failed.
[2022-08-31 23:55:35,081][ERROR][     dns_server.c:312 ] epoll ctl failed, fd = 6, Invalid argument
[2022-08-31 23:55:35,081][ERROR][       smartdns.c:374 ] start dns server failed.

netstat -tunlp | grep 53 查询后入下。 image

dnsmasq的占用了。首页文档说是配置53时,smart会自动处理dnsmasq的。不知道咋整了,求助。

pymumu commented 2 years ago

所以,你们估计是什么?openwrt官网已经升级了这些基础组件。

用小写r

grep -n "iptables" /etc/init.d/ -r
jxph1123 commented 2 years ago

grep -n "iptables" /etc/init.d/ -r

root@OpenWrt:~# grep -n "iptables" /etc/init.d/ -r
/etc/init.d/dnsfilter:332:      iptables -I FORWARD -m set --match-set blockip dst -m comment --comment "$TAG" -j DROP
/etc/init.d/dnsfilter:333:      iptables -I OUTPUT -m set --match-set blockip dst -m comment --comment "$TAG" -j DROP
/etc/init.d/dnsfilter:337:              iptables-save -t $1 | grep DNSFILTER |\
/etc/init.d/dnsfilter:342:      iptables-save -c | grep -v DNSFILTER | iptables-restore -c
/etc/init.d/dnsfilter:343:      iptables-restore -n <<-EOT
/etc/init.d/dnsfilter:369:      iptables -D FORWARD -m set --match-set blockip dst -m comment --comment "$TAG" -j DROP 2>/dev/null
/etc/init.d/dnsfilter:370:      iptables -D OUTPUT -m set --match-set blockip dst -m comment --comment "$TAG" -j DROP 2>/dev/null
/etc/init.d/dnsmasq:1174:               iptables -t nat -A PREROUTING -m comment --comment "DNSMASQ" -p udp --dport 53 -j REDIRECT --to-ports $dns_port
/etc/init.d/dnsmasq:1194:iptables_clear()
/etc/init.d/dnsmasq:1197:       iptables -t nat -D PREROUTING -m comment --comment "DNSMASQ" -p udp --dport 53 -j REDIRECT --to-ports $dns_port 2>"/dev/null"
/etc/init.d/dnsmasq:1271:       iptables_clear
/etc/init.d/dnsmasq:1298:       iptables_clear
/etc/init.d/mia:47:             iptables -t filter -I MIA  -m mac --mac-source $macaddr -m time --kerneltz --timestart $timeon --timestop $timeoff --weekdays $Z1$Z2$Z3$Z4$Z5$Z6$Z7 -j DROP
/etc/init.d/mia:58:     blackMacAdd=$(iptables -t nat -L $type | grep -w RETURN | grep -w "MAC" | awk '{print $7}')
/etc/init.d/mia:62:                     iptables -t nat -D $type -m mac --mac-source $macaddrb -j RETURN
/etc/init.d/mia:71:  iptables -t filter -N MIA
/etc/init.d/mia:72:  iptables -I INPUT -p udp --dport 53 -m comment --comment "Rule For Control" -j MIA
/etc/init.d/mia:73:  iptables -I INPUT -p tcp --dport 53 -m comment --comment "Rule For Control" -j MIA
/etc/init.d/mia:74:  iptables -t nat -A PREROUTING -p udp --dport 53 -j REDIRECT --to-ports 53 -m comment --comment "Rule For Control"
/etc/init.d/mia:75:  iptables -t nat -A PREROUTING -p tcp --dport 53 -j REDIRECT --to-ports 53 -m comment --comment "Rule For Control"
/etc/init.d/mia:77:  [ $strict -eq 1 ] && iptables -t filter -I FORWARD -m comment --comment "Rule For Control" -j MIA
/etc/init.d/mia:81:  iptables -t filter -D FORWARD -m comment --comment "Rule For Control" -j MIA 2>/dev/null
/etc/init.d/mia:82:  iptables -D INPUT -p udp --dport 53 -m comment --comment "Rule For Control" -j MIA 2>/dev/null
/etc/init.d/mia:83:  iptables -D INPUT -p tcp --dport 53 -m comment --comment "Rule For Control" -j MIA 2>/dev/null
/etc/init.d/mia:84:  iptables -t nat -D PREROUTING -p udp --dport 53 -j REDIRECT --to-ports 53 -m comment --comment "Rule For Control" 2>/dev/null
/etc/init.d/mia:85:  iptables -t nat -D PREROUTING -p tcp --dport 53 -j REDIRECT --to-ports 53 -m comment --comment "Rule For Control" 2>/dev/null
/etc/init.d/mia:86:  iptables -t filter -F MIA 2>/dev/null
/etc/init.d/mia:87:  iptables -t filter -X MIA 2>/dev/null
/etc/init.d/miniupnpd:189:              iptables -L MINIUPNPD >/dev/null 2>/dev/null || fw3 reload
/etc/init.d/miniupnpd:206:      iptables -t nat -F MINIUPNPD 2>/dev/null
/etc/init.d/miniupnpd:207:      iptables -t filter -F MINIUPNPD 2>/dev/null
/etc/init.d/qca-nss-ecm:73:             sysctl -w net.bridge.bridge-nf-call-iptables=1
/etc/init.d/qca-nss-ecm:79:     sysctl -w net.bridge.bridge-nf-call-iptables=0
/etc/init.d/qca-nss-ecm:114:            echo 'net.bridge.bridge-nf-call-iptables=1' >> /etc/sysctl.d/qca-nss-ecm.conf
/etc/init.d/qca-nss-ecm:132:    sed '/net.bridge.bridge-nf-call-iptables=1/d' -i /etc/sysctl.d/qca-nss-ecm.conf
/etc/init.d/shadowsocksr:691:                   if ! (iptables-save -t filter | grep SSR-SERVER-RULE >/dev/null); then
/etc/init.d/shadowsocksr:692:                           iptables -N SSR-SERVER-RULE && iptables -t filter -I INPUT -j SSR-SERVER-RULE
/etc/init.d/shadowsocksr:708:           iptables -t filter -A SSR-SERVER-RULE -p tcp --dport $(uci_get_by_name $1 server_port) -j ACCEPT
/etc/init.d/shadowsocksr:709:           iptables -t filter -A SSR-SERVER-RULE -p udp --dport $(uci_get_by_name $1 server_port) -j ACCEPT
/etc/init.d/shadowsocksr:720:                   iptables-save -t filter | grep SSR-SERVER-RULE | sed -e "s/^-A INPUT/-I INPUT/"
/etc/init.d/shadowsocksr:724:                   iptables-save -c | grep -v "SSR-SERVER" | iptables-restore -c
/etc/init.d/shadowsocksr:725:                   iptables-restore -n <<-EOT
/etc/init.d/shadowsocksr:858:   local srulecount=$(iptables -L | grep SSR-SERVER-RULE | wc -l)
/etc/init.d/shadowsocksr:860:           iptables -F SSR-SERVER-RULE
/etc/init.d/shadowsocksr:861:           iptables -t filter -D INPUT -j SSR-SERVER-RULE
/etc/init.d/shadowsocksr:862:           iptables -X SSR-SERVER-RULE 2>/dev/null
/etc/init.d/smartdns:118:               iptables -t nat -D PREROUTING -p udp -d "$IP" --dport 53 -j REDIRECT --to-ports "$OLD_PORT" >/dev/null 2>&1
/etc/init.d/smartdns:119:               iptables -t nat -D PREROUTING -p tcp -d "$IP" --dport 53 -j REDIRECT --to-ports "$OLD_PORT" >/dev/null 2>&1
pymumu commented 2 years ago

贴一下这个文件:/etc/init.d/dnsmasq 你这个文件和openwrt原生不一样。

pymumu commented 2 years ago

看了下,你把这个设置下就好了

uci delete dhcp.@dnsmasq[0].dns_redirect
uci commit dhcp
/etc/init.d/dnsmasq restart
/etc/init.d/smartdns restart

你这个固件可能是被打过强制修改dns的补丁了,这个和openwrt官方的不一样。

jxph1123 commented 2 years ago
#!/bin/sh /etc/rc.common
# Copyright (C) 2007-2012 OpenWrt.org

START=19

USE_PROCD=1
PROG=/usr/sbin/dnsmasq

ADD_LOCAL_DOMAIN=1
ADD_LOCAL_HOSTNAME=1
ADD_WAN_FQDN=0
ADD_LOCAL_FQDN=""

BASECONFIGFILE="/var/etc/dnsmasq.conf"
BASEHOSTFILE="/tmp/hosts/dhcp"
TRUSTANCHORSFILE="/usr/share/dnsmasq/trust-anchors.conf"
TIMEVALIDFILE="/var/state/dnsmasqsec"
BASEDHCPSTAMPFILE="/var/run/dnsmasq"
DHCPBOGUSHOSTNAMEFILE="/usr/share/dnsmasq/dhcpbogushostname.conf"
RFC6761FILE="/usr/share/dnsmasq/rfc6761.conf"
DHCPSCRIPT="/usr/lib/dnsmasq/dhcp-script.sh"
DHCPSCRIPT_DEPENDS="/usr/share/libubox/jshn.sh /usr/bin/jshn /bin/ubus"

DNSMASQ_DHCP_VER=4

dnsmasq_ignore_opt() {
    local opt="$1"

    if [ -z "$dnsmasq_features" ]; then
        dnsmasq_features="$(dnsmasq --version | grep -m1 'Compile time options:' | cut -d: -f2) "
        [ "${dnsmasq_features#* DHCP }" = "$dnsmasq_features" ] || dnsmasq_has_dhcp=1
        [ "${dnsmasq_features#* DHCPv6 }" = "$dnsmasq_features" ] || dnsmasq_has_dhcp6=1
        [ "${dnsmasq_features#* DNSSEC }" = "$dnsmasq_features" ] || dnsmasq_has_dnssec=1
        [ "${dnsmasq_features#* TFTP }" = "$dnsmasq_features" ] || dnsmasq_has_tftp=1
        [ "${dnsmasq_features#* ipset }" = "$dnsmasq_features" ] || dnsmasq_has_ipset=1
    fi

    case "$opt" in
        dhcp-duid|\
        ra-param)
            [ -z "$dnsmasq_has_dhcp6" ] ;;
        dhcp-*|\
        bootp-*|\
        pxe-*)
            [ -z "$dnsmasq_has_dhcp" ] ;;
        dnssec*|\
        trust-anchor)
            if [ -z "$dnsmasq_has_dnssec" ]; then
                echo "dnsmasq: \"$opt\" requested, but dnssec support is not available" >&2
                exit 1
            fi
            return 1
            ;;
        tftp-*)
            [ -z "$dnsmasq_has_tftp" ] ;;
        ipset)
            [ -z "$dnsmasq_has_ipset" ] ;;
        *)
            return 1
    esac
}

xappend() {
    local value="${1#--}"
    local opt="${value%%=*}"

    if ! dnsmasq_ignore_opt "$opt"; then
        echo "$value" >>$CONFIGFILE_TMP
    fi
}

hex_to_hostid() {
    local var="$1"
    local hex="${2#0x}" # strip optional "0x" prefix

    if [ -n "${hex//[0-9a-fA-F]/}" ]; then
        # is invalid hex literal
        return 1
    fi

    # convert into host id
    export "$var=$(
        printf "%0x:%0x" \
        $(((0x$hex >> 16) % 65536)) \
        $(( 0x$hex        % 65536))
        )"

    return 0
}

dhcp_calc() {
    local ip="$1"
    local res=0

    while [ -n "$ip" ]; do
        part="${ip%%.*}"
        res="$(($res * 256))"
        res="$(($res + $part))"
        [ "${ip%.*}" != "$ip" ] && ip="${ip#*.}" || ip=
    done
    echo "$res"
}

dhcp_check() {
    local ifname="$1"
    local stamp="${BASEDHCPSTAMPFILE_CFG}.${ifname}.dhcp"
    local rv=0

    [ -s "$stamp" ] && return $(cat "$stamp")

    # If interface is down, skip it.
    # The init script will be called again once the link is up
    case "$(devstatus "$ifname" | jsonfilter -e @.up)" in
        false) return 1;;
    esac

    udhcpc -n -q -s /bin/true -t 1 -i "$ifname" >&- && rv=1 || rv=0

    echo $rv > "$stamp"
    return $rv
}

log_once() {
    pidof dnsmasq >/dev/null || \
        logger -t dnsmasq "$@"
}

has_handler() {
    local file

    for file in /etc/hotplug.d/dhcp/* /etc/hotplug.d/tftp/* /etc/hotplug.d/neigh/*; do
        [ -f "$file" ] && return 0
    done

    return 1
}

append_bool() {
    local section="$1"
    local option="$2"
    local value="$3"
    local default="$4"
    local _loctmp
    [ -z "$default" ] && default="0"
    config_get_bool _loctmp "$section" "$option" "$default"
    [ $_loctmp -gt 0 ] && xappend "$value"
}

append_parm() {
    local section="$1"
    local option="$2"
    local switch="$3"
    local default="$4"
    local _loctmp
    config_get _loctmp "$section" "$option" "$default"
    [ -z "$_loctmp" ] && return 0
    xappend "$switch=$_loctmp"
}

append_server() {
    xappend "--server=$1"
}

append_rev_server() {
    xappend "--rev-server=$1"
}

append_address() {
    xappend "--address=$1"
}

append_ipset() {
    xappend "--ipset=$1"
}

append_connmark_allowlist() {
    xappend "--connmark-allowlist=$1"
}

append_interface() {
    network_get_device ifname "$1" || ifname="$1"
    xappend "--interface=$ifname"
}

append_listenaddress() {
    xappend "--listen-address=$1"
}

append_notinterface() {
    network_get_device ifname "$1" || ifname="$1"
    xappend "--except-interface=$ifname"
}

ismounted() {
    local filename="$1"
    local dirname
    for dirname in $EXTRA_MOUNT ; do
        case "$filename" in
            "${dirname}/"* | "${dirname}" )
                return 0
                ;;
        esac
    done

    return 1
}

append_addnhosts() {
    ismounted "$1" || append EXTRA_MOUNT "$1"
    xappend "--addn-hosts=$1"
}

append_bogusnxdomain() {
    xappend "--bogus-nxdomain=$1"
}

append_pxe_service() {
    xappend "--pxe-service=$1"
}

append_interface_name() {
    xappend "--interface-name=$1,$2"
}

filter_dnsmasq() {
    local cfg="$1" func="$2" match_cfg="$3" found_cfg

    # use entry when no instance entry set, or if it matches
    config_get found_cfg "$cfg" "instance"
    if [ -z "$found_cfg" ] || [ "$found_cfg" = "$match_cfg" ]; then
        $func $cfg
    fi
}

dhcp_subscrid_add() {
    local cfg="$1"

    config_get networkid "$cfg" networkid
    [ -n "$networkid" ] || return 0

    config_get subscriberid "$cfg" subscriberid
    [ -n "$subscriberid" ] || return 0

    xappend "--dhcp-subscrid=set:$networkid,$subscriberid"

    config_get_bool force "$cfg" force 0

    dhcp_option_add "$cfg" "$networkid" "$force"
}

dhcp_remoteid_add() {
    local cfg="$1"

    config_get networkid "$cfg" networkid
    [ -n "$networkid" ] || return 0

    config_get remoteid "$cfg" remoteid
    [ -n "$remoteid" ] || return 0

    xappend "--dhcp-remoteid=set:$networkid,$remoteid"

    config_get_bool force "$cfg" force 0

    dhcp_option_add "$cfg" "$networkid" "$force"
}

dhcp_circuitid_add() {
    # TODO: DHCPV6 does not have circuitid; catch "option6:"
    local cfg="$1"

    config_get networkid "$cfg" networkid
    [ -n "$networkid" ] || return 0

    config_get circuitid "$cfg" circuitid
    [ -n "$circuitid" ] || return 0

    xappend "--dhcp-circuitid=set:$networkid,$circuitid"

    config_get_bool force "$cfg" force 0

    dhcp_option_add "$cfg" "$networkid" "$force"
}

dhcp_userclass_add() {
    local cfg="$1"

    config_get networkid "$cfg" networkid
    [ -n "$networkid" ] || return 0

    config_get userclass "$cfg" userclass
    [ -n "$userclass" ] || return 0

    xappend "--dhcp-userclass=set:$networkid,$userclass"

    config_get_bool force "$cfg" force 0

    dhcp_option_add "$cfg" "$networkid" "$force"
}

dhcp_vendorclass_add() {
    # TODO: DHCPV6 vendor class has stricter definitions; catch? fixup?
    local cfg="$1"

    config_get networkid "$cfg" networkid
    [ -n "$networkid" ] || return 0

    config_get vendorclass "$cfg" vendorclass
    [ -n "$vendorclass" ] || return 0

    xappend "--dhcp-vendorclass=set:$networkid,$vendorclass"

    config_get_bool force "$cfg" force 0

    dhcp_option_add "$cfg" "$networkid" "$force"
}

dhcp_match_add() {
    local cfg="$1"

    config_get networkid "$cfg" networkid
    [ -n "$networkid" ] || return 0

    config_get match "$cfg" match
    [ -n "$match" ] || return 0

    xappend "--dhcp-match=set:$networkid,$match"

    config_get_bool force "$cfg" force 0

    dhcp_option_add "$cfg" "$networkid" "$force"
}

dhcp_host_add() {
    local cfg="$1"
    local hosttag nametime addrs duids macs tags mtags

    config_get_bool force "$cfg" force 0

    config_get networkid "$cfg" networkid
    [ -n "$networkid" ] && dhcp_option_add "$cfg" "$networkid" "$force"

    config_get_bool enable "$cfg" enable 1
    [ "$enable" = "0" ] && return 0

    config_get name "$cfg" name
    config_get ip "$cfg" ip
    config_get hostid "$cfg" hostid

    [ -z "$ip" ] && [ -z "$name" ] && [ -z "$hostid" ] && return 0

    config_get_bool dns "$cfg" dns 0
    [ "$dns" = "1" ] && [ -n "$ip" ] && [ -n "$name" ] && {
        echo "$ip $name${DOMAIN:+.$DOMAIN}" >> $HOSTFILE_TMP
    }

    config_get mac "$cfg" mac
    config_get duid "$cfg" duid
    config_get tag "$cfg" tag

    add_tag() {
        mtags="${mtags}tag:$1,"
    }
    config_list_foreach "$cfg" match_tag add_tag

    if [ -n "$mac" ]; then
        # --dhcp-host=00:20:e0:3b:13:af,192.168.0.199,lap
        # many MAC are possible to track a laptop ON/OFF dock
        for m in $mac; do append macs "$m" ","; done
    fi

    if [ $DNSMASQ_DHCP_VER -eq 6 ] && [ -n "$duid" ]; then
        # --dhcp-host=id:00:03:00:01:12:00:00:01:02:03,[::beef],lap
        # one (virtual) machine gets one DUID per RFC3315
        duids="id:${duid// */}"
    fi

    if [ -z "$macs" ] && [ -z "$duids" ]; then
        # --dhcp-host=lap,192.168.0.199,[::beef]
        [ -n "$name" ] || return 0
        macs="$name"
        name=""
    fi

    if [ -n "$hostid" ]; then
        hex_to_hostid hostid "$hostid"
    fi

    if [ -n "$tag" ]; then
        for t in $tag; do append tags "$t" ",set:"; done
    fi

    config_get_bool broadcast "$cfg" broadcast 0
    config_get leasetime "$cfg" leasetime

    [ "$broadcast" = "0" ] && broadcast= || broadcast=",set:needs-broadcast"

    hosttag="${networkid:+,set:${networkid}}${tags:+,set:${tags}}$broadcast"
    nametime="${name:+,$name}${leasetime:+,$leasetime}"

    if [ $DNSMASQ_DHCP_VER -eq 6 ]; then
        addrs="${ip:+,$ip}${hostid:+,[::$hostid]}"
        xappend "--dhcp-host=$mtags$macs${duids:+,$duids}$hosttag$addrs$nametime"
    else
        xappend "--dhcp-host=$mtags$macs$hosttag${ip:+,$ip}$nametime"
    fi
}

dhcp_this_host_add() {
    local net="$1"
    local ifname="$2"
    local mode="$3"
    local routerstub routername ifdashname
    local lanaddr lanaddr6 lanaddrs6 ulaprefix

    if [ "$mode" -gt 0 ] ; then
        ifdashname="${ifname//./-}"
        routerstub="$( md5sum /etc/os-release )"
        routerstub="router-${routerstub// */}"
        routername="$( uci_get system @system[0] hostname $routerstub )"

        if [ "$mode" -gt 1 ] ; then
            if [ "$mode" -gt 2 ] ; then
                if [ "$mode" -gt 3 ] ; then
                    append_interface_name "$ifdashname.$routername.$DOMAIN" "$ifname"
                fi

                append_interface_name "$routername.$DOMAIN" "$ifname"
            fi

            # All IP addresses discovered by dnsmasq will be labeled (except fe80::)
            append_interface_name "$routername" "$ifname"

        else
            # This uses a static host file entry for only limited addresses.
            # Use dnsmasq option "--expandhosts" to enable FQDN on host files.
            ulaprefix="$(uci_get network @globals[0] ula_prefix)"
            network_get_ipaddr lanaddr "$net"
            network_get_ipaddrs6 lanaddrs6 "$net"

            if [ -n "$lanaddr" ] ; then
                dhcp_domain_add "" "$routername" "$lanaddr"
            fi

            if [ -n "$ulaprefix" ] && [ -n "$lanaddrs6" ] ; then
                for lanaddr6 in $lanaddrs6 ; do
                    case "$lanaddr6" in
                    "${ulaprefix%%:/*}"*)
                        dhcp_domain_add "" "$routername" "$lanaddr6"
                        ;;
                    esac
                done
            fi
        fi
    fi
}

dhcp_tag_add() {
    # NOTE: dnsmasq has explicit "option6:" prefix for DHCPv6 so no collisions
    local cfg="$1"

    tag="$cfg"

    [ -n "$tag" ] || return 0

    config_get_bool force "$cfg" force 0
    [ "$force" = "0" ] && force=

    config_get option "$cfg" dhcp_option
    for o in $option; do
        xappend "--dhcp-option${force:+-force}=tag:$tag,$o"
    done
}

dhcp_mac_add() {
    local cfg="$1"

    config_get networkid "$cfg" networkid
    [ -n "$networkid" ] || return 0

    config_get mac "$cfg" mac
    [ -n "$mac" ] || return 0

    xappend "--dhcp-mac=$networkid,$mac"

    dhcp_option_add "$cfg" "$networkid"
}

dhcp_boot_add() {
    # TODO: BOOTURL is different between DHCPv4 and DHCPv6
    local cfg="$1"

    config_get networkid "$cfg" networkid

    config_get filename "$cfg" filename
    [ -n "$filename" ] || return 0

    config_get servername "$cfg" servername
    config_get serveraddress "$cfg" serveraddress

    [ -n "$serveraddress" ] && [ ! -n "$servername" ] && return 0

    xappend "--dhcp-boot=${networkid:+net:$networkid,}${filename}${servername:+,$servername}${serveraddress:+,$serveraddress}"

    config_get_bool force "$cfg" force 0

    dhcp_option_add "$cfg" "$networkid" "$force"
}

dhcp_add() {
    local cfg="$1"
    local dhcp6range="::"
    local nettag
    local tags

    config_get net "$cfg" interface
    [ -n "$net" ] || return 0

    config_get networkid "$cfg" networkid
    [ -n "$networkid" ] || networkid="$net"

    network_get_device ifname "$net" || return 0

    [ "$cachelocal" = "0" ] && network_get_dnsserver dnsserver "$net" && {
        DNS_SERVERS="$DNS_SERVERS $dnsserver"
    }

    append_bool "$cfg" ignore "--no-dhcp-interface=$ifname" && {
        # Many ISP do not have useful names for DHCP customers (your WAN).
        dhcp_this_host_add "$net" "$ifname" "$ADD_WAN_FQDN"
        return 0
    }

    network_get_subnet subnet "$net" || return 0
    network_get_protocol proto "$net" || return 0

    # Do not support non-static interfaces for now
    [ static = "$proto" ] || return 0

    # Override interface netmask with dhcp config if applicable
    config_get netmask "$cfg" netmask "${subnet##*/}"

    #check for an already active dhcp server on the interface, unless 'force' is set
    config_get_bool force "$cfg" force 0
    [ $force -gt 0 ] || dhcp_check "$ifname" || {
        logger -t dnsmasq \
            "found already running DHCP-server on interface '$ifname'" \
            "refusing to start, use 'option force 1' to override"
        return 0
    }

    config_get start "$cfg" start 100
    config_get limit "$cfg" limit 150
    config_get leasetime "$cfg" leasetime 12h
    config_get options "$cfg" options
    config_get_bool dynamicdhcp "$cfg" dynamicdhcp 1

    config_get dhcpv4 "$cfg" dhcpv4
    config_get dhcpv6 "$cfg" dhcpv6

    config_get ra "$cfg" ra
    config_get ra_management "$cfg" ra_management
    config_get ra_preference "$cfg" ra_preference
    config_get dns "$cfg" dns

    config_list_foreach "$cfg" "interface_name" append_interface_name "$ifname"

    # Put the router host name on this DHCP served interface address(es)
    dhcp_this_host_add "$net" "$ifname" "$ADD_LOCAL_FQDN"

    start="$( dhcp_calc "$start" )"

    add_tag() {
        tags="${tags}tag:$1,"
    }
    config_list_foreach "$cfg" tag add_tag

    nettag="${networkid:+set:${networkid},}"

    if [ "$limit" -gt 0 ] ; then
        limit=$((limit-1))
    fi

    eval "$(ipcalc.sh "${subnet%%/*}" $netmask $start $limit)"

    if [ "$dynamicdhcp" = "0" ] ; then
        END="static"
        dhcp6range="::,static"
    else
        dhcp6range="::1000,::ffff"
    fi

    if [ "$dhcpv4" != "disabled" ] ; then
        xappend "--dhcp-range=$tags$nettag$START,$END,$NETMASK,$leasetime${options:+ $options}"
    fi

    if [ $DNSMASQ_DHCP_VER -eq 6 ] && [ "$ra" = "server" ] ; then
        # Note: dnsmasq cannot just be a DHCPv6 server (all-in-1)
        # and let some other machine(s) send RA pointing to it.

        case $ra_preference in
        *high*)
            xappend "--ra-param=$ifname,high,0,7200"
            ;;
        *low*)
            xappend "--ra-param=$ifname,low,0,7200"
            ;;
        *)
            # Send UNSOLICITED RA at default interval and live for 2 hours.
            # TODO: convert flexible lease time into route life time (only seconds).
            xappend "--ra-param=$ifname,0,7200"
            ;;
        esac

        if [ "$dhcpv6" = "disabled" ] ; then
            ra_management="3"
        fi

        case $ra_management in
        0)
            # SLACC with DCHP for extended options
            xappend "--dhcp-range=$nettag::,constructor:$ifname,ra-stateless,ra-names"
            ;;
        2)
            # DHCP address and RA only for management redirection
            xappend "--dhcp-range=$nettag$dhcp6range,constructor:$ifname,$leasetime"
            ;;
        3)
            # SLAAC only but dnsmasq attempts to link HOSTNAME, DHCPv4 MAC, and SLAAC
            xappend "--dhcp-range=$nettag::,constructor:$ifname,ra-only,ra-names"
            ;;
        *)
            # SLAAC and full DHCP
            xappend "--dhcp-range=$nettag$dhcp6range,constructor:$ifname,slaac,ra-names,$leasetime"
            ;;
        esac

        if [ -n "$dns" ]; then
            dnss=""
            for d in $dns; do append dnss "[$d]" ","; done
        else
            dnss="[::]"
        fi

        dhcp_option_append "option6:dns-server,$dnss" "$networkid"
    fi

    dhcp_option_add "$cfg" "$networkid" 0
    dhcp_option_add "$cfg" "$networkid" 2
}

dhcp_option_append() {
    local option="$1"
    local networkid="$2"
    local force="$3"

    xappend "--dhcp-option${force:+-force}=${networkid:+$networkid,}$option"
}

dhcp_option_add() {
    # NOTE: dnsmasq has explicit "option6:" prefix for DHCPv6 so no collisions
    local cfg="$1"
    local networkid="$2"
    local force="$3"
    local opt="dhcp_option"

    [ "$force" = "0" ] && force=
    [ "$force" = "2" ] && opt="dhcp_option_force"

    local list_len
    config_get list_len "$cfg" "${opt}_LENGTH"

    if [ -n "$list_len" ]; then
        config_list_foreach "$cfg" "$opt" dhcp_option_append "$networkid" "$force"
    else
        config_get dhcp_option "$cfg" "$opt"

        [ -n "$dhcp_option" ] && echo "Warning: the 'option $opt' syntax is deprecated, use 'list $opt'" >&2

        local option
        for option in $dhcp_option; do
            dhcp_option_append "$option" "$networkid" "$force"
        done
    fi
}

dhcp_domain_add() {
    local cfg="$1"
    local ip name names record

    config_get names "$cfg" name "$2"
    [ -n "$names" ] || return 0

    config_get ip "$cfg" ip "$3"
    [ -n "$ip" ] || return 0

    for name in $names; do
        record="${record:+$record }$name"
    done

    echo "$ip $record" >> $HOSTFILE_TMP
}

dhcp_srv_add() {
    local cfg="$1"

    config_get srv "$cfg" srv
    [ -n "$srv" ] || return 0

    config_get target "$cfg" target
    [ -n "$target" ] || return 0

    config_get port "$cfg" port
    [ -n "$port" ] || return 0

    config_get class "$cfg" class
    config_get weight "$cfg" weight

    local service="$srv,$target,$port${class:+,$class${weight:+,$weight}}"

    xappend "--srv-host=$service"
}

dhcp_mx_add() {
    local cfg="$1"
    local domain relay pref

    config_get domain "$cfg" domain
    [ -n "$domain" ] || return 0

    config_get relay "$cfg" relay
    [ -n "$relay" ] || return 0

    config_get pref "$cfg" pref 0

    local service="$domain,$relay,$pref"

    xappend "--mx-host=$service"
}

dhcp_cname_add() {
    local cfg="$1"
    local cname target

    config_get cname "$cfg" cname
    [ -n "$cname" ] || return 0

    config_get target "$cfg" target
    [ -n "$target" ] || return 0

    xappend "--cname=${cname},${target}"
}

dhcp_hostrecord_add() {
    local cfg="$1"
    local names addresses record val

    config_get names "$cfg" name "$2"
    if [ -z "$names" ]; then
        return 0
    fi

    config_get addresses "$cfg" ip "$3"
    if [ -z "$addresses" ]; then
        return 0
    fi

    for val in $names $addresses; do
        record="${record:+$record,}$val"
    done

    xappend "--host-record=$record"
}

dhcp_relay_add() {
    local cfg="$1"
    local local_addr server_addr interface

    config_get local_addr "$cfg" local_addr
    [ -n "$local_addr" ] || return 0

    config_get server_addr "$cfg" server_addr
    [ -n "$server_addr" ] || return 0

    config_get interface "$cfg" interface
    if [ -z "$interface" ]; then
        xappend "--dhcp-relay=$local_addr,$server_addr"
    else
        network_get_device ifname "$interface" || return
        xappend "--dhcp-relay=$local_addr,$server_addr,$ifname"
    fi
}

dnsmasq_ipset_add() {
    local cfg="$1"
    local ipsets domains

    add_ipset() {
        ipsets="${ipsets:+$ipsets,}$1"
    }

    add_domain() {
        # leading '/' is expected
        domains="$domains/$1"
    }

    config_list_foreach "$cfg" "name" add_ipset
    config_list_foreach "$cfg" "domain" add_domain

    if [ -z "$ipsets" ] || [ -z "$domains" ]; then
        return 0
    fi

    xappend "--ipset=$domains/$ipsets"
}

dnsmasq_start()
{
    local cfg="$1"
    local disabled user_dhcpscript
    local resolvfile resolvdir localuse=0

    config_get_bool disabled "$cfg" disabled 0
    [ "$disabled" -gt 0 ] && return 0

    # reset list of DOMAINS, DNS servers and EXTRA mounts (for each dnsmasq instance)
    DNS_SERVERS=""
    DOMAIN=""
    EXTRA_MOUNT=""
    CONFIGFILE="${BASECONFIGFILE}.${cfg}"
    CONFIGFILE_TMP="${CONFIGFILE}.$$"
    HOSTFILE="${BASEHOSTFILE}.${cfg}"
    HOSTFILE_TMP="${HOSTFILE}.$$"
    HOSTFILE_DIR="$(dirname "$HOSTFILE")"
    BASEDHCPSTAMPFILE_CFG="${BASEDHCPSTAMPFILE}.${cfg}"

    # before we can call xappend
    umask u=rwx,g=rx,o=rx
    mkdir -p /var/run/dnsmasq/
    mkdir -p $(dirname $CONFIGFILE)
    mkdir -p "$HOSTFILE_DIR"
    mkdir -p /var/lib/misc
    chown dnsmasq:dnsmasq /var/run/dnsmasq

    echo "# auto-generated config file from /etc/config/dhcp" > $CONFIGFILE_TMP
    echo "# auto-generated config file from /etc/config/dhcp" > $HOSTFILE_TMP

    local dnsmasqconffile="/etc/dnsmasq.${cfg}.conf"
    if [ ! -r "$dnsmasqconffile" ]; then
        dnsmasqconffile=/etc/dnsmasq.conf
    fi

    # if we did this last, we could override auto-generated config
    [ -f "${dnsmasqconffile}" ] && {
        xappend "--conf-file=${dnsmasqconffile}"
    }

    $PROG --version | grep -osqE "^Compile time options:.* DHCPv6( |$)" && DHCPv6CAPABLE=1 || DHCPv6CAPABLE=0

    if [ -x /usr/sbin/odhcpd ] && [ -x /etc/init.d/odhcpd ] ; then
        local odhcpd_is_main odhcpd_is_enabled
        config_get odhcpd_is_main odhcpd maindhcp 0
        /etc/init.d/odhcpd enabled && odhcpd_is_enabled=1 || odhcpd_is_enabled=0

        if [ "$odhcpd_is_enabled" -eq 0 ] && [ "$DHCPv6CAPABLE" -eq 1 ] ; then
            # DHCP V4 and V6 in DNSMASQ
            DNSMASQ_DHCP_VER=6
        elif [ "$odhcpd_is_main" -gt 0 ] ; then
            # ODHCPD is doing it all
            DNSMASQ_DHCP_VER=0
        else
            # You have ODHCPD but use DNSMASQ for DHCPV4
            DNSMASQ_DHCP_VER=4
        fi

    elif [ "$DHCPv6CAPABLE" -eq 1 ] ; then
        # DHCP V4 and V6 in DNSMASQ
        DNSMASQ_DHCP_VER=6
    else
        DNSMASQ_DHCP_VER=4
    fi

    # Allow DHCP/DHCPv6 to be handled by ISC DHCPD
    if [ -x /usr/sbin/dhcpd ] ; then
        if [ -x /etc/init.d/dhcpd ] ; then
            /etc/init.d/dhcpd enabled && DNSMASQ_DHCP_VER=0
        fi
        if [ -x /etc/init.d/dhcpd6 ] && [ "$DNSMASQ_DHCP_VER" -gt 0 ] ; then
            /etc/init.d/dhcpd6 enabled && DNSMASQ_DHCP_VER=4
        fi
    fi

    append_bool "$cfg" authoritative "--dhcp-authoritative"
    append_bool "$cfg" nodaemon "--no-daemon"
    append_bool "$cfg" domainneeded "--domain-needed"
    append_bool "$cfg" filterwin2k "--filterwin2k"
    append_bool "$cfg" nohosts "--no-hosts"
    append_bool "$cfg" nonegcache "--no-negcache"
    append_bool "$cfg" strictorder "--strict-order"
    append_bool "$cfg" logqueries "--log-queries=extra"
    append_bool "$cfg" noresolv "--no-resolv"
    append_bool "$cfg" localise_queries "--localise-queries"
    append_bool "$cfg" readethers "--read-ethers"

    local instance_name="dnsmasq.$cfg"
    if [ "$cfg" = "$DEFAULT_INSTANCE" ]; then
        instance_name="dnsmasq"
    fi
    config_get_bool dbus "$cfg" "dbus" 0
    [ $dbus -gt 0 ] && xappend "--enable-dbus=uk.org.thekelleys.$instance_name"
    config_get_bool ubus "$cfg" "ubus" 1
    [ $ubus -gt 0 ] && xappend "--enable-ubus=$instance_name"

    append_bool "$cfg" expandhosts "--expand-hosts"
    config_get tftp_root "$cfg" "tftp_root"
    [ -n "$tftp_root" ] && mkdir -p "$tftp_root" && append_bool "$cfg" enable_tftp "--enable-tftp"
    append_bool "$cfg" tftp_no_fail "--tftp-no-fail"
    append_bool "$cfg" nonwildcard "--bind-dynamic" 1
    append_bool "$cfg" fqdn "--dhcp-fqdn"
    append_bool "$cfg" proxydnssec "--proxy-dnssec"
    append_bool "$cfg" localservice "--local-service"
    append_bool "$cfg" logdhcp "--log-dhcp"
    append_bool "$cfg" quietdhcp "--quiet-dhcp"
    append_bool "$cfg" sequential_ip "--dhcp-sequential-ip"
    append_bool "$cfg" allservers "--all-servers"
    append_bool "$cfg" noping "--no-ping"
    append_bool "$cfg" rapidcommit "--dhcp-rapid-commit"
    append_bool "$cfg" scriptarp "--script-arp"

    append_bool "$cfg" filter_aaaa "--filter-aaaa"

    append_parm "$cfg" logfacility "--log-facility"

    append_parm "$cfg" mini_ttl "--min-ttl"

    append_parm "$cfg" cachesize "--cache-size"
    append_parm "$cfg" dnsforwardmax "--dns-forward-max"
    append_parm "$cfg" port "--port"
    append_parm "$cfg" ednspacket_max "--edns-packet-max"
    append_parm "$cfg" dhcpleasemax "--dhcp-lease-max"
    append_parm "$cfg" "queryport" "--query-port"
    append_parm "$cfg" "minport" "--min-port"
    append_parm "$cfg" "maxport" "--max-port"
    append_parm "$cfg" "domain" "--domain"
    append_parm "$cfg" "local" "--local"
    config_list_foreach "$cfg" "listen_address" append_listenaddress
    config_list_foreach "$cfg" "server" append_server
    config_list_foreach "$cfg" "rev_server" append_rev_server
    config_list_foreach "$cfg" "address" append_address
    config_list_foreach "$cfg" "ipset" append_ipset

    local connmark_allowlist_enable
    config_get connmark_allowlist_enable "$cfg" connmark_allowlist_enable 0
    [ "$connmark_allowlist_enable" -gt 0 ] && {
        append_parm "$cfg" "connmark_allowlist_enable" "--connmark-allowlist-enable"
        config_list_foreach "$cfg" "connmark_allowlist" append_connmark_allowlist
    }

    [ -n "$BOOT" ] || {
        config_list_foreach "$cfg" "interface" append_interface
        config_list_foreach "$cfg" "notinterface" append_notinterface
    }
    config_get_bool ignore_hosts_dir "$cfg" ignore_hosts_dir 0
    if [ "$ignore_hosts_dir" = "1" ]; then
        xappend "--addn-hosts=$HOSTFILE"
        append EXTRA_MOUNT "$HOSTFILE"
    else
        xappend "--addn-hosts=$HOSTFILE_DIR"
        append EXTRA_MOUNT "$HOSTFILE_DIR"
    fi
    config_list_foreach "$cfg" "addnhosts" append_addnhosts
    config_list_foreach "$cfg" "bogusnxdomain" append_bogusnxdomain
    append_parm "$cfg" "leasefile" "--dhcp-leasefile" "/tmp/dhcp.leases"
    append_parm "$cfg" "serversfile" "--servers-file"
    append_parm "$cfg" "tftp_root" "--tftp-root"
    append_parm "$cfg" "dhcp_boot" "--dhcp-boot"
    append_parm "$cfg" "local_ttl" "--local-ttl"
    append_parm "$cfg" "max_ttl" "--max-ttl"
    append_parm "$cfg" "min_cache_ttl" "--min-cache-ttl"
    append_parm "$cfg" "max_cache_ttl" "--max-cache-ttl"
    append_parm "$cfg" "pxe_prompt" "--pxe-prompt"
    append_parm "$cfg" "tftp_unique_root" "--tftp-unique-root"
    config_list_foreach "$cfg" "pxe_service" append_pxe_service
    config_get DOMAIN "$cfg" domain

    config_get_bool ADD_LOCAL_DOMAIN "$cfg" add_local_domain 1
    config_get_bool ADD_LOCAL_HOSTNAME "$cfg" add_local_hostname 1
    config_get ADD_LOCAL_FQDN "$cfg" add_local_fqdn ""
    config_get ADD_WAN_FQDN "$cfg" add_wan_fqdn 0

    if [ -z "$ADD_LOCAL_FQDN" ] ; then
        # maintain support for previous UCI
        ADD_LOCAL_FQDN="$ADD_LOCAL_HOSTNAME"
    fi

    config_get user_dhcpscript $cfg dhcpscript
    if has_handler || [ -n "$user_dhcpscript" ]; then
        xappend "--dhcp-script=$DHCPSCRIPT"
        xappend "--script-arp"
    fi

    config_get leasefile $cfg leasefile "/tmp/dhcp.leases"
    [ -n "$leasefile" ] && [ ! -e "$leasefile" ] && touch "$leasefile"
    config_get_bool cachelocal "$cfg" cachelocal 1

    config_get_bool noresolv "$cfg" noresolv 0
    if [ "$noresolv" != "1" ]; then
        config_get resolvfile "$cfg" resolvfile /tmp/resolv.conf.d/resolv.conf.auto
        [ -n "$resolvfile" ] && [ ! -e "$resolvfile" ] && touch "$resolvfile"
        xappend "--resolv-file=$resolvfile"
        [ "$resolvfile" = "/tmp/resolv.conf.d/resolv.conf.auto" ] && localuse=1
        resolvdir="$(dirname "$resolvfile")"
    fi
    config_get_bool localuse "$cfg" localuse "$localuse"

    config_get hostsfile "$cfg" dhcphostsfile
    [ -e "$hostsfile" ] && xappend "--dhcp-hostsfile=$hostsfile"

    local rebind
    config_get_bool rebind "$cfg" rebind_protection 1
    [ $rebind -gt 0 ] && {
        log_once \
            "DNS rebinding protection is active," \
            "will discard upstream RFC1918 responses!"
        xappend "--stop-dns-rebind"

        local rebind_localhost
        config_get_bool rebind_localhost "$cfg" rebind_localhost 0
        [ $rebind_localhost -gt 0 ] && {
            log_once "Allowing 127.0.0.0/8 responses"
            xappend "--rebind-localhost-ok"
        }

        append_rebind_domain() {
            log_once "Allowing RFC1918 responses for domain $1"
            xappend "--rebind-domain-ok=$1"
        }

        config_list_foreach "$cfg" rebind_domain append_rebind_domain
    }

    config_get_bool dnssec "$cfg" dnssec 0
    [ "$dnssec" -gt 0 ] && {
        xappend "--conf-file=$TRUSTANCHORSFILE"
        xappend "--dnssec"
        [ -x /etc/init.d/sysntpd ] && {
            if /etc/init.d/sysntpd enabled || [ "$(uci_get system.ntp.enabled)" = "1" ] ; then
                [ -f "$TIMEVALIDFILE" ] || xappend "--dnssec-no-timecheck"
            fi
        }
        config_get_bool dnsseccheckunsigned "$cfg" dnsseccheckunsigned 1
        [ "$dnsseccheckunsigned" -eq 0 ] && xappend "--dnssec-check-unsigned=no"
    }

    config_get addmac "$cfg" addmac 0
    [ "$addmac" != "0" ] && {
        [ "$addmac" = "1" ] && addmac=
        xappend "--add-mac${addmac:+="$addmac"}"
    }

    dhcp_option_add "$cfg" "" 0
    dhcp_option_add "$cfg" "" 2

    xappend "--dhcp-broadcast=tag:needs-broadcast"

    config_get dnsmasqconfdir "$cfg" confdir "/tmp/dnsmasq.d"
    xappend "--conf-dir=$dnsmasqconfdir"
    dnsmasqconfdir="${dnsmasqconfdir%%,*}"
    [ ! -d "$dnsmasqconfdir" ] && mkdir -p $dnsmasqconfdir
    xappend "--user=dnsmasq"
    xappend "--group=dnsmasq"
    echo >> $CONFIGFILE_TMP

    config_get_bool enable_tftp "$cfg" enable_tftp 0
    [ "$enable_tftp" -gt 0 ] && {
        config_get tftp_root "$cfg" tftp_root
        append EXTRA_MOUNT $tftp_root
    }

    config_foreach filter_dnsmasq host dhcp_host_add "$cfg"
    echo >> $CONFIGFILE_TMP

    config_get_bool dhcpbogushostname "$cfg" dhcpbogushostname 1
    [ "$dhcpbogushostname" -gt 0 ] && {
        xappend "--dhcp-ignore-names=tag:dhcp_bogus_hostname"
        [ -r "$DHCPBOGUSHOSTNAMEFILE" ] && xappend "--conf-file=$DHCPBOGUSHOSTNAMEFILE"
    }

    config_foreach filter_dnsmasq boot dhcp_boot_add "$cfg"
    config_foreach filter_dnsmasq mac dhcp_mac_add "$cfg"
    config_foreach filter_dnsmasq tag dhcp_tag_add "$cfg"
    config_foreach filter_dnsmasq vendorclass dhcp_vendorclass_add "$cfg"
    config_foreach filter_dnsmasq userclass dhcp_userclass_add "$cfg"
    config_foreach filter_dnsmasq circuitid dhcp_circuitid_add "$cfg"
    config_foreach filter_dnsmasq remoteid dhcp_remoteid_add "$cfg"
    config_foreach filter_dnsmasq subscrid dhcp_subscrid_add "$cfg"
    config_foreach filter_dnsmasq match dhcp_match_add "$cfg"
    config_foreach filter_dnsmasq domain dhcp_domain_add "$cfg"
    config_foreach filter_dnsmasq hostrecord dhcp_hostrecord_add "$cfg"
    [ -n "$BOOT" ] || config_foreach filter_dnsmasq relay dhcp_relay_add "$cfg"

    echo >> $CONFIGFILE_TMP
    config_foreach filter_dnsmasq srvhost dhcp_srv_add "$cfg"
    config_foreach filter_dnsmasq mxhost dhcp_mx_add "$cfg"
    echo >> $CONFIGFILE_TMP

    config_get_bool boguspriv "$cfg" boguspriv 1
    [ "$boguspriv" -gt 0 ] && {
        xappend "--bogus-priv"
        [ -r "$RFC6761FILE" ] && xappend "--conf-file=$RFC6761FILE"
    }

    if [ "$DNSMASQ_DHCP_VER" -gt 4 ] ; then
        # Enable RA feature for when/if it is constructed,
        # and RA is selected per interface pool (RA, DHCP, or both),
        # but no one (should) want RA broadcast in syslog
        [ -n "$BOOT" ] || config_foreach filter_dnsmasq dhcp dhcp_add "$cfg"
        xappend "--enable-ra"
        xappend "--quiet-ra"
        append_bool "$cfg" quietdhcp "--quiet-dhcp6"

    elif [ "$DNSMASQ_DHCP_VER" -gt 0 ] ; then
        [ -n "$BOOT" ] || config_foreach filter_dnsmasq dhcp dhcp_add "$cfg"
    fi

    echo >> $CONFIGFILE_TMP
    config_foreach filter_dnsmasq cname dhcp_cname_add "$cfg"
    echo >> $CONFIGFILE_TMP

    echo >> $CONFIGFILE_TMP
    config_foreach filter_dnsmasq ipset dnsmasq_ipset_add "$cfg"
    echo >> $CONFIGFILE_TMP

    echo >> $CONFIGFILE_TMP
    mv -f $CONFIGFILE_TMP $CONFIGFILE
    mv -f $HOSTFILE_TMP $HOSTFILE

    [ "$localuse" -gt 0 ] && {
        rm -f /tmp/resolv.conf
        [ $ADD_LOCAL_DOMAIN -eq 1 ] && [ -n "$DOMAIN" ] && {
            echo "search $DOMAIN" >> /tmp/resolv.conf
        }
        DNS_SERVERS="$DNS_SERVERS 127.0.0.1"
        for DNS_SERVER in $DNS_SERVERS ; do
            echo "nameserver $DNS_SERVER" >> /tmp/resolv.conf
        done
    }

    procd_open_instance $cfg
    procd_set_param command $PROG -C $CONFIGFILE -k -x /var/run/dnsmasq/dnsmasq."${cfg}".pid
    procd_set_param file $CONFIGFILE
    [ -n "$user_dhcpscript" ] && procd_set_param env USER_DHCPSCRIPT="$user_dhcpscript"
    procd_set_param respawn

    procd_add_jail dnsmasq ubus log
    procd_add_jail_mount $CONFIGFILE $DHCPBOGUSHOSTNAMEFILE $DHCPSCRIPT $DHCPSCRIPT_DEPENDS
    procd_add_jail_mount $EXTRA_MOUNT $RFC6761FILE $TRUSTANCHORSFILE
    procd_add_jail_mount $dnsmasqconffile $dnsmasqconfdir $resolvdir $user_dhcpscript
    procd_add_jail_mount /etc/passwd /etc/group /etc/TZ /etc/hosts /etc/ethers
    procd_add_jail_mount_rw /var/run/dnsmasq/ $leasefile

    procd_close_instance

    config_get_bool dns_redirect "$cfg" dns_redirect 0
    config_get dns_port "$cfg" port 53
    if [ "$dns_redirect" = 1 ]; then
        iptables -t nat -A PREROUTING -m comment --comment "DNSMASQ" -p udp --dport 53 -j REDIRECT --to-ports $dns_port
        [ -n "$(command -v ip6tables)" ] && ip6tables -t nat -A PREROUTING -m comment --comment "DNSMASQ" -p udp --dport 53 -j REDIRECT --to-ports $dns_port
    fi
}

dnsmasq_stop()
{
    local cfg="$1"
    local noresolv resolvfile localuse=0

    config_get_bool noresolv "$cfg" noresolv 0
    config_get resolvfile "$cfg" "resolvfile"

    [ "$noresolv" = 0 ] && [ "$resolvfile" = "/tmp/resolv.conf.d/resolv.conf.auto" ] && localuse=1
    config_get_bool localuse "$cfg" localuse "$localuse"
    [ "$localuse" -gt 0 ] && ln -sf "/tmp/resolv.conf.d/resolv.conf.auto" /tmp/resolv.conf

    rm -f ${BASEDHCPSTAMPFILE}.${cfg}.*.dhcp
}

iptables_clear()
{
    config_get dns_port "$cfg" port 53
    iptables -t nat -D PREROUTING -m comment --comment "DNSMASQ" -p udp --dport 53 -j REDIRECT --to-ports $dns_port 2>"/dev/null"
    [ -n "$(command -v ip6tables)" ] && ip6tables -t nat -D PREROUTING -m comment --comment "DNSMASQ" -p udp --dport 53 -j REDIRECT --to-ports $dns_port 2>"/dev/null"
}

add_interface_trigger()
{
    local interface ignore

    config_get interface "$1" interface
    config_get_bool ignore "$1" ignore 0

    [ -n "$interface" ] && [ $ignore -eq 0 ] && procd_add_interface_trigger "interface.*" "$interface" /etc/init.d/dnsmasq reload
}

service_triggers()
{
    procd_add_reload_trigger "dhcp" "system"

    config_load dhcp
    config_foreach add_interface_trigger dhcp
    config_foreach add_interface_trigger relay
}

boot()
{
    BOOT=1
    start "$@"
}

start_service() {
    local instance="$1"
    local instance_found=0
    local first_instance=""

    . /lib/functions/network.sh

    config_cb() {
        local type="$1"
        local name="$2"
        if [ "$type" = "dnsmasq" ]; then
            if [ -n "$instance" ] && [ "$instance" = "$name" ]; then
                instance_found=1
            fi
            if [ -z "$DEFAULT_INSTANCE" ]; then
                local disabled
                config_get_bool disabled "$name" disabled 0
                if [ "$disabled" -eq 0 ]; then
                    # First enabled section will be assigned default instance name.
                    # Unnamed sections get precedence over named sections.
                    if expr "$cfg" : 'cfg[0-9a-f]*$' >/dev/null = "9"; then # See uci_fixup_section.
                        DEFAULT_INSTANCE="$name" # Unnamed config section.
                    elif [ -z "$first_instance" ]; then
                        first_instance="$name"
                    fi
                fi
            fi
        fi
    }

    DEFAULT_INSTANCE=""
    config_load dhcp
    if [ -z "$DEFAULT_INSTANCE" ]; then
        DEFAULT_INSTANCE="$first_instance" # No unnamed config section was found.
    fi

    if [ -n "$instance" ]; then
        [ "$instance_found" -gt 0 ] || return
        dnsmasq_start "$instance"
    else
        config_foreach dnsmasq_start dnsmasq
    fi
}

reload_service() {
    iptables_clear
    rc_procd start_service "$@"
    procd_send_signal dnsmasq "$@"
}

stop_service() {
    local instance="$1"
    local instance_found=0

    config_cb() {
        local type="$1"
        local name="$2"
        if [ "$type" = "dnsmasq" ]; then
            if [ -n "$instance" ] && [ "$instance" = "$name" ]; then
                instance_found=1
            fi
        fi
    }

    config_load dhcp

    if [ -n "$instance" ]; then
        [ "$instance_found" -gt 0 ] || return
        dnsmasq_stop "$instance"
    else
        config_foreach dnsmasq_stop dnsmasq
    fi
    iptables_clear
}
jxph1123 commented 2 years ago

看了下,你把这个设置下就好了

uci delete dhcp.@dnsmasq[0].dns_redirect
uci commit dhcp
/etc/init.d/dnsmasq restart
/etc/init.d/smartdns restart

你这个固件可能是被打过强制修改dns的补丁了,这个和openwrt官方的不一样。

我这是2.86版本的dnsmasq,不知的哪里出来的补丁。。。

pymumu commented 2 years ago

看了下,你把这个设置下就好了

uci delete dhcp.@dnsmasq[0].dns_redirect
uci commit dhcp
/etc/init.d/dnsmasq restart
/etc/init.d/smartdns restart

你这个固件可能是被打过强制修改dns的补丁了,这个和openwrt官方的不一样。

我这是2.86版本的dnsmasq,不知的哪里出来的补丁。。。

和dnsmasq无关,和你的固件提供者有关系。

jxph1123 commented 2 years ago

看了下,你把这个设置下就好了

uci delete dhcp.@dnsmasq[0].dns_redirect
uci commit dhcp
/etc/init.d/dnsmasq restart
/etc/init.d/smartdns restart

你这个固件可能是被打过强制修改dns的补丁了,这个和openwrt官方的不一样。

我这是2.86版本的dnsmasq,不知的哪里出来的补丁。。。

和dnsmasq无关,和你的固件提供者有关系。

感谢大佬,配置了重启能上了,我自己编译的固件,我找找看是哪个打了补丁

yyysuo commented 2 years ago

各固件基本上都带翻墙方案,要么是自己编译的,默认启用真是会造成各种奇怪的问题。

jxph1123 commented 2 years ago

看了下,你把这个设置下就好了

uci delete dhcp.@dnsmasq[0].dns_redirect
uci commit dhcp
/etc/init.d/dnsmasq restart
/etc/init.d/smartdns restart

你这个固件可能是被打过强制修改dns的补丁了,这个和openwrt官方的不一样。

我这是2.86版本的dnsmasq,不知的哪里出来的补丁。。。

和dnsmasq无关,和你的固件提供者有关系。

image 大佬,破案了,刚刚是这个DNS重定向默认开启了,建议大佬切换53端口的时候把这个给强制关掉~~

zxlhhyccc commented 2 years ago

看了下,你把这个设置下就好了

uci delete dhcp.@dnsmasq[0].dns_redirect
uci commit dhcp
/etc/init.d/dnsmasq restart
/etc/init.d/smartdns restart

你这个固件可能是被打过强制修改dns的补丁了,这个和openwrt官方的不一样。

请问大佬,这个应该是修改哪个文件,dnsmasq还是smartdns的init文件?

jxph1123 commented 2 years ago

看了下,你把这个设置下就好了

uci delete dhcp.@dnsmasq[0].dns_redirect
uci commit dhcp
/etc/init.d/dnsmasq restart
/etc/init.d/smartdns restart

你这个固件可能是被打过强制修改dns的补丁了,这个和openwrt官方的不一样。

请问大佬,这个应该是修改哪个文件,dnsmasq还是smartdns的init文件?

DHCP/DNS里面有个DNS 重定向,取消打勾就行了。 image

luckyyyyy commented 2 years ago

太混乱了,我才看到我写的那篇东西被@了无数次,我真的不建议小白去设置DNS或者任何套娃,只有你确定你在做什么以及你需要做什么才去做这些事。

而且现在有很多第三方修改版固件,做了很多DNS等魔法在里面 iptables 一顿混乱,真的建议大家只有在清楚自己做什么才去设置。