#!/bin/sh
#
#  This is automatically generated file. DO NOT MODIFY !
#
#  Firewall Builder  fwb_pf v5.0.1.3591
#
#  Generated Wed Nov 30 18:39:03 2011 PST by vadim
#
# files: * firewall103-2.fw /etc/fw/pf.fw
# files:   firewall103-2.conf /etc/fw/path\ with\ space/pf.conf
#
# Compiled for pf 4.0
#
# bridge interface, static address, shell script format, OpenBSD <4.7





FWDIR=`dirname $0`

IFCONFIG="/sbin/ifconfig"
PFCTL="/sbin/pfctl"
SYSCTL="/sbin/sysctl"
LOGGER="/usr/bin/logger"

log() {
    echo "$1"
    command -v "$LOGGER" >/dev/null 2>&1 && $LOGGER -p info "$1"
}

diff_intf() {
    func=$1
    list1=$2
    list2=$3
    cmd=$4
    for intf in $list1
    do
        echo $list2 | grep -q $intf || {
        # $vlan is absent in list 2
            $func $intf $cmd
        }
    done
}


missing_address() {
    address=$1
    cmd=$2

    oldIFS=$IFS
    IFS="@"
    set $address
    addr=$1
    interface=$2
    IFS=$oldIFS

    if echo "$addr" | grep -q ':'
    then
        inet="inet6"
        addr=$(echo "$addr" | sed 's!/! prefixlen !')
    else
        inet="inet"
        addr=$(echo "$addr" | sed 's!/! netmask !')
    fi

    parameter=""
    test "$cmd" = "add" && {
      echo "# Adding ip address: $interface $addr"
      parameter="alias"
    }
    test "$cmd" = "del" && {
      echo "# Removing ip address: $interface $addr"
      parameter="delete"
    }

    $FWBDEBUG $IFCONFIG $interface $inet $addr $parameter || exit 1
    $FWBDEBUG $IFCONFIG $interface up
}

list_addresses_by_scope() {
    interface=$1
    scope=$2
    ignore_list=$3

    scope_regex="1"
    if test -n "$scope"; then scope_regex=" \$0 !~ \"$scope\" "; fi

    $IFCONFIG $interface | sed "s/%$interface//" | \
      awk -v IGNORED="$ignore_list" \
        "BEGIN {  
           split(IGNORED,ignored_arr);
           for (a in ignored_arr) {ignored_dict[ignored_arr[a]]=1;}
         }
         (/inet |inet6 / && $scope_regex && !(\$2 in ignored_dict)) {printf \"%s/%s\n\",\$2,\$4;}" | \
        while read addr; do
          echo "${addr}@$interface"
        done | sort
   
}

update_addresses_of_interface() {
    ignore_list=$2
    set $1 
    interface=$1 
    shift

    FWB_ADDRS=$(
      for addr in $*; do
        echo "${addr}@$interface"
      done | sort
    )

    CURRENT_ADDRS_ALL_SCOPES=""
    CURRENT_ADDRS_GLOBAL_SCOPE=""

    $IFCONFIG $interface >/dev/null 2>&1 && {
      CURRENT_ADDRS_ALL_SCOPES=$(list_addresses_by_scope $interface '' "$ignore_list")
      CURRENT_ADDRS_GLOBAL_SCOPE=$(list_addresses_by_scope $interface 'scopeid .*' "$ignore_list")
    } || {
      echo "# Interface $interface does not exist"
      # Stop the script if we are not in test mode
      test -z "$FWBDEBUG" && exit 1
    }


    echo "$interface" | grep -q carp && {
        diff_intf missing_address "$CURRENT_ADDRS_GLOBAL_SCOPE" "$FWB_ADDRS" del
        diff_intf missing_address "$FWB_ADDRS" "$CURRENT_ADDRS_ALL_SCOPES" add
    } || {
        diff_intf missing_address "$FWB_ADDRS" "$CURRENT_ADDRS_ALL_SCOPES" add
        diff_intf missing_address "$CURRENT_ADDRS_GLOBAL_SCOPE" "$FWB_ADDRS" del
    }
}

