#!/bin/sh /etc/rc.common
# Copyright (C) 2006 OpenWrt.org

START=41
STOP=40
DEFAULT_RT_PRIO=39000
DEFAULT_RT_AUTOLB_BASE=39000
INVALID_DEFAULT_ROUTE=99999
JSON_FILE="/var/cd_status"
JSON="json -f $JSON_FILE"
model=`head -n 1 /etc/version`
switch_model=$(/sbin/mtd fw_printenv 1|grep switch_model|awk -F = '{print $2}')
TIMEOBJ_CONFIG="time_object"
CGI_ERROR_MSG="/tmp/cgi_error_msg"
LOG="/usr/bin/logger -t network -p local4.info"

model=$(head -n 1 /etc/version)
if [ "$model" = "Vigor3900" ] ;then
	intface="wan1 wan2 wan3 wan4 wan5 usb1 usb2"
elif [ "$model" = "Vigor2960" -o "$model" = "Vigor2960F" ] ;then
	intface="wan1 wan2 usb1 usb2"
elif [ "$model" = "Vigor300B" ] ;then
	intface="wan1 wan2 wan3 wan4 usb1 usb2"
fi


set_default_rt_auto_lb() {
	auto_lb_status=`uci -q get network.default_route.auto_lb`
	MNGT_WAN=`uci get acc_ctrl.access_control.mngt_wan`
	if [ -z "$auto_lb_status" ] ;then
		uci set network.default_route.auto_lb="enable"
		auto_lb_status="enable"
	fi
	if [ "$auto_lb_status" = "enable" ] ;then
		for i in $intface ;do
			[ "$i" = "$MNGT_WAN" ] && continue
			online_status=`json get network.$i.connection`
			#only apply "enabled" and "up" interface profile
			if [ "$online_status" = "up" ] ;then
				rt_table_id=`json get policy_rt.table_map.$i`
				/usr/sbin/ip rule del pref `expr $DEFAULT_RT_AUTOLB_BASE + $rt_table_id` > /dev/null 2> /dev/null
				/usr/sbin/ip rule add pref `expr $DEFAULT_RT_AUTOLB_BASE + $rt_table_id` table $rt_table_id > /dev/null 2> /dev/null
				#/usr/sbin/ip -6 rule add pref `expr $DEFAULT_RT_AUTOLB_BASE + $rt_table_id` table $rt_table_id > /dev/null 2> /dev/null
			fi
		done
	elif [ "$auto_lb_status" = "disable" ] ;then
		for i in $intface ;do
			rt_table_id=`json get policy_rt.table_map.$i`
			/usr/sbin/ip rule del pref `expr $DEFAULT_RT_AUTOLB_BASE + $rt_table_id` table $rt_table_id > /dev/null 2> /dev/null
		done
	fi
}

set_default_rt() {
	default_table=`uci -q get network.default_route.default`
	rt_table_id=`get_route_table_id $default_table`
	#Type regular need to check if the single iface is down
	online_status=`json get network.$default_table.connection`
	if [ "$online_status" = "down" ];then
		rt_table_id=$INVALID_DEFAULT_ROUTE
		#echo "network, type: regular, iface:$trigger_if is down, invalid Droute" >/dev/console
	fi
	#echo "network, result: rt_table_id=$rt_table_id, default_table=$default_table" >/dev/console
	/usr/sbin/ip rule del pref $DEFAULT_RT_PRIO > /dev/null 2> /dev/null
	/usr/sbin/ip rule add pref $DEFAULT_RT_PRIO table $rt_table_id
	#Notice: Here flush ALL route cache
	/usr/sbin/flush_route_cache.sh "network"
	#/usr/sbin/ip route flush cache

	/usr/sbin/ip -6 rule del pref $DEFAULT_RT_PRIO > /dev/null 2> /dev/null
	/usr/sbin/ip -6 rule add pref $DEFAULT_RT_PRIO table $rt_table_id
	/usr/sbin/ip -6 route flush cache
	
	#/etc/init.d/base_configuration restart 2>/dev/null
}

