[RDKB: add bridge mode feature]

[Description]
Add bridge mode feature
Refer to service_bridge_rpi.sh
dmcli eRT setv Device.X_CISCO_COM_DeviceControl.LanManagementEntry.1.LanMode string bridge-static

[Release-log]

diff --git a/recipes-ccsp/util/utopia.bbappend b/recipes-ccsp/util/utopia.bbappend
index 3cdc0e6..3f011eb 100644
--- a/recipes-ccsp/util/utopia.bbappend
+++ b/recipes-ccsp/util/utopia.bbappend
@@ -12,6 +12,7 @@
     file://0003-remove-autoconf.patch;apply=no \
     file://system_defaults \
     file://0004-enable-sshd-by-default-at-bootup.patch;apply=no \
+    file://service_bridge_mtk.sh \
 "
 SRC_URI_append_dunfell = "file://0001-Work-around-for-brlan0-issue.patch;apply=no"
 
@@ -113,7 +114,7 @@
     install -m 755 ${S}/source/scripts/init/system/need_wifi_default.sh ${D}${sysconfdir}/utopia/
     touch ${D}${sysconfdir}/dhcp_static_hosts
     #filogic uses default service_bridge.sh for now
-    install -m 755 ${S}/source/scripts/init/service.d/service_bridge.sh ${D}${sysconfdir}/utopia/service.d/service_bridge.sh
+    install -m 755 ${WORKDIR}/service_bridge_mtk.sh ${D}${sysconfdir}/utopia/service.d/service_bridge.sh
 
     install -m 755 ${WORKDIR}/dhcp_script.sh ${D}${sysconfdir}/
     
