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.

269 lines
7.1 KiB

  1. #!/bin/sh
  2. #
  3. # Copyright (C) 2010 segal.di.ubi.pt
  4. # Copyright (C) 2020 nbembedded.com
  5. #
  6. # This is free software, licensed under the GNU General Public License v2.
  7. #
  8. get_ping_size() {
  9. ps=$1
  10. case "$ps" in
  11. small)
  12. ps="1"
  13. ;;
  14. windows)
  15. ps="32"
  16. ;;
  17. standard)
  18. ps="56"
  19. ;;
  20. big)
  21. ps="248"
  22. ;;
  23. huge)
  24. ps="1492"
  25. ;;
  26. jumbo)
  27. ps="9000"
  28. ;;
  29. *)
  30. echo "Error: invalid ping_size. ping_size should be either: small, windows, standard, big, huge or jumbo" 1>&2
  31. echo "Corresponding ping packet sizes (bytes): small=1, windows=32, standard=56, big=248, huge=1492, jumbo=9000" 1>&2
  32. ;;
  33. esac
  34. echo $ps
  35. }
  36. get_ping_family_flag() {
  37. family=$1
  38. case "$family" in
  39. any)
  40. family=""
  41. ;;
  42. ipv4)
  43. family="-4"
  44. ;;
  45. ipv6)
  46. family="-6"
  47. ;;
  48. *)
  49. echo "Error: invalid address_family \"$family\". address_family should be one of: any, ipv4, ipv6" 1>&2
  50. ;;
  51. esac
  52. echo $family
  53. }
  54. reboot_now() {
  55. reboot &
  56. [ "$1" -ge 1 ] && {
  57. sleep "$1"
  58. echo 1 > /proc/sys/kernel/sysrq
  59. echo b > /proc/sysrq-trigger # Will immediately reboot the system without syncing or unmounting your disks.
  60. }
  61. }
  62. watchcat_periodic() {
  63. failure_period="$1"
  64. force_reboot_delay="$2"
  65. sleep "$failure_period" && reboot_now "$force_reboot_delay"
  66. }
  67. watchcat_restart_modemmanager_iface() {
  68. [ "$2" -gt 0 ] && {
  69. logger -p daemon.info -t "watchcat[$$]" "Resetting current-bands to 'any' on modem: \"$1\" now."
  70. /usr/bin/mmcli -m any --set-current-bands=any
  71. }
  72. logger -p daemon.info -t "watchcat[$$]" "Reconnecting modem: \"$1\" now."
  73. /etc/init.d/modemmanager restart
  74. ifup "$1"
  75. }
  76. watchcat_restart_network_iface() {
  77. logger -p daemon.info -t "watchcat[$$]" "Restarting network interface: \"$1\"."
  78. ip link set "$1" down
  79. ip link set "$1" up
  80. }
  81. watchcat_run_script() {
  82. logger -p daemon.info -t "watchcat[$$]" "Running script \"$1\" for network interface: \"$2\"."
  83. "$1" "$2"
  84. }
  85. watchcat_restart_all_network() {
  86. logger -p daemon.info -t "watchcat[$$]" "Restarting networking now by running: /etc/init.d/network restart"
  87. /etc/init.d/network restart
  88. }
  89. watchcat_monitor_network() {
  90. failure_period="$1"
  91. ping_hosts="$2"
  92. ping_frequency_interval="$3"
  93. ping_size="$4"
  94. iface="$5"
  95. mm_iface_name="$6"
  96. mm_iface_unlock_bands="$7"
  97. address_family="$8"
  98. script="$9"
  99. time_now="$(cat /proc/uptime)"
  100. time_now="${time_now%%.*}"
  101. [ "$time_now" -lt "$failure_period" ] && sleep "$((failure_period - time_now))"
  102. time_now="$(cat /proc/uptime)"
  103. time_now="${time_now%%.*}"
  104. time_lastcheck="$time_now"
  105. time_lastcheck_withinternet="$time_now"
  106. ping_size="$(get_ping_size "$ping_size")"
  107. ping_family="$(get_ping_family_flag "$address_family")"
  108. while true; do
  109. # account for the time ping took to return. With a ping time of 5s, ping might take more than that, so it is important to avoid even more delay.
  110. time_now="$(cat /proc/uptime)"
  111. time_now="${time_now%%.*}"
  112. time_diff="$((time_now - time_lastcheck))"
  113. [ "$time_diff" -lt "$ping_frequency_interval" ] && sleep "$((ping_frequency_interval - time_diff))"
  114. time_now="$(cat /proc/uptime)"
  115. time_now="${time_now%%.*}"
  116. time_lastcheck="$time_now"
  117. for host in $ping_hosts; do
  118. if [ "$iface" != "" ]; then
  119. ping_result="$(
  120. ping $ping_family -I "$iface" -s "$ping_size" -c 1 "$host" &> /dev/null
  121. echo $?
  122. )"
  123. else
  124. ping_result="$(
  125. ping $ping_family -s "$ping_size" -c 1 "$host" &> /dev/null
  126. echo $?
  127. )"
  128. fi
  129. if [ "$ping_result" -eq 0 ]; then
  130. time_lastcheck_withinternet="$time_now"
  131. else
  132. if [ "$script" != "" ]; then
  133. logger -p daemon.info -t "watchcat[$$]" "Could not reach $host via \"$iface\" for \"$((time_now - time_lastcheck_withinternet))\" seconds. Running script after reaching \"$failure_period\" seconds"
  134. elif [ "$iface" != "" ]; then
  135. logger -p daemon.info -t "watchcat[$$]" "Could not reach $host via \"$iface\" for \"$((time_now - time_lastcheck_withinternet))\" seconds. Restarting \"$iface\" after reaching \"$failure_period\" seconds"
  136. else
  137. logger -p daemon.info -t "watchcat[$$]" "Could not reach $host for \"$((time_now - time_lastcheck_withinternet))\" seconds. Restarting networking after reaching \"$failure_period\" seconds"
  138. fi
  139. fi
  140. done
  141. [ "$((time_now - time_lastcheck_withinternet))" -ge "$failure_period" ] && {
  142. if [ "$script" != "" ]; then
  143. watchcat_run_script "$script" "$iface"
  144. else
  145. if [ "$mm_iface_name" != "" ]; then
  146. watchcat_restart_modemmanager_iface "$mm_iface_name" "$mm_iface_unlock_bands"
  147. fi
  148. if [ "$iface" != "" ]; then
  149. watchcat_restart_network_iface "$iface"
  150. else
  151. watchcat_restart_all_network
  152. fi
  153. fi
  154. /etc/init.d/watchcat start
  155. # Restart timer cycle.
  156. time_lastcheck_withinternet="$time_now"
  157. }
  158. done
  159. }
  160. watchcat_ping() {
  161. failure_period="$1"
  162. force_reboot_delay="$2"
  163. ping_hosts="$3"
  164. ping_frequency_interval="$4"
  165. ping_size="$5"
  166. address_family="$6"
  167. time_now="$(cat /proc/uptime)"
  168. time_now="${time_now%%.*}"
  169. [ "$time_now" -lt "$failure_period" ] && sleep "$((failure_period - time_now))"
  170. time_now="$(cat /proc/uptime)"
  171. time_now="${time_now%%.*}"
  172. time_lastcheck="$time_now"
  173. time_lastcheck_withinternet="$time_now"
  174. ping_size="$(get_ping_size "$ping_size")"
  175. ping_family="$(get_ping_family_flag "$address_family")"
  176. while true; do
  177. # account for the time ping took to return. With a ping time of 5s, ping might take more than that, so it is important to avoid even more delay.
  178. time_now="$(cat /proc/uptime)"
  179. time_now="${time_now%%.*}"
  180. time_diff="$((time_now - time_lastcheck))"
  181. [ "$time_diff" -lt "$ping_frequency_interval" ] && sleep "$((ping_frequency_interval - time_diff))"
  182. time_now="$(cat /proc/uptime)"
  183. time_now="${time_now%%.*}"
  184. time_lastcheck="$time_now"
  185. for host in $ping_hosts; do
  186. if [ "$iface" != "" ]; then
  187. ping_result="$(
  188. ping $ping_family -I "$iface" -s "$ping_size" -c 1 "$host" &> /dev/null
  189. echo $?
  190. )"
  191. else
  192. ping_result="$(
  193. ping $ping_family -s "$ping_size" -c 1 "$host" &> /dev/null
  194. echo $?
  195. )"
  196. fi
  197. if [ "$ping_result" -eq 0 ]; then
  198. time_lastcheck_withinternet="$time_now"
  199. else
  200. logger -p daemon.info -t "watchcat[$$]" "Could not reach $host for $((time_now - time_lastcheck_withinternet)). Rebooting after reaching $failure_period"
  201. fi
  202. done
  203. [ "$((time_now - time_lastcheck_withinternet))" -ge "$failure_period" ] && reboot_now "$force_reboot_delay"
  204. done
  205. }
  206. mode="$1"
  207. # Fix potential typo in mode and provide backward compatibility.
  208. [ "$mode" = "allways" ] && mode="periodic_reboot"
  209. [ "$mode" = "always" ] && mode="periodic_reboot"
  210. [ "$mode" = "ping" ] && mode="ping_reboot"
  211. case "$mode" in
  212. periodic_reboot)
  213. # args from init script: period forcedelay
  214. watchcat_periodic "$2" "$3"
  215. ;;
  216. ping_reboot)
  217. # args from init script: period forcedelay pinghosts pingperiod pingsize addressfamily
  218. watchcat_ping "$2" "$3" "$4" "$5" "$6" "$7"
  219. ;;
  220. restart_iface)
  221. # args from init script: period pinghosts pingperiod pingsize interface mmifacename unlockbands addressfamily
  222. watchcat_monitor_network "$2" "$3" "$4" "$5" "$6" "$7" "$8" "$9" ""
  223. ;;
  224. run_script)
  225. # args from init script: period pinghosts pingperiod pingsize interface addressfamily script
  226. watchcat_monitor_network "$2" "$3" "$4" "$5" "$6" "" "" "$7" "$8"
  227. ;;
  228. *)
  229. echo "Error: invalid mode selected: $mode"
  230. ;;
  231. esac