#!/bin/sh
. /etc/functions.sh
pppX="$1"
tty="$2"
speed="$3"
local_ip="$4"
remote_ip="$5"
iface="$6"
dns1="$7"
dns2="$8"
dialin_username="$9"
din_ack="$10"
PPP_FLUSH_MEM=150
PPP_FLUSH_MEM_INTERVAL=60

[ -z "$dialin_username" ] && logger -p 160.5 "PPP IFACE=$1 TTY=$2 SPEED=$3 LOCAL=$4 REMOTE=$5 IPPARAM=$6"
export PATH=/usr/bin:/bin:/usr/sbin:/sbin
UCI_CONFIG=pptp_l2l_din
IPTABLES_CHAIN=PPTP_L2L_RULE
IPTABLES_MSS_CHAIN=PPTP_TCPMSS
RESOLV_CONF="/tmp/resolv.conf.auto"
#TCPMSS=`uci get pptpd_config.pptpd.pptp_mss`
GAP=1000
VPN_LAST_LOG_MAX=20
if [ "$din_ack" = "PPPOE" ]; then
	VPN_LAST_LOG="/tmp/pppoe_last_log"
else
	VPN_LAST_LOG="/tmp/vpn_last_log"
fi



proto=`uci get network.$iface.proto`
profile=`json get $dialin_username.profile -f /var/pptp_din_mapping`
routername=`uci get syslogd.syslogd.routername`
cvm_status=$(uci get cvmd.general.status)
[ -z "$profile" ] || {
	state=`uci get $UCI_CONFIG.$profile.state`
	if   [ "$state" != "enable" ]; then
		return 0;
	fi
	
	# add json item
	localsubnet=`uci get $UCI_CONFIG.$profile.localsubnet`
	remotesubnet=`uci get $UCI_CONFIG.$profile.remotesubnet`
	json set pptp_l2l.$dialin_username ppp_if=$pppX
	#json set $dialin_username.$pppX mss=$TCPMSS

	# add tcp mss rule
	#/usr/sbin/iptables -t mangle -I $IPTABLES_MSS_CHAIN -p tcp --tcp-flags SYN,RST SYN -i $pppX -j TCPMSS --set-mss $TCPMSS
	#/usr/sbin/iptables -t mangle -I $IPTABLES_MSS_CHAIN -p tcp --tcp-flags SYN,RST SYN -o $pppX -j TCPMSS --set-mss $TCPMSS
	
	# add routing rule
	ROUTE_TABLE_ID=`json -f /var/pptp_rt_id get policy_rt.table_map.$profile`
	/usr/sbin/ip route add default dev $pppX table $ROUTE_TABLE_ID

	# flush route cache
	#/usr/sbin/flush_route_cache.sh "ip-up"
	#/usr/sbin/ip route flush cache #Comment off by Vincent F. 2013/02/01
	[ "$remotesubnet" ] && {
		for subn in $remotesubnet ; do
			/usr/sbin/flush_route_cache.sh "ip-up" all $subn
		done
	}
	# pptp acceleration
	cmm -c set pptp $pppX
	
	/usr/sbin/flush_route_cache.sh "ip-up" all $remote_ip	# for udp udp-broadcast-relay
	#Following commands will clear route cache, not necessary to flush cache here.
	#1. ip route flush/replace
	#2. ip route flush/replace table
	#3. ip addr flush dev
	#4. ip link set device down
	
	#vpn syslog and mail alert for L2L
	pptp_din_idx=$(cat /etc/config/pptp_l2l_din | grep pptp-l2l-din | grep pptp-l2l-din -n | grep $profile | awk -F":" '{print $1}')
	logger -p local1.notice "PPP IFACE=$1 TTY=$2 SPEED=$3 LOCAL=$4 REMOTE=$5 IPPARAM=$6"
	logger -p local1.notice "[L2L][UP][PPTP][@$pptp_din_idx:$profile]"
	logger -p local1.alert "[L2L][UP][PPTP][@$pptp_din_idx:$profile]"
	pptp_alert_date=$(date +"%Y-%m-%d %H:%M:%S")
	sh /sbin/SendAlert.sh "4" "[L2L][UP][PPTP][@$pptp_din_idx:$profile] from $routername is Up $pptp_alert_date" >/dev/console
	sh /sbin/MailSendAlert.sh "4" "[L2L][UP][PPTP][@$pptp_din_idx:$profile] from $routername is Up $pptp_alert_date" >/dev/console
	echo "$pptp_alert_date -- UpVPN() L2L PPTP : Profile Index = $pptp_din_idx, Name = $profile" >> /tmp/vpn_mailalert
	/etc/mailtest.sh vpn &
	if [ $(sort $VPN_LAST_LOG/$profile 2>/dev/null | wc -l) -lt $VPN_LAST_LOG_MAX ]; then
		[ -d $VPN_LAST_LOG ] || mkdir $VPN_LAST_LOG
		echo "$profile UP $pptp_alert_date" >> $VPN_LAST_LOG/$profile
	else
		lastnum=`expr $VPN_LAST_LOG_MAX - 1`
		tail -$lastnum $VPN_LAST_LOG/$profile > /tmp/tmp_vpn_last_log
		cat /tmp/tmp_vpn_last_log > $VPN_LAST_LOG/$profile
		echo "$profile UP $pptp_alert_date" >> $VPN_LAST_LOG/$profile
	fi
	date +%s > /var/run/$pppX.stime

	#send alert to cvm
	if [ "$cvm_status" == "enable" ]; then
		if [ -f /tmp/cvm/nextalert ]; then
			alertid=$(cat /tmp/cvm/nextalert)
			json -f /tmp/cvm/alert.json set $alertid time="$(date +"%Y-%m-%d %H:%M:%S %Z")" devicename="$profile" type="PPTP" description="$profile connected!"
			let "alertid++"
			echo $alertid > /tmp/cvm/nextalert
		else
			json -f /tmp/cvm/alert.json set 1 time="$(date +"%Y-%m-%d %H:%M:%S %Z")" devicename="$profile" type="PPTP" description="$profile connected!"
			mkdir -p /tmp/cvm
			echo 2 > /tmp/cvm/nextalert
		fi
	fi
}

