#!/bin/sh /etc/rc.common
# Copyright (C) 2007-2012 OpenWrt.org
# patch by yinjiajin@xiaomi.com, use conf-dir

START=48
STOP=60 # stop dnsmasq to ensure it will not miss up LAN

#SERVICE_USE_PID=1

DNS_SERVERS=""
DOMAIN=""

ADD_LOCAL_DOMAIN=1
ADD_LOCAL_HOSTNAME=1

CONFIGFILE="/var/etc/.dnsmasq.conf"
FINAL_CONFIGFILE="/var/etc/dnsmasq.conf"

EXECMD="/usr/sbin/dnsmasq --user=root -C ${FINAL_CONFIGFILE}"
EXECMD_RULE_ONLY="pidof dnsmasq |xargs kill -s SIGHUP "
loader="/var/etc/dnsmasq_loader"
loader_reload="/var/etc/dnsmasq_loader_reload"

export OOM_FLAG=0

minet_rep_mode="false"

EXTRA_COMMANDS=" status dump "

. /lib/dnsmasq/gen_config_from_uci

gen_conf_file() {
    #lock for gen config
    local LOCKFILE=/var/lock/dnsmasq_init.lock
    trap "lock -u ${LOCKFILE}; return 0" EXIT HUP INT QUIT PIPE TERM
    lock $LOCKFILE

    include /lib/network
    scan_interfaces

    #read lan ip
    local lanipaddr
    config_load network
    config_get lanipaddr lan ipaddr '192.168.31.1'

    config_load dhcp

    # before we can call xappend
    mkdir -p $(dirname $CONFIGFILE)
    echo "# auto-generated config file from /etc/config/dhcp" >$CONFIGFILE

    mkdir -p /etc/dnsmasq.d/ || {
        syslog "ERROR: mkdir -p /etc/dnsmasq.d/ failed."
        exit 1
    }

    mkdir -p /tmp/etc/ || {
        syslog "ERROR: mkdir -p /tmp/etc/ failed."
        exit 1
    }

    cp -a /etc/dnsmasq.d /tmp/etc/ 2>/dev/null
    if [ $? -ne 0 ]; then
        conlog "INFO: --config-dir=/etc/dnsmasq.d/"
        xappend "--conf-dir=/etc/dnsmasq.d/"
    else
        conlog "INFO: --config-dir=/tmp/etc/dnsmasq.d/"
        xappend "--conf-dir=/tmp/etc/dnsmasq.d/"
    fi

    #disabled legacy config file /etc/dnsmasq.conf
    needclean=$(cat /etc/dnsmasq.conf 2>/dev/null | grep -v '^#' | grep -cv '^$')
    if [ $needclean -ne 0 ]; then
        conlog "WARNING: diable legacy config /etc/dnsmasq.conf, backup to /etc/dnsmasq.conf.disabled.$$"
        cat /etc/dnsmasq.conf >/etc/dnsmasq.conf.disabled.$$
        rm -f /overlay/etc/dnsmasq.conf
    fi

    #log ignored noexist link file
    for onefile in $(ls /etc/dnsmasq.d/); do
        if [ ! -f "/etc/dnsmasq.d/$onefile" ]; then
            conlog "no-exist file, ignored: /etc/dnsmasq.d/$onefile"
        fi
    done

    #here need check if ipv6 enabled or not
    local ipv6flag=$(lsmod | grep ip6_tables)

    #a flag for dnsmasq status detecting
    #address=/workforme.stat.localdomain/127.0.0.1
    xappend "--address=/workforme.stat.localdomain/127.0.0.1"
    #
    #setup router domain
    mkdir -p /tmp/hosts/ && {
        echo "${lanipaddr} miwifi.com" >/tmp/hosts/miwifi.com
        echo "${lanipaddr} www.miwifi.com" >/tmp/hosts/www.miwifi.com
    }

    myhostname="$(uci get system.@system[0].hostname 2>/dev/null)"
    if [ -z "$myhostname" ]; then
        syslog "ERROR: hostname no found: $(uci get system.@system[0].hostname 2>&1)"
    else
        mkdir -p /tmp/hosts/ && echo "${lanipaddr} ${myhostname}" >/tmp/hosts/${myhostname}
        if [ $? -ne 0 ]; then
            #domainneeded
            syslog "ERROR: save ${lanipaddr} ${myhostname} to /tmp/hosts/${myhostname} failed."
        fi
    fi

    mydomain="$(uci get dhcp.@dnsmasq[0].domain 2>/dev/null)"
    test -z "$mydomain" && mydomain='lan'
    if [ -n "$myhostname" ]; then
        staticfqdn="${myhostname}.${mydomain}"
        mkdir -p /tmp/hosts/ && echo "${lanipaddr} ${staticfqdn}" >/tmp/hosts/${staticfqdn}
        if [ $? -ne 0 ]; then
            syslog "ERROR: save ${lanipaddr} ${staticfqdn} to /tmp/hosts/${staticfqdn} failed."
        fi
        staticfqdn="miwifi.com.${mydomain}"
        mkdir -p /tmp/hosts/ && echo "${lanipaddr} ${staticfqdn}" >/tmp/hosts/${staticfqdn}
        if [ $? -ne 0 ]; then
            syslog "ERROR: save ${lanipaddr} ${staticfqdn} to /tmp/hosts/${staticfqdn} failed."
        fi
        staticfqdn="www.miwifi.com.${mydomain}"
        mkdir -p /tmp/hosts/ && echo "${lanipaddr} ${staticfqdn}" >/tmp/hosts/${staticfqdn}
        if [ $? -ne 0 ]; then
            syslog "ERROR: save ${lanipaddr} ${staticfqdn} to /tmp/hosts/${staticfqdn} failed."
        fi
    fi

    #custom hosts
    [ -f /etc/custom_hosts ] && cp -f /etc/custom_hosts /tmp/hosts/

    #clear cache onreload, set in /etc/config/dhcp
    #xappend "--clear-on-reload"

    args=""
    config_foreach dnsmasq dnsmasq
    config_foreach dhcp_host_add host
    echo >>$CONFIGFILE
    config_foreach dhcp_boot_add boot
    config_foreach dhcp_mac_add mac
    config_foreach dhcp_tag_add tag
    config_foreach dhcp_vendorclass_add vendorclass
    config_foreach dhcp_userclass_add userclass
    config_foreach dhcp_circuitid_add circuitid
    config_foreach dhcp_remoteid_add remoteid
    config_foreach dhcp_subscrid_add subscrid
    config_foreach dhcp_domain_add domain
    echo >>$CONFIGFILE
    config_foreach dhcp_srv_add srvhost
    config_foreach dhcp_mx_add mxhost
    echo >>$CONFIGFILE
    config_foreach dhcp_add dhcp
    echo >>$CONFIGFILE
    config_foreach dhcp_cname_add cname
    echo >>$CONFIGFILE

    # config minet repeater mode dnsmasq
    if [ "$minet_rep_mode" = "true" ]; then
        xappend "--interface=$minet_if"
        xappend "--no-dhcp-interface=br-lan"
    fi

    # add own hostname
    [ $ADD_LOCAL_HOSTNAME -eq 1 ] && [ -n "$lanipaddr" ] && {
        local hostname="$(uci_get system.@system[0].hostname)"
        dhcp_domain_add "" "${hostname:-OpenWrt}" "$lanipaddr"
    }

    remote_resolv=0
    DEVINITMARK="$(uci get xiaoqiang.common.INITTED 2>/dev/null)"
    if [ "${DEVINITMARK}" != 'YES' ]; then
        remote_resolv=1
        # ${lanipaddr}
        conlog "WARNING: "
        conlog "WARNING: all domain resolv to ${lanipaddr} for router has not initialed."
        conlog "WARNING: "
        xappend "--address=/#/${lanipaddr}"
        #max-ttl=30
        sed -i -e '/max-ttl=/d' $CONFIGFILE && echo 'max-ttl=0' >>$CONFIGFILE
        if [ $? -ne 0 ]; then
            conlog "WARNING: set max-ttl=5 failed."
        fi
        #resolv-file=
        echo '#dummy resolv file for device no initialed' >/tmp/resolv.conf.dummy && sed -i -e '/resolv-file=/d' $CONFIGFILE && echo 'resolv-file=/tmp/resolv.conf.dummy' >>$CONFIGFILE
        if [ $? -ne 0 ]; then
            conlog "WARNING: resolv-file=/tmp/resolv.conf.dummy failed."
        fi
    fi

    #here need check if ipv6 enabled or not
    local ipv6flag=`uci -q get ipv6.settings.enabled`
    [ "$ipv6flag" = "1" ] && {
        #support ipv6 address assign with dnsmasq.
        #here must notice that prefix must equal to 64
        xappend "--enable-ra"
        xappend "--ra-param=br-lan,90,600"
        xappend "--dhcp-range=::100,::600,constructor:*,slaac,120m"
        #xappend "--servers-file=/tmp/ip6_server"
        #xappend "--AAAA-dns-only-file=/tmp/ip6_dns"
    }

    #
    #ignored wan nic for pppoe
    #
    wannic=$(uci get network.wan.ifname 2>/dev/null)
    if [ -n "$wannic" ]; then
        grep -q "no-dhcp-interface=$wannic" $CONFIGFILE
        if [ $? -ne 0 ]; then
            xappend "--no-dhcp-interface=$wannic"
        fi
    fi

    #filter address/server/ipset from /tmp/etc/dnsmasq.conf to /tmp/etc/dnsmasq.d/
    grep -E "^\s*server=|^\s*address=|^\s*ipset=" $CONFIGFILE >/tmp/etc/dnsmasq.d/filter_main_opt.conf

    ##check if config file changed or not
    sum_new=$(md5sum $CONFIGFILE | awk '{print $1}')
    sum_old=$(md5sum $FINAL_CONFIGFILE | awk '{print $1}')
    status && [ "$sum_new" = "$sum_old" ] && {
        return 0
    }

    # restart dnsmasq if config changed
    cp $CONFIGFILE $FINAL_CONFIGFILE
    return 1
}

start() {
    local mode
    mode=$(uci -q get xiaoqiang.common.NETMODE)
    if [ "$mode" == "wifiapmode" -o "$mode" == "lanapmode" -o "$mode" == "whc_re" ]; then
        # we need dnsmasq for dhcp if minet is enabled
        minet_en=$(uci -q get minet.setting.enabled)
        minet_if=$(uci -q get minet.setting.ready_intf)
        if [ "$minet_en" != "1" -o -z "$minet_if" ]; then
            syslog "INFO: In AP mode, needn't dnsmasq. exit!"
            stop
            return 0
        fi
        minet_rep_mode="true"
    fi

    #generate conf file
    mkdir -p /tmp/state/ && chmod o+w /tmp/state/

    gen_conf_file
    #need restart dnsmasq
    if [ "$?" = "1" ]; then
        syslog "INFO: restart dnsmasq process, as main-conf file is changed."
        # ensure /tmp/state can be written by nobody
        cat >$loader <<EOF
        [ -f /usr/bin/trmd ] && /usr/bin/trmd -g
        ubus call eventservice dnsmasq_restart_notify -t 2 >/dev/null 2>&1
        ${EXECMD}
EOF

        export PROCLINE="ash $loader"
        export PROCFLAG="${EXECMD}"
        export PROCNUM='2'
        /usr/sbin/supervisord restart

    else
        syslog "INFO: only reload rules without restarting dnsmasq process."
        cat >$loader_reload <<EOF
        [ -f /usr/bin/trmd ] && /usr/bin/trmd -g
        ubus call eventservice dnsmasq_restart_notify -t 2 >/dev/null 2>&1
        ${EXECMD_RULE_ONLY}
EOF
        ash $loader_reload >/dev/null 2>&1
    fi

    # mac bind
    if [ -f /etc/ethers ]; then
        conlog "INFO: loading IP-MAC binding from /etc/ethers"
        cat /etc/ethers | conlog
        /usr/bin/arp -f 2>&1 | conlog
        if [ $? -ne 0 ]; then
            conlog "WARNING: load IP-MAC binding from /etc/ethers failed."
        fi
    fi

    #change local dns server
    if [ $? -eq 0 ]; then
        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
    fi

    return 0

}

stop() {
    export PROCLINE="${EXECMD}"
    export PROCFLAG="${EXECMD}"
    # dnsmasq will fork itself.
    export PROCNUM='2'
    /usr/sbin/supervisord stop && {
        [ -f /tmp/resolv.conf ] && {
            rm -f /tmp/resolv.conf
            ln -s /tmp/resolv.conf.auto /tmp/resolv.conf
        }
    }
}

# do not stop dnsmasq, but just reload rules
restart() {
    start
}

status() {
    export PROCLINE="${EXECMD}"
    export PROCFLAG="${EXECMD}"
    # dnsmasq will fork itself.
    export PROCNUM='2'
    /usr/sbin/supervisord status
    return $?
}

dump() {
    pidof dnsmasq | xargs kill -s USR1 >/dev/null 2>&1
    echo "dnsmasq dump info to syslog done."
}
