#!/bin/bash

cd $(dirname $0)
INSTDIR=$(pwd -P)
LANDER_CONF_DIR=/etc/lander
hostname=$(hostname -s)
VLANNETDENYFILE=$LANDER_CONF_DIR/filter_vlan_net_deny.$hostname
VLANNETALLOWFILE=$LANDER_CONF_DIR/filter_vlan_net_allow.$hostname

usage() {
cat >&2 <<EOF
$0: read filtering configuration from files and load dag filters onto the card
  FILES:
        $LANDER_CONF_DIR/filter_vlan_net_deny.<hostname>
        $LANDER_CONF_DIR/filter_vlan_net_allow.<hostname>
  ORDER:
    First, all deny vlans/nets are matched.  Then all allow rules.
    All unmatched packets are denied.
  EXAMPLE:
    filter_vlans_allow.<hostname>:
        1234    *       #allow all packets on vlan 1234
        *       1/8     #allow all packets to/from 1/8
        *       *       #allow all packets

EOF
}

process_options() {
    OPTIND=1
    while getopts "hUu" opt; do
        case "$opt" in
            ( h ) usage; exit 0; ;;
            ( * ) echo "unknown option $1" 2>&1; usage; exit 1; ;;
        esac
        shift
        OPTIND=1
    done
}

VLANBITS=""
mk_vlan_filter_bits() {
    local _vlan=$1
    local _b _vlan_bits=12
    if [ -z "$_vlan" -o "$_vlan" == "*" ]; then
        VLANBITS=""
    else
        #convert to binary
        _b=000000000000$(echo "ibase=10; obase=2; $_vlan" | bc)
        VLANBITS="----${_b: -$_vlan_bits}"
    fi
}

NETSBITS=""
mk_nets_filter_bits() {
    local _p=$1 #"128.125/16" or "68.181/16"
    local _p _n _l _o _m _b _nn _mm _ip_bits=32
    if [ -z "$_p" -o "$_p" == "*" ]; then
        NETSBITS=""
    else
        _l=${_p#*/}
        _n=${_p%/*}
        _nn=0
        _mm=$((1<<24))
        for _o in ${_n//./ }; do
            _nn=$(( _nn + _o * _mm ))
            _mm=$(( _mm >> 8 ))
        done
        _nn=$(( (_nn >> (32-_l)) ))
        #convert to binary
        _b=000000000000000000000000$(echo "ibase=10; obase=2; $_nn" | bc)
        _b=${_b: -$_l}--------------------------------
        NETSBITS="${_b:0:$_ip_bits}"
    fi
}

mk_dag_rules() {
    local _input=$1
    local _color=$2
    local _vlan _net _rest _rule
    if ! [ -e $_input ]; then
        echo "WARN: file $_input isn't found" >&2
    else
        while read _vlan _net _rest; do
            [ -z "${_vlan%\#*}" ] && continue
            _rule="$_color"
            mk_vlan_filter_bits "$_vlan"
            mk_nets_filter_bits "$_net"
            echo "vlan:($_vlan, $VLANBITS), nets:($_net, $NETSBITS)" >&2
            [ -n "$VLANBITS" ] && _rule+=" vlan-1 {$VLANBITS}"
            if [ -n "$NETSBITS" ]; then
                echo "$_rule src-ip {$NETSBITS}"
                echo "$_rule dst-ip {$NETSBITS}"
            else
                if [ -z "$VLANBITS" ]; then
                    echo "$_rule all"
                else
                    echo "$_rule"
                fi
            fi
        done <$_input 
    fi
}

mk_cat_rules () {
  cat <<EOF
color $PASS_COLOR stream 0
EOF
}

#MAIN
PASS_COLOR=100
DENY_COLOR=200

cmdline=$@
process_options $cmdline

DAGRULES_FILE=/tmp/dagfilter.rules
{
    mk_dag_rules $VLANNETDENYFILE $DENY_COLOR
    mk_dag_rules $VLANNETALLOWFILE $PASS_COLOR
} >$DAGRULES_FILE
[ -s $DAGRULES_FILE ] || {
    echo "WARN: empty ruleset, dagfilters are not installed" >&2
    exit 1
}
echo "loading coloring rules"
dagconfig -S ipf_enable=on
dagconfig -S hash_encoding_from_ipf=off
dagfilter-loader --initialize --init-ports 1 --init-rulesets 1  --verify -f $DAGRULES_FILE

CATRULES_FILE=/tmp/cat.rules
mk_cat_rules >$CATRULES_FILE
echo "installing CAT"
dagcat-setup -f $CATRULES_FILE

echo "enabling filtering" >&2
dagconfig -S sram_miss_value=$DENY_COLOR
dagconfig -S by_pass=off

#echo "configure memory streams"
#dagconfig mem=160:0:160:0 #split 320MB between two streams
