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

START=41
STOP=40
UCI_CONFIG="network"
DEFAULT_RT_PRIO=`/usr/sbin/iprule_idx.sh default`
DEFAULT_RT_AUTOLB_BASE=`/usr/sbin/iprule_idx.sh default`
INVALID_DEFAULT_ROUTE=99999
JSON_FILE="/var/cd_status"
JSON="json -f $JSON_FILE"
model=`head -n 1 /etc/version`
TIMEOBJ_CONFIG="time_object"
CGI_ERROR_MSG="/tmp/cgi_error_msg"
LOG="/usr/bin/logger -t network -p local4.info"
SCRIPT_LOCK="/tmp/web_apply_lock/network"

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
	
	conntrack -F
	#/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 "network($$):refresh connection detection settings" >/dev/console
			kill -SIGUSR1 `cat /var/run/conn_dect.pid`
		else
			echo "network($$):connection detection pid error, restart conn_dect" >/dev/console
			rm -f /var/run/conn_dect.pid
			nohup /sbin/conn_dect &> /dev/null &
		fi
	else
		echo "network($$):start connection detection" >/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_double_tag_mode_disable()  {
	cmm -c vlan doubletag remove
	/sbin/ifdown_doubletag_enable -a
	/usr/sbin/ip rule del pref $DEFAULT_RT_PRIO > /dev/null 2> /dev/null
	set_default_rt
	ifup -a
	/sbin/wifi up    
}
change_double_tag_mode_enable() {
    /sbin/ifdown_doubletag_disable -a
	/usr/sbin/ip rule del pref $DEFAULT_RT_PRIO > /dev/null 2> /dev/null	
	set_default_rt
	ifup -a
	/sbin/wifi up
	cmm -c vlan doubletag add
}
change_wan_mode_to_basic() {
	. $IPKG_INSTROOT/lib/network/config.sh
	config_load network
	#vigor300B does not have "WAN Advance mode"
	scan_interfaces
	if [ "$model" == "Vigor3900" ];then
		wan_port_list=wan[1-5]
		wan_interface="wan1 wan2 wan3 wan4 wan5"
	else
		wan_port_list=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_list)
			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
}

