## -*- mode: shell-script; -*-
##
## To be able to make changes to the part of configuration created
## from this configlet you need to copy this file to the directory
## fwbuilder/configlets/linux24/ in your home directory and modify it.
## Double "##" comments are removed during processing but single "#"
## comments are be retained and appear in the generated script. Empty
## lines are removed as well.
##
## Configlets support simple macro language with these constructs:
## {{$var}} is variable expansion
## {{if var}} is conditional operator.
##
## The three conditional blocks below hang their {{if}} and {{endif}} on
## the end of a line rather than standing on one of their own: a block
## that is left out otherwise leaves the newline in front of it and the
## one behind it, and a script with no IPv6 route would gain three blank
## lines it never had.
##

# ============== ROUTING RULES ==============

HAVE_MKTEMP=$(command -v mktemp)

test -n "$HAVE_MKTEMP" && {
  TMPDIRNAME=$(mktemp -d)
  test -z "$TMPDIRNAME" && exit 1
}

test -z "$HAVE_MKTEMP" && {
  TMPDIRNAME="/tmp/.fwbuilder.tempdir.$$"
  (umask 077 && mkdir "$TMPDIRNAME") || exit 1
}

TMPFILENAME="$TMPDIRNAME/.fwbuilder.out"
OLD_ROUTES="$TMPDIRNAME/.old_routes"

#
# This function stops stdout redirection
# and sends previously saved output to terminal
restore_script_output()
{
  exec 1>&3 2>&1
  cat "$TMPFILENAME"
  rm -rf "$TMPDIRNAME"
}

# if any routing rule fails we do our best to prevent freezing the firewall
route_command_error()
{
  echo "Error: Routing rule $1 couldn't be activated"
  echo "Recovering previous routing configuration..."
  # delete current routing rules
  # A route is several arguments, so the expansion is split on purpose.
  # shellcheck disable=SC2086
  "$IP" -o route show | tr -d '\134' | while read -r route ; do "$IP" route del $route ; done{{if have_ipv6_routes}}
  # shellcheck disable=SC2086
  "$IP" -o -6 route show | tr -d '\134' | while read -r route ; do "$IP" -6 route del $route ; done{{endif}}
  # restore old routing rules
  sh "$OLD_ROUTES"
  echo "...done"
  restore_script_output
  epilog_commands
  exit 1
}

# redirect output to prevent ssh session from stalling
exec 3>&1
exec 1> "$TMPFILENAME"
exec 2>&1

# store previous routing configuration (sort: 'via' GW has to be
# inserted after device routes).  "-o" puts a route with several next
# hops on one line, where "ip route show" spreads it over one line per
# hop: read line by line, "default" and "nexthop via ..." are three
# commands, and the two the loops below would build out of the tail are
# not routes at all.  The separator "-o" writes in their place is a
# backslash, which is not part of any route and is spelled in octal
# because shellcheck reads a doubled one inside single quotes as an
# attempt at escaping the quote (SC1003).

"$IP" -o route show | tr -d '\134' | sort -k 2 | awk '{printf "ip route add %s\n",$0;}' > "$OLD_ROUTES"{{if have_ipv6_routes}}
# "ip route" is the IPv4 table and nothing else, and this script installs
# an IPv6 route as well, so the other table is saved, cleared and put back
# beside it - or the route is still there on the next activation and
# "ip -6 route add" answers "File exists", which stops the script.
"$IP" -o -6 route show | tr -d '\134' | sort -k 2 | awk '{printf "ip -6 route add %s\n",$0;}' >> "$OLD_ROUTES"{{endif}}

echo "Deleting routing rules previously set by user space processes..."
# A route is several arguments, so the expansion is split on purpose.
# shellcheck disable=SC2086
"$IP" -o route show | tr -d '\134' | grep -v {{$proto_filter}} | \
    while read -r route ; do "$IP" route del $route ; done{{if have_ipv6_routes}}
# shellcheck disable=SC2086
"$IP" -o -6 route show | tr -d '\134' | grep -v {{$proto_filter6}} | \
    while read -r route ; do "$IP" -6 route del $route ; done{{endif}}

echo "Activating non-ecmp routing rules..."
