1#!/usr/bin/python
2
3# Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
4# Use of this source code is governed by a BSD-style license that can be
5# found in the LICENSE file.
6
7import sys
8
9import common
10from autotest_lib.client.cros.networking import wifi_proxy
11
12SERVICE_PROP_PARSERS = {
13    'EAP.AnonymousIdentity': unicode,
14    'EAP.CACertID': unicode,
15    'EAP.CACertNSS': unicode,
16    'EAP.CACertPEM': unicode,
17    'EAP.CertID': unicode,
18    'EAP.ClientCert': unicode,
19    'EAP.EAP': unicode,
20    'EAP.Identity': unicode,
21    'EAP.InnerEAP': unicode,
22    'EAP.KeyID': unicode,
23    'EAP.KeyMgmt': unicode,
24    'EAP.Password': unicode,
25    'EAP.PIN': unicode,
26    'EAP.SubjectMatch': unicode,
27    'EAP.UseSystemCAs': bool,
28    wifi_proxy.WifiProxy.SERVICE_PROPERTY_SECURITY_CLASS: unicode,
29    }
30
31
32def usage():
33    """ Prints a usage message and returns False. """
34    cmd = sys.argv[0]
35    print 'Usage:'
36    print cmd, 'connect <ssid> [passphrase] [security]'
37    print '    |security| defaults to "psk" when |passphrase|',
38    print 'is given without |security|'
39    print
40    print cmd, 'disconnect <ssid> [timeout seconds]'
41    print
42    print cmd, 'connect_with_props <ssid> <timeout seconds>'
43    print '    <Security=[none|psk|802_1x]> [Property=Value ...]'
44    print '    for Property in:'
45    print '\n'.join(['\t\t' + x for x in sorted(SERVICE_PROP_PARSERS.keys())])
46    print
47    print cmd, 'configure <ssid> [passphrase] [security]'
48    print '    |security| defaults to "psk" when |passphrase|',
49    print 'is given without |security|'
50    return False
51
52
53def configure(ssid, security, passphrase):
54    wifi = wifi_proxy.WifiProxy()
55    security_parameters = {}
56    if passphrase is not None:
57        security_parameters[wifi.SERVICE_PROPERTY_PASSPHRASE] = passphrase
58    successful = wifi.configure_wifi_service(ssid, security,
59                                             security_parameters)
60    if successful:
61        print 'Operation succeeded.'
62    else:
63        print 'Operation failed.'
64    return successful
65
66
67def connect(ssid, security, credentials, save_credentials, timeout=15):
68    """Attempt to connect to a WiFi network.
69
70    Blocks until we connect successfully to a WiFi network described
71    by the given parameters or time out while attempting to do so.
72
73    @param ssid string Name of the network to connect to.
74    @param security string security type of the network to connect to.
75    @param credentials dict of service properties that includes credentials
76            like the passphrase for psk security.
77    @param save_credentials bool True if credentials should be saved.
78    @return True upon success, False otherwise.
79
80    """
81    wifi = wifi_proxy.WifiProxy()
82    result = wifi.connect_to_wifi_network(ssid,
83            security,
84            credentials,
85            save_credentials,
86            discovery_timeout_seconds=timeout,
87            association_timeout_seconds=timeout,
88            configuration_timeout_seconds=timeout)
89    (successful, discovery, association, configuration, reason) = result
90    if successful:
91        print 'Operation succeeded.'
92    else:
93        print 'Operation failed. (%s)' % reason
94    print 'Discovery time: %f.' % discovery
95    print 'Association time: %f.' % association
96    print 'Configuration time: %f.' % configuration
97    return successful
98
99
100def disconnect(ssid, timeout=None):
101    """Disconnect from the specified network.
102
103    Disconnect from a network with name |ssid|.  Note that this
104    method will not fail if we're already disconnected.
105
106    @param ssid string Name of the network to disconnect from.
107    @param timeout float number of seconds to wait for transition
108            to idle state.
109    @return True upon seeing network is in idle state.
110
111    """
112    wifi = wifi_proxy.WifiProxy()
113    result = wifi.disconnect_from_wifi_network(ssid, timeout)
114    (successful, duration, reason) = result
115    if successful:
116        print 'Operation succeeded.'
117    else:
118        print 'Operation failed: %s.' % reason
119    print 'Disconnect time: %f.' % duration
120    return successful
121
122
123def parse_security_from_credentials(credentials):
124    """Parses SERVICE_PROPERTY_SECURITY from credentials.
125
126    @param credentials dict of service properties that includes credentials
127            like the passphrase for psk security.
128    @return SERVICE_PROPERTY_SECURITY value from credentials,
129            or exit if no such key/value in credentials.
130
131    """
132    security = credentials.pop(
133            wifi_proxy.WifiProxy.SERVICE_PROPERTY_SECURITY, None)
134    if security is None:
135        print "Error: security type not provided"
136        usage()
137        sys.exit(1)
138
139    if security not in ['none', 'wep', 'psk', '802_1x']:
140        print "Error: invalid security type %s" % security
141        usage()
142        sys.exit(1)
143
144    return security
145
146
147def parse_service_property(property_string):
148    """Parses one commandline key=value string into a tuple.
149
150    @param property_string string to be parsed into (key,value).
151    @return parsed tuple of (key,value) or exit on parsing error.
152
153    """
154    property_name, raw_value = property_string.split('=', 1)
155
156    if not property_name in SERVICE_PROP_PARSERS:
157        print '%s is not a recognized service property' % property_name
158        usage()
159        sys.exit(1)
160
161    try:
162        return property_name, SERVICE_PROP_PARSERS[property_name](raw_value)
163    except:
164        print 'Failed parsing value from %s' % property_string
165        usage()
166        sys.exit(1)
167
168
169def main(args):
170    """Main method for this script.
171
172    @param args list of arguments to the script, not including script name.
173    @return True on success, False otherwise.
174
175    """
176    if len(args) < 2:
177        return usage()
178    command = args[0]
179    ssid = args[1]
180    save_credentials = True
181
182    if command == 'configure':
183        security = 'none'
184        passphrase = None
185        if len(args) > 2:
186            security = 'psk'
187            passphrase = args[2]
188        if len(args) > 3:
189            security = args[3]
190        return configure(ssid, security, passphrase)
191
192    if command == 'connect':
193        security = 'none'
194        credentials = {}
195        save_credentials = True
196        if len(args) > 2:
197            credentials[wifi_proxy.WifiProxy.SERVICE_PROPERTY_PASSPHRASE] = \
198                    args[2]
199            security = 'psk'
200        if len(args) > 3:
201            security = args[3]
202        return connect(ssid, security, credentials, save_credentials)
203
204    if command == 'connect_with_props':
205        timeout = float(args[2])
206        credentials = {}
207        if len(args) > 3:
208            for i in xrange(3, len(args)):
209                credentials.update((parse_service_property(args[i]),))
210        security = parse_security_from_credentials(credentials)
211        return connect(ssid, security, credentials, save_credentials, timeout)
212
213    if command == 'disconnect':
214        timeout=None
215        if len(args) > 2:
216            timeout = float(args[2])
217        return disconnect(ssid, timeout)
218
219    return usage()
220
221
222if __name__ == '__main__':
223    if not main(sys.argv[1:]):
224      sys.exit(1)
225