missing_vlan() {
    vlan=$1
    cmd=$2

    oldIFS=$IFS
    IFS="@:"
    set $vlan
    subint=$1
    vlan_id=$2
    parent=$3
    IFS=$oldIFS

    test "$cmd" = "add" && {
        echo "# Adding VLAN interface $subint (vlan id: $vlan_id parent: $parent)"
        $FWBDEBUG $IFCONFIG $subint vlan $vlan_id vlandev $parent || exit 1
        $FWBDEBUG $IFCONFIG $subint up || exit 1
    }
    test "$cmd" = "rem" && {
        echo "# Removing VLAN interface $subint (vlan id: $vlan_id parent: $parent)"
        $FWBDEBUG $IFCONFIG $subint vlan $vlan_id -vlandev || exit 1
        $FWBDEBUG $IFCONFIG $subint destroy || exit 1
    }
}

parse_fwb_vlans() {
    set $1 
    vlan_parent=$1 
    shift

    FWB_VLANS=$(
      for subint in $*; do
        echo "${subint}@$vlan_parent"
      done | sort
    )
    echo $FWB_VLANS
}

parse_current_vlans() {
    vlan_parent=$1
    $IFCONFIG -A | grep -E 'vlan[^ ]*:' | paste - - | \
        sed 's/flags=.*vlan://;s/://g;s/parent interface//' | \
    while read vlan_subint vlan_id parent
    do
       test "$parent" = "$vlan_parent" && echo "$vlan_subint:$vlan_id@$parent"
    done | sort
}

update_vlans_of_interface() {
    args="$1"
    set $1 
    vlan_parent=$1 

    FWB_VLANS=$(parse_fwb_vlans "$args")
    CURRENT_VLANS=$(parse_current_vlans $vlan_parent)

    $IFCONFIG $vlan_parent up || exit 1
    diff_intf missing_vlan "$FWB_VLANS" "$CURRENT_VLANS" add
    diff_intf missing_vlan "$CURRENT_VLANS" "$FWB_VLANS" rem
}

sync_vlan_interfaces() {
    $IFCONFIG -A | awk -v IGNORED="$*" \
        'BEGIN {
           split(IGNORED,ignored_arr);
           for (a in ignored_arr) {ii=ignored_arr[a]":"; ignored_dict[ii]=1;}
         }
         ($1 ~ /^vlan[0-9]/ && !($1 in ignored_dict)) {print $1;}' | sed 's/://' |\
         while read intf; do
            echo "# Deleting vlan interface $intf"
             $FWBDEBUG $IFCONFIG $intf destroy || exit 1
         done

    for intf in $*; do
        $IFCONFIG $intf >/dev/null 2>&1 || {
            echo "# Creating vlan interface $intf"
            $FWBDEBUG $IFCONFIG $intf create || exit 1
        }
    done
}

BRCONFIG="brconfig"






missing_port() {
    intf=$1
    cmd=$2

    oldIFS=$IFS
    IFS="@"
    set $intf
    port=$1
    bridge_interface=$2
    IFS=$oldIFS

    echo "# Updating bridge configuration: $bridge_interface $cmd $port"
    $FWBDEBUG $BRCONFIG $bridge_interface $cmd $port
    test "$cmd" = "addm" && $FWBDEBUG $IFCONFIG $port up
}

update_bridge_interface() {
    bridge_interface=$1
    shift

    FWB_PORTS=""
    CURRENT_PORTS=""

    FWB_PORTS=$(
        for subint in $*; do
          echo "${subint}@$bridge_interface"
        done | sort
    )

    # this is really redundant because we create missing bridge
    # interfaces in sync_bridge_interfaces. However will leave this
    # here so that function update_bridge can be used without prior
    # call to sync_bridge_interfaces The difference is that
    # sync_bridge_interfaces also deletes bridge interfaces that exist
    # on the machine but are missing in fwbuilder confgiuration. The
    # update_bridge function can only add bridge interfaces.
    $BRCONFIG $bridge_interface >/dev/null 2>&1 || {
        echo "# Creating bridge interface $bridge_interface"
        $FWBDEBUG $IFCONFIG $bridge_interface create
        $FWBDEBUG $IFCONFIG $bridge_interface up
    }

    PORTS=$(
        $BRCONFIG $bridge_interface | awk '($1~/member:/) { print $2; }'
    )

    test -n "$PORTS" && {
        CURRENT_PORTS=$(
            for subint in $PORTS; do
                echo "${subint}@$bridge_interface"
            done | sort
        )
    }

    # first delete bridge ports, then add. This way, if an interface
    # moves from one bridge to another, we remove it first and then
    # add. It would not work if we tried to add it first, brctl issues
    # an error:
    # device eth2 is already a member of a bridge; can't enslave it to bridge br1.
    #
    diff_intf missing_port "$CURRENT_PORTS" "$FWB_PORTS" deletem
    diff_intf missing_port "$FWB_PORTS" "$CURRENT_PORTS" addm
}


