#!/bin/bash

set -x

netcard_wan=eth0
cfgfile_wan=
account_file=/etc/router/run/account_list.txt

# 从文档中 mac.txt 筛选出的mac前缀
# 选取出现频率大于50的mac，可见 mac.csv
mac_prefix_pool=("04:27:58:" "14:69:a2:" "18:44:e6:" "18:c5:01:" "20:f1:7c:" "30:0c:23:" "30:91:76:" "48:43:5a:" "48:55:5f:" "4c:f2:bf:" "50:6f:77:" "60:b6:17:" "64:3e:8c:" "68:a8:28:" "70:d9:31:" "74:9d:8f:" "7c:a2:3e:" "80:b0:7b:" "88:cf:98:" "b8:05:ab:" "d0:d0:4b:" "d8:74:95:" "e4:a8:b6:" "e8:68:19:" "f4:9e:ef:" "f8:6e:ee:" "fc:8f:7d:" "68:d1:ba:")
get_virtual_mac() {
	# 获取随机数 % 数组长度
	local index=$(expr $RANDOM % ${#mac_prefix_pool[*]})
	echo "${mac_prefix_pool[$index]}$(openssl rand -hex 3 | sed 's/\(..\)/\1:/g; s/.$//') " #取前缀并随机生成后缀
	return $?
}

wan_start_lan() {
	proc=$(pgrep dnsmasq)
	if [[ -z ${proc} ]]; then
		/etc/router/scripts/start_lan.sh >/dev/null 2>&1
	fi
	proc=$(pgrep hostapd)
	if [[ -z ${proc} ]]; then
		/etc/router/scripts/start_wireless_5g.sh >/dev/null 2>&1
		/etc/router/scripts/start_wireless_2g.sh >/dev/null 2>&1
	fi
}

wan_stop_lan() {
	proc=$(pgrep dnsmasq)
	if [[ -n ${proc} ]]; then
		kill -9 ${proc}
	fi
	proc=$(pgrep hostapd)
	if [[ -n ${proc} ]]; then
		kill -9 ${proc}
	fi
}

wan_stop_pppd() {
	proc=$(pgrep pppd)
	if [[ -n ${proc} ]]; then
		kill -9 ${proc}
		sleep 0.5
	fi
}

wan_stop_wireless() {
	local netcard=wlan0
	if [[ ! -d /sys/class/net/${netcard} ]]; then
		return
	fi

	proc=$(ps -ef | grep "dhclient ${netcard}" | grep -v grep | awk '{print $2}')
	if [[ -n ${proc} ]]; then
		kill -9 ${proc}
		sleep 0.2
	fi
	proc=$(pgrep wpa_supplicant)
	if [[ -n ${proc} ]]; then
		kill -9 ${proc}
		sleep 0.2
	fi

	if [[ -d /sys/class/net/${netcard}-ap ]]; then
		proc=$(ps -ef | grep "hostapd.conf-${netcard}-ap" | grep -v grep | awk '{print $2}')
		if [[ -n ${proc} ]]; then
			kill -9 ${proc}
		fi
		iw dev ${netcard}-ap del
		sleep 0.2
	fi

	if [[ ${setup} != 7 ]]; then
		return
	fi

	proc=$(ps -ef | grep "hostapd.conf-${netcard}" | grep -v grep | awk '{print $2}')
	if [[ -n ${proc} ]]; then
		hostapd_cli -i ${netcard} disable
		kill -9 ${proc}
		sleep 0.5
	fi

	systemctl stop wpa_supplicant
	ifconfig ${netcard} down
	ifconfig ${netcard} 0.0.0.0
	brctl delif br-lan ${netcard} >/dev/null 2>&1
}

wan_dns_manual() {
	dns_manual=$(cat ${cfgfile_wan} | jq -r .dns_manual)

	if [[ ${dns_manual} == 1 ]]; then
		dns1=$(cat ${cfgfile_wan} | jq -r .dns1)
		dns2=$(cat ${cfgfile_wan} | jq -r .dns2)
		echo "nameserver ${dns1}" >/etc/resolv.conf
		echo "nameserver ${dns2}" >>/etc/resolv.conf
	fi
}

wan_create_br_lan() {
	cfgfile_gateway=/etc/router/config/lan_gateway.json
	lan_gateway=$(cat ${cfgfile_gateway} | jq -r .ipaddr)
	lan_netmask=$(cat ${cfgfile_gateway} | jq -r .netmask)

	ifconfig br-lan
	if [[ $? != 0 ]]; then
		brctl addbr br-lan
		ifconfig br-lan ${lan_gateway} netmask ${lan_netmask} up

		lan_segment=$(ip route | grep br-lan | awk '{print $1}' | head -1)
		iptables -A FORWARD -o br-lan -j ACCEPT
		iptables -A FORWARD -i br-lan -j ACCEPT
		iptables -t nat -A POSTROUTING -s ${lan_segment} ! -o br-lan -j MASQUERADE
	fi
}

wan_br_addif() {
	netcard_lan=$(ls /sys/class/net/ | grep -v "$(ls /sys/devices/virtual/net/)" | grep -v ${netcard_wan})
	for lan_if in ${netcard_lan[@]}; do
		nmcli device set ${lan_if} managed no
		brctl addif br-lan ${lan_if} >/dev/null 2>&1
		ifconfig ${lan_if} 0.0.0.0 up
	done

	if [[ ${setup} == 6 ]] || [[ ${setup} == 8 ]]; then
		brctl addif br-lan ${netcard_wan} >/dev/null 2>&1
		nmcli device set ${netcard_wan} managed yes
	else
		brctl delif br-lan ${netcard_wan} >/dev/null 2>&1
		nmcli device set ${netcard_wan} managed no
	fi
}

wan_pppoe_dial() {
	cfgfile_wan=/etc/router/config/wan_pppoe_dial.json
	netcard=${netcard_wan}
	username=$(cat ${cfgfile_wan} | jq -r .username)
	password=$(cat ${cfgfile_wan} | jq -r .password)

	cat >/etc/ppp/options.prfile <<EOF
noauth
refuse-eap
user '${username}'
password '${password}'
plugin rp-pppoe.so ${netcard}
mru 1492 mtu 1492
persist
holdoff 10
maxfail 0
usepeerdns
ipcp-accept-remote ipcp-accept-local noipdefault
ktune
default-asyncmap nopcomp noaccomp
novj nobsdcomp nodeflate
lcp-echo-interval 6
lcp-echo-failure 10
lcp-echo-adaptive
unit 0
linkname prfile0
EOF

	pppd file /etc/ppp/options.prfile
	wan_dns_manual
	wan_br_addif
	wan_start_lan
}
wan_pppoe_multidial() {
	cfgfile_wan=/etc/router/config/wan_pppoe_multidial.json
	vlan_enabled=$(cat ${cfgfile_wan} | jq -r .vlan_enabled)
	cat ${cfgfile_wan} | jq -r .account_list >${account_file}

	docker ps -a
	mac=$(ifconfig docker0 | grep ether | awk '{print $2}')
	n=0
	netcard=${netcard_wan}
	pppif=veth${n}
	vlanif=${netcard}
	while read line; do
		ac=$(echo ${line} | awk '{print $1}')
		pw=$(echo ${line} | awk '{print $2}')
		vlan=$(echo ${line} | awk '{print $3}')
		vlanif=${netcard}
		pppif=veth${n}
		if [[ -n ${vlan} ]]; then
			vlanif=${netcard}.${vlan}
			pppif=veth${n}
			local macvlan=$(get_virtual_mac)
			cmd=$(cat /etc/network/interfaces | grep ${vlanif} | head -n 1 | awk '{print $2}')
			if [ -z ${cmd} ]; then
				cat >>/etc/network/interfaces <<EOF
auto ${vlanif}
iface ${vlanif} inet manual
pre-up ifconfig ${vlanif} hw ether ${macvlan}
EOF
				ip link add link ${netcard} name ${vlanif} type vlan id ${vlan}
			fi
		fi

		brctl delif br-lan ${vlanif} >/dev/null 2>&1

		local vethmac=$(get_virtual_mac)
		ip link delete ${pppif}
		sleep 0.5
		ip link add link ${vlanif} name ${pppif} address ${vethmac} type macvlan
		sleep 0.5
		ip link set ${pppif} up
		sleep 0.5
		ifconfig ${pppif} down
		sleep 0.5
		ifconfig ${pppif} up
		sleep 0.5

		cat >/etc/ppp/options.prfile${n} <<EOF
noauth
refuse-eap
user '${ac}'
password '${pw}'
plugin rp-pppoe.so ${pppif}
mru 1492 mtu 1492
persist
holdoff 10
maxfail 0
usepeerdns
ipcp-accept-remote ipcp-accept-local noipdefault
ktune
default-asyncmap nopcomp noaccomp
novj nobsdcomp nodeflate
lcp-echo-interval 6
lcp-echo-failure 10
lcp-echo-adaptive
unit ${n}
linkname prfile${n}
EOF
		pppd file /etc/ppp/options.prfile${n}
		sleep 1
		let n+=1
	done <${account_file}

	wan_dns_manual
	wan_start_lan
}

wan_pppoe_multiwan() {
	cfgfile_wan=/etc/router/config/wan_pppoe_multiwan.json
	vlan_enabled=$(cat ${cfgfile_wan} | jq -r .vlan_enabled)
	cat ${cfgfile_wan} | jq -r .account_list >${account_file}

	docker ps -a
	mac=$(ifconfig docker0 | grep ether | awk '{print $2}')
	n=0
	netcard=
	pppif=
	while read line; do
		ac=$(echo ${line} | awk '{print $1}')
		pw=$(echo ${line} | awk '{print $2}')
		netcard=$(echo ${line} | awk '{print $3}')
		vlan=$(echo ${line} | awk '{print $4}')
		pppif=veth${n}
		vlanif=${netcard}
		if [[ -n ${vlan} ]]; then
			vlanif=${netcard}.${vlan}
			pppif=veth${n}
			local macvlan=$(get_virtual_mac)
			#cmd=` cat /etc/network/interfaces | grep ${vlanif} | head -n 1 | awk '{print $2}'`
			cmd=
			if [ -z ${cmd} ]; then
				cat >>/etc/network/interfaces <<EOF
auto ${vlanif}
iface ${vlanif} inet manual
pre-up ifconfig ${vlanif} hw ether ${macvlan}
EOF
				ip link delete ${vlanif}
				sleep 1
				ip link add link ${netcard} name ${vlanif} type vlan id ${vlan}
				ip link set ${vlanif} up
			fi
		fi
		brctl delif br-lan ${vlanif} >/dev/null 2>&1

		local vethmac=$(get_virtual_mac)
		ip link delete ${pppif}
		sleep 0.5
		ip link add link ${vlanif} name ${pppif} address ${vethmac} type macvlan
		sleep 0.5
		ip link set ${pppif} up
		sleep 0.5
		ifconfig ${pppif} down
		sleep 0.5
		ifconfig ${pppif} up
		sleep 0.5

		ipparam=$(echo "${n}*10+10" | bc)

		sed '/ppp'"${n}"'/{h;s/^.*$/'"${ipparam} ppp${n}"'/};${x;/^$/{s//'"${ipparam} ppp${n}"'/;H};x}' -i /etc/iproute2/rt_tables

		cat >/etc/ppp/options.prfile${n} <<EOF
noauth
refuse-eap
user '${ac}'
password '${pw}'
plugin rp-pppoe.so ${pppif}
mru 1492 mtu 1492
persist
holdoff 10
maxfail 0
usepeerdns
ipcp-accept-remote ipcp-accept-local noipdefault
ktune
default-asyncmap nopcomp noaccomp
novj nobsdcomp nodeflate
lcp-echo-interval 6
lcp-echo-failure 10
lcp-echo-adaptive
unit ${n}
linkname prfile${n}
ipparam ${ipparam}
EOF
		pppd file /etc/ppp/options.prfile${n}
		sleep 1
		let n+=1
	done <${account_file}

	wan_dns_manual
	wan_start_lan
}

# nmcli 是ubuntu 用于管理网络的,这里用于获取dhcp ip
wan_dhcp() {
	cfgfile_wan=/etc/router/config/wan_dhcp.json
	netcard=${netcard_wan}
	con_name=${netcard}-con
	nmcli c delete ${con_name}
	dns_manual=$(cat ${cfgfile_wan} | jq -r .dns_manual)
	if [[ ${dns_manual} == 1 ]]; then
		dns1=$(cat ${cfgfile_wan} | jq -r .dns1)
		dns2=$(cat ${cfgfile_wan} | jq -r .dns2)
		nmcli c add type ethernet con-name ${con_name} ifname ${netcard} ipv4.ignore-auto-dns yes ipv4.dns "${dns1},${dns2}" ipv4.method auto
	else
		nmcli c add type ethernet con-name ${con_name} ifname ${netcard} ipv4.method auto
	fi
	nmcli c up ${con_name}

	wan_br_addif
	wan_start_lan
}

netmask_to_prefix() {
	n=0
	b=3
	for i in ${1//./ }; do
		if ((0 <= i < 256)); then
			let n+=$((2 ** (b * 8) * i))
			let b--
		else
			exit 1
		fi
	done
	[[ $(echo "obase=2;$n" | bc) =~ ^(1+)0*$ ]] && ((${#BASH_REMATCH[0]} == 32)) && echo ${#BASH_REMATCH[1]}
}

wan_static_multi() {

	wan_br_addif
	cfgfile_wan=/etc/router/config/wan_multistatic.json
	local vlan_enabled=$(jq -r .vlan_enabled ${cfgfile_wan})
	local ipv4_enabled=$(jq -r .ipv4_enabled ${cfgfile_wan})
	local ipv6_enabled=$(jq -r .ipv6_enabled ${cfgfile_wan})
	local mask=100
	local n=0
	local json=null

	jq -c '.infos[]' ${cfgfile_wan} | while read info; do
		local interface_based=$(echo $info | jq .interface | tr -d '"')
		local vlan=$(echo $info | jq .vlan | tr -d '"')
		local ipaddr=$(echo $info | jq .ipaddr | tr -d '"')
		local netmask=$(echo $info | jq .netmask | tr -d '"')
		local gateway=$(echo $info | jq .gateway | tr -d '"')
		local dns1=$(echo $info | jq .dns1 | tr -d '"')
		local dns2=$(echo $info | jq .dns2 | tr -d '"')
		local ipaddr6=$(echo $info | jq .ipaddr6 | tr -d '"')
		local gateway6=$(echo $info | jq .gateway6 | tr -d '"')
		local dns6_1=$(echo $info | jq .dns6_1 | tr -d '"')
		local dns6_2=$(echo $info | jq .dns6_2 | tr -d '"')

		local arg="type ethernet ifname ${interface_based}"

		# TODO: VLAN
		# Temporarily not implemented
		local interface=${interface_based}

		if [ "$vlan_enabled" = "1" ]; then
			# generate vlan interface
			# Use vlan interface as con_name

			interface=${interface_based}.${vlan}
			arg="type vlan ifname ${interface} dev ${interface_based} id ${vlan}"
		fi
		if [ "$ipv4_enabled" = "1" ]; then
			prefix=$(netmask_to_prefix ${netmask})
			arg="${arg} ipv4.addr ${ipaddr}/${prefix} ipv4.gateway ${gateway} ipv4.dns ${dns1},${dns2} ipv4.method manual"
		fi
		if [ "$ipv6_enabled" = "1" ]; then
			arg="${arg} ipv6.addr ${ipaddr6} ipv6.gateway ${gateway} ipv6.dns ${dns6_1},${dns6_2} ipv6.method manual"
		fi

		local con_name="${interface}-con"
		nmcli c delete ${con_name}
		nmcli c add con-name ${con_name} ${arg}
		nmcli c up ${con_name}

		brctl delif br-lan ${interface} >/dev/null 2>&1
		brctl delif br-lan ${interface_based} >/dev/null 2>&1
		if [ "$vlan_enabled" = "1" ]; then
			local macvlan="${mac:0:8}:$(openssl rand -hex 3 | sed 's/\(..\)/\1:/g; s/.$//') "
			ifconfig ${interface} hw ether ${macvlan}
		fi
		if [ "$ipv4_enabled" = "1" ]; then
			# add monitor list
			# configure ip rule
			/etc/router/scripts/route.sh -s "${interface} ${ipaddr} ${gateway} ${mask}"

			json=$(echo ${json} | jq "setpath([${n},\"interface\"]; \"${interface}\")")
			json=$(echo $json | jq "setpath([${n},\"ipaddr\"]; \"${ipaddr}\")")
			json=$(echo $json | jq "setpath([${n},\"gateway\"]; \"${gateway}\")")
			json=$(echo $json | jq "setpath([${n},\"mask\"]; \"${mask}\")")
			echo $json >/etc/router/config/monitor_multi_static_ip.json

		fi
		sleep 1
		let mask+=10
		let n+=1
	done
	wan_start_lan
}

wan_static() {
	cfgfile_wan=/etc/router/config/wan_static.json
	netcard=${netcard_wan}
	addr=$(cat ${cfgfile_wan} | jq -r .ipaddr)
	mask=$(cat ${cfgfile_wan} | jq -r .netmask)
	gateway=$(cat ${cfgfile_wan} | jq -r .gateway)
	dns1=$(cat ${cfgfile_wan} | jq -r .dns1)
	dns2=$(cat ${cfgfile_wan} | jq -r .dns2)
	prefix=$(netmask_to_prefix ${mask})
	con_name=${netcard}-con
	nmcli c delete ${con_name}
	nmcli c add type ethernet con-name ${con_name} ifname ${netcard} ipv4.addr ${addr}/${prefix} ipv4.gateway ${gateway} ipv4.dns "${dns1},${dns2}" ipv4.method manual
	nmcli c up ${con_name}
	wan_br_addif
	wan_start_lan
}

wan_bridge() {
	cfgfile_wan=/etc/router/config/wan_bridge.json
	wan_br_addif
	wan_stop_lan
}

wan_wireless_repeater() {
	#wan_stop_wireless
	cfgfile_wan=/etc/router/config/wan_wireless_repeater.json
	ssid=$(cat ${cfgfile_wan} | jq -r .ssid)
	key=$(cat ${cfgfile_wan} | jq -r .key)
	encryption=$(cat ${cfgfile_wan} | jq -r .encryption)
	netcard=wlan0
	mac=$(ifconfig docker0 | grep ether | awk '{print $2}')
	mac_ap="${mac:0:8}:$(openssl rand -hex 3 | sed 's/\(..\)/\1:/g; s/.$//') "
	iw dev ${netcard} interface add ${netcard}-ap type managed addr ${mac_ap}
	wpa_supplicant_cfgpath=/etc/router/run/wpa_supplicant.conf
	if [[ ${encryption} == "on" ]]; then
		cat >${wpa_supplicant_cfgpath} <<EOF
ctrl_interface=/var/run/wpa_supplicant
network={
	scan_ssid=1
	ssid="${ssid}"
	psk="${key}"
}
EOF
	else
		cat >${wpa_supplicant_cfgpath} <<EOF
ctrl_interface=/var/run/wpa_supplicant
network={
	scan_ssid=1
	ssid="${ssid}"
	key_mgmt=NONE
}
EOF
	fi
	wpa_supplicant -B -i ${netcard} -c ${wpa_supplicant_cfgpath}
	nohup /etc/router/scripts/dhcp_get_ip.sh ${netcard} >/dev/null 2>&1 &
	wan_br_addif
	wan_start_lan
}

cfgfile_wan_method=/etc/router/config/wan_method.json
setup=$(cat ${cfgfile_wan_method} | jq -r .setup)
wan_stop_pppd
wan_stop_wireless
wan_create_br_lan
if [ -r /etc/router/config/custom.cfg ]; then
	netcard_wan=$(cat /etc/router/config/custom.cfg | grep wan_if | tail -1 | awk -F= '{print $2}')
fi

# delete the previous con_name
nmcli c show | grep "\-con" | awk '{print $1}' | while read con_name; do
	nmcli c delete ${con_name}
done

# delete
/etc/router/scripts/route.sh -a

case "${setup}" in
1)
	wan_pppoe_dial
	;;
2)
	wan_pppoe_multidial
	;;
3)
	wan_pppoe_multiwan
	;;
4)
	wan_dhcp
	;;
5)
	wan_static
	;;
6)
	wan_bridge
	;;
7)
	wan_wireless_repeater
	;;
8)
	wan_static_multi
	;;
*)
	exit 1
	;;
esac

#exit 0
