#!/bin/bash

#
# LRP/Debian network configuration system
#
# Ring a ding ding, my dang a lang dong	   Dave 'Kill a Cop' Cinege   GPL2
# Ding Dong Dell, Pussy's in the well      Matthew 'Network Cowboy' Grant GPL2

# 
# start)
# Depending on the auto config portions in /etc/network.conf, it auto-
# generates hosts, resolv.conf, sets the hostname, starts up interfaces,
# configures the IP filter/firewall and sets up routes (not necessarily
# in that order). 
# 
# stop)
# brings down all interfaces listed in /proc/net/dev, and their associated
# routes. Flushes all rules for iptables.
#

# bail out if we are not root
if [ "`id -un`" != "root" ] ; then
	echo 1>&2
	echo "  `basename $0`: you must be root to run this command." 1>&2
	echo 1>&2
	exit 1
fi

TARGET_KERNEL1="2.4"
TARGET_KERNEL2="2.6"
TARGET_KERNEL3="3"

#DEBUG=1

SP='   '

qt () { "$@" >/dev/null 2>&1 ; }
vb () { "$@" ; }
source () { . $1 ; }
basename () { echo "${1##*/}"; }

BANNER="# This file was generated by $0. It may be overwritten!"


#Default safe settings
VERBOSE=YES
IPV6_MODULE=NO
IPV4_FWDING_KERNEL=NO
IPV6_FWDING_KERNEL=NO
IP_FILTER_KERNEL=PACKET
IF_AUTO="eth0"
IPV4_DISABLE=NO
IPV6_DISABLE=NO
BASE_MODPATH="/lib/modules/`uname -r`/kernel"
MODPATH="${BASE_MODPATH}/net"
KERN_VERSION=`uname -r | cut -d . -f 1,2`
if echo "$KERN_VERSION" | grep '^3\..*' -q; then
	KERN_VERSION='3'
fi
[ "$KERN_VERSION" = "$TARGET_KERNEL1" ] && MODEXT="o"
[ "$KERN_VERSION" = "$TARGET_KERNEL2" ] && MODEXT="ko"
[ "$KERN_VERSION" = "$TARGET_KERNEL3" ] && MODEXT="ko"
LIB_MODPATH="${BASE_MODPATH}/lib"
SCHED_MODPATH="${MODPATH}/sched"
NETFILTER_XMODPATH="${MODPATH}/netfilter"
NETFILTER_V4MODPATH="${MODPATH}/ipv4/netfilter"
NETFILTER_V6MODPATH="${MODPATH}/ipv6/netfilter"
NETFILTER_IPSETMODPATH="${NETFILTER_XMODPATH}/ipset"
NETFILTER_IPVSMODPATH="${NETFILTER_XMODPATH}/ipvs"
QOS_MODULES="sch_cbq sch_sfq sch_red sch_gred cls_fw"
NETFILTER_CONF="/etc/netscript"
IPTBL_FILE="$NETFILTER_CONF/iptables"
IPTBL_FILE_BACKUP="$IPTBL_FILE.backup"
IP6TBL_FILE="$NETFILTER_CONF/ip6tables"
IP6TBL_FILE_BACKUP="$IP6TBL_FILE.backup"
IPTBL="/sbin/iptables"
IPTBL_RESTORE="/sbin/iptables-restore"
IPTBL_SAVE="/sbin/iptables-save"
IP6TBL="/sbin/ip6tables"
IP6TBL_RESTORE="/sbin/ip6tables-restore"
IP6TBL_SAVE="/sbin/ip6tables-save"
MODULE_PROC="/proc/modules"
IPTBL_V4PROC="/proc/net/ip_tables_names"
IPTBL_V6PROC="/proc/net/ip6_tables_names"
IPV4_PROC="/proc/sys/net/ipv4"
IPV6_PROC="/proc/sys/net/ipv6"
IPFWD_V4PROC="${IPV4_PROC}/ip_forward"
IPFWD_V6PROC="${IPV6_PROC}/conf/all/forwarding"
IPV6_MODPATH=${MODPATH}/ipv6/ipv6.${MODEXT}
IPV6_DEFAULT_PREFIX=default
DEFAULT_METRIC=999999999
IPSPEC_MODULE=NO
IPSEC_MODPATH="${MODPATH}/ipsec/ipsec.${MODEXT}"
IPSEC_EXTMODPATH="${MODPATH}/ipsec/ext"
BACKUP_LEVELS=2
BRG_NETFILTER_REMOVE="YES"
BRG_LIST="brg0"
IF_DEFAULT_IPV6_DISABLE="NO"
INITCTL="/sbin/initctl"

#==============================================================================#

# Read in configuration files 
# 	- these ones can be changed by users
[ -f $NETFILTER_CONF/network.conf ] \
	&& source $NETFILTER_CONF/network.conf
IPFILTER=0
[ -f $NETFILTER_CONF/ipfilter.conf ] \
	&& source $NETFILTER_CONF/ipfilter.conf && IPFILTER=1
[ -f $NETFILTER_CONF/srvfilter.conf ] \
	&& source $NETFILTER_CONF/srvfilter.conf
[ -f $NETFILTER_CONF/if.conf ] \
	&& source $NETFILTER_CONF/if.conf
[ -f $NETFILTER_CONF/qos.conf ] \
	&& source $NETFILTER_CONF/qos.conf

[ "$DEBUG" ] && qt () { "$@" ; }
[ "$VERBOSE" = "NO" ] && vb () { qt "$@" ; }


[ -f /proc/net/ip_fwchains ] && IPCHAINS=1
[ -f /proc/net/ip_masq/autofw ] && IPAUTOFW=1
[ -f /proc/net/ip_masq/portfw ] && IPPORTFW=1
[ -f /proc/net/ip_masq/mfw ] && IPMFW=1

GDC_PATH=/usr/bin/gdc
IF_LIST="$IF_AUTO"
IFDEVLIST=`cat /proc/net/dev | grep '^[ _a-zA-Z0-9\-]\+:' | sed -e 's/^ *\([a-zA-Z0-9_\-]\+\):.*$/\1/'`
IFDEVLIST="$IFDEVLIST $IF_DYNAMIC"
for DEV in $IFDEVLIST; do
	if [ "$DEV" = "lo" ]; then
		continue
	fi
	ANS=`echo "$IF_LIST" | grep $DEV`
	if [ -z "$ANS" ]; then
		IF_LIST="$IF_LIST $DEV"
	fi
done
unset DEV IFDEVLIST ANS
IFLIST="`echo $IF_LIST | sed 's/ /|/g'`|all"
for IF in $IF_LIST; do
    REV_IF_LIST="$IF $REV_IF_LIST"
done
unset IF

# determine runlevel for disabling functionality in parallel boot environment
[ -x /sbin/runlevel ] && RUNLVL=`/sbin/runlevel | sed -e 's/^. \(.\)$/\1/'`

# translate old values for compatibility
if [ -n "$IPFWDING_KERNEL" ]; then
	IPV4_FWDING_KERNEL="$IPFWDING_KERNEL"
fi
if [ -n "$IPALWAYSDEFRAG_KERNEL" ]; then
	case "$IPALWAYSDEFRAG_KERNEL" in
	YES|Yes|yes)
		IP_FILTER_KERNEL=NAT
		;;
	NO|No|no)
		IP_FILTER_KERNEL=PACKET
		;;
	esac
fi

if [ -n "$IPV4_FILTER_KERNEL" ]; then
	IP_FILTER_KERNEL="$IPV4_FILTER_KERNEL"
fi

# Setup stuff for IPv6
IPV6_KRNL=0
[ -d $IPV6_PROC ] && IPV6_KRNL=1

#############################################################################
# Code to set up function lists for filtering
#############################################################################

get_fns () {
	local STR="s/^.* ${1}\([^ ]\+\)$/\1/"
	if [ -n "$BASH_VERSION" ]; then
		declare -F | grep $1 | sed -e "$STR"
	else
		hash | grep "^function $1" | sed -e "$STR"
	fi
}

for FN in `get_fns ipf4_`; do
	if [ -z "$IPF4_FNS" ]; then
		IPF4_FNS="$FN"
	else
		IPF4_FNS="${IPF4_FNS}|$FN"
	fi
done; unset FN

for FN in `get_fns ipf6_`; do
	if [ -z "$IPF6_FNS" ]; then
		IPF6_FNS="$FN"
	else
		IPF6_FNS="${IPF6_FNS}|$FN"
	fi
done; unset FN

###############################################################################
#Module loading on start up for iptables and QoS
###############################################################################


