diff --git a/in/init=debian=wicd.in b/in/init=debian=wicd.in index 448d019..f08e836 100755 --- a/in/init=debian=wicd.in +++ b/in/init=debian=wicd.in @@ -18,14 +18,18 @@ PATH=/usr/sbin:/usr/bin:/sbin:/bin DESC="Network connection manager" NAME=wicd +RUNDIR=/var/run/$NAME DAEMON=%SBIN%$NAME DAEMON_ARGS="" -PIDFILE=%PIDFILE% +PIDFILE=$RUNDIR/wicd.pid SCRIPTNAME=%INIT%%INITFILENAME% # Exit if the package is not installed [ -x "$DAEMON" ] || exit 0 +# Create RUNDIR if it doesn't exist +[ -d "$RUNDIR" ] || mkdir -p "$RUNDIR" + # Read configuration variable file if it is present [ -r /etc/default/$NAME ] && . /etc/default/$NAME diff --git a/in/init=pld=wicd.in b/in/init=pld=wicd.in index 2d6d6ea..75ce3e2 100755 --- a/in/init=pld=wicd.in +++ b/in/init=pld=wicd.in @@ -8,7 +8,7 @@ # # processname: wicd # config: -# pidfile: /var/run/wicd.pid +# pidfile: %PIDFILE% # # $Id: template.init 9689 2008-03-27 16:15:39Z patrys $ diff --git a/setup.py b/setup.py index 80a1187..4b39c74 100755 --- a/setup.py +++ b/setup.py @@ -441,7 +441,6 @@ try: piddir = os.path.dirname(wpath.pidfile) if not piddir.endswith('/'): piddir += '/' - data.append (( piddir, [] )) if not wpath.no_install_docs: data.append((wpath.docdir, ['INSTALL', 'LICENSE', 'AUTHORS', 'README', 'CHANGES', ])) diff --git a/wicd/backends/be-ioctl.py b/wicd/backends/be-ioctl.py index a397fcf..0b80a2b 100644 --- a/wicd/backends/be-ioctl.py +++ b/wicd/backends/be-ioctl.py @@ -34,7 +34,7 @@ from wicd import misc from wicd import wnettools from wicd import wpath from wicd.wnettools import * -from wicd.wnettools import wep_pattern, signaldbm_pattern +from wicd.wnettools import wep_pattern, signaldbm_pattern, neediface import iwscan import wpactrl @@ -79,13 +79,13 @@ SIOCGIFFLAGS = 0x8913 def get_iw_ioctl_result(iface, call): """ Makes the given ioctl call and returns the results. - + Keyword arguments: call -- The ioctl call to make - + Returns: The results of the ioctl call. - + """ s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) buff = array.array('c', '\0' * 32) @@ -118,12 +118,13 @@ class Interface(wnettools.BaseInterface): wnettools.BaseInterface.__init__(self, iface, verbose) self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) self.Check() - + def CheckWirelessTools(self): """ Check for the existence needed wireless tools """ # We don't need any external apps so just return pass + @neediface("") def GetIP(self, ifconfig=""): """ Get the IP address of the interface. @@ -138,17 +139,17 @@ class Interface(wnettools.BaseInterface): return None except OSError: return None - + return socket.inet_ntoa(raw_ip[20:24]) - + + @neediface(False) def IsUp(self): """ Determines if the interface is up. - + Returns: True if the interface is up, False otherwise. - + """ - if not self.iface: return False data = (self.iface + '\0' * 16)[:18] try: result = fcntl.ioctl(self.sock.fileno(), SIOCGIFFLAGS, data) @@ -156,7 +157,7 @@ class Interface(wnettools.BaseInterface): if self.verbose: print "SIOCGIFFLAGS failed: " + str(e) return False - + flags, = struct.unpack('H', result[16:18]) return bool(flags & 1) @@ -174,18 +175,18 @@ class WiredInterface(Interface, wnettools.BaseWiredInterface): wnettools.BaseWiredInterface.__init__(self, iface, verbose) Interface.__init__(self, iface, verbose) + @neediface(False) def GetPluggedIn(self): """ Get the current physical connection state. - + The method will first attempt to use ethtool do determine physical connection state. Should ethtool fail to run properly, mii-tool will be used instead. - + Returns: True if a link is detected, False otherwise. - + """ - if not self.iface: return False if self.ethtool_cmd and self.link_detect in [misc.ETHTOOL, misc.AUTO]: return self._eth_get_plugged_in() elif self.miitool_cmd and self.link_detect in [misc.MIITOOL, misc.AUTO]: @@ -197,10 +198,10 @@ class WiredInterface(Interface, wnettools.BaseWiredInterface): def _eth_get_plugged_in(self): """ Use ethtool to determine the physical connection state. - + Returns: True if a link is detected, False otherwise. - + """ if not self.IsUp(): self.Up() @@ -216,19 +217,19 @@ class WiredInterface(Interface, wnettools.BaseWiredInterface): print 'SIOCETHTOOL failed: ' + str(e) return False return bool(buff.tolist()[1]) - + def _mii_get_plugged_in(self): """ Use mii-tool to determine the physical connection state. - + Returns: True if a link is detected, False otherwise. - + """ if not self.IsUp(): self.Up() time.sleep(2.5) buff = struct.pack('16shhhh', (self.iface + '\0' * 16)[:16], 0, 1, - 0x0004, 0) + 0x0004, 0) try: result = fcntl.ioctl(self.sock.fileno(), SIOCGMIIPHY, buff) except IOError, e: @@ -253,7 +254,8 @@ class WirelessInterface(Interface, wnettools.BaseWirelessInterface): wpa_driver) Interface.__init__(self, iface, verbose) self.scan_iface = None - + + @neediface([]) def GetNetworks(self): """ Get a list of available wireless networks. @@ -267,14 +269,14 @@ class WirelessInterface(Interface, wnettools.BaseWirelessInterface): except iwscan.error, e: print "GetNetworks caught an exception: %s" % e return [] - + try: results = self.scan_iface.Scan() except iwscan.error, e: print "ERROR: %s" return [] return filter(None, [self._parse_ap(cell) for cell in results]) - + def _parse_ap(self, cell): """ Parse a single cell from the python-iwscan list. """ ap = {} @@ -283,22 +285,22 @@ class WirelessInterface(Interface, wnettools.BaseWirelessInterface): except UnicodeError: print 'Unicode problem with the current network essid, ignoring!!' return None - + if ap['essid'] in [ "", '']: ap['essid'] = '' ap['hidden'] = True else: ap['hidden'] = False - + if cell["channel"]: ap["channel"] = cell["channel"] else: ap["channel"] = self._FreqToChannel(cell["frequency"]) - + ap["bssid"] = cell["bssid"] ap["mode"] = cell["mode"] ap["bitrates"] = cell["bitrate"] - + if cell["enc"]: ap["encryption"] = True if cell["ie"] and cell["ie"].get('type'): @@ -310,7 +312,7 @@ class WirelessInterface(Interface, wnettools.BaseWirelessInterface): ap['encryption_method'] = 'WEP' else: ap["encryption"] = False - + # Link Quality ap['qual_found'] = True ap['quality'] = self._get_link_quality(cell['stats']) @@ -324,9 +326,9 @@ class WirelessInterface(Interface, wnettools.BaseWirelessInterface): ap['strength'] = misc.RunRegex(signaldbm_pattern, cell["stats"]) elif self.wpa_driver != RALINK_DRIVER: # This is already set for ralink ap['strength'] = -1 - + return ap - + def _connect_to_wpa_ctrl_iface(self): """ Connect to the wpa ctrl interface. """ ctrl_iface = '/var/run/wpa_supplicant' @@ -340,7 +342,7 @@ class WirelessInterface(Interface, wnettools.BaseWirelessInterface): else: print "Couldn't find a wpa_supplicant ctrl_interface for iface %s" % self.iface return None - + def ValidateAuthentication(self, auth_time): """ Validate WPA authentication. @@ -350,27 +352,27 @@ class WirelessInterface(Interface, wnettools.BaseWirelessInterface): NOTE: It's possible this could return False, though in reality wpa_supplicant just isn't finished yet. - + Keyword arguments: auth_time -- The time at which authentication began. - + Returns: True if wpa_supplicant authenticated succesfully, False otherwise. """ error= "Unable to find ctrl_interface for wpa_supplicant. " + \ - "Could not validate authentication." - + "Could not validate authentication." + # Right now there's no way to do this for ralink drivers if self.wpa_driver == RALINK_DRIVER: return True - + wpa = self._connect_to_wpa_ctrl_iface() if not wpa: print "Failed to open ctrl interface" return False - + MAX_TIME = 35 MAX_DISCONNECTED_TIME = 3 disconnected_time = 0 @@ -380,15 +382,15 @@ class WirelessInterface(Interface, wnettools.BaseWirelessInterface): except: print "wpa_supplicant status query failed." return False - + if self.verbose: print 'wpa_supplicant ctrl_interface status query is %s' % str(status) - + try: [result] = [l for l in status if l.startswith("wpa_state=")] except ValueError: return False - + result = result if result.endswith("COMPLETED"): return True @@ -404,7 +406,8 @@ class WirelessInterface(Interface, wnettools.BaseWirelessInterface): print 'wpa_supplicant authentication may have failed.' return False - + + @neediface(False) def StopWPA(self): """ Terminates wpa_supplicant using its ctrl interface. """ wpa = self._connect_to_wpa_ctrl_iface() @@ -433,7 +436,7 @@ class WirelessInterface(Interface, wnettools.BaseWirelessInterface): info[4] == 'WEP'): print 'Setting up WEP' cmd = ''.join(['iwconfig ', self.iface, ' key ', - network.get('key')]) + network.get('key')]) if self.verbose: print cmd misc.Run(cmd) else: @@ -451,7 +454,7 @@ class WirelessInterface(Interface, wnettools.BaseWirelessInterface): key_name = 'WPAPSK' else: print 'Unknown AuthMode, can\'t complete ' + \ - 'connection process!' + 'connection process!' return cmd_list = [] @@ -469,9 +472,9 @@ class WirelessInterface(Interface, wnettools.BaseWirelessInterface): if self.verbose: print cmd misc.Run(cmd) + @neediface("") def GetBSSID(self, iwconfig=None): """ Get the MAC address for the interface. """ - if not self.iface: return "" data = (self.iface + '\0' * 32)[:32] try: result = fcntl.ioctl(self.sock.fileno(), SIOCGIWAP, data)[16:] @@ -482,9 +485,9 @@ class WirelessInterface(Interface, wnettools.BaseWirelessInterface): raw_addr = struct.unpack("xxBBBBBB", result[:8]) return "%02X:%02X:%02X:%02X:%02X:%02X" % raw_addr + @neediface("") def GetCurrentBitrate(self, iwconfig=None): """ Get the current bitrate for the interface. """ - if not self.iface: return "" data = (self.iface + '\0' * 32)[:32] fmt = "ihbb" size = struct.calcsize(fmt) @@ -495,7 +498,7 @@ class WirelessInterface(Interface, wnettools.BaseWirelessInterface): print "SIOCGIWRATE failed: " + str(e) return "" f, e, x, x = struct.unpack(fmt, result[:size]) - return "%s %s" % ((f / 1000000), 'Mb/s') + return "%s %s" % ((f / 1000000), 'Mb/s') #def GetOperationalMode(self, iwconfig=None): # """ Get the operational mode for the interface. """ @@ -507,6 +510,7 @@ class WirelessInterface(Interface, wnettools.BaseWirelessInterface): # TODO: Implement me # return '' + @neediface(-1) def GetSignalStrength(self, iwconfig=None): """ Get the signal strength of the current network. @@ -514,7 +518,6 @@ class WirelessInterface(Interface, wnettools.BaseWirelessInterface): The signal strength. """ - if not self.iface: return -1 buff = get_iw_ioctl_result(self.iface, SIOCGIWSTATS) strength = ord(buff[2]) max_strength = self._get_max_strength() @@ -524,7 +527,7 @@ class WirelessInterface(Interface, wnettools.BaseWirelessInterface): return int(strength) else: return None - + def _get_max_strength(self): """ Gets the maximum possible strength from the wireless driver. """ buff = array.array('c', '\0' * 700) @@ -544,7 +547,8 @@ class WirelessInterface(Interface, wnettools.BaseWirelessInterface): data = data[0:size] values = struct.unpack(fmt, data) return values[12] - + + @neediface(-100) def GetDBMStrength(self, iwconfig=None): """ Get the dBm signal strength of the current network. @@ -552,13 +556,13 @@ class WirelessInterface(Interface, wnettools.BaseWirelessInterface): The dBm signal strength. """ - if not self.iface: return -100 buff = get_iw_ioctl_result(self.iface, SIOCGIWSTATS) if not buff: return None return str((ord(buff[3]) - 256)) + @neediface("") def GetCurrentNetwork(self, iwconfig=None): """ Get the essid of the current network. @@ -566,10 +570,8 @@ class WirelessInterface(Interface, wnettools.BaseWirelessInterface): The current network essid. """ - if not self.iface: return "" buff = get_iw_ioctl_result(self.iface, SIOCGIWESSID) if not buff: return None return buff.strip('\x00') - diff --git a/wicd/misc.py b/wicd/misc.py index 3b7eb00..3e6eba3 100644 --- a/wicd/misc.py +++ b/wicd/misc.py @@ -69,7 +69,8 @@ class WicdError(Exception): __LANG = None -def Run(cmd, include_stderr=False, return_pipe=False, return_obj=False): +def Run(cmd, include_stderr=False, return_pipe=False, + return_obj=False, return_retcode=True): """ Run a command. Runs the given command, returning either the output @@ -81,8 +82,10 @@ def Run(cmd, include_stderr=False, return_pipe=False, return_obj=False): be included in the pipe to the cmd. return_pipe - Boolean specifying if a pipe to the command should be returned. If it is - false, all that will be returned is + False, all that will be returned is one output string from the command. + return_obj - If True, Run will return the Popen object + for the command that was run. """ global __LANG @@ -135,9 +138,15 @@ def LaunchAndWait(cmd): """ Launches the given program with the given arguments, then blocks. cmd : A list contained the program name and its arguments. + + returns: The exit code of the process. """ - call(cmd, shell=False) + if not isinstance(cmd, list): + cmd = to_unicode(str(cmd)) + cmd = cmd.split() + p = Popen(cmd, shell=False, stdout=PIPE, stderr=STDOUT, stdin=None) + return p.wait() def IsValidIP(ip): """ Make sure an entered IP is valid. """ diff --git a/wicd/monitor.py b/wicd/monitor.py index c590a10..7333724 100755 --- a/wicd/monitor.py +++ b/wicd/monitor.py @@ -38,7 +38,7 @@ misc.RenameProcess("wicd-monitor") if __name__ == '__main__': wpath.chdir(__file__) - + dbusmanager.connect_to_dbus() dbus_dict = dbusmanager.get_dbus_ifaces() daemon = dbus_dict["daemon"] @@ -61,7 +61,7 @@ def diewithdbus(func): mainloop.quit() self.__lost_dbus_count += 1 return True - + wrapper.__name__ = func.__name__ wrapper.__dict__ = func.__dict__ wrapper.__doc__ = func.__doc__ @@ -86,7 +86,7 @@ class ConnectionStatus(object): self.iwconfig = "" self.trigger_reconnect = False self.__lost_dbus_count = 0 - + bus = dbusmanager.get_bus() bus.add_signal_receiver(self._force_update_connection_status, "UpdateState", "org.wicd.daemon") @@ -99,7 +99,7 @@ class ConnectionStatus(object): in, and the user has chosen to switch to a wired connection whenever its available, even if already connected to a wireless network. - + 2) A wired connection is currently active. """ @@ -107,7 +107,7 @@ class ConnectionStatus(object): if not wired_ip and daemon.GetPreferWiredNetwork(): if not daemon.GetForcedDisconnect() and wired.CheckPluggedIn(): self.trigger_reconnect = True - + elif wired_ip and wired.CheckPluggedIn(): # Only change the interface if it's not already set for wired if not self.still_wired: @@ -128,7 +128,7 @@ class ConnectionStatus(object): Checks for an active wireless connection. Also notes if the signal strength is 0, and if it remains there for too long, triggers a wireless disconnect. - + Returns True if wireless connection is active, and False otherwise. @@ -144,7 +144,7 @@ class ConnectionStatus(object): self.iwconfig = '' # Reset this, just in case. self.tried_reconnect = False - + wifi_signal = self._get_printable_sig_strength() if wifi_signal == 0: # If we have no signal, increment connection loss counter. @@ -165,17 +165,17 @@ class ConnectionStatus(object): self.last_network = self.network self.signal_changed = True daemon.SetCurrentInterface(daemon.GetWirelessInterface()) - + return True @diewithdbus def update_connection_status(self): """ Updates the tray icon and current connection status. - + Determines the current connection state and sends a dbus signal announcing when the status changes. Also starts the automatic reconnection process if necessary. - + """ wired_ip = None wifi_ip = None @@ -183,24 +183,21 @@ class ConnectionStatus(object): if daemon.GetSuspend(): print "Suspended." state = misc.SUSPENDED - self.update_state(state) - return True + return self.update_state(state) # Determine what our current state is. # Are we currently connecting? if daemon.CheckIfConnecting(): state = misc.CONNECTING - self.update_state(state) - return True - + return self.update_state(state) + daemon.SendConnectResultsIfAvail() - + # Check for wired. wired_ip = wired.GetWiredIP("") wired_found = self.check_for_wired_connection(wired_ip) if wired_found: - self.update_state(misc.WIRED, wired_ip=wired_ip) - return True + return self.update_state(misc.WIRED, wired_ip=wired_ip) # Check for wireless wifi_ip = wireless.GetWirelessIP("") @@ -213,35 +210,32 @@ class ConnectionStatus(object): # connection is active. So we kill the wireless connection # so the autoconnect logic will connect to the wired network. self.trigger_reconnect = False - + # Don't trigger it if the gui is open, because autoconnect # is disabled while it's open. if not daemon.GetGUIOpen(): print 'Killing wireless connection to switch to wired...' wireless.DisconnectWireless() - daemon.AutoConnect(False, reply_handler=lambda:None, - error_handler=lambda:None) - self.update_state(misc.NOT_CONNECTED) - return True - self.update_state(misc.WIRELESS, wifi_ip=wifi_ip) - return True - + daemon.AutoConnect(False, reply_handler=lambda *a:None, + error_handler=lambda *a:None) + return self.update_state(misc.NOT_CONNECTED) + return self.update_state(misc.WIRELESS, wifi_ip=wifi_ip) + state = misc.NOT_CONNECTED if self.last_state == misc.WIRELESS: from_wireless = True else: from_wireless = False self.auto_reconnect(from_wireless) - self.update_state(state) - return True - + return self.update_state(state) + def _force_update_connection_status(self): """ Run a connection status update on demand. - + Removes the scheduled update_connection_status() call, explicitly calls the function, and reschedules it. - + """ global update_callback gobject.source_remove(update_callback) @@ -272,6 +266,7 @@ class ConnectionStatus(object): else: print 'ERROR: Invalid state!' return True + daemon.SetConnectionStatus(state, info) # Send a D-Bus signal announcing status has changed if necessary. @@ -280,7 +275,7 @@ class ConnectionStatus(object): daemon.EmitStatusChanged(state, info) self.last_state = state return True - + def _get_printable_sig_strength(self): """ Get the correct signal strength format. """ try: @@ -290,7 +285,7 @@ class ConnectionStatus(object): wifi_signal = int(wireless.GetCurrentDBMStrength(self.iwconfig)) except TypeError: wifi_signal = 0 - + return wifi_signal def auto_reconnect(self, from_wireless=None): @@ -303,37 +298,37 @@ class ConnectionStatus(object): """ if self.reconnecting: return - + # Some checks to keep reconnect retries from going crazy. if (self.reconnect_tries > 3 and - (time.time() - self.last_reconnect_time) < 200): + (time.time() - self.last_reconnect_time) < 200): print "Throttling autoreconnect" return self.reconnecting = True daemon.SetCurrentInterface('') - + if daemon.ShouldAutoReconnect(): print 'Starting automatic reconnect process' self.last_reconnect_time = time.time() self.reconnect_tries += 1 - + # If we just lost a wireless connection, try to connect to that # network again. Otherwise just call Autoconnect. cur_net_id = wireless.GetCurrentNetworkID(self.iwconfig) if from_wireless and cur_net_id > -1: print 'Trying to reconnect to last used wireless ' + \ - 'network' + 'network' wireless.ConnectWireless(cur_net_id) else: daemon.AutoConnect(True, reply_handler=reply_handle, error_handler=err_handle) self.reconnecting = False - + def reply_handle(): """ Just a dummy function needed for asynchronous dbus calls. """ pass - + def err_handle(error): """ Just a dummy function needed for asynchronous dbus calls. """ pass @@ -343,16 +338,16 @@ def add_poll_callback(): update_callback = misc.timeout_add(to_time, monitor.update_connection_status) - + def main(): """ Starts the connection monitor. - + Starts a ConnectionStatus instance, sets the status to update an amount of time determined by the active backend. - + """ global monitor, to_time, mainloop - + monitor = ConnectionStatus() to_time = daemon.GetBackendUpdateInterval() add_poll_callback() diff --git a/wicd/networking.py b/wicd/networking.py index b984eb0..6f8e42e 100644 --- a/wicd/networking.py +++ b/wicd/networking.py @@ -425,7 +425,30 @@ class ConnectThread(threading.Thread): if self.connect_result != "aborted": self.abort_connection(dhcp_status) return + + @abortable + def verify_association(self, iface): + """ Verify that our association the AP is valid. + Try to ping the gateway we have set to see if we're + really associated with it. This is only done if + we're using a static IP. + + """ + if self.network.get('gateway'): + self.SetStatus('verifying_association') + print "Verifying AP association" + retcode = self.iface.VerifyAPAssociation(self.network['gateway']) + #TODO this should be in wnettools.py + if retcode: + print "Connection Failed: Failed to ping the access point!" + # Clean up before aborting. + iface.SetAddress('0.0.0.0') + iface.FlushRoutes() + if hasattr(iface, "StopWPA"): + iface.StopWPA() + self.abort_connection("association_failed") + @abortable def set_dns_addresses(self, iface): """ Set the DNS address(es). @@ -838,6 +861,7 @@ class WirelessConnectThread(ConnectThread): self.set_broadcast_address(wiface) self.set_ip_address(wiface) self.set_dns_addresses(wiface) + self.verify_association(wiface) # Run post-connection script. self.run_global_scripts_if_needed(wpath.postconnectscripts) diff --git a/wicd/translations.py b/wicd/translations.py index 98c3ac7..308d620 100644 --- a/wicd/translations.py +++ b/wicd/translations.py @@ -153,6 +153,8 @@ language['dhcp_failed'] = _('Connection Failed: Unable to Get IP Address') language['no_dhcp_offers'] = _('Connection Failed: No DHCP offers received.') language['aborted'] = _('Connection Cancelled') language['bad_pass'] = _('Connection Failed: Could not authenticate (bad password?)') +language['verifying_association'] = _("Verifying access point association...") +language['association_failed'] = _("Connection Failed: Could not contact the wireless access point.") language['done'] = _('Done connecting...') language['scanning'] = _('Scanning') language['scanning_stand_by'] = _('Scanning networks... stand by...') diff --git a/wicd/wnettools.py b/wicd/wnettools.py index 88a236b..5300b21 100644 --- a/wicd/wnettools.py +++ b/wicd/wnettools.py @@ -143,6 +143,25 @@ def IsValidWpaSuppDriver(driver): return False else: return True + +def neediface(default_response): + """ A decorator for only running a method if self.iface is defined. + + This decorator is wrapped around Interface methods, and will + return a provided default_response value if self.iface is not + defined. + + """ + def wrapper(func): + def newfunc(self, *args, **kwargs): + if not self.iface: + return default_response + return func(self, *args, **kwargs) + newfunc.__dict__ = func.__dict__ + newfunc.__doc__ = func.__doc__ + newfunc.__module__ = func.__module__ + return newfunc + return wrapper class BaseInterface(object): @@ -304,6 +323,7 @@ class BaseInterface(object): self.kdesu_cmd = self._find_program_path("kdesu") self.ktsuss_cmd = self._find_program_path("ktsuss") + @neediface(False) def Up(self): """ Bring the network interface up. @@ -311,12 +331,12 @@ class BaseInterface(object): True """ - if not self.iface: return False cmd = 'ifconfig ' + self.iface + ' up' if self.verbose: print cmd misc.Run(cmd) return True + @neediface(False) def Down(self): """ Take down the network interface. @@ -324,12 +344,12 @@ class BaseInterface(object): True """ - if not self.iface: return False cmd = 'ifconfig ' + self.iface + ' down' if self.verbose: print cmd misc.Run(cmd) return True + @neediface("") def SetAddress(self, ip=None, netmask=None, broadcast=None): """ Set the IP addresses of an interface. @@ -339,9 +359,6 @@ class BaseInterface(object): broadcast -- broadcast address in dotted quad form """ - if not self.iface: - return - for val in [ip, netmask, broadcast]: if not val: continue @@ -452,6 +469,7 @@ class BaseInterface(object): print 'DHCP connection failed' return 'dhcp_failed' + @neediface def StartDHCP(self): """ Start the DHCP client to obtain an IP address. @@ -460,8 +478,6 @@ class BaseInterface(object): _check_dhcp_result for the possible values. """ - if not self.iface: return False - cmd = self._get_dhcp_command('connect') if self.verbose: print cmd self.dhcp_object = misc.Run(cmd, include_stderr=True, return_obj=True) @@ -477,16 +493,16 @@ class BaseInterface(object): else: print 'ERROR no dhclient found!' + @neediface def ReleaseDHCP(self): """ Release the DHCP lease for this interface. """ - if not self.iface: return False cmd = self._get_dhcp_command("release") if self.verbose: print cmd misc.Run(cmd) + @neediface def DelDefaultRoute(self): """ Delete only the default route for a device. """ - if not self.iface: return False if self.ip_cmd and self.flush_tool in [misc.AUTO, misc.IP]: cmd = '%s route del default dev %s' % (self.ip_cmd, self.iface) elif self.route_cmd and self.flush_tool in [misc.AUTO, misc.ROUTE]: @@ -497,6 +513,7 @@ class BaseInterface(object): if self.verbose: print cmd misc.Run(cmd) + @neediface def SetDNS(self, dns1=None, dns2=None, dns3=None, dns_dom=None, search_dom=None): """ Set the DNS of the system to the specified DNS servers. @@ -511,7 +528,6 @@ class BaseInterface(object): search_dom -- DNS search domain """ - if not self.iface: return False resolv_params = "" if dns_dom: resolv_params += 'domain %s\n' % dns_dom @@ -541,9 +557,9 @@ class BaseInterface(object): resolv.write(resolv_params + "\n") resolv.close() + @neediface def FlushRoutes(self): """ Flush network routes for this device. """ - if not self.iface: return False if self.ip_cmd and self.flush_tool in [misc.AUTO, misc.IP]: cmds = ['%s route flush dev %s' % (self.ip_cmd, self.iface)] elif self.route_cmd and self.flush_tool in [misc.AUTO, misc.ROUTE]: @@ -555,6 +571,7 @@ class BaseInterface(object): if self.verbose: print cmd misc.Run(cmd) + @neediface def SetDefaultRoute(self, gw): """ Add a default route with the specified gateway. @@ -562,7 +579,6 @@ class BaseInterface(object): gw -- gateway of the default route in dotted quad form """ - if not self.iface: return if not misc.IsValidIP(gw): print 'WARNING: Invalid gateway found. Aborting!' return False @@ -570,6 +586,7 @@ class BaseInterface(object): if self.verbose: print cmd misc.Run(cmd) + @neediface("") def GetIP(self, ifconfig=""): """ Get the IP address of the interface. @@ -585,6 +602,19 @@ class BaseInterface(object): output = ifconfig return misc.RunRegex(ip_pattern, output) + @neediface(False) + def VerifyAPAssociation(self, gateway): + """ Verify assocation with an access point. + + Verifies that an access point can be contacted by + trying to ping it. + + """ + cmd = "ping -q -w 3 -c 1 %s" % gateway + if self.verbose: print cmd + return misc.LaunchAndWait(cmd) + + @neediface(False) def IsUp(self, ifconfig=None): """ Determines if the interface is up. @@ -592,7 +622,6 @@ class BaseInterface(object): True if the interface is up, False otherwise. """ - if not self.iface: return False flags_file = '/sys/class/net/%s/flags' % self.iface try: flags = open(flags_file, "r").read().strip() @@ -631,6 +660,7 @@ class BaseWiredInterface(BaseInterface): """ BaseInterface.__init__(self, iface, verbose) + @neediface(False) def GetPluggedIn(self): """ Get the current physical connection state. @@ -642,8 +672,6 @@ class BaseWiredInterface(BaseInterface): True if a link is detected, False otherwise. """ - if not self.iface: - return False # check for link using /sys/class/net/iface/carrier # is usually more accurate sys_device = '/sys/class/net/%s/' % self.iface @@ -741,6 +769,7 @@ class BaseWirelessInterface(BaseInterface): """ Sets the wpa_driver. """ self.wpa_driver = _sanitize_string(driver) + @neediface(False) def SetEssid(self, essid): """ Set the essid of the wireless interface. @@ -752,6 +781,7 @@ class BaseWirelessInterface(BaseInterface): if self.verbose: print str(cmd) misc.Run(cmd) + @neediface(False) def GetKillSwitchStatus(self): """ Determines if the wireless killswitch is enabled. @@ -759,7 +789,6 @@ class BaseWirelessInterface(BaseInterface): True if the killswitch is enabled, False otherwise. """ - if not self.iface: return False output = self.GetIwconfig() killswitch_pattern = re.compile('.*radio off', re.I | re.M | re.S) @@ -770,9 +799,9 @@ class BaseWirelessInterface(BaseInterface): return radiostatus + @neediface(False) def GetIwconfig(self): """ Returns the output of iwconfig for this interface. """ - if not self.iface: return "" cmd = "iwconfig " + self.iface if self.verbose: print cmd return misc.Run(cmd) @@ -881,6 +910,7 @@ class BaseWirelessInterface(BaseInterface): ap['encryption'] = False return ap + @neediface(False) def SetMode(self, mode): """ Set the mode of the wireless interface. @@ -888,7 +918,6 @@ class BaseWirelessInterface(BaseInterface): mode -- mode to set the interface to """ - if not self.iface: return False mode = _sanitize_string_strict(mode) if mode.lower() == 'master': mode = 'managed' @@ -896,6 +925,7 @@ class BaseWirelessInterface(BaseInterface): if self.verbose: print cmd misc.Run(cmd) + @neediface(False) def SetChannel(self, channel): """ Set the channel of the wireless interface. @@ -903,7 +933,6 @@ class BaseWirelessInterface(BaseInterface): channel -- channel to set the interface to """ - if not self.iface: return False if not channel.isdigit(): print 'WARNING: Invalid channel found. Aborting!' return False @@ -912,6 +941,7 @@ class BaseWirelessInterface(BaseInterface): if self.verbose: print cmd misc.Run(cmd) + @neediface(False) def SetKey(self, key): """ Set the encryption key of the wireless interface. @@ -919,11 +949,11 @@ class BaseWirelessInterface(BaseInterface): key -- encryption key to set """ - if not self.iface: return False cmd = 'iwconfig %s key %s' % (self.iface, key) if self.verbose: print cmd misc.Run(cmd) + @neediface(False) def Associate(self, essid, channel=None, bssid=None): """ Associate with the specified wireless network. @@ -933,7 +963,6 @@ class BaseWirelessInterface(BaseInterface): bssid -- bssid of the network """ - if not self.iface: return False cmd = ['iwconfig', self.iface, 'essid', essid] if channel and str(channel).isdigit(): cmd.extend(['channel', str(channel)]) @@ -957,6 +986,7 @@ class BaseWirelessInterface(BaseInterface): if self.verbose: print cmd return misc.RunRegex(key_pattern, misc.Run(cmd)) + @neediface(False) def Authenticate(self, network): """ Authenticate with the specified wireless network. @@ -1014,6 +1044,7 @@ class BaseWirelessInterface(BaseInterface): if self.verbose: print ' '.join(cmd) misc.Run(cmd) + @neediface([]) def GetNetworks(self): """ Get a list of available wireless networks. @@ -1191,12 +1222,14 @@ class BaseWirelessInterface(BaseInterface): cmd = 'wpa_cli -i' + self.iface + ' scan' misc.Run(cmd) + @neediface(False) def StopWPA(self): """ Terminates wpa using wpa_cli""" cmd = 'wpa_cli -i %s terminate' % self.iface if self.verbose: print cmd misc.Run(cmd) + @neediface("") def GetBSSID(self, iwconfig=None): """ Get the MAC address for the interface. """ if not iwconfig: @@ -1209,6 +1242,7 @@ class BaseWirelessInterface(BaseInterface): bssid = misc.RunRegex(bssid_pattern, output) return bssid + @neediface("") def GetCurrentBitrate(self, iwconfig=None): """ Get the current bitrate for the interface. """ if not iwconfig: @@ -1221,6 +1255,7 @@ class BaseWirelessInterface(BaseInterface): bitrate = misc.RunRegex(bitrate_pattern, output) return bitrate + @neediface("") def GetOperationalMode(self, iwconfig=None): """ Get the operational mode for the interface. """ if not iwconfig: @@ -1235,6 +1270,7 @@ class BaseWirelessInterface(BaseInterface): opmode = opmode.strip() return opmode + @neediface("") def GetAvailableAuthMethods(self, iwlistauth=None): """ Get the available authentication methods for the interface. """ if not iwlistauth: @@ -1264,6 +1300,7 @@ class BaseWirelessInterface(BaseInterface): else: return None + @neediface(-1) def GetSignalStrength(self, iwconfig=None): """ Get the signal strength of the current network. @@ -1279,6 +1316,7 @@ class BaseWirelessInterface(BaseInterface): output = iwconfig return self._get_link_quality(output) + @neediface(-100) def GetDBMStrength(self, iwconfig=None): """ Get the dBm signal strength of the current network. @@ -1297,6 +1335,7 @@ class BaseWirelessInterface(BaseInterface): dbm_strength = misc.RunRegex(signaldbm_pattern, output) return dbm_strength + @neediface("") def GetCurrentNetwork(self, iwconfig=None): """ Get the essid of the current network. @@ -1315,4 +1354,3 @@ class BaseWirelessInterface(BaseInterface): if network: network = misc.to_unicode(network) return network -