#!/bin/sh
# Firewall anchor for all environments
# Nokia
# author: Rene Veldsink / Dieter Knueppel
#
# chkconfig: S 29 0
# processname: iptables
#
# Symbols with an _ as prefix are ment to be private for the local file
#
# The idea behind: Currently we have three chains (system, qos, and user),
#                  where packets are passed through this chain list
#

trap '' INT TERM PIPE HUP QUIT
trap 'rm -rf /tmp/iptables_test' EXIT

while ! mkdir /tmp/iptables_test 2> /dev/null
  do
  sleep 1
done

##############
# some helpers
##############

LOG_ERROR="logger -p kern.crit -t iptables"
LOG_INFO="logger -p kern.info -t iptables"

_CHAIN_USER="user"
_CHAIN_QOS="qos"
_CHAIN_SYSTEM="system"

tryinclude() {
    if [ -e "$1" ]; then
        . $1
        $LOG_INFO ".. included $1"
        return 1
    fi

    if [ -e "$2" ]; then
        . $2
        $LOG_INFO ".. included $2"
        return 1
    fi
    return 0
}


selective_do() {
    if [ "$1" -eq 1 ]; then
        IPTABLES=$IP4TABLES   
        IPVERSION=4
        $2_$3
        if [ "$HAVE_IPV6" = "1" ]; then
            IPTABLES=$IP6TABLES
            IPVERSION=6
            $2_$3
            IPTABLES=$IP4TABLES
            IPVERSION=4
        fi
    fi                
}

###################################
# param #1 start, stop, status
# param #2 system, qos, user or all
#
# special behaviour for system, because if addresses are
# changed, we have to setup all the other stuff again
###################################
selective_execute() {
    case "$2" in
        $_CHAIN_SYSTEM)
            selective_do $HAVE_CHAIN_SYSTEM $1 $_CHAIN_SYSTEM
            selective_do $HAVE_CHAIN_QOS    $1 $_CHAIN_QOS
            selective_do $HAVE_CHAIN_USER   $1 $_CHAIN_USER
            ;;
        $_CHAIN_QOS)
            selective_do $HAVE_CHAIN_QOS $1 $2
            ;;
        $_CHAIN_USER)
            selective_do $HAVE_CHAIN_SYSTEM $1 $_CHAIN_SYSTEM
            ;;
        *)
            selective_do $HAVE_CHAIN_SYSTEM $1 $_CHAIN_SYSTEM
            selective_do $HAVE_CHAIN_QOS    $1 $_CHAIN_QOS
            selective_do $HAVE_CHAIN_USER   $1 $_CHAIN_USER
            ;;
    esac
}

###################################
# common exit function
# param #1 cause text
###################################
iptables_exit() {
    $LOG_INFO "iptables - exit with cause ($1)"
    exit
}

# default implementation for chaining
# since currently we use filter and mangle table, a real chaining isn't
# used. so chaining may has to be improved 
user_get_chain () {
    return "ACCEPT"
}

qos_get_chain () {
    $_CHAIN_USER_get_chain
    return $?
}

system_get_chain () {
    $_CHAIN_QOS_get_chain
    return $?
}

enable_ssh () {
    $IPTABLES  -D INPUT -i eth1+ -p tcp --dport 22 -j ACCEPT 2>/dev/null
    $IPTABLES  -D ETH_SECURITY_CHAIN -p tcp --dport 22 -j ACCEPT 2>/dev/null
    $IPTABLES  -D INPUT -p tcp --dport 22 -j DROP 2>/dev/null
    $IPTABLES  -D MP_TRAFFIC -p tcp --dport 22 -j ACCEPT 2>/dev/null
    $IP6TABLES  -D INPUT -p tcp --dport 22 -j DROP 2>/dev/null
    $IP6TABLES  -D MP_TRAFFIC -p tcp --dport 22 -j ACCEPT 2>/dev/null
    $IPTABLES  -D ETH_SECURITY_CHAIN -p tcp --dport 22 -j DROP 2>/dev/null
    $IPTABLES  -A INPUT -i eth1+ -p tcp --dport 22 -j ACCEPT 2>/dev/null
    $IPTABLES  -A MP_TRAFFIC -p tcp --dport 22 -j ACCEPT 2>/dev/null
    $IP6TABLES  -A MP_TRAFFIC -p tcp --dport 22 -j ACCEPT 2>/dev/null
    $IPTABLES  -I ETH_SECURITY_CHAIN 1 -p tcp --dport 22 -j ACCEPT 2>/dev/null
    touch $ENABLE_SSH
    return 0
}

