### Author: CuteBi ###
#### Version: 0.4 ####
####  ipv4 share  ####

#检查脚本更新
checkUpdate() {
	[ -f 'Changes.txt' ] && {
		echo "检测到新版本(更新后请删除Core目录下Changes.txt文件):"
		cat Changes.txt
	}
	if type curl; then
		httpCmd='curl'
	elif type wget; then
		httpCmd='wget -O -'
	else
		return
	fi &>/dev/null
	{
		sleep 10
		version='0.4'
		changes=`$httpCmd "http://pros.cutebi.taobao69.cn/clncScript/natShareChanges.php?version=$version" 2>/dev/null`
		if [ "$?" = '0' ]; then
			if echo "$changes" | grep -q 'no update'; then
				rm -f Changes.txt
			elif echo "$changes" | grep -q "$version"; then
				cat >Changes.txt <<-EOF
				$changes
				EOF
			fi
		fi
	} &>/dev/null &
}


#自动更新核心
autoUpdataCores() {
	for coreInfo in 'clnc_clnc'; do
		coreName="${coreInfo%%_*}"
		helpFlag="${coreInfo#*_}"
		if ! ./$coreName -h 2>/dev/null | grep -q "$helpFlag"; then
			./下载核心.sh "$mlHost" "$coreName" "$helpFlag"
		fi
	done
}

