2
# -*- coding: utf-8 -*-
4
""" networking - Provides wrappers for common network operations
6
This module provides wrappers of the common network tasks as well as
7
threads to perform the actual connecting to networks.
9
class Controller() -- Parent class to Wireless and Wired
10
class ConnectThread() -- Parent class to WirelessConnectThread and
12
class Wireless() -- Wrapper for various wireless functions
13
class Wired() -- Wrapper for various wired functions
14
class WirelessConnectThread() -- Connection thread for wireless
16
class WiredConnectThread() -- Connection thread for wired
22
# Copyright (C) 2007 - 2009 Adam Blackburn
23
# Copyright (C) 2007 - 2009 Dan O'Reilly
24
# Copyright (C) 2007 - 2009 Byron Hillis
25
# Copyright (C) 2009 Andrew Psaltis
27
# This program is free software; you can redistribute it and/or modify
28
# it under the terms of the GNU General Public License Version 2 as
29
# published by the Free Software Foundation.
31
# This program is distributed in the hope that it will be useful,
32
# but WITHOUT ANY WARRANTY; without even the implied warranty of
33
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
34
# GNU General Public License for more details.
36
# You should have received a copy of the GNU General Public License
37
# along with this program. If not, see <http://www.gnu.org/licenses/>.
41
# Much thanks to wieman01 for help and support with various types of encyption.
42
# Also thanks to foxy123, yopnono, and the many others who reported bugs helped
43
# and helped keep this project moving.
50
from signal import SIGTERM
55
from backend import BackendManager
57
if __name__ == '__main__':
61
BACKEND_MGR = BackendManager()
64
""" Mark a method in a ConnectionThread as abortable.
66
This decorator runs a check that will abort the connection thread
67
if necessary before running a given method.
70
def wrapper(self, *__args, **__kargs):
71
self.abort_if_needed()
72
return func(self, *__args, **__kargs)
74
wrapper.__name__ = func.__name__
75
wrapper.__dict__ = func.__dict__
76
wrapper.__doc__ = func.__doc__
77
wrapper.__module = func.__module__
80
def get_backend_list():
81
""" Returns a list of available backends. """
83
return BACKEND_MGR.get_available_backends()
87
def get_backend_update_interval():
88
""" Returns the suggested connection status update interval. """
90
return BACKEND_MGR.get_update_interval()
92
return 5 # Seconds, this should never happen though.
94
def get_current_backend():
95
""" Returns the current backend instance. """
97
return BACKEND_MGR.get_current_backend()
101
def get_backend_description(backend_name):
102
""" Returns the description of the currently loaded backend. """
103
return BACKEND_MGR.get_backend_description(backend_name)
105
def get_backend_description_dict():
106
""" Returns a dict of all available backend descriptions. """
108
for be in get_backend_list():
110
d[be] = get_backend_description(be)
113
def expand_script_macros(script, msg, bssid, essid):
114
"""Expands any supported macros in a script.
117
script -- the script to execute.
118
msg -- the name of the script, %{script} will be expanded to this.
119
bssid -- the bssid of the network we connect to, defaults to 'wired'.
120
essid -- the essid of the network we connect to, defaults to 'wired'.
124
macro = match.group(1).lower()
125
if macro_dict.has_key(macro):
126
return macro_dict[macro]
127
print 'Warning: found illegal macro %s in %s script' % (macro, msg)
130
macro_dict = { 'script' : msg,
133
regex = re.compile(r'%\{([a-zA-Z0-9]+)\}')
134
expanded = regex.sub(repl, script)
135
print "Expanded '%s' to '%s'" % (script, expanded)
139
class Controller(object):
140
""" Parent class for the different interface types. """
141
def __init__(self, debug=False):
142
""" Initialise the class. """
143
self.global_dns_1 = None
144
self.global_dns_2 = None
145
self.global_dns_3 = None
146
self.global_dns_dom = None
147
self.global_search_dom = None
148
self._dhcp_client = None
149
self._flush_tool = None
152
self.connecting_thread = None
153
self.before_script = None
154
self.after_script = None
155
self.pre_disconnect_script = None
156
self.post_disconnect_script = None
160
def get_debug(self): return self._debug
161
def set_debug(self, value):
164
self.iface.SetDebugMode(value)
165
debug = property(get_debug, set_debug)
167
def set_dhcp_client(self, value):
168
self._dhcp_client = value
170
self.iface.DHCP_CLIENT = value
171
def get_dhcp_client(self): return self._dhcp_client
172
dhcp_client = property(get_dhcp_client, set_dhcp_client)
174
def set_flush_tool(self, value):
175
self._flush_tool = value
177
self.iface.flush_tool = value
178
def get_flush_tool(self): return self._flush_tool
179
flush_tool = property(get_flush_tool, set_flush_tool)
181
def LoadBackend(self, backend_name):
182
""" Load the given networking backend. """
184
if backend_name == self._backend:
186
self._backend = BACKEND_MGR.load_backend(backend_name)
187
BACKEND = self._backend
189
def NeedsExternalCalls(self):
190
""" Returns true if the loaded backend needs external calls. """
192
return self._backend.NeedsExternalCalls()
196
def GetIP(self, ifconfig=""):
197
""" Get the IP of the interface.
200
The IP address of the interface in dotted notation.
203
return self.iface.GetIP(ifconfig)
205
def Disconnect(self, nettype, name, mac):
206
""" Disconnect from the network. """
208
# mac and name need to be strings
209
if mac in (None, ''):
211
if name in (None, ''):
213
misc.ExecuteScripts(wpath.predisconnectscripts, self.debug,
214
extra_parameters=(nettype, name, mac))
215
if self.pre_disconnect_script:
216
print 'Running pre-disconnect script'
217
misc.ExecuteScript(expand_script_macros(self.pre_disconnect_script,
222
iface.SetAddress('0.0.0.0')
226
misc.ExecuteScripts(wpath.postdisconnectscripts, self.debug,
227
extra_parameters=(nettype, name, mac))
228
if self.post_disconnect_script:
229
print 'Running post-disconnect script'
230
misc.ExecuteScript(expand_script_macros(self.post_disconnect_script,
231
'post-disconnection',
235
def ReleaseDHCP(self):
236
""" Release the DHCP lease for this interface. """
237
return self.iface.ReleaseDHCP()
240
""" Kill the managed DHCP client if its in a connecting state. """
241
print 'running kill dhcp.'
242
if (self.connecting_thread.is_connecting and
243
self.iface.dhcp_object):
244
if self.iface.dhcp_object.poll() is None:
245
os.kill(self.iface.dhcp_object.pid, SIGTERM)
246
self.iface.dhcp_object = None
249
""" Calls the IsUp method for the wired interface.
252
True if the interface is up, False otherwise.
255
return self.iface.IsUp()
257
def EnableInterface(self):
258
""" Puts the interface up.
261
True if the interface was put up succesfully, False otherwise.
264
return self.iface.Up()
266
def DisableInterface(self):
267
""" Puts the interface down.
270
True if the interface was put down succesfully, False otherwise.
273
return self.iface.Down()
275
def AppAvailable(self, app):
276
""" Determine if the given application is installed. """
277
return self.iface.AppAvailable(app)
280
class ConnectThread(threading.Thread):
281
""" A class to perform network connections in a multi-threaded way.
283
Useless on it's own, this class provides the generic functions
284
necessary for connecting using a separate thread.
290
lock = threading.Lock()
292
def __init__(self, network, interface_name, before_script, after_script,
293
pre_disconnect_script, post_disconnect_script, gdns1,
294
gdns2, gdns3, gdns_dom, gsearch_dom, iface,
296
""" Initialise the required object variables and the thread.
299
network -- the network to connect to
300
wireless -- name of the wireless interface
301
wired -- name of the wired interface
302
before_script -- script to run before bringing up the interface
303
after_script -- script to run after bringing up the interface
304
pre_disconnect_script -- script to run before disconnection
305
post_disconnect_script -- script to run after disconnection
306
gdns1 -- global DNS server 1
307
gdns2 -- global DNS server 2
308
gdns3 -- global DNS server 3
309
debug -- debug mode status
312
threading.Thread.__init__(self)
313
self.network = network
314
self.is_connecting = False
315
self.is_aborted = False
316
self.connect_result = None
317
self.before_script = before_script
318
self.after_script = after_script
319
self.pre_disconnect_script = pre_disconnect_script
320
self.post_disconnect_script = post_disconnect_script
321
self._should_die = False
322
self.abort_reason = ""
323
self.connect_result = ""
325
self.global_dns_1 = gdns1
326
self.global_dns_2 = gdns2
327
self.global_dns_3 = gdns3
328
self.global_dns_dom = gdns_dom
329
self.global_search_dom = gsearch_dom
333
self.connecting_message = None
336
self.SetStatus('interface_down')
339
self.connect_result = "Failed"
343
self.is_connecting = False
345
def set_should_die(self, val):
348
self._should_die = val
351
def get_should_die(self): return self._should_die
352
should_die = property(get_should_die, set_should_die)
354
def SetStatus(self, status):
355
""" Set the threads current status message in a thread-safe way.
358
status -- the current connection status
363
self.connecting_message = status
368
""" Get the threads current status message in a thread-safe way.
371
The current connection status.
376
message = self.connecting_message
382
def reset_ip_addresses(self, iface):
383
""" Resets the IP addresses for both wired/wireless interfaces.
385
Sets a false ip so that when we set the real one, the correct
386
routing entry is created.
389
print 'Setting false IP...'
390
self.SetStatus('resetting_ip_address')
391
iface.SetAddress('0.0.0.0')
394
def put_iface_down(self, iface):
395
""" Puts the given interface down. """
396
print 'Putting interface down'
397
self.SetStatus('interface_down')
401
def run_global_scripts_if_needed(self, script_dir, extra_parameters=()):
402
misc.ExecuteScripts(script_dir, verbose=self.debug,
403
extra_parameters=extra_parameters)
406
def run_script_if_needed(self, script, msg, bssid='wired', essid='wired'):
407
""" Execute a given script if needed.
410
script -- the script to execute, or None/'' if there isn't one.
411
msg -- the name of the script to display in the log.
415
print 'Executing %s script' % (msg)
416
misc.ExecuteScript(expand_script_macros(script, msg, bssid, essid),
420
def flush_routes(self, iface):
421
""" Flush the routes for both wired/wireless interfaces. """
422
self.SetStatus('flushing_routing_table')
423
print 'Flushing the routing table...'
427
def set_broadcast_address(self, iface):
428
""" Set the broadcast address for the given interface. """
429
if not self.network.get('broadcast') == None:
430
self.SetStatus('setting_broadcast_address')
431
print 'Setting the broadcast address...' + self.network['broadcast']
432
iface.SetAddress(broadcast=self.network['broadcast'])
435
def set_ip_address(self, iface):
436
""" Set the IP address for the given interface.
438
Assigns a static IP if one is requested, otherwise calls DHCP.
441
if self.network.get('ip'):
442
self.SetStatus('setting_static_ip')
443
print 'Setting static IP : ' + self.network['ip']
444
iface.SetAddress(self.network['ip'], self.network['netmask'])
445
if self.network.get('gateway'):
446
print 'Setting default gateway : ' + self.network['gateway']
447
iface.SetDefaultRoute(self.network['gateway'])
450
self.SetStatus('running_dhcp')
451
if self.network.get('usedhcphostname') == None:
452
self.network['usedhcphostname'] = False
453
if self.network.get('dhcphostname') == None:
454
self.network['dhcphostname'] = os.uname()[1]
455
if not self.network['usedhcphostname']:
456
hname = os.uname()[1]
458
hname = self.network['dhcphostname']
459
print "Running DHCP with hostname",hname
460
dhcp_status = iface.StartDHCP(hname)
461
if dhcp_status in ['no_dhcp_offers', 'dhcp_failed']:
462
if self.connect_result != "aborted":
463
self.abort_connection(dhcp_status)
467
def set_dns_addresses(self, iface):
468
""" Set the DNS address(es).
470
If static DNS servers or global DNS servers are specified, set them.
471
Otherwise do nothing.
474
if self.network.get('use_global_dns'):
475
iface.SetDNS(misc.Noneify(self.global_dns_1),
476
misc.Noneify(self.global_dns_2),
477
misc.Noneify(self.global_dns_3),
478
misc.Noneify(self.global_dns_dom),
479
misc.Noneify(self.global_search_dom))
480
elif self.network.get('use_static_dns') and (self.network.get('dns1') or
481
self.network.get('dns2') or self.network.get('dns3')):
482
self.SetStatus('setting_static_dns')
483
iface.SetDNS(self.network.get('dns1'),
484
self.network.get('dns2'),
485
self.network.get('dns3'),
486
self.network.get('dns_domain'),
487
self.network.get('search_domain'))
490
def release_dhcp_clients(self, iface):
491
""" Release all running dhcp clients. """
492
print "Releasing DHCP leases..."
495
def connect_aborted(self, reason):
496
""" Sets the thread status to aborted. """
497
if self.abort_reason:
498
reason = self.abort_reason
499
self.connecting_message = reason
500
self.is_aborted = True
501
self.connect_result = reason
502
self.is_connecting = False
503
print 'exiting connection thread'
505
def abort_connection(self, reason=""):
506
""" Schedule a connection abortion for the given reason. """
507
self.abort_reason = reason
508
self.should_die = True
510
def abort_if_needed(self):
511
""" Abort the thread is it has been requested. """
515
self.connect_aborted('aborted')
521
def put_iface_up(self, iface):
522
""" Bring up given interface. """
523
print 'Putting interface up...'
524
self.SetStatus('interface_up')
526
for x in range(0, 5):
530
self.abort_if_needed()
532
# If we get here, the interface never came up
533
print "WARNING: Timed out waiting for interface to come up"
536
class Wireless(Controller):
537
""" A wrapper for common wireless interface functions. """
539
def __init__(self, debug=False):
540
""" Initialize the class. """
541
Controller.__init__(self, debug=debug)
542
self._wpa_driver = None
543
self._wireless_interface = None
545
self.should_verify_ap = True
547
def set_wireless_iface(self, value):
548
self._wireless_interface = value
550
self.wiface.SetInterface(value)
551
def get_wireless_iface(self): return self._wireless_interface
552
wireless_interface = property(get_wireless_iface, set_wireless_iface)
554
def set_wpa_driver(self, value):
555
self._wpa_driver = value
557
self.SetWPADriver(value)
558
def get_wpa_driver(self): return self._wpa_driver
559
wpa_driver = property(get_wpa_driver, set_wpa_driver)
561
def set_iface(self, value):
565
iface = property(get_iface, set_iface)
567
def LoadBackend(self, backend):
568
""" Load a given backend.
570
Load up a backend into the backend manager and associate with
571
the networking interface.
574
Controller.LoadBackend(self, backend)
576
self.wiface = self._backend.WirelessInterface(self.wireless_interface,
577
self.debug, self.wpa_driver)
579
def Scan(self, essid=None):
580
""" Scan for available wireless networks.
583
essid -- The essid of a hidden network
586
A list of available networks sorted by strength.
594
return cmp(x[key], y[key])
596
if not self.wiface: return []
599
# Prepare the interface for scanning
602
# If there is a hidden essid then set it now, so that when it is
603
# scanned it will be recognized.
604
essid = misc.Noneify(essid)
605
if essid is not None:
606
print 'Setting hidden essid' + essid
607
wiface.SetEssid(essid)
608
# sleep for a bit; scanning to fast will result in nothing
611
aps = wiface.GetNetworks()
612
aps.sort(cmp=comp, reverse=True)
616
def Connect(self, network, debug=False):
617
""" Spawn a connection thread to connect to the network.
620
network -- network to connect to
623
if not self.wiface: return False
625
self.connecting_thread = WirelessConnectThread(network,
626
self.wireless_interface, self.wpa_driver, self.before_script,
627
self.after_script, self.pre_disconnect_script,
628
self.post_disconnect_script, self.global_dns_1,
629
self.global_dns_2, self.global_dns_3, self.global_dns_dom,
630
self.global_search_dom, self.wiface, self.should_verify_ap, debug)
631
self.connecting_thread.setDaemon(True)
632
self.connecting_thread.start()
635
def GetSignalStrength(self, iwconfig=""):
636
""" Get signal strength of the current network.
639
The current signal strength.
642
return self.wiface.GetSignalStrength(iwconfig)
644
def GetDBMStrength(self, iwconfig=""):
645
""" Get the dBm signal strength of the current network.
648
The current dBm signal strength.
651
return self.wiface.GetDBMStrength(iwconfig)
653
def GetCurrentNetwork(self, iwconfig=""):
654
""" Get current network name.
657
The name of the currently connected network.
660
return self.wiface.GetCurrentNetwork(iwconfig)
663
""" Get the BSSID of the current access point.
666
The MAC Adress of the active access point as a string, or
667
None the BSSID can't be found.
670
return self.wiface.GetBSSID()
672
def GetCurrentBitrate(self, iwconfig):
673
""" Get the current bitrate of the interface.
676
The bitrate of the active access point as a string, or
677
None the bitrate can't be found.
680
return self.wiface.GetCurrentBitrate(iwconfig)
682
def GetOperationalMode(self, iwconfig):
683
""" Get the current operational mode of the interface.
686
The operational mode of the interface as a string, or
687
None if the operational mode can't be found.
690
return self.wiface.GetOperationalMode(iwconfig)
692
def GetAvailableAuthMethods(self, iwlistauth):
693
""" Get the available authentication methods for the interface.
696
The available authentication methods of the interface as a string, or
697
None if the auth methods can't be found.
700
return self.wiface.GetAvailableAuthMethods(iwlistauth)
702
def GetIwconfig(self):
703
""" Get the out of iwconfig. """
704
return self.wiface.GetIwconfig()
706
def GetWpaSupplicantDrivers(self):
707
""" Returns all valid wpa_supplicant drivers on the system. """
708
return BACKEND.GetWpaSupplicantDrivers()
711
return self.wiface.StopWPA()
713
def CreateAdHocNetwork(self, essid, channel, ip, enctype, key,
715
""" Create an ad-hoc wireless network.
718
essid -- essid of the ad-hoc network
719
channel -- channel of the ad-hoc network
720
ip -- ip of the ad-hoc network
722
key -- key of the ad-hoc network
723
enc_used -- encrytion enabled on ad-hoc network
727
print 'Creating ad-hoc network'
728
print 'Stopping dhcp client and wpa_supplicant'
731
print 'Putting wireless interface down'
733
print 'Setting mode, channel, and essid'
734
wiface.SetMode('ad-hoc')
735
wiface.SetChannel(channel)
736
wiface.SetEssid(essid)
737
# Right now it just assumes you're using WEP
739
print 'Setting encryption key'
741
print 'Putting interface up'
743
print 'Setting IP address'
744
wiface.SetAddress(ip, '255.255.255.0')
746
def DetectWirelessInterface(self):
747
""" Detect available wireless interfaces.
750
The first available wireless interface.
753
ifaces = BACKEND.GetWirelessInterfaces()
759
def GetKillSwitchStatus(self):
760
""" Get the current status of the Killswitch.
763
True if the killswitch is on, False otherwise.
766
return self.wiface.GetKillSwitchStatus()
768
def Disconnect(self):
769
""" Disconnect the given iface.
771
Executes the disconnect script associated with a given interface,
772
Resets it's IP address, and puts the interface down then up.
775
if BACKEND.NeedsExternalCalls():
776
iwconfig = self.GetIwconfig()
779
bssid = self.wiface.GetBSSID(iwconfig)
780
essid = self.wiface.GetCurrentNetwork(iwconfig)
782
Controller.Disconnect(self, 'wireless', essid, bssid)
785
def SetWPADriver(self, driver):
786
""" Sets the wpa_supplicant driver associated with the interface. """
787
self.wiface.SetWpaDriver(driver)
790
class WirelessConnectThread(ConnectThread):
791
""" A thread class to perform the connection to a wireless network.
793
This thread, when run, will perform the necessary steps to connect
794
to the specified network.
798
def __init__(self, network, wireless, wpa_driver, before_script,
799
after_script, pre_disconnect_script, post_disconnect_script,
800
gdns1, gdns2, gdns3, gdns_dom, gsearch_dom, wiface,
801
should_verify_ap, debug=False):
802
""" Initialise the thread with network information.
805
network -- the network to connect to
806
wireless -- name of the wireless interface
807
wpa_driver -- type of wireless interface
808
before_script -- script to run before bringing up the interface
809
after_script -- script to run after bringing up the interface
810
pre_disconnect_script -- script to run before disconnection
811
post_disconnect_script -- script to run after disconnection
812
gdns1 -- global DNS server 1
813
gdns2 -- global DNS server 2
814
gdns3 -- global DNS server 3
817
ConnectThread.__init__(self, network, wireless, before_script,
818
after_script, pre_disconnect_script,
819
post_disconnect_script, gdns1, gdns2,
820
gdns3, gdns_dom, gsearch_dom, wiface, debug)
821
self.wpa_driver = wpa_driver
822
self.should_verify_ap = should_verify_ap
826
""" The main function of the connection thread.
828
This function performs the necessary calls to connect to the
829
specified network, using the information provided. The following
830
indicates the steps taken.
831
1. Run pre-connection script.
832
2. Take down the interface and clean up any previous
834
3. Generate a PSK if required and authenticate.
835
4. Associate with the WAP.
836
5. Get/set IP address and DNS servers.
840
self.is_connecting = True
842
# Run pre-connection script.
843
self.run_global_scripts_if_needed(wpath.preconnectscripts,
844
extra_parameters=('wireless',
845
self.network['essid'],
846
self.network['bssid'])
848
self.run_script_if_needed(self.before_script, 'pre-connection',
849
self.network['bssid'], self.network['essid'])
852
# Take down interface and clean up previous connections.
853
self.put_iface_down(wiface)
854
self.release_dhcp_clients(wiface)
855
self.reset_ip_addresses(wiface)
856
self.stop_wpa(wiface)
857
self.flush_routes(wiface)
858
wiface.SetMode(self.network['mode'])
861
self.SetStatus('configuring_interface')
862
self.put_iface_up(wiface)
864
# Generate PSK and authenticate if needed.
865
if self.wpa_driver != 'ralink legacy':
866
self.generate_psk_and_authenticate(wiface)
869
wiface.Associate(self.network['essid'], self.network['channel'],
870
self.network['bssid'])
872
# Authenticate after association for Ralink legacy cards.
873
if self.wpa_driver == 'ralink legacy':
874
if self.network.get('key'):
875
wiface.Authenticate(self.network)
877
# Validate Authentication.
878
if self.network.get('enctype'):
879
self.SetStatus('validating_authentication')
880
if not wiface.ValidateAuthentication(time.time()):
881
print "connect result is %s" % self.connect_result
882
if not self.connect_result or self.connect_result == 'Failed':
883
self.abort_connection('bad_pass')
885
# Set up gateway, IP address, and DNS servers.
886
self.set_broadcast_address(wiface)
887
self.set_ip_address(wiface)
888
self.set_dns_addresses(wiface)
889
self.verify_association(wiface)
891
# Run post-connection script.
892
self.run_global_scripts_if_needed(wpath.postconnectscripts,
893
extra_parameters=('wireless',
894
self.network['essid'],
895
self.network['bssid'])
897
self.run_script_if_needed(self.after_script, 'post-connection',
898
self.network['bssid'], self.network['essid'])
900
self.SetStatus('done')
901
print 'Connecting thread exiting.'
903
print "IP Address is: " + str(wiface.GetIP())
904
self.connect_result = "Success"
905
self.is_connecting = False
908
def verify_association(self, iface):
909
""" Verify that our association the AP is valid.
911
Try to ping the gateway we have set to see if we're
912
really associated with it. This is only done if
913
we're using a static IP.
916
if self.network.get('gateway') and self.should_verify_ap:
917
self.SetStatus('verifying_association')
918
print "Verifying AP association..."
919
for tries in range(1, 11):
920
print "Attempt %d of 10..." % tries
921
retcode = self.iface.VerifyAPAssociation(self.network['gateway'])
923
print "Successfully associated."
926
#TODO this should be in wnettools.py
928
print "Connection Failed: Failed to ping the access point!"
929
# Clean up before aborting.
930
iface.SetAddress('0.0.0.0')
932
if hasattr(iface, "StopWPA"):
934
self.abort_connection("association_failed")
936
print 'not verifying'
940
def stop_wpa(self, wiface):
941
""" Stops wpa_supplicant. """
942
print 'Stopping wpa_supplicant'
946
def generate_psk_and_authenticate(self, wiface):
947
""" Generates a PSK and authenticates if necessary.
949
Generates a PSK, and starts the authentication process
953
# Check to see if we need to generate a PSK (only for non-ralink
956
print "enctype is %s" % self.network.get('enctype')
957
if self.network.get('key') and 'wpa' in str(self.network.get('enctype')):
958
self.SetStatus('generating_psk')
959
print 'Generating psk...'
960
self.network['psk'] = wiface.GeneratePSK(self.network)
962
if not self.network.get('psk'):
963
self.network['psk'] = self.network['key']
964
print 'WARNING: PSK generation failed! Falling back to ' + \
965
'wireless key.\nPlease report this error to the wicd ' + \
967
# Generate the wpa_supplicant file...
968
if self.network.get('enctype'):
969
self.SetStatus('generating_wpa_config')
970
print 'Attempting to authenticate...'
971
wiface.Authenticate(self.network)
974
class Wired(Controller):
975
""" A wrapper for common wired interface functions. """
977
def __init__(self, debug=False):
978
""" Initialise the class. """
979
Controller.__init__(self, debug=debug)
980
self.wpa_driver = None
981
self._link_detect = None
982
self._wired_interface = None
985
def set_link_detect(self, value):
986
self._link_detect = value
988
self.liface.link_detect = value
989
def get_link_detect(self): return self._link_detect
990
link_detect = property(get_link_detect, set_link_detect)
993
def set_wired_iface(self, value):
994
self._wired_interface = value
996
self.liface.SetInterface(value)
997
def get_wired_iface(self): return self._wired_interface
998
wired_interface = property(get_wired_iface, set_wired_iface)
1000
def set_iface(self, value):
1002
def get_iface(self):
1004
iface = property(get_iface, set_iface)
1006
def LoadBackend(self, backend):
1007
""" Load the backend up. """
1008
Controller.LoadBackend(self, backend)
1010
self.liface = self._backend.WiredInterface(self.wired_interface,
1013
def CheckPluggedIn(self):
1014
""" Check whether the wired connection is plugged in.
1017
The status of the physical connection link.
1020
return self.liface.GetPluggedIn()
1022
def Connect(self, network, debug=False):
1023
""" Spawn a connection thread to connect to the network.
1026
network -- network to connect to
1029
if not self.liface: return False
1030
self.connecting_thread = WiredConnectThread(network,
1031
self.wired_interface, self.before_script, self.after_script,
1032
self.pre_disconnect_script, self.post_disconnect_script,
1033
self.global_dns_1, self.global_dns_2, self.global_dns_3,
1034
self.global_dns_dom, self.global_search_dom, self.liface,
1036
self.connecting_thread.setDaemon(True)
1037
self.connecting_thread.start()
1038
return self.connecting_thread
1040
def Disconnect(self):
1041
Controller.Disconnect(self, 'wired', 'wired', 'wired')
1043
def DetectWiredInterface(self):
1044
""" Attempts to automatically detect a wired interface. """
1046
return BACKEND.GetWiredInterfaces()[0]
1051
class WiredConnectThread(ConnectThread):
1052
""" A thread class to perform the connection to a wired network.
1054
This thread, when run, will perform the necessary steps to connect
1055
to the specified network.
1058
def __init__(self, network, wired, before_script, after_script,
1059
pre_disconnect_script, post_disconnect_script, gdns1,
1060
gdns2, gdns3, gdns_dom, gsearch_dom, liface, debug=False):
1061
""" Initialise the thread with network information.
1064
network -- the network to connect to
1065
wireless -- name of the wireless interface
1066
wired -- name of the wired interface
1067
before_script -- script to run before bringing up the interface
1068
after_script -- script to run after bringing up the interface
1069
pre_disconnect_script -- script to run before disconnection
1070
post_disconnect_script -- script to run after disconnection
1071
gdns1 -- global DNS server 1
1072
gdns2 -- global DNS server 2
1073
gdns3 -- global DNS server 3
1076
ConnectThread.__init__(self, network, wired, before_script,
1077
after_script, pre_disconnect_script,
1078
post_disconnect_script, gdns1, gdns2,
1079
gdns3, gdns_dom, gsearch_dom, liface,
1083
""" The main function of the connection thread.
1085
This function performs the necessary calls to connect to the
1086
specified network, using the information provided. The following
1087
indicates the steps taken.
1088
1. Run pre-connection script.
1089
2. Take down the interface and clean up any previous
1091
3. Bring up the interface.
1092
4. Get/set IP address and DNS servers.
1093
5. Run post-connection script.
1098
self.is_connecting = True
1100
# Run pre-connection script.
1101
self.run_global_scripts_if_needed(wpath.preconnectscripts,
1102
extra_parameters=('wired', 'wired',
1103
self.network['profilename'])
1105
self.run_script_if_needed(self.before_script, 'pre-connection', 'wired',
1108
# Take down interface and clean up previous connections.
1109
self.put_iface_down(liface)
1110
self.release_dhcp_clients(liface)
1111
self.reset_ip_addresses(liface)
1112
self.flush_routes(liface)
1114
# Bring up interface.
1115
self.put_iface_up(liface)
1117
# Set gateway, IP adresses, and DNS servers.
1118
self.set_broadcast_address(liface)
1119
self.set_ip_address(liface)
1120
self.set_dns_addresses(liface)
1122
# Run post-connection script.
1123
self.run_global_scripts_if_needed(wpath.postconnectscripts,
1124
extra_parameters=('wired', 'wired',
1125
self.network['profilename'])
1127
self.run_script_if_needed(self.after_script, 'post-connection', 'wired',
1130
self.SetStatus('done')
1131
print 'Connecting thread exiting.'
1133
print "IP Address is: " + str(liface.GetIP())
1135
self.connect_result = "Success"
1136
self.is_connecting = False