3
#Auto-NDISwrapper by Nils Schlupp, Gabriel J. Perez and Richard Kaufman
7
#This program automatically looks at what Wi-Fi card you have, it disables any wireless driver currently installed, fetches #the correct Windows driver from the Internet and installs it with NDISwrapper.
9
#Copyright (C) 2007, 2008 Gabriel J. Perez <gabrieljoel@gmail.com>, Nils Schlupp <nils.schlupp@gmail.com> and Richard Kaufman <richardbkaufman@gmail.com>
11
#This program is free software; you can redistribute it and/or modify
12
#it under the terms of the GNU General Public License as published by
13
#the Free Software Foundation; either version 2 of the License, or
14
#(at your option) any later version.
16
#This program is distributed in the hope that it will be useful,
17
#but WITHOUT ANY WARRANTY; without even the implied warranty of
18
#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19
#GNU General Public License for more details.
21
#You should have received a copy of the GNU General Public License
22
#along with this program; if not, write to the Free Software
23
#Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25
"""Auto-NDISwrapper -- Linux Wi-Fi as easy as it can get"""
29
import os, platform, sys, re, subprocess, webbrowser, commands
32
class NullHandler(logging.Handler):
33
'''Define an empty logger'''
34
def emit(self, record):
38
class UIDError(Exception):
39
'''Raised when not run as root'''
41
class BinaryNotFound(Exception):
42
'''Raised when ndiswrapper binary not found'''
44
class AUTO_NDIS(object):
45
'''Primary auto-ndiswrapper class'''
48
#sys.path.append(os.getcwd())
49
self.logger = logging.getLogger("AUTO-NDIS MAIN")
52
def perform_initial_checks(self):
53
'''Check for root privileges and ndiswrapper binary'''
54
self.logger.info('perform_initial_checks')
55
##If the user isn't root the program will quit
59
##If the user doesn't have ndiswrapper installed the program will quit
60
if not os.path.exists(opts.ndiswrapper_bin) and not opts.nocheck:
63
self.logger.info('Done perform_initial_checks')
67
"""Like commands.getoutput, but uses subprocess. It also returns the return code of the process."""
69
myproc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
70
value = myproc.stdout.read()
71
retcode = myproc.wait()
74
def get_print_card_info():
76
Prints the pci id and other information about the pci wireless cards.
79
output, retcode = getoutput('lspci')
80
lines = output.split('\n')
83
if 'Network controller' in line:
88
card_info = card_data[28:len(card_data)]
91
print 'No Network Devices Found!'
93
def check_for_internet():
94
"""Pings google to see if the user has an internet conecction available."""
96
print '\n[*] Looking if an Internet connection is available, this may take a few seconds'
98
test, retcode = getoutput('ping', '-c', '1', 'google.com')
100
if 'unknown host' in test:
101
print '[ERROR] An Internet connection was not found'
102
choice = raw_input('(C)ontinue, (R)etry, (O)ffline mode or (E)xit: ')
104
if choice == 'C' or choice == 'c':
107
elif choice == 'R' or choice == 'r':
108
return check_for_internet()
110
elif choice == 'O' or choice == 'o':
113
installation_report()
116
elif choice == 'E' or choice == 'e':
120
return check_for_internet()
123
print '[*] Internet connection found, continuing installation'
125
def searchcard(devices_list, database):
127
Looks if one of the ids in the devices list given as argument matches an entry in the database given as argument.
130
for item in devices_list:
136
def remove_old_drivers():
137
"""Removes existing wireless drivers."""
138
print '[*] Removing Old Drivers:'
139
baddrivers = yourcard_dic['blacklist']
140
if baddrivers in getoutput('lsmod| awk "{print $1}"'):
141
print ' removing %s' % (baddrivers, )
142
subprocess.call(['rmmod', baddrivers])
144
print ' Drivers not loaded, nothing to remove'
146
def blacklist_drivers():
147
"""Blacklists existing wireless drivers."""
149
print '[*] Blacklisting:'
150
baddrivers = yourcard_dic['blacklist']
152
if any(baddrivers in line.split('#')[0] for line in open('/etc/modprobe.d/blacklist')):
153
print ' driver already blacklisted, skipping'
155
print ' writing to /etc/modprobe.d/blacklist'
156
blacklist = open('/etc/modprobe.d/blacklist', 'a')
157
blacklist.write('\n#%s' % (baddrivers, ))
160
def print_driver_license():
162
Checks if the user agrees with the driver's EULA.
165
print 'Do you agree with this proprietary driver\'s End User License Agreement? You can find it in the website of your card\'s manufacturer.'
166
choice = raw_input('(Y)es or (N)o, if you don\'t agree the program will quit: ')
168
if choice == 'Y' or choice == 'y':
171
elif choice == 'N' or choice == 'n':
175
return driver_license()
177
def create_auto_ndis_folder():
179
Creates a folder in which place the downloaded drivers.
183
os.makedirs('%s/%s' % (opts.tmp_dir, card_id, ))
184
print 'Tmpdir created'
185
os.chmod(opts.tmp_dir,0777)
186
os.chdir('%s/%s' % (opts.tmp_dir, card_id, ))
188
if os.path.exists('%s/%s' % (opts.tmp_dir, card_id, )):
189
print '\nTmpdir exists and ok, continuing'
190
os.chdir('%s/%s' % (opts.tmp_dir, card_id, ))
192
print '[ERROR] can\'t create tmpdir'
193
print ' Either specify an alternative or ensure that /tmp is writable and not full'
196
def find_decompression():
198
Determines the right decompression program to be used with the downloaded driver.
201
decompression = 'manual'
203
if '.exe' in url or '.zip' in url:
204
decompression = 'unzip'
207
decompression = 'tar -vvf'
209
elif '.tar.gz' in url:
210
decompression = 'tar -xvvzf'
212
elif '.tar.bz2' in url:
213
decompression = 'tar -xvvjf'
216
decompression = 'cabextract'
219
decompression = 'unrar'
221
if decompression != 'manual':
222
#Checks if the system has the necessary decompression program
223
test = commands.getoutput(decompression)
224
if 'not found' in test:
225
print '[ERROR] The program to extract %s files is not installed in your system' % (decompression, )
226
print 'Install a program on your system to extract %s files and then rerun the script' %(decompression, )
232
Downloads the apropiate driver.
235
print '[*] Downloading driver now from "%s"' % (url, )
237
retcode = subprocess.call(['wget', url, '-qO ', opts.tmp_dir + '/' + card_id + '/' + driver, '-o ', opts.tmp_dir + '/' + card_id + '/' + 'wget.log'])
239
retcode = subprocess.call(['wget', url, '-O ', opts.tmp_dir + '/' + card_id + '/' + driver, '-o ', opts.tmp_dir + '/' + card_id + '/' + 'wget.log'])
243
print '[ERROR] Download unsuccessfull, please check your Internet conecction and wget.log in your tmpdir for errors.'
245
print '[DEBUG] wget returned code: %s' % (retcode, )
248
def extract(decompression):
250
Extracts the dowloaded driver.
253
print '[*] Extracting driver'
256
print '[DEBUG] Decompression method: %s' % (decompression, )
258
retcode = subprocess.call([decompression, opts.tmp_dir + '/' + card_id + '/' + driver])
261
print '[WARNING] Decompression may have failed'
264
print '[DEBUG] Decompression method returned code: %s' % (retcode, )
266
choice = raw_input('(C)ontinue, (R)etry, (S)pecify different decompression method or (E)xit: ')
268
if choice == 'C' or choice == 'c':
271
elif choice == 'R' or choice == 'r':
272
return extract(decompression)
274
elif choice == 'S' or choice == 's':
275
divided_url = url.split('.')
276
file_type = divided_url[len(divided_url)-1]
277
decompression = raw_input('Enter command to decompress %s files: ' % (file_type, ))
278
return extract(decompression)
280
elif choice == 'E' or choice == 'e':
284
return extract(decompression)
288
Comes into play if the user doesn't have an internet connection or if the driver need to be fetched manually.
291
print '\nThe driver needs to be fetched manually from: %s' % (url, )
292
print 'Please place the "%s" file, along with the .sys files into:' % (driver, )
293
print '%s/%s' % (opts.tmp_dir, card_id, )
294
webbrowser.open_new(url)
296
while not any(driver in line for line in os.listdir('%s/%s/' % (opts.tmp_dir, card_id, ))):
298
dummy = raw_input('When you have succesfully dowloaded the driver and extracted it press <Enter>: ')
301
##Executed when CTRL + C is pressed.
302
print '\n\nCanceled!\n'
305
print '\nDriver file found! Continuing installation.'
309
Installs the driver with NDISwrapper.
313
inf_files, retcode = getoutput('find', opts.tmp_dir + '/' + card_id, '-type', 'f', '-name', '*.inf')
314
inf_files = inf_files.split('\n')
315
inf_file = inf_files[0]
316
print '\nA driver has not been specified yet for this card, will attempt procedure with the first found driver in %s/%s: %s' % (opts.tmp_dir, card_id, inf_file)
319
inf_file, retcode = getoutput('find', opts.tmp_dir + '/' + card_id, '-type', 'f', '-name', driver)
321
create_log_file(inf_file)
324
print '[DEBUG] Driver found at %s' % (inf_file, )
326
#Attempt to install driver
327
output, retcode = getoutput('ndiswrapper', '-i', inf_file)
329
#Attempt to detect errors
330
if 'already' in output:
331
print '\nDriver is already installed'
335
print '[ERROR] Driver installation failed'
337
print '[DEBUG] NDISwrapper returned code: %s' % (retcode, )
341
##Assume driver installed successfully and then set up and reload the module
342
subprocess.call(['ndiswrapper', '-ma'])
343
subprocess.call(['modprobe', '-r', 'ndiswrapper'])
344
subprocess.call(['modprobe', 'ndiswrapper'])
345
print 'Installation finished'
348
def create_log_file(driver):
350
Creates a simple log file with some useful info.
353
log = open('autondis-log.txt', 'w')
356
distribution = platform.dist()
357
ndis_version, retcode = getoutput('ndiswrapper', '-v')
359
log.write('OS and date = ')
363
log.write('\nDistribution = ')
364
for item in distribution:
367
log.write('\nNDISwrapper info = ')
369
for item in ndis_version:
372
log.write('\nID = %s \n' % (card_id, ))
373
log.write('URL = %s \n' % (url, ))
374
log.write('DRIVER = %s \n' % (driver, ))
380
Gets the wireless card's id number and revision number.
383
##Gets the id of all the pci devices
384
outtext, retcode = getoutput('lspci', '-n')
386
##Stores the pci ids with the revision number in a list
387
pci = re.findall('.{4}:.{4}\ \(rev .{2}\)',outtext)
389
##Gets the id of all the usb devices
390
outtext2, retcode = getoutput('lsusb')
391
##Stores the usb ids in a list
392
usb = re.findall('.{4}:.{4}',outtext2)
394
pcicard = searchcard(pci, data)
395
usbcard = searchcard(usb, data)
397
##Checks if the user has a pci card or a usb card, if he has both the program will ask card he wants to setup
398
##If he has neither the program will exit and tell him what pci card he has if he has one
399
if pcicard != 'empty' and usbcard == 'empty':
402
elif pcicard == 'empty' and usbcard != 'empty':
405
elif pcicard != 'empty' and usbcard != 'empty':
406
choice = raw_input('Setup (w)ificard or setup your (u)sbcard?: ')
408
while choice != 'W' and choice != 'w' and choice != 'U' and choice != 'u':
409
print 'Please try again'
410
choice = raw_input('Setup (w)ificard or setup your (u)sbcard?: ')
411
if choice == 'W' or choice == 'w':
413
elif choice == 'U' or choice == 'u':
418
elif pcicard == 'empty' and usbcard == 'empty':
419
print 'Sorry, card not yet supported by Auto-NDISwrapper'
420
print 'Save this output as it will help other people give you support'
421
get_print_card_info()
424
def installation_report():
426
Prompts the user to report the installation if it was succesful.
429
output, retcode = getoutput('ndiswrapper', '-l')
430
print '\n' + 'NDISwrapper output: ' + '\n' + output
432
print 'Is your wireless connection working now with NDISwrapper thanks to this script?'
433
choice = raw_input('(Y)es and I would like to help this project by reporting my installation manually trough www.easylinuxwifi.org, (N)o it did not work for me: ')
435
if choice == 'Y' or choice == 'y':
436
print '\nPlease when you have time visit www.easylinuxwifi.org and report your installation. All the information needed for the report is available in your computer in %s/%s/autondis-log.txt\nThank You!' % (opts.tmp_dir, card_id )
439
elif choice == 'N' or choice == 'n':
440
print '\nWe are sorry that the procedure failed, but don\'t get discouraged! Please visit easylinuxwifi.org for help or any other community support website. Remember, the community is here to help. You may also want to try with other .inf files if more than one was included in the dowloaded driver. You may do this by entering manual mode with -m flag. and removing all .inf files from %s/%s/ except the one you want to try to install. Also if possible report any broken urls as bugs in our bug tracker.' % (opts.tmp_dir, card_id)
444
return installation_report()
447
#card_id = get_card_id()
448
#yourcard_dic = data[card_id]
449
#url = yourcard_dic['url']
450
#driver = yourcard_dic['driver']
451
#decompression = find_decompression()
453
#print '\n[*] Card Supported'
455
#print '[*] Card detected as a %s' % (yourcard_dic['name'], )
457
#print '[*] Card ciptset detected as a %s' % (yourcard_dic['chipset'], )
459
#print '[*] Aditional comments were provided:\n"%s"' % (yourcard_dic['other']
460
#print '[*] Will attempt to fetch and install driver for the card with id: %s' % (card_id, )
461
#print '[*] Will attempt to fetch driver from: %s' % (url, )
462
#print '[*] Will attempt to install driver: %s' % (driver, )
465
#print ' Do you want to continue?'
467
#dummy = raw_input(' Please hit <Enter> to continue, or use Ctrl+C to cancel: ')
469
#print '\n\nCanceled!\n'
473
#print '[*] Beginning Setup Procedure:\n'
475
#print_driver_license()
476
#create_auto_ndis_folder()
478
#if decompression != 'manual' and not (opts.manual):
479
#check_for_internet()
481
#extract(decompression)
483
#installation_report()
487
#installation_report()
492
'''Parse comand line options'''
493
parser = OptionParser(version='version: '+auto_ndis.__version__)
494
parser.add_option('--ndiswrapper-bin', default='/usr/sbin/ndiswrapper', help='default: %default', metavar='FILE')
495
parser.add_option('-t', '--tmp-dir', default='/tmp/auto-ndis', help='default: %default', metavar='DIR')
496
parser.add_option('-a', '--ask', action='store_true', default=False, help='ask for confirmation')
497
parser.add_option('-q', '--quiet', action='store_true', default=False, help='reduce some output')
498
parser.add_option('--nocheck', action='store_true', default=False, help='doesn\'t check for ndiswrapper binary (debug only)')
499
parser.add_option('-d', '--debug', action='store_true', default=False, help='turn on debugging output')
500
parser.add_option('-m', '--manual', action='store_true', default=False, help='proceed with manual procedure')
501
parser.add_option('-r', '--repo', default='auto', help='sets source of card information. use either remote, local or auto. defaults to %default')
502
parser.add_option('-c', '--clear', action='store_true', default=False, help='clears tmp-dir before running again')
503
return parser.parse_args()
506
if opts.clear and os.path.isdir(opts.tmp_dir):
507
for root, dirs, files in os.walk(opts.tmp_dir, topdown=False):
509
os.remove(os.path.join(root, name))
511
os.rmdir(os.path.join(root, name))
512
if not os.path.isdir(opts.tmp_dir):
513
os.mkdir(opts.tmp_dir)
515
def initialise_logging():
516
'''Create a logging facility'''
518
__logname__ = '%s/log' % (opts.tmp_dir,)
519
logger = logging.getLogger("AUTO-NDIS CLI")
520
logger.setLevel(logging.DEBUG)
521
# create file handler which logs even debug messages
522
fh = logging.FileHandler(__logname__)
523
fh.setLevel(logging.DEBUG)
524
# create console handler with a higher log level
525
ch = logging.StreamHandler()
527
ch.setLevel(logging.DEBUG)
529
ch.setLevel(logging.ERROR)
530
# create formatter and add it to the handlers
531
formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
532
fh.setFormatter(formatter)
533
ch.setFormatter(formatter)
534
# add the handlers to the logger
535
logger.addHandler(fh)
536
logger.addHandler(ch)
542
print 'Welcome to auto-ndiswrapper %s' % (auto_ndis.__version__, )
543
print 'Please remember to always try to use the latest version of ndiswrapper with this script'
545
opts, args = parse_args()
549
logger = initialise_logging()
550
#initialise main modules
551
main = auto_ndis.AUTO_NDIS()
552
#print the debug options enabled
553
logger.debug('options: %s' % (opts,))
554
logger.debug('arguments: %s' % (args,))
555
#check for root and binary
558
main.perform_initial_checks()
561
logger.error('you must be root to run this script')
562
logger.error('try, "su then python auto-ndis.py" or "sudo python auto-ndis.py"')
563
except BinaryNotFound:
564
logger.error('ndiswrapper not found!!!')
565
logger.error('please look for "ndiswrapper" in your distribution\'s package manager and install it or go to www.ndiswrapper.com and download the latest sources')
567
logger.error('Error occured, exiting')
574
if __name__ == '__main__':