netifd-wireless.sh 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352
  1. NETIFD_MAIN_DIR="${NETIFD_MAIN_DIR:-/lib/netifd}"
  2. . /usr/share/libubox/jshn.sh
  3. . $NETIFD_MAIN_DIR/utils.sh
  4. CMD_UP=0
  5. CMD_SET_DATA=1
  6. CMD_PROCESS_ADD=2
  7. CMD_PROCESS_KILL_ALL=3
  8. CMD_SET_RETRY=4
  9. add_driver() {
  10. return
  11. }
  12. wireless_setup_vif_failed() {
  13. local error="$1"
  14. echo "Interface $_w_iface setup failed: $error"
  15. }
  16. wireless_setup_failed() {
  17. local error="$1"
  18. echo "Device setup failed: $error"
  19. wireless_set_retry 0
  20. }
  21. prepare_key_wep() {
  22. local key="$1"
  23. local hex=1
  24. echo -n "$key" | grep -qE "[^a-fA-F0-9]" && hex=0
  25. [ "${#key}" -eq 10 -a $hex -eq 1 ] || \
  26. [ "${#key}" -eq 26 -a $hex -eq 1 ] || {
  27. [ "${key:0:2}" = "s:" ] && key="${key#s:}"
  28. key="$(echo -n "$key" | hexdump -ve '1/1 "%02x" ""')"
  29. }
  30. echo "$key"
  31. }
  32. _wdev_prepare_channel() {
  33. json_get_vars channel hwmode
  34. auto_channel=0
  35. enable_ht=0
  36. htmode=
  37. hwmode="${hwmode##11}"
  38. hwmode_n="${hwmode##n}"
  39. case "$channel" in
  40. ""|0|auto)
  41. channel=0
  42. auto_channel=1
  43. ;;
  44. [0-9]*) ;;
  45. *)
  46. wireless_setup_failed "INVALID_CHANNEL"
  47. ;;
  48. esac
  49. [[ "$hwmode_n" = "$hwmode" ]] || {
  50. enable_ht=1
  51. hwmode="$hwmode_n"
  52. json_get_vars htmode
  53. case "$htmode" in
  54. HT20|HT40+|HT40-);;
  55. *) htmode= ;;
  56. esac
  57. }
  58. case "$hwmode" in
  59. a|b|g) ;;
  60. *)
  61. if [ "$channel" -gt 14 ]; then
  62. hwmode=a
  63. else
  64. hwmode=g
  65. fi
  66. ;;
  67. esac
  68. }
  69. _wdev_handler() {
  70. json_load "$data"
  71. json_select config
  72. _wdev_prepare_channel
  73. json_select ..
  74. eval "drv_$1_$2 \"$interface\""
  75. }
  76. _wdev_msg_call() {
  77. local old_cb
  78. json_set_namespace wdev old_cb
  79. "$@"
  80. json_set_namespace $old_cb
  81. }
  82. _wdev_wrapper() {
  83. while [ -n "$1" ]; do
  84. eval "$1() { _wdev_msg_call _$1 \"\$@\"; }"
  85. shift
  86. done
  87. }
  88. _wdev_notify_init() {
  89. local command="$1"
  90. local interface="$2"
  91. json_init
  92. json_add_int "command" "$command"
  93. json_add_string "device" "$__netifd_device"
  94. [ -n "$interface" ] && json_add_string "interface" "$interface"
  95. json_add_object "data"
  96. }
  97. _wdev_notify() {
  98. local options="$1"
  99. json_close_object
  100. ubus $options call network.wireless notify "$(json_dump)"
  101. }
  102. _wdev_add_variables() {
  103. while [ -n "$1" ]; do
  104. local var="${1%%=*}"
  105. local val="$1"
  106. shift
  107. [[ "$var" = "$val" ]] && continue
  108. val="${val#*=}"
  109. json_add_string "$var" "$val"
  110. done
  111. }
  112. _wireless_add_vif() {
  113. local name="$1"; shift
  114. local ifname="$1"; shift
  115. _wdev_notify_init $CMD_SET_DATA "$name"
  116. json_add_string "ifname" "$ifname"
  117. _wdev_add_variables "$@"
  118. _wdev_notify
  119. }
  120. _wireless_set_up() {
  121. _wdev_notify_init $CMD_UP
  122. _wdev_notify
  123. }
  124. _wireless_set_data() {
  125. _wdev_notify_init $CMD_SET_DATA
  126. _wdev_add_variables "$@"
  127. _wdev_notify
  128. }
  129. _wireless_add_process() {
  130. _wdev_notify_init $CMD_PROCESS_ADD
  131. local exe="$2"
  132. [ -L "$exe" ] && exe="$(readlink -f "$exe")"
  133. json_add_int pid "$1"
  134. json_add_string exe "$exe"
  135. [ -n "$3" ] && json_add_boolean required 1
  136. exe2="$(readlink -f /proc/$1/exe)"
  137. [ "$exe" != "$exe2" ] && echo "WARNING (wireless_add_process): executable path $exe does not match process $1 path ($exe2)"
  138. _wdev_notify
  139. }
  140. _wireless_process_kill_all() {
  141. _wdev_notify_init $CMD_PROCESS_KILL_ALL
  142. [ -n "$1" ] && json_add_int signal "$1"
  143. _wdev_notify
  144. }
  145. _wireless_set_retry() {
  146. _wdev_notify_init $CMD_SET_RETRY
  147. json_add_int retry "$1"
  148. _wdev_notify
  149. }
  150. _wdev_wrapper \
  151. wireless_add_vif \
  152. wireless_set_up \
  153. wireless_set_data \
  154. wireless_add_process \
  155. wireless_process_kill_all \
  156. wireless_set_retry \
  157. wireless_vif_parse_encryption() {
  158. json_get_vars encryption
  159. set_default encryption none
  160. auth_mode_open=1
  161. auth_mode_shared=0
  162. auth_type=none
  163. wpa_cipher=CCMP
  164. case "$encryption" in
  165. *tkip+aes|*tkip+ccmp|*aes+tkip|*ccmp+tkip) wpa_cipher="CCMP TKIP";;
  166. *aes|*ccmp) wpa_cipher="CCMP";;
  167. *tkip) wpa_cipher="TKIP";;
  168. esac
  169. # 802.11n requires CCMP for WPA
  170. [ "$enable_ht:$wpa_cipher" = "1:TKIP" ] && wpa_cipher="CCMP TKIP"
  171. # Examples:
  172. # psk-mixed/tkip => WPA1+2 PSK, TKIP
  173. # wpa-psk2/tkip+aes => WPA2 PSK, CCMP+TKIP
  174. # wpa2/tkip+aes => WPA2 RADIUS, CCMP+TKIP
  175. case "$encryption" in
  176. wpa2*|wpa3*|*psk2*|psk3*|sae*|owe*)
  177. wpa=2
  178. ;;
  179. wpa*mixed*|*psk*mixed*)
  180. wpa=3
  181. ;;
  182. wpa*|*psk*)
  183. wpa=1
  184. ;;
  185. *)
  186. wpa=0
  187. wpa_cipher=
  188. ;;
  189. esac
  190. wpa_pairwise="$wpa_cipher"
  191. case "$encryption" in
  192. owe*)
  193. auth_type=owe
  194. ;;
  195. wpa3-mixed*)
  196. auth_type=eap-eap192
  197. ;;
  198. wpa3*)
  199. auth_type=eap192
  200. ;;
  201. psk3-mixed*|sae-mixed*)
  202. auth_type=psk-sae
  203. ;;
  204. psk3*|sae*)
  205. auth_type=sae
  206. ;;
  207. *psk*)
  208. auth_type=psk
  209. ;;
  210. *wpa*|*8021x*)
  211. auth_type=eap
  212. ;;
  213. *wep*)
  214. auth_type=wep
  215. case "$encryption" in
  216. *shared*)
  217. auth_mode_open=0
  218. auth_mode_shared=1
  219. ;;
  220. *mixed*)
  221. auth_mode_shared=1
  222. ;;
  223. esac
  224. ;;
  225. esac
  226. }
  227. _wireless_set_brsnoop_isolation() {
  228. local multicast_to_unicast="$1"
  229. local isolate
  230. json_get_var isolate isolate
  231. [ ${isolate:-0} -gt 0 -o -z "$network_bridge" ] && return
  232. [ ${multicast_to_unicast:-1} -gt 0 ] && json_add_boolean isolate 1
  233. }
  234. for_each_interface() {
  235. local _w_types="$1"; shift
  236. local _w_ifaces _w_iface
  237. local _w_type
  238. local _w_found
  239. local multicast_to_unicast
  240. json_get_keys _w_ifaces interfaces
  241. json_select interfaces
  242. for _w_iface in $_w_ifaces; do
  243. json_select "$_w_iface"
  244. if [ -n "$_w_types" ]; then
  245. json_get_var network_bridge bridge
  246. json_get_var multicast_to_unicast multicast_to_unicast
  247. json_select config
  248. _wireless_set_brsnoop_isolation "$multicast_to_unicast"
  249. json_get_var _w_type mode
  250. json_select ..
  251. _w_types=" $_w_types "
  252. [[ "${_w_types%$_w_type*}" = "$_w_types" ]] && {
  253. json_select ..
  254. continue
  255. }
  256. fi
  257. "$@" "$_w_iface"
  258. json_select ..
  259. done
  260. json_select ..
  261. }
  262. _wdev_common_device_config() {
  263. config_add_string channel hwmode htmode noscan
  264. }
  265. _wdev_common_iface_config() {
  266. config_add_string mode ssid encryption 'key:wpakey'
  267. }
  268. init_wireless_driver() {
  269. name="$1"; shift
  270. cmd="$1"; shift
  271. case "$cmd" in
  272. dump)
  273. add_driver() {
  274. eval "drv_$1_cleanup"
  275. json_init
  276. json_add_string name "$1"
  277. json_add_array device
  278. _wdev_common_device_config
  279. eval "drv_$1_init_device_config"
  280. json_close_array
  281. json_add_array iface
  282. _wdev_common_iface_config
  283. eval "drv_$1_init_iface_config"
  284. json_close_array
  285. json_dump
  286. }
  287. ;;
  288. setup|teardown)
  289. interface="$1"; shift
  290. data="$1"; shift
  291. export __netifd_device="$interface"
  292. add_driver() {
  293. [[ "$name" == "$1" ]] || return 0
  294. _wdev_handler "$1" "$cmd"
  295. }
  296. ;;
  297. esac
  298. }