sync_bridge_interfaces() {
    $BRCONFIG -a | awk -F: -v IGNORED="$*" \
        'BEGIN {
           split(IGNORED,ignored_arr);
           for (a in ignored_arr) {ignored_dict[ignored_arr[a]]=1;}
         }
         ($1 ~ /^bridge[0-9]/ && !($1 in ignored_dict)) {print $1;}' | \
         while read brintf; do
            echo "# Deleting bridge interface $brintf"
             $FWBDEBUG $IFCONFIG $brintf down
             $FWBDEBUG $IFCONFIG $brintf destroy
         done

    for brint in $*; do
        $BRCONFIG $brint >/dev/null 2>&1 || {
            echo "# Creating bridge interface $brintf"
            $FWBDEBUG $IFCONFIG $brint create 
            $FWBDEBUG $IFCONFIG $brint up
        }
    done
}


sync_carp_interfaces() {
    $IFCONFIG -A | awk -v IGNORED="$*" \
        'BEGIN {
           split(IGNORED,ignored_arr);
           for (a in ignored_arr) {ii=ignored_arr[a]":"; ignored_dict[ii]=1;}
         }
         ($1 ~ /^carp[0-9]/ && !($1 in ignored_dict)) {print $1;}' | sed 's/://' |\
         while read intf; do
            echo "# Deleting carp interface $intf"
             $FWBDEBUG $IFCONFIG $intf destroy
         done

    for intf in $*; do
        $IFCONFIG $intf >/dev/null 2>&1 || {
            echo "# Creating carp interface $intf"
            $SYSCTL -w net.inet.carp.allow=1
            $FWBDEBUG $IFCONFIG $intf create || {
                echo "Error: CARP interface $intf could not be created. Does the kernel have CARP enabled?"
                exit 1
            }
        }
    done
}


sync_pfsync_interfaces() {
    $IFCONFIG -A | awk -v IGNORED="$*" \
        'BEGIN {
           split(IGNORED,ignored_arr);
           for (a in ignored_arr) {ii=ignored_arr[a]":"; ignored_dict[ii]=1;}
         }
         ($1 ~ /^pfsync[0-9]/ && !($1 in ignored_dict)) {print $1;}' | sed 's/://' |\
         while read intf; do
            echo "# Deleting pfsync interface $intf"
             $FWBDEBUG $IFCONFIG $intf destroy
         done

    for intf in $*; do
        $IFCONFIG $intf >/dev/null 2>&1 || {
            echo "# Creating pfsync interface $intf"
            $FWBDEBUG $IFCONFIG $intf create
        }
    done
}

verify_interfaces() {
    :
    
}

set_kernel_vars() {
    :
    $SYSCTL -w net.inet.ip.forwarding=1
}

prolog_commands() {
    :
    
}

epilog_commands() {
    :
    
}

run_epilog_and_exit() {
    epilog_commands
    exit $1
}

configure_interfaces() {
    :
    sync_vlan_interfaces 
    sync_bridge_interfaces bridge0
    sync_carp_interfaces 
    sync_pfsync_interfaces 
    update_addresses_of_interface "em0 10.3.14.81/0xffffff00" ""
    update_addresses_of_interface "em1 10.1.1.81/0xffffff00" ""
    update_addresses_of_interface "em2" ""
    update_addresses_of_interface "em3" ""
    update_bridge_interface bridge0 "em2 em3"
    $IFCONFIG bridge0 -stp em2
    $IFCONFIG bridge0 -stp em3
    update_addresses_of_interface "bridge0 192.168.1.1/0xffffff00" ""
}

log "Activating firewall script generated Wed Nov 30 18:39:03 2011 by vadim"

set_kernel_vars
configure_interfaces
prolog_commands

$PFCTL    -f /etc/fw/path\ with\ space/pf.conf || exit 1







epilog_commands