contrib/freifunk-policyrouting: Almost complete rewrite, use ip only (no firewall depencies).

This commit is contained in:
Manuel Munz 2013-03-20 02:53:14 +00:00
parent f804a21c8d
commit 6efd34e9ec
5 changed files with 229 additions and 225 deletions

View file

@ -4,7 +4,7 @@
include $(TOPDIR)/rules.mk include $(TOPDIR)/rules.mk
PKG_NAME:=freifunk-policyrouting PKG_NAME:=freifunk-policyrouting
PKG_RELEASE:=1 PKG_RELEASE:=2
PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME) PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)
@ -15,7 +15,7 @@ define Package/freifunk-policyrouting
CATEGORY:=LuCI CATEGORY:=LuCI
SUBMENU:=9. Freifunk SUBMENU:=9. Freifunk
TITLE:=Freifunk policy routing addon TITLE:=Freifunk policy routing addon
DEPENDS:=+firewall +ip DEPENDS:=+ip
endef endef
define Package/freifunk-policyrouting/description define Package/freifunk-policyrouting/description

View file

@ -1,116 +0,0 @@
if [ "$ACTION" = "add" ] && [ "$INTERFACE" = "wan" ]; then
pr=`uci get freifunk-policyrouting.pr.enable`
strict=`uci get freifunk-policyrouting.pr.strict`
zones=`uci get freifunk-policyrouting.pr.zones`
[ -f /proc/net/ipv6_route ] && has_ipv6=1
if [ $pr = "1" ]; then
# The wan device name
if [ -n "`uci -p /var/state get network.wan.ifname`" ]; then
wandev=`uci -p /var/state get network.wan.ifname`
else
wandev=`uci -p /var/state get network.wan.device`
fi
iptables -t mangle -D PREROUTING -j prerouting_policy > /dev/null 2>&1
iptables -t mangle -F prerouting_policy > /dev/null 2>&1
iptables -t mangle -N prerouting_policy > /dev/null 2>&1
iptables -t mangle -I PREROUTING -j prerouting_policy > /dev/null 2>&1
if [ "$has_ipv6" = 1 ]; then
ip6tables -t mangle -D PREROUTING -j prerouting_policy > /dev/null 2>&1
ip6tables -t mangle -F prerouting_policy > /dev/null 2>&1
ip6tables -t mangle -N prerouting_policy > /dev/null 2>&1
ip6tables -t mangle -I PREROUTING -j prerouting_policy > /dev/null 2>&1
fi
# If no route is in table olsr-default, then usually the hosts local default route is used.
# If set to strict then we add a filter which prevents this
if [ "$strict" == "1" ]; then
ln=$(( `iptables -L FORWARD -v --line-numbers | grep -m 1 reject | awk {' print $1 '}` - 1 ))
if [ ! $ln -gt 0 ]; then
ln=1
fi
if [ -z "`iptables -L |grep 'Chain forward_policy'`" ]; then
iptables -N forward_policy
fi
if [ -z "`iptables -L FORWARD -v |grep forward_policy`" ]; then
iptables -I FORWARD $ln -m mark --mark 1 -j forward_policy
fi
iptables -F forward_policy
iptables -I forward_policy -o $wandev -j REJECT --reject-with icmp-net-prohibited
if [ "$has_ipv6" = 1 ]; then
ln=$(( `ip6tables -L FORWARD -v --line-numbers | grep -m 1 reject | awk {' print $1 '}` - 1 ))
if [ ! $ln -gt 0 ]; then
ln=1
fi
if [ -z "`ip6tables -L |grep 'Chain forward_policy'`" ]; then
ip6tables -N forward_policy
fi
if [ -z "`ip6tables -L FORWARD -v |grep forward_policy`" ]; then
ip6tables -I FORWARD $ln -m mark --mark 1 -j forward_policy
fi
ip6tables -F forward_policy
ip6tables -I forward_policy -o $wandev -j REJECT
fi
fi
# set mark 1 for all packets coming in via enabled zones
for i in $zones; do
# find out which interfaces belong to this zone
zone=`uci show firewall |grep "name=$i" |awk {' FS="."; print $1"."$2 '}`
interfaces=`uci get $zone.network`
if [ "$interfaces" == "" ]; then
interfaces=$i
fi
for int in $interfaces; do
if [ "`uci -q get network.$int.type`" == "bridge" ]; then
dev="br-$int"
else
if [ -n "`uci -p /var/state get network.$int.ifname`" ]; then
dev=`uci -p /var/state get network.$int.ifname`
else
dev=`uci -p /var/state get network.$int.device`
fi
fi
logger -t policyrouting "Add mark 1 to packages coming in via interface $dev"
iptables -t mangle -I prerouting_policy -i $dev -j MARK --set-mark 1
if [ "$has_ipv6" = 1 ]; then
ip6tables -t mangle -I prerouting_policy -i $dev -j MARK --set-mark 1
fi
done
done
else
# Cleanup policy routing stuff that might be lingering around
if [ -n "`iptables -t mangle -L PREROUTING |grep _policy`" ]; then
logger -t policyrouting "Delete prerouting_policy chain in table mangle (IPv4)"
iptables -t mangle -D PREROUTING -j prerouting_policy
iptables -t mangle -F prerouting_policy
iptables -t mangle -X prerouting_policy
fi
if [ -n "`iptables -L FORWARD |grep forward_policy`" ]; then
logger -t policyrouting "Delete strict forwarding rules (IPv4)"
iptables -D FORWARD -m mark --mark 1 -j forward_policy
iptables -F forward_policy
iptables -X forward_policy
fi
if [ "$has_ipv6" = 1 ]; then
if [ -n "`ip6tables -t mangle -L PREROUTING |grep _policy`" ]; then
logger -t policyrouting "Delete prerouting_policy chain in table mangle (IPv6)"
ip6tables -t mangle -D PREROUTING -j prerouting_policy
ip6tables -t mangle -F prerouting_policy
ip6tables -t mangle -X prerouting_policy
fi
if [ -n "`ip6tables -L FORWARD |grep forward_policy`" ]; then
logger -t policyrouting "Delete strict forwarding rules (IPv6)"
ip6tables -D FORWARD -m mark --mark 1 -j forward_policy
ip6tables -F forward_policy
ip6tables -X forward_policy
fi
fi
logger -t policyrouting "All firewall rules for policyrouting removed."
fi
fi

