00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 import struct
00025 import array
00026 import math
00027 import errno
00028 import fcntl
00029 import os
00030 import socket
00031 import time
00032 import re
00033
00034 import flags
00035 from types import StringType, IntType, TupleType
00036
00037
00038 KILO = 10**3
00039 MEGA = 10**6
00040 GIGA = 10**9
00041
00042
00043 def getNICnames():
00044 """ Extract network device names from /proc/net/dev.
00045
00046 Returns list of device names. Returns empty list if no network
00047 devices are present.
00048
00049 >>> getNICnames()
00050 ['lo', 'eth0']
00051
00052 """
00053 device = re.compile('[a-z]{2,}[0-9]*:')
00054 ifnames = []
00055
00056 fp = open('/proc/net/dev', 'r')
00057 for line in fp:
00058 try:
00059
00060 ifnames.append(device.search(line).group()[:-1])
00061 except AttributeError:
00062 pass
00063 return ifnames
00064
00065 def getWNICnames():
00066 """ Extract wireless device names from /proc/net/wireless.
00067
00068 Returns empty list if no devices are present.
00069
00070 >>> getWNICnames()
00071 ['eth1', 'wifi0']
00072
00073 """
00074 device = re.compile('[a-z]{2,}[0-9]*:')
00075 ifnames = []
00076
00077 fp = open('/proc/net/wireless', 'r')
00078 for line in fp:
00079 try:
00080
00081 ifnames.append(device.search(line).group()[:-1])
00082 except AttributeError:
00083 pass
00084
00085 if ifnames == []:
00086 ifnames = getConfiguredWNICnames()
00087
00088 return ifnames
00089
00090 def getConfiguredWNICnames():
00091 """ Get the *configured* ifnames by a systemcall.
00092
00093 >>> getConfiguredWNICnames()
00094 []
00095
00096 """
00097 iwstruct = Iwstruct()
00098 ifnames = []
00099 buff = array.array('c', '\0'*1024)
00100 caddr_t, length = buff.buffer_nfo()
00101 datastr = iwstruct.pack('iP', length, caddr_t)
00102 result = iwstruct._fcntl(flags.SIOCGIFCONF, datastr)
00103
00104 for i in range(0, 1024, 32):
00105 ifname = buff.tostring()[i:i+32]
00106 ifname = struct.unpack('32s', ifname)[0]
00107 ifname = ifname.split('\0', 1)[0]
00108 if ifname:
00109
00110 wifi = Wireless(ifname)
00111 try:
00112 result = wifi.getAPaddr()
00113 except IOError, (errno, strerror):
00114
00115 pass
00116 if result[0] == 0:
00117 ifnames.append(ifname)
00118 return ifnames
00119
00120 def makedict(**kwargs):
00121 return kwargs
00122
00123 def hex2int(hexstring):
00124 """ Convert hex string to integer. """
00125 return int(hexstring, 16)
00126
00127
00128 class Wireless(object):
00129 """ Provides high-level access to wireless interfaces.
00130
00131 This class uses WirelessInfo for most access.
00132
00133 """
00134
00135 def __init__(self, ifname):
00136 self.sockfd = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
00137 self.ifname = ifname
00138 self.iwstruct = Iwstruct()
00139 self.wireless_info = WirelessInfo(self.ifname)
00140
00141 def getAPaddr(self):
00142 """ Returns the access point MAC address.
00143
00144 >>> from iwlibs import Wireless, getNICnames
00145 >>> ifnames = getNICnames()
00146 >>> ifnames
00147 ['eth1', 'wifi0']
00148 >>> wifi = Wireless(ifnames[0])
00149 >>> wifi.getAPaddr()
00150 '00:0D:88:8E:4E:93'
00151
00152 Test with non-wifi card:
00153 >>> wifi = Wireless('eth0')
00154 >>> wifi.getAPaddr()
00155 (95, 'Operation not supported')
00156
00157 Test with non-existant card:
00158 >>> wifi = Wireless('eth2')
00159 >>> wifi.getAPaddr()
00160 (19, 'No such device')
00161
00162 """
00163 return self.wireless_info.getAPaddr()
00164
00165 def setAPaddr(self, addr):
00166 """ Sets the access point MAC address.
00167
00168 translated from iwconfig.c
00169
00170 """
00171 addr = addr.upper()
00172 if (addr == "AUTO" or addr == "ANY"):
00173 mac_addr = "\xFF"*flags.ETH_ALEN
00174 elif addr == "OFF":
00175 mac_addr = '\x00'*flags.ETH_ALEN
00176 else:
00177 if ":" not in addr: return (errno.ENOSYS, os.strerror(errno.ENOSYS))
00178 mac_addr = "%c%c%c%c%c%c" % tuple(map(hex2int, addr.split(':')))
00179
00180 iwreq = self.iwstruct.pack("H14s", 1, mac_addr)
00181 status, result = self.iwstruct.iw_set_ext(self.ifname,
00182 flags.SIOCSIWAP,
00183 iwreq)
00184
00185 def _formatBitrate(self, raw_bitrate):
00186 """ Returns formatted bitrate.
00187
00188 'raw_bitrate' -- long -- The unformatted bitrate as a long integer.
00189
00190 """
00191 if raw_bitrate >= GIGA:
00192 return "%g Gb/s" % (float(raw_bitrate)/GIGA)
00193 if raw_bitrate >= MEGA:
00194 return "%g Mb/s" % (float(raw_bitrate)/MEGA)
00195 if raw_bitrate >= KILO:
00196 return "%g kb/s" % (float(raw_bitrate)/KILO)
00197
00198 def getBitrate(self):
00199 """ Returns the device's currently set bit rate in Mbit.
00200
00201 >>> from iwlibs import Wireless
00202 >>> wifi = Wireless('eth1')
00203 >>> wifi.getBitrate()
00204 '11 Mb/s'
00205
00206 """
00207 iwparam = self.wireless_info.getBitrate()
00208 return self._formatBitrate(iwparam.value)
00209
00210 def getBitrates(self):
00211 """ Returns the number of bitrates available for the device.
00212
00213 >>> from iwlibs import Wireless
00214 >>> wifi = Wireless('eth1')
00215 >>> num, rates = wifi.getBitrates()
00216 >>> num == len(rates)
00217 True
00218
00219 """
00220 num_bitrates, bitrates = self.wireless_info.getBitrates()
00221 cooked_rates = []
00222 for rate in bitrates:
00223 cooked_rates.append(self._formatBitrate(rate))
00224 return (num_bitrates, cooked_rates)
00225
00226 def _formatFrequency(self, raw_frequency):
00227 """ Returns formatted frequency.
00228
00229 'raw_frequency' -- long -- The unformatted frequency as a long
00230 integer.
00231
00232 """
00233 raw_frequency = float(raw_frequency)
00234 if raw_frequency >= GIGA:
00235 return "%0.3f GHz" % (raw_frequency/GIGA)
00236 if raw_frequency >= MEGA:
00237 return "%0.3f MHZ" % (raw_frequency/MEGA)
00238 if raw_frequency >= KILO:
00239 return "%0.3f kHz" % (raw_frequency/KILO)
00240
00241 raw_frequency = int(raw_frequency)
00242 try:
00243 return self.getChannelInfo()[1][raw_frequency-1]
00244 except IndexError:
00245
00246 pass
00247 return raw_frequency
00248
00249 def getChannelInfo(self):
00250 """ Returns the number of channels and available frequencies for
00251 the device.
00252
00253 >>> from iwlibs import Wireless
00254 >>> wifi = Wireless('eth1')
00255 >>> num, rates = wifi.getChannelInfo()
00256 >>> num == len(rates)
00257 True
00258
00259 """
00260 iwrange = Iwrange(self.ifname)
00261 frequencies = []
00262 for freq in iwrange.frequencies:
00263 frequencies.append(self._formatFrequency(freq))
00264 return (iwrange.num_channels, frequencies)
00265
00266 def getEssid(self):
00267 """ Returns the current ESSID information.
00268
00269 >>> from iwlibs import Wireless
00270 >>> wifi = Wireless('eth1')
00271 >>> wifi.getEssid()
00272 'romanofski'
00273
00274 """
00275 return self.wireless_info.getEssid()
00276
00277 def setEssid(self, essid):
00278 """ Sets the ESSID.
00279
00280 >>> from iwlibs import Wireless
00281 >>> wifi = Wireless('eth1')
00282 >>> wifi.getEssid()
00283 'romanofski'
00284 >>> wifi.setEssid('Joost')
00285 >>> wifi.getEssid()
00286 'Joost'
00287
00288 """
00289 if len(essid) > flags.IW_ESSID_MAX_SIZE:
00290 raise OverflowError(errno.EOVERFLOW, os.strerror(errno.EOVERFLOW))
00291 iwpoint = Iwpoint(essid, 1)
00292 status, result = self.iwstruct.iw_set_ext(self.ifname,
00293 flags.SIOCSIWESSID,
00294 data=iwpoint.packed_data)
00295
00296 def getEncryption(self):
00297 """ Get the association mode, which is probably a string of '*',
00298 'open', 'private', 'off'.
00299
00300 As a normal user, you will get an 'Operation not permitted'
00301 error:
00302
00303 >>> from iwlibs import Wireless
00304 >>> wifi = Wireless('eth1')
00305 >>> wifi.getEncryption()
00306 (1, 'Operation not permitted')
00307
00308 """
00309
00310
00311 iwpoint = Iwpoint('\x00'*flags.IW_ENCODING_TOKEN_MAX)
00312 status, result = self.iwstruct.iw_get_ext(self.ifname,
00313 flags.SIOCGIWENCODE,
00314 data=iwpoint.packed_data)
00315 iwpoint.update(result)
00316
00317 if iwpoint.flags & flags.IW_ENCODE_NOKEY > 0:
00318 return '**'*iwpoint.length
00319 elif iwpoint.flags & flags.IW_ENCODE_OPEN > 0:
00320 return 'open'
00321 elif iwpoint.flags & flags.IW_ENCODE_RESTRICTED > 0:
00322 return 'restricted'
00323 elif iwpoint.flags & flags.IW_ENCODE_DISABLED > 0:
00324 return 'off'
00325
00326 def setEncryption(self, mode):
00327 """ Set the association mode.
00328
00329 As a normal user, you will get an 'Operation not permitted'
00330 error:
00331
00332 >>> from iwlibs import Wireless
00333 >>> wifi = Wireless('eth1')
00334 >>> wifi.setEncryption()
00335 (1, 'Operation not permitted')
00336
00337 """
00338 if type(mode) == IntType:
00339 mode = mode
00340 else:
00341 mode = mode.upper()
00342 numeric_mode = self.getEncryption(symbolic=False)
00343
00344 numeric_mode = numeric_mode & ~flags.IW_ENCODE_OPEN \
00345 & ~flags.IW_ENCODE_RESTRICTED \
00346 & ~flags.IW_ENCODE_DISABLED
00347 if (mode == 'OPEN') or (mode == flags.IW_ENCODE_OPEN):
00348 numeric_mode = numeric_mode | flags.IW_ENCODE_OPEN
00349 elif (mode == 'RESTRICTED') or (mode == flags.IW_ENCODE_RESTRICTED):
00350 numeric_mode = numeric_mode | flags.IW_ENCODE_RESTRICTED
00351 elif (mode == 'OFF') or (mode == flags.IW_ENCODE_DISABLED):
00352 numeric_mode = numeric_mode | flags.IW_ENCODE_DISABLED
00353 iwpoint = Iwpoint('\x00'*flags.IW_ENCODING_TOKEN_MAX, numeric_mode)
00354 status, result = self.iwstruct.iw_get_ext(self.ifname,
00355 flags.SIOCSIWENCODE,
00356 data=iwpoint.packed_data)
00357
00358 def getKey(self, key=0, formatted=True):
00359 """ Get an encryption key.
00360
00361 key 0 is current key, otherwise, retrieve specific key (1-4)
00362
00363 As a normal user, you will get an 'Operation not permitted'
00364 error:
00365
00366 >>> from iwlibs import Wireless
00367 >>> wifi = Wireless('eth1')
00368 >>> wifi.getKey()
00369 ABCD-9512-34
00370
00371 """
00372 iwpoint = self.wireless_info.getKey(key)
00373
00374
00375 raw_key = map(ord, iwpoint.buff.tolist())[:iwpoint.length]
00376 if sum(raw_key) == 0:
00377 return "off"
00378 if not formatted:
00379 return raw_key
00380
00381
00382 key = "%.2X" % raw_key[0]
00383 for i in range(1, iwpoint.length):
00384 if ( i & 0x1 ) == 0:
00385 key = key + '-'
00386 key = key + "%.2X" % raw_key[i]
00387 return key
00388
00389 def setKey(self, key, index=0):
00390 """ Set an encryption key.
00391
00392 As a normal user, you will get an 'Operation not permitted'
00393 error:
00394
00395 >>> from iwlibs import Wireless
00396 >>> wifi = Wireless('eth1')
00397 >>> wifi.setKey()
00398
00399 """
00400 if index not in range(1, flags.IW_ENCODE_INDEX):
00401 raise IndexError
00402
00403 if key:
00404 cooked_key = ''
00405 for i in range(0, len(key), 2):
00406 cooked_key = cooked_key + chr(hex2int(key[i:i+2]))
00407 else:
00408 raw_key = self.getKey(index, False)
00409 cooked_key = map(chr, raw_key)
00410
00411 iwpoint = Iwpoint(cooked_key,
00412 index + flags.IW_ENCODE_ENABLED)
00413 status, result = self.iwstruct.iw_get_ext(self.ifname,
00414 flags.SIOCSIWENCODE,
00415 data=iwpoint.packed_data)
00416
00417 def getKeys(self):
00418 """ Get all encryption keys.
00419
00420 Returns a list of tuples.
00421
00422 As a normal user, you will get a 'Operation not permitted'
00423 error:
00424
00425 >>> from iwlibs import Wireless
00426 >>> wifi = Wireless('eth1')
00427 >>> wifi.getKeys()
00428 [(1, '1234-5678-91'), (2, None), (3, 'ABCD-EFAB-CD'), (4, None)]
00429
00430 """
00431 iwrange = Iwrange(self.ifname);
00432 keys = []
00433 if iwrange.max_encoding_tokens > 0:
00434 for i in range(1, iwrange.max_encoding_tokens+1):
00435 keys.append((i, self.getKey(i)))
00436 return keys
00437
00438 def getFragmentation(self):
00439 """ Returns the fragmentation threshold.
00440
00441 It depends on what the driver says. If you have fragmentation
00442 threshold turned on, you'll get an int. If it's turned off
00443 you'll get a string: 'off'.
00444
00445 >>> from iwlibs import Wireless
00446 >>> wifi = Wireless('eth1')
00447 >>> wifi.getFragmentation()
00448 'off'
00449
00450 """
00451 iwparam = self.wireless_info.getFragmentation()
00452 if iwparam.disabled:
00453 return "off"
00454 return iwparam.value
00455
00456 def getFrequency(self):
00457 """ Returns currently set frequency of the card.
00458
00459 >>> from iwlibs import Wireless
00460 >>> wifi = Wireless('eth1')
00461 >>> wifi.getFrequency()
00462 '2.417 GHz'
00463
00464 """
00465 iwfreq = self.wireless_info.getFrequency()
00466 return self._formatFrequency(iwfreq.getFrequency())
00467
00468 def setFrequency(self, freq):
00469 """ Sets the frequency on the card.
00470
00471 translated from iwconfig.c
00472
00473 """
00474 iwstruct = Iwstruct()
00475 if freq == "auto":
00476 iwreq = iwstruct.pack("ihBB", -1, 0, 0, flags.IW_FREQ_AUTO)
00477 else:
00478 if freq == "fixed":
00479 freq = self.getFrequency()
00480 freq_pattern = re.compile("([\d\.]+)(\w)", re.I|re.M|re.S)
00481 freq_match = freq_pattern.search(freq)
00482 freq_num, unit = freq_match.groups()
00483 if unit == "G": freq_num = float(freq_num) * GIGA
00484 if unit == "M": freq_num = float(freq_num) * MEGA
00485 if unit == "k": freq_num = float(freq_num) * KILO
00486 e = math.floor(math.log10(freq_num))
00487 if e > 8:
00488 m = int(math.floor(freq_num / math.pow(10, e - 6))) * 100
00489 e = e - 8
00490 else:
00491 m = int(math.floor(freq_num))
00492 e = 0
00493 iwreq = iwstruct.pack("ihBB", m, e, 0, flags.IW_FREQ_FIXED)
00494 status, result = iwstruct.iw_set_ext(self.ifname,
00495 flags.SIOCSIWFREQ,
00496 iwreq)
00497
00498 def getMode(self):
00499 """ Returns currently set operation mode.
00500
00501 >>> from iwlibs import Wireless
00502 >>> wifi = Wireless('eth1')
00503 >>> wifi.getMode()
00504 'Managed'
00505
00506 """
00507 return flags.modes[self.wireless_info.getMode()]
00508
00509 def setMode(self, mode):
00510 """ Sets the operation mode.
00511
00512 """
00513 try:
00514 this_modes = [x.lower() for x in flags.modes]
00515 mode = mode.lower()
00516 wifimode = this_modes.index(mode)
00517 except ValueError:
00518 raise ValueError("Invalid operation mode!")
00519
00520 datastr = self.iwstruct.pack('I', wifimode)
00521 status, result = self.iwstruct.iw_set_ext(self.ifname,
00522 flags.SIOCSIWMODE,
00523 data=datastr)
00524
00525 def getWirelessName(self):
00526 """ Returns the wireless name.
00527
00528 >>> from iwlibs import Wireless
00529 >>> wifi = Wireless('eth1')
00530 >>> wifi.getWirelessName()
00531 'IEEE 802.11-DS'
00532
00533 """
00534 return self.wireless_info.getWirelessName()
00535
00536 def getPowermanagement(self):
00537 """ Returns the power management settings.
00538
00539 #>>> from iwlibs import Wireless
00540 #>>> wifi = Wireless('eth1')
00541 #>>> wifi.getPowermanagement()
00542 #'off'
00543
00544 """
00545 iwrange = Iwrange(self.ifname)
00546 iwparam = self.wireless_info.getPower()
00547 return (iwrange.pm_capa,
00548 (iwrange.pmp_flags, iwrange.min_pmp, iwrange.max_pmp),
00549 (iwrange.pmt_flags, iwrange.min_pmt, iwrange.max_pmt),
00550 (iwrange.pms_flags, iwrange.min_pms, iwrange.max_pms),
00551 iwparam)
00552
00553 def getQualityMax(self):
00554 """ Returns an Iwquality object with maximum quality information.
00555
00556 >>> from iwlibs import Wireless
00557 >>> wifi = Wireless('eth1')
00558 >>> mq = wifi.getQualityMax()
00559 >>> print "quality:", mq.quality, "signal:", mq.siglevel, "noise:", mq.nlevel
00560 quality: 38 signal: 13 noise: 0
00561
00562 """
00563 iwrange = Iwrange(self.ifname)
00564 if iwrange.errorflag:
00565 return (iwrange.errorflag, iwrange.error)
00566 return iwrange.max_qual
00567
00568 def getQualityAvg(self):
00569 """ Returns an Iwquality object with average quality information.
00570
00571 >>> from iwlibs import Wireless
00572 >>> wifi = Wireless('eth1')
00573 >>> aq = wifi.getQualityAvg()
00574 >>> print "quality:", aq.quality, "signal:", aq.siglevel, "noise:", aq.nlevel
00575 quality: 38 signal: 13 noise: 0
00576
00577 """
00578 iwrange = Iwrange(self.ifname)
00579 if iwrange.errorflag:
00580 return (iwrange.errorflag, iwrange.error)
00581 return iwrange.avg_qual
00582
00583 def getRetrylimit(self):
00584 """ Returns the retry/lifetime limit.
00585
00586 man iwconfig:
00587 "Most cards have MAC retransmissions, and some allow to set
00588 the behaviour of the retry mechanism."
00589
00590 >>> from iwlibs import Wireless
00591 >>> wifi = Wireless('eth1')
00592 >>> wifi.getRetrylimit()
00593 16
00594
00595 """
00596 iwparam = self.wireless_info.getRetry()
00597 return iwparam.value
00598
00599 def getRTS(self):
00600 """ Returns the RTS threshold, likely to be int, 'auto',
00601 'fixed', 'off'
00602
00603 man iwconfig:
00604 "RTS/CTS adds a handshake before each packet transmission to
00605 make sure that the channel is clear. This adds overhead, but
00606 increases performance in case of hidden nodes or a large
00607 number of active nodes. This parameter sets the size of the
00608 smallest packet for which the node sends RTS; a value equal
00609 to the maximum packet size disable the mechanism."
00610
00611 >>> from iwlibs import Wireless
00612 >>> wifi = Wireless('eth1')
00613 >>> wifi.getRTS()
00614 'off'
00615
00616 """
00617 iwparam = self.wireless_info.getRTS()
00618 if iwparam.disabled:
00619 return "off"
00620 return iwparam.value
00621
00622 def getSensitivity(self):
00623 """ Returns sensitivity information.
00624
00625 man iwconfig:
00626 "This is the lowest signal level for which the hardware
00627 attempt packet reception, signals weaker than this are
00628 ignored. This is used to avoid receiving background noise,
00629 so you should set it according to the average noise
00630 level. Positive values are assumed to be the raw value used
00631 by the hardware or a percentage, negative values are
00632 assumed to be dBm."
00633
00634 >>> from iwlibs import Wireless
00635 >>> wifi = Wireless('eth1')
00636 >>> wifi.getSensitivity()
00637 'off'
00638
00639 """
00640 iwparam = self.wireless_info.getSensitivity()
00641 return iwparam.value
00642
00643 def getTXPower(self):
00644 """ Returns the transmit power in dBm.
00645
00646 >>> from iwlibs import Wireless
00647 >>> wifi = Wireless('eth1')
00648 >>> wifi.getTXPower()
00649 '17 dBm'
00650
00651 """
00652 def mw2dbm(self, mwatt):
00653 """ Converts mW to dBm (float). """
00654 if mwatt == 0:
00655 return 0
00656 return math.ceil(10.0 * math.log10(mwatt))
00657
00658 iwparam = self.wireless_info.getTXPower()
00659 return "%i dBm" % iwparam.value
00660
00661 def getStatistics(self):
00662 """ Returns statistics information which can also be found in
00663 /proc/net/wireless.
00664
00665 """
00666 iwstats = Iwstats(self.ifname)
00667 if iwstats.errorflag > 0:
00668 return (iwstats.errorflag, iwstats.error)
00669 return [iwstats.status, iwstats.qual, iwstats.discard,
00670 iwstats.missed_beacon]
00671
00672 def scan(self):
00673 """ Returns Iwscanresult objects, after a successful scan. """
00674 return Iwscan(self.ifname)
00675
00676 def commit(self):
00677 """ Commit pending changes. """
00678 status, result = self.iwstruct.iw_set_ext(self.ifname,
00679 flags.SIOCSIWCOMMIT)
00680 return (status, result)
00681
00682
00683 class WirelessConfig(object):
00684 """ Low level access to wireless information on a device. This class
00685 contains only those things absolutely needed to configure a card.
00686
00687 WirelessConfig implements the wireless_config struct in iwlib.h.
00688 It will probably never be called directly, but instead be used via
00689 WirelessInfo.
00690
00691 """
00692
00693 def __init__(self, ifname):
00694 self.sockfd = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
00695 self.ifname = ifname
00696 self.iwstruct = Iwstruct()
00697
00698 self.freq_flags = 0
00699 self.essid_on = 0
00700
00701 def getWirelessName(self):
00702 """ Returns the wireless name.
00703
00704 >>> from iwlibs import Wireless
00705 >>> wifi = Wireless('eth1')
00706 >>> wifi.getWirelessName()
00707 'IEEE 802.11-DS'
00708
00709 """
00710 status, result = self.iwstruct.iw_get_ext(self.ifname,
00711 flags.SIOCGIWNAME)
00712 return result.tostring().strip('\x00')
00713
00714 def getEncryption(self):
00715 """ Returns the encryption status.
00716
00717 >>> from iwlibs import Wireless
00718 >>> wifi = Wireless('eth1')
00719 >>> wifi.getEncryption()
00720 'off'
00721
00722 """
00723
00724
00725 iwpoint = Iwpoint('\x00'*flags.IW_ENCODING_TOKEN_MAX)
00726 status, result = self.iwstruct.iw_get_ext(self.ifname,
00727 flags.SIOCGIWENCODE,
00728 data=iwpoint.packed_data)
00729 iwpoint.update(result)
00730
00731 return iwpoint
00732
00733 def getFrequency(self):
00734 """ Returns currently set frequency of the card.
00735
00736 >>> from iwlibs import Wireless
00737 >>> wifi = Wireless('eth1')
00738 >>> wifi.getFrequency()
00739 '2.417 GHz'
00740
00741 """
00742 status, result = self.iwstruct.iw_get_ext(self.ifname,
00743 flags.SIOCGIWFREQ)
00744 return Iwfreq(result)
00745
00746 def getKey(self, key=0):
00747 """ Get an encryption key.
00748
00749 key 0 is current key, otherwise, retrieve specific key (1-4)
00750
00751 As a normal user, you will get an 'Operation not permitted'
00752 error:
00753
00754 >>> from iwlibs import Wireless
00755 >>> wifi_conf = WirelessConfig('eth1')
00756 >>> isinstance(wifi_conf.getKey(), Iwpoint)
00757 True
00758
00759 """
00760
00761
00762 iwpoint = Iwpoint('\x00'*flags.IW_ENCODING_TOKEN_MAX, key)
00763 status, result = self.iwstruct.iw_get_ext(self.ifname,
00764 flags.SIOCGIWENCODE,
00765 data=iwpoint.packed_data)
00766 iwpoint.update(result)
00767 return iwpoint
00768
00769 def getEssid(self):
00770 """ Returns the current ESSID information.
00771
00772 >>> from iwlibs import Wireless
00773 >>> wifi = Wireless('eth1')
00774 >>> wifi.getEssid()
00775 'romanofski'
00776
00777 """
00778
00779
00780 iwpoint = Iwpoint('\x00'*flags.IW_ESSID_MAX_SIZE)
00781 status, result = self.iwstruct.iw_get_ext(self.ifname,
00782 flags.SIOCGIWESSID,
00783 data=iwpoint.packed_data)
00784 raw_essid = iwpoint.buff.tostring()
00785 return raw_essid.strip('\x00')
00786
00787 def getMode(self):
00788 """ Returns currently set operation mode.
00789
00790 >>> from iwlibs import Wireless
00791 >>> wifi = Wireless('eth1')
00792 >>> wifi.getMode()
00793 'Managed'
00794
00795 """
00796 status, result = self.iwstruct.iw_get_ext(self.ifname,
00797 flags.SIOCGIWMODE)
00798 return self.iwstruct.unpack('I', result[:4])[0]
00799
00800
00801 class WirelessInfo(WirelessConfig):
00802 """ Low level access to wireless extensions on a device. This class
00803 is the exhaustive list of information for a card.
00804
00805 WirelessInfo implements the wireless_info struct in iwlib.h.
00806 This class should be used by those needing lower-level access
00807 than Wireless provides.
00808
00809 """
00810
00811 def __init__(self, ifname):
00812 self.sockfd = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
00813 self.ifname = ifname
00814 self.iwstruct = Iwstruct()
00815
00816 self.nickname = ""
00817
00818 self.stats = Iwstats
00819 self.range = Iwrange
00820
00821 self.auth_key_mgmt = 0
00822 self.has_auth_key_mgmt = 0
00823 self.auth_cipher_pairwise = 0
00824 self.has_auth_cipher_pairwise = 0
00825 self.auth_cipher_group = 0
00826 self.has_auth_cipher_group = 0
00827 WirelessConfig.__init__(self, ifname)
00828
00829 def getSensitivity(self):
00830 """ Returns sensitivity information.
00831
00832 man iwconfig:
00833 "This is the lowest signal level for which the hardware
00834 attempt packet reception, signals weaker than this are
00835 ignored. This is used to avoid receiving background noise,
00836 so you should set it according to the average noise
00837 level. Positive values are assumed to be the raw value used
00838 by the hardware or a percentage, negative values are
00839 assumed to be dBm."
00840
00841 >>> from iwlibs import Wireless
00842 >>> wifi = Wireless('eth1')
00843 >>> wifi.getSensitivity()
00844 'off'
00845
00846 """
00847 return Iwparam(self.ifname, flags.SIOCGIWSENS)
00848
00849 def getAPaddr(self):
00850 """ Returns the access point MAC address.
00851
00852 >>> from iwlibs import Wireless, getNICnames
00853 >>> ifnames = getNICnames()
00854 >>> ifnames
00855 ['eth1', 'wifi0']
00856 >>> wifi = Wireless(ifnames[0])
00857 >>> wifi.getAPaddr()
00858 '00:0D:88:8E:4E:93'
00859
00860 Test with non-wifi card:
00861 >>> wifi = Wireless('eth0')
00862 >>> wifi.getAPaddr()
00863 (95, 'Operation not supported')
00864
00865 Test with non-existant card:
00866 >>> wifi = Wireless('eth2')
00867 >>> wifi.getAPaddr()
00868 (19, 'No such device')
00869
00870 """
00871 buff, datastr = self.iwstruct.pack_wrq(32)
00872 status, result = self.iwstruct.iw_get_ext(self.ifname,
00873 flags.SIOCGIWAP,
00874 data=datastr)
00875
00876 mac_addr = struct.unpack('xxBBBBBB', result[:8])
00877 return "%02X:%02X:%02X:%02X:%02X:%02X" % mac_addr
00878
00879 def getBitrate(self):
00880 """ Returns the device's currently set bit rate.
00881
00882 >>> from iwlibs import Wireless
00883 >>> wifi = Wireless('eth1')
00884 >>> wifi.getBitrate()
00885 '11 Mb/s'
00886
00887 """
00888 return Iwparam(self.ifname, flags.SIOCGIWRATE)
00889
00890 def getBitrates(self):
00891 """ Returns the device's number and list of available bit rates.
00892
00893 The bit rates in the list are long integer type.
00894
00895 """
00896 iwrange = Iwrange(self.ifname)
00897 return (iwrange.num_bitrates, iwrange.bitrates)
00898
00899 def getRTS(self):
00900 """ Returns the RTS threshold.
00901
00902 >>> from iwlibs import Wireless
00903 >>> wifi = Wireless('eth1')
00904 >>> wifi.getRTS()
00905 'off'
00906
00907 """
00908 return Iwparam(self.ifname, flags.SIOCGIWRTS)
00909
00910 def getFragmentation(self):
00911 """ Returns the fragmentation threshold.
00912
00913 >>> from iwlibs import Wireless
00914 >>> wifi = Wireless('eth1')
00915 >>> wifi.getFragmentation()
00916 'off'
00917
00918 """
00919 return Iwparam(self.ifname, flags.SIOCGIWFRAG)
00920
00921 def getPower(self):
00922 """ Returns the power management settings.
00923
00924 #>>> from iwlibs import Wireless
00925 #>>> wifi = Wireless('eth1')
00926 #>>> wifi.getPowermanagement()
00927 #'off'
00928
00929 """
00930 return Iwparam(self.ifname, flags.SIOCGIWPOWER)
00931
00932 def getTXPower(self):
00933 """ Returns the transmit power in dBm.
00934
00935 >>> from iwlibs import Wireless
00936 >>> wifi = Wireless('eth1')
00937 >>> wifi.getTXPower()
00938 '17 dBm'
00939
00940 """
00941 return Iwparam(self.ifname, flags.SIOCGIWTXPOW)
00942
00943 def getRetry(self):
00944 """ Returns the retry/lifetime limit.
00945
00946 man iwconfig:
00947 "Most cards have MAC retransmissions, and some allow to set
00948 the behaviour of the retry mechanism."
00949
00950 >>> from iwlibs import Wireless
00951 >>> wifi = Wireless('eth1')
00952 >>> wifi.getRetrylimit()
00953 16
00954
00955 """
00956 return Iwparam(self.ifname, flags.SIOCGIWRETRY)
00957
00958
00959 class Iwstruct(object):
00960 """ The basic class to handle iwstruct data. """
00961
00962 def __init__(self):
00963 self.idx = 0
00964 self.sockfd = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
00965
00966 def parse_data(self, fmt, data):
00967 """ Unpacks raw C data. """
00968 size = struct.calcsize(fmt)
00969 idx = self.idx
00970
00971 datastr = data[idx:idx + size]
00972 self.idx = idx+size
00973 value = struct.unpack(fmt, datastr)
00974
00975
00976 if len(value) == 1:
00977 return value[0]
00978 else:
00979 return value
00980
00981 def pack(self, fmt, *args):
00982 """ Calls struct.pack and returns the result. """
00983 return struct.pack(fmt, *args)
00984
00985 def pack_wrq(self, buffsize):
00986 """ Packs wireless request data for sending it to the kernel. """
00987
00988
00989
00990
00991
00992 buff = array.array('c', '\0'*buffsize)
00993 caddr_t, length = buff.buffer_info()
00994 datastr = struct.pack('Pi', caddr_t, length)
00995 return buff, datastr
00996
00997 def pack_test(self, string, buffsize):
00998 """ Packs wireless request data for sending it to the kernel. """
00999 buffsize = buffsize - len(string)
01000 buff = array.array('c', string+'\0'*buffsize)
01001 caddr_t, length = buff.buffer_info()
01002 s = struct.pack('PHH', caddr_t, length, 1)
01003 return buff, s
01004
01005 def unpack(self, fmt, packed_data):
01006 """ Unpacks data with given format. """
01007 return struct.unpack(fmt, packed_data)
01008
01009 def _fcntl(self, request, args):
01010 return fcntl.ioctl(self.sockfd.fileno(), request, args)
01011
01012 def iw_get_ext(self, ifname, request, data=None):
01013 """ Read information from ifname. """
01014 buff = flags.IFNAMSIZE-len(ifname)
01015 ifreq = array.array('c', ifname + '\0'*buff)
01016
01017 if data is not None:
01018 ifreq.extend(data)
01019 else:
01020 buff = 32
01021 ifreq.extend('\0'*buff)
01022
01023 result = self._fcntl(request, ifreq)
01024 return (result, ifreq[flags.IFNAMSIZE:])
01025
01026 def iw_set_ext(self, ifname, operation, data=None):
01027 """ Set options on ifname. """
01028 return self.iw_get_ext(ifname, operation, data)
01029
01030
01031
01032
01033
01034
01035
01036 class Iwparam(object):
01037 """ Class to hold iwparam data. """
01038
01039 def __init__(self, ifname, ioctl):
01040
01041 self.fmt = "ibbH"
01042 self.ifname = ifname
01043 self.ioctl = ioctl
01044 self.value = 0
01045 self.fixed = 0
01046 self.disabled = 0
01047 self.flags = 0
01048 self.update()
01049
01050 def update(self):
01051 """ Updates Iwstruct object by a system call to the kernel
01052 and updates internal attributes.
01053
01054 """
01055 iwstruct = Iwstruct()
01056 status, result = iwstruct.iw_get_ext(self.ifname, self.ioctl)
01057 self._parse(result)
01058
01059 def _parse(self, data):
01060 """ Unpacks iwparam data. """
01061 iwstruct = Iwstruct()
01062 self.value, self.fixed, self.disabled, self.flags = \
01063 iwstruct.parse_data(self.fmt, data)
01064
01065 class Iwfreq(object):
01066 """ Class to hold iwfreq data. """
01067
01068 def __init__(self, data=None):
01069
01070 self.fmt = "ihbb"
01071 self.m = 0
01072 self.e = 0
01073 self.index = 0
01074 self.flags = 0
01075 if data:
01076 if isinstance(data, TupleType):
01077 self.m, self.e, self.index, self.flags = data
01078 else:
01079 self.parse(data)
01080
01081 def parse(self, data):
01082 """ Unpacks iw_freq. """
01083 size = struct.calcsize(self.fmt)
01084 self.m, self.e, self.index, self.flags = struct.unpack(self.fmt, data[:size])
01085
01086 def getFrequency(self):
01087 """ Returns frequency or channel, depending on the driver. """
01088 if self.e == 0:
01089 return self.m
01090 else:
01091 return self.m*10**self.e
01092
01093 def setFrequency(self, value):
01094 """ Sets mantissa and exponent from given frequency (or channel). """
01095 if value % GIGA == 0:
01096 self.e = 9
01097 if value % MEGA == 0:
01098 self.e = 6
01099 if value % KILO == 0:
01100 self.e = 3
01101 else:
01102 self.e = 0
01103 self.m = value / 10**self.e
01104
01105
01106 class Iwstats(object):
01107 """ Class to hold iwstat data. """
01108
01109 def __init__(self, ifname):
01110
01111 self.fmt = "2B4B6i"
01112 self.status = 0
01113 self.qual = Iwquality()
01114 self.discard = {}
01115 self.missed_beacon = 0
01116 self.ifname = ifname
01117 self.errorflag = 0
01118 self.error = ""
01119 self.update()
01120
01121 def update(self):
01122 """ Updates Iwstats object by a system call to the kernel
01123 and updates internal attributes.
01124
01125 """
01126 iwstruct = Iwstruct()
01127 buff, s = iwstruct.pack_wrq(32)
01128 i, result = iwstruct.iw_get_ext(self.ifname,
01129 flags.SIOCGIWSTATS,
01130 data=s)
01131 if i > 0:
01132 self.error = result
01133 self.errorflag = i
01134 self._parse(buff.tostring())
01135
01136 def _parse(self, data):
01137 """ Unpacks iwstruct data. """
01138 iwstruct = Iwstruct()
01139 iwqual = Iwquality()
01140 iwstats_data = iwstruct.parse_data(self.fmt, data)
01141
01142 self.status = iwstats_data[0:2]
01143 self.qual.quality, self.qual.siglevel, self.qual.nlevel, \
01144 self.qual.updated = iwstats_data[2:6]
01145
01146 self.qual.siglevel -= 256
01147 self.qual.nlevel -= 256
01148 nwid, code, frag, retries, iwflags = iwstats_data[6:11]
01149 self.missed_beacon = iwstats_data[11:12][0]
01150 self.discard = makedict(nwid=nwid, code=code,
01151 fragment=frag, retries=retries, misc=iwflags)
01152
01153
01154 class Iwquality(object):
01155 """ Class to hold iwquality data. """
01156
01157 def __init__(self):
01158 self.quality = 0
01159 self.siglevel = 0
01160 self.nlevel = 0
01161 self.updated = 0
01162 self.fmt = "4B"
01163
01164 def parse(self, data):
01165 """ Unpacks iwquality data. """
01166 iwstruct = Iwstruct()
01167 qual, siglevel, nlevel, iwflags = iwstruct.parse_data(self.fmt, data)
01168
01169
01170 self.siglevel = siglevel
01171 self.nlevel = nlevel
01172
01173
01174 self.quality = qual
01175 self.updated = iwflags
01176
01177 def setValues(self, vallist):
01178 """ Assigns values given by a list to our attributes. """
01179 attributes = ["quality", "siglevel", "nlevel", "updated"]
01180 assert len(vallist) == 4
01181
01182 for i in range(len(vallist)):
01183 setattr(self, attributes[i], vallist[i])
01184
01185 def getSignallevel(self):
01186 """ Returns signal level. """
01187 return self.siglevel
01188
01189 def setSignallevel(self, siglevel):
01190 """ Sets signal level. """
01191 self.siglevel = siglevel
01192 signallevel = property(getSignallevel, setSignallevel)
01193
01194 def getNoiselevel(self):
01195 """ Returns noise level. """
01196 return self.nlevel
01197
01198 def setNoiselevel(self, val):
01199
01200
01201 self.nlevel = val
01202 noiselevel = property(getNoiselevel, setNoiselevel)
01203
01204
01205 class Iwpoint(object):
01206 """ Class to hold iw_point data. """
01207
01208 def __init__(self, data=None, flags=0):
01209 if data is None:
01210 raise ValueError, "data must be passed to Iwpoint"
01211
01212 self.fmt = 'PHH'
01213 self.flags = flags
01214 self.buff = array.array('c', data)
01215 self.caddr_t, self.length = self.buff.buffer_info()
01216 self.packed_data = struct.pack(self.fmt, self.caddr_t,
01217 self.length, self.flags)
01218
01219 def update(self, packed_data):
01220 """ Updates the object attributes. """
01221 self.packed_data = packed_data
01222 self.caddr_t, self.length, self.flags = struct.unpack(self.fmt,
01223 self.packed_data)
01224
01225
01226 class Iwrange(object):
01227 """ Holds iwrange struct. """
01228
01229 def __init__(self, ifname):
01230 self.fmt = "IIIHB6Ii4B4BB" + flags.IW_MAX_BITRATES*"i" + \
01231 "2i2i2i2i3H" + flags.IW_MAX_ENCODING_SIZES*"H" + \
01232 "2BBHB" + flags.IW_MAX_TXPOWER*"i" + \
01233 "2B3H2i2iHB" + flags.IW_MAX_FREQUENCIES*"ihBB" + \
01234 "IiiHiI"
01235
01236 self.ifname = ifname
01237 self.errorflag = 0
01238 self.error = ""
01239
01240
01241 self.throughput = 0
01242
01243
01244 self.min_nwid = self.max_nwid = 0
01245
01246
01247 self.old_num_channels = self.old_num_frequency = self.old_freq = 0
01248
01249
01250 self.sensitivity = 0
01251
01252
01253 self.max_qual = Iwquality()
01254 self.avg_qual = Iwquality()
01255
01256
01257 self.num_bitrates = 0
01258 self.bitrates = []
01259
01260
01261 self.min_rts = self.max_rts = 0
01262
01263
01264 self.min_frag = self.max_frag = 0
01265
01266
01267 self.min_pmp = self.max_pmp = 0
01268 self.min_pmt = self.max_pmt = 0
01269 self.pmp_flags = self.pmt_flags = self.pm_capa = 0
01270
01271
01272 self.encoding_size = 0
01273 self.num_encoding_sizes = self.max_encoding_tokens = 0
01274 self.encoding_login_index = 0
01275
01276
01277 self.txpower_capa = self.num_txpower = self.txpower = 0
01278
01279
01280 self.we_vers_compiled = self.we_vers_src = 0
01281
01282
01283 self.retry_capa = self.retry_flags = self.r_time_flags = 0
01284 self.min_retry = self.max_retry = 0
01285 self.min_r_time = self.max_r_time = 0
01286
01287
01288 self.num_channels = self.num_frequency = 0
01289 self.frequencies = []
01290
01291
01292 self.enc_capa = 0
01293 self.min_pms = self.max_pms = self.pms_flags = 0
01294 self.modul_capa = 0
01295 self.bitrate_capa = 0
01296
01297 self.update()
01298
01299 def update(self):
01300 """ Updates Iwrange object by a system call to the kernel
01301 and updates internal attributes.
01302
01303 """
01304 iwstruct = Iwstruct()
01305 buff, s = iwstruct.pack_wrq(640)
01306 status, result = iwstruct.iw_get_ext(self.ifname,
01307 flags.SIOCGIWRANGE,
01308 data=s)
01309 data = buff.tostring()
01310 self._parse(data)
01311
01312 def _parse(self, data):
01313 iwstruct = Iwstruct()
01314 result = iwstruct.parse_data(self.fmt, data)
01315
01316
01317 self.throughput, self.min_nwid, self.max_nwid = result[0:3]
01318 self.old_num_channels, self.old_num_frequency = result[3:5]
01319 self.old_freq = result[5:11]
01320 self.sensitivity = result[11]
01321 self.max_qual.setValues(result[12:16])
01322 self.avg_qual.setValues(result[16:20])
01323 self.num_bitrates = result[20]
01324 raw_bitrates = result[21:21+self.num_bitrates]
01325 for rate in raw_bitrates:
01326 if rate is not None:
01327 self.bitrates.append(rate)
01328
01329 self.min_rts, self.max_rts = result[53:55]
01330 self.min_frag, self.max_frag = result[55:57]
01331 self.min_pmp, self.max_pmp = result[57:59]
01332 self.min_pmt, self.max_pmt = result[59:61]
01333 self.pmp_flags, self.pmt_flags, self.pm_capa = result[61:64]
01334 self.encoding_size = result[64:72]
01335 self.num_encoding_sizes, self.max_encoding_tokens = result[72:74]
01336 self.encoding_login_index = result[74]
01337 self.txpower_capa, self.num_txpower = result[75:77]
01338 self.txpower = result[77:85]
01339 self.we_vers_compiled, self.we_vers_src = result[85:87]
01340 self.retry_capa, self.retry_flags, self.r_time_flags = result[87:90]
01341 self.min_retry, self.max_retry = result[90:92]
01342 self.min_r_time, self.max_r_time = result[92:94]
01343 self.num_channels = result[94]
01344 self.num_frequency = result[95]
01345
01346 freq = result[96:224]
01347 i = self.num_frequency
01348 for x in range(0, len(freq), 4):
01349 iwfreq = Iwfreq(freq[x:x+4])
01350 fq = iwfreq.getFrequency()
01351 if fq is not None:
01352 self.frequencies.append(fq)
01353 i -= 1
01354 if i <= 0:
01355 break
01356 self.enc_capa = result[224]
01357 self.min_pms = result[225]
01358 self.max_pms = result[226]
01359 self.pms_flags = result[227]
01360 self.modul_capa = result[228]
01361 self.bitrate_capa = result[229]
01362
01363
01364 class Iwscan(object):
01365 """ Class to handle AP scanning. """
01366
01367 def __init__(self, ifname, fullscan=True):
01368 """ Completes a scan for available access points,
01369 and returns them in Iwscanresult format.
01370
01371 fullscan: If False, data is read from a cache of the last scan
01372 If True, a scan is conducted, and then the data is read
01373
01374 """
01375 self.ifname = ifname
01376 self.range = Iwrange(ifname)
01377 self.stream = None
01378 self.aplist = None
01379 self.index = -1
01380
01381 if fullscan:
01382
01383 iwstruct = Iwstruct()
01384 datastr = iwstruct.pack("Pii", 0, 0, 0)
01385 status, result = iwstruct.iw_set_ext(self.ifname,
01386 flags.SIOCSIWSCAN,
01387 datastr)
01388 self.getScan()
01389
01390 def __iter__(self):
01391 return self
01392
01393 def __len__(self):
01394 return len(self.aplist)
01395
01396 def next(self):
01397 self.index = self.index + 1
01398 if self.index > len(self.aplist) - 1:
01399 raise StopIteration
01400 return self.aplist[self.index]
01401
01402 def getScan(self):
01403 """ Retrieves results, stored from the most recent scan.
01404
01405 """
01406 iwstruct = Iwstruct()
01407 bufflen = flags.IW_SCAN_MAX_DATA
01408
01409
01410 while (True):
01411 buff, datastr = iwstruct.pack_wrq(bufflen)
01412 try:
01413 status, result = iwstruct.iw_get_ext(self.ifname,
01414 flags.SIOCGIWSCAN,
01415 data=datastr)
01416 except IOError, (error_number, error_string):
01417 if error_number == errno.E2BIG:
01418
01419
01420 pbuff, newlen = iwstruct.unpack('Pi', datastr)
01421 if bufflen < newlen:
01422
01423 bufflen = newlen
01424 else:
01425
01426 bufflen = bufflen * 2
01427 elif error_number == errno.EAGAIN:
01428
01429
01430 time.sleep(0.1)
01431 else:
01432 raise
01433 except:
01434 raise
01435 else:
01436 break
01437
01438
01439 pbuff, reslen = iwstruct.unpack('Pi', datastr)
01440 if reslen > 0:
01441
01442 self.aplist = self._parse(buff.tostring())
01443
01444 def _parse(self, data):
01445 """ Parse the event stream, and return a list of Iwscanresult
01446 objects.
01447
01448 """
01449 iwstruct = Iwstruct()
01450 scanresult = None
01451 aplist = []
01452
01453
01454 while (len(data) >= flags.IW_EV_LCP_PK_LEN):
01455
01456 length, cmd = iwstruct.unpack('HH',
01457 data[:flags.IW_EV_LCP_PK_LEN])
01458
01459
01460 if length < flags.IW_EV_LCP_PK_LEN:
01461 break;
01462
01463 if cmd == flags.SIOCGIWAP:
01464 if scanresult:
01465 aplist.append(scanresult)
01466 scanresult = Iwscanresult(
01467 data[flags.IW_EV_LCP_PK_LEN:length],
01468 self.range)
01469 elif scanresult is None:
01470 raise RuntimeError("Attempting to add an event without AP data.")
01471 else:
01472 scanresult.addEvent(cmd,
01473 data[flags.IW_EV_LCP_PK_LEN:length])
01474
01475 data = data[length:]
01476
01477
01478 if scanresult:
01479 if scanresult.bssid != "00:00:00:00:00:00":
01480 aplist.append(scanresult)
01481 else:
01482 raise RuntimeError, 'Attempting to add an AP without a bssid'
01483 return aplist
01484
01485
01486 class Iwscanresult(object):
01487 """ An object to contain all the events associated with a single
01488 scanned AP.
01489
01490 """
01491
01492 def __init__(self, data, iwrange):
01493 """ Initialize the scan result with the access point data. """
01494 self.range = iwrange
01495 self.bssid = "%02X:%02X:%02X:%02X:%02X:%02X" % (
01496 struct.unpack('BBBBBB', data[2:8]))
01497 self.essid = None
01498 self.mode = None
01499 self.rate = []
01500 self.quality = Iwquality()
01501 self.frequency = None
01502 self.encode = None
01503 self.custom = []
01504 self.protocol = None
01505
01506 def addEvent(self, cmd, data):
01507 """ Attempts to add the data from an event to a scanresult.
01508 Only certain data is accepted, in which case the result is True
01509 If the event data is invalid, None is returned
01510 If the data is valid but unused, False is returned
01511
01512 """
01513 if ((cmd in range(flags.SIOCIWFIRST,
01514 flags.SIOCIWLAST+1)) or
01515 (cmd in range(flags.IWEVFIRST,
01516 flags.IWEVLAST+1))):
01517 if cmd == flags.SIOCGIWNWID:
01518 pass
01519 elif cmd == flags.SIOCGIWFREQ:
01520 self.frequency = Iwfreq(data)
01521 elif cmd == flags.SIOCGIWMODE:
01522 raw_mode = struct.unpack('I', data)[0]
01523 self.mode = flags.modes[raw_mode]
01524 elif cmd == flags.SIOCGIWNAME:
01525 self.protocol = data[:len(data)-2]
01526 elif cmd == flags.SIOCGIWESSID:
01527 self.essid = data[4:]
01528 elif cmd == flags.SIOCGIWENCODE:
01529 data = struct.unpack("B"*len(data), data)
01530 self.encode = Iwpoint("")
01531 self.encode.update(struct.pack('PHH',
01532 (int(data[0])<<16)+int(data[1]), data[2]<<8, data[3]<<8))
01533 if (self.encode.caddr_t is None):
01534 self.encode.flags = \
01535 self.encode.flags | flags.IW_ENCODE_NOKEY
01536 elif cmd == flags.SIOCGIWRATE:
01537 freqsize = struct.calcsize("ihbb")
01538 rates = []
01539 while len(data) >= freqsize:
01540 m, e, dummy, pad = struct.unpack("ihbb", data[:freqsize])
01541 if e == 0:
01542 rates.append(m)
01543 else:
01544 rates.append(m*10**e)
01545 data = data[freqsize:]
01546 self.rate.append(rates)
01547 elif cmd == flags.SIOCGIWMODUL:
01548 pass
01549 elif cmd == flags.IWEVQUAL:
01550 self.quality.parse(data)
01551 elif cmd == flags.IWEVGENIE:
01552 pass
01553 elif cmd == flags.IWEVCUSTOM:
01554 self.custom.append(data[1:])
01555 else:
01556 raise ValueError("Unknown IW event command received. This " + \
01557 "command cannot be used to add information " + \
01558 "to the WiFi cell's profile.")
01559 else:
01560 raise ValueError("Invalid IW event command received. \
01561 This command is not allowed.")
01562
01563 def display(self):
01564 print "ESSID:", self.essid
01565 print "Access point:", self.bssid
01566 print "Mode:", self.mode
01567 if len(self.rate) > 0:
01568 print "Highest Bitrate:", self.rate[len(self.rate)-1]
01569 print "Quality: Quality ", self.quality.quality,
01570 print "Signal ", self.quality.getSignallevel(),
01571 print " Noise ", self.quality.getNoiselevel()
01572 print "Encryption:", map(lambda x: hex(ord(x)), self.encode)
01573
01574
01575 for custom in self.custom:
01576 print "Custom:", custom
01577 print ""
01578