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