11f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley#!/usr/bin/python
21f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley
31f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley# Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
41f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley# Use of this source code is governed by a BSD-style license that can be
51f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley# found in the LICENSE file.
61f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley
71f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wileyimport sys
81f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley
911deef18d2b8f0babb8361be8be1844534aff6cfChristopher Wileyimport common
101f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wileyfrom autotest_lib.client.cros.networking import wifi_proxy
111f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley
121f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher WileySERVICE_PROP_PARSERS = {
131f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley    'EAP.AnonymousIdentity': unicode,
141f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley    'EAP.CACertID': unicode,
151f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley    'EAP.CACertNSS': unicode,
161f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley    'EAP.CACertPEM': unicode,
171f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley    'EAP.CACert': unicode,
181f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley    'EAP.CertID': unicode,
191f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley    'EAP.ClientCert': unicode,
201f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley    'EAP.EAP': unicode,
211f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley    'EAP.Identity': unicode,
221f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley    'EAP.InnerEAP': unicode,
231f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley    'EAP.KeyID': unicode,
241f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley    'EAP.KeyMgmt': unicode,
251f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley    'EAP.Password': unicode,
261f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley    'EAP.PIN': unicode,
271f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley    'EAP.PrivateKey': unicode,
281f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley    'EAP.SubjectMatch': unicode,
291f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley    'EAP.UseSystemCAs': bool,
301f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley    wifi_proxy.WifiProxy.SERVICE_PROPERTY_SECURITY: unicode,
311f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley    }
321f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley
331f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley
341f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wileydef usage():
351f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley    """ Prints a usage message and returns False. """
361f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley    cmd = sys.argv[0]
371f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley    print 'Usage:'
381f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley    print cmd, 'connect <ssid> [passphrase] [security]'
391f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley    print '    |security| defaults to "psk" when |passphrase|',
401f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley    print 'is given without |security|'
411f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley    print
421f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley    print cmd, 'disconnect <ssid> [timeout seconds]'
431f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley    print
441f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley    print cmd, 'connect_with_props <ssid> <timeout seconds>'
451f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley    print '    <Security=[none|psk|802_1x]> [Property=Value ...]'
461f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley    print '    for Property in:'
471f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley    print '\n'.join(['\t\t' + x for x in sorted(SERVICE_PROP_PARSERS.keys())])
481f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley    print
491f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley    print cmd, 'configure <ssid> [passphrase] [security]'
501f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley    print '    |security| defaults to "psk" when |passphrase|',
511f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley    print 'is given without |security|'
521f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley    return False
531f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley
541f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley
551f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wileydef configure(ssid, security, passphrase):
561f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley    wifi = wifi_proxy.WifiProxy()
571f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley    security_parameters = {}
581f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley    if passphrase is not None:
591f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley        security_parameters[wifi.SERVICE_PROPERTY_PASSPHRASE] = passphrase
601f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley    successful = wifi.configure_wifi_service(ssid, security,
611f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley                                             security_parameters)
621f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley    if successful:
631f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley        print 'Operation succeeded.'
641f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley    else:
651f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley        print 'Operation failed.'
661f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley    return successful
671f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley
681f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley
691f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wileydef connect(ssid, security, credentials, save_credentials, timeout=15):
701f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley    """Attempt to connect to a WiFi network.
711f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley
721f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley    Blocks until we connect successfully to a WiFi network described
731f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley    by the given parameters or time out while attempting to do so.
741f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley
751f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley    @param ssid string Name of the network to connect to.
761f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley    @param security string security type of the network to connect to.
771f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley    @param credentials dict of service properties that includes credentials
781f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley            like the passphrase for psk security.
791f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley    @param save_credentials bool True if credentials should be saved.
801f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley    @return True upon success, False otherwise.
811f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley
821f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley    """
831f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley    wifi = wifi_proxy.WifiProxy()
841f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley    result = wifi.connect_to_wifi_network(ssid,
851f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley            security,
861f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley            credentials,
871f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley            save_credentials,
881f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley            discovery_timeout_seconds=timeout,
891f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley            association_timeout_seconds=timeout,
901f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley            configuration_timeout_seconds=timeout)
911f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley    (successful, discovery, association, configuration, reason) = result
921f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley    if successful:
931f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley        print 'Operation succeeded.'
941f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley    else:
951f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley        print 'Operation failed. (%s)' % reason
961f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley    print 'Discovery time: %f.' % discovery
971f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley    print 'Association time: %f.' % association
981f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley    print 'Configuration time: %f.' % configuration
991f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley    return successful
1001f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley
1011f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley
1021f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wileydef disconnect(ssid, timeout=None):
1031f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley    """Disconnect from the specified network.
1041f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley
1051f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley    Disconnect from a network with name |ssid|.  Note that this
1061f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley    method will not fail if we're already disconnected.
1071f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley
1081f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley    @param ssid string Name of the network to disconnect from.
1091f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley    @param timeout float number of seconds to wait for transition
1101f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley            to idle state.
1111f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley    @return True upon seeing network is in idle state.
1121f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley
1131f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley    """
1141f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley    wifi = wifi_proxy.WifiProxy()
1151f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley    result = wifi.disconnect_from_wifi_network(ssid, timeout)
1161f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley    (successful, duration, reason) = result
1171f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley    if successful:
1181f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley        print 'Operation succeeded.'
1191f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley    else:
1201f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley        print 'Operation failed: %s.' % reason
1211f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley    print 'Disconnect time: %f.' % duration
1221f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley    return successful
1231f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley
1241f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley
1251f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wileydef parse_security_from_credentials(credentials):
1261f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley    """Parses SERVICE_PROPERTY_SECURITY from credentials.
1271f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley
1281f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley    @param credentials dict of service properties that includes credentials
1291f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley            like the passphrase for psk security.
1301f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley    @return SERVICE_PROPERTY_SECURITY value from credentials,
1311f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley            or exit if no such key/value in credentials.
1321f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley
1331f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley    """
1341f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley    security = credentials.pop(
1351f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley            wifi_proxy.WifiProxy.SERVICE_PROPERTY_SECURITY, None)
1361f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley    if security is None:
1371f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley        print "Error: security type not provided"
1381f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley        usage()
1391f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley        sys.exit(1)
1401f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley
1411f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley    if security not in ['none', 'wep', 'psk', '802_1x']:
1421f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley        print "Error: invalid security type %s" % security
1431f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley        usage()
1441f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley        sys.exit(1)
1451f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley
1461f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley    return security
1471f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley
1481f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley
1491f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wileydef parse_service_property(property_string):
1501f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley    """Parses one commandline key=value string into a tuple.
1511f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley
1521f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley    @param property_string string to be parsed into (key,value).
1531f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley    @return parsed tuple of (key,value) or exit on parsing error.
1541f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley
1551f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley    """
1561f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley    property_name, raw_value = property_string.split('=', 1)
1571f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley
1581f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley    if not property_name in SERVICE_PROP_PARSERS:
1591f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley        print '%s is not a recognized service property' % property_name
1601f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley        usage()
1611f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley        sys.exit(1)
1621f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley
1631f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley    try:
1641f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley        return property_name, SERVICE_PROP_PARSERS[property_name](raw_value)
1651f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley    except:
1661f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley        print 'Failed parsing value from %s' % property_string
1671f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley        usage()
1681f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley        sys.exit(1)
1691f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley
1701f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley
1711f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wileydef main(args):
1721f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley    """Main method for this script.
1731f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley
1741f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley    @param args list of arguments to the script, not including script name.
1751f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley    @return True on success, False otherwise.
1761f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley
1771f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley    """
1781f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley    if len(args) < 2:
1791f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley        return usage()
1801f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley    command = args[0]
1811f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley    ssid = args[1]
1821f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley    save_credentials = True
1831f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley
1841f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley    if command == 'configure':
1851f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley        security = 'none'
1861f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley        passphrase = None
1871f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley        if len(args) > 2:
1881f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley            security = 'psk'
1891f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley            passphrase = args[2]
1901f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley        if len(args) > 3:
1911f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley            security = args[3]
1921f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley        return configure(ssid, security, passphrase)
1931f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley
1941f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley    if command == 'connect':
1951f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley        security = 'none'
1961f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley        credentials = {}
1971f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley        save_credentials = True
1981f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley        if len(args) > 2:
1991f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley            credentials[wifi_proxy.WifiProxy.SERVICE_PROPERTY_PASSPHRASE] = \
2001f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley                    args[2]
2011f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley            security = 'psk'
2021f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley        if len(args) > 3:
2031f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley            security = args[3]
2041f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley        return connect(ssid, security, credentials, save_credentials)
2051f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley
2061f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley    if command == 'connect_with_props':
2071f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley        timeout = float(args[2])
2081f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley        credentials = {}
2091f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley        if len(args) > 3:
2101f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley            for i in xrange(3, len(args)):
2111f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley                credentials.update((parse_service_property(args[i]),))
2121f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley        security = parse_security_from_credentials(credentials)
2131f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley        return connect(ssid, security, credentials, save_credentials, timeout)
2141f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley
2151f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley    if command == 'disconnect':
2161f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley        timeout=None
2171f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley        if len(args) > 2:
2181f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley            timeout = float(args[2])
2191f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley        return disconnect(ssid, timeout)
2201f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley
2211f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley    return usage()
2221f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley
2231f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley
2241f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wileyif __name__ == '__main__':
2251f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley    if not main(sys.argv[1:]):
2261f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley      sys.exit(1)
227