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.

281 lines
8.4 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.7"
  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. f_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 disabled="$(uci -q get wireless."${config}".disabled)"
  27. if [ "${mode}" = "ap" ] && [ -n "${network}" ] &&
  28. ([ -z "${trm_device}" ] || [ "${trm_device}" = "${device}" ])
  29. then
  30. f_ifname "${device}"
  31. if [ -z "${disabled}" ] || [ "${disabled}" = "1" ]
  32. then
  33. f_set "none" "${config}" "${network}" "up"
  34. fi
  35. elif [ "${mode}" = "sta" ] && [ -n "${network}" ]
  36. then
  37. trm_stalist="${trm_stalist} ${config}_${network}"
  38. if [ -z "${disabled}" ] || [ "${disabled}" = "0" ]
  39. then
  40. f_set "none" "${config}" "${network}" "down"
  41. fi
  42. fi
  43. }
  44. # function to set different wlan interface status
  45. #
  46. f_set()
  47. {
  48. local change="${1}"
  49. local config="${2}"
  50. local interface="${3}"
  51. local command="${4}"
  52. if [ "${command}" = "up" ]
  53. then
  54. uci -q set wireless."${config}".disabled=0
  55. ubus call network.interface."${interface}" "${command}"
  56. trm_checklist="${trm_checklist} ${interface}"
  57. elif [ "${command}" = "down" ]
  58. then
  59. uci -q set wireless."${config}".disabled=1
  60. ubus call network.interface."${interface}" "${command}"
  61. fi
  62. f_log "debug" "set ::: change: ${change}, config: ${config}, interface: ${interface}, command: ${command}, checklist: ${trm_checklist}, uci-changes: $(uci -q changes wireless)"
  63. if [ -n "$(uci -q changes wireless)" ]
  64. then
  65. if [ "${change}" = "commit" ]
  66. then
  67. uci -q commit wireless
  68. ubus call network reload
  69. f_check
  70. elif [ "${change}" = "partial" ]
  71. then
  72. ubus call network reload
  73. f_check
  74. elif [ "${change}" = "defer" ]
  75. then
  76. uci -q revert wireless
  77. elif [ "${change}" = "revert" ]
  78. then
  79. uci -q revert wireless
  80. ubus call network reload
  81. f_check
  82. fi
  83. fi
  84. }
  85. # function to get ap ifnames by ubus call
  86. #
  87. f_ifname()
  88. {
  89. local device="${1}"
  90. local name cfg
  91. json_load "$(ubus -S call network.wireless status)"
  92. json_select "${device}"
  93. json_get_keys if_list interfaces
  94. json_select interfaces
  95. for iface in ${if_list}
  96. do
  97. json_select "${iface}"
  98. json_get_var name ifname
  99. json_select "config"
  100. json_get_var cfg mode
  101. if [ -n "${name}" ] && [ "${cfg}" = "ap" ]
  102. then
  103. trm_aplist="${trm_aplist} ${name}"
  104. fi
  105. done
  106. }
  107. # function to check interface status on "up" event
  108. #
  109. f_check()
  110. {
  111. local interface value
  112. local cnt=0
  113. for interface in ${trm_checklist}
  114. do
  115. while [ $((cnt)) -lt 15 ]
  116. do
  117. json_load "$(ubus -S call network.interface."${interface}" status)"
  118. json_get_var trm_status up
  119. if [ "${trm_status}" = "1" ] || [ -n "${trm_uplink}" ]
  120. then
  121. f_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}))"
  122. json_cleanup
  123. break
  124. fi
  125. cnt=$((cnt+1))
  126. sleep 1
  127. done
  128. done
  129. if [ -n "${trm_uplink}" ] && [ "${trm_status}" = "0" ]
  130. then
  131. ubus call network reload
  132. eval "trm_count_${trm_uplink}=\$((trm_count_${trm_uplink}+1))"
  133. trm_checklist=""
  134. trm_uplink=""
  135. f_log "info" "uplink ${trm_ssid} get lost"
  136. elif [ -z "${trm_uplink}" ] && [ -n "${trm_checklist}" ]
  137. then
  138. trm_checklist=""
  139. fi
  140. }
  141. # function to write to syslog
  142. #
  143. f_log()
  144. {
  145. local class="${1}"
  146. local log_msg="${2}"
  147. if [ -n "${log_msg}" ] && ([ "${class}" != "debug" ] || ([ "${class}" = "debug" ] && [ $((trm_debug)) -eq 1 ]))
  148. then
  149. logger -t "travelmate-${trm_ver}[${trm_pid}] ${class}" "${log_msg}" 2>&1
  150. fi
  151. }
  152. # source required system libraries
  153. #
  154. if [ -r "/lib/functions.sh" ] && [ -r "/usr/share/libubox/jshn.sh" ]
  155. then
  156. . "/lib/functions.sh"
  157. . "/usr/share/libubox/jshn.sh"
  158. json_init
  159. else
  160. f_log "error" "required system libraries not found"
  161. exit 255
  162. fi
  163. # load uci config and check 'enabled' option
  164. #
  165. option_cb()
  166. {
  167. local option="${1}"
  168. local value="${2}"
  169. eval "${option}=\"${value}\""
  170. }
  171. config_load travelmate
  172. if [ "${trm_enabled}" != "1" ]
  173. then
  174. f_log "info" "travelmate is currently disabled, please set 'trm_enabled' to '1' to use this service"
  175. exit 0
  176. fi
  177. # check for preferred wireless tool
  178. #
  179. if [ $((trm_iw)) -eq 1 ]
  180. then
  181. trm_scanner="$(which iw)"
  182. else
  183. trm_scanner="$(which iwinfo)"
  184. fi
  185. if [ -z "${trm_scanner}" ]
  186. then
  187. f_log "error" "no wireless tool for wlan scanning found, please install 'iw' or 'iwinfo'"
  188. exit 1
  189. fi
  190. # infinitive loop to establish and track STA uplink connections
  191. #
  192. while true
  193. do
  194. if [ -z "${trm_uplink}" ] || [ "${trm_status}" = "0" ]
  195. then
  196. trm_aplist=""
  197. trm_stalist=""
  198. config_load wireless
  199. config_foreach f_prepare wifi-iface
  200. f_set "commit"
  201. if [ -z "${trm_aplist}" ]
  202. then
  203. f_log "error" "no usable AP configuration found, please check '/etc/config/wireless'"
  204. exit 1
  205. fi
  206. for ap in ${trm_aplist}
  207. do
  208. ubus -t 10 wait_for hostapd."${ap}"
  209. if [ $((trm_iw)) -eq 1 ]
  210. then
  211. 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 "\" "}}')"
  212. else
  213. trm_ssidlist="$(${trm_scanner} "${ap}" scan | awk '/ESSID: ".*"/{ORS=" ";if (!seen[$0]++) for(i=2; i<=NF; i++) print $i}')"
  214. fi
  215. f_log "debug" "main ::: scan-tool: ${trm_scanner}, aplist: ${trm_aplist}, ssidlist: ${trm_ssidlist}"
  216. if [ -n "${trm_ssidlist}" ]
  217. then
  218. if [ -z "${trm_stalist}" ]
  219. then
  220. f_log "error" "no usable STA configuration found, please check '/etc/config/wireless'"
  221. exit 1
  222. fi
  223. for sta in ${trm_stalist}
  224. do
  225. trm_config="${sta%%_*}"
  226. trm_network="${sta##*_}"
  227. trm_ssid="\"$(uci -q get wireless."${trm_config}".ssid)\""
  228. if [ $((trm_count_${trm_config})) -lt $((trm_maxretry)) ] || [ $((trm_maxretry)) -eq 0 ]
  229. then
  230. if [ -n "$(printf "${trm_ssidlist}" | grep -Fo "${trm_ssid}")" ]
  231. then
  232. f_set "partial" "${trm_config}" "${trm_network}" "up"
  233. if [ "${trm_status}" = "1" ]
  234. then
  235. trm_checklist="${trm_network}"
  236. trm_uplink="${trm_config}"
  237. f_set "defer"
  238. f_log "info" "wwan interface connected to uplink ${trm_ssid}"
  239. break 2
  240. else
  241. f_set "revert"
  242. eval "trm_count_${trm_config}=\$((trm_count_${trm_config}+1))"
  243. fi
  244. fi
  245. elif [ $((trm_count_${trm_config})) -eq $((trm_maxretry)) ] && [ $((trm_maxretry)) -ne 0 ]
  246. then
  247. eval "trm_count_${trm_config}=\$((trm_count_${trm_config}+1))"
  248. f_log "info" "uplink ${trm_ssid} disabled due to permanent connection failures"
  249. fi
  250. done
  251. fi
  252. sleep 5
  253. done
  254. else
  255. f_check
  256. if [ -n "${trm_uplink}" ]
  257. then
  258. sleep ${trm_loop}
  259. fi
  260. fi
  261. done