set_dmz_rule()
{
	caller=$1
	old_proto=`uci oget network.wan4.proto`
	old_mode=`uci oget network.wan4.dmz_mode`
	old_status=`uci oget network.wan4.status`
	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_status" = "enable" -a "$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
		ipset -F wan4_dmz_host
	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
				## Add each host ip into wan4_dmz_host
				ipset -A wan4_dmz_host $dmz_host_ip/255.255.255.255 >/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 >/dev/null 2>/dev/null
			ipset -A wan4_dmz_host $nat_ipaddr/$nat_mask >/dev/null 2>/dev/null
		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
}
alloc_route_id()
{
	/sbin/get_route_table_id $1 >/dev/null
}
boot() {
	boot_old_nowtime=$(cat /proc/uptime | awk 'FS="[.]+" {print $1}')
	echo "network($$): boot start" >/dev/console
	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
	#allow remote request to WAN4 DMZ Host
	iptables -A BLOCKDIRECTNAT -t mangle -i wan+ -m mset2 --set2 wan4_dmz_host src --set2 wan4_dmz_host dst -j ACCEPT
	iptables -A BLOCKDIRECTNAT -t mangle -i wan+ -m set --set lan_net_set dst -j DROP
	#iptables -A LANROUTE -j DROP		#moved to lanroute

	##### 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.
	
	#old_nowtime=$(cat /proc/uptime | awk 'FS="[.]+" {print $1}')
	config_load network
	config_foreach alloc_route_id
	config_foreach boot_ifup_lan
	config_foreach boot_ifup_wan
	#nowtime=$(cat /proc/uptime | awk 'FS="[.]+" {print $1}')
	#echo "network($$): boot_ifup_lan_wan time=$(($nowtime - $old_nowtime))" >/dev/console
	
	#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_foreach nat_route_rule	#has been integrated into config.sh
	
	config_foreach schedule_reconnect
	doubletag=`uci get network.general.double_tag`
	if [ -z "$doubletag" ] ;then 
	    uci set network.general.double_tag=disable
		uci commit network
	fi
	    
# 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
	boot_nowtime=$(cat /proc/uptime | awk 'FS="[.]+" {print $1}')
	echo "network($$): boot END exec_time=$(($boot_nowtime - $boot_old_nowtime))" >/dev/console
}

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() {
	lock $SCRIPT_LOCK
	apply_start_time=$(cat /proc/uptime | awk 'FS="[.]+" {print $1}')
	echo "network($$): (start) apply_lock created at time=$apply_start_time" > /dev/console

#########	Modify Interface mode #######
	## pre-make mac address
	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
	
	## if change wan mode from advance to basic
	old_wan_mode=`uci oget network.general.wan_mode`
	new_wan_mode=`uci get network.general.wan_mode`
	[ "$old_wan_mode" = "advance" -a "$new_wan_mode" = "basic" ] && change_wan_mode_to_basic
	
	## modify double tag mode
	old_doubletag=`uci oget network.general.double_tag`
	new_doubletag=`uci get network.general.double_tag`
	if [ "$old_doubletag" = "disable" -a  "$new_doubletag" = "enable" ] ;then
		echo "Enable double tag mode" >/dev/console
		change_double_tag_mode_enable
	elif [ "$old_doubletag" = "enable" -a  "$new_doubletag" = "disable" ] ;then
		echo "Disable double tag mode" >/dev/console
		#for iface in $intface; do
		#	vid=`uci get network.$iface.vlan_id`
		#	port=`uci get network.$iface.port`
		#	untag=`uci get network.$iface.untag`
		#	wan_port "$vid" "$port" "$untag"
		#done
		change_double_tag_mode_disable
	fi
	
#########	Interface APPLY MAIN BODY #######
	chg_all_ifs=`uci fchanges all network`
	for iface in $chg_all_ifs; do
		[ "$iface" = "default_route" ] && {
			set_default_rt
			set_default_rt_auto_lb
			continue
		}
		
		[ "$iface" = "general" ] && {
			continue
		}
		status=`uci get $UCI_CONFIG.$iface.status`
		physical=`uci get $UCI_CONFIG.$iface.physical`
		vid=`uci get $UCI_CONFIG.$iface.vlan_id`
		default_mac=`uci get $UCI_CONFIG.$iface.default_mac`
		macaddr=`uci get $UCI_CONFIG.$iface.macaddr`
		port=`uci get $UCI_CONFIG.$iface.port`
		untag=`uci get $UCI_CONFIG.$iface.untag`
		pvlan_id=`uci get $UCI_CONFIG.$iface.vlan_id`
		priority=`uci get $UCI_CONFIG.$iface.pvid`
		
		##### block HA_LAN modification when High availability is running
		if [ "$physical" = "eth0" ] ;then
			ha_status=`uci get ucarp_mode.general.status`
			if [ "$ha_status" = "enable" ] ;then
				ucarp_hs_lan=`uci filter ucarp_hs lan $iface`
				ucarp_as_lan=`uci filter ucarp_as lan $iface`
				if [ -n "$ucarp_hs_lan" -o -n "$ucarp_as_lan" ] ;then
					echo -n "High Availabilty is running, operation on the LAN profile($iface) is not permitted. Please disable HA function first" >$CGI_ERROR_MSG
					uci revert network.$iface
					nowtime=$(cat /proc/uptime | awk 'FS="[.]+" {print $1}')
					echo "network($$)HA LAN Event: apply_lock removed at time:$nowtime, exec_time=$(($nowtime - $apply_start_time))" >/dev/console
					lock -u $SCRIPT_LOCK
					exit 102
				fi
			fi
		fi
		
		##### set ifname = physical.vlan_id. All interfaces must have vlan tag.
		[ "$physical" = "eth0" -o "$physical" = "eth2" ] && {
			ifname="$physical.$vid"
			uci set network.$iface.ifname=$ifname
			##### 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($$):run ifup $iface:exe_time=$(($nowtime - $old_nowtime))" >/dev/console
		if [ "$ifup_ret" = "101" ] ;then
			echo -n "$iface is currently busy due to internal processing. Try to open the profile and click apply again" >$CGI_ERROR_MSG
			nowtime=$(cat /proc/uptime | awk 'FS="[.]+" {print $1}')
			echo "network($$)Ifup busy Event: apply_lock removed at time:$nowtime, exec_time=$(($nowtime - $apply_start_time))" >/dev/console
			lock -u $SCRIPT_LOCK
			exit $ifup_ret
		fi
		
############# Do interface relative works here !!!
	#########	vlan_id priority bit set #######
		if   [ "$physical" = "eth0" ]; then
			/sbin/switch_vid lan $vid
			uci set vlan_lan.$pvlan_id.pvid=$priority
			if [ "$untag" = "disable" ] ; then
				vconfig set_egress_map lan-$iface 0 $priority
			else
				vconfig set_egress_map lan-$iface 0 0
			fi
			
			pppoe_stat=`uci oget pppoe_server.general.status`
			if [ "$pppoe_stat" = "1" ]; then
				new_ifs=`uci fchanges new network`
				for pppoe_iface in $new_ifs; do
					physical=`uci get network.$pppoe_iface.physical`
					if [ "$physical" = "eth0" ]; then
						pppoe_name=`uci oget pppoe_server.general.name`
						`pppoe-server -k -I lan-$pppoe_iface -C $pppoe_name`
					fi
				done
			fi
			/etc/init.d/dhcpd apply & >/dev/null 2>&1
			/etc/init.d/pptpd restart & >/dev/null 2>&1
			/etc/init.d/ssltunnel restart & >/dev/null 2>&1
			/etc/init.d/iprouting lan_changed $iface & >/dev/null 2>&1
		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"
			uci set vlan_wan.$pvlan_id.pvid=$priority
			if [ "$untag" = "disable" ] ; then
				vconfig set_egress_map wan-$iface 0 $priority
			else
				vconfig set_egress_map wan-$iface 0 0
			fi
		fi
		#Modify WAN schedule reconnect
		schedule_reconnect "$iface" apply
		/etc/init.d/cron restart &
		[ "$iface" = "wan4" ] && set_dmz_rule "apply"
		#tr069
		cwmp_intf=$(uci get cwmp.tr069.wan_profile)
		if [ "$cwmp_intf" = "$iface" ];then
			/etc/init.d/cwmp restart &
		fi
	#########	Delete related interface attributes if status is disabled #######
		[ "$status" = "disable" ] && {
			echo "network($$): profile $iface has been disable, delete records" >/dev/console
			json delete network.$iface
			rt_table_id=`json get policy_rt.table_map.$iface`
			#/etc/init.d/lb_rule "do_auto_failover" "$rt_table_id" "DOWN" &
			#/etc/init.d/addr_map "do_auto_failover" "$rt_table_id" "DOWN" &
			/etc/route_down_drop.sh "network#profile_disable" "$rt_table_id" "DOWN" &
			/etc/bind/restart_my_dns 4 $iface &
			/usr/sbin/check_policy_rt.sh $iface &
			failover_tell_up $iface
			
			#Signal lighttpd to update new LAN subnet attributes
			sed "/^$iface /d" -i /tmp/enabled_lan_attr
			kill -47 `pidof lighttpd`
		}
		
		##### if USB WAN changed, have to power off and power on usb device
		if [ "$iface" = "usb1" -o "$iface" = "usb2" ]; then
			proto=$(uci get $UCI_CONFIG.$iface.proto)
			if [ "$iface" = "usb1" -a "$proto" = "3g" ]; then
				echo 0 > /proc/lte_drv
			elif [ "$iface" = "usb1" -a "$proto" = "4g" ]; then
				echo 1 > /proc/lte_drv
			elif [ "$iface" = "usb2" -a "$proto" = "3g" ]; then
				echo 2 > /proc/lte_drv
			elif [ "$iface" = "usb2" -a "$proto" = "4g" ]; then
				echo 3 > /proc/lte_drv
			fi
			
			/etc/init.d/usb usb_pw $iface off
			sleep 2
			/etc/init.d/usb usb_pw $iface on
		fi
	done
	
	## refresh NAT_ROUTE_PREROUTING				#moved to config.sh, run by interface
	
	del_ifs=`uci fchanges delete network`
	for iface in $del_ifs; do
		echo "network($$): profile $iface has been deleted, delete records" >/dev/console
		json delete network.$iface
		/etc/bind/restart_my_dns 4 $iface &
		/usr/sbin/check_policy_rt.sh $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
			ip link delete eth0.$vid
			#Signal lighttpd to update new LAN subnet attributes
			sed "/^$iface /d" -i /tmp/enabled_lan_attr
			kill -47 `pidof lighttpd`
		elif [ "$physical" = "eth2" ]; then
			uci delete vlan_wan.$vid
			ip link delete eth2.$vid
		fi
	done
	/etc/init.d/rtk8366_vlan apply 	
	start_conn_dect
	#igmp proxy
	#/etc/init.d/igmpproxy_script restart 2>/dev/null &		#moved to 10-status
	
	uci commit $UCI_CONFIG
	nowtime=$(cat /proc/uptime | awk 'FS="[.]+" {print $1}')
	echo "network($$): (finished) apply_lock removed at time $nowtime, exec_time=$(($nowtime - $apply_start_time))" >/dev/console
	lock -u $SCRIPT_LOCK
}
