1
0
mirror of https://github.com/gryf/wicd.git synced 2025-12-22 05:48:03 +01:00

experimental:

- Merge in changes from pluggablebackends.
This commit is contained in:
imdano
2008-09-06 16:54:53 +00:00
parent 9639cc8a14
commit 59d282ee6e
17 changed files with 2217 additions and 1329 deletions

0
wicd/__init__.py Normal file
View File

97
wicd/backend.py Normal file
View File

@@ -0,0 +1,97 @@
#!/usr/bin/env python
""" Backend manager for wicd.
Manages and loads the pluggable backends for wicd.
"""
#
# Copyright (C) 2007 Adam Blackburn
# Copyright (C) 2007 Dan O'Reilly
# Copyright (C) 2007 Byron Hillis
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License Version 2 as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
import sys
import os
import wicd.wpath as wpath
class BackendManager(object):
def __init__(self):
""" Initialize the backend manager. """
self.backend_dir = wpath.backends
self.__loaded_backend = None
def _valid_backend_file(self, be_file):
""" Make sure the backend file is valid. """
return (os.access(be_file, os.F_OK) and
os.path.basename(be_file).startswith("be-") and
be_file.endswith(".py"))
def get_current_backend(self):
if self.__loaded_backend and not self.__loaded_backend is None:
return self.__loaded_backend.NAME
else:
return None
def get_available_backends(self):
""" Returns a list of all valid backends in the backend directory. """
be_list = [""]
for f in os.listdir(self.backend_dir):
if self._valid_backend_file(os.path.join(self.backend_dir, f)):
be_list.append(f[3:-3])
return be_list
def load_backend(self, backend_name):
""" Load and return a backend module.
Given a backend name be-foo, attempt to load a python module
in the backends directory called be-foo.py. The module must
include a certain set of classes and variables to be considered
valid.
"""
def fail(backend_name, reason):
print "Failed to load backend %s: %s" % (backend_name, reason)
print 'trying to load backend %s' % backend_name
backend_path = os.path.join(self.backend_dir,
'be-' + backend_name + '.py')
if self._valid_backend_file(backend_path):
sys.path.insert(0, self.backend_dir)
backend = __import__('be-' + backend_name)
else:
fail(backend_name, 'Invalid backend file.')
return None
if not backend.NAME:
fail(backend_name, 'Missing NAME declaration.')
return None
if not backend.WiredInterface:
fail(backend_name, "Missing WiredInterface class")
return None
if not backend.WirelessInterface:
fail(backend_name, "Missing WirelessInterface class")
return None
self.__loaded_backend = backend
print 'successfully loaded backend %s' % backend_name
return backend

View File

@@ -0,0 +1,491 @@
#!/usr/bin/env python
""" Network interface control tools for wicd.
This module implements functions to control and obtain information from
network interfaces.
def SetDNS() -- Set the DNS servers of the system.
def GetWirelessInterfaces() -- Get the wireless interfaces available.
class Interface() -- Control a network interface.
class WiredInterface() -- Control a wired network interface.
class WirelessInterface() -- Control a wireless network interface.
"""
#
# Copyright (C) 2007 Adam Blackburn
# Copyright (C) 2007 Dan O'Reilly
# Copyright (C) 2007 Byron Hillis
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License Version 2 as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
import wicd.misc as misc
import wicd.wnettools as wnettools
import re
import os
import wicd.wpath as wpath
import time
NAME = "external"
DESCRIPTION = """External app (slow) backend
This backend uses external program calls like ifconfig and
iwconfig to query network information. This makes it a bit
slower and more CPU intensive than the ioctl backend, but
it doesn't require any thirdy party libraries and may be
more stable for some set ups.
"""
# Compile the regex patterns that will be used to search the output of iwlist
# scan for info these are well tested, should work on most cards
essid_pattern = re.compile('.*ESSID:"(.*?)"\n', re.I | re.M | re.S)
ap_mac_pattern = re.compile('.*Address: (.*?)\n', re.I | re.M | re.S)
channel_pattern = re.compile('.*Channel:? ?(\d\d?)', re.I | re.M | re.S)
strength_pattern = re.compile('.*Quality:?=? ?(\d+)\s*/?\s*(\d*)', re.I | re.M | re.S)
# These next two look a lot a like, altstrength is for Signal level = xx/100,
# which is just an alternate way of displaying link quality, signaldbm is
# for displaying actual signal strength (-xx dBm).
altstrength_pattern = re.compile('.*Signal level:?=? ?(\d\d*)', re.I | re.M | re.S)
signaldbm_pattern = re.compile('.*Signal level:?=? ?(-\d\d*)', re.I | re.M | re.S)
mode_pattern = re.compile('.*Mode:(.*?)\n', re.I | re.M | re.S)
freq_pattern = re.compile('.*Frequency:(.*?)\n', re.I | re.M | re.S)
ip_pattern = re.compile(r'inet [Aa]d?dr[^.]*:([^.]*\.[^.]*\.[^.]*\.[0-9]*)', re.S)
bssid_pattern = re.compile('.*Access Point: (([0-9A-Z]{2}:){5}[0-9A-Z]{2})', re.I | re.M | re.S)
wep_pattern = re.compile('.*Encryption key:(.*?)\n', re.I | re.M | re.S)
altwpa_pattern = re.compile('(wpa_ie)', re.I | re.M | re.S)
wpa1_pattern = re.compile('(WPA Version 1)', re.I | re.M | re.S)
wpa2_pattern = re.compile('(WPA2)', re.I | re.M | re.S)
# Patterns for wpa_cli output
auth_pattern = re.compile('.*wpa_state=(.*?)\n', re.I | re.M | re.S)
RALINK_DRIVER = 'ralink legacy'
def SetDNS(dns1=None, dns2=None, dns3=None):
return wnettools.SetDNS(dns1, dns2, dns3)
def GetDefaultGateway():
return wnettools.GetDefaultGateway()
def StopDHCP():
return wnettools.StopDHCP()
def GetWirelessInterfaces():
return wnettools.GetWirelessInterfaces()
def GetWiredInterfaces():
return wnettools.GetWiredInterfaces()
def NeedsExternalCalls():
return True
class Interface(wnettools.BaseInterface):
""" Control a network interface. """
def __init__(self, iface, verbose=False):
""" Initialise the object.
Keyword arguments:
iface -- the name of the interface
verbose -- whether to print every command run
"""
wnettools.BaseInterface.__init__(self, iface, verbose)
self.Check()
def GetIP(self, ifconfig=""):
""" Get the IP address of the interface.
Returns:
The IP address of the interface in dotted quad form.
"""
if not ifconfig:
cmd = 'ifconfig ' + self.iface
if self.verbose: print cmd
output = misc.Run(cmd)
else:
output = ifconfig
return misc.RunRegex(ip_pattern, output)
def IsUp(self, ifconfig=None):
""" Determines if the interface is up.
Returns:
True if the interface is up, False otherwise.
"""
if not ifconfig:
cmd = "ifconfig " + self.iface
if self.verbose: print cmd
output = misc.Run(cmd)
else:
output = ifconfig
lines = output.split('\n')
if len(lines) < 5:
return False
for line in lines[1:4]:
if line.strip().startswith('UP'):
return True
return False
class WiredInterface(Interface, wnettools.BaseWiredInterface):
""" Control a wired network interface. """
def __init__(self, iface, verbose=False):
""" Initialise the wired network interface class.
Keyword arguments:
iface -- name of the interface
verbose -- print all commands
"""
wnettools.BaseWiredInterface.__init__(self, iface, verbose)
Interface.__init__(self, iface, verbose)
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_FOUND and self.link_detect != misc.MIITOOL:
return self._eth_get_plugged_in()
elif self.MIITOOL_FOUND:
return self._mii_get_plugged_in()
else:
print 'Error: No way of checking for a wired connection. Make \
sure that either mii-tool or ethtool is installed.'
return False
def _eth_get_plugged_in(self):
""" Use ethtool to determine the physical connection state.
Returns:
True if a link is detected, False otherwise.
"""
link_tool = 'ethtool'
if not self.IsUp():
print 'Wired Interface is down, putting it up'
self.Up()
time.sleep(6)
tool_data = misc.Run(link_tool + ' ' + self.iface, True)
if misc.RunRegex(re.compile('(Link detected: yes)', re.I | re.M |
re.S), tool_data) is not None:
return True
else:
return False
def _mii_get_plugged_in(self):
""" Use mii-tool to determine the physical connection state.
Returns:
True if a link is detected, False otherwise.
"""
link_tool = 'mii-tool'
tool_data = misc.Run(link_tool + ' ' + self.iface, True)
if misc.RunRegex(re.compile('(Invalid argument)', re.I | re.M | re.S),
tool_data) is not None:
print 'Wired Interface is down, putting it up'
self.Up()
time.sleep(4)
tool_data = misc.Run(link_tool + ' ' + self.iface, True)
if misc.RunRegex(re.compile('(link ok)', re.I | re.M | re.S),
tool_data) is not None:
return True
else:
return False
class WirelessInterface(Interface, wnettools.BaseWirelessInterface):
""" Control a wireless network interface. """
def __init__(self, iface, verbose=False, wpa_driver='wext'):
""" Initialise the wireless network interface class.
Keyword arguments:
iface -- name of the interface
verbose -- print all commands
"""
wnettools.BaseWirelessInterface.__init__(self, iface, verbose,
wpa_driver)
Interface.__init__(self, iface, verbose)
def GetNetworks(self):
""" Get a list of available wireless networks.
Returns:
A list containing available wireless networks.
"""
cmd = 'iwlist ' + self.iface + ' scan'
if self.verbose: print cmd
results = misc.Run(cmd)
# Split the networks apart, using Cell as our split point
# this way we can look at only one network at a time.
# The spaces around ' Cell ' are to minimize the chance that someone
# has an essid named Cell...
networks = results.split( ' Cell ' )
# Get available network info from iwpriv get_site_survey
# if we're using a ralink card (needed to get encryption info)
if self.wpa_driver == RALINK_DRIVER:
ralink_info = self._GetRalinkInfo()
else:
ralink_info = None
# An array for the access points
access_points = []
for cell in networks:
# Only use sections where there is an ESSID.
if 'ESSID:' in cell:
# Add this network to the list of networks
entry = self._ParseAccessPoint(cell, ralink_info)
if entry is not None:
access_points.append(entry)
return access_points
def _ParseAccessPoint(self, cell, ralink_info):
""" Parse a single cell from the output of iwlist.
Keyword arguments:
cell -- string containing the cell information
ralink_info -- string contating network information needed
for ralink cards.
Returns:
A dictionary containing the cell networks properties.
"""
ap = {}
# ESSID - Switch '<hidden>' to 'Hidden' to remove
# brackets that can mix up formatting.
ap['essid'] = misc.RunRegex(essid_pattern, cell)
try:
ap['essid'] = misc.to_unicode(ap['essid'])
except (UnicodeDecodeError, UnicodeEncodeError):
print 'Unicode problem with current network essid, ignoring!!'
return None
if ap['essid'] in ['<hidden>', ""]:
ap['essid'] = 'Hidden'
ap['hidden'] = True
else:
ap['hidden'] = False
# Channel - For cards that don't have a channel number,
# convert the frequency.
ap['channel'] = misc.RunRegex(channel_pattern, cell)
if ap['channel'] == None:
freq = misc.RunRegex(freq_pattern, cell)
ap['channel'] = self._FreqToChannel(freq)
# BSSID
ap['bssid'] = misc.RunRegex(ap_mac_pattern, cell)
# Mode
ap['mode'] = misc.RunRegex(mode_pattern, cell)
# Break off here if we're using a ralink card
if self.wpa_driver == RALINK_DRIVER:
ap = self._ParseRalinkAccessPoint(ap, ralink_info, cell)
elif misc.RunRegex(wep_pattern, cell) == 'on':
# Encryption - Default to WEP
ap['encryption'] = True
ap['encryption_method'] = 'WEP'
if misc.RunRegex(wpa1_pattern, cell) == 'WPA Version 1':
ap['encryption_method'] = 'WPA'
if misc.RunRegex(altwpa_pattern, cell) == 'wpa_ie':
ap['encryption_method'] = 'WPA'
if misc.RunRegex(wpa2_pattern, cell) == 'WPA2':
ap['encryption_method'] = 'WPA2'
else:
ap['encryption'] = False
# Link Quality
# Set strength to -1 if the quality is not found
# more of the patch from
# https://bugs.launchpad.net/wicd/+bug/175104
if (strength_pattern.match(cell)):
[(strength, max_strength)] = strength_pattern.findall(cell)
if max_strength:
ap["quality"] = 100 * int(strength) // int(max_strength)
else:
ap["quality"] = int(strength)
elif misc.RunRegex(altstrength_pattern,cell):
ap['quality'] = misc.RunRegex(altstrength_pattern, cell)
else:
ap['quality'] = -1
# Signal Strength (only used if user doesn't want link
# quality displayed or it isn't found)
if misc.RunRegex(signaldbm_pattern, cell):
ap['strength'] = misc.RunRegex(signaldbm_pattern, cell)
elif self.wpa_driver != RALINK_DRIVER: # This is already set for ralink
ap['strength'] = -1
return ap
def ValidateAuthentication(self, auth_time):
""" Validate WPA authentication.
Validate that the wpa_supplicant authentication
process was successful.
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.
"""
# Right now there's no way to do this for these drivers
if self.wpa_driver == RALINK_DRIVER or not self.WPA_CLI_FOUND:
return True
MAX_TIME = 15
MAX_DISCONNECTED_TIME = 3
while (time.time() - auth_time) < MAX_TIME:
cmd = 'wpa_cli -i ' + self.iface + ' status'
output = misc.Run(cmd)
result = misc.RunRegex(auth_pattern, output)
if self.verbose:
print 'WPA_CLI RESULT IS', result
if not result:
return False
if result == "COMPLETED":
return True
elif result == "DISCONNECTED" and \
(time.time() - auth_time) > MAX_DISCONNECTED_TIME:
# Force a rescan to get wpa_supplicant moving again.
self._ForceSupplicantScan()
MAX_TIME += 5
time.sleep(1)
print 'wpa_supplicant authentication may have failed.'
return False
def _ForceSupplicantScan(self):
""" Force wpa_supplicant to rescan available networks.
This function forces wpa_supplicant to rescan.
This works around authentication validation sometimes failing for
wpa_supplicant because it remains in a DISCONNECTED state for
quite a while, after which a rescan is required, and then
attempting to authenticate. This whole process takes a long
time, so we manually speed it up if we see it happening.
"""
print 'wpa_supplicant rescan forced...'
cmd = 'wpa_cli -i' + self.iface + ' scan'
misc.Run(cmd)
def GetBSSID(self, iwconfig=None):
""" Get the MAC address for the interface. """
if not iwconfig:
cmd = 'iwconfig ' + self.iface
if self.verbose: print cmd
output = misc.Run(cmd)
else:
output = iwconfig
bssid = misc.RunRegex(bssid_pattern, output)
return bssid
def GetSignalStrength(self, iwconfig=None):
""" Get the signal strength of the current network.
Returns:
The signal strength.
"""
if not iwconfig:
cmd = 'iwconfig ' + self.iface
if self.verbose: print cmd
output = misc.Run(cmd)
else:
output = iwconfig
[(strength, max_strength)] = strength_pattern.findall(output)
if max_strength and strength:
return 100 * int(strength) // int(max_strength)
if strength is None:
strength = misc.RunRegex(altstrength_pattern, output)
return strength
def GetDBMStrength(self, iwconfig=None):
""" Get the dBm signal strength of the current network.
Returns:
The dBm signal strength.
"""
if not iwconfig:
cmd = 'iwconfig ' + self.iface
if self.verbose: print cmd
output = misc.Run(cmd)
else:
output = iwconfig
dbm_strength = misc.RunRegex(signaldbm_pattern, output)
return dbm_strength
def GetCurrentNetwork(self, iwconfig=None):
""" Get the essid of the current network.
Returns:
The current network essid.
"""
if not iwconfig:
cmd = 'iwconfig ' + self.iface
if self.verbose: print cmd
output = misc.Run(cmd)
else:
output = iwconfig
network = misc.RunRegex(re.compile('.*ESSID:"(.*?)"',
re.I | re.M | re.S), output)
if network:
network = misc.to_unicode(network)
return network

