summaryrefslogtreecommitdiffstats
path: root/src/wireless.subr
blob: d188d19aac33d2e8ba3e7e70ac2308d8c8c7fa75 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
#! /bin/bash

# Uses wpa_supplicant to check for association to a network
# wpa_check interface [timeout]
wpa_check()
{
    INTERFACE=$1; TIMEOUT=$2
    
    [[ -z "$TIMEOUT" ]] && TIMEOUT=15
    let timeout=0
    while [[ $timeout -ne $TIMEOUT ]]; do
        eval `wpa_cli status|grep wpa_state` 
        [[ "$wpa_state" = "COMPLETED" ]] && return 0
        sleep 1
        let timeout++
    done

    wpa_cli terminate >/dev/null 2>&1
    err_append "Wireless association failed."
    return 1 
}

# Uses wireless_tools, to check for association to a network.
# wep_check interface [timeout]
wep_check()
{
    INTERFACE=$1; TIMEOUT=$2
 
    [[ -z "$TIMEOUT" ]] && TIMEOUT=15
    let timeout=0
    while [[ $timeout -ne $TIMEOUT ]]; do
        bssid=`iwgetid $INTERFACE -ra`
        [[ ! "$bssid" = "00:00:00:00:00:00" ]] && return 0
        sleep 1
        let timeout++
    done
    
    err_append "Wireless association failed."
    return 1
}

# Check if a particular network is within range
# find_essid interface essid
find_essid()
{
    INTERFACE=$1; ESSID=$2; RETRIES=5
    try=0;
    while [[ $try -ne $RETRIES ]]; do
        if iwlist $INTERFACE scan|sed "s/ESSID://g"|grep -q "\"$ESSID\""; then
            return 0 # network found
        fi
        sleep 1
        let try++
    done
    return 1
}

# Return a filename containing a list of network ESSID's found.
# list_networks interface
list_networks()
{
    # temp file used, as keeping ESSID's with spaces in their name in arrays 
    # is hard, obscure and kinda nasty. This is simpler and clearer.
 
    [[ -z "$1" ]] && return 1
    essids=$(mktemp /tmp/essid.XXXXX)

    let try=0;
    RETRIES=6;
    while [[ $try -ne $RETRIES ]]; do        
        iwlist $1 scan 2> /dev/null|grep ESSID|sed 's/.*ESSID:"\([^"]\+\)".*/\1/' > $essids
        sleep 0.5; let try++
    done
    sort -u $essids -o $essids
  
    # File of 0 length, ie. no ssid's.
    if [[ ! -s $essids ]]; then
        return 1
    fi

    echo $essids
    return 0
}

start_wpa() 
{
    INTERFACE=$1; WPA_CONF=$2; WPA_OPTS=$3
     
    [[ "$WPA_OPTS" == "" ]] && WPA_OPTS="-Dwext"

    wpa_supplicant -wB -P/var/run/wpa_supplicant_${INTERFACE}.pid -i${INTERFACE} -c $WPA_CONF $WPA_OPTS    
    sleep 1
    
    if [[ ! -f /var/run/wpa_supplicant_${INTERFACE}.pid ]]; then
        err_append "wpa_supplicant did not start, possible configuration error"
        return 1
    fi
}

