@@ -71,9 +71,23 @@ dnsmasq_restart() { /etc/init.d/dnsmasq restart >/dev/null 2>&1; }
7171is_alnum () { case " $1 " in (* [![:alnum:]_\ @]* |" " ) return 1;; esac ; }
7272is_fw4_restart_needed () { [ " $( uci_get " $packageName " ' config' ' force_dns' ' 1' ) " = ' 1' ]; }
7373is_mac_address () { expr " $1 " : ' [0-9A-F][0-9A-F]:[0-9A-F][0-9A-F]:[0-9A-F][0-9A-F]:[0-9A-F][0-9A-F]:[0-9A-F][0-9A-F]:[0-9A-F][0-9A-F]$' > /dev/null; }
74- is_integer () { case " $1 " in ' ' |* [!0-9]* ) return 1;; esac ; }
74+ is_integer () { case " $1 " in ' ' |* [!0-9]* ) return 1;; esac ; [ " $1 " -ge 1 ] && [ " $1 " -le 65535 ] || return 1 ; return 0 ; }
7575is_ipv4 () { expr " $1 " : ' [0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*$' > /dev/null; }
7676is_ipv6 () { ! is_mac_address " $1 " && str_contains " $1 " " :" ; }
77+ is_port_listening () {
78+ local hex
79+ is_integer " $1 " || return 1
80+ hex=" $( printf ' %04X' " $1 " ) "
81+ # TCP: state 0A == LISTEN
82+ if awk -v h=" $hex " ' NR>1{split($2,a,":"); if (toupper(a[2])==h && $4=="0A") {found=1}} END{exit found?0:1}' /proc/net/tcp /proc/net/tcp6 2> /dev/null; then
83+ return 0
84+ fi
85+ # UDP: presence indicates a bound socket
86+ if awk -v h=" $hex " ' NR>1{split($2,a,":"); if (toupper(a[2])==h) {found=1}} END{exit found?0:1}' /proc/net/udp /proc/net/udp6 2> /dev/null; then
87+ return 0
88+ fi
89+ return 1
90+ }
7791is_resolver_working () {
7892 local heartbeat_domain heartbeat_sleep_timeout heartbeat_wait_timeout
7993 config_load " $packageName "
@@ -274,7 +288,7 @@ start_instance() {
274288 json_add_array firewall
275289 for iface in ${force_dns_src_interface/ ,/ } ; do
276290 for p in ${force_dns_port/ ,/ } ; do
277- if netstat -tuln | grep ' LISTEN ' | grep " : ${p} " > /dev/null 2>&1 || [ " $p " = ' 53 ' ] ; then
291+ if is_port_listening " $p " ; then
278292 json_add_object ' '
279293 json_add_string type ' redirect'
280294 json_add_string target ' DNAT'
0 commit comments