ls_mod () {
	if qt type lsmod && [ -f "$MODULE_PROC" ] && [ -z "$LS_MOD" ]; then
		LS_MOD=`lsmod | sed -e 's/^\([a-zA-Z0-9_\-]\+\) .*$/\1/'`
	fi
	
	echo "$LS_MOD"

	return 0
}


check_mod () {
	local MOD

	for MOD in `ls_mod`; do
		if [ "$MOD" = "$1" ]; then
			return 0
		fi
	done

	return 1
}

load_mod () {
	local MODNAME
	
	MODNAME="${1##*/}"
	MODNAME="${MODNAME%.$MODEXT}"
	
	# Check that the kernel supports modules
	if [ ! -f "$MODULE_PROC" ]; then
		return 0
	fi
	
	if [ ! -f $1 ]; then
		return 0
	fi
	
	if ! check_mod $MODNAME; then
		/sbin/insmod $1
	fi
}

unload_mod () {
	local MODNAME

	MODNAME="${1##*/}"
	MODNAME="${MODNAME%.$MODEXT}"

	check_mod $MODNAME && /sbin/rmmod $MODNAME > /dev/null 2>&1
}


IPSEC_EXTMOD_EXCLUDE="aes-opt"
ipsec_start_mod () {
	local I ANS

	if [ "$IPSEC_MODULE" != "YES" -a "$IPSEC_MODULE" != "Yes" \
		-a "$IPSEC_MODULE" != "yes" ]; then
		ipsec_stop_mod
		return 0
	fi
	
	if [ ! -f "$IPSEC_MODPATH" ]; then
		return 0
	fi

	load_mod "$IPSEC_MODPATH"

	if [ -d $IPSEC_EXTMODPATH ]; then
		for I in ${IPSEC_EXTMODPATH}/ipsec_*; do
			ANS="${I##*_}" 
			ANS="${ANS%.$MODEXT}"
		
			eval "case \"$ANS\" in
				$IPSEC_EXTMOD_EXCLUDE)
					continue;
				;;
				esac"
			
			load_mod $I
		done
	fi
	
	return 0
}

ipsec_stop_mod () {
	local I 

	if [ -d $IPSEC_EXTMODPATH ]; then
		for I in ${IPSEC_EXTMODPATH}/ipsec_*; do
			unload_mod $I
		done
	fi

	unload_mod "$IPSEC_MODPATH"
	return 0
}

ipv6_start_mod () {
	
	if [ "$IPV6_MODULE" != "YES" -a "$IPV6_MODULE" != "Yes" \
		-a "$IPV6_MODULE" != "yes" ]; then
		ipv6_stop_mod 
		return 0
	fi
	
	if [ $IPV6_KRNL -eq 1 ]; then
		return 0
	fi
	
	if [ ! -f "$IPV6_MODPATH" ]; then
		return 0
	fi

	load_mod "$IPV6_MODPATH"

	# Enable IPv6
	IPV6_KRNL=1

	return 1
}

ipv6_stop_mod () {
	unload_mod "$IPV6_MODPATH"
}

qos_start_mod () {
	local I
	if [ -d $SCHED_MODPATH ] ; then
		for I in $QOS_MODULES; do
			load_mod "$SCHED_MODPATH/${I}.${MODEXT}"
		done
	fi
}

qos_stop_mod () {
	local I 
	
	if [ -d $SCHED_MODPATH ] ; then
		for I in $SCHED_MODPATH/cls_* $SCHED_MODPATH/sch_*; do
			unload_mod $I
		done
	fi
}

# These exist to make the following code easier to understand

X_BASE_MODS="x_tables nfnetlink nfnetlink_log nfnetlink_queue nfnetlink_acct xt_nfacct xt_RATEEST"
X_BASE_MODS_REV="xt_RATEEST xt_nfacct nfnetlink_acct nfnetlink_queue nfnetlink_log nfnetlink x_tables"
X_STATE_MODS_CASE="state|helper|connbytes|connlimit|conntrack|connmark|cluster|CONNMARK|NOTRACK|CONNSECMARK|hashlimit|CT|TEE|socket|TPROXY|ipvs|NETMAP|REDIRECT|connlabel|nat|nfacct"
X_STATE_MODS="xt_state xt_helper xt_connbytes xt_connlimit xt_conntrack xt_connmark xt_cluster xt_CONNMARK xt_NOTRACK xt_CONNSECMARK xt_CT xt_TEE xt_NETMAP xt_REDIRECT xt_connlabel xt_nat xt_nfacct"

x_nfbase_start_mod () {
	local I ANS

	case "$IP_FILTER_KERNEL" in
	PACKET|Packet|packet|NAT|Nat|nat|STATEFUL|Stateful|stateful)
		# load the base netfilter modules
		for I in $X_BASE_MODS; do
			load_mod $NETFILTER_XMODPATH/${I}.${MODEXT}
		done

		# Load all the ipset modules
		for I in $NETFILTER_IPSETMODPATH/ip_set.${MODEXT} \
			$NETFILTER_IPSETMODPATH/ip_set_*; do
			load_mod $I
		done 

		# Load all the x_ modules save stateful ones 
		for I in $NETFILTER_XMODPATH/xt_*; do
			ANS="${I##*_}" 
			ANS="${ANS%.$MODEXT}"
			
			eval "case \"$ANS\" in
				$X_STATE_MODS_CASE)
					continue;
				;;
				esac"
			
			load_mod $I
		done
		return 2
		;;
	*|NONE|None|none)
		return 1
		;;
	esac
}

x_nfbase_stop_mod () {
	local I ANS

	# Unload all the xt_ modules save stateful ones 
	for I in $NETFILTER_XMODPATH/xt_*; do
		ANS="${I##*_}" 
		ANS="${ANS%.$MODEXT}"
		
		eval "case \"$ANS\" in
			$X_STATE_MODS_CASE)
				continue;
			;;
			esac"
		
		unload_mod $I
	done
	
	# Unload all the ipset modules
	for I in $NETFILTER_IPSETMODPATH/ip_set_* \
		$NETFILTER_IPSETMODPATH/ip_set.${MODEXT}; do
		unload_mod $I
	done 
	
	# Unload the base netfilter modules
	for I in $X_BASE_MODS_REV; do
		unload_mod $NETFILTER_XMODPATH/${I}.${MODEXT}
	done

	return 0
}

# These exist to make the following code easier to understand

IPV4_BASE_MODS="ip_tables iptable_filter iptable_mangle ip_queue ip_pool"
IPV4_BASE_MODS_REV="iptable_filter iptable_mangle ip_queue ip_pool ip_tables"
IPV4_STATE_MODS_CASE="defrag_ipv4|helper|state|iplimit|REDIRECT|MASQUERADE|conntrack|NETMAP|SAME|nat|CLUSTERIP"
IPV4_STATE_MODS="ipt_helper ipt_state ipt_iplimit ipt_REDIRECT ipt_MASQUERADE ipt_conntrack ipt_NETMAP ipt_SAME ipt_CLUSTERIP xt_ipvs"

ipv4_nfbase_start_mod () {
	local I ANS

	# load the base netfilter modules
	for I in $IPV4_BASE_MODS; do
		load_mod $NETFILTER_V4MODPATH/${I}.${MODEXT}
	done

	# Load all the ipt_ modules save ipt_helper, ipt_state, 
	# ipt_REDIRECT, ipt_MASQUERADE and ipt_iplimit
	for I in $NETFILTER_V4MODPATH/ipt_*; do
		ANS="${I##*_}" 
		ANS="${ANS%.$MODEXT}"
		
		eval "case \"$ANS\" in
			$IPV4_STATE_MODS_CASE)
				continue;
			;;
			esac"
		
		load_mod $I
	done
	
	return 0
}

