home *** CD-ROM | disk | FTP | other *** search
/ PC World 2000 February / PCWorld_2000-02_cd.bin / live / sbin / ipfwadm-wrapper < prev    next >
Text File  |  1998-12-05  |  21KB  |  842 lines

  1. #! /bin/bash
  2.  
  3. # This is a wrapper script to simulate ipfwadm 2.3a.  It ain't pretty,
  4. # but it should work (for valid commands).  `-V' is translated to `-W'
  5. # or ignored if a `-W' option is already there, but always warned
  6. # about.
  7.  
  8. # Paul.Russell@rustcorp.com.au, Nov-1997.
  9.  
  10. # This program is free software; you can redistribute it and/or modify
  11. # it under the terms of the GNU General Public License as published by
  12. # the Free Software Foundation; either version 2 of the License, or
  13. # (at your option) any later version.
  14. #
  15. # This program is distributed in the hope that it will be useful,
  16. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18. # GNU General Public License for more details.
  19. #
  20. # You should have received a copy of the GNU General Public License
  21. # along with this program; if not, write to the Free Software
  22. # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  23. #
  24. # Version: 1.0.1: Fixed -t (no longer de-hexizes).
  25. #
  26. # Version: 1.0.2: Fixed undocumented `-a masq'.
  27. #                 Should be OK now with bash v1.
  28. #                 If we can't find ip_fwnames, call /sbin/ipfwadm.real
  29. #
  30. if [ -n "$DEBUG_IPFWADM" ]; then IPCHAINS=print_ipchains;
  31. else IPCHAINS=/sbin/ipchains;
  32. fi
  33. PROC_FIREWALL_NAMES="/proc/net/ip_fwnames"
  34. SPECIAL_CHAIN="IpFwAdM!"
  35. START_MARK=10000
  36.  
  37. barf()
  38. {
  39.     echo "$@"
  40.     echo
  41.     echo If this command worked with the original ipfwadm 2.3, please
  42.     echo submit a bug report to \`ipchains@wantree.com.au\'.
  43.     echo
  44.     echo The best way to do this is to submit the output of \`$0 --version\',
  45.     echo the command used to obtain this error, any previous ipfwadm
  46.     echo commands, and the output of \`ipchains-save\'.
  47.     echo
  48.     echo Then try flushing all the rules \`ipchains -F; ipchains -X\',
  49.     echo setting the DEBUG_IPFWADM variable \`export DEBUG_IPFWADM=1\' or
  50.     echo \`setenv DEBUG_IPFWADM 1\' and rerunning the command\(s\) which
  51.     echo caused this error.
  52.     exit 1
  53. }
  54.  
  55. print_ipchains()
  56. {
  57.     echo ipchains "$@" 1>&2
  58.     /sbin/ipchains "$@"
  59. }
  60.  
  61. setup_chains()
  62. {
  63.     if [ `wc -l < $PROC_FIREWALL_NAMES` != 3 -a -z "$DEBUG_IPFWADM" ]
  64.     then
  65.     echo You cannot mix the \`ipfwadm\' wrapper with ipchains. 1>&2
  66.     echo You must delete all user chains and flush all built-in chains 1>&2
  67.     echo if you want to use the \`ipfwadm\' wrapper. 1>&2
  68.     exit 1
  69.     fi
  70.     $IPCHAINS -N acctin
  71.     $IPCHAINS -N acctout
  72.     $IPCHAINS -N acctboth
  73.     $IPCHAINS -N inp
  74.     $IPCHAINS -N out
  75.     $IPCHAINS -N fwd
  76.  
  77.     # Let all fragments through like the old code used to.
  78.     $IPCHAINS -A input -f -j ACCEPT
  79.     $IPCHAINS -A output -f -j ACCEPT
  80.     $IPCHAINS -A forward -f -j ACCEPT
  81.  
  82.     # Jump to accounting rules.  Order of traversal of acct rules
  83.     # doesn't matter.
  84.     $IPCHAINS -A input -j acctin
  85.     $IPCHAINS -A input -j acctboth
  86.     $IPCHAINS -A output -j acctout
  87.     $IPCHAINS -A output -j acctboth
  88.  
  89.     # Now go to `real' chains.
  90.     $IPCHAINS -A input -j inp
  91.     $IPCHAINS -A output -j out
  92.     $IPCHAINS -A forward -j fwd
  93.  
  94.     # Create dummy chains to mark this as an ipfwadm-emulation firewall.
  95.     $IPCHAINS -N $SPECIAL_CHAIN
  96.     # Insert min and max mark values.
  97.     $IPCHAINS -A $SPECIAL_CHAIN -m $START_MARK
  98.     $IPCHAINS -A $SPECIAL_CHAIN -m $(($START_MARK + 1))
  99. }
  100.  
  101. # SIGH.  We use identical marks to indicate which rules are actually
  102. # the same rule (to simulate multiple ports, and -y without -P tcp).
  103.  
  104. # We start the marks at 1,000,000, so we can insert before them or append
  105. # after them.
  106.  
  107. # In the accounting chain, marks are unique between the three acct* chains,
  108. # so we can tell ordering.
  109.  
  110. print_count()
  111. {
  112.     count=$(($1))
  113.     if let $(($count > 99999))
  114.     then
  115.     cntkb=$((($count + 500) / 1000))
  116.     if let $((cntkb > 9999))
  117.     then
  118.         cntmb=$((($count + 500000) / 1000000))
  119.         printf "%4sM " $cntmb
  120.     else
  121.         printf "%4sK " $cntkb
  122.     fi
  123.     else
  124.     printf "%5s " $count
  125.     fi
  126. }
  127.  
  128. dump_rule()
  129. {
  130. # ARGS: $LIST_VERBOSE $EXPAND_NUMBERS $BIDIR $SYN_NO_PROTO $SRCPORTS $DSTPTS
  131. # $PCNT $BCNT $TARG $PROTO $FLAGS $TOSA $TOSX $IFNM $NUM $SRCIP $DSTIP $REDIR
  132.  
  133. # The ipfwadm code looks like: (* = -e only)
  134. # *    *               *    *    *    *    *       
  135. # pcnt bcnt kind proto bkyo TOSA TXOR IFNM IFADD SRC DST SPTs -> DPTs REDIR
  136.     if [ -n "$1" ]
  137.     then
  138.     # Packet and byte counts.
  139.     if [ -n "$2" ]; then printf "%8u " $7; else print_count $7; fi
  140.     if [ -n "$2" ]; then printf "%8u " $8; else print_count $8; fi
  141.     fi
  142.  
  143.     # Kind
  144.     case "$9" in
  145.     in) printf "%-3s " "$9" ;;
  146.     out) printf "%-3s " "$9" ;;
  147.     i/o) printf "%-3s " "$9" ;;
  148.     *) printf "%-5s " "$9" ;;
  149.     esac
  150.  
  151.     # Proto
  152.     printf "%-5s" "${10}"
  153.  
  154.     if [ -n "$1" ]
  155.     then
  156.     # Flags
  157.     if [ "$3" != 0 ]; then printf "b"; else printf "-"; fi
  158.     case "${11}" in
  159.         *!y*) printf "k-" ;;
  160.         *y*) printf "-y" ;;
  161.         *) printf "--" ;;
  162.     esac
  163.     case "${11}" in
  164.         *l*) printf "l " ;;
  165.         *) printf "- " ;;
  166.     esac
  167.  
  168.     # TOS
  169.     printf "${12} ${13} "
  170.  
  171.     # Interface name
  172.     printf "%-7.16s " "${14}"
  173.  
  174.     # Interface address
  175.     if [ -n "${15}" ]; then printf "%-15s " 0.0.0.0;
  176.     else printf "%-15s " any;
  177.     fi
  178.     fi
  179.  
  180.     # Source and dest.
  181.     printf "%-20s " "${16}"
  182.     printf "%-20s" "${17}"
  183.  
  184.     # Source Ports.
  185.     if [ "${10}" != tcp -a "${10}" != udp -a "${10}" != icmp ]
  186.     then
  187.     echo " n/a"
  188.     return
  189.     fi
  190.     printf " "
  191.     printf "$5" | tr ' ' ','
  192.  
  193.     if [ "${10}" = icmp ]
  194.     then
  195.     echo
  196.     return
  197.     fi
  198.  
  199.     # Dest ports.
  200.     if [ "$5" != "n/a" ]
  201.     then
  202.     printf " -> " 
  203.     printf "$6" | tr ' ' ','
  204.     fi
  205.  
  206.     # redirect ports.
  207.     if [ "$9" = "acc/r" ]
  208.     then
  209.     printf " => %s" "${18}"
  210.     fi
  211.     echo
  212. }
  213.  
  214. get_policy() # CHAIN
  215. {
  216.     case "`ipchains -L $1 | head -1`" in
  217.     *ACCEPT*)
  218.     echo accept;;
  219.     *MASQ*)
  220.     echo accept/masquerade;;
  221.     *REJECT*)
  222.     echo reject;;
  223.     *DENY*)
  224.     echo deny;;
  225.     *)
  226.     barf "Unknown policy for \`$1' - `ipchains -L $1 2>&1`"
  227.     esac
  228. }
  229.  
  230. list_chain() # $CHAIN $LIST_VERBOSE $NUMERIC $EXPAND_NUMBERS
  231. {
  232. # if (!(format & FMT_NOCOUNTS)) {
  233. #     if (format & FMT_KILOMEGA) {
  234. #         fprintf(fp, FMT("%5s ","%s "), "pkts");
  235. #         fprintf(fp, FMT("%5s ","%s "), "bytes");
  236. #     } else {
  237. #         fprintf(fp, FMT("%8s ","%s "), "pkts");
  238. #         fprintf(fp, FMT("%10s ","%s "), "bytes");
  239. #     }
  240. # }
  241.     case "$1" in
  242.     acct*) ;;
  243.     inp) printf "IP firewall input rules, default policy: " 
  244.     get_policy input
  245.     ;;
  246.     out) printf "IP firewall output rules, default policy: " 
  247.     get_policy output
  248.     ;;
  249.     fwd) printf "IP firewall forward rules, default policy: " 
  250.     get_policy forward
  251.     ;;
  252.     *) barf "Unknown chain for list_chain - \`$1'"
  253.     ;;
  254.     esac
  255.  
  256.     if [ -n "$2" ]
  257.     then
  258.     if [ -z "$4" ]
  259.     then
  260.         printf "%5s " pkts
  261.         printf "%5s " bytes
  262.     else
  263.         printf "%8s " pkts
  264.         printf "%10s " bytes
  265.     fi
  266.     fi
  267.  
  268. # if (!(format & FMT_NOKIND)) {
  269. #     if (chain == CHN_ACCT)
  270. #         fprintf(fp, FMT("%-3s ","%s "), "dir");
  271. #     else
  272. #         fprintf(fp, FMT("%-5s ","%s "), "type");
  273. # }
  274.     case "$1" in
  275.     acct*) printf "%-3s " dir ;;
  276.     *) printf "%-5s " type ;;
  277.     esac
  278.  
  279. # fputs("prot ", fp);
  280.     printf "prot "
  281.  
  282. # if (format & FMT_OPTIONS)
  283. #     fputs("opt  ", fp);
  284. # if (format & FMT_TOS)
  285. #     fputs("tosa tosx ", fp);
  286. # if (format & FMT_VIA) {
  287. #     fprintf(fp, FMT("%-7s ","(%s "), "ifname");
  288. #     fprintf(fp, FMT("%-15s ","%s) "), "ifaddress");
  289. # }
  290.     if [ -n "$2" ]
  291.     then
  292.     printf "opt  tosa tosx %-7s %-15s " ifname ifaddress
  293.     fi
  294.  
  295. # fprintf(fp, FMT("%-20s ","%s "), "source");
  296. # fprintf(fp, FMT("%-20s ","%s "), "destination");
  297. # fputs("ports\n", fp);
  298. # }
  299.     printf "%-20s %-20s ports" source destination
  300.     echo
  301.  
  302.     case "$1" in
  303.     acct*) shift;
  304.         (list_chain_real acctin "$@" "1"
  305.          list_chain_real acctout "$@" "1" 
  306.          list_chain_real acctboth "$@" "1") | sort -n | cut -c11-;;
  307.     *) list_chain_real "$@" ;;
  308.     esac
  309. }
  310.  
  311. list_chain_real() # $CHAIN $LIST_VERBOSE $NUMERIC $EXPAND_NUMBERS $PREPEND_MARK
  312. {
  313.     CHAIN="$1"
  314.     LIST_VERBOSE="$2"
  315.     NUMERIC="$3"
  316.     EXPAND_NUMBERS="$4"
  317.     PREPEND_MARK="$5"
  318.  
  319.     # The ipfwadm code looks like: (* = -e only)
  320.     # *    *               *    *    *    *    *       
  321.     # pcnt bcnt kind proto bkyo TOSA TXOR IFNM IFADD SRC DST SPTs -> DPTs REDIR
  322.     #
  323.     # The ipchains code looks like: (* = -v only)
  324.     # *    *               *    *    *    *    *       
  325.     # pcnt bcnt targ proto !yfl TOSA TXOR IFNM MARK SRC DST SPTs -> DPTs REDIR
  326.     LAST_MARK=xxx
  327.  
  328.     BIDIR=0
  329.     SYN_NO_PROTO=0
  330.     SRCPORTS=""
  331.     DSTPORTS=""
  332.  
  333.     [ -z "$NUMERIC" ] || NUMERIC="-n"
  334.     $IPCHAINS -L $CHAIN -v -x $NUMERIC | tail +3 |
  335.     while true
  336.     do
  337.     if ! read PCNT BCNT TARG PROTO FLAGS TOSA TOSX IFNM MARK SRCIP DSTIP SRCPTS IGN1 DSTPTS REDIR
  338.     then
  339.         # Dump last rule.
  340.         if [ "$LAST_MARK" != "xxx" ] 
  341.         then
  342.         [ -z "$PREPEND_MARK" ] || printf "%-10s " "$LAST_MARK"
  343.         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"
  344.         fi
  345.         return
  346.     fi
  347.     [ -z "$DEBUG_IPFWADM" ] || echo RULE is "$PCNT $BCNT $TARG $PROTO $FLAGS $TOSA $TOSX "$IFNM" $MARK $SRCIP $DSTIP $SRCPTS $IGN1 $DSTPTS $REDIR" 1>&2
  348.  
  349.     if [ "$LAST_MARK" = "$MARK" ]
  350.     then
  351. # Fold rules back together.
  352.     
  353. # We combine for any of the following reasons:
  354. # -k or -y used with no protocol: first rule has proto TCP and 'y'.
  355. # -b used: SRC & DST reversed.
  356. # Multiple ports: all the same but for port.
  357.  
  358. # Worst cases:
  359. # ipfwadm -I -a accept -b -P tcp -S 0/0 1 4 -D 1/1 5 9
  360. # => pcnt bcnt targ proto !yfl TOSA TXOR IFNM MARK SRC DST SPTs -> DPTs REDIR
  361. #    ?    ?    ?    TCP   ?    ?    ?    ?    ?    0/0 1/1 1       5
  362. #    ?    ?    ?    TCP   ?    ?    ?    ?    ?    1/1 0/0 5       1
  363. #    ?    ?    ?    TCP   ?    ?    ?    ?    ?    0/0 1/1 1       9
  364. #    ?    ?    ?    TCP   ?    ?    ?    ?    ?    1/1 0/0 9       1
  365. #    ?    ?    ?    TCP   ?    ?    ?    ?    ?    0/0 1/1 4       5
  366. #    ?    ?    ?    TCP   ?    ?    ?    ?    ?    1/1 0/0 5       4
  367. #    ?    ?    ?    TCP   ?    ?    ?    ?    ?    0/0 1/1 4       9
  368. #    ?    ?    ?    TCP   ?    ?    ?    ?    ?    1/1 0/0 9       4
  369. #
  370. # ipfwadm -I -a accept -b -y -S 0/0 -D 1/1
  371. # => pcnt bcnt targ proto !yfl TOSA TXOR IFNM MARK SRC DST SPTs -> DPTs REDIR
  372. #    ?    ?    ?    TCP   ?y?? ?    ?    ?    ?    0/0 1/1
  373. #    ?    ?    ?    TCP   ?y?? ?    ?    ?    ?    1/1 0/0
  374. #    ?    ?    ?    ANY   ?-?? ?    ?    ?    ?    0/0 1/1
  375. #    ?    ?    ?    ANY   ?-?? ?    ?    ?    ?    1/1 0/0
  376. #         if [ -n "$DEBUG_IPFWADM" ]
  377. #         then
  378. #        echo LAST_PROTO = \`"$LAST_PROTO"\'
  379. #        echo PROTO = \`"$PROTO"\'
  380. #         echo LAST_SRCIP = \`"$LAST_SRCIP"\'
  381. #         echo DSTIP = \`"$DSTIP"\'
  382. #         echo LAST_DSTIP = \`"$LAST_DSTIP"\'
  383. #         echo SRCIP = \`"$SRCIP"\'
  384. #         echo LAST_SRCPTS = \`"$LAST_SRCPTS"\'
  385. #         echo DSTPTS = \`"$DSTPTS"\'
  386. #         echo LAST_DSTPTS = \`"$LAST_DSTPTS"\'
  387. #         echo SRCPTS = \`"$SRCPTS"\'
  388. #         fi
  389.         if [ "$LAST_PROTO" = \!tcp -a "$PROTO" = tcp ]
  390.         then
  391.         [ -n "$DEBUG_IPFWADM" ] && echo "Found SYN rule."
  392.         SYN_NO_PROTO=1
  393.         PCNT=$(($LAST_PCNT + $PCNT))
  394.         BCNT=$(($LAST_BCNT + $BCNT))
  395.         PROTO="all"
  396.         elif [ "$LAST_SRCIP" = "$DSTIP" -a "$LAST_DSTIP" = "$SRCIP" -a "$LAST_SRCPTS" = "$DSTPTS" -a "$LAST_DSTPTS" = "$SRCPTS" ]
  397.         then
  398.         [ -n "$DEBUG_IPFWADM" ] && echo "Found bidir rule."
  399.         BIDIR=1
  400.         LAST_PCNT=$(($LAST_PCNT + $PCNT))
  401.         LAST_BCNT=$(($LAST_BCNT + $BCNT))
  402.         # Don't transfer this rule to LAST_ vars - effectively ignore.
  403.         continue;
  404.         else
  405.         [ -n "$DEBUG_IPFWADM" ] && echo "Found port rule."
  406.         # For n source ports and m dest ports, there will be
  407.         # n x m rules.  So, we add to SRCPORTS when we see a new
  408.         # SRCPTS, but only add to DSTPORTS for the first SRCPORTS.
  409.         if [ "$SRCPTS" != "$LAST_SRCPTS" ]
  410.         then
  411.             SRCPORTS="$SRCPORTS $SRCPTS"
  412.         fi
  413.         if [ "$SRCPORTS" = "$SRCPTS" ]
  414.         then
  415.             DSTPORTS="$DSTPORTS $DSTPTS"
  416.         fi
  417.         PCNT=$(($LAST_PCNT + $PCNT))
  418.         BCNT=$(($LAST_BCNT + $BCNT))
  419.         fi
  420.     else
  421.         # Dump last rule.
  422.         if [ "$LAST_MARK" != "xxx" ]
  423.         then
  424.         [ -z "$PREPEND_MARK" ] || printf "%-10s " "$LAST_MARK"
  425.         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"
  426.         fi
  427.  
  428.         BIDIR=0
  429.         SYN_NO_PROTO=0
  430.         SRCPORTS="$SRCPTS"
  431.         DSTPORTS="$DSTPTS"
  432.     fi
  433.  
  434.     # Save for next iteration, in case mark the same.
  435.     LAST_PCNT=$PCNT
  436.     LAST_BCNT=$BCNT
  437.     LAST_PROTO=$PROTO
  438.     LAST_FLAGS=$FLAGS
  439.     LAST_TOSA=$TOSA
  440.     LAST_TOSX=$TOSX
  441.     LAST_IFNM="$IFNM"
  442.     LAST_MARK=$MARK
  443.     LAST_SRCIP=$SRCIP
  444.     LAST_DSTIP=$DSTIP
  445.     LAST_REDIR="$REDIR"
  446.     LAST_SRCPTS="$SRCPTS"
  447.     LAST_DSTPTS="$DSTPTS"
  448.     case "$CHAIN" in
  449.     acctin) LAST_TARG=in ;;
  450.     acctout) LAST_TARG=out ;;
  451.     acctboth) LAST_TART=i/o ;;
  452.     *)
  453.         case "$TARG" in
  454.         REDIRECT) LAST_TARG="acc/r" ;;
  455.         MASQ) LAST_TARG="acc/m" ;;
  456.         ACCEPT) LAST_TARG="acc" ;;
  457.         REJECT) LAST_TARG="rej" ;;
  458.         DENY) LAST_TARG="deny" ;;
  459.         *) barf Unknown target \`"$TARG"\'. ;;
  460.         esac
  461.         ;;
  462.     esac
  463.     done
  464. }
  465.  
  466. ############################################################################
  467.  
  468. if [ ! -f $PROC_FIREWALL_NAMES ]
  469. then
  470.     if [ -f /proc/net/ip_input -a -x /sbin/ipfwadm.real ]
  471.     then
  472.     # Old kernel.  Let's play nice.
  473.     /sbin/ipfwadm.real "$@"; exit
  474.     fi
  475.     echo "Generic IP Firewall Chains not in this kernel" 1>&2
  476.     exit 1
  477. fi
  478.  
  479. while [ $# != 0 ]
  480. do
  481.     case "$1" in
  482.     -A)
  483.     case x"$2" in
  484.     x-*) CHAIN=acctboth ;;
  485.     xboth) CHAIN=acctboth; shift ;;
  486.     xin) CHAIN=acctin; shift ;;
  487.     xout) CHAIN=acctout; shift ;;
  488.     x) CHAIN=acctboth ;;
  489.      *) barf Unknown option \`"$2"\' ;;
  490.     esac
  491.     ;;
  492.     -I)
  493.     CHAIN=inp
  494.     ;;
  495.     -O)
  496.     CHAIN=out
  497.     ;;
  498.     -F)
  499.     CHAIN=fwd
  500.     ;;
  501.     -M)
  502.     MASQ_MODE=1
  503.     ;;
  504.     -a)
  505.     COMMAND=-A
  506.     case x"$2" in
  507.     x-*) TARGET="" ;;
  508.     x) TARGET="" ;;
  509.     xr*) TARGET=REJECT; shift ;;
  510.     xd*) TARGET=DENY; shift ;;
  511.     xa*) TARGET=ACCEPT; shift ;;
  512.     xm*) TARGET=ACCEPT; MASQ=1; shift ;;
  513.      *) barf Unknown policy for append: \`"$2"\' ;;
  514.     esac
  515.     ;;
  516.     -i)
  517.     COMMAND="-I "
  518.     case x"$2" in
  519.     x-*) TARGET="" ;;
  520.     x) TARGET="" ;;
  521.     xr*) TARGET=REJECT; shift ;;
  522.     xd*) TARGET=DENY; shift ;;
  523.     xa*) TARGET=ACCEPT; shift ;;
  524.      *) barf Unknown policy for insert: \`"$2"\' ;;
  525.     esac
  526.     ;;
  527.     -d)
  528.     COMMAND=-D
  529.     case x"$2" in
  530.     x-*) TARGET="" ;;
  531.     x) TARGET="" ;;
  532.     xr*) TARGET=REJECT; shift ;;
  533.     xd*) TARGET=DENY; shift ;;
  534.     xa*) TARGET=ACCEPT; shift ;;
  535.      *) barf Unknown policy for delete: \`"$2"\' ;;
  536.     esac
  537.     ;;
  538.     -l)
  539.     LIST=1
  540.     ;;
  541.     -z)
  542.     COMMAND=-Z
  543.     ;;
  544.     -f)
  545.     COMMAND=-F
  546.     ;;
  547.     -p)
  548.     COMMAND=-P
  549.     case "$2" in
  550.     r*) TARGET=REJECT; shift ;;
  551.     d*) TARGET=DENY; shift ;;
  552.     a*) TARGET=ACCEPT; shift ;;
  553.      *) barf Unknown policy for -p: \`"$2"\' ;;
  554.     esac
  555.     ;;
  556.  
  557.     -s)
  558.     COMMAND=-S
  559.     OPTIONS="$2 $3 $4"
  560.     shift 3
  561.     ;;
  562.     -c)
  563.     COMMAND=-C
  564.     ;;
  565.     -h)
  566.     print_help
  567.     ;;
  568.     -P)
  569.     PROTOCOL="-p $2"
  570.     shift
  571.     ;;
  572.     -S)
  573.     SRC_OPTIONS="-s $2"
  574.     shift
  575.     while true
  576.     do
  577.         case x"$2" in
  578.         x) break ;;
  579.         x-*) break ;;
  580.         x?*) SRC_PORTS="$2 $SRC_PORTS" ;;
  581.         esac
  582.         shift
  583.     done
  584.     ;;
  585.     -D)
  586.     DST_OPTIONS="-d $2"
  587.     shift
  588.     while true
  589.     do
  590.         case x"$2" in
  591.         x) break ;;
  592.         x-*) break ;;
  593.         x?*) DST_PORTS="$2 $DST_PORTS" ;;
  594.         esac
  595.         shift
  596.     done
  597.     ;;
  598.     -V)
  599.     VIA_ADDR="$2"
  600.     shift
  601.     ;;
  602.     -W)
  603.     INTERFACE="$2"
  604.     OPTIONS="$OPTIONS -i $2"
  605.     shift
  606.     ;;
  607.     -b)
  608.     OPTIONS="$OPTIONS -b"
  609.     ;;
  610.     -e)
  611.     LIST_VERBOSE=1
  612.     ;;
  613.     -k)
  614.     TCPSYN="! -y"
  615.     ;;
  616.     -m)
  617.     MASQ=1
  618.     ;;
  619.     -n)
  620.     NUMERIC=1
  621.     ;;
  622.     -o)
  623.     OPTIONS="$OPTIONS -l"
  624.     ;;
  625.     -r)
  626.     case x"$2" in
  627.         x-*) REDIR=0 ;;
  628.         x) REDIR=0 ;;
  629.         x?*) REDIR="$2"; shift ;;
  630.     esac
  631.     ;;
  632.     -t)
  633.     TOSAND=$(($2 | 0x01))
  634.     TOSXOR=$(($3 & 0xFE))
  635.     OPTIONS="$OPTIONS -t "`printf "0x%02x 0x%02x" $TOSAND $TOSXOR`
  636.     shift 2
  637.     ;;
  638.     -v)
  639.     OPTIONS="$OPTIONS -v"
  640.     ;;
  641.     -x)
  642.     EXPAND_NUMBERS=1;
  643.     ;;
  644.     -y)
  645.     TCPSYN="-y"
  646.     ;;
  647.  
  648.     --version)
  649.     echo "ipfwadm wrapper version 1.0.2"
  650.     exit 0
  651.     ;;
  652.  
  653.     *) barf Unexpected argument \`"$1"\'.
  654.     ;;
  655.     esac
  656.     shift
  657. done
  658.  
  659. # Variables to worry about:
  660. #  $CHAIN - actual chain to work on.
  661. # X$MASQ_MODE - set if -M given.
  662. # X$COMMAND - set if this is a simple command conversion.
  663. # X$TARGET - set for COMMAND of -A, -I, -D or -P (but see REDIR and MASQ).
  664. # X$LIST - set if they want a list.
  665. # X$NUMERIC - list with -n.
  666. # X$LIST_VERBOSE - list all info.
  667. # X$EXPAND_NUMBERS - list full numbers.
  668. # X$OPTIONS - miscellaneous easy-to-convert options.
  669. # X$SRC_OPTIONS - set if a source address is specified.
  670. # X$SRC_PORTS - space-separated list of specified source ports/ranges.
  671. # X$DST_OPTIONS - set if a dest address is specified.
  672. # X$DST_PORTS - space-separated list of specified dest ports/ranges.
  673. #  $VIA_ADDR - an interface address if one is specified.
  674. #  $INTERFACE - an interface name if one is specified.
  675. # X$TCPSYN - set if `-k' or `-y' is specified.
  676. # X$MASQ - set if `-m' is specified.
  677. # X$REDIR - set to the port if `-r port' is specified
  678.  
  679. if [ -n "$MASQ_MODE" ]
  680. then
  681.     if [ -n "$LIST" ]
  682.     then
  683.     $IPCHAINS -M -L $OPTIONS
  684.     else
  685.     $IPCHAINS $COMMAND $OPTIONS
  686.     fi
  687. elif [ -n "$LIST" ]
  688. then
  689.     if ! grep -q IpFwAdM! < $PROC_FIREWALL_NAMES
  690.     then
  691.     echo "Chains are empty. (ie. ipfwadm has not been used on them)." 1>&2
  692.     exit 0
  693.     fi
  694.     # Construct a list.
  695.     if [ x$COMMAND = x-Z ]
  696.     then
  697.     # We have to atomically zero and list a chain.  This is
  698.     # currently impossible, so we:
  699.     # 1) stop all packets on the given chain. 
  700.     # 2) list the values.
  701.     # 3) clear the counters.
  702.     # 4) resume on the given chain.
  703.     case "$CHAIN" in
  704.         acct*)
  705.         $IPCHAINS -I 1 input -j DENY
  706.         $IPCHAINS -I 1 output -j DENY
  707.         ;;
  708.         inp)
  709.         $IPCHAINS -I 1 input -j DENY
  710.         ;;
  711.         out)
  712.         $IPCHAINS -I 1 output -j DENY
  713.         ;;
  714.         fwd)
  715.         $IPCHAINS -I 1 forward -j DENY
  716.         ;;
  717.         *) barf Unknown chain to stop: \`"$CHAIN"\'.
  718.     esac
  719.  
  720.     list_chain $CHAIN "$LIST_VERBOSE" "$NUMERIC" "$EXPAND_NUMBERS"
  721.     $IPFWADM -Z $CHAIN
  722.     
  723.     case "$CHAIN" in
  724.         acct*)
  725.         $IPCHAINS -D 1 input
  726.         $IPCHAINS -D 1 output
  727.         ;;
  728.         inp)
  729.         $IPCHAINS -D 1 input
  730.         ;;
  731.         out)
  732.         $IPCHAINS -D 1 output
  733.         ;;
  734.         fwd)
  735.         $IPCHAINS -D 1 forward
  736.         ;;
  737.         *) barf Unknown chain to restart: \`"$CHAIN"\'.
  738.     esac
  739.     else
  740.     list_chain $CHAIN "$LIST_VERBOSE" "$NUMERIC" "$EXPAND_NUMBERS"
  741.     fi
  742. elif [ x"$COMMAND" = x"-F" -o x"$COMMAND" = x"-Z" -o x"$COMMAND" = x"-C" ]
  743. then
  744.     if ! grep -q IpFwAdM! < $PROC_FIREWALL_NAMES
  745.     then
  746.     echo "Chains are empty. (ie. ipfwadm has not been used on them)." 1>&2
  747.     exit 0
  748.     fi
  749.     $IPCHAINS $COMMAND $CHAIN $OPTIONS
  750. else
  751.     grep -q IpFwAdM! < $PROC_FIREWALL_NAMES || setup_chains
  752.  
  753.     # Figure out what the target should be.
  754.     if [ -n "$REDIR" ]
  755.     then
  756.     TARGET=REDIRECT
  757.     elif [ -n "$MASQ" ]
  758.     then
  759.     TARGET=MASQ
  760.     fi
  761.  
  762.     if [ x"$COMMAND" = x"-P" ]
  763.     then
  764.     case "$CHAIN" in
  765.     inp) CHAIN=input ;;
  766.     out) CHAIN=output ;;
  767.     fwd) CHAIN=forward ;;
  768.     *) barf "Illegal chain for -P: \`$CHAIN'" ;;
  769.     esac
  770.     $IPCHAINS $COMMAND $CHAIN $TARGET $OPTIONS
  771.     else
  772.     # If they used -V, and not -W, then try to figure out interface
  773.     # name.  ALWAYS warn about difference.
  774.     if [ -n "$VIA_ADDR" ]
  775.     then
  776.         if [ -n "$INTERFACE" ]
  777.         then
  778.         echo Warning: \`-V $VIA_ADDR\' option ignored\; using \`-W $INTERFACE\' only.
  779.         else
  780.         INTERFACE=`ifconfig | awk -v ADDR=$VIA_ADDR '/^[a-z0-9A-Z]/ { IFNAME=$1 } $0 ~ "^[^A-Za-z0-9:]*inet addr:" ADDR { print IFNAME}'`
  781.         if [ -z "$INTERFACE" ]
  782.         then
  783.             echo Can\'t handle -V option: can\'t find interface name for the address \`$VIA_ADDR\'. 1>&2
  784.             echo Please replace the -V with the appropriate -W option. 1>&2
  785.             exit 1
  786.         fi
  787.         echo Replacing \`-V $VIA_ADDR\' with \`-W $INTERFACE\'.
  788.         OPTIONS="$OPTIONS -i $INTERFACE"
  789.         fi
  790.     fi
  791.  
  792.     # Insert, append or delete.
  793.     case $COMMAND in
  794.         # For Insert, get (and decrement) minimal mark #.
  795.         -I*) MARK=$(set $($IPCHAINS -L $SPECIAL_CHAIN -v | head -3 | tail -1); echo $9)
  796.         $IPCHAINS -R $SPECIAL_CHAIN 1 -m $(($MARK - 1))
  797.         MARK="-m $MARK"
  798.         ;;
  799.  
  800.         # For Append, get (and increment) maximum mark #.
  801.         -A) MARK=$(set $($IPCHAINS -L $SPECIAL_CHAIN -v | head -4 | tail -1); echo $9)
  802.         $IPCHAINS -R $SPECIAL_CHAIN 2 -m $(($MARK + 1))
  803.         MARK="-m $MARK"
  804.         ;;
  805.     esac
  806.  
  807.     # Only care about TCP SYN if -p TCP not specified.
  808.     if [ -n "$TCPSYN" ]
  809.     then
  810.         case "$PROTOCOL" in
  811.         *[Tt][Cc][Pp]) 
  812.             OPTIONS="$OPTIONS $PROTOCOL $TCPSYN"
  813.             TCPSYN=""
  814.         ;;
  815.         esac
  816.     else
  817.         OPTIONS="$OPTIONS $PROTOCOL"
  818.     fi
  819.  
  820.     # Mangle source port and dest port args.
  821.     if [ -z "$SRC_PORTS" ]; then SRC_PORTS="X"; fi
  822.     if [ -z "$DST_PORTS" ]; then DST_PORTS="X"; fi
  823.  
  824.     [ -n "$TARGET" ] && TARGET="-j $TARGET"
  825.     for SRC in $SRC_PORTS
  826.     do
  827.         if [ $SRC = "X" ]; then SRC=""; fi
  828.         for DST in $DST_PORTS
  829.         do
  830.         if [ $DST = "X" ]; then DST=""; fi
  831.         if [ -n "$TCPSYN" ]
  832.         then
  833.             $IPCHAINS $COMMAND $CHAIN $SRC $DST $OPTIONS -p ! tcp $TARGET $MARK || barf "ipchains failed!"
  834.             $IPCHAINS $COMMAND $CHAIN $SRC $DST $OPTIONS -p tcp $TCPSYN $TARGET $MARK  || barf "ipchains failed!"
  835.         else
  836.             $IPCHAINS $COMMAND $CHAIN $SRC_OPTIONS $SRC $DST_OPTIONS $DST $OPTIONS $TARGET $MARK
  837.         fi
  838.         done
  839.     done
  840.     fi
  841. fi
  842.