summaryrefslogtreecommitdiffstats
path: root/package/firewall/files/lib/fw.sh
diff options
context:
space:
mode:
Diffstat (limited to 'package/firewall/files/lib/fw.sh')
-rw-r--r--package/firewall/files/lib/fw.sh182
1 files changed, 182 insertions, 0 deletions
diff --git a/package/firewall/files/lib/fw.sh b/package/firewall/files/lib/fw.sh
new file mode 100644
index 000000000..c06e86423
--- /dev/null
+++ b/package/firewall/files/lib/fw.sh
@@ -0,0 +1,182 @@
+# Copyright (C) 2009-2010 OpenWrt.org
+# Copyright (C) 2009 Malte S. Stretz
+
+export FW_4_ERROR=0
+export FW_6_ERROR=0
+export FW_i_ERROR=0
+export FW_e_ERROR=0
+export FW_a_ERROR=0
+
+#TODO: remove this
+[ "${-#*x}" == "$-" ] && {
+ fw() {
+ fw__exec "$@"
+ }
+} || {
+ fw() {
+ local os=$-
+ set +x
+ fw__exec "$@"
+ local rc=$?
+ set -$os
+ return $rc
+ }
+}
+
+fw__exec() { # <action> <family> <table> <chain> <target> <position> { <rules> }
+ local cmd fam tab chn tgt pos
+ local i
+ for i in cmd fam tab chn tgt pos; do
+ if [ "$1" -a "$1" != '{' ]; then
+ eval "$i='$1'"
+ shift
+ else
+ eval "$i=-"
+ fi
+ done
+
+ fw__rc() {
+ export FW_${fam}_ERROR=$1
+ return $1
+ }
+
+ fw__dualip() {
+ fw $cmd 4 $tab $chn $tgt $pos "$@"
+ fw $cmd 6 $tab $chn $tgt $pos "$@"
+ fw__rc $((FW_4_ERROR | FW_6_ERROR))
+ }
+
+ fw__autoip() {
+ local ip4 ip6
+ shift
+ while [ "$1" != '}' ]; do
+ case "$1" in
+ *.*.*.*) ip4=1 ;;
+ *:*) ip6=1 ;;
+ esac
+ shift
+ done
+ shift
+ if [ "${ip4:-4}" == "${ip6:-6}" ]; then
+ echo "fw: can't mix ip4 and ip6" >&2
+ return 1
+ fi
+ local ver=${ip4:+4}${ip6:+6}
+ fam=i
+ fw $cmd ${ver:-i} $tab $chn $tgt $pos "$@"
+ fw__rc $?
+ }
+
+ fw__has() {
+ local tab=${1:-$tab}
+ if [ $tab == '-' ]; then
+ type $app > /dev/null 2> /dev/null
+ fw__rc $(($? & 1))
+ return
+ fi
+ local mod
+ eval "mod=\$FW_${fam}_${tab}"
+ if [ "$mod" ]; then
+ fw__rc $mod
+ return
+ fi
+ case "$fam" in
+ 4) mod=iptable_${tab} ;;
+ 6) mod=ip6table_${tab} ;;
+ *) mod=. ;;
+ esac
+ grep "^${mod} " /proc/modules > /dev/null
+ mod=$?
+ export FW_${fam}_${tab}=$mod
+ fw__rc $mod
+ }
+
+ fw__err() {
+ local err
+ eval "err=\$FW_${fam}_ERROR"
+ fw__rc $err
+ }
+
+ local app=
+ local pol=
+ case "$fam" in
+ 4) app=iptables ;;
+ 6) app=ip6tables ;;
+ i) fw__dualip "$@"; return ;;
+ I) fw__autoip "$@"; return ;;
+ e) app=ebtables ;;
+ a) app=arptables ;;
+ -) fw $cmd i $tab $chn $tgt $pos "$@"; return ;;
+ *) return 254 ;;
+ esac
+ case "$tab" in
+ f) tab=filter ;;
+ m) tab=mangle ;;
+ n) tab=nat ;;
+ r) tab=raw ;;
+ -) tab=filter ;;
+ esac
+ case "$cmd:$chn:$tgt:$pos" in
+ add:*:-:*) cmd=new-chain ;;
+ add:*:*:-) cmd=append ;;
+ add:*:*:$) cmd=append ;;
+ add:*:*:*) cmd=insert ;;
+ del:-:*:*) cmd=delete-chain; fw flush $fam $tab ;;
+ del:*:-:*) cmd=delete-chain; fw flush $fam $tab $chn ;;
+ del:*:*:*) cmd=delete ;;
+ flush:*) ;;
+ policy:*) pol=$tgt; tgt=- ;;
+ has:*) fw__has; return ;;
+ err:*) fw__err; return ;;
+ list:*) cmd="numeric --verbose --$cmd" ;;
+ *) return 254 ;;
+ esac
+ case "$chn" in
+ -) chn= ;;
+ esac
+ case "$tgt" in
+ -) tgt= ;;
+ esac
+ case "$pos" in
+ ^) pos=1 ;;
+ $) pos= ;;
+ -) pos= ;;
+ esac
+
+ if ! fw__has - family || ! fw__has $tab ; then
+ export FW_${fam}_ERROR=0
+ return 0
+ fi
+
+ if [ $# -gt 0 ]; then
+ shift
+ if [ $cmd == del ]; then
+ pos=-
+ fi
+ fi
+ while [ $# -gt 1 ]; do
+ echo -n "$1"
+ echo -ne "\0"
+ shift
+ done | xargs -0 ${FW_TRACE:+-t} \
+ $app --table ${tab} --${cmd} ${chn} ${pol} ${pos} ${tgt:+--jump "$tgt"}
+ fw__rc $?
+}
+
+fw_get_port_range() {
+ local ports=$1
+ local delim=${2:-:}
+ if [ "$3" ]; then
+ fw_get_port_range "${ports}-${3}" $delim
+ return
+ fi
+
+ local first=${ports%-*}
+ local last=${ports#*-}
+ if [ "$first" != "$last" ]; then
+ echo "$first$delim$last"
+ else
+ echo "$first"
+ fi
+}
+