#读取模式文件  得到所需内容
readModeFile() {
	[ ! -f "../$modeName" -a -f "../${modeName}.conf" ] && modeName="${modeName}.conf"
	listen_port=`grep '^ *dns_listen' "../$modeName" | grep -o :[0-9][0-9]\*`
	dns_listen=${listen_port#:}
	listen_port=`grep '^ *tcp_listen' "../$modeName" | grep -o :[0-9][0-9]\*\;`
	tcp_listen=`echo ${listen_port#:} | grep -o [0-9][0-9]*`
	if grep -q 'TPROXY' /proc/net/ip_tables_targets; then
		listen_port=`grep '^ *udp_tproxy_listen' "../$modeName" | grep -o :[0-9][0-9]\*`
		udp_listen=${listen_port#:}
	fi
	grep -q '^ *tcp_option *= *TFO' "../$modeName" && echo '3' >/proc/sys/net/ipv4/tcp_fastopen
}

#通过包名得到uid
getPackageUid() {
	packageName=${1%%_*}  #过滤包名后面的端口
	if echo $packageName | grep -q '[A-Za-z]'; then
		packageInfo=`grep -oE "^$packageName ([0-9])+" /data/system/packages.list`
		[ $? != 0 ] && return 1
		echo "$1" | grep -qE '_([0-9])+' && \
			echo "${packageInfo#* }_${1#*_}" || \
			echo "${packageInfo#* }"
	else
		echo "$1"
	fi
}

#放行
allowService() {
	#共享UDP放行
	for p in $shareAllowUdpPorts; do
		iptables -t mangle -I CLNC_FORWARD -p udp --dport $p -j ACCEPT
	done
	#IP放行
	for ip in $allowIPs; do
		iptables -t mangle -I CLNC_FORWARD -d $ip -j ACCEPT
		iptables -t nat -I CLNC_PREROUTING -d $ip -j ACCEPT
	done
}

#配置iptables转发和ip路由
iptablesAndIp() {
	###nat表
	iptables -t nat -N CLNC_PREROUTING 2>&-
	iptables -t nat -I PREROUTING -s 192.168/16 -g CLNC_PREROUTING
	iptables -t nat -A CLNC_PREROUTING -p udp --dport 53 -j REDIRECT --to $dns_listen #53
	iptables -t nat -A CLNC_PREROUTING ! -d 192.168/16 -p tcp -j REDIRECT --to $tcp_listen
	###mangle表
	iptables -t mangle -N CLNC_FORWARD 2>&-
	iptables -t mangle -I FORWARD -g CLNC_FORWARD
	if [ -z "$udp_listen" ]; then
		iptables -t mangle -A CLNC_FORWARD ! -d 192.168/16 -j DROP
	else
		iptables -t mangle -A CLNC_FORWARD ! -d 192.168/16 ! -p udp -j DROP
		iptables -t mangle -N CLNC_PREROUTING 2>&-
		iptables -t mangle -I PREROUTING -g CLNC_PREROUTING
		for allowIp in 127/8 10/8 192.168/16 172.16/12 255/8 224/4 240/4 169.254/16; do
			iptables -t mangle -A CLNC_PREROUTING -d $allowIp -j ACCEPT
		done
		iptables -t mangle -A CLNC_PREROUTING ! -i tun+ -p udp -j TPROXY --on-port $udp_listen --tproxy-mark 999
		##路由
		ip rule add fwmark 999 table 100 pref 49 2>&-
		ip route add local default dev lo table 100 2>&-
	fi
}

#clnc运行状态检测
clncRunStatus() {
	if [ -f "/proc/$(grep -o ^[0-9]* clnc.pid)/cwd/CuteBi" ]; then
		echo '✔  clnc 正在运行'
	else
		echo '✘  clnc 没有运行'
	fi
}

#状态检查
statusCheck() {
	##网卡和IP检测
	ip addr | grep -E "^[0-9]+:|inet" | while read line; do
		if echo $line|grep -qE "^[0-9]+:"; then
			devName=`echo $line|grep -iE "^[0-9]+: [^:]+:"`
			devName=${devName#*: }
			devName=${devName%%:*}
			typeset -L17 devName=${devName%@*} 2>/dev/null
		else
			ipAddr=${line#* }
			ipAddr=${ipAddr%% *}
			echo "$devName$ipAddr"
		fi
	done
	echo "✄┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄"
	echo
	clncRunStatus
	{
		iptables -t nat -N CLNC_PREROUTING
		iptables -t mangle -N CLNC_FORWARD
		iptables -t mangle -N CLNC_PREROUTING
	} 2>/dev/null
	echo
	echo "✄┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄"
	echo '❁ mangle表 PREROUTING链:'
	iptables -t mangle -S PREROUTING
	echo '✺ mangle表 CLNC_PREROUTING链:'
	iptables -t mangle -S CLNC_PREROUTING
	echo '❁ nat表 PREROUTING链:'
	iptables -t nat -S PREROUTING
	echo '✺ nat表 CLNC_PREROUTING链:'
	iptables -t nat -S CLNC_PREROUTING
	echo '❁ mangle表 FORWARD链:'
	iptables -t mangle -S FORWARD
	echo '✺ mangle表 CLNC_FORWARD链:'
	iptables -t mangle -S CLNC_FORWARD
}

clearServer() {
	#关闭程序
	pid=`grep -o ^[0-9]* clnc.pid 2>/dev/null`
	[ -f "/proc/$pid/cwd/CuteBi" ] && kill $pid	
	./clnc -k
	{
		#清理ip路由规则
		ip rule delete fwmark 999 table 100
		ip route delete local default dev lo table 100
		#清理iptables规则
		iptables -t nat -D PREROUTING -s 192.168/16 -g CLNC_PREROUTING
		iptables -t mangle -D PREROUTING -g CLNC_PREROUTING
		iptables -t mangle -D FORWARD -g CLNC_FORWARD
		iptables -t nat -F CLNC_PREROUTING
		iptables -t mangle -F CLNC_PREROUTING
		iptables -t mangle -F CLNC_FORWARD
		iptables -t nat -Z CLNC_PREROUTING
		iptables -t mangle -Z CLNC_PREROUTING
		iptables -t mangle -Z CLNC_FORWARD
		iptables -t nat -X CLNC_PREROUTING
		iptables -t mangle -X CLNC_PREROUTING
		iptables -t mangle -X CLNC_FORWARD
	} 2>/dev/null
}

startServer() {
	readModeFile #读取模式文件
	clearServer #关闭脚本
	autoUpdataCores  #自动更新核心
	iptablesAndIp #启动防跳
	allowService #执行放行服务
	[ -n "$clnc_dns" ] && export CLNC_INIT_CONFIG_DNS="$clnc_dns"
	#启动程序
	[ $(echo $modeName | grep "open_cns") ] && ./clnc -p cns.pid -c "../cns.conf"
	./clnc -p clnc.pid -g 3004 -c "../$modeName"
}

#ip[6]tables命令获取锁失败则重新执行
aliasIptables() {
	iptables_path=`which iptables`
	ip6tables_path=`which ip6tables`
	if iptables --help | grep -q "\-w"; then
		iptables() { "${iptables_path:-/system/bin/iptables}" -w $@; }
		ip6tables() { "${ip6tables_path:-/system/bin/ip6tables}" -w $@; }
	else
		iptables() {
			result=`"${iptables_path:-/system/bin/iptables}" $@ 2>&1`
			[ "$?" = '4' ] && iptables $@ || echo -E "$result"|grep -qE 'xtables block|xtables_lock wait = [1-9]'
		}
		ip6tables() {
			result=`"${ip6tables_path:-/system/bin/ip6tables}" $@ 2>&1`
			[ "$?" = '4' ] && ip6tables $@ || echo -E "$result"|grep -qE 'xtables block|xtables_lock wait = [1-9]'
		}
	fi
}

#读取脚本配置文件
readConfigFile() {
	eval "`grep -v '^\;' ../config.ini`"  #ini文件;开头是注释
}

#脚本入口
main() {
	cd "${1%/*}"
	chmod 777 *
	readConfigFile
	aliasIptables
	case "$2" in
		'stop')
			clearServer
			echo "✄┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄"
			clncRunStatus
			echo "✄┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄"
		;;
		'start')
			startServer
			echo "✄┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄"
			clncRunStatus
			echo "✄┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄"
			checkUpdate
		;;
		'status')
			statusCheck
		;;
	esac
}

main "$0" "$1" 2>&1
