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.

249 lines
7.7 KiB

  1. #!/bin/sh
  2. # travelmate, a wlan connection manager for travel router
  3. # written by Dirk Brenken (dev@brenken.org)
  4. # This is free software, licensed under the GNU General Public License v3.
  5. # You should have received a copy of the GNU General Public License
  6. # along with this program. If not, see <http://www.gnu.org/licenses/>.
  7. # prepare environment
  8. #
  9. LC_ALL=C
  10. PATH="/usr/sbin:/usr/bin:/sbin:/bin"
  11. trm_pid="${$}"
  12. trm_ver="0.2.5"
  13. trm_debug=0
  14. trm_loop=30
  15. trm_maxretry=3
  16. trm_iw=1
  17. trm_device=""
  18. # function to prepare all relevant AP and STA interfaces
  19. #
  20. trm_prepare()
  21. {
  22. local config="${1}"
  23. local mode="$(uci -q get wireless."${config}".mode)"
  24. local device="$(uci -q get wireless."${config}".device)"
  25. local network="$(uci -q get wireless."${config}".network)"
  26. local ifname="$(uci -q get wireless."${config}".ifname)"
  27. local disabled="$(uci -q get wireless."${config}".disabled)"
  28. if [ "${mode}" = "ap" ] &&
  29. ([ -z "${trm_device}" ] || [ "${trm_device}" = "${device}" ])
  30. then
  31. trm_aplist="${trm_aplist} ${ifname}"
  32. if [ -z "${disabled}" ] || [ "${disabled}" = "1" ]
  33. then
  34. trm_set "none" "${config}" "${network}" "up"
  35. fi
  36. elif [ "${mode}" = "sta" ]
  37. then
  38. trm_stalist="${trm_stalist} ${config}_${network}"
  39. if [ -z "${disabled}" ] || [ "${disabled}" = "0" ]
  40. then
  41. trm_set "none" "${config}" "${network}" "down"
  42. fi
  43. fi
  44. }
  45. # function to set different wlan interface status
  46. #
  47. trm_set()
  48. {
  49. local change="${1}"
  50. local config="${2}"
  51. local interface="${3}"
  52. local command="${4}"
  53. if [ "${command}" = "up" ]
  54. then
  55. uci -q set wireless."${config}".disabled=0
  56. ubus call network.interface."${interface}" "${command}"
  57. trm_checklist="${trm_checklist} ${interface}"
  58. elif [ "${command}" = "down" ]
  59. then
  60. uci -q set wireless."${config}".disabled=1
  61. ubus call network.interface."${interface}" "${command}"
  62. fi
  63. trm_log "debug" "set ::: change: ${change}, config: ${config}, interface: ${interface}, command: ${command}, checklist: ${trm_checklist}, uci-changes: $(uci -q changes wireless)"
  64. if [ -n "$(uci -q changes wireless)" ]
  65. then
  66. if [ "${change}" = "commit" ]
  67. then
  68. uci -q commit wireless
  69. ubus call network reload
  70. trm_check
  71. elif [ "${change}" = "partial" ]
  72. then
  73. ubus call network reload
  74. trm_check
  75. elif [ "${change}" = "defer" ]
  76. then
  77. uci -q revert wireless
  78. elif [ "${change}" = "revert" ]
  79. then
  80. uci -q revert wireless
  81. ubus call network reload
  82. trm_check
  83. fi
  84. fi
  85. }
  86. # function to check interface status on "up" event
  87. #
  88. trm_check()
  89. {
  90. local interface value
  91. local cnt=0
  92. for interface in ${trm_checklist}
  93. do
  94. while [ $((cnt)) -lt 15 ]
  95. do
  96. json_load "$(ubus -S call network.interface."${interface}" status)"
  97. json_get_var trm_status up
  98. if [ "${trm_status}" = "1" ] || [ -n "${trm_uplink}" ]
  99. then
  100. trm_log "debug" "check::: interface: ${interface}, status: ${trm_status}, uplink-cfg: ${trm_uplink}, uplink-ssid: ${trm_ssid}, loop-cnt: ${cnt}, error-cnt: $((trm_count_${trm_config}))"
  101. json_cleanup
  102. break
  103. fi
  104. cnt=$((cnt+1))
  105. sleep 1
  106. done
  107. done
  108. if [ -n "${trm_uplink}" ] && [ "${trm_status}" = "0" ]
  109. then
  110. ubus call network reload
  111. eval "trm_count_${trm_uplink}=\$((trm_count_${trm_uplink}+1))"
  112. trm_checklist=""
  113. trm_uplink=""
  114. trm_log "info" "uplink ${trm_ssid} get lost"
  115. elif [ -z "${trm_uplink}" ] && [ -n "${trm_checklist}" ]
  116. then
  117. trm_checklist=""
  118. fi
  119. }
  120. # function to write to syslog
  121. #
  122. trm_log()
  123. {
  124. local class="${1}"
  125. local log_msg="${2}"
  126. if [ -n "${log_msg}" ] && ([ "${class}" != "debug" ] || ([ "${class}" = "debug" ] && [ $((trm_debug)) -eq 1 ]))
  127. then
  128. logger -t "travelmate-${trm_ver}[${trm_pid}] ${class}" "${log_msg}" 2>&1
  129. fi
  130. }
  131. # source required system libraries
  132. #
  133. if [ -r "/lib/functions.sh" ] && [ -r "/usr/share/libubox/jshn.sh" ]
  134. then
  135. . "/lib/functions.sh"
  136. . "/usr/share/libubox/jshn.sh"
  137. json_init
  138. else
  139. trm_log "error" "required system libraries not found"
  140. exit 255
  141. fi
  142. # load uci config and check 'enabled' option
  143. #
  144. option_cb()
  145. {
  146. local option="${1}"
  147. local value="${2}"
  148. eval "${option}=\"${value}\""
  149. }
  150. config_load travelmate
  151. if [ "${trm_enabled}" != "1" ]
  152. then
  153. trm_log "info" "travelmate is currently disabled, please set 'trm_enabled' to '1' to use this service"
  154. exit 0
  155. fi
  156. # check for preferred wireless tool
  157. #
  158. if [ $((trm_iw)) -eq 1 ]
  159. then
  160. trm_scanner="$(which iw)"
  161. else
  162. trm_scanner="$(which iwinfo)"
  163. fi
  164. if [ -z "${trm_scanner}" ]
  165. then
  166. trm_log "error" "no wireless tool for wlan scanning found, please install 'iw' or 'iwinfo'"
  167. exit 255
  168. fi
  169. # infinitive loop to establish and track STA uplink connections
  170. #
  171. while true
  172. do
  173. if [ -z "${trm_uplink}" ] || [ "${trm_status}" = "0" ]
  174. then
  175. trm_aplist=""
  176. trm_stalist=""
  177. config_load wireless
  178. config_foreach trm_prepare wifi-iface
  179. trm_set "commit"
  180. for ap in ${trm_aplist}
  181. do
  182. ubus -t 10 wait_for hostapd."${ap}"
  183. if [ $((trm_iw)) -eq 1 ]
  184. then
  185. trm_ssidlist="$(${trm_scanner} dev "${ap}" scan 2>/dev/null | awk '/SSID: /{if(!seen[$0]++){printf "\"";for(i=2; i<=NF; i++)if(i==2)printf $i;else printf " "$i;printf "\" "}}')"
  186. else
  187. trm_ssidlist="$(${trm_scanner} "${ap}" scan | awk '/ESSID: ".*"/{ORS=" ";if (!seen[$0]++) for(i=2; i<=NF; i++) print $i}')"
  188. fi
  189. trm_log "debug" "main ::: scan-tool: ${trm_scanner}, ssidlist: ${trm_ssidlist}"
  190. if [ -n "${trm_ssidlist}" ]
  191. then
  192. for sta in ${trm_stalist}
  193. do
  194. trm_config="${sta%%_*}"
  195. trm_network="${sta##*_}"
  196. trm_ifname="$(uci -q get wireless."${trm_config}".ifname)"
  197. trm_ssid="\"$(uci -q get wireless."${trm_config}".ssid)\""
  198. if [ $((trm_count_${trm_config})) -lt $((trm_maxretry)) ] || [ $((trm_maxretry)) -eq 0 ]
  199. then
  200. if [ -n "$(printf "${trm_ssidlist}" | grep -Fo "${trm_ssid}")" ]
  201. then
  202. trm_set "partial" "${trm_config}" "${trm_network}" "up"
  203. if [ "${trm_status}" = "1" ]
  204. then
  205. trm_checklist="${trm_network}"
  206. trm_uplink="${trm_config}"
  207. trm_set "defer"
  208. trm_log "info" "wwan interface \"${trm_ifname}\" connected to uplink ${trm_ssid}"
  209. break 2
  210. else
  211. trm_set "revert"
  212. eval "trm_count_${trm_config}=\$((trm_count_${trm_config}+1))"
  213. fi
  214. fi
  215. elif [ $((trm_count_${trm_config})) -eq $((trm_maxretry)) ] && [ $((trm_maxretry)) -ne 0 ]
  216. then
  217. eval "trm_count_${trm_config}=\$((trm_count_${trm_config}+1))"
  218. trm_log "info" "uplink ${trm_ssid} disabled due to permanent connection failures"
  219. fi
  220. done
  221. fi
  222. sleep 5
  223. done
  224. else
  225. trm_check
  226. if [ -n "${trm_uplink}" ]
  227. then
  228. sleep ${trm_loop}
  229. fi
  230. fi
  231. done