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.

243 lines
7.3 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_debug="0"
  12. trm_pid="${$}"
  13. trm_ver="0.2.2"
  14. trm_loop=30
  15. trm_maxretry=3
  16. trm_device=""
  17. trm_iw="$(which iw)"
  18. # function to prepare all relevant AP and STA interfaces
  19. #
  20. trm_prepare()
  21. {
  22. local config="${1}"
  23. local device="$(uci -q get wireless."${config}".device)"
  24. local mode="$(uci -q get wireless."${config}".mode)"
  25. local network="$(uci -q get wireless."${config}".network)"
  26. local disabled="$(uci -q get wireless."${config}".disabled)"
  27. if [ "${mode}" = "ap" ] &&
  28. ([ -z "${trm_device}" ] || [ "${trm_device}" = "${device}" ])
  29. then
  30. ifname="$(uci -q get wireless."${config}".ifname)"
  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 states
  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 state 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_state up
  98. if [ "${trm_state}" = "1" ] || [ -n "${trm_uplink}" ]
  99. then
  100. trm_log "debug" "check::: interface: ${interface}, status: ${trm_state}, uplink: ${trm_uplink}, count: ${cnt}"
  101. json_cleanup
  102. break
  103. fi
  104. cnt=$((cnt+1))
  105. sleep 1
  106. done
  107. done
  108. if [ -n "${trm_uplink}" ] && [ "${trm_state}" = "0" ]
  109. then
  110. ubus call network reload
  111. trm_checklist=""
  112. trm_log "info" "uplink ${ssid} get lost"
  113. elif [ -z "${trm_uplink}" ] && [ -n "${trm_checklist}" ]
  114. then
  115. trm_checklist=""
  116. fi
  117. }
  118. # function to write to syslog
  119. #
  120. trm_log()
  121. {
  122. local class="${1}"
  123. local log_msg="${2}"
  124. if [ -n "${log_msg}" ] && ([ "${class}" != "debug" ] || ([ "${class}" = "debug" ] && [ "${trm_debug}" = "1" ]))
  125. then
  126. logger -t "travelmate-${trm_ver}[${trm_pid}] ${class}" "${log_msg}" 2>&1
  127. fi
  128. }
  129. # source required system libraries
  130. #
  131. if [ -r "/lib/functions.sh" ] && [ -r "/usr/share/libubox/jshn.sh" ]
  132. then
  133. . "/lib/functions.sh"
  134. . "/usr/share/libubox/jshn.sh"
  135. json_init
  136. else
  137. trm_log "error" "required system libraries not found"
  138. exit 255
  139. fi
  140. # load uci config and check 'enabled' option
  141. #
  142. option_cb()
  143. {
  144. local option="${1}"
  145. local value="${2}"
  146. eval "${option}=\"${value}\""
  147. }
  148. config_load travelmate
  149. if [ "${trm_enabled}" != "1" ]
  150. then
  151. trm_log "info" "travelmate is currently disabled, please set 'trm_enabled' to '1' to use this service"
  152. exit 0
  153. fi
  154. # check for preferred wireless tool
  155. #
  156. if [ ! -f "${trm_iw}" ]
  157. then
  158. trm_iwinfo="$(which iwinfo)"
  159. if [ ! -f "${trm_iwinfo}" ]
  160. then
  161. trm_log "error" "no wireless tool for scanning found, please install 'iw' or 'iwinfo'"
  162. exit 255
  163. fi
  164. fi
  165. # infinitive loop to establish and track STA uplink connections
  166. #
  167. while true
  168. do
  169. if [ -z "${trm_uplink}" ] || [ "${trm_state}" = "0" ]
  170. then
  171. trm_uplink=""
  172. trm_aplist=""
  173. trm_stalist=""
  174. config_load wireless
  175. config_foreach trm_prepare wifi-iface
  176. trm_set "commit"
  177. for ap in ${trm_aplist}
  178. do
  179. ubus -t 10 wait_for hostapd."${ap}"
  180. if [ -f "${trm_iw}" ]
  181. then
  182. trm_ssidlist="$(${trm_iw} 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 "\" "}}')"
  183. else
  184. trm_ssidlist="$(${trm_iwinfo} "${ap}" scan | awk '/ESSID: ".*"/{ORS=" ";if (!seen[$0]++) for(i=2; i<=NF; i++) print $i}')"
  185. fi
  186. trm_log "debug" "main ::: iw: ${trm_iw}, iwinfo: ${trm_iwinfo}, ssidlist: ${trm_ssidlist}"
  187. if [ -n "${trm_ssidlist}" ]
  188. then
  189. for sta in ${trm_stalist}
  190. do
  191. config="${sta%%_*}"
  192. network="${sta##*_}"
  193. ssid="\"$(uci -q get wireless."${config}".ssid)\""
  194. if [ $((trm_count_${network})) -lt $((trm_maxretry)) ]
  195. then
  196. if [ -n "$(printf "${trm_ssidlist}" | grep -Fo "${ssid}")" ]
  197. then
  198. trm_set "partial" "${config}" "${network}" "up"
  199. if [ "${trm_state}" = "1" ]
  200. then
  201. trm_uplink="${network}"
  202. trm_checklist="${trm_uplink}"
  203. trm_set "defer"
  204. trm_log "info" "wlan interface \"${network}\" connected to uplink ${ssid}"
  205. break 2
  206. else
  207. trm_set "revert"
  208. eval "trm_count_${network}=\$((trm_count_${network}+1))"
  209. fi
  210. fi
  211. elif [ $((trm_count_${network})) -eq $((trm_maxretry)) ]
  212. then
  213. eval "trm_count_${network}=\$((trm_count_${network}+1))"
  214. trm_log "info" "uplink ${ssid} disabled due to permanent connection failures"
  215. fi
  216. done
  217. fi
  218. sleep 1
  219. done
  220. sleep 5
  221. else
  222. trm_check
  223. if [ -n "${trm_checklist}" ]
  224. then
  225. sleep ${trm_loop}
  226. fi
  227. fi
  228. done