netifd-wireless.sh 7.8 KB

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