disable_ssh () {
    $IPTABLES  -D INPUT -p tcp --dport 22 -j DROP 2>/dev/null
    $IPTABLES  -D ETH_SECURITY_CHAIN -p tcp --dport 22 -j DROP 2>/dev/null
    $IPTABLES  -I INPUT 1 -p tcp --dport 22 -j DROP 2>/dev/null
    $IPTABLES  -I ETH_SECURITY_CHAIN 1 -p tcp --dport 22 -j DROP 2>/dev/null
    $IPTABLES  -D INPUT -i eth1+ -p tcp --dport 22 -j ACCEPT 2>/dev/null
    $IPTABLES  -D ETH_SECURITY_CHAIN -p tcp --dport 22 -j ACCEPT 2>/dev/null
    $IPTABLES  -D MP_TRAFFIC -p tcp --dport 22 -j ACCEPT 2>/dev/null

    $IP6TABLES  -D INPUT -p tcp --dport 22 -j DROP 2>/dev/null
    $IP6TABLES  -I INPUT 1 -p tcp --dport 22 -j DROP 2>/dev/null
    $IP6TABLES  -D MP_TRAFFIC -p tcp --dport 22 -j ACCEPT 2>/dev/null

    if [ -f $ENABLE_SSH ]; then
        rm -f $ENABLE_SSH
    fi
    return 0
}

enable_ftp () {
    $IPTABLES -D INPUT  -p tcp --dport 21 -j DROP 2>/dev/null
    $IPTABLES -D INPUT -p tcp --dport 21 -j ACCEPT 2>/dev/null
    $IPTABLES -I INPUT 1 -p tcp --dport 21 -j ACCEPT 2>/dev/null
    touch $ENABLE_FTP
    return 0
}

###############
# here we start
###############
OPT_DIR="/opt/trs"
CCS_DIR="/opt/CCS"
TRS_LIB_DEST="${OPT_DIR}/lib64"

export LD_LIBRARY_PATH="${TRS_LIB_DEST}:${CCS_DIR}:/usr/lib64:/lib64:/lib:$LD_LIBRARY_PATH"

#
# get the environment we are running in
#
PROD_WCDMA=1
PROD_WIMAX=2
PROD_LTE_DCM=3
PROD_LTE_WMP=4
PROD_MULTIMODE_DCM=7
PROD_MULTIMODE_WMP=8

#${OPT_DIR}/bin/test_envInfo envInfoProductType > /dev/null
#PROD=$?
PROD=$PROD_LTE_WMP # Hardcode to this value for FZM

case "$PROD" in
    $PROD_WIMAX)
        PROD_STR="wimax"
        ;;
    $PROD_WCDMA)
        PROD_STR="wcdma"
        ;;
    $PROD_LTE_DCM)
        PROD_STR="ltd"
        ;;
    $PROD_LTE_WMP)
        PROD_STR="ltwmp"
        ;;
    $PROD_MULTIMODE_DCM)
        PROD_STR="multimode_dcm"
        ;;
    $PROD_MULTIMODE_WMP)
        PROD_STR="ltwmp"
        ;;
    *)
        $LOG_ERROR "unknow product type"
        exit
        ;;
esac

#
#   read the different config files, i.e.
#       - ip adress parameter of interfaces
#       - qos parameter
#       - debug flags
#
_IPTABLES_ADDRESS_CONFIG_FILE=/tmp/iptables_addresses.conf
_IPTABLES_QOS_CONFIG_FILE=/tmp/iptables_qos.conf
_IPTABLES_QOS_DSCP_PCP_CONFIG_FILE=/tmp/iptables_qos_dscp_vpri.conf
_IPTABLES_DEBUG_FILE=/tmp/iptables_debug

$LOG_INFO "iptables - reading configuration files"

tryinclude $_IPTABLES_ADDRESS_CONFIG_FILE $_IPTABLES_ADDRESS_CONFIG_FILE
HAVE_ADDRESS_CONFIG=$?

tryinclude $_IPTABLES_QOS_CONFIG_FILE $_IPTABLES_QOS_CONFIG_FILE
HAVE_QOS_CONFIG=$?

tryinclude $_IPTABLES_DEBUG_FILE $_IPTABLES_DEBUG_FILE
DEBUG_LOGGING=$?

tryinclude $_IPTABLES_QOS_DSCP_PCP_CONFIG_FILE $_IPTABLES_QOS_DSCP_PCP_CONFIG_FILE
HAVE_QOS_CONFIG=$?

