home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PC World 2000 February
/
PCWorld_2000-02_cd.bin
/
live
/
sbin
/
ipfwadm-wrapper
< prev
next >
Wrap
Text File
|
1998-12-05
|
21KB
|
842 lines
#! /bin/bash
# This is a wrapper script to simulate ipfwadm 2.3a. It ain't pretty,
# but it should work (for valid commands). `-V' is translated to `-W'
# or ignored if a `-W' option is already there, but always warned
# about.
# Paul.Russell@rustcorp.com.au, Nov-1997.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
# Version: 1.0.1: Fixed -t (no longer de-hexizes).
#
# Version: 1.0.2: Fixed undocumented `-a masq'.
# Should be OK now with bash v1.
# If we can't find ip_fwnames, call /sbin/ipfwadm.real
#
if [ -n "$DEBUG_IPFWADM" ]; then IPCHAINS=print_ipchains;
else IPCHAINS=/sbin/ipchains;
fi
PROC_FIREWALL_NAMES="/proc/net/ip_fwnames"
SPECIAL_CHAIN="IpFwAdM!"
START_MARK=10000
barf()
{
echo "$@"
echo
echo If this command worked with the original ipfwadm 2.3, please
echo submit a bug report to \`ipchains@wantree.com.au\'.
echo
echo The best way to do this is to submit the output of \`$0 --version\',
echo the command used to obtain this error, any previous ipfwadm
echo commands, and the output of \`ipchains-save\'.
echo
echo Then try flushing all the rules \`ipchains -F; ipchains -X\',
echo setting the DEBUG_IPFWADM variable \`export DEBUG_IPFWADM=1\' or
echo \`setenv DEBUG_IPFWADM 1\' and rerunning the command\(s\) which
echo caused this error.
exit 1
}
print_ipchains()
{
echo ipchains "$@" 1>&2
/sbin/ipchains "$@"
}
setup_chains()
{
if [ `wc -l < $PROC_FIREWALL_NAMES` != 3 -a -z "$DEBUG_IPFWADM" ]
then
echo You cannot mix the \`ipfwadm\' wrapper with ipchains. 1>&2
echo You must delete all user chains and flush all built-in chains 1>&2
echo if you want to use the \`ipfwadm\' wrapper. 1>&2
exit 1
fi
$IPCHAINS -N acctin
$IPCHAINS -N acctout
$IPCHAINS -N acctboth
$IPCHAINS -N inp
$IPCHAINS -N out
$IPCHAINS -N fwd
# Let all fragments through like the old code used to.
$IPCHAINS -A input -f -j ACCEPT
$IPCHAINS -A output -f -j ACCEPT
$IPCHAINS -A forward -f -j ACCEPT
# Jump to accounting rules. Order of traversal of acct rules
# doesn't matter.
$IPCHAINS -A input -j acctin
$IPCHAINS -A input -j acctboth
$IPCHAINS -A output -j acctout
$IPCHAINS -A output -j acctboth
# Now go to `real' chains.
$IPCHAINS -A input -j inp
$IPCHAINS -A output -j out
$IPCHAINS -A forward -j fwd
# Create dummy chains to mark this as an ipfwadm-emulation firewall.
$IPCHAINS -N $SPECIAL_CHAIN
# Insert min and max mark values.
$IPCHAINS -A $SPECIAL_CHAIN -m $START_MARK
$IPCHAINS -A $SPECIAL_CHAIN -m $(($START_MARK + 1))
}
# SIGH. We use identical marks to indicate which rules are actually
# the same rule (to simulate multiple ports, and -y without -P tcp).
# We start the marks at 1,000,000, so we can insert before them or append
# after them.
# In the accounting chain, marks are unique between the three acct* chains,
# so we can tell ordering.
print_count()
{
count=$(($1))
if let $(($count > 99999))
then
cntkb=$((($count + 500) / 1000))
if let $((cntkb > 9999))
then
cntmb=$((($count + 500000) / 1000000))
printf "%4sM " $cntmb
else
printf "%4sK " $cntkb
fi
else
printf "%5s " $count
fi
}
dump_rule()
{
# ARGS: $LIST_VERBOSE $EXPAND_NUMBERS $BIDIR $SYN_NO_PROTO $SRCPORTS $DSTPTS
# $PCNT $BCNT $TARG $PROTO $FLAGS $TOSA $TOSX $IFNM $NUM $SRCIP $DSTIP $REDIR
# The ipfwadm code looks like: (* = -e only)
# * * * * * * *
# pcnt bcnt kind proto bkyo TOSA TXOR IFNM IFADD SRC DST SPTs -> DPTs REDIR
if [ -n "$1" ]
then
# Packet and byte counts.
if [ -n "$2" ]; then printf "%8u " $7; else print_count $7; fi
if [ -n "$2" ]; then printf "%8u " $8; else print_count $8; fi
fi
# Kind
case "$9" in
in) printf "%-3s " "$9" ;;
out) printf "%-3s " "$9" ;;
i/o) printf "%-3s " "$9" ;;
*) printf "%-5s " "$9" ;;
esac
# Proto
printf "%-5s" "${10}"
if [ -n "$1" ]
then
# Flags
if [ "$3" != 0 ]; then printf "b"; else printf "-"; fi
case "${11}" in
*!y*) printf "k-" ;;
*y*) printf "-y" ;;
*) printf "--" ;;
esac
case "${11}" in
*l*) printf "l " ;;
*) printf "- " ;;
esac
# TOS
printf "${12} ${13} "
# Interface name
printf "%-7.16s " "${14}"
# Interface address
if [ -n "${15}" ]; then printf "%-15s " 0.0.0.0;
else printf "%-15s " any;
fi
fi
# Source and dest.
printf "%-20s " "${16}"
printf "%-20s" "${17}"
# Source Ports.
if [ "${10}" != tcp -a "${10}" != udp -a "${10}" != icmp ]
then
echo " n/a"
return
fi
printf " "
printf "$5" | tr ' ' ','
if [ "${10}" = icmp ]
then
echo
return
fi
# Dest ports.
if [ "$5" != "n/a" ]
then
printf " -> "
printf "$6" | tr ' ' ','
fi
# redirect ports.
if [ "$9" = "acc/r" ]
then
printf " => %s" "${18}"
fi
echo
}
get_policy() # CHAIN
{
case "`ipchains -L $1 | head -1`" in
*ACCEPT*)
echo accept;;
*MASQ*)
echo accept/masquerade;;
*REJECT*)
echo reject;;
*DENY*)
echo deny;;
*)
barf "Unknown policy for \`$1' - `ipchains -L $1 2>&1`"
esac
}
list_chain() # $CHAIN $LIST_VERBOSE $NUMERIC $EXPAND_NUMBERS
{
# if (!(format & FMT_NOCOUNTS)) {
# if (format & FMT_KILOMEGA) {
# fprintf(fp, FMT("%5s ","%s "), "pkts");
# fprintf(fp, FMT("%5s ","%s "), "bytes");
# } else {
# fprintf(fp, FMT("%8s ","%s "), "pkts");
# fprintf(fp, FMT("%10s ","%s "), "bytes");
# }
# }
case "$1" in
acct*) ;;
inp) printf "IP firewall input rules, default policy: "
get_policy input
;;
out) printf "IP firewall output rules, default policy: "
get_policy output
;;
fwd) printf "IP firewall forward rules, default policy: "
get_policy forward
;;
*) barf "Unknown chain for list_chain - \`$1'"
;;
esac
if [ -n "$2" ]
then
if [ -z "$4" ]
then
printf "%5s " pkts
printf "%5s " bytes
else
printf "%8s " pkts
printf "%10s " bytes
fi
fi
# if (!(format & FMT_NOKIND)) {
# if (chain == CHN_ACCT)
# fprintf(fp, FMT("%-3s ","%s "), "dir");
# else
# fprintf(fp, FMT("%-5s ","%s "), "type");
# }
case "$1" in
acct*) printf "%-3s " dir ;;
*) printf "%-5s " type ;;
esac
# fputs("prot ", fp);
printf "prot "
# if (format & FMT_OPTIONS)
# fputs("opt ", fp);
# if (format & FMT_TOS)
# fputs("tosa tosx ", fp);
# if (format & FMT_VIA) {
# fprintf(fp, FMT("%-7s ","(%s "), "ifname");
# fprintf(fp, FMT("%-15s ","%s) "), "ifaddress");
# }
if [ -n "$2" ]
then
printf "opt tosa tosx %-7s %-15s " ifname ifaddress
fi
# fprintf(fp, FMT("%-20s ","%s "), "source");
# fprintf(fp, FMT("%-20s ","%s "), "destination");
# fputs("ports\n", fp);
# }
printf "%-20s %-20s ports" source destination
echo
case "$1" in
acct*) shift;
(list_chain_real acctin "$@" "1"
list_chain_real acctout "$@" "1"
list_chain_real acctboth "$@" "1") | sort -n | cut -c11-;;
*) list_chain_real "$@" ;;
esac
}
list_chain_real() # $CHAIN $LIST_VERBOSE $NUMERIC $EXPAND_NUMBERS $PREPEND_MARK
{
CHAIN="$1"
LIST_VERBOSE="$2"
NUMERIC="$3"
EXPAND_NUMBERS="$4"
PREPEND_MARK="$5"
# The ipfwadm code looks like: (* = -e only)
# * * * * * * *
# pcnt bcnt kind proto bkyo TOSA TXOR IFNM IFADD SRC DST SPTs -> DPTs REDIR
#
# The ipchains code looks like: (* = -v only)
# * * * * * * *
# pcnt bcnt targ proto !yfl TOSA TXOR IFNM MARK SRC DST SPTs -> DPTs REDIR
LAST_MARK=xxx
BIDIR=0
SYN_NO_PROTO=0
SRCPORTS=""
DSTPORTS=""
[ -z "$NUMERIC" ] || NUMERIC="-n"
$IPCHAINS -L $CHAIN -v -x $NUMERIC | tail +3 |
while true
do
if ! read PCNT BCNT TARG PROTO FLAGS TOSA TOSX IFNM MARK SRCIP DSTIP SRCPTS IGN1 DSTPTS REDIR
then
# Dump last rule.
if [ "$LAST_MARK" != "xxx" ]
then
[ -z "$PREPEND_MARK" ] || printf "%-10s " "$LAST_MARK"
dump_rule "$LIST_VERBOSE" "$EXPAND_NUMBERS" $BIDIR $SYN_NO_PROTO "$SRCPORTS" "$DSTPORTS" $LAST_PCNT $LAST_BCNT $LAST_TARG $LAST_PROTO $LAST_FLAGS $LAST_TOSA $LAST_TOSX "$LAST_IFNM" "$NUMERIC" $LAST_SRCIP $LAST_DSTIP "$LAST_REDIR"
fi
return
fi
[ -z "$DEBUG_IPFWADM" ] || echo RULE is "$PCNT $BCNT $TARG $PROTO $FLAGS $TOSA $TOSX "$IFNM" $MARK $SRCIP $DSTIP $SRCPTS $IGN1 $DSTPTS $REDIR" 1>&2
if [ "$LAST_MARK" = "$MARK" ]
then
# Fold rules back together.
# We combine for any of the following reasons:
# -k or -y used with no protocol: first rule has proto TCP and 'y'.
# -b used: SRC & DST reversed.
# Multiple ports: all the same but for port.
# Worst cases:
# ipfwadm -I -a accept -b -P tcp -S 0/0 1 4 -D 1/1 5 9
# => pcnt bcnt targ proto !yfl TOSA TXOR IFNM MARK SRC DST SPTs -> DPTs REDIR
# ? ? ? TCP ? ? ? ? ? 0/0 1/1 1 5
# ? ? ? TCP ? ? ? ? ? 1/1 0/0 5 1
# ? ? ? TCP ? ? ? ? ? 0/0 1/1 1 9
# ? ? ? TCP ? ? ? ? ? 1/1 0/0 9 1
# ? ? ? TCP ? ? ? ? ? 0/0 1/1 4 5
# ? ? ? TCP ? ? ? ? ? 1/1 0/0 5 4
# ? ? ? TCP ? ? ? ? ? 0/0 1/1 4 9
# ? ? ? TCP ? ? ? ? ? 1/1 0/0 9 4
#
# ipfwadm -I -a accept -b -y -S 0/0 -D 1/1
# => pcnt bcnt targ proto !yfl TOSA TXOR IFNM MARK SRC DST SPTs -> DPTs REDIR
# ? ? ? TCP ?y?? ? ? ? ? 0/0 1/1
# ? ? ? TCP ?y?? ? ? ? ? 1/1 0/0
# ? ? ? ANY ?-?? ? ? ? ? 0/0 1/1
# ? ? ? ANY ?-?? ? ? ? ? 1/1 0/0
# if [ -n "$DEBUG_IPFWADM" ]
# then
# echo LAST_PROTO = \`"$LAST_PROTO"\'
# echo PROTO = \`"$PROTO"\'
# echo LAST_SRCIP = \`"$LAST_SRCIP"\'
# echo DSTIP = \`"$DSTIP"\'
# echo LAST_DSTIP = \`"$LAST_DSTIP"\'
# echo SRCIP = \`"$SRCIP"\'
# echo LAST_SRCPTS = \`"$LAST_SRCPTS"\'
# echo DSTPTS = \`"$DSTPTS"\'
# echo LAST_DSTPTS = \`"$LAST_DSTPTS"\'
# echo SRCPTS = \`"$SRCPTS"\'
# fi
if [ "$LAST_PROTO" = \!tcp -a "$PROTO" = tcp ]
then
[ -n "$DEBUG_IPFWADM" ] && echo "Found SYN rule."
SYN_NO_PROTO=1
PCNT=$(($LAST_PCNT + $PCNT))
BCNT=$(($LAST_BCNT + $BCNT))
PROTO="all"
elif [ "$LAST_SRCIP" = "$DSTIP" -a "$LAST_DSTIP" = "$SRCIP" -a "$LAST_SRCPTS" = "$DSTPTS" -a "$LAST_DSTPTS" = "$SRCPTS" ]
then
[ -n "$DEBUG_IPFWADM" ] && echo "Found bidir rule."
BIDIR=1
LAST_PCNT=$(($LAST_PCNT + $PCNT))
LAST_BCNT=$(($LAST_BCNT + $BCNT))
# Don't transfer this rule to LAST_ vars - effectively ignore.
continue;
else
[ -n "$DEBUG_IPFWADM" ] && echo "Found port rule."
# For n source ports and m dest ports, there will be
# n x m rules. So, we add to SRCPORTS when we see a new
# SRCPTS, but only add to DSTPORTS for the first SRCPORTS.
if [ "$SRCPTS" != "$LAST_SRCPTS" ]
then
SRCPORTS="$SRCPORTS $SRCPTS"
fi
if [ "$SRCPORTS" = "$SRCPTS" ]
then
DSTPORTS="$DSTPORTS $DSTPTS"
fi
PCNT=$(($LAST_PCNT + $PCNT))
BCNT=$(($LAST_BCNT + $BCNT))
fi
else
# Dump last rule.
if [ "$LAST_MARK" != "xxx" ]
then
[ -z "$PREPEND_MARK" ] || printf "%-10s " "$LAST_MARK"
dump_rule "$LIST_VERBOSE" "$EXPAND_NUMBERS" $BIDIR $SYN_NO_PROTO "$SRCPORTS" "$DSTPORTS" $LAST_PCNT $LAST_BCNT $LAST_TARG $LAST_PROTO $LAST_FLAGS $LAST_TOSA $LAST_TOSX "$LAST_IFNM" "$NUMERIC" $LAST_SRCIP $LAST_DSTIP "$LAST_REDIR"
fi
BIDIR=0
SYN_NO_PROTO=0
SRCPORTS="$SRCPTS"
DSTPORTS="$DSTPTS"
fi
# Save for next iteration, in case mark the same.
LAST_PCNT=$PCNT
LAST_BCNT=$BCNT
LAST_PROTO=$PROTO
LAST_FLAGS=$FLAGS
LAST_TOSA=$TOSA
LAST_TOSX=$TOSX
LAST_IFNM="$IFNM"
LAST_MARK=$MARK
LAST_SRCIP=$SRCIP
LAST_DSTIP=$DSTIP
LAST_REDIR="$REDIR"
LAST_SRCPTS="$SRCPTS"
LAST_DSTPTS="$DSTPTS"
case "$CHAIN" in
acctin) LAST_TARG=in ;;
acctout) LAST_TARG=out ;;
acctboth) LAST_TART=i/o ;;
*)
case "$TARG" in
REDIRECT) LAST_TARG="acc/r" ;;
MASQ) LAST_TARG="acc/m" ;;
ACCEPT) LAST_TARG="acc" ;;
REJECT) LAST_TARG="rej" ;;
DENY) LAST_TARG="deny" ;;
*) barf Unknown target \`"$TARG"\'. ;;
esac
;;
esac
done
}
############################################################################
if [ ! -f $PROC_FIREWALL_NAMES ]
then
if [ -f /proc/net/ip_input -a -x /sbin/ipfwadm.real ]
then
# Old kernel. Let's play nice.
/sbin/ipfwadm.real "$@"; exit
fi
echo "Generic IP Firewall Chains not in this kernel" 1>&2
exit 1
fi
while [ $# != 0 ]
do
case "$1" in
-A)
case x"$2" in
x-*) CHAIN=acctboth ;;
xboth) CHAIN=acctboth; shift ;;
xin) CHAIN=acctin; shift ;;
xout) CHAIN=acctout; shift ;;
x) CHAIN=acctboth ;;
*) barf Unknown option \`"$2"\' ;;
esac
;;
-I)
CHAIN=inp
;;
-O)
CHAIN=out
;;
-F)
CHAIN=fwd
;;
-M)
MASQ_MODE=1
;;
-a)
COMMAND=-A
case x"$2" in
x-*) TARGET="" ;;
x) TARGET="" ;;
xr*) TARGET=REJECT; shift ;;
xd*) TARGET=DENY; shift ;;
xa*) TARGET=ACCEPT; shift ;;
xm*) TARGET=ACCEPT; MASQ=1; shift ;;
*) barf Unknown policy for append: \`"$2"\' ;;
esac
;;
-i)
COMMAND="-I "
case x"$2" in
x-*) TARGET="" ;;
x) TARGET="" ;;
xr*) TARGET=REJECT; shift ;;
xd*) TARGET=DENY; shift ;;
xa*) TARGET=ACCEPT; shift ;;
*) barf Unknown policy for insert: \`"$2"\' ;;
esac
;;
-d)
COMMAND=-D
case x"$2" in
x-*) TARGET="" ;;
x) TARGET="" ;;
xr*) TARGET=REJECT; shift ;;
xd*) TARGET=DENY; shift ;;
xa*) TARGET=ACCEPT; shift ;;
*) barf Unknown policy for delete: \`"$2"\' ;;
esac
;;
-l)
LIST=1
;;
-z)
COMMAND=-Z
;;
-f)
COMMAND=-F
;;
-p)
COMMAND=-P
case "$2" in
r*) TARGET=REJECT; shift ;;
d*) TARGET=DENY; shift ;;
a*) TARGET=ACCEPT; shift ;;
*) barf Unknown policy for -p: \`"$2"\' ;;
esac
;;
-s)
COMMAND=-S
OPTIONS="$2 $3 $4"
shift 3
;;
-c)
COMMAND=-C
;;
-h)
print_help
;;
-P)
PROTOCOL="-p $2"
shift
;;
-S)
SRC_OPTIONS="-s $2"
shift
while true
do
case x"$2" in
x) break ;;
x-*) break ;;
x?*) SRC_PORTS="$2 $SRC_PORTS" ;;
esac
shift
done
;;
-D)
DST_OPTIONS="-d $2"
shift
while true
do
case x"$2" in
x) break ;;
x-*) break ;;
x?*) DST_PORTS="$2 $DST_PORTS" ;;
esac
shift
done
;;
-V)
VIA_ADDR="$2"
shift
;;
-W)
INTERFACE="$2"
OPTIONS="$OPTIONS -i $2"
shift
;;
-b)
OPTIONS="$OPTIONS -b"
;;
-e)
LIST_VERBOSE=1
;;
-k)
TCPSYN="! -y"
;;
-m)
MASQ=1
;;
-n)
NUMERIC=1
;;
-o)
OPTIONS="$OPTIONS -l"
;;
-r)
case x"$2" in
x-*) REDIR=0 ;;
x) REDIR=0 ;;
x?*) REDIR="$2"; shift ;;
esac
;;
-t)
TOSAND=$(($2 | 0x01))
TOSXOR=$(($3 & 0xFE))
OPTIONS="$OPTIONS -t "`printf "0x%02x 0x%02x" $TOSAND $TOSXOR`
shift 2
;;
-v)
OPTIONS="$OPTIONS -v"
;;
-x)
EXPAND_NUMBERS=1;
;;
-y)
TCPSYN="-y"
;;
--version)
echo "ipfwadm wrapper version 1.0.2"
exit 0
;;
*) barf Unexpected argument \`"$1"\'.
;;
esac
shift
done
# Variables to worry about:
# $CHAIN - actual chain to work on.
# X$MASQ_MODE - set if -M given.
# X$COMMAND - set if this is a simple command conversion.
# X$TARGET - set for COMMAND of -A, -I, -D or -P (but see REDIR and MASQ).
# X$LIST - set if they want a list.
# X$NUMERIC - list with -n.
# X$LIST_VERBOSE - list all info.
# X$EXPAND_NUMBERS - list full numbers.
# X$OPTIONS - miscellaneous easy-to-convert options.
# X$SRC_OPTIONS - set if a source address is specified.
# X$SRC_PORTS - space-separated list of specified source ports/ranges.
# X$DST_OPTIONS - set if a dest address is specified.
# X$DST_PORTS - space-separated list of specified dest ports/ranges.
# $VIA_ADDR - an interface address if one is specified.
# $INTERFACE - an interface name if one is specified.
# X$TCPSYN - set if `-k' or `-y' is specified.
# X$MASQ - set if `-m' is specified.
# X$REDIR - set to the port if `-r port' is specified
if [ -n "$MASQ_MODE" ]
then
if [ -n "$LIST" ]
then
$IPCHAINS -M -L $OPTIONS
else
$IPCHAINS $COMMAND $OPTIONS
fi
elif [ -n "$LIST" ]
then
if ! grep -q IpFwAdM! < $PROC_FIREWALL_NAMES
then
echo "Chains are empty. (ie. ipfwadm has not been used on them)." 1>&2
exit 0
fi
# Construct a list.
if [ x$COMMAND = x-Z ]
then
# We have to atomically zero and list a chain. This is
# currently impossible, so we:
# 1) stop all packets on the given chain.
# 2) list the values.
# 3) clear the counters.
# 4) resume on the given chain.
case "$CHAIN" in
acct*)
$IPCHAINS -I 1 input -j DENY
$IPCHAINS -I 1 output -j DENY
;;
inp)
$IPCHAINS -I 1 input -j DENY
;;
out)
$IPCHAINS -I 1 output -j DENY
;;
fwd)
$IPCHAINS -I 1 forward -j DENY
;;
*) barf Unknown chain to stop: \`"$CHAIN"\'.
esac
list_chain $CHAIN "$LIST_VERBOSE" "$NUMERIC" "$EXPAND_NUMBERS"
$IPFWADM -Z $CHAIN
case "$CHAIN" in
acct*)
$IPCHAINS -D 1 input
$IPCHAINS -D 1 output
;;
inp)
$IPCHAINS -D 1 input
;;
out)
$IPCHAINS -D 1 output
;;
fwd)
$IPCHAINS -D 1 forward
;;
*) barf Unknown chain to restart: \`"$CHAIN"\'.
esac
else
list_chain $CHAIN "$LIST_VERBOSE" "$NUMERIC" "$EXPAND_NUMBERS"
fi
elif [ x"$COMMAND" = x"-F" -o x"$COMMAND" = x"-Z" -o x"$COMMAND" = x"-C" ]
then
if ! grep -q IpFwAdM! < $PROC_FIREWALL_NAMES
then
echo "Chains are empty. (ie. ipfwadm has not been used on them)." 1>&2
exit 0
fi
$IPCHAINS $COMMAND $CHAIN $OPTIONS
else
grep -q IpFwAdM! < $PROC_FIREWALL_NAMES || setup_chains
# Figure out what the target should be.
if [ -n "$REDIR" ]
then
TARGET=REDIRECT
elif [ -n "$MASQ" ]
then
TARGET=MASQ
fi
if [ x"$COMMAND" = x"-P" ]
then
case "$CHAIN" in
inp) CHAIN=input ;;
out) CHAIN=output ;;
fwd) CHAIN=forward ;;
*) barf "Illegal chain for -P: \`$CHAIN'" ;;
esac
$IPCHAINS $COMMAND $CHAIN $TARGET $OPTIONS
else
# If they used -V, and not -W, then try to figure out interface
# name. ALWAYS warn about difference.
if [ -n "$VIA_ADDR" ]
then
if [ -n "$INTERFACE" ]
then
echo Warning: \`-V $VIA_ADDR\' option ignored\; using \`-W $INTERFACE\' only.
else
INTERFACE=`ifconfig | awk -v ADDR=$VIA_ADDR '/^[a-z0-9A-Z]/ { IFNAME=$1 } $0 ~ "^[^A-Za-z0-9:]*inet addr:" ADDR { print IFNAME}'`
if [ -z "$INTERFACE" ]
then
echo Can\'t handle -V option: can\'t find interface name for the address \`$VIA_ADDR\'. 1>&2
echo Please replace the -V with the appropriate -W option. 1>&2
exit 1
fi
echo Replacing \`-V $VIA_ADDR\' with \`-W $INTERFACE\'.
OPTIONS="$OPTIONS -i $INTERFACE"
fi
fi
# Insert, append or delete.
case $COMMAND in
# For Insert, get (and decrement) minimal mark #.
-I*) MARK=$(set $($IPCHAINS -L $SPECIAL_CHAIN -v | head -3 | tail -1); echo $9)
$IPCHAINS -R $SPECIAL_CHAIN 1 -m $(($MARK - 1))
MARK="-m $MARK"
;;
# For Append, get (and increment) maximum mark #.
-A) MARK=$(set $($IPCHAINS -L $SPECIAL_CHAIN -v | head -4 | tail -1); echo $9)
$IPCHAINS -R $SPECIAL_CHAIN 2 -m $(($MARK + 1))
MARK="-m $MARK"
;;
esac
# Only care about TCP SYN if -p TCP not specified.
if [ -n "$TCPSYN" ]
then
case "$PROTOCOL" in
*[Tt][Cc][Pp])
OPTIONS="$OPTIONS $PROTOCOL $TCPSYN"
TCPSYN=""
;;
esac
else
OPTIONS="$OPTIONS $PROTOCOL"
fi
# Mangle source port and dest port args.
if [ -z "$SRC_PORTS" ]; then SRC_PORTS="X"; fi
if [ -z "$DST_PORTS" ]; then DST_PORTS="X"; fi
[ -n "$TARGET" ] && TARGET="-j $TARGET"
for SRC in $SRC_PORTS
do
if [ $SRC = "X" ]; then SRC=""; fi
for DST in $DST_PORTS
do
if [ $DST = "X" ]; then DST=""; fi
if [ -n "$TCPSYN" ]
then
$IPCHAINS $COMMAND $CHAIN $SRC $DST $OPTIONS -p ! tcp $TARGET $MARK || barf "ipchains failed!"
$IPCHAINS $COMMAND $CHAIN $SRC $DST $OPTIONS -p tcp $TCPSYN $TARGET $MARK || barf "ipchains failed!"
else
$IPCHAINS $COMMAND $CHAIN $SRC_OPTIONS $SRC $DST_OPTIONS $DST $OPTIONS $TARGET $MARK
fi
done
done
fi
fi