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.

173 lines
4.2 KiB

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