netifd-wireless.sh 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451
  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 band hwmode htmode
  34. auto_channel=0
  35. enable_ht=0
  36. hwmode="${hwmode##11}"
  37. case "$channel" in
  38. ""|0|auto)
  39. channel=0
  40. auto_channel=1
  41. ;;
  42. [0-9]*) ;;
  43. *)
  44. wireless_setup_failed "INVALID_CHANNEL"
  45. ;;
  46. esac
  47. case "$hwmode" in
  48. a|b|g|ad) ;;
  49. *)
  50. if [ "$channel" -gt 14 ]; then
  51. hwmode=a
  52. else
  53. hwmode=g
  54. fi
  55. ;;
  56. esac
  57. case "$band" in
  58. 2g) hwmode=g;;
  59. 5g|6g) hwmode=a;;
  60. 60g) hwmode=ad;;
  61. *)
  62. case "$hwmode" in
  63. *a) band=5g;;
  64. *ad) band=60g;;
  65. *b|*g) band=2g;;
  66. esac
  67. ;;
  68. esac
  69. case "$htmode" in
  70. HE*|EHT*) wpa3_cipher="GCMP-256 ";;
  71. *) wpa3_cipher="";;
  72. esac
  73. }
  74. _wdev_handler() {
  75. json_load "$data"
  76. json_select config
  77. _wdev_prepare_channel
  78. json_select ..
  79. eval "drv_$1_$2 \"$interface\""
  80. }
  81. _wdev_msg_call() {
  82. local old_cb
  83. json_set_namespace wdev old_cb
  84. "$@"
  85. json_set_namespace $old_cb
  86. }
  87. _wdev_wrapper() {
  88. while [ -n "$1" ]; do
  89. eval "$1() { _wdev_msg_call _$1 \"\$@\"; }"
  90. shift
  91. done
  92. }
  93. _wdev_notify_init() {
  94. local command="$1"; shift;
  95. json_init
  96. json_add_int "command" "$command"
  97. json_add_string "device" "$__netifd_device"
  98. while [ -n "$1" ]; do
  99. local name="$1"; shift
  100. local value="$1"; shift
  101. json_add_string "$name" "$value"
  102. done
  103. json_add_object "data"
  104. }
  105. _wdev_notify() {
  106. local options="$1"
  107. json_close_object
  108. ubus $options call network.wireless notify "$(json_dump)"
  109. }
  110. _wdev_add_variables() {
  111. while [ -n "$1" ]; do
  112. local var="${1%%=*}"
  113. local val="$1"
  114. shift
  115. [[ "$var" = "$val" ]] && continue
  116. val="${val#*=}"
  117. json_add_string "$var" "$val"
  118. done
  119. }
  120. _wireless_add_vif() {
  121. local name="$1"; shift
  122. local ifname="$1"; shift
  123. _wdev_notify_init $CMD_SET_DATA "interface" "$name"
  124. json_add_string "ifname" "$ifname"
  125. _wdev_add_variables "$@"
  126. _wdev_notify
  127. }
  128. _wireless_add_vlan() {
  129. local name="$1"; shift
  130. local ifname="$1"; shift
  131. _wdev_notify_init $CMD_SET_DATA interface "$__cur_interface" "vlan" "$name"
  132. json_add_string "ifname" "$ifname"
  133. _wdev_add_variables "$@"
  134. _wdev_notify
  135. }
  136. _wireless_set_up() {
  137. _wdev_notify_init $CMD_UP
  138. _wdev_notify
  139. }
  140. _wireless_set_data() {
  141. _wdev_notify_init $CMD_SET_DATA
  142. _wdev_add_variables "$@"
  143. _wdev_notify
  144. }
  145. _wireless_add_process() {
  146. _wdev_notify_init $CMD_PROCESS_ADD
  147. local exe="$2"
  148. [ -L "$exe" ] && exe="$(readlink -f "$exe")"
  149. json_add_int pid "$1"
  150. json_add_string exe "$exe"
  151. [ -n "$3" ] && json_add_boolean required 1
  152. [ -n "$4" ] && json_add_boolean keep 1
  153. exe2="$(readlink -f /proc/$1/exe)"
  154. [ "$exe" != "$exe2" ] && echo "WARNING (wireless_add_process): executable path $exe does not match process $1 path ($exe2)"
  155. _wdev_notify
  156. }
  157. _wireless_process_kill_all() {
  158. _wdev_notify_init $CMD_PROCESS_KILL_ALL
  159. [ -n "$1" ] && json_add_int signal "$1"
  160. _wdev_notify
  161. }
  162. _wireless_set_retry() {
  163. _wdev_notify_init $CMD_SET_RETRY
  164. json_add_int retry "$1"
  165. _wdev_notify
  166. }
  167. _wdev_wrapper \
  168. wireless_add_vif \
  169. wireless_add_vlan \
  170. wireless_set_up \
  171. wireless_set_data \
  172. wireless_add_process \
  173. wireless_process_kill_all \
  174. wireless_set_retry \
  175. wireless_vif_parse_encryption() {
  176. json_get_vars encryption rsn_override
  177. set_default encryption none
  178. set_default rsn_override 1
  179. auth_mode_open=1
  180. auth_mode_shared=0
  181. auth_type=none
  182. wpa_override_cipher=
  183. rsn_override_pairwise=
  184. if [ "$hwmode" = "ad" ]; then
  185. wpa_cipher="GCMP"
  186. else
  187. wpa_cipher="CCMP"
  188. case "$encryption" in
  189. sae*|wpa3*|psk3*|owe)
  190. if [ "$rsn_override" -gt 0 ]; then
  191. wpa_override_cipher="${wpa3_cipher}$wpa_cipher"
  192. else
  193. wpa_cipher="${wpa3_cipher}$wpa_cipher"
  194. fi
  195. ;;
  196. esac
  197. fi
  198. case "$encryption" in
  199. *tkip+aes|*tkip+ccmp|*aes+tkip|*ccmp+tkip) wpa_cipher="CCMP TKIP";;
  200. *ccmp256) wpa_cipher="CCMP-256";;
  201. *aes|*ccmp) wpa_cipher="CCMP";;
  202. *tkip) wpa_cipher="TKIP";;
  203. *gcmp256) wpa_cipher="GCMP-256";;
  204. *gcmp) wpa_cipher="GCMP";;
  205. wpa3-192*) wpa_cipher="GCMP-256";;
  206. *) rsn_override_pairwise="$wpa_override_cipher";;
  207. esac
  208. # 802.11n requires CCMP for WPA
  209. [ "$enable_ht:$wpa_cipher" = "1:TKIP" ] && wpa_cipher="CCMP TKIP"
  210. # Examples:
  211. # psk-mixed/tkip => WPA1+2 PSK, TKIP
  212. # wpa-psk2/tkip+aes => WPA2 PSK, CCMP+TKIP
  213. # wpa2/tkip+aes => WPA2 RADIUS, CCMP+TKIP
  214. case "$encryption" in
  215. wpa2*|wpa3*|*psk2*|psk3*|sae*|owe*)
  216. wpa=2
  217. ;;
  218. wpa*mixed*|*psk*mixed*)
  219. wpa=3
  220. ;;
  221. wpa*|*psk*)
  222. wpa=1
  223. ;;
  224. *)
  225. wpa=0
  226. wpa_cipher=
  227. ;;
  228. esac
  229. wpa_pairwise="$wpa_cipher"
  230. case "$encryption" in
  231. owe*)
  232. auth_type=owe
  233. ;;
  234. wpa3-192*)
  235. auth_type=eap192
  236. ;;
  237. wpa3-mixed*)
  238. auth_type=eap-eap2
  239. ;;
  240. wpa3*)
  241. auth_type=eap2
  242. ;;
  243. psk3-mixed*|sae-mixed*)
  244. auth_type=psk-sae
  245. ;;
  246. psk3*|sae*)
  247. auth_type=sae
  248. ;;
  249. *psk*)
  250. auth_type=psk
  251. ;;
  252. *wpa*|*8021x*)
  253. auth_type=eap
  254. ;;
  255. *wep*)
  256. auth_type=wep
  257. case "$encryption" in
  258. *shared*)
  259. auth_mode_open=0
  260. auth_mode_shared=1
  261. ;;
  262. *mixed*)
  263. auth_mode_shared=1
  264. ;;
  265. esac
  266. ;;
  267. esac
  268. }
  269. _wireless_set_brsnoop_isolation() {
  270. local multicast_to_unicast="$1"
  271. local isolate
  272. json_get_vars isolate proxy_arp
  273. [ ${isolate:-0} -gt 0 -o -z "$network_bridge" ] && return
  274. [ ${multicast_to_unicast:-1} -gt 0 -o ${proxy_arp:-0} -gt 0 ] && json_add_boolean isolate 1
  275. }
  276. for_each_interface() {
  277. local _w_types="$1"; shift
  278. local _w_ifaces _w_iface
  279. local _w_type
  280. local _w_found
  281. local multicast_to_unicast
  282. json_get_keys _w_ifaces interfaces
  283. json_select interfaces
  284. for _w_iface in $_w_ifaces; do
  285. json_select "$_w_iface"
  286. if [ -n "$_w_types" ]; then
  287. json_get_var network_bridge bridge
  288. json_get_var network_ifname bridge-ifname
  289. json_get_var multicast_to_unicast multicast_to_unicast
  290. json_select config
  291. _wireless_set_brsnoop_isolation "$multicast_to_unicast"
  292. json_get_var _w_type mode
  293. json_select ..
  294. _w_types=" $_w_types "
  295. [[ "${_w_types%$_w_type*}" = "$_w_types" ]] && {
  296. json_select ..
  297. continue
  298. }
  299. fi
  300. __cur_interface="$_w_iface"
  301. "$@" "$_w_iface"
  302. json_select ..
  303. done
  304. json_select ..
  305. }
  306. for_each_vlan() {
  307. local _w_vlans _w_vlan
  308. json_get_keys _w_vlans vlans
  309. json_select vlans
  310. for _w_vlan in $_w_vlans; do
  311. json_select "$_w_vlan"
  312. json_select config
  313. "$@" "$_w_vlan"
  314. json_select ..
  315. json_select ..
  316. done
  317. json_select ..
  318. }
  319. for_each_station() {
  320. local _w_stas _w_sta
  321. json_get_keys _w_stas stas
  322. json_select stas
  323. for _w_sta in $_w_stas; do
  324. json_select "$_w_sta"
  325. json_select config
  326. "$@" "$_w_sta"
  327. json_select ..
  328. json_select ..
  329. done
  330. json_select ..
  331. }
  332. _wdev_common_device_config() {
  333. config_add_string channel hwmode band htmode noscan
  334. }
  335. _wdev_common_iface_config() {
  336. config_add_string mode ssid encryption 'key:wpakey'
  337. config_add_boolean bridge_isolate
  338. config_add_array tags
  339. }
  340. _wdev_common_vlan_config() {
  341. config_add_string name vid iface
  342. config_add_boolean bridge_isolate
  343. }
  344. _wdev_common_station_config() {
  345. config_add_string mac key vid iface
  346. }
  347. init_wireless_driver() {
  348. name="$1"; shift
  349. cmd="$1"; shift
  350. case "$cmd" in
  351. dump)
  352. add_driver() {
  353. eval "drv_$1_cleanup"
  354. json_init
  355. json_add_string name "$1"
  356. json_add_array device
  357. _wdev_common_device_config
  358. eval "drv_$1_init_device_config"
  359. json_close_array
  360. json_add_array iface
  361. _wdev_common_iface_config
  362. eval "drv_$1_init_iface_config"
  363. json_close_array
  364. json_add_array vlan
  365. _wdev_common_vlan_config
  366. eval "drv_$1_init_vlan_config"
  367. json_close_array
  368. json_add_array station
  369. _wdev_common_station_config
  370. eval "drv_$1_init_station_config"
  371. json_close_array
  372. json_dump
  373. }
  374. ;;
  375. setup|teardown)
  376. interface="$1"; shift
  377. data="$1"; shift
  378. export __netifd_device="$interface"
  379. add_driver() {
  380. [[ "$name" == "$1" ]] || return 0
  381. _wdev_handler "$1" "$cmd"
  382. }
  383. ;;
  384. esac
  385. }