[ -z "$profile" -a -n "$dialin_username" ] && {
	if [ "$din_ack" = "L2TP" ]; then
		pppid=$(cat /var/run/$pppX.pid 2>/dev/null)
		if [ "$pppid" != "" ]; then
			remote_host=$(strings /proc/$pppid/cmdline | grep -A 1 remote-host | tail -1)
			[ $(ipsec whack --status | grep l2tp_over_ipsec | grep $remote_host -c) != "0" ] && {
				din_ack="L2TP/IPSec"
				echo $pppid > /var/run/$pppX.pid.ipsec
			}
		fi
	elif [ "$din_ack" = "PPTP" ]; then
		# pptp acceleration
		cmm -c set pptp $pppX
	else
		[ -z "$din_ack" ] && din_ack="PPP"
	fi
	logger -p local1.notice "PPP IFACE=$1 TTY=$2 SPEED=$3 LOCAL=$4 REMOTE=$5 IPPARAM=$6"
	logger -p local1.notice "[H2L][UP][$din_ack][@$dialin_username]"
	logger -p local1.alert "[H2L][UP][$din_ack][@$dialin_username]"
	pptp_alert_date=$(date +"%Y-%m-%d %H:%M:%S")
	sh /sbin/SendAlert.sh "4" "[H2L][UP][$din_ack][@$dialin_username] from $routername is Up $pptp_alert_date" >/dev/console
	sh /sbin/MailSendAlert.sh "4" "[H2L][UP][$din_ack][@$dialin_username] from $routername is Up $pptp_alert_date" >/dev/console
	echo "$pptp_alert_date -- UpVPN() H2L $din_ack : Profile Name = $dialin_username" >> /tmp/vpn_mailalert
	/etc/mailtest.sh vpn &
	/usr/sbin/flush_route_cache.sh "ip-up" all $remote_ip	# for udp udp-broadcast-relay
	if [ $(sort $VPN_LAST_LOG/$dialin_username 2>/dev/null | wc -l) -lt $VPN_LAST_LOG_MAX ]; then
		[ -d $VPN_LAST_LOG ] || mkdir $VPN_LAST_LOG
		echo "$dialin_username UP $pptp_alert_date" >> $VPN_LAST_LOG/$dialin_username
	else
		lastnum=`expr $VPN_LAST_LOG_MAX - 1`
		tail -$lastnum $VPN_LAST_LOG/$dialin_username > /tmp/tmp_vpn_last_log
		cat /tmp/tmp_vpn_last_log > $VPN_LAST_LOG/$dialin_username
		echo "$dialin_username UP $pptp_alert_date" >> $VPN_LAST_LOG/$dialin_username
	fi
	date +%s > /var/run/$pppX.stime
}