538
wicd/backends/be-ioctl.py Normal file
View File

@@ -0,0 +1,538 @@
#!/usr/bin/env python
""" ioctl Network interface control tools for wicd.
This module implements functions to control and obtain information from
network interfaces. It utilizes ioctl calls and python modules to
obtain this information whenever possible.
def SetDNS() -- Set the DNS servers of the system.
def GetWirelessInterfaces() -- Get the wireless interfaces available.
class Interface() -- Control a network interface.
class WiredInterface() -- Control a wired network interface.
class WirelessInterface() -- Control a wireless network interface.
"""
#
# Copyright (C) 2007 Adam Blackburn
# Copyright (C) 2007 Dan O'Reilly
# Copyright (C) 2007 Byron Hillis
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License Version 2 as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
import wicd.misc as misc
import wicd.wnettools as wnettools
import wicd.wpath as wpath
import iwscan
import wpactrl
import re
import os
import time
import socket
import fcntl
import struct
import array
NAME = "ioctl"
DESCRIPTION = """IOCTL (fast) backend
This backend uses IOCTL calls and python libraries to query
network information whenever possible. This makes it fast,
but it may not work properly on all systems.
Dependencies:
python-wpactrl (http://projects.otaku42.de/wiki/PythonWpaCtrl)
python-iwscan (http://projects.otaku42.de/browser/python-iwscan/)"""
strength_pattern = re.compile('.*Quality:?=? ?(\d+)\s*/?\s*(\d*)',
re.I | re.M | re.S)
altstrength_pattern = re.compile('.*Signal level:?=? ?(\d\d*)',
re.I | re.M | re.S)
signaldbm_pattern = re.compile('.*Signal level:?=? ?(-\d\d*)',
re.I | re.M | re.S)
wep_pattern = re.compile('.*Encryption key:(.*?)\n', re.I | re.M | re.S)
RALINK_DRIVER = 'ralink legacy'
# Got these from /usr/include/linux/wireless.h
SIOCGIWESSID = 0x8B1B
SIOCGIWRANGE = 0x8B0B
SIOCGIWAP = 0x8B15
SIOCGIWSTATS = 0x8B0F
# Got these from /usr/include/sockios.h
SIOCGIFADDR = 0x8915
SIOCGIFHWADDR = 0x8927
SIOCGMIIPHY = 0x8947
SIOCETHTOOL = 0x8946
SIOCGIFFLAGS = 0x8913
def SetDNS(dns1=None, dns2=None, dns3=None):
return wnettools.SetDNS(dns1, dns2, dns3)
def GetDefaultGateway():
return wnettools.GetDefaultGateway()
def StopDHCP():
return wnettools.StopDHCP()
def GetWirelessInterfaces():
return wnettools.GetWirelessInterfaces()
def GetWiredInterfaces():
return wnettools.GetWiredInterfaces()
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)
addr, length = buff.buffer_info()
arg = struct.pack('Pi', addr, length)
data = (iface + '\0' * 16)[:16] + arg
try:
result = fcntl.ioctl(s.fileno(), call, data)
except IOError:
return None
except OSError:
return None
return buff.tostring()
def NeedsExternalCalls():
return False
class Interface(wnettools.BaseInterface):
""" Control a network interface. """
def __init__(self, iface, verbose=False):
""" Initialise the object.
Keyword arguments:
iface -- the name of the interface
verbose -- whether to print every command run
"""
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
def GetIP(self, ifconfig=""):
""" Get the IP address of the interface.
Returns:
The IP address of the interface in dotted quad form.
"""
ifstruct = struct.pack('256s', self.iface)
try:
raw_ip = fcntl.ioctl(self.sock.fileno(), SIOCGIFADDR, ifstruct)
except IOError:
return None
except OSError:
return None
return socket.inet_ntoa(raw_ip[20:24])
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)
except IOError, e:
if self.verbose:
print "SIOCGIFFLAGS failed: " + str(e)
return False
flags, = struct.unpack('H', result[16:18])
return bool(flags & 1)
class WiredInterface(Interface, wnettools.BaseWiredInterface):
""" Control a wired network interface. """
def __init__(self, iface, verbose=False):
""" Initialise the wired network interface class.
Keyword arguments:
iface -- name of the interface
verbose -- print all commands
"""
wnettools.BaseWiredInterface.__init__(self, iface, verbose)
Interface.__init__(self, iface, verbose)
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_FOUND and self.link_detect != misc.MIITOOL:
return self._eth_get_plugged_in()
elif self.MIITOOL_FOUND:
return self._mii_get_plugged_in()
else:
print 'Error: No way of checking for a wired connection. Make \
sure that either mii-tool or ethtool is installed.'
return False
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()
time.sleep(5)
buff = array.array('i', [0x0000000a, 0x00000000])
addr, length = buff.buffer_info()
arg = struct.pack('Pi', addr, length)
data = (self.iface + '\0' * 16)[:16] + arg
try:
fcntl.ioctl(self.sock.fileno(), SIOCETHTOOL, data)
except IOError, e:
if self.verbose:
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)
try:
result = fcntl.ioctl(self.sock.fileno(), SIOCGMIIPHY, buff)
except IOError, e:
if self.verbose:
print 'SIOCGMIIPHY failed: ' + str(e)
return False
reg = struct.unpack('16shhhh', result)[-1]
return bool(reg & 0x0004)
class WirelessInterface(Interface, wnettools.BaseWirelessInterface):
""" Control a wireless network interface. """
def __init__(self, iface, verbose=False, wpa_driver='wext'):
""" Initialise the wireless network interface class.
Keyword arguments:
iface -- name of the interface
verbose -- print all commands
"""
wnettools.BaseWirelessInterface.__init__(self, iface, verbose,
wpa_driver)
Interface.__init__(self, iface, verbose)
self.scan_iface = None
def GetNetworks(self):
""" Get a list of available wireless networks.
Returns:
A list containing available wireless networks.
"""
if not self.scan_iface:
self.scan_iface = iwscan.WirelessInterface(self.iface)
results = self.scan_iface.Scan()
return [self._parse_ap(cell) for cell in results]
def _parse_ap(self, cell):
""" Parse a single cell from the python-iwscan list. """
ap = {}
try:
ap['essid'] = misc.to_unicode(cell['essid'])
except UnicodeError:
print 'Unicode problem with the current network essid, ignoring!!'
return None
if ap['essid'] in [ "", '<hidden>']:
ap['essid'] = 'Hidden'
ap['hidden'] = True
else:
ap['hidden'] = False
ap["channel"] = True and cell["channel"] or \
self._FreqToChannel(cell["frequency"])
ap["bssid"] = cell["bssid"]
ap["mode"] = cell["mode"]
if cell["enc"]:
ap["encryption"] = True
if cell["ie"]:
if "WPA2" in cell['ie']['type'].upper():
ap['encryption_method'] = 'WPA2'
elif "WPA" in cell['ie']['type'].upper():
ap['encryption_method'] = 'WPA'
else:
ap['encryption_method'] = 'WEP'
else:
ap["encryption"] = False
# Link Quality
ap['qual_found'] = True
try:
[(strength, max_strength)] = strength_pattern.findall(cell["stats"])
if max_strength:
ap["quality"] = 100 * int(strength) // int(max_strength)
else:
ap["quality"] = int(strength)
except ValueError:
ap['quality'] = misc.RunRegex(altstrength_pattern,cell["stats"])
if not ap['quality']:
ap['qual_found'] = False
ap['quality'] = -1
# Signal Strength (only used if user doesn't want link
# quality displayed or it isn't found)
if misc.RunRegex(signaldbm_pattern, cell["stats"]):
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 ValidateAuthentication(self, auth_time):
""" Validate WPA authentication.
Validate that the wpa_supplicant authentication
process was successful.
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.
"""
def error():
print "Unable to find ctrl_interface for wpa_supplicant. " + \
"Could not validate authentication."
# Right now there's no way to do this for ralink drivers
if self.wpa_driver == RALINK_DRIVER:
return True
ctrl_iface = '/var/run/wpa_supplicant'
try:
socket = [os.path.join(ctrl_iface, s) \
for s in os.listdir(ctrl_iface) if s == self.iface][0]
except OSError:
error()
return True
wpa = wpactrl.WPACtrl(socket)
MAX_TIME = 15
MAX_DISCONNECTED_TIME = 3
while (time.time() - auth_time) < MAX_TIME:
status = wpa.request("STATUS").split("\n")
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
elif result.endswith("DISCONNECTED") and \
(time.time() - auth_time) > MAX_DISCONNECTED_TIME:
# Force a rescan to get wpa_supplicant moving again.
wpa.request("SCAN")
MAX_TIME += 5
time.sleep(1)
print 'wpa_supplicant authentication may have failed.'
return False
def _AuthenticateRalinkLegacy(self, network):
""" Authenticate with the specified wireless network.
This function handles Ralink legacy cards that cannot use
wpa_supplicant.
Keyword arguments:
network -- dictionary containing network info
"""
if network.get('key') != None:
lines = self._GetRalinkInfo()
for x in lines:
info = x.split()
if len(info) < 5:
break
if info[2] == network.get('essid'):
if info[5] == 'WEP' or (info[5] == 'OPEN' and \
info[4] == 'WEP'):
print 'Setting up WEP'
cmd = ''.join(['iwconfig ', self.iface, ' key ',
network.get('key')])
if self.verbose: print cmd
misc.Run(cmd)
else:
if info[5] == 'SHARED' and info[4] == 'WEP':
print 'Setting up WEP'
auth_mode = 'SHARED'
key_name = 'Key1'
elif info[5] == 'WPA-PSK':
print 'Setting up WPA-PSK'
auth_mode = 'WPAPSK'
key_name = 'WPAPSK'
elif info[5] == 'WPA2-PSK':
print 'Setting up WPA2-PSK'
auth_mode = 'WPA2PSK'
key_name = 'WPAPSK'
else:
print 'Unknown AuthMode, can\'t complete ' + \
'connection process!'
return
cmd_list = []
cmd_list.append('NetworkType=' + info[6])
cmd_list.append('AuthMode=' + auth_mode)
cmd_list.append('EncrypType=' + info[4])
cmd_list.append('SSID=' + info[2])
cmd_list.append(key_name + '=' + network.get('key'))
if info[5] == 'SHARED' and info[4] == 'WEP':
cmd_list.append('DefaultKeyID=1')
cmd_list.append('SSID=' + info[2])
for cmd in cmd_list:
cmd = 'iwpriv ' + self.iface + ' '
if self.verbose: print cmd
misc.Run(cmd)
def GetBSSID(self):
""" 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:]
except IOError, e:
if self.verbose:
print "SIOCGIWAP failed: " + str(e)
return ""
raw_addr = struct.unpack("xxBBBBBB", result[:8])
return "%02X:%02X:%02X:%02X:%02X:%02X" % raw_addr
def GetSignalStrength(self, iwconfig=None):
""" Get the signal strength of the current network.
Returns:
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()
if strength and max_strength:
return 100 * int(strength) // int(max_strength)
return strength
def _get_max_strength(self):
""" Gets the maximum possible strength from the wireless driver. """
buff = array.array('c', '\0' * 700)
addr, length = buff.buffer_info()
arg = struct.pack('Pi', addr, length)
iwfreq = (self.iface + '\0' * 16)[:16] + arg
try:
result = fcntl.ioctl(self.sock.fileno(), SIOCGIWRANGE, iwfreq)
except IOError, e:
if self.verbose:
print "SIOCGIWRANGE failed: " + str(e)
return None
# This defines the iwfreq struct, used to get signal strength.
fmt = "iiihb6ii4B4Bi32i2i2i2i2i3h8h2b2bhi8i2b3h2i2ihB17x" + 32 * "ihbb"
size = struct.calcsize(fmt)
data = buff.tostring()
data = data[0:size]
values = struct.unpack(fmt, data)
return values[12]
def GetDBMStrength(self, iwconfig=None):
""" Get the dBm signal strength of the current network.
Returns:
The dBm signal strength.
"""
if not self.iface: return -100
buff = misc.get_irwange_ioctl_result(self.iface, SIOCGIWSTATS)
if not buff:
return None
return str((ord(buff[3]) - 256))
def GetCurrentNetwork(self, iwconfig=None):
""" Get the essid of the current network.
Returns:
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')

102
wicd/configmanager.py Normal file
View File

@@ -0,0 +1,102 @@
#!/usr/bin/env python
""" Wicd Configuration Manager
Wrapper around ConfigParser for wicd, though it should be
reusable for other purposes as well.
"""
#
# Copyright (C) 2007 Adam Blackburn
# Copyright (C) 2007 Dan O'Reilly
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License Version 2 as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
from ConfigParser import ConfigParser
from wicd.misc import stringToNone
class ConfigManager(ConfigParser):
""" A class that can be used to manage a given configuration file. """
def __init__(self, path):
ConfigParser.__init__(self)
self.config_file = path
self.read(path)
def __repr__(self):
return self.config_file
def __str__(self):
return self.config_file
def get_config(self):
return self.config_file
def set_option(self, section, option, value, save=False):
""" Wrapper around ConfigParser.set
Adds the option to write the config file change right away.
"""
if not self.has_section(section):
self.add_section(section)
ConfigParser.set(self, section, str(option), str(value))
if save:
self.write()
def set(self, *args, **kargs):
self.set_option(*args, **kargs)
def get_option(self, section, option, default=None):
""" Wrapper around ConfigParser.get.
Automatically adds any missing sections, adds the ability
to write a default value, and if one is provided prints if
the default or a previously saved value is returned.
"""
if not self.has_section(section):
self.add_section(section)
if self.has_option(section, option):
ret = ConfigParser.get(self, section, option)
if default:
print ''.join(['found ', option, ' in configuration ', ret])
else:
print ''.join(['did not find ', option,
' in configuration, setting default ', str(default)])
self.set(section, option, str(default), save=True)
ret = default
# Try to intelligently handle the type of the return value.
try:
ret = int(ret)
except ValueError, TypeError:
ret = stringToNone(ret)
return ret
def get(self, *args, **kargs):
return self.get_option(*args, **kargs)
def write(self):
configfile = open(self.config_file, 'w')
ConfigParser.write(self, configfile)
configfile.close()
def remove_section(self,section):
if self.has_section(section):
ConfigParser.remove_section(self, section)

View File

@@ -58,7 +58,6 @@ except Exception:
wireless = dbus.Interface(proxy_obj, 'org.wicd.daemon.wireless')
wired = dbus.Interface(proxy_obj, 'org.wicd.daemon.wired')
config = dbus.Interface(proxy_obj, 'org.wicd.daemon.config')
wireless_conf = wpath.etc + 'wireless-settings.conf'
wired_conf = wpath.etc + 'wired-settings.conf'
@@ -132,8 +131,8 @@ def write_scripts(network, network_type, script_info):
con.set(network, "afterscript", script_info["post_entry"])
con.set(network, "disconnectscript", script_info["disconnect_entry"])
con.write(open(wired_conf, "w"))
config.ReadWiredNetworkProfile(network)
config.SaveWiredNetworkProfile(network)
wired.ReadWiredNetworkProfile(network)
wired.SaveWiredNetworkProfile(network)
else:
bssid = wireless.GetWirelessProperty(int(network), "bssid")
con.read(wireless_conf)
@@ -143,8 +142,8 @@ def write_scripts(network, network_type, script_info):
con.set(bssid, "afterscript", script_info["post_entry"])
con.set(bssid, "disconnectscript", script_info["disconnect_entry"])
con.write(open(wireless_conf, "w"))
config.ReadWirelessNetworkProfile(int(network))
config.SaveWirelessNetworkProfile(int(network))
wireless.ReadWirelessNetworkProfile(int(network))
wireless.SaveWirelessNetworkProfile(int(network))
def main (argv):
""" Runs the script configuration dialog. """
@@ -157,7 +156,7 @@ def main (argv):
script_info = get_script_info(network, network_type)
gladefile = wpath.etc + "wicd.glade"
gladefile = wpath.share + "wicd.glade"
wTree = gtk.glade.XML(gladefile)
dialog = wTree.get_widget("configure_script_dialog")
wTree.get_widget("pre_label").set_label(language['before_script'] + ":")

View File

@@ -34,9 +34,9 @@ import gtk.glade
from dbus import DBusException
from dbus import version as dbus_version
import wicd.misc
import wicd.wpath
from wicd.misc import noneToString, noneToBlankString, stringToBoolean, checkboxTextboxToggle
from wicd import misc
from wicd import wpath
from wicd.misc import noneToString
from wicd.netentry import WiredNetworkEntry, WirelessNetworkEntry
from wicd.prefs import PreferencesDialog
from wicd.dbusmanager import DBusManager
@@ -56,12 +56,11 @@ else:
from dbus.mainloop.glib import DBusGMainLoop
DBusGMainLoop(set_as_default=True)
proxy_obj, daemon, wireless, wired, bus, config = [None for x in
range(0, 6)]
proxy_obj, daemon, wireless, wired, bus = [None for x in range(0, 5)]
language = misc.get_language_list_gui()
def setup_dbus(dbus_man=None):
global bus, daemon, wireless, wired, config, dbus_manager
global bus, daemon, wireless, wired, dbus_manager
if dbus_man:
dbus_manager = dbus_man
else:
@@ -83,7 +82,6 @@ def setup_dbus(dbus_man=None):
daemon = dbus_ifaces['daemon']
wireless = dbus_ifaces['wireless']
wired = dbus_ifaces['wired']
config = dbus_ifaces['config']
return True
@@ -95,6 +93,14 @@ def error(parent, message):
dialog.run()
dialog.destroy()
def alert(parent, message):
""" Shows an error dialog """
dialog = gtk.MessageDialog(parent, gtk.DIALOG_MODAL, gtk.MESSAGE_WARNING,
gtk.BUTTONS_OK)
dialog.set_markup(message)
dialog.run()
dialog.destroy()
########################################
##### GTK EXTENSION CLASSES
########################################
@@ -202,7 +208,7 @@ class WiredProfileChooser:
response = dialog.run()
if response == 1:
print 'reading profile ', wired_profiles.get_active_text()
config.ReadWiredNetworkProfile(wired_profiles.get_active_text())
wired.ReadWiredNetworkProfile(wired_profiles.get_active_text())
wired.ConnectWired()
else:
if stoppopcheckbox.get_active():
@@ -217,10 +223,10 @@ class appGui(object):
if not standalone:
setup_dbus(dbus_man)
gladefile = "data/wicd.glade"
gladefile = wpath.share + "wicd.glade"
self.wTree = gtk.glade.XML(gladefile)
dic = { "refresh_clicked" : self.refresh_networks,
dic = { "refresh_clicked" : self.refresh_clicked,
"quit_clicked" : self.exit,
"disconnect_clicked" : self.disconnect_all,
"main_exit" : self.exit,
@@ -258,7 +264,6 @@ class appGui(object):
self.standalone = standalone
self.wpadrivercombo = None
self.connecting = False
self.fast = True # Use ioctl instead of external program calls
self.prev_state = None
self.refresh_networks(fresh=False)
@@ -274,7 +279,7 @@ class appGui(object):
else:
self.wTree.get_widget("iface_menu_enable_wired").hide()
size = config.ReadWindowSize("main")
size = daemon.ReadWindowSize("main")
width = size[0]
height = size[1]
if width > -1 and height > -1:
@@ -449,7 +454,7 @@ class appGui(object):
if not self.is_visible:
return True
fast = self.fast
fast = not daemon.NeedsExternalCalls()
wired_connecting = wired.CheckIfWiredConnecting()
wireless_connecting = wireless.CheckIfWirelessConnecting()
self.connecting = wired_connecting or wireless_connecting
@@ -467,7 +472,7 @@ class appGui(object):
iwconfig = wireless.GetIwconfig()
else:
iwconfig = ''
self.set_status(wireless.GetCurrentNetwork(iwconfig, fast) + ': ' +
self.set_status(wireless.GetCurrentNetwork(iwconfig) + ': ' +
language[str(wireless.CheckWirelessConnectingMessage())])
if wired_connecting:
self.set_status(language['wired_network'] + ': ' +
@@ -484,14 +489,13 @@ class appGui(object):
self.status_bar.remove(1, self.statusID)
# Determine connection status.
if self.check_for_wired(wired.GetWiredIP(fast)):
if self.check_for_wired(wired.GetWiredIP("")):
return True
if not fast:
iwconfig = wireless.GetIwconfig()
else:
iwconfig = ''
if self.check_for_wireless(iwconfig,
wireless.GetWirelessIP(fast)):
if self.check_for_wireless(iwconfig, wireless.GetWirelessIP("")):
return True
self.set_status(language['not_connected'])
return True
@@ -510,9 +514,10 @@ class appGui(object):
def check_for_wired(self, wired_ip):
""" Determine if wired is active, and if yes, set the status. """
if wired_ip and wired.CheckPluggedIn(self.fast):
self.set_status(language['connected_to_wired'].replace('$A',
wired_ip))
if wired_ip and wired.CheckPluggedIn():
self.set_status(
language['connected_to_wired'].replace('$A',wired_ip)
)
return True
else:
return False
@@ -522,15 +527,15 @@ class appGui(object):
if not wireless_ip:
return False
network = wireless.GetCurrentNetwork(iwconfig, self.fast)
network = wireless.GetCurrentNetwork(iwconfig)
if not network:
return False
network = str(network)
if daemon.GetSignalDisplayType() == 0:
strength = wireless.GetCurrentSignalStrength(iwconfig, self.fast)
strength = wireless.GetCurrentSignalStrength(iwconfig)
else:
strength = wireless.GetCurrentDBMStrength(iwconfig, self.fast)
strength = wireless.GetCurrentDBMStrength(iwconfig)
if strength is None:
return False
@@ -549,16 +554,20 @@ class appGui(object):
def dbus_scan_finished(self):
""" Calls for a non-fresh update of the gui window.
This method is called after the daemon runs an automatic
rescan.
This method is called after a wireless scan is completed.
"""
if not self.connecting:
self.refresh_networks(fresh=False)
def dbus_scan_started(self):
""" Called when a wireless scan starts. """
self.network_list.set_sensitive(False)
def refresh_clicked(self, widget=None):
def dummy(x=None):pass
wireless.Scan(reply_handler=dummy, error_handler=dummy)
def refresh_networks(self, widget=None, fresh=True, hidden=None):
""" Refreshes the network list.
@@ -579,7 +588,7 @@ class appGui(object):
z.destroy()
del z
if wired.CheckPluggedIn(self.fast) or wired.GetAlwaysShowWiredInterface():
if wired.CheckPluggedIn() or daemon.GetAlwaysShowWiredInterface():
printLine = True # In this case we print a separator.
wirednet = WiredNetworkEntry(dbus_manager.get_dbus_ifaces())
self.network_list.pack_start(wirednet, False, False)
@@ -691,7 +700,7 @@ class appGui(object):
entry.set_net_prop("dns1", '')
entry.set_net_prop("dns2", '')
entry.set_net_prop("dns3", '')
config.SaveWiredNetworkProfile(entry.prof_name)
wired.SaveWiredNetworkProfile(entry.prof_name)
return True
def save_wireless_settings(self, networkid, entry, netent):
@@ -758,9 +767,9 @@ class appGui(object):
entry.set_net_prop('use_settings_globally', True)
else:
entry.set_net_prop('use_settings_globally', False)
config.RemoveGlobalEssidEntry(networkid)
wireless.RemoveGlobalEssidEntry(networkid)
config.SaveWirelessNetworkProfile(networkid)
wireless.SaveWirelessNetworkProfile(networkid)
return True
def edit_advanced(self, widget, event, ttype, networkid, networkentry):
@@ -864,7 +873,7 @@ class appGui(object):
"""
self.window.hide()
[width, height] = self.window.get_size()
config.WriteWindowSize(width, height, "main")
daemon.WriteWindowSize(width, height, "main")
if self.standalone:
self.window.destroy()
@@ -895,9 +904,9 @@ if __name__ == '__main__':
setup_dbus()
app = appGui(standalone=True)
bus.add_signal_receiver(app.dbus_scan_finished, 'SendEndScanSignal',
'org.wicd.daemon')
'org.wicd.daemon.wireless')
bus.add_signal_receiver(app.dbus_scan_started, 'SendStartScanSignal',
'org.wicd.daemon')
'org.wicd.daemon.wireless')
bus.add_signal_receiver(app.update_connect_buttons, 'StatusChanged',
'org.wicd.daemon')
gtk.main()

View File

@@ -23,6 +23,8 @@ import sys
import os
import time
import wicd.wpath as wpath
class SizeError(IOError):
pass
@@ -89,6 +91,8 @@ class ManagedLog(object):
"""
def __init__(self, name, maxsize=360000, maxsave=3):
if not os.path.exists(os.path.dirname(name)):
os.makedirs(os.path.dirname(name))
self._lf = LogFile(name, "a", maxsize)
self.maxsave = maxsave

