#! /usr/bin/env python import sys import dbus import shlex import subprocess from signal import SIGTERM import os from time import sleep # dbus constants. WPAS_DBUS_SERVICE = "fi.epitest.hostap.WPASupplicant" WPAS_DBUS_INTERFACE = "fi.epitest.hostap.WPASupplicant" WPAS_DBUS_OPATH = "/fi/epitest/hostap/WPASupplicant" WPAS_DBUS_INTERFACES_INTERFACE = "fi.epitest.hostap.WPASupplicant.Interface" WPAS_DBUS_INTERFACES_OPATH = "/fi/epitest/hostap/WPASupplicant/Interfaces" WPAS_DBUS_BSSID_INTERFACE = "fi.epitest.hostap.WPASupplicant.BSSID" WPAS_DBUS_NETWORKS_INTERFACE = "fi.epitest.hostap.WPASupplicant.Network" def read_config(config): cfg = shlex.split(open(config, "r").read()) options = {} for line in cfg: (var, delim, value) = line.partition('=') if delim: var = var.lstrip() # JP: allow assignments to be indented, as they can be when sourced if var[0] != '#': value = value.partition("#")[0].rstrip() # JP: strip off comments and trailing whitespace if value[0] == value[-1] and value[0] in ('"',"'"): # JP: strip any surrounding quotes value=value[1:-1] options[var] = value return options def wep_hex2dec(key): if len(key) not in [10, 26]: fail("Bad key", report_type="err") x=0 new_key=[] while x>sys.stderr, output # JP: print to stderr fail("Could not start wpa_supplicant") # Connect to wpa_supplicant report('debug', 'wireless_dbus', 'connecting to wpa_supplicant') bus = dbus.SystemBus() wpas_obj = bus.get_object(WPAS_DBUS_SERVICE, WPAS_DBUS_OPATH) wpas = dbus.Interface(wpas_obj, WPAS_DBUS_INTERFACE) # Add/Get interface path try: driver=profile["WPA_DRIVER"] except KeyError: driver="wext" try: path = wpas.getInterface(profile["INTERFACE"]) except dbus.exceptions.DBusException: path = wpas.addInterface(profile["INTERFACE"], {"driver":dbus.String(driver,variant_level=1)}) # Get interface object if_obj = bus.get_object(WPAS_DBUS_SERVICE, path) iface = dbus.Interface(if_obj, WPAS_DBUS_INTERFACES_INTERFACE); # Add and select the network. Networks already specified for wpa-config if profile['SECURITY'] in ['wpa','wep','none']: report('debug', 'wireless_dbus', 'add and select network') path = iface.addNetwork() net_obj = bus.get_object(WPAS_DBUS_SERVICE, path) rnet = dbus.Interface(net_obj, WPAS_DBUS_NETWORKS_INTERFACE) iface.selectNetwork(rnet) if not essid: essid = profile["ESSID"] if profile['SECURITY'] == "wpa": opts = dbus.Dictionary({"ssid": dbus.ByteArray(essid), "psk": dbus.String(profile['KEY'])}, signature="sv") report('debug', 'wireless_dbus', 'connect to network with security=wpa') rnet.set(opts) elif profile['SECURITY'] == "wep": key=profile['KEY'] if key[:2] == "s:": # String key prefixed by "s:" keydbus=key[2:] else: # Hex key key=wep_hex2dec(key) keydbus = dbus.ByteArray() for l in key: keydbus+=chr(l) opts = dbus.Dictionary({"ssid": dbus.ByteArray(essid), "key_mgmt": dbus.String("NONE"), "wep_tx_keyidx": dbus.Int32(1), "wep_key0": dbus.ByteArray(keydbus)}, signature="sv") report('debug', 'wireless_dbus', 'connect to network with security=wep') rnet.set(opts) elif profile['SECURITY'] == "none": opts = dbus.Dictionary({"ssid": dbus.ByteArray(essid)}, signature="sv") report('debug', 'wireless_dbus', 'connect to network with security=none') rnet.set(opts) # Determine timeout try: timeout = int(profile["TIMEOUT"]) except KeyError: timeout = 15 # Check for association n=0 while n <= timeout: n+=1 sleep(1) state = iface.state() if state == "COMPLETED": break if n == timeout: fail("Association/Authentication failed:" + state) # Run ethernet and get an ip. try: subprocess.check_call([ETHERNET_IPROUTE, "up", sys.argv[2]]) except subprocess.CalledProcessError: fail() sys.exit(0) def stop(profile): ret = subprocess.call([ETHERNET_IPROUTE, "down", sys.argv[2]]) os.kill(int(open("/var/run/wpa_supplicant.pid").read()),SIGTERM) sys.exit(ret) if __name__ == "__main__": CONN_DIR = os.path.abspath(os.path.dirname(sys.argv[0])) ETHERNET_IPROUTE = os.path.join(CONN_DIR,"ethernet-iproute") WIRELESS = os.path.join(CONN_DIR,"wireless") # setup bash report_* handler report_handler_script = 'source %s/../globals; while read cmd args; do eval $cmd "$args"; done' % (CONN_DIR,) report_handler = subprocess.Popen(report_handler_script, executable='/bin/bash', stdin=subprocess.PIPE, shell=True) try: profile_name = sys.argv[2] profile = read_config("/etc/network.d/"+profile_name) essid = sys.argv[3] if len(sys.argv)>3 else "" # JP: pass literal ESSID as an argument, so that we can have entry in profile be a regexp if sys.argv[1] == "up": start(profile, essid) elif sys.argv[1] == "down": stop(profile) finally: report_handler.stdin.close() report_handler.wait() # vim: et ts=4