[ -z "$proto" ] || {
	##### ian.20100323 change pppoe(pppx) to uniform ifname
	#TOCHK: Should proto=PPTP be renamed => yes
	
	ifname=wan-$iface
	#excute "ip link set down" will cause inet6 address disappear, we save it before setting down, then re-add it back
	#ip6linkip=`ip -6 addr show dev $pppX 2> /dev/null | awk '/scope link/{ printf $2 }'`#get link local IPv6 of ?an?-?an?
	/usr/sbin/ip link set $pppX down
	/usr/sbin/ip link set $pppX name $ifname
	/usr/sbin/ip link set $ifname up
	#ip -6 addr add $ip6linkip dev $ifname

	json set network.$iface ifname=$ifname ipaddr=$local_ip netmask="255.255.255.255" gateway=$remote_ip dns="" ip_alias=""
	/usr/sbin/ipset -A ipalias_$iface $local_ip
	/usr/sbin/ipset -A ip_$iface $local_ip

	logger "$iface PPP($$)ip-up: add new dns record"
	sed -i "/#$iface$/d" $RESOLV_CONF 2> /dev/null
	
	user_dns=$(uci -q get "network.$iface.user_dns")
	user_dns_status=$(uci -q get "network.$iface.user_dns_status")
	if [ "$user_dns_status" = "enable" -a -n "$user_dns" ]; then 
		dns="$user_dns"
		[ -n "$dns" ] && {
			for i in $dns ; do
				[ "$i" = "0.0.0.0" ] && continue
				echo "nameserver $i #$iface" >> $RESOLV_CONF
				json set network.$iface dns=",$i"
			done
		}
	else
		[ -z "$dns1" -o "$dns1" = "0.0.0.0" ] || {
			echo "nameserver $dns1 #$iface" >> $RESOLV_CONF
			json set network.$iface dns=",$dns1"
		}
		[ -z "$dns2" -o "$dns2" = "0.0.0.0" ] || {
			echo "nameserver $dns2 #$iface" >> $RESOLV_CONF
			json set network.$iface dns=",$dns2"
		}
	fi

	rt_table_id=`get_route_table_id $iface`
	#PS: no need to flush route, ip-down should have done it

	logger "$iface PPP($$)ip-up: adding primary ip:$local_ip related settings"
	/usr/sbin/iptables -t mangle -A OUTPUT_WAN -s $local_ip -j MARK --set-mark $rt_table_id
	#/usr/sbin/ip route del default 2>/dev/null		#this seems no use
	##### add route of primary wan ip
	/usr/sbin/ip route replace default via $remote_ip dev $ifname table $rt_table_id
	/usr/sbin/ip rule add pref $((33267+$rt_table_id)) from $local_ip table $rt_table_id
	
	##### add route of ip alias
	if [ "$proto" = "pppoe" ]; then
		ip_alias=`uci get network.$iface.pppoe_ip_alias`
		[ -n "$ip_alias" -a -n "$rt_table_id" ] && {
			for ip2 in $ip_alias; do
				logger "$iface PPP($$)ip-up: adding ip alias $ip2 related settings"
				echo $ip2 | grep "/" >/dev/null || continue
				/usr/sbin/ip addr add $ip2 dev $ifname brd + 2>/dev/null
				/usr/sbin/ipset -A ipalias_$iface ${ip2%/*}
				local NETWORK PREFIX
				eval `ipcalc -np $ip2`
				ip route add $NETWORK/$PREFIX dev $ifname table $rt_table_id 2>/dev/null
				ip rule add pref $((33267+$rt_table_id)) from $ip2 table $rt_table_id
				json set network.$iface ip_alias=",$ip2"
				/usr/sbin/iptables -t mangle -A OUTPUT_WAN -s $ip2 -j MARK --set-mark $rt_table_id
			done
		}
	fi

	logger "$iface PPP($$)ip-up: cd_mode=$cd_mode, call hotplug-call iface, reset connection detection retry counter"
	now=$(cat /proc/uptime | awk 'FS="[.]+" {print $1}')
	json -f /var/cd_status set interface.$iface retried=0 pppd_start_time=$now
	env -i ACTION="ifup" INTERFACE="$iface" DEVICE="$ifname" PROTO="$proto" /sbin/hotplug-call "iface" &
	
	/etc/init.d/cwmp restart 2>/dev/null >/dev/null
	#restart dnsmasq for [G35964]
	/etc/init.d/dnsmasq restart 2>/dev/null >/dev/null
}

[ -d /etc/ppp/ip-up.d ] && {
	for SCRIPT in /etc/ppp/ip-up.d/*
	do
		[ -x "$SCRIPT" ] && "$SCRIPT" $@
	done
}

# udp udp-broadcast-relay for netbios name
if [ "$proto" != "pppoe" -a  "$din_ack" != "PPPOE" ]; then
	killall udp-broadcast-relay
	all_ppp=$(echo $(ifconfig | grep -o ppp[0-9]*))
	localif=$(uci -q get pptpd_config.pptpd.localif || echo 'lan1')
	nbns_off=$(uci -q get pptpd_config.pptpd.disable_nbns || echo '1')
	logger -p local1.notice "PPTP client joined. Resetting UDP Broadcast Relay on port 137: lan-${localif} ${all_ppp}"
	[ "$nbns_off" == "0" ] && /usr/sbin/udp-broadcast-relay -f 1 137 lan-$localif $all_ppp &
fi

ppp_num=$(ps | grep ppp -c)
if [ $ppp_num -gt $PPP_FLUSH_MEM ]; then
        if [ -f /tmp/do_ppp_flush_mem_cache ]; then
                flush_now=$(date +"%s")
                flush_last=$(cat /tmp/do_ppp_flush_mem_cache)
                flush_interval=`expr $flush_now - $flush_last`
                if [ $flush_interval -ge $PPP_FLUSH_MEM_INTERVAL ]; then
                        echo "$(date +"%s")" > /tmp/do_ppp_flush_mem_cache
                        logger -p local1.notice "PPP total number $ppp_num, release MEM Cache"
                        /sbin/sysctl -w vm.drop_caches=3
                fi
        else
                echo "$(date +"%s")" > /tmp/do_ppp_flush_mem_cache
                logger -p local1.notice "PPP total number $ppp_num, release MEM Cache"
                /sbin/sysctl -w vm.drop_caches=3
        fi
fi