View file

@ -1,109 +1,99 @@
[ "$INTERFACE" != "wan" ] && exit 0 #!/bin/sh
[ -f /proc/net/ipv6_route ] && has_ipv6=1
olsrd_rmtables() { . /lib/functions.sh
# Remove custom routing tables from olsrd . /lib/functions/network.sh
if [ "`uci -q get olsrd.@olsrd[0].RtTable`" == "111" ] || [ "`uci -q get olsrd.@olsrd[0].RtTableDefault`" == "112" ]; then
uci delete olsrd.@olsrd[0].RtTable
uci delete olsrd.@olsrd[0].RtTableDefault
uci commit
/etc/init.d/olsrd restart
fi
}
case $ACTION in proto="4"
ifup) [ -f /proc/net/ipv6_route ] && proto="4 6"
pr="`uci get freifunk-policyrouting.pr.enable`"
fallback="`uci get freifunk-policyrouting.pr.fallback`"
# check if ipv6 is enabled:
if [ $pr = "1" ]; then config_load freifunk-policyrouting
logger -s -t policyrouting "Starting policy routing on $INTERFACE" config_get enable pr enable
config_get fallback pr fallback
config_get zones pr zones
# Setup new tables if [ "$ACTION" = "ifup" ] && [ "$enable" = "1" ]; then
tables="/etc/iproute2/rt_tables" network_get_subnet net $INTERFACE
if [ -z "`grep "111" $tables`" ]; then network_get_subnet6 net6 $INTERFACE
echo "111 olsr" >> $tables network_get_physdev dev $INTERFACE
fi
if [ -z "`grep "112" $tables`" ]; then
echo "112 olsr-default" >> $tables
fi
# Make sure Rt_tables in olsrd are in place if [ "$net" != "" -a -n "$dev" ]; then
if [ ! "`uci -q get olsrd.@olsrd[0].RtTable`" == "111" ] || [ ! "`uci -q get olsrd.@olsrd[0].RtTableDefault`" == "112" ]; then eval $(/bin/ipcalc.sh $net)
uci set olsrd.@olsrd[0].RtTable='111' if [ "$PREFIX" != "0" ]; then
uci set olsrd.@olsrd[0].RtTableDefault='112' if [ ! "$(ip r s t olsr-default |grep "throw $NETWORK/$PREFIX")" ]; then
uci commit ip r a throw $NETWORK/$PREFIX table olsr-default
/etc/init.d/olsrd restart if [ "$?" = 0 ]; then
fi logger -s -t policyrouting "Add route: throw $NETWORK/$PREFIX table olsr-default"
# Disable dyn_gw and dyngw_plain
dyngwlib=`uci show olsrd |grep dyn_gw.so |awk {' FS="."; print $1"."$2 '}`
if [ -n "$dyngwlib" ]; then
uci set $dyngwlib.ignore=1
uci commit
fi
dyngwplainlib=`uci show olsrd |grep dyn_gw_plain |awk {' FS="."; print $1"."$2 '}`
if [ -n "$dyngwplainlib" ]; then
uci set $dyngwplainlib.ignore=1
uci commit
fi
gw="$(ip r |grep default | cut -d " " -f 3)"
# if no gateway was found stop now
[ -z "$gw" ] && logger -s -t policyrouting "No gateway found" && exit 1
device="`uci -q -p /var/state get network.wan.ifname`"
[ -z "$device" ] && device="`uci -q -p /var/state get network.wan.device`"
[ -z "$device" ] && logger -s -t policyrouting "No device found for wan." && exit 1
test -n "`ip r s t default`" && ip r d default t default
test -n "`ip r s |grep default`" && ip route del default
ip route add default via $gw dev $device table default
if [ "$has_ipv6" = 1 ]; then
local ip6gw=$(ip -6 r |grep default |cut -d " " -f 3)
test -n "`ip -6 r s t default`" && ip -6 r d default t default
if [ -n "`ip -6 r s |grep default`" ]; then
ip -6 route del default
ip -6 r a $ip6gw via $ip6gw dev $dev table default
ip -6 route add default via $ip6gw dev $device table default
fi
fi
ip rule del lookup main
ip rule add fwmark 1 lookup olsr-default
ip rule add lookup main
ip rule add lookup olsr
# Fallback via mesh if no ipv4 gateway is found in default table
[ "$fallback" = 1 ] && ip rule add lookup olsr-default prio 32800
if [ "$has_ipv6" = 1 ]; then
ip -6 rule del lookup main
ip -6 rule add lookup olsr prio 16380
ip -6 rule add lookup main prio 16390
ip -6 rule add fwmark 1 lookup olsr-default prio 16400
ip -6 rule add lookup default prio 16410
[ "$fallback" = 1 ] && ip -6 rule add lookup olsr-default prio 16420
fi
else else
olsrd_rmtables logger -s -t policyrouting "Error! Could not add route: throw $NETWORK/$PREFIX table olsr-default"
fi
fi
fi fi
;;
ifdown) if [ -n "$net6" ]; then
logger -s -t policyrouting "Deleting ipv4 policy rules for $INTERFACE" if [ ! "$(ip -6 r s t olsr-default |grep "throw $net6")" ]; then
olsrd_rmtables rule="throw $net6 table olsr-default dev $dev"
ip rule del fwmark 1 lookup olsr-default > /dev/null 2>&1 ip -6 r a $rule
ip rule del lookup olsr-default > /dev/null 2>&1 if [ "$?" = 0 ]; then
ip rule del lookup olsr > /dev/null 2>&1 logger -s -t policyrouting "Add route: $rule (IPv6)"
if [ "$has_ipv6" = 1 ]; then else
logger -s -t policyrouting "Deleting ipv4 policy rules for $INTERFACE" logger -s -t policyrouting "Error! Could not add route: $rule (IPv6)"
ip -6 rule del fwmark 1 lookup olsr-default > /dev/null 2>&1 fi
ip -6 rule del lookup olsr-default > /dev/null 2>&1 fi
ip -6 rule del lookup olsr > /dev/null 2>&1 fi
ip -6 rule del lookup default > /dev/null 2>&1
networks=""
for z in $zones; do
network_zone="$(uci -q get firewall.zone_${z}.network)"
if [ -z "$network_zone" ]; then
network_zone="$z"
fi
networks="$networks $network_zone"
done
for n in $networks; do
if [ "$INTERFACE" = "$n" ]; then
for p in $proto; do
if [ ! "$(ip -$p ru s | grep "from all iif $dev lookup olsr-default")" ]; then
ip -$p rule add dev "$dev" lookup olsr-default prio 20000
if [ "$?" = 0 ]; then
logger -s -t policyrouting "Use mesh gateway for interface $dev (IPv$p)"
if [ -z "$(uci -P /var/state get freifunk-policyrouting.${INTERFACE})" ]; then
uci -P /var/state set freifunk-policyrouting.${INTERFACE}="state"
fi
uci -P /var/state set freifunk-policyrouting.${INTERFACE}.device="$dev"
else
logger -s -t policyrouting "Error: Could not add rule: dev "$dev" lookup olsr-default prio 20000 (IPv$p)"
fi
fi
done
fi
done
fi
fi
if [ "$ACTION" = "ifdown" ]; then
dev="$(uci -q -P /var/state get freifunk-policyrouting.${INTERFACE}.device)"
if [ -n "$dev" ]; then
networks=""
for z in $zones; do
network_zone="$(uci -q get firewall.zone_${z}.network)"
if [ -z "$network_zone" ]; then
network_zone="$z"
fi
networks="$networks $network_zone"
done
for n in $networks; do
if [ "$INTERFACE" = "$n" ]; then
for p in $proto; do
if [ "$(ip -$p ru s | grep "from all iif $dev lookup olsr-default")" ]; then
ip -$p rule del dev "$dev" lookup olsr-default prio 20000
if [ "$?" = 0 ]; then
logger -s -t policyrouting "Remove rule: dev "$dev" lookup olsr-default prio 20000 (IPv$p)"
else
logger -s -t policyrouting "Error! Could not remove rule: dev "$dev" lookup olsr-default prio 20000 (IPv$p)"
fi
fi
done
fi
done
fi
fi fi
;;
esac

