mirror of
https://gitlab.com/shorewall/code.git
synced 2025-08-18 04:35:33 +02:00
First cut at factoring out Shorewall-shell
git-svn-id: https://shorewall.svn.sourceforge.net/svnroot/shorewall/trunk@5818 fbd18981-670d-0410-9b5c-8dc0c1a9a2bb
This commit is contained in:
447
Shorewall-shell/lib.providers
Normal file
447
Shorewall-shell/lib.providers
Normal file
@@ -0,0 +1,447 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Shorewall 3.4 -- /usr/share/shorewall/lib.providers
|
||||
#
|
||||
# This program is under GPL [http://www.gnu.org/copyleft/gpl.htm]
|
||||
#
|
||||
# (c) 1999,2000,2001,2002,2003,2004,2005,2006,2007 - Tom Eastep (teastep@shorewall.net)
|
||||
#
|
||||
# Complete documentation is available at http://shorewall.net
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of Version 2 of the GNU General Public License
|
||||
# as published by the Free Software Foundation.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA
|
||||
#
|
||||
# This library is loaded by /usr/share/shorewall/compiler when the providers file is
|
||||
# non-empty.
|
||||
#
|
||||
|
||||
#
|
||||
# Process the providers file
|
||||
#
|
||||
setup_providers()
|
||||
{
|
||||
local table number mark duplicate interface gateway options provider address copy route loose addresses rulenum rulebase balance save_indent="$INDENT" mask= first=Yes save_indent1=
|
||||
|
||||
copy_table() {
|
||||
indent >&3 << __EOF__
|
||||
ip route show table $duplicate | while read net route; do
|
||||
case \$net in
|
||||
default|nexthop)
|
||||
;;
|
||||
*)
|
||||
run_ip route add table $number \$net \$route
|
||||
;;
|
||||
esac
|
||||
done
|
||||
__EOF__
|
||||
}
|
||||
|
||||
copy_and_edit_table() {
|
||||
indent >&3 << __EOF__
|
||||
ip route show table $duplicate | while read net route; do
|
||||
case \$net in
|
||||
default|nexthop)
|
||||
;;
|
||||
*)
|
||||
case \$(find_device \$route) in
|
||||
`echo $copy\) | sed 's/ /|/g'`
|
||||
run_ip route add table $number \$net \$route
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
__EOF__
|
||||
}
|
||||
|
||||
balance_default_route() # $1 = weight
|
||||
{
|
||||
balance=yes
|
||||
|
||||
save_command
|
||||
if [ -n "$first" ]; then
|
||||
if [ -n "$gateway" ] ; then
|
||||
save_command "DEFAULT_ROUTE=\"nexthop via $gateway dev $interface weight $1\""
|
||||
else
|
||||
save_command "DEFAULT_ROUTE=\"nexthop dev $interface weight $1\""
|
||||
fi
|
||||
|
||||
first=
|
||||
else
|
||||
if [ -n "$gateway" ] ; then
|
||||
save_command "DEFAULT_ROUTE=\"\$DEFAULT_ROUTE nexthop via $gateway dev $interface weight $1\""
|
||||
else
|
||||
save_command "DEFAULT_ROUTE=\"\$DEFAULT_ROUTE nexthop dev $interface weight $1\""
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
add_a_provider() {
|
||||
local t n iface option optional=
|
||||
|
||||
[ -n "$MANGLE_ENABLED" ] || fatal_error "Providers require mangle support in your kernel and iptables"
|
||||
|
||||
for t in $PROVIDERS local main default unspec; do
|
||||
if [ "$t" = "$table" ]; then
|
||||
fatal_error "Duplicate Provider: $table, provider: \"$provider\""
|
||||
fi
|
||||
|
||||
eval n=\$${t}_number
|
||||
#
|
||||
# The following is because the %$#@ shell doesn't accept hex numbers in '-eq' tests
|
||||
#
|
||||
if [ $(($n)) -eq $(($number)) ]; then
|
||||
fatal_error "Duplicate Provider number: $number, provider: \"$provider\""
|
||||
fi
|
||||
done
|
||||
|
||||
eval ${table}_number=$number
|
||||
|
||||
indent >&3 << __EOF__
|
||||
#
|
||||
# Add Provider $table ($number)
|
||||
#
|
||||
__EOF__
|
||||
save_command "if interface_is_usable $interface; then"
|
||||
save_indent1="$INDENT"
|
||||
INDENT="$INDENT "
|
||||
|
||||
iface=$(chain_base $interface)
|
||||
|
||||
save_command "${iface}_up=Yes"
|
||||
|
||||
save_command "qt ip route flush table $number"
|
||||
|
||||
indent >&3 << __EOF__
|
||||
echo "qt ip route flush table $number" >> \${VARDIR}/undo_routing
|
||||
__EOF__
|
||||
|
||||
if [ "x${duplicate:=-}" != x- ]; then
|
||||
if [ "x${copy:=-}" != "x-" ]; then
|
||||
if [ "x${copy}" = xnone ]; then
|
||||
copy=$interface
|
||||
else
|
||||
copy="$interface $(separate_list $copy)"
|
||||
fi
|
||||
copy_and_edit_table
|
||||
else
|
||||
copy_table
|
||||
fi
|
||||
elif [ "x${copy:=-}" != x- ]; then
|
||||
fatal_error "A non-empty COPY column requires that a routing table be specified in the DUPLICATE column"
|
||||
fi
|
||||
|
||||
if [ "x$gateway" = xdetect ] ; then
|
||||
gateway='$gateway'
|
||||
indent >&3 << __EOF__
|
||||
gateway=\$(detect_gateway $interface)
|
||||
|
||||
if [ -n "\$gateway" ]; then
|
||||
run_ip route replace \$gateway src \$(find_first_interface_address $interface) dev $interface table $number
|
||||
run_ip route add default via \$gateway dev $interface table $number
|
||||
else
|
||||
fatal_error "Unable to detect the gateway through interface $interface"
|
||||
fi
|
||||
|
||||
__EOF__
|
||||
elif [ "x$gateway" != "x-" -a -n "$gateway" ]; then
|
||||
indent >&3 << __EOF__
|
||||
run_ip route replace $gateway src \$(find_first_interface_address $interface) dev $interface table $number
|
||||
run_ip route add default via $gateway dev $interface table $number
|
||||
__EOF__
|
||||
else
|
||||
gateway=
|
||||
save_command "run_ip route add default dev $interface table $number"
|
||||
fi
|
||||
|
||||
if [ x${mark} != x- ]; then
|
||||
verify_mark $mark
|
||||
|
||||
if [ $(($mark)) -lt 256 ]; then
|
||||
if [ -n "$HIGH_ROUTE_MARKS" ]; then
|
||||
fatal_error "Invalid Mark Value ($mark) with HIGH_ROUTE_MARKS=Yes"
|
||||
fi
|
||||
elif [ -z "$HIGH_ROUTE_MARKS" ]; then
|
||||
fatal_error "Invalid Mark Value ($mark) with HIGH_ROUTE_MARKS=No"
|
||||
fi
|
||||
|
||||
eval ${table}_mark=$mark
|
||||
|
||||
indent >&3 << __EOF__
|
||||
qt ip rule del fwmark $mark
|
||||
run_ip rule add fwmark $mark pref $((10000 + $mark)) table $number
|
||||
echo "qt ip rule del fwmark $mark" >> \${VARDIR}/undo_routing
|
||||
__EOF__
|
||||
fi
|
||||
|
||||
loose=
|
||||
|
||||
for option in $(separate_list $options); do
|
||||
case $option in
|
||||
-)
|
||||
;;
|
||||
track)
|
||||
list_search $interface $ROUTEMARK_INTERFACES && \
|
||||
fatal_error "Interface $interface is tracked through an earlier provider"
|
||||
[ x${mark} = x- ] && fatal_error "The 'track' option requires a numeric value in the MARK column - Provider \"$provider\""
|
||||
eval ${iface}_routemark=$mark
|
||||
ROUTEMARK_INTERFACES="$ROUTEMARK_INTERFACES $interface"
|
||||
;;
|
||||
balance=*)
|
||||
balance_default_route ${option#*=}
|
||||
;;
|
||||
balance)
|
||||
balance_default_route 1
|
||||
;;
|
||||
loose)
|
||||
loose=Yes
|
||||
;;
|
||||
optional)
|
||||
optional=Yes
|
||||
;;
|
||||
*)
|
||||
error_message "WARNING: Invalid option ($option) ignored in provider \"$provider\""
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
rulenum=0
|
||||
|
||||
if [ -z "$loose" ]; then
|
||||
rulebase=$(( 20000 + ( 256 * ($number-1) ) ))
|
||||
indent >&3 << __EOF__
|
||||
|
||||
rulenum=0
|
||||
|
||||
find_interface_addresses $interface | while read address; do
|
||||
qt ip rule del from \$address
|
||||
run_ip rule add from \$address pref \$(( $rulebase + \$rulenum )) table $number
|
||||
echo "qt ip rule del from \$address" >> \${VARDIR}/undo_routing
|
||||
rulenum=\$((\$rulenum + 1))
|
||||
done
|
||||
__EOF__
|
||||
else
|
||||
indent >&3 << __EOF__
|
||||
|
||||
find_interface_addresses $interface | while read address; do
|
||||
qt ip rule del from \$address
|
||||
done
|
||||
__EOF__
|
||||
[ -n "$balance" ] && error_message "WARNING: 'balance' and 'loose' should not be specified together - Provider \"$provider\""
|
||||
fi
|
||||
|
||||
|
||||
indent >&3 << __EOF__
|
||||
|
||||
progress_message " Provider $table ($number) Added"
|
||||
|
||||
__EOF__
|
||||
|
||||
INDENT="$save_indent1"
|
||||
save_command else
|
||||
|
||||
if [ -n "$optional" ]; then
|
||||
save_command " error_message \"WARNING: Interface $interface is not configured -- Provider $table ($number) not Added\""
|
||||
save_command " ${iface}_up="
|
||||
else
|
||||
save_command " fatal_error \"ERROR: Interface $interface is not configured -- Provider $table ($number) Cannot be Added\""
|
||||
fi
|
||||
|
||||
save_command fi
|
||||
save_command
|
||||
|
||||
}
|
||||
|
||||
verify_provider()
|
||||
{
|
||||
local p n
|
||||
|
||||
for p in $PROVIDERS main; do
|
||||
[ "$p" = "$1" ] && return 0
|
||||
eval n=\$${p}_number}
|
||||
[ "$n" = "$1" ] && return 0
|
||||
done
|
||||
|
||||
fatal_error "Unknown provider $1 in route rule \"$rule\""
|
||||
}
|
||||
|
||||
add_an_rtrule()
|
||||
{
|
||||
verify_provider $provider
|
||||
|
||||
[ "x$source" = x- ] && source=
|
||||
[ "x$dest" = x- ] && dest= || dest="to $dest"
|
||||
|
||||
[ -n "${source}${dest}" ] || fatal_error "You must specify either the source or destination in an rt rule: \"$rule\""
|
||||
|
||||
[ -n "$source" ] && case $source in
|
||||
*:*)
|
||||
source="iif ${source%:*} from ${source#*:}"
|
||||
;;
|
||||
*.*.*)
|
||||
source="from $source"
|
||||
;;
|
||||
*)
|
||||
source="iif $source"
|
||||
;;
|
||||
esac
|
||||
|
||||
case "$priority" in
|
||||
[0-9][0-9][0-9][0-9]|[0-9][0-9][0-9][0-9][0-9])
|
||||
;;
|
||||
*)
|
||||
fatal_error "Invalid priority ($priority) in rule \"$rule\""
|
||||
;;
|
||||
esac
|
||||
|
||||
priority="priority $priority"
|
||||
|
||||
save_command "qt ip rule del $source $dest $priority"
|
||||
save_command "run_ip rule add $source $dest $priority table $provider"
|
||||
indent >&3 << __EOF__
|
||||
echo "qt ip rule del $source $dest $priority" >> \${VARDIR}/undo_routing
|
||||
__EOF__
|
||||
progress_message "Routing rule \"$rule\" $DONE"
|
||||
}
|
||||
#
|
||||
# E x e c u t i o n B e g i n s H e r e
|
||||
#
|
||||
local_number=255
|
||||
main_number=254
|
||||
default_number=253
|
||||
unspec_number=0
|
||||
balance=
|
||||
|
||||
progress_message2 "$DOING $1..."
|
||||
save_command
|
||||
save_command "if [ -z \"\$NOROUTES\" ]; then"
|
||||
INDENT="$INDENT "
|
||||
indent >&3 << __EOF__
|
||||
#
|
||||
# Undo any changes made since the last time that we [re]started -- this will not restore the default route
|
||||
#
|
||||
undo_routing
|
||||
#
|
||||
# Save current routing table database so that it can be restored later
|
||||
#
|
||||
cp /etc/iproute2/rt_tables \${VARDIR}/
|
||||
#
|
||||
# Capture the default route(s) if we don't have it (them) already.
|
||||
#
|
||||
[ -f \${VARDIR}/default_route ] || ip route ls | grep -E '^\s*(default |nexthop )' > \${VARDIR}/default_route
|
||||
#
|
||||
# Initialize the file that holds 'undo' commands
|
||||
#
|
||||
> \${VARDIR}/undo_routing
|
||||
__EOF__
|
||||
save_progress_message "Adding Providers..."
|
||||
save_command "DEFAULT_ROUTE="
|
||||
|
||||
while read table number mark duplicate interface gateway options copy; do
|
||||
provider="$table $number $mark $duplicate $interface $gateway $options $copy"
|
||||
add_a_provider
|
||||
PROVIDERS="$PROVIDERS $table"
|
||||
progress_message "Provider $provider $DONE"
|
||||
done < $TMP_DIR/providers
|
||||
|
||||
if [ -n "$PROVIDERS" ]; then
|
||||
if [ -n "$balance" ]; then
|
||||
save_command "if [ -n \"\$DEFAULT_ROUTE\" ]; then"
|
||||
save_command " run_ip route replace default scope global \$DEFAULT_ROUTE"
|
||||
save_command " progress_message \"Default route '\$(echo \$DEFAULT_ROUTE | sed 's/\$\\s*//')' Added\""
|
||||
save_command "else"
|
||||
save_command " error_message \"WARNING: No Default route added (all 'balance' providers are down)\""
|
||||
save_command " restore_default_route"
|
||||
save_command "fi"
|
||||
save_command
|
||||
else
|
||||
save_command "#"
|
||||
save_command "# We don't have any 'balance' providers so we retore any default route that we've saved"
|
||||
save_command "#"
|
||||
save_command restore_default_route
|
||||
fi
|
||||
|
||||
cat >&3 << __EOF__
|
||||
${INDENT}cat > /etc/iproute2/rt_tables <<EOF
|
||||
#
|
||||
# reserved values
|
||||
#
|
||||
255 local
|
||||
254 main
|
||||
253 default
|
||||
0 unspec
|
||||
#
|
||||
# local
|
||||
#
|
||||
EOF
|
||||
|
||||
${INDENT}echocommand=\$(find_echo)
|
||||
__EOF__
|
||||
for table in $PROVIDERS; do
|
||||
eval number=\$${table}_number
|
||||
indent >&3 << __EOF__
|
||||
\$echocommand "$number\t$table" >> /etc/iproute2/rt_tables
|
||||
__EOF__
|
||||
done
|
||||
|
||||
if [ -s $TMP_DIR/route_rules ]; then
|
||||
progress_message2 "$DOING $(find_file route_rules)..."
|
||||
|
||||
save_command
|
||||
|
||||
while read source dest provider priority; do
|
||||
rule="$source $dest $priority $provider"
|
||||
add_an_rtrule
|
||||
done < $TMP_DIR/route_rules
|
||||
fi
|
||||
fi
|
||||
|
||||
save_command
|
||||
save_command "run_ip route flush cache"
|
||||
INDENT="$save_indent"
|
||||
save_command "fi"
|
||||
save_command
|
||||
}
|
||||
|
||||
#
|
||||
# Set up Route marking (Only called if $ROUTEMARK_INTERFACES is non-empty)
|
||||
#
|
||||
setup_route_marking()
|
||||
{
|
||||
local mask=0xFF mark_op="--set-mark" save_indent="$INDENT"
|
||||
|
||||
[ -n "$HIGH_ROUTE_MARKS" ] && mask=0xFF00 && mark_op="--or-mark"
|
||||
|
||||
run_iptables -t mangle -A PREROUTING -m connmark ! --mark 0/$mask -j CONNMARK --restore-mark --mask $mask
|
||||
run_iptables -t mangle -A OUTPUT -m connmark ! --mark 0/$mask -j CONNMARK --restore-mark --mask $mask
|
||||
createmanglechain routemark
|
||||
|
||||
for interface in $ROUTEMARK_INTERFACES ; do
|
||||
iface=$(chain_base $interface)
|
||||
eval mark_value=\$${iface}_routemark
|
||||
|
||||
save_command
|
||||
save_command "if [ -n \"\$${iface}_up\" ]; then"
|
||||
INDENT="$INDENT "
|
||||
run_iptables -t mangle -A PREROUTING -i $interface -m mark --mark 0/$mask -j routemark
|
||||
run_iptables -t mangle -A routemark -i $interface -j MARK $mark_op $mark_value
|
||||
INDENT="$save_indent"
|
||||
save_command "fi"
|
||||
done
|
||||
|
||||
save_command
|
||||
|
||||
run_iptables -t mangle -A routemark -m mark ! --mark 0/$mask -j CONNMARK --save-mark --mask $mask
|
||||
|
||||
}
|
Reference in New Issue
Block a user