diff --git a/recipes-ccsp/util/utopia/service_bridge_mtk.sh b/recipes-ccsp/util/utopia/service_bridge_mtk.sh
new file mode 100644
index 0000000..186bf86
--- /dev/null
+++ b/recipes-ccsp/util/utopia/service_bridge_mtk.sh
@@ -0,0 +1,769 @@
+#!/bin/sh
+##########################################################################
+# If not stated otherwise in this file or this component's Licenses.txt
+# file the following copyright and licenses apply:
+#
+# Copyright 2018 RDK Management
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+##########################################################################
+
+##########################################################################
+#   Copyright [2018] [Cisco Systems, Inc.]
+# 
+#   Licensed under the Apache License, Version 2.0 (the "License");
+#   you may not use this file except in compliance with the License.
+#   You may obtain a copy of the License at
+# 
+#       http://www.apache.org/licenses/LICENSE-2.0
+# 
+#   Unless required by applicable law or agreed to in writing, software
+#   distributed under the License is distributed on an "AS IS" BASIS,
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#   See the License for the specific language governing permissions and
+#   limitations under the License.
+#########################################################################
+
+
+source /etc/utopia/service.d/hostname_functions.sh
+source /etc/utopia/service.d/ulog_functions.sh
+source /etc/utopia/service.d/event_handler_functions.sh
+
+SERVICE_NAME="bridge"
+
+UDHCPC_PID_FILE=/var/run/udhcpc.pid
+UDHCPC_SCRIPT=/etc/utopia/service.d/service_bridge/dhcp_link.sh
+
+POSTD_START_FILE="/tmp/.postd_started"
+
+#Separate routing table used to ensure that responses from the web UI go directly to the LAN interface, not out erouter0
+BRIDGE_MODE_TABLE=69
+
+
+
+#-------------------------------------------------------------
+# Registration/Deregistration of dhcp client restart/release/renew handlers
+# These are only needed if the dhcp is used
+# Note that service_bridge is creating the pseudo service dhcp_client
+#-------------------------------------------------------------
+HANDLER="/etc/utopia/service.d/service_bridge/dhcp_link.sh"
+
+unregister_dhcp_client_handlers() {
+   # ulog bridge status "$PID unregister_dhcp_client_handlers"
+   asyncid1=`sysevent get ${SERVICE_NAME}_async_id_1`;
+   if [ -n "$asyncid1" ] ; then
+      sysevent rm_async "$asyncid1"
+      sysevent set ${SERVICE_NAME}_async_id_1
+   fi
+   asyncid2=`sysevent get ${SERVICE_NAME}_async_id_2`;
+   if [ -n "$asyncid2" ] ; then
+      sysevent rm_async "$asyncid2"
+      sysevent set ${SERVICE_NAME}_async_id_2
+   fi
+   asyncid3=`sysevent get ${SERVICE_NAME}_async_id_3`;
+   if [ -n "$asyncid3" ] ; then
+      sysevent rm_async "$asyncid3"
+      sysevent set ${SERVICE_NAME}_async_id_3
+   fi
+}
+
+register_dhcp_client_handlers() {
+   # ulog bridge status "$PID register_dhcp_client_handlers"
+   # Remove any prior notification requests
+   unregister_dhcp_client_handlers
+
+   # instantiate a request to be notified when the dhcp_client-restart changes
+   # make it an event (TUPLE_FLAG_EVENT = $TUPLE_FLAG_EVENT)
+   asyncid1=`sysevent async dhcp_client-restart "$HANDLER"`;
+   sysevent setoptions dhcp_client-restart "$TUPLE_FLAG_EVENT"
+   sysevent set ${SERVICE_NAME}_async_id_1 "$asyncid1"
+
+   # instantiate a request to be notified when the dhcp_client-release / renew changes
+   # make it an event (TUPLE_FLAG_EVENT = $TUPLE_FLAG_EVENT)
+   asyncid2=`sysevent async dhcp_client-release "$HANDLER"`;
+   sysevent setoptions dhcp_client-release "$TUPLE_FLAG_EVENT"
+   sysevent set ${SERVICE_NAME}_async_id_2 "$asyncid2"
+
+   asyncid3=`sysevent async dhcp_client-renew "$HANDLER"`;
+   sysevent setoptions dhcp_client-renew "$TUPLE_FLAG_EVENT"
+   sysevent set ${SERVICE_NAME}_async_id_3 "$asyncid3"
+}
+
+
+#--------------------------------------------------------------
+# Enslave a physical or virtual interface to a bridge
+# 
+# Takes parameters : 
+#   $1  : the name of the interface to enslave
+#   $2  : the name of the interface to enslave it to
+#--------------------------------------------------------------
+enslave_a_interface() {
+   ip link set "$1" up
+   ip link set "$1" allmulticast on
+   brctl addif "$2" "$1"
+}
+
+#--------------------------------------------------------------
+# Bring up the ethernet interfaces
+#--------------------------------------------------------------
+bringup_ethernet_interfaces() {
+   return 0
+}
+
+#--------------------------------------------------------------
+# Tear down the ethernet interfaces
+#--------------------------------------------------------------
+teardown_ethernet_interfaces() {
+   for loop in $SYSCFG_lan_ethernet_physical_ifnames
+   do
+      ip link set "$loop" down
+   done
+}
+
+#--------------------------------------------------------------
+# Bring up the wireless interfaces
+#--------------------------------------------------------------
+bringup_wireless_interfaces() {
+
+   INCR_AMOUNT=10
+   WIFI_IF_INDEX=1
+
+   if [ -n "$SYSCFG_lan_wl_physical_ifnames" ] ; then
+       for loop in $SYSCFG_lan_wl_physical_ifnames
+       do
+           MAC=`syscfg get "macwifi0${WIFI_IF_INDEX}bssid1"`
+           
+           ifconfig "$loop" hw ether "$MAC"
+           ip link set "$loop" allmulticast on
+           ulog lan status "setting $loop hw address to $MAC"
+           WL_STATE=`syscfg get wl$(($WIFI_IF_INDEX-1))_state`
+
+           ulog lan status "wlancfg $loop $WL_STATE"
+           wlancfg "$loop" "$WL_STATE"
+           wlancfg "$loop" "$WL_STATE"
+           WIFI_IF_INDEX=`expr $WIFI_IF_INDEX + 1`
+      done
+   fi
+}
+
+#--------------------------------------------------------------
+# Teardown the wireless interfaces
+#--------------------------------------------------------------
+teardown_wireless_interfaces() {
+   for loop in $SYSCFG_lan_wl_physical_ifnames
+   do
+      wlancfg "$loop" down
+      ip link set "$loop" down
+   done
+
+   teardown_wireless_daemons
+}
+
+#--------------------------------------------------------------
+# stop_firewall
+# If the firewall is up, then tear it down
+#--------------------------------------------------------------
+stop_firewall()
+{
+   STATUS=`sysevent get firewall-status`
+   if [ "stopped" != "$STATUS" ] ; then
+      sysevent set firewall-stop
+      sleep 1
+      wait_till_end_state firewall
+   fi
+}
+
+#--------------------------------------------------------------
+# add_ebtable_rule
+# Add rule in ebtable nat PREROUTING chain
+#--------------------------------------------------------------
+add_ebtable_rule()
+{
+   echo "Inside add_ebtable_rule"
+    # Add the rule to redirect diagnostic traffic to CM-LAN in bridge mode
+    #prod_model=`awk -F'[-=]' '/^VERSION/ {print $2}' /etc/versions`
+
+    cmdiag_if=`syscfg get cmdiag_ifname`
+    cmdiag_if_mac=`ip link show "$cmdiag_if" | awk '/link/ {print $2}'`
+    cmdiag_ip="192.168.100.1"
+    wan_if=`syscfg get wan_physical_ifname`
+
+
+    wan_if=`syscfg get wan_physical_ifname` #erouter0
+    subnet_wan=`ip route show | awk '/'"$wan_if"'/ {print $1}' | tail -1` 
+
+     echo "###############################################"
+     echo "cmdiag_if=$cmdiag_if"
+     echo "cmdiag_ip=$cmdiag_ip"
+     echo "wan_if=$wan_if"
+     echo "subnet_wan=$subnet_wan"
+     echo "###############################################"
+
+    echo "ip route del $subnet_wan dev $wan_if"
+    ip route del "$subnet_wan" dev "$wan_if"
+
+    echo "ip route add $subnet_wan dev $cmdiag_if" #proto kernel scope link src $cmdiag_ip"
+    ip route add "$subnet_wan" dev "$cmdiag_if" #proto kernel scope link src $cmdiag_ip
+
+    dst_ip="10.0.0.1" # RT-10-580 @ XB3 
+    echo "ip addr add $dst_ip/24 dev $cmdiag_if"
+    ip addr add $dst_ip/24 dev "$cmdiag_if"
+
+    echo "ebtables -t nat -A PREROUTING -p ipv4 --ip-dst $dst_ip -j dnat --to-destination $cmdiag_if_mac"
+    ebtables -t nat -A PREROUTING -p ipv4 --ip-dst $dst_ip -j dnat --to-destination "$cmdiag_if_mac"
+
+    echo 2 > /proc/sys/net/ipv4/conf/wlan0/arp_announce
+    echo "echo 2 > /proc/sys/net/ipv4/conf/wlan0/arp_announce"
+}
+
+#--------------------------------------------------------------
+# del_ebtable_rule
+# Delete rule in ebtable nat PREROUTING chain
+#--------------------------------------------------------------
+del_ebtable_rule()
+{
+    prod_model=`awk -F'[-=]' '/^VERSION/ {print $2}' /etc/versions`
+    cmdiag_if=`syscfg get cmdiag_ifname`
+    cmdiag_if_mac=`ip link show "$cmdiag_if" | awk '/link/ {print $2}'`
+    
+    wan_if=`syscfg get wan_physical_ifname`
+    wan_ip=`sysevent get ipv4_wan_ipaddr`
+    subnet_wan=`ip route show | grep "$cmdiag_if" | grep -v 192.168.100. | grep -v 10.0.0 | awk '/'"$cmdiag_if"'/ {print $1}'`
+
+    ip route del "$subnet_wan" dev "$cmdiag_if"
+    ip route add "$subnet_wan" dev "$wan_if" proto kernel scope link src "$wan_ip"
+
+
+
+    dst_ip="10.0.0.1" # RT-10-580 @ XB3 PRD
+    ip addr del $dst_ip/24 dev "$cmdiag_if"
+    ebtables -t nat -D PREROUTING -p ipv4 --ip-dst $dst_ip -j dnat --to-destination "$cmdiag_if_mac"
+    #echo 0 > /proc/sys/net/ipv4/conf/wan0/arp_announce
+    echo 0 > /proc/sys/net/ipv4/conf/wlan0/arp_announce
+    echo "echo 0 > /proc/sys/net/ipv4/conf/wlan0/arp_announce"
+}
+
+#--------------------------------------------------------------
+# do_start
+#--------------------------------------------------------------
+do_start()
+{
+   ulog bridge status "stopping firewall"
+   stop_firewall
+   ulog bridge status "firewall status is now `sysevent get firewall-status`"
+
+   ulog bridge status "reprogramming ethernet switch to remove vlans"
+   #disable_vlan_mode_on_ethernet_switch
+
+   ulog bridge status "bringing up lan interface in bridge mode"
+   bringup_ethernet_interfaces
+   bringup_wireless_interfaces
+   
+   brctl addbr "$SYSCFG_lan_ifname"
+   brctl setfd "$SYSCFG_lan_ifname" 0
+   #brctl stp $SYSCFG_lan_ifname on
+   brctl stp "$SYSCFG_lan_ifname" off
+
+
+   # enslave interfaces to the bridge
+   enslave_a_interface "$SYSCFG_wan_physical_ifname" "$SYSCFG_lan_ifname"
+   for loop in $LAN_IFNAMES
+   do
+      enslave_a_interface "$loop" "$SYSCFG_lan_ifname"
+   done
+
+   # bring up the bridge
+   ip link set "$SYSCFG_lan_ifname" up 
+   ip link set "$SYSCFG_lan_ifname" allmulticast on
+
+   ifconfig "$SYSCFG_lan_ifname" hw ether "`get_mac "$SYSCFG_wan_physical_ifname"`" 
+
+   # bridge_mode 1 is dhcp, bridge_mode 2 is static
+   if [ "2" = "$SYSCFG_bridge_mode" ] && [ -n "$SYSCFG_bridge_ipaddr" ] && [ -n "$SYSCFG_bridge_netmask" ] && [ -n "$SYSCFG_bridge_default_gateway" ]; then
+      RESOLV_CONF="/etc/resolv.conf"
+      echo -n  > $RESOLV_CONF
+      if [ -n "$SYSCFG_bridge_domain" ] ; then
+         echo "search $SYSCFG_bridge_domain" >> $RESOLV_CONF
+      fi
+      if [ -n "$SYSCFG_bridge_nameserver1" ]  && [ "0.0.0.0" !=  "$SYSCFG_bridge_nameserver1" ] ; then
+         echo "nameserver $SYSCFG_bridge_nameserver1" >> $RESOLV_CONF
+      fi
+      if [ -n "$SYSCFG_bridge_nameserver2" ]  && [ "0.0.0.0" !=  "$SYSCFG_bridge_nameserver2" ] ; then
+         echo "nameserver $SYSCFG_bridge_nameserver2" >> $RESOLV_CONF
+      fi
+      if [ -n "$SYSCFG_bridge_nameserver3" ]  && [ "0.0.0.0" !=  "$SYSCFG_bridge_nameserver3" ] ; then
+         echo "nameserver $SYSCFG_bridge_nameserver3" >> $RESOLV_CONF
+      fi
+      ip -4 addr add  "$SYSCFG_bridge_ipaddr"/"$SYSCFG_bridge_netmask" broadcast + dev "$SYSCFG_lan_ifname"
+      ip -4 route add default dev "$SYSCFG_lan_ifname" via "$SYSCFG_bridge_default_gateway"
+      # set sysevent tuple showing current state
+      sysevent set bridge_ipv4_ipaddr "$SYSCFG_bridge_ipaddr"
+      sysevent set bridge_ipv4_subnet "$SYSCFG_bridge_netmask"
+      sysevent set bridge_default_router "$SYSCFG_bridge_default_gateway"
+
+   else
+      udhcpc -S -b -i "$SYSCFG_lan_ifname" -h "$SYSCFG_hostname" -p $UDHCPC_PID_FILE  --arping -s $UDHCPC_SCRIPT 
+      register_dhcp_client_handlers
+   fi
+
+ #  vendor_block_dos_land_attack
+
+   bringup_wireless_daemons
+
+   prepare_hostname
+   
+   if [ "1" = "`sysevent get byoi_bridge_mode`" ]; then
+      sysevent set dns-start
+   fi
+
+   ulog bridge status "lan interface up"
+}
+
+#--------------------------------------------------------------
+# do_stop
+#--------------------------------------------------------------
+do_stop()
+{
+   sysevent set dns-stop
+
+   unregister_dhcp_client_handlers
+   ip link set "$SYSCFG_lan_ifname" down
+   ip addr flush dev "$SYSCFG_lan_ifname"
+
+   teardown_wireless_interfaces
+   teardown_ethernet_interfaces
+
+   # remove interfaces from the bridge
+   for loop in $LAN_IFNAMES
+   do
+      ip link set "$loop" down
+      brctl delif "$SYSCFG_lan_ifname" "$loop"
+   done
+   ip link set "$SYSCFG_wan_physical_ifname" down
+
+   ip link set "$SYSCFG_lan_ifname" down
+
+   brctl delbr "$SYSCFG_lan_ifname"
+}
+
+do_start_multi()
+{
+# TODO: add brport to defaults
+PRI_L2=`sysevent get primary_lan_l2net`
+sysevent set multinet-start "$PRI_L2"
+/etc/utopia/service.d/ebtable_rules.sh
+# set brport enabled
+# set resync for primary l2net
+# set firewall restart
+}
+
+do_stop_multi()
+{
+# set brport disabled
+# set resync primary l2net
+# set firewall restart
+echo
+}
+
+#--------------------------------------------------------------
+# service_init
+#--------------------------------------------------------------
+service_init ()
+{
+   # Get all provisioning data
+   # Figure out the names and addresses of the lan interface
+   #
+   # SYSCFG_lan_ethernet_physical_ifnames is the physical ethernet interfaces that
+   # will be part of the lan
+   #
+   # SYSCFG_lan_wl_physical_ifnames is the names of each wireless interface as known
+   # to the operating system
+
+   SYSCFG_FAILED='false'
+   FOO=`utctx_cmd get bridge_mode lan_ifname lan_ethernet_physical_ifnames lan_wl_physical_ifnames wan_physical_ifname bridge_ipaddr bridge_netmask bridge_default_gateway bridge_nameserver1 bridge_nameserver2 bridge_nameserver3 bridge_domain hostname`
+   eval "$FOO"
+  if [ $SYSCFG_FAILED = 'true' ] ; then
+     ulog bridge status "$PID utctx failed to get some configuration data"
+     ulog bridge status "$PID BRIDGE CANNOT BE CONTROLLED"
+     exit
+  fi
+
+  if [ -z "$SYSCFG_hostname" ] ; then
+     SYSCFG_hostname="Utopia"
+  fi 
+
+  LAN_IFNAMES="$SYSCFG_lan_ethernet_physical_ifnames"
+
+   # if we are using wireless interfafes then add them
+   if [ -n "$SYSCFG_lan_wl_physical_ifnames" ] ; then
+      LAN_IFNAMES="$LAN_IFNAMES $SYSCFG_lan_wl_physical_ifnames"
+   fi
+}
+
+#Create a virtual lan0 management interface and connect it to the bride
+#Also prevent this interface from sending any packets to the DOCSIS bridge
+virtual_interface()
+{
+   echo "Inside virtual_interface"
+    CMDIAG_IF=`syscfg get cmdiag_ifname`
+    LAN_IP=`syscfg get lan_ipaddr`
+    LAN_NETMASK=`syscfg get lan_netmask`
+
+    if [ "$1" = "enable" ] ; then
+
+        echo "ifconfig $CMDIAG_IF hw ether `cat /sys/class/net/lan0/address`"
+        ifconfig "$CMDIAG_IF" hw ether "`cat /sys/class/net/${CMDIAG_IF}/address`"
+      
+        virtual_interface_ebtables_rules enable
+
+        echo "ifconfig ${CMDIAG_IF} promisc up"
+        ifconfig "${CMDIAG_IF}" promisc up
+
+        echo "ifconfig $CMDIAG_IF $LAN_IP netmask $LAN_NETMASK up"
+        ifconfig "$CMDIAG_IF" "$LAN_IP" netmask "$LAN_NETMASK" up
+
+        if [ "$LAN_IP" != "$dst_ip" ]; then
+                ifconfig "$CMDIAG_IF" $dst_ip netmask "$LAN_NETMASK" up
+        fi
+    else
+        ip addr flush dev "$CMDIAG_IF"
+        virtual_interface_ebtables_rules disable
+    fi
+}
+
+virtual_interface_ebtables_rules ()
+{
+    CMDIAG_IF=`syscfg get cmdiag_ifname`
+    CMDIAG_MAC=`cat /sys/class/net/"${CMDIAG_IF}"/address`   
+    EROUTER_MAC=`cat /sys/class/net/erouter0/address`
+    BRIDGE_NAME=`syscfg get lan_ifname`
+    LAN_IP=`syscfg get lan_ipaddr`
+     if [ "$1" = "enable" ] ; then
+##Filter table
+           #--------------------------------------------------------------------------------------
+           #####Forward rules for virtual interface(Dont allow lan0 to send traffic to erouter0)
+           #--------------------------------------------------------------------------------------
+
+        ebtables -N BRIDGE_FORWARD_FILTER
+        ebtables -F BRIDGE_FORWARD_FILTER 2> /dev/null
+        ebtables -I FORWARD -j BRIDGE_FORWARD_FILTER
+
+        echo "ebtables -A BRIDGE_FORWARD_FILTER -s $CMDIAG_MAC -o erouter0 -j DROP"
+        ebtables -A BRIDGE_FORWARD_FILTER -s "$CMDIAG_MAC" -o erouter0 -j DROP
+
+        echo "ebtables -A BRIDGE_FORWARD_FILTER -j RETURN"
+        ebtables -A BRIDGE_FORWARD_FILTER -j RETURN
+
+##NAT TABLE
+         #--------------------------------------------------------------------------------------
+         ####Redirect traffic destined to lan0 IP to lan0 MAC address from brlan0(Prerouting rules)
+         #--------------------------------------------------------------------------------------
+        ebtables -t nat -N BRIDGE_REDIRECT
+        ebtables -t nat -F BRIDGE_REDIRECT 2> /dev/null
+        ebtables -t nat -I PREROUTING -j BRIDGE_REDIRECT
+
+        #echo "ebtables -t nat -A BRIDGE_REDIRECT --logical-in $BRIDGE_NAME -p ipv4 --ip-dst $LAN_IP 
+        #      -j dnat --to-destination $CMDIAG_MAC" 
+        #ebtables -t nat -A BRIDGE_REDIRECT --logical-in "$BRIDGE_NAME" -p ipv4 --ip-dst "$LAN_IP" -j dnat --to-destination "$CMDIAG_MAC"
+
+        #echo "ebtables -t nat -A BRIDGE_REDIRECT --logical-in $BRIDGE_NAME -p ipv4 --ip-dst $LAN_IP 
+         #    -j forward --forward-dev l$CMDIAG_IF"
+        #ebtables -t nat -A BRIDGE_REDIRECT --logical-in $BRIDGE_NAME -p ipv4 --ip-dst $LAN_IP -j forward --forward-dev l$CMDIAG_IF
+
+        echo "ebtables -t nat -A BRIDGE_REDIRECT -j RETURN"
+        ebtables -t nat -A BRIDGE_REDIRECT -j RETURN
+
+###BROUTE TABLE
+         #--------------------------------------------------------------------------------------
+         #DROP target in this BROUTING chain actually broutes the frame(frame has to be routed)
+         #--------------------------------------------------------------------------------------
+        echo "ebtables -t broute -A BROUTING -i erouter0 -d $EROUTER_MAC -j redirect --redirect-target DROP"
+        #ebtables -t broute -A BROUTING -i erouter0 -d "$EROUTER_MAC" -j redirect --redirect-target DROP 
+        ebtables -A FORWARD -i erouter0 -d "$EROUTER_MAC" -j DROP
+
+   else
+        echo "ebtables -D FORWARD -j BRIDGE_FORWARD_FILTER"
+        ebtables -D FORWARD -j BRIDGE_FORWARD_FILTER
+
+        echo "ebtables -X BRIDGE_FORWARD_FILTER"
+        ebtables -X BRIDGE_FORWARD_FILTER
+
+        echo "ebtables -t nat -D PREROUTING -j BRIDGE_REDIRECT"
+        ebtables -t nat -D PREROUTING -j BRIDGE_REDIRECT
+
+        echo "ebtables -t nat -X BRIDGE_REDIRECT"
+        ebtables -t nat -X BRIDGE_REDIRECT
+    fi
+}
+
+add_to_group()
+{
+  bridge_name=`syscfg get lan_ifname`
+  
+  bridge_dir="/sys/class/net/$bridge_name"
+  lan_ethernet_ifname=`syscfg get lan_ethernet_physical_ifnames`
+
+  if [  -d "$bridge_dir" ] ;then
+     bridge_status=`cat /sys/class/net/"$bridge_name"/operstate`
+     if [ "$bridge_status" = "down" ] ; then
+        echo "brctl addbr $bridge_name"
+        brctl addbr "$bridge_name"
+        ip link set "$bridge_name" up
+     fi
+  else
+        echo "brctl addbr $bridge_name"
+        brctl addbr "$bridge_name"
+        ip link set "$bridge_name" up
+  fi
+
+  echo "ifconfig $lan_ethernet_ifname up"
+  for loop in $lan_ethernet_ifname
+  do
+     ifconfig "$loop" up
+  done
+
+  echo "brctl addif $bridge_name $lan_ethernet_ifname"
+  for loop in $lan_ethernet_ifname
+  do
+     brctl addif "$bridge_name" "$loop"
+  done
+
+  cmdiag_if=`syscfg get cmdiag_ifname`
+  wan_if=`syscfg get wan_physical_ifname`
+
+  echo "brctl addif brlan0 $wan_if"
+  brctl addif brlan0 "$wan_if"
+
+  echo "brctl delif $bridge_name wifi0 wifi1 wifi2"
+  wifi_wifi0=`iwconfig wifi0|grep IEEE\ 802.11 | wc -l`
+  wifi_wifi1=`iwconfig wifi1|grep IEEE\ 802.11 | wc -l`
+  wifi_wifi2=`iwconfig wifi2|grep IEEE\ 802.11 | wc -l`
+  if [ $wifi_wifi0 == "1" ] ; then
+        brctl delif "$bridge_name" wifi0
+  elif [ $wifi_wifi1 == "1" ]; then
+        brctl delif "$bridge_name" wifi1
+  elif [ $wifi_wifi2 == "1" ]; then
+        brctl delif "$bridge_name" wifi2
+  fi
+
+}
+del_from_group()
+{
+  bridge_name=`syscfg get lan_ifname`
+  echo "brctl addif $bridge_name wifi0 wifi1 wifi2"
+  wifi_wifi0=`iwconfig wifi0|grep IEEE\ 802.11 | wc -l`
+  wifi_wifi1=`iwconfig wifi1|grep IEEE\ 802.11 | wc -l`
+  wifi_wifi2=`iwconfig wifi2|grep IEEE\ 802.11 | wc -l`
+
+  if [ $wifi_wifi0 == "1" ] ; then
+        brctl addif "$bridge_name" wifi0
+  elif [ $wifi_wifi1 == "1" ]; then
+        brctl addif "$bridge_name" wifi1
+  elif [ $wifi_wifi2 == "1" ]; then
+        brctl addif "$bridge_name" wifi2
+  fi
+
+  cmdiag_if=`syscfg get cmdiag_ifname`
+  wan_if=`syscfg get wan_physical_ifname`
+
+  echo "brctl delif brlan0 $wan_if"
+  brctl delif brlan0 "$wan_if"
+}
+
+filter_local_traffic()
+{
+     if [ "$1" = "enable" ] ; then
+        echo "ebtables -N BRIDGE_OUTPUT_FILTER"
+        ebtables -N BRIDGE_OUTPUT_FILTER
+        ebtables -F BRIDGE_OUTPUT_FILTER 2> /dev/null
+        ebtables -I OUTPUT -j BRIDGE_OUTPUT_FILTER
+
+        echo "ebtables -A BRIDGE_OUTPUT_FILTER --logical-out $BRIDGE_NAME -j DROP"
+        ebtables -A BRIDGE_OUTPUT_FILTER --logical-out "$BRIDGE_NAME" -j DROP
+        echo "ebtables -A BRIDGE_OUTPUT_FILTER -o erouter0 -j DROP"
+        ebtables -A BRIDGE_OUTPUT_FILTER -o erouter0 -j DROP
+
+        #Return from filter chain
+        echo "ebtables -A BRIDGE_OUTPUT_FILTER -j RETURN"
+        ebtables -A BRIDGE_OUTPUT_FILTER -j RETURN
+     else
+        ebtables -D OUTPUT -j BRIDGE_OUTPUT_FILTER
+        ebtables -X BRIDGE_OUTPUT_FILTER
+     fi
+}
+
+
+routing_rules(){
+    CMDIAG_IF=`syscfg get cmdiag_ifname`
+    LAN_IP=`syscfg get lan_ipaddr`
+    if [ "$1" = "enable" ] ; then
+
+        #Send responses from $BRIDGE_NAME IP to a separate bridge mode route table
+        echo "ip rule add from $LAN_IP lookup $BRIDGE_MODE_TABLE"
+        ip rule add from "$LAN_IP" lookup $BRIDGE_MODE_TABLE
+
+        #if [ "$LAN_IP" != "$dst_ip" ]; then
+        #        echo "ip rule add from $dst_ip lookup $BRIDGE_MODE_TABLE"
+        #        ip rule add from $dst_ip lookup $BRIDGE_MODE_TABLE
+        #fi
+
+        echo "ip route add table $BRIDGE_MODE_TABLE default dev $CMDIAG_IF"
+        ip route add table $BRIDGE_MODE_TABLE default dev "$CMDIAG_IF"
+
+    else
+        echo "ip rule del from $LAN_IP lookup $BRIDGE_MODE_TABLE"
+        ip rule del from "$LAN_IP" lookup $BRIDGE_MODE_TABLE
+
+        #if [ $LAN_IP != $dst_ip ]; then
+        #        ip rule del from $dst_ip lookup $BRIDGE_MODE_TABLE
+        #fi
+
+        echo "ip route flush table $BRIDGE_MODE_TABLE"
+        ip route flush table $BRIDGE_MODE_TABLE
+    fi
+}
+
+block_bridge(){
+    ebtables -A FORWARD -i erouter0 -j DROP
+}
+
+#Unblock bridged traffic through erouter0
+unblock_bridge(){
+    ebtables -D FORWARD -i erouter0 -j DROP
+}
+
+
+#--------------------------------------------------------------
+# service_start
+#--------------------------------------------------------------
+service_start ()
+{
+   wait_till_end_state ${SERVICE_NAME}
+   STATUS=`sysevent get ${SERVICE_NAME}-status`
+   echo "sysevent get ${SERVICE_NAME}-status $STATUS"
+   if [ "started" != "$STATUS" ] ; then
+
+         sysevent set ${SERVICE_NAME}-errinfo
+         sysevent set ${SERVICE_NAME}-status starting
+
+         block_bridge
+		
+         virtual_interface enable #create lan0 interface and write ebtable rules
+
+         routing_rules enable
+
+         add_to_group
+
+         filter_local_traffic enable 
+
+         unblock_bridge
+
+         # Force a DHCP renew by issuing a physical link down/up, when WAN port mode switches between bridging and routing
+         PSM_MODE=`sysevent get system_psm_mode`
+         #if [ "$PSM_MODE" != "1" ]; then
+            # It is not a good practice to force all physical links to refresh -- should have used arguments to specify which ports/links
+            #gw_lan_refresh
+         #fi
+
+       prepare_hostname
+       if [  -f /tmp/wifi_initialized ];then
+          sysevent set ${SERVICE_NAME}-errinfo
+          sysevent set ${SERVICE_NAME}-status started
+       else
+            sleep 60
+            sysevent set ${SERVICE_NAME}-errinfo
+            sysevent set ${SERVICE_NAME}-status started
+       fi
+
+   fi
+}
+
+#--------------------------------------------------------------
+# service_stop
+#--------------------------------------------------------------
+service_stop ()
+{
+   wait_till_end_state ${SERVICE_NAME}
+   #STATUS=`sysevent get ${SERVICE_NAME}-status` 
+   #if [ "stopped" != "$STATUS" ] ; then
+
+        sysevent set ${SERVICE_NAME}-errinfo
+        sysevent set ${SERVICE_NAME}-status stopping
+
+        block_bridge
+
+        del_from_group
+
+        #Disconnect management interface
+        virtual_interface disable
+        filter_local_traffic disable
+        routing_rules disable
+
+        unblock_bridge
+
+        #Flush connection tracking and packet processor sessions to avoid stale information
+        #flush_connection_info
+
+        sysevent set ${SERVICE_NAME}-errinfo
+        sysevent set ${SERVICE_NAME}-status stopped
+
+#    fi
+
+}
+
+#------------------------------------------------------------------
+# ENTRY
+#------------------------------------------------------------------
+BRIDGE_NAME="$SYSCFG_lan_ifname"
+CMDIAG_IF=`syscfg get cmdiag_ifname`
+
+INSTANCE=`sysevent get primary_lan_l2net`
+LAN_NETMASK=`syscfg get lan_netmask`
+
+
+service_init 
+echo "service_bridge.sh called with $1 $2" > /dev/console
+case "$1" in
+   "${SERVICE_NAME}-start")
+      firewall firewall-stop
+      service_start
+      if [ ! -f "$POSTD_START_FILE" ];
+      then
+          touch $POSTD_START_FILE
+          execute_dir /etc/utopia/post.d/
+      fi         
+      #gw_lan_refresh
+      sysevent set firewall-restart
+      ;;
+   "${SERVICE_NAME}-stop")
+        service_stop
+        if [ ! -f "$POSTD_START_FILE" ];
+        then
+              touch $POSTD_START_FILE
+              execute_dir /etc/utopia/post.d/
+        fi           
+        #gw_lan_refresh
+        sysevent set firewall-restart
+
+      ;;
+   "${SERVICE_NAME}-restart")
+      sysevent set lan-restarting 1
+      service_stop
+      service_start
+      sysevent set lan-restarting 0
+      ;;
+   *)
+      echo "Usage: service-${SERVICE_NAME} [ ${SERVICE_NAME}-start | ${SERVICE_NAME}-stop | ${SERVICE_NAME}-restart]" > /dev/console
+      exit 3
+      ;;
+esac