View file

@ -1,13 +1,143 @@
#!/bin/sh /etc/rc.common #!/bin/sh /etc/rc.common
START=60 START=15
. /lib/functions/network.sh . /lib/functions/network.sh
boot() . /lib/functions.sh
{
prenabled=$(uci get freifunk-policyrouting.pr.enable) proto="4"
if [ ! "$prenabled" = "1" ] || ! network_is_up wan; then [ -f /proc/net/ipv6_route ] && proto="4 6"
uci -q delete olsrd.@olsrd[0].RtTable
uci -q delete olsrd.@olsrd[0].RtTableDefault config_load freifunk-policyrouting
config_get enable pr enable
config_get fallback pr fallback
config_get zones pr zones
olsrd_rmtables() {
# Remove custom routing tables from olsrd
if [ "`uci -q get olsrd.@olsrd[0].RtTable`" == "111" ] || [ "`uci -q get olsrd.@olsrd[0].RtTableDefault`" == "112" ]; then
uci delete olsrd.@olsrd[0].RtTable
uci delete olsrd.@olsrd[0].RtTableDefault
uci commit
fi
}
olsrd_intalltables() {
if [ ! "`uci -q get olsrd.@olsrd[0].RtTable`" == "111" ] || [ ! "`uci -q get olsrd.@olsrd[0].RtTableDefault`" == "112" ]; then
uci set olsrd.@olsrd[0].RtTable='111'
uci set olsrd.@olsrd[0].RtTableDefault='112'
uci commit olsrd
/etc/init.d/olsrd restart
fi
}
rt_tables() {
tables="/etc/iproute2/rt_tables"
if [ -z "`grep "111" $tables`" ]; then
echo "111 olsr" >> $tables
fi
if [ -z "`grep "112" $tables`" ]; then
echo "112 olsr-default" >> $tables
fi
}
disable_dyngw() {
dyngwlib=`uci show olsrd |grep dyn_gw.so |awk {' FS="."; print $1"."$2 '}`
if [ -n "$dyngwlib" ]; then
uci set $dyngwlib.ignore=1
uci commit olsrd
fi
dyngwplainlib=`uci show olsrd |grep dyn_gw_plain |awk {' FS="."; print $1"."$2 '}`
if [ -n "$dyngwplainlib" ]; then
uci set $dyngwplainlib.ignore=1
uci commit olsrd uci commit olsrd
fi fi
} }
restart_services() {
wifi
/etc/init.d/network restart
/etc/init.d/olsrd restart
}
boot() {
if [ "$enable" = "1" ]; then
[ -d /var/state ] || mkdir -p /var/state
touch /var/state/freifunk-policyrouting
start
else
olsrd_rmtables
fi
}
start() {
if [ $enable = "1" ]; then
logger -s -t policyrouting "Starting policy routing."
rt_tables
olsrd_intalltables
disable_dyngw
for p in $proto; do
if [ ! "$(ip -$p ru s | grep "1000: from all lookup olsr")" ]; then
ip -$p rule add lookup olsr prio 1000
if [ "$?" = "0" ]; then
logger -s -t policyrouting "Added rule: lookup olsr prio 1000 (IPv$p)"
else
logger -s -t policyrouting "Error! Could not add rule: lookup olsr prio 1000 (IPv$p)"
fi
fi
done
# add unreachable with high metric so packets stop here if they find no gateway
# in table olsr-default
if [ "$strict" != 0 ]; then
for p in $proto; do
[ ! "$(ip -$p r s t olsr-default |grep "unreachable default")" ] && {
ip -$p route add unreachable default table olsr-default metric 65535
if [ "$?" = "0" ]; then
logger -s -t policyrouting "Added route: unreachable default table olsr-default metric 65535 (IPv$p)"
else
logger -s -t policyrouting "Error! Could not add route: unreachable default table olsr-default metric 65535 (IPv$p)"
fi
}
done
fi
if [ "$fallback" = 1 ]; then
for p in $proto; do
[ ! "$(ip -$p ru s |grep "from all lookup olsr-default")" ] && {
ip -$p rule add lookup olsr-default prio 33000
if [ "$?" = "0" ]; then
logger -s -t policyrouting "Added rule: olsr-default prio 33000 (IPv$p)"
else
logger -s -t policyrouting "Error! Could not add rule: olsr-default prio 33000 (IPv$p)"
fi
}
done
fi
fi
}
stop() {
logger -s -t policyrouting "Stopping policy routing"
olsrd_rmtables
for p in $proto; do
ip -$p route flush table olsr-default
ip -$p rule del lookup olsr-default > /dev/null 2>&1
ip -$p rule del lookup olsr > /dev/null 2>&1
done
restart_services
echo "Hint: To completely disable freifunk-policyrouting set enable=0 in /etc/config/freifunk-policyrouting."
}
restart() {
logger -s -t policyrouting "Restarting policy routing"
olsrd_rmtables
for p in $proto; do
ip -$p route flush table olsr-default
ip -$p rule del lookup olsr-default > /dev/null 2>&1
ip -$p rule del lookup olsr > /dev/null 2>&1
done
start
restart_services
}

View file

@ -1,7 +1,7 @@
#!/bin/sh #!/bin/sh
uci batch <<-EOF uci batch <<-EOF
add ucitrack freifunk-policyrouting add ucitrack freifunk-policyrouting
add_list ucitrack.@freifunk-policyrouting[-1].affects="network" add_list ucitrack.@freifunk-policyrouting[-1].exec="/etc/init.d/freifunk-policyrouting restart"
commit ucitrack commit ucitrack
EOF EOF