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.

172 lines
4.1 KiB

  1. #!/bin/sh
  2. . /lib/functions.sh
  3. . /lib/functions/network.sh
  4. . /lib/mwan3/mwan3.sh
  5. trap_with_arg()
  6. {
  7. func="$1" ; shift
  8. pid="$1" ; shift
  9. for sig ; do
  10. # shellcheck disable=SC2064
  11. trap "$func $sig $pid" "$sig"
  12. done
  13. }
  14. func_trap()
  15. {
  16. kill -${1} ${2} 2>/dev/null
  17. }
  18. mwan3_add_all_routes()
  19. {
  20. local tid IP IPT route_line family active_tbls tid initial_state error
  21. local ipv=$1
  22. add_active_tbls()
  23. {
  24. let tid++
  25. config_get family "$1" family ipv4
  26. config_get initial_state "$1" initial_state "online"
  27. [ "$family" != "$ipv" ] && return
  28. if $IPT -S "mwan3_iface_in_$1" &> /dev/null; then
  29. active_tbls="$active_tbls${tid} "
  30. fi
  31. }
  32. add_route()
  33. {
  34. let tid++
  35. [ -n "${active_tbls##* $tid *}" ] && return
  36. error=$($IP route add table $tid $route_line 2>&1) ||
  37. LOG warn "failed to add $route_line to table $tid - error: $error"
  38. }
  39. mwan3_update_dev_to_table
  40. [ "$ipv" = "ipv6" ] && [ $NO_IPV6 -ne 0 ] && return
  41. if [ "$ipv" = "ipv4" ]; then
  42. IP="$IP4"
  43. IPT="$IPT4"
  44. elif [ "$ipv" = "ipv6" ]; then
  45. IP="$IP6"
  46. IPT="$IPT6"
  47. fi
  48. tid=0
  49. active_tbls=" "
  50. config_foreach add_active_tbls interface
  51. [ "$active_tbls" = " " ] && return
  52. mwan3_get_routes | while read -r route_line; do
  53. mwan3_route_line_dev "tid" "$route_line" "$ipv"
  54. if [ -n "$tid" ] && [ -z "${active_tbls##* $tid *}" ]; then
  55. $IP route add table $tid $route_line
  56. elif [ -n "${route_line##default*}" ] && [ -n "${route_line##fe80::/64*}" ]; then
  57. config_foreach add_route interface
  58. fi
  59. done
  60. }
  61. mwan3_rtmon_route_handle()
  62. {
  63. local action route_line family tbl device line tid
  64. route_line=${1##"Deleted "}
  65. route_family=$2
  66. if [ "$route_line" = "$1" ]; then
  67. action="replace"
  68. $IPS -! add mwan3_connected_${route_family##ip} ${route_line%% *}
  69. else
  70. action="del"
  71. mwan3_set_connected_${route_family}
  72. fi
  73. if [ -z "${route_line##*linkdown*}" ]; then
  74. LOG debug "attempting to add link on down interface - $route_line"
  75. fi
  76. if [ "$route_family" = "ipv4" ]; then
  77. IP="$IP4"
  78. elif [ "$route_family" = "ipv6" ] && [ $NO_IPV6 -eq 0 ]; then
  79. IP="$IP6"
  80. else
  81. LOG warn "route update called with invalid family - $route_family"
  82. return
  83. fi
  84. route_line=$(echo "$route_line" | sed -ne "$MWAN3_ROUTE_LINE_EXP")
  85. handle_route() {
  86. local error
  87. local iface=$1
  88. tbl=$($IP route list table $tid 2>/dev/null)$'\n'
  89. if [ -n "$iface" ] && [ "$(mwan3_get_mwan3track_status $iface)" != "active" ]; then
  90. LOG debug "interface $iface is disabled - skipping '$route_line'";
  91. return
  92. fi
  93. # check that action needs to be performed. May not need to take action if we
  94. # got a delete event, but table was already flushed
  95. if [ $action = "del" ] && [ -n "${tbl##*$route_line$'\n'*}" ]; then
  96. LOG debug "skipping already deleted route table $tid - skipping '$route_line'"
  97. return
  98. fi
  99. network_get_device device "$iface"
  100. LOG debug "adjusting route $device: '$IP route $action table $tid $route_line'"
  101. error=$($IP route "$action" table $tid $route_line 2>&1)||
  102. LOG warn "failed: '$IP route $action table $tid $route_line' - error: $error"
  103. }
  104. handle_route_cb(){
  105. local iface=$1
  106. let tid++
  107. config_get family "$iface" family ipv4
  108. [ "$family" != "$route_family" ] && return
  109. handle_route "$iface"
  110. }
  111. mwan3_update_dev_to_table
  112. mwan3_route_line_dev "tid" "$route_line" "$route_family"
  113. if [ -n "$tid" ]; then
  114. handle_route
  115. elif [ -n "${route_line##default*}" ] && [ -n "${route_line##fe80::/64*}" ]; then
  116. config_foreach handle_route_cb interface
  117. fi
  118. }
  119. main()
  120. {
  121. local IP family
  122. mwan3_init
  123. family=$1
  124. [ -z $family ] && family=ipv4
  125. if [ "$family" = "ipv6" ]; then
  126. if [ $NO_IPV6 -ne 0 ]; then
  127. LOG warn "mwan3rtmon started for ipv6, but ipv6 not enabled on system"
  128. exit 1
  129. fi
  130. IP="$IP6"
  131. else
  132. IP="$IP4"
  133. fi
  134. sh -c "echo \$\$; exec $IP monitor route" | {
  135. read -r monitor_pid
  136. trap_with_arg func_trap "$monitor_pid" SIGINT SIGTERM SIGKILL
  137. KILL -SIGSTOP $$
  138. while IFS='' read -r line; do
  139. [ -z "${line##*table*}" ] && continue
  140. LOG debug "handling route update $family '$line'"
  141. mwan3_rtmon_route_handle "$line" "$family"
  142. done
  143. } &
  144. child=$!
  145. trap_with_arg func_trap "$child" SIGINT SIGTERM SIGKILL
  146. mwan3_set_connected_${family}
  147. mwan3_add_all_routes ${family}
  148. kill -SIGCONT $child
  149. wait $child
  150. }
  151. main "$@"