#!/bin/bash
# Monitors for multicast groups that have been added, and
# sets up the appropriate flow.
# $1 action, start, stop
# $2 WAN interface name
# $3 WAN bridge name
# $4 lan_dev name

BRIDGE=bridge
action=${1:-stop}

add_del_mdb_entry() {
    if [ "$#" -ne 4 ]; then
        return
    fi
    WAN=$1
    GRP=$2
    PORT_INDEX=$3
    PORT=$4
    cat /proc/driver/flowmgr/mdb | grep $GRP |grep -e "$PORT_INDEX("
    if [ $? -eq 0 ]; then
        FLOWMGR_MDB="1"
    else
        FLOWMGR_MDB="0"
    fi

    bridge mdb show |grep $GRP |grep $PORT
    if [ $? -eq 0 ]; then
        KERNEL_MDB="1"
    else
        KERNEL_MDB="0"
    fi

    if [ $KERNEL_MDB == "1" ] && [ $FLOWMGR_MDB == "0" ]; then
        echo "Add multicast flow for port $PORT group $GRP"
        echo mdb_add $WAN $PORT $GRP > /proc/driver/flowmgr/cmd
    fi
    if [ $KERNEL_MDB == "0" ] && [ $FLOWMGR_MDB == "1" ]; then
        echo "Del multicast flow for port $PORT group $GRP"
        echo mdb_del $WAN $PORT $GRP > /proc/driver/flowmgr/cmd
    fi

}

parse_mdb_entries() {
    while IFS= read -r line || [[ -n "$line" ]]; do
            echo "$line"

            if [[ $line =~ ^Deleted ]]; then
                PORT=$(echo "$line" | awk '/dev'" $lan_dev/"' {print $5}')
                GRP=$(echo "$line" | awk '/dev'" $lan_dev/"' {print $7}')
            else
                PORT=$(echo "$line" | awk '/dev'" $lan_dev/"' {print $4}')
                GRP=$(echo "$line" | awk '/dev'" $lan_dev/"' {print $6}')
            fi
            [ -z $PORT ] || PORT_INDEX=$(bridge link show dev $PORT | awk -F ':' '{print $1}')
            if [[ $GRP =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
                echo "valid ipv4: $GRP"
                ADDR=$(echo "$GRP" | cut -d'.' -f1)
                if [[ $ADDR -gt 223 && $ADDR -lt 240 ]]; then
                    #make sure the PORT is a LAN port
                    if [[ $1 != $PORT ]]; then
                        add_del_mdb_entry $1 $GRP $PORT_INDEX $PORT
                    fi
                fi
            else
                regex='^([0-9a-fA-F]{0,4}:){1,7}[0-9a-fA-F]{0,4}$'
                if [[ $GRP =~ $regex ]]; then
                    echo "valid IPv6: $GRP"
                    regex='^(ff02:)'
                    if [[ $GRP =~ $regex ]]; then
                        echo "link scope multicast: $GRP"
                    else
                        echo "no-link scope multicast: $GRP"
                        PORT_IF=$(echo $PORT | cut -d'.' -f1)

                        #make sure the PORT is a LAN port
                        if [[ $1 != $PORT ]]; then
                            add_del_mdb_entry $1 $GRP $PORT_INDEX $PORT
                        fi
                    fi
                fi
            fi

    done
}

start () {
    ps -C $BRIDGE &> /dev/null
    if [ $? -eq 0 ]; then
        exit 0
    fi

    # if GFAP driver is present, this is a 3384 and uses an external
    # switch.  Tell ethsw that bridge is running and multicast
    # destinations are learned so IPv6 multicast will not
    # be flooded to all ports
    local lan_dev=$3
    [[ -d /proc/driver/gfap && -f /proc/driver/ethsw/vlan ]] && echo m 1 > /proc/driver/ethsw/vlan
    echo > /dev/console "Start Multicast Monitoring"
    echo > /dev/console "mcast_mon: Reading MDB entries"
    bridge mdb show | parse_mdb_entries $1
    echo > /dev/console "mcast_mon: Begin MDB state monitoring"

    ifconfig $2 |grep "inet addr:"
    while [ $? -ne 0 ]; do
        sleep 3
        ifconfig $2 |grep "inet addr:"
    done

    cp -f /usr/local/etc/mcproxy.conf /var/
    sed -i -E "s/pinstance A: (.*) ==> (.*);/pinstance A: $2 ==> \2;/g" /var/mcproxy.conf
    /usr/local/bin/mcproxy -d -v -f /var/mcproxy.conf  &
    cd /var && script -f -c "bridge mon mdb"  | parse_mdb_entries $1
    echo > /dev/console "End Multicast Monitoring"
}

stop () {
    echo > /dev/console "mcast_mon: Stop"
    killall mcproxy &> /dev/null
    kill -9 $(ps -C "script -f -c bridge mon mdb" -o pid=)  &> /dev/null
    killall mcast_mon &> /dev/null
}

$action $2 $3 $4