# fixvalues
for varname in \
    IP_PRIM_TRS \
    IP_OCT_INTERNAL \
    IP_MPLANE \
    IP_CMP_CA_SERVER \
    PORT_CMP_CA_SERVER \
    IP_CMP_CR_SERVER \
    PORT_CMP_CR_SERVER \
    IP_LDAP_SERVER \
    PORT_LDAP_SERVER \
    IP_NTP_SERVER1 \
    IP_NTP_SERVER2 \
    IP_NTP_SERVER3 \
    IP_SPLANE \
    IP_UPLANE \
    IP_CPLANE \
    IP_TOPMASTER \
    IP_DNS_SERVER1 \
    IP_DNS_SERVER2 \
    PORT_BFD_SESSION1 \
    IP_BFD_SESSION_PEERONE1 \
    IP_BFD_SESSION_PEERTWO1 \
    PORT_BFD_SESSION2 \
    IP_BFD_SESSION_PEERONE2 \
    IP_BFD_SESSION_PEERTWO2 \
    PORT_BFD_SESSION3 \
    IP_BFD_SESSION_PEERONE3 \
    IP_BFD_SESSION_PEERTWO3 \
    PORT_BFD_SESSION4 \
    IP_BFD_SESSION_PEERONE4 \
    IP_BFD_SESSION_PEERTWO4 \
    PORT_BFD_SESSION5 \
    IP_BFD_SESSION_PEERONE5 \
    IP_BFD_SESSION_PEERTWO5 \
    IP_CMP_CRL_SOURCE_IP_ADDR; do
  eval "value=\${$varname}"
  if [ "x$value" = "x0" ]; then
      unset $varname
  fi
done

#
#    here we include the environment specific stuff
#    where we have three chains, i.e.
#        - system  used for system firewall
#        - qos     used for qos behaviour
#        - user    used for user firewall
#
#    if environment specific rules are available, they will be included
#    where:  iptables_system_wcdma is the specific and iptables_system is the common
#
_CHAIN_DIR=/opt/trs

$LOG_INFO "iptables - reading subsystems"

tryinclude "${_CHAIN_DIR}/iptables_${_CHAIN_USER}_${PROD_STR}" "${_CHAIN_DIR}/iptables_${_CHAIN_USER}"
HAVE_CHAIN_USER=$?

tryinclude "${_CHAIN_DIR}/iptables_${_CHAIN_QOS}_${PROD_STR}" "${_CHAIN_DIR}/iptables_${_CHAIN_QOS}"
HAVE_CHAIN_QOS=$?

tryinclude "${_CHAIN_DIR}/iptables_${_CHAIN_SYSTEM}_${PROD_STR}" "${_CHAIN_DIR}/iptables_${_CHAIN_SYSTEM}"
HAVE_CHAIN_SYSTEM=$?

IP4TABLES=/usr/sbin/iptables
IPTABLES=$IP4TABLES
IP6TABLES="/usr/sbin/xtables-multi ip6tables"
IPV6_DISABLED=`/bin/cat /proc/sys/net/ipv6/conf/eth0/disable_ipv6`

 HAVE_IPV6=1

ENABLE_SSH=/tmp/ssh_enabled
ENABLE_FTP=/tmp/trs_ftp_flag
MP_TRAFFIC_SHAPER=/opt/trs/mp_traffic_shaper.sh

if [ -e "$2" ]; then
    _SUBSYSTEM="all"
else
    _SUBSYSTEM="$2"
fi

case "$1" in
    start)
        $LOG_INFO "iptables - $1 $_SUBSYSTEM"
        selective_execute start $_SUBSYSTEM
        if [ "$_SUBSYSTEM" = "$_CHAIN_SYSTEM" ]; then
            if [ -f $ENABLE_SSH ]; then
                enable_ssh
            else
                disable_ssh
            fi
            if [ -f $ENABLE_FTP ]; then
                enable_ftp
            fi
        fi
        ;;
    restart|reload)
        $LOG_INFO "iptables - $1 $_SUBSYSTEM"
        selective_execute stop $_SUBSYSTEM
        selective_execute start $_SUBSYSTEM
        `$MP_TRAFFIC_SHAPER`
        if [ "$_SUBSYSTEM" = "$_CHAIN_SYSTEM" ]; then
            if [ -f $ENABLE_SSH ]; then
                enable_ssh
            else
                disable_ssh
            fi
            
            if [ -f $ENABLE_FTP ]; then
                enable_ftp
            fi
        fi
        ;;
    stop)
        $LOG_INFO "iptables - $1 $_SUBSYSTEM"
        selective_execute stop $_SUBSYSTEM
        ;;
    status)
        $LOG_INFO "iptables - $1 $_SUBSYSTEM"
        selective_execute status $_SUBSYSTEM
        ;;
    ssh_enable)
        enable_ssh
        ;;
    ssh_disable)
        disable_ssh
        ;;
    *)
        $LOG_ERROR "Usage: $0 {start|restart|reload|stop|status}"
        $LOG_ERROR "with optional subsystem <system|qos|user>"
        ;;
esac

$LOG_INFO "iptables finished successfully"
