You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

239 lines
4.9 KiB

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
  1. #!/bin/sh
  2. . /lib/functions.sh
  3. . /usr/share/libubox/jshn.sh
  4. . /lib/functions/network.sh
  5. . /lib/mwan3/mwan3.sh
  6. help()
  7. {
  8. cat <<EOF
  9. Syntax: mwan3 [command]
  10. Available commands:
  11. start Load iptables rules, ip rules and ip routes
  12. stop Unload iptables rules, ip rules and ip routes
  13. restart Reload iptables rules, ip rules and ip routes
  14. ifup <iface> Load rules and routes for specific interface
  15. ifdown <iface> Unload rules and routes for specific interface
  16. interfaces Show interfaces status
  17. policies Show currently active policy
  18. connected Show directly connected networks
  19. rules Show active rules
  20. status Show all status
  21. EOF
  22. }
  23. ifdown()
  24. {
  25. if [ -z "$1" ]; then
  26. echo "Error: Expecting interface. Usage: mwan3 ifdown <interface>" && exit 0
  27. fi
  28. if [ -n "$2" ]; then
  29. echo "Error: Too many arguments. Usage: mwan3 ifdown <interface>" && exit 0
  30. fi
  31. ACTION=ifdown INTERFACE=$1 /sbin/hotplug-call iface
  32. kill $(pgrep -f "mwan3track $1 $2") &> /dev/null
  33. mwan3_track_clean $1
  34. }
  35. ifup()
  36. {
  37. local device enabled up l3_device status
  38. config_load mwan3
  39. config_get_bool enabled globals 'enabled' 0
  40. [ ${enabled} -gt 0 ] || {
  41. echo "The service mwan3 is global disabled."
  42. echo "Please execute \"/etc/init.d/mwan3 start\" first."
  43. exit 1
  44. }
  45. if [ -z "$1" ]; then
  46. echo "Expecting interface. Usage: mwan3 ifup <interface>" && exit 0
  47. fi
  48. if [ -n "$2" ]; then
  49. echo "Too many arguments. Usage: mwan3 ifup <interface>" && exit 0
  50. fi
  51. config_get_bool enabled globals 'enabled' 0
  52. [ ${enabled} -gt 0 ] || {
  53. echo "Warning: mwan3 is global disabled. Usage: /etc/init.d/mwan3 start"
  54. exit 0
  55. }
  56. status=$(ubus -S call network.interface.$1 status)
  57. [ -n "$status" ] && {
  58. json_load $status
  59. json_get_vars up l3_device
  60. }
  61. config_get enabled "$1" enabled 0
  62. if [ "$up" = "1" ] \
  63. && [ -n "$l3_device" ] \
  64. && [ "$enabled" = "1" ]; then
  65. ACTION=ifup INTERFACE=$1 DEVICE=$l3_device /sbin/hotplug-call iface
  66. fi
  67. }
  68. interfaces()
  69. {
  70. config_load mwan3
  71. echo "Interface status:"
  72. config_foreach mwan3_report_iface_status interface
  73. echo -e
  74. }
  75. policies()
  76. {
  77. echo "Current ipv4 policies:"
  78. mwan3_report_policies_v4
  79. echo -e
  80. echo "Current ipv6 policies:"
  81. mwan3_report_policies_v6
  82. echo -e
  83. }
  84. connected()
  85. {
  86. echo "Directly connected ipv4 networks:"
  87. mwan3_report_connected_v4
  88. echo -e
  89. echo "Directly connected ipv6 networks:"
  90. mwan3_report_connected_v6
  91. echo -e
  92. }
  93. rules()
  94. {
  95. echo "Active ipv4 user rules:"
  96. mwan3_report_rules_v4
  97. echo -e
  98. echo "Active ipv6 user rules:"
  99. mwan3_report_rules_v6
  100. echo -e
  101. }
  102. status()
  103. {
  104. interfaces
  105. policies
  106. connected
  107. rules
  108. }
  109. start()
  110. {
  111. local enabled src_ip local_source
  112. uci_toggle_state mwan3 globals enabled "1"
  113. config_get local_source globals local_source 'none'
  114. [ "${local_source}" = "none" ] || {
  115. src_ip=$(uci_get_state mwan3 globals src_ip)
  116. [ "${src_ip}" != "" ] && {
  117. ip route del default via "${src_ip}" dev lo 1>/dev/null 2>&1
  118. ip addr del "${src_ip}/32" dev lo 1>/dev/null 2>&1
  119. }
  120. network_get_ipaddr src_ip "${local_source}"
  121. if [ "${src_ip}" = "" ]; then
  122. $LOG warn "Unable to set source ip for own initiated traffic (${local_source})"
  123. else
  124. ip addr add "${src_ip}/32" dev lo
  125. ip route add default via "${src_ip}" dev lo
  126. uci_toggle_state mwan3 globals src_ip "${src_ip}"
  127. fi
  128. }
  129. config_foreach ifup interface
  130. }
  131. stop()
  132. {
  133. local ipset route rule table IP IPT pid src_ip
  134. for pid in $(pgrep -f "mwan3rtmon"); do
  135. kill -TERM "$pid" > /dev/null 2>&1
  136. sleep 1
  137. kill -KILL "$pid" > /dev/null 2>&1
  138. done
  139. for pid in $(pgrep -f "mwan3track"); do
  140. kill -TERM "$pid" > /dev/null 2>&1
  141. sleep 1
  142. kill -KILL "$pid" > /dev/null 2>&1
  143. done
  144. config_load mwan3
  145. config_foreach mwan3_track_clean interface
  146. for IP in "$IP4" "$IP6"; do
  147. for route in $(seq 1 $MWAN3_INTERFACE_MAX); do
  148. $IP route flush table $route &> /dev/null
  149. done
  150. for rule in $($IP rule list | egrep '^[1-2][0-9]{3}\:' | cut -d ':' -f 1); do
  151. $IP rule del pref $rule &> /dev/null
  152. done
  153. done
  154. for IPT in "$IPT4" "$IPT6"; do
  155. $IPT -D PREROUTING -j mwan3_hook &> /dev/null
  156. $IPT -D OUTPUT -j mwan3_hook &> /dev/null
  157. for table in $($IPT -S | awk '{print $2}' | grep mwan3 | sort -u); do
  158. $IPT -F $table &> /dev/null
  159. done
  160. for table in $($IPT -S | awk '{print $2}' | grep mwan3 | sort -u); do
  161. $IPT -X $table &> /dev/null
  162. done
  163. done
  164. for ipset in $($IPS -n list | grep mwan3_); do
  165. $IPS -q destroy $ipset
  166. done
  167. for ipset in $($IPS -n list | grep mwan3 | grep -E '_v4|_v6'); do
  168. $IPS -q destroy $ipset
  169. done
  170. mwan3_lock_clean
  171. rm -rf $MWAN3_STATUS_DIR $MWAN3TRACK_STATUS_DIR
  172. src_ip=$(uci_get_state mwan3 globals src_ip)
  173. [ "${src_ip}" = "" ] || {
  174. ip route del default via "${src_ip}" dev lo 1>/dev/null 2>&1
  175. ip addr del "${src_ip}/32" dev lo 1>/dev/null 2>&1
  176. }
  177. uci_toggle_state mwan3 globals enabled "0"
  178. }
  179. restart() {
  180. stop
  181. start
  182. }
  183. case "$1" in
  184. ifup|ifdown|interfaces|policies|connected|rules|status|start|stop|restart)
  185. mwan3_init
  186. $*
  187. ;;
  188. *)
  189. help
  190. ;;
  191. esac
  192. exit 0