ipv4_nfnat_start_mod () {
	local I 
	
	# Load conection tracking
	for I in $NETFILTER_V4MODPATH/ip_conntrack.${MODEXT} \
		$NETFILTER_V4MODPATH/nf_defrag_ipv4.${MODEXT} \
		$NETFILTER_XMODPATH/nf_conntrack.${MODEXT} \
		$NETFILTER_XMODPATH/nf_conntrack_proto_gre.${MODEXT} \
		$NETFILTER_XMODPATH/nf_conntrack_* \
		$NETFILTER_XMODPATH/nf_tproxy_* \
		$NETFILTER_V4MODPATH/nf_conntrack_* \
		$NETFILTER_V4MODPATH/ip_conntrack_*; do
		ANS="${I##*/}" 
		ANS="${ANS%.$MODEXT}"
		
		case $ANS in
			nf_conntrack_netlink)
				continue;
			;;
			esac
		
		load_mod $I
	done

	# Load NAT modules
	for I in $NETFILTER_V4MODPATH/ip_nat.${MODEXT} \
		$NETFILTER_V4MODPATH/nf_nat.${MODEXT} \
		$NETFILTER_XMODPATH/nf_nat.${MODEXT} \
		$NETFILTER_V4MODPATH/nf_nat_ipv4.${MODEXT} \
		$NETFILTER_V4MODPATH/nf_conntrack_netlink.${MODEXT} \
		$NETFILTER_V4MODPATH/iptable_nat.${MODEXT} \
		$NETFILTER_V4MODPATH/ip_nat*.${MODEXT}; 
	do 
		load_mod $I
	done

	# Load virtual server modules
	load_mod $LIB_MODPATH/libcrc32c.${MODEXT}
	for I in $NETFILTER_IPVSMODPATH/ip_vs.${MODEXT} \
		$NETFILTER_IPVSMODPATH/ip_vs_*; do
		load_mod $I
	done 

	# Load rest of xt_ modules
	for I in $X_STATE_MODS; do
		load_mod $NETFILTER_XMODPATH/${I}.${MODEXT}
	done

	# Load rest of ipt_ modules
	for I in $IPV4_STATE_MODS; do
		load_mod $NETFILTER_V4MODPATH/${I}.${MODEXT}
	done

	return 0
}

ipv4_nfnat_stop_mod () {
	local I
	
	# Unload rest of ipt_ modules
	for I in $IPV4_STATE_MODS; do
		unload_mod $NETFILTER_V4MODPATH/${I}.${MODEXT}
	done

	# Unload rest of xt_ modules
	for I in $X_STATE_MODS; do
		unload_mod $NETFILTER_XMODPATH/${I}.${MODEXT}
	done

	# Unoad virtual server modules
	for I in $NETFILTER_IPVSMODPATH/ip_vs_* \
		$NETFILTER_IPVSMODPATH/ip_vs.${MODEXT}; do
		unload_mod $I
	done
	unload_mod libcrc32c 

	# Unload NAT modules
	for I in $NETFILTER_V4MODPATH/ip_nat*.${MODEXT} \
		$NETFILTER_V4MODPATH/iptable_nat.${MODEXT} \
		$NETFILTER_V4MODPATH/nf_conntrack_netlink.${MODEXT} \
		$NETFILTER_V4MODPATH/nf_nat_ipv4.${MODEXT} \
		$NETFILTER_V4MODPATH/nf_nat.${MODEXT} \
		$NETFILTER_V4MODPATH/ip_nat.${MODEXT};
	do 
		unload_mod $I
	done
	
	# Unload conection tracking
	for I in $NETFILTER_V4MODPATH/ip_conntrack_* \
		$NETFILTER_V4MODPATH/nf_conntrack_* \
		$NETFILTER_V4MODPATH/nf_defrag_ipv4 \
		$NETFILTER_XMODPATH/nf_conntrack_pptp.${MODEXT} \
		$NETFILTER_XMODPATH/nf_tproxy_* \
		$NETFILTER_XMODPATH/nf_conntrack_* \
		$NETFILTER_XMODPATH/nf_conntrack_broadcast.${MODEXT} \
		$NETFILTER_XMODPATH/nf_conntrack.${MODEXT} \
		$NETFILTER_V4MODPATH/ip_conntrack.${MODEXT}; do
		unload_mod $I
	done

	return 0
}

ipv4_nf_stop_mod () {
	local I ANS
	
	# Unload all nat and connection tracking modules
	ipv4_nfnat_stop_mod

	# Unload all the ipt_ modules save ipt_state, ipt_REDIRECT 
	# ipt_iplimit and ipt_MASQUERADE
	for I in $NETFILTER_V4MODPATH/ipt_*; do
		ANS="${I##*_}" 
		ANS="${ANS%.$MODEXT}"

		eval "case \"$ANS\" in
			$IPV4_STATE_MODS_CASE)
				continue;
			;;
			esac"
		
		unload_mod $I
	done



	# Unload the core netfilter modules
	for I in $IPV4_BASE_MODS_REV; do
		unload_mod $NETFILTER_V4MODPATH/${I}.${MODEXT}
	done

	return 0
}

ipv4_nf_start_mod () {
	
	case "$IP_FILTER_KERNEL" in
	PACKET|Packet|packet)
		# Stop NAT level modules to provide packet reasembly switch
		# functionality
		ipv4_nfnat_stop_mod
		# Load Netfilter base modules
		ipv4_nfbase_start_mod
		return 2
		;;
	NAT|Nat|nat|STATEFUL|Stateful|stateful)
		ipv4_nfbase_start_mod
		ipv4_nfnat_start_mod
		return 3
		;;
	*|NONE|None|none)
		return 1
		;;
	esac
}

# IPv6 Module strings - adjust these to suite as needed
IPV6_BASE_MODS="ip6_tables ip6table_filter ip6table_mangle"
IPV6_BASE_MODS_REV="ip6table_filter ip6table_mangle ip6_tables"
IPV6_STATE_MODS_CASE='"MASQUERADE"'
IPV6_STATE_MODS="ip6t_MASQUERADE"

ipv6_nfbase_start_mod () {
	local I ANS

	# load the base netfilter modules
	for I in $IPV6_BASE_MODS; do
		load_mod $NETFILTER_V6MODPATH/${I}.${MODEXT}
	done

	# Load all the ipt_ modules save ip6t_state, ip6t_REDIRECT 
	# ip6t_MASQUERADE and ip6t_iplimit
	for I in $NETFILTER_V6MODPATH/ip6t_*; do
		ANS="${I##*_}" 
		ANS="${ANS%.$MODEXT}"

		eval "case \"$ANS\" in
			$IPV6_STATE_MODS_CASE)
				continue;
			;;
			esac"

		load_mod $I
	done

	load_mod $NETFILTER_XMODPATH/xt_hashlimit.${MODEXT}
	
	return 0
}



ipv6_nfnat_start_mod () {
	local I 
	
	# Load conection tracking
	for I in $NETFILTER_V6MODPATH/ip6_conntrack.${MODEXT} \
		$NETFILTER_V6MODPATH/ip6_conntrack_* \
		$NETFILTER_V6MODPATH/nf_defrag_ipv6.${MODEXT} \
		$NETFILTER_V6MODPATH/nf_conntrack_ipv6.${MODEXT}; do
		load_mod $I
	done

	# Load NAT modules
	for I in $NETFILTER_V6MODPATH/nf_nat_ipv6.${MODEXT} \
		$NETFILTER_V6MODPATH/ip6table_nat.${MODEXT} \
		$NETFILTER_V6MODPATH/ip6_nat*.${MODEXT};
	do 
		load_mod $I
	done

	# Load xt_socket and xt_TPROXY
	load_mod $NETFILTER_XMODPATH/xt_socket.${MODEXT}
	load_mod $NETFILTER_XMODPATH/xt_TPROXY.${MODEXT}

	# Load rest of ip6t_ modules
	for I in $IPV6_STATE_MODS; do
		load_mod $NETFILTER_V6MODPATH/${I}.${MODEXT}
	done

	return 0
}

ipv6_nfnat_stop_mod () {
	local I
	
	# Unload rest of ip6t_ modules
	for I in $IPV6_STATE_MODS; do
		unload_mod $NETFILTER_V6MODPATH/${I}.${MODEXT}
	done

	# Unload xt_socket and xt_TPROXY
	unload_mod $NETFILTER_XMODPATH/xt_TPROXY.${MODEXT}
	unload_mod $NETFILTER_XMODPATH/xt_socket.${MODEXT}

	# Unload NAT modules
	for I in $NETFILTER_V6MODPATH/ip6_nat*.${MODEXT} \
		 $NETFILTER_V6MODPATH/ip6table_nat.${MODEXT} \
		 $NETFILTER_V6MODPATH/nf_nat_ipv6.${MODEXT};
	do 
		unload_mod $I
	done
	
	# Unload conection tracking
	for I in $NETFILTER_V6MODPATH/nf_conntrack_ipv6.${MODEXT} \
		$NETFILTER_V6MODPATH/nf_defrag_ipv6.${MODEXT} \
		$NETFILTER_XMODPATH/nf_conntrack_broadcast.${MODEXT} \
		$NETFILTER_XMODPATH/nf_conntrack.${MODEXT} \
		$NETFILTER_V6MODPATH/ip6_conntrack_* \
		$NETFILTER_V6MODPATH/ip6_conntrack.${MODEXT}; do
		unload_mod $I
	done

	return 0
}

