Makefile, base.m4: Inject the target hostname into the generated script.
[firewall] / functions.m4
index 484c30d..05decbf 100644 (file)
@@ -50,6 +50,14 @@ defport () {
   eval port_$name=$number
 }
 
+## defproto NAME NUMBER
+##
+## Define $proto_NAME to be NUMBER.
+defproto () {
+  name=$1 number=$2
+  eval proto_$name=$number
+}
+
 m4_divert(38)m4_dnl
 ###--------------------------------------------------------------------------
 ### Utility chains (used by function definitions).
@@ -77,10 +85,23 @@ clearchain () {
       *:*) table=${chain%:*} chain=${chain#*:} ;;
       *) table=filter ;;
     esac
-    run ip46tables -t $table -N $chain
+    run ip46tables -t $table -N $chain 2>/dev/null || :
   done
 }
 
+## makeset SET TYPE [PARAMS]
+##
+## Ensure that the named ipset exists.  Don't clear it.
+makeset () {
+  set -e
+  name=$1; shift
+  if ipset -nL | grep -q "^Name: $name$"; then
+    :
+  else
+    ipset -N "$name" "$@"
+  fi
+}
+
 ## errorchain CHAIN ACTION ARGS ...
 ##
 ## Make a chain which logs a message and then invokes some other action,
@@ -96,7 +117,9 @@ errorchain () {
   run ip46tables -t $table -A $chain -j LOG \
          -m limit --limit 3/minute --limit-burst 10 \
          --log-prefix "fw: $chain " --log-level notice
-  run ip46tables -t $table -A $chain -j "$@"
+  run ip46tables -t $table -A $chain -j "$@" \
+         -m limit --limit 20/second --limit-burst 100
+  run ip46tables -t $table -A $chain -j DROP
 }
 
 m4_divert(24)m4_dnl
@@ -108,19 +131,50 @@ m4_divert(24)m4_dnl
 ## Set an IP sysctl.
 setopt () {
   set -e
-  opt=$1; shift; val=$*
-  run sysctl -q net/ipv4/$opt="$val"
+  opt=$1 val=$2
+  any=nil
+  for ver in ipv4 ipv6; do
+    if [ -f /proc/sys/net/$ver/$opt ]; then
+      run sysctl -q net/$ver/$opt="$val"
+      any=t
+    fi
+  done
+  case $any in
+    nil) echo >&2 "$0: unknown IP option $opt"; exit 1 ;;
+  esac
 }
 
-## setdevopt OPTION VALUE
+## setdevopt OPTION VALUE [INTERFACES ...]
 ##
 ## Set an IP interface-level sysctl.
 setdevopt () {
   set -e
-  opt=$1; shift; val=$*
-  for i in /proc/sys/net/ipv4/conf/*; do
-    [ -f $i/$opt ] &&
-      run sysctl -q net/ipv4/conf/${i#/proc/sys/net/ipv4/conf/}/$opt="$val"
+  opt=$1 val=$2; shift 2
+  case "$#,$1" in
+    0, | 1,all)
+      set -- $(
+       seen=:
+       for ver in ipv4 ipv6; do
+         cd /proc/sys/net/$ver/conf
+         for i in *; do
+           [ -f $i/$opt ] || continue
+           case "$seen" in (*:$i:*) continue ;; esac
+           echo $i
+         done
+       done)
+      ;;
+  esac
+  for i in "$@"; do
+    any=nil
+    for ver in ipv4 ipv6; do
+      if [ -f /proc/sys/net/$ver/conf/$i/$opt ]; then
+       any=t
+       run sysctl -q net/ipv4/conf/$i/$opt="$val"
+      fi
+    done
+    case $any in
+      nil) echo >&2 "$0: unknown device option $opt"; exit 1 ;;
+    esac
   done
 }
 
@@ -344,7 +398,7 @@ defnetclass () {
 ## As a special case, the NETWORK/MASK can be the string `default', which
 ## indicates that all addresses not matched elsewhere should be considered.
 ifaces=:
-defaultiface=none
+defaultifaces=""
 allnets= allnets6=
 defiface () {
   set -e
@@ -365,9 +419,16 @@ defiface () {
       netclass=${item%:*} addr=${item#*:}
       case $addr in
        default)
-         defaultiface=$name
-         defaultclass=$netclass
-         run ip46tables -t mangle -A out-classify -g mark-to-$netclass
+         case "$defaultifaces,$defaultclass" in
+           ,* | *,$netclass)
+             defaultifaces="$defaultifaces $name"
+             defaultclass=$netclass
+             ;;
+           *)
+             echo >&2 "$0: inconsistent default netclasses"
+             exit 1
+             ;;
+         esac
          ;;
        *:*)
          run ip6tables -t mangle -A in-$name -g mark-from-$netclass \