mwan3: fix interface-bound traffic when interface is offline
This commit fixed what 6d99b602 was supposed to fix without affecting
interface-bound traffic.
Before 6d99b602 interface-bound traffic was working normally as long
as at least one interface was online. However when the last interface
went offline, it was impossible to ping and such state was
unrecoverable.
Commit 6d99b602 fixed unrecoverable offline state problem (it was
possible to ping -I iface) but messed inteface-bound traffic. Traffic
with interface source address was not working if the interface was in
"offline" state, even if another interface was online.
The problem was caused by an inconsistent "offline" interface state:
iptables-related rules were kept while routing table and policy were
deleted.
The idea behind this commit is to:
1. Keep all the rules for each interface (iptables, routing table,
policy) regardless of its state. This ensures consistency,
2. Make interface state hotplug events affect only iptables'
mwan3_policy_* rules. Interface-related iptables, routing table
and policy is removed only when mwan3 is manually stopped.
To make such changes possible, it's necessary to change the way
mwan3_policy_* rule generator keeps track of interface state hotplug
events.
Until now, it checked for the existence of custom interface-related
routing table (table id 1, 2, 3, ...). Clearly we can no longer rely
on that so each interface state is stored explicitly in file.
Signed-off-by: Marcin Jurkowski <marcin1j@gmail.com>
7 years ago |
|
- #!/bin/sh
-
- . /lib/functions.sh
- . /usr/share/libubox/jshn.sh
- . /lib/functions/network.sh
- . /lib/mwan3/mwan3.sh
-
- help()
- {
- cat <<EOF
- Syntax: mwan3 [command]
-
- Available commands:
- start Load iptables rules, ip rules and ip routes
- stop Unload iptables rules, ip rules and ip routes
- restart Reload iptables rules, ip rules and ip routes
- ifup <iface> Load rules and routes for specific interface
- ifdown <iface> Unload rules and routes for specific interface
- interfaces Show interfaces status
- policies Show currently active policy
- connected Show directly connected networks
- rules Show active rules
- status Show all status
-
- EOF
- }
-
- ifdown()
- {
- if [ -z "$1" ]; then
- echo "Error: Expecting interface. Usage: mwan3 ifdown <interface>" && exit 0
- fi
-
- if [ -n "$2" ]; then
- echo "Error: Too many arguments. Usage: mwan3 ifdown <interface>" && exit 0
- fi
-
- ACTION=ifdown INTERFACE=$1 /sbin/hotplug-call iface
-
- kill $(pgrep -f "mwan3track $1 $2") &> /dev/null
- mwan3_track_clean $1
- }
-
- ifup()
- {
- local device enabled up l3_device status
-
- config_load mwan3
- config_get_bool enabled globals 'enabled' 0
- [ ${enabled} -gt 0 ] || {
- echo "The service mwan3 is global disabled."
- echo "Please execute \"/etc/init.d/mwan3 start\" first."
- exit 1
- }
-
- if [ -z "$1" ]; then
- echo "Expecting interface. Usage: mwan3 ifup <interface>" && exit 0
- fi
-
- if [ -n "$2" ]; then
- echo "Too many arguments. Usage: mwan3 ifup <interface>" && exit 0
- fi
-
- config_get_bool enabled globals 'enabled' 0
- [ ${enabled} -gt 0 ] || {
- echo "Warning: mwan3 is global disabled. Usage: /etc/init.d/mwan3 start"
- exit 0
- }
-
- status=$(ubus -S call network.interface.$1 status)
- [ -n "$status" ] && {
- json_load $status
- json_get_vars up l3_device
- }
-
- config_get enabled "$1" enabled 0
-
-
- if [ "$up" = "1" ] \
- && [ -n "$l3_device" ] \
- && [ "$enabled" = "1" ]; then
- ACTION=ifup INTERFACE=$1 DEVICE=$l3_device /sbin/hotplug-call iface
- fi
- }
-
- interfaces()
- {
- config_load mwan3
-
- echo "Interface status:"
- config_foreach mwan3_report_iface_status interface
- echo -e
- }
-
- policies()
- {
- echo "Current ipv4 policies:"
- mwan3_report_policies_v4
- echo -e
- echo "Current ipv6 policies:"
- mwan3_report_policies_v6
- echo -e
- }
-
- connected()
- {
- echo "Directly connected ipv4 networks:"
- mwan3_report_connected_v4
- echo -e
- echo "Directly connected ipv6 networks:"
- mwan3_report_connected_v6
- echo -e
- }
-
- rules()
- {
- echo "Active ipv4 user rules:"
- mwan3_report_rules_v4
- echo -e
- echo "Active ipv6 user rules:"
- mwan3_report_rules_v6
- echo -e
- }
-
- status()
- {
- interfaces
- policies
- connected
- rules
- }
-
- start()
- {
- local enabled src_ip local_source
-
- uci_toggle_state mwan3 globals enabled "1"
-
- config_get local_source globals local_source 'none'
- [ "${local_source}" = "none" ] || {
- src_ip=$(uci_get_state mwan3 globals src_ip)
- [ "${src_ip}" != "" ] && {
- ip route del default via "${src_ip}" dev lo 1>/dev/null 2>&1
- ip addr del "${src_ip}/32" dev lo 1>/dev/null 2>&1
- }
-
- network_get_ipaddr src_ip "${local_source}"
- if [ "${src_ip}" = "" ]; then
- $LOG warn "Unable to set source ip for own initiated traffic (${local_source})"
- else
- ip addr add "${src_ip}/32" dev lo
- ip route add default via "${src_ip}" dev lo
- uci_toggle_state mwan3 globals src_ip "${src_ip}"
- fi
- }
-
- config_foreach ifup interface
- }
-
- stop()
- {
- local ipset route rule table IP IPT pid src_ip
-
- for pid in $(pgrep -f "mwan3rtmon"); do
- kill -TERM "$pid" > /dev/null 2>&1
- sleep 1
- kill -KILL "$pid" > /dev/null 2>&1
- done
-
- for pid in $(pgrep -f "mwan3track"); do
- kill -TERM "$pid" > /dev/null 2>&1
- sleep 1
- kill -KILL "$pid" > /dev/null 2>&1
- done
-
- config_load mwan3
- config_foreach mwan3_track_clean interface
-
- for IP in "$IP4" "$IP6"; do
-
- for route in $(seq 1 $MWAN3_INTERFACE_MAX); do
- $IP route flush table $route &> /dev/null
- done
-
- for rule in $($IP rule list | egrep '^[1-2][0-9]{3}\:' | cut -d ':' -f 1); do
- $IP rule del pref $rule &> /dev/null
- done
- done
-
- for IPT in "$IPT4" "$IPT6"; do
-
- $IPT -D PREROUTING -j mwan3_hook &> /dev/null
- $IPT -D OUTPUT -j mwan3_hook &> /dev/null
-
- for table in $($IPT -S | awk '{print $2}' | grep mwan3 | sort -u); do
- $IPT -F $table &> /dev/null
- done
-
- for table in $($IPT -S | awk '{print $2}' | grep mwan3 | sort -u); do
- $IPT -X $table &> /dev/null
- done
- done
-
- for ipset in $($IPS -n list | grep mwan3_); do
- $IPS -q destroy $ipset
- done
-
- for ipset in $($IPS -n list | grep mwan3 | grep -E '_v4|_v6'); do
- $IPS -q destroy $ipset
- done
-
- mwan3_lock_clean
- rm -rf $MWAN3_STATUS_DIR $MWAN3TRACK_STATUS_DIR
-
- src_ip=$(uci_get_state mwan3 globals src_ip)
- [ "${src_ip}" = "" ] || {
- ip route del default via "${src_ip}" dev lo 1>/dev/null 2>&1
- ip addr del "${src_ip}/32" dev lo 1>/dev/null 2>&1
- }
-
- uci_toggle_state mwan3 globals enabled "0"
- }
-
- restart() {
- stop
- start
- }
-
- case "$1" in
- ifup|ifdown|interfaces|policies|connected|rules|status|start|stop|restart)
- mwan3_init
- $*
- ;;
- *)
- help
- ;;
- esac
-
- exit 0
|