ipv6_nf_stop_mod () {
	local I ANS
	
	# Unload all nat and connection traking modules
	ipv6_nfnat_stop_mod

	unload_mod $NETFILTER_XMODPATH/xt_hashlimit.${MODEXT}

	# Unload all the ipt_ modules save ipt_state, ipt_REDIRECT 
	# ipt_iplimit and ipt_MASQUERADE
	for I in $NETFILTER_V6MODPATH/ip6t_*; do
		ANS="${I##*_}" 
		ANS="${ANS%.$MODEXT}"

		eval "case \"$ANS\" in
			$IPV6_STATE_MODS_CASE)
				continue;
			;;
			esac"
		
		unload_mod $I
	done

	# Unload the core netfilter modules
	for I in $IPV6_BASE_MODS_REV; do
		unload_mod $NETFILTER_V6MODPATH/${I}.${MODEXT}
	done

	return 0
}

ipv6_nf_start_mod () {
	
	if [ $IPV6_KRNL -lt 1 ]; then
		return 0
	fi
	
	case "$IP_FILTER_KERNEL" in
	PACKET|Packet|packet)
		# Stop NAT level modules to provide packet reasembly switch
		# functionality
		ipv6_nfnat_stop_mod
		# Load Netfilter base modules
		ipv6_nfbase_start_mod
		return 2
		;;
	NAT|Nat|nat|STATEFUL|Stateful|stateful)
		ipv6_nfbase_start_mod
		ipv6_nfnat_start_mod
		return 3
		;;
	*|NONE|None|none)
		return 1
		;;
	esac
}


start_mod () {
	local NFXRES NFV4RES NFV6RES V6RES 

	vb echo "Loading networking modules..."	

	# Load QoS modules
	qos_start_mod

	# Load Free S/WAN ipsec modules
	ipsec_start_mod

	# Load IPv6
	ipv6_start_mod
	V6RES=$?
	
	# Load X Netfilter modules
	x_nfbase_start_mod
	NFXRES=$?
	
	# Load IPv4 NetFilter
	ipv4_nf_start_mod
	NFV4RES=$?

	# Load IPv6 Netfilter
	ipv6_nf_start_mod
	NFV6RES=$?

	vb echo "Networking modules loaded."

	case "$NFV4RES" in
	3)
		vb echo "IPv4 filtering level is \`STATEFUL/NAT'."
		;;
	2)	
		vb echo "IPv4 filtering level is \`PACKET'."
		;;
	1)
		vb echo "IPv4 filtering level is \`NONE'."
		;;
	esac
	
	case "$V6RES" in
	1)
		vb echo "IPv6 protocol module is loaded." 
		;;
	esac
	
	case "$NFV6RES" in
	3)
		vb echo "IPv6 filtering level is \`STATEFUL/NAT'."
		;;
	2)	
		vb echo "IPv6 filtering level is \`PACKET'."
		;;
	1)
		vb echo "IPv6 filtering level is \`NONE'."
		;;
	esac
	
	return 0

}

stop_mod () {

	# Unload IPv6 Netfilter
	ipv6_nf_stop_mod

	# Unload all IPv4 Netfilter modules 
	ipv4_nf_stop_mod

	# Unload all X Netfilter modules
	x_nfbase_stop_mod

	# Unload IPv6
	ipv6_stop_mod

	# Unload Free S/WAN ipsec modules
	ipsec_stop_mod
	
	# Unload QoS modules
	qos_stop_mod

	return 0
}

###############################################################################
#IP kernel option loading for global kernel switches
###############################################################################
read_sysctl () {
        local PROCFILE PROCVAL COMMENT ANS

	while read PROCFILE PROCVAL COMMENT; do
		if [ -z "$PROCFILE" -o -z "$PROCVAL" ]; then
			continue
		fi
	
		if [ "$PROCFILE"  = "#" -o "$PROCVAL" = "#" ]; then
			continue
		fi
		
		case "$PROCVAL" in
		YES|Yes|yes)
			PROCVAL=1
			;;
		NO|No|no)
			PROCVAL=0
			;;
		esac

		[ ! -f $1/$PROCFILE ] && continue

		echo $PROCVAL > $1/$PROCFILE
	done

}

read_gbl_sysctl () {

	echo "$NET_GLOBAL_SYSCTL" | read_sysctl /proc/sys/net
	
	return 0
}


