source: trunk/package/mac80211/files/lib/wifi/mac80211.sh @ 19915

Last change on this file since 19915 was 19915, checked in by nbd, 6 years ago

mac80211: fix client mode

File size: 10.8 KB
Line 
1#!/bin/sh
2append DRIVERS "mac80211"
3
4mac80211_hostapd_setup_base() {
5        local phy="$1"
6        local ifname="$2"
7
8        cfgfile="/var/run/hostapd-$phy.conf"
9        config_get device "$vif" device
10        config_get country "$device" country
11        config_get hwmode "$device" hwmode
12        config_get channel "$device" channel
13        [ -n "$channel" -a -z "$hwmode" ] && wifi_fixup_hwmode "$device"
14        [ "$channel" = auto ] && channel=
15        [ -n "$hwmode" ] && {
16                config_get hwmode_11n "$device" hwmode_11n
17                [ -n "$hwmode_11n" ] && {
18                        hwmode="$hwmode_11n"
19                        append base_cfg "ieee80211n=1" "$N"
20                        config_get htmode "$device" htmode
21                        config_get ht_capab_list "$device" ht_capab
22                        case "$htmode" in
23                                HT20|HT40+|HT40-) ht_capab="[$htmode]";;
24                                *)ht_capab=;;
25                        esac
26                        for cap in $ht_capab_list; do
27                                ht_capab="$ht_capab[$cap]"
28                        done
29                        [ -n "$ht_capab" ] && append base_cfg "ht_capab=$ht_capab" "$N"
30                }
31        }
32        cat > "$cfgfile" <<EOF
33ctrl_interface=/var/run/hostapd-$phy
34driver=nl80211
35wmm_ac_bk_cwmin=4
36wmm_ac_bk_cwmax=10
37wmm_ac_bk_aifs=7
38wmm_ac_bk_txop_limit=0
39wmm_ac_bk_acm=0
40wmm_ac_be_aifs=3
41wmm_ac_be_cwmin=4
42wmm_ac_be_cwmax=10
43wmm_ac_be_txop_limit=0
44wmm_ac_be_acm=0
45wmm_ac_vi_aifs=2
46wmm_ac_vi_cwmin=3
47wmm_ac_vi_cwmax=4
48wmm_ac_vi_txop_limit=94
49wmm_ac_vi_acm=0
50wmm_ac_vo_aifs=2
51wmm_ac_vo_cwmin=2
52wmm_ac_vo_cwmax=3
53wmm_ac_vo_txop_limit=47
54wmm_ac_vo_acm=0
55tx_queue_data3_aifs=7
56tx_queue_data3_cwmin=15
57tx_queue_data3_cwmax=1023
58tx_queue_data3_burst=0
59tx_queue_data2_aifs=3
60tx_queue_data2_cwmin=15
61tx_queue_data2_cwmax=63
62tx_queue_data2_burst=0
63tx_queue_data1_aifs=1
64tx_queue_data1_cwmin=7
65tx_queue_data1_cwmax=15
66tx_queue_data1_burst=3.0
67tx_queue_data0_aifs=1
68tx_queue_data0_cwmin=3
69tx_queue_data0_cwmax=7
70tx_queue_data0_burst=1.5
71${hwmode:+hw_mode=$hwmode}
72${channel:+channel=$channel}
73${country:+country_code=$country}
74$base_cfg
75
76EOF
77}
78
79mac80211_hostapd_setup_bss() {
80        local phy="$1"
81        local vif="$2"
82
83        hostapd_cfg=
84        cfgfile="/var/run/hostapd-$phy.conf"
85        config_get ifname "$vif" ifname
86
87        if [ -f "$cfgfile" ]; then
88                append hostapd_cfg "bss=$ifname" "$N"
89        else
90                mac80211_hostapd_setup_base "$phy" "$ifname"
91                append hostapd_cfg "interface=$ifname" "$N"
92        fi
93
94        local net_cfg bridge
95        net_cfg="$(find_net_config "$vif")"
96        [ -z "$net_cfg" ] || bridge="$(bridge_interface "$net_cfg")"
97        config_set "$vif" bridge "$bridge"
98
99        hostapd_set_bss_options hostapd_cfg "$vif"
100
101        config_get_bool wds "$vif" wds 0
102        [ "$wds" -gt 0 ] && append hostapd_cfg "wds_sta=1" "$N"
103
104        config_get macaddr "$vif" macaddr
105        config_get_bool hidden "$vif" hidden 0
106        cat >> /var/run/hostapd-$phy.conf <<EOF
107$hostapd_cfg
108wmm_enabled=1
109bssid=$macaddr
110ignore_broadcast_ssid=$hidden
111EOF
112}
113
114mac80211_start_vif() {
115        local vif="$1"
116        local ifname="$2"
117
118        local net_cfg
119        net_cfg="$(find_net_config "$vif")"
120        [ -z "$net_cfg" ] || start_net "$ifname" "$net_cfg"
121
122        set_wifi_up "$vif" "$ifname"
123}
124
125find_mac80211_phy() {
126        local device="$1"
127
128        local macaddr="$(config_get "$device" macaddr | tr 'A-Z' 'a-z')"
129        config_get phy "$device" phy
130        [ -z "$phy" -a -n "$macaddr" ] && {
131                for phy in $(ls /sys/class/ieee80211 2>/dev/null); do
132                        [ "$macaddr" = "$(cat /sys/class/ieee80211/${phy}/macaddress)" ] || continue
133                        config_set "$device" phy "$phy"
134                        break
135                done
136                config_get phy "$device" phy
137        }
138        [ -n "$phy" -a -d "/sys/class/ieee80211/$phy" ] || {
139                echo "PHY for wifi device $1 not found"
140                return 1
141        }
142        [ -z "$macaddr" ] && {
143                config_set "$device" macaddr "$(cat /sys/class/ieee80211/${phy}/macaddress)"
144        }
145        return 0
146}
147
148scan_mac80211() {
149        local device="$1"
150        local adhoc sta ap monitor mesh
151
152        config_get vifs "$device" vifs
153        for vif in $vifs; do
154                config_get mode "$vif" mode
155                case "$mode" in
156                        adhoc|sta|ap|monitor|mesh)
157                                append $mode "$vif"
158                        ;;
159                        *) echo "$device($vif): Invalid mode, ignored."; continue;;
160                esac
161        done
162
163        config_set "$device" vifs "${ap:+$ap }${adhoc:+$adhoc }${sta:+$sta }${monitor:+$monitor }${mesh:+$mesh}"
164}
165
166
167disable_mac80211() (
168        local device="$1"
169
170        find_mac80211_phy "$device" || return 0
171        config_get phy "$device" phy
172
173        set_wifi_down "$device"
174        # kill all running hostapd and wpa_supplicant processes that
175        # are running on atheros/mac80211 vifs
176        for pid in `pidof hostapd`; do
177                grep -E "$phy" /proc/$pid/cmdline >/dev/null && \
178                        kill $pid
179        done
180
181        include /lib/network
182        for wdev in $(ls /sys/class/ieee80211/${phy}/device/net 2>/dev/null); do
183                [ -f "/var/run/$wdev.pid" ] && kill $(cat /var/run/$wdev.pid) >&/dev/null 2>&1
184                for pid in `pidof wpa_supplicant`; do
185                        grep "$wdev" /proc/$pid/cmdline >/dev/null && \
186                                kill $pid
187                done
188                ifconfig "$wdev" down 2>/dev/null
189                unbridge "$dev"
190                iw dev "$wdev" del
191        done
192
193        return 0
194)
195get_freq() {
196        local phy="$1"
197        local chan="$2"
198        iw "$phy" info | grep -E -m1 "(\* ${chan:-....} MHz${chan:+|\\[$chan\\]})" | grep MHz | awk '{print $2}'
199}
200enable_mac80211() {
201        local device="$1"
202        config_get channel "$device" channel
203        config_get vifs "$device" vifs
204        config_get txpower "$device" txpower
205        config_get country "$device" country
206        config_get distance "$device" distance
207        find_mac80211_phy "$device" || return 0
208        config_get phy "$device" phy
209        local i=0
210        local macidx=0
211        local apidx=0
212        fixed=""
213
214        [ -n "$country" ] && iw reg set "$country"
215        [ "$channel" = "auto" -o "$channel" = "0" ] || {
216                fixed=1
217        }
218
219        [ -n "$distance" ] && iw phy "$phy" set distance "$distance"
220
221        export channel fixed
222        # convert channel to frequency
223        local freq="$(get_freq "$phy" "${fixed:+$channel}")"
224
225        wifi_fixup_hwmode "$device" "g"
226        for vif in $vifs; do
227                while [ -d "/sys/class/net/wlan$i" ]; do
228                        i=$(($i + 1))
229                done
230
231                config_get ifname "$vif" ifname
232                [ -n "$ifname" ] || {
233                        ifname="wlan$i"
234                }
235                config_set "$vif" ifname "$ifname"
236
237                config_get mode "$vif" mode
238                config_get ssid "$vif" ssid
239
240                # It is far easier to delete and create the desired interface
241                case "$mode" in
242                        adhoc)
243                                iw phy "$phy" interface add "$ifname" type adhoc
244                        ;;
245                        ap)
246                                # Hostapd will handle recreating the interface and
247                                # it's accompanying monitor
248                                apidx="$(($apidx + 1))"
249                                i=$(($i + 1))
250                                [ "$apidx" -gt 1 ] || iw phy "$phy" interface add "$ifname" type managed
251                        ;;
252                        mesh)
253                                config_get mesh_id "$vif" mesh_id
254                                iw phy "$phy" interface add "$ifname" type mp mesh_id "$mesh_id"
255                        ;;
256                        monitor)
257                                iw phy "$phy" interface add "$ifname" type monitor
258                        ;;
259                        sta)
260                                local wdsflag
261                                config_get_bool wds "$vif" wds 0
262                                [ "$wds" -gt 0 ] && wdsflag="4addr on"
263                                iw phy "$phy" interface add "$ifname" type managed $wdsflag
264                                config_get_bool powersave "$vif" powersave 0
265                                [ "$powersave" -gt 0 ] && powersave="on" || powersave="off"
266                                iwconfig "$ifname" power "$powersave"
267                        ;;
268                esac
269
270                # All interfaces must have unique mac addresses
271                # which can either be explicitly set in the device
272                # section, or automatically generated
273                config_get macaddr "$device" macaddr
274                local mac_1="${macaddr%%:*}"
275                local mac_2="${macaddr#*:}"
276
277                config_get vif_mac "$vif" macaddr
278                [ -n "$vif_mac" ] || {
279                        if [ "$macidx" -gt 0 ]; then
280                                offset="$(( 2 + $macidx * 4 ))"
281                        else
282                                offset="0"
283                        fi
284                        vif_mac="$( printf %02x $((0x$mac_1 + $offset)) ):$mac_2"
285                        macidx="$(($macidx + 1))"
286                }
287                [ "$mode" = "ap" ] || ifconfig "$ifname" hw ether "$vif_mac"
288                config_set "$vif" macaddr "$vif_mac"
289
290                # !! ap !!
291                #
292                # ALL ap functionality will be passed to hostapd
293                #
294                # !! station !!
295                #
296                # ALL station functionality will be passed to wpa_supplicant
297                #
298                if [ ! "$mode" = "ap" ]; then
299                        # We attempt to set the channel for all interfaces, although
300                        # mac80211 may not support it or the driver might not yet
301                        # for ap mode this is handled by hostapd
302                        [ -n "$fixed" -a -n "$channel" ] && iw dev "$ifname" set channel "$channel"
303                fi
304
305                # txpower is not yet implemented in iw
306                config_get vif_txpower "$vif" txpower
307                # use vif_txpower (from wifi-iface) to override txpower (from
308                # wifi-device) if the latter doesn't exist
309                txpower="${txpower:-$vif_txpower}"
310                [ -z "$txpower" ] || iwconfig "$ifname" txpower "${txpower%%.*}"
311
312                config_get frag "$vif" frag
313                if [ -n "$frag" ]; then
314                        iw phy "$phy" set frag "${frag%%.*}"
315                fi
316
317                config_get rts "$vif" rts
318                if [ -n "$rts" ]; then
319                        iw phy "$phy" set rts "${rts%%.*}"
320                fi
321        done
322
323        local start_hostapd=
324        rm -f /var/run/hostapd-$phy.conf
325        for vif in $vifs; do
326                config_get mode "$vif" mode
327                [ "$mode" = "ap" ] || continue
328                mac80211_hostapd_setup_bss "$phy" "$vif"
329                start_hostapd=1
330        done
331
332        [ -n "$start_hostapd" ] && {
333                hostapd -P /var/run/wifi-$phy.pid -B /var/run/hostapd-$phy.conf || {
334                        echo "Failed to start hostapd for $phy"
335                        return
336                }
337                sleep 2
338
339                for vif in $vifs; do
340                        config_get mode "$vif" mode
341                        config_get ifname "$vif" ifname
342                        [ "$mode" = "ap" ] || continue
343                        mac80211_start_vif "$vif" "$ifname"
344                done
345        }
346
347        for vif in $vifs; do
348                config_get mode "$vif" mode
349                config_get ifname "$vif" ifname
350                [ ! "$mode" = "ap" ] || continue
351                ifconfig "$ifname" up
352
353                if [ ! "$mode" = "ap" ]; then
354                        mac80211_start_vif "$vif" "$ifname"
355
356                        case "$mode" in
357                                adhoc)
358                                        config_get bssid "$vif" bssid
359                                        config_get bssid "$vif" ssid
360                                        iw dev "$ifname" ibss join "$ssid" $freq ${fixed:+fixed-freq} $bssid
361                                ;;
362                                sta)
363                                        if eval "type wpa_supplicant_setup_vif" 2>/dev/null >/dev/null; then
364                                                wpa_supplicant_setup_vif "$vif" wext || {
365                                                        echo "enable_mac80211($device): Failed to set up wpa_supplicant for interface $ifname" >&2
366                                                        # make sure this wifi interface won't accidentally stay open without encryption
367                                                        ifconfig "$ifname" down
368                                                        continue
369                                                }
370                                        fi
371                                ;;
372                        esac
373                fi
374        done
375
376}
377
378
379check_device() {
380        config_get phy "$1" phy
381        [ -z "$phy" ] && {
382                find_mac80211_phy "$1" >/dev/null || return 0
383                config_get phy "$1" phy
384        }
385        [ "$phy" = "$dev" ] && found=1
386}
387
388detect_mac80211() {
389        devidx=0
390        config_load wireless
391        while :; do
392                config_get type "radio$devidx" type
393                [ -n "$type" ] || break
394                devidx=$(($devidx + 1))
395        done
396        for dev in $(ls /sys/class/ieee80211); do
397                found=0
398                config_foreach check_device wifi-device
399                [ "$found" -gt 0 ] && continue
400
401                mode_11n=""
402                mode_band="g"
403                channel="5"
404                ht_cap=0
405                for cap in $(iw phy "$dev" info | grep 'Capabilities:' | cut -d: -f2); do
406                        ht_cap="$(($ht_cap | $cap))"
407                done
408                ht_capab="";
409                [ "$ht_cap" -gt 0 ] && {
410                        mode_11n="n"
411                        append ht_capab "       option htmode   HT20" "$N"
412
413                        list="  list ht_capab"
414                        [ "$(($ht_cap & 1))" -eq 1 ] && append ht_capab "$list  LDPC" "$N"
415                        [ "$(($ht_cap & 32))" -eq 32 ] && append ht_capab "$list        SHORT-GI-20" "$N"
416                        [ "$(($ht_cap & 64))" -eq 64 ] && append ht_capab "$list        SHORT-GI-40" "$N"
417                        [ "$(($ht_cap & 4096))" -eq 4096 ] && append ht_capab "$list    DSSS_CCK-40" "$N"
418                }
419                iw phy "$dev" info | grep -q '2412 MHz' || { mode_band="a"; channel="36"; }
420
421                cat <<EOF
422config wifi-device  radio$devidx
423        option type     mac80211
424        option channel  ${channel}
425        option macaddr  $(cat /sys/class/ieee80211/${dev}/macaddress)
426        option hwmode   11${mode_11n}${mode_band}
427$ht_capab
428        # REMOVE THIS LINE TO ENABLE WIFI:
429        option disabled 1
430
431config wifi-iface
432        option device   radio$devidx
433        option network  lan
434        option mode     ap
435        option ssid     OpenWrt
436        option encryption none
437
438EOF
439        devidx=$(($devidx + 1))
440        done
441}
442
Note: See TracBrowser for help on using the repository browser.