View File

@@ -21,12 +21,12 @@ import os
import locale
import gettext
import sys
from subprocess import Popen, STDOUT, PIPE
from copy import copy
from subprocess import Popen, STDOUT, PIPE, call
import subprocess
import commands
import wicd.wpath as wpath
# wicd imports
import wpath
if __name__ == '__main__':
wpath.chdir(__file__)
@@ -77,7 +77,7 @@ def Run(cmd, include_stderr=False, return_pipe=False):
err = None
fds = False
tmpenv = copy(os.environ)
tmpenv = os.environ.copy()
tmpenv["LC_ALL"] = "C"
tmpenv["LANG"] = "C"
f = Popen(cmd, shell=True, stdout=PIPE, stderr=err, close_fds=fds,
@@ -89,11 +89,15 @@ def Run(cmd, include_stderr=False, return_pipe=False):
return f.communicate()[0]
def LaunchAndWait(cmd):
""" Launches the given program with the given arguments, then blocks. """
subprocess.call(cmd)
""" Launches the given program with the given arguments, then blocks.
cmd : A list contained the program name and its arguments.
"""
call(cmd)
def IsValidIP(ip):
""" Make sure an entered IP is valid """
""" Make sure an entered IP is valid. """
if ip != None:
if ip.count('.') == 3:
ipNumbers = ip.split('.')
@@ -167,7 +171,7 @@ def ParseEncryption(network):
and creating a config file for it
"""
enctemplate = open("encryption/templates/" + network["enctype"])
enctemplate = open(wpath.encryption + network["enctype"])
template = enctemplate.readlines()
# Set these to nothing so that we can hold them outside the loop
z = "ap_scan=1\n"
@@ -206,7 +210,7 @@ def LoadEncryptionMethods():
encryptionTypes = []
try:
enctypes = open("encryption/templates/active","r").readlines()
enctypes = open(wpath.encryption + "active","r").readlines()
except IOError, e:
print "Fatal Error: template index file is missing."
raise IOError(e)
@@ -215,7 +219,7 @@ def LoadEncryptionMethods():
for x in enctypes:
x = x.strip()
try:
f = open("encryption/templates/" + x, "r")
f = open(wpath.encryption + x, "r")
except IOError:
print 'Failed to load encryption type ' + str(x)
continue
@@ -424,6 +428,8 @@ def get_language_list_gui():
language["dhcp_client"] = _("DHCP Client")
language["wired_detect"] = _("Wired Link Detection")
language["route_flush"] = _("Route Table Flushing")
language["backend"] = _("Backend")
language["backend_alert"] = _("Changes to your backend won't occur until the daemon is restarted.")
language['0'] = _('0')
language['1'] = _('1')
@@ -467,7 +473,7 @@ def get_language_list_tray():
language['connecting'] = _('Connecting')
language['wired'] = _('Wired Network')
language['scanning'] = _('Scanning')
language['no_wireless_networks_found'] = _('No wireless networks found.')
return language
def noneToBlankString(text):

View File

@@ -41,9 +41,14 @@ misc.RenameProcess("wicd-monitor")
if __name__ == '__main__':
wpath.chdir(__file__)
proxy_obj = dbus.SystemBus().get_object('org.wicd.daemon', '/org/wicd/daemon')
bus = dbus.SystemBus()
proxy_obj = bus.get_object('org.wicd.daemon', '/org/wicd/daemon')
daemon = dbus.Interface(proxy_obj, 'org.wicd.daemon')
proxy_obj = bus.get_object('org.wicd.daemon', '/org/wicd/daemon/wired')
wired = dbus.Interface(proxy_obj, 'org.wicd.daemon.wired')
proxy_obj = bus.get_object('org.wicd.daemon', '/org/wicd/daemon/wireless')
wireless = dbus.Interface(proxy_obj, 'org.wicd.daemon.wireless')
class ConnectionStatus(object):
@@ -61,9 +66,6 @@ class ConnectionStatus(object):
self.reconnect_tries = 0
self.last_reconnect_time = time.time()
self.signal_changed = False
# This determines if we use ioctl or external programs
self.fast = True
self.iwconfig = ""
def check_for_wired_connection(self, wired_ip):
@@ -74,7 +76,7 @@ class ConnectionStatus(object):
"""
if wired_ip and wired.CheckPluggedIn(self.fast):
if wired_ip and wired.CheckPluggedIn():
# Only change the interface if it's not already set for wired
if not self.still_wired:
daemon.SetCurrentInterface(daemon.GetWiredInterface())
@@ -97,25 +99,14 @@ class ConnectionStatus(object):
if wireless_ip is None:
return False
if self.fast:
self.iwconfig = ''
else:
if daemon.NeedsExternalCalls():
self.iwconfig = wireless.GetIwconfig()
else:
self.iwconfig = ''
# Reset this, just in case.
self.tried_reconnect = False
# Try getting signal strength, and default to 0
# if something goes wrong.
try:
if daemon.GetSignalDisplayType() == 0:
wifi_signal = int(wireless.GetCurrentSignalStrength(self.iwconfig,
self.fast))
else:
wifi_signal = int(wireless.GetCurrentDBMStrength(self.iwconfig,
self.fast))
except:
wifi_signal = 0
wifi_signal = self._get_printable_sig_strength()
if wifi_signal == 0:
# If we have no signal, increment connection loss counter.
# If we haven't gotten any signal 4 runs in a row (12 seconds),
@@ -123,6 +114,7 @@ class ConnectionStatus(object):
self.connection_lost_counter += 1
print self.connection_lost_counter
if self.connection_lost_counter >= 4:
wireless.DisconnectWireless()
self.connection_lost_counter = 0
return False
else: # If we have a signal, reset the counter
@@ -131,8 +123,7 @@ class ConnectionStatus(object):
# Only update if the signal strength has changed because doing I/O
# calls is expensive, and the icon flickers.
if (wifi_signal != self.last_strength or
self.network != wireless.GetCurrentNetwork(self.iwconfig,
self.fast)):
self.network != wireless.GetCurrentNetwork(self.iwconfig)):
self.last_strength = wifi_signal
self.signal_changed = True
daemon.SetCurrentInterface(daemon.GetWirelessInterface())
@@ -159,15 +150,14 @@ class ConnectionStatus(object):
# Determine what our current state is.
# Check for wired.
wired_ip = wired.GetWiredIP(self.fast)
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
# Check for wireless
wifi_ip = wireless.GetWirelessIP(self.fast)
#self.iwconfig = wireless.GetIwconfig()
wifi_ip = wireless.GetWirelessIP("")
self.signal_changed = False
wireless_found = self.check_for_wireless_connection(wifi_ip)
if wireless_found:
@@ -194,7 +184,6 @@ class ConnectionStatus(object):
""" Set the current connection state. """
# Set our connection state/info.
iwconfig = self.iwconfig
fast = self.fast
if state == misc.NOT_CONNECTED:
info = [""]
elif state == misc.SUSPENDED:
@@ -203,12 +192,12 @@ class ConnectionStatus(object):
if wired.CheckIfWiredConnecting():
info = ["wired"]
else:
info = ["wireless", wireless.GetCurrentNetwork(iwconfig, fast)]
info = ["wireless", wireless.GetCurrentNetwork(iwconfig)]
elif state == misc.WIRELESS:
self.reconnect_tries = 0
info = [wifi_ip, wireless.GetCurrentNetwork(iwconfig, fast),
str(wireless.GetPrintableSignalStrength(iwconfig, fast)),
str(wireless.GetCurrentNetworkID(iwconfig, fast))]
info = [wifi_ip, wireless.GetCurrentNetwork(iwconfig),
str(self._get_printable_sig_strength()),
str(wireless.GetCurrentNetworkID(iwconfig))]
elif state == misc.WIRED:
self.reconnect_tries = 0
info = [wired_ip]
@@ -224,6 +213,18 @@ class ConnectionStatus(object):
self.last_state = state
return True
def _get_printable_sig_strength(self):
""" Get the correct signal strength format. """
try:
if daemon.GetSignalDisplayType() == 0:
wifi_signal = int(wireless.GetCurrentSignalStrength(self.iwconfig))
else:
wifi_signal = int(wireless.GetCurrentDBMStrength(self.iwconfig))
except TypeError:
wifi_signal = 0
return wifi_signal
def auto_reconnect(self, from_wireless=None):
""" Automatically reconnects to a network if needed.
@@ -250,7 +251,7 @@ class ConnectionStatus(object):
# 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, self.fast)
cur_net_id = wireless.GetCurrentNetworkID(self.iwconfig)
if from_wireless and cur_net_id > -1:
print 'Trying to reconnect to last used wireless ' + \
'network'
@@ -279,7 +280,6 @@ def err_handle(error):
""" Just a dummy function needed for asynchronous dbus calls. """
pass
def main():
""" Starts the connection monitor.
@@ -289,8 +289,7 @@ def main():
"""
monitor = ConnectionStatus()
gobject.timeout_add(2000, monitor.update_connection_status)
#gobject.timeout_add(120000, monitor.rescan_networks)
gobject.timeout_add(2500, monitor.update_connection_status)
mainloop = gobject.MainLoop()
mainloop.run()

View File

@@ -16,15 +16,18 @@
#
import gtk
import os
import wicd.misc as misc
from wicd.misc import noneToString, stringToNone, noneToBlankString, stringToBoolean
import wicd.wpath as wpath
import misc
from misc import noneToString, stringToNone, noneToBlankString, stringToBoolean
import wpath
language = misc.get_language_list_gui()
# These get set when a NetworkEntry is instantiated.
daemon, wireless, wired, vpn_session, config = [None for x in range(0, 5)]
daemon = None
wired = None
wireless = None
def error(parent, message):
""" Shows an error dialog """
@@ -219,7 +222,7 @@ class AdvancedSettingsDialog(gtk.Dialog):
self.txt_dns_2.set_sensitive(not self.chkbox_global_dns.get_active())
self.txt_dns_3.set_sensitive(not self.chkbox_global_dns.get_active())
def destroy_called(self):
def destroy_called(self, *args):
""" Clean up everything.
This might look excessive, but it was the only way to prevent
@@ -264,7 +267,7 @@ class WiredSettingsDialog(AdvancedSettingsDialog):
""" Helper method to fetch and format wired properties. """
return noneToBlankString(wired.GetWiredProperty(label))
def destroy_called(self):
def destroy_called(self, *args):
""" Clean up everything.
This might look excessive, but it was the only way to prevent
@@ -326,7 +329,7 @@ class WirelessSettingsDialog(AdvancedSettingsDialog):
self.combo_encryption.connect("changed", self.change_encrypt_method)
self.des = self.connect("destroy", self.destroy_called)
def destroy_called(self):
def destroy_called(self, *args):
""" Clean up everything.
This might look excessive, but it was the only way to prevent
@@ -435,11 +438,10 @@ class NetworkEntry(gtk.HBox):
WirelessNetworkEntry classes.
"""
global daemon, wired, wireless, config
global daemon, wired, wireless
daemon = dbus_ifaces["daemon"]
wired = dbus_ifaces["wired"]
wireless = dbus_ifaces["wireless"]
config = dbus_ifaces["config"]
gtk.HBox.__init__(self, False, 2)
self.expander = gtk.Expander()
self.image = gtk.Image()
@@ -541,7 +543,7 @@ class WiredNetworkEntry(NetworkEntry):
# Build the profile list.
self.combo_profile_names = gtk.combo_box_entry_new_text()
self.profile_list = config.GetWiredProfileList()
self.profile_list = wired.GetWiredProfileList()
if self.profile_list:
for x in self.profile_list:
self.combo_profile_names.append_text(x)
@@ -582,7 +584,7 @@ class WiredNetworkEntry(NetworkEntry):
# Display the default profile if it exists.
if self.profile_list is not None:
prof = config.GetDefaultWiredNetwork()
prof = wired.GetDefaultWiredNetwork()
if prof != None: # Make sure the default profile gets displayed.
i = 0
while self.combo_profile_names.get_active_text() != prof:
@@ -624,6 +626,7 @@ class WiredNetworkEntry(NetworkEntry):
def edit_scripts(self, widget=None, event=None):
""" Launch the script editting dialog. """
profile = self.combo_profile_names.get_active_text()
if os.getuid() != 0:
try:
sudo_prog = misc.choose_sudo_prog()
msg = "You must enter your password to configure scripts"
@@ -631,15 +634,18 @@ class WiredNetworkEntry(NetworkEntry):
msg_flag = "-m"
else:
msg_flag = "--caption"
misc.LaunchAndWait([sudo_prog, msg_flag, msg, "./configscript.py",
profile, "wired"])
misc.LaunchAndWait([sudo_prog, msg_flag, msg,
wpath.lib + "configscript.py", profile,
"wired"])
except misc.WicdError:
error("Could not find a graphical sudo program." + \
error(None, "Could not find a graphical sudo program." + \
" Script editor could not be launched.")
else:
misc.LaunchAndWait([wpath.lib + "configscript.py", profile, "wired"])
def check_enable(self):
""" Disable objects if the profile list is empty. """
profile_list = config.GetWiredProfileList()
profile_list = wired.GetWiredProfileList()
if profile_list == None:
self.button_delete.set_sensitive(False)
self.connect_button.set_sensitive(False)
@@ -659,13 +665,13 @@ class WiredNetworkEntry(NetworkEntry):
""" Add a profile to the profile list. """
print "adding profile"
profile_name = self.combo_profile_names.get_active_text()
profile_list = config.GetWiredProfileList()
profile_list = wired.GetWiredProfileList()
if profile_list:
if profile_name in profile_list:
return False
if profile_name != "":
self.profile_help.hide()
config.CreateWiredNetworkProfile(profile_name)
wired.CreateWiredNetworkProfile(profile_name)
self.combo_profile_names.prepend_text(profile_name)
self.combo_profile_names.set_active(0)
self.advanced_dialog.prof_name = profile_name
@@ -679,12 +685,12 @@ class WiredNetworkEntry(NetworkEntry):
""" Remove a profile from the profile list. """
print "removing profile"
profile_name = self.combo_profile_names.get_active_text()
config.DeleteWiredNetworkProfile(profile_name)
wired.DeleteWiredNetworkProfile(profile_name)
self.combo_profile_names.remove_text(self.combo_profile_names.
get_active())
self.combo_profile_names.set_active(0)
self.advanced_dialog.prof_name = self.combo_profile_names.get_active_text()
if not config.GetWiredProfileList():
if not wired.GetWiredProfileList():
self.profile_help.show()
entry = self.combo_profile_names.child
entry.set_text("")
@@ -700,10 +706,10 @@ class WiredNetworkEntry(NetworkEntry):
""" Change the default profile. """
if self.chkbox_default_profile.get_active():
# Make sure there is only one default profile at a time
config.UnsetWiredDefault()
wired.UnsetWiredDefault()
wired.SetWiredProperty("default",
self.chkbox_default_profile.get_active())
config.SaveWiredNetworkProfile(self.combo_profile_names.get_active_text())
wired.SaveWiredNetworkProfile(self.combo_profile_names.get_active_text())
def change_profile(self, widget):
""" Called when a new profile is chosen from the list. """
@@ -713,7 +719,7 @@ class WiredNetworkEntry(NetworkEntry):
return
profile_name = self.combo_profile_names.get_active_text()
config.ReadWiredNetworkProfile(profile_name)
wired.ReadWiredNetworkProfile(profile_name)
self.advanced_dialog.txt_ip.set_text(self.format_entry("ip"))
self.advanced_dialog.txt_netmask.set_text(self.format_entry("netmask"))
@@ -906,6 +912,7 @@ class WirelessNetworkEntry(NetworkEntry):
def edit_scripts(self, widget=None, event=None):
""" Launch the script editting dialog. """
if os.getuid() != 0:
try:
sudo_prog = misc.choose_sudo_prog()
msg = "You must enter your password to configure scripts"
@@ -913,15 +920,19 @@ class WirelessNetworkEntry(NetworkEntry):
msg_flag = "-m"
else:
msg_flag = "--caption"
misc.LaunchAndWait([sudo_prog, msg_flag, msg, "./configscript.py",
misc.LaunchAndWait([sudo_prog, msg_flag, msg,
wpath.lib + "configscript.py",
str(self.networkID), "wireless"])
except IOError:
error("Could not find a graphical sudo program." + \
error(None, "Could not find a graphical sudo program." + \
" Script editor could no be launched.")
else:
misc.LaunchAndWait(["./configscript.py", str(self.networkID),
"wireless"])
def update_autoconnect(self, widget=None):
""" Called when the autoconnect checkbox is toggled. """
wireless.SetWirelessProperty(self.networkID, "automatic",
noneToString(self.chkbox_autoconnect.
get_active()))
config.SaveWirelessNetworkProperty(self.networkID, "automatic")
wireless.SaveWirelessNetworkProperty(self.networkID, "automatic")

View File

@@ -42,17 +42,32 @@ class WiredConnectThread() -- Connection thread for wired
#
import re
import time
import threading
import thread
import time
import wicd.misc as misc
import wicd.wnettools as wnettools
import wicd.wpath as wpath
# wicd imports
import misc
import wpath
from backend import BackendManager
if __name__ == '__main__':
wpath.chdir(__file__)
BACKEND = None
BACKEND_MGR = BackendManager()
def get_backend_list():
if not BACKEND_MGR:
return [""]
else:
return BACKEND_MGR.get_available_backends()
def get_current_backend():
if not BACKEND_MGR:
return None
else:
return BACKEND_MGR.get_current_backend()
class Controller(object):
""" Parent class for the different interface types. """
@@ -66,6 +81,7 @@ class Controller(object):
self._dhcp_client = None
self._flush_tool = None
self._debug = None
self._backend = None
self.connecting_thread = None
self.before_script = None
self.after_script = None
@@ -73,6 +89,7 @@ class Controller(object):
self.driver = None
self.wiface = None
self.liface = None
self.backend_manager = BackendManager()
def set_wireless_iface(self, value):
self._wireless_interface = value
@@ -128,6 +145,21 @@ class Controller(object):
flush_tool = property(get_flush_tool, set_flush_tool)
dhcp_client = property(get_dhcp_client, set_dhcp_client)
def LoadBackend(self, backend_name):
""" Load the given networking backend. """
global BACKEND
if backend_name == self._backend:
return
self._backend = BACKEND_MGR.load_backend(backend_name)
BACKEND = self._backend
def NeedsExternalCalls(self):
""" Returns true if the loaded backend needs external calls. """
if self._backend:
return self._backend.NeedsExternalCalls()
else:
return True
class ConnectThread(threading.Thread):
""" A class to perform network connections in a multi-threaded way.
@@ -169,7 +201,7 @@ class ConnectThread(threading.Thread):
self.before_script = before_script
self.after_script = after_script
self.disconnect_script = disconnect_script
self.should_die = False
self._should_die = False
self.abort_reason = ""
self.global_dns_1 = gdns1
@@ -184,6 +216,15 @@ class ConnectThread(threading.Thread):
self.SetStatus('interface_down')
def get_should_die(self):
return self._should_die
def set_should_die(self, val):
self.lock.acquire()
self._should_die = val
should_die = property(should_die, get_should_die, set_should_die)
def SetStatus(self, status):
""" Set the threads current status message in a thread-safe way.
@@ -286,13 +327,14 @@ class ConnectThread(threading.Thread):
"""
if self.network.get('use_global_dns'):
wnettools.SetDNS(misc.Noneify(self.global_dns_1),
BACKEND.SetDNS(misc.Noneify(self.global_dns_1),
misc.Noneify(self.global_dns_2),
misc.Noneify(self.global_dns_3))
elif self.network.get('use_static_dns') and (self.network.get('dns1') or
self.network.get('dns2') or self.network.get('dns3')):
self.SetStatus('setting_static_dns')
wnettools.SetDNS(self.network.get('dns1'), self.network.get('dns2'),
BACKEND.SetDNS(self.network.get('dns1'),
self.network.get('dns2'),
self.network.get('dns3'))
def connect_aborted(self, reason):
@@ -325,13 +367,18 @@ class ConnectThread(threading.Thread):
""" Stop and running DHCP clients, as well as wpa_supplicant. """
print 'Stopping wpa_supplicant and any DHCP clients'
iface.StopWPA()
wnettools.StopDHCP()
BACKEND.StopDHCP()
def abort_if_needed(self):
""" Abort the thread is it has been requested. """
if self.should_die:
self.lock.acquire()
try:
if self._should_die:
self.connect_aborted('aborted')
self.lock.release()
thread.exit()
finally:
self.lock.release()
def put_iface_up(self, iface):
""" Bring up given interface. """
@@ -347,8 +394,6 @@ class Wireless(Controller):
""" Initialize the class. """
Controller.__init__(self)
self._wpa_driver = None
self.wiface = wnettools.WirelessInterface(self.wireless_interface,
self.debug, self.wpa_driver)
def set_wpa_driver(self, value):
self._wpa_driver = value
@@ -359,13 +404,11 @@ class Wireless(Controller):
wpa_driver = property(get_wpa_driver, set_wpa_driver)
#def LoadInterfaces(self, dhcp_client, flush_tool):
# """ Load the wnettools controls for the wired/wireless interfaces. """
# #self.wiface = wnettools.WirelessInterface(self.wireless_interface,
# # self.debug, self.wpa_driver)
# self.dhcp_client = dhcp_client
# self.flush_tool = flush_tool
def LoadBackend(self, backend):
Controller.LoadBackend(self, backend)
if self._backend:
self.wiface = self._backend.WirelessInterface(self.wireless_interface,
self.debug, self.wpa_driver)
def Scan(self, essid=None):
""" Scan for available wireless networks.
@@ -431,43 +474,43 @@ class Wireless(Controller):
self.connecting_thread.start()
return True
def GetSignalStrength(self, iwconfig=None, fast=False):
def GetSignalStrength(self, iwconfig=""):
""" Get signal strength of the current network.
Returns:
The current signal strength.
"""
return self.wiface.GetSignalStrength(iwconfig, fast)
return self.wiface.GetSignalStrength(iwconfig)
def GetDBMStrength(self, iwconfig=None, fast=False):
def GetDBMStrength(self, iwconfig=""):
""" Get the dBm signal strength of the current network.
Returns:
The current dBm signal strength.
"""
return self.wiface.GetDBMStrength(iwconfig, fast)
return self.wiface.GetDBMStrength(iwconfig)
def GetCurrentNetwork(self, iwconfig=None, fast=False):
def GetCurrentNetwork(self, iwconfig=""):
""" Get current network name.
Returns:
The name of the currently connected network.
"""
return self.wiface.GetCurrentNetwork(iwconfig, fast)
return self.wiface.GetCurrentNetwork(iwconfig)
def GetIP(self, fast=False):
def GetIP(self, ifconfig=""):
""" Get the IP of the interface.
Returns:
The IP address of the interface in dotted notation.
"""
return self.wiface.GetIP(fast)
return self.wiface.GetIP(ifconfig)
def GetBSSID(self, fast=True):
def GetBSSID(self):
""" Get the BSSID of the current access point.
Returns:
@@ -475,7 +518,7 @@ class Wireless(Controller):
None the BSSID can't be found.
"""
return self.wiface.GetBSSID(fast)
return self.wiface.GetBSSID()
def GetIwconfig(self):
""" Get the out of iwconfig. """
@@ -507,7 +550,7 @@ class Wireless(Controller):
wiface = self.wiface
print 'Creating ad-hoc network'
print 'Killing dhclient and wpa_supplicant'
wnettools.StopDHCP()
BACKEND.StopDHCP()
wiface.StopWPA()
print 'Putting wireless interface down'
wiface.Down()
@@ -556,7 +599,7 @@ class Wireless(Controller):
The first available wireless interface.
"""
return wnettools.GetWirelessInterfaces()
return BACKEND.GetWirelessInterfaces()
def GetKillSwitchStatus(self):
""" Get the current status of the Killswitch.
@@ -645,7 +688,6 @@ class WirelessConnectThread(ConnectThread):
wiface = self.wiface
liface = self.liface
self.is_connecting = True
self.is_fast = True
# Run pre-connection script.
self.abort_if_needed()
@@ -684,8 +726,7 @@ class WirelessConnectThread(ConnectThread):
# Validate Authentication.
if self.network.get('enctype'):
self.SetStatus('validating_authentication')
if not wiface.ValidateAuthentication(time.time(),
fast=self.is_fast):
if not wiface.ValidateAuthentication(time.time()):
self.abort_connection('bad_pass')
self.abort_if_needed()
@@ -702,7 +743,7 @@ class WirelessConnectThread(ConnectThread):
self.SetStatus('done')
print 'Connecting thread exiting.'
if self.debug:
print "IP Address is: " + str(wiface.GetIP(fast=self.is_fast))
print "IP Address is: " + str(wiface.GetIP())
self.is_connecting = False
def generate_psk_and_authenticate(self, wiface):
@@ -756,7 +797,6 @@ class Wired(Controller):
Controller.__init__(self)
self.wpa_driver = None
self._link_detect = None
self.liface = wnettools.WiredInterface(self.wired_interface, self.debug)
def set_link_detect(self, value):
self._link_detect = value
@@ -767,21 +807,21 @@ class Wired(Controller):
link_detect = property(get_link_detect, set_link_detect)
#def LoadInterfaces(self, dhcp_client, link_tool, flush_tool):
# """ Load the wnettools controls for the wired/wireless interfaces. """
# #self.liface = wnettools.WiredInterface(self.wired_interface, self.debug)
# self.dhcp_client = dhcp_client
# self.link_detect = link_tool
# self.flush_tool = flush_tool
def LoadBackend(self, backend):
""" Load the backend up. """
Controller.LoadBackend(self, backend)
if self._backend:
self.liface = self._backend.WiredInterface(self.wired_interface,
self.debug)
def CheckPluggedIn(self, fast=False):
def CheckPluggedIn(self):
""" Check whether the wired connection is plugged in.
Returns:
The status of the physical connection link.
"""
return self.liface.GetPluggedIn(fast)
return self.liface.GetPluggedIn()
def Connect(self, network, debug=False):
""" Spawn a connection thread to connect to the network.
@@ -804,18 +844,18 @@ class Wired(Controller):
def DetectWiredInterface(self):
""" Attempts to automatically detect a wired interface. """
try:
return wnettools.GetWiredInterfaces()[0]
return BACKEND.GetWiredInterfaces()[0]
except IndexError:
return None
def GetIP(self, fast=False):
def GetIP(self, ifconfig=""):
""" Get the IP of the interface.
Returns:
The IP address of the interface in dotted notation.
"""
return self.liface.GetIP(fast)
return self.liface.GetIP(ifconfig)
def Disconnect(self):
""" Disconnect from the network. """
@@ -903,8 +943,6 @@ class WiredConnectThread(ConnectThread):
liface = self.liface
self.is_connecting = True
#TODO pass is_fast in.
self.is_fast = True
# Run pre-connection script.
self.abort_if_needed()
@@ -936,5 +974,5 @@ class WiredConnectThread(ConnectThread):
self.SetStatus('done')
print 'Connecting thread exiting.'
if self.debug:
print "IP Address is: " + str(liface.GetIP(fast=self.is_fast))
print "IP Address is: " + str(liface.GetIP())
self.is_connecting = False

View File

@@ -27,23 +27,22 @@ import gtk
import gobject
import pango
import wicd.misc
from wicd import misc
from wicd import gui
from wicd.misc import checkboxTextboxToggle, noneToBlankString
daemon = None
wireless = None
wired = None
config = None
language = misc.get_language_list_gui()
class PreferencesDialog(object):
def __init__(self, wTree, dbus):
global daemon, wireless, wired, config
global daemon, wireless, wired
daemon = dbus['daemon']
wireless = dbus['wireless']
wired = dbus['wired']
config = dbus['config']
self.wTree = wTree
self.prep_settings_diag()
self.build_preferences_diag()
@@ -68,7 +67,7 @@ class PreferencesDialog(object):
self.dialog = self.wTree.get_widget("pref_dialog")
self.dialog.set_title(language['preferences'])
size = config.ReadWindowSize("pref")
size = daemon.ReadWindowSize("pref")
width = size[0]
height = size[1]
if width > -1 and height > -1:
@@ -76,7 +75,7 @@ class PreferencesDialog(object):
self.wiredcheckbox = setup_label("pref_always_check",
'wired_always_on')
self.wiredcheckbox.set_active(wired.GetAlwaysShowWiredInterface())
self.wiredcheckbox.set_active(daemon.GetAlwaysShowWiredInterface())
self.reconnectcheckbox = setup_label("pref_auto_check",
'auto_reconnect')
self.reconnectcheckbox.set_active(daemon.GetAutoReconnect())
@@ -181,6 +180,25 @@ class PreferencesDialog(object):
self.dns2Entry.set_sensitive(False)
self.dns3Entry.set_sensitive(False)
# Load backend combobox
self.backendcombo = build_combobox("pref_backend_combobox")
self.backends = daemon.GetBackendList()
# "" is included as a hack for DBus limitations, so we remove it.
self.backends.remove("")
found = False
cur_backend = daemon.GetSavedBackend()
for i, x in enumerate(self.backends):
if x == cur_backend:
found = True
backend_index = i
self.backendcombo.remove_text(i)
self.backendcombo.append_text(x)
if found:
self.backendcombo.set_active(backend_index)
else:
self.backendcombo.set_active(0)
self.wTree.get_widget("notebook2").set_current_page(0)
def run(self):
@@ -199,10 +217,10 @@ class PreferencesDialog(object):
daemon.SetWirelessInterface(self.entryWirelessInterface.get_text())
daemon.SetWiredInterface(self.entryWiredInterface.get_text())
daemon.SetWPADriver(self.wpadrivers[self.wpadrivercombo.get_active()])
wired.SetAlwaysShowWiredInterface(self.wiredcheckbox.get_active())
daemon.SetAlwaysShowWiredInterface(self.wiredcheckbox.get_active())
daemon.SetAutoReconnect(self.reconnectcheckbox.get_active())
daemon.SetDebugMode(self.debugmodecheckbox.get_active())
daemon.SetSignalDisplayType(self.displaytypecheckbox.get_active())
wireless.SetSignalDisplayType(self.displaytypecheckbox.get_active())
if self.showlistradiobutton.get_active():
wired.SetWiredAutoConnectMethod(2)
elif self.lastusedradiobutton.get_active():
@@ -210,6 +228,10 @@ class PreferencesDialog(object):
else:
wired.SetWiredAutoConnectMethod(1)
if self.backends[self.backendcombo.get_active()] != daemon.GetSavedBackend():
gui.alert(self.dialog, language["backend_alert"])
daemon.SetBackend(self.backends[self.backendcombo.get_active()])
# External Programs Tab
if self.dhcpautoradio.get_active():
dhcp_client = misc.AUTO
@@ -238,7 +260,7 @@ class PreferencesDialog(object):
daemon.SetFlushTool(flush_tool)
[width, height] = self.dialog.get_size()
config.WriteWindowSize(width, height, "pref")
daemon.WriteWindowSize(width, height, "pref")
def set_label(self, glade_str, label):
""" Sets the label for the given widget in wicd.glade. """
@@ -252,6 +274,7 @@ class PreferencesDialog(object):
self.wTree.get_widget("dhcp_client_label").set_label(language["dhcp_client"])
self.wTree.get_widget("wired_detect_label").set_label(language["wired_detect"])
self.wTree.get_widget("route_flush_label").set_label(language["route_flush"])
self.wTree.get_widget("pref_backend_label").set_label(language["backend"] + ":")
entryWiredAutoMethod = self.wTree.get_widget("pref_wired_auto_label")
entryWiredAutoMethod.set_label('Wired Autoconnect Setting:')

View File

@@ -42,13 +42,14 @@ import gobject
import getopt
import os
import pango
import time
from dbus import DBusException
from dbus import version as dbus_version
# Wicd specific imports
import wicd.wpath as wpath
import wicd.misc as misc
import wicd.gui as gui
from wicd import wpath
from wicd import misc
from wicd import gui
from wicd.dbusmanager import DBusManager
# Import egg.trayicon if we're using an older gtk version
@@ -78,7 +79,6 @@ daemon = None
wireless = None
wired = None
wired = None
config = None
language = misc.get_language_list_tray()
@@ -203,7 +203,7 @@ class TrayIcon:
if self.animate:
prefix = self.get_bandwidth_state()
else:
prefix = ''
prefix = 'idle-'
if daemon.GetSignalDisplayType() == 0:
if wireless_signal > 75:
signal_img = "high-signal"
@@ -298,7 +298,7 @@ class TrayIcon:
return (active, max_gain, last_bytes)
class TrayIconGUI:
class TrayIconGUI(object):
""" Base Tray Icon UI class.
Implements methods and variables used by both egg/StatusIcon
@@ -336,16 +336,24 @@ class TrayIcon:
props.parent)
self.gui_win = None
self.current_icon_path = None
self.dbus_available = True
self.use_tray = use_tray
self._is_scanning = False
net_menuitem = self.manager.get_widget("/Menubar/Menu/Connect/")
net_menuitem.connect("activate", self.on_net_menu_activate)
def tray_scan_started(self):
""" Callback for when a wireless scan is started. """
self._is_scanning = True
self.init_network_menu()
def tray_scan_ended(self):
""" Callback for when a wireless scan finishes. """
self._is_scanning = False
self.populate_network_menu()
def on_activate(self, data=None):
""" Opens the wicd GUI. """
try:
self.toggle_wicd_gui()
except dbus.DBusException:
self.dbus_available = False
gui.error(None, "Could not connect to wicd daemon. Unable to load GUI")
def on_quit(self, widget=None):
""" Closes the tray icon. """
@@ -361,8 +369,8 @@ class TrayIcon:
dialog.run()
dialog.destroy()
def _add_item_to_menu(self, net_menu, lbl, type_,
n_id, is_connecting, is_active):
def _add_item_to_menu(self, net_menu, lbl, type_, n_id, is_connecting,
is_active):
""" Add an item to the network list submenu. """
def network_selected(widget, net_type, net_id):
""" Callback method for a menu item selection. """
@@ -423,6 +431,29 @@ class TrayIcon:
signal_img = 'signal-25.png'
return wpath.images + signal_img
def on_net_menu_activate(self, item):
""" Trigger a background scan to populate the network menu.
Called when the network submenu is moused over. We
sleep briefly, clear pending gtk events, and if
we're still being moused over we trigger a scan.
This is to prevent scans when the user is just
mousing past the menu to select another menu item.
"""
def dummy(x=None): pass
if self._is_scanning:
return True
self.init_network_menu()
time.sleep(.4)
while gtk.events_pending():
gtk.main_iteration()
if item.state != gtk.STATE_PRELIGHT:
return True
wireless.Scan(reply_handler=dummy, error_handler=dummy)
def populate_network_menu(self, data=None):
""" Populates the network list submenu. """
def get_prop(net_id, prop):
@@ -436,14 +467,14 @@ class TrayIcon:
num_networks = wireless.GetNumberOfNetworks()
[status, info] = daemon.GetConnectionStatus()
if wired.GetAlwaysShowWiredInterface() or \
wired.CheckPluggedIn(True):
if daemon.GetAlwaysShowWiredInterface() or \
wired.CheckPluggedIn():
if status == misc.WIRED:
is_active = True
else:
is_active = False
self._add_item_to_menu(submenu, "Wired Network", "__wired__",
0, is_connecting, is_active)
self._add_item_to_menu(submenu, "Wired Network", "__wired__", 0,
is_connecting, is_active)
sep = gtk.SeparatorMenuItem()
submenu.append(sep)
sep.show()
@@ -457,10 +488,16 @@ class TrayIcon:
is_active = False
self._add_item_to_menu(submenu, essid, "wifi", x,
is_connecting, is_active)
else:
no_nets_item = gtk.MenuItem(language['no_wireless_networks_found'])
no_nets_item.set_sensitive(False)
no_nets_item.show()
submenu.append(no_nets_item)
net_menuitem.show()
def init_network_menu(self):
""" Set the right-click menu for to the scanning state. """
net_menuitem = self.manager.get_widget("/Menubar/Menu/Connect/")
submenu = net_menuitem.get_submenu()
self._clear_menu(submenu)
@@ -469,10 +506,10 @@ class TrayIcon:
loading_item.set_sensitive(False)
loading_item.show()
submenu.append(loading_item)
#net_menuitem.set_submenu(net_menu)
net_menuitem.show()
def _clear_menu(self, menu):
""" Clear the right-click menu. """
for item in menu.get_children():
menu.remove(item)
item.destroy()
@@ -484,10 +521,10 @@ class TrayIcon:
bus = dbus_manager.get_bus()
bus.add_signal_receiver(self.gui_win.dbus_scan_finished,
'SendEndScanSignal',
'org.wicd.daemon')
'org.wicd.daemon.wireless')
bus.add_signal_receiver(self.gui_win.dbus_scan_started,
'SendStartScanSignal',
'org.wicd.daemon')
'org.wicd.daemon.wireless')
bus.add_signal_receiver(self.gui_win.update_connect_buttons,
'StatusChanged', 'org.wicd.daemon')
elif not self.gui_win.is_visible:
@@ -530,7 +567,7 @@ class TrayIcon:
if event.button == 1:
self.toggle_wicd_gui()
elif event.button == 3:
self.populate_network_menu()
self.init_network_menu()
self.menu.popup(None, None, None, event.button, event.time)
def set_from_file(self, val=None):
@@ -574,8 +611,6 @@ class TrayIcon:
def on_popup_menu(self, status, button, timestamp):
""" Opens the right click menu for the tray icon. """
self.init_network_menu()
wireless.Scan(reply_handler=self.populate_network_menu,
error_handler=lambda x: x)
self.menu.popup(None, None, None, button, timestamp)
def set_from_file(self, path = None):
@@ -599,7 +634,7 @@ Arguments:
"""
def setup_dbus():
global bus, daemon, wireless, wired, config, dbus_manager
global bus, daemon, wireless, wired, dbus_manager
dbus_manager = DBusManager()
try:
@@ -617,7 +652,6 @@ def setup_dbus():
daemon = dbus_ifaces['daemon']
wireless = dbus_ifaces['wireless']
wired = dbus_ifaces['wired']
config = dbus_ifaces['config']
return True
def main(argv):
@@ -674,23 +708,13 @@ def main(argv):
'LaunchChooser', 'org.wicd.daemon')
bus.add_signal_receiver(tray_icon.icon_info.update_tray_icon,
'StatusChanged', 'org.wicd.daemon')
bus.add_signal_receiver(tray_icon.tr.tray_scan_ended, 'SendEndScanSignal',
'org.wicd.daemon.wireless')
bus.add_signal_receiver(tray_icon.tr.tray_scan_started,
'SendStartScanSignal', 'org.wicd.daemon.wireless')
print 'Done.'
while 1:
mainloop = gobject.MainLoop()
try:
mainloop.run()
except DBusException:
print 'Warning. Caught a D-Bus exception! Connection to daemon lost.'
print 'Trying to reconnect...'
sleep(10)
try:
setup_dbus()
except:
pass
if __name__ == '__main__':

File diff suppressed because it is too large Load Diff

View File

@@ -31,51 +31,15 @@ class WirelessInterface() -- Control a wireless network interface.
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
import re
import os
import time
import socket
import fcntl
import struct
import array
import re
import wicd.wpath as wpath
import wicd.misc as misc
# Compile the regex patterns that will be used to search the output of iwlist
# scan for info these are well tested, should work on most cards
essid_pattern = re.compile('.*ESSID:"(.*?)"\n', re.I | re.M | re.S)
ap_mac_pattern = re.compile('.*Address: (.*?)\n', re.I | re.M | re.S)
channel_pattern = re.compile('.*Channel:? ?(\d\d?)', re.I | re.M | re.S)
strength_pattern = re.compile('.*Quality:?=? ?(\d+)\s*/?\s*(\d*)', re.I | re.M | re.S)
# These next two look a lot a like, altstrength is for Signal level = xx/100,
# which is just an alternate way of displaying link quality, signaldbm is
# for displaying actual signal strength (-xx dBm).
altstrength_pattern = re.compile('.*Signal level:?=? ?(\d\d*)', re.I | re.M | re.S)
signaldbm_pattern = re.compile('.*Signal level:?=? ?(-\d\d*)', re.I | re.M | re.S)
mode_pattern = re.compile('.*Mode:(.*?)\n', re.I | re.M | re.S)
freq_pattern = re.compile('.*Frequency:(.*?)\n', re.I | re.M | re.S)
ip_pattern = re.compile(r'inet [Aa]d?dr[^.]*:([^.]*\.[^.]*\.[^.]*\.[0-9]*)', re.S)
bssid_pattern = re.compile('.*Access Point: (([0-9A-Z]{2}:){5}[0-9A-Z]{2})', re.I | re.M | re.S)
wep_pattern = re.compile('.*Encryption key:(.*?)\n', re.I | re.M | re.S)
altwpa_pattern = re.compile('(wpa_ie)', re.I | re.M | re.S)
wpa1_pattern = re.compile('(WPA Version 1)', re.I | re.M | re.S)
wpa2_pattern = re.compile('(WPA2)', re.I | re.M | re.S)
# Patterns for wpa_cli output
auth_pattern = re.compile('.*wpa_state=(.*?)\n', re.I | re.M | re.S)
import wpath
import misc
RALINK_DRIVER = 'ralink legacy'
SIOCGIWESSID = 0x8B1B
SIOCGIFADDR = 0x8915
SIOCGIWSTATS = 0x8B0F
SIOCGIFHWADDR = 0x8927
SIOCGMIIPHY = 0x8947
SIOCGETHTOOL = 0x8946
SIOCGIFFLAGS = 0x8913
SIOCGIWRANGE = 0x8B0B
SIOCGIWAP = 0x8B15
def _sanitize_string(string):
blacklist = [';', '`', '$', '!', '*', '|', '>', '<']
@@ -147,42 +111,24 @@ def GetWirelessInterfaces():
dev_dir = '/sys/class/net/'
ifnames = []
ifnames = [iface for iface in os.listdir(dev_dir) if os.path.isdir(dev_dir + iface) \
ifnames = [iface for iface in os.listdir(dev_dir) if os.path.isdir(dev_dir + iface)
and 'wireless' in os.listdir(dev_dir + iface)]
return bool(ifnames) and ifnames[0] or None
def GetWiredInterfaces():
basedir = '/sys/class/net/'
return [iface for iface in os.listdir(basedir) if not 'wireless' \
in os.listdir(basedir + iface) and \
return [iface for iface in os.listdir(basedir) if not 'wireless'
in os.listdir(basedir + iface) and
open(basedir + iface + "/type").readlines()[0].strip() == "1"]
def NeedsExternalCalls():
print ("NeedsExternalCalls: returning default of True. You should " +
"implement this yourself.")
return True
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)
addr, length = buff.buffer_info()
arg = struct.pack('Pi', addr, length)
data = (iface + '\0' * 16)[:16] + arg
try:
result = fcntl.ioctl(s.fileno(), call, data)
except IOError:
return None
except OSError:
return None
return buff.tostring()
class Interface(object):
class BaseInterface(object):
""" Control a network interface. """
def __init__(self, iface, verbose=False):
""" Initialise the object.
@@ -202,8 +148,6 @@ class Interface(object):
self.IP_FOUND = False
self.flush_tool = None
self.link_detect = None
self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
self.Check()
def SetDebugMode(self, value):
""" If True, verbose output is enabled. """
@@ -556,77 +500,28 @@ class Interface(object):
if self.verbose: print cmd
misc.Run(cmd)
def GetIP(self, fast=False):
def GetIP(self, ifconfig=""):
""" Get the IP address of the interface.
Returns:
The IP address of the interface in dotted quad form.
"""
if not self.iface: return False
if fast:
return self._fast_get_ip()
cmd = 'ifconfig ' + self.iface
if self.verbose: print cmd
output = misc.Run(cmd)
return misc.RunRegex(ip_pattern, output)
print 'Implement this in a derived class!'
pass
def _fast_get_ip(self):
""" Gets the IP Address of the interface using ioctl.
Using ioctl calls to get the IP Address info is MUCH faster
than calling ifconfig and paring it's output. It's less
portable though, so there may be problems with it on some
systems.
"""
ifstruct = struct.pack('256s', self.iface)
try:
raw_ip = fcntl.ioctl(self.sock.fileno(), SIOCGIFADDR, ifstruct)
except IOError:
return None
except OSError:
return None
return socket.inet_ntoa(raw_ip[20:24])
def IsUp(self, fast=True):
def IsUp(self):
""" Determines if the interface is up.
Returns:
True if the interface is up, False otherwise.
"""
if not self.iface: return False
if fast:
return self._fast_is_up()
cmd = "ifconfig " + self.iface
output = misc.Run(cmd)
lines = output.split('\n')
if len(lines) < 5:
return False
for line in lines[1:4]:
if line.strip().startswith('UP'):
return True
return False
def _fast_is_up(self):
""" Determines if the interfae is up using an ioctl call. """
data = (self.iface + '\0' * 16)[:18]
try:
result = fcntl.ioctl(self.sock.fileno(), SIOCGIFFLAGS, data)
except IOError, e:
if self.verbose:
print "SIOCGIFFLAGS failed: " + str(e)
return False
flags, = struct.unpack('H', result[16:18])
return bool(flags & 1)
print 'Implement this in a derived class!'
pass
class WiredInterface(Interface):
class BaseWiredInterface(BaseInterface):
""" Control a wired network interface. """
def __init__(self, iface, verbose=False):
""" Initialise the wired network interface class.
@@ -636,9 +531,9 @@ class WiredInterface(Interface):
verbose -- print all commands
"""
Interface.__init__(self, iface, verbose)
BaseInterface.__init__(self, iface, verbose)
def GetPluggedIn(self, fast=False):
def GetPluggedIn(self):
""" Get the current physical connection state.
The method will first attempt to use ethtool do determine
@@ -649,104 +544,11 @@ class WiredInterface(Interface):
True if a link is detected, False otherwise.
"""
if not self.iface: return False
if self.ETHTOOL_FOUND and self.link_detect != misc.MIITOOL:
return self._eth_get_plugged_in(fast)
elif self.MIITOOL_FOUND:
return self._mii_get_plugged_in(fast)
else:
print 'Error: No way of checking for a wired connection. Make \
sure that either mii-tool or ethtool is installed.'
return False
def _eth_get_plugged_in(self, fast):
""" Use ethtool to determine the physical connection state.
Returns:
True if a link is detected, False otherwise.
"""
if fast:
self._fast_eth_get_plugged_in()
link_tool = 'ethtool'
if not self.IsUp():
print 'Wired Interface is down, putting it up'
self.Up()
time.sleep(6)
tool_data = misc.Run(link_tool + ' ' + self.iface, True)
if misc.RunRegex(re.compile('(Link detected: yes)', re.I | re.M |
re.S), tool_data) is not None:
return True
else:
return False
def _fast_eth_get_plugged_in(self):
""" Determines link connection status using an ioctl call.
Uses the SIOCGETHTOOL ioctl call to determine link status.
Returns:
True if a wire is plugged in, False otherwise.
"""
if not self.IsUp():
self.Up()
time.sleep(5)
buff = array.array('i', [0x0000000a, 0x00000000])
addr, length = buff.buffer_info()
arg = struct.pack('Pi', addr, length)
data = (self.iface + '\0' * 16)[:16] + arg
try:
fcntl.ioctl(self.sock.fileno(), SIOCGETHTOOL, data)
except IOError, e:
if self.verbose:
print 'SIOCGETHTOOL failed: ' + str(e)
return False
return bool(buff.tolist()[1])
print 'Implement this in a derived class!'
pass
def _mii_get_plugged_in(self, fast):
""" Use mii-tool to determine the physical connection state.
Returns:
True if a link is detected, False otherwise.
"""
if fast:
return self._fast_mii_get_plugged_in()
link_tool = 'mii-tool'
tool_data = misc.Run(link_tool + ' ' + self.iface, True)
if misc.RunRegex(re.compile('(Invalid argument)', re.I | re.M | re.S),
tool_data) is not None:
print 'Wired Interface is down, putting it up'
self.Up()
time.sleep(4)
tool_data = misc.Run(link_tool + ' ' + self.iface, True)
if misc.RunRegex(re.compile('(link ok)', re.I | re.M | re.S),
tool_data) is not None:
return True
else:
return False
def _fast_mii_get_plugged_in(self):
""" Get link status using the SIOCGMIIPHY ioctl call. """
if not self.IsUp():
self.Up()
time.sleep(2.5)
buff = struct.pack('16shhhh', (self.iface + '\0' * 16)[:16], 0, 1,
0x0004, 0)
try:
result = fcntl.ioctl(self.sock.fileno(), SIOCGMIIPHY, buff)
except IOError, e:
if self.verbose:
print 'SIOCGMIIPHY failed: ' + str(e)
return False
reg = struct.unpack('16shhhh', result)[-1]
return bool(reg & 0x0004)
class WirelessInterface(Interface):
class BaseWirelessInterface(BaseInterface):
""" Control a wireless network interface. """
def __init__(self, iface, verbose=False, wpa_driver='wext'):
""" Initialise the wireless network interface class.
@@ -756,7 +558,7 @@ class WirelessInterface(Interface):
verbose -- print all commands
"""
Interface.__init__(self, iface, verbose)
BaseInterface.__init__(self, iface, verbose)
self.wpa_driver = wpa_driver
self.scan_iface = None
@@ -790,7 +592,7 @@ class WirelessInterface(Interface):
"""
if not self.iface: return False
output = misc.Run("iwconfig " + self.iface)
output = self.GetIwconfig()
killswitch_pattern = re.compile('.*radio off', re.I | re.M | re.S)
if killswitch_pattern.search(output):
@@ -803,43 +605,9 @@ class WirelessInterface(Interface):
def GetIwconfig(self):
""" Returns the output of iwconfig for this interface. """
if not self.iface: return ""
return misc.Run("iwconfig " + self.iface)
def GetNetworks(self):
""" Get a list of available wireless networks.
Returns:
A list containing available wireless networks.
"""
cmd = 'iwlist ' + self.iface + ' scan'
cmd = "iwconfig " + self.iface
if self.verbose: print cmd
results = misc.Run(cmd)
# Split the networks apart, using Cell as our split point
# this way we can look at only one network at a time.
# The spaces around ' Cell ' are to minimize the chance that someone
# has an essid named Cell...
networks = results.split( ' Cell ' )
# Get available network info from iwpriv get_site_survey
# if we're using a ralink card (needed to get encryption info)
if self.wpa_driver == RALINK_DRIVER:
ralink_info = self._GetRalinkInfo()
else:
ralink_info = None
# An array for the access points
access_points = []
for cell in networks:
# Only use sections where there is an ESSID.
if 'ESSID:' in cell:
# Add this network to the list of networks
entry = self._ParseAccessPoint(cell, ralink_info)
if entry is not None:
access_points.append(entry)
return access_points
return misc.Run(cmd)
def _FreqToChannel(self, freq):
""" Translate the specified frequency to a channel.
@@ -880,90 +648,6 @@ class WirelessInterface(Interface):
lines = lines[2:]
return lines
def _ParseAccessPoint(self, cell, ralink_info):
""" Parse a single cell from the output of iwlist.
Keyword arguments:
cell -- string containing the cell information
ralink_info -- string contating network information needed
for ralink cards.
Returns:
A dictionary containing the cell networks properties.
"""
ap = {}
# ESSID - Switch '<hidden>' to 'Hidden' to remove
# brackets that can mix up formatting.
ap['essid'] = misc.RunRegex(essid_pattern, cell)
try:
ap['essid'] = misc.to_unicode(ap['essid'])
except (UnicodeDecodeError, UnicodeEncodeError):
print 'Unicode problem with current network essid, ignoring!!'
return None
if ap['essid'] in ['<hidden>', ""]:
ap['essid'] = 'Hidden'
ap['hidden'] = True
else:
ap['hidden'] = False
# Channel - For cards that don't have a channel number,
# convert the frequency.
ap['channel'] = misc.RunRegex(channel_pattern, cell)
if ap['channel'] == None:
freq = misc.RunRegex(freq_pattern, cell)
ap['channel'] = self._FreqToChannel(freq)
# BSSID
ap['bssid'] = misc.RunRegex(ap_mac_pattern, cell)
# Mode
ap['mode'] = misc.RunRegex(mode_pattern, cell)
# Break off here if we're using a ralink card
if self.wpa_driver == RALINK_DRIVER:
ap = self._ParseRalinkAccessPoint(ap, ralink_info, cell)
elif misc.RunRegex(wep_pattern, cell) == 'on':
# Encryption - Default to WEP
ap['encryption'] = True
ap['encryption_method'] = 'WEP'
if misc.RunRegex(wpa1_pattern, cell) == 'WPA Version 1':
ap['encryption_method'] = 'WPA'
if misc.RunRegex(altwpa_pattern, cell) == 'wpa_ie':
ap['encryption_method'] = 'WPA'
if misc.RunRegex(wpa2_pattern, cell) == 'WPA2':
ap['encryption_method'] = 'WPA2'
else:
ap['encryption'] = False
# Link Quality
# Set strength to -1 if the quality is not found
# more of the patch from
# https://bugs.launchpad.net/wicd/+bug/175104
if (strength_pattern.match(cell)):
[(strength, max_strength)] = strength_pattern.findall(cell)
if max_strength:
ap["quality"] = 100 * int(strength) // int(max_strength)
else:
ap["quality"] = int(strength)
elif misc.RunRegex(altstrength_pattern,cell):
ap['quality'] = misc.RunRegex(altstrength_pattern, cell)
else:
ap['quality'] = -1
# Signal Strength (only used if user doesn't want link
# quality displayed or it isn't found)
if misc.RunRegex(signaldbm_pattern, cell):
ap['strength'] = misc.RunRegex(signaldbm_pattern, cell)
elif self.wpa_driver != RALINK_DRIVER: # This is already set for ralink
ap['strength'] = -1
return ap
def _ParseRalinkAccessPoint(self, ap, ralink_info, cell):
""" Parse encryption and signal strength info for ralink cards
@@ -1101,52 +785,8 @@ class WirelessInterface(Interface):
False otherwise.
"""
# Right now there's no way to do this for ralink drivers
if self.wpa_driver == RALINK_DRIVER or not self.WPA_CLI_FOUND:
return True
MAX_TIME = 15
MAX_DISCONNECTED_TIME = 3
while (time.time() - auth_time) < MAX_TIME:
cmd = 'wpa_cli -i ' + self.iface + ' status'
output = misc.Run(cmd)
result = misc.RunRegex(auth_pattern, output)
if self.verbose:
print 'WPA_CLI RESULT IS', result
if not result:
print "WARNING: Received an unexpected result from wpa_cli!" + \
"\nMake sure you're using the right wpa_supplicant " + \
"driver (you probably want wext).\nIf the problem " + \
"persists, please file a bug report."
return False
if result == "COMPLETED":
return True
elif result == "DISCONNECTED" and \
(time.time() - auth_time) > MAX_DISCONNECTED_TIME:
# Force a rescan to get wpa_supplicant moving again.
self._ForceSupplicantScan()
MAX_TIME += 5
time.sleep(1)
print 'wpa_supplicant authentication may have failed.'
return False
def _ForceSupplicantScan(self):
""" Force wpa_supplicant to rescan available networks.
This function forces wpa_supplicant to rescan.
This works around authentication validation sometimes failing for
wpa_supplicant because it remains in a DISCONNECTED state for
quite a while, after which a rescan is required, and then
attempting to authenticate. This whole process takes a long
time, so we manually speed it up if we see it happening.
"""
print 'wpa_supplicant rescan forced...'
cmd = 'wpa_cli -i' + self.iface + ' scan'
misc.Run(cmd)
print 'Implement this in a derived class!'
pass
def _AuthenticateRalinkLegacy(self, network):
""" Authenticate with the specified wireless network.
@@ -1205,154 +845,38 @@ class WirelessInterface(Interface):
if self.verbose: print cmd
misc.Run(cmd)
def GetBSSID(self, iwconfig="", fast=True):
def GetBSSID(self, iwconfig=None):
""" Get the MAC address for the interface. """
if not self.iface: return ""
if fast:
return self._fast_get_bssid()
else:
if not iwconfig:
cmd = 'iwconfig ' + self.iface
if self.verbose: print cmd
output = misc.Run(cmd)
else:
output = iwconfig
print 'Implement this in a derived class!'
pass
bssid = misc.RunRegex(bssid_pattern, output)
return bssid
def _fast_get_bssid(self):
""" Gets the MAC address for the connected AP using ioctl calls. """
data = (self.iface + '\0' * 32)[:32]
try:
result = fcntl.ioctl(self.sock.fileno(), SIOCGIWAP, data)[16:]
except IOError, e:
if self.verbose:
print "SIOCGIWAP failed: " + str(e)
return ""
raw_addr = struct.unpack("xxBBBBBB", result[:8])
return "%02X:%02X:%02X:%02X:%02X:%02X" % raw_addr
def GetSignalStrength(self, iwconfig=None, fast=False):
def GetSignalStrength(self, iwconfig=None):
""" Get the signal strength of the current network.
Returns:
The signal strength.
"""
if not self.iface: return -1
if fast:
return self._get_signal_strength_fast()
print 'Implement this in a derived class!'
pass
if not iwconfig:
cmd = 'iwconfig ' + self.iface
if self.verbose: print cmd
output = misc.Run(cmd)
else:
output = iwconfig
[(strength, max_strength)] = strength_pattern.findall(output)
if max_strength and strength:
return 100 * int(strength) // int(max_strength)
if strength is None:
strength = misc.RunRegex(altstrength_pattern, output)
return strength
def _get_signal_strength_fast(self):
""" Get the link quality using ioctl calls. """
buff = get_iw_ioctl_result(self.iface, SIOCGIWSTATS)
strength = ord(buff[2])
max_strength = self._get_max_strength_fast()
if strength and max_strength:
return 100 * int(strength) // int(max_strength)
return strength
def _get_max_strength_fast(self):
""" Gets the maximum possible strength from the wireless driver. """
buff = array.array('c', '\0' * 700)
addr, length = buff.buffer_info()
arg = struct.pack('Pi', addr, length)
iwfreq = (self.iface + '\0' * 16)[:16] + arg
try:
result = fcntl.ioctl(self.sock.fileno(), SIOCGIWRANGE, iwfreq)
except IOError, e:
if self.verbose:
print "SIOCGIWRANGE failed: " + str(e)
return None
# This defines the iwfreq struct, used to get signal strength.
fmt = "iiihb6ii4B4Bi32i2i2i2i2i3h8h2b2bhi8i2b3h2i2ihB17x" + 32 * "ihbb"
size = struct.calcsize(fmt)
data = buff.tostring()
data = data[0:size]
values = struct.unpack(fmt, data)
return values[12]
def GetDBMStrength(self, iwconfig=None, fast=False):
def GetDBMStrength(self, iwconfig=None):
""" Get the dBm signal strength of the current network.
Returns:
The dBm signal strength.
"""
if not self.iface: return -100
if fast:
return self._get_dbm_strength_fast()
if iwconfig:
cmd = 'iwconfig ' + self.iface
if self.verbose: print cmd
output = misc.Run(cmd)
else:
output = iwconfig
dbm_strength = misc.RunRegex(signaldbm_pattern, output)
return dbm_strength
print 'Implement this in a derived class!'
pass
def _get_dbm_strength_fast(self):
""" Uses the SIOCGIWSTATS ioctl call to get dbm signal strength.
Returns:
The dBm signal strength or None if it can't be found.
"""
buff = misc.get_irwange_ioctl_result(self.iface, SIOCGIWSTATS)
if not buff:
return None
return str((ord(buff[3]) - 256))
def GetCurrentNetwork(self, iwconfig=None, fast=False):
def GetCurrentNetwork(self, iwconfig=None):
""" Get the essid of the current network.
Returns:
The current network essid.
"""
if not self.iface: return ""
if fast:
return self._get_essid_fast()
if not iwconfig:
cmd = 'iwconfig ' + self.iface
if self.verbose: print cmd
output = misc.Run(cmd)
else:
output = iwconfig
network = misc.RunRegex(re.compile('.*ESSID:"(.*?)"',
re.I | re.M | re.S), output)
if network:
network = misc.to_unicode(network)
return network
def _get_essid_fast(self):
""" Get the current essid using ioctl. """
buff = get_iw_ioctl_result(self.iface, SIOCGIWESSID)
if not buff:
return None
return buff.strip('\x00')
print 'Implement this in a derived class!'
pass

View File

@@ -12,13 +12,49 @@ current = os.path.dirname(os.path.realpath(__file__)) + '/'
# These paths can easily be modified to handle system wide installs, or
# they can be left as is if all files remain with the source directory
# layout.
lib = current
images = lib + 'images/'
encryption = lib + 'encryption/templates/'
bin = current
etc = current + 'data/'
networks = lib + 'encryption/configurations/'
log = current + 'data/'
# These paths are replaced when setup.py configure is run
# All of these paths *MUST* end in a /
# except the python one, of course as it is an executable
lib = '/usr/lib/wicd/'
share = '/usr/share/wicd/'
etc = '/etc/wicd/'
images = '/usr/share/pixmaps/wicd/'
encryption = '/etc/wicd/encryption/templates/'
bin = '/usr/bin/'
networks = '/var/lib/wicd/configurations/'
log = '/var/log/wicd/'
backends = '/usr/lib/wicd/backends/'
# other, less useful entries
resume = '/etc/acpi/resume.d/'
suspend = '/etc/acpi/suspend.d/'
sbin = '/usr/sbin/'
dbus = '/etc/dbus-1/system.d/'
desktop = '/usr/share/applications/'
translations = '/usr/share/locale/'
icons = '/usr/share/icons/hicolor/'
autostart = '/etc/xdg/autostart/'
init = '/etc/init.d/'
docdir = '/usr/share/doc/wicd/'
mandir = '/usr/share/man/'
kdedir = '/usr/share/autostart/'
python = '/usr/bin/python'
pidfile = '/var/run/wicd/wicd.pid'
# stores something like other/wicd
# really only used in the install
initfile = 'init/debian/wicd'
# stores only the file name, i.e. wicd
initfilename = 'wicd'
no_install_init = False
no_install_man = False
no_install_kde = False
no_install_acpi = False
no_install_install = False
no_install_license = False
def chdir(file):
"""Change directory to the location of the specified file.