start_conn_dect() {
	if [ -f "/var/run/conn_dect.pid" ]; then
		conndect_pid=`cat /var/run/conn_dect.pid 2>/dev/null`
		cmd_line=`cat /proc/$conndect_pid/cmdline 2>/dev/null`
		echo "$cmd_line" | grep "^/bin/sh/sbin/conn_dect$" >/dev/null 2>/dev/null
		if [ "$?" = 0 ] ;then
			echo "Restart conn_dect" >/dev/console
			kill -SIGUSR1 `cat /var/run/conn_dect.pid`
		else
			echo "conn_dect pid error, re-initialize" >/dev/console
			rm -f /var/run/conn_dect.pid
			nohup /sbin/conn_dect &> /dev/null &
		fi
	else
		echo "Start conn_dect" >/dev/console
		nohup /sbin/conn_dect &> /dev/null &
	fi
}

cal_wan_mac() {
	set - `cat /sys/class/net/eth2/address | sed 's/^\([0-9a-f:]*\)\([0-9a-f]\)$/\1 \2/'`
	
	if   [ "$2" = "1" ]; then
		echo "${1}1 ${1}2 ${1}3 ${1}4 ${1}5"
	elif [ "$2" = "9" ]; then
		echo "${1}9 ${1}a ${1}b ${1}c ${1}d"
	fi
}

