From 02a0875646ee25bb3767930d04102e6cafbb8278 Mon Sep 17 00:00:00 2001 From: kriss Date: Sat, 26 Jul 2008 18:05:00 +0000 Subject: [PATCH] FEATURE: First implementation of a WiFi panel. Done by John Beaven as part of the mofi project: http://projects.openmoko.org/projects/mofi/ - Thanks! git-svn-id: http://www.neo1973-germany.de/svn@84 46df4e5c-bc4e-4628-a0fc-830ba316316d --- .../trunk/src/settingsgui/MofiPanel.py | 245 ++++ .../trunk/src/settingsgui/SettingsGUI.py | 5 +- .../trunk/src/settingsgui/pythonwifi/LICENSE | 504 ++++++++ .../trunk/src/settingsgui/pythonwifi/PKG-INFO | 23 + .../trunk/src/settingsgui/pythonwifi/README | 153 +++ .../src/settingsgui/pythonwifi/__init__.py | 1 + .../settingsgui/pythonwifi/flags.latin1.py | 104 ++ .../trunk/src/settingsgui/pythonwifi/flags.py | 103 ++ .../settingsgui/pythonwifi/iwlibs.latin1.py | 1115 +++++++++++++++++ 9 files changed, 2252 insertions(+), 1 deletion(-) create mode 100644 SettingsGUI/trunk/src/settingsgui/MofiPanel.py create mode 100644 SettingsGUI/trunk/src/settingsgui/pythonwifi/LICENSE create mode 100644 SettingsGUI/trunk/src/settingsgui/pythonwifi/PKG-INFO create mode 100644 SettingsGUI/trunk/src/settingsgui/pythonwifi/README create mode 100644 SettingsGUI/trunk/src/settingsgui/pythonwifi/__init__.py create mode 100644 SettingsGUI/trunk/src/settingsgui/pythonwifi/flags.latin1.py create mode 100644 SettingsGUI/trunk/src/settingsgui/pythonwifi/flags.py create mode 100644 SettingsGUI/trunk/src/settingsgui/pythonwifi/iwlibs.latin1.py diff --git a/SettingsGUI/trunk/src/settingsgui/MofiPanel.py b/SettingsGUI/trunk/src/settingsgui/MofiPanel.py new file mode 100644 index 0000000..76d4cf9 --- /dev/null +++ b/SettingsGUI/trunk/src/settingsgui/MofiPanel.py @@ -0,0 +1,245 @@ +""" + * MofiPanel.py - SettingsGUI - Wireless AP Connection Settings + * + * Added and programmed by John Beaven + * + * (C) 2007 by Kristian Mueller + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +""" + +import sys +import os +import gtk + +from settingsgui.pythonwifi.iwlibs import Wireless, getNICnames +from ConfigParser import * +import os +import subprocess + +class MofiPanel(gtk.VBox): + def __init__(self): + + gtk.VBox.__init__(self, False, 0) + + self.config = ConfigParser() + self.config.read(os.path.join(os.environ['HOME'], '.mofi.conf')) + + self.ap_ui = {} + + self.create_notebook_page() + + def get_aps(self): + + found_aps = {} + + # search for accesspoints the interfaces can access.. + # and show list of connections to user.. + for ifname in getNICnames(): + + wifi = Wireless(ifname) + essid = wifi.getEssid() + + wifi.scan() + for results in wifi.scan(): + + enc_type = "unknown" + + # seems encryption [0x0,0x0,0x0,0x8] is WPA, [0x0,0x0,0x0,0x80] is open + enc = map(lambda x: hex(ord(x)), results.encode) + + if enc[3] == '0x80': + enc_type = "open" + elif enc[3] == '0x8': + enc_type = "WPA" + + # see if we have a config setting for this essid.. + password = '' + if self.config.has_option(results.essid, 'password'): + password = str(self.config.get(results.essid, 'password')) + + #print "ESSID:", results.essid + #print "PASSWORD:", password + #print "Access point:", results.bssid + #print "Mode:", results.mode + #if len(results.rate) > 0: + # print "Highest Bitrate:", results.rate[len(results.rate)-1] + #print "Quality: Quality ", results.quality.quality, "Signal ", results.quality.getSignallevel(), " Noise ", results.quality.getNoiselevel() + + found_aps[results.essid] = {'essid':results.essid, 'enc':enc_type, 'password':password, 'connected': (essid == results.essid)} + + return found_aps + + def generate_wpa_supplicant(self, pref = []): + + found_aps = self.get_aps() + + print 'generating wpa_supplicant configuration' + + prefered_order = pref + + if self.config.has_option('DEFAULT', 'prefered_order'): + prefered_order += str(self.config.get('DEFAULT', 'prefered_order')).split(',') + + # generate wpa_supplicant.conf from retrieved data.. + # if we have no pass, just assume open network.. + wpa_conf = """#NOTE: this file is overwritten by mofi - do not edit! +ctrl_interface=/var/run/wpa_supplicant +eapol_version=1 +ap_scan=1 +""" + + # prioritise aps in prefered_order from conf.. + for aps in prefered_order: + + if aps in found_aps: + + wpa_conf += """ +network={ + ssid="%s" + scan_ssid=1 + key_mgmt=WPA-PSK + pairwise=CCMP TKIP + group=TKIP CCMP + psk="%s" + priority=10 +}""" %(aps, found_aps[aps]['password']) + + del found_aps[aps] + + # finally gen open connections for remaining aps.. + for aps in found_aps: + + wpa_conf += """ +network={ + ssid="%s" + key_mgmt=NONE + priority=5 +}""" %(aps) + + + # save config to file + FILE = open(os.path.join(os.environ['HOME'], 'mofi_wpa_supplicant.conf'),"w") + FILE.write(wpa_conf) + FILE.close() + + + def create_notebook_page(self): + + # nasty nasty gui - sorry, I'm in a hurry! + + for child in self.get_children(): + self.remove(child) + + aps = self.get_aps() + self.last_aps = aps + + button_scan = gtk.Button("Scan (update)") + + def scan_update(caller): + self.create_notebook_page() + + button_scan.connect("clicked", scan_update) + + grpAps = None + + for essid in aps: + + # handle hidden Network names + if '\x00' in essid: + hidden_essid = essid.replace("\x00", "*") + radio = gtk.RadioButton(grpAps, "%s (%s)" \ + %(hidden_essid,aps[essid]['enc'])) + else: + radio = gtk.RadioButton(grpAps, "%s (%s)"%(essid,aps[essid]['enc'])) + + radio.set_active(aps[essid]['connected']); + grpAps = radio + + connected_str = '' + if aps[essid]['connected']: + connected_str = 'connected, ' + + self.ap_ui[essid] = radio + + self.passbox = gtk.HBox() + self.passbox.add(gtk.Label('Password:')) + self.password = gtk.Entry() + self.passbox.add(self.password) + button_save = gtk.Button("save") + def on_save(caller): + if not self.config.has_section(self.connecting_to): + self.config.add_section(self.connecting_to) + self.config.set(self.connecting_to, 'password', self.password.get_text()) + FILE = open(os.path.join(os.environ['HOME'], '.mofi.conf'),"w") + self.config.write(FILE) + FILE.close() + self.last_aps[self.connecting_to]['password'] = self.password.get_text() + self.button_connect.show() + self.passbox.hide() + connect_selected(caller) + + button_save.connect("clicked", on_save) + self.passbox.add(button_save) + + + def connect_selected(caller): + for essid in self.ap_ui: + if self.ap_ui[essid].get_active(): + + self.connecting_to = essid + + l.set_text('') + + #make sure we have a password for the AP.. + if self.last_aps[essid]['enc'] == 'WPA' and self.last_aps[essid]['password'] == '': + + print 'get the password..' + self.password.set_text(self.last_aps[essid]['password']) + self.button_connect.hide() + self.passbox.show() + return + + self.generate_wpa_supplicant([essid]) + + # call our connection shell script and capture the output.. + proc = subprocess.Popen([r"sh", "./connect.sh"], stdout=subprocess.PIPE) + proc.wait() + output = proc.stdout.read() + + print "out: "+output + l.set_text(output) + + return + + self.button_connect = gtk.Button("Connect to selected") + self.button_connect.connect("clicked", connect_selected) + + l = gtk.Label('') + l.set_line_wrap(True) + + + self.pack_start(button_scan, False, False, 2) + for essid in self.ap_ui: + self.pack_start(self.ap_ui[essid], False, False, 2) + self.pack_start(self.button_connect, False, False, 2) + self.pack_start(self.passbox, False, False, 2) + self.pack_start(l, False, False, 2) + + self.show_all() + self.passbox.hide() + + diff --git a/SettingsGUI/trunk/src/settingsgui/SettingsGUI.py b/SettingsGUI/trunk/src/settingsgui/SettingsGUI.py index abe2b9c..02b5348 100644 --- a/SettingsGUI/trunk/src/settingsgui/SettingsGUI.py +++ b/SettingsGUI/trunk/src/settingsgui/SettingsGUI.py @@ -89,6 +89,7 @@ class SettingsGUI: from GSMPanel import GSMPanel from GPRSPanel import GPRSPanel from BluetoothPanel import BluetoothPanel + from MofiPanel import MofiPanel print "0.3: %s" %(time.time() - start_time) @@ -113,13 +114,15 @@ class SettingsGUI: print "5: %s" %(time.time() - start_time) self.add_notebook_page(BluetoothPanel(), "gtk-connect") print "6: %s" %(time.time() - start_time) + self.add_notebook_page(MofiPanel(), "gtk-network") + print "7: %s" %(time.time() - start_time) ## expand page selectors to full width for child in self.notebook.get_children(): self.notebook.child_set_property(child, "tab_expand", True) self.notebook.show() - print "7: %s" %(time.time() - start_time) + print "8: %s" %(time.time() - start_time) #self.main_panel.add(self.notebook) diff --git a/SettingsGUI/trunk/src/settingsgui/pythonwifi/LICENSE b/SettingsGUI/trunk/src/settingsgui/pythonwifi/LICENSE new file mode 100644 index 0000000..5ab7695 --- /dev/null +++ b/SettingsGUI/trunk/src/settingsgui/pythonwifi/LICENSE @@ -0,0 +1,504 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! + + diff --git a/SettingsGUI/trunk/src/settingsgui/pythonwifi/PKG-INFO b/SettingsGUI/trunk/src/settingsgui/pythonwifi/PKG-INFO new file mode 100644 index 0000000..9366ae1 --- /dev/null +++ b/SettingsGUI/trunk/src/settingsgui/pythonwifi/PKG-INFO @@ -0,0 +1,23 @@ +Metadata-Version: 1.0 +Name: python-wifi +Version: 0.3 +Summary: Python-wifi is a Python wireless library. +Home-page: http://www.romanofski.de/downloads/pywifi/ +Author: Róman Joost +Author-email: roman@bromeco.de +License: LGPL +Description: Pywifi is a Python library that provides access to + information about a W-Lan card's capabilities, like the wireless + extensions written in C. + + + + +Platform: UNKNOWN +Classifier: Development Status :: 4 - Beta +Classifier: Intended Audience :: Developers +Classifier: Intended Audience :: Information Technology +Classifier: License :: OSI Approved :: GNU Lesser General Public License (LGPL) +Classifier: Programming Language :: Python +Classifier: Operating System :: Posix :: Linux +Classifier: Topic :: System :: Networking diff --git a/SettingsGUI/trunk/src/settingsgui/pythonwifi/README b/SettingsGUI/trunk/src/settingsgui/pythonwifi/README new file mode 100644 index 0000000..cf2a464 --- /dev/null +++ b/SettingsGUI/trunk/src/settingsgui/pythonwifi/README @@ -0,0 +1,153 @@ +############################################# +# +# Please, check also the 'docs' directory! +# +############################################# + +python-wifi - README +==================== + +I startet to write a python library which reads wireless data from the +kernel like the wireless extensions. In order to know how to handle all +this binary encrypted C structure stuff, Guido Goldstein from Infrae +helped me to getting started. Thanks to him! + +I want to see some output! +-------------------------- +I've implemented some example programs which use the functionality of +the libraries. You'll find them in the 'examples' directory. + +Files: +------ + + - pyiwconfig, pyiwlist: the corresponding python programs to the C + correspondents. These are example implementations. + - iwlibs.py: handles all the black magic ;) + +Installing: +----------- +If you want an easy install, use the .egg file and install it via +easy_install. See: + + http://peak.telecommunity.com/DevCenter/EasyInstall + +Python Wireless users: +---------------------- +If you want to use the wirless library, the methods in the Wireless +class are the ones you want. Lets assume a little example program, which +prints the ESSID: + + >>> from pythonwifi.iwlibs import Wireless + >>> wifi = Wireless('eth1') + >>> wifi.getEssid() + 'romanofski' + >>> wifi.getMode() + 'Managed' + +Python Wireless developers: +--------------------------- +So, you want to know what the other classes doing? Well, lets talk about +the wireless tools at first. If you don't know anything about C, forget +the following information. Learn C first or at least read some tutorials +about C (I don't know C very well, but know how to handle all this C +stuff which works for me ;). + +The wireless tools store the request in a union which is passed with a +pointer to the kernel by a system call. The union is defined in the +wireless.h and holds the following structures: + + union iwreq_data + { + /* Config - generic */ + char name[IFNAMSIZ]; + /* Name : used to verify the presence of wireless extensions. + * Name of the protocol/provider... */ + + struct iw_point essid; /* Extended network name */ + struct iw_param nwid; /* network id (or domain - the cell) */ + struct iw_freq freq; /* frequency or channel : + * 0-1000 = channel + * > 1000 = frequency in Hz */ + + struct iw_param sens; /* signal level threshold */ + struct iw_param bitrate; /* default bit rate */ + struct iw_param txpower; /* default transmit power */ + struct iw_param rts; /* RTS threshold threshold */ + struct iw_param frag; /* Fragmentation threshold */ + __u32 mode; /* Operation mode */ + struct iw_param retry; /* Retry limits & lifetime */ + + struct iw_point encoding; /* Encoding stuff : tokens */ + struct iw_param power; /* PM duration/timeout */ + struct iw_quality qual; /* Quality part of statistics */ + + struct sockaddr ap_addr; /* Access point address */ + struct sockaddr addr; /* Destination address (hw/mac) */ + + struct iw_param param; /* Other small parameters */ + struct iw_point data; /* Other large parameters */ + }; + +Well, anyway -- the interesting thing here is, that I need to build a +C struct in Python, where the kernel can write his information in. +For example the ESSID (relevant methods are: pack_wrq and iw_get_ext in +Iwstruct): + + First, we build a buffer with a buffersize of 32 + byte: + + buff = array.array('c', '\0'*buffsize) + + Then, the system call needs the address of this buffer and the + length, which can be optained by a method on the buffer. + This information need to be packed in C like style by 'struct': + + caddr_t, length = buff.buffer_info() + s = struct.pack('Pi', caddr_t, length) + + Then, the request can be made by specifying the interface name, + which is passed as a second argument to the ioctl method. + +Please let me help you! +----------------------- + + Well, thanks for your help. This python library is a learning project + for me and if you're able to pass me some hints for a better + coding style, I would be thankful. + + If you already know, how to gather information out of the kernel and + know how to handle all this stuff better, let me know. But please + don't implement something which is not in the current release. Some + of us spared unnecessary time on something, which can be handled with + a little bit more communication. + + So, if you wanna help me, drop me an e-mail (roman@bromeco.de). + +What is implemented? +-------------------- + + - pyiwconfig: + + read write + --------------------------------||-------- + Accesspoint MAC Mode + Bitrate + available Bitrates + available Channels/Frequency + ESSID + Encryption + Frequency + Mode + WirelessName + Powermanagement + Retrylimit + RTS + Sensitivity + TXPower + Statistics + + - pyiwlist: prints detailed information about: + + o Bitrates + o Channels/Frequency + o Scanning support! diff --git a/SettingsGUI/trunk/src/settingsgui/pythonwifi/__init__.py b/SettingsGUI/trunk/src/settingsgui/pythonwifi/__init__.py new file mode 100644 index 0000000..ca0d2c4 --- /dev/null +++ b/SettingsGUI/trunk/src/settingsgui/pythonwifi/__init__.py @@ -0,0 +1 @@ +# make it a python package diff --git a/SettingsGUI/trunk/src/settingsgui/pythonwifi/flags.latin1.py b/SettingsGUI/trunk/src/settingsgui/pythonwifi/flags.latin1.py new file mode 100644 index 0000000..63910f6 --- /dev/null +++ b/SettingsGUI/trunk/src/settingsgui/pythonwifi/flags.latin1.py @@ -0,0 +1,104 @@ +# -*- coding: latin1 -*- +# python-wifi -- a wireless library to access wireless cards via python +# Copyright (C) 2004, 2005, 2006 Róman Joost +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public License +# as published by the Free Software Foundation; either version 2.1 of +# the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +# USA + +modes = ['Auto', + 'Ad-Hoc', + 'Managed', + 'Master', + 'Repeat', + 'Second', + 'Monitor'] + +IFNAMSIZE = 16 +IW_ESSID_MAX_SIZE = 16 + +KILO = 10**3 +MEGA = 10**6 +GIGA = 10**9 + +# ioctl calls for the Linux/i386 kernel +SIOCIWFIRST = 0x8B00 # FIRST ioctl identifier +SIOCGIFCONF = 0x8912 # ifconf struct +SIOCGIWNAME = 0x8B01 # get name == wireless protocol +SIOCGIWFREQ = 0x8B05 # get channel/frequency +SIOCSIWMODE = 0x8B06 # set the operation mode +SIOCGIWMODE = 0x8B07 # get operation mode +SIOCGIWSENS = 0x8B09 # get sensitivity +SIOCGIWAP = 0x8B15 # get AP MAC address +SIOCSIWSCAN = 0x8B18 # set scanning off +SIOCGIWSCAN = 0x8B19 # get scanning results +SIOCGIWRATE = 0x8B21 # get default bit rate +SIOCGIWRTS = 0x8B23 # get rts/cts threshold +SIOCGIWFRAG = 0x8B25 # get fragmention thrh +SIOCGIWTXPOW = 0x8B27 # get transmit power (dBm) +SIOCGIWRETRY = 0x8B29 # get retry limit +SIOCGIWRANGE = 0x8B0B # range +SIOCGIWSTATS = 0x8B0F # get wireless statistics +SIOCSIWESSID = 0x8B1A # set essid +SIOCGIWESSID = 0x8B1B # get essid +SIOCGIWPOWER = 0x8B2D # get power managment settings +SIOCGIWENCODE = 0x8B2B # get encryption information +SIOCIWLAST = 0x8BFF # LAST ioctl identifier + +# Power management flags +IW_POWER_ON = 0x0000 # No details ... +IW_POWER_TYPE = 0xF000 # Type of parameter +IW_POWER_PERIOD = 0x1000 # Value is a period/duration of +IW_POWER_TIMEOUT = 0x2000 # Value is a timeout +IW_POWER_MODE = 0x0F00 # Power management mode +IW_POWER_MIN = 0x0001 # Value is a minimum +IW_POWER_MAX = 0x0002 # Value is a maximum +IW_POWER_RELATIVE = 0x0004 # Value is not in seconds/ms/us + +# Retry limits +IW_RETRY_TYPE = 0xF000 # Type of parameter + +# encoding stuff +IW_ENCODE_DISABLED = 0x8000 # encoding is disabled +IW_ENCODE_NOKEY = 0x0800 # key is write only, not present + +# constants responsible for scanning +IW_SCAN_MAX_DATA = 4096 + +IW_EV_LCP_LEN = 4 +IW_EV_CHAR_LEN = IW_EV_LCP_LEN + IFNAMSIZE +IW_EV_UINT_LEN = IW_EV_LCP_LEN + 4 +IW_EV_FREQ_LEN = IW_EV_LCP_LEN + 8 +IW_EV_ADDR_LEN = IW_EV_LCP_LEN + 16 +IW_EV_POINT_LEN = IW_EV_LCP_LEN + 4 +IW_EV_PARAM_LEN = IW_EV_LCP_LEN + 8 +IW_EV_QUAL_LEN = IW_EV_LCP_LEN + 4 + +EPERM = 1 +E2BIG = 7 +EAGAIN = 11 + +IWHT_NULL = 0 +IWHT_CHAR = 2 +IWHT_UINT = 4 +IWHT_FREQ = 5 +IWHT_ADDR = 6 +IWHT_POINT = 8 +IWHT_PARAM = 9 +IWHT_QUAL = 10 + +IWEVFIRST = 0x8C00 # FIRST event identifier +IWEVQUAL = 0x8C01 # Quality statistics from scan +IWEVCUSTOM = 0x8C02 # Custom Ascii string from Driver +IWEVLAST = 0x8C0A # LAST event identifier diff --git a/SettingsGUI/trunk/src/settingsgui/pythonwifi/flags.py b/SettingsGUI/trunk/src/settingsgui/pythonwifi/flags.py new file mode 100644 index 0000000..7b91dd5 --- /dev/null +++ b/SettingsGUI/trunk/src/settingsgui/pythonwifi/flags.py @@ -0,0 +1,103 @@ +# python-wifi -- a wireless library to access wireless cards via python +# Copyright (C) 2004, 2005, 2006 Roman Joost +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public License +# as published by the Free Software Foundation; either version 2.1 of +# the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +# USA + +modes = ['Auto', + 'Ad-Hoc', + 'Managed', + 'Master', + 'Repeat', + 'Second', + 'Monitor'] + +IFNAMSIZE = 16 +IW_ESSID_MAX_SIZE = 16 + +KILO = 10**3 +MEGA = 10**6 +GIGA = 10**9 + +# ioctl calls for the Linux/i386 kernel +SIOCIWFIRST = 0x8B00 # FIRST ioctl identifier +SIOCGIFCONF = 0x8912 # ifconf struct +SIOCGIWNAME = 0x8B01 # get name == wireless protocol +SIOCGIWFREQ = 0x8B05 # get channel/frequency +SIOCSIWMODE = 0x8B06 # set the operation mode +SIOCGIWMODE = 0x8B07 # get operation mode +SIOCGIWSENS = 0x8B09 # get sensitivity +SIOCGIWAP = 0x8B15 # get AP MAC address +SIOCSIWSCAN = 0x8B18 # set scanning off +SIOCGIWSCAN = 0x8B19 # get scanning results +SIOCGIWRATE = 0x8B21 # get default bit rate +SIOCGIWRTS = 0x8B23 # get rts/cts threshold +SIOCGIWFRAG = 0x8B25 # get fragmention thrh +SIOCGIWTXPOW = 0x8B27 # get transmit power (dBm) +SIOCGIWRETRY = 0x8B29 # get retry limit +SIOCGIWRANGE = 0x8B0B # range +SIOCGIWSTATS = 0x8B0F # get wireless statistics +SIOCSIWESSID = 0x8B1A # set essid +SIOCGIWESSID = 0x8B1B # get essid +SIOCGIWPOWER = 0x8B2D # get power managment settings +SIOCGIWENCODE = 0x8B2B # get encryption information +SIOCIWLAST = 0x8BFF # LAST ioctl identifier + +# Power management flags +IW_POWER_ON = 0x0000 # No details ... +IW_POWER_TYPE = 0xF000 # Type of parameter +IW_POWER_PERIOD = 0x1000 # Value is a period/duration of +IW_POWER_TIMEOUT = 0x2000 # Value is a timeout +IW_POWER_MODE = 0x0F00 # Power management mode +IW_POWER_MIN = 0x0001 # Value is a minimum +IW_POWER_MAX = 0x0002 # Value is a maximum +IW_POWER_RELATIVE = 0x0004 # Value is not in seconds/ms/us + +# Retry limits +IW_RETRY_TYPE = 0xF000 # Type of parameter + +# encoding stuff +IW_ENCODE_DISABLED = 0x8000 # encoding is disabled +IW_ENCODE_NOKEY = 0x0800 # key is write only, not present + +# constants responsible for scanning +IW_SCAN_MAX_DATA = 4096 + +IW_EV_LCP_LEN = 4 +IW_EV_CHAR_LEN = IW_EV_LCP_LEN + IFNAMSIZE +IW_EV_UINT_LEN = IW_EV_LCP_LEN + 4 +IW_EV_FREQ_LEN = IW_EV_LCP_LEN + 8 +IW_EV_ADDR_LEN = IW_EV_LCP_LEN + 16 +IW_EV_POINT_LEN = IW_EV_LCP_LEN + 4 +IW_EV_PARAM_LEN = IW_EV_LCP_LEN + 8 +IW_EV_QUAL_LEN = IW_EV_LCP_LEN + 4 + +EPERM = 1 +E2BIG = 7 +EAGAIN = 11 + +IWHT_NULL = 0 +IWHT_CHAR = 2 +IWHT_UINT = 4 +IWHT_FREQ = 5 +IWHT_ADDR = 6 +IWHT_POINT = 8 +IWHT_PARAM = 9 +IWHT_QUAL = 10 + +IWEVFIRST = 0x8C00 # FIRST event identifier +IWEVQUAL = 0x8C01 # Quality statistics from scan +IWEVCUSTOM = 0x8C02 # Custom Ascii string from Driver +IWEVLAST = 0x8C0A # LAST event identifier diff --git a/SettingsGUI/trunk/src/settingsgui/pythonwifi/iwlibs.latin1.py b/SettingsGUI/trunk/src/settingsgui/pythonwifi/iwlibs.latin1.py new file mode 100644 index 0000000..74dca9e --- /dev/null +++ b/SettingsGUI/trunk/src/settingsgui/pythonwifi/iwlibs.latin1.py @@ -0,0 +1,1115 @@ +# coding=latin1 +# python-wifi -- a wireless library to access wireless cards via python +# Copyright (C) 2004, 2005, 2006 Róman Joost +# +# Contributions from: +# Mike Auty (Iwscanresult, Iwscan) +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public License +# as published by the Free Software Foundation; either version 2.1 of +# the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +# USA + +import struct +import array +import math +import fcntl +import socket +import time +import re + +from types import StringType +from flags import * + +def getNICnames(): + """ extract wireless device names of /proc/net/wireless + + returns empty list if no devices are present + + >>> getNICnames() + ['eth1', 'wifi0'] + """ + device = re.compile('[a-z]{3,4}[0-9]') + ifnames = [] + + f = open('/proc/net/wireless', 'r') + data = f.readlines() + for line in data: + try: + ifnames.append(device.search(line).group()) + except AttributeError: + pass + # if we couldn't lookup the devices, try to ask the kernel + if ifnames == []: + ifnames = getConfiguredNICnames() + + return ifnames + +def getConfiguredNICnames(): + """get the *configured* ifnames by a systemcall + + >>> getConfiguredNICnames() + [] + """ + iwstruct = Iwstruct() + ifnames = [] + buff = array.array('c', '\0'*1024) + caddr_t, length = buff.buffer_info() + s = iwstruct.pack('iP', length, caddr_t) + try: + result = iwstruct._fcntl(SIOCGIFCONF, s) + except IOError, (i, e): + return i, e + + # get the interface names out of the buffer + for i in range(0, 1024, 32): + ifname = buff.tostring()[i:i+32] + ifname = struct.unpack('32s', ifname)[0] + ifname = ifname.split('\0', 1)[0] + if ifname: + # verify if ifnames are really wifi devices + wifi = Wireless(ifname) + result = wifi.getAPaddr() + if result[0] == 0: + ifnames.append(ifname) + + return ifnames + +def makedict(**kwargs): + return kwargs + + +class Wireless(object): + """Access to wireless interfaces""" + + def __init__(self, ifname): + self.sockfd = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + self.ifname = ifname + self.iwstruct = Iwstruct() + + def getAPaddr(self): + """ returns accesspoint mac address + + >>> from iwlibs import Wireless, getNICnames + >>> ifnames = getNICnames() + >>> ifnames + ['eth1', 'wifi0'] + >>> wifi = Wireless(ifnames[0]) + >>> wifi.getAPaddr() + '00:0D:88:8E:4E:93' + + Test with non-wifi card: + >>> wifi = Wireless('eth0') + >>> wifi.getAPaddr() + (95, 'Operation not supported') + + Test with non-existant card: + >>> wifi = Wireless('eth2') + >>> wifi.getAPaddr() + (19, 'No such device') + """ + buff, s = self.iwstruct.pack_wrq(32) + i, result = self.iwstruct.iw_get_ext(self.ifname, + SIOCGIWAP, + data=s) + if i > 0: + return (i, result) + + return self.iwstruct.getMAC(result) + + def getBitrate(self): + """returns device currently set bit rate + + >>> from iwlibs import Wireless + >>> wifi = Wireless('eth1') + >>> wifi.getBitrate() + '11 Mb/s' + """ + i, result = self.iwstruct.iw_get_ext(self.ifname, + SIOCGIWRATE) + if i > 0: + return (i, result) + iwfreq = Iwfreq(result) + return iwfreq.getBitrate() + + def getBitrates(self): + """returns the number of available bitrates for the device + + >>> from iwlibs import Wireless + >>> wifi = Wireless('eth1') + >>> num, rates = wifi.getBitrates() + >>> num == len(rates) + True + """ + range = Iwrange(self.ifname) + if range.errorflag: + return (range.errorflag, range.error) + return (range.num_bitrates, range.bitrates) + + def getChannelInfo(self): + """returns the number of channels and available frequency for + the device + + >>> from iwlibs import Wireless + >>> wifi = Wireless('eth1') + >>> num, rates = wifi.getChannelInfo() + >>> num == len(rates) + True + """ + range = Iwrange(self.ifname) + if range.errorflag: + return (range.errorflag, range.error) + return (range.num_channels, range.frequencies) + + def getEssid(self): + """get essid information + + >>> from iwlibs import Wireless + >>> wifi = Wireless('eth1') + >>> wifi.getEssid() + 'romanofski' + """ + essid = "" + buff, s = self.iwstruct.pack_wrq(32) + i, result = self.iwstruct.iw_get_ext(self.ifname, + SIOCGIWESSID, + data=s) + if i > 0: + return (i, result) + str = buff.tostring() + return str.strip('\x00') + + def setEssid(self, essid): + """set essid """ + raise NotImplementedError + if len(essid) > IW_ESSID_MAX_SIZE: + return "essid to big" + buff, s = self.iwstruct.pack_test(essid, 32) + i, result = self.iwstruct.iw_get_ext(self.ifname, + SIOCSIWESSID, + data=s) + if i > 0: + return (i, result) + + def getEncryption(self): + """get encryption information which is probably a string of '*', + 'open', 'private' + + as a normal user, you will get a 'Operation not permitted' + error: + + >>> from iwlibs import Wireless + >>> wifi = Wireless('eth1') + >>> wifi.getEncryption() + (1, 'Operation not permitted') + """ + iwpoint = Iwpoint(self.ifname) + if iwpoint.errorflag: + return (iwpoint.errorflag, iwpoint.error) + return iwpoint.getEncryptionKey() + + def getFragmentation(self): + """returns fragmentation threshold + + It depends on what the driver says. If you have fragmentation + threshold turned on, you'll get an int. If it's turned of + you'll get a string: 'off'. + >>> from iwlibs import Wireless + >>> wifi = Wireless('eth1') + >>> wifi.getFragmentation() + 'off' + """ + iwparam = Iwparam(self.ifname, SIOCGIWFRAG) + if iwparam.errorflag: + return (iwparam.errorflag, iwparam.error) + return iwparam.getValue() + + def getFrequency(self): + """returns currently set frequency of the card + + >>> from iwlibs import Wireless + >>> wifi = Wireless('eth1') + >>> wifi.getFrequency() + '2.417GHz' + """ + i, r = self.iwstruct.iw_get_ext(self.ifname, + SIOCGIWFREQ) + if i > 0: + return (i, r) + iwfreq = Iwfreq(r) + return iwfreq.getFrequency() + + + def getMode(self): + """returns currently set operation mode + + >>> from iwlibs import Wireless + >>> wifi = Wireless('eth1') + >>> wifi.getMode() + 'Managed' + """ + i, result = self.iwstruct.iw_get_ext(self.ifname, + SIOCGIWMODE) + if i > 0: + return (i, result) + mode = self.iwstruct.unpack('i', result[:4])[0] + return modes[mode] + + def setMode(self, mode): + """sets the operation mode """ + try: + this_modes = [x.lower() for x in modes] + mode = mode.lower() + wifimode = this_modes.index(mode) + except ValueError: + return "Invalid operation mode!" + + s = self.iwstruct.pack('I', wifimode) + i, result = self.iwstruct.iw_get_ext(self.ifname, + SIOCSIWMODE, + data=s) + if i > 0: + return (i, result) + + def getWirelessName(self): + """ returns wireless name + + >>> from iwlibs import Wireless + >>> wifi = Wireless('eth1') + >>> wifi.getWirelessName() + 'IEEE 802.11-DS' + """ + i, result = self.iwstruct.iw_get_ext(self.ifname, + SIOCGIWNAME) + if i > 0: + return (i, result) + return result.split('\0')[0] + + def getPowermanagement(self): + """returns power management settings + + >>> from iwlibs import Wireless + >>> wifi = Wireless('eth1') + >>> wifi.getPowermanagement() + 'off' + """ + iwparam = Iwparam(self.ifname, SIOCGIWPOWER) + if iwparam.errorflag: + return (iwparam.errorflag, iwparam.error) + return iwparam.getValue() + + + def getRetrylimit(self): + """returns limit retry/lifetime + + man iwconfig: + Most cards have MAC retransmissions, and some allow to set + the behaviour of the retry mechanism. + + >>> from iwlibs import Wireless + >>> wifi = Wireless('eth1') + >>> wifi.getRetrylimit() + 16 + """ + iwparam = Iwparam(self.ifname, SIOCGIWRETRY) + if iwparam.errorflag: + return (iwparam.errorflag, iwparam.error) + return iwparam.getValue() + + def getRTS(self): + """returns rts threshold + + returns int, 'auto', 'fixed', 'off' + + man iwconfig: + RTS/CTS adds a handshake before each packet transmission to + make sure that the channel is clear. This adds overhead, but + increases performance in case of hidden nodes or a large + number of active nodes. This parameter sets the size of the + smallest packet for which the node sends RTS; a value equal + to the maximum packet size disable the mechanism. + + >>> from iwlibs import Wireless + >>> wifi = Wireless('eth1') + >>> wifi.getRTS() + 'off' + """ + iwparam = Iwparam(self.ifname, SIOCGIWRTS) + if iwparam.errorflag: + return (iwparam.errorflag, iwparam.error) + return iwparam.getValue() + + def getSensitivity(self): + """returns sensitivity information + + man iwconfig: + This is the lowest signal level for which the hardware + attempt packet reception, signals weaker than this are + ignored. This is used to avoid receiving background noise, + so you should set it according to the average noise + level. Positive values are assumed to be the raw value used + by the hardware or a percentage, negative values are + assumed to be dBm. + + >>> from iwlibs import Wireless + >>> wifi = Wireless('eth1') + >>> wifi.getSensitivity() + 'off' + + """ + iwparam = Iwparam(self.ifname, SIOCGIWSENS) + if iwparam.errorflag: + return (iwparam.errorflag, iwparam.error) + return iwparam.getValue() + + def getTXPower(self): + """returns transmit power in dBm + + >>> from iwlibs import Wireless + >>> wifi = Wireless('eth1') + >>> wifi.getTXPower() + '17 dBm' + """ + i, r = self.iwstruct.iw_get_ext(self.ifname, + SIOCGIWTXPOW) + if i > 0: + return (i, r) + iwfreq = Iwfreq(r) + return iwfreq.getTransmitPower() + + def getStatistics(self): + """returns statistics information which can also be found in + /proc/net/wireless + """ + iwstats = Iwstats(self.ifname) + if iwstats.errorflag > 0: + return (iwstats.errorflag, iwstats.error) + return [iwstats.status, iwstats.qual, iwstats.discard, + iwstats.missed_beacon] + + def scan(self): + """returns Iwscanresult objects, after a successful scan""" + iwscan = Iwscan(self.ifname) + return iwscan.scan() + + +class Iwstruct(object): + """basic class to handle iwstruct data """ + + def __init__(self): + self.idx = 0 + self.sockfd = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + + def parse_data(self, fmt, data): + """ unpacks raw C data """ + size = struct.calcsize(fmt) + idx = self.idx + + str = data[idx:idx + size] + self.idx = idx+size + value = struct.unpack(fmt, str) + + # take care of a tuple like (int, ) + if len(value) == 1: + return value[0] + else: + return value + + def pack(self, fmt, *args): + """ calls struct.pack and returns the result """ + return struct.pack(fmt, *args) + + def pack_wrq(self, buffsize): + """ packs wireless request data for sending it to the kernel """ + # Prepare a buffer + # We need the address of our buffer and the size for it. The + # ioctl itself looks for the pointer to the address in our + # memory and the size of it. + # Dont change the order how the structure is packed!!! + buff = array.array('c', '\0'*buffsize) + caddr_t, length = buff.buffer_info() + s = struct.pack('Pi', caddr_t, length) + return buff, s + + def pack_test(self, string, buffsize): + """ packs wireless request data for sending it to the kernel """ + buffsize = buffsize - len(string) + buff = array.array('c', string+'\0'*buffsize) + caddr_t, length = buff.buffer_info() + s = struct.pack('Pii', caddr_t, length, 1) + return buff, s + + def unpack(self, fmt, packed_data): + """ unpacks data with given format """ + return struct.unpack(fmt, packed_data) + + def _fcntl(self, request, args): + return fcntl.ioctl(self.sockfd.fileno(), request, args) + + def iw_get_ext(self, ifname, request, data=None): + """ read information from ifname """ + # put some additional data behind the interface name + if data is not None: + buff = IFNAMSIZE-len(ifname) + ifreq = ifname + '\0'*buff + ifreq = ifreq + data + else: + ifreq = (ifname + '\0'*32) + + try: + result = self._fcntl(request, ifreq) + except IOError, (i, e): + return i, e + + return (0, result[16:]) + + def getMAC(self, packed_data): + """ extracts mac addr from packed data and returns it as str """ + mac_addr = struct.unpack('xxBBBBBB', packed_data[:8]) + return "%02X:%02X:%02X:%02X:%02X:%02X" % mac_addr + +class Iwparam(object): + """class to hold iwparam data """ + + def __init__(self, ifname, ioctl): + # (i) value, (b) fixed, (b) disabled, (b) flags + self.fmt = "ibbH" + self.value = 0 + self.fixed = 0 + self.disabled = 0 + self.flags = 0 + self.errorflag = 0 + self.error = "" + self.ioctl = ioctl + self.ifname = ifname + self.update() + + def getValue(self): + """returns the value if not disabled """ + + if self.disabled: + return 'off' + if self.flags & IW_RETRY_TYPE == 0: + return self.getRLAttributes() + else: + return self.getPMAttributes() + + def getRLAttributes(self): + """returns a string with attributes determined by self.flags + """ + return self.value + + def getPMAttributes(self): + """returns a string with attributes determined by self.flags + and IW_POWER* + """ + result = "" + + # Modifiers + if self.flags & IW_POWER_MIN == 0: + result = " min" + if self.flags & IW_POWER_MAX == 0: + result = " max" + + # Type + if self.flags & IW_POWER_TIMEOUT == 0: + result = " period:" + else: + result = " timeout:" + # Value with or without units + # IW_POWER_RELATIVE - value is *not* in s/ms/us + if self.flags & IW_POWER_RELATIVE: + result += "%f" %(float(self.value)/MEGA) + else: + if self.value >= MEGA: + result += "%fs" %(float(self.value)/MEGA) + elif self.value >= KILO: + result += "%fms" %(float(self.value)/KILO) + else: + result += "%dus" % self.value + + return result + + def update(self): + iwstruct = Iwstruct() + i, r = iwstruct.iw_get_ext(self.ifname, + self.ioctl) + if i > 0: + self.errorflag = i + self.error = r + self._parse(r) + + def _parse(self, data): + """ unpacks iwparam data """ + iwstruct = Iwstruct() + self.value, self.fixed, self.disabled, self.flags =\ + iwstruct.parse_data(self.fmt, data) + +class Iwfreq(object): + """ class to hold iwfreq data + delegates to Iwstruct class + """ + + def __init__(self, data=None): + self.fmt = "ihbb" + if data is not None: + self.frequency = self.parse(data) + else: + self.frequency = 0 + self.iwstruct = Iwstruct() + + def __getattr__(self, attr): + return getattr(self.iwstruct, attr) + + def parse(self, data): + """ unpacks iwparam""" + + size = struct.calcsize(self.fmt) + m, e, i, pad = struct.unpack(self.fmt, data[:size]) + # XXX well, its not *the* frequency - we need a better name + if e == 0: + return m + else: + return float(m)*10**e + + def getFrequency(self): + """returns Frequency (str) + + data - binary data returned by systemcall (iw_get_ext()) + """ + freq = self.frequency + + if freq >= GIGA: + return "%0.3fGHz" %(freq/GIGA) + + if freq >= MEGA: + return "%0.3fMHZ" %(freq/MEGA) + + if freq >= KILO: + return "%0.3fKHz" %(freq/KILO) + + def getBitrate(self): + """ returns Bitrate in Mbit + + data - binary data returned by systemcall (iw_get_ext()) + """ + bitrate = self.frequency + + if bitrate >= GIGA: + return "%i Gb/s" %(bitrate/GIGA) + + if bitrate >= MEGA: + return "%i Mb/s" %(bitrate/MEGA) + + if bitrate >= KILO: + return "%i Kb/s" %(bitrate/KILO) + + def getTransmitPower(self): + """ returns transmit power in dbm """ + # XXX something flaky is going on with m and e + # eg. m = 50 and e should than be 0, because the number is stored in + # m and don't needs to be recalculated + return "%i dBm" %self.mw2dbm(self.frequency/10) + + def getChannel(self, freq, iwrange): + """returns channel information given by frequency + + returns None if frequency can't be converted + freq = frequency to convert (int) + iwrange = Iwrange object + """ + if freq < KILO: + return None + + # XXX + # for frequency in iwrange.frequencies + + + def mw2dbm(self, mwatt): + """ converts mw to dbm(float) """ + return math.ceil(10.0 * math.log10(mwatt)) + + def _setFrequency(self, list): + """sets self.frequency by given list + + currently only used by Iwrange + """ + assert len(list) == 4 + m, e, i, pad = list + if e == 0: + self.frequency = m + else: + self.frequency = float(m)*10**e + +class Iwstats(object): + """ class to hold iwstat data """ + + def __init__(self, ifname): + # (2B) status, 4B iw_quality, 6i iw_discarded + self.fmt = "2B4B6i" + self.status = 0 + self.qual = Iwquality() + self.discard = {} + self.missed_beacon = 0 + self.ifname = ifname + self.errorflag = 0 + self.error = "" + self.update() + + def update(self): + iwstruct = Iwstruct() + buff, s = iwstruct.pack_wrq(32) + i, result = iwstruct.iw_get_ext(self.ifname, + SIOCGIWSTATS, + data=s) + if i > 0: + self.error = result + self.errorflag = i + self._parse(buff.tostring()) + + def _parse(self, data): + """ unpacks iwstruct data """ + struct = Iwstruct() + iwqual = Iwquality() + iwstats_data = struct.parse_data(self.fmt, data) + + self.status = iwstats_data[0:2] + self.qual.quality, self.qual.sl, self.qual.nl,\ + self.qual.flags = iwstats_data[2:6] + nwid, code, frag, retries, flags = iwstats_data[6:11] + self.missed_beacon = iwstats_data[11:12][0] + self.discard = makedict(nwid=nwid, code=code, + fragment=frag, retries=retries, misc=flags) + +class Iwquality(object): + """ class to hold iwquality data """ + + def __init__(self): + self.quality = 0 + self.sl = 0 + self.nl = 0 + self.updated = 0 + self.fmt = "4B" + + def parse(self, data): + """ unpacks iwquality data """ + struct = Iwstruct() + qual, sl, nl, flags = struct.parse_data(self.fmt, data) + + # compute signal and noise level + self.signal_level = sl + self.noise_level = nl + + # asign the other values + self.quality = qual + self.updated = flags + + def setValues(self, list): + """ assigns values given by a list to our attributes """ + attributes = ["quality", "signallevel", "noise_level", + "updated"] + assert len(list) == 4 + + for i in range(len(list)): + setattr(self, attributes[i], list[i]) + + def getSignallevel(self): + """ returns signal level """ + return self.sl-0x100 + + def setSignallevel(self, sl): + """ sets signal level """ + self.sl = sl + signallevel = property(getSignallevel, setSignallevel) + + def getNoiselevel(self): + """ returns noise level """ + return self.nl - 0x100 + + def setNoiselevel(self): + raise NotImplementedError + self.nl = nl + noiselevel = property(getNoiselevel, setNoiselevel) + +class Iwpoint(object): + """ class to hold iwpoint data """ + + def __init__(self, ifname): + self.key = [0,0,0,0] + self.fields = 0 + self.flags = 0 + # (4B) pointer to data, H length, H flags + self.fmt = "4BHH" + self.errorflag = 0 + self.error = "" + self.ifname = ifname + self.update() + + def __getattr__(self, attr): + return getattr(self.iwstruct, attr) + + def update(self): + iwstruct = Iwstruct() + buff, s = iwstruct.pack_wrq(32) + i, result = iwstruct.iw_get_ext(self.ifname, + SIOCGIWENCODE, + data=s) + if i > 0: + self.errorflag = i + self.error = result + self._parse(result) + + def getEncryptionKey(self): + """ returns encryption key as '**' or 'off' as str """ + if self.flags & IW_ENCODE_DISABLED != 0: + return 'off' + elif self.flags & IW_ENCODE_NOKEY != 0: + # a key is set, so print it + return '**' * self.fields + + def _parse(self, data): + """ unpacks iwpoint data + """ + iwstruct = Iwstruct() + ptr, ptr, ptr, ptr, self.fields, self.flags =\ + iwstruct.parse_data(self.fmt, data) + self.key = [ptr, ptr, ptr, ptr] + +class Iwrange(object): + """holds iwrange struct """ + IW_MAX_FREQUENCIES = 32 + + def __init__(self, ifname): + self.fmt = "iiihb6ii4B4Bi32i2i2i2i2i3h8h2b2bhi8i2b3h2i2ihB17x"\ + + self.IW_MAX_FREQUENCIES*"ihbb" + + self.ifname = ifname + self.errorflag = 0 + self.error = "" + + # informative stuff + self.throughput = 0 + + # nwid (or domain id) + self.min_nwid = self.max_nwid = 0 + + # frequency for backward compatibility + self.old_num_channels = self.old_num_frequency = self.old_freq = 0 + + # signal level threshold + self.sensitivity = 0 + + # link quality + self.max_qual = Iwquality() + self.avg_qual = Iwquality() + + # rates + self.num_bitrates = 0 + self.bitrates = [] + + # rts threshold + self.min_rts = self.max_rts = 0 + + # fragmention threshold + self.min_frag = self.max_frag = 0 + + # power managment + self.min_pmp = self.max_pmp = 0 + self.min_pmt = self.max_pmt = 0 + self.pmp_flags = self.pmt_flags = self.pm_capa = 0 + + # encoder stuff + self.encoding_size = 0 + self.num_encoding_sizes = self.max_encoding_tokens = 0 + self.encoding_login_index = 0 + + # transmit power + self.txpower_capa = self.num_txpower = self.txpower = 0 + + # wireless extension version info + self.we_vers_compiled = self.we_vers_src = 0 + + # retry limits and lifetime + self.retry_capa = self.retry_flags = self.r_time_flags = 0 + self.min_retry = self.max_retry = 0 + self.min_r_time = self.max_r_time = 0 + + # frequency + self.num_channels = self.num_frequency = 0 + self.frequencies = [] + self.update() + + def update(self): + """updates Iwrange object by a system call to the kernel + and updates internal attributes + """ + iwstruct = Iwstruct() + buff, s = iwstruct.pack_wrq(640) + i, result = iwstruct.iw_get_ext(self.ifname, + SIOCGIWRANGE, + data=s) + if i > 0: + self.errorflag = i + self.error = result + data = buff.tostring() + self._parse(data) + + def _parse(self, data): + struct = Iwstruct() + result = struct.parse_data(self.fmt, data) + + # XXX there is maybe a much more elegant way to do this + self.throughput, self.min_nwid, self.max_nwid = result[0:3] + self.old_num_channels, self.old_num_frequency = result[3:5] + self.old_freq = result[5:11] + self.sensitivity = result[11] + self.max_qual.setValues(result[12:16]) + self.avg_qual.setValues(result[16:20]) + self.num_bitrates = result[20] # <- XXX + raw_bitrates = result[21:53] + for rate in raw_bitrates: + iwfreq = Iwfreq() + iwfreq.frequency = rate + br = iwfreq.getBitrate() + if br is not None: + self.bitrates.append(br) + + self.min_rts, self.max_rts = result[53:55] + self.min_frag, self.max_frag = result[55:57] + self.min_pmp, self.max_pmp = result[57:59] + self.min_pmt, self.max_pmt = result[59:61] + self.pmp_flags, self.pmt_flags, self.pm_capa = result[61:64] + self.encoding_size = result[64:72] + self.num_encoding_sizes, self.max_encoding_tokens = result[72:74] + self.encoding_login_index = result[74:76] + self.txpower_capa, self.num_txpower = result[76:78] + self.txpower = result[78:86] + self.we_vers_compiled, self.we_vers_src = result[86:88] + self.retry_capa, self.retry_flags, self.r_time_flags = result[88:91] + self.min_retry, self.max_retry = result[91:93] + self.min_r_time, self.max_r_time = result[93:95] + self.num_channels = result[95] + self.num_frequency = result[96] + freq = result[97:] + + i = self.num_frequency + for x in range(0, len(freq), 4): + iwfreq = Iwfreq() + iwfreq._setFrequency(freq[x:x+4]) + fq = iwfreq.getFrequency() + if fq is not None: + self.frequencies.append(fq) + i -= 1 + if i <= 0: + break + +class Iwscan(object): + """class to handle AP scanning""" + + def __init__(self, ifname): + self.ifname = ifname + self.range = Iwrange(ifname) + self.errorflag = 0 + self.error = "" + self.stream = None + self.aplist = None + + def scan(self, fullscan=True): + """Completes a scan for available access points, + and returns them in Iwscanresult format + + fullscan: If False, data is read from a cache of the last scan + If True, a scan is conducted, and then the data is read + """ + # By default everything is fine, do not wait + result = 1 + if fullscan: + self.setScan() + if self.errorflag > EPERM: + raise RuntimeError, 'setScan failure ' + str(self.errorflag) + " " + str(self.error) + return None + elif self.errorflag < EPERM: + # Permission was NOT denied, therefore we must WAIT to get results + result = 250 + + while (result > 0): + time.sleep(result/1000) + result = self.getScan() + + if result < 0 or self.errorflag != 0: + raise RuntimeError, 'getScan failure ' + str(self.errorflag) + " " + str(self.error) + + return self.aplist + + + def setScan(self): + """Triggers the scan, if we have permission + """ + iwstruct = Iwstruct() + s = iwstruct.pack('Pii', 0, 0, 0) + i, result = iwstruct.iw_get_ext(self.ifname, + SIOCSIWSCAN,s) + if i > 0: + self.errorflag = i + self.error = result + return result + + def getScan(self): + """Retreives results, stored from the most recent scan + Returns 0 if successful, a delay if the data isn't ready yet + or -1 if something really nasty happened + """ + iwstruct = Iwstruct() + i = E2BIG + bufflen = IW_SCAN_MAX_DATA + + # Keep resizing the buffer until it's large enough to hold the scan + while (i == E2BIG): + buff, s = iwstruct.pack_wrq(bufflen) + i, result = iwstruct.iw_get_ext(self.ifname, + SIOCGIWSCAN, + data=s) + if i == E2BIG: + pbuff, newlen = iwstruct.unpack('Pi', s) + if bufflen < newlen: + bufflen = newlen + else: + bufflen = bufflen * 2 + + if i == EAGAIN: + return 100 + if i > 0: + self.errorflag = i + self.error = result + return -1 + + pbuff, reslen = iwstruct.unpack('Pi', s) + if reslen > 0: + # Initialize the stream, and turn it into an enumerator + self.aplist = self._parse(buff.tostring()) + return 0 + + def _parse(self, data): + """Parse the event stream, and return a list of Iwscanresult objects + """ + iwstruct = Iwstruct() + scanresult = None + aplist = [] + + # Run through the stream, until broken + while 1: + # If we're the stream doesn't have enough space left for a header, break + if len(data) < IW_EV_LCP_LEN: + break; + + # Unpack the header + length, cmd = iwstruct.unpack('HH', data[:4]) + # If the header says the following data is shorter than the header, then break + if length < IW_EV_LCP_LEN: + break; + + # Put the events into their respective result data + if cmd == SIOCGIWAP: + if scanresult is not None: + aplist.append(scanresult) + scanresult = Iwscanresult(data[IW_EV_LCP_LEN:length], self.range) + elif scanresult is None: + raise RuntimeError, 'Attempting to add an event without AP data' + else: + scanresult.addEvent(cmd, data[IW_EV_LCP_LEN:length]) + + # We're finished with the preveious event + data = data[length:] + + # Don't forgset the final result + if scanresult.bssid != "00:00:00:00:00:00": + aplist.append(scanresult) + else: + raise RuntimeError, 'Attempting to add an AP without a bssid' + return aplist + +class Iwscanresult(object): + """An object to contain all the events associated with a single scanned AP + """ + + def __init__(self, data, range): + """Initialize the scan result with the access point data""" + self.iwstruct = Iwstruct() + self.range = range + self.bssid = "%02X:%02X:%02X:%02X:%02X:%02X" % struct.unpack('BBBBBB', data[2:8]) + self.essid = None + self.mode = None + self.rate = [] + self.quality = Iwquality() + self.frequency = None + self.encode = None + self.custom = [] + self.protocol = None + + def addEvent(self, cmd, data): + """Attempts to add the data from an event to a scanresult + Only certain data is accept, in which case the result is True + If the event data is invalid, None is returned + If the data is valid but unused, False is returned + """ + if cmd <= SIOCIWLAST: + if cmd < SIOCIWFIRST: + return None + elif cmd >= IWEVFIRST: + if cmd > IWEVLAST: + return None + else: + return None + + if cmd == SIOCGIWESSID: + self.essid = data[4:] + elif cmd == SIOCGIWMODE: + self.mode = modes[self.iwstruct.unpack('i', data[:4])[0]] + elif cmd == SIOCGIWRATE: + # TODO, deal with multiple rates, or at least the highest rate + freqsize = struct.calcsize("ihbb") + while len(data) >= freqsize: + iwfreq = Iwfreq(data) + self.rate.append(iwfreq.getBitrate()) + data = data[freqsize:] + elif cmd == IWEVQUAL: + self.quality.parse(data) + elif cmd == SIOCGIWFREQ: + self.frequency = Iwfreq(data) + elif cmd == SIOCGIWENCODE: + self.encode = data + elif cmd == IWEVCUSTOM: + self.custom.append(data[1:]) + elif cmd == SIOCGIWNAME: + self.protocol = data[:len(data)-2] + else: + print "Cmd:", cmd + return False + return True + + def display(self): + print "ESSID:", self.essid + print "Access point:", self.bssid + print "Mode:", self.mode + if len(self.rate) > 0: + print "Highest Bitrate:", self.rate[len(self.rate)-1] + print "Quality: Quality ", self.quality.quality, "Signal ", self.quality.getSignallevel(), " Noise ", self.quality.getNoiselevel() + print "Encryption:", map(lambda x: hex(ord(x)), self.encode) + # XXX + # print "Frequency:", self.frequency.getFrequency(), "(Channel", self.frequency.getChannel(self.range), ")" + for custom in self.custom: + print "Custom:", custom + print "" + +#$LastChangedDated$ +#$Rev: 37 $