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