1
0
mirror of https://github.com/gryf/wicd.git synced 2025-12-21 21:38:06 +01:00

Fixed crash bug in script configuration dialog when a network doesn't have script options written in the config file yet.

Refactored networking.py to not have to create a new wnettools interface every time a method gets called.  Now it reuses the same one and makes changes to the iface name/driver as needed.
Refactored a few methods in wnettools.py to be organized more logically and reduce external program calls.
In experimental branch, added a few methods to networking/wnettools that can be used for enabling/disabling interfaces, as well as unloading/loading the driver associated with an interface.
Added a check for mii-tool/ethtool that gets run when wicd starts, so it can decide which to use to check for a wired connection.
Added a check for ip, to decide how to flush the routing tables.
Rewrote some of the DHCP client checking code.
Added a method (that's currently unused) to release a dhcp lease for each of the supported clients.
This commit is contained in:
imdano
2008-02-29 14:16:21 +00:00
parent 1b6108ce03
commit 3986ddd4fb
7 changed files with 257 additions and 80 deletions

View File

@@ -83,6 +83,12 @@ def blank_to_none(text):
else:
return str(text)
def get_val(con, network, val, default="None"):
if not con.has_option(network, val):
con.set(network, val, default)
return con.get(network, val)
def get_script_info(network, network_type):
""" Read script info from disk and load it into the configuration dialog """
info = {}
@@ -90,17 +96,16 @@ def get_script_info(network, network_type):
if network_type == "wired":
con.read(wired_conf)
if con.has_section(network):
info["pre_entry"] = con.get(network, "beforescript")
info["post_entry"] = con.get(network, "afterscript")
info["disconnect_entry"] = con.get(network, "disconnectscript")
info["pre_entry"] = get_val(con, network, "beforescript")
info["post_entry"] = get_val(con, network, "afterscript")
info["disconnect_entry"] = get_val(con, network, "disconnectscript")
else:
bssid = wireless.GetWirelessProperty(int(network), "bssid")
con.read(wireless_conf)
if con.has_section(bssid):
info["pre_entry"] = con.get(bssid, "beforescript")
info["post_entry"] = con.get(bssid, "afterscript")
info["disconnect_entry"] = con.get(bssid, "disconnectscript")
info["pre_entry"] = get_val(con, bssid, "beforescript")
info["post_entry"] = get_val(con, bssid, "afterscript")
info["disconnect_entry"] = get_val(con, bssid, "disconnectscript")
return info
def write_scripts(network, network_type, script_info):

View File

@@ -45,6 +45,7 @@ import dbus
import dbus.service
if getattr(dbus, 'version', (0, 0, 0)) >= (0, 41, 0):
import dbus.glib
# wicd specific libraries
import wpath
import networking
@@ -176,7 +177,7 @@ class ConnectionWizard(dbus.service.Object):
This number is major-minor-micro. Major is only incremented if minor
reaches > 9. Minor is incremented if changes that break core stucture
are implemented. Micro is for everything else, and micro may be
anything >= 0. This number is effective starting wicd v1.2.0
anything >= 0. This number is effective starting wicd v1.2.0.
"""
version = '1.5.0'

13
misc.py
View File

@@ -167,8 +167,9 @@ def ParseEncryption(network):
x = x.replace("$_" + str(t).upper(), str(network[t]))
z = z + "\n" + x
y += 1
# Write the data to the files
# then chmod them so they can't be read by normal users
# Write the data to the files then chmod them so they can't be read
# by normal users.
file = open(wpath.networks + network["bssid"].replace(":", "").lower(),
"w")
os.chmod(wpath.networks + network["bssid"].replace(":", "").lower(), 0600)
@@ -207,14 +208,14 @@ def LoadEncryptionMethods():
index = -1
for current in requiredFields:
# The pretty names will start with an * so we can
# seperate them with that
# separate them with that.
if current[0] == "*":
# Make underscores spaces
# and remove the *
encryptionTypes[typeID][2][index][0] = current.replace("_",
" ").lstrip("*")
else:
# Add to the list of things that are required
# Add to the list of things that are required.
index = len(encryptionTypes[typeID][2])
encryptionTypes[typeID][2][index] = {}
encryptionTypes[typeID][2][index][1] = current
@@ -252,7 +253,6 @@ def get_gettext():
_ = lang.gettext
return _
def to_unicode(x):
""" Attempts to convert a string to unicode """
try: # This may never fail, but let's be safe
@@ -275,7 +275,8 @@ def error(parent, message):
dialog.run()
dialog.destroy()
class LogWriter():
class LogWriter:
""" A class to provide timestamped logging. """
def __init__(self):
self.file = open(wpath.log + 'wicd.log','a')

View File

@@ -36,9 +36,9 @@ class WiredConnectThread() -- Connection thread for wired
#
#
# Much thanks to wieman01 for help and support with various types of encyption
# Much thanks to wieman01 for help and support with various types of encyption.
# Also thanks to foxy123, yopnono, and the many others who reported bugs helped
# and helped keep this project moving
# and helped keep this project moving.
#
import re
@@ -63,6 +63,8 @@ class Controller(object):
after_script = None
disconnect_script = None
driver = None
wiface = None
liface = None
def __init__(self):
""" Initialise the class. """
@@ -70,6 +72,25 @@ class Controller(object):
self.global_dns_2 = None
self.global_dns_3 = None
def SetWiface(self, iface):
self.wiface.SetInterface(iface)
def SetLiface(self, iface):
self.liface.SetInterface(iface)
def __setattr__(self, attr, value):
if attr == 'wireless_interface':
object.__setattr__(self, attr, value)
if self.wiface:
self.SetWiface(value)
print 'hmm', self.wireless_interface
elif attr == 'wired_interface':
object.__setattr__(self, attr, value)
if self.liface:
self.SetLiface(value)
else:
object.__setattr__(self, attr, value)
class ConnectThread(threading.Thread):
""" A class to perform network connections in a multi-threaded way.
@@ -168,6 +189,21 @@ class Wireless(Controller):
""" Initialise the class. """
Controller.__init__(self)
self.wpa_driver = None
self.wiface = wnettools.WirelessInterface(self.wireless_interface,
self.wpa_driver)
def __setattr__(self, attr, value):
if attr == 'wpa_driver':
self.__dict__[attr] = value
if self.wiface:
self.SetWPADriver(value)
else:
object.__setattr__(self, attr, value)
def LoadInterfaces(self):
""" Load the wnettools controls for the wired/wireless interfaces. """
self.wiface = wnettools.WirelessInterface(self.wireless_interface,
self.wpa_driver)
def Scan(self, essid=None):
""" Scan for available wireless networks.
@@ -179,8 +215,7 @@ class Wireless(Controller):
A list of available networks sorted by strength.
"""
wiface = wnettools.WirelessInterface(self.wireless_interface,
self.wpa_driver)
wiface = self.wiface
# Prepare the interface for scanning
wiface.Up()
@@ -193,7 +228,7 @@ class Wireless(Controller):
wiface.SetEssid(essid)
aps = wiface.GetNetworks()
print aps
#print aps
aps.sort(key=lambda x: x['strength'])
return aps
@@ -219,9 +254,7 @@ class Wireless(Controller):
The current signal strength.
"""
wiface = wnettools.WirelessInterface(self.wireless_interface,
self.wpa_driver)
return wiface.GetSignalStrength(iwconfig)
return self.wiface.GetSignalStrength(iwconfig)
def GetDBMStrength(self, iwconfig=None):
""" Get the dBm signal strength of the current network.
@@ -230,9 +263,7 @@ class Wireless(Controller):
The current dBm signal strength.
"""
wiface = wnettools.WirelessInterface(self.wireless_interface,
self.wpa_driver)
return wiface.GetDBMStrength(iwconfig)
return self.wiface.GetDBMStrength(iwconfig)
def GetCurrentNetwork(self, iwconfig=None):
""" Get current network name.
@@ -241,9 +272,7 @@ class Wireless(Controller):
The name of the currently connected network.
"""
wiface = wnettools.WirelessInterface(self.wireless_interface,
self.wpa_driver)
return wiface.GetCurrentNetwork(iwconfig)
return self.wiface.GetCurrentNetwork(iwconfig)
def GetIP(self):
""" Get the IP of the interface.
@@ -252,15 +281,11 @@ class Wireless(Controller):
The IP address of the interface in dotted notation.
"""
wiface = wnettools.WirelessInterface(self.wireless_interface,
self.wpa_driver)
return wiface.GetIP()
return self.wiface.GetIP()
def GetIwconfig(self):
""" Get the out of iwconfig. """
wiface = wnettools.WirelessInterface(self.wireless_interface,
self.wpa_driver)
return wiface.GetIwconfig()
return self.wiface.GetIwconfig()
def CreateAdHocNetwork(self, essid, channel, ip, enctype, key,
enc_used, ics):
@@ -276,8 +301,7 @@ class Wireless(Controller):
ics -- enable internet connection sharing
"""
wiface = wnettools.WirelessInterface(self.wireless_interface,
self.wpa_driver)
wiface = self.wiface
print 'Creating ad-hoc network'
print 'Killing dhclient and wpa_supplicant'
wiface.StopDHCP()
@@ -288,7 +312,7 @@ class Wireless(Controller):
wiface.SetMode('ad-hoc')
wiface.SetChannel(channel)
wiface.SetEssid(essid)
#Right now it just assumes you're using WEP
# Right now it just assumes you're using WEP
if enc_used:
print 'Setting encryption key'
wiface.SetKey(key)
@@ -332,14 +356,11 @@ class Wireless(Controller):
return wnettools.GetWirelessInterfaces()
def GetKillSwitchStatus(self):
wiface = wnettools.WirelessInterface(self.wireless_interface,
self.wpa_driver)
return wiface.GetKillSwitchStatus()
return self.wiface.GetKillSwitchStatus()
def Disconnect(self):
""" Disconnect from the network. """
wiface = wnettools.WirelessInterface(self.wireless_interface,
self.wpa_driver)
wiface = self.wiface
if self.disconnect_script != None:
print 'Running wireless network disconnect script'
misc.ExecuteScript(self.disconnect_script)
@@ -348,6 +369,16 @@ class Wireless(Controller):
wiface.Down()
wiface.Up()
def SetDriver(self):
self.driver = self.GetDriverName()
def GetDriverName(self):
""" Gets the driver associated with the wireless interface. """
return self.wiface.GetDriverName()
def SetWPADriver(self, driver):
self.wiface.SetWpaDriver(driver)
class WirelessConnectThread(ConnectThread):
""" A thread class to perform the connection to a wireless network.
@@ -425,10 +456,9 @@ class WirelessConnectThread(ConnectThread):
wiface.SetAddress('0.0.0.0')
liface.SetAddress('0.0.0.0')
print 'Stopping wpa_supplicant, dhclient, dhclient3'
wiface.StopDHCP()
print 'Stopping wpa_supplicant, and any running dhcp clients'
wiface.StopWPA()
liface.StopDHCP()
wnettools.StopDHCP()
if self.should_die:
wiface.Up()
@@ -561,6 +591,14 @@ class Wired(Controller):
""" Initialise the class. """
Controller.__init__(self)
self.wpa_driver = None
self.liface = wnettools.WiredInterface(self.wired_interface)
def __setattr__(self, attr, val):
object.__setattr__(self, attr, val)
def LoadInterfaces(self):
""" Load the wnettools controls for the wired/wireless interfaces. """
self.liface = wnettools.WiredInterface(self.wired_interface)
def CheckPluggedIn(self):
""" Check whether the wired connection is plugged in.
@@ -569,8 +607,7 @@ class Wired(Controller):
The status of the physical connection link.
"""
liface = wnettools.WiredInterface(self.wired_interface)
return liface.GetPluggedIn()
return self.liface.GetPluggedIn()
def Connect(self, network):
""" Spawn a connection thread to connect to the network.
@@ -594,12 +631,11 @@ class Wired(Controller):
The IP address of the interface in dotted notation.
"""
liface = wnettools.WiredInterface(self.wired_interface)
return liface.GetIP()
return self.liface.GetIP()
def Disconnect(self):
""" Disconnect from the network. """
liface = wnettools.WiredInterface(self.wired_interface)
liface = self.liface
if self.disconnect_script != None:
print 'Running wired disconnect script'
misc.Run(self.disconnect_script)
@@ -608,6 +644,25 @@ class Wired(Controller):
liface.Down()
liface.Up()
def SetDriver(self):
self.driver = self.GetDriverName()
def GetDriverName(self):
""" Get the driver associated with the wired interface. """
return self.liface.GetDriverName()
def LoadDriver(self):
return self.liface.LoadDriver(self.driver)
def UnloadDriver(self):
return self.liface.UnloadDriver(self.driver)
def EnableInterface(self):
return self.liface.Up()
def DisableInterface(self):
return self.liface.Down()
class WiredConnectThread(ConnectThread):
""" A thread class to perform the connection to a wired network.
@@ -680,10 +735,9 @@ class WiredConnectThread(ConnectThread):
wiface.SetAddress('0.0.0.0')
liface.SetAddress('0.0.0.0')
print 'Stopping wpa_supplicant, dhclient, dhclient3'
wiface.StopDHCP()
print 'Stopping wpa_supplicant, and any dhcp clients'
wiface.StopWPA()
liface.StopDHCP()
wnettools.StopDHCP()
if self.should_die:
liface.Up()

View File

@@ -32,5 +32,7 @@ proxy_obj = bus.get_object('org.wicd.daemon', '/org/wicd/daemon')
daemon = dbus.Interface(proxy_obj, 'org.wicd.daemon')
if __name__ == '__main__':
daemon.Disconnect()
daemon.SetForcedDisconnect(False)
daemon.SetSuspend(True)

View File

@@ -376,7 +376,7 @@ class TrayIcon():
def usage():
""" Print usage information. """
print """
wicd 1.40
wicd 1.50
wireless (and wired) connection daemon front-end.
Arguments:

View File

@@ -99,6 +99,11 @@ def GetDefaultGateway():
gateway = None
return gateway
def StopDHCP():
""" Stop the DHCP client. """
cmd = 'killall dhclient dhclient3 pump dhcpcd-bin'
misc.Run(cmd)
def GetWirelessInterfaces():
""" Get available wireless interfaces.
@@ -122,38 +127,124 @@ class Interface(object):
"""
self.iface = iface
self.verbose = verbose
self.Check()
def SetInterface(self, iface):
""" Sets the interface. """
self.iface = iface
def CheckDHCP(self):
""" Check that all required tools are available. """
# TODO: Implement this function.
# THINGS TO CHECK FOR: ethtool, pptp-linux, dhclient, host
dhcpclients = ["dhclient", "dhcpcd", "pump -i"]
dhcpclients = ["dhclient", "dhcpcd", "pump"]
for client in dhcpclients:
if misc.Run("which " + client.split()[0]):
if misc.Run("which " + client):
DHCP_CLIENT = client
break
if not DHCP_CLIENT:
print "WARNING: NO DHCP CLIENT DETECTED!"
print "WARNING: NO DHCP CLIENT DETECTED! Make sure there is one \
set in your path."
return
elif DHCP_CLIENT == "dhclient":
DHCP_CMD = "dhclient"
DHCP_RELEASE = "dhclient -r"
elif DHCP_CLIENT == "pump":
DHCP_CMD = "pump -i"
DHCP_RELEASE = "pump -r -i"
elif DHCP_CLIENT == "dhcpcd":
DHCP_CMD = "dhcpcd"
DHCP_RELEASE = "dhcpcd -r"
self.DHCP_CMD = DHCP_CMD
self.DHCP_RELEASE = DHCP_RELEASE
self.DHCP_CLIENT = DHCP_CLIENT
def CheckWiredTools(self):
""" Check for the existence of ethtool and mii-tool. """
if misc.Run("which mii-tool"):
self.MIITOOL_FOUND = True
else:
self.MIITOOL_FOUND = False
if misc.Run("which ethtool"):
self.ETHTOOL_FOUND = True
else:
self.ETHTOOL_FOUND = False
def Check(self):
""" Check that all required tools are available."""
# TODO: Implement this function.
# THINGS TO CHECK FOR: ethtool, pptp-linux, dhclient, host
pass
self.CheckDHCP()
self.CheckWiredTools()
if misc.Run("which ip"):
self.IP_FOUND = True
else:
self.IP_FOUND = False
def Up(self):
""" Bring the network interface up. """
cmd = 'ifconfig ' + self.iface + ' up'
if self.verbose: print cmd
misc.Run(cmd)
return True
def Down(self):
""" Take down the network interface. """
cmd = 'ifconfig ' + self.iface + ' down'
if self.verbose: print cmd
misc.Run(cmd)
return True
def GetDriverName(self):
""" Determine the driver name for the interface.
Attempt to use ethtool to get the driver associated with a given
interface. If ethtool is not installed or ethtool fails to provide
a driver, None is returned.
"""
if self.ETHTOOL_FOUND:
cmd = 'ethtool -i ' + self.iface
driver_pattern = re.compile('.*driver: (.*?)\n', re.I | re.M |
re.S)
driver_name = misc.RunRegex(driver_pattern, misc.Run(cmd))
if not driver_name or not self.ETHTOOL_FOUND:
print ("Could not determine driver name for iface " + self.iface +
" Is ethtool installed?")
return driver_name
def LoadDriver(self, driver):
""" Enables the interface by loading the module given by driver. """
if not driver:
print 'Error: No driver associated with this interface.'
return False
cmd = "modprobe " + driver
if self.verbose: print cmd
output = misc.Run(cmd, True, True)
out = output.readlines()
if out and out[0].startswith("FATAL"):
print "Could not enable Interface: " + out[0]
return False
return True
def UnloadDriver(self, driver):
""" Disables the interface by removing the module given by driver """
if not driver:
print 'Error: No driver associated with this interface.'
return False
cmd = "modprobe -r " + driver
if self.verbose: print cmd
output = misc.Run(cmd, True, True)
out = output.readlines()
if out and out[0].startswith("FATAL"):
print "Could not enable Interface: " + out[0]
return False
return True
def SetAddress(self, ip=None, netmask=None, broadcast=None):
""" Set the IP addresses of an interface.
@@ -253,29 +344,29 @@ class Interface(object):
def StartDHCP(self):
""" Start the DHCP client to obtain an IP address. """
self.CheckDHCP()
DHCP_CLIENT = self.DHCP_CLIENT
cmd = DHCP_CLIENT + " " + self.iface
cmd = self.DHCP_CMD + " " + self.iface
if self.verbose: print cmd
pipe = misc.Run(cmd, include_stderr=True, return_pipe=True)
DHCP_CLIENT = self.DHCP_CLIENT
if DHCP_CLIENT == "dhclient":
return self._parse_dhclient(pipe)
elif DHCP_CLIENT == "pump -i":
elif DHCP_CLIENT == "pump":
return self._parse_pump(pipe)
elif DHCP_CLIENT == "dhcpcd":
return self._parse_dhcpcd(pipe)
def StopDHCP(self):
""" Stop the DHCP client. """
cmd = 'killall dhclient dhclient3 pump dhcpcd-bin'
if self.verbose: print cmd
def ReleaseDHCP(self):
""" Release the DHCP lease for this interface. """
cmd = self.DHCP_RELEASE + " " + self.iface
misc.Run(cmd)
def FlushRoutes(self):
""" Flush all network routes. """
cmd = 'ip route flush dev ' + self.iface
if self.IP_FOUND:
cmd = "ip route flush dev " + self.iface
else:
cmd = 'route del dev ' + self.iface
if self.verbose: print cmd
misc.Run(cmd)
@@ -323,21 +414,40 @@ class WiredInterface(Interface):
mii-tool will be used instead.
"""
if self.ETHTOOL_FOUND:
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):
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('(Operation not supported|\
ethtool: command not found)', re.I),
tool_data) is not None:
print "ethtool check failed, falling back to mii-tool"
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):
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 detected: yes|link ok)',
re.I | re.M | re.S), tool_data) is not None:
if misc.RunRegex(re.compile('(link ok)', re.I | re.M | re.S),
tool_data) is not None:
return True
else:
return False
@@ -370,6 +480,10 @@ class WirelessInterface(Interface):
Interface.__init__(self, iface, verbose)
self.wpa_driver = wpa_driver
def SetWpaDriver(self, driver):
""" Sets the wpa_driver. """
self.wpa_driver = driver
def SetEssid(self, essid):
""" Set the essid of the wireless interface.