###############################################################################
#IP Forwarding configuration
###############################################################################
start_auto_ipkrnlswch () {
    	local DIR
    
	# read in the global sysctl settings
	read_gbl_sysctl

	# Turn on global RP filter switch - this is ANDed with 
	# the per interface ones
	echo 1 > ${IPV4_PROC}/conf/all/rp_filter
	# Fix the Shared Media Mess
	echo 0 > ${IPV4_PROC}/conf/all/shared_media
	echo 0 > ${IPV4_PROC}/conf/default/shared_media


	if [ "$IPV4_FWDING_KERNEL" = "YES" ]; then
		vb echo -n "Enabling IPv4 packet forwarding..."
		echo "1" >$IPFWD_V4PROC && vb echo "done."
	elif [ "$IPV4_FWDING_KERNEL" != "FILTER_ON" ]; then
		vb echo -n "Disabling IPv4 packet forwarding..."
		echo "0" >$IPFWD_V4PROC && vb echo "done."
	fi 

	# IPv6  
	if [ $IPV6_KRNL -lt 1 ]; then
		return 0
	fi
	
	# Most hardened servers and routers need defaults like these
	# for interface host mode
	for DIR in ${IPV6_PROC}/conf/*; do
		# Don't allow ICMP redirect by default
		echo 0 > $DIR/accept_redirects
	done

	# This is here just to do the printing when IPv6 IS disabled.
	case "$IPV6_DISABLE" in
	YES|Yes|yes)
		vb echo -n "Disabling IPv6 protocol..." 
		ifv6_setproc all disable_ipv6 "$IPV6_DISABLE" && echo "done."
		;;
	*)
		ifv6_setproc all disable_ipv6 "$IPV6_DISABLE"
		;;
	esac

	# Set this flag as required for creation of dynamic bridged
	# interfaces
	ifv6_setproc default disable_ipv6 "$IF_DEFAULT_IPV6_DISABLE"

	if [ "$IPV6_FWDING_KERNEL" = "YES" ]; then
		vb echo -n "Enabling IPv6 packet forwarding..." 
		echo "1" >$IPFWD_V6PROC && vb echo "done."
	elif [ "$IPV6_FWDING_KERNEL" != "FILTER_ON" ]; then
		vb echo -n "Disabling IPv6 packet forwarding..." 
		echo "0" >$IPFWD_V6PROC && vb echo "done."
	fi 

}

###############################################################################
#Interface configuration
###############################################################################
start_auto_if () {

	###
	#localhost interface
	####################
	vb echo -n "Configuring loopback interface lo..."
	if_lo_up && vb echo "done."
	# Do the rest of the interfaces
	iface_up all
}

##############################################################################
# Interface stuff iface_up, iface_down, iface_reset, iface_upstart_emit
##############################################################################
iface_up () {
    local IF
    vb echo -n "Configuring interface:"
    if [ "$1" = "all" ] ; then
	for IF in $IF_AUTO; do
	    if_up $IF && vb echo -n " $IF"
	done
	unset IF
    else
	# Don't do anything during boot or shutdown
	case "$RUNLVL" in
	unknown|0|1|6)
    		vb echo "."
		return 0
		;;
	esac
	eval local IF_CHAIN_AUTO=\"\${"$1"_IF_CHAIN_AUTO:-""}\"
	if_up $1 && vb echo -n " $1"
	for IF in $IF_CHAIN_AUTO; do
	    if_up $IF && vb echo -n " $IF"
	done
	unset IF
    fi
    vb echo "."
}


iface_down () {
    local IF
    vb echo -n "Stopping interface:"
    if [ "$1" = "all" ] ; then
	for IF in $REV_IF_LIST; do
	    if_down $IF && vb echo -n " $IF"
	done
	unset IF
    else
	# Don't do anything during boot or shutdown
	case "$RUNLVL" in
	unknown|0|1|6)
    		vb echo "."
		return 0
		;;
	esac
	local REV_IF_CHAIN
	eval local IF_CHAIN=\"\${"$1"_IF_CHAIN:-""}\"
	eval local IF_CHAIN_AUTO=\"\${"$1"_IF_CHAIN_AUTO:-""}\"
	IF_CHAIN="$IF_CHAIN_AUTO $IF_CHAIN" 
	for IF in $IF_CHAIN; do
		REV_IF_CHAIN="$REV_IF_CHAIN $IF"
	done
	unset IF
	for IF in $REV_IF_CHAIN; do
		if_down $IF && vb echo -n " $IF"
	done
	unset IF
	if_down $1 && vb echo -n " $1"
    fi
    vb echo "."
}


iface_reset () {
    iface_down $1
    sleep 2
    iface_up $1
    # If gated is around, tell it all about this!
    [ -f $GDC_PATH ] && vb echo -n "Telling gated..."
    [ -f $GDC_PATH ] && sleep 5 && $GDC_PATH interface
    [ -f $GDC_PATH ] && vb echo "done."
}


iface_qos () {
    
    vb echo -n "Reloading QoS for interface: "
    if [ "$1" = "all" ] ; then
	for IF in $IF_AUTO; do
		ip_QoSppp $IF
		ip_QoSclear $IF && ip_QoS $IF && vb echo -n " $IF"
	done
	unset IF
    else
	ip_QoSppp $1
	ip_QoSclear $1 && ip_QoS $1 && vb echo -n " $1"
    fi
    vb echo "."
    return 0
}

iface_upstart_emit () {
	if ! [ -x "$INITCTL" ]; then
		return 0
	fi

	$INITCTL emit --no-wait "$@"
}


##############################################################################
# Functions to set 2.4 kernel interface parameters
# ifv4_setproc (<interface> <file> YES|NO
# ifv6_setproc (<interface> <file> YES|NO
##############################################################################
ifv4_setproc () {
	if [ -z "$3" ]; then
		return 0;
	fi

	[ ! -f ${IPV4_PROC}/conf/$1/$2 ] && return 1

	case "$3" in 
	YES|Yes|yes)
		echo 1 > ${IPV4_PROC}/conf/$1/$2
		return 0;
		;;
	NO|No|no)
		echo 0 > ${IPV4_PROC}/conf/$1/$2
		return 0;
		;;
	*)
		if echo $3 | grep -q '^[0-9]\+$'; then
			echo $3 > ${IPV4_PROC}/conf/$1/$2
			return 0
		fi

		return 1;
		;;
	esac
	
	return 0;
	
}

ifv6_setproc () {
	if [ -z "$3" ]; then
		return 0;
	fi

	[ $IPV6_KRNL -lt 1 ] && return 1 
	[ ! -f ${IPV6_PROC}/conf/$1/$2 ] && return 1

	case "$3" in 
	YES|Yes|yes)
		echo 1 > ${IPV6_PROC}/conf/$1/$2
		return 0;
		;;
	NO|No|no)
		echo 0 > ${IPV6_PROC}/conf/$1/$2
		return 0;
		;;
	*)
		if echo $3 | grep -q '^[0-9]\+$'; then
			echo $3 > ${IPV6_PROC}/conf/$1/$2
			return 0
		fi
		
		return 1;
		;;
	esac
	
	return 0;
	
}


##############################################################################
# Functions to configure the bridge
# brg_global()
##############################################################################
brg_unbind_netfilter () {
	local STUFF

	# Unbind bridges from Netfilter
	if [ "$BRG_NETFILTER_REMOVE" != "NO" \
		-a "$BRG_NETFILTER_REMOVE" != "No" \
		-a "$BRG_NETFILTER_REMOVE" != "no" ]; then
		STUFF=" 
# Disable netfilter in bridge(s) - useful when not
# doing bridge filtering.
bridge/bridge-nf-call-ip6tables NO
bridge/bridge-nf-call-iptables NO
bridge/bridge-nf-call-arptables NO
bridge/bridge-nf-filter-pppoe-tagged NO
bridge/bridge-nf-filter-vlan-tagged NO
"
		echo "$STUFF" | read_sysctl /proc/sys/net

	else
		STUFF=" 
# Disable netfilter in bridge(s) - useful when not
# doing bridge filtering.
bridge/bridge-nf-call-ip6tables YES
bridge/bridge-nf-call-iptables YES
bridge/bridge-nf-call-arptables YES
bridge/bridge-nf-filter-pppoe-tagged YES
bridge/bridge-nf-filter-vlan-tagged YES
"
		echo "$STUFF" | read_sysctl /proc/sys/net
	fi

	return 0
}

brg_global() {
	local INT BRG ANS
	local BRG_DEVLIST
	
	case "$BRG_SWITCH" in
	YES|Yes|yes)
		BRG_LIST="$BRG_LIST"
		;;
	NO|No|no)
		unset BRG_LIST
		;;
	0|1|2|3|4|5|6|7|8|9|10)
		INT=0
		while [ $INT -lt $BRG_SWITCH ]; do

			BRG_LIST="$BRG_LIST brg${INT}"
			INT=$(( $INT + 1 ))
		done
		;;
	esac

	BRG_DEVLIST=`brctl show | sed -e '1d' | grep '^[-a-zA-Z0-9_]' | sed -e 's/^\([a-zA-Z0-9_\-]\+\)[ 	].*$/\1/'`

	for BRG in $BRG_DEVLIST; do
		ANS=`echo $BRG_LIST | grep $BRG`
		if [ -z "$ANS" ]; then
			qt ip link set dev $BRG down
			brctl delbr $BRG
		fi
	done
	for BRG in $BRG_LIST; do
		brctl addbr $BRG > /dev/null 2>&1
	done

	brg_unbind_netfilter

	return 0
}

brg_iface () {
	local BRG ANS

	case $2 in
	up)
		if [ "$3" = "NO" -o "$3" = "No" -o "$3" = "no" ]; then
			return 0
		fi
		if [ "$3" = "YES" -o "$3" = "Yes" -o "$3" = "yes" ]; then
			BRG=brg0
		else
			BRG=$3
		fi
		[ -z "$BRG" ] && return 0
		ANS="echo $BRG_LIST | grep $BRG"
		if [ -n "$ANS" ]; then
			brctl addif $BRG $1 > /dev/null 2>&1
			[ -z "$4" ] && ifv6_setproc $1 disable_ipv6 YES
		fi
		;;
	down)	
		BRG=`brctl show | sed -e '1d' | grep "${1}\$" | sed -e 's/^\([a-zA-Z]\+[0-9]\+\)[ 	]\+.*$/\1/'`
		[ -z "$BRG" ] && BRG=brg0
		brctl delif $BRG $1 > /dev/null 2>&1
		[ -z "$3" ] && ifv6_setproc $1 disable_ipv6 NO
		;;
	esac

	return 0
}

##############################################################################
# Functions to set the default route
##############################################################################

ipv4_default_route () {
	
	if [ "$1" != "$IPV4_DEFAULT_GWDEV" ]; then
		return 0
	fi
	
	# Default route support
        case "$IPV4_DEFAULT_GW" in
	OTHER|Other|other|OFF|Off|off|NO|No|no)
		;;
	"")
		ip route del default metric $DEFAULT_METRIC > /dev/null 2>&1
		;;
	*)
		ip route replace default via $IPV4_DEFAULT_GW \
			metric $DEFAULT_METRIC
		;;
	esac
	
	return 0
}

ipv6_default_route () {
	
	if [ "$1" != "$IPV6_DEFAULT_GWDEV" ]; then
		return 0
	fi
	
	# IPv6 default route - this could be better 
	case "$IPV6_DEFAULT_GW" in
	OTHER|Other|other|OFF|Off|off|NO|No|no)
		;;
	"")
		ip -6 route del $IPV6_DEFAULT_PREFIX metric $DEFAULT_METRIC \
			> /dev/null 2>&1
		;;
	*)
		local IPV6_ZERO_GW=`echo $IPV6_DEFAULT_GW \
			| eval $SED_IPV6ADDR`
		if ! ip -6 route list $IPV6_DEFAULT_PREFIX \
			| grep  -q "$IPV6_ZERO_GW.*metric $DEFAULT_METRIC"; 
		then
			ip -6 route del $IPV6_DEFAULT_PREFIX \
				metric $DEFAULT_METRIC > /dev/null 2>&1
			ip -6 route add $IPV6_DEFAULT_PREFIX \
				metric $DEFAULT_METRIC via $IPV6_DEFAULT_GW \
				dev $IPV6_DEFAULT_GWDEV
		fi
		;;
	esac
}



##############################################################################
# checkarg() a function to check interface arguments
##############################################################################
checkarg() {
    eval "case \"$*\" in
        $IFLIST)
            ;;
        *)
            echo \"Usage: `basename $0` ifup|ifdown|ifqos|ifreload\" 
	    echo \"       ${SP} {$IFLIST}\"
            exit 1
            ;;
         esac"
}


##############################################################################
# functions to handle filter stuff
##############################################################################

#
# backup_rotate <filename> <maxlevel>
#
backup_rotate () {
        local MAX="$2"
        [ $MAX -lt 2 ] && MAX=2
        local COUNT=$(($MAX - 1))
        local PREV="$MAX"
        while [ $COUNT -gt 0 ]; do
                [ -f "${1}.${COUNT}" ] && mv "${1}.${COUNT}" "${1}.${PREV}"
                PREV=$COUNT
                COUNT=$(( $COUNT - 1 ))
        done
        [ -f "$1" ] && mv "$1" "${1}.1"
	return 0
}

ipv4filter_kernfwd () {
	local OVERRIDE="$2"

	if [ "$OVERRIDE" != "YES" -a "$OVERRIDE" != "Yes" \
		-a "$OVERRIDE" != "yes" \
		-a  "$IPV4_FWDING_KERNEL" != "FILTER_ON" ]; then
		return 0;
    	fi
    
	case $1 in 
	on)
		vb echo -n "Enabling IPv4 packet forwarding..."
		echo "1" >$IPFWD_V4PROC \
			&& vb echo "done."
		;;
	off)
		vb echo -n "Disabling IPv4 packet forwarding..."
		echo "0" >$IPFWD_V4PROC \
			&& vb echo "done."
	    	;;
	*)
		echo "AAARGGHH - wrong argument given to ipv4filter_kernfwd: $1"
		exit 1
		;;
	esac
}

# Check and see if filtering and mangling are available
ipv4filter_check () {
	local TBL MANGLE FILTER
	MANGLE=0
	FILTER=0

	[ ! -f "$IPTBL_V4PROC" ] && return 1

	for TBL in `cat $IPTBL_V4PROC`; do
		case $TBL in
		mangle)
			MANGLE=1
			;;
		filter)
			FILTER=1
			;;
		esac
	done

	if [ $MANGLE -ne 1 -a $FILTER -ne 1 ]; then
		return 1
	fi

	return 0
}

# A function to flush the filters (for internal use)
ipv4filter_flush  () {
	local TBL

	# Flush the IPV4 filters out, and user defined chains
	[ ! -f $IPTBL_V4PROC ] && return 0
	for TBL in `cat $IPTBL_V4PROC`; do
		if [ "$TBL" = "$1" ]; then
			continue
		fi
		$IPTBL -t $TBL -F
		$IPTBL -t $TBL -X
	done

	return 0
}

ipv4filter_policy () {
	local TBL

	[ ! -f $IPTBL_V4PROC ] && return 0
	for TBL in `cat $IPTBL_V4PROC`; do
		if [ "$TBL" = "$2" ]; then
			continue
		fi

		case $TBL in
		mangle)
			$IPTBL -t $TBL -P PREROUTING $1
			$IPTBL -t $TBL -P OUTPUT $1
			;;
		filter)
			$IPTBL -t $TBL -P INPUT $1
			$IPTBL -t $TBL -P FORWARD $1
			$IPTBL -t $TBL -P OUTPUT $1
			;;
		nat)
			$IPTBL -t $TBL -P PREROUTING $1
			$IPTBL -t $TBL -P POSTROUTING $1
			$IPTBL -t $TBL -P OUTPUT $1
			;;
		esac
	done

	return 0
}
				
# function to set the filter default policies
ipv4filter_clear () { 

	ipv4filter_flush $1

	ipv4filter_policy ACCEPT $1

	return 0	    

}

# Selects basic filter type configuration function
ipv4filter_iptbl_cfg () {
	if ! ipv4filter_check; then
		echo 
		echo "IPv4 filters: netfilter kernel modules not loaded." 
		echo
		return 1
	fi

	if [ ! -f $1 ] ; then
		echo
		echo "IPv4 filters: no $1 file."
		echo
		return 1
	fi
	echo -n "Loading IPv4 filters..." 
	if $IPTBL_RESTORE < $1; then
		ipv4filter_fairq
		ipf4_laptopfw
		vb echo "done."
		ipv4filter_kernfwd on
	else
		return 1
	fi

	return 0

}

ipv4filter_iptbl_save () {
	local OLD_UMASK
	
	if ! ipv4filter_check; then
		echo 
		echo "IPv4 filters: netfilter kernel modules not loaded." 
		echo
		return 1
	fi
	
	echo -n "Saving IPv4 filters..."
	backup_rotate "$IPTBL_FILE" "$BACKUP_LEVELS"
	OLD_UMASK=`umask`
	umask 0277
	if $IPTBL_SAVE > $IPTBL_FILE; then
		umask $OLD_UMASK
		chmod 0400 $IPTBL_FILE
		vb echo "done."
	else
		umask $OLD_UMASK
		vb echo
		return 1
	fi 

	vb echo
	return 0
}

# Some functions to handle Protocol IP Port tuples

ipfilter_echoParam () {
	local format="$1"
	local IFS='_'
	set -- $2
	eval "echo \"$format\""
}
	
ipfilter_echoIpPort () {
	local format1="$1"
	local format2="$2"
	local testpar="$3"
	local IFS='_'
	set -- $4
	eval "echo -n \"$format1\""
	eval "if [ -n \"$testpar\" ]; then
		echo \" $format2\"
	fi"
}

ipv4filter_delTie () {
	local CHAIN="$1"
	shift
	qt $IPTBL -t mangle -D "$CHAIN" $*
	qt $IPTBL -t mangle -D "$CHAIN" -s 0/0 $*
	qt $IPTBL -t mangle -D "$CHAIN" -d 0/0 $*
	qt $IPTBL -t mangle -D "$CHAIN" -d 0/0 -s 0/0 $*
	return 0
}

# A function to mark packets for classification 
ipv4filter_fairq () {
	local CLS
	local TNL

	if ! ipv4filter_check; then
		return 1
	fi

	[ -z "$MANGLE_OUTPUT_BYPASS" ] && [ -z "$CLS_FAIRQ" ] && return 0
	
	qt $IPTBL -t mangle -F nomangle
	qt $IPTBL -t mangle -N nomangle

	# Accept IPv4 tunnel traffic - any changes on
	# OUTPUT chain will cause rerouting, and Free S/WAN problems
	for TNL in $MANGLE_OUTPUT_BYPASS; do
		$IPTBL -t mangle -A nomangle -j ACCEPT \
			-p `ipfilter_echoParam '$1' $TNL` \
			-d `ipfilter_echoIpPort '$2' ' --dport $3' '$3' $TNL`
	done

	# Add the nomangle chain to the OUTPUT chain
	# NOTE position this is inserted.
	ipv4filter_delTie OUTPUT -j nomangle
	$IPTBL -t mangle -I OUTPUT 1 -j nomangle

	[ -z "$CLS_FAIRQ" ] && return 0
	
	# Clear chain if it already exists
	qt $IPTBL -t mangle -F fairq

	# Create new chain
	qt $IPTBL -t mangle -N fairq

	# Populate chains
	for CLS in $CLS_FAIRQ; do
		$IPTBL -t mangle -A fairq -j MARK \
			--set-mark `ipfilter_echoParam '$1' $CLS` \
			-p `ipfilter_echoParam '$2' $CLS` \
			`ipfilter_echoIpPort '-d $3' ' --dport $4' '$4' $CLS`
		$IPTBL -t mangle -A fairq -j MARK \
			--set-mark `ipfilter_echoParam '$1' $CLS` \
			-p `ipfilter_echoParam '$2' $CLS` \
			`ipfilter_echoIpPort '-s $3' ' --sport $4' '$4' $CLS`
	done;

	# Add fairq chain to OUTPUT and PREROUTING chains
	ipv4filter_delTie OUTPUT -j fairq
	$IPTBL -t mangle -I OUTPUT 2 -j fairq # NOTE postion this is inserted.
	ipv4filter_delTie PREROUTING -j fairq
	$IPTBL -t mangle -I PREROUTING 1 -j fairq

	return 0
}

ipv4filter_exec () {
	local RES
	
	if ! ipv4filter_check; then
		return 1
	fi

	local FN="$1"
	shift
	eval "case \"$FN\" in
		$IPF4_FNS)
			case \$1 in 
			-r|remove)
				vb echo -n \"Removing IPv4 filter $FN...\"
				;;
			*)
				vb echo -n \"Loading IPv4 filter $FN...\"
				;;
			esac
			if ipf4_${FN} $*; then 	
				echo \"done.\"
				exit 0
			fi
			exit 1
			;;
		*)
    			echo \"       `basename $0` ipfilter exec $IPF4_FNS\"
			echo \"                              [chain p1 p2 ...]\"
    			exit 1
			;;
		esac"

	return 0
}


ipv4filter_cmd () {
	
	if [ "$KERN_VERSION" != "$TARGET_KERNEL1" \
		-a "$KERN_VERSION" != "$TARGET_KERNEL2" \
		-a "$KERN_VERSION" != "$TARGET_KERNEL3" ] ; then
		echo
		echo "IPv4 filters: kernel not version ${TARGET_KERNEL1}.x, ${TARGET_KERNEL2}.x, or ${TARGET_KERNEL3}.x."
		if [ "$IPV4_FWDING_KERNEL" = "FILTER_ON" ]; then
			# Keep the output pretty..
			echo
		fi
		ipv4filter_kernfwd off
		echo
		return 1
	fi
	if ! [ -x $IPTBL ] ; then
		echo
		echo "IPv4 filters: $IPTBL not found."
		echo
		return 1
	fi
	case $1 in
	load|reload|restart|reset)
		ipv4filter_iptbl_cfg $IPTBL_FILE
    		;;
	usebackup)
		local BKUP_NUM=1
    		[ -n "$2" ] && BKUP_NUM="$2"
		ipv4filter_iptbl_cfg "${IPTBL_FILE}.${BKUP_NUM}"
		;;
	save)
		ipv4filter_iptbl_save
    		;;
	fairq)
		echo -n "Reloading IPv4 fairq filters..."
		if ipv4filter_fairq; then 
			echo "done."
    		else
			echo "netfilter kernel modules not loaded."
    		fi
    		;;
	clear|flush)
		ipv4filter_kernfwd off
 		vb echo -n "Flushing IPv4 filters..."
 		ipv4filter_clear
		ipv4filter_fairq
    		vb echo "done."
    		;;
	exec)
		shift
		ipv4filter_exec $*
		;;
	forward|fwd)
		ipv4filter_kernfwd on yes
		;;
	noforward|nofwd)
		ipv4filter_kernfwd off yes
		;;
	
	*)
		echo "Usage: `basename $0` ipfilter load|clear|fairq|flush|fwd|nofwd|reload|save"
		echo "                              usebackup [backup-number]"
		echo "       `basename $0` ipfilter exec $IPF4_FNS"
		echo "                              [chain p1 p2 ...]"
		exit 1
		;;
	esac
}

# IPv6 filters

ipv6filter_kernfwd () {
	local OVERRIDE="$2"

	if [ "$OVERRIDE" != "YES" -a "$OVERRIDE" != "Yes" \
		-a "$OVERRIDE" != "yes" \
		-a  "$IPV6_FWDING_KERNEL" != "FILTER_ON" ]; then
		return 0;
    	fi
    
	case $1 in 
	on)
		vb echo -n "Enabling IPv6 packet forwarding..." 
		echo "1" >$IPFWD_V6PROC \
			&& vb echo "done."
		;;
	off)
		vb echo -n "Disabling IPv6 packet forwarding..."
		echo "0" >$IPFWD_V6PROC \
			&& vb echo "done."
	    	;;
	*)
		echo "AAARGGHH - wrong argument given to ipv6filter_kernfwd: $1"
		exit 1
		;;
	esac
}

# Check and see if filtering and mangling are available
ipv6filter_check () {
	local TBL MANGLE FILTER
	MANGLE=0
	FILTER=0

	[ ! -f "$IPTBL_V6PROC" ] && return 1

	for TBL in `cat $IPTBL_V6PROC`; do
		case $TBL in
		mangle)
			MANGLE=1
			;;
		filter)
			FILTER=1
			;;
		esac
	done

	if [ $MANGLE -ne 1 -a $FILTER -ne 1 ]; then
		return 1
	fi

	return 0
}


# A function to flush the filters (for internal use)
ipv6filter_flush  () {
	local TBL

	# Flush the IPV6 filters out, and user defined chains
	[ ! -f $IPTBL_V6PROC ] && return 0
	for TBL in `cat $IPTBL_V6PROC`; do
		if [ "$TBL" = "$1" ]; then
			continue
		fi
		$IP6TBL -t $TBL -F
		$IP6TBL -t $TBL -X
	done

	return 0
}

ipv6filter_policy () {
	local TBL

	[ ! -f $IPTBL_V6PROC ] && return 0
	for TBL in `cat $IPTBL_V6PROC`; do
		if [ "$TBL" = "$2" ]; then
			continue
		fi

		case $TBL in
		mangle)
			$IP6TBL -t $TBL -P PREROUTING $1
			$IP6TBL -t $TBL -P OUTPUT $1
			;;
		filter)
			$IP6TBL -t $TBL -P INPUT $1
			$IP6TBL -t $TBL -P FORWARD $1
			$IP6TBL -t $TBL -P OUTPUT $1
			;;
		nat)
			$IP6TBL -t $TBL -P PREROUTING $1
			$IP6TBL -t $TBL -P POSTROUTING $1
			$IP6TBL -t $TBL -P OUTPUT $1
			;;
		esac
	done

	return 0
}
				
# function to set the filter default policies
ipv6filter_clear () { 

	ipv6filter_flush $1

	ipv6filter_policy ACCEPT $1

	return 0	    

}

# Selects basic filter type configuration function
ipv6filter_iptbl_cfg () {
	if ! ipv6filter_check; then
		echo 
		echo "IPv6 filters: netfilter kernel modules not loaded." 
		echo
		return 1
	fi

	if [ ! -f $1 ] ; then
		echo
		echo "IPv6 filters: no $1 file."
		echo
		return 1
	fi
	echo -n "Loading IPv6 filters..." 
	if $IP6TBL_RESTORE < $1; then
		ipv6filter_fairq
		ipf6_laptopfw
		vb echo "done."
		ipv6filter_kernfwd on
	else
		return 1
	fi

	return 0

}

ipv6filter_iptbl_save () {
	local OLD_UMASK

	if ! ipv6filter_check; then
		echo 
		echo "IPv6 filters: netfilter kernel modules not loaded." 
		echo
		return 1
	fi

	echo -n "Saving IPv6 filters..."
	backup_rotate "$IP6TBL_FILE" "$BACKUP_LEVELS"
	OLD_UMASK=`umask`
	umask 0277
	if $IP6TBL_SAVE > $IP6TBL_FILE; then
		umask $OLD_UMASK
		chmod 0400 $IP6TBL_FILE
		vb echo "done."
	else
		umask $OLD_UMASK
		vb echo
		return 1
	fi 

	vb echo
	return 0
}

ipv6filter_delTie () {
	local CHAIN="$1"
	shift
	qt $IP6TBL -t mangle -D "$CHAIN" $*
	qt $IP6TBL -t mangle -D "$CHAIN" -s ::/0 $*
	qt $IP6TBL -t mangle -D "$CHAIN" -d ::/0 $*
	qt $IP6TBL -t mangle -D "$CHAIN" -s ::/0 -d ::/0 $*
	return 0
}

# A function to mark packets for classification 
ipv6filter_fairq () {
	local CLS
	local TNL

	if ! ipv6filter_check; then
		return 1
	fi

	[ -z "$IPV6_MANGLE_OUTPUT_BYPASS" ] && [ -z "$IPV6_CLS_FAIRQ" ] \
		&& return 0
	
	qt $IP6TBL -t mangle -F nomangle
	qt $IP6TBL -t mangle -N nomangle

	# Accept IPv6 tunnel traffic - any changes on
	# OUTPUT chain will cause rerouting, and Free S/WAN problems
	for TNL in $IPV6_MANGLE_OUTPUT_BYPASS; do
		$IP6TBL -t mangle -A nomangle -j ACCEPT \
			-p `ipfilter_echoParam '$1' $TNL` \
			-d `ipfilter_echoIpPort '$2' ' --dport $3' '$3' $TNL`
	done

	# Add the nomangle chain to the OUTPUT chain
	# NOTE position this is inserted.
	ipv6filter_delTie OUTPUT -j nomangle
	$IP6TBL -t mangle -I OUTPUT 1 -j nomangle

	[ -z "$IPV6_CLS_FAIRQ" ] && return 0
	
	# Clear chain if it already exists
	qt $IP6TBL -t mangle -F fairq

	# Create new chain
	qt $IP6TBL -t mangle -N fairq

	# Populate chains
	for CLS in $IPV6_CLS_FAIRQ; do
		$IP6TBL -t mangle -A fairq -j MARK \
			--set-mark `ipfilter_echoParam '$1' $CLS` \
			-p `ipfilter_echoParam '$2' $CLS` \
			`ipfilter_echoIpPort '-d $3' ' --dport $4' '$4' $CLS`
		$IP6TBL -t mangle -A fairq -j MARK \
			--set-mark `ipfilter_echoParam '$1' $CLS` \
			-p `ipfilter_echoParam '$2' $CLS` \
			`ipfilter_echoIpPort '-s $3' ' --sport $4' '$4' $CLS`
	done;

	# Add fairq chain to OUTPUT and PREROUTING chains
	ipv6filter_delTie OUTPUT -j fairq
	$IP6TBL -t mangle -I OUTPUT 2 -j fairq # NOTE postion this is inserted.
	ipv6filter_delTie PREROUTING -j fairq
	$IP6TBL -t mangle -I PREROUTING 1 -j fairq

	return 0
}

ipv6filter_exec () {
	local RES
	
	if ! ipv6filter_check; then
		return 1
	fi

	local FN="$1"
	shift
	eval "case \"$FN\" in
		$IPF6_FNS)
			case \$1 in 
			-r|remove)
				vb echo -n \"Removing IPv6 filter $FN...\"
				;;
			*)
				vb echo -n \"Loading IPv6 filter $FN...\"
				;;
			esac
			if ipf6_${FN} $*; then 	
				echo \"done.\"
				exit 0
			fi
			exit 1
			;;
		*)
    			echo \"       `basename $0` ip6filter exec $IPF6_FNS\"
			echo \"                              [chain p1 p2 ...]\"
    			exit 1
			;;
		esac"


	return 0
}

ipv6filter_cmd () {
	if [ $IPV6_KRNL -lt 1 ]; then
		return 0
	fi

	if [ "$KERN_VERSION" != "$TARGET_KERNEL1"  \
		-a "$KERN_VERSION" != "$TARGET_KERNEL2" \
		-a "$KERN_VERSION" != "$TARGET_KERNEL3" ] ; then
		echo
		echo "IPv6 filters: kernel not version ${TARGET_KERNEL1}.x, ${TARGET_KERNEL2}.x, or ${TARGET_KERNEL3}.x."
		if [ "$IPV6_FWDING_KERNEL" = "FILTER_ON" ]; then
			# Keep the output pretty..
			echo
		fi
		ipv6filter_kernfwd off
		echo
		return 1
	fi
	if ! [ -x $IP6TBL ] ; then
		echo
		echo "IPv6 filters: $IP6TBL not found."
		echo
		return 1
	fi
	case $1 in
	load|reload|restart|reset)
		ipv6filter_iptbl_cfg $IP6TBL_FILE
    		;;
	usebackup)
		local BKUP_NUM=1
    		[ -n "$2" ] && BKUP_NUM="$2"
		ipv6filter_iptbl_cfg "${IP6TBL_FILE}.${BKUP_NUM}"
		;;
	save)
		ipv6filter_iptbl_save
    		;;
	fairq)
		echo -n "Reloading IPv6 fairq filters..."
		if ipv6filter_fairq; then 
			echo "done."
    		else
			echo "netfilter IPv6 kernel modules not loaded."
    		fi
    		;;
	clear|flush)
		ipv6filter_kernfwd off
 		vb echo -n "Flushing IPv6 filters..."
 		ipv6filter_clear
		ipv6filter_fairq
    		vb echo "done."
    		;;
	exec)
		shift
		ipv6filter_exec $*
		;;
	forward|fwd)
		ipv6filter_kernfwd on yes
		;;
	noforward|nofwd)
		ipv6filter_kernfwd off yes
		;;
	
	*)
		echo "Usage: `basename $0` ip6filter load|clear|fairq|flush|fwd|nofwd|reload|save"
		echo "                               usebackup [backup-number]"
		echo "       `basename $0` ip6filter exec $IPF6_FNS"
		echo "                              [chain p1 p2 ...]"
		exit 1
		;;
	esac
}


##############################################################################
# Start and stop
##############################################################################

start () {

	start_mod
	start_auto_ipkrnlswch
	if [ "$1" != "reload" ]; then
		ipv4filter_cmd load
	else
		ipv4filter_fairq
	fi
	
	if [ $IPV6_KRNL -ge 1 ]; then
		if [ "$1" != "reload" ]; then
			ipv6filter_cmd load
		else
			ipv6filter_fairq
		fi
	fi
	
	start_auto_if
		
}	#END start ()

stop () {

	iface_down all

	vb echo -n "Disabling IPv4 packet forwarding..."
	echo "0" >$IPFWD_V4PROC \
	    && vb echo "done."
	vb echo -n "Flushing IPv4 filters..."
	ipv4filter_clear && vb echo "done."
	
	if [ $IPV6_KRNL -ge 1 ]; then
		vb echo -n "Disabling IPv6 packet forwarding..."
		echo "0" >$IPFWD_V6PROC \
	    		&& vb echo "done."
		vb echo -n "Flushing IPv6 filters..."
		ipv6filter_clear && vb echo "done."
	fi

	# Deal with modules do kernel printk stuff...
	vb echo "Unloading networking modules..."
	stop_mod && vb echo "Networking modules unloaded."

}	#END stop ()

#############################################################################
# Debian compatibility hooks 
#############################################################################

ifupdown_usage () {
	echo "Usage: `basename $0` -a|$IFLIST" 1>&2
	echo "       Use the netscript command instead as it a lot better." 1>&2
	exit 1
}

ifupdown () {
	local OPTA
	local OPTIND

	OPTA=0
	OPTIND=1
        while getopts :ah F; do
                case $F in
		a) 	OPTA=1
			;;
                h)
                        ifupdown_usage
                        exit 1
                        ;;
                \?)
                        ;;
                esac
        done
        shift $(( $OPTIND - 1 ))

	case "$RUNLVL" in
	unknown|0|1|6)
		# Do nothing
		exit 0
		;;
	*)
		if [ "`basename $0`" = "ifup" -a $OPTA -gt 0 ]; then
			iface_up all > /dev/null
			exit 0
		elif [ "`basename $0`" = "ifdown" -a $OPTA -gt 0 ]; then
			iface_down all > /dev/null
			exit 0
		fi
		;;
	esac

	if [ $# -eq 1 ]; then
		eval "case \"$*\" in
            			$IFLIST)
	                		;;
			        *)
					ifupdown_usage
					exit 1
					;;
			esac"

		case "`basename $0`" in
			ifup)

				iface_up $1 > /dev/null
				exit 0
				;;
			ifdown)
				iface_down $1 > /dev/null
				exit 0
				;;
		esac
	fi
	

	ifupdown_usage
	exit 1

}

#############################################################################
# Main - Down to business
#############################################################################


# Handle symlinked ifup and ifdown commands

if [ "`basename $0`" = "ifup" -o "`basename $0`" = "ifdown" ]; then 
	ifupdown $*
fi

case "$1" in
	start)	start	;;
	stop)	stop	;; 
	reload) start reload ;;
	restart|force-reload)
		$0 stop
		sleep 1
		$0 start
		;;

	ifup|ifreload)
		shift
		checkarg $*
		iface_up $1
		;;

	ifdown)
		shift
		checkarg $*
		iface_down $1
		;;
	
	ifqos)
		shift
		checkarg $*
		iface_qos $1
		;;

	ifreset|ifrestart)
		shift
		checkarg $*
		iface_reset $1
		;;

	ipfilter)
		shift
		if ! ipv4filter_cmd $*; then
		    exit 1
		fi
		;;

	*)
		if [ $IPV6_KRNL -ge 1 -a "$1" = "ip6filter" ]; then
			shift
			if ! ipv6filter_cmd $*; then
		    	exit 1
			fi
			exit 0
		fi
		echo "Usage: `basename $0` start|stop|reload|restart" 
		echo "       `basename $0` ifup|ifdown|ifqos|ifreload"
		echo "       ${SP} {$IFLIST}"
		echo "Usage: `basename $0` ipfilter load|clear|fairq|flush|fwd|nofwd|reload|save"
		echo "                              usebackup [backup-number]"
		echo "       `basename $0` ipfilter exec $IPF4_FNS"
		echo "                              [chain p1 p2 ...]"
		if [ $IPV6_KRNL -ge 1 ]; then 
			echo "Usage: `basename $0` ip6filter load|clear|fairq|flush|fwd|nofwd|reload|save"
			echo "                              usebackup [backup-number]"
			echo "       `basename $0` ip6filter exec $IPF6_FNS"
			echo "                              [chain p1 p2 ...]"
		fi
		exit 1 
        ;;
esac

exit 0