wireless_up() {

    load_profile $1
    
    if [[ ! -d /sys/class/net/$INTERFACE/wireless ]]; then 
        err_append "Interface $INTERFACE is not a wireless interface"
        return 1
    fi
 
    # Required by atheros and others (mac80211?) to enable device
    ifconfig $INTERFACE up 

    # Hack that has been required by some broadcom
    quirk "prescan" && iwlist $INTERFACE scan &> /dev/null
    quirk "test" && echo "TESTWORKS!" 
    # Required by ipw3945 to properly re-associate
    quirk "preessid" && eval "iwconfig $INTERFACE mode managed essid \"$ESSID\""

    # Kill any lingering wpa_supplicants.
    if [[ -f /var/run/wpa_supplicant_$INTERFACE.pid ]]; then
        kill $(cat /var/run/wpa_supplicant_$INTERFACE.pid)
    fi

    # Default scan off as it won't see hidden networks and some hardware's scanning is dodgy
    [[ ! "$SCAN" ]] && SCAN="no" 
    if checkyesno $SCAN; then
        if ! find_essid $INTERFACE "$ESSID"; then
            err_append "Network unavailable"
            return 1
        fi 
    fi
  
    # Manually set iwconfig options
    if [[ "$IWCONFIG" ]]; then
        iwconfig $INTERFACE $IWCONFIG
    fi

    case $SECURITY in
    wep|none)
        # 'none' security uses iwconfig, like wep, so use same code, minus keysetting.
        # Use sane default if no alternative is specified
        if [[ "$SECURITY" = "wep" && "$WEP_OPTS" = "" ]]; then 
            WEP_OPTS="mode managed essid \"$ESSID\" key open $KEY"
        elif [[ "$SECURITY" = "none" && "$WEP_OPTS" = "" ]]; then
            WEP_OPTS="mode managed essid \"$ESSID\""
        fi 
        
        # Add wierd quirk for some Atheros in response to FS#10585
        quirk "predown" && ifconfig $INTERFACE down

        if ! eval iwconfig $INTERFACE $WEP_OPTS; then
            err_append "Could not set wireless configuration"
            return 1
        fi

        quirk "postsleep" && sleep 1
        quirk "postscan" && sleep 1 && iwlist $INTERFACE scan &>/dev/null
        quirk "predown" && ifconfig $INTERFACE up

        wep_check $INTERFACE $TIMEOUT|| return 1
        ;;    
    wpa)
        local WPA_CONF=`mktemp /tmp/wpa.XXXXXXXX`
        
        # Quirk for broken drivers... http://bbs.archlinux.org/viewtopic.php?id=36384
        quirk "wpaessid" && eval iwconfig $INTERFACE mode managed essid "\"$ESSID\""
        
        # Create a random file to store configuration, make it root only. 
        chmod 600 $WPA_CONF
        echo "ctrl_interface=/var/run/wpa_supplicant" >> $WPA_CONF
        echo "ctrl_interface_group=0" >> $WPA_CONF        
        
        # Generate configuration
        if ! wpa_passphrase "$ESSID" "$KEY" >> $WPA_CONF; then
            err_append "Configuration generation failed: `cat $WPA_CONF`"
            return 1
        fi

        # Connect!
        start_wpa $INTERFACE $WPA_CONF $WPA_OPTS || return 1
        wpa_check $INTERFACE $TIMEOUT || return 1
        ;;
    wpa-config)
        # If user hasnt defined one, use stock config.
        [[ -z "$WPA_CONF" ]] && WPA_CONF="/etc/wpa_supplicant.conf"
        start_wpa $INTERFACE $WPA_CONF $WPA_OPTS || return 1
        wpa_check $INTERFACE $TIMEOUT || return 1
        ;;        
    esac
    
    . $SUBR_DIR/ethernet.subr
    if ! ethernet_up $1; then
        wireless_down $1 YES
        return 1
    fi
}
 
wireless_down() {
    PROFILE=$1 NOETHERNETDOWN=$2
    if ! checkyesno $2; then
        . $SUBR_DIR/ethernet.subr
        ethernet_down $1
       fi
    wpa_cli terminate &> /dev/null 
    iwconfig $INTERFACE essid off key off &> /dev/null 
    #ifconfig $INTERFACE down
}

wireless_clean_scope() {
    unset INTERFACE CONNECTION
    unset TIMEOUT WPA_CONF WPA_OPTS KEY ESSID SECURITY WEP_OPTS
    . $SUBR_DIR/ethernet.subr
    ethernet_clean_scope
}


# vim: set ts=4 et sw=4: