123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570 |
- #!/bin/sh
- #
- # Copyright (C) 2018-2025 Ruilin Peng (Nick) <[email protected]>.
- #
- # smartdns is free software: you can redistribute it and/or modify
- # it under the terms of the GNU General Public License as published by
- # the Free Software Foundation, either version 3 of the License, or
- # (at your option) any later version.
- #
- # smartdns 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.
- #
- # You should have received a copy of the GNU General Public License
- # along with this program. If not, see <http://www.gnu.org/licenses/>.
- SMARTDNS_BIN=/opt/usr/sbin/smartdns
- SMARTDNS_CONF=/opt/etc/smartdns/smartdns.conf
- DNSMASQ_CONF="/etc/dnsmasq.conf /var/etc/dnsmasq.conf /etc/storage/dnsmasq/dnsmasq.conf"
- SMARTDNS_PID=/run/smartdns.pid
- SMARTDNS_CHECK_PID=/tmp/smartdns_delay_check.pid
- if [ ! -d "/run" ]; then
- SMARTDNS_PID=/var/run/smartdns.pid
- fi
- SMARTDNS_PORT=535
- SMARTDNS_OPT=/opt/etc/smartdns/smartdns-opt.conf
- # workmode
- # DO NOT CHANGE THIS, CHANGE MODE IN smartdns-opt.conf
- # 0: run as port only
- # 1: redirect port
- # 2: replace
- SMARTDNS_WORKMODE="1"
- SMARTDNS_INIT_SCRIPT="$0"
- if [ -f "$SMARTDNS_OPT" ]; then
- . "$SMARTDNS_OPT"
- fi
- set_iptable()
- {
- local redirect_tcp
- redirect_tcp=0
- grep ^bind-tcp $SMARTDNS_CONF > /dev/null 2>&1
- if [ $? -eq 0 ]; then
- redirect_tcp=1;
- fi
- IPS="$(ifconfig | grep "inet addr" | grep -v ":127" | grep "Bcast" | awk '{print $2}' | awk -F: '{print $2}')"
- for IP in $IPS
- do
- if [ $redirect_tcp -eq 1 ]; then
- iptables -t nat -A PREROUTING -p tcp -d "$IP" --dport 53 -j REDIRECT --to-ports "$SMARTDNS_PORT" > /dev/null 2>&1
- fi
- iptables -t nat -A PREROUTING -p udp -d "$IP" --dport 53 -j REDIRECT --to-ports "$SMARTDNS_PORT" > /dev/null 2>&1
- done
- }
- clear_iptable()
- {
- IPS="$(ifconfig | grep "inet addr" | grep -v ":127" | grep "Bcast" | awk '{print $2}' | awk -F: '{print $2}')"
- for IP in $IPS
- do
- iptables -t nat -D PREROUTING -p tcp -d "$IP" --dport 53 -j REDIRECT --to-ports "$SMARTDNS_PORT" > /dev/null 2>&1
- iptables -t nat -D PREROUTING -p udp -d "$IP" --dport 53 -j REDIRECT --to-ports "$SMARTDNS_PORT" > /dev/null 2>&1
- done
-
- }
- get_dnsmasq_cmd()
- {
- CMD="$(ps 2>/dev/null | grep -e '[a-zA-Z]\{0,2\} \{1,\}dnsmasq' | grep -v grep 2>/dev/null)"
- if [ ! -z "$CMD" ]; then
- return
- fi
- CMD="$(ps 2>/dev/null | grep '/usr/sbin/dnsmasq' | grep -v grep 2>/dev/null)"
- if [ ! -z "$CMD" ]; then
- return
- fi
- CMD="$(ps 2>/dev/null | grep 'dnsmasq' | grep -v grep 2>/dev/null)"
- if [ ! -z "$CMD" ]; then
- return
- fi
- CMD="$(ps ax 2>/dev/null | grep -e '[a-zA-Z]\{0,2\} \{1,\}dnsmasq' | grep -v grep 2>/dev/null)"
- if [ ! -z "$CMD" ]; then
- return
- fi
- CMD="$(ps ax 2>/dev/null | grep /usr/sbin/dnsmasq | grep -v grep 2>/dev/null)"
- if [ ! -z "$CMD" ]; then
- return
- fi
- CMD="$(ps ax 2>/dev/null | grep 'dnsmasq' | grep -v grep 2>/dev/null)"
- if [ ! -z "$CMD" ]; then
- return
- fi
- }
- get_dnsmasq_cmdline()
- {
- local CMD=""
- local loop=0
- while [ $loop -lt 3 ]; do
- get_dnsmasq_cmd
- if [ ! -z "$CMD" ]; then
- break;
- fi
- $SMARTDNS_INIT_SCRIPT stop
- sleep 1
- loop=$((loop+1))
- done
- if [ -z "$CMD" ]; then
- echo "cannot find dnsmasq"
- service restart_dnsmasq 2>/dev/null
- return 1
- fi
- # check multiple dnsmasq
- linecount="$(echo "$CMD" | wc -l)"
- if [ $linecount -eq 1 ]; then
- PID="$(echo "$CMD" | awk '{print $1}')"
- elif [ $linecount -gt 1 ]; then
- PID1="$(echo "$CMD" | awk 'NR==1{print $1}')"
- PID2="$(echo "$CMD" | awk 'NR==2{print $1}')"
- PID2_PPID="$(grep 'PPid:' /proc/$PID2/status | awk '{print $2}' 2>/dev/null)"
- if [ "$PID2_PPID" != "$PID1" ]; then
- kill -9 "$PID2" 2>/dev/null
- fi
- PID=$PID1
- else
- echo "find multiple dnsmasq, but not started by the same process"
- return 1
- fi
- if [ ! -d "/proc/$PID" ]; then
- echo "dnsmasq is not running"
- return 1
- fi
- CMD="$(echo "$CMD" | head -n 1)"
- DNSMASQ_CMD="$(echo "$CMD" | awk '{for(i=5; i<=NF;i++)printf $i " "}')"
- return 0
- }
- restart_dnsmasq()
- {
- if [ -z "$DNSMASQ_CMD" ]; then
- get_dnsmasq_cmdline
- if [ $? -ne 0 ]; then
- echo "cannot find dnsmasq"
- return 1
- fi
- fi
- if [ ! -z "$PID" ]; then
- kill -9 "$PID"
- fi
- $DNSMASQ_CMD
- return $?
- }
- add_dhcp_options6()
- {
- CONF_FILE=$1
- IPS="$(ifconfig | grep "inet addr" | grep -v ":127" | grep "Bcast" | awk '{print $2}' | awk -F: '{print $2}')"
- for IP in $IPS
- do
- DHCP_OPTION="$(grep "dhcp-option=" "$CONF_FILE" | grep "$IP" | head -n 1)"
- if [ -z "$DHCP_OPTION" ]; then
- continue
- fi
- SERVER_TAG="$(echo "$DHCP_OPTION" | awk -F= '{print $2}' | awk -F, '{print $1}')"
- LOCAL_SERVER_IP="$IP"
- grep "dhcp-option *= *$SERVER_TAG, *6 *, *$LOCAL_SERVER_IP" "$CONF_FILE" 1>/dev/null 2>&1
- if [ $? -eq 0 ]; then
- continue
- fi
-
- DHCP_OPTION="dhcp-option=$SERVER_TAG,6,$LOCAL_SERVER_IP"
- echo "$DHCP_OPTION" >> "$CONF_FILE"
- RESTART_DNSMASQ=1
- done
- return 1
- }
- clear_dhcp_options6()
- {
- CONF_FILE=$1
- IPS="$(ifconfig | grep "inet addr" | grep -v ":127" | grep "Bcast" | awk '{print $2}' | awk -F: '{print $2}')"
- for IP in $IPS
- do
- DHCP_OPTION="$(grep "dhcp-option=" "$CONF_FILE" | grep "$IP" | head -n 1)"
- if [ -z "$DHCP_OPTION" ]; then
- continue
- fi
- SERVER_TAG="$(echo "$DHCP_OPTION" | awk -F= '{print $2}' | awk -F, '{print $1}')"
- LOCAL_SERVER_IP="$IP"
- grep "dhcp-option *= *$SERVER_TAG, *6 *, *$LOCAL_SERVER_IP" "$CONF_FILE" 1>/dev/null 2>&1
- if [ $? -ne 0 ]; then
- continue
- fi
-
- sed -i "/^dhcp-option *=$SERVER_TAG,6,/d" "$CONF_FILE"
- RESTART_DNSMASQ=1
- done
- return 1
- }
- set_dnsmasq_conf()
- {
- local LOCAL_SERVER_IP=""
- local SERVER_TAG=""
- local CONF_FILE=$1
- local DHCP_OPTIONS=""
- add_dhcp_options6 "$CONF_FILE"
- grep "^port *=0" "$CONF_FILE" > /dev/null 2>&1
- if [ $? -ne 0 ]; then
- sed -i "/^port *=/d" "$CONF_FILE"
- echo "port=0" >> "$CONF_FILE"
- RESTART_DNSMASQ=1
- fi
- }
- do_set_dnsmasq()
- {
- local RESTART_DNSMASQ=0
- for conf in $DNSMASQ_CONF
- do
- if [ ! -e "$conf" ]; then
- continue
- fi
- set_dnsmasq_conf "$conf"
- done
-
- if [ $RESTART_DNSMASQ -ne 0 ]; then
- restart_dnsmasq
- fi
- }
- kill_dnsmasq_delay_check_pid()
- {
- if [ ! -e "$SMARTDNS_CHECK_PID" ]; then
- return
- fi
- PID="$(cat $SMARTDNS_CHECK_PID)"
- if [ -d "/proc/$PID" ]; then
- kill -9 $PID
- fi
- rm -f $SMARTDNS_CHECK_PID
- }
- dnsmasq_delay_check()
- {
- sleep 8
- rm -f $SMARTDNS_CHECK_PID
- get_dnsmasq_cmdline
- if [ -z "$DNSMASQ_CMD" ] ; then
- $SMARTDNS_INIT_SCRIPT restart
- return
- fi
- do_set_dnsmasq
- pid="$(cat $SMARTDNS_PID |head -n 1 2>/dev/null)"
- if [ -z "$pid" ]; then
- do_clear_dnsmasq
- $SMARTDNS_INIT_SCRIPT start > /dev/null 2>&1 &
- elif [ ! -d "/proc/$pid" ]; then
- do_clear_dnsmasq
- $SMARTDNS_INIT_SCRIPT start > /dev/null 2>&1 &
- fi
- exit 0
- }
- begin_dnsmasq_delay_check()
- {
- DNSMASQ_CMD=""
- kill_dnsmasq_delay_check_pid
- get_dnsmasq_cmdline
- dnsmasq_delay_check > /dev/null 2>&1 &
- PID=$!
- echo $PID > $SMARTDNS_CHECK_PID
- }
- set_dnsmasq()
- {
- get_dnsmasq_cmdline
- do_set_dnsmasq
- begin_dnsmasq_delay_check
- }
- set_jffs_dnsmasq()
- {
- local RESTART_DNSMASQ=0
- if [ "$(nvram get jffs2_scripts)" -ne 1 ]; then
- nvram set jffs2_scripts="1"
- nvram commit
- fi
- touch /jffs/configs/dnsmasq.conf.add
- if [ -e "/jffs/configs/dnsmasq.conf.add" ]; then
- set_dnsmasq_conf "/jffs/configs/dnsmasq.conf.add"
- fi
- if [ -e "/jffs/configs/dnsmasq.conf" ]; then
- set_dnsmasq_conf "/jffs/configs/dnsmasq.conf"
- fi
- if [ $RESTART_DNSMASQ -ne 0 ]; then
- restart_dnsmasq
- fi
- }
- clear_dnsmasq_conf()
- {
- local LOCAL_SERVER_IP=""
- local SERVER_TAG=""
- local CONF_FILE=$1
-
- clear_dhcp_options6 "$CONF_FILE"
- grep "^port *=" "$CONF_FILE" > /dev/null 2>&1
- if [ $? -eq 0 ]; then
- sed -i "/^port *=/d" "$CONF_FILE"
- RESTART_DNSMASQ=1
- fi
- }
- do_clear_dnsmasq()
- {
- local RESTART_DNSMASQ=0
- for conf in $DNSMASQ_CONF
- do
- if [ ! -e "$conf" ]; then
- continue
- fi
- clear_dnsmasq_conf "$conf"
- done
- if [ $RESTART_DNSMASQ -ne 0 ]; then
- if [ $? -eq 0 ]; then
- return
- fi
- restart_dnsmasq
- fi
- }
- clear_dnsmasq()
- {
- kill_dnsmasq_delay_check_pid
- do_clear_dnsmasq
- }
- clear_jffs_dnsmasq()
- {
- local RESTART_DNSMASQ=0
- if [ -e "/jffs/configs/dnsmasq.conf.add" ]; then
- clear_dnsmasq_conf "/jffs/configs/dnsmasq.conf.add"
- fi
- if [ -e "/jffs/configs/dnsmasq.conf" ]; then
- clear_dnsmasq_conf "/jffs/configs/dnsmasq.conf"
- fi
- if [ $RESTART_DNSMASQ -ne 0 ]; then
- restart_dnsmasq
- fi
- }
- set_smartdns_port()
- {
- if [ "$SMARTDNS_WORKMODE" = "0" ]; then
- return 0
- elif [ "$SMARTDNS_WORKMODE" = "1" ]; then
- sed -i "s/^\(bind .*\):53\(@[^ ]*\)\?\( .*\)\?$/\1:$SMARTDNS_PORT\2 \3/g" $SMARTDNS_CONF
- sed -i "s/^\(bind-tcp .*\):53\(@[^ ]*\)\?\( .*\)\?$/\1:$SMARTDNS_PORT\2 \3/g" $SMARTDNS_CONF
- elif [ "$SMARTDNS_WORKMODE" = "2" ]; then
- sed -i "s/^\(bind .*\):$SMARTDNS_PORT\(@[^ ]*\)\?\( .*\)\?$/\1:53\2 \3/g" $SMARTDNS_CONF
- sed -i "s/^\(bind-tcp .*\):$SMARTDNS_PORT\(@[^ ]*\)\?\( .*\)\?$/\1:53\2 \3/g" $SMARTDNS_CONF
- elif [ "$SMARTDNS_WORKMODE" = "3" ]; then
- return 0
- else
- return 1
- fi
- return 0
- }
- set_rule()
- {
- if [ "$SMARTDNS_WORKMODE" = "0" ]; then
- return 0
- elif [ "$SMARTDNS_WORKMODE" = "1" ]; then
- set_iptable
- return $?
- elif [ "$SMARTDNS_WORKMODE" = "2" ]; then
- set_dnsmasq
- return $?
- elif [ "$SMARTDNS_WORKMODE" = "3" ]; then
- set_jffs_dnsmasq
- return $?
- else
- return 1
- fi
- }
- clear_rule()
- {
- if [ "$SMARTDNS_WORKMODE" = "0" ]; then
- return 0
- elif [ "$SMARTDNS_WORKMODE" = "1" ]; then
- clear_iptable
- return $?
- elif [ "$SMARTDNS_WORKMODE" = "2" ]; then
- clear_dnsmasq
- return $?
- elif [ "$SMARTDNS_WORKMODE" = "3" ]; then
- clear_jffs_dnsmasq
- return $?
- else
- return 1
- fi
- }
- get_tz()
- {
- if [ -e "/etc/localtime" ]; then
- return
- fi
-
- for tzfile in /etc/TZ /var/etc/TZ
- do
- if [ ! -e "$tzfile" ]; then
- continue
- fi
-
- tz="$(cat $tzfile 2>/dev/null)"
- done
-
- if [ -z "$tz" ]; then
- return
- fi
-
- export TZ=$tz
- }
- case "$1" in
- start)
- set_rule
- if [ $? -ne 0 ]; then
- exit 1
- fi
- SMARTDNS_OPTION=""
- [ "$SMARTDNS_CRASH_RESTART" = "1" ] && SMARTDNS_OPTION="$SMARTDNS_OPTION -R"
- set_smartdns_port
- get_tz
- $SMARTDNS_BIN -c "$SMARTDNS_CONF" -p $SMARTDNS_PID $SMARTDNS_OPTION
- if [ $? -ne 0 ]; then
- clear_rule
- exit 1
- fi
- ;;
- status)
- pid="$(cat $SMARTDNS_PID |head -n 1 2>/dev/null)"
- if [ -z "$pid" ]; then
- echo "smartdns not running."
- exit 0
- fi
- if [ -d "/proc/$pid" ]; then
- echo "smartdns is running"
- exit 0
- fi
- echo "smartdns not running."
- exit 0
- ;;
- stop)
- pid="$(cat "$SMARTDNS_PID" | head -n 1 2>/dev/null)"
- if [ -z "$pid" ]; then
- echo "smartdns not running."
- exit 0
- fi
- kill -15 "$pid" 2>/dev/null
- SLEEP=$(which usleep 2>/dev/null)
- SLEEPTIME=200000
- if [ -z "$SLEEP" ]; then
- SLEEP="sleep"
- SLEEPTIME=0.2
- fi
- N=300
- while [ $N -gt 0 ]
- do
- pid="$(cat "$SMARTDNS_PID" | head -n 1 2>/dev/null)"
- if [ -z "$pid" ]; then
- break
- fi
- if [ ! -d "/proc/$pid" ]; then
- break
- fi
- stat="$(cat /proc/${pid}/stat 2>/dev/null | awk '{print $3}' 2>/dev/null)"
- if [ "$stat" = "Z" ]; then
- $SLEEP $SLEEPTIME
- break
- fi
- $SLEEP $SLEEPTIME 2>/dev/null
- N=$((N-1))
- done
- kill -9 "$pid" 2>/dev/null
- clear_rule
- exit 0
- ;;
- restart)
- $0 stop
- $0 start
- ;;
- reload)
- ;;
- enable)
- nvram set apps_state_enable=2
- nvram set apps_state_error=0
- nvram set apps_state_install=5
- nvram set apps_state_action=install
- nvram set apps_u2ec_ex=2
- ;;
- firewall-start|reload|force-reload|reconfigure)
- $0 restart
- ;;
- *)
- ;;
- esac
|