OpenWrt – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | #!/bin/sh |
2 | . /lib/netifd/netifd-wireless.sh |
||
3 | . /lib/netifd/hostapd.sh |
||
4 | |||
5 | init_wireless_driver "$@" |
||
6 | |||
7 | MP_CONFIG_INT="mesh_retry_timeout mesh_confirm_timeout mesh_holding_timeout mesh_max_peer_links |
||
8 | mesh_max_retries mesh_ttl mesh_element_ttl mesh_hwmp_max_preq_retries |
||
9 | mesh_path_refresh_time mesh_min_discovery_timeout mesh_hwmp_active_path_timeout |
||
10 | mesh_hwmp_preq_min_interval mesh_hwmp_net_diameter_traversal_time mesh_hwmp_rootmode |
||
11 | mesh_hwmp_rann_interval mesh_gate_announcements mesh_sync_offset_max_neighor |
||
12 | mesh_rssi_threshold mesh_hwmp_active_path_to_root_timeout mesh_hwmp_root_interval |
||
13 | mesh_hwmp_confirmation_interval mesh_awake_window mesh_plink_timeout" |
||
14 | MP_CONFIG_BOOL="mesh_auto_open_plinks mesh_fwding" |
||
15 | MP_CONFIG_STRING="mesh_power_mode" |
||
16 | |||
17 | iw() { |
||
18 | command iw $@ || logger -t mac80211 "Failed command: iw $@" |
||
19 | } |
||
20 | |||
21 | drv_mac80211_init_device_config() { |
||
22 | hostapd_common_add_device_config |
||
23 | |||
24 | config_add_string path phy 'macaddr:macaddr' |
||
25 | config_add_string hwmode |
||
26 | config_add_int beacon_int chanbw frag rts |
||
27 | config_add_int rxantenna txantenna antenna_gain txpower distance |
||
28 | config_add_boolean noscan ht_coex |
||
29 | config_add_array ht_capab |
||
30 | config_add_array channels |
||
31 | config_add_boolean \ |
||
32 | rxldpc \ |
||
33 | short_gi_80 \ |
||
34 | short_gi_160 \ |
||
35 | tx_stbc_2by1 \ |
||
36 | su_beamformer \ |
||
37 | su_beamformee \ |
||
38 | mu_beamformer \ |
||
39 | mu_beamformee \ |
||
40 | vht_txop_ps \ |
||
41 | htc_vht \ |
||
42 | rx_antenna_pattern \ |
||
43 | tx_antenna_pattern |
||
44 | config_add_int vht_max_a_mpdu_len_exp vht_max_mpdu vht_link_adapt vht160 rx_stbc tx_stbc |
||
45 | config_add_boolean \ |
||
46 | ldpc \ |
||
47 | greenfield \ |
||
48 | short_gi_20 \ |
||
49 | short_gi_40 \ |
||
50 | max_amsdu \ |
||
51 | dsss_cck_40 |
||
52 | } |
||
53 | |||
54 | drv_mac80211_init_iface_config() { |
||
55 | hostapd_common_add_bss_config |
||
56 | |||
57 | config_add_string 'macaddr:macaddr' ifname |
||
58 | |||
59 | config_add_boolean wds powersave |
||
60 | config_add_int maxassoc |
||
61 | config_add_int max_listen_int |
||
62 | config_add_int dtim_period |
||
63 | config_add_int start_disabled |
||
64 | |||
65 | # mesh |
||
66 | config_add_string mesh_id |
||
67 | config_add_int $MP_CONFIG_INT |
||
68 | config_add_boolean $MP_CONFIG_BOOL |
||
69 | config_add_string $MP_CONFIG_STRING |
||
70 | } |
||
71 | |||
72 | mac80211_add_capabilities() { |
||
73 | local __var="$1"; shift |
||
74 | local __mask="$1"; shift |
||
75 | local __out= oifs |
||
76 | |||
77 | oifs="$IFS" |
||
78 | IFS=: |
||
79 | for capab in "$@"; do |
||
80 | set -- $capab |
||
81 | |||
82 | [ "$(($4))" -gt 0 ] || continue |
||
83 | [ "$(($__mask & $2))" -eq "$((${3:-$2}))" ] || continue |
||
84 | __out="$__out[$1]" |
||
85 | done |
||
86 | IFS="$oifs" |
||
87 | |||
88 | export -n -- "$__var=$__out" |
||
89 | } |
||
90 | |||
91 | mac80211_hostapd_setup_base() { |
||
92 | local phy="$1" |
||
93 | |||
94 | json_select config |
||
95 | |||
96 | [ "$auto_channel" -gt 0 ] && channel=acs_survey |
||
97 | [ "$auto_channel" -gt 0 ] && json_get_values channel_list channels |
||
98 | |||
99 | json_get_vars noscan ht_coex |
||
100 | json_get_values ht_capab_list ht_capab |
||
101 | |||
102 | ieee80211n=1 |
||
103 | ht_capab= |
||
104 | case "$htmode" in |
||
105 | VHT20|HT20) ;; |
||
106 | HT40*|VHT40|VHT80|VHT160) |
||
107 | case "$hwmode" in |
||
108 | a) |
||
109 | case "$(( ($channel / 4) % 2 ))" in |
||
110 | 1) ht_capab="[HT40+]";; |
||
111 | 0) ht_capab="[HT40-]";; |
||
112 | esac |
||
113 | ;; |
||
114 | *) |
||
115 | case "$htmode" in |
||
116 | HT40+) ht_capab="[HT40+]";; |
||
117 | HT40-) ht_capab="[HT40-]";; |
||
118 | *) |
||
119 | if [ "$channel" -lt 7 ]; then |
||
120 | ht_capab="[HT40+]" |
||
121 | else |
||
122 | ht_capab="[HT40-]" |
||
123 | fi |
||
124 | ;; |
||
125 | esac |
||
126 | ;; |
||
127 | esac |
||
128 | [ "$auto_channel" -gt 0 ] && ht_capab="[HT40+]" |
||
129 | ;; |
||
130 | *) ieee80211n= ;; |
||
131 | esac |
||
132 | |||
133 | [ -n "$ieee80211n" ] && { |
||
134 | append base_cfg "ieee80211n=1" "$N" |
||
135 | |||
136 | set_default ht_coex 0 |
||
137 | append base_cfg "ht_coex=$ht_coex" "$N" |
||
138 | |||
139 | json_get_vars \ |
||
140 | ldpc:1 \ |
||
141 | greenfield:0 \ |
||
142 | short_gi_20:1 \ |
||
143 | short_gi_40:1 \ |
||
144 | tx_stbc:1 \ |
||
145 | rx_stbc:3 \ |
||
146 | max_amsdu:1 \ |
||
147 | dsss_cck_40:1 |
||
148 | |||
149 | ht_cap_mask=0 |
||
150 | for cap in $(iw phy "$phy" info | grep 'Capabilities:' | cut -d: -f2); do |
||
151 | ht_cap_mask="$(($ht_cap_mask | $cap))" |
||
152 | done |
||
153 | |||
154 | cap_rx_stbc=$((($ht_cap_mask >> 8) & 3)) |
||
155 | [ "$rx_stbc" -lt "$cap_rx_stbc" ] && cap_rx_stbc="$rx_stbc" |
||
156 | ht_cap_mask="$(( ($ht_cap_mask & ~(0x300)) | ($cap_rx_stbc << 8) ))" |
||
157 | |||
158 | mac80211_add_capabilities ht_capab_flags $ht_cap_mask \ |
||
159 | LDPC:0x1::$ldpc \ |
||
160 | GF:0x10::$greenfield \ |
||
161 | SHORT-GI-20:0x20::$short_gi_20 \ |
||
162 | SHORT-GI-40:0x40::$short_gi_40 \ |
||
163 | TX-STBC:0x80::$tx_stbc \ |
||
164 | RX-STBC1:0x300:0x100:1 \ |
||
165 | RX-STBC12:0x300:0x200:1 \ |
||
166 | RX-STBC123:0x300:0x300:1 \ |
||
167 | MAX-AMSDU-7935:0x800::$max_amsdu \ |
||
168 | DSSS_CCK-40:0x1000::$dsss_cck_40 |
||
169 | |||
170 | ht_capab="$ht_capab$ht_capab_flags" |
||
171 | [ -n "$ht_capab" ] && append base_cfg "ht_capab=$ht_capab" "$N" |
||
172 | } |
||
173 | |||
174 | # 802.11ac |
||
175 | enable_ac=0 |
||
176 | idx="$channel" |
||
177 | case "$htmode" in |
||
178 | VHT20) enable_ac=1;; |
||
179 | VHT40) |
||
180 | case "$(( ($channel / 4) % 2 ))" in |
||
181 | 1) idx=$(($channel + 2));; |
||
182 | 0) idx=$(($channel - 2));; |
||
183 | esac |
||
184 | enable_ac=1 |
||
185 | append base_cfg "vht_oper_chwidth=0" "$N" |
||
186 | append base_cfg "vht_oper_centr_freq_seg0_idx=$idx" "$N" |
||
187 | ;; |
||
188 | VHT80) |
||
189 | case "$(( ($channel / 4) % 4 ))" in |
||
190 | 1) idx=$(($channel + 6));; |
||
191 | 2) idx=$(($channel + 2));; |
||
192 | 3) idx=$(($channel - 2));; |
||
193 | 0) idx=$(($channel - 6));; |
||
194 | esac |
||
195 | enable_ac=1 |
||
196 | append base_cfg "vht_oper_chwidth=1" "$N" |
||
197 | append base_cfg "vht_oper_centr_freq_seg0_idx=$idx" "$N" |
||
198 | ;; |
||
199 | VHT160) |
||
200 | case "$channel" in |
||
201 | 36|40|44|48|52|56|60|64) idx=50;; |
||
202 | 100|104|108|112|116|120|124|128) idx=114;; |
||
203 | esac |
||
204 | enable_ac=1 |
||
205 | append base_cfg "vht_oper_chwidth=2" "$N" |
||
206 | append base_cfg "vht_oper_centr_freq_seg0_idx=$idx" "$N" |
||
207 | ;; |
||
208 | esac |
||
209 | |||
210 | if [ "$enable_ac" != "0" ]; then |
||
211 | json_get_vars \ |
||
212 | rxldpc:1 \ |
||
213 | short_gi_80:1 \ |
||
214 | short_gi_160:1 \ |
||
215 | tx_stbc_2by1:1 \ |
||
216 | su_beamformer:1 \ |
||
217 | su_beamformee:1 \ |
||
218 | mu_beamformer:1 \ |
||
219 | mu_beamformee:1 \ |
||
220 | vht_txop_ps:1 \ |
||
221 | htc_vht:1 \ |
||
222 | rx_antenna_pattern:1 \ |
||
223 | tx_antenna_pattern:1 \ |
||
224 | vht_max_a_mpdu_len_exp:7 \ |
||
225 | vht_max_mpdu:11454 \ |
||
226 | rx_stbc:4 \ |
||
227 | vht_link_adapt:3 \ |
||
228 | vht160:2 |
||
229 | |||
230 | append base_cfg "ieee80211ac=1" "$N" |
||
231 | vht_cap=0 |
||
232 | for cap in $(iw phy "$phy" info | awk -F "[()]" '/VHT Capabilities/ { print $2 }'); do |
||
233 | vht_cap="$(($vht_cap | $cap))" |
||
234 | done |
||
235 | |||
236 | cap_rx_stbc=$((($vht_cap >> 8) & 7)) |
||
237 | [ "$rx_stbc" -lt "$cap_rx_stbc" ] && cap_rx_stbc="$rx_stbc" |
||
238 | vht_cap="$(( ($vht_cap & ~(0x700)) | ($cap_rx_stbc << 8) ))" |
||
239 | |||
240 | mac80211_add_capabilities vht_capab $vht_cap \ |
||
241 | RXLDPC:0x10::$rxldpc \ |
||
242 | SHORT-GI-80:0x20::$short_gi_80 \ |
||
243 | SHORT-GI-160:0x40::$short_gi_160 \ |
||
244 | TX-STBC-2BY1:0x80::$tx_stbc_2by1 \ |
||
245 | SU-BEAMFORMER:0x800::$su_beamformer \ |
||
246 | SU-BEAMFORMEE:0x1000::$su_beamformee \ |
||
247 | MU-BEAMFORMER:0x80000::$mu_beamformer \ |
||
248 | MU-BEAMFORMEE:0x100000::$mu_beamformee \ |
||
249 | VHT-TXOP-PS:0x200000::$vht_txop_ps \ |
||
250 | HTC-VHT:0x400000::$htc_vht \ |
||
251 | RX-ANTENNA-PATTERN:0x10000000::$rx_antenna_pattern \ |
||
252 | TX-ANTENNA-PATTERN:0x20000000::$tx_antenna_pattern \ |
||
253 | RX-STBC-1:0x700:0x100:1 \ |
||
254 | RX-STBC-12:0x700:0x200:1 \ |
||
255 | RX-STBC-123:0x700:0x300:1 \ |
||
256 | RX-STBC-1234:0x700:0x400:1 \ |
||
257 | |||
258 | # supported Channel widths |
||
259 | vht160_hw=0 |
||
260 | [ "$(($vht_cap & 12))" -eq 4 -a 1 -le "$vht160" ] && \ |
||
261 | vht160_hw=1 |
||
262 | [ "$(($vht_cap & 12))" -eq 8 -a 2 -le "$vht160" ] && \ |
||
263 | vht160_hw=2 |
||
264 | [ "$vht160_hw" = 1 ] && vht_capab="$vht_capab[VHT160]" |
||
265 | [ "$vht160_hw" = 2 ] && vht_capab="$vht_capab[VHT160-80PLUS80]" |
||
266 | |||
267 | # maximum MPDU length |
||
268 | vht_max_mpdu_hw=3895 |
||
269 | [ "$(($vht_cap & 3))" -ge 1 -a 7991 -le "$vht_max_mpdu" ] && \ |
||
270 | vht_max_mpdu_hw=7991 |
||
271 | [ "$(($vht_cap & 3))" -ge 2 -a 11454 -le "$vht_max_mpdu" ] && \ |
||
272 | vht_max_mpdu_hw=11454 |
||
273 | [ "$vht_max_mpdu_hw" != 3895 ] && \ |
||
274 | vht_capab="$vht_capab[MAX-MPDU-$vht_max_mpdu_hw]" |
||
275 | |||
276 | # maximum A-MPDU length exponent |
||
277 | vht_max_a_mpdu_len_exp_hw=0 |
||
278 | [ "$(($vht_cap & 58720256))" -ge 8388608 -a 1 -le "$vht_max_a_mpdu_len_exp" ] && \ |
||
279 | vht_max_a_mpdu_len_exp_hw=1 |
||
280 | [ "$(($vht_cap & 58720256))" -ge 16777216 -a 2 -le "$vht_max_a_mpdu_len_exp" ] && \ |
||
281 | vht_max_a_mpdu_len_exp_hw=2 |
||
282 | [ "$(($vht_cap & 58720256))" -ge 25165824 -a 3 -le "$vht_max_a_mpdu_len_exp" ] && \ |
||
283 | vht_max_a_mpdu_len_exp_hw=3 |
||
284 | [ "$(($vht_cap & 58720256))" -ge 33554432 -a 4 -le "$vht_max_a_mpdu_len_exp" ] && \ |
||
285 | vht_max_a_mpdu_len_exp_hw=4 |
||
286 | [ "$(($vht_cap & 58720256))" -ge 41943040 -a 5 -le "$vht_max_a_mpdu_len_exp" ] && \ |
||
287 | vht_max_a_mpdu_len_exp_hw=5 |
||
288 | [ "$(($vht_cap & 58720256))" -ge 50331648 -a 6 -le "$vht_max_a_mpdu_len_exp" ] && \ |
||
289 | vht_max_a_mpdu_len_exp_hw=6 |
||
290 | [ "$(($vht_cap & 58720256))" -ge 58720256 -a 7 -le "$vht_max_a_mpdu_len_exp" ] && \ |
||
291 | vht_max_a_mpdu_len_exp_hw=7 |
||
292 | vht_capab="$vht_capab[MAX-A-MPDU-LEN-EXP$vht_max_a_mpdu_len_exp_hw]" |
||
293 | |||
294 | # whether or not the STA supports link adaptation using VHT variant |
||
295 | vht_link_adapt_hw=0 |
||
296 | [ "$(($vht_cap & 201326592))" -ge 134217728 -a 2 -le "$vht_link_adapt" ] && \ |
||
297 | vht_link_adapt_hw=2 |
||
298 | [ "$(($vht_cap & 201326592))" -ge 201326592 -a 3 -le "$vht_link_adapt" ] && \ |
||
299 | vht_link_adapt_hw=3 |
||
300 | [ "$vht_link_adapt_hw" != 0 ] && \ |
||
301 | vht_capab="$vht_capab[VHT-LINK-ADAPT-$vht_link_adapt_hw]" |
||
302 | |||
303 | [ -n "$vht_capab" ] && append base_cfg "vht_capab=$vht_capab" "$N" |
||
304 | fi |
||
305 | |||
306 | hostapd_prepare_device_config "$hostapd_conf_file" nl80211 |
||
307 | cat >> "$hostapd_conf_file" <<EOF |
||
308 | ${channel:+channel=$channel} |
||
309 | ${channel_list:+chanlist=$channel_list} |
||
310 | ${noscan:+noscan=$noscan} |
||
311 | $base_cfg |
||
312 | |||
313 | EOF |
||
314 | json_select .. |
||
315 | } |
||
316 | |||
317 | mac80211_hostapd_setup_bss() { |
||
318 | local phy="$1" |
||
319 | local ifname="$2" |
||
320 | local macaddr="$3" |
||
321 | local type="$4" |
||
322 | |||
323 | hostapd_cfg= |
||
324 | append hostapd_cfg "$type=$ifname" "$N" |
||
325 | |||
326 | hostapd_set_bss_options hostapd_cfg "$vif" || return 1 |
||
327 | json_get_vars wds dtim_period max_listen_int start_disabled |
||
328 | |||
329 | set_default wds 0 |
||
330 | set_default start_disabled 0 |
||
331 | |||
332 | [ "$wds" -gt 0 ] && append hostapd_cfg "wds_sta=1" "$N" |
||
333 | [ "$staidx" -gt 0 -o "$start_disabled" -eq 1 ] && append hostapd_cfg "start_disabled=1" "$N" |
||
334 | |||
335 | cat >> /var/run/hostapd-$phy.conf <<EOF |
||
336 | $hostapd_cfg |
||
337 | bssid=$macaddr |
||
338 | ${dtim_period:+dtim_period=$dtim_period} |
||
339 | ${max_listen_int:+max_listen_interval=$max_listen_int} |
||
340 | EOF |
||
341 | } |
||
342 | |||
343 | mac80211_get_addr() { |
||
344 | local phy="$1" |
||
345 | local idx="$(($2 + 1))" |
||
346 | |||
347 | head -n $(($macidx + 1)) /sys/class/ieee80211/${phy}/addresses | tail -n1 |
||
348 | } |
||
349 | |||
350 | mac80211_generate_mac() { |
||
351 | local phy="$1" |
||
352 | local id="${macidx:-0}" |
||
353 | |||
354 | local ref="$(cat /sys/class/ieee80211/${phy}/macaddress)" |
||
355 | local mask="$(cat /sys/class/ieee80211/${phy}/address_mask)" |
||
356 | |||
357 | [ "$mask" = "00:00:00:00:00:00" ] && { |
||
358 | mask="ff:ff:ff:ff:ff:ff"; |
||
359 | |||
360 | [ "$(wc -l < /sys/class/ieee80211/${phy}/addresses)" -gt 1 ] && { |
||
361 | addr="$(mac80211_get_addr "$phy" "$id")" |
||
362 | [ -n "$addr" ] && { |
||
363 | echo "$addr" |
||
364 | return |
||
365 | } |
||
366 | } |
||
367 | } |
||
368 | |||
369 | local oIFS="$IFS"; IFS=":"; set -- $mask; IFS="$oIFS" |
||
370 | |||
371 | local mask1=$1 |
||
372 | local mask6=$6 |
||
373 | |||
374 | local oIFS="$IFS"; IFS=":"; set -- $ref; IFS="$oIFS" |
||
375 | |||
376 | macidx=$(($id + 1)) |
||
377 | [ "$((0x$mask1))" -gt 0 ] && { |
||
378 | b1="0x$1" |
||
379 | [ "$id" -gt 0 ] && \ |
||
380 | b1=$(($b1 ^ ((($id - 1) << 2) | 0x2))) |
||
381 | printf "%02x:%s:%s:%s:%s:%s" $b1 $2 $3 $4 $5 $6 |
||
382 | return |
||
383 | } |
||
384 | |||
385 | [ "$((0x$mask6))" -lt 255 ] && { |
||
386 | printf "%s:%s:%s:%s:%s:%02x" $1 $2 $3 $4 $5 $(( 0x$6 ^ $id )) |
||
387 | return |
||
388 | } |
||
389 | |||
390 | off2=$(( (0x$6 + $id) / 0x100 )) |
||
391 | printf "%s:%s:%s:%s:%02x:%02x" \ |
||
392 | $1 $2 $3 $4 \ |
||
393 | $(( (0x$5 + $off2) % 0x100 )) \ |
||
394 | $(( (0x$6 + $id) % 0x100 )) |
||
395 | } |
||
396 | |||
397 | find_phy() { |
||
398 | [ -n "$phy" -a -d /sys/class/ieee80211/$phy ] && return 0 |
||
399 | [ -n "$path" ] && { |
||
400 | for phy in $(ls /sys/class/ieee80211 2>/dev/null); do |
||
401 | case "$(readlink -f /sys/class/ieee80211/$phy/device)" in |
||
402 | *$path) return 0;; |
||
403 | esac |
||
404 | done |
||
405 | } |
||
406 | [ -n "$macaddr" ] && { |
||
407 | for phy in $(ls /sys/class/ieee80211 2>/dev/null); do |
||
408 | grep -i -q "$macaddr" "/sys/class/ieee80211/${phy}/macaddress" && return 0 |
||
409 | done |
||
410 | } |
||
411 | return 1 |
||
412 | } |
||
413 | |||
414 | mac80211_check_ap() { |
||
415 | has_ap=1 |
||
416 | } |
||
417 | |||
418 | mac80211_iw_interface_add() { |
||
419 | local phy="$1" |
||
420 | local ifname="$2" |
||
421 | local type="$3" |
||
422 | local wdsflag="$4" |
||
423 | local rc |
||
424 | |||
425 | iw phy "$phy" interface add "$ifname" type "$type" $wdsflag |
||
426 | rc="$?" |
||
427 | |||
428 | [ "$rc" = 233 ] && { |
||
429 | # Device might have just been deleted, give the kernel some time to finish cleaning it up |
||
430 | sleep 1 |
||
431 | |||
432 | iw phy "$phy" interface add "$ifname" type "$type" $wdsflag |
||
433 | rc="$?" |
||
434 | } |
||
435 | |||
436 | [ "$rc" = 233 ] && { |
||
437 | # Device might not support virtual interfaces, so the interface never got deleted in the first place. |
||
438 | # Check if the interface already exists, and avoid failing in this case. |
||
439 | ip link show dev "$ifname" >/dev/null 2>/dev/null && rc=0 |
||
440 | } |
||
441 | |||
442 | [ "$rc" != 0 ] && wireless_setup_failed INTERFACE_CREATION_FAILED |
||
443 | return $rc |
||
444 | } |
||
445 | |||
446 | mac80211_prepare_vif() { |
||
447 | json_select config |
||
448 | |||
449 | json_get_vars ifname mode ssid wds powersave macaddr |
||
450 | |||
451 | [ -n "$ifname" ] || ifname="wlan${phy#phy}${if_idx:+-$if_idx}" |
||
452 | if_idx=$((${if_idx:-0} + 1)) |
||
453 | |||
454 | set_default wds 0 |
||
455 | set_default powersave 0 |
||
456 | |||
457 | json_select .. |
||
458 | |||
459 | [ -n "$macaddr" ] || { |
||
460 | macaddr="$(mac80211_generate_mac $phy)" |
||
461 | macidx="$(($macidx + 1))" |
||
462 | } |
||
463 | |||
464 | json_add_object data |
||
465 | json_add_string ifname "$ifname" |
||
466 | json_close_object |
||
467 | json_select config |
||
468 | |||
469 | # It is far easier to delete and create the desired interface |
||
470 | case "$mode" in |
||
471 | adhoc) |
||
472 | mac80211_iw_interface_add "$phy" "$ifname" adhoc || return |
||
473 | ;; |
||
474 | ap) |
||
475 | # Hostapd will handle recreating the interface and |
||
476 | # subsequent virtual APs belonging to the same PHY |
||
477 | if [ -n "$hostapd_ctrl" ]; then |
||
478 | type=bss |
||
479 | else |
||
480 | type=interface |
||
481 | fi |
||
482 | |||
483 | mac80211_hostapd_setup_bss "$phy" "$ifname" "$macaddr" "$type" || return |
||
484 | |||
485 | [ -n "$hostapd_ctrl" ] || { |
||
486 | mac80211_iw_interface_add "$phy" "$ifname" __ap || return |
||
487 | hostapd_ctrl="${hostapd_ctrl:-/var/run/hostapd/$ifname}" |
||
488 | } |
||
489 | ;; |
||
490 | mesh) |
||
491 | mac80211_iw_interface_add "$phy" "$ifname" mp || return |
||
492 | ;; |
||
493 | monitor) |
||
494 | mac80211_iw_interface_add "$phy" "$ifname" monitor || return |
||
495 | ;; |
||
496 | sta) |
||
497 | local wdsflag= |
||
498 | staidx="$(($staidx + 1))" |
||
499 | [ "$wds" -gt 0 ] && wdsflag="4addr on" |
||
500 | mac80211_iw_interface_add "$phy" "$ifname" managed "$wdsflag" || return |
||
501 | [ "$powersave" -gt 0 ] && powersave="on" || powersave="off" |
||
502 | iw "$ifname" set power_save "$powersave" |
||
503 | ;; |
||
504 | esac |
||
505 | |||
506 | case "$mode" in |
||
507 | monitor|mesh) |
||
508 | [ "$auto_channel" -gt 0 ] || iw dev "$ifname" set channel "$channel" $htmode |
||
509 | ;; |
||
510 | esac |
||
511 | |||
512 | if [ "$mode" != "ap" ]; then |
||
513 | # ALL ap functionality will be passed to hostapd |
||
514 | # All interfaces must have unique mac addresses |
||
515 | # which can either be explicitly set in the device |
||
516 | # section, or automatically generated |
||
517 | ip link set dev "$ifname" address "$macaddr" |
||
518 | fi |
||
519 | |||
520 | json_select .. |
||
521 | } |
||
522 | |||
523 | mac80211_setup_supplicant() { |
||
524 | wpa_supplicant_prepare_interface "$ifname" nl80211 || return 1 |
||
525 | if [ "$mode" = "sta" ]; then |
||
526 | wpa_supplicant_add_network "$ifname" |
||
527 | else |
||
528 | wpa_supplicant_add_network "$ifname" "$freq" "$htmode" "$noscan" |
||
529 | fi |
||
530 | wpa_supplicant_run "$ifname" ${hostapd_ctrl:+-H $hostapd_ctrl} |
||
531 | } |
||
532 | |||
533 | mac80211_setup_supplicant_noctl() { |
||
534 | wpa_supplicant_prepare_interface "$ifname" nl80211 || return 1 |
||
535 | wpa_supplicant_add_network "$ifname" "$freq" "$htmode" "$noscan" |
||
536 | wpa_supplicant_run "$ifname" |
||
537 | } |
||
538 | |||
539 | mac80211_setup_adhoc_htmode() { |
||
540 | case "$htmode" in |
||
541 | VHT20|HT20) ibss_htmode=HT20;; |
||
542 | HT40*|VHT40|VHT160) |
||
543 | case "$hwmode" in |
||
544 | a) |
||
545 | case "$(( ($channel / 4) % 2 ))" in |
||
546 | 1) ibss_htmode="HT40+" ;; |
||
547 | 0) ibss_htmode="HT40-";; |
||
548 | esac |
||
549 | ;; |
||
550 | *) |
||
551 | case "$htmode" in |
||
552 | HT40+) ibss_htmode="HT40+";; |
||
553 | HT40-) ibss_htmode="HT40-";; |
||
554 | *) |
||
555 | if [ "$channel" -lt 7 ]; then |
||
556 | ibss_htmode="HT40+" |
||
557 | else |
||
558 | ibss_htmode="HT40-" |
||
559 | fi |
||
560 | ;; |
||
561 | esac |
||
562 | ;; |
||
563 | esac |
||
564 | [ "$auto_channel" -gt 0 ] && ibss_htmode="HT40+" |
||
565 | ;; |
||
566 | VHT80) |
||
567 | ibss_htmode="80MHZ" |
||
568 | ;; |
||
569 | NONE|NOHT) |
||
570 | ibss_htmode="NOHT" |
||
571 | ;; |
||
572 | *) ibss_htmode="" ;; |
||
573 | esac |
||
574 | |||
575 | } |
||
576 | |||
577 | mac80211_setup_adhoc() { |
||
578 | json_get_vars bssid ssid key mcast_rate |
||
579 | |||
580 | keyspec= |
||
581 | [ "$auth_type" = "wep" ] && { |
||
582 | set_default key 1 |
||
583 | case "$key" in |
||
584 | [1234]) |
||
585 | local idx |
||
586 | for idx in 1 2 3 4; do |
||
587 | json_get_var ikey "key$idx" |
||
588 | |||
589 | [ -n "$ikey" ] && { |
||
590 | ikey="$(($idx - 1)):$(prepare_key_wep "$ikey")" |
||
591 | [ $idx -eq $key ] && ikey="d:$ikey" |
||
592 | append keyspec "$ikey" |
||
593 | } |
||
594 | done |
||
595 | ;; |
||
596 | *) |
||
597 | append keyspec "d:0:$(prepare_key_wep "$key")" |
||
598 | ;; |
||
599 | esac |
||
600 | } |
||
601 | |||
602 | brstr= |
||
603 | for br in $basic_rate_list; do |
||
604 | wpa_supplicant_add_rate brstr "$br" |
||
605 | done |
||
606 | |||
607 | mcval= |
||
608 | [ -n "$mcast_rate" ] && wpa_supplicant_add_rate mcval "$mcast_rate" |
||
609 | |||
610 | iw dev "$ifname" ibss join "$ssid" $freq $ibss_htmode fixed-freq $bssid \ |
||
611 | beacon-interval $beacon_int \ |
||
612 | ${brstr:+basic-rates $brstr} \ |
||
613 | ${mcval:+mcast-rate $mcval} \ |
||
614 | ${keyspec:+keys $keyspec} |
||
615 | } |
||
616 | |||
617 | mac80211_setup_mesh() { |
||
618 | json_get_vars ssid mesh_id mcast_rate |
||
619 | |||
620 | mcval= |
||
621 | [ -n "$mcast_rate" ] && wpa_supplicant_add_rate mcval "$mcast_rate" |
||
622 | [ -n "$mesh_id" ] && ssid="$mesh_id" |
||
623 | |||
624 | case "$htmode" in |
||
625 | VHT20|HT20) mesh_htmode=HT20;; |
||
626 | HT40*|VHT40) |
||
627 | case "$hwmode" in |
||
628 | a) |
||
629 | case "$(( ($channel / 4) % 2 ))" in |
||
630 | 1) mesh_htmode="HT40+" ;; |
||
631 | 0) mesh_htmode="HT40-";; |
||
632 | esac |
||
633 | ;; |
||
634 | *) |
||
635 | case "$htmode" in |
||
636 | HT40+) mesh_htmode="HT40+";; |
||
637 | HT40-) mesh_htmode="HT40-";; |
||
638 | *) |
||
639 | if [ "$channel" -lt 7 ]; then |
||
640 | mesh_htmode="HT40+" |
||
641 | else |
||
642 | mesh_htmode="HT40-" |
||
643 | fi |
||
644 | ;; |
||
645 | esac |
||
646 | ;; |
||
647 | esac |
||
648 | ;; |
||
649 | VHT80) |
||
650 | mesh_htmode="80Mhz" |
||
651 | ;; |
||
652 | VHT160) |
||
653 | mesh_htmode="160Mhz" |
||
654 | ;; |
||
655 | *) mesh_htmode="NOHT" ;; |
||
656 | esac |
||
657 | iw dev "$ifname" mesh join "$ssid" freq $freq $mesh_htmode \ |
||
658 | ${mcval:+mcast-rate $mcval} \ |
||
659 | beacon-interval $beacon_int |
||
660 | } |
||
661 | |||
662 | mac80211_setup_vif() { |
||
663 | local name="$1" |
||
664 | local failed |
||
665 | |||
666 | json_select data |
||
667 | json_get_vars ifname |
||
668 | json_select .. |
||
669 | |||
670 | json_select config |
||
671 | json_get_vars mode |
||
672 | json_get_var vif_txpower txpower |
||
673 | |||
674 | ip link set dev "$ifname" up || { |
||
675 | wireless_setup_vif_failed IFUP_ERROR |
||
676 | json_select .. |
||
677 | return |
||
678 | } |
||
679 | |||
680 | set_default vif_txpower "$txpower" |
||
681 | [ -z "$vif_txpower" ] || iw dev "$ifname" set txpower fixed "${vif_txpower%%.*}00" |
||
682 | |||
683 | case "$mode" in |
||
684 | mesh) |
||
685 | wireless_vif_parse_encryption |
||
686 | freq="$(get_freq "$phy" "$channel")" |
||
687 | if [ "$wpa" -gt 0 -o "$auto_channel" -gt 0 ] || chan_is_dfs "$phy" "$channel"; then |
||
688 | mac80211_setup_supplicant || failed=1 |
||
689 | else |
||
690 | mac80211_setup_mesh |
||
691 | fi |
||
692 | for var in $MP_CONFIG_INT $MP_CONFIG_BOOL $MP_CONFIG_STRING; do |
||
693 | json_get_var mp_val "$var" |
||
694 | [ -n "$mp_val" ] && iw dev "$ifname" set mesh_param "$var" "$mp_val" |
||
695 | done |
||
696 | ;; |
||
697 | adhoc) |
||
698 | wireless_vif_parse_encryption |
||
699 | mac80211_setup_adhoc_htmode |
||
700 | if [ "$wpa" -gt 0 -o "$auto_channel" -gt 0 ]; then |
||
701 | freq="$(get_freq "$phy" "$channel")" |
||
702 | mac80211_setup_supplicant_noctl || failed=1 |
||
703 | else |
||
704 | mac80211_setup_adhoc |
||
705 | fi |
||
706 | ;; |
||
707 | sta) |
||
708 | mac80211_setup_supplicant || failed=1 |
||
709 | ;; |
||
710 | esac |
||
711 | |||
712 | json_select .. |
||
713 | [ -n "$failed" ] || wireless_add_vif "$name" "$ifname" |
||
714 | } |
||
715 | |||
716 | get_freq() { |
||
717 | local phy="$1" |
||
718 | local chan="$2" |
||
719 | iw "$phy" info | grep -E -m1 "(\* ${chan:-....} MHz${chan:+|\\[$chan\\]})" | grep MHz | awk '{print $2}' |
||
720 | } |
||
721 | |||
722 | chan_is_dfs() { |
||
723 | local phy="$1" |
||
724 | local chan="$2" |
||
725 | iw "$phy" info | grep -E -m1 "(\* ${chan:-....} MHz${chan:+|\\[$chan\\]})" | grep -q "MHz.*radar detection" |
||
726 | return $! |
||
727 | } |
||
728 | |||
729 | mac80211_interface_cleanup() { |
||
730 | local phy="$1" |
||
731 | |||
732 | for wdev in $(list_phy_interfaces "$phy"); do |
||
733 | ip link set dev "$wdev" down 2>/dev/null |
||
734 | iw dev "$wdev" del |
||
735 | done |
||
736 | } |
||
737 | |||
738 | drv_mac80211_cleanup() { |
||
739 | hostapd_common_cleanup |
||
740 | } |
||
741 | |||
742 | drv_mac80211_setup() { |
||
743 | json_select config |
||
744 | json_get_vars \ |
||
745 | phy macaddr path \ |
||
746 | country chanbw distance \ |
||
747 | txpower antenna_gain \ |
||
748 | rxantenna txantenna \ |
||
749 | frag rts beacon_int:100 htmode |
||
750 | json_get_values basic_rate_list basic_rate |
||
751 | json_select .. |
||
752 | |||
753 | find_phy || { |
||
754 | echo "Could not find PHY for device '$1'" |
||
755 | wireless_set_retry 0 |
||
756 | return 1 |
||
757 | } |
||
758 | |||
759 | wireless_set_data phy="$phy" |
||
760 | mac80211_interface_cleanup "$phy" |
||
761 | |||
762 | # convert channel to frequency |
||
763 | [ "$auto_channel" -gt 0 ] || freq="$(get_freq "$phy" "$channel")" |
||
764 | |||
765 | [ -n "$country" ] && { |
||
766 | iw reg get | grep -q "^country $country:" || { |
||
767 | iw reg set "$country" |
||
768 | sleep 1 |
||
769 | } |
||
770 | } |
||
771 | |||
772 | hostapd_conf_file="/var/run/hostapd-$phy.conf" |
||
773 | |||
774 | no_ap=1 |
||
775 | macidx=0 |
||
776 | staidx=0 |
||
777 | |||
778 | [ -n "$chanbw" ] && { |
||
779 | for file in /sys/kernel/debug/ieee80211/$phy/ath9k/chanbw /sys/kernel/debug/ieee80211/$phy/ath5k/bwmode; do |
||
780 | [ -f "$file" ] && echo "$chanbw" > "$file" |
||
781 | done |
||
782 | } |
||
783 | |||
784 | set_default rxantenna all |
||
785 | set_default txantenna all |
||
786 | set_default distance 0 |
||
787 | set_default antenna_gain 0 |
||
788 | |||
789 | iw phy "$phy" set antenna $txantenna $rxantenna >/dev/null 2>&1 |
||
790 | iw phy "$phy" set antenna_gain $antenna_gain |
||
791 | iw phy "$phy" set distance "$distance" |
||
792 | |||
793 | [ -n "$frag" ] && iw phy "$phy" set frag "${frag%%.*}" |
||
794 | [ -n "$rts" ] && iw phy "$phy" set rts "${rts%%.*}" |
||
795 | |||
796 | has_ap= |
||
797 | hostapd_ctrl= |
||
798 | for_each_interface "ap" mac80211_check_ap |
||
799 | |||
800 | rm -f "$hostapd_conf_file" |
||
801 | [ -n "$has_ap" ] && mac80211_hostapd_setup_base "$phy" |
||
802 | |||
803 | for_each_interface "sta adhoc mesh monitor" mac80211_prepare_vif |
||
804 | for_each_interface "ap" mac80211_prepare_vif |
||
805 | |||
806 | [ -n "$hostapd_ctrl" ] && { |
||
807 | /usr/sbin/hostapd -s -P /var/run/wifi-$phy.pid -B "$hostapd_conf_file" |
||
808 | ret="$?" |
||
809 | wireless_add_process "$(cat /var/run/wifi-$phy.pid)" "/usr/sbin/hostapd" 1 |
||
810 | [ "$ret" != 0 ] && { |
||
811 | wireless_setup_failed HOSTAPD_START_FAILED |
||
812 | return |
||
813 | } |
||
814 | } |
||
815 | |||
816 | for_each_interface "ap sta adhoc mesh monitor" mac80211_setup_vif |
||
817 | |||
818 | wireless_set_up |
||
819 | } |
||
820 | |||
821 | list_phy_interfaces() { |
||
822 | local phy="$1" |
||
823 | if [ -d "/sys/class/ieee80211/${phy}/device/net" ]; then |
||
824 | ls "/sys/class/ieee80211/${phy}/device/net" 2>/dev/null; |
||
825 | else |
||
826 | ls "/sys/class/ieee80211/${phy}/device" 2>/dev/null | grep net: | sed -e 's,net:,,g' |
||
827 | fi |
||
828 | } |
||
829 | |||
830 | drv_mac80211_teardown() { |
||
831 | wireless_process_kill_all |
||
832 | |||
833 | json_select data |
||
834 | json_get_vars phy |
||
835 | json_select .. |
||
836 | |||
837 | mac80211_interface_cleanup "$phy" |
||
838 | } |
||
839 | |||
840 | add_driver mac80211 |