"Fossies" - the Fresh Open Source Software Archive

Member "aif-2.1.1/share/arno-iptables-firewall/environment" (16 Sep 2020, 52650 Bytes) of package /linux/privat/aif-2.1.1.tar.gz:


As a special service "Fossies" has tried to format the requested text file into HTML format (style: standard) with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file. See also the latest Fossies "Diffs" side-by-side code changes report for "environment": 2.1.0_vs_2.1.1.

    1 # ------------------------------------------------------------------------------
    2 #                         -= Arno's Iptables Firewall(AIF) =-
    3 #              Single- & multi-homed firewall script with DSL/ADSL support
    4 #
    5 #                           ~ In memory of my dear father ~
    6 #
    7 # (C) Copyright 2001-2020 by Arno van Amersfoort & Lonnie Abelbeck
    8 # Homepage              : https://rocky.eld.leidenuniv.nl/
    9 # Email                 : a r n o v a AT r o c k y DOT e l d DOT l e i d e n u n i v DOT n l
   10 #                         (note: you must remove all spaces and substitute the @ and the .
   11 #                         at the proper locations!)
   12 # ------------------------------------------------------------------------------
   13 # This program is free software; you can redistribute it and/or
   14 # modify it under the terms of the GNU General Public License
   15 # version 2 as published by the Free Software Foundation.
   16 
   17 # This program is distributed in the hope that it will be useful,
   18 # but WITHOUT ANY WARRANTY; without even the implied warranty of
   19 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   20 # GNU General Public License for more details.
   21 
   22 # You should have received a copy of the GNU General Public License
   23 # along with this program; if not, write to the Free Software
   24 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
   25 # ------------------------------------------------------------------------------
   26 
   27 # NOTE: When used in combination with firewall.conf. Load firewall.conf first before calling us!
   28 
   29 # Some predefined variables/macros:
   30 ANYHOST="0/0"
   31 ANYPORT="0:65535"
   32 SEP="~"
   33 SEP2="#"
   34 SEP3="|"
   35 INDENT=""
   36 TAB="$(printf '\t')"
   37 EOL='
   38 '
   39 
   40 # Globals variables:
   41 RULE_WARNING=0
   42 DNS_FAST_FAIL_ONCE=0
   43 
   44 ################################# Functions ####################################
   45 
   46 # Find command path with '/hint/path/command' as the argument
   47 find_command()
   48 {
   49   local cmd IFS
   50 
   51   IFS=' '
   52   for cmd in $*; do
   53     if [ -x "$cmd" ]; then
   54       echo "$cmd"
   55       return 0
   56     fi
   57   done
   58 
   59   which $(basename "$1") 2>/dev/null
   60   return 1
   61 }
   62 
   63 
   64 # Check whether a certain command is available
   65 check_command()
   66 {
   67   local cmd path IFS
   68 
   69   IFS=' '
   70   for cmd in $*; do
   71     case "$cmd" in
   72       /*) path="" ;;
   73       ip|tc|modprobe|sysctl) path="/sbin/" ;;
   74       sed|cat|date|uname) path="/bin/" ;;
   75       ipset) path="/usr/sbin/" ;;
   76       *) path="/usr/bin/" ;;
   77     esac
   78 
   79     if [ -x "$path$cmd" ]; then
   80       return 0
   81     fi
   82 
   83     if [ -n "$(which "$cmd" 2>/dev/null)" ]; then
   84       return 0
   85     fi
   86   done
   87 
   88   return 1
   89 }
   90 
   91 
   92 # Check whether a binary is available and if not, generate an error and stop program execution
   93 check_command_error()
   94 {
   95   local IFS=' '
   96 
   97   if ! check_command "$@"; then
   98     printf "\033[40m\033[1;31mERROR  : Command(s) \"$(echo "$@" |tr ' ' '|')\" is/are not available!\033[0m\n" >&2
   99     printf "\033[40m\033[1;31m         Please investigate. Quitting...\033[0m\n" >&2
  100     echo ""
  101     exit 2
  102   fi
  103 }
  104 
  105 
  106 # Check whether a binary is available and if not, generate a warning but continue program execution
  107 check_command_warning()
  108 {
  109   local retval IFS=' '
  110 
  111   check_command "$@"
  112   retval=$?
  113 
  114   if [ $retval -ne 0 ]; then
  115     printf "\033[40m\033[1;31mWARNING: Command(s) \"$(echo "$@" |tr ' ' '|')\" is/are not available!\033[0m\n" >&2
  116     printf "\033[40m\033[1;31m         Please investigate. This *may* be a problem!\033[0m\n" >&2
  117     echo ""
  118   fi
  119 
  120   return $retval
  121 }
  122 
  123 
  124 # Check if the current kernel is at least a certain version (or newer)
  125 # Arguments: major minor rev (eg. "2 6 25")
  126 # Return   : 0 = kernel is equal or newer, 1 = kernel is older
  127 ######################################################################
  128 kernel_ver_chk()
  129 {
  130   local maj min rev ver ver_maj ver_min ver_rev
  131 
  132   if [ -n "$2" ]; then
  133     maj="$1"
  134     min="$2"
  135     rev="$3"
  136   else
  137     maj=$(echo "$1" |cut -s -d'.' -f1)
  138     min=$(echo "$1" |cut -s -d'.' -f2)
  139     rev=$(echo "$1" |cut -s -d'.' -f3)
  140   fi
  141 
  142   ver=$(uname -r |cut -d'-' -f1)
  143 
  144   ver_maj=$(echo "$ver" |cut -s -d'.' -f1)
  145   if [ $ver_maj -gt $maj ]; then
  146     return 0
  147   elif [ $ver_maj -lt $maj ]; then
  148     return 1
  149   fi
  150 
  151   ver_min=$(echo "$ver" |cut -s -d'.' -f2)
  152   if [ $ver_min -gt $min ]; then
  153     return 0
  154   elif [ $ver_min -lt $min ]; then
  155     return 1
  156   fi
  157 
  158   ver_rev=$(echo "$ver" |cut -s -d'.' -f3)
  159   if [ $ver_rev -gt $rev ]; then
  160     return 0
  161   elif [ $ver_rev -lt $rev ]; then
  162     return 1
  163   fi
  164 
  165   return 0
  166 }
  167 
  168 # nf_conntrack helper assignment
  169 # Example: load_conntrack_helper_module ftp tcp 21
  170 ##
  171 load_conntrack_helper_module()
  172 {
  173   local helper="$1" proto="$2" dport="$3" do_iptables related
  174 
  175   modprobe_multi nf_conntrack_$helper ip_conntrack_$helper
  176   if [ "$NAT" = "1" ]; then
  177     modprobe_multi nf_nat_$helper ip_nat_$helper
  178   fi
  179 
  180   if ip4tables -nL CONNTRACK_HELPER >/dev/null 2>&1; then
  181     case $helper in
  182        ftp) do_iptables="iptables" ; related="-p $proto --dport 1024:" ;;
  183       pptp) do_iptables="ip4tables"; related="" ;;
  184          *) do_iptables="iptables" ; related="" ;;
  185     esac
  186     $do_iptables -A CONNTRACK_HELPER -m conntrack --ctstate RELATED -m helper --helper $helper $related -j ACCEPT
  187     $do_iptables -t raw -A PREROUTING -p $proto --dport $dport -j CT --helper $helper
  188   fi
  189 }
  190 
  191 # Linecount function
  192 lc()
  193 {
  194   wc -l |awk '{ print $1 }'
  195 }
  196 
  197 
  198 note_iptables_error()
  199 {
  200   local arg IFS
  201 
  202   IFS='~'  # expand command-line args using the unique 'tilde' character
  203   for arg in $*; do
  204     if [ "$arg" = "-A" -o "$arg" = "-I" ]; then
  205       return 0
  206     fi
  207   done
  208 
  209   return 1
  210 }
  211 
  212 
  213 ip6tables_icmp_args()
  214 {
  215   local arg args="" action="" tilde="~" IFS
  216 
  217   IFS='~'  # expand command-line args using the unique 'tilde' character
  218   for arg in $*; do
  219     if [ "$action" = "p" ]; then
  220       if [ "$arg" = "icmp" ]; then
  221         arg="icmpv6"
  222       fi
  223       action=""
  224     else
  225       # parse option flags
  226       case $arg in
  227       --icmp-type)
  228         arg="--icmpv6-type"
  229         ;;
  230       -p|--proto)
  231         action="p"
  232         ;;
  233       esac
  234     fi
  235     # build 'tilde' separated command-line
  236     # Note: use $tilde instead of ~ to workaround Busybox 'ash' bug
  237     args="$args${args:+$tilde}$arg"
  238   done
  239   
  240   # return 'tilde' separated command-line
  241   echo "$args"
  242 }
  243 
  244 
  245 iptables()
  246 {
  247   local arg action="" IFS
  248   local src=0 dst=0 table="" proto=""
  249 
  250   if [ "$IPV6_SUPPORT" = "1" ]; then
  251     IFS='~'  # expand command-line args using the unique 'tilde' character
  252     for arg in $*; do
  253       if [ -n "$action" ]; then
  254         case $action in
  255         s)
  256           get_numeric_ip_version "$arg"
  257           src=$?
  258           ;;
  259         d)
  260           get_numeric_ip_version "$arg"
  261           dst=$?
  262           ;;
  263         t)
  264           table="$arg"
  265           ;;
  266         p)
  267           proto="$arg"
  268           ;;
  269         esac
  270         action=""
  271       else
  272         # parse option flags
  273         case $arg in
  274         -s|--source)
  275           action="s"
  276           ;;
  277         -d|--destination)
  278           action="d"
  279           ;;
  280         -t|--table)
  281           action="t"
  282           ;;
  283         -p|--proto)
  284           action="p"
  285           ;;
  286         esac
  287       fi
  288     done
  289     unset IFS
  290 
  291     #
  292     # Call ip4tables and/or ip6tables as appropriate
  293     #
  294     if [ $src -eq 4 -o $dst -eq 4 -o "$table" = "nat" ]; then
  295       ip4tables "$@"
  296     elif [ $src -eq 6 -o $dst -eq 6 -o "$proto" = "icmpv6" ]; then
  297       if [ "$proto" = "icmp" ]; then
  298         IFS='~'; set -- $(ip6tables_icmp_args "$@"); unset IFS
  299       fi
  300       ip6tables "$@"
  301     elif [ "$proto" = "icmp" ]; then
  302       ip4tables "$@"
  303       # Regenerate ip6tables command-line from the returned 'tilde' separated string
  304       IFS='~'; set -- $(ip6tables_icmp_args "$@"); unset IFS
  305       ip6tables "$@"
  306     else
  307       ip4tables "$@"
  308       ip6tables "$@"
  309     fi
  310   else
  311     #
  312     # Only call ip4tables since IPv6 filtering is disabled.
  313     #
  314     ip4tables "$@"
  315   fi
  316 }
  317 
  318 
  319 ip4tables()
  320 {
  321   local err_result retval IFS=' '
  322 
  323   # Create extra FD
  324   exec 3>&1
  325 
  326   err_result=`$IP4TABLES${IPTABLES_OPTIONS:+ $IPTABLES_OPTIONS} "$@" 2>&1 1>&3`
  327   retval=$?
  328 
  329   # Release extra FD
  330   exec 3>&-
  331 
  332   if [ $retval -ne 0 ]; then
  333     # Show any (error) messages in red
  334     printf "\033[40m\033[1;31m${IP4TABLES} $*\nERROR ($retval): ${err_result}\n\033[0m" >&2
  335 
  336     if note_iptables_error "$@"; then
  337       RULE_WARNING=$((RULE_WARNING + 1))
  338     fi
  339   elif [ -n "$err_result" ]; then
  340     # ip4tables returned success, so normal output of stderr but filter some messages
  341     echo "$err_result" |grep -v -e 'WARNING:.*match is obsolete' -e 'iptables-legacy tables present' >&2
  342   fi
  343 
  344   return $retval
  345 }
  346 
  347 
  348 ip6tables()
  349 {
  350   local err_result retval IFS=' '
  351 
  352   # Create extra FD
  353   exec 3>&1
  354 
  355   err_result=`$IP6TABLES${IPTABLES_OPTIONS:+ $IPTABLES_OPTIONS} "$@" 2>&1 1>&3`
  356   retval=$?
  357 
  358   # Release extra FD
  359   exec 3>&-
  360 
  361   if [ $retval -ne 0 ]; then
  362     # Show any (error) messages in red
  363     printf "\033[40m\033[1;31m${IP6TABLES} $*\nERROR ($retval): ${err_result}\n\033[0m" >&2
  364 
  365     if note_iptables_error "$@"; then
  366       RULE_WARNING=$((RULE_WARNING + 1))
  367     fi
  368   elif [ -n "$err_result" ]; then
  369     # ip6tables returned success, so normal output of stderr but filter some messages
  370     echo "$err_result" |grep -v -e 'WARNING:.*match is obsolete' -e 'iptables-legacy tables present' >&2
  371   fi
  372 
  373   return $retval
  374 }
  375 
  376 
  377 ip4tables_save()
  378 {
  379   local retval IFS=' '
  380 
  381   $IP4TABLES_SAVE "$@"
  382   retval=$?
  383 
  384   if [ $retval -ne 0 ]; then
  385     # Show any (error) messages in red
  386     printf "\033[40m\033[1;31m${IP4TABLES_SAVE} $*\nERROR ($retval)\033[0m\n" >&2
  387     RULE_WARNING=$((RULE_WARNING + 1))
  388   fi
  389 
  390   return $retval
  391 }
  392 
  393 
  394 ip4tables_restore()
  395 {
  396   local err_result retval IFS=' '
  397 
  398   # Create extra FD
  399   exec 3>&1
  400 
  401   err_result=`$IP4TABLES_RESTORE "$@" 2>&1 1>&3`
  402   retval=$?
  403 
  404   # Release extra FD
  405   exec 3>&-
  406 
  407   if [ $retval -ne 0 ]; then
  408     # Show any (error) messages in red
  409     printf "\033[40m\033[1;31m${IP4TABLES_RESTORE} $*\nERROR ($retval): ${err_result}\n\033[0m" >&2
  410 
  411     RULE_WARNING=$((RULE_WARNING + 1))
  412   elif [ -n "$err_result" ]; then
  413     # ip4tables_restore returned success, so normal output of stderr
  414     echo "$err_result" >&2
  415   fi
  416 
  417   return $retval
  418 }
  419 
  420 
  421 ip6tables_save()
  422 {
  423   local retval IFS=' '
  424 
  425   $IP6TABLES_SAVE "$@"
  426   retval=$?
  427 
  428   if [ $retval -ne 0 ]; then
  429     # Show any (error) messages in red
  430     printf "\033[40m\033[1;31m${IP6TABLES_SAVE} $*\nERROR ($retval)\033[0m\n" >&2
  431     RULE_WARNING=$((RULE_WARNING + 1))
  432   fi
  433 
  434   return $retval
  435 }
  436 
  437 
  438 ip6tables_restore()
  439 {
  440   local err_result retval IFS=' '
  441 
  442   # Create extra FD
  443   exec 3>&1
  444 
  445   err_result=`$IP6TABLES_RESTORE "$@" 2>&1 1>&3`
  446   retval=$?
  447 
  448   # Release extra FD
  449   exec 3>&-
  450 
  451   if [ $retval -ne 0 ]; then
  452     # Show any (error) messages in red
  453     printf "\033[40m\033[1;31m${IP6TABLES_RESTORE} $*\nERROR ($retval): ${err_result}\n\033[0m" >&2
  454 
  455     RULE_WARNING=$((RULE_WARNING + 1))
  456   elif [ -n "$err_result" ]; then
  457     # ip6tables_restore returned success, so normal output of stderr
  458     echo "$err_result" >&2
  459   fi
  460 
  461   return $retval
  462 }
  463 
  464 
  465 try_ip4tables()
  466 {
  467   local IFS=' '
  468 
  469   $IP4TABLES${IPTABLES_OPTIONS:+ $IPTABLES_OPTIONS} "$@" >/dev/null 2>&1
  470 }
  471 
  472 
  473 try_ip6tables()
  474 {
  475   local IFS=' '
  476 
  477   $IP6TABLES${IPTABLES_OPTIONS:+ $IPTABLES_OPTIONS} "$@" >/dev/null 2>&1
  478 }
  479 
  480 
  481 # Wrapper function for modprobe
  482 ###############################
  483 modprobe()
  484 {
  485   local result retval IFS=' '
  486 
  487   # Module support available?
  488   if [ -e /proc/modules ]; then
  489     # Make sure environment variable is not set
  490     MODPROBE_OPTIONS=""
  491 
  492     result=`$MODPROBE $@ 2>&1`
  493     retval=$?
  494 
  495     if [ $retval -ne 0 ]; then
  496       if ! echo "$result" |grep -q -e "Module .* not found" -e "Can't locate module" -e "^ *$"; then
  497         # Show any (error) messages in red
  498         printf "\033[40m\033[1;31m${MODPROBE} $*\nERROR ($retval): ${result}\033[0m\n" >&2
  499       elif [ "$COMPILED_IN_KERNEL_MESSAGES" != "0" ]; then
  500         printf "WARNING: Module \"$1\" failed to load. Assuming compiled-in-kernel.\n" >&2
  501       fi
  502       return $retval
  503     else
  504       if echo "$result" |grep -q -e '^WARNING:'; then
  505         # Show any (warning) messages in red
  506         printf "\033[40m\033[1;31m${MODPROBE} $*\nWARNING: ${result}\033[0m\n" >&2
  507       else
  508         echo "${INDENT}Loaded kernel module $1. $result"
  509       fi
  510       return 0
  511     fi
  512   elif [ "$COMPILED_IN_KERNEL_MESSAGES" != "0" ]; then
  513     echo "${INDENT}NOTE: Kernel has no module support. Assuming compiled-in-kernel for module \"$1\""
  514   fi
  515 
  516   return 0
  517 }
  518 
  519 
  520 # Multi modprobe - Modprobe different modules until one succeeds, group modules with a comma
  521 modprobe_multi()
  522 {
  523   local result retval OPTIONS="" MODULES="" IFS=' '
  524 
  525   # Split options and modules
  526   while [ -n "$1" ]; do
  527     case "$1" in
  528       -*) OPTIONS="$OPTIONS${OPTIONS:+ }$1";;
  529        *) MODULES="${MODULES}${MODULES:+ }$1";;
  530     esac
  531     shift
  532   done
  533 
  534 
  535   # Module support available?
  536   if [ -e /proc/modules ]; then
  537     # Make sure environment variable is not set
  538     MODPROBE_OPTIONS=""
  539 
  540     local module modules fail modprobe_commandline
  541 
  542     IFS=' '
  543     for modules in $MODULES; do
  544       fail=0
  545       IFS=','
  546       for module in $modules; do
  547         modprobe_commandline="$MODPROBE"
  548         if [ -n "$OPTIONS" ]; then
  549           modprobe_commandline="$modprobe_commandline $OPTIONS"
  550         fi
  551         modprobe_commandline="$modprobe_commandline $module"
  552 
  553         IFS=' '
  554         result=`$modprobe_commandline 2>&1`
  555         retval=$?
  556 
  557         if [ $retval -ne 0 ]; then
  558           if ! echo "$result" |grep -q -e "Module .* not found" -e "Can't locate module" -e "^ *$"; then
  559             # Show any (error) messages in red
  560             printf "\033[40m\033[1;31m${modprobe_commandline}\nERROR ($retval): $result\033[0m\n" >&2
  561           fi
  562           fail=1
  563         else
  564           if echo "$result" |grep -q -e '^WARNING:'; then
  565             # Show any (warning) messages in red
  566             printf "\033[40m\033[1;31m${modprobe_commandline}\nWARNING: $result\033[0m\n" >&2
  567           else
  568             echo "${INDENT}Loaded kernel module $module. $result"
  569           fi
  570         fi
  571       done
  572       if [ $fail -eq 0 ]; then
  573         return 0
  574       fi
  575     done
  576     if [ "$COMPILED_IN_KERNEL_MESSAGES" != "0" ]; then
  577       printf "WARNING: Modules \"$(echo "$MODULES" |tr ' ' '|')\" failed to load. Assuming compiled-in-kernel.\n" >&2
  578       return 1
  579     fi
  580   elif [ "$COMPILED_IN_KERNEL_MESSAGES" != "0" ]; then
  581     echo "${INDENT}NOTE: Kernel has no module support. Assuming compiled-in-kernel for modules \"$(echo "$MODULES" |tr ' ' '|')\""
  582   fi
  583 
  584   return 0
  585 }
  586 
  587 
  588 # sysctl binary wrapper
  589 #######################
  590 sysctl()
  591 {
  592   local result retval IFS=' '
  593 
  594   result=`$SYSCTL "$@" 2>&1`
  595   retval=$?
  596 
  597   if [ $retval -ne 0 ]; then
  598     # Show any (error) messages in red
  599     printf "\033[40m\033[1;31m${SYSCTL} $*\nERROR ($retval): ${result}\033[0m\n" >&2
  600     return $retval
  601   fi
  602 
  603   if [ -n "$result" ]; then
  604     echo "${INDENT}$result"
  605   fi
  606 
  607   return 0
  608 }
  609 
  610 
  611 # Multi sysctl - Try sysctl-variables until one succeeds
  612 sysctl_multi()
  613 {
  614   local result retval OPTIONS="" VARIABLES="" IFS=' '
  615 
  616   while [ -n "$1" ]; do
  617     # Combine options and exit on first non-option
  618     case "$1" in
  619       -*) OPTIONS="${OPTIONS}${OPTIONS:+ }$1";;
  620        *) VARIABLES="${VARIABLES}${VARIABLES:+ }$1";;
  621     esac
  622     shift
  623   done
  624 
  625   IFS=' '
  626   for variable in $VARIABLES; do
  627     if $SYSCTL "$(echo "$variable" |cut -d'=' -f1)" >/dev/null 2>&1; then
  628       local sysctl_commandline="$SYSCTL"
  629       if [ -n "$OPTIONS" ]; then
  630         sysctl_commandline="$sysctl_commandline $OPTIONS"
  631       fi
  632       sysctl_commandline="$sysctl_commandline $variable"
  633 
  634       result=`$sysctl_commandline 2>&1`
  635       retval=$?
  636 
  637       if [ $retval -eq 0 ]; then
  638         if [ -n "$result" ]; then
  639           echo "${INDENT}$result"
  640         fi
  641         return 0
  642       else
  643         # Show any (error) messages in red
  644         printf "\033[40m\033[1;31m${sysctl_commandline}\nERROR ($retval): $result\033[0m\n" >&2
  645       fi
  646     fi
  647   done
  648   printf "\033[40m\033[1;31mERROR: Unable to find kernel parameters \"$(echo "$VARIABLES" |tr ' ' '|')\"!\033[0m\n" >&2
  649   return 1
  650 }
  651 
  652 
  653 # Set a value for sysctl wildcard interfaces (like "net.ipv4.conf.*.rp_filter")
  654 # $1 = prefix (eg. net.ipv4.conf)
  655 # $2 = variable (eg. rp_filter)
  656 # $3 = value to set
  657 sysctl_set_all()
  658 {
  659   local prefix="$1" variable="$2" value="$3"
  660   local interface line IFS
  661 
  662   IFS=$EOL
  663   for line in $($SYSCTL -a 2>/dev/null |cut -d' ' -f1 |grep "^${prefix}\..*\.${variable}$"); do
  664     IFS=' ,'
  665     for interface in all default lo $EXT_IF $INT_IF $DMZ_IF; do
  666       if [ "$line" = "$prefix.$interface.$variable" ]; then
  667         sysctl -w "$line=$value"
  668         break
  669       fi
  670     done
  671   done
  672 }
  673 
  674 
  675 sysctl_key_prefix()
  676 {
  677   $SYSCTL -a 2>/dev/null |grep -q "^$1"
  678 }
  679 
  680 
  681 sysctl_key_match()
  682 {
  683   $SYSCTL "$1" >/dev/null 2>&1
  684 }
  685 
  686 
  687 sysctl_get_value()
  688 {
  689   $SYSCTL -n "$1" 2>/dev/null
  690 }
  691 
  692 
  693 # tc binary wrapper
  694 ###################
  695 tc()
  696 {
  697   $TC "$@"
  698 }
  699 
  700 
  701 # ip binary wrapper
  702 ###################
  703 ip()
  704 {
  705   $IP "$@"
  706 }
  707 
  708 
  709 # dig binary wrapper
  710 ####################
  711 dig()
  712 {
  713   local x=0 addr name lines item retval first IFS
  714 
  715   if [ -n "$DIG" ]; then
  716     if [ "$DNS_FAST_FAIL" = "1" -o "$DNS_FAST_FAIL_ONCE" = "1" ]; then
  717       lines="$($DIG +noauthority +noadditional +tries=1 +time=1 "$@" 2>/dev/null)"
  718       retval=$?
  719       DNS_FAST_FAIL_ONCE=0
  720     else
  721       lines="$($DIG +noauthority +noadditional "$@" 2>/dev/null)"
  722       retval=$?
  723     fi
  724     retval=$?
  725 
  726     first=1
  727     IFS=$EOL
  728     for item in `echo "$lines" |awk '{ if (substr($0,0,1) != ";" && ($4 == "A" || $4 == "PTR")) print $NF }'`; do
  729       if [ $first -eq 1 ]; then
  730         first=0
  731       else
  732         printf " "
  733       fi
  734 
  735       printf "$item"
  736     done
  737     echo "" # Carriage return
  738     return $retval
  739   elif [ -n "$NSLOOKUP" ]; then
  740     while [ $# -gt 1 ]; do
  741       if [ "$1" = "-x" ]; then
  742         x=1
  743       fi
  744       shift
  745     done
  746     if [ -n "$1" ]; then
  747       if [ "$DNS_FAST_FAIL" = "1" -o "$DNS_FAST_FAIL_ONCE" = "1" ]; then
  748         lines="$($NSLOOKUP -retry=1 -timeout=1 "$1" 2>/dev/null |sed -e "1,2d")"
  749         DNS_FAST_FAIL_ONCE=0
  750       else
  751         lines="$($NSLOOKUP "$1" 2>/dev/null |sed -e "1,2d")"
  752       fi
  753 
  754       addr=""
  755       name=""
  756       IFS=$EOL
  757       for line in $lines; do
  758         case "$line" in
  759                       'Address'*) addr="${addr}${addr:+ }$(echo "$line" |sed -n -r -e 's/^Address.*: *([0-9.]{7,}).*$/\1/p')"
  760                                   ;;
  761                      *'name = '*) name="${name}${name:+ }$(echo "$line" |sed -e 's/^.*name = *//' -e 's/ .*$//')"
  762                                   ;;
  763         esac
  764       done
  765 
  766       if [ $x -eq 0 -a -n "$addr" ]; then
  767         echo "$addr"
  768         return 0
  769       elif [ $x -eq 1 -a -n "$name" ]; then
  770         echo "$name"
  771         return 0
  772       fi
  773 
  774       # Failure:
  775       return 9
  776     fi
  777     return 1
  778   else
  779     return 9
  780   fi
  781 }
  782 
  783 
  784 # Helper function to expand out wildcards in interface name list
  785 wildcard_ifs()
  786 {
  787   local expnd if0 if1
  788 
  789   expnd=""
  790 
  791   local IFS=', '
  792   for if0 in $*; do
  793     if1="$if0"
  794     case $if1 in
  795     *+)
  796       if1="${if1%+}"
  797       if1="$(ip link | awk "\$2 ~ /${if1}[0-9]+:/ { print substr(\$2, 1, length(\$2)-1); }" | tr '\n' ' ')"
  798       if [ -z "$if1" ]; then
  799         echo "wildcard: $if0 unmatched!" >&2
  800         continue
  801       fi
  802       ;;
  803     esac
  804     expnd="$expnd${expnd:+ }$if1"
  805   done
  806   echo "$expnd"
  807 }
  808 
  809 
  810 parse_rule()
  811 {
  812   local rule="$1" var="$2" type="$3" left_rule right_rule
  813 
  814   case $type in
  815 
  816   hosts-ports|hosts-protos)
  817     hosts=$(get_hosts_ihp "$rule")
  818     ports=$(get_ports_ihp "$rule")
  819     if [ -z "$hosts" -o -z "$ports" ]; then
  820       parse_rule_warning "$rule"
  821       return 1
  822     fi
  823     protos="$ports"
  824     ;;
  825 
  826   hosts:ANYHOST-ports:ANYPORT|hosts:ANYHOST-protos)
  827     hosts=$(get_hosts_ihp "$rule" "$ANYHOST")
  828     if [ "$type" = "hosts:ANYHOST-ports:ANYPORT" ]; then
  829       ports=$(get_ports_ihp "$rule" "$ANYPORT")
  830     else
  831       ports=$(get_ports_ihp "$rule")
  832     fi
  833     if [ -z "$ports" ]; then
  834       parse_rule_warning "$rule"
  835       return 1
  836     fi
  837     protos="$ports"
  838     ;;
  839 
  840   interfaces-ports|interfaces-protos)
  841     interfaces=$(get_ifs "$rule")
  842     ports=$(get_ports_ip "$rule")
  843     if [ -z "$ports" ]; then
  844       parse_rule_warning "$rule"
  845       return 1
  846     fi
  847     protos="$ports"
  848     ;;
  849 
  850   interfaces-srcips-ports|interfaces-srcips-protos)
  851     interfaces=$(get_ifs "$rule")
  852     srcips=$(get_ips "$rule")
  853     ports=$(get_ports_ip "$rule")
  854     if [ -z "$ports" ]; then
  855       parse_rule_warning "$rule"
  856       return 1
  857     fi
  858     protos="$ports"
  859     ;;
  860 
  861   interfaces-srcips-hosts)
  862     interfaces=$(get_ifs "$rule")
  863     srcips=$(get_ips "$rule")
  864     hosts=$(get_hosts_ih "$rule")
  865     if [ -z "$hosts" ]; then
  866       parse_rule_warning "$rule"
  867       return 1
  868     fi
  869     ;;
  870 
  871   interfaces-srcips-hosts-ports|interfaces-srcips-hosts-protos)
  872     interfaces=$(get_ifs "$rule")
  873     srcips=$(get_ips "$rule")
  874     hosts=$(get_hosts_ihp "$rule")
  875     ports=$(get_ports_ihp "$rule")
  876     if [ -z "$hosts" -o -z "$ports" ]; then
  877       parse_rule_warning "$rule"
  878       return 1
  879     fi
  880     protos="$ports"
  881     ;;
  882 
  883   interfaces-destips-ports|interfaces-destips-protos)
  884     interfaces=$(get_ifs "$rule")
  885     destips=$(get_ips "$rule")
  886     ports=$(get_ports_ip "$rule")
  887     if [ -z "$ports" ]; then
  888       parse_rule_warning "$rule"
  889       return 1
  890     fi
  891     protos="$ports"
  892     ;;
  893 
  894   interfaces-destips-hosts)
  895     interfaces=$(get_ifs "$rule")
  896     destips=$(get_ips "$rule")
  897     hosts=$(get_hosts_ih "$rule")
  898     if [ -z "$hosts" ]; then
  899       parse_rule_warning "$rule"
  900       return 1
  901     fi
  902     ;;
  903 
  904   interfaces-destips-hosts-ports|interfaces-destips-hosts-protos)
  905     interfaces=$(get_ifs "$rule")
  906     destips=$(get_ips "$rule")
  907     hosts=$(get_hosts_ihp "$rule")
  908     ports=$(get_ports_ihp "$rule")
  909     if [ -z "$hosts" -o -z "$ports" ]; then
  910       parse_rule_warning "$rule"
  911       return 1
  912     fi
  913     protos="$ports"
  914     ;;
  915 
  916   shosts:ANYHOST-dhosts-ports:ANYPORT|shosts:ANYHOST-dhosts-ports|shosts:ANYHOST-dhosts-protos)
  917     left_rule=$(echo "$rule" |cut -s -d'>' -f1)
  918     right_rule=$(echo "$rule" |cut -d'>' -f2)
  919 
  920     shosts=$(get_hosts_ih "$left_rule" "$ANYHOST")
  921     dhosts=$(get_hosts_hp "$right_rule")
  922     if [ "$type" = "shosts:ANYHOST-dhosts-ports:ANYPORT" ]; then
  923       ports=$(get_ports_hp "$right_rule" "$ANYPORT")
  924     else
  925       ports=$(get_ports_hp "$right_rule")
  926     fi
  927     if [ -z "$dhosts" -o -z "$ports" ]; then
  928       parse_rule_warning "$rule"
  929       return 1
  930     fi
  931     protos="$ports"
  932     ;;
  933 
  934   interfaces-shosts:ANYHOST-dhosts-ports:ANYPORT|interfaces-shosts:ANYHOST-dhosts-protos)
  935     left_rule=$(echo "$rule" |cut -s -d'>' -f1)
  936     right_rule=$(echo "$rule" |cut -d'>' -f2)
  937 
  938     interfaces=$(get_ifs "$left_rule")
  939     shosts=$(get_hosts_ih "$left_rule" "$ANYHOST")
  940     dhosts=$(get_hosts_hp "$right_rule")
  941     if [ "$type" = "interfaces-shosts:ANYHOST-dhosts-ports:ANYPORT" ]; then
  942       ports=$(get_ports_hp "$right_rule" "$ANYPORT")
  943     else
  944       ports=$(get_ports_hp "$right_rule")
  945     fi
  946     if [ -z "$dhosts" -o -z "$ports" ]; then
  947       parse_rule_warning "$rule"
  948       return 1
  949     fi
  950     protos="$ports"
  951     ;;
  952 
  953   interfaces-shosts-dhosts-ports:ANYPORT|interfaces-shosts-dhosts-protos)
  954     left_rule=$(echo "$rule" |cut -s -d'>' -f1)
  955     right_rule=$(echo "$rule" |cut -s -d'>' -f2)
  956 
  957     interfaces=$(get_ifs "$left_rule")
  958     shosts=$(get_hosts_ih "$left_rule")
  959     dhosts=$(get_hosts_hp "$right_rule")
  960     if [ "$type" = "interfaces-shosts-dhosts-ports:ANYPORT" ]; then
  961       ports=$(get_ports_hp "$right_rule" "$ANYPORT")
  962     else
  963       ports=$(get_ports_hp "$right_rule")
  964     fi
  965     if [ -z "$shosts" -o -z "$dhosts" -o -z "$ports" ]; then
  966       parse_rule_warning "$rule"
  967       return 1
  968     fi
  969     protos="$ports"
  970     ;;
  971 
  972   interfaces:EXT_IF-shosts-dhosts-ports:ANYPORT|interfaces:EXT_IF-shosts-dhosts-protos)
  973     left_rule=$(echo "$rule" |cut -s -d'>' -f1)
  974     right_rule=$(echo "$rule" |cut -s -d'>' -f2)
  975 
  976     interfaces=$(get_ifs "$left_rule" "$EXT_IF")
  977     shosts=$(get_hosts_ih "$left_rule")
  978     dhosts=$(get_hosts_hp "$right_rule")
  979     if [ "$type" = "interfaces:EXT_IF-shosts-dhosts-ports:ANYPORT" ]; then
  980       ports=$(get_ports_hp "$right_rule" "$ANYPORT")
  981     else
  982       ports=$(get_ports_hp "$right_rule")
  983     fi
  984     if [ -z "$shosts" -o -z "$dhosts" -o -z "$ports" ]; then
  985       parse_rule_warning "$rule"
  986       return 1
  987     fi
  988     protos="$ports"
  989     ;;
  990 
  991   interfaces:EXT_IF-destips-shosts-ports-dhost_dport|interfaces:EXT_IF-destips-shosts-protos-dhost)
  992     left_rule=$(echo "$rule" |cut -s -d'>' -f1)
  993     right_rule=$(echo "$rule" |cut -s -d'>' -f2)
  994 
  995     interfaces=$(get_ifs "$left_rule" "$EXT_IF")
  996     destips=$(get_ips "$left_rule")
  997 
  998     # Check for separator(SEP)
  999     if echo "$left_rule" |grep -q "$SEP"; then
 1000       shosts=$(get_hosts_ihp "$left_rule")
 1001       ports=$(get_ports_ihp "$left_rule")
 1002     else
 1003       # Assume ports/protos only if no separator
 1004       shosts="$ANYHOST"
 1005       ports=$(get_ports_ip "$left_rule")
 1006     fi
 1007 
 1008     dhost_dport="$right_rule"
 1009     if [ -z "$shosts" -o -z "$ports" ]; then
 1010       parse_rule_warning "$rule"
 1011       return 1
 1012     fi
 1013     protos="$ports"
 1014     dhost="$dhost_dport"
 1015     ;;
 1016 
 1017   interfaces:NAT_IF-destips-shosts-ports-dhost_dport|interfaces:NAT_IF-destips-shosts-protos-dhost)
 1018     left_rule=$(echo "$rule" |cut -s -d'>' -f1)
 1019     right_rule=$(echo "$rule" |cut -s -d'>' -f2)
 1020 
 1021     interfaces=$(get_ifs "$left_rule" "$NAT_IF")
 1022     destips=$(get_ips "$left_rule")
 1023 
 1024     # Check for separator(SEP)
 1025     if echo "$left_rule" |grep -q "$SEP"; then
 1026       shosts=$(get_hosts_ihp "$left_rule")
 1027       ports=$(get_ports_ihp "$left_rule")
 1028     else
 1029       # Assume ports/protos only if no separator
 1030       shosts="$ANYHOST"
 1031       ports=$(get_ports_ip "$left_rule")
 1032     fi
 1033 
 1034     dhost_dport="$right_rule"
 1035     if [ -z "$shosts" -o -z "$ports" ]; then
 1036       parse_rule_warning "$rule"
 1037       return 1
 1038     fi
 1039     protos="$ports"
 1040     dhost="$dhost_dport"
 1041     ;;
 1042 
 1043   shosts:ANYHOST-dhosts)
 1044     left_rule=$(echo "$rule" |cut -s -d'>' -f1)
 1045     right_rule=$(echo "$rule" |cut -d'>' -f2)
 1046 
 1047     shosts=$(get_hosts_ih "$left_rule" "$ANYHOST")
 1048     dhosts=$(get_hosts_hp "$right_rule")
 1049 
 1050     if [ -z "$dhosts" ]; then
 1051       parse_rule_warning "$rule"
 1052       return 1
 1053     fi
 1054     ;;
 1055 
 1056   shosts-dhosts:ANYHOST)
 1057     left_rule=$(echo "$rule" |cut -d'>' -f1)
 1058     right_rule=$(echo "$rule" |cut -s -d'>' -f2)
 1059 
 1060     shosts=$(get_hosts_ih "$left_rule")
 1061     dhosts=$(get_hosts_hp "$right_rule" "$ANYHOST")
 1062 
 1063     if [ -z "$shosts" ]; then
 1064       parse_rule_warning "$rule"
 1065       return 1
 1066     fi
 1067     ;;
 1068 
 1069   *)
 1070     echo "** ERROR: Invalid rule parse type \"$type\"!" >&2
 1071     return 1
 1072     ;;
 1073 
 1074   esac
 1075 
 1076   return 0
 1077 }
 1078 
 1079 
 1080 parse_rule_warning()
 1081 {
 1082   local rule="$1"
 1083 
 1084   RULE_WARNING=$((RULE_WARNING + 1))
 1085 
 1086   echo "** WARNING: In variable $var, Rule: \"$rule\" is ignored." >&2
 1087 }
 1088 
 1089 
 1090 # Helper function to work around non working + wildcard in some versions of iptables
 1091 ipt_if()
 1092 {
 1093   if [ -n "$2" -a "$2" != "+" ]; then
 1094     echo "$1${IFS:- }$2"
 1095   fi
 1096 }
 1097 
 1098 
 1099 # Helper function to get interface(s) from variable
 1100 get_ifs()
 1101 {
 1102   local result=""
 1103 
 1104   if echo "$1" |grep -q -e "$SEP2"; then
 1105     result="$(echo "$1" |cut -s -d"$SEP2" -f1 |grep -v -e '[.][0-9][0-9]*[.]' -e ':[0-9a-fA-F]*:' -e "$ANYHOST" |tr ' ' ',')"
 1106   fi
 1107 
 1108   if [ -n "$result" ]; then
 1109     echo "$result"
 1110     return 0
 1111   else
 1112     if [ -n "$2" ]; then
 1113       echo "$2"
 1114     else
 1115       echo "+"
 1116     fi
 1117     return 1
 1118   fi
 1119 }
 1120 
 1121 
 1122 # Helper function to get source/destination interface IP(s) from variable
 1123 get_ips()
 1124 {
 1125   local result=""
 1126 
 1127   if echo "$1" |grep -q -e "$SEP2"; then
 1128     result="$(echo "$1" |cut -s -d"$SEP2" -f1 |grep -e '[.][0-9][0-9]*[.]' -e ':[0-9a-fA-F]*:' -e "$ANYHOST" |tr ' ' ',')"
 1129   fi
 1130 
 1131   if [ -n "$result" ]; then
 1132     echo "$result"
 1133     return 0
 1134   else
 1135     if [ -n "$2" ]; then
 1136       echo "$2"
 1137     else
 1138       echo "$ANYHOST"
 1139     fi
 1140     return 1
 1141   fi
 1142 }
 1143 
 1144 
 1145 # Helper function to get hostname(s) from variable (ifs|ips#hosts)
 1146 get_hosts_ih()
 1147 {
 1148   local result="$(echo "$1" |sed "s!^.*$SEP2!!")"
 1149 
 1150   if [ -n "$result" ]; then
 1151     echo "$result"
 1152     return 0
 1153   else
 1154     echo "$2"
 1155     return 1
 1156   fi
 1157 }
 1158 
 1159 
 1160 # Helper function to get hostname(s) from variable (ifs|ips#hosts~ports|protos)
 1161 get_hosts_ihp()
 1162 {
 1163   local result="$(echo "$1" |sed "s!^.*$SEP2!!" |cut -s -d"$SEP" -f1)"
 1164 
 1165   if [ -n "$result" ]; then
 1166     echo "$result"
 1167     return 0
 1168   else
 1169     echo "$2"
 1170     return 1
 1171   fi
 1172 }
 1173 
 1174 
 1175 # Helper function to get port(s) from variable (ifs|ips#hosts~ports|protos)
 1176 get_ports_ihp()
 1177 {
 1178   local result="$(echo "$1" |sed "s!^.*$SEP2!!")"
 1179 
 1180   if echo "$result" |grep -q -e "$SEP"; then
 1181     echo "$result" |cut -s -d"$SEP" -f2 |tr '-' ':'
 1182     return 0
 1183   elif [ -n "$2" ]; then
 1184     # Use default, if specified
 1185     echo "$2"
 1186     return 1
 1187   else
 1188     # When we have no separator, assume port(s) only and no host(s)
 1189     echo "$result" |tr '-' ':'
 1190     return 0
 1191   fi
 1192 }
 1193 
 1194 
 1195 # Helper function to get hostname(s) from variable (hosts~ports|protos)
 1196 get_hosts_hp()
 1197 {
 1198   local result="$(echo "$1" |sed "s!^.*$SEP2!!")"
 1199 
 1200   if echo "$result" |grep -q -e "$SEP"; then
 1201     echo "$result" |cut -s -d"$SEP" -f1
 1202     return 0
 1203   elif [ -n "$2" ]; then
 1204     # Use default, if specified
 1205     echo "$2"
 1206     return 1
 1207   else
 1208     # When we have no separator, assume host(s) only and no port(s)
 1209     echo "$result"
 1210     return 0
 1211   fi
 1212 }
 1213 
 1214 
 1215 # Helper function to get port(s) from variable (hosts~ports|protos)
 1216 get_ports_hp()
 1217 {
 1218   local result="$(echo "$1" |sed "s!^.*$SEP2!!")"
 1219 
 1220   if echo "$result" |grep -q -e "$SEP"; then
 1221     echo "$result" |cut -s -d"$SEP" -f2 |tr '-' ':'
 1222     return 0
 1223   else
 1224     echo "$2"
 1225     return 1
 1226   fi
 1227 }
 1228 
 1229 
 1230 # Helper function to get port(s) from variable (ifs|ips#ports|protos)
 1231 get_ports_ip()
 1232 {
 1233   local result="$(echo "$1" |sed "s!^.*$SEP2!!")"
 1234 
 1235   if [ -n "$result" ]; then
 1236     echo "$result" |tr '-' ':'
 1237     return 0
 1238   else
 1239     echo "$2"
 1240     return 1
 1241   fi
 1242 }
 1243 
 1244 
 1245 get_numeric_ip_version()
 1246 {
 1247   case $1 in
 1248   0/0)
 1249     ;;
 1250   [0-9][0-9.][0-9.][0-9.][0-9.]*.*[0-9])
 1251     return 4
 1252     ;;
 1253   [0-9]*.*/*[0-9]|[0-9]/*[0-9]|[1-9][0-9]/*[0-9]|[12][0-9][0-9]/*[0-9])
 1254     return 4
 1255     ;;
 1256   *:*)
 1257     return 6
 1258     ;;
 1259   esac
 1260 
 1261   return 0 # Unknown, possibly a hostname
 1262 }
 1263 
 1264 
 1265 # Is argument IPv4 numeric?
 1266 is_numeric_ipv4()
 1267 {
 1268   if [ "$1" = "0/0" ]; then
 1269     return 0 # Consider 0/0 also as numeric
 1270   fi
 1271 
 1272   get_numeric_ip_version "$1"
 1273   if [ $? -eq 4 ]; then
 1274     return 0
 1275   fi
 1276 
 1277   return 1
 1278 }
 1279 
 1280 
 1281 # Is argument IPv6 numeric?
 1282 is_numeric_ipv6()
 1283 {
 1284   if [ "$1" = "0/0" ]; then
 1285     return 0 # Consider 0/0 also as numeric
 1286   fi
 1287 
 1288   get_numeric_ip_version "$1"
 1289   if [ $? -eq 6 ]; then
 1290     return 0
 1291   fi
 1292 
 1293   return 1
 1294 }
 1295 
 1296 
 1297 # Is argument a (numeric) IP?
 1298 is_numeric_ip()
 1299 {
 1300   if [ "$1" = "0/0" ]; then
 1301     return 0 # Consider 0/0 also as numeric
 1302   fi
 1303 
 1304   get_numeric_ip_version "$1"
 1305   if [ $? -ne 0 ]; then
 1306     return 0
 1307   fi
 1308 
 1309   return 1
 1310 }
 1311 
 1312 
 1313 # Helper function to resolve an IP to a DNS name
 1314 # $1 = IP. $2 (optional) = Additional arguments for dig. stdout = DNS name
 1315 gethostbyaddr()
 1316 {
 1317   local host="$1" result retval=0
 1318 
 1319   # We can't resolve addresses with a subnet mask
 1320   case "$host" in
 1321     */*) return 1 ;;
 1322   esac
 1323 
 1324   # Don't try to resolve DNS names:
 1325   if ! is_numeric_ip "$host"; then
 1326     # It's a DNS name already, so just return it
 1327     echo "$host"
 1328     return 0
 1329   fi
 1330 
 1331   shift
 1332   result="$(dig -x "$@" "$host")"
 1333   retval=$?
 1334 
 1335   if [ $retval -eq 0 ]; then
 1336     if [ -n "$result" ]; then
 1337       echo "$result"
 1338       return 0
 1339     else
 1340       return 1
 1341     fi
 1342   else
 1343     return $retval
 1344   fi
 1345 }
 1346 
 1347 
 1348 # Helper function to resolve a DNS name to an IP
 1349 # $1 = Hostname. $2 (optional) = Additional arguments for dig. stdout = IP
 1350 gethostbyname()
 1351 {
 1352   local host="$1" result retval=0
 1353 
 1354   # Don't try to resolve IPs:
 1355   if is_numeric_ip "$host"; then
 1356     # It's an IP already, so just return it
 1357     echo "$host"
 1358     return 0
 1359   fi
 1360 
 1361   shift
 1362   result="$(dig "$@" "$host")"
 1363   retval=$?
 1364 
 1365   if [ $retval -eq 0 ]; then
 1366     if [ -n "$result" ]; then
 1367       echo "$result"
 1368       return 0
 1369     else
 1370       return 1
 1371     fi
 1372   else
 1373     return $retval
 1374   fi
 1375 }
 1376 
 1377 
 1378 # Get resolved host->ip from host cache
 1379 # Arguments : $1 = hostname to resolve
 1380 # Returns   : 0 = Got result, 1 = no result, 2 = in cache with no-ip. IP is send to stdout (if any).
 1381 # NOTE      : Hosts with multiple IPs are outputted space separated
 1382 get_dynamic_host_from_cache()
 1383 {
 1384   local host="$1"
 1385 
 1386   if is_numeric_ip "$host"; then
 1387     echo "$host"
 1388     return 0
 1389   fi
 1390 
 1391   if [ -f "$HOST_CACHE_FILE" ]; then
 1392     # First try to get host from host-cache
 1393     local find_host="$(grep "^$host " -m1 "$HOST_CACHE_FILE")"
 1394     if [ -n "$find_host" ]; then
 1395       local host_ip="$(echo "$find_host" |cut -s -d' ' -f2 |tr ',' ' ')"
 1396 
 1397       if [ "$host_ip" = "NO_IP" ]; then
 1398         host_ip=""
 1399         return 2 # NO-IP result
 1400       elif [ -n "$host_ip" ]; then
 1401         echo "$host_ip"
 1402         return 0
 1403       fi
 1404     fi
 1405   fi
 1406 
 1407   return 1 # No result
 1408 }
 1409 
 1410 
 1411 # Get IP for (dynamic) host. In case it already exists in our cache and is not too old
 1412 # use that else resolve and store in our cache
 1413 # Arguments : $1 = hostname to resolve
 1414 # Returns   : Resolved host's IP in "$host_ip"
 1415 # NOTE      : Hosts with multiple IPs are outputted space separated
 1416 get_dynamic_host_cached()
 1417 {
 1418   host_ip=""            # Reset result
 1419   local host="$1"
 1420   local retval=0
 1421   local cache_lookup=""
 1422   local cache_time=0 fail_count=0
 1423   local max_age cur_time store_ip threshold count
 1424 
 1425   # Don't try to resolve stuff that's already numeric
 1426   if is_numeric_ip "$host"; then
 1427     host_ip="$host"
 1428     return 0
 1429   fi
 1430 
 1431   printf "${INDENT}Resolving host \"$host\" -> "
 1432 
 1433   # Check whether we already have it in our cache
 1434   if [ -f "${HOST_CACHE_FILE}" ]; then
 1435     cache_lookup="$(grep "^$host " -m1 "${HOST_CACHE_FILE}")"
 1436     if [ -n "$cache_lookup" ]; then
 1437       # Check whether it's not too old
 1438       cache_time="$(echo "$cache_lookup" |cut -d' ' -f3)"
 1439       cur_time="$(($(date +'%s') / 60))"
 1440 
 1441       if [ -n "$DNS_MAX_AGE" ]; then
 1442         max_age="$DNS_MAX_AGE"
 1443       else
 1444         max_age=10 # Fallback to 10 minutes
 1445       fi
 1446 
 1447       # Check cache age
 1448       if [ -n "$cache_time" -a $cache_time -le $cur_time -a $cur_time -le $((cache_time + max_age)) ]; then
 1449         host_ip="$(echo "$cache_lookup" |cut -d' ' -f2)"
 1450         if [ -n "$host_ip" ]; then
 1451           echo "$host_ip (cached)"
 1452 
 1453           if [ "$host_ip" = "NO_IP" ]; then
 1454             host_ip=""
 1455             return 1
 1456           fi
 1457           return 0
 1458         fi
 1459       fi
 1460     fi
 1461   fi
 1462 
 1463   DNS_FAST_FAIL_ONCE="$DNS_FAST_FAIL"
 1464   host_ip="$(gethostbyname "$host" |tr ' ' ',')"
 1465   gethost_retval=$?
 1466 
 1467   # Update cache time
 1468   cache_time="$(($(date +'%s') / 60))"
 1469 
 1470   if [ $gethost_retval -ne 0 -o -z "$host_ip" ]; then
 1471     retval=1 # Error
 1472 
 1473     # Use value from cache as a fallback, but only if allowed
 1474     if [ -n "$cache_lookup" ]; then
 1475       count="$(echo "$cache_lookup" |cut -s -d' ' -f4)"
 1476       if [ -n "$count" ]; then
 1477         fail_count=$count
 1478       fi
 1479 
 1480       # Try to get from (old) cache, if allowed
 1481       if [ "$DNS_FAIL_THRESHOLD" != "0" ]; then
 1482         host_ip="$(echo "$cache_lookup" |cut -s -d' ' -f2)"
 1483       fi
 1484     fi
 1485 
 1486     if [ -z "$host_ip" -o "$host_ip" = "NO_IP" ]; then
 1487       host_ip=""
 1488       printf "\033[40m\033[1;31mFAILED!\n\033[0m"
 1489       echo "** ERROR: Unresolvable host \"$host\" and no old IP to fallback on! **" >&2
 1490     else
 1491       echo "$host_ip (cached!)"
 1492       echo "** WARNING($retval): Unresolvable host \"$host\". Re-using old IP ($host_ip)! **" >&2
 1493 
 1494       # Ignore error:
 1495       retval=0
 1496     fi
 1497 
 1498     if [ -n "$DNS_FAIL_THRESHOLD" ]; then
 1499       threshold=$DNS_FAIL_THRESHOLD
 1500     else
 1501       threshold=4 # default
 1502     fi
 1503 
 1504     # Increment fail count
 1505     fail_count=$((fail_count + 1))
 1506 
 1507     # Check fail count
 1508     if [ $threshold -gt 0 -a $fail_count -ge $threshold ]; then
 1509       fail_count=1
 1510     fi
 1511   else
 1512     echo "$host_ip"
 1513     cache_time="$(($(date +'%s') / 60))"
 1514     fail_count=0
 1515   fi
 1516 
 1517   if [ -z "$host_ip" ]; then
 1518     # NOTE Explicitly store empty results as well else we'll keep trying over and over again for each plugin/rule
 1519     store_ip="NO_IP"
 1520   else
 1521     store_ip="$host_ip"
 1522   fi
 1523 
 1524   if [ -n "$cache_lookup" ]; then
 1525     # Update existing entry
 1526     sed -i "s/^$host[[:blank:]].*/$host $store_ip $cache_time $fail_count/" "${HOST_CACHE_FILE}"
 1527   else
 1528     # Add new entry
 1529     echo "$host $store_ip $(($(date +'%s') / 60)) $fail_count" >>"${HOST_CACHE_FILE}"
 1530   fi
 1531 
 1532   return $retval
 1533 }
 1534 
 1535 
 1536 # Leave lock function to release lock
 1537 # $1 = Lock (file) name
 1538 lock_leave()
 1539 {
 1540   local LOCK_FILE RETVAL=0
 1541 
 1542   if [ -z "$1" ]; then
 1543     echo "ERROR: Exception due to missing lock argument" >&2
 1544     return 1 # Failure
 1545   fi
 1546 
 1547   LOCK_FILE="/var/lock/aif_$1.lock"
 1548 
 1549   # Remove lockfile
 1550   if ! rm -f "$LOCK_FILE"; then
 1551     echo "ERROR: Failed to remove lock file: $LOCK_FILE" >&2
 1552     RETVAL=1
 1553   fi
 1554 
 1555   # Disable int handler
 1556   trap - INT TERM EXIT
 1557 
 1558   return $RETVAL
 1559 }
 1560 
 1561 
 1562 lock_ctrl_handler()
 1563 {
 1564   lock_leave "$1"
 1565 
 1566   stty intr ^C # Back to normal
 1567   exit         # Yep, I meant to do that... Kill/hang the shell.
 1568 }
 1569 
 1570 
 1571 # Internal lock_enter() function. Only to be used by lock_enter_single() and lock_enter() (below)
 1572 # $1 = Lock (file) name
 1573 lock_enter_internal()
 1574 {
 1575   local LOCK_FILE="$1"
 1576   local PID
 1577 
 1578   # Check lock PID:
 1579   # If cat isn't able to read the file, another instance is probably
 1580   # about to remove the lock -- exit, we're *still* locked
 1581   # Thanks to Grzegorz Wierzowiecki for pointing out this race condition on
 1582   # http://wiki.grzegorz.wierzowiecki.pl/code:mutex-in-bash
 1583   PID="$(cat "$LOCK_FILE" 2>/dev/null)"
 1584   if [ $? -eq 0 ]; then
 1585     if ! kill -0 "$PID" 2>/dev/null; then
 1586       # lock is stale, remove it and restart
 1587       echo "WARNING: Removing stale lockfile \"$LOCK_FILE\" of nonexistant PID \"$PID\"" >&2
 1588       rm -f "$LOCK_FILE"
 1589     fi
 1590   fi
 1591 
 1592   # Acquire lock
 1593   if ( set -o noclobber; echo "$$" > "$LOCK_FILE") 2> /dev/null; then
 1594     # Setup int handler
 1595     trap "lock_ctrl_handler $LOCK_FILE" INT TERM EXIT
 1596 
 1597     return 0 # Lock success
 1598   fi
 1599 
 1600   return 1 # Lock failure
 1601 }
 1602 
 1603 
 1604 # Lock enter function to acquire a single lock. Prevents running of multiple instances
 1605 # When an instance is already running, this (new) instance will be aborted
 1606 # $1 = Lock (file) name
 1607 # $2 = Amount of retries (optional, defaults to 5)
 1608 lock_enter_single()
 1609 {
 1610   local LOCK_FILE="/var/lock/aif_$1.lock"
 1611 
 1612   if [ -z "$1" ]; then
 1613     echo "ERROR: Exception due to missing lock argument" >&2
 1614     return 1 # Failure
 1615   fi
 1616 
 1617   if lock_enter_internal "$LOCK_FILE"; then
 1618     return 0 # Lock success
 1619   fi
 1620 
 1621   echo "NOTE: Another instance is already running for lockfile \"$LOCK_FILE\". Held by PID $(cat $LOCK_FILE)" >&2
 1622   return 1 # Lock failed
 1623 }
 1624 
 1625 
 1626 # Lock enter function to acquire lock. Prevents running of multiple instances
 1627 # When an instance is already running, a new instance will wait until the lock is released (in case a timeout is reached, it will be aborted)
 1628 # $1 = Lock (file) name
 1629 # $2 = Amount of retries (optional, defaults to 5)
 1630 lock_enter()
 1631 {
 1632   local LOCK_FILE="/var/lock/aif_$1.lock"
 1633   local MAX_RETRIES="${2:-5}"
 1634   local FAIL_COUNT=0
 1635 
 1636   if [ -z "$1" ]; then
 1637     echo "ERROR: Exception due to missing lock argument" >&2
 1638     return 1 # Failure
 1639   fi
 1640 
 1641   while [ $FAIL_COUNT -lt $MAX_RETRIES ]; do
 1642     if lock_enter_internal "$LOCK_FILE"; then
 1643       return 0 # Lock success
 1644     fi
 1645 
 1646     FAIL_COUNT=$((FAIL_COUNT + 1))
 1647 
 1648     # Sleep between retries
 1649     sleep 1
 1650   done
 1651 
 1652   echo "ERROR: Failed to acquire lockfile \"$LOCK_FILE\". Held by PID $(cat $LOCK_FILE)" >&2
 1653 
 1654   return 1 # Lock failed
 1655 }
 1656 
 1657 
 1658 # Function to wait for lock to be released
 1659 # $1 = Lock (file) name
 1660 # $2 = Optional wait time in seconds (default = 5 seconds)
 1661 lock_wait()
 1662 {
 1663   local LOCK_FILE="/var/lock/aif_$1.lock"
 1664   local cnt="${2:-5}" # Default to 5 seconds
 1665 
 1666   if [ -z "$1" ]; then
 1667     echo "ERROR: Exception due to missing lock argument" >&2
 1668     return 1 # Failure
 1669   fi
 1670 
 1671   # Wait for lock to disappear
 1672   while [ $cnt -gt 0 ]; do
 1673     if [ ! -f "$LOCK_FILE" ]; then
 1674       return 0 # Lock wait success
 1675     fi
 1676 
 1677     cnt=$((cnt - 1))
 1678     sleep 1
 1679   done
 1680 
 1681   return 1 # Lock wait failed
 1682 }
 1683 
 1684 
 1685 # Helper function to show interfaces / ips in front of verbose line
 1686 # $1 =  interfaces. $2 = ips
 1687 show_if_ip()
 1688 {
 1689   # Only show interfaces if not empty:
 1690   if [ -n "$1" -a "$1" != "+" ]; then
 1691     printf "($1) "
 1692   fi
 1693 
 1694   # Only show destination IPs if not empty:
 1695   if [ -n "$2" -a "$2" != "$ANYHOST" ]; then
 1696     printf "($2) "
 1697   fi
 1698 }
 1699 
 1700 
 1701 # Helper function to show hosts:ports
 1702 # $1 = host. $2 = ports
 1703 show_hosts_ports()
 1704 {
 1705   # Only show interfaces if not empty:
 1706   if [ -n "$1" ]; then
 1707     printf "$1:$2"
 1708   else
 1709     printf "$2"
 1710   fi
 1711 }
 1712 
 1713 
 1714 # Helper function to translate host ranges from variable
 1715 ip_range()
 1716 {
 1717   local FIRST IFS=' '
 1718   
 1719   # Return the args if there is no '-' for improved execution speed
 1720   case "$@" in
 1721     *-*) ;;
 1722       *) echo "$@"; return;;
 1723   esac
 1724 
 1725   FIRST=1
 1726 
 1727   IFS=', '
 1728   # Get variable from commandline
 1729   for item in $*; do
 1730     # Check whether an IP range was specified (only works like w.x.y.z1-z2!):
 1731     start="$(echo "$item" |cut -s -d'-' -f1 |awk -F'.' '{ print $NF }' |grep -e '[0-9]')"
 1732     host_base="$(echo "$item" |cut -s -d'-' -f1 |awk -F'.' '{ for (i=1; i<NF; i++) printf ("%s.",$i) }')"
 1733     stop="$(echo "$item" |cut -s -d'-' -f2 |grep -e '[0-9]')"
 1734 
 1735     if [ -n "$stop" -a -n "$start" ]; then
 1736       IFS=' '
 1737       for x in `seq -s' ' $start $stop`; do
 1738         if [ $FIRST -eq 1 ]; then
 1739           FIRST=0
 1740         else
 1741           printf ","
 1742         fi
 1743         printf "$host_base$x"
 1744       done
 1745     else
 1746       if [ $FIRST -eq 1 ]; then
 1747         FIRST=0
 1748       else
 1749         printf ","
 1750       fi
 1751       printf "$item"
 1752     fi
 1753   done
 1754 }
 1755 
 1756 
 1757 iptables_batch()
 1758 {
 1759   local IFS=' '
 1760   # Note: this wrapper does not perform IPv4/IPv6 address type checking
 1761   # That must be done elsewhere for speed reasons
 1762   #
 1763   if [ "$IPV6_SUPPORT" = "1" ]; then
 1764     ip4tables_batch "$@"
 1765     ip6tables_batch "$@"
 1766   else
 1767     ip4tables_batch "$@"
 1768   fi
 1769 }
 1770 
 1771 
 1772 # Add iptables rules in batch using iptables-save and iptables-restore
 1773 ip4tables_batch()
 1774 {
 1775   local ARGS CHAIN CHAINFILE RESULT=0 IFS=' '
 1776   
 1777   # Args must be of the form and called in this order:
 1778   #   start
 1779   #   init CHAIN
 1780   #   -A CHAIN ...
 1781   #   apply CHAIN
 1782   #   stop
 1783   #
 1784   # Note: the added rules will be placed after a required
 1785   #       pre-existing rule in CHAIN.
 1786   #
 1787   ARGS="$@"
 1788   CHAIN="$2"
 1789 
 1790   if [ "$DISABLE_IPTABLES_BATCH" = "1" ]; then
 1791     if [ "$1" = "-A" ]; then
 1792       ip4tables "$@"
 1793     fi
 1794     return
 1795   fi
 1796 
 1797   if [ -n "$CHAIN" ]; then
 1798     CHAINFILE="$IP4TABLES_BATCH_FILE"_"$CHAIN"
 1799     if [ "$1" = "-A" ]; then
 1800       echo "$ARGS" >> "$CHAINFILE"
 1801     elif [ "$1" = "init" ]; then
 1802       rm -f "$CHAINFILE"
 1803     elif [ "$1" = "apply" ]; then
 1804       sed -i "/^-A $CHAIN / r $CHAINFILE" "$IP4TABLES_BATCH_FILE"
 1805       ip4tables_restore < "$IP4TABLES_BATCH_FILE"
 1806       RESULT=$?
 1807       rm -f "$CHAINFILE"
 1808     else
 1809       RESULT=1
 1810     fi
 1811   else
 1812     if [ "$1" = "start" ]; then
 1813       ip4tables_save -t filter > "$IP4TABLES_BATCH_FILE"
 1814       RESULT=$?
 1815     elif [ "$1" = "stop" ]; then
 1816       rm -f "$IP4TABLES_BATCH_FILE"
 1817     else
 1818       RESULT=1
 1819     fi
 1820   fi
 1821 
 1822   return $RESULT
 1823 }
 1824 
 1825 
 1826 # Add ip6tables rules in batch using ip6tables-save and ip6tables-restore
 1827 ip6tables_batch()
 1828 {
 1829   local ARGS CHAIN CHAINFILE RESULT=0 IFS=' '
 1830 
 1831   # Args must be of the form and called in this order:
 1832   #   start
 1833   #   init CHAIN
 1834   #   -A CHAIN ...
 1835   #   apply CHAIN
 1836   #   stop
 1837   #
 1838   # Note: the added rules will be placed after a required
 1839   #       pre-existing rule in CHAIN.
 1840   #
 1841   ARGS="$@"
 1842   CHAIN="$2"
 1843 
 1844   if [ "$DISABLE_IPTABLES_BATCH" = "1" ]; then
 1845     if [ "$1" = "-A" ]; then
 1846       ip6tables "$@"
 1847     fi
 1848     return
 1849   fi
 1850 
 1851   if [ -n "$CHAIN" ]; then
 1852     CHAINFILE="$IP6TABLES_BATCH_FILE"_"$CHAIN"
 1853     if [ "$1" = "-A" ]; then
 1854       echo "$ARGS" >> "$CHAINFILE"
 1855     elif [ "$1" = "init" ]; then
 1856       rm -f "$CHAINFILE"
 1857     elif [ "$1" = "apply" ]; then
 1858       sed -i "/^-A $CHAIN / r $CHAINFILE" "$IP6TABLES_BATCH_FILE"
 1859       ip6tables_restore < "$IP6TABLES_BATCH_FILE"
 1860       RESULT=$?
 1861       rm -f "$CHAINFILE"
 1862     else
 1863       RESULT=1
 1864     fi
 1865   else
 1866     if [ "$1" = "start" ]; then
 1867       ip6tables_save -t filter > "$IP6TABLES_BATCH_FILE"
 1868       RESULT=$?
 1869     elif [ "$1" = "stop" ]; then
 1870       rm -f "$IP6TABLES_BATCH_FILE"
 1871     else
 1872       RESULT=1
 1873     fi
 1874   fi
 1875 
 1876   return $RESULT
 1877 }
 1878 
 1879 
 1880 # Log message function. Message is read from stdin
 1881 # $1 = Optional prefix
 1882 log_msg()
 1883 {
 1884   local PREFIX="$1"
 1885 
 1886   # Get message from stdin
 1887   IFS=$EOL
 1888   while read LINE; do
 1889     # Have sed remove any colouring
 1890     echo "${PREFIX}${LINE}" |sed 's/\x1B\[[0-9;]\+[A-Za-z]//g' |logger -t firewall -p user.info
 1891   done
 1892 }
 1893 
 1894 
 1895 # Display progress bar, 0% to 100% in 2% increments
 1896 progress_bar()
 1897 {
 1898   # Args: cur_cnt total_cnt
 1899   local prev
 1900 
 1901   if [ $2 -gt 0 ]; then
 1902     if [ $1 -eq 0 ]; then
 1903       progress_percent=0
 1904       printf " 0%%"
 1905     else
 1906       cur=$(($1 / $2))
 1907       if [ $progress_percent -lt $cur ]; then
 1908         prev=$progress_percent
 1909         while [ $prev -le $cur ]; do
 1910           if [ $progress_percent -lt $prev ]; then
 1911             progress_percent=$prev
 1912             if [ $((progress_percent % 20)) -eq 0 ]; then
 1913               printf "$progress_percent%%"
 1914             else
 1915               printf "."
 1916             fi
 1917           fi
 1918           prev=$((prev + 2))
 1919         done
 1920       fi
 1921     fi
 1922   fi
 1923 }
 1924 
 1925 
 1926 # Check existence of an interface
 1927 check_interface()
 1928 {
 1929   local interface IFS=' '
 1930 
 1931   local interfaces="$(ip -o link show | cut -d':' -f2)"
 1932 
 1933   unset IFS
 1934   for interface in $interfaces; do
 1935     case "$1" in
 1936       # Wildcard interface?
 1937       *+) if [ "${1%+}" = "${interface%%[0-9]*}" ]; then
 1938             return 0
 1939           fi
 1940           ;;
 1941        *) if [ "${1}" = "${interface%@*}" ]; then
 1942             return 0
 1943           fi
 1944           ;;
 1945     esac
 1946   done
 1947 
 1948   # Interface not found
 1949   return 1
 1950 }
 1951 
 1952 # Get all IP address(es)/mask(s) of specified network interface
 1953 get_network_ipv4_address_mask_all()
 1954 {
 1955   ip -o addr show dev "$1" 2>/dev/null \
 1956     |awk '$3 == "inet" { print $4 }' |tr '\n' ' ' |sed s,' $',,
 1957 }
 1958 
 1959 # Get (primary) IP address/mask of specified network interface
 1960 get_network_ipv4_address_mask()
 1961 {
 1962   get_network_ipv4_address_mask_all "$1" |cut -d' ' -f1
 1963 }
 1964 
 1965 # Get all IP address(es) of the specified network interface
 1966 get_network_ipv4_address_all()
 1967 {
 1968   ip -o addr show dev "$1" 2>/dev/null \
 1969     |awk '$3 == "inet" { print $4 }' |cut -f1 -d'/' |tr '\n' ' ' |sed s,' $',,
 1970 }
 1971 
 1972 # Get (primary) IP address of the specified network interface
 1973 get_network_ipv4_address()
 1974 {
 1975   get_network_ipv4_address_mask "$1" |cut -f1 -d'/'
 1976 }
 1977 
 1978 # Get (primary) netmask of the specified network interface
 1979 get_network_ipv4_mask()
 1980 {
 1981   get_network_ipv4_address_mask "$1" |cut -f2 -d'/'
 1982 }
 1983 
 1984 # Get broadcast address of the specified network interface
 1985 get_network_ipv4_broadcast()
 1986 {
 1987   ip -o addr show dev "$1" 2>/dev/null \
 1988     |awk '$3 == "inet" && $5 == "brd" { print $6; exit; }'
 1989 }
 1990 
 1991 # Get IPv6 address/mask of specified network interface
 1992 get_network_ipv6_address_mask()
 1993 {
 1994   ip -o addr show dev "$1" 2>/dev/null \
 1995     |awk '$3 == "inet6" { print $4; exit; }'
 1996 }
 1997 
 1998 # Get IPv6 address of the specified network interface
 1999 get_network_ipv6_address()
 2000 {
 2001   get_network_ipv6_address_mask "$1" |cut -f1 -d'/'
 2002 }
 2003 
 2004 # Get IPv6 netmask of the specified network interface
 2005 get_network_ipv6_mask()
 2006 {
 2007   get_network_ipv6_address_mask "$1" |cut -f2 -d'/'
 2008 }
 2009 
 2010 
 2011 ################################# Main ####################################
 2012 
 2013 # Set base file for iptables_batch
 2014 IP4TABLES_BATCH_FILE="/var/tmp/aif_ip4tables_batch"
 2015 IP6TABLES_BATCH_FILE="/var/tmp/aif_ip6tables_batch"
 2016 
 2017 # Set file to store which plugins are loaded
 2018 PLUGIN_LOAD_FILE="/var/tmp/aif_active_plugins"
 2019 PLUGIN_LOAD_FILE_RESTART="/var/tmp/aif_active_plugins_restart"
 2020 
 2021 # (Dynamic) host cache. Used by compatible plugins
 2022 HOST_CACHE_FILE="/var/tmp/aif_host_cache"
 2023 
 2024 # Check for a local/global config file
 2025 ######################################
 2026 if [ -f "$LOCAL_CONFIG_FILE" ]; then
 2027   . "$LOCAL_CONFIG_FILE"
 2028 fi
 2029 
 2030 # Source config directory (conf.d)
 2031 ##################################
 2032 if [ -z "$LOCAL_CONFIG_DIR" ]; then
 2033   LOCAL_CONFIG_DIR="/etc/arno-iptables-firewall/conf.d"
 2034 fi
 2035 if [ -d "$LOCAL_CONFIG_DIR" ] && ls "$LOCAL_CONFIG_DIR"/*.conf >/dev/null 2>&1; then
 2036   unset IFS
 2037   for conf_file in "$LOCAL_CONFIG_DIR/"*.conf; do
 2038     . "$conf_file"
 2039   done
 2040 fi
 2041 
 2042 # if $LOGLEVEL is not set, default to "info"
 2043 ############################################
 2044 if [ -z "$LOGLEVEL" ]; then
 2045   LOGLEVEL="info"
 2046 fi
 2047 
 2048 # Detect all binaries
 2049 #####################
 2050 if [ -z "$IP6TABLES" ]; then
 2051   IP6TABLES="$(find_command /sbin/ip6tables /usr/sbin/ip6tables)"
 2052 fi
 2053 if [ -n "$IP6TABLES" ]; then
 2054   IP6TABLES_SAVE="$(find_command "$IP6TABLES"-save)"
 2055   IP6TABLES_RESTORE="$(find_command "$IP6TABLES"-restore)"
 2056 fi
 2057 
 2058 if [ -z "$IP4TABLES" ]; then
 2059   IP4TABLES="$(find_command /sbin/iptables /usr/sbin/iptables)"
 2060 fi
 2061 if [ -n "$IP4TABLES" ]; then
 2062   IP4TABLES_SAVE="$(find_command "$IP4TABLES"-save)"
 2063   IP4TABLES_RESTORE="$(find_command "$IP4TABLES"-restore)"
 2064 fi
 2065 
 2066 IP="$(find_command /sbin/ip)"
 2067 
 2068 TC="$(find_command /sbin/tc /usr/sbin/tc)"
 2069 
 2070 SYSCTL="$(find_command /sbin/sysctl)"
 2071 
 2072 MODPROBE="$(find_command /sbin/modprobe)"
 2073 
 2074 DIG="$(find_command /usr/bin/dig)"
 2075 
 2076 if [ -z "$DIG" ]; then
 2077   NSLOOKUP="$(find_command /usr/bin/nslookup)"
 2078 fi
 2079 
 2080 # Enable xtables lock "wait" option found in iptables 1.4.20+
 2081 if $IP4TABLES -w --version >/dev/null 2>&1; then
 2082   IPTABLES_OPTIONS="-w"
 2083 else
 2084   IPTABLES_OPTIONS=""
 2085 fi
 2086 
 2087 # Setup IPv6 detected environment variable
 2088 if sysctl_key_prefix net.ipv6.conf; then
 2089   IPV6_DETECTED=1
 2090 else
 2091   IPV6_DETECTED=0
 2092   IPV6_SUPPORT=0
 2093 fi
 2094 
 2095 # Default NAT_INTERNAL_NET to INTERNAL_NET, if not specified
 2096 ############################################################
 2097 if [ -z "$NAT_INTERNAL_NET" ]; then
 2098   NAT_INTERNAL_NET="$INTERNAL_NET"
 2099 fi
 2100 
 2101 # Default NAT_IF to EXT_IF, if not specified
 2102 #############################################################
 2103 if [ -z "$NAT_IF" ]; then
 2104   NAT_IF="$EXT_IF"
 2105 fi
 2106 
 2107 # IPv6 ICMPv6 types that are allowed, not including echo-request (128)
 2108 ######################################################################
 2109 ICMPV6_SPECIAL_TYPES="133 134 135 136"
 2110 
 2111 # IPv6 ICMPv6 Multicast Listener Discovery (RFC 2710, 3810)
 2112 ######################################################################
 2113 ICMPV6_MLD_TYPES="130 131 132 143"
 2114 
 2115 # Default conntrack match method, if needed the main script will
 2116 # fallback to an older method after the conntrack modules are loaded.
 2117 ######################################################################
 2118 NF_CONNTRACK_STATE="-m conntrack --ctstate"
 2119 
 2120 # Set system wide share path
 2121 ############################
 2122 if [ -z "$USR_SHARE_PATH" ]; then
 2123   USR_SHARE_PATH="/usr/local/share/arno-iptables-firewall"
 2124   if [ ! -d "$USR_SHARE_PATH" ]; then
 2125     USR_SHARE_PATH="/usr/share/arno-iptables-firewall"
 2126     if [ ! -d "$USR_SHARE_PATH" ]; then
 2127       echo "** ERROR: Unable to determine USR_SHARE_PATH!" >&2
 2128     fi
 2129   fi
 2130 fi
 2131 
 2132 # Check plugin bin path and fallback in case it's empty
 2133 #######################################################
 2134 if [ -z "$PLUGIN_BIN_PATH" ]; then
 2135   PLUGIN_BIN_PATH="$USR_SHARE_PATH/plugins"
 2136 fi
 2137 
 2138 # File containing (background) jobs to run
 2139 JOBS_FILE="/var/tmp/aif_jobs"
 2140 
 2141 # Lock file for accessing the JOBS_FILE
 2142 JOBS_LOCK_NAME="jobs"
 2143 
 2144 # Jobs process (file) name
 2145 JOB_PROCESSOR="$USR_SHARE_PATH/aif-job-processor"
 2146 
 2147 JOB_EXECUTER="$USR_SHARE_PATH/aif-job-execute"
 2148 
 2149 # Check plugin bin path and fallback in case it's empty
 2150 #######################################################
 2151 if [ -z "$PLUGIN_CONF_PATH" ]; then
 2152   if [ -d "/etc/arno-iptables-firewall/plugins" ]; then
 2153     PLUGIN_CONF_PATH="/etc/arno-iptables-firewall/plugins"
 2154   fi
 2155 fi
 2156 
 2157 # Check for EXT_NET_BCAST_ADDRESS and autodetect if empty
 2158 #########################################################
 2159 if [ -z "$EXT_NET_BCAST_ADDRESS" -a -n "$EXT_IF" ]; then
 2160   ext_count=0
 2161   IFS=' ,'
 2162   for eif in $EXT_IF; do
 2163     found=0
 2164     for eif1 in $(wildcard_ifs $eif); do
 2165       baddr="$(get_network_ipv4_broadcast "$eif1")"
 2166 
 2167       # NOTE: If no broadcast address found, then probably interface is not up (yet)
 2168       if [ -n "$baddr" ]; then
 2169         EXT_NET_BCAST_ADDRESS="${EXT_NET_BCAST_ADDRESS}${EXT_NET_BCAST_ADDRESS:+ }${baddr}"
 2170         found=1
 2171       fi
 2172     done
 2173 
 2174     ext_count=$((ext_count + 1))
 2175     if [ $found -eq 0 -a -n "$EXTERNAL_NET" ]; then
 2176       ext_net="$(echo "$EXTERNAL_NET" |awk "{ print \$$ext_count }")"
 2177 
 2178       case "$ext_net" in
 2179         */24) baddr="$(echo "$ext_net" |awk -F. '{ print $1"."$2"."$3".255" }')" ;;
 2180         */16) baddr="$(echo "$ext_net" |awk -F. '{ print $1"."$2".255.255" }')" ;;
 2181          */8) baddr="$(echo "$ext_net" |awk -F. '{ print $1".255.255.255" }')" ;;
 2182            *) baddr="" ;;
 2183       esac
 2184 
 2185       if [ -n "$baddr" ]; then
 2186         EXT_NET_BCAST_ADDRESS="${EXT_NET_BCAST_ADDRESS}${EXT_NET_BCAST_ADDRESS:+ }${baddr}"
 2187       fi
 2188     fi
 2189   done
 2190 fi
 2191 
 2192 # Check for EXTERNAL_NET and autodetect if empty
 2193 ################################################
 2194 if [ -z "$EXTERNAL_NET" -a -n "$EXT_IF" ]; then
 2195   IFS=' ,'
 2196   for eif in $EXT_IF; do
 2197     for eif1 in $(wildcard_ifs $eif); do
 2198       addr_mask="$(get_network_ipv4_address_mask "$eif1")"
 2199 
 2200       # NOTE: If no mask found, then probably interface is not up (yet)
 2201       if [ -n "$addr_mask" ]; then
 2202         EXTERNAL_NET="${EXTERNAL_NET}${EXTERNAL_NET:+ }${addr_mask}"
 2203       fi
 2204     done
 2205   done
 2206 fi