iwlist.py
Go to the documentation of this file.
00001 #!/usr/bin/env python
00002 # -*- coding: utf-8 -*-
00003 # Copyright 2004, 2005 R�man Joost <roman@bromeco.de> - Rotterdam, Netherlands
00004 # Copyright 2009 by Sean Robinson <seankrobinson@gmail.com>
00005 #
00006 # This file is part of Python WiFi
00007 #
00008 #   This program is free software; you can redistribute it and/or modify
00009 #   it under the terms of the GNU General Public License as published by
00010 #   the Free Software Foundation; either version 2 of the License, or
00011 #   (at your option) any later version.
00012 #
00013 #   This program is distributed in the hope that it will be useful,
00014 #   but WITHOUT ANY WARRANTY; without even the implied warranty of
00015 #   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016 #   GNU General Public License for more details.
00017 #
00018 #   You should have received a copy of the GNU General Public License
00019 #   along with this program; if not, write to the Free Software
00020 #   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00021 #
00022 import errno
00023 import sys
00024 import types
00025 
00026 import rocon_python_wifi.flags
00027 from rocon_python_wifi.iwlibs import Wireless, Iwrange, getNICnames
00028 
00029 def print_scanning_results(wifi, args=None):
00030     """ Print the access points detected nearby.
00031 
00032     """
00033     # "Check if the interface could support scanning"
00034     try:
00035         iwrange = Iwrange(wifi.ifname)
00036     except IOError, (error_number, error_string):
00037         sys.stderr.write("%-8.16s  Interface doesn't support scanning.\n\n" % (
00038                             wifi.ifname))
00039     else:
00040         # "Check for Active Scan (scan with specific essid)"
00041         # "Check for last scan result (do not trigger scan)"
00042         # "Initiate Scanning"
00043         try:
00044             results = wifi.scan()
00045         except IOError, (error_number, error_string):
00046             if error_number != errno.EPERM:
00047                 sys.stderr.write(
00048                     "%-8.16s  Interface doesn't support scanning : %s\n\n" %
00049                     (wifi.ifname, error_string))
00050         else:
00051             if (len(results) == 0):
00052                 print "%-8.16s  No scan results" % (wifi.ifname, )
00053             else:
00054                 (num_channels, frequencies) = wifi.getChannelInfo()
00055                 print "%-8.16s  Scan completed :" % (wifi.ifname, )
00056                 index = 1
00057                 for ap in results:
00058                     print "          Cell %02d - Address: %s" % (index, ap.bssid)
00059                     print "                    ESSID:\"%s\"" % (ap.essid, )
00060                     print "                    Mode:%s" % (ap.mode, )
00061                     print "                    Frequency:%s (Channel %d)" % \
00062                         (wifi._formatFrequency(ap.frequency.getFrequency()),
00063                         frequencies.index(wifi._formatFrequency(
00064                             ap.frequency.getFrequency())) + 1)
00065                     if (ap.quality.updated & \
00066                                 pythonwifi.flags.IW_QUAL_QUAL_UPDATED):
00067                         quality_updated = "="
00068                     else:
00069                         quality_updated = ":"
00070                     if (ap.quality.updated & \
00071                                 pythonwifi.flags.IW_QUAL_LEVEL_UPDATED):
00072                         signal_updated = "="
00073                     else:
00074                         signal_updated = ":"
00075                     if (ap.quality.updated & \
00076                                 pythonwifi.flags.IW_QUAL_NOISE_UPDATED):
00077                         noise_updated = "="
00078                     else:
00079                         noise_updated = ":"
00080                     print "                    " + \
00081                         "Quality%c%s/%s  Signal level%c%s/%s  Noise level%c%s/%s" % \
00082                         (quality_updated,
00083                         ap.quality.quality,
00084                         wifi.getQualityMax().quality,
00085                         signal_updated,
00086                         ap.quality.getSignallevel(),
00087                         "100",
00088                         noise_updated,
00089                         ap.quality.getNoiselevel(),
00090                         "100")
00091                     # This code on encryption keys is very fragile
00092                     if (ap.encode.flags & pythonwifi.flags.IW_ENCODE_DISABLED):
00093                         key_status = "off"
00094                     else:
00095                         if (ap.encode.flags & pythonwifi.flags.IW_ENCODE_NOKEY):
00096                             if (ap.encode.length <= 0):
00097                                 key_status = "on"
00098                     print "                    Encryption key:%s" % (key_status, )
00099                     if len(ap.rate) > 0:
00100                         for rate_list in ap.rate:
00101                             # calc how many full lines of bitrates
00102                             rate_lines = len(rate_list) / 5
00103                             # calc how many bitrates on last line
00104                             rate_remainder = len(rate_list) % 5
00105                             line = 0
00106                             # first line should start with a label
00107                             rate_line = "                    Bit Rates:"
00108                             while line < rate_lines:
00109                                 # print full lines
00110                                 if line > 0:
00111                                     # non-first lines should start *very* indented
00112                                     rate_line = "                              "
00113                                 rate_line = rate_line + "%s; %s; %s; %s; %s" % \
00114                                     tuple(wifi._formatBitrate(x) for x in
00115                                         rate_list[line * 5:(line * 5) + 5])
00116                                 line = line + 1
00117                                 print rate_line
00118                             if line > 0:
00119                                 # non-first lines should start *very* indented
00120                                 rate_line = "                              "
00121                             # print non-full line
00122                             print rate_line + "%s; "*(rate_remainder - 1) % \
00123                                 tuple(wifi._formatBitrate(x) for x in
00124                                     rate_list[line * 5:line * 5 + rate_remainder - 1]) + \
00125                                 "%s" % (wifi._formatBitrate(
00126                                         rate_list[line * 5 + rate_remainder - 1]))
00127                     index = index + 1
00128             print
00129 
00130 def print_channels(wifi, args=None):
00131     """ Print all frequencies/channels available on the card.
00132 
00133     """
00134     try:
00135         (num_frequencies, channels) = wifi.getChannelInfo()
00136         current_freq = wifi.getFrequency()
00137     except IOError, (error_number, error_string):
00138         # Channel/frequency info not available
00139         if (error_number == errno.EOPNOTSUPP) or \
00140            (error_number == errno.EINVAL) or \
00141            (error_number == errno.ENODEV):
00142             sys.stderr.write("%-8.16s  no frequency information.\n\n" % (
00143                                 wifi.ifname, ))
00144         else:
00145             report_error("channel", wifi.ifname, error_number, error_string)
00146     else:
00147         # Channel/frequency info available
00148         print "%-8.16s  %02d channels in total; available frequencies :" % \
00149                     (wifi.ifname, num_frequencies)
00150         for channel in channels:
00151             print "          Channel %02d : %s" % \
00152                     (channels.index(channel)+1, channel)
00153         # Do some low-level comparisons on frequency info
00154         iwfreq = wifi.wireless_info.getFrequency()
00155         # XXX - this is not the same flags value as iwlist.c
00156         if iwfreq.flags & pythonwifi.flags.IW_FREQ_FIXED:
00157             fixed = "="
00158         else:
00159             fixed = ":"
00160         if iwfreq.getFrequency() < pythonwifi.iwlibs.KILO:
00161             return_type = "Channel"
00162         else:
00163             return_type = "Frequency"
00164         # Output current channel/frequency
00165         current_freq = wifi.getFrequency()
00166         print "          Current %s%c%s (Channel %d)\n" % \
00167                     (return_type, fixed, current_freq, channels.index(current_freq) + 1 )
00168 
00169 def print_bitrates(wifi, args=None):
00170     """ Print all bitrates available on the card.
00171 
00172     """
00173     try:
00174         num_bitrates, bitrates = wifi.getBitrates()
00175     except IOError, (error_number, error_string):
00176         if (error_number == errno.EOPNOTSUPP) or \
00177            (error_number == errno.EINVAL) or \
00178            (error_number == errno.ENODEV):
00179             # not a wireless device
00180             sys.stderr.write("%-8.16s  no bit-rate information.\n\n" % (
00181                                 wifi.ifname, ))
00182         else:
00183             report_error("bit rate", wifi.ifname, error_number, error_string)
00184     else:
00185         if (num_bitrates > 0) and \
00186            (num_bitrates <= pythonwifi.flags.IW_MAX_BITRATES):
00187             # wireless device with bit rate info, so list 'em
00188             print "%-8.16s  %02d available bit-rates :" % \
00189                     (wifi.ifname, num_bitrates)
00190             for rate in bitrates:
00191                 print "\t  %s" % rate
00192         else:
00193             # wireless device, but no bit rate info available
00194             print "%-8.16s  unknown bit-rate information." % (wifi.ifname, )
00195     # current bit rate
00196     try:
00197         bitrate = wifi.wireless_info.getBitrate()
00198     except IOError, (error_number, error_string):
00199         # no bit rate info is okay, error was given above
00200         pass
00201     else:
00202         if bitrate.fixed:
00203             fixed = "="
00204         else:
00205             fixed = ":"
00206         print "          Current Bit Rate%c%s" % (fixed, wifi.getBitrate())
00207         # broadcast bit rate
00208         # XXX add broadcast bit rate
00209         print
00210 
00211 def print_encryption(wifi, args=None):
00212     """ Print encryption keys on the card.
00213 
00214     """
00215     try:
00216         keys = wifi.getKeys()
00217     except IOError, (error_number, error_string):
00218         if (error_number == errno.EOPNOTSUPP) or \
00219            (error_number == errno.EINVAL) or \
00220            (error_number == errno.ENODEV):
00221             # not a wireless device
00222             sys.stderr.write("%-8.16s  no encryption keys information.\n\n" % (
00223                                 wifi.ifname, ))
00224     else:
00225         range_info = Iwrange(wifi.ifname)
00226         key_sizes = ""
00227         for index in range(range_info.num_encoding_sizes - 1):
00228             key_sizes = key_sizes + \
00229                         repr(range_info.encoding_size[index] * 8) + \
00230                         ", "
00231         key_sizes = key_sizes + \
00232                     repr(range_info.encoding_size[range_info.num_encoding_sizes - 1] * 8) + \
00233                     "bits"
00234         print "%-8.16s  %d key sizes : %s" % \
00235                 (wifi.ifname, range_info.num_encoding_sizes, key_sizes)
00236         print "          %d keys available :" % (len(keys), )
00237         for key in keys:
00238             print "\t\t[%d]: %s" % (key[0], key[1])
00239         print "          Current Transmit Key: [%s]" % \
00240                 (wifi.wireless_info.getKey().flags & pythonwifi.flags.IW_ENCODE_INDEX, )
00241         if wifi.wireless_info.getKey().flags & pythonwifi.flags.IW_ENCODE_RESTRICTED:
00242             print "          Security mode:restricted"
00243         if wifi.wireless_info.getKey().flags & pythonwifi.flags.IW_ENCODE_OPEN:
00244             print "          Security mode:open"
00245         print "\n"
00246 
00247 def format_pm_value(value, args=None):
00248     """ Return formatted PM value.
00249 
00250     """
00251     if (value >= pythonwifi.iwlibs.MEGA):
00252         fvalue = "%gs" % (value / pythonwifi.iwlibs.MEGA, )
00253     else:
00254         if (value >= pythonwifi.iwlibs.KILO):
00255             fvalue = "%gms" % (value / pythonwifi.iwlibs.KILO, )
00256         else:
00257             fvalue = "%dus" % (value, )
00258     return fvalue
00259 
00260 def print_power(wifi, args=None):
00261     """ Print power management info for the card.
00262 
00263     """
00264     try:
00265         (pm_capa, power_period, power_timeout, power_saving, power_params) = \
00266             wifi.getPowermanagement()
00267     except IOError, (error_number, error_string):
00268         if (error_number == errno.ENODEV):
00269             sys.stderr.write("%-8.16s  no power management information.\n\n" % (
00270                             wifi.ifname, ))
00271     else:
00272         print "%-8.16s " % (wifi.ifname, ),
00273         if (pm_capa & pythonwifi.flags.IW_POWER_MODE):
00274             print "Supported modes :"
00275             if pm_capa & (pythonwifi.flags.IW_POWER_UNICAST_R |
00276                         pythonwifi.flags.IW_POWER_MULTICAST_R):
00277                 print "\t\t\to Receive all packets (unicast & multicast)"
00278                 print "\t ",
00279             if pm_capa & pythonwifi.flags.IW_POWER_UNICAST_R:
00280                 print "\t\to Receive Unicast only (discard multicast)"
00281                 print "\t ",
00282             if pm_capa & pythonwifi.flags.IW_POWER_MULTICAST_R:
00283                 print "\t\to Receive Multicast only (discard unicast)"
00284                 print "\t ",
00285             if pm_capa & pythonwifi.flags.IW_POWER_FORCE_S:
00286                 print "\t\to Force sending using Power Management"
00287                 print "\t ",
00288             if pm_capa & pythonwifi.flags.IW_POWER_REPEATER:
00289                 print "\t\to Repeat multicast"
00290                 print "\t ",
00291         if (power_period[0] & pythonwifi.flags.IW_POWER_PERIOD):
00292             if (power_period[0] & pythonwifi.flags.IW_POWER_MIN):
00293                 print "Auto  period  ; ",
00294             else:
00295                 print "Fixed period  ; ",
00296             print "min period:%s\n\t\t\t  " % \
00297                     (format_pm_value(power_period[1]), ),
00298             print "max period:%s\n\t " % (format_pm_value(power_period[2]), ),
00299         if (power_timeout[0] & pythonwifi.flags.IW_POWER_TIMEOUT):
00300             if (power_timeout[0] & pythonwifi.flags.IW_POWER_MIN):
00301                 print "Auto  timeout ; ",
00302             else:
00303                 print "Fixed timeout ; ",
00304             print "min period:%s\n\t\t\t  " % \
00305                     (format_pm_value(power_timeout[1]), ),
00306             print "max period:%s\n\t " % (format_pm_value(power_timeout[2]), ),
00307         if (power_saving[0] & pythonwifi.flags.IW_POWER_SAVING):
00308             if (power_saving[0] & pythonwifi.flags.IW_POWER_MIN):
00309                 print "Auto  saving  ; ",
00310             else:
00311                 print "Fixed saving  ; ",
00312             print "min period:%s\n\t\t\t  " % \
00313                     (format_pm_value(power_saving[1]), ),
00314             print "max period:%s\n\t " % (format_pm_value(power_saving[2]), ),
00315         if power_params.disabled:
00316             print "Current mode:off"
00317         else:
00318             if (power_params.flags & pythonwifi.flags.IW_POWER_MODE == \
00319                         pythonwifi.flags.IW_POWER_UNICAST_R):
00320                 print "Current mode:Unicast only received"
00321             elif (power_params.flags & pythonwifi.flags.IW_POWER_MODE == \
00322                         pythonwifi.flags.IW_POWER_MULTICAST_R):
00323                 print "Current mode:Multicast only received"
00324             elif (power_params.flags & pythonwifi.flags.IW_POWER_MODE == \
00325                         pythonwifi.flags.IW_POWER_ALL_R):
00326                 print "Current mode:All packets received"
00327             elif (power_params.flags & pythonwifi.flags.IW_POWER_MODE == \
00328                         pythonwifi.flags.IW_POWER_FORCE_S):
00329                 print "Current mode:Force sending"
00330             elif (power_params.flags & pythonwifi.flags.IW_POWER_MODE == \
00331                         pythonwifi.flags.IW_POWER_REPEATER):
00332                 print "Current mode:Repeat multicasts"
00333         print
00334 
00335 def print_txpower(wifi, args=None):
00336     """ Print transmit power info for the card.
00337 
00338     """
00339     pass
00340 
00341 def print_retry(wifi, args=None):
00342     try:
00343         range_info = Iwrange(wifi.ifname)
00344     except IOError, (error_number, error_string):
00345         if (error_number == errno.EOPNOTSUPP) or \
00346            (error_number == errno.EINVAL) or \
00347            (error_number == errno.ENODEV):
00348             sys.stderr.write("%-8.16s  no retry limit/lifetime information.\n\n" % (
00349                             wifi.ifname, ))
00350     else:
00351         ifname = "%-8.16s  "  % (wifi.ifname, )
00352         if (range_info.retry_flags & pythonwifi.flags.IW_RETRY_LIMIT):
00353             if (range_info.retry_flags & pythonwifi.flags.IW_RETRY_MIN):
00354                 limit = "Auto  limit    ;  min limit:%d" % (
00355                     range_info.min_retry, )
00356             else:
00357                 limit = "Fixed limit    ;  min limit:%d" % (
00358                     range_info.min_retry, )
00359             print ifname + limit
00360             ifname = None
00361             print "                            max limit:%d" % (
00362                 range_info.max_retry, )
00363         if (range_info.r_time_flags & pythonwifi.flags.IW_RETRY_LIFETIME):
00364             if (range_info.r_time_flags & pythonwifi.flags.IW_RETRY_MIN):
00365                 lifetime = "Auto  lifetime ;  min lifetime:%d" % (
00366                     range_info.min_r_time, )
00367             else:
00368                 lifetime = "Fixed lifetime ;  min lifetime:%d" % (
00369                     range_info.min_r_time, )
00370             if ifname:
00371                 print ifname + lifetime
00372                 ifname = None
00373             else:
00374                 print "          " + lifetime
00375             print "                            max lifetime:%d" % (
00376                 range_info.max_r_time, )
00377         iwparam = wifi.wireless_info.getRetry()
00378         if iwparam.disabled:
00379             print "          Current mode:off"
00380         else:
00381             print "          Current mode:on"
00382             if (iwparam.flags & pythonwifi.flags.IW_RETRY_TYPE):
00383                 if (iwparam.flags & pythonwifi.flags.IW_RETRY_LIFETIME):
00384                     mode_type = "lifetime"
00385                 else:
00386                     mode_type = "limit"
00387                 mode = "                 "
00388                 if (iwparam.flags & pythonwifi.flags.IW_RETRY_MIN):
00389                     mode = mode + " min %s:%d" % (mode_type, iwparam.value)
00390                 if (iwparam.flags & pythonwifi.flags.IW_RETRY_MAX):
00391                     mode = mode + " max %s:%d" % (mode_type, iwparam.value)
00392                 if (iwparam.flags & pythonwifi.flags.IW_RETRY_SHORT):
00393                     mode = mode + " short %s:%d" % (mode_type, iwparam.value)
00394                 if (iwparam.flags & pythonwifi.flags.IW_RETRY_LONG):
00395                     mode = mode + " long %s:%d" % (mode_type, iwparam.value)
00396                 print mode
00397 
00398 def print_aps(wifi, args=None):
00399     """ Print the access points detected nearby.
00400 
00401         iwlist.c uses the deprecated SIOCGIWAPLIST, but iwlist.py uses
00402         regular scanning (i.e. Wireless.scan()).
00403 
00404     """
00405     # "Check if the interface could support scanning"
00406     try:
00407         iwrange = Iwrange(wifi.ifname)
00408     except IOError, (error_number, error_string):
00409         sys.stderr.write("%-8.16s  Interface doesn't support scanning.\n\n" % (
00410                             wifi.ifname))
00411     else:
00412         # "Check for Active Scan (scan with specific essid)"
00413         # "Check for last scan result (do not trigger scan)"
00414         # "Initiate Scanning"
00415         try:
00416             results = wifi.scan()
00417         except IOError, (error_number, error_string):
00418             if error_number != errno.EPERM:
00419                 sys.stderr.write(
00420                     "%-8.16s  Interface doesn't support scanning : %s\n\n" %
00421                     (wifi.ifname, error_string))
00422         else:
00423             if (len(results) == 0):
00424                 print "%-8.16s  Interface doesn't have " % (wifi.ifname, ) + \
00425                       "a list of Peers/Access-Points"
00426             else:
00427                 print "%-8.16s  Peers/Access-Points in range:"% (wifi.ifname, )
00428                 for ap in results:
00429                     if (ap.quality.quality):
00430                         if (ap.quality.updated & \
00431                                     pythonwifi.flags.IW_QUAL_QUAL_UPDATED):
00432                             quality_updated = "="
00433                         else:
00434                             quality_updated = ":"
00435                         if (ap.quality.updated & \
00436                                     pythonwifi.flags.IW_QUAL_LEVEL_UPDATED):
00437                             signal_updated = "="
00438                         else:
00439                             signal_updated = ":"
00440                         if (ap.quality.updated & \
00441                                     pythonwifi.flags.IW_QUAL_NOISE_UPDATED):
00442                             noise_updated = "="
00443                         else:
00444                             noise_updated = ":"
00445                         print "    %s : Quality%c%s/%s  Signal level%c%s/%s  Noise level%c%s/%s" % \
00446                             (ap.bssid,
00447                             quality_updated,
00448                             ap.quality.quality,
00449                             wifi.getQualityMax().quality,
00450                             signal_updated,
00451                             ap.quality.getSignallevel(),
00452                             "100",
00453                             noise_updated,
00454                             ap.quality.getNoiselevel(),
00455                             "100")
00456                     else:
00457                         print "    %s" % (ap.bssid, )
00458                 print
00459 
00460 
00461 def report_error(function, interface, error_number, error_string):
00462     """ Print error to user. """
00463     print """Uncaught error condition.  Please report this to the \
00464 developers' mailing list (informaion available at \
00465 http://lists.berlios.de/mailman/listinfo/pythonwifi-dev).  While attempting to \
00466 print %s informaion for %s, the error "%d - %s" occurred.""" % \
00467 (function, interface, error_number, error_string)
00468 
00469 def usage():
00470     print """\
00471 Usage: iwlist.py [interface] scanning [essid NNN] [last]
00472                  [interface] frequency
00473                  [interface] channel
00474                  [interface] bitrate
00475                  [interface] encryption
00476                  [interface] keys
00477                  [interface] power
00478                  [interface] txpower
00479                  [interface] retry
00480                  [interface] ap
00481                  [interface] accesspoints
00482                  [interface] peers"""
00483 
00484 def get_matching_command(option):
00485     """ Return a function for the command.
00486 
00487         'option' -- string -- command to match
00488 
00489         Return None if no match found.
00490 
00491     """
00492     # build dictionary of commands and functions
00493     iwcommands = { "s"   : ("scanning", print_scanning_results),
00494                    "c"   : ("channel", print_channels),
00495                    "f"   : ("frequency", print_channels),
00496                    "b"   : ("bitrate", print_bitrates),
00497                    "ra"  : ("rate", print_bitrates),
00498                    "en"  : ("encryption", print_encryption),
00499                    "k"   : ("keys", print_encryption),
00500                    "po"  : ("power", print_power),
00501                    "t"   : ("txpower", print_txpower),
00502                    "re"  : ("retry", print_retry),
00503                    "ap"  : ("ap", print_aps),
00504                    "ac"  : ("accesspoints", print_aps),
00505                    "pe"  : ("peers", print_aps),
00506                    #"ev" : ("event", print_event),
00507                    #"au" : ("auth", print_auth),
00508                    #"w"  : ("wpakeys", print_wpa),
00509                    #"g"  : ("genie", print_genie),
00510                    #"m"  : ("modulation", print_modulation),
00511                  }
00512 
00513     function = None
00514     for command in iwcommands.keys():
00515         if option.startswith(command):
00516             if iwcommands[command][0].startswith(option):
00517                 function = iwcommands[command][1]
00518     return function
00519 
00520 def main():
00521     # if only program name is given, print usage info
00522     if len(sys.argv) == 1:
00523         usage()
00524 
00525     # if program name and one argument are given
00526     if len(sys.argv) == 2:
00527         option = sys.argv[1]
00528         # look for matching command
00529         list_command = get_matching_command(option)
00530         # if the one argument is a command
00531         if list_command is not None:
00532             for ifname in getNICnames():
00533                 wifi = Wireless(ifname)
00534                 list_command(wifi)
00535         else:
00536             print "iwlist.py: unknown command `%s' " \
00537                   "(check 'iwlist.py --help')." % (option, )
00538 
00539     # if program name and more than one argument are given
00540     if len(sys.argv) > 2:
00541         # Get the interface and command from command line
00542         ifname, option = sys.argv[1:]
00543         # look for matching command
00544         list_command = get_matching_command(option)
00545         # if the second argument is a command
00546         if list_command is not None:
00547             wifi = Wireless(ifname)
00548             list_command(wifi, sys.argv[3:])
00549         else:
00550             print "iwlist.py: unknown command `%s' " \
00551                    "(check 'iwlist.py --help')." % (option, )
00552 
00553 
00554 if __name__ == "__main__":
00555     main()
00556 


rocon_python_wifi
Author(s): Róman Joost, Sean Robinson
autogenerated on Fri May 2 2014 10:35:45