wan_port() {
	vid=$1
	port=${2#WAN}
	untag=$3

	uci show vlan_wan.$vid > /dev/null || {
		local tmp
		tmp=`uci add vlan_wan vlanid`
		uci rename vlan_wan.$tmp=$vid
		uci set vlan_wan.$vid.intf=wan
	}
	uci set vlan_wan.$vid.member=$port
	if   [ "$untag" = "enable" ]; then
		uci set vlan_wan.$vid.untag=$port
	else
		uci delete vlan_wan.$vid.untag
	fi
	uci set vlan_wan.$vid.fid=$port	
}

change_wan_mode() {
	. $IPKG_INSTROOT/lib/network/config.sh
	#vigor300B does not have "WAN Advance mode"
	scan_interfaces
      if [ "$model" == "Vigor3900" ];then
       wan_port=wan[1-5]
	   wan_interface="wan1 wan2 wan3 wan4 wan5"
      else
       wan_port=wan[1-2]
	   wan_interface="wan1 wan2"		
      fi
	for ifs in $interfaces; do
		config_get physical $ifs physical
		[ "$physical" = "eth2" ] || continue

		case $ifs in
		$wan_port)
			PORT=${ifs#wan}
			config_get default_mac $ifs default_mac
			config_get macaddr $ifs macaddr
			[ "$default_mac" = "enable" -o "$macaddr" = "default" -o -z "$macaddr" ] && {
				eval WAN_MACADDR=\${WAN${PORT}_MACADDR}
				[ "$macaddr" = "$WAN_MACADDR" ] || uci set network.$ifs.macaddr=$WAN_MACADDR
			}
			config_get port $ifs port
			[ "$port" = "WAN$PORT" ] || uci set network.$ifs.port=WAN$PORT
			config_get vlan_id $ifs vlan_id
			config_get untag $ifs untag
			wan_port "$vlan_id" "WAN$PORT" "$untag"
			;;
		#*)
			#uci delete network.$ifs
			#config_get vid $ifs vlan_id
			#uci delete vlan_wan.$vid
			#;;
		esac
		ifup $ifs
	done
	for ifs in $wan_interface; do
		PORT=${ifs#wan}
		vid=$(($PORT+9))
		uci show network.$ifs > /dev/null && continue

		tmp=`uci add network interface`
		uci rename network.$tmp=$ifs
		uci set network.$ifs.ifname=eth2.$vid
		uci set network.$ifs.physical=eth2
		uci set network.$ifs.vlan_id=$vid
		uci set network.$ifs.port=WAN$PORT
		uci set network.$ifs.untag=enable
		uci set network.$ifs.defaule_mac=enable
		eval WAN_MACADDR=\${WAN${PORT}_MACADDR}
		uci set network.$ifs.macaddr=$WAN_MACADDR
		uci set network.$ifs.status=disable
		uci set network.$ifs.proto=none
		uci set network.$ifs.proto6=link-local
		uci set network.$ifs.mode=NAT
		uci set network.$ifs.pvid=0
	done
}
nat_route_rule()
{
	config_get physical $1 physical
	
	if [ "$physical" = "eth2" -o "$physical" = "usb" ];then
		route_id=$(/sbin/get_route_table_id $1)	
		iptables -t mangle -A NAT_ROUTE_PREROUTING -i wan-$1 -m mset ! --set exception_subnet_set src -m conntrack --ctstate NEW -j MARK --set-mark $route_id
	elif [ "$physical" = "eth0" ];then
		iptables -t mangle -A NAT_ROUTE_PREROUTING -i lan-$1 -o wan+ -m conntrack --ctstate ESTABLISHED,RELATED -j CONNMARK --restore-mark	
	fi 
	
}
set_dmz_rule()
{
	caller=$1
	old_proto=`uci oget network.wan4.proto`
	old_mode=`uci oget network.wan4.dmz_mode`
	status=`uci get network.wan4.status`
	proto=`uci get network.wan4.proto`
	mode=`uci get network.wan4.dmz_mode`
	need_restart_dmz=0
	
	###### Delete old DMZ settings
	if [ "$old_proto" = "dmz" ] ;then
		if [ "$old_mode" = "routing" ] ;then
			old_host_ip_list=`uci oget network.wan4.dmz_host_ip_list`
			old_outgoing_interface=`uci oget network.wan4.dmz_outgoing_interface`
			old_oif_ipaddr=`uci oget network.$old_outgoing_interface.static_ipaddr`
			old_oif_mask=`uci oget network.$old_outgoing_interface.static_netmask`
			for old_dmz_host_ip in $old_host_ip_list ;do
				route del -net $old_dmz_host_ip netmask 255.255.255.255 dev wan-wan4 >/dev/null 2>/dev/null
				arp -i wan-$old_outgoing_interface -d $old_dmz_host_ip pub >/dev/null 2>/dev/null
			done
			arp -i wan-wan4 -d $old_oif_ipaddr netmask $old_oif_mask pub >/dev/null 2>/dev/null
		elif [ "$old_mode" = "nat" ] ;then
			old_nat_ipaddr=`uci oget network.wan4.dmz_ipaddr`
			old_nat_mask=`uci oget network.wan4.dmz_netmask`
			ipset -D lan_nat_subnet $old_nat_ipaddr/$old_nat_mask
		fi
		[ "$caller" != "boot" ] && need_restart_dmz=1
	fi
	
	if [ "$status" = "enable" -a "$proto" = "dmz" ] ;then
		#In ROUTING mode, outgoing WAN should use static protocol
			#Subnet of outgoing interface and of WAN4 DMZ Hosts should be the same
		if [ "$mode" = "routing" ]; then
			outgoing_interface=`uci get network.wan4.dmz_outgoing_interface`
			host_ip_list=`uci get network.wan4.dmz_host_ip_list`
			## Add arp subnet entries according to outgoing interface on WAN4 
			oif_ipaddr=`uci get network.$outgoing_interface.static_ipaddr`
			oif_mask=`uci get network.$outgoing_interface.static_netmask`
			arp -i wan-wan4 -Ds $oif_ipaddr wan-wan4 netmask $oif_mask pub >/dev/null 2>/dev/null

			for dmz_host_ip in $host_ip_list ;do
				## Delete non-necessary arp entries of host_ip_list in subnet
				arp -i wan-wan4 -d $dmz_host_ip >/dev/null 2>/dev/null
				## Add static routes to WAN4 for DMZ hosts
				route add -net $dmz_host_ip netmask 255.255.255.255 dev wan-wan4 >/dev/null 2>/dev/null
				## Add arp entries of DMZ hosts on outgoing WAN
				arp -i wan-$outgoing_interface -Ds $dmz_host_ip wan-$outgoing_interface pub >/dev/null 2>/dev/null
			done
			#The belows doesn't work
			#echo "1" > /proc/sys/net/ipv4/conf/wan-$outgoing_interface/proxy_arp
			#echo "1" > /proc/sys/net/ipv4/conf/wan-wan4/proxy_arp
		elif [ "$mode" = "nat" ]; then
			nat_ipaddr=`uci get network.wan4.dmz_ipaddr`
			nat_mask=`uci get network.wan4.dmz_netmask`
			ipset -A lan_nat_subnet $nat_ipaddr/$nat_mask
		fi
		[ "$caller" != "boot" ] && need_restart_dmz=1
	fi
	
	## If WAN4 dmz is changed by UI apply, need to restart DMZ Host
	[ "$need_restart_dmz" = "1" ] && {
		echo "Network: restart dmz" >/dev/console
		/etc/init.d/dmz restart &
	}
}
schedule_reconnect()
{
	if [ "$2" = "apply" ] ;then
		schedule_reconnect=`uci get network.$1.schedule_reconnect`
		timeobj=`uci get network.$1.timeobj`
	else
		config_get schedule_reconnect $1 schedule_reconnect
		config_get timeobj $1 timeobj
	fi
	#echo "iface=$1, from=$2, schedule_reconnect=$schedule_reconnect, timeobj=$timeobj" >/dev/console
	sed "/========== Schedule reconnect $1 /d" -i /etc/crontabs/root >/dev/null 2>&1
	if [ "$schedule_reconnect" = "enable" ] ;then
		starttime=`uci get $TIMEOBJ_CONFIG.$timeobj.starttime`
		weekdays=`uci get $TIMEOBJ_CONFIG.$timeobj.weekdays`
		hour=`echo $starttime|awk -F":" '{print $1}'`
		min=`echo $starttime|awk -F":" '{print $2}'`
		cron_week=`echo $weekdays|sed 's/Mon/1/g'|sed 's/Tue/2/g'|sed 's/Wed/3/g'|sed 's/Thu/4/g'|sed 's/Fri/5/g'|sed 's/Sat/6/g'|sed 's/Sun/0/g'|awk '{OFS=",";$1=$1;print $0}'`
		echo "$min $hour * * $cron_week logger \"========== Schedule reconnect $1 \";ifup $1" >>/etc/crontabs/root
	fi
}

boot_ifup_lan() {
	local status
	local phy

	config_get status $1 status
	[ "$status" == "enable" ] || return
	config_get phy $1 physical
	[ "$phy" == "eth0" ] || return
	#echo "[network-boot][`cat /proc/uptime |awk -F" " '{print $1}'`] ifup $1" > /dev/console
	ifup $1
}
boot_ifup_wan() {
	local status
	local phy

	config_get status $1 status
	[ "$status" == "enable" ] || return
	config_get phy $1 physical
	[ "$phy" == "eth0" ] && return
	#echo "[network-boot][`cat /proc/uptime |awk -F" " '{print $1}'`] ifup $1" > /dev/console
	ifup $1
}
boot() {
	##### insert module for iptables TCPMSS target
	#for module in iptable_mangle xt_TCPMSS xt_MARK; do
	#	/sbin/insmod $module 2>&- >&-
	#done
	#iptables -t mangle -N WAN_TCPMSS
	#iptables -t mangle -N TCPMSS_FORWARD
	#iptables -t mangle -A POSTROUTING -p tcp --tcp-flags SYN,RST SYN -j WAN_TCPMSS
	#iptables -t mangle -A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS_FORWARD

	#iptables -t nat -N nat_post_route
	#iptables -t nat -A POSTROUTING -j nat_post_route
	#ipset -N lan_nat_subnet iptreemap
    #iptables -t nat -A nat_post_route -o wan-+ -m set --set lan_nat_subnet src -j MASQUERADE
    #iptables -t nat -A nat_post_route -o eth2.+ -m set --set lan_nat_subnet src -j MASQUERADE

	## 20100806 , BLOCK DIRECT NAT
	#ipset -N lan_routing_subnet iptreemap
	#ipset -N lan_net_set setlist --size 200
	#ipset -A lan_net_set lan_nat_subnet
	#ipset -A lan_net_set lan_routing_subnet
	#iptables -t mangle -N BLOCKDIRECTNAT
	#iptables -t mangle -A PREROUTING -j BLOCKDIRECTNAT
	iptables -A BLOCKDIRECTNAT -t mangle -i wan-+ -m set --set lan_routing_subnet dst -j ACCEPT
	iptables -A BLOCKDIRECTNAT -t mangle -i eth2.+ -m set --set lan_routing_subnet dst -j ACCEPT
	iptables -A BLOCKDIRECTNAT -t mangle -i wan+ -m mset --set exception_subnet_set src --set lan_net_set dst -j ACCEPT
	iptables -A BLOCKDIRECTNAT -t mangle -i wan+ -m mset --set exception_subnet_gre_set src --set lan_net_set dst -j ACCEPT
	iptables -A BLOCKDIRECTNAT -t mangle -i wan+ -m set --set lan_net_set dst -j DROP

    ## 20110322, For inter-LAN routing
	#iptables -t mangle -N LANROUTE
    iptables -t mangle -A LANROUTE -j DROP
    ## End inter-LAN routing

	## 201110120 , [G29983][G28679] add all in port redirect
	#ipset -N all_interface setlist --size 200
	#ipset -N all_interface_lan setlist --size 200
	
	#iptables -t mangle -N CTMARK
	#iptables -t mangle -A POSTROUTING -j CTMARK

	#iptables -t mangle -N OUTPUT_WAN
	#iptables -t mangle -A OUTPUT -j OUTPUT_WAN

	##### dnsmasq need /var/resolv.conf.auto
	touch /var/resolv.conf.auto

#	ip6addr=$( ifconfig eth0 2>&1 | grep "fe80::" | cut -d'r' -f 2 | cut -d' ' -f 2 )
#	ip -6 add del $ip6addr dev eth0
#	ip -6 add add $ip6addr dev eth0

	#setup_switch() { return 0; }

	include /lib/network
	#setup_switch
#	[ -s /etc/config/wireless ] || \
#		/sbin/wifi detect > /etc/config/wireless
		/sbin/wifi detect
	echo 1 > /proc/sys/net/ipv6/conf/all/forwarding
	ifconfig lo up
	ifconfig lo 127.0.0.1 netmask 255.0.0.0
	ifconfig eth0 up
	ifconfig eth2 up
	json set policy_rt index_ptr=1
	json set policy_rt vsdf_index_ptr=201
	json -f /var/pptp_rt_id set policy_rt index_ptr_no_fpp=1000
	
	#Give the WANs precedence over others when creating route table id
	model=$(head -n 1 /etc/version)
	if [ "$model" = "Vigor3900" ] ;then
		for intf in $intface ;do
			get_route_table_id $intf >/dev/null 2>/dev/null
		done
	elif [ "$model" = "Vigor2960" -o "$model" = "Vigor2960F" ] ;then
		for intf in $intface ;do
			get_route_table_id $intf >/dev/null 2>/dev/null
		done
	elif [ "$model" = "Vigor300B" ] ;then
		for intf in $intface ;do
			get_route_table_id $intf >/dev/null 2>/dev/null
		done
	fi
	#Vincent F. 2013/07/31, copy from sysctl.init (start=94)
	#Enable ip forward before ifup
	[ -f /etc/sysctl.conf ] && sysctl -p >&-
	sysctl -w net.netfilter.nf_conntrack_icmp_timeout=1 >/dev/null 2>/dev/null
	#ifup -a
	#Vincent F. 2013/07/31, UCI sequence may ordered: lan1, wan1, wan2, wan3, wan4, lan2, lan3.
	#Do not ifup by UCI sequence. We should ifup all LANs first.
	config_load network
	config_foreach boot_ifup_lan
	config_foreach boot_ifup_wan
	#echo "[network-boot][`cat /proc/uptime |awk -F" " '{print $1}'`] ifup all interface ok!" > /dev/console
	set_default_rt
	set_default_rt_auto_lb
	
	set_dmz_rule "boot"
	/sbin/wifi up
    start_conn_dect

	#routing for multipath
	#$DEBUG iptables -t mangle -N LB_RULE
	#$DEBUG iptables -t mangle -N NAT_ROUTE_PREROUTING
	#$DEBUG iptables -t mangle -I PREROUTING 1 -j NAT_ROUTE_PREROUTING
	
	#config_load network
	config_foreach nat_route_rule
	
	config_foreach schedule_reconnect
	
# Commented part below is moved to sysnetif_enable script
#	count=`uci get bridge.general.count`
#	i=1
#	while [ "$i" -le "$count" ]
#	do
#	        brname=`uci get bridge.general.brname$i`
#		ifup "$brname"
#		i=`expr $i + 1`
#	done
#	wifi=`uci get wireless.general.type`
#	case "$wifi" in
#		ra0)
#			ssid=`uci get wireless.ra0.ssid`
#			iwpriv ra0 set SSID="$ssid" >/dev/null 2>/dev/null ;;
#	esac
}

start() {

	set_default_rt
	ifup -a
	/sbin/wifi up
	start_conn_dect
}

restart() {	
	set_default_rt
	ifup -a
	/sbin/wifi up
	start_conn_dect
}

stop() {
	ifdown -a
	/usr/sbin/ip rule del pref $DEFAULT_RT_PRIO > /dev/null 2> /dev/null

	[ -f "/var/run/conn_dect.pid" ] && kill `cat /var/run/conn_dect.pid`
}

#failover: tell my backup to up if i was disabled
failover_tell_up()
{
	backup=`$JSON get interface.$1.backup`
	[ -n "$backup" ] && {
		for bak_if in $backup; do
			$LOG "(Failover)$1 was disabled, tell backup($bak_if) to up"
			$JSON set interface.$bak_if bak_down=0
		done
	}
}


apply() {
	local do_dhcp_restart

	#prevent concurrenct web apply operation by multiple admin
	lockfile="/tmp/web_apply_lock/network"
	nowtime=$(cat /proc/uptime | awk 'FS="[.]+" {print $1}')
	while [ -f "$lockfile" ]
	do
		BREAK_LOCK_INTV=60
		locktime=`cat $lockfile |awk -F" " '{print $2}'`
		nowtime=$(cat /proc/uptime | awk 'FS="[.]+" {print $1}')
		DIFF=$(($nowtime - $locktime))
		if [ $DIFF -le $BREAK_LOCK_INTV ] ;then
			echo "network($$):lockfile(PID=$$, time=$nowtime) exists, go spin 10 secs" > /dev/console
			sleep 10
		else
			echo "network($$):lockfile(PID=$$, time=$nowtime) exceed 60 secs, remove it forcely" > /dev/console
			rm -f $lockfile
		fi
	done
	if [ ! -f "$lockfile" ]; then
		### create lock 
		touch $lockfile
		echo "$$ $nowtime" > "$lockfile"
		echo "network($$):lockfile(PID=$$, time=$nowtime) created" > /dev/console
	fi
	
	config_load network

	LAN_MACADDR=`cat /sys/class/net/eth0/address`
	set -- `cal_wan_mac`
	WAN1_MACADDR=$1
	WAN2_MACADDR=$2
	WAN3_MACADDR=$3
	WAN4_MACADDR=$4
	WAN5_MACADDR=$5

	old_mode=`uci oget network.general.wan_mode`
	config_get wan_mode general wan_mode
	[ "$old_mode" = "advance" -a "$wan_mode" = "basic" ] && change_wan_mode
	
	ifs=`uci fchanges all network`
	for iface in $ifs; do
		[ "$iface" = "default_route" ] && {
			set_default_rt
			set_default_rt_auto_lb
			continue
		}
		
		[ "$iface" = "general" ] && {
			continue
		}
		
		##### block HA_LAN modification when High availability is running
		config_get physical $iface physical
		if [ "$physical" = "eth0" ] ;then
			ha_status=`uci get ucarp_mode.general.status`
			if [ "$ha_status" = "enable" ] ;then
				bind_ha_profile=`uci filter ucarp lan $iface`
				[ -n "$bind_ha_profile" ] && {
					echo -n "Function: High Availabilty is running, the LAN binding with HA profile:[$bind_ha_profile] can not be modified right now. Please disable the HA function first" >$CGI_ERROR_MSG
					uci revert network.$iface
					rm -f $lockfile
					exit 102
				}
			fi
		fi
		
		##### set ifname = physical.vlan_id. All interfaces must have vlan tag.
		[ "$physical" = "eth0" -o "$physical" = "eth2" ] && {
			config_get vid $iface vlan_id
			ifname="$physical.$vid"
			uci set network.$iface.ifname=$ifname

			config_get default_mac $iface default_mac
			config_get macaddr $iface macaddr
			config_get port $iface port
			config_get untag $iface untag

			##### set default mac
			[ "$default_mac" = "enable" -o "$macaddr" = "default" -o -z "$macaddr" ] && {
				if   [ "$physical" = "eth0" ]; then
					[ "$macaddr" = "$LAN_MACADDR" ] || uci set network.$iface.macaddr=$LAN_MACADDR
				elif [ "$physical" = "eth2" ]; then
					eval WAN_MACADDR=\${${port}_MACADDR}
					[ "$macaddr" = "$WAN_MACADDR" ] || uci set network.$iface.macaddr=$WAN_MACADDR
				fi
			}
		}
		logger -p 160.5 "network($$): start to update $iface configuration"
#old_nowtime=$(cat /proc/uptime | awk 'FS="[.]+" {print $1}')
		ifup $iface
		ifup_ret=$?
#nowtime=$(cat /proc/uptime | awk 'FS="[.]+" {print $1}')
#echo "network($$): ifup $iface:execution time=$(($nowtime - $old_nowtime))" >/dev/console
		if [ "$ifup_ret" = "101" ] ;then
			echo -n "$iface is currently busy by internal processing. Your apply is aborted, please open the profile and click apply again" >$CGI_ERROR_MSG
			lockpid=`cat $lockfile |awk -F" " '{print $1}'`
			nowtime=$(cat /proc/uptime | awk 'FS="[.]+" {print $1}')
			if [ "$lockpid" = "$$" ] ;then
				locktime=`cat $lockfile |awk -F" " '{print $2}'`
				echo "network($$)Event 101:lockfile removed at time $nowtime, elapsed time=$(($nowtime - $locktime))" >/dev/console
				rm -f $lockfile
			fi
			exit $ifup_ret
		fi
		
		##### do interface relative works here !!!
		if   [ "$physical" = "eth0" ]; then
#old_nowtime=$(cat /proc/uptime | awk 'FS="[.]+" {print $1}')
			/sbin/switch_vid lan $vid
#nowtime=$(cat /proc/uptime | awk 'FS="[.]+" {print $1}')
#echo "network($$): switch_vid:execution time=$(($nowtime - $old_nowtime))" >/dev/console
			#/etc/init.d/vs lan_changed $iface
			#/etc/init.d/dhcpd apply
			do_dhcp_restart=1
			/etc/init.d/iprouting lan_changed $iface
		elif [ "$physical" = "eth2" ]; then
			old_vid=`uci oget network.$iface.vlan_id`
			[ "$old_vid" = "$vid" ] || uci delete vlan_wan.$old_vid
			wan_port "$vid" "$port" "$untag"
		fi

		config_get status $iface status
		[ "$status" = "enable" ] || {
			echo "network($$): profile $iface has been disable, delete records" >/dev/console
			json delete network.$iface
			/etc/bind/restart_my_dns 4 $iface &
			failover_tell_up $iface
			#[ -f "/var/status_system_interface" ] && json -f /var/status_system_interface delete network.$iface
		}
######### vlan_id priority bit set#######
     
		[ "$physical" = "eth0" ] && {
		 pvlan_id=`uci get network.$iface.vlan_id`
		 priority=`uci get network.$iface.pvid`
		 uci set vlan_lan.$pvlan_id.pvid=$priority
		 
        }	
		[ "$physical" = "eth2" ] && {
		 pvlan_id=`uci get network.$iface.vlan_id`
		 priority=`uci get network.$iface.pvid`
		 uci set vlan_wan.$pvlan_id.pvid=$priority
		 
        }	
		
		#WAN schedule reconnect
		schedule_reconnect $iface apply
		
	done
	
	## refresh NAT_ROUTE_PREROUTING
#old_nowtime=$(cat /proc/uptime | awk 'FS="[.]+" {print $1}')
	iptables -t mangle -F NAT_ROUTE_PREROUTING
	config_foreach nat_route_rule
#nowtime=$(cat /proc/uptime | awk 'FS="[.]+" {print $1}')
#echo "network($$): nat_route_rule:execution time=$(($nowtime - $old_nowtime))" >/dev/console
	
	pppoe_stat=`uci oget pppoe_server.general.status`
	if [ "$pppoe_stat" = "1" ]; then
		pppoe_name=`uci oget pppoe_server.general.name`
		ifs=`uci fchanges new network`
		for iface in $ifs; do
			physical=`uci get network.$iface.physical`
			if [ "$physical" = "eth0" ]; then
				`pppoe-server -k -I lan-$iface -C $pppoe_name`
			fi
		done
	fi
	
	ifs=`uci fchanges delete network`
	for iface in $ifs; do
		echo "network($$): profile $iface has been deleted, delete records in jsonstatus.txt" >/dev/console
		json delete network.$iface
		/etc/bind/restart_my_dns 4 $iface &
		#[ -f "/var/status_system_interface" ] && json -f /var/status_system_interface delete network.$iface
		physical=`uci oget network.$iface.physical`
		vid=`uci oget network.$iface.vlan_id`
		if   [ "$physical" = "eth0" ]; then
			uci delete vlan_lan.$vid
		elif [ "$physical" = "eth2" ]; then
			uci delete vlan_wan.$vid
		fi
	done
	chage_intf=$(uci fchanges all network)
	for iface in $chage_intf ;do
		[ "$iface" = "wan4" ] && set_dmz_rule "apply"
	done
	
	#before some global relative works, commit uci config changes
	uci commit network
	##Warning: procedures below will not be able to "uci oget network"

	## do global relative works here !!!
	[ "$do_dhcp_restart" == "1" ] && {
		config_clear
		/etc/init.d/dhcpd apply 
		/etc/init.d/pptpd restart >/dev/null
	}	
	/etc/init.d/rtk8366_vlan apply
	start_conn_dect
	
	#user-based firewall
	#jimmy
	#dr=$(uci get network.default_route.default)
	#if [ "$dr" = "$chage_intf" ];then
	#	/etc/init.d/base_configuration restart
	#fi
	
	#tr069
	cwmp_intf=$(uci get cwmp.tr069.wan_profile)
	if [ "$cwmp_intf" = "$chage_intf" ];then
		/etc/init.d/cwmp restart &
	fi
	
	#igmp proxy
	/etc/init.d/igmpproxy_script restart 2>/dev/null
	
	
	#Restart for WAN schedule reconnect
	/etc/init.d/cron restart &

	#remove lock of concurrenct web apply
	lockpid=`cat $lockfile |awk -F" " '{print $1}'`
	if [ "$lockpid" = "$$" ] ;then
		nowtime=$(cat /proc/uptime | awk 'FS="[.]+" {print $1}')
		locktime=`cat $lockfile |awk -F" " '{print $2}'`
		echo "network($$):lockfile removed at time $nowtime, elapsed time=$(($nowtime - $locktime))" >/dev/console
		rm -f $lockfile
	fi
}
