From 9d42d6ed3b587b36a32c32d9b878998dca73bb3b Mon Sep 17 00:00:00 2001 From: wraith-wireless Date: Sat, 14 May 2016 02:55:13 -0600 Subject: [PATCH] 0.0.7 --- LICENSE | 40 + MANIFEST.in | 6 + PyRIC.pdf | Bin 0 -> 176975 bytes README.md | 357 ++++ __init__.py | 1 + examples/pentest.py | 97 + pyric/RFI | 116 ++ pyric/TODO | 18 + pyric/__init__.py | 130 ++ pyric/channels.py | 89 + pyric/device.py | 93 + pyric/docs/__init__.py | 38 + pyric/docs/attributes.help | 5 + pyric/docs/commands.help | 5 + pyric/docs/nlhelp.py | 155 ++ pyric/docs/res/PyRIC.bib | 52 + pyric/docs/res/PyRIC.tex | 785 +++++++ pyric/lib/__init__.py | 47 + pyric/lib/libio.py | 80 + pyric/lib/libnl.py | 658 ++++++ pyric/net/__init__.py | 44 + pyric/net/genetlink_h.py | 120 ++ pyric/net/if_h.py | 352 ++++ pyric/net/netlink_h.py | 339 +++ pyric/net/policy.py | 87 + pyric/net/sockios_h.py | 153 ++ pyric/net/wireless/__init__.py | 39 + pyric/net/wireless/nl80211_c.py | 285 +++ pyric/net/wireless/nl80211_h.py | 3451 +++++++++++++++++++++++++++++++ pyric/pyw.py | 992 +++++++++ setup.cfg | 4 + setup.py | 72 + 32 files changed, 8710 insertions(+) create mode 100644 LICENSE create mode 100644 MANIFEST.in create mode 100644 PyRIC.pdf create mode 100644 README.md create mode 100644 __init__.py create mode 100644 examples/pentest.py create mode 100644 pyric/RFI create mode 100644 pyric/TODO create mode 100644 pyric/__init__.py create mode 100644 pyric/channels.py create mode 100644 pyric/device.py create mode 100644 pyric/docs/__init__.py create mode 100644 pyric/docs/attributes.help create mode 100644 pyric/docs/commands.help create mode 100644 pyric/docs/nlhelp.py create mode 100644 pyric/docs/res/PyRIC.bib create mode 100644 pyric/docs/res/PyRIC.tex create mode 100644 pyric/lib/__init__.py create mode 100644 pyric/lib/libio.py create mode 100644 pyric/lib/libnl.py create mode 100644 pyric/net/__init__.py create mode 100644 pyric/net/genetlink_h.py create mode 100644 pyric/net/if_h.py create mode 100644 pyric/net/netlink_h.py create mode 100644 pyric/net/policy.py create mode 100644 pyric/net/sockios_h.py create mode 100644 pyric/net/wireless/__init__.py create mode 100644 pyric/net/wireless/nl80211_c.py create mode 100644 pyric/net/wireless/nl80211_h.py create mode 100644 pyric/pyw.py create mode 100644 setup.cfg create mode 100644 setup.py diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..80fa603 --- /dev/null +++ b/LICENSE @@ -0,0 +1,40 @@ +PyRIC: Python Radio Interface Controller +Copyright (C) 2016 Dale V. Patterson (wraith.wireless@yandex.com) + +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 3 of the License, or (at your option) any later +version. + +Redistribution and use in source and binary forms, with or without modifications, +are permitted provided that the following conditions are met: + o Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + o Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + o Neither the name of the orginal author Dale V. Patterson nor the names of any + contributors may be used to endorse or promote products derived from this + software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT +OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +PyRIC is free software but use, duplication or disclosure by the United States +Government is subject to the restrictions set forth in DFARS 252.227-7014. + +Use of this software is governed by all applicable federal, state and local +laws of the United States and subject to the laws of the country where you reside. +The copyright owner and contributors will be not be held liable for use of this +software in furtherance of or with intent to commit any fraudulent or other illegal +activities, or otherwise in violation of any applicable law, regulation or legal +agreement. + +See for a copy of the GNU General Public License. diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 0000000..ce7fd91 --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1,6 @@ +# Include license, README +include LICENSE README.md __init__.py channels.py device.py pyw.py PyRIC.pdf + +# Include subdirectories +recursive-include lib net examples docs +recursive-include docs *.help *.pdf \ No newline at end of file diff --git a/PyRIC.pdf b/PyRIC.pdf new file mode 100644 index 0000000000000000000000000000000000000000..e54637ad317df10113168340a00c85bfe441b2f4 GIT binary patch literal 176975 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

AT8Z$iDclcm298 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

y!)!J3?`m2_e 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

Sjs~solc6 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 literal 0 HcmV?d00001 diff --git a/README.md b/README.md new file mode 100644 index 0000000..fdacc9e --- /dev/null +++ b/README.md @@ -0,0 +1,357 @@ +# PyRIC: Python Radio Interface Controller +## Pythonic iw + +## 1 DESCRIPTION: +BLUF: Stop using subprocess.Popen, regular expressions and str.find. PyRIC +is a python port of a subset of iw and python port of netlink (w.r.t nl80211 +functions). + +### a. Background +PyRIC arose out of a need in Wraith (https://github.com/wraith-wireless/wraith) +for Python nl80211/netlink and ioctl functionality. Originally, Wraith used +ifconfig, iwconfig and iw via subprocess.Popen and parsed the output. There +are obvious shortfalls with this method, especially in terms of iw that is +actively changing (revisions break the parser) and I started looking for an +open source alternative. There are several open source projects out there +such as pyroute, pymnl (and the python files included in the libnl source) but +they generally have either not been maintained recently or come with warnings. +I desired a simple interface to the underlying nl80211 kernel support that +handles the complex operations of netlink seamlessy while maintaining a minimum +of "code walking" to understand, modify and extend. I decided to write my own +because I do not need complete netlink functionality, only that provided by +generic netlink and within the nl80221 family. Additionally, for Wraith, I do +not need a full blown port of iw et. al. functionality to Python but only +require the ability to turn a wireless nic on/off, get/set the hwaddr, get/set +the channel, determine some properties of the card and add/delete interfaces. + +So, why did I do this and why is it done "this" way? When I first started to +explore the idea of moving away from iw output parsing, I looked at the source +for iw, and existing Python ports. Just to figure out how to get the family id +for nl80211 required reading through five different source files with no +comments. To that extent, I have attempted to keep subclassing to a minimum, +the total number of classes to a minimum, combine files where possible and where +it makes since and keep the number of files required to be open simulateneously +in order to understand the methodology and follow the program to a minimum. One +can understand the PyRIC program flow with only two files open at any time namely, +pyw and libnl. In fact, only an understanding of pyw is required to add additional +commands although an understanding of libnl(.py) is helpful especially, if for +example, the code is to be extended to handle multicast or callbacks. + +### b. Additions to iw +In addition to providing some ifconfig functionality, I have also added several +"extensions" to iw: +* Persistent sockets: pyw provides the caller with functions & ability to pass +their own netlink (or ioctl socket) to pyw functions; +* One-time request for the nl80211 family id: pyw stores the family id in a +global variable +* Consolidating different "reference" values to wireless NICs in one class +(Cards are tuples t=(dev,phy #,ifindex) + +These are minimal changes but they can improve the performance of any progams +that need to access the wireless nic repeatedly. + +### c. Current State +ATT, PyRIC accomplish my core needs but it is still a work in progress. It provides +the following: +* enumerate interfaces and wireless interfaces +* identify a cards chipset and driver +* get/set hardware address +* turn card on/off +* get supported standards +* get supported commands +* get supported modes +* get dev info +* get phy info (does not currently process the bands) +* get/set regulatory domain +* get/set mode +* add/delete interfaces + +It also provides limited help functionality concerning nl80211 commands/attributes +(for those who wish to add additional commands). However, it pulls directly from +the nl80211 header file and may be vague. + +### d. What is PyRIC? + +What it does - defines programmatic access to a small subset of iw and ifconfig. + +What it does not do - handle multicast messages, callbacks or dumps or non nl80211 +funtionality. + +## 2. INSTALLING/USING: + +Starting with version 0.0.6, the structure (see Section 4) has changed to facilitate +packaging on PyPI. This restructing has of course led to some minor difficulties +especially when attempting to install (or even just test) outside of a pip +installation. + +### a. Requirements +PyRIC has only two requirements: Linux and Python. There has been very little +testing (on my side) on kernel 4.x and Python 3 but working out the small bugs +continues on Python 2.7 and kernel 3.13.x. + +### b. Install from Package Manager +Obviously, the easiest way to install PyRIC is through PyPI: + + sudo pip install --pre PyRIC + +Note the use of the '--pre' flag. Without it, pip will not install PyRIC since +it is still in the developmental stage. + +### c. Install from Source +The PyRIC source (tarball) can be downloaded from https://pypi.python.org/pypi/PyRIC +or http://wraith-wireless.github.io/PyRIC. Additionally, the source, as a zip file, +can be downloaded from https://github.com/wraith-wireless/PyRIC. Once downloaded, +extract the files and from the PyRIC directory run: + + sudo python setup.py install + +### d. Test without Installing + +If you just want to test PyRIC out, download your choice from above. After extraction, +move the pyric folder (the package directory) to your location of choice and from +there start Python and import pyw. It is very important that you do not try and +run it from PyRIC which is the distribution directory. This will break the imports +pyw uses. + +You will only be able to test PyRIC from the pyric directory but, if you want to, +you can add it to your Python path and run it from any program or any location. +To do so, assume you untared PyRIC to /home/bob/PyRIC. Create a text file named +pyric.pth with one line + + /home/bob/PyRIC + +and save this file to /usr/lib/python2.7/dist-packages (or /usr/lib/python3/dist-packages +if you want to try it in Python 3). + +### e. Stability vs Latest + +Keep in mind that the most stable version and easist installallation but oldest +release is on PyPI (installed through pip). The source on http://wraith-wireless.github.io/PyRIC tends to be +newer but may have some bugs. The most recent source but hardest to install is on +https://github.com/wraith-wireless/pyric/releases/ It is not guaranteed to be stable +(as I tend to commit changes periodically while working on the code) and may in +fact not run at all. + +## 3. USING +Once installed, see examples/pentest.py which covers most pyw functions or read +throuhg PyRIC.pdf. However, for those impatient types: + +```python +import pyric # pyric error and EUNDEF error code +from pyric import device # driver and chipset lookup +from pyric import channels # channels, freqs, widths and conversions +from pyric import pyw # iw functionality +``` + +will import the basic requirements and is assumed for the examples below. It is also assumed +that the system is in the US and has three devices lo, eth0 and wlan0 (only wlan0 of course +being wireless). Keep in mind that these examples use one-time sockets. + +### a. Wireless Core Functionality +These functions do not work with a specific device rather with the system. + +```python + +pyw.interfaces() # get all system interfaces +=> ['lo','eth0','wlan'] + +pyw.isinterface('eth0') # deterimine if eth0 is an interface +=> True + +pyw.isinterface('bob0') +=> False + +pyw.winterfaces() # get all system wireless interfaces +=> ['wlan0'] + +pyw.isinterface('eth0') # check eth0 for wireless +=> False + +pyw.iswinterface('wlan0') +=> True + +pyw.regget() # get the regulatory domain +=> 'US' + +pyw.regset('BO') # set the regulatory domain + +pyw.regget() +=> 'BO' +``` + +### b. Interface Specific +Recall that PyRIC utilizes a Card object - this removes the necessity of having to +remember what to pass each function i.e. whether it is a device name, physical index +or ifindex. + +```python +w0 = pyw.getcard('wlan0') # get a card for wlan0 + +w0 +=> Card(phy=0,dev='wlan0',ifindex=2) +``` + +You can also use pyw.devinfo to get a Card object and pyw.devadd will return a card +object for the newly created virtual interface. The card, w0, will be used throughout +the remainder of the examples. + +#### i. Setting The Mac Address + +```python +mac = pyw.macget(w0) # get the hw addr + +mac +=> 'a0:b1:c2:d3:e4:f5' + +pyw.down(w0) # turn the card off to set the mac + +pyw.macset(w0,'00:1F:32:00:01:00') # lets be a nintendo device + +pyw.up(w0) # bring wlan0 back up + +pyw.macget(w0) # see if it worked +=> '00:1F:32:00:01:00' +``` +#### ii. Getting Info On Your Card + +```python +pyw.txget(w0) +=> 20 + +pyw.modeget(w0) +=> 'managed' + +pyw.devstds(w0) +=> ['b', 'g', 'n'] + +pyw.devmodes(w0) +=> ['ibss', 'managed', 'AP', 'AP VLAN', 'wds', 'monitor', 'mesh'] + +pyw.devcmds(w0) +=> [u'new_interface', u'set_interface', u'new_key', u'start_ap', u'new_station', +u'new_mpath', u'set_mesh_config', u'set_bss', u'authenticate', u'associate', +u'deauthenticate', u'disassociate', u'join_ibss', u'join_mesh', u'set_tx_bitrate_mask', +u'frame', u'frame_wait_cancel', u'set_wiphy_netns', u'set_channel', u'set_wds_peer', +u'probe_client', u'set_noack_map', u'register_beacons', u'start_p2p_device', +u'set_mcast_rate', u'connect', u'disconnect'] + +pyw.devinfo(w0) +=> {'wdev': 4294967297, 'RF': None, 'CF': None, 'mac': '00:c0:ca:59:af:a6', +'mode': 'managed', 'CHW': None, 'card': Card(phy=1,dev=alfa0,ifindex=4)} + +pinfo = pyw.phyinfo(w0) + +pinfo['scan_ssids'] +=> 4 + +pinfo['retry_short'] +=> 7 + +pinfo['retry_long'] +=> 4 + +pinfo['frag_thresh'] +=> 4294967295 + +pinfo['rts_thresh'] +=> 4294967295 + +pinfo['cov_class'] +=> 0 + +``` + +#### iii. Virtual Interfaces +In my experience, virtual interfaces are primarily used to recon, attack or some +other tomfoolery but can also be used to analyze your wireless network. In either +case, it is generally advised to create a virtual monitor interface and delete +all others (on the same phy) - this makes sure that some external process like +NetworkManager does not interfere with your shenanigans. In the below example, +in addition to creating an interface in monitor mode, we find all interfaces +on the same physical index and delete them. You may not need to do this. + +NOTE: When creating a device in monitor mode, you can also set flags (see +NL80211_MNTR_FLAGS in nl80211_h), although some cards (usually atheros) do not +always obey these requests. + +```python +'monitor' in pyw.devmodes(w0) # make sure we can set wlan0 to monitor +=> True + +m0 = pyw.devadd(w0,'mon0','monitor') # create mon0 in monitor mode + +for iface in pyw.ifaces(w0): # delete all interfaces + pyw.devdel(iface[0]) # on the this phy + +pyw.up(m0) # bring the new card up to use + +pyw.chset(m0,6,None) # and set the card to channel 6 +=> True + +m0 +=> Card(phy=0,dev='mon0',ifindex=3) +``` + +Of course, once you are done, you will probably want to restore your original set +up. + +```python +w0 = pyw.devadd(m0,'wlan0','managed') # restore wlan0 in managed mode + +pyw.devdel(m0) # delete the monitor interface + +pyw.setmac(w0,mac) # restore the original mac address + +pyw.up(w0) # and bring the card up + +w0 +=> Card(phy0,dev='wlan0',ifindex=4) + +``` + +## 4. EXTENDING: + +Extending PyRIC is fun and easy too, see the user guide PyRIC.pdf. + +## 5. ARCHITECTURE/HEIRARCHY: Brief Overview of the project file structure + +* pyric root Distribution directory + - \_\_init\_\_.py initialize distrubution PyRIC module + - examples example folder + + pentest.py create wireless pentest environment example + - setup.py install file + - setup.cfg used by setup.py + - MANIFEST.in used by setup.py + - README.md this file + - LICENSE GPLv3 License + * PyRIC.pdf User Guide + - pyric package directory + + \_\_init\_\_.py initialize pyric module + + pyw.py wireless nic functionality + + radio.py consolidate pyw in a class + + channels.py 802.11 ISM/UNII freqs. & channels + + device.py device/chipset utility functions + + TODO todos for PyRIC + + RFI comments and observations + + net linux header ports + * \_\_init\_\_.py initialize net subpackage + * if_h.py inet/ifreq definition + * sockios_h.py socket-level I/O control calls + * genetlink_h.py port of genetlink.h + * netlink_h.py port of netlink.h + * policy.py defines attribute datatypes + * wireless wireless subpackage + - \_\_init\_\_.py initialize wireless subpackage + - nl80211_h.py nl80211 constants + - nl80211_c.py nl80211 attribute policies + + lib library subpackages + * \_\_init\_\_.py initialize lib subpackage + * libnl.py netlink helper functions + * libio.py sockios helper functions + + docs netlinke documentation/help + * nlhelp.py nl80211 search + * commands.help nl80211 commands help data + * attributes.help nl80211 attributes help data + * res User Guide resources + - PyRIC.tex User Guide LaTex + - PyRIC.bib User Guide bibliography diff --git a/__init__.py b/__init__.py new file mode 100644 index 0000000..9c9064d --- /dev/null +++ b/__init__.py @@ -0,0 +1 @@ +# root Distribution directory \ No newline at end of file diff --git a/examples/pentest.py b/examples/pentest.py new file mode 100644 index 0000000..86b21ca --- /dev/null +++ b/examples/pentest.py @@ -0,0 +1,97 @@ +#!/usr/bin/env python +""" pentest.py + +Example for setting up a wireless environment - must be done as root +""" + +import argparse as ap +import time +import pyric # pyric error (and ecode EUNDEF) +from pyric import pyw # for iw functionality +from pyric import device # for chipset/driver +from pyric.channels import rf2ch # rf to channel conversion + +def execute(dev): + print 'Setting up...' + # ensure dev is a wireless interfaces + ifaces = pyw.interfaces() + wifaces = pyw.winterfaces() + if dev not in ifaces: + print "Device {0} is not valid, use one of {1}".format(dev,ifaces) + return + elif dev not in wifaces: + print "Device {0} is not wireless, use one of {1}".format(dev,wifaces) + + # get a Card & info for dev + print "Regulatory Domain currently: ", pyw.regget() + dinfo = pyw.devinfo(dev) + card = dinfo['card'] + pinfo = pyw.phyinfo(card) + driver = device.ifdriver(card.dev) + chipset = device.ifchipset(driver) + + # bring the card down and change the mac + pyw.down(card) + pyw.macset(card,'00:03:93:57:54:46') + + # print details + msg = "Using {0} currently in mode: {1}\n".format(card,dinfo['mode']) + msg += "\tDriver: {0} Chipset: {1}\n".format(driver,chipset) + if dinfo['mode'] == 'managed': + msg += "\tcurrently on channel {0} width {1}\n".format(rf2ch(dinfo['RF']), + dinfo['CHW']) + msg += "\tSupports modes {0}\n".format(pinfo['modes']) + msg += "\tSupports commands {0}".format(pinfo['commands']) + msg += "\thw addr {0}".format(pyw.macget(card)) + print msg + + # prepare a virtual interface named pent0 in monitor mode + # delete all ifaces on the phy to avoid interference + print 'Preparing pent0 for monitor mode' + pdev = 'pent0' + for iface in pyw.ifaces(card): + print "deleting {0} in mode {1}".format(iface[0],iface[1]) + pyw.devdel(iface[0]) + pcard = pyw.devadd(card, pdev, 'monitor') + pyw.up(pcard) + print "Using", pcard + + print "Setting channel to 6 NOHT" + pyw.chset(pcard,6,None) + msg = "Virtual interface {0} in monitor mode on ch 6".format(pcard) + print msg + ", using hwaddr: {0}".format(pyw.macget(pcard)) + + # DO stuff here + try: + print 'Now ready to do stuff' + print 'For example, run wireshark to verify card is seeing all packets' + print 'Hit Ctrl-C to quit and restore' + while True: time.sleep(1) + except KeyboardInterrupt: + pass + + # restore original + print "Restoring..." + print "deleting ", pcard + pyw.devdel(pcard) + + print 'Restoring', card, 'mode =', dinfo['mode'], 'mac =', dinfo['mac'] + card = pyw.devadd(card,card.dev,dinfo['mode']) + pyw.macset(card,dinfo['mac']) + pyw.up(card) + print "card ", card, " restored" + +if __name__ == '__main__': + # create arg parser and parse command line args + print "Wireless Pentest Environment using PyRIC v{0}".format(pyric.__version__) + argp = ap.ArgumentParser(description="Wireless Pentest") + argp.add_argument('-d','--dev',help="Pentesting Wireless Device") + args = argp.parse_args() + try: + dev = args.dev + if dev is None: + print "usage: python pentest -d -v " + else: + execute(dev) + except pyric.error as e: + print e diff --git a/pyric/RFI b/pyric/RFI new file mode 100644 index 0000000..f611442 --- /dev/null +++ b/pyric/RFI @@ -0,0 +1,116 @@ +Reading through the iw source code to figure out how to get the regulatory domain +is like reading through a ham radio radio manual to figure out how to turn it on. +Even when I could see what iw was doing there were no comments or directions as +to why they were doing it a specific way. And, I could not find any definitive +resources on nl80211 via netlink. Fortunately, Thomas Graf provides excellent +documentation on libnl at http://www.carisma.slowglass.com/~tgr/libnl/doc/core.html. +Reading this, I was able to write a simple netlink message class and parser. I still +cannot follow the iw code but with strace, I was able to copy the hex strings and +parse the communications to and from the kernel. However, this leaves a lot of +questions unaswered which is the purpose of this document - to document my +observations, findings and questions in a central location rather than dispersed +throughout the code. + +1) Odd error on what should be a NLE_PERM +When running a root level cmd (reg set) as non-root), I get a return message w/ +the following format: + + nlmsghdr(len=48, type=2, flags=5, seq=1460441619, pid=9865) + genlmsghdr(cmd=255) + attributes: + 0: type = 0, datatype = 0 + value = 1a00050013920c57892600001b000000070021005553 + +and the hex of this message is: + +"\x30\x00\x00\x00\x02\x00\x00\x00\x13\x92\x0c\x57\x89\x26\x00\x00\xff\xff\xff\xff\x1c\x00\x00\x00\x1a\x00\x05\x00\x13\x92\x0c\x57\x89\x26\x00\x00\x1b\x00\x00\x00\x07\x00\x21\x00\x55\x53\x00\x00" + +First, type=2 generally designates an error (at least when executing nl80211). +Second, there is no cmd = 255. Third attempting to parse it as an netlink error +results in a errno of -1. Finally, it does not follow the correct error message +format which should be nlmsghdr+errno+nlmsghdr. + +I checked and this is the same response iw gets. + +* workaround is in place in libnl.nlmsg_fromstream() + +2) ACK messages +PyRIC is set up in a simple send a message & receive the response method. However, +if the caller designates the message with a NLM_F_ACK flag and the ack is not +pulled off the socket subsequent messages will fail due to sequence numbers +mismatching. This is only a problem when using a persistent netlink socket. +ATT I set the NLM_F_ACK flag on all sent packets to ensure we get ack messages +back. + +* workaround is in place in libnl.nl_recvmsg + +3) Hanging terminal +I don't attempt to parse attributes of type nested or unspec. In some situations +when printing the hex values of these attributes on the terminal some character +or set of characters causes the terminal to hang. No combinination of keys etc +can then kill the terminal. I haven't yet looked into trying to determine what +hex value(s) is causing this. + +* workaround is in place in GENLMsg.__repr__ using hexlify + +4) Using deprecated programs/processes +IOT to replicate iw dev info, one has to pass the ifindex (I've tried using +the device name with appropriate attribute type but it fails). The only way to +get the ifindex is by using the supposedly deprecated ioctl (iw does the same). +Seems kind of ironic that the 'new and improved' relies on the old and deprecated + +* no workaround at this point + +5) Error +Netlink provides error codes in netlink/errno.h. However these do not match those +found in /usr/include/asm-generic/errno-base.h and /usr/include/asm-generic/errno.h. +In most cases, it appears that using the netlink errors results in reporting an +incorrect error - there doesn't seem to be any rhyme or reason for this as even +the error codes reporting in the nlmsgerr struct fit linux errors over netlink +errors (in most cases). But, of course there is a catch. NLE_SUCCESS (0) and +NLE_FAILURE (1) as reported in ack/error messages are correct but do not correspond +to the same error code in the linux asm header files. + +* workaround in place, added '-1' as an undefined, use errno for error codes, +error strings and test for NLE_SUCCESS in netlink error message + +6) Setting the channel/Frequency +nl80211.h states that using NL80211_CMD_SET_WIPHY to set the channel is deprecated +in place of NL80211_CMD_SET_CHANNEL. Below is the attempted code: +phy = devinfoex(nlsock,nic)['phy'] +msg = nl.nlmsg_new(nl_type=_FAM80211ID_, + cmd=nl80211h.NL80211_CMD_SET_CHANNEL, + flags=nlh.NLM_F_REQUEST | nlh.NLM_F_ACK) +msg.nla_put_u32(phy,nl80211h.NL80211_ATTR_WIPHY) +msg.nla_put_u32(channels.ch2rf(ch),nl80211h.NL80211_ATTR_WIPHY_FREQ) +msg.nla_put_u32(CHWIDTHS.index(chw),nl80211h.NL80211_ATTR_WIPHY_CHANNEL_TYPE) + +and results in a 'invalid argument' error. So, am I sending the wrong crap? The +description for this command in nl80211_h + + * @NL80211_CMD_SET_CHANNEL: Set the channel (using %NL80211_ATTR_WIPHY_FREQ + * and the attributes determining channel width) the given interface + * (identifed by %NL80211_ATTR_IFINDEX) shall operate on. + * In case multiple channels are supported by the device, the mechanism + * with which it switches channels is implementation-defined. + * When a monitor interface is given, it can only switch channel while + * no other interfaces are operating to avoid disturbing the operation + * of any other interfaces, and other interfaces will again take + * precedence when they are used. + +mentions ifindex. Adding the ifindex with: + +msg.nla_put_u32(nl80211h.NL80211_ATTR_IFINDEX,8) + +still gives an 'invalid argument' error. Took out channel width and still no go + +* workaround in place, using the deprecated NL80211_CMD_SET_WIPHY + +7) Would like to be able set the tx-power, not just to the max but lower or raise +as desired, neither of the below work in iw or through netlinks + +dev set txpower [] + Specify transmit power level and setting type. + +phy set txpower [] + Specify transmit power level and setting type. diff --git a/pyric/TODO b/pyric/TODO new file mode 100644 index 0000000..25df1d0 --- /dev/null +++ b/pyric/TODO @@ -0,0 +1,18 @@ + 1) overall + o look at iw dev wlan0 link + o look at iw dev + o have been using iwlist nic channel to get the current channel. + - this only works on STAs that are associated + - this uses ioctl + - Can we use iw to find the current channel? and can we find the current + channel of a radio in monitor mode that is actively scanning? If not, just + use the structure returned from info + 2) libnl.py + o see (1) in RFI + o define attr_ops and attr_mcast_groups in nla_policy_attr + 4) pyw + o add txget from iw perspective + o figure out why txset doesn't work + o devstds sucks, find a better way to find the supported standards of a card + 5) User Guide + o finish it \ No newline at end of file diff --git a/pyric/__init__.py b/pyric/__init__.py new file mode 100644 index 0000000..d6a9d8e --- /dev/null +++ b/pyric/__init__.py @@ -0,0 +1,130 @@ +#!/usr/bin/env python +""" pyric Python Radio Interface Controller + +Copyright (C) 2016 Dale V. Patterson (wraith.wireless@yandex.com) + +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 3 of the License, or (at your option) any later +version. + +Redistribution and use in source and binary forms, with or without modifications, +are permitted provided that the following conditions are met: + o Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + o Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + o Neither the name of the orginal author Dale V. Patterson nor the names of any + contributors may be used to endorse or promote products derived from this + software without specific prior written permission. + +Defines the Pyric error class and constants for some errors. All pyric errors +will follow the 2-tuple form of EnvironmentError + +Requires: + linux (preferred 3.x kernel) + Python 2.7 + + pyric 0.0.2 + desc: wireless nic (radio) manipulation, enumeration, and attribute enumeration + includes: /net /lib pyw 0.0.3 radio 0.0.4 utils 0.0.2 + changes: + o added ifconfig/iwconfig functions to pyw + o reworked exception handling + - all exceptions from libnl, libio & pyw are pyric.error + - pyw will allow pyric to pass through + - reworked errorcodes to derive from errno + o added _iostub_, _nlstub_ and reworked traditiona commands to utilize these + o finished porting nl80211_h and nl80211_c (for attribute policies) + o pyw no longer provides familyid as a public function, rather it now uses a + private global value for the nl80211 family id and will instantiate it one + time only. In this way, callers do not not have to worry about retrieving and + passing it + o regdom get & set implemented + o info implemented + + pyric 0.0.3 + desc: wireless nic (radio) manipulation, enumeration, and attribute enumeration + includes: /net /lib pyw 0.0.3 device 0.0.3 channels 0.0.1 + changes: + o removed radio/Radio class (shouldn't be the responsibility of this) + o added channels.py (provides channel/freq functions) + o added RFI page for notes/observations/questions + o changed utils.py to device.py + o updated libnl + o added channel set & get + - channel get only works when device is associated + - channel set only works when card is in monitor mode and all other interfaces + have been deleted + o added device add & delete + + pyric 0.0.4 + desc: wireless nic (radio) manipulation, enumeration, and attribute enumeration + includes: /net /lib pyw 0.1.0 device 0.0.3 channels 0.0.1 setup 0.0.2 + changes: + o rewrote pyw function to handle one-time & persistent functions using a + single function interface for each command + + pyric 0.0.5 + desc: wireless nic (radio) manipulation, enumeration, and attribute enumeration + includes: /net /lib /docs pyw 0.1.2 device 0.0.3 channels 0.0.1 + changes: + o added Card class and wrote functions to handle it in pyw + o implemented basic help functionality (for nl80211) + o added monitor flag(s) support in devadd + o began work on a user guide + o added nested attribute handling + o added partial phyinfo handles all but supported channels/bands + o fixed bugs in devinfo and phyinfo + o added setup.py and required files + + pyric 0.0.6 + desc: Pythonic iw - wireless nic (radio) manipulation, enumeration, and attribute + enumeration + includes: /docs /examples /lib /net pyw 0.1.2 device 0.0.3 channels 0.0.1 + changes: + o move pyric under pyric to facilitate setuptools and packaging + - moved LICENSE, MANIFEST.in README.md setup.cfg setup.py examples/ PyRIC.pdf + to outer pyric + o at least one card (ath9k_htc) has an unknown supported command, added a + wrapper around the list IFTYPES to handle commands not listed + + pyric 0.0.7 + desc: Pythonic iw - wireless nic (radio) manipulation, enumeration, and attribute + enumeration + includes: /docs /examples /lib /net pyw 0.1.2 device 0.0.3 channels 0.0.1 + changes: + o libnl: attribute related i.e. nla_* moved out of GENLMsg class and made as + standalone functions + o in pyw + - added modeset/modeget in pyw + - readded freqset in pyw + - added devcmds in pyw + - annotated (in comments) if fcts needed root privileges +""" + +__name__ = 'pyric' +__license__ = 'GPLv3' +__version__ = '0.0.7' +__date__ = 'April 2016' +__author__ = 'Dale Patterson' +__maintainer__ = 'Dale Patterson' +__email__ = 'wraith.wireless@yandex.com' +__status__ = 'Development' + +from os import strerror + +# all exceptions are tuples t=(error code,error message) +# we use errno.errocodes and use codes < 0 as an undefined error code +EUNDEF = -1 +class error(EnvironmentError): pass + +def perror(e): + """ + :param e: error code + :returns: string description of error code + """ + # anything less than 0 is an unknown + return strerror(e) + diff --git a/pyric/channels.py b/pyric/channels.py new file mode 100644 index 0000000..1ad359a --- /dev/null +++ b/pyric/channels.py @@ -0,0 +1,89 @@ +#!/usr/bin/env python + +""" channels.py: 802.11 channel/freq utilities + +Copyright (C) 2016 Dale V. Patterson (wraith.wireless@yandex.com) + +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 3 of the License, or (at your option) any later +version. + +Redistribution and use in source and binary forms, with or without modifications, +are permitted provided that the following conditions are met: + o Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + o Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + o Neither the name of the orginal author Dale V. Patterson nor the names of any + contributors may be used to endorse or promote products derived from this + software without specific prior written permission. + +Only defines ISM 2.4Ghz and UNII 5Ghz + +""" + +__name__ = 'channels' +__license__ = 'GPLv3' +__version__ = '0.0.1' +__date__ = 'August 2014' +__author__ = 'Dale Patterson' +__maintainer__ = 'Dale Patterson' +__email__ = 'wraith.wireless@yandex.com' +__status__ = 'Production' + +import pyric.net.wireless.nl80211_h as nl80211h + +# redefined widths (allowed in nl80211h) +CHWIDTHS = nl80211h.NL80211_CHAN_WIDTHS + +# ISM Bands +ISM_24_C2F={1:2412,2:2417,3:2422,4:2427,5:2432,6:2437,7:2442, + 8:2447,9:2452,10:2457,11:2462,12:2467,13:2472,14:2484} +ISM_24_F2C={2432:5,2467:12,2437:6,2472:13,2442:7,2484:14,2412:1, + 2447:8,2417:2,2452:9,2422:3,2457:10,2427:4,2462:11} + +# UNII 5 Bands +UNII_5_C2F={36:5180,38:5190,40:5200,42:5210,44:5220,46:5230,48:5240,52:5260, + 56:5280,60:5300,64:5320,100:5500,104:5520,108:5540,112:5560,116:5580, + 120:5600,124:5620,128:5640,132:5660,136:5680,140:5700,149:5745, + 153:5765,157:5785,161:5805,165:5825} +UNII_5_F2C={5765:153,5640:128,5260:52,5520:104,5785:157,5660:132,5280:56, + 5540:108,5805:161,5680:136,5300:60,5560:112,5180:36,5825:165, + 5700:140,5190:38,5320:64,5580:116,5200:40,5210:42,5600:120, + 5220:44,5230:46,5745:149,5620:124,5240:48,5500:100} + +# UNII 4 Bands +#UNII_4_C2F={183:4915,184:4920,185:4925,187:4935,188:4940,189:4945,192:4960,196:4980} +#UNII_4_F2C={4960:192,4935:187,4940:188,4945:189,4915:183,4980:196,4920:184,4925:185} + +def channels(): + """ :returns: list of all channels """ + return sorted(ISM_24_C2F.keys() + UNII_5_C2F.keys()) + +def freqs(): + """ :returns: list of frequencies """ + return sorted(ISM_24_F2C.keys() + UNII_5_F2C.keys()) + +def ch2rf(c): + """ + channel to frequency conversion + + :param c: channel + :returns: frequency in MHz corresponding to channel + """ + if c in ISM_24_C2F: return ISM_24_C2F[c] + if c in UNII_5_C2F: return UNII_5_C2F[c] + return None + +def rf2ch(f): + """ + frequency to channel conversion + + :param f: frequency (in MHz) + :returns: channel number corresponding to frequency + """ + if f in ISM_24_F2C: return ISM_24_F2C[f] + if f in UNII_5_F2C: return UNII_5_F2C[f] + return None \ No newline at end of file diff --git a/pyric/device.py b/pyric/device.py new file mode 100644 index 0000000..0ab18f3 --- /dev/null +++ b/pyric/device.py @@ -0,0 +1,93 @@ +#!/usr/bin/env python +""" device.py: utility functions + +Copyright (C) 2016 Dale V. Patterson (wraith.wireless@yandex.com) + +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 3 of the License, or (at your option) any later +version. + +Redistribution and use in source and binary forms, with or without modifications, +are permitted provided that the following conditions are met: + o Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + o Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + o Neither the name of the orginal author Dale V. Patterson nor the names of any + contributors may be used to endorse or promote products derived from this + software without specific prior written permission. + +Defines device functions to get driver and chipset. Should we move hwaddr from +hex string to here? + +""" + +__name__ = 'device' +__license__ = 'GPLv3' +__version__ = '0.0.3' +__date__ = 'August 2014' +__author__ = 'Dale Patterson' +__maintainer__ = 'Dale Patterson' +__email__ = 'wraith.wireless@yandex.com' +__status__ = 'Production' + +from os import listdir + +dpath = '/proc/net/dev' # system device details +drvpath = '/sys/class/net/{0}/device/driver/module/drivers' # format w/ device name +phypath = '/sys/class/ieee80211/{0}' # format w/ phyiscal name +# NOTE phypath + index contains the ifindex (sometimes) + +def ifdriver(dev): + """ + :param dev: device name + :returns: driver (or unknown) + """ + try: + # find the driver for nic in driver's module, split on ':' and return + ds = listdir(drvpath.format(dev)) + if len(ds) > 1: return "Unknown" + return ds[0].split(':')[1] + except OSError: + return "Unknown" + +def ifchipset(driver): + """ + returns the chipset for given driver (Thanks aircrack-ng team) + :param driver: nic driver + :returns: chipset of driver + NOTE: does not fully implement the airmon-ng getChipset where identification + requires system commands + """ + if driver == "Unknown": return "Unknown" + if driver == "Otus" or driver == "arusb_lnx": return "AR9001U" + if driver == "WiLink": return "TIWLAN" + if driver == "ath9k_htc" or driver == "usb": return "AR9001/9002/9271" + if driver.startswith("ath") or driver == "ar9170usb": return "Atheros" + if driver == "zd1211rw_mac80211": return "ZyDAS 1211" + if driver == "zd1211rw": return "ZyDAS" + if driver.startswith("acx"): return "TI ACX1xx" + if driver == "adm8211": return "ADMtek 8211" + if driver == "at76_usb": return "Atmel" + if driver.startswith("b43") or driver == "bcm43xx": return "Broadcom" + if driver.startswith("p54") or driver == "prism54": return "PrismGT" + if driver == "hostap": return "Prism 2/2.5/3" + if driver == "r8180" or driver == "rtl8180": return "RTL8180/RTL8185" + if driver == "rtl8187" or driver == "r8187": return "RTL8187" + if driver == "rt2570" or driver == "rt2500usb": return "Ralink 2570 USB" + if driver == "rt2400" or driver == "rt2400pci": return "Ralink 2400 PCI" + if driver == "rt2500" or driver == "rt2500pci": return "Ralink 2560 PCI" + if driver == "rt61" or driver == "rt61pci": return "Ralink 2561 PCI" + if driver == "rt73" or driver == "rt73usb": return "Ralink 2573 USB" + if driver == "rt2800" or driver == "rt2800usb" or driver == "rt3070sta": return "Ralink RT2870/3070" + if driver == "ipw2100": return "Intel 2100B" + if driver == "ipw2200": return "Intel 2200BG/2915ABG" + if driver == "ipw3945" or driver == "ipwraw" or driver == "iwl3945": return "Intel 3945ABG" + if driver == "ipw4965" or driver == "iwl4965": return "Intel 4965AGN" + if driver == "iwlagn" or driver == "iwlwifi": return "Intel 4965/5xxx/6xxx/1xxx" + if driver == "orinoco": return "Hermes/Prism" + if driver == "wl12xx": return "TI WL1251/WL1271" + if driver == "r871x_usb_drv": return "Realtek 81XX" + return "Unknown" \ No newline at end of file diff --git a/pyric/docs/__init__.py b/pyric/docs/__init__.py new file mode 100644 index 0000000..1f0b5ce --- /dev/null +++ b/pyric/docs/__init__.py @@ -0,0 +1,38 @@ +#!/usr/bin/env python +""" docs + +Copyright (C) 2016 Dale V. Patterson (wraith.wireless@yandex.com) + +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 3 of the License, or (at your option) any later +version. + +Redistribution and use in source and binary forms, with or without modifications, +are permitted provided that the following conditions are met: + o Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + o Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + o Neither the name of the orginal author Dale V. Patterson nor the names of any + contributors may be used to endorse or promote products derived from this + software without specific prior written permission. + +Documentation to include lookup functionality for nl80211 commands and attributes + + docs 0.0.1 + desc: PyRIC and nl80211 documentation/help + includes: nl80211.cmd + changes: + o Began work on User Guide +""" + +__name__ = 'docs' +__license__ = 'GPLv3' +__version__ = '0.0.1' +__date__ = 'April 2016' +__author__ = 'Dale Patterson' +__maintainer__ = 'Dale Patterson' +__email__ = 'wraith.wireless@yandex.com' +__status__ = 'Development' \ No newline at end of file diff --git a/pyric/docs/attributes.help b/pyric/docs/attributes.help new file mode 100644 index 0000000..5a62eb6 --- /dev/null +++ b/pyric/docs/attributes.help @@ -0,0 +1,5 @@ +# attributes.help (json format) +# Automatically generated 2016-04-17T11:06:58.35097 + +{"@NL80211_ATTR_PMKID": {"cmds": [], "type": "unspec", "desc": "PMK material for PMKSA caching"}, "@NL80211_ATTR_WIPHY": {"cmds": [], "type": "unspec", "desc": "index of wiphy to operate on /sys/class/ieee80211//index"}, "@NL80211_ATTR_SCAN_SUPP_RATES": {"cmds": [], "type": "unspec", "desc": "rates per to be advertised as supported in scan nested array attribute containing an entry for each band, with the entry being a list of supported rates as defined by IEEE 802.11 7.3.2.2 but without the length restriction (at most %NL80211_MAX_SUPP_RATES)."}, "@NL80211_ATTR_AKM_SUITES": {"cmds": [], "type": "unspec", "desc": "Used with CONNECT indicate which key management algorithm(s) to use (an array of u32)."}, "@NL80211_ATTR_SCAN_FLAGS": {"cmds": [], "type": "unspec", "desc": "scan request control flags "}, "@NL80211_ATTR_IFTYPE": {"cmds": [], "type": "unspec", "desc": "type of virtual interface"}, "@NL80211_ATTR_MAX_SCAN_IE_LEN": {"cmds": [], "type": "unspec", "desc": "maximum length of information elements that can be added to a scan request"}, "@NL80211_ATTR_FREQ_BEFORE": {"cmds": [], "type": "unspec", "desc": "A channel which has suffered a regulatory change due to considerations from a beacon hint. This attribute reflects the state of the channel _before_ the beacon hint processing. This attributes consists of a nested attribute containing NL80211_FREQUENCY_ATTR_*"}, "@NL80211_ATTR_P2P_OPPPS": {"cmds": [], "type": "unspec", "desc": "P2P GO opportunistic PS START_AP and SET_BSS commands. This can have the values 0 or 1; if not given in START_AP 0 is assumed, if not given in SET_BSS no change is made."}, "@NL80211_ATTR_IE_ASSOC_RESP": {"cmds": ["%NL80211_CMD_NEW_BEACON", "%NL80211_CMD_SET_BEACON"], "type": "unspec", "desc": "Information element Response frames. This is used with %NL80211_CMD_NEW_BEACON and %NL80211_CMD_SET_BEACON to provide extra IEs (e.g., WPS/P2P IE) into (Re)Association Response frames when the driver (or firmware) replies to (Re)Association Request frames."}, "@NL80211_ATTR_MPATH_NEXT_HOP": {"cmds": [], "type": "unspec", "desc": "MAC address of the next hop for a mesh path"}, "@NL80211_ATTR_RXMGMT_FLAGS": {"cmds": [], "type": "unspec", "desc": "flags for nl80211_send_mgmt As specified in the &enum nl80211_rxmgmt_flags."}, "@NL80211_ATTR_MAX_CRIT_PROT_DURATION": {"cmds": [], "type": "unspec", "desc": "duration in milliseconds in which the connection should have increased reliability (u16)."}, "@NL80211_ATTR_STA_LISTEN_INTERVAL": {"cmds": [], "type": "unspec", "desc": "listen interval as defined by IEEE 802.11 7.3.1.6 (u16)."}, "@NL80211_ATTR_FRAME_TYPE": {"cmds": [], "type": "unspec", "desc": "A u16 indicating the frame type @NL80211_CMD_REGISTER_FRAME command."}, "@NL80211_ATTR_REG_RULES": {"cmds": [], "type": "unspec", "desc": "a nested array of regulatory domain regulatory rules."}, "@NL80211_ATTR_STATUS_CODE": {"cmds": [], "type": "unspec", "desc": "StatusCode for the event (u16)"}, "@NL80211_ATTR_VHT_CAPABILITY": {"cmds": [], "type": "unspec", "desc": "VHT Capability information element association request when used with NL80211_CMD_NEW_STATION)"}, "@NL80211_ATTR_CRIT_PROT_ID": {"cmds": [], "type": "unspec", "desc": "critical protocol identifier requiring increased reliability, see &enum nl80211_crit_proto_id (u16)."}, "@NL80211_ATTR_TDLS_ACTION": {"cmds": [], "type": "unspec", "desc": "Low level TDLS action code request, link setup confirm, link teardown, etc.). Values are described in the TDLS (802.11z) specification."}, "@NL80211_ATTR_RESP_IE": {"cmds": [], "type": "unspec", "desc": " sent by peer, for ROAM and successful CONNECT events."}, "@NL80211_ATTR_WDEV": {"cmds": [], "type": "unspec", "desc": "wireless device identifier that don't have a netdev (u64)"}, "@NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS": {"cmds": [], "type": "unspec", "desc": "number of SSIDs you can scan with a single scheduled scan request, a wiphy attribute."}, "@NL80211_ATTR_CONTROL_PORT_ETHERTYPE": {"cmds": [], "type": "unspec", "desc": "A 16 ethertype that will be used for key negotiation. It can be specified with the associate and connect commands. If it is not specified, the value defaults to 0x888E (PAE, 802.1X). This attribute is also used as a flag in the wiphy information to indicate that protocols other than PAE are supported."}, "@NL80211_ATTR_KEY_TYPE": {"cmds": [], "type": "unspec", "desc": "Key Type"}, "@NL80211_ATTR_ROAM_SUPPORT": {"cmds": [], "type": "unspec", "desc": "Indicates whether the firmware is capable of roaming to another AP in the same ESS if the signal lever is low."}, "@NL80211_ATTR_TX_NO_CCK_RATE": {"cmds": ["%NL80211_CMD_TRIGGER_SCAN", "%NL80211_CMD_FRAME"], "type": "unspec", "desc": "Indicates whether to use CCK rate or not for management frames transmission. In order to avoid p2p probe/action frames are being transmitted at CCK rate in 2GHz band, the user space applications use this attribute. This attribute is used with %NL80211_CMD_TRIGGER_SCAN and %NL80211_CMD_FRAME commands."}, "@NL80211_ATTR_MGMT_SUBTYPE": {"cmds": ["%NL80211_CMD_SET_MGMT_EXTRA_IE"], "type": "unspec", "desc": "Management frame subtype for %NL80211_CMD_SET_MGMT_EXTRA_IE."}, "@NL80211_ATTR_RX_FRAME_TYPES": {"cmds": [], "type": "unspec", "desc": "wiphy capability attribute nested attribute of %NL80211_ATTR_FRAME_TYPE attributes, containing information about which frame types can be registered for RX."}, "@NL80211_ATTR_BSS_BASIC_RATES": {"cmds": [], "type": "unspec", "desc": "basic rates rates in format defined by IEEE 802.11 7.3.2.2 but without the length restriction (at most %NL80211_MAX_SUPP_RATES)."}, "@NL80211_ATTR_IE_PROBE_RESP": {"cmds": ["%NL80211_CMD_NEW_BEACON", "%NL80211_CMD_SET_BEACON"], "type": "unspec", "desc": "Information element This is used with %NL80211_CMD_NEW_BEACON and %NL80211_CMD_SET_BEACON to provide extra IEs (e.g., WPS/P2P IE) into Probe Response frames when the driver (or firmware) replies to Probe Request frames."}, "@NL80211_ATTR_SUPPORTED_IFTYPES": {"cmds": [], "type": "unspec", "desc": "nested attribute containing all supported interface types, each a flag attribute with the number of the interface mode."}, "@NL80211_ATTR_IFINDEX": {"cmds": [], "type": "unspec", "desc": "network interface index of the device to operate on"}, "@NL80211_ATTR_EXT_CAPA_MASK": {"cmds": [], "type": "unspec", "desc": "Extended capabilities that the kernel driver has set in the %NL80211_ATTR_EXT_CAPA value, for multibit fields."}, "@NL80211_ATTR_MAX_REMAIN_ON_CHANNEL_DURATION": {"cmds": [], "type": "unspec", "desc": "Device attribute that specifies the maximum duration that can be requested with the remain-on-channel operation, in milliseconds, u32."}, "@NL80211_ATTR_REQ_IE": {"cmds": [], "type": "unspec", "desc": " sent out by the card, for ROAM and successful CONNECT events."}, "@NL80211_ATTR_REKEY_DATA": {"cmds": [], "type": "unspec", "desc": "nested attribute containing the information necessary for GTK rekeying in the device, see &enum nl80211_rekey_data."}, "@NL80211_ATTR_HT_CAPABILITY": {"cmds": [], "type": "unspec", "desc": "HT Capability information element association request when used with NL80211_CMD_NEW_STATION)"}, "@NL80211_ATTR_KEY_DATA": {"cmds": [], "type": "unspec", "desc": " 16 bytes encryption key followed by 8 bytes each for TX and RX MIC keys"}, "@NL80211_ATTR_KEY_DEFAULT": {"cmds": [], "type": "unspec", "desc": "Flag attribute indicating the key is default key"}, "@NL80211_ATTR_MESH_SETUP": {"cmds": [], "type": "unspec", "desc": "Optional mesh setup parameters changed once the mesh is active."}, "@NL80211_ATTR_PMKSA_CANDIDATE": {"cmds": [], "type": "unspec", "desc": "Nested attribute containing the PMKSA caching candidate information, see &enum nl80211_pmksa_candidate_attr."}, "@NL80211_ATTR_WIPHY_RTS_THRESHOLD": {"cmds": [], "type": "unspec", "desc": "RTS threshold larger than or equal to this use RTS/CTS handshake); allowed range: 0..65536, disable with (u32)-1; dot11RTSThreshold; u32"}, "@NL80211_ATTR_DTIM_PERIOD": {"cmds": [], "type": "unspec", "desc": "DTIM period for beaconing"}, "@NL80211_ATTR_MAX_NUM_SCAN_SSIDS": {"cmds": [], "type": "unspec", "desc": "number of SSIDs you can scan with a single scan request, a wiphy attribute."}, "@NL80211_ATTR_MESH_CONFIG": {"cmds": [], "type": "unspec", "desc": "Mesh configuration parameters containing attributes from &enum nl80211_meshconf_params."}, "@NL80211_ATTR_COOKIE": {"cmds": [], "type": "unspec", "desc": "Generic 64"}, "@NL80211_ATTR_MAX_MATCH_SETS": {"cmds": [], "type": "unspec", "desc": "maximum number of sets that can be used with @NL80211_ATTR_SCHED_SCAN_MATCH, a wiphy attribute."}, "@NL80211_ATTR_CH_SWITCH_COUNT": {"cmds": [], "type": "unspec", "desc": "u32 attribute specifying the number of TBTT until the channel switch event."}, "@NL80211_ATTR_OFFCHANNEL_TX_OK": {"cmds": [], "type": "unspec", "desc": "For management frame TX transmitted on another channel when the channel given doesn't match the current channel. If the current channel doesn't match and this flag isn't set, the frame will be rejected. This is also used as an nl80211 capability flag."}, "@NL80211_ATTR_SUPPORT_MESH_AUTH": {"cmds": [], "type": "unspec", "desc": "Currently allows auth frames in a mesh to be passed to userspace for processing via the @NL80211_MESH_SETUP_USERSPACE_AUTH flag."}, "@NL80211_ATTR_REASON_CODE": {"cmds": ["%NL80211_CMD_DISASSOCIATE"], "type": "unspec", "desc": "ReasonCode for %NL80211_CMD_DISASSOCIATE, u16"}, "@NL80211_ATTR_STA_WME": {"cmds": [], "type": "unspec", "desc": "Nested attribute containing the wme configuration of the station, see &enum nl80211_sta_wme_attr."}, "@NL80211_ATTR_AP_ISOLATE": {"cmds": [], "type": "unspec", "desc": " connected to this BSS."}, "@NL80211_ATTR_TESTDATA": {"cmds": [], "type": "unspec", "desc": "Testmode data blob We recommend using nested, driver-specific attributes within this."}, "@NL80211_ATTR_CIPHER_SUITES_PAIRWISE": {"cmds": [], "type": "unspec", "desc": "For crypto settings for connect or other commands, indicates which pairwise cipher suites are used"}, "@NL80211_ATTR_BSS_CTS_PROT": {"cmds": [], "type": "unspec", "desc": "whether CTS protection is enabled "}, "@NL80211_ATTR_BSS_SHORT_SLOT_TIME": {"cmds": [], "type": "unspec", "desc": "whether short slot time enabled (u8, 0 or 1)"}, "@NL80211_ATTR_PEER_AID": {"cmds": [], "type": "unspec", "desc": "Association ID for the peer TDLS station This is similar to @NL80211_ATTR_STA_AID but with a difference of being allowed to be used with the first @NL80211_CMD_SET_STATION command to update a TDLS peer STA entry."}, "@NL80211_ATTR_SPLIT_WIPHY_DUMP": {"cmds": [], "type": "unspec", "desc": "flag attribute receiving the data for a single wiphy split across multiple messages, given with wiphy dump message"}, "@NL80211_ATTR_SUPPORT_IBSS_RSN": {"cmds": [], "type": "unspec", "desc": "The device supports IBSS RSN means support for per-station GTKs."}, "@NL80211_ATTR_IE": {"cmds": ["%NL80211_CMD_SET_MGMT_EXTRA_IE"], "type": "unspec", "desc": "Information element %NL80211_CMD_SET_MGMT_EXTRA_IE)."}, "@NL80211_ATTR_AUTH_TYPE": {"cmds": [], "type": "unspec", "desc": "AuthenticationType represented as a u32"}, "@NL80211_ATTR_BSS": {"cmds": [], "type": "unspec", "desc": "scan result BSS"}, "@NL80211_ATTR_PROBE_RESP_OFFLOAD": {"cmds": [], "type": "unspec", "desc": "Indicates that the HW responds to probe requests while operating in AP-mode. This attribute holds a bitmap of the supported protocols for offloading (see &enum nl80211_probe_resp_offload_support_attr)."}, "@NL80211_ATTR_STA_SUPPORTED_CHANNELS": {"cmds": [], "type": "unspec", "desc": "array of supported channels"}, "@NL80211_ATTR_KEY_SEQ": {"cmds": [], "type": "unspec", "desc": "transmit key sequence number CCMP keys, each six bytes in little endian"}, "@NL80211_ATTR_4ADDR": {"cmds": [], "type": "unspec", "desc": "Use 4"}, "@NL80211_ATTR_TIMED_OUT": {"cmds": ["%NL80211_CMD_AUTHENTICATE"], "type": "unspec", "desc": "a flag indicating than an operation timed out is used, e.g., with %NL80211_CMD_AUTHENTICATE event"}, "@NL80211_ATTR_UNSPEC": {"cmds": [], "type": "unspec", "desc": "unspecified attribute to catch errors"}, "@NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT": {"cmds": [], "type": "unspec", "desc": "When included along with %NL80211_ATTR_CONTROL_PORT_ETHERTYPE, indicates that the custom ethertype frames used for key negotiation must not be encrypted."}, "@NL80211_ATTR_BEACON_TAIL": {"cmds": [], "type": "unspec", "desc": "portion of the beacon after the TIM IE"}, "@NL80211_ATTR_REG_INITIATOR": {"cmds": [], "type": "unspec", "desc": "indicates who requested the regulatory domain currently in effect. This could be any of the %NL80211_REGDOM_SET_BY_*"}, "@NL80211_ATTR_WIPHY_TX_POWER_LEVEL": {"cmds": [], "type": "unspec", "desc": "Transmit power level in signed mBm units This is used in association with @NL80211_ATTR_WIPHY_TX_POWER_SETTING for non-automatic settings."}, "@NL80211_ATTR_ACL_POLICY": {"cmds": [], "type": "unspec", "desc": "ACL policy carried in a u32 attribute"}, "@NL80211_ATTR_SAE_DATA": {"cmds": [], "type": "unspec", "desc": "SAE elements in Authentication frames with the Authentication transaction sequence number field."}, "@NL80211_ATTR_WIPHY_RETRY_LONG": {"cmds": [], "type": "unspec", "desc": "TX retry limit for frames whose length is greater than the RTS threshold; allowed range: 1..255; dot11ShortLongLimit; u8"}, "@NL80211_ATTR_INTERFACE_COMBINATIONS": {"cmds": [], "type": "unspec", "desc": "Nested attribute listing the supported interface combinations. In each nested item, it contains attributes defined in &enum nl80211_if_combination_attrs."}, "@NL80211_ATTR_WIPHY_ANTENNA_AVAIL_TX": {"cmds": [], "type": "unspec", "desc": "Bitmap of antennas which are available for configuration as TX antennas via the above parameters."}, "@NL80211_ATTR_KEY_DEFAULT_MGMT": {"cmds": [], "type": "unspec", "desc": "Flag attribute indicating the key is the default management key"}, "@NL80211_ATTR_BSS_HT_OPMODE": {"cmds": [], "type": "unspec", "desc": "HT operation mode "}, "@NL80211_ATTR_BEACON_HEAD": {"cmds": [], "type": "unspec", "desc": "portion of the beacon before the TIM IE"}, "@NL80211_ATTR_KEYS": {"cmds": [], "type": "unspec", "desc": "array of keys for static WEP keys for connect and join_ibss(), key information is in a nested attribute each with %NL80211_KEY_* sub-attributes"}, "@NL80211_ATTR_MDID": {"cmds": [], "type": "unspec", "desc": "Mobility Domain Identifier"}, "@NL80211_ATTR_STA_PLINK_ACTION": {"cmds": [], "type": "unspec", "desc": "action to perform on the mesh peer link (see &enum nl80211_plink_action)."}, "@NL80211_ATTR_ACK": {"cmds": [], "type": "unspec", "desc": "Flag attribute indicating that the frame was acknowledged by the recipient."}, "@NL80211_ATTR_WIPHY_FREQ": {"cmds": [], "type": "unspec", "desc": "frequency of the selected channel in MHz defines the channel together with the (deprecated) %NL80211_ATTR_WIPHY_CHANNEL_TYPE attribute or the attributes %NL80211_ATTR_CHANNEL_WIDTH and if needed %NL80211_ATTR_CENTER_FREQ1 and %NL80211_ATTR_CENTER_FREQ2"}, "@NL80211_ATTR_WPA_VERSIONS": {"cmds": [], "type": "unspec", "desc": "Used with CONNECT indicate which WPA version(s) the AP we want to associate with is using (a u32 with flags from &enum nl80211_wpa_versions)."}, "@NL80211_ATTR_SUPPORT_AP_UAPSD": {"cmds": [], "type": "unspec", "desc": "the device supports uapsd when working as AP."}, "@NL80211_ATTR_SCHED_SCAN_MATCH": {"cmds": [], "type": "unspec", "desc": "Nested attribute with one or more sets of attributes to match during scheduled scans. Only BSSs that match any of the sets will be reported. These are pass-thru filter rules. For a match to succeed, the BSS must match all attributes of a set. Since not every hardware supports matching all types of attributes, there is no guarantee that the reported BSSs are fully complying with the match sets and userspace needs to be able to ignore them by itself. Thus, the implementation is somewhat hardware-dependent, but this is only an optimization and the userspace application needs to handle all the non-filtered results anyway. If the match attributes don't make sense when combined with the values passed in @NL80211_ATTR_SCAN_SSIDS (eg. if an SSID is included in the probe request, but the match attributes will never let it go through), -EINVAL may be returned. If ommited, no filtering is done."}, "@NL80211_ATTR_LOCAL_MESH_POWER_MODE": {"cmds": [], "type": "unspec", "desc": "local mesh STA link defined in &enum nl80211_mesh_power_mode."}, "@NL80211_ATTR_SCHED_SCAN_INTERVAL": {"cmds": [], "type": "unspec", "desc": "Interval between scheduled scan cycles, in msecs."}, "@NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED": {"cmds": [], "type": "unspec", "desc": "indicates capabilities, the supported WoWLAN triggers"}, "@NL80211_ATTR_REG_TYPE": {"cmds": [], "type": "unspec", "desc": "indicates the type of the regulatory domain currently set. This can be one of the nl80211_reg_type (%NL80211_REGDOM_TYPE_*)"}, "@NL80211_ATTR_SUPPORTED_COMMANDS": {"cmds": [], "type": "unspec", "desc": "wiphy attribute that specifies an array of command numbers (i.e. a mapping index to command number) that the driver for the given wiphy supports."}, "@NL80211_ATTR_SCAN_FREQUENCIES": {"cmds": [], "type": "unspec", "desc": "nested attribute with frequencies "}, "@NL80211_ATTR_IFNAME": {"cmds": [], "type": "unspec", "desc": "network interface name"}, "@NL80211_ATTR_CSA_IES": {"cmds": [], "type": "unspec", "desc": "Nested set of attributes containing the IE information for the time while performing a channel switch."}, "@NL80211_ATTR_CONTROL_PORT": {"cmds": ["%NL80211_CMD_ASSOCIATE"], "type": "unspec", "desc": "A flag indicating whether user space controls IEEE 802.1X port, i.e., sets/clears %NL80211_STA_FLAG_AUTHORIZED, in station mode. If the flag is included in %NL80211_CMD_ASSOCIATE request, the driver will assume that the port is unauthorized until authorized by user space. Otherwise, port is marked authorized by default in station mode."}, "@NL80211_ATTR_CSA_C_OFF_PRESP": {"cmds": [], "type": "unspec", "desc": "Offset of the channel switch counter field in the probe response (%NL80211_ATTR_PROBE_RESP)."}, "@NL80211_ATTR_CIPHERS_PAIRWISE": {"cmds": [], "type": "unspec", "desc": "Used with CONNECT to indicate which unicast key ciphers will be used with the connection (an array of u32)."}, "@NL80211_ATTR_WIPHY_ANTENNA_RX": {"cmds": [], "type": "unspec", "desc": "Bitmap of allowed antennas for receiving This can be used to mask out antennas which are not attached or should not be used for receiving. If an antenna is not selected in this bitmap the hardware should not be configured to receive on this antenna. For a more detailed description see @NL80211_ATTR_WIPHY_ANTENNA_TX."}, "@NL80211_ATTR_DISCONNECTED_BY_AP": {"cmds": [], "type": "unspec", "desc": "A flag indicating that the DISCONNECT event was due to the AP disconnecting the station, and not due to a local disconnect request."}, "@NL80211_ATTR_INACTIVITY_TIMEOUT": {"cmds": [], "type": "unspec", "desc": "timeout value in seconds used by the drivers which has MLME in firmware and does not have support to report per station tx/rx activity to free up the staion entry from the list. This needs to be used when the driver advertises the capability to timeout the stations."}, "@NL80211_ATTR_TDLS_SUPPORT": {"cmds": [], "type": "unspec", "desc": "A flag indicating the device can operate as a TDLS peer sta."}, "@NL80211_ATTR_CENTER_FREQ2": {"cmds": [], "type": "unspec", "desc": "Center frequency of the second part of the channel, used only for 80+80 MHz bandwidth"}, "@NL80211_ATTR_STA_EXT_CAPABILITY": {"cmds": [], "type": "unspec", "desc": "Station extended capabilities are advertised to the driver, e.g., to enable TDLS off channel operations and PU-APSD."}, "@NL80211_ATTR_STA_PLINK_STATE": {"cmds": [], "type": "unspec", "desc": "The state of a mesh peer link as defined in &enum nl80211_plink_state. Used when userspace is driving the peer link management state machine. @NL80211_MESH_SETUP_USERSPACE_AMPE or @NL80211_MESH_SETUP_USERSPACE_MPM must be enabled."}, "@NL80211_ATTR_MAC": {"cmds": [], "type": "unspec", "desc": "MAC address "}, "@NL80211_ATTR_CSA_C_OFF_BEACON": {"cmds": [], "type": "unspec", "desc": "Offset of the channel switch counter field in the beacons tail (%NL80211_ATTR_BEACON_TAIL)."}, "@NL80211_ATTR_WIPHY_NAME": {"cmds": [], "type": "unspec", "desc": "wiphy name "}, "@NL80211_ATTR_WIPHY_ANTENNA_AVAIL_RX": {"cmds": [], "type": "unspec", "desc": "Bitmap of antennas which are available for configuration as RX antennas via the above parameters."}, "@NL80211_ATTR_CONN_FAILED_REASON": {"cmds": [], "type": "unspec", "desc": "The reason for which AP has rejected the connection request from a station. nl80211_connect_failed_reason enum has different reasons of connection failure."}, "@NL80211_ATTR_CENTER_FREQ1": {"cmds": [], "type": "unspec", "desc": "Center frequency of the first part of the channel, used for anything but 20 MHz bandwidth"}, "@NL80211_ATTR_FRAME": {"cmds": [], "type": "unspec", "desc": "frame data and body, but not FCS; used, e.g., with NL80211_CMD_AUTHENTICATE and NL80211_CMD_ASSOCIATE events"}, "@NL80211_ATTR_SOFTWARE_IFTYPES": {"cmds": [], "type": "unspec", "desc": "Nested attribute %NL80211_ATTR_SUPPORTED_IFTYPES) containing the interface types that are managed in software: interfaces of these types aren't subject to any restrictions in their number or combinations."}, "@NL80211_ATTR_PID": {"cmds": [], "type": "unspec", "desc": "Process ID of a network namespace"}, "@NL80211_ATTR_USE_MFP": {"cmds": ["%NL80211_CMD_ASSOCIATE", "%NL80211_CMD_CONNECT"], "type": "unspec", "desc": "Whether management frame protection used for the association (&enum nl80211_mfp, represented as a u32); this attribute can be used with %NL80211_CMD_ASSOCIATE and %NL80211_CMD_CONNECT requests"}, "@NL80211_ATTR_PS_STATE": {"cmds": [], "type": "unspec", "desc": "powersave state"}, "@NL80211_ATTR_PREV_BSSID": {"cmds": [], "type": "unspec", "desc": "previous BSSID commands to specify using a reassociate frame"}, "@NL80211_ATTR_DISABLE_HT": {"cmds": [], "type": "unspec", "desc": " Force HT capable interfaces to disable this feature. Currently, only supported in mac80211 drivers."}, "@NL80211_ATTR_TX_RATES": {"cmds": ["%NL80211_CMD_SET_TX_BITRATE_MASK"], "type": "unspec", "desc": "Nested set of attributes (enum nl80211_tx_rate_attributes) describing TX rates per band. The enum nl80211_band value is used as the index (nla_type() of the nested data. If a band is not included, it will be configured to allow all rates based on negotiated supported rates information. This attribute is used with %NL80211_CMD_SET_TX_BITRATE_MASK."}, "@NL80211_ATTR_MAC_ADDRS": {"cmds": [], "type": "unspec", "desc": "Array of nested MAC addresses"}, "@NL80211_ATTR_COALESCE_RULE": {"cmds": [], "type": "unspec", "desc": "Coalesce rule information"}, "@NL80211_ATTR_RADAR_EVENT": {"cmds": [], "type": "unspec", "desc": "Type of radar event for notification to userspace contains a value of enum nl80211_radar_event (u32)."}, "@NL80211_ATTR_STA_SUPPORTED_RATES": {"cmds": [], "type": "unspec", "desc": "supported rates rates as defined by IEEE 802.11 7.3.2.2 but without the length restriction (at most %NL80211_MAX_SUPP_RATES)."}, "@NL80211_ATTR_IE_RIC": {"cmds": [], "type": "unspec", "desc": "Resource Information Container Information element"}, "@NL80211_ATTR_STA_FLAGS2": {"cmds": [], "type": "unspec", "desc": "Attribute containing a &struct nl80211_sta_flag_update."}, "@NL80211_ATTR_PRIVACY": {"cmds": [], "type": "unspec", "desc": "Flag attribute that protected APs should be used. This is also used with NEW_BEACON to indicate that the BSS is to use protection."}, "@NL80211_ATTR_WIPHY_COVERAGE_CLASS": {"cmds": [], "type": "unspec", "desc": "Coverage Class as defined by IEEE 802 section 7.3.2.9; dot11CoverageClass; u8"}, "@NL80211_ATTR_BSS_SHORT_PREAMBLE": {"cmds": [], "type": "unspec", "desc": "whether short preamble is enabled (u8, 0 or 1)"}, "@NL80211_ATTR_MCAST_RATE": {"cmds": [], "type": "unspec", "desc": "Multicast tx rate "}, "@NL80211_ATTR_WIPHY_CHANNEL_TYPE": {"cmds": [], "type": "unspec", "desc": "included with NL80211_ATTR_WIPHY_FREQ if HT20 or HT40 are to be used (i.e., HT disabled if not included): NL80211_CHAN_NO_HT = HT not allowed (same as not including) NL80211_CHAN_HT20 = HT20 only NL80211_CHAN_HT40MINUS = secondary channel is below the primary channel NL80211_CHAN_HT40PLUS = secondary channel is above the primary channel This attribute is now deprecated."}, "@NL80211_ATTR_PROBE_RESP": {"cmds": [], "type": "unspec", "desc": "Probe Response template data probe-response frame. The DA field in the 802.11 header is zero-ed out, to be filled by the FW."}, "@NL80211_ATTR_CQM": {"cmds": [], "type": "unspec", "desc": "connection quality monitor configuration in a nested attribute with %NL80211_ATTR_CQM_* sub-attributes."}, "@NL80211_ATTR_DONT_WAIT_FOR_ACK": {"cmds": [], "type": "unspec", "desc": "Used with the driver to not wait for an acknowledgement. Note that due to this, it will also not give a status callback nor return a cookie. This is mostly useful for probe responses to save airtime."}, "@NL80211_ATTR_STA_VLAN": {"cmds": [], "type": "unspec", "desc": "interface index of VLAN interface to move station to, or the AP interface the station was originally added to to."}, "@NL80211_ATTR_FREQ_AFTER": {"cmds": [], "type": "unspec", "desc": "A channel which has suffered a regulatory change due to considerations from a beacon hint. This attribute reflects the state of the channel _after_ the beacon hint processing. This attributes consists of a nested attribute containing NL80211_FREQUENCY_ATTR_*"}, "@NL80211_ATTR_MESH_ID": {"cmds": [], "type": "unspec", "desc": "mesh id "}, "@NL80211_ATTR_DFS_REGION": {"cmds": [], "type": "unspec", "desc": "region for regulatory rules which this country abides to when initiating radiation on DFS channels. A country maps to one DFS region."}, "@NL80211_ATTR_MNTR_FLAGS": {"cmds": [], "type": "unspec", "desc": "flags &enum nl80211_mntr_flags."}, "@NL80211_ATTR_WIPHY_FRAG_THRESHOLD": {"cmds": [], "type": "unspec", "desc": "fragmentation threshold length in octets for frames; allowed range: 256..8000, disable fragmentation with (u32)-1; dot11FragmentationThreshold; u32"}, "@NL80211_ATTR_KEY_CIPHER": {"cmds": [], "type": "unspec", "desc": "key cipher suite section 7.3.2.25.1, e.g. 0x000FAC04)"}, "@NL80211_ATTR_KEY_IDX": {"cmds": [], "type": "unspec", "desc": "key ID "}, "@NL80211_ATTR_P2P_CTWINDOW": {"cmds": [], "type": "unspec", "desc": "P2P GO Client Traffic Window the START_AP and SET_BSS commands"}, "@NL80211_ATTR_TDLS_EXTERNAL_SETUP": {"cmds": ["%NL80211_CMD_TDLS_MGMT", "%NL80211_CMD_TDLS_OPER"], "type": "unspec", "desc": "The TDLS discovery procedures should be performed by sending TDLS packets via %NL80211_CMD_TDLS_MGMT. Otherwise %NL80211_CMD_TDLS_OPER should be used for asking the driver to perform a TDLS operation."}, "@NL80211_ATTR_PROTOCOL_FEATURES": {"cmds": [], "type": "unspec", "desc": "global nl80211 feature flags &enum nl80211_protocol_features, the attribute is a u32."}, "@NL80211_ATTR_MPATH_INFO": {"cmds": ["%NL80211_CMD_GET_MPATH"], "type": "unspec", "desc": "information about a mesh_path info given for %NL80211_CMD_GET_MPATH, nested attribute described at &enum nl80211_mpath_info."}, "@NL80211_ATTR_MAX_SCHED_SCAN_IE_LEN": {"cmds": [], "type": "unspec", "desc": "maximum length of information elements that can be added to a scheduled scan request"}, "@NL80211_ATTR_TDLS_OPERATION": {"cmds": [], "type": "unspec", "desc": "High level TDLS operation &enum nl80211_tdls_operation, represented as a u8."}, "@NL80211_ATTR_FREQ_FIXED": {"cmds": [], "type": "unspec", "desc": "a flag indicating the IBSS should not try to look for other networks on different channels"}, "@NL80211_ATTR_STA_FLAGS": {"cmds": [], "type": "unspec", "desc": "flags &enum nl80211_sta_flags (deprecated, use %NL80211_ATTR_STA_FLAGS2)"}, "@NL80211_ATTR_MAX_NUM_PMKIDS": {"cmds": [], "type": "unspec", "desc": "maximum number of PMKIDs a firmware can cache, a wiphy attribute."}, "@NL80211_ATTR_MAC_ACL_MAX": {"cmds": [], "type": "unspec", "desc": "u32 attribute to advertise the maximum number of MAC addresses that a device can support for MAC ACL"}, "@NL80211_ATTR_STA_AID": {"cmds": [], "type": "unspec", "desc": "Association ID for the station "}, "@NL80211_ATTR_KEY": {"cmds": [], "type": "unspec", "desc": "key information in a nested attribute with %NL80211_KEY_* sub-attributes"}, "@NL80211_ATTR_STA_CAPABILITY": {"cmds": [], "type": "unspec", "desc": "Station capabilities the driver, e.g., to enable TDLS power save (PU-APSD)."}, "@NL80211_ATTR_DEVICE_AP_SME": {"cmds": [], "type": "unspec", "desc": "This u32 attribute may be listed for devices that have AP support to indicate that they have the AP SME integrated with support for the features listed in this attribute, see &enum nl80211_ap_sme_features."}, "@NL80211_ATTR_HIDDEN_SSID": {"cmds": [], "type": "unspec", "desc": "indicates whether SSID is to be hidden from Beacon and Probe Response (when response to wildcard Probe Request); see &enum nl80211_hidden_ssid, represented as a u32"}, "@NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES": {"cmds": [], "type": "unspec", "desc": "array of supported supported operating classes."}, "@NL80211_ATTR_FRAME_MATCH": {"cmds": [], "type": "unspec", "desc": "A binary attribute which typically must contain at least one byte, currently used with @NL80211_CMD_REGISTER_FRAME."}, "@NL80211_ATTR_STA_INFO": {"cmds": ["%NL80211_CMD_GET_STATION"], "type": "unspec", "desc": "information about a station given for %NL80211_CMD_GET_STATION, nested attribute containing info as possible, see &enum nl80211_sta_info."}, "@NL80211_ATTR_GENERATION": {"cmds": [], "type": "unspec", "desc": "Used to indicate consistent snapshots for dumps. This number increases whenever the object list being dumped changes, and as such userspace can verify that it has obtained a complete and consistent snapshot by verifying that all dump messages contain the same generation number. If it changed then the list changed and the dump should be repeated completely from scratch."}, "@NL80211_ATTR_WIPHY_RETRY_SHORT": {"cmds": [], "type": "unspec", "desc": "TX retry limit for frames whose length is less than or equal to the RTS threshold; allowed range: 1..255; dot11ShortRetryLimit; u8"}, "@NL80211_ATTR_CIPHER_GROUP": {"cmds": [], "type": "unspec", "desc": "Used with CONNECT indicate which group key cipher will be used with the connection, a u32"}, "@NL80211_ATTR_DURATION": {"cmds": [], "type": "unspec", "desc": "Duration of an operation in milliseconds"}, "@NL80211_ATTR_BG_SCAN_PERIOD": {"cmds": [], "type": "unspec", "desc": "Background scan period in seconds or 0 to disable background scan."}, "@NL80211_ATTR_WIPHY_BANDS": {"cmds": [], "type": "unspec", "desc": "Information about an operating bands consisting of a nested array."}, "@NL80211_ATTR_CIPHER_SUITES": {"cmds": [], "type": "unspec", "desc": "a set of u32 values indicating the supported cipher suites"}, "@NL80211_ATTR_TDLS_DIALOG_TOKEN": {"cmds": [], "type": "unspec", "desc": "Non TDLS conversation between two devices."}, "@NL80211_ATTR_REG_ALPHA2": {"cmds": [], "type": "unspec", "desc": "an ISO current regulatory domain should be set to or is already set to. For example, 'CR', for Costa Rica. This attribute is used by the kernel to query the CRDA to retrieve one regulatory domain. This attribute can also be used by userspace to query the kernel for the currently set regulatory domain. We chose an alpha2 as that is also used by the IEEE-802.11 country information element to identify a country. Users can also simply ask the wireless core to set regulatory domain to a specific alpha2."}, "@NL80211_ATTR_LOCAL_STATE_CHANGE": {"cmds": [], "type": "unspec", "desc": "Flag attribute to indicate that a command is requesting a local authentication/association state change without invoking actual management frame exchange. This can be used with NL80211_CMD_AUTHENTICATE, NL80211_CMD_DEAUTHENTICATE, NL80211_CMD_DISASSOCIATE."}, "@NL80211_ATTR_USER_REG_HINT_TYPE": {"cmds": [], "type": "unspec", "desc": "type of regulatory hint passed from userspace. If unset it is assumed the hint comes directly from a user. If set code could specify exactly what type of source was used to provide the hint. For the different types of allowed user regulatory hints see nl80211_user_reg_hint_type."}, "@NL80211_ATTR_BEACON_INTERVAL": {"cmds": [], "type": "unspec", "desc": "beacon interval in TU"}, "@NL80211_ATTR_EXT_CAPA": {"cmds": [], "type": "unspec", "desc": "802 has and handles. The format is the same as the IE contents. See 802.11-2012 8.4.2.29 for more information."}, "@NL80211_ATTR_CH_SWITCH_BLOCK_TX": {"cmds": [], "type": "unspec", "desc": "flag attribute specifying that transmission must be blocked on the current channel (before the channel switch operation)."}, "@NL80211_ATTR_WIPHY_TXQ_PARAMS": {"cmds": [], "type": "unspec", "desc": "a nested array of TX queue parameters"}, "@NL80211_ATTR_WOWLAN_TRIGGERS": {"cmds": ["%NL80211_CMD_GET_WOWLAN"], "type": "unspec", "desc": "used by indicate which WoW triggers should be enabled. This is also used by %NL80211_CMD_GET_WOWLAN to get the currently enabled WoWLAN triggers."}, "@NL80211_ATTR_HT_CAPABILITY_MASK": {"cmds": [], "type": "unspec", "desc": "Specify which bits of the ATTR_HT_CAPABILITY to which attention should be paid. Currently, only mac80211 NICs support this feature. The values that may be configured are: MCS rates, MAX-AMSDU, HT-20-40 and HT_CAP_SGI_40 AMPDU density and AMPDU factor. All values are treated as suggestions and may be ignored by the driver as required. The actual values may be seen in the station debugfs ht_caps file."}, "@NL80211_ATTR_TX_FRAME_TYPES": {"cmds": ["%NL80211_CMD_FRAME"], "type": "unspec", "desc": "wiphy capability attribute nested attribute of %NL80211_ATTR_FRAME_TYPE attributes, containing information about which frame types can be transmitted with %NL80211_CMD_FRAME."}, "@NL80211_ATTR_CIPHER_SUITE_GROUP": {"cmds": [], "type": "unspec", "desc": "For crypto settings for connect or other commands, indicates which group cipher suite is used"}, "@NL80211_ATTR_RX_SIGNAL_DBM": {"cmds": ["%NL80211_CMD_FRAME"], "type": "unspec", "desc": "signal strength in dBm this attribute is (depending on the driver capabilities) added to received frames indicated with %NL80211_CMD_FRAME."}, "@NL80211_ATTR_SSID": {"cmds": [], "type": "unspec", "desc": "SSID "}, "@NL80211_ATTR_KEY_DEFAULT_TYPES": {"cmds": [], "type": "unspec", "desc": "A nested attribute containing flags attributes, specifying what a key should be set as default as. See &enum nl80211_key_default_types."}, "@NL80211_ATTR_SURVEY_INFO": {"cmds": ["%NL80211_CMD_GET_SURVEY"], "type": "unspec", "desc": "survey information about a channel the survey response for %NL80211_CMD_GET_SURVEY, nested attribute containing info as possible, see &enum survey_info."}, "@NL80211_ATTR_WIPHY_TX_POWER_SETTING": {"cmds": [], "type": "unspec", "desc": "Transmit power setting type &enum nl80211_tx_power_setting for possible values."}, "@NL80211_ATTR_WIPHY_ANTENNA_TX": {"cmds": [], "type": "unspec", "desc": "Bitmap of allowed antennas for transmitting This can be used to mask out antennas which are not attached or should not be used for transmitting. If an antenna is not selected in this bitmap the hardware is not allowed to transmit on this antenna. Each bit represents one antenna, starting with antenna 1 at the first bit. Depending on which antennas are selected in the bitmap, 802.11n drivers can derive which chainmasks to use (if all antennas belonging to a particular chain are disabled this chain should be disabled) and if a chain has diversity antennas wether diversity should be used or not. HT capabilities (STBC, TX Beamforming, Antenna selection) can be derived from the available chains after applying the antenna mask. Non-802.11n drivers can derive wether to use diversity or not. Drivers may reject configurations or RX/TX mask combinations they cannot support by returning -EINVAL."}, "@NL80211_ATTR_CHANNEL_WIDTH": {"cmds": [], "type": "unspec", "desc": "u32 attribute containing one of the values of &enum nl80211_chan_width, describing the channel width. See the documentation of the enum for more information."}, "@NL80211_ATTR_NOACK_MAP": {"cmds": [], "type": "unspec", "desc": "This u16 bitmap contains the No Ack Policy of up to 16 TIDs."}, "@NL80211_ATTR_SCAN_SSIDS": {"cmds": [], "type": "unspec", "desc": "nested attribute with SSIDs scanning and include a zero-length SSID (wildcard) for wildcard scan"}, "@NL80211_ATTR_FEATURE_FLAGS": {"cmds": [], "type": "unspec", "desc": "This u32 attribute contains flags from &enum nl80211_feature_flags and is advertised in wiphy information."}, "@NL80211_ATTR_HANDLE_DFS": {"cmds": ["%NL80211_CMD_JOIN_IBSS"], "type": "unspec", "desc": "A flag indicating whether user space controls DFS operation in IBSS mode. If the flag is included in %NL80211_CMD_JOIN_IBSS request, the driver will allow use of DFS channels and reports radar events to userspace. Userspace is required to react to radar events, e.g. initiate a channel switch or leave the IBSS network."}} +{"0": ["@NL80211_ATTR_UNSPEC"], "1": ["@NL80211_ATTR_WIPHY"], "2": ["@NL80211_ATTR_WIPHY_NAME"], "3": ["@NL80211_ATTR_IFINDEX"], "4": ["@NL80211_ATTR_IFNAME"], "5": ["@NL80211_ATTR_IFTYPE"], "6": ["@NL80211_ATTR_MAC"], "7": ["@NL80211_ATTR_KEY_DATA"], "8": ["@NL80211_ATTR_KEY_IDX"], "9": ["@NL80211_ATTR_KEY_CIPHER"], "10": ["@NL80211_ATTR_KEY_SEQ"], "11": ["@NL80211_ATTR_KEY_DEFAULT"], "12": ["@NL80211_ATTR_BEACON_INTERVAL"], "13": ["@NL80211_ATTR_DTIM_PERIOD"], "14": ["@NL80211_ATTR_BEACON_HEAD"], "15": ["@NL80211_ATTR_BEACON_TAIL"], "16": ["@NL80211_ATTR_STA_AID"], "17": ["@NL80211_ATTR_STA_FLAGS"], "18": ["@NL80211_ATTR_STA_LISTEN_INTERVAL"], "19": ["@NL80211_ATTR_STA_SUPPORTED_RATES"], "20": ["@NL80211_ATTR_STA_VLAN"], "21": ["@NL80211_ATTR_STA_INFO"], "22": ["@NL80211_ATTR_WIPHY_BANDS"], "23": ["@NL80211_ATTR_MNTR_FLAGS"], "24": ["@NL80211_ATTR_MESH_ID"], "25": ["@NL80211_ATTR_STA_PLINK_ACTION"], "26": ["@NL80211_ATTR_MPATH_NEXT_HOP"], "27": ["@NL80211_ATTR_MPATH_INFO"], "28": ["@NL80211_ATTR_BSS_CTS_PROT"], "29": ["@NL80211_ATTR_BSS_SHORT_PREAMBLE"], "30": ["@NL80211_ATTR_BSS_SHORT_SLOT_TIME"], "31": ["@NL80211_ATTR_HT_CAPABILITY"], "32": ["@NL80211_ATTR_SUPPORTED_IFTYPES"], "33": ["@NL80211_ATTR_REG_ALPHA2"], "34": ["@NL80211_ATTR_REG_RULES"], "35": ["@NL80211_ATTR_MESH_CONFIG"], "36": ["@NL80211_ATTR_BSS_BASIC_RATES"], "37": ["@NL80211_ATTR_WIPHY_TXQ_PARAMS"], "38": ["@NL80211_ATTR_WIPHY_FREQ"], "39": ["@NL80211_ATTR_WIPHY_CHANNEL_TYPE"], "40": ["@NL80211_ATTR_KEY_DEFAULT_MGMT"], "41": ["@NL80211_ATTR_MGMT_SUBTYPE"], "42": ["@NL80211_ATTR_IE"], "43": ["@NL80211_ATTR_MAX_NUM_SCAN_SSIDS"], "44": ["@NL80211_ATTR_SCAN_FREQUENCIES"], "45": ["@NL80211_ATTR_SCAN_SSIDS"], "46": ["@NL80211_ATTR_GENERATION"], "47": ["@NL80211_ATTR_BSS"], "48": ["@NL80211_ATTR_REG_INITIATOR"], "49": ["@NL80211_ATTR_REG_TYPE"], "50": ["@NL80211_ATTR_SUPPORTED_COMMANDS"], "51": ["@NL80211_ATTR_FRAME"], "52": ["@NL80211_ATTR_SSID"], "53": ["@NL80211_ATTR_AUTH_TYPE"], "54": ["@NL80211_ATTR_REASON_CODE"], "55": ["@NL80211_ATTR_KEY_TYPE"], "56": ["@NL80211_ATTR_MAX_SCAN_IE_LEN"], "57": ["@NL80211_ATTR_CIPHER_SUITES"], "58": ["@NL80211_ATTR_FREQ_BEFORE"], "59": ["@NL80211_ATTR_FREQ_AFTER"], "60": ["@NL80211_ATTR_FREQ_FIXED"], "61": ["@NL80211_ATTR_WIPHY_RETRY_SHORT"], "62": ["@NL80211_ATTR_WIPHY_RETRY_LONG"], "63": ["@NL80211_ATTR_WIPHY_FRAG_THRESHOLD"], "64": ["@NL80211_ATTR_WIPHY_RTS_THRESHOLD"], "65": ["@NL80211_ATTR_TIMED_OUT"], "66": ["@NL80211_ATTR_USE_MFP"], "67": ["@NL80211_ATTR_STA_FLAGS2"], "68": ["@NL80211_ATTR_CONTROL_PORT"], "69": ["@NL80211_ATTR_TESTDATA"], "70": ["@NL80211_ATTR_PRIVACY"], "71": ["@NL80211_ATTR_DISCONNECTED_BY_AP"], "72": ["@NL80211_ATTR_STATUS_CODE"], "73": ["@NL80211_ATTR_CIPHER_SUITES_PAIRWISE"], "74": ["@NL80211_ATTR_CIPHER_SUITE_GROUP"], "75": ["@NL80211_ATTR_WPA_VERSIONS"], "76": ["@NL80211_ATTR_AKM_SUITES"], "77": ["@NL80211_ATTR_REQ_IE"], "78": ["@NL80211_ATTR_RESP_IE"], "79": ["@NL80211_ATTR_PREV_BSSID"], "80": ["@NL80211_ATTR_KEY"], "81": ["@NL80211_ATTR_KEYS"], "82": ["@NL80211_ATTR_PID"], "83": ["@NL80211_ATTR_4ADDR"], "84": ["@NL80211_ATTR_SURVEY_INFO"], "85": ["@NL80211_ATTR_PMKID"], "86": ["@NL80211_ATTR_MAX_NUM_PMKIDS"], "87": ["@NL80211_ATTR_DURATION"], "88": ["@NL80211_ATTR_COOKIE"], "89": ["@NL80211_ATTR_WIPHY_COVERAGE_CLASS"], "90": ["@NL80211_ATTR_TX_RATES"], "91": ["@NL80211_ATTR_FRAME_MATCH"], "92": ["@NL80211_ATTR_ACK"], "93": ["@NL80211_ATTR_PS_STATE"], "94": ["@NL80211_ATTR_CQM"], "95": ["@NL80211_ATTR_LOCAL_STATE_CHANGE"], "96": ["@NL80211_ATTR_AP_ISOLATE"], "97": ["@NL80211_ATTR_WIPHY_TX_POWER_SETTING"], "98": ["@NL80211_ATTR_WIPHY_TX_POWER_LEVEL"], "99": ["@NL80211_ATTR_TX_FRAME_TYPES"], "100": ["@NL80211_ATTR_RX_FRAME_TYPES"], "101": ["@NL80211_ATTR_FRAME_TYPE"], "102": ["@NL80211_ATTR_CONTROL_PORT_ETHERTYPE"], "103": ["@NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT"], "104": ["@NL80211_ATTR_SUPPORT_IBSS_RSN"], "105": ["@NL80211_ATTR_WIPHY_ANTENNA_TX"], "106": ["@NL80211_ATTR_WIPHY_ANTENNA_RX"], "107": ["@NL80211_ATTR_MCAST_RATE"], "108": ["@NL80211_ATTR_OFFCHANNEL_TX_OK"], "109": ["@NL80211_ATTR_BSS_HT_OPMODE"], "110": ["@NL80211_ATTR_KEY_DEFAULT_TYPES"], "111": ["@NL80211_ATTR_MAX_REMAIN_ON_CHANNEL_DURATION"], "112": ["@NL80211_ATTR_MESH_SETUP"], "113": ["@NL80211_ATTR_WIPHY_ANTENNA_AVAIL_TX"], "114": ["@NL80211_ATTR_WIPHY_ANTENNA_AVAIL_RX"], "115": ["@NL80211_ATTR_SUPPORT_MESH_AUTH"], "116": ["@NL80211_ATTR_STA_PLINK_STATE"], "117": ["@NL80211_ATTR_WOWLAN_TRIGGERS"], "118": ["@NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED"], "119": ["@NL80211_ATTR_SCHED_SCAN_INTERVAL"], "120": ["@NL80211_ATTR_INTERFACE_COMBINATIONS"], "121": ["@NL80211_ATTR_SOFTWARE_IFTYPES"], "122": ["@NL80211_ATTR_REKEY_DATA"], "123": ["@NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS"], "124": ["@NL80211_ATTR_MAX_SCHED_SCAN_IE_LEN"], "125": ["@NL80211_ATTR_SCAN_SUPP_RATES"], "126": ["@NL80211_ATTR_HIDDEN_SSID"], "127": ["@NL80211_ATTR_IE_PROBE_RESP"], "128": ["@NL80211_ATTR_IE_ASSOC_RESP"], "129": ["@NL80211_ATTR_STA_WME"], "130": ["@NL80211_ATTR_SUPPORT_AP_UAPSD"], "131": ["@NL80211_ATTR_ROAM_SUPPORT"], "132": ["@NL80211_ATTR_SCHED_SCAN_MATCH"], "133": ["@NL80211_ATTR_MAX_MATCH_SETS"], "134": ["@NL80211_ATTR_PMKSA_CANDIDATE"], "135": ["@NL80211_ATTR_TX_NO_CCK_RATE"], "136": ["@NL80211_ATTR_TDLS_ACTION"], "137": ["@NL80211_ATTR_TDLS_DIALOG_TOKEN"], "138": ["@NL80211_ATTR_TDLS_OPERATION"], "139": ["@NL80211_ATTR_TDLS_SUPPORT"], "140": ["@NL80211_ATTR_TDLS_EXTERNAL_SETUP"], "141": ["@NL80211_ATTR_DEVICE_AP_SME"], "142": ["@NL80211_ATTR_DONT_WAIT_FOR_ACK"], "143": ["@NL80211_ATTR_FEATURE_FLAGS"], "144": ["@NL80211_ATTR_PROBE_RESP_OFFLOAD"], "145": ["@NL80211_ATTR_PROBE_RESP"], "146": ["@NL80211_ATTR_DFS_REGION"], "147": ["@NL80211_ATTR_DISABLE_HT"], "148": ["@NL80211_ATTR_HT_CAPABILITY_MASK"], "149": ["@NL80211_ATTR_NOACK_MAP"], "150": ["@NL80211_ATTR_INACTIVITY_TIMEOUT"], "151": ["@NL80211_ATTR_RX_SIGNAL_DBM"], "152": ["@NL80211_ATTR_BG_SCAN_PERIOD"], "153": ["@NL80211_ATTR_WDEV"], "154": ["@NL80211_ATTR_USER_REG_HINT_TYPE"], "155": ["@NL80211_ATTR_CONN_FAILED_REASON"], "156": ["@NL80211_ATTR_SAE_DATA"], "157": ["@NL80211_ATTR_VHT_CAPABILITY"], "158": ["@NL80211_ATTR_SCAN_FLAGS"], "159": ["@NL80211_ATTR_CHANNEL_WIDTH"], "160": ["@NL80211_ATTR_CENTER_FREQ1"], "161": ["@NL80211_ATTR_CENTER_FREQ2"], "162": ["@NL80211_ATTR_P2P_CTWINDOW"], "163": ["@NL80211_ATTR_P2P_OPPPS"], "164": ["@NL80211_ATTR_LOCAL_MESH_POWER_MODE"], "165": ["@NL80211_ATTR_ACL_POLICY"], "166": ["@NL80211_ATTR_MAC_ADDRS"], "167": ["@NL80211_ATTR_MAC_ACL_MAX"], "168": ["@NL80211_ATTR_RADAR_EVENT"], "169": ["@NL80211_ATTR_EXT_CAPA"], "170": ["@NL80211_ATTR_EXT_CAPA_MASK"], "171": ["@NL80211_ATTR_STA_CAPABILITY"], "172": ["@NL80211_ATTR_STA_EXT_CAPABILITY"], "173": ["@NL80211_ATTR_PROTOCOL_FEATURES"], "174": ["@NL80211_ATTR_SPLIT_WIPHY_DUMP"], "177": ["@NL80211_ATTR_MDID"], "178": ["@NL80211_ATTR_IE_RIC"], "179": ["@NL80211_ATTR_CRIT_PROT_ID"], "180": ["@NL80211_ATTR_MAX_CRIT_PROT_DURATION"], "181": ["@NL80211_ATTR_PEER_AID"], "182": ["@NL80211_ATTR_COALESCE_RULE"], "183": ["@NL80211_ATTR_CH_SWITCH_COUNT"], "184": ["@NL80211_ATTR_CH_SWITCH_BLOCK_TX"], "185": ["@NL80211_ATTR_CSA_IES"], "186": ["@NL80211_ATTR_CSA_C_OFF_BEACON"], "187": ["@NL80211_ATTR_CSA_C_OFF_PRESP"], "188": ["@NL80211_ATTR_RXMGMT_FLAGS"], "189": ["@NL80211_ATTR_STA_SUPPORTED_CHANNELS"], "190": ["@NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES"], "191": ["@NL80211_ATTR_HANDLE_DFS"]} diff --git a/pyric/docs/commands.help b/pyric/docs/commands.help new file mode 100644 index 0000000..a69f29b --- /dev/null +++ b/pyric/docs/commands.help @@ -0,0 +1,5 @@ +# commands.help (json format) +# Automatically generated 2016-04-17T11:06:57.694132 + +{"@NL80211_CMD_GET_REG": {"attrs": [], "desc": "ask the wireless core to send us its currently set\tregulatory domain."}, "@NL80211_CMD_STOP_SCHED_SCAN": {"attrs": [], "desc": "stop if scheduled scan is not running."}, "@NL80211_CMD_START_SCHED_SCAN": {"attrs": ["%NL80211_ATTR_SCHED_SCAN_INTERVAL", "%NL80211_ATTR_SCAN_SSIDS", "%NL80211_ATTR_SCAN_FREQUENCIES", "%NL80211_ATTR_IE"], "desc": "start intervals, as specified by %NL80211_ATTR_SCHED_SCAN_INTERVAL. Like with normal scans, if SSIDs (%NL80211_ATTR_SCAN_SSIDS) are passed, they are used in the probe requests. For broadcast, a broadcast SSID must be passed (ie. an empty string). If no SSID is passed, no probe requests are sent and a passive scan is performed. %NL80211_ATTR_SCAN_FREQUENCIES, if passed, define which channels should be scanned; if not passed, all channels allowed for the current regulatory domain are used. Extra IEs can also be passed from the userspace by using the %NL80211_ATTR_IE attribute."}, "@NL80211_CMD_NEW_SURVEY_RESULTS": {"attrs": [], "desc": "survey NL80211_CMD_GET_SURVEY and on the \"scan\" multicast group)"}, "@NL80211_CMD_SET_INTERFACE": {"attrs": ["%NL80211_ATTR_IFINDEX", "%NL80211_ATTR_IFTYPE"], "desc": "Set %NL80211_ATTR_IFINDEX and %NL80211_ATTR_IFTYPE."}, "@NL80211_CMD_DISASSOCIATE": {"attrs": [], "desc": "disassociation NL80211_CMD_AUTHENTICATE but for Disassociation frames (similar to MLME-DISASSOCIATE.request and MLME-DISASSOCIATE.indication primitives)."}, "@NL80211_CMD_FRAME": {"attrs": ["%NL80211_ATTR_FRAME", "%NL80211_ATTR_WIPHY_FREQ", "%NL80211_ATTR_DURATION", "%NL80211_ATTR_COOKIE", "%NL80211_ATTR_TX_NO_CCK_RATE"], "desc": "Management command is used both as a request to transmit a management frame and as an event indicating reception of a frame that was not processed in kernel code, but is for us (i.e., which may need to be processed in a user space application). %NL80211_ATTR_FRAME is used to specify the frame contents (including header). %NL80211_ATTR_WIPHY_FREQ is used to indicate on which channel the frame is to be transmitted or was received. If this channel is not the current channel (remain-on-channel or the operational channel) the device will switch to the given channel and transmit the frame, optionally waiting for a response for the time specified using %NL80211_ATTR_DURATION. When called, this operation returns a cookie (%NL80211_ATTR_COOKIE) that will be included with the TX status event pertaining to the TX request. %NL80211_ATTR_TX_NO_CCK_RATE is used to decide whether to send the management frames at CCK rate or not in 2GHz band."}, "@NL80211_CMD_NEW_KEY": {"attrs": ["%NL80211_ATTR_KEY_IDX", "%NL80211_ATTR_MAC", "%NL80211_ATTR_KEY_CIPHER", "%NL80211_ATTR_KEY_SEQ"], "desc": "add %NL80211_ATTR_KEY_IDX, %NL80211_ATTR_MAC, %NL80211_ATTR_KEY_CIPHER, and %NL80211_ATTR_KEY_SEQ attributes."}, "@NL80211_CMD_STOP_AP": {"attrs": [], "desc": "Stop"}, "@NL80211_CMD_DEL_INTERFACE": {"attrs": ["%NL80211_ATTR_IFINDEX", "%NL80211_ATTR_WIPHY", "%NL80211_ATTR_IFINDEX"], "desc": "Virtual %NL80211_ATTR_IFINDEX and %NL80211_ATTR_WIPHY. Can also be sent from userspace to request deletion of a virtual interface, then requires attribute %NL80211_ATTR_IFINDEX."}, "@NL80211_CMD_UNEXPECTED_4ADDR_FRAME": {"attrs": ["%NL80211_ATTR_MAC"], "desc": "Sent associated station identified by %NL80211_ATTR_MAC sent a 4addr frame and wasn't already in a 4-addr VLAN. The event will be sent similarly to the %NL80211_CMD_UNEXPECTED_FRAME event, to the same listener."}, "@NL80211_CMD_SET_MESH_CONFIG": {"attrs": ["%NL80211_ATTR_IFINDEX"], "desc": "Set interface identified by %NL80211_ATTR_IFINDEX"}, "@NL80211_CMD_STOP_P2P_DEVICE": {"attrs": ["%NL80211_ATTR_WDEV"], "desc": "Stop its %NL80211_ATTR_WDEV identifier."}, "@NL80211_CMD_START_P2P_DEVICE": {"attrs": ["%NL80211_ATTR_WDEV"], "desc": "Start its %NL80211_ATTR_WDEV identifier. It must have been created with %NL80211_CMD_NEW_INTERFACE previously. After it has been started, the P2P Device can be used for P2P operations, e.g. remain-on-channel and public action frame TX."}, "@NL80211_CMD_SET_COALESCE": {"attrs": [], "desc": "Configure"}, "@NL80211_CMD_DEL_WIPHY": {"attrs": ["%NL80211_ATTR_WIPHY", "%NL80211_ATTR_WIPHY_NAME"], "desc": "Wiphy %NL80211_ATTR_WIPHY and %NL80211_ATTR_WIPHY_NAME."}, "@NL80211_CMD_SET_STATION": {"attrs": ["%NL80211_ATTR_MAC", "%NL80211_ATTR_IFINDEX"], "desc": "Set %NL80211_ATTR_MAC on the interface identified by %NL80211_ATTR_IFINDEX."}, "@NL80211_CMD_LEAVE_MESH": {"attrs": [], "desc": "Leave network is determined by the network interface."}, "@NL80211_CMD_GET_KEY": {"attrs": ["%NL80211_ATTR_KEY_IDX", "%NL80211_ATTR_MAC"], "desc": "Get by %NL80211_ATTR_KEY_IDX and/or %NL80211_ATTR_MAC."}, "@NL80211_CMD_GET_SURVEY": {"attrs": [], "desc": "get"}, "@NL80211_CMD_TDLS_MGMT": {"attrs": [], "desc": "Send"}, "@NL80211_CMD_SET_BSS": {"attrs": ["%NL80211_ATTR_IFINDEX"], "desc": "Set %NL80211_ATTR_IFINDEX."}, "@NL80211_CMD_SET_WOWLAN": {"attrs": ["%NL80211_ATTR_WOWLAN_TRIGGERS"], "desc": "set Since wireless is more complex than wired ethernet, it supports various triggers. These triggers can be configured through this command with the %NL80211_ATTR_WOWLAN_TRIGGERS attribute. For more background information, see http://wireless.kernel.org/en/users/Documentation/WoWLAN. The @NL80211_CMD_SET_WOWLAN command can also be used as a notification from the driver reporting the wakeup reason. In this case, the @NL80211_ATTR_WOWLAN_TRIGGERS attribute will contain the reason for the wakeup, if it was caused by wireless. If it is not present in the wakeup notification, the wireless device didn't cause the wakeup but reports that it was woken up."}, "@NL80211_CMD_NEW_STATION": {"attrs": ["%NL80211_ATTR_IFINDEX"], "desc": "Add the interface identified by %NL80211_ATTR_IFINDEX."}, "@NL80211_CMD_SET_PMKSA": {"attrs": ["%NL80211_ATTR_PMKID"], "desc": "Add (for the BSSID) and %NL80211_ATTR_PMKID."}, "@NL80211_CMD_SET_MPATH": {"attrs": ["%NL80211_ATTR_MAC", "%NL80211_ATTR_IFINDEX"], "desc": " destination %NL80211_ATTR_MAC on the interface identified by %NL80211_ATTR_IFINDEX."}, "@NL80211_CMD_DEL_STATION": {"attrs": ["%NL80211_ATTR_IFINDEX"], "desc": "Remove or, if no MAC address given, all stations, on the interface identified by %NL80211_ATTR_IFINDEX."}, "@NL80211_CMD_UNPROT_DISASSOCIATE": {"attrs": [], "desc": "Unprotected notification. This event is used to indicate that an unprotected disassociation frame was dropped when MFP is in use."}, "@NL80211_CMD_CH_SWITCH_NOTIFY": {"attrs": ["%NL80211_ATTR_IFINDEX", "%NL80211_ATTR_WIPHY_FREQ"], "desc": "An independently of the userspace SME, send this event indicating %NL80211_ATTR_IFINDEX is now on %NL80211_ATTR_WIPHY_FREQ and the attributes determining channel width."}, "@NL80211_CMD_SET_KEY": {"attrs": ["%NL80211_ATTR_KEY_DEFAULT_MGMT", "%NL80211_ATTR_KEY_THRESHOLD"], "desc": "Set %NL80211_ATTR_KEY_DEFAULT_MGMT, or %NL80211_ATTR_KEY_THRESHOLD."}, "@NL80211_CMD_SET_MAC_ACL": {"attrs": ["%NL80211_ATTR_MAC_ADDRS", "%NL80211_ATTR_ACL_POLICY"], "desc": "sets This is to be used with the drivers advertising the support of MAC address based access control. List of MAC addresses is passed in %NL80211_ATTR_MAC_ADDRS and ACL policy is passed in %NL80211_ATTR_ACL_POLICY. Driver will enable ACL with this list, if it is not already done. The new list will replace any existing list. Driver will clear its ACL when the list of MAC addresses passed is empty. This command is used in AP/P2P GO mode. Driver has to make sure to clear its ACL list during %NL80211_CMD_STOP_AP."}, "@NL80211_CMD_GET_WOWLAN": {"attrs": [], "desc": "get"}, "@NL80211_CMD_GET_STATION": {"attrs": ["%NL80211_ATTR_MAC", "%NL80211_ATTR_IFINDEX"], "desc": "Get %NL80211_ATTR_MAC on the interface identified by %NL80211_ATTR_IFINDEX."}, "@NL80211_CMD_UNSPEC": {"attrs": [], "desc": "unspecified"}, "@NL80211_CMD_NEW_PEER_CANDIDATE": {"attrs": [], "desc": "Notification beacon or probe response from a compatible mesh peer. This is only sent while no station information (sta_info) exists for the new peer candidate and when @NL80211_MESH_SETUP_USERSPACE_AUTH, @NL80211_MESH_SETUP_USERSPACE_AMPE, or @NL80211_MESH_SETUP_USERSPACE_MPM is set. On reception of this notification, userspace may decide to create a new station (@NL80211_CMD_NEW_STATION). To stop this notification from reoccurring, the userspace authentication daemon may want to create the new station with the AUTHENTICATED flag unset and maybe change it later depending on the authentication result."}, "@NL80211_CMD_REGISTER_ACTION": {"attrs": [], "desc": "Alias backward compatibility"}, "@NL80211_CMD_REG_CHANGE": {"attrs": ["%NL80211_ATTR_REG_INITIATOR", "%NL80211_ATTR_REG_ALPHA2", "%NL80211_ATTR_REG_TYPE", "%NL80211_ATTR_REG_ALPHA2"], "desc": "indicates has been changed and provides details of the request information that caused the change such as who initiated the regulatory request (%NL80211_ATTR_REG_INITIATOR), the wiphy_idx (%NL80211_ATTR_REG_ALPHA2) on which the request was made from if the initiator was %NL80211_REGDOM_SET_BY_COUNTRY_IE or %NL80211_REGDOM_SET_BY_DRIVER, the type of regulatory domain set (%NL80211_ATTR_REG_TYPE), if the type of regulatory domain is %NL80211_REG_TYPE_COUNTRY the alpha2 to which we have moved on to (%NL80211_ATTR_REG_ALPHA2)."}, "@NL80211_CMD_CONN_FAILED": {"attrs": ["%NL80211_ATTR_CONN_FAILED_REASON"], "desc": "connection notify userspace that AP has rejected the connection request from a station, due to particular reason. %NL80211_ATTR_CONN_FAILED_REASON is used for this."}, "@NL80211_CMD_SCAN_ABORTED": {"attrs": [], "desc": "scan partial scan results may be available"}, "@NL80211_CMD_SET_POWER_SAVE": {"attrs": [], "desc": "Set"}, "@NL80211_CMD_SET_MGMT_EXTRA_IE": {"attrs": ["%NL80211_ATTR_IFINDEX", "%NL80211_ATTR_MGMT_SUBTYPE", "%NL80211_ATTR_IE"], "desc": "Set interface is identified with %NL80211_ATTR_IFINDEX and the management frame subtype with %NL80211_ATTR_MGMT_SUBTYPE. The extra IE data to be added to the end of the specified management frame is specified with %NL80211_ATTR_IE. If the command succeeds, the requested data will be added to all specified management frames generated by kernel/firmware/driver. Note: This command has been removed and it is only reserved at this point to avoid re-using existing command number. The functionality this command was planned for has been provided with cleaner design with the option to specify additional IEs in NL80211_CMD_TRIGGER_SCAN, NL80211_CMD_AUTHENTICATE, NL80211_CMD_ASSOCIATE, NL80211_CMD_DEAUTHENTICATE, and NL80211_CMD_DISASSOCIATE."}, "@NL80211_CMD_SET_REKEY_OFFLOAD": {"attrs": ["%NL80211_ATTR_REKEY_DATA"], "desc": "This the necessary information for supporting GTK rekey offload. This feature is typically used during WoWLAN. The configuration data is contained in %NL80211_ATTR_REKEY_DATA (which is nested and contains the data in sub-attributes). After rekeying happened, this command may also be sent by the driver as an MLME event to inform userspace of the new replay counter."}, "@NL80211_CMD_SET_CHANNEL": {"attrs": ["%NL80211_ATTR_IFINDEX"], "desc": "Set and the attributes determining channel width) the given interface (identifed by %NL80211_ATTR_IFINDEX) shall operate on. In case multiple channels are supported by the device, the mechanism with which it switches channels is implementation-defined. When a monitor interface is given, it can only switch channel while no other interfaces are operating to avoid disturbing the operation of any other interfaces, and other interfaces will again take precedence when they are used."}, "@NL80211_CMD_START_AP": {"attrs": ["%NL80211_ATTR_BEACON_INTERVAL", "%NL80211_ATTR_DTIM_PERIOD", "%NL80211_ATTR_SSID", "%NL80211_ATTR_HIDDEN_SSID", "%NL80211_ATTR_CIPHERS_PAIRWISE", "%NL80211_ATTR_CIPHER_GROUP", "%NL80211_ATTR_WPA_VERSIONS", "%NL80211_ATTR_AKM_SUITES", "%NL80211_ATTR_PRIVACY", "%NL80211_ATTR_AUTH_TYPE", "%NL80211_ATTR_INACTIVITY_TIMEOUT", "%NL80211_ATTR_ACL_POLICY", "%NL80211_ATTR_MAC_ADDRS", "%NL80211_ATTR_WIPHY_FREQ"], "desc": "Start are like for %NL80211_CMD_SET_BEACON, and additionally parameters that do not change are used, these include %NL80211_ATTR_BEACON_INTERVAL, %NL80211_ATTR_DTIM_PERIOD, %NL80211_ATTR_SSID, %NL80211_ATTR_HIDDEN_SSID, %NL80211_ATTR_CIPHERS_PAIRWISE, %NL80211_ATTR_CIPHER_GROUP, %NL80211_ATTR_WPA_VERSIONS, %NL80211_ATTR_AKM_SUITES, %NL80211_ATTR_PRIVACY, %NL80211_ATTR_AUTH_TYPE, %NL80211_ATTR_INACTIVITY_TIMEOUT, %NL80211_ATTR_ACL_POLICY and %NL80211_ATTR_MAC_ADDRS. The channel to use can be set on the interface or be given using the %NL80211_ATTR_WIPHY_FREQ and the attributes determining channel width."}, "@NL80211_CMD_DEL_PMKSA": {"attrs": ["%NL80211_ATTR_PMKID"], "desc": "Delete (for the BSSID) and %NL80211_ATTR_PMKID."}, "@NL80211_CMD_UNEXPECTED_FRAME": {"attrs": ["%NL80211_ATTR_MAC"], "desc": "Used (or GO) interface (i.e. hostapd) to ask for unexpected frames to implement sending deauth to stations that send unexpected class 3 frames. Also used as the event sent by the kernel when such a frame is received. For the event, the %NL80211_ATTR_MAC attribute carries the TA and other attributes like the interface index are present. If used as the command it must have an interface index and you can only unsubscribe from the event by closing the socket. Subscription is also for %NL80211_CMD_UNEXPECTED_4ADDR_FRAME events."}, "@NL80211_CMD_GET_MPATH": {"attrs": ["%NL80211_ATTR_MAC", "%NL80211_ATTR_IFINDEX"], "desc": "Get destination %NL80211_ATTR_MAC on the interface identified by %NL80211_ATTR_IFINDEX."}, "@NL80211_CMD_GET_BEACON": {"attrs": [], "desc": ""}, "@NL80211_CMD_PMKSA_CANDIDATE": {"attrs": [], "desc": "This of PMKSA caching dandidates."}, "@NL80211_CMD_PROBE_CLIENT": {"attrs": ["%NL80211_ATTR_IFINDEX", "%NL80211_ATTR_MAC", "%NL80211_ATTR_COOKIE", "%NL80211_ATTR_ACK"], "desc": "Probe by sending a null data frame to it and reporting when the frame is acknowleged. This is used to allow timing out inactive clients. Uses %NL80211_ATTR_IFINDEX and %NL80211_ATTR_MAC. The command returns a direct reply with an %NL80211_ATTR_COOKIE that is later used to match up the event with the request. The event includes the same data and has %NL80211_ATTR_ACK set if the frame was ACKed."}, "@NL80211_CMD_NEW_INTERFACE": {"attrs": ["%NL80211_ATTR_IFINDEX", "%NL80211_ATTR_WIPHY", "%NL80211_ATTR_IFTYPE", "%NL80211_ATTR_WIPHY", "%NL80211_ATTR_IFTYPE", "%NL80211_ATTR_IFNAME"], "desc": "Newly to %NL80211_CMD_GET_INTERFACE. Has %NL80211_ATTR_IFINDEX, %NL80211_ATTR_WIPHY and %NL80211_ATTR_IFTYPE attributes. Can also be sent from userspace to request creation of a new virtual interface, then requires attributes %NL80211_ATTR_WIPHY, %NL80211_ATTR_IFTYPE and %NL80211_ATTR_IFNAME."}, "@NL80211_CMD_SET_TX_BITRATE_MASK": {"attrs": ["%NL80211_ATTR_IFINDEX"], "desc": "Set rate selection. %NL80211_ATTR_IFINDEX is used to specify the interface and @NL80211_ATTR_TX_RATES the set of allowed rates."}, "@NL80211_CMD_NEW_SCAN_RESULTS": {"attrs": [], "desc": "scan NL80211_CMD_GET_SCAN and on the \"scan\" multicast group)"}, "@NL80211_CMD_GET_WIPHY": {"attrs": [], "desc": "request to get a list of all present wiphys."}, "@NL80211_CMD_SET_NOACK_MAP": {"attrs": [], "desc": "sets No Acknowledgement Policy should be applied."}, "@NL80211_CMD_ACTION": {"attrs": [], "desc": "Alias"}, "@NL80211_CMD_FLUSH_PMKSA": {"attrs": [], "desc": "Flush"}, "@NL80211_CMD_ASSOCIATE": {"attrs": [], "desc": "association NL80211_CMD_AUTHENTICATE but for Association and Reassociation (similar to MLME-ASSOCIATE.request, MLME-REASSOCIATE.request, MLME-ASSOCIATE.confirm or MLME-REASSOCIATE.confirm primitives)."}, "@NL80211_CMD_GET_PROTOCOL_FEATURES": {"attrs": ["%NL80211_ATTR_PROTOCOL_FEATURES"], "desc": "Get i.e. features for the nl80211 protocol rather than device features. Returns the features in the %NL80211_ATTR_PROTOCOL_FEATURES bitmap."}, "@NL80211_CMD_DEAUTHENTICATE": {"attrs": [], "desc": "deauthentication NL80211_CMD_AUTHENTICATE but for Deauthentication frames (similar to MLME-DEAUTHENTICATION.request and MLME-DEAUTHENTICATE.indication primitives)."}, "@NL80211_CMD_CRIT_PROTOCOL_STOP": {"attrs": [], "desc": "Indicates return back to normal."}, "@NL80211_CMD_FT_EVENT": {"attrs": [], "desc": "Send to the supplicant. This will carry the target AP's MAC address along with the relevant Information Elements. This event is used to report received FT IEs (MDIE, FTIE, RSN IE, TIE, RICIE)."}, "@NL80211_CMD_NEW_WIPHY": {"attrs": ["%NL80211_ATTR_WIPHY", "%NL80211_ATTR_WIPHY_NAME"], "desc": "Newly or rename notification. Has attributes %NL80211_ATTR_WIPHY and %NL80211_ATTR_WIPHY_NAME."}, "@NL80211_CMD_UPDATE_FT_IES": {"attrs": [], "desc": "Pass Information Element to the WLAN driver"}, "@NL80211_CMD_SET_WDS_PEER": {"attrs": [], "desc": "Set"}, "@NL80211_CMD_SCHED_SCAN_STOPPED": {"attrs": [], "desc": "indicates stopped. The driver may issue this event at any time during a scheduled scan. One reason for stopping the scan is if the hardware does not support starting an association or a normal scan while running a scheduled scan. This event is also sent when the %NL80211_CMD_STOP_SCHED_SCAN command is received or when the interface is brought down while a scheduled scan was running."}, "@NL80211_CMD_FRAME_TX_STATUS": {"attrs": ["%NL80211_ATTR_COOKIE", "%NL80211_ATTR_FRAME", "%NL80211_ATTR_ACK"], "desc": "Report transmitted with %NL80211_CMD_FRAME. %NL80211_ATTR_COOKIE identifies the TX command and %NL80211_ATTR_FRAME includes the contents of the frame. %NL80211_ATTR_ACK flag is included if the recipient acknowledged the frame."}, "@NL80211_CMD_TDLS_OPER": {"attrs": ["%NL80211_ATTR_TDLS_OPERATION", "%NL80211_ATTR_MAC", "%NL80211_ATTR_REASON_CODE"], "desc": "Perform In addition, this can be used as an event to request userspace to take actions on TDLS links (set up a new link or tear down an existing one). In such events, %NL80211_ATTR_TDLS_OPERATION indicates the requested operation, %NL80211_ATTR_MAC contains the peer MAC address, and %NL80211_ATTR_REASON_CODE the reason code to be used (only with %NL80211_TDLS_TEARDOWN)."}, "@NL80211_CMD_GET_SCAN": {"attrs": [], "desc": "get"}, "@NL80211_CMD_SET_WIPHY": {"attrs": ["%NL80211_ATTR_IFINDEX", "%NL80211_ATTR_WIPHY_NAME", "%NL80211_ATTR_WIPHY_TXQ_PARAMS", "%NL80211_ATTR_WIPHY_FREQ", "%NL80211_ATTR_WIPHY_RETRY_SHORT", "%NL80211_ATTR_WIPHY_RETRY_LONG", "%NL80211_ATTR_WIPHY_FRAG_THRESHOLD", "%NL80211_ATTR_WIPHY_RTS_THRESHOLD"], "desc": "set %NL80211_ATTR_IFINDEX; can be used to set %NL80211_ATTR_WIPHY_NAME, %NL80211_ATTR_WIPHY_TXQ_PARAMS, %NL80211_ATTR_WIPHY_FREQ (and the attributes determining the channel width; this is used for setting monitor mode channel), %NL80211_ATTR_WIPHY_RETRY_SHORT, %NL80211_ATTR_WIPHY_RETRY_LONG, %NL80211_ATTR_WIPHY_FRAG_THRESHOLD, and/or %NL80211_ATTR_WIPHY_RTS_THRESHOLD. However, for setting the channel, see %NL80211_CMD_SET_CHANNEL instead, the support here is for backward compatibility only."}, "@NL80211_CMD_AUTHENTICATE": {"attrs": ["%NL80211_ATTR_IFINDEX", "%NL80211_ATTR_MAC", "%NL80211_ATTR_SSID", "%NL80211_ATTR_WIPHY_FREQ", "%NL80211_ATTR_AUTH_TYPE", "%NL80211_ATTR_IE", "%NL80211_ATTR_FRAME", "%NL80211_ATTR_FRAME", "%NL80211_ATTR_TIMED_OUT", "%NL80211_ATTR_MAC"], "desc": "authentication This command is used both as a command (request to authenticate) and as an event on the \"mlme\" multicast group indicating completion of the authentication process. When used as a command, %NL80211_ATTR_IFINDEX is used to identify the interface. %NL80211_ATTR_MAC is used to specify PeerSTAAddress (and BSSID in case of station mode). %NL80211_ATTR_SSID is used to specify the SSID (mainly for association, but is included in authentication request, too, to help BSS selection. %NL80211_ATTR_WIPHY_FREQ is used to specify the frequence of the channel in MHz. %NL80211_ATTR_AUTH_TYPE is used to specify the authentication type. %NL80211_ATTR_IE is used to define IEs (VendorSpecificInfo, but also including RSN IE and FT IEs) to be added to the frame. When used as an event, this reports reception of an Authentication frame in station and IBSS modes when the local MLME processed the frame, i.e., it was for the local STA and was received in correct state. This is similar to MLME-AUTHENTICATE.confirm primitive in the MLME SAP interface (kernel providing MLME, userspace SME). The included %NL80211_ATTR_FRAME attribute contains the management frame (including both the header and frame body, but not FCS). This event is also used to indicate if the authentication attempt timed out. In that case the %NL80211_ATTR_FRAME attribute is replaced with a %NL80211_ATTR_TIMED_OUT flag (and %NL80211_ATTR_MAC to indicate which pending authentication timed out)."}, "@NL80211_CMD_DEL_PATH": {"attrs": ["%NL80211_ATTR_IFINDEX"], "desc": "Remove or, if no MAC address given, all mesh paths, on the interface identified by %NL80211_ATTR_IFINDEX."}, "@NL80211_CMD_GET_MESH_CONFIG": {"attrs": ["%NL80211_ATTR_IFINDEX"], "desc": "Get interface identified by %NL80211_ATTR_IFINDEX"}, "@NL80211_CMD_NEW_PATH": {"attrs": ["%NL80211_ATTR_IFINDEX"], "desc": "Add the interface identified by %NL80211_ATTR_IFINDEX."}, "@NL80211_CMD_NEW_MPATH": {"attrs": ["%NL80211_ATTR_MAC", "%NL80211_ATTR_MPATH_NEXT_HOP"], "desc": "Create %NL80211_ATTR_MAC via %NL80211_ATTR_MPATH_NEXT_HOP."}, "@NL80211_CMD_MICHAEL_MIC_FAILURE": {"attrs": ["%NL80211_ATTR_MAC", "%NL80211_ATTR_KEY_TYPE", "%NL80211_ATTR_KEY_IDX", "%NL80211_ATTR_KEY_SEQ"], "desc": "notification MIC (part of TKIP) failure; sent on the \"mlme\" multicast group; the event includes %NL80211_ATTR_MAC to describe the source MAC address of the frame with invalid MIC, %NL80211_ATTR_KEY_TYPE to show the key type, %NL80211_ATTR_KEY_IDX to indicate the key identifier, and %NL80211_ATTR_KEY_SEQ to indicate the TSC value of the frame; this event matches with MLME-MICHAELMICFAILURE.indication() primitive"}, "@NL80211_CMD_SET_WIPHY_NETNS": {"attrs": [], "desc": "Set associated with this wiphy must be down and will follow."}, "@NL80211_CMD_DEL_KEY": {"attrs": ["%NL80211_ATTR_MAC"], "desc": "delete or %NL80211_ATTR_MAC."}, "@NL80211_CMD_SET_CQM": {"attrs": [], "desc": "Connection is used to configure connection quality monitoring notification trigger levels."}, "@NL80211_CMD_REMAIN_ON_CHANNEL": {"attrs": ["%NL80211_ATTR_IFINDEX", "%NL80211_ATTR_WIPHY_FREQ", "%NL80211_ATTR_DURATION", "%NL80211_ATTR_COOKIE"], "desc": "Request channel for the specified amount of time. This can be used to do off-channel operations like transmit a Public Action frame and wait for a response while being associated to an AP on another channel. %NL80211_ATTR_IFINDEX is used to specify which interface (and thus radio) is used. %NL80211_ATTR_WIPHY_FREQ is used to specify the frequency for the operation. %NL80211_ATTR_DURATION is used to specify the duration in milliseconds to remain on the channel. This command is also used as an event to notify when the requested duration starts (it may take a while for the driver to schedule this time due to other concurrent needs for the radio). When called, this operation returns a cookie (%NL80211_ATTR_COOKIE) that will be included with any events pertaining to this request; the cookie is also used to cancel the request."}, "@NL80211_CMD_JOIN_IBSS": {"attrs": ["%NL80211_ATTR_BEACON_INTERVAL"], "desc": "Join FREQ attribute (for the initial frequency if no peer can be found) and optionally a MAC (as BSSID) and FREQ_FIXED attribute if those should be fixed rather than automatically determined. Can only be executed on a network interface that is UP, and fixed BSSID/FREQ may be rejected. Another optional parameter is the beacon interval, given in the %NL80211_ATTR_BEACON_INTERVAL attribute, which if not given defaults to 100 TU (102.4ms)."}, "@NL80211_CMD_REG_BEACON_HINT": {"attrs": ["%NL80211_ATTR_WIPHY", "%NL80211_ATTR_FREQ_BEFORE", "%NL80211_ATTR_FREQ_AFTER"], "desc": "indicates has been found while world roaming thus enabling active scan or any mode of operation that initiates TX (beacons) on a channel where we would not have been able to do either before. As an example if you are world roaming (regulatory domain set to world or if your driver is using a custom world roaming regulatory domain) and while doing a passive scan on the 5 GHz band you find an AP there (if not on a DFS channel) you will now be able to actively scan for that AP or use AP mode on your card on that same channel. Note that this will never be used for channels 1-11 on the 2 GHz band as they are always enabled world wide. This beacon hint is only sent if your device had either disabled active scanning or beaconing on a channel. We send to userspace the wiphy on which we removed a restriction from (%NL80211_ATTR_WIPHY) and the channel on which this occurred before (%NL80211_ATTR_FREQ_BEFORE) and after (%NL80211_ATTR_FREQ_AFTER) the beacon hint was processed."}, "@NL80211_CMD_CRIT_PROTOCOL_START": {"attrs": [], "desc": "Indicates a critical protocol that needs more reliability in the connection to complete."}, "@NL80211_CMD_UNPROT_DEAUTHENTICATE": {"attrs": [], "desc": "Unprotected notification. This event is used to indicate that an unprotected deauthentication frame was dropped when MFP is in use."}, "@NL80211_CMD_REQ_SET_REG": {"attrs": [], "desc": "ask to the specified ISO/IEC 3166-1 alpha2 country code. The core will store this as a valid request and then query userspace for it."}, "@NL80211_CMD_SCHED_SCAN_RESULTS": {"attrs": [], "desc": "indicates results available."}, "@NL80211_CMD_REGISTER_BEACONS": {"attrs": [], "desc": "Register other BSSes when any interfaces are in AP mode. This helps implement OLBC handling in hostapd. Beacons are reported in %NL80211_CMD_FRAME messages. Note that per PHY only one application may register."}, "@NL80211_CMD_NEW_BEACON": {"attrs": [], "desc": "old"}, "@NL80211_CMD_NOTIFY_CQM": {"attrs": [], "desc": "Connection command is used as an event to indicate the that a trigger level was reached."}, "@NL80211_CMD_TRIGGER_SCAN": {"attrs": ["%NL80211_ATTR_TX_NO_CCK_RATE"], "desc": "trigger %NL80211_ATTR_TX_NO_CCK_RATE is used to decide whether to send the probe requests at CCK rate or not."}, "@NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL": {"attrs": ["%NL80211_ATTR_WIPHY", "%NL80211_ATTR_IFINDEX", "%NL80211_ATTR_COOKIE"], "desc": "This pending remain-on-channel duration if the desired operation has been completed prior to expiration of the originally requested duration. %NL80211_ATTR_WIPHY or %NL80211_ATTR_IFINDEX is used to specify the radio. The %NL80211_ATTR_COOKIE attribute must be given as well to uniquely identify the request. This command is also used as an event to notify when a requested remain-on-channel duration has expired."}, "@NL80211_CMD_REGISTER_FRAME": {"attrs": [], "desc": "Register (via @NL80211_CMD_FRAME) for processing in userspace. This command requires an interface index, a frame type attribute (optional for backward compatibility reasons, if not given assumes action frames) and a match attribute containing the first few bytes of the frame that should match, e.g. a single byte for only a category match or four bytes for vendor frames including the OUI. The registration cannot be dropped, but is removed automatically when the netlink socket is closed. Multiple registrations can be made."}, "@NL80211_CMD_CHANNEL_SWITCH": {"attrs": ["%NL80211_ATTR_CH_SWITCH_COUNT", "%NL80211_ATTR_WIPHY_FREQ", "%NL80211_ATTR_CH_SWITCH_BLOCK_TX"], "desc": "Perform the new channel information (Channel Switch Announcement - CSA) in the beacon for some time (as defined in the %NL80211_ATTR_CH_SWITCH_COUNT parameter) and then change to the new channel. Userspace provides the new channel information (using %NL80211_ATTR_WIPHY_FREQ and the attributes determining channel width). %NL80211_ATTR_CH_SWITCH_BLOCK_TX may be supplied to inform other station that transmission must be blocked until the channel switch is complete."}, "@NL80211_CMD_GET_INTERFACE": {"attrs": ["%NL80211_ATTR_WIPHY", "%NL80211_ATTR_IFINDEX"], "desc": "Request either a dump request on a %NL80211_ATTR_WIPHY or a specific get on an %NL80211_ATTR_IFINDEX is supported."}, "@NL80211_CMD_RADAR_DETECT": {"attrs": ["%NL80211_ATTR_RADAR_EVENT"], "desc": "Start a radar is detected or the channel availability scan (CAC) has finished or was aborted, or a radar was detected, usermode will be notified with this event. This command is also used to notify userspace about radars while operating on this channel. %NL80211_ATTR_RADAR_EVENT is used to inform about the type of the event."}, "@NL80211_CMD_GET_POWER_SAVE": {"attrs": [], "desc": "Get"}, "@NL80211_CMD_DISCONNECT": {"attrs": ["%NL80211_ATTR_DISCONNECTED_BY_AP", "%NL80211_ATTR_REASON_CODE"], "desc": "drop userspace that a connection was dropped by the AP or due to other reasons, for this the %NL80211_ATTR_DISCONNECTED_BY_AP and %NL80211_ATTR_REASON_CODE attributes are used."}, "@NL80211_CMD_CONNECT": {"attrs": ["%NL80211_ATTR_SSID", "%NL80211_ATTR_IE", "%NL80211_ATTR_AUTH_TYPE", "%NL80211_ATTR_USE_MFP", "%NL80211_ATTR_MAC", "%NL80211_ATTR_WIPHY_FREQ", "%NL80211_ATTR_CONTROL_PORT", "%NL80211_ATTR_CONTROL_PORT_ETHERTYPE", "%NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT", "%NL80211_ATTR_BG_SCAN_PERIOD"], "desc": "connection requests to connect to a specified network but without separating auth and assoc steps. For this, you need to specify the SSID in a %NL80211_ATTR_SSID attribute, and can optionally specify the association IEs in %NL80211_ATTR_IE, %NL80211_ATTR_AUTH_TYPE, %NL80211_ATTR_USE_MFP, %NL80211_ATTR_MAC, %NL80211_ATTR_WIPHY_FREQ, %NL80211_ATTR_CONTROL_PORT, %NL80211_ATTR_CONTROL_PORT_ETHERTYPE and %NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT. Background scan period can optionally be specified in %NL80211_ATTR_BG_SCAN_PERIOD, if not specified default background scan configuration in driver is used and if period value is 0, bg scan will be disabled. This attribute is ignored if driver does not support roam scan. It is also sent as an event, with the BSSID and response IEs when the connection is established or failed to be established. This can be determined by the STATUS_CODE attribute."}, "@NL80211_CMD_SET_BEACON": {"attrs": ["%NL80211_ATTR_BEACON_HEAD", "%NL80211_ATTR_BEACON_TAIL", "%NL80211_ATTR_IE", "%NL80211_ATTR_IE_PROBE_RESP", "%NL80211_ATTR_IE_ASSOC_RESP"], "desc": "change using the %NL80211_ATTR_BEACON_HEAD and %NL80211_ATTR_BEACON_TAIL attributes. For drivers that generate the beacon and probe responses internally, the following attributes must be provided: %NL80211_ATTR_IE, %NL80211_ATTR_IE_PROBE_RESP and %NL80211_ATTR_IE_ASSOC_RESP."}, "@NL80211_CMD_ACTION_TX_STATUS": {"attrs": [], "desc": "Alias backward compatibility."}, "@NL80211_CMD_JOIN_MESH": {"attrs": [], "desc": "Join mesh config parameters may be given."}, "@NL80211_CMD_ROAM": {"attrs": [], "desc": "request sent as an event when the card/driver roamed by itself."}, "@NL80211_CMD_SET_REG": {"attrs": ["%NL80211_ATTR_REG_ALPHA", "%NL80211_ATTR_REG_RULE_FREQ_", "%NL80211_ATTR_FREQ_RANGE_MAX_BW", "%NL80211_ATTR_REG_RULE_POWER_MAX_ANT_GAIN", "%NL80211_ATTR_REG_RULE_POWER_MAX_EIRP"], "desc": "Set after being queried by the kernel. CRDA replies by sending a regulatory domain structure which consists of %NL80211_ATTR_REG_ALPHA set to our current alpha2 if it found a match. It also provides NL80211_ATTR_REG_RULE_FLAGS, and a set of regulatory rules. Each regulatory rule is a nested set of attributes given by %NL80211_ATTR_REG_RULE_FREQ_[START|END] and %NL80211_ATTR_FREQ_RANGE_MAX_BW with an attached power rule given by %NL80211_ATTR_REG_RULE_POWER_MAX_ANT_GAIN and %NL80211_ATTR_REG_RULE_POWER_MAX_EIRP."}, "@NL80211_CMD_GET_COALESCE": {"attrs": [], "desc": "Get"}, "@NL80211_CMD_FRAME_WAIT_CANCEL": {"attrs": [], "desc": "When command may be used with the corresponding cookie to cancel the wait time if it is known that it is no longer necessary."}, "@NL80211_CMD_DEL_BEACON": {"attrs": [], "desc": "old"}, "@NL80211_CMD_LEAVE_IBSS": {"attrs": [], "desc": "Leave determined by the network interface."}, "@NL80211_CMD_SET_MCAST_RATE": {"attrs": [], "desc": "Change for IBSS or MESH vif."}, "@NL80211_CMD_TESTMODE": {"attrs": [], "desc": "testmode to identify the device, and the TESTDATA blob attribute to pass through to the driver."}, "@NL80211_CMD_DEL_MPATH": {"attrs": ["%NL80211_ATTR_MAC"], "desc": "Delete %NL80211_ATTR_MAC."}} +{"0": "@NL80211_CMD_UNSPEC", "1": "@NL80211_CMD_GET_WIPHY", "2": "@NL80211_CMD_SET_WIPHY", "3": "@NL80211_CMD_NEW_WIPHY", "4": "@NL80211_CMD_DEL_WIPHY", "5": "@NL80211_CMD_GET_INTERFACE", "6": "@NL80211_CMD_SET_INTERFACE", "7": "@NL80211_CMD_NEW_INTERFACE", "8": "@NL80211_CMD_DEL_INTERFACE", "9": "@NL80211_CMD_GET_KEY", "10": "@NL80211_CMD_SET_KEY", "11": "@NL80211_CMD_NEW_KEY", "12": "@NL80211_CMD_DEL_KEY", "13": "@NL80211_CMD_GET_BEACON", "14": "@NL80211_CMD_SET_BEACON", "15": ["@NL80211_CMD_START_AP", "@NL80211_CMD_NEW_BEACON"], "16": ["@NL80211_CMD_STOP_AP", "@NL80211_CMD_DEL_BEACON"], "17": "@NL80211_CMD_GET_STATION", "18": "@NL80211_CMD_SET_STATION", "19": "@NL80211_CMD_NEW_STATION", "20": "@NL80211_CMD_DEL_STATION", "21": "@NL80211_CMD_GET_MPATH", "22": "@NL80211_CMD_SET_MPATH", "23": "@NL80211_CMD_NEW_MPATH", "24": "@NL80211_CMD_DEL_MPATH", "25": "@NL80211_CMD_SET_BSS", "26": "@NL80211_CMD_SET_REG", "27": "@NL80211_CMD_REQ_SET_REG", "28": "@NL80211_CMD_GET_MESH_CONFIG", "29": "@NL80211_CMD_SET_MESH_CONFIG", "30": "@NL80211_CMD_SET_MGMT_EXTRA_IE", "31": "@NL80211_CMD_GET_REG", "32": "@NL80211_CMD_GET_SCAN", "33": "@NL80211_CMD_TRIGGER_SCAN", "34": "@NL80211_CMD_NEW_SCAN_RESULTS", "35": "@NL80211_CMD_SCAN_ABORTED", "36": "@NL80211_CMD_REG_CHANGE", "37": "@NL80211_CMD_AUTHENTICATE", "38": "@NL80211_CMD_ASSOCIATE", "39": "@NL80211_CMD_DEAUTHENTICATE", "40": "@NL80211_CMD_DISASSOCIATE", "41": "@NL80211_CMD_MICHAEL_MIC_FAILURE", "42": "@NL80211_CMD_REG_BEACON_HINT", "43": "@NL80211_CMD_JOIN_IBSS", "44": "@NL80211_CMD_LEAVE_IBSS", "45": "@NL80211_CMD_TESTMODE", "46": "@NL80211_CMD_CONNECT", "47": "@NL80211_CMD_ROAM", "48": "@NL80211_CMD_DISCONNECT", "49": "@NL80211_CMD_SET_WIPHY_NETNS", "50": "@NL80211_CMD_GET_SURVEY", "51": "@NL80211_CMD_NEW_SURVEY_RESULTS", "52": "@NL80211_CMD_SET_PMKSA", "53": "@NL80211_CMD_DEL_PMKSA", "54": "@NL80211_CMD_FLUSH_PMKSA", "55": "@NL80211_CMD_REMAIN_ON_CHANNEL", "56": "@NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL", "57": "@NL80211_CMD_SET_TX_BITRATE_MASK", "58": ["@NL80211_CMD_REGISTER_ACTION", "@NL80211_CMD_REGISTER_FRAME"], "59": ["@NL80211_CMD_FRAME", "@NL80211_CMD_ACTION"], "60": ["@NL80211_CMD_FRAME_TX_STATUS", "@NL80211_CMD_ACTION_TX_STATUS"], "61": "@NL80211_CMD_SET_POWER_SAVE", "62": "@NL80211_CMD_GET_POWER_SAVE", "63": "@NL80211_CMD_SET_CQM", "64": "@NL80211_CMD_NOTIFY_CQM", "65": "@NL80211_CMD_SET_CHANNEL", "66": "@NL80211_CMD_SET_WDS_PEER", "67": "@NL80211_CMD_FRAME_WAIT_CANCEL", "68": "@NL80211_CMD_JOIN_MESH", "69": "@NL80211_CMD_LEAVE_MESH", "70": "@NL80211_CMD_UNPROT_DEAUTHENTICATE", "71": "@NL80211_CMD_UNPROT_DISASSOCIATE", "72": "@NL80211_CMD_NEW_PEER_CANDIDATE", "73": "@NL80211_CMD_GET_WOWLAN", "74": "@NL80211_CMD_SET_WOWLAN", "75": "@NL80211_CMD_START_SCHED_SCAN", "76": "@NL80211_CMD_STOP_SCHED_SCAN", "77": "@NL80211_CMD_SCHED_SCAN_RESULTS", "78": "@NL80211_CMD_SCHED_SCAN_STOPPED", "79": "@NL80211_CMD_SET_REKEY_OFFLOAD", "80": "@NL80211_CMD_PMKSA_CANDIDATE", "81": "@NL80211_CMD_TDLS_OPER", "82": "@NL80211_CMD_TDLS_MGMT", "83": "@NL80211_CMD_UNEXPECTED_FRAME", "84": "@NL80211_CMD_PROBE_CLIENT", "85": "@NL80211_CMD_REGISTER_BEACONS", "86": "@NL80211_CMD_UNEXPECTED_4ADDR_FRAME", "87": "@NL80211_CMD_SET_NOACK_MAP", "88": "@NL80211_CMD_CH_SWITCH_NOTIFY", "89": "@NL80211_CMD_START_P2P_DEVICE", "90": "@NL80211_CMD_STOP_P2P_DEVICE", "91": "@NL80211_CMD_CONN_FAILED", "92": "@NL80211_CMD_SET_MCAST_RATE", "93": "@NL80211_CMD_SET_MAC_ACL", "94": "@NL80211_CMD_RADAR_DETECT", "95": "@NL80211_CMD_GET_PROTOCOL_FEATURES", "96": "@NL80211_CMD_UPDATE_FT_IES", "97": "@NL80211_CMD_FT_EVENT", "98": "@NL80211_CMD_CRIT_PROTOCOL_START", "99": "@NL80211_CMD_CRIT_PROTOCOL_STOP", "100": "@NL80211_CMD_GET_COALESCE", "101": "@NL80211_CMD_SET_COALESCE", "102": "@NL80211_CMD_CHANNEL_SWITCH"} \ No newline at end of file diff --git a/pyric/docs/nlhelp.py b/pyric/docs/nlhelp.py new file mode 100644 index 0000000..a523c8a --- /dev/null +++ b/pyric/docs/nlhelp.py @@ -0,0 +1,155 @@ +#!/usr/bin/env python +""" nlhelp.py: nl80211 help functions + +A set of functions to assist in finding info on nl80211 commands and attributes. +These are stored in the "data" files commands.help and attributes.help which are +json files. + +Copyright (C) 2016 Dale V. Patterson (wraith.wireless@yandex.com) + +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 3 of the License, or (at your option) any later +version. + +Redistribution and use in source and binary forms, with or without modifications, +are permitted provided that the following conditions are met: + o Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + o Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + o Neither the name of the orginal author Dale V. Patterson nor the names of any + contributors may be used to endorse or promote products derived from this + software without specific prior written permission. + +""" + +__name__ = 'nlhelp' +__license__ = 'GPLv3' +__version__ = '0.0.1' +__date__ = 'August 2014' +__author__ = 'Dale Patterson' +__maintainer__ = 'Dale Patterson' +__email__ = 'wraith.wireless@yandex.com' +__status__ = 'Development' + +import os +import json +import pyric +import pyric.net.wireless.nl80211_h as nl80211h + +# where are we? +fpath = os.path.dirname(os.path.realpath(__file__)) + +# read in the files here +cmdpath = os.path.join(fpath,'commands.help') +commands = None # cmd -> desc,attributes used dict +cmdlookup = None # reverse lookup for command constants +cin = None +try: + # first two lines are comments, 3rd line is empty + cin = open(cmdpath,'r') + for _ in xrange(3): _in = cin.readline() + commands = json.loads(cin.readline()) + cmdlookup = json.loads(cin.readline()) +except: + raise pyric.error(pyric.EUNDEF,"Failed to process commands.help") +finally: + if cin: cin.close() + +attrpath = os.path.join(fpath,'attributes.help') +attributes = None # attr -> desc, commands used by, datatype +attrlookup = None # reverse lookup for attribute constants +ain = None +try: + # first two lines are comments, 3rd line is empty + ain = open(attrpath,'r') + for _ in xrange(3): _in = ain.readline() + attributes = json.loads(ain.readline()) + attrlookup = json.loads(ain.readline()) +except: + raise pyric.error(pyric.EUNDEF, "Failed to process attributes.help") +finally: + if ain: ain.close() + +def command(cmd): + """ + shows help on command can either be the full name i.e. NL80211_CMD_GET_WIPHY + or a shortened version GET_WIPHY + :param cmd: command to show description of. + :returns: description of command, attributes used in command and the constant + that refers to the command + """ + try: + cmd = cmd.upper().replace('@','') # in the event it comes from cmdbynum + if not cmd.startswith("NL80211_CMD_"): cmd = "@NL80211_CMD_" + cmd + else: cmd = '@' + cmd + entry = commands[cmd] + attrs = ", ".join([attr.replace('%','') for attr in entry['attrs']]) + out = "{0}\tValue={1}\n".format(cmd,eval('nl80211h.' + cmd[1:])) + out += "------------------------------------------------------\n" + out += "Description: {0}\n".format(entry['desc']) + out += "------------------------------------------------------\n" + out += "Attributes: {0}".format(attrs) + return out + except KeyError: + return "No entry found for command {0}".format(cmd) + except AttributeError: + return "{0} not found in nl80211_h".format(cmd) + +def cmdbynum(n): + """ + reverse lookup n to corresponding command variable + :param n: integer value to search for + :returns: string representation of the command variable corresponding to n + """ + return cmdlookup[str(n)] + +def attribute(attr): + """ + shows help on attribute can either be the full name i.e. NL80211_ATTR_MAC + or a shortened version MAC + :param attr: attribute to show description of. + :returns: description of attribute, commands that use the attribute, datatype + of the attribute and the constant that refers to the attribute + """ + try: + attr = attr.upper().replace('@','') # in the event it comes from attrbynum + if not attr.startswith("NL80211_ATTR_"): attr = "@NL80211_ATTR_" + attr + else: attr = '@' + attr + entry = attributes[attr] + cmds = ", ".join([cmd.replace('%', '') for cmd in entry['cmds']]) + out = "{0}\tValue={1}\tDatatype={2}\n".format(attr, + eval('nl80211h.' + attr[1:]), + entry['type']) + out += "------------------------------------------------------\n" + out += "Description: {0}\n".format(entry['desc']) + out += "------------------------------------------------------\n" + out += "Commands: {0}".format(cmds) + return out + except KeyError: + return "No entry found for attribute {0}".format(attr) + except AttributeError: + return "{0} not found in nl80211_h".format(attr) + +def attrbynum(n): + """ + reverse lookup n to corresponding attribute variable + :param n: integer value to search for + :returns: string representation of the command variable corresponding to n + """ + return attrlookup[str(n)][0] + +def search(tkn): + """ + searches for and returns any commands,attributes with tkn + :param tkn: + :returns: a list of commands,attributes with tkn in them + """ + tkn = tkn.upper() + if len(tkn) < 3: + raise pyric.error(pyric.EUNDEF,"{0} is to ambiguous".format(tkn)) + found = [cmd for cmd in commands if tkn in cmd] + found += [attr for attr in attributes if tkn in attr] + return found \ No newline at end of file diff --git a/pyric/docs/res/PyRIC.bib b/pyric/docs/res/PyRIC.bib new file mode 100644 index 0000000..61e08ca --- /dev/null +++ b/pyric/docs/res/PyRIC.bib @@ -0,0 +1,52 @@ +% This file was created with JabRef 2.10b2. +% Encoding: UTF-8 + + +@Misc{libnl, + Title = {Netlink Library (libnl)}, + Author = {Thomas Graf}, + Month = {May}, + Year = {2011}, + Date = {2011-05-09}, + Language = {english}, + Organization = {Swiss Internet User Group}, + Shorthand = {libnl}, + Url = {http://www.carisma.slowglass.com/~tgr/libnl/doc/core.html}, + Version = {3.2} +} + +@Article{spae, + Title = {Communicating between the kernel and user-space in Linux using Netlink sockets}, + Author = {Pablo Neira Ayuso, Rafael M. Gasca, Laurent Lefevre}, + Journal = {Software - Practice And Experience}, + Year = {2010}, + Month = {August}, + Pages = {797-810}, + Volume = {40} +} + +@Misc{wraith, + Title = {Wireless Reconnaissance And Intelligent Target Harvesting}, + Author = {Dale V. Patterson}, + Month = {April}, + Year = {2016}, + Date = {2016-04-03}, + Language = {english}, + Shorthand = {wraith}, + Url = {https://github.com/wraith-wireless/wraith}, + Version = {0.0.6} +} + +@Misc{gplv3, + Title = {GNU General Public License}, + Month = {June}, + Year = {2007}, + Date = {2007-06-29}, + Language = {english}, + Organization = {Free Software Foundation}, + Pagination = {section}, + Shorthand = {GPL}, + Url = {http://www.gnu.org/licenses/gpl.html}, + Version = {3} +} + diff --git a/pyric/docs/res/PyRIC.tex b/pyric/docs/res/PyRIC.tex new file mode 100644 index 0000000..4b39ca6 --- /dev/null +++ b/pyric/docs/res/PyRIC.tex @@ -0,0 +1,785 @@ +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Copyright (C) 2016 Dale V. Patterson (wraith.wireless@yandex.com) +% +%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 3 of the License, or (at your option) any later +%version. +% +%Redistribution and use in source and binary forms, with or without modifications, +%are permitted provided that the following conditions are met: +% o Redistributions of source code must retain the above copyright notice, this +% list of conditions and the following disclaimer. +% o Redistributions in binary form must reproduce the above copyright notice, +% this list of conditions and the following disclaimer in the documentation +% and/or other materials provided with the distribution. +% o Neither the name of the orginal author Dale V. Patterson nor the names of any +% contributors may be used to endorse or promote products derived from this +% software without specific prior written permission. +% +% __name__ = 'User Guide' +%__license__ = 'GPLv3' +%__version__ = '0.0.2' +%__date__ = 'May 2016' +%__author__ = 'Dale Patterson' +%__maintainer__ = 'Dale Patterson' +%__email__ = 'wraith.wireless@yandex.com' +%__status__ = 'Development' +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\documentclass[11pt]{article} +\usepackage[utf8]{inputenc} +\setlength{\parindent}{0pt} +\usepackage{graphicx} +\usepackage{listings} +\usepackage{caption} +\usepackage{geometry} +\usepackage{color} +\usepackage[titletoc,toc,title]{appendix} +\usepackage[T1]{fontenc} + +\definecolor{codegreen}{rgb}{0,0.6,0} +\definecolor{codegray}{rgb}{0.5,0.5,0.5} +\definecolor{codepurple}{rgb}{0.58,0,0.82} +\definecolor{backcolour}{rgb}{0.95,0.95,0.92} + +\geometry{left=1.0in,right=1.0in,top=1.0in,bottom=1.0in } + +\lstset{ + frame=top, + frame=bottom, + basicstyle=\small\normalfont\ , + stepnumber=1, + numbersep=10pt, + tabsize=2, + extendedchars=true, + breaklines=true, + captionpos=b, + mathescape=true, + showspaces=false, + showtabs=false, + xleftmargin=17pt, + framexleftmargin=17pt, + framexrightmargin=17pt, + framexbottommargin=5pt, + framextopmargin=5pt, + showstringspaces=false, + backgroundcolor=\color{backcolour}, + commentstyle=\color{codegreen}, + keywordstyle=\color{magenta}, + numberstyle=\tiny\color{codegray}, + stringstyle=\color{codepurple}, + basicstyle=\footnotesize +} + +\title{PyRIC v0.0.5: User Manual} +\author{Dale V. Patterson\\ wraith.wireless@yandex.com} + +\begin{document} +\maketitle +\tableofcontents + +\section{About PyRIC}\label{sec:About} +PyRIC is a python port of (a subset of) iw and by extension a python port of +Netlink\cite{spae} (w.r.t nl80211 functions). The goal of PyRIc is to provide +a simple interface to the underlying nl80211 kernel support that handles the +complex operations of Netlink seamlessy while maintaining a minimum of "code +walking" to understand, modify and extend. PyRIC will only work on Linux +with Netlink support.\\ + +While users can utilize libnl(.py) and libio(.py) to communicate directly with +the kernel, the true utility of PyRIC is pyw(.py). Like iw, pyw provides an +interface/buffer between the caller and the kernel, handling all message +construction, parsing and transfer transparently and without requiring any +Netlink knowledge or experience. \\ + +At this time, PyRIC (through pyw functions) can: +\begin{itemize} +\item enumerate interfaces and wireless interfaces, +\item get/set hw address, +\item identify a radio's chipset and driver, +\item turn device on/off, +\item get supported standards, +\item get/set regulatory domain, +\item get info on device, +\item add/delete interfaces. +\end{itemize} +It also provides users with the ability, through libnl(.py) to extend the above +functionality by creating additional commands.\\ + +Currently, PyRIC does handle multicast messages i.e. events or dumps although +plans for future versions include adding the ability to process dumps. + +\subsection{Naming Conventions} +The terms interface, device and radio are all used interchangeably throughout to +refer to a network interface card (NIC) wireless or Ethernet. The following terms +will always have one one meaning: +\begin{itemize} +\item \textbf{dev} - the device name i.e. wlan0 or eth0 of a NIC, +\item \textbf{phy} - the physical index of a NIC i.e. the 0 in phy0, +\item \textbf{ifindex} - the interface index of a NIC, +\item \textbf{card} or \textbf{Card} - a NIC abstraction, an object used in pyw +functions see the following section for a description. +\end{itemize} + +\subsection{Cards} +A Card is merely a wrapper around a tuple t = (phy index,device name,ifindex). +Since the underlying Netlink calls sometimes require the physical index, sometimes +the device name, and sometimes the ifindex, pyw functions\footnote{Not all functions +accept a Card, the function pyw.devinfo() will accept either a Card or a dev and +pyw.isinterface() only accepts a dev} take a Card object which doesn't require +callers to know which identifier to use for each function. There are four primary methods to creating a Card: +\begin{enumerate} +\item \textbf{pyw.getcard} returns a Card object from a given dev, +\item \textbf{pyw.devinfo} returns the dict info where info['card'] is the Card +object. This function will take either a card or a dev +\item \textbf{pyw.devadd} returns a new Card object, +\item \textbf{pyw.ifaces} returns a list of tuples t = (Card,mode) sharing the +same phy as a given dev. +\end{enumerate} + +A side affect of using Cards is that many of the netlink calls require the ifindex. +The ifindex is found through the use of ioctl, meaning two sockets have to be +created and two messages have to be sent, received and parsed in order to execute +the command. With Cards, the ifindex is requested for only once. \\ + +Keep in mind that any identifier (phy,dev,ifindex) can be invalidated outside of +your control. Another program can rename your interface, that is change the dev +without your knowledge. Depending on what functions are being used this may not +be noticed right away as the phy will remain the same. Also, usb devices (if the +usb is disconnected and reconnected) will have the same dev but the phy and +ifindex will be different. + +\subsection{Hierarchy/Architecture} +PyRIC's hierarchy is briefly discussed next. + +\begin{enumerate} +\item \textbf{\_\_init\_\_.py}: Initialize PyRIC, defines the EUNDEF error code +(PyRIC uses errno for all errorcodes adding EUNDEF) and PyRIC's common exception +class, 'error' - all submodules use this class for any exceptions. +\item \textbf{README.md}: self-descriptive +\item \textbf{TODO}: lists any outstanding TODOs, ideas for future revisions +\item \textbf{RFI}: comments and observations about netlinks, nl80211 etc +\item \textbf{channels.py}: ISM and UNII frequencies and channels, with conversion functions +\item \textbf{device.py}: device and chipset utility functions +\item \textbf{pyw.py}: this is the interface, providing wireless interface manipulation functions +\item \textbf{lib}: lib subpackage +\begin{enumerate} +\item \textbf{\_\_init\_\_.py}: initialize lib subpackage +\item \textbf{libnl.py}: netlink API +\item \textbf{libio.py}: ioctl API +\end{enumerate} +\item \textbf{net}: net subpackage +\begin{enumerate} +\item \textbf{\_\_init\_\_.py}: initialize net subpackage +\item \textbf{if\_h.py}: inet/ifreq definition +\item \textbf{sockios\_h.py}: socket-level I/O control call flags +\item \textbf{netlink\_h.py}: port of netlink.h +\item \textbf{genetlink\_h.py}: port of genetlink.h +\item \textbf{policy.py}: defines attribute datatypes +\item \textbf{wireless}: wireless subpackage +\begin{enumerate} +\item \textbf{\_\_init\_\_.py}: initialize lib subpackage +\item \textbf{nl80211\_h.py}: port of nl80211 (commands \& attributes) +\item \textbf{nl80211\_c.py}: nl80211 attribute datatypes/policies +\end{enumerate} +\end{enumerate} +\item \textbf{docs}: docs subpackage +\item \textbf{\_\_init\_\_.py}: initialize docs subpackage +\item \textbf{nlhelp.py}: functions to search display nl80211 constants +\item \textbf{commands.help}: nl80211 commands help data (json) +\item \textbf{attributes.help}: nl80211 attributes help data (json) +\item \textbf{PyRIC.pdf}: this file +\item \textbf{res}:resource subpackage +\begin{enumerate} +\item \textbf{PyRIC.tex}: LaTeX for user guide +\item \textbf{PyRIC.bib}: bibliography for user guide +\end{enumerate} +\end{enumerate} + +\section{Installing PyRIC}\label{sec:installing} +PyRIC is self-sufficient in that there are no third-party/external dependencies +and can be run out of the box. To install, from a terminal type 'pip install +--pre PyRIC' as root. This is my first attempt at packaging and it has not been +currently tested. The latest PyRIC release can be downloaded as a tarball on PyPI +at https://pypi.python.org/pypi?name=PyRIC or github at +https://github.com/wraith-wireless/pyric/releases/latest. If you decide to download +the tarball and run PyRIC outside of it's directory or from another program, you +should put it on your Python path. Use Google for directions on doing so. Note: +put /yourpath/pyric/pyric in the .pth file, not the outer pyric directory. + +\section{Using PyRIC}\label{sec:using} +As stated previously, PyRIC provides a set of functions to interact with your +system's radio(s) and the ability to interact directly with the kernel through +netlink and ioctl sockets. \\ + +It is expected that the reader has a basic knowledge of netlinks. For a +review see Graf\cite{libnl}. + +\subsection{Interacting with the Wireless Core and Wireless NICs: pyw.py} +If you can use iw, you can use pyw. The easist way to explain how to use pyw is +with an example. Imagine your wireless network on ch 6 has been experiencing +difficulites lately and you want to capture some traffic to analyse it. Listing +\ref{lst:pentest} shows how to set up a wireless pentest environment. \\ + +\begin{lstlisting}[caption={Setting up a Wireless Pentest Environment}, + label={lst:pentest}, + language=Python] + 1: import pyric # pyric error (and ecode EUNDEF) + 2: from pyric import pyw # for iw functionality + 3: from pyric import device # for chipset/driver + 4: from pyric.channels import rf2ch # rf to channel conversion + 5: + 6: # list interfaces, wireless interfaces + 7: print "Interfaces: ", pyw.interfaces() + 8: print "Wireless Interfaces: ", pyw.winterfaces() + 9: +10: # get a Card & info for alfa0 & print a description +11: info = pyw.devinfo('alfa0') +12: card = info['card'] +13: driver = device.ifdriver(card.dev) +14: chipset = device.ifchipset(driver) +15: msg = "{Using {0} in mode: {1}".format(card,info['mode']) +16: if info['mode'] == 'managed': +17: msg += " currently on channel {0} width {1}".format(rf2ch(info['RF']), +18: info['CHW']) +19: msg += " driver: {0}, chipset: {1}".format(driver,chipset) +20: print msg +21: +22: # prepare a virtual interface named pent0 in monitor mode +23: pdev = 'pent0' +24: pcard = pyw.devadd(card,pdev,'monitor') +25: for iface in pyw.ifaces(card): +26: if iface[0].dev != pdev: +27: msg = "deleting {0} in mode {1}".format(iface[0],iface[1]) +28: print msg +29: pyw.devdel(iface[0]) +30: pyw.macset(pcard,'00:03:93:57:54:46') +31: pyw.up(pcard) +32: pyw.chset(pcard,6,None) +33: msg = "Virtual interface {0} in monitor mode on ch 6".format(pcard) +34: print msg + ", using hwaddr: {0}".format(pyw.macget(pcard) +35: +36: # DO stuff here +37: +38: # restore original +39: print "deleting ", pcard +40: pyw.devdel(pcard) +41: card = pyw.devadd(card,card.dev,info['mode']) +42: pyw.up(card) +43: print "card ", card, " restored" +\end{lstlisting} + +Listing \ref{lst:pentest} attempts to show most of the available pyw functions +in use and is the basic shell used in another project, Wraith\cite{wraith}, to +instantiate a wireless (802.11) sensor. Lines 1 and 2 should always be included +as they import the pyric error and pyw functions. Lines 3 and 4 import ifchipset, +ifdriver and rf2ch functions. In lines 10 through 20, a Card object for 'alfa0' +is created and details about the interface are printed. On line 24, a device named +'pent0' is created in monitor mode and in lines 25 through 29, all interfaces on +the same phy as the new device are deleted (we have found that it is better to +delete all interfaces on the same phy ensuring that processes like NetworkManager +for example, don't interfere with the new device). Then, the mac address is spoofed +and the device is set to listen on channel 6 NOHT. Starting on line 40, the system +is restored by deleting the monitor card and restoring the original device, 'alfa0'. +Note, only 'alfa0' is restored, and not any devices that may have been deleted on +line 29. Additionally, bringing the device up (line 43) will usually result in the +device reconnecting although in some situations, a manual reconnect to the AP is +required. Future versions of pyw will include "connect" functionality to rectify +this. + +\subsubsection{One-time vs Persistent Sockets} +The example Listing \ref{lst:pentest} uses one-time sockets (netlink and ioctl). +When using iw, there are several things that occur prior to the actual command +or request being submitted. First, iw creates a netlink socket. Then, iw will +request the family id for nl80211. The relative time spent doing this is neglible +but, it is redundant and it may become noticeable in programs that repeatedly +use the Netlink service. Once comlete, iw closes the socket. PyRIC eliminates +these redundancies by using a global variable in pyw that stores the family id +after the first time it is requested and by providing callers the option to use +persistent sockets. +\begin{itemize} +\item \textbf{One-time Sockets} Similar to iw. The command, creates the netlink +socket (or ioctl socket), composes the message, sends the message and receives +the response, parses the results, closes the socket and returns the results to +the caller. At no time does the caller need to be aware of any underlying Netlink +processes or structures. +\item \textbf{Persistent Sockets} Communication and parsing only. The onus of +socket creation and deletion is on the caller which allows them to create one +(or more) socket(s). The pyw functions will only handle message construction, +message sending and receiving and message parsing. +\end{itemize} +The caller needs to be cognizant of whether the function requires a netlink or +ioctl socket. Passing the wrong type will result in an error. \\ + +NOTE: One must remember that there is an upper limit to the number of open netlink +sockets. It is advised to use one-time functions as much as possible and save the +use of persistent sockets for use in code that repeatedly makes use of netlink. \\ + +The latest version of pyw (v 0.1.*) implements this functionality through the +use of what I call templates\footnote{I use templates and stubs for the lack +of any better naming convention}, Listing \ref{lst:template} and stubs Listing +\ref{lst:stub}. + +\begin{lstlisting}[caption={A Basic Netlink Function Template}, + label={lst:template}, + language=Python] +def fcttemplate(arg0,arg1,..,argn,*argv): + # put parameter validation (if any) here + try: + nlsock = argv[0] + except IndexError: + return _nlstub_(fcttemplate,arg0,arg1,...,argn) + + # command execution + ... + return results +\end{lstlisting} + +The template function in Listing \ref{lst:template} checks if argv has a netlink +socket\footnote{ioctl calls operate in the same manner} at index 0. If so, it +proceeds to execution. If there is no socket, the stub is executed which creates +one. If something other than a netlink socket is at argv[0], an error will be +raised during execution. \\ + +\begin{lstlisting}[caption={Function \_nlstub\_}, + label={lst:stub}, + language=Python] +def _nlstub_(fct,*argv): + nlsock = None + try: + nlsock = nlsock = nl.nl_socket_alloc() + argv = list(argv) + [nlsock] + return fct(*argv) + except pyric.error: + raise # catch & release + finally: + if nlsock: nl.nl_socket_free(nlsock) +\end{lstlisting} + +The stub function, Listing \ref{lst:stub} allocates a netlink socket, executes +the original (now with a netlink socket) and then destroys the netlink socket.\\ + +\begin{lstlisting}[caption={Using Persistent Sockets}, + label={lst:persistent}, + language=Python] + 1: import pyric # pyric error (and ecode EUNDEF) + 2: from pyric import pyw # for iw functionality + 3: from pyric import device # for chipset/driver + 4: from pyric.channels import rf2ch # rf to channel conversion + 5: from pyric.lib import libnl as nl # for netlink sockets + 6: from pyric.lib import libio as io # for ioctl sockets + 7: + 8: # create our sockets + 9: nlsock = nl.nl_socket_alloc(timeout=1) +10: iosock = io.io_socket_alloc() +11: +12: # list interfaces, wireless interfaces +13: print "Interfaces: ", pyw.interfaces() +14: print "Wireless Interfaces: ", pyw.winterfaces(iosock): +15: +16: # get a Card & info for alfa0 & print a description +17: info = pyw.devinfo('alfa0',nlsock) +18: card = info['card'] +19: driver = device.ifdriver(card.dev) +20: chipset = device.ifchipset(driver) +21: msg = "{Using {0} in mode: {1}".format(card,info['mode']) +22: if info['mode'] == 'managed': +23: msg += " currently on channel {0} width {1}".format(rf2ch(info['RF']), +24: info['CHW']) +25: msg += " driver: {0}, chipset: {1}".format(driver,chipset) +26: print msg +27: +28: # prepare a virtual interface named pent0 in monitor mode +29: pdev = 'pent0' +30: pcard = pyw.devadd(card,pdev,'monitor',nlsock) +31: for iface in pyw.ifaces(card,nlsock): +32: if iface[0].dev != pdev: +33: msg = "deleting {0} in mode {1}".format(iface[0],iface[1]) +34: print msg +35: pyw.devdel(iface[0],nlsock) +36: pyw.macset(pcard,'00:03:93:57:54:46',iosock) +37: pyw.up(pcard,ioctl) +38: pyw.chset(pcard,6,None) +39: msg = "Virtual interface {0} in monitor mode on ch 6".format(pcard) +40: msg += ", using hwaddr: {0}".format(pyw.macget(pcard,iosock) +41: +42: # DO stuff here +43: +44: # restore original +45: print "deleting ", pcard +46: pyw.devdel(pcard,nlsock) +47: card = pyw.devadd(card,card.dev,info['mode'],nlsock) +48: pyw.up(card,ioctl) +49: print "card ", card, " restored" +50: +51: # release the sockets +52: nl.nl_socket_free(nlsock) +53: io.io_socket_alloc(iosock) +\end{lstlisting} + +In Listing \ref{lst:persistent}, the wireless pentesting environment from Listing +\ref{lst:pentest} is repeated, this time using persistent sockets. Note the imports +at lines 5 and 6 for libnl and libio, socket creation at lines 9 and 10 and socket +destructions at lines 52 and 53. Also, note the lack of a socket used in the +pyw.interfaces() call. This is due to the fact the function interfaces() reads +from the file system and does not use netlink or ioctl. \\ + +Use Python's built in help features on pyw functions or see Appendex \ref{sec:pywapi} +to determine what type of +socket is needed. + +\subsection{Interacting with the Kernel: libnl.py and libio.py} +The kernel interfaces, libnl.py and libio.py are located in the lib directory. +They handle socket creation/deletion, message creation/parsing and kernel +communication. Aside from creating and deleting persistent sockets, there is +little need to access their functions unless you plan on extending pyw +functionality. As such, a further discussion of libnl.py and libio.py can be in +the next section. + +\section{Extending PyRIC}\label{sec:extending} +You may find that pyw does not offer some of the functionality you need. Using +libnl.py and/or libnl.io, additional functionality can be added to your program. + +\subsection{Porting C} +All Python ports of C header files can be found in the net directory. C Enums and +\#defines are ported using constants. C structs are ported using three Python +structures and the Python struct package: +\begin{enumerate} +\item a format string for packing and unpacking the struct +\item a constant specifying the size of the struct in bytes +\item a function taking the attributes of the struct as arguments and returning +a packed string +\end{enumerate} +Listing \ref{lst:cstruct} shows the C definition of the nlmsghdr found in netlink.h. + +\begin{lstlisting}[caption={C Struct nlmsghdr}, + label={lst:cstruct}, + language=C] +struct nlmsghdr { + __u32 nlmsg_len; + __u16 nlmsg_type; + __u16 nlmsg_flags; + __u32 nlmsg_seq; + __u32 nlmsg_pid; +}; +\end{lstlisting} + +And Listing \ref{lst:pstruct} shows the ported version in Python. + +\begin{lstlisting}[caption={Corresponding Python Definition}, + label={lst:pstruct}, + language=Python] +nl_nlmsghdr = "IHHII" +NLMSGHDRLEN = struct.calcsize(nl_nlmsghdr) +def nlmsghdr(mlen,nltype,flags,seq,pid): + return struct.pack(nl_nlmsghdr,NLMSGHDRLEN+mlen,nltype,flags,seq,pid) +\end{lstlisting} + +When using pyw, dealing with these structures is handled transparently by libnl.py +and libio.py. When extending or customizing pyw, a basic understanding of the +definitions in netlink\_h.py, genetlink\_h.py and if\_h.py. + +\subsection{Input/Output Control (ioctl)} +PyRIC provides more than just iw-related functions, it also implements functions +from ifconfig and iwconfig. These command line tools still use ioctl (or the proc +directory). For example, interfaces() reads from '/proc/net/dev' to retrieve all +system interfaces and winterfaces() use ioctl to check if a device is wireless. +Input/Output control calls have only been used when there was no viable alternative +and, it should not be necessary to have to add any further ioctl commands. If you +find that you need an ioctl related command, search through if\_h.py for the +appropriate structure and add it's definitions to ifreq. + +\subsection{Netlink and nl80211} +Documentation on Netlink, and nl80211 in particular, is so minimal as to be +neglible. The clusterfuck of code and lack of comments in the iw source tree +make it impossible to use as any sort of roadmap. Fortunately Thomas Graf's +site\cite{libnl} has excellent coverage of the libnl, the Netlink library. +Using this as a reference, a simple Netlink parser was put together. With +strace and the parser, Netlink messages could be dissected and analyzed. \\ + +\begin{appendices} +\section{API: pyw.py}\label{sec:pywapi} + +\subsection{Constants} +\begin{itemize} +\item \textbf{\_FAM80211ID\_}: Global netlink family id of nl80211. Do not touch +\item \textbf{IFTYPES}: redefined (from nl80211\_h.py) interface modes +\item \textbf{MNTRFLAGS}: redefined (from nl80211\_h.py) monitor mode flags +\end{itemize} + +\subsection{Objects/Classes} +\textbf{Card} A wrapper around a tuple +\texttt{t = (physical index,device name,interface index)} +which exposes the following properties through '.': +\begin{itemize} +\item \textbf{phy}: physical index +\item \textbf{dev}: device name +\item \textbf{idx}: interface index (ifindex) +\end{itemize} +Because the underlying Netlink calls will sometimes require the physical index, +sometimes the device name, and sometimes the ifindex, pyw functions accept a Card, +object. This allows callers to use pyw functions without having to remember which +identifier the function requires. However, in some cases the function requires +a dev or accepts both. See the next section on functions.\\ + +While callers could create their own Cards, it is recommend to use one of the following +\begin{itemize} +\item \textbf{pyw.getcard} returns a Card object from a given dev +\item \textbf{pyw.devinfo} returns the dict info where info['card'] is the Card +object. This function will take either a card or a dev +\item \textbf{pyw.devadd} returns a new Card object +\item \textbf{pyw.ifaces} returns a list of tuples t = (Card,mode) sharing the +same phy as a given dev +to do so. It is also recommended to periodically validate the Card. On some +cheaper usb wireless nics, there are periodic disconnects which results in a new +phy and ifindex. +\end{itemize} + +\subsection{Functions} +\begin{itemize} +\item interfaces(): (ifconfig), type: filesystem, returns list of all network dev +\item isinterface(dev): (ifconfig ) type: filesystem, check dev is an interface +\item winterfaces([iosock]): (iwconfig), type: ioctl, list wireless interfaces +\item iswireless(dev,[iosock]): (iwconfig ), type: ioctl, check dev is a +wireless interface +\item regget([nlsock]: (iw reg get), type: netlink, get regulatory domain +\item regset(rd,[nlsock]): (iw reg set ), type: netlink, set regulatory domain +to rd +\item getcard(dev,[nlsock]) (N/A), type: hybrid netlink and ioctl: get a Card +object for dev +\item macget(card,[iosock]): (ifconfig card.), type: ioctl get card's hw +address +\item macset(card,mac,[iosock]): (ifconfig card. hw ether ), type: +ioctl, set card's hw address to mac +\item txget(card,[iosock]): (iwconfig card. | grep Tx-Power card), type: +ioctl, get card's transmission power +\item up(card,[iosock]) (ifconfig card. up), type: ioctl, bring card up +\item down(card,[iosock]): (ifconfig card. down), type: ioctl, bring card +down +\item devstds(card,[iosock]): (iwconfig card. | grep IEEE), type: ioctl, get +list of card's 802.11 supported standards +\item validcard(card,[nlsock]): (N/A), type: (hyrbrid netlink and ioctl), verify +card is still valid +\item devinfo(card,[nlsock]): (iw dev card. info), type: netlink, get info +for dev +\item phyinfo(card,[nlsock]): (iw phy card. info), type: netlink, get info +for phy +\item ifaces(card,[nlsock]): (APX iw card.dev | grep phy\#), type: netlink, get all +cards (w/ modes) of interfaces sharing the same phy as card +\item chget(card,[nlsock]): (iw dev info | grep channelS), type: +netlink, get card's current channel (only works for cards in mode managed) +\item chset(card,ch,chw,[nlsock]): iw phy set channel ), +type: netlink, set card's current channel to ch with width chw +\item devmodes(card,[iosock]): (iw phy card.), type: netlink, get modes +supported by card +\item devadd(card,vnic,mode,[flags],[nlsock]): (iw phy card. interface add + type flags ), type: netlink, creates a new virtual interface +on card's phy with dev vdev, in mode and using flags. Note: flags are only supported +in when creating a monitor mode +\item devdel(card,[nlsock]): (iw card. del), type: netlink, deletes dev +\begin{itemize} +\item \_hex2mac\_(v): returns a ':' separated mac address from byte stream v +\item \_issetf\_(flags,flag): determines if flag is set in flags +\item \_setf\_(flags,flag): set flag in flags to on +\item \_unsetf\_(flags,flag): set flag in flags to off +\item \_familyid\_(nlsock): returns and sets the Netlink family id for nl80211, +only called once per module import +\item \_ifindex\_(dev,[iosock]): returns dev's ifindex +\item \_flagsget\_(dev,[iosock]): get's the dev's interface flags +\item \_flagsset\_(dev,flags,[iosock]): set's the dev's interface flags +\item \_iostub\_(fct,*argv): ioctl stub function, calls fct with parameter list argv +and an allocated ioctl socket +\item \_nlstub\_(fct,*argv): netlink stub function, calls fct with parameter list +argv and an allocated netlink socket +\end{itemize} +\end{itemize} + +\section{API: libnl.py}\label{sec:libnlapi} +Providing libnl similar functionality, libnl.py provides the interface between +pyw and the underlying nl80211 core. It relates similarily to libnl by providing +functions handling netlink messages and sockets and where possible uses similarly +named functions as those libnl to ease any transitions from C to PyRIC. However, +several liberties have been taken as libnl.py handles only nl80211 generic netlink +messages. + +\subsection{Constants} +\begin{itemize} +\item \textbf{BUFSZ} default rx and tx buffer size +\end{itemize} + +\subsection{Classes/Objects} +The two classes in libnl.py, NLSocket and GENLMsg, discussed in the following +sections subclass Python's builtin dict. This has been done IOT to take advantage +of dict's already existing functions and primarily their mutability and Python's +'pass by name' i.e. modifications in a function will be reflected in the caller. +This makes the classes very similar to the use C pointers to structs in libnl. + +\subsubsection{NLSocket} +NLSocket is a wrapper around a netlink socket which exposes the following +properties through '.': +\begin{itemize} +\item \textbf{sock}: the actual socket +\item \textbf{fd}: the socket's file descriptor (deprecated) +\item \textbf{tx}: size of the send buffer +\item \textbf{rx}: size of the receive buffer +\item \textbf{pid}: port id +\item \textbf{grpm}: group mask +\item \textbf{seq}: sequence number +\item \textbf{timeout}: socket timeout +\end{itemize} +and has the following methods: +\begin{itemize} +\item incr(): increment sequence number +\item send(pkt): sends pkt returning bytes sent +\item recv(): returns received message (will block unless timeout is set) +\item close(): close the socket +\end{itemize} + +NLSockets are created with nl\_socket\_alloc and must be freed with nl\_socket\_free. +See Section \ref{sec:libnlfct}. + +\subsubsection{GENLMsg} +GENLMsg is a wrapper around a dict with the following key->value pairs: +\begin{itemize} +\item \textbf{len}: total message length including the header +\item \textbf{nltype}: netlink type +\item \textbf{flags}: message flags +\item \textbf{seq}: seq. \# +\item \textbf{pid}: port id +\item \textbf{cmd}: generic netlink command +\item \textbf{attrs}: list of message attributes. Each attribute is a tuple t = +(attribute,value,datatype) where: +\begin{itemize} +\item \textbf{attribute}: netlink attribute type i.e. CTRL\_ATTR\_FAMILY\_ID +\item \textbf{value}: the unpacked attribute value +\item \textbf{datatype}: datatype of the attribute as defined in nelink\_h i.e. +NLA\_U8 +\end{itemize} +\end{itemize} +NOTE: as discussed below, on sending, the seq. \# and port id are overridden with +values of the netlink socket.\\ + +GENLMsg exposes the following properties: +\begin{itemize} +\item \textbf{len}: length of the message (get only) +\item \textbf{vers}: returns 1 (default version) (get only) +\item \textbf{nltype}: message content i.e. generic or nl80211 (get or set) +\item \textbf{flags}: message flags (get or set) +\item \textbf{seq}: current sequence \# (get or set) +\item \textbf{pid}: port id (get or set) +\item \textbf{cmd}: netlink command (get or set) +\item \textbf{attrs}: attribute list (get only) +\item \textbf{numattrs}: number of attributes (get only) +\end{itemize} + +GENLMsg has the following methods: +\begin{itemize} +\item \_\_repr\_\_(): returns a string representation useful for debugging +\item tostream(): returns a packed netlink message +\item nla\_put(v,a,t): appends the attribute a, with value v and datatype t to +the attribute list +\item nla\_put\_(v,a): eight specialize functions that append attribute +a with value v and type to the attribute list +\item nla\_putat(i,v,a,d): puts attribute a, with value v and datatype d at +index i in the attribute list. +\item nla\_pop(i): removes the attribute tuple at index i, returning the popped +tuple +\item nla\_find(a,value=True): returns the first attribute a. If value returns only +the value otherwise returns the attribute tuple +\item nla\_get(i,value=True): returns the attribute at index i. If value returns only +the value otherwise returns the attribute tuple +\item \_attrpack(a,v,d): (private) packs the attribute tuple +\end{itemize} + +There are two methods of creating a GENLMsg. Create a new message (to send) with nlmsg\_new and create a message from a received packet with nlmsg\_fromstream. These +are discussed below. + +\subsection{Functions}\label{sec:libnlfct} +\begin{itemize} +\item \textbf{Netlink Socket Related} +\begin{itemize} +\item nl\_socket\_alloc(pid,grps,seq,rx,tx,timeout): creates a netlink socket +with port id = pid, group mask = grps, initial seq. \# = seq, send and receive +buffer size = tx and rx respectively and blocking timeout = timeout +\item nl\_socket\_free(sock): closes the socket +\item nl\_socket\_pid(sock): (deprecated for NLSocket.pid) returns the port id +\item nl\_socket\_grpmask(sock): (deprecated for NLSocket.grpmask) returns the +group mask +\item nl\_sendmsg(sock,msg,override=False): sends the netlink msg over socket. +NOTE: NLSockets will automatically set the port id and seq. \# regardless of +their value in the message. If override is True, the message's pid and seq. \# +will be used instead. +\item nl\_recvmsg(sock): returns a GENLMsg or blocks unless the socket's timeout +is set. Should only be called once per every nl\_sendmsg. +\end{itemize} +\item \textbf{Netlink Message Related} +\begin{itemize} +\item nlmsg\_new(nltype=None,cmd=None,pid=None,flags=None,attrs=None): creates a +new GENLMsg with zero or more attributes defined. +\item nlmsg\_fromstream(stream): parses the message in stream returning the +corresponding GENLMsg +\item nla\_parse(msg,l,mtype,stream,idx): parses the attributes in stream appending +them to the attribute list of message where msg = the GENLMsg, l = the total length +of the message, mtype = the message content (i.e. netlink type) stream is the +original byte stream and idx is the index of the start of the attribute list +\item nla\_parse\_nested(nested): returns the list of packed nested attributes +extracted from the stream nested. Callers must unpack and parse the returned +attributes themselves +\item \_nla\_strip(v): (private) strips padding bytes from the end of v +\item \_maxbufsz\_(): returns the maximum allowable socket buffer size +\end{itemize} +\end{itemize} + +\section{Copyright and License}\label{sec:copy} +PYRIC: Python Radio Interface Controller v0.0.5\\ + +Copyright (C) 2016 Dale V. Patterson (wraith.wireless@yandex.com)\\ + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License\cite{gplv3} as published by the Free +Software Foundation, either version 3 of the License, or (at your option) any +later version.\\ + +Redistribution and use in source and binary forms, with or without modifications, +are permitted provided that the following conditions are met: +\begin{itemize} +\item Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. +\item Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. +\item Neither the name of the orginal author Dale V. Patterson nor the names of +any contributors may be used to endorse or promote products derived from this +software without specific prior written permission. +\end{itemize} + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT +OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\\ + +PyRIC is free software but use, duplication or disclosure by the United States +Government is subject to the restrictions set forth in DFARS 252.227-7014.\\ + +Use of this software is governed by all applicable federal, state and local +laws of the United States and subject to the laws of the country where you reside. +The copyright owner and contributors will be not be held liable for use of this +software in furtherance of or with intent to commit any fraudulent or other illegal +activities, or otherwise in violation of any applicable law, regulation or legal +agreement.\\ + +See http://www.gnu.org/licenses/licenses.html for a copy of the GNU General Public +License. +\end{appendices} + +\bibliographystyle{acm} +\bibliography{PyRIC} +%\addcontentsline{toc}{chapter}{Bibliography} + +\end{document} \ No newline at end of file diff --git a/pyric/lib/__init__.py b/pyric/lib/__init__.py new file mode 100644 index 0000000..8429e1e --- /dev/null +++ b/pyric/lib/__init__.py @@ -0,0 +1,47 @@ +#!/usr/bin/env python +""" lib lib subpackage + +Copyright (C) 2016 Dale V. Patterson (wraith.wireless@yandex.com) + +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 3 of the License, or (at your option) any later +version. + +Redistribution and use in source and binary forms, with or without modifications, +are permitted provided that the following conditions are met: + o Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + o Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + o Neither the name of the orginal author Dale V. Patterson nor the names of any + contributors may be used to endorse or promote products derived from this + software without specific prior written permission. + +lib subpackage + + lib 0.0.2 + desc: lib subpackage + includes: libnl 0.0.6 libio 0.0.1 + changes: + o added libio + o updated libnl + - added nlmsg_fromstream + - added NLSocket class + - added partial support of nested attributes + o added functionality to modify rx,tx and timeout after socket creation + o update libnl.py + - remove nla_* from GENLMsg stand-alone functions as this was my original + intent where the classes should only be 'placeholders', similar to C structs + and not full blow objects +""" + +__name__ = 'lib' +__license__ = 'GPLv3' +__version__ = '0.0.2' +__date__ = 'April 2016' +__author__ = 'Dale Patterson' +__maintainer__ = 'Dale Patterson' +__email__ = 'wraith.wireless@yandex.com' +__status__ = 'Development' \ No newline at end of file diff --git a/pyric/lib/libio.py b/pyric/lib/libio.py new file mode 100644 index 0000000..d35d74a --- /dev/null +++ b/pyric/lib/libio.py @@ -0,0 +1,80 @@ +#!/usr/bin/env python +""" libio provides ioctl socket & send/recv functionality + +Copyright (C) 2016 Dale V. Patterson (wraith.wireless@yandex.com) + +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 3 of the License, or (at your option) any later +version. + +Redistribution and use in source and binary forms, with or without modifications, +are permitted provided that the following conditions are met: + o Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + o Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + o Neither the name of the orginal author Dale V. Patterson nor the names of any + contributors may be used to endorse or promote products derived from this + software without specific prior written permission. + +Basic wrappers providing functionality for socket creation/deletion and send/recv +w.r.t ioctl calls + +""" + +__name__ = 'libio' +__license__ = 'GPLv3' +__version__ = '0.0.1' +__date__ = 'April 2016' +__author__ = 'Dale Patterson' +__maintainer__ = 'Dale Patterson' +__email__ = 'wraith.wireless@yandex.com' +__status__ = 'Development' + +import socket +import struct +import errno +from fcntl import ioctl +import pyric + +def io_socket_alloc(): + """ + create a socket for ioctl calls + :returns: an io socket + """ + return socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + +def io_socket_free(sock): + """ close the socket """ + try: + sock.close() + except Exception: # ignore all + pass + return None + +def io_transfer(iosock,flag,ifreq): + """ + send & recieve an ifreq struct + :param iosock: io socket + :param flag: sockios control call + :param ifreq: ifreq to send + :returns: an the ifreq struct recieved + """ + try: + return ioctl(iosock.fileno(),flag,ifreq) + except (AttributeError,struct.error) as e: + # either sock is not valid or a bad value passed to ifreq + # note: should not get these but just in case + if e.message.find('fileno'): raise pyric.error(errno.ENOTSOCK,"bad socket") + else: raise pyric.error(errno.EINVAL,e) + except IOError as e: + # generally device cannot be found sort but can also be + # permissions etc, catch and reraise as our own + if e.errno is not None: # just in case we have a none 2-tuple error + raise pyric.error(e.errno,e.strerror) + else: + raise pyric.error(pyric.EUNDEF,e) + except Exception as e: + raise pyric.error(pyric.EUNDEF,e.args[0]) \ No newline at end of file diff --git a/pyric/lib/libnl.py b/pyric/lib/libnl.py new file mode 100644 index 0000000..6a0a3d3 --- /dev/null +++ b/pyric/lib/libnl.py @@ -0,0 +1,658 @@ +#!/usr/bin/env python +""" libnl provides libnl(ish) functionality + +Copyright (C) 2016 Dale V. Patterson (wraith.wireless@yandex.com) + +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 3 of the License, or (at your option) any later +version. + +Redistribution and use in source and binary forms, with or without modifications, +are permitted provided that the following conditions are met: + o Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + o Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + o Neither the name of the orginal author Dale V. Patterson nor the names of any + contributors may be used to endorse or promote products derived from this + software without specific prior written permission. + +Relates similarily to libnl by providing functions handling netlink messages +and sockets. Where possible I have attempted to name the below functions the +same as would be found in libnl to ease any transitions. However, I have taken +liberties with the below as these functions only handle nl80211 generic netlink +messages. + +see http://www.carisma.slowglass.com/~tgr/libnl/doc/core.html + +Provides access to netlink sockets and messages in a manner similar to libnl. + +""" + +__name__ = 'libnl' +__license__ = 'GPLv3' +__version__ = '0.0.6' +__date__ = 'May 2016' +__author__ = 'Dale Patterson' +__maintainer__ = 'Dale Patterson' +__email__ = 'wraith.wireless@yandex.com' +__status__ = 'Development' + +from time import time +from os import getpid,strerror +import struct +import socket +from binascii import hexlify +import pyric, errno +import pyric.net.netlink_h as nlh +import pyric.net.genetlink_h as genlh +from pyric.net.policy import nla_datatype + +BUFSZ = 32768 # Generic default buffersize + +""" +NETLINK SOCKET +""" + +class NLSocket(dict): + """ + Wrapper around a Netlink socket. Exposes the following properties: (callable + by '.') + sock: socket, get only + fd: file descriptor, get only + pid: (local) port id, get/set + grpm: group mask, get/set + seq: seq. #, get/set + tx: tx buffer size, get only + rx: rx buffer size, get only + """ + def __new__(cls,d=None): + return super(NLSocket,cls).__new__(cls,dict({} if not d else d)) + + def __repr__(self): + """ :returns: description """ + fmt = "NLSocket(fd: {0}, pid: {1}, grpm: {2}, seq: {3}, tx: {4}, rx: {5})" + return fmt.format(self.fd,self.pid,self.grpm,self.seq,self.tx,self.rx) + + @property + def sock(self): return self['sock'] + + @property + def fd(self): return self['sock'].fileno() + + @property + def tx(self): return self['sock'].getsockopt(socket.SOL_SOCKET,socket.SO_SNDBUF) + + @tx.setter + def tx(self,v): + if v < 128 or v > _maxbufsz_(): + raise pyric.error(errno.EINVAL,"Invalid buffer size") + self['sock'].setsockopt(socket.SOL_SOCKET,socket.SO_SNDBUF,v) + + @property + def rx(self): return self['sock'].getsockopt(socket.SOL_SOCKET,socket.SO_RCVBUF) + + @rx.setter + def rx(self,v): + if v < 128 or v > _maxbufsz_(): + raise pyric.error(errno.EINVAL,"Invalid buffer size") + self['sock'].setsockopt(socket.SOL_SOCKET,socket.SO_RCVBUF,v) + + @property + def pid(self): return self['pid'] + + @pid.setter + def pid(self,v): + if v < 1: raise pyric.error(errno.EINVAL,"Invalid port id") + self['pid'] = v + + @property + def grpm(self): return self['grpm'] + + @grpm.setter + def grpm(self,v): self['grpm'] = v + + @property + def seq(self): return self['seq'] + + @seq.setter + def seq(self,v): + if v < 1: raise pyric.error(errno.EINVAL,"Invalid sequence number") + self['seq'] = v + + @property + def timeout(self): return self['sock'].gettimeout() + + @timeout.setter + def timeout(self,v): + if v and v < 0: raise pyric.error(errno.EINVAL,"Invalid timeout value") + self['sock'].settimeout(v) + + #### wrap socket functions + + def incr(self): + """ increments seq num """ + self['seq'] += 1 + + def send(self,pkt): + """ + send data + :param pkt: data to be sent + :returns: bytes sent + """ + return self['sock'].send(pkt) + + def recv(self): + """ :returns: msg from kernel """ + return self['sock'].recv(self.rx) + + def close(self): + """ closes the socket """ + if self['sock']: self['sock'].close() + self['sock'] = self['fid'] = None + self['pid'] = self['grpm'] = self['seq'] = None + self['rx'] = self['tx'] = None + +def nl_socket_alloc(pid=None,grps=0,seq=None,rx=None,tx=None,timeout=None): + """ + create a netlink socket + :param pid: port id + :param grps: multicast groups mask + :param seq: initial seq. # + :param rx: rx buffer size + :param tx: tx buffer size + :param timeout: time to block on socket + :returns: a NLSocket + NOTE: + per man socket, the kernel will double the specified rx/tx buffer size and + the min. size is 128 + """ + # set & validate paramaters + pid = pid or getpid() + int(time()) # allow multiple sockets on this host + if pid < 1: raise pyric.error(errno.EINVAL,"Invalid port id") + seq = seq or int(time()) + if seq < 1: raise pyric.error(errno.EINVAL,"Invalid sequence number") + rx = rx or BUFSZ + if rx < 128 or rx > _maxbufsz_(): raise pyric.error(errno.EINVAL,"Invalid rx size") + tx = tx or BUFSZ + if tx < 128 or tx > _maxbufsz_(): raise pyric.error(errno.EINVAL,"Invalid tx size") + + # create the socket and rturn it + try: + s = socket.socket(socket.AF_NETLINK,socket.SOCK_RAW,nlh.NETLINK_GENERIC) + s.setsockopt(socket.SOL_SOCKET,socket.SO_SNDBUF,tx) + s.setsockopt(socket.SOL_SOCKET,socket.SO_RCVBUF,rx) + s.settimeout(timeout) + s.bind((pid,grps)) + except socket.error as e: + raise pyric.error(e.errno,e.strerror) + return NLSocket({'sock':s,'tx':tx,'rx':rx,'pid':pid,'grpm':grps,'seq':seq}) + +def nl_socket_free(sock): + """ close the socket """ + try: + sock.close() + except AttributeError: # sock already closed + pass + return None + +def nl_socket_pid(sock): + """ :returns netlink socket's pid """ + return sock.pid + +def nl_socket_grpmask(sock): + """ :returns netlink socket's group mask """ + return sock.grpm + +def nl_sendmsg(sock,msg,override=False): + """ + sends msg to kernel + :param sock: netlink socket + :param msg: nlmsg stream + :param override: if True will keep the message's pid and seq. This can + be used for testing + """ + try: + # change the msg's pid & seq to that of the sockets prior to sending & + # set the ack flag - I can't figure how to tell in recv if the an ack was + # requested or not so I force an ACK here + if not override: + msg.pid = sock.pid + msg.seq = sock.seq + msg.flags = msg.flags | nlh.NLM_F_ACK + sent = sock.send(msg.tostream()) + if sent != msg.len: + raise pyric.error(errno.EBADMSG,"Message sent incomplete") + except socket.error as e: + raise pyric.error(errno.ECOMM, e) + except AttributeError: + raise pyric.error(errno.ENOTSOCK, "Invalid netlink socket") + +def nl_recvmsg(sock): + """ + :param sock: netlink socket + :returns: a GENLMsg received from the socket + """ + try: + # pull of the message and following ack message + # NOTE: nlmsg_fromstream will throw an exception if msg is an ack/nack + # catch it and test for ack. If it was an ack, return the success code + # otherwise, reraise it. If it wasn't an ack/nack, return the message + msg = nlmsg_fromstream(sock.recv()) + try: + _ = nlmsg_fromstream(sock.recv()) + except pyric.error as e: + if e.errno == nlh.NLE_SUCCESS: pass + else: raise + if sock.seq != msg.seq: + raise pyric.error(errno.EBADMSG,"seq. # out of order") + return msg + except socket.timeout: + raise pyric.error(pyric.EUNDEF,"socket timed out") + except socket.error as e: + raise pyric.error(errno.ENOTSOCK,e) + except pyric.error as e: + if e.errno == nlh.NLE_SUCCESS: return nlh.NLE_SUCCESS + raise # rethrow + finally: + # always increment the sequence # + sock.incr() + +""" +NETLINK MESSAGES + +generic netlink data exchanged between user and kernel space is a netlink message +of type NETLINK_GENERIC using the netlink attributes interface. Messages are in +the format: + + <------- NLMSG_ALIGN(hlen) ------> <---- NLMSG_ALIGN(len) ---> + +----------------------------+-----+---------------------+-----+ + | Header | Pad | Payload | Pad | + | struct nlmsghdr | | | | + +----------------------------+-----+---------------------+-----+ + + <-------- GENL_HDRLEN -------> <--- hdrlen --> + <------- genlmsg_len(ghdr) ------> + +------------------------+-----+---------------+-----+------------+ + | Generic Netlink Header | Pad | Family Header | Pad | Attributes | + | struct genlmsghdr | | | | | + +------------------------+-----+---------------+-----+------------+ + + <-------- nla_attr_size(payload) ---------> + +------------------+-----+------------------+-----+ + | Attribute Header | Pad | Payload | Pad | + +------------------+-----+------------------+-----+ + +Example: nlmsg for retrieving the family id of nl80211 + |<----------- nlmsghdr ---------->|gemsghdr|<-------- attr -------->| + | |< hdr >|<--- payload -->| + | 0 1 2 3 4 5 6 7| 0 1 2 3 4 5 6 7| 0 1 2 3 4 5 6 7| 0 1 2 3 4 5 6 7| + |2000000010000500|02000000626b0000|030100000c000200|6e6c383032313100| + +Netlink message components are aligned on boundaries of 4 +""" + +""" +The GENLMsg class. There are two methods of creating a GENLMsg: + 1) nlmsg_new -> create a new 'default' msg + 2) nlmsg_fromstream -> create a msg from a string + +NOTE: regardles of the message's specified port id & seq #, when sending they + will be set to that of the socket's port id & seq #. The can be set during + creation IOT facilitate testing etc +""" + +class GENLMsg(dict): + """ + A wrapper around dict for an underlying generic netlink message of nl80211 + family. Exposes the following properties: (callable by '.') + len: message length, get only + nltype: netlink type, get/set + flags: message flags, get/set + seq: seq. #, get/set + pid: port id, get/set + cmd: etlink command, get/set + attrs: message attributes get only + Each attributes is a tuple t = (attribute,value,datatype) + attribute: netlink type of attribute like CTRL_ATTR_FAMILY_ID + value: actual value (i.e. unpacked) + datatype: datatype of attribute value as defined in netlink_h i.e. NLA_U8 + and are sent in the order they are put on the attr list + """ + def __new__(cls,d=None): + return super(GENLMsg,cls).__new__(cls,dict({} if not d else d)) + + def __repr__(self): + fmt = "nlmsghdr(len={0},type={1},flags={2},seq={3},pid={4})\n" + ret = fmt.format(self.len,self.nltype,self.flags,self.seq,self.pid) + ret += "genlmsghdr(cmd={0})\n".format(self.cmd) + ret += "attributes:\n" + for i,(a,v,d) in enumerate(self.attrs): + if d == nlh.NLA_UNSPEC: + # getting character(s) in some bytestrings that cause the + # terminal to hang (why?) hexlify to avoid this + v = hexlify(v) + elif d == nlh.NLA_NESTED: + v = [hexlify(vi) for vi in v] + ret += "\t{0}: type={1},datatype={2}\n\tvalue={3}\n".format(i,a,d,v) + return ret + + #### PROPERTIES + + @property # length (inlcuding padding and headers) + def len(self): return len(self.tostream()) + + @property + def vers(self): return 1 + + @property + def nltype(self): return self['type'] + + @nltype.setter + def nltype(self,v): + if v < 0: raise pyric.error(errno.ERANGE,"nltype {0} is invalid".format(v)) + self['type'] = v + + @property + def flags(self): return self['flags'] + + @flags.setter + def flags(self,v): self['flags'] = v + + @property + def seq(self): return self['seq'] + + @seq.setter + def seq(self,v): + if v < 1: raise pyric.error(errno.ERANGE,"invalid seq. number") + self['seq'] = v + + @property + def pid(self): return self['pid'] + + @pid.setter + def pid(self,v): + if v < 1: raise pyric.error(errno.ERANGE,"invalid port id") + self['pid'] = v + + @property + def cmd(self): return self['cmd'] + + @cmd.setter + def cmd(self,v): + if v < 0: raise pyric.error(errno.ERANGE,"invalid cmd") + self['cmd'] = v + + @property + def attrs(self): return self['attrs'] + + @property + def numattrs(self): return len(self['attrs']) + + #### METHODS + + def tostream(self): + """ :returns packed netlink message """ + payload = genlh.genlmsghdr(self['cmd']) # nlhsghdr, genlmsghdr end at boundary of 4 + for attr,v,data in self['attrs']: + try: + payload += _attrpack_(attr,v,data) + except struct.error: + raise pyric.error(pyric.EUNDEF,"Packing {0} {1}".format(attr,v)) + return nlh.nlmsghdr(len(payload),self.nltype,self.flags,self.seq,self.pid) + payload + +def nlmsg_new(nltype=None,cmd=None,seq=None,pid=None,flags=None,attrs=None): + """ + :param nltype: message content + :param cmd: genetlink service type + :param seq: sequence number + :param pid: port id + :param flags: additional flags + :param attrs: attr list list of tuples t = (attribute,value,attr_datatype) + attribute = netlinke type of attribute like CTRL_ATTR_FAMILY_ID + value = actual value (i.e. unpacked) + attr_datatype = type of attribute value as defined in netlink_h i.e. NLA_U8 + :returns a GENLMsg + NOTE: + # version is hardcoded as 1 and len is calculated + """ + return GENLMsg({'type':nltype or nlh.NETLINK_GENERIC, + 'flags':flags or (nlh.NLM_F_REQUEST|nlh.NLM_F_ACK), + 'seq':seq or int(time()), + 'pid':pid or getpid(), + 'cmd':cmd or genlh.CTRL_CMD_UNSPEC, + 'attrs':attrs or []}) + +def nlmsg_fromstream(stream): + """ + create a GENLMsg from a stream + :param stream: packed binary data + :returns: a GENLMsg + """ + # parse out netlink/generic netlink headers + try: + l,t,fs,s,p = struct.unpack_from(nlh.nl_nlmsghdr,stream,0) + if t == nlh.NLMSG_ERROR or l == nlh.NLMSGACKLEN: + # have an (possible) ack/nack i.e. error msg + e = struct.unpack_from(nlh.nl_nlmsgerr,stream,nlh.NLMSGHDRLEN)[0] + # here is a big problem report NLE_* or errno? + raise pyric.error(abs(e),strerror(abs(e))) + c,_,_ = struct.unpack_from(genlh.genl_genlmsghdr,stream,nlh.NLMSGHDRLEN) + except struct.error as e: + raise pyric.error(pyric.EUNDEF,"error parsing headers: {0}".format(e)) + + # create a new message with hdr values then parse the attributes + msg = nlmsg_new(t,c,s,p,fs) + nla_parse(msg,l,t,stream,nlh.NLMSGHDRLEN + genlh.GENLMSGHDRLEN) + return msg + +def nla_parse(msg,l,mtype,stream,idx): + """ + parses attributes in stream, putting them in msg + :param msg: current message + :param l: total length of message + :param mtype: message content + :param stream: byte stream + :param idx: current index in stream + """ + # get policy family NOTE: cheating here, we know it's either generic or nl80211 + pol = 'ctrl_attr' if mtype == nlh.NETLINK_GENERIC else 'nl80211_attr' + attrlen = nlh.NLATTRHDRLEN # pull out these to avoid + attrhdr = nlh.nl_nlattrhdr # doing so in each iteration + + # eat the stream until the end + while idx < l: + a = atype = alen = None # shut pycharm up about unitialized variable + try: + alen,atype = struct.unpack_from(attrhdr,stream,idx) # get length, type + idx += attrlen # move to attr start + alen -= attrlen # attr length (w/ padding) + a = stream[idx:idx+alen] # attr value + dt = nla_datatype(pol,atype) # attr datatype + + # Note: we use unpack_from which will ignore the null bytes in numeric + # datatypes & for strings & unspec we just strip trailing null bytes + if dt == nlh.NLA_STRING or dt == nlh.NLA_UNSPEC: a = _nla_strip(a) + if dt == nlh.NLA_NESTED: a = nla_parse_nested(a) + elif dt == nlh.NLA_U8: a = struct.unpack_from("B",a,0)[0] + elif dt == nlh.NLA_U16: a = struct.unpack_from("H",a,0)[0] + elif dt == nlh.NLA_U32: a = struct.unpack_from("I",a,0)[0] + elif dt == nlh.NLA_U64: a = struct.unpack_from("Q",a,0)[0] + elif dt == nlh.NLA_FLAG: a = '' # flags should be 0 size + elif dt == nlh.NLA_MSECS: a = struct.unpack_from("Q",a,0)[0] + nla_put(msg,a,atype,dt) + except struct.error: + # append as Error, stripping null bytes + nla_put(msg,_nla_strip(a),atype,nlh.NLA_ERROR) + idx = nlh.NLMSG_ALIGN(idx + alen) # move index to next attr + +def nla_parse_nested(nested): + """ + :param nested: the nested attribute with attribute header removed + :returns: list of 'packed' nested attributes after length and padding are + stripped - Callers must parse these themselves + NOTE: experimental ATT still determining if nl80211 has taken some + propietary treament(s) of nested attributes or if this is how nested + attributes should be handled + + From nl80211.h + @NL80211_ATTR_SUPPORTED_IFTYPES: nested attribute containing all + supported interface types, each a flag attribute with the number + of the interface mode. + and from libnl (Thomas Graf) + When nesting attributes, the nested attributes are included as payload of + a container attribute. Attributes are nested by surrounding them with calls + to nla_nest_start() and nla_nest_end(). + + <-------- nla_attr_size(payload) ---------> + +------------------+-----+------------------+-----+ + | Attribute Header | Pad | Payload | Pad | + +------------------+-----+------------------+-----+ + + Looking at nl80211 nested attributes, it appears that inside the payload + there are no dataypes or attribute types, with each nested atrribute as: + + +--------+---------+------+-----+ + | Length | Payload | Null | Pad | + +--------+---------+------+-----+ + + where length is total length of the nested payload exluding the pad bytes. + """ + ns = [] + idx = 0 + l = len(nested) + while idx < l: + # first byte is the length, including this byte and one pad byte - does + # not include additional pad bytes for proper alignment + alen = struct.unpack_from('B',nested,idx)[0] + ns.append(nested[idx+1:idx+(alen-1)]) + idx = nlh.NLMSG_ALIGN(idx + alen) + return ns + +def _nla_strip(v): + """ + strips padding from v + :param v: value to strip + :returns: v w/o padding + **NOTE: Do not use on numeric attributes + """ + try: + for i,e in reversed(list(enumerate(v))): + if e != '\x00': return v[:i+1] + return v + except IndexError: + return v + +def nla_put(msg,v,a,d): + """ + append attribute to msg's attribute list + :param msg: GENLMsg + :param v: attribute value + :param a: attribute type + :param d: attribute datatype + """ + if d > nlh.NLA_TYPE_MAX: raise pyric.error(errno.ERANGE,"value type is invalid") + msg['attrs'].append((a,v,d)) + +# nla_put_* append data of specified datatype +def nla_put_unspec(msg,v,a): nla_put(msg,v,a,nlh.NLA_UNSPEC) +def nla_put_u8(msg,v,a): nla_put(msg,v,a,nlh.NLA_U8) +def nla_put_u16(msg,v,a): nla_put(msg,v,a,nlh.NLA_U16) +def nla_put_u32(msg,v,a): nla_put(msg,v,a,nlh.NLA_U32) +def nla_put_u64(msg,v,a): nla_put(msg,v,a,nlh.NLA_U64) +def nla_put_string(msg,v,a): nla_put(msg,v,a,nlh.NLA_STRING) +def nla_put_msecs(msg,v,a): nla_put(msg,v,a,nlh.NLA_MSECS) +def nla_put_nested(msg,v,a): nla_put(msg,v,a,nlh.NLA_NESTED) + +def nla_putat(msg,i,v,a,d): + """ + puts (overwrites) attribute at index i in msg's attr list + :param msg: GENLMsg + :param i: index to put attribute + :param v: attribute value + :param a: attribute type + :param d: attribute datatype + """ + if d > nlh.NLA_TYPE_MAX: raise pyric.error(errno.ERANGE,"invalid datatype") + msg['attrs'][i] = (a,v,d) + +def nla_pop(msg,i): + """ + pop and return the attr tuple at i in msg's attr list + :param msg: GENLMsg + :param i: index to pop + :returns: the 'popped' attribute + """ + attr = msg.attrs[i] + del msg['attrs'][i] + return attr + +def nla_find(msg,a,value=True): + """ + find the first attribute having type a in msg's attr list + :param msg: GENLMsg + :param a: attribute + :param value: {True=return attr. value only|False=return attr. triple} + :returns: first attribute found with a or None + """ + for t,v,d in msg.attrs: + if t == a: + if value: return v + else: return t,v,d + return None + +def nla_get(msg,i,value=True): + """ + get attribute at index i in msg's attribute list + :param msg: GENLMsg + :param i: index of desired attribute + :param value: {True=return attr. value only|False=return attr. triple} + :returns: attribute at i + """ + attr = msg.attrs[i] + if value: return attr[1] + else: return attr + +#### FILE PRIVATE #### + +def _attrpack_(a,v,d): + """ + :param a: attribute type + :param v: value to pack + :param d: datatype of value + :returns: packed attribute w/ padding if necessary + """ + attr = "" # appease PyCharm + if d == nlh.NLA_UNSPEC: attr = v + elif d == nlh.NLA_U8: attr = struct.pack("B",v) + elif d == nlh.NLA_U16: attr = struct.pack("H",v) + elif d == nlh.NLA_U32: attr = struct.pack("I",v) + elif d == nlh.NLA_U64: attr = struct.pack("Q",v) + elif d == nlh.NLA_STRING: attr = struct.pack("{0}sx".format(len(v)),v) + elif d == nlh.NLA_FLAG: attr = '' # a 0 sized attribute + elif d == nlh.NLA_MSECS: attr = struct.pack("Q",v) + elif d == nlh.NLA_NESTED: + attr = '' + for nested in v: + nlen = len(v) + 2 + nattr = struct.pack('B',nlen) + nested + '\x00' + nattr += struct.pack("{0}x".format(nlh.NLMSG_ALIGNBY(len(nattr)))) + attr += nattr + attr = nlh.nlattrhdr(len(attr),a) + attr + # this is nlmsg_padlen + attr += struct.pack("{0}x".format(nlh.NLMSG_ALIGNBY(len(attr)))) + return attr + +def _maxbufsz_(): + """ :returns: maximum allowable socket buffer size """ + fin = None + try: + fin = open('/proc/sys/net/core/rmem_max') + return int(fin.read().strip()) / 2 + except (IOError,ValueError): + # return a hardcoded value + return 2097152 + finally: + if fin: fin.close() \ No newline at end of file diff --git a/pyric/net/__init__.py b/pyric/net/__init__.py new file mode 100644 index 0000000..8a8c27a --- /dev/null +++ b/pyric/net/__init__.py @@ -0,0 +1,44 @@ +#!/usr/bin/env python +""" net + +Copyright (C) 2016 Dale V. Patterson (wraith.wireless@yandex.com) + +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 3 of the License, or (at your option) any later +version. + +Redistribution and use in source and binary forms, with or without modifications, +are permitted provided that the following conditions are met: + o Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + o Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + o Neither the name of the orginal author Dale V. Patterson nor the names of any + contributors may be used to endorse or promote products derived from this + software without specific prior written permission. + +Linux header ports for netlink et al. + + net 0.0.2 + desc: linux header ports + includes: /wireless genetlink_h 0.0.1 if_h 0.0.2 netlink_h 0.0.3 sockios_h 0.0.2 + policy 0.0.2 + changes: + o added attribute constants to nl80211_h + o added attributes.py to define nla_policies + o renamed attributes.py to policy.py to avoid confusion + o changed policies from list to dict + o removed nle_error related as we use python errno +""" + +__name__ = 'net' +__license__ = 'GPLv3' +__version__ = '0.0.2' +__date__ = 'April 2016' +__author__ = 'Dale Patterson' +__maintainer__ = 'Dale Patterson' +__email__ = 'wraith.wireless@yandex.com' +__status__ = 'Development' + diff --git a/pyric/net/genetlink_h.py b/pyric/net/genetlink_h.py new file mode 100644 index 0000000..4ef1fc5 --- /dev/null +++ b/pyric/net/genetlink_h.py @@ -0,0 +1,120 @@ +#!/usr/bin/env python + +""" genetlink_h.py: port of netlink.h public header +/* + * NETLINK Generic Netlink Family + * + * Authors: Jamal Hadi Salim + * Thomas Graf + * Johannes Berg + */ + +Copyright (C) 2016 Dale V. Patterson (wraith.wireless@yandex.com) + +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 3 of the License, or (at your option) any later +version. + +Redistribution and use in source and binary forms, with or without modifications, +are permitted provided that the following conditions are met: + o Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + o Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + o Neither the name of the orginal author Dale V. Patterson nor the names of any + contributors may be used to endorse or promote products derived from this + software without specific prior written permission. + +A port of genetlink.h to python. Includes as well the nla_policy for generic +netlink attributes. + +""" + +#__name__ = 'genetlink_h.py' +__license__ = 'GPLv3' +__version__ = '0.0.1' +__date__ = 'March 2016' +__author__ = 'Dale Patterson' +__maintainer__ = 'Dale Patterson' +__email__ = 'wraith.wireless@yandex.com' +__status__ = 'Production' + +import struct + +GENL_NAMSIZ = 16 # length of family name + +GENL_MIN_ID = 0x10 # hardcoded from netlink_h +GENL_MAX_ID = 1023 + +""" +struct genlmsghdr { + __u8 cmd; + __u8 version; + __u16 reserved; +}; +""" +genl_genlmsghdr = "BBH" +GENLMSGHDRLEN = struct.calcsize(genl_genlmsghdr) +def genlmsghdr(cmd,vers=1): + """ + create a generic netlink header + :param cmd: message type of genetlink service + :param vers: revision value for backward compatability + :returns: packed generic netlink header + """ + return struct.pack(genl_genlmsghdr,cmd,vers,0) + +#GENL_HDRLEN NLMSG_ALIGN(sizeof(struct genlmsghdr)) + +GENL_ADMIN_PERM = 0x01 +GENL_CMD_CAP_DO = 0x02 +GENL_CMD_CAP_DUMP = 0x04 +GENL_CMD_CAP_HASPOL = 0x08 + +# List of reserved static generic netlink identifiers: +GENL_ID_GENERATE = 0 +GENL_ID_CTRL = 0x10 # hardcoded from netlink_h +GENL_ID_VFS_DQUOT = GENL_ID_CTRL + 1 +GENL_ID_PMCRAID = GENL_ID_CTRL + 2 + + +#Controller +CTRL_CMD_UNSPEC = 0 +CTRL_CMD_NEWFAMILY = 1 +CTRL_CMD_DELFAMILY = 2 +CTRL_CMD_GETFAMILY = 3 +CTRL_CMD_NEWOPS = 4 +CTRL_CMD_DELOPS = 5 +CTRL_CMD_GETOPS = 6 +CTRL_CMD_NEWMCAST_GR = 7 +CTRL_CMD_DELMCAST_GRP = 8 +CTRL_CMD_GETMCAST_GRP = 9 # unused +__CTRL_CMD_MAX = 10 +CTRL_CMD_MAX = __CTRL_CMD_MAX - 1 + +CTRL_ATTR_UNSPEC = 0 +CTRL_ATTR_FAMILY_ID = 1 +CTRL_ATTR_FAMILY_NAME = 2 +CTRL_ATTR_VERSION = 3 +CTRL_ATTR_HDRSIZE = 4 +CTRL_ATTR_MAXATTR = 5 +CTRL_ATTR_OPS = 6 +CTRL_ATTR_MCAST_GROUPS = 7 +__CTRL_ATTR_MAX = 9 +CTRL_ATTR_MAX = __CTRL_ATTR_MAX - 1 + +CTRL_ATTR_OP_UNSPEC = 0 +CTRL_ATTR_OP_ID = 1 +CTRL_ATTR_OP_FLAGS = 2 +__CTRL_ATTR_OP_MAX = 3 +CTRL_ATTR_OP_MAX = __CTRL_ATTR_OP_MAX - 1 +nla_policy_attr_op = [] + +CTRL_ATTR_MCAST_GRP_UNSPEC = 0 +CTRL_ATTR_MCAST_GRP_NAME = 1 +CTRL_ATTR_MCAST_GRP_ID = 2 +__CTRL_ATTR_MCAST_GRP_MAX = 3 +CTRL_ATTR_MCAST_GRP_MAX = __CTRL_ATTR_MCAST_GRP_MAX - 1 +nla_policy_attr_mcast = [] \ No newline at end of file diff --git a/pyric/net/if_h.py b/pyric/net/if_h.py new file mode 100644 index 0000000..d981dc6 --- /dev/null +++ b/pyric/net/if_h.py @@ -0,0 +1,352 @@ +#!/usr/bin/env python + +""" sockios_h.py: definitions for INET interface module + +/* + * INET An implementation of the TCP/IP protocol suite for the LINUX + * operating system. INET is implemented using the BSD Socket + * interface as the means of communication with the user level. + * + * Global definitions for the INET interface module. + * + * Version: @(#)if.h 1.0.2 04/18/93 + * + * Authors: Original taken from Berkeley UNIX 4.3, (c) UCB 1982-1988 + * Ross Biro + * Fred N. van Kempen, + * + * 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. + */ + +Copyright (C) 2016 Dale V. Patterson (wraith.wireless@yandex.com) + +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 3 of the License, or (at your option) any later +version. + +Redistribution and use in source and binary forms, with or without modifications, +are permitted provided that the following conditions are met: + o Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + o Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + o Neither the name of the orginal author Dale V. Patterson nor the names of any + contributors may be used to endorse or promote products derived from this + software without specific prior written permission. + +A port of if.h (and iw_param from wireless.h) to python + + Additionally + 1) imports definitions from wireless_h to check if a nic is wireless and get + the tx-power + 2) defines the sockaddr struct from netint/in.h + +""" + +__name__ = 'if_h' +__license__ = 'GPLv3' +__version__ = '0.0.2' +__date__ = 'February 2016' +__author__ = 'Dale Patterson' +__maintainer__ = 'Dale Patterson' +__email__ = 'wraith.wireless@yandex.com' +__status__ = 'Production' + +import struct +import pyric.net.sockios_h as sioc + +IFNAMSIZ = 16 +IFALIASZ = 256 + +# Standard interface flags (netdevice->flags). +IFF_UP = 0x1 # interface is up +IFF_BROADCAST = 0x2 # broadcast address valid +IFF_DEBUG = 0x4 # turn on debugging +IFF_LOOPBACK = 0x8 # is a loopback net +IFF_POINTOPOINT = 0x10 # interface is has p-p link +IFF_NOTRAILERS = 0x20 # avoid use of trailers +IFF_RUNNING = 0x40 # interface RFC2863 OPER_UP +IFF_NOARP = 0x80 # no ARP protocol +IFF_PROMISC = 0x100 # receive all packets +IFF_ALLMULTI = 0x200 # receive all multicast packets +IFF_MASTER = 0x400 # master of a load balancer +IFF_SLAVE = 0x800 # slave of a load balancer +IFF_MULTICAST = 0x1000 # Supports multicast +IFF_PORTSEL = 0x2000 # can set media type +IFF_AUTOMEDIA = 0x4000 # auto media select active +IFF_DYNAMIC = 0x8000 # dialup device with changing addresses +IFF_LOWER_UP = 0x10000 # driver signals L1 up +IFF_DORMANT = 0x20000 # driver signals dormant +IFF_ECHO = 0x40000 # echo sent packets + +IFF_VOLATILE = IFF_LOOPBACK | IFF_POINTOPOINT | IFF_BROADCAST | IFF_ECHO | \ + IFF_MASTER | IFF_SLAVE | IFF_RUNNING | IFF_LOWER_UP | IFF_DORMANT + +# Private (from user) interface flags (netdevice->priv_flags). +IFF_802_1Q_VLAN = 0x1 # 802.1Q VLAN device. +IFF_EBRIDGE = 0x2 # Ethernet bridging device. +IFF_SLAVE_INACTIVE = 0x4 # bonding slave not the curr. active +IFF_MASTER_8023AD = 0x8 # bonding master, 802.3ad. +IFF_MASTER_ALB = 0x10 # bonding master, balance-alb. +IFF_BONDING = 0x20 # bonding master or slave +IFF_SLAVE_NEEDARP = 0x40 # need ARPs for validation +IFF_ISATAP = 0x80 # ISATAP interface (RFC4214) +IFF_MASTER_ARPMON = 0x100 # bonding master, ARP mon in use +IFF_WAN_HDLC = 0x200 # WAN HDLC device +IFF_XMIT_DST_RELEASE = 0x400 # dev_hard_start_xmit() is allowed to release skb->dst + +IFF_DONT_BRIDGE = 0x800 # disallow bridging this ether dev +IFF_DISABLE_NETPOLL = 0x1000 # disable netpoll at run-time +IFF_MACVLAN_PORT = 0x2000 # device used as macvlan port +IFF_BRIDGE_PORT = 0x4000 # device used as bridge port +IFF_OVS_DATAPATH = 0x8000 # device used as Open vSwitch datapath port +IFF_TX_SKB_SHARING = 0x10000 # The interface supports sharing skbs on transmit +IFF_UNICAST_FLT = 0x20000 # Supports unicast filtering +IFF_TEAM_PORT = 0x40000 # device used as team port +IFF_SUPP_NOFCS = 0x80000 # device supports sending custom FCS +IFF_LIVE_ADDR_CHANGE = 0x100000 # device supports hardware address change when it's running +IFF_MACVLAN = 0x200000 # Macvlan device + +IF_GET_IFACE = 0x0001 # for querying only +IF_GET_PROTO = 0x0002 + +# For definitions see hdlc.h +IF_IFACE_V35 = 0x1000 # V.35 serial interface +IF_IFACE_V24 = 0x1001 # V.24 serial interface +IF_IFACE_X21 = 0x1002 # X.21 serial interface +IF_IFACE_T1 = 0x1003 # T1 telco serial interface +IF_IFACE_E1 = 0x1004 # E1 telco serial interface +IF_IFACE_SYNC_SERIAL = 0x1005 # can't be set by software +IF_IFACE_X21D = 0x1006 # X.21 Dual Clocking (FarSite) + +# For definitions see hdlc.h +IF_PROTO_HDLC = 0x2000 # raw HDLC protocol +IF_PROTO_PPP = 0x2001 # PPP protocol +IF_PROTO_CISCO = 0x2002 # Cisco HDLC protocol +IF_PROTO_FR = 0x2003 # Frame Relay protocol +IF_PROTO_FR_ADD_PVC = 0x2004 # Create FR PVC +IF_PROTO_FR_DEL_PVC = 0x2005 # Delete FR PVC +IF_PROTO_X25 = 0x2006 # X.25 +IF_PROTO_HDLC_ETH = 0x2007 # raw HDLC, Ethernet emulation +IF_PROTO_FR_ADD_ETH_PVC = 0x2008 # Create FR Ethernet-bridged PVC +IF_PROTO_FR_DEL_ETH_PVC = 0x2009 # Delete FR Ethernet-bridged PVC +IF_PROTO_FR_PVC = 0x200A # for reading PVC status +IF_PROTO_FR_ETH_PVC = 0x200B +IF_PROTO_RAW = 0x200C # RAW Socket + +# RFC 2863 operational status +IF_OPER_UNKNOWN = 0 +IF_OPER_NOTPRESENT = 1 +IF_OPER_DOWN = 2 +IF_OPER_LOWERLAYERDOWN = 3 +IF_OPER_TESTING = 4 +IF_OPER_DORMANT = 5 +IF_OPER_UP = 6 + +# link modes +IF_LINK_MODE_DEFAULT = 0 +IF_LINK_MODE_DORMANT = 1 # limit upward transition to dormant + +#### Interface request structure used for socket +# ioctl's. All interface ioctl's must have parameter +# definitions which begin with ifr_name. The +# remainder may be interface specific. +# +#struct ifreq { +# +# union +# { +# char ifrn_name[IFNAMSIZ]; # if name, e.g. "en0" +# } ifr_ifrn; +# +# union { +# struct sockaddr ifru_addr; +# struct sockaddr ifru_dstaddr; +# struct sockaddr ifru_broadaddr; +# struct sockaddr ifru_netmask; +# struct sockaddr ifru_hwaddr; +# short ifru_flags; +# int ifru_ivalue; +# int ifru_mtu; +# struct ifmap ifru_map; +# char ifru_slave[IFNAMSIZ]; # Just fits the size +# char ifru_newname[IFNAMSIZ]; +# void * ifru_data; +# struct if_settings ifru_settings; +# } ifr_ifru; +#}; +# +# from wireless.h we build +#struct iw_param +#{ +# __s32 value; /* The value of the parameter itself */ +# __u8 fixed; /* Hardware should not use auto select */ +# __u8 disabled; /* Disable the feature */ +# __u16 flags; /* Various specifc flags (if any) */ +# to get the txpower and verify the presense of wireless extensions +#}; + +""" + We use packed strings to represent these stucts. The ifreq struct is defined by + the SOCKIOS_H constants, format strings, lengths and the function ifreq. Together + they can be used to get/set properties. +""" +# SOCKADDR DEFINITION +ARPHRD_ETHER = 1 # from net/if_arp.h sa_family ethernet +AF_UNSPEC = 0 # from socket.h sa_family unspecified +sa_addr = 'H6B' # sockaddr is {unsigned short sa_family,char [14] address} +def sockaddr(sa_family,sa_data): + """ + create a sockaddr + :param sa_family: address family + :param sa_data: protocal address (up to 14 bytes) + :returns: packed sockaddr + """ + # the address must be "prepended" with sa_family IOT follow the sockaddr struct + if sa_family == ARPHRD_ETHER: + vs = [sa_family] + vs.extend([int(x,16) for x in sa_data.split(':')]) + return struct.pack(sa_addr,*vs) # struct error caught at libio level + else: + raise AttributeError("sa_family {0} not supported".format(sa_family)) + +# IFREQ DEFINITION +ifr_name = '{0}s'.format(IFNAMSIZ) # formats for ifreq struct +ifr_flags = 'h' +ifr_ifindex = 'i' +ifr_iwname = '{0}s'.format(256-IFNAMSIZ) # dirty hack to get an unknown string back +ifr_iwtxpwr = 'iBBH' +IFNAMELEN = struct.calcsize(ifr_name) # lengths +IFHWADDRLEN = struct.calcsize(sa_addr) +IFFLAGLEN = struct.calcsize(ifr_flags) +IFIFINDEXLEN = struct.calcsize(ifr_ifindex) +IWNAMELEN = struct.calcsize(ifr_iwname) +IWTXPWRLEN = struct.calcsize(ifr_iwtxpwr) +def ifreq(ifrn,ifru=None,param=None): + """ + creates a 'packed' struct cooresponding loosely to the ifreq struct. Padded + bytes are added on all 'gets' otherwise the ioctl will only return the + number of bytes sent + :param ifrn: name of interface/nic + :param ifru: from SOCKIOS_H, defines what type of ifreq struct to pack + :param param: list of params If None, pad byes are added having the size of + the appropriate param. If a hwaddr, must be a sockaddr family & string of + form "XX:XX:XX:XX:XX:XX", if flags must be an integer (c short) or (int) + respectively + :returns: packed ifreq + """ + # pack the nic + try: + # NOTE: don't need to keep the name to 16 chars as struct does it for us + ifr = struct.pack(ifr_name,ifrn) + except struct.error: + raise AttributeError("ifr_ifrn (dev name) {0} is invalid".format(ifrn)) + + try: + if not ifru: pass # only pass the device name + elif ifru == sioc.SIOCGIFHWADDR: # get hwaddr + ifr += struct.pack('{0}x'.format(IFHWADDRLEN)) + elif ifru == sioc.SIOCSIFHWADDR: # set hwaddr + ifr += sockaddr(param[0],param[1]) + elif ifru == sioc.SIOCGIFFLAGS: # get flags + ifr += struct.pack('{0}x'.format(IFFLAGLEN)) + elif ifru == sioc.SIOCSIFFLAGS: # set flags + ifr += struct.pack(ifr_flags,param[0]) + elif ifru == sioc.SIOCGIFINDEX: # get if index + ifr += struct.pack('{0}x'.format(IFIFINDEXLEN)) + elif ifru == sioc.SIOCGIWNAME: # get iw name + ifr += struct.pack('{0}x'.format(IWNAMELEN)) + elif ifru == sioc.SIOCGIWTXPOW: # get tx pwr + ifr += struct.pack('{0}x'.format(IWTXPWRLEN)) + else: + raise AttributeError("ifru {0} not supported".format(ifru)) + except (TypeError,IndexError): + raise AttributeError("param is invalid") + + return ifr + +""" +If we use ioctl to get the current frequency, below should be the structure +we have to create to get the results back + +/* + * A frequency + * For numbers lower than 10^9, we encode the number in 'm' and + * set 'e' to 0 + * For number greater than 10^9, we divide it by the lowest power + * of 10 to get 'm' lower than 10^9, with 'm'= f / (10^'e')... + * The power of 10 is in 'e', the result of the division is in 'm'. + */ +struct iw_freq +{ + __s32 m; /* Mantissa */ + __s16 e; /* Exponent */ + __u8 i; /* List index (when in range struct) */ + __u8 flags; /* Flags (fixed/auto) */ +}; +""" + +""" +/* + * Device mapping structure. I'd just gone off and designed a + * beautiful scheme using only loadable modules with arguments + * for driver options and along come the PCMCIA people 8) + * + * Ah well. The get() side of this is good for WDSETUP, and it'll + * be handy for debugging things. The set side is fine for now and + * being very small might be worth keeping for clean configuration. + */ + +struct ifmap { + unsigned long mem_start; + unsigned long mem_end; + unsigned short base_addr; + unsigned char irq; + unsigned char dma; + unsigned char port; + # 3 bytes spare +}; +""" + +""" +struct if_settings { + unsigned int type; # Type of physical device or protocol + unsigned int size; # Size of the data allocated by the caller + union { + # {atm/eth/dsl}_settings anyone ? + raw_hdlc_proto *raw_hdlc; + cisco_proto *cisco; + fr_proto *fr; + fr_proto_pvc *fr_pvc; + fr_proto_pvc_info *fr_pvc_info; + + # interface settings + sync_serial_settings *sync; + te1_settings *te1; + } ifs_ifsu; +}; +""" + +""" +/* + * Structure used in SIOCGIFCONF request. + * Used to retrieve interface configuration + * for machine (useful for programs which + * must know all networks accessible). + */ + +struct ifconf { + int ifc_len; # size of buffer + union { + char *ifcu_buf; + struct ifreq *ifcu_req; + } ifc_ifcu; +}; +ifc_buf ifc_ifcu.ifcu_buf # buffer address +ifc_req ifc_ifcu.ifcu_req # array of structures +""" \ No newline at end of file diff --git a/pyric/net/netlink_h.py b/pyric/net/netlink_h.py new file mode 100644 index 0000000..8f853ff --- /dev/null +++ b/pyric/net/netlink_h.py @@ -0,0 +1,339 @@ +#!/usr/bin/env python + +""" netlink_h.py: port of netlink.h public header +/* + * netlink/netlink.h Netlink Interface + * + * 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 version 2.1 + * of the License. + * + * Copyright (c) 2003-2006 Thomas Graf + */ + +Copyright (C) 2016 Dale V. Patterson (wraith.wireless@yandex.com) + +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 3 of the License, or (at your option) any later +version. + +Redistribution and use in source and binary forms, with or without modifications, +are permitted provided that the following conditions are met: + o Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + o Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + o Neither the name of the orginal author Dale V. Patterson nor the names of any + contributors may be used to endorse or promote products derived from this + software without specific prior written permission. + +A port of netlink.h, netlink/attr.h netlink/errno.h to python + +""" + +# NOTE: get the below error when calling import netlink_h +#RuntimeWarning: Parent module 'netlink_h' not found while handling absolute import +# import struct +# unless I comment out the name +#__name__ = 'netlink_h.py' +__license__ = 'GPLv3' +__version__ = '0.0.3' +__date__ = 'March 2016' +__author__ = 'Dale Patterson' +__maintainer__ = 'Dale Patterson' +__email__ = 'wraith.wireless@yandex.com' +__status__ = 'Development' + +import struct + +NETLINK_ROUTE = 0 # Routing/device hook +NETLINK_UNUSED = 1 # Unused number +NETLINK_USERSOCK = 2 # Reserved for user mode socket protocols +NETLINK_FIREWALL = 3 # Unused number, formerly ip_queue +NETLINK_SOCK_DIAG = 4 # socket monitoring +NETLINK_NFLOG = 5 # netfilter/iptables ULOG +NETLINK_XFRM = 6 # ipsec +NETLINK_SELINUX = 7 # SELinux event notifications +NETLINK_ISCSI = 8 # Open-iSCSI +NETLINK_AUDIT = 9 # auditing +NETLINK_FIB_LOOKUP = 10 +NETLINK_CONNECTOR = 11 +NETLINK_NETFILTER = 12 # netfilter subsystem +NETLINK_IP6_FW = 13 +NETLINK_DNRTMSG = 14 # DECnet routing messages +NETLINK_KOBJECT_UEVENT = 15 # Kernel messages to userspace +NETLINK_GENERIC = 16 +#leave room for NETLINK_DM (DM Events) +NETLINK_SCSITRANSPORT = 18 # SCSI Transports +NETLINK_ECRYPTFS = 19 +NETLINK_RDMA = 20 +NETLINK_CRYPTO = 21 # Crypto layer +__NETLINK_TYPE_MAX = 22 +NETLINK_TYPE_MAX = __NETLINK_TYPE_MAX - 1 + +NETLINK_INET_DIAG = NETLINK_SOCK_DIAG + +MAX_LINKS = 32 + +""" +struct sockaddr_nl { + __kernel_sa_family_t nl_family; /* AF_NETLINK */ + unsigned short nl_pad; /* zero */ + __u32 nl_pid; /* port ID */ + __u32 nl_groups; /* multicast groups mask */ +}; +""" + +""" +struct nlmsghdr { + __u32 nlmsg_len; /* Length of message including header */ + __u16 nlmsg_type; /* Message content */ + __u16 nlmsg_flags; /* Additional flags */ + __u32 nlmsg_seq; /* Sequence number */ + __u32 nlmsg_pid; /* Sending process port ID */ +}; +""" +nl_nlmsghdr = "IHHII" +NLMSGHDRLEN = struct.calcsize(nl_nlmsghdr) +def nlmsghdr(mlen,nltype,flags,seq,pid): + """ + create a nlmsghdr + :param mlen: length of message + :param nltype: message content + :param flags: additional flags + :param seq: sequence number + :param pid: process port id + :returns: packed netlink msg header + """ + return struct.pack(nl_nlmsghdr,NLMSGHDRLEN+mlen,nltype,flags,seq,pid) + +# Flags values +NLM_F_REQUEST = 1 # It is request message. +NLM_F_MULTI = 2 # Multipart message, terminated by NLMSG_DONE +NLM_F_ACK = 4 # Reply with ack, with zero or error code +NLM_F_ECHO = 8 # Echo this request +NLM_F_DUMP_INTR = 16 # Dump was inconsistent due to sequence change + +# Modifiers to GET request +NLM_F_ROOT = 0x100 # specify tree root +NLM_F_MATCH = 0x200 # return all matching +NLM_F_ATOMIC = 0x400 # atomic GET +NLM_F_DUMP = (NLM_F_ROOT|NLM_F_MATCH) + +# Modifiers to NEW request +NLM_F_REPLACE = 0x100 # Override existing +NLM_F_EXCL = 0x200 # Do not touch, if it exists +NLM_F_CREATE = 0x400 # Create, if it does not exist +NLM_F_APPEND = 0x800 # Add to end of list + +""" +/* + 4.4BSD ADD NLM_F_CREATE|NLM_F_EXCL + 4.4BSD CHANGE NLM_F_REPLACE + + True CHANGE NLM_F_CREATE|NLM_F_REPLACE + Append NLM_F_CREATE + Check NLM_F_EXCL + */ +""" + +# Most netlink protocols enforce a strict alignment policy for all boundries. +# The alignment value is defined by NLMSG_ALIGNTO and is fixed to 4 bytes. +# Therefore all netlink message headers, begin of payload sections, protocol +# specific headers, and attribute sections must start at an offset which is a +# multiple of NLMSG_ALIGNTO. +# <----------- nlmsg_total_size(len) ------------> +# <----------- nlmsg_size(len) ------------> +# +-------------------+- - -+- - - - - - - - +- - -+-------------------+- - - +# | struct nlmsghdr | Pad | Payload | Pad | struct nlsmghdr | +# +-------------------+- - -+- - - - - - - - +- - -+-------------------+- - - +# <---- NLMSG_HDRLEN -----> <- NLMSG_ALIGN(len) -> <---- NLMSG_HDRLEN --- +NLMSG_ALIGNTO = 4 +def NLMSG_ALIGN(l): return (l+NLMSG_ALIGNTO-1) & ~(NLMSG_ALIGNTO-1) +def NLMSG_LENGTH(l): return l+NLMSGHDRLEN +def NLMSG_SPACE(l): return NLMSG_ALIGN(NLMSG_LENGTH(l)) +def NLMSG_ALIGNBY(l): return NLMSG_ALIGN(l) - l +# still working the below out +#NLMSG_DATA(nlh) ((void*)(((char*)nlh) + NLMSGHDRLEN)) +#NLMSG_NEXT(hl,len) ((len) -= NLMSG_ALIGN((nlh)->nlmsg_len), \ +# (struct nlmsghdr*)(((char*)(nlh)) + NLMSG_ALIGN((nlh)->nlmsg_len))) +#NLMSG_OK(nlh,len) ((len) >= (int)sizeof(struct nlmsghdr) && \ +# (nlh)->nlmsg_len >= sizeof(struct nlmsghdr) && \ +# (nlh)->nlmsg_len <= (len)) +#NLMSG_PAYLOAD(nlh,len) ((nlh)->nlmsg_len - NLMSG_SPACE((len))) + +NLMSG_NOOP = 0x1 # Nothing. +NLMSG_ERROR = 0x2 # Error +NLMSG_DONE = 0x3 # End of a dump +NLMSG_OVERRUN = 0x4 # Data lost + +NLMSG_MIN_TYPE = 0x10 # < 0x10: reserved control messages + +""" +struct nlmsgerr { + int error; + struct nlmsghdr msg; +}; +""" +nl_nlmsgerr = "hIHHII" +NLMSGERRLEN = struct.calcsize(nl_nlmsgerr) +NLMSGACKLEN = NLMSGHDRLEN + NLMSGERRLEN # this is size of an error or ack message +def nlmsgerr(error,mlen,nltype,flags,seq,pid): + """ + create a nlmsgerr + NOTE: the function itself is here for illustrative purposes - users will + only need the format string above to unpack these + :param error: error code + :param mlen: length of header + :param nltype: message content + :param flags: additional flags + :param seq: sequence number + :param pid: process port id + :returns: packed netlink msg error + """ + return struct.pack(nl_nlmsgerr,error,mlen,nltype,flags,seq,pid) + +NETLINK_ADD_MEMBERSHIP = 1 +NETLINK_DROP_MEMBERSHIP = 2 +NETLINK_PKTINFO = 3 +NETLINK_BROADCAST_ERROR = 4 +NETLINK_NO_ENOBUFS = 5 +NETLINK_RX_RING = 6 +NETLINK_TX_RING = 7 + +""" +struct nl_pktinfo { + __u32 group; +}; +""" + +""" +struct nl_mmap_req { + unsigned int nm_block_size; + unsigned int nm_block_nr; + unsigned int nm_frame_size; + unsigned int nm_frame_nr; +}; +""" + +""" +struct nl_mmap_hdr { + unsigned int nm_status; + unsigned int nm_len; + __u32 nm_group; + /* credentials */ + __u32 nm_pid; + __u32 nm_uid; + __u32 nm_gid; +}; +""" + +# nume nl_nmap_status +NL_MMAP_STATUS_UNUSED = 0 +NL_MMAP_STATUS_RESERVED = 1 +NL_MMAP_STATUS_VALID = 2 +NL_MMAP_STATUS_COPY = 3 +NL_MMAP_STATUS_SKIP = 4 + +#NL_MMAP_MSG_ALIGNMENT NLMSG_ALIGNTO +#NL_MMAP_MSG_ALIGN(sz) __ALIGN_KERNEL(sz, NL_MMAP_MSG_ALIGNMENT) +#NL_MMAP_HDRLEN NL_MMAP_MSG_ALIGN(sizeof(struct nl_mmap_hdr)) + +NET_MAJOR = 36 # Major 36 is reserved for networking + +NETLINK_UNCONNECTED = 0 +NETLINK_CONNECTED = 1 + +""" +/* +* netlink/attr.h Netlink Attributes + * + * 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 version 2.1 + * of the License. + * + * Copyright (c) 2003-2013 Thomas Graf + * + * <------- NLA_HDRLEN ------> <-- NLA_ALIGN(payload)--> + * +---------------------+- - -+- - - - - - - - - -+- - -+ + * | Header | Pad | Payload | Pad | + * | (struct nlattr) | ing | | ing | + * +---------------------+- - -+- - - - - - - - - -+- - -+ + * <-------------- nlattr->nla_len --------------> + */ +""" + +# Attribute Datatypes +NLA_ERROR = -1 # my own -> failed to unpack attribute, treat as unspec +NLA_UNSPEC = 0 # Unspecified type, binary data chunk +NLA_U8 = 1 # 8 bit integer +NLA_U16 = 2 # 16 bit integer +NLA_U32 = 3 # 32 bit integer +NLA_U64 = 4 # 64 bit integer +NLA_STRING = 5 # NUL terminated character string +NLA_FLAG = 6 # Flag +NLA_MSECS = 7 # Micro seconds (64bit) +NLA_NESTED = 8 # Nested attributes +__NLA_TYPE_MAX = 9 +NLA_TYPE_MAX = __NLA_TYPE_MAX - 1 + +""" +struct nlattr { + __u16 nla_len; # length of attribute + nlattr size + __u16 nla_type; +}; +""" +nl_nlattrhdr = "HH" +NLATTRHDRLEN = struct.calcsize(nl_nlattrhdr) +def nlattrhdr(alen,atype): + """ + create a nlattr + :param alen: length of attribute + :param atype: type of attribute + return packed netlink attribute + """ + return struct.pack(nl_nlattrhdr,alen+NLATTRHDRLEN,atype) + +""" +/* + * nla_type (16 bits) + * +---+---+-------------------------------+ + * | N | O | Attribute Type | + * +---+---+-------------------------------+ + * N := Carries nested attributes + * O := Payload stored in network byte order + * + * Note: The N and O flag are mutually exclusive. + */ +""" +NLA_F_NESTED = (1 << 15) +NLA_F_NET_BYTEORDER = (1 << 14) +NLA_TYPE_MASK = ~(NLA_F_NESTED | NLA_F_NET_BYTEORDER) + +#NLA_ALIGNTO = 4 +#NLA_ALIGN(len) = (((len) + NLA_ALIGNTO - 1) & ~(NLA_ALIGNTO - 1)) +#NLA_HDRLEN = ((int) NLA_ALIGN(sizeof(struct nlattr))) + +# defined error codes +""" + For ease of use, I define netlink errors (netlink/errno.h) here + +/* + * netlink/errno.h Error Numbers + * + * 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 version 2.1 + * of the License. + * + * Copyright (c) 2008 Thomas Graf + */ +""" +# only use success and failure -> using errno for other error numbers +NLE = ['Success','Unspecified failure'] +NLE_SUCCESS = 0 +NLE_FAILURE = 1 \ No newline at end of file diff --git a/pyric/net/policy.py b/pyric/net/policy.py new file mode 100644 index 0000000..df4df7e --- /dev/null +++ b/pyric/net/policy.py @@ -0,0 +1,87 @@ +#!/usr/bin/env python +""" attributes defines netlink attribute policies and functions. + +Copyright (C) 2016 Dale V. Patterson (wraith.wireless@yandex.com) + +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 3 of the License, or (at your option) any later +version. + +Redistribution and use in source and binary forms, with or without modifications, +are permitted provided that the following conditions are met: + o Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + o Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + o Neither the name of the orginal author Dale V. Patterson nor the names of any + contributors may be used to endorse or promote products derived from this + software without specific prior written permission. + +For lack of a better place to put these, this defines attribute datatypes from +genetlink.h and imports those defined in nl80211_c. + +NOTE: I only use the datatype ignoring minlength, maxlength + +""" + +__name__ = 'attributes' +__license__ = 'GPLv3' +__version__ = '0.0.2' +__date__ = 'April 2016' +__author__ = 'Dale Patterson' +__maintainer__ = 'Dale Patterson' +__email__ = 'wraith.wireless@yandex.com' +__status__ = 'Development' + +import pyric.net.netlink_h as nlh +import pyric.net.genetlink_h as genlh +import pyric.net.wireless.nl80211_c as nl80211c + +def nla_datatype(policy,attr): + """ + determines the appropriate attribute datatype as found in policy + :param policy: policy name + :param attr: attribute type + :returns: a datatype as specified in netlink_h + NOTE: will return NLA_UNSPEC if given attr can not be found in policy + """ + try: + return nla_dts[policy][attr] + except (KeyError,IndexError): + return nlh.NLA_UNSPEC + +# map string names to datatype lists +nla_dts = {} + +#### CTRL_ATTR_* +nla_dts["ctrl_attr"] = {genlh.CTRL_ATTR_UNSPEC:nlh.NLA_UNSPEC, + genlh.CTRL_ATTR_FAMILY_ID:nlh.NLA_U16, + genlh.CTRL_ATTR_FAMILY_NAME:nlh.NLA_STRING, + genlh.CTRL_ATTR_VERSION:nlh.NLA_U32, + genlh.CTRL_ATTR_HDRSIZE:nlh.NLA_U32, + genlh.CTRL_ATTR_MAXATTR:nlh.NLA_U32, + genlh.CTRL_ATTR_OPS:nlh.NLA_NESTED, + genlh.CTRL_ATTR_MCAST_GROUPS:nlh.NLA_NESTED} + +#### CTRL_ATTR_OP_* +nla_dts["ctrl_attr_op"] = {genlh.CTRL_ATTR_OP_UNSPEC:nlh.NLA_UNSPEC, + genlh.CTRL_ATTR_OP_ID:nlh.NLA_U32, + genlh.CTRL_ATTR_OP_FLAGS:nlh.NLA_U32} + +#### CTRL_ATTR_MCAST_* +nla_dts["ctrl_attr_mcast"] = {genlh.CTRL_ATTR_MCAST_GRP_UNSPEC:nlh.NLA_UNSPEC, + genlh.CTRL_ATTR_MCAST_GRP_NAME:nlh.NLA_STRING, + genlh.CTRL_ATTR_MCAST_GRP_ID:nlh.NLA_U32} + +nla_dts["nl80211_attr"] = nl80211c.nl80211_policy + +# ATT we do include the below +#nla_dts["nl80211_key"] = nl80211c.nl80211_key_policy +#nla_dts["nl80211_wowlan_trig"] = nl80211_wowlan_trig_policy +#nla_dts["nl80211_wowlan_tcp"] = nl80211_wowlan_tcp_policy +#nla_dts["nl80211_coalesce"] = nl80211_coalesce_policy +#nla_dts["nl80211_rekey"] = nl80211_rekey_policy +#nla_dts["nl80211_match"] = nl80211_match_policy +#nla_dts["nl80211_plan"] = nl80211_plan_policy \ No newline at end of file diff --git a/pyric/net/sockios_h.py b/pyric/net/sockios_h.py new file mode 100644 index 0000000..649d3a1 --- /dev/null +++ b/pyric/net/sockios_h.py @@ -0,0 +1,153 @@ +#!/usr/bin/env python + +""" sockios_h.py: definitions of the socket-level I/O control calls. + +A port of sockios.h (and two constants from wireless.h) to python +/* + * INET An implementation of the TCP/IP protocol suite for the LINUX + * operating system. INET is implemented using the BSD Socket + * interface as the means of communication with the user level. + * + * Definitions of the socket-level I/O control calls. + * + * Version: @(#)sockios.h 1.0.2 03/09/93 + * + * Authors: Ross Biro + * Fred N. van Kempen, + * + * 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. + */ + +Copyright (C) 2016 Dale V. Patterson (wraith.wireless@yandex.com) + +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 3 of the License, or (at your option) any later +version. + +Redistribution and use in source and binary forms, with or without modifications, +are permitted provided that the following conditions are met: + o Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + o Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + o Neither the name of the orginal author Dale V. Patterson nor the names of any + contributors may be used to endorse or promote products derived from this + software without specific prior written permission. + +Most of these constants are not used but are left for possible future use. + +""" + +__name__ = 'sockios_h' +__license__ = 'GPLv3' +__version__ = '0.0.2' +__date__ = 'February 2016' +__author__ = 'Dale Patterson' +__maintainer__ = 'Dale Patterson' +__email__ = 'wraith.wireless@yandex.com' +__status__ = 'Production' + +# Linux-specific socket ioctls +#SIOCINQ = FIONREAD +#SIOCOUTQ = TIOCOUTQ # output queue size (not sent + not acked) + +# Routing table calls +SIOCADDRT = 0x890B # add routing table entry +SIOCDELRT = 0x890C # delete routing table entry +SIOCRTMSG = 0x890D # call to routing system + +# Socket configuration controls from wireless.h +SIOCGIWNAME = 0x8B01 # get name (standards can be retrieved here) +SIOCGIWTXPOW = 0x8B27 # get transmit power +SIOCGIWFREQ = 0x8B05 # get frequency + +# Socket configuration controls +SIOCGIFNAME = 0x8910 # get iface name +SIOCSIFLINK = 0x8911 # set iface channel +SIOCGIFCONF = 0x8912 # get iface list +SIOCGIFFLAGS = 0x8913 # get flags +SIOCSIFFLAGS = 0x8914 # set flags +SIOCGIFADDR = 0x8915 # get PA address +SIOCSIFADDR = 0x8916 # set PA address +SIOCGIFDSTADDR = 0x8917 # get remote PA address +SIOCSIFDSTADDR = 0x8918 # set remote PA address +SIOCGIFBRDADDR = 0x8919 # get broadcast PA address +SIOCSIFBRDADDR = 0x891a # set broadcast PA address +SIOCGIFNETMASK = 0x891b # get network PA mask +SIOCSIFNETMASK = 0x891c # set network PA mask +SIOCGIFMETRIC = 0x891d # get metric +SIOCSIFMETRIC = 0x891e # set metric +SIOCGIFMEM = 0x891f # get memory address (BSD) +SIOCSIFMEM = 0x8920 # set memory address (BSD) +SIOCGIFMTU = 0x8921 # get MTU size +SIOCSIFMTU = 0x8922 # set MTU size +SIOCSIFNAME = 0x8923 # set interface name +SIOCSIFHWADDR = 0x8924 # set hardware address +SIOCGIFENCAP = 0x8925 # get/set encapsulations +SIOCSIFENCAP = 0x8926 +SIOCGIFHWADDR = 0x8927 # Get hardware address +SIOCGIFSLAVE = 0x8929 # Driver slaving support +SIOCSIFSLAVE = 0x8930 +SIOCADDMULTI = 0x8931 # Multicast address lists +SIOCDELMULTI = 0x8932 +SIOCGIFINDEX = 0x8933 # name -> if_index mapping +SIOGIFINDEX = SIOCGIFINDEX # misprint compatibility :-) +SIOCSIFPFLAGS = 0x8934 # set/get extended flags set +SIOCGIFPFLAGS = 0x8935 +SIOCDIFADDR = 0x8936 # delete PA address +SIOCSIFHWBROADCAST = 0x8937 # set hardware broadcast addr +SIOCGIFCOUNT = 0x8938 # get number of devices +SIOCGIFBR = 0x8940 # Bridging support +SIOCSIFBR = 0x8941 # Set bridging options +SIOCGIFTXQLEN = 0x8942 # Get the tx queue length +SIOCSIFTXQLEN = 0x8943 # Set the tx queue length +SIOCETHTOOL = 0x8946 # Ethtool interface +SIOCGMIIPHY = 0x8947 # Get address of MII PHY in use +SIOCGMIIREG = 0x8948 # Read MII PHY register. +SIOCSMIIREG = 0x8949 # Write MII PHY register. +SIOCWANDEV = 0x894A # get/set netdev parameters +SIOCOUTQNSD = 0x894B # output queue size (not sent only) + +# ARP cache control calls +SIOCDARP = 0x8953 # delete ARP table entry +SIOCGARP = 0x8954 # get ARP table entry +SIOCSARP = 0x8955 # set ARP table entry + +# RARP cache control calls +SIOCDRARP = 0x8960 # delete RARP table entry +SIOCGRARP = 0x8961 # get RARP table entry +SIOCSRARP = 0x8962 # set RARP table entry + +# Driver configuration calls +SIOCGIFMAP = 0x8970 # Get device parameters +SIOCSIFMAP = 0x8971 # Set device parameters + +# DLCI configuration calls +SIOCADDDLCI = 0x8980 # Create new DLCI device +SIOCDELDLCI = 0x8981 # Delete DLCI device + +SIOCGIFVLAN = 0x8982 # 802.1Q VLAN support +SIOCSIFVLAN = 0x8983 # Set 802.1Q VLAN options + +# bonding calls +SIOCBONDENSLAVE = 0x8990 # enslave a device to the bond +SIOCBONDRELEASE = 0x8991 # release a slave from the bond +SIOCBONDSETHWADDR = 0x8992 # set the hw addr of the bond +SIOCBONDSLAVEINFOQUERY = 0x8993 # rtn info about slave state +SIOCBONDINFOQUERY = 0x8994 # rtn info about bond state +SIOCBONDCHANGEACTIVE = 0x8995 # update to a new active slave + +# bridge calls +SIOCBRADDBR = 0x89a0 # create new bridge device +SIOCBRDELBR = 0x89a1 # remove bridge device +SIOCBRADDIF = 0x89a2 # add interface to bridge +SIOCBRDELIF = 0x89a3 # remove interface from bridge + +# hardware time stamping: parameters in linux/net_tstamp.h +SIOCSHWTSTAMP = 0x89b0 # set and get config +SIOCGHWTSTAMP = 0x89b1 # get config \ No newline at end of file diff --git a/pyric/net/wireless/__init__.py b/pyric/net/wireless/__init__.py new file mode 100644 index 0000000..89464f2 --- /dev/null +++ b/pyric/net/wireless/__init__.py @@ -0,0 +1,39 @@ +#!/usr/bin/env python +""" net +Copyright (C) 2016 Dale V. Patterson (wraith.wireless@yandex.com) + +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 3 of the License, or (at your option) any later +version. + +Redistribution and use in source and binary forms, with or without modifications, +are permitted provided that the following conditions are met: + o Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + o Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + o Neither the name of the orginal author Dale V. Patterson nor the names of any + contributors may be used to endorse or promote products derived from this + software without specific prior written permission. + +Linux header port nl80211.h, .c + + net 0.0.1 + desc: linux port of nl80211.h + includes: nl80211_h 0.0.2 nl80211_c 0.0.1 + changes: + o added nl80211_c to handle attribute policies + +""" + +__name__ = 'wireless' +__license__ = 'GPLv3' +__version__ = '0.0.1' +__date__ = 'April 2016' +__author__ = 'Dale Patterson' +__maintainer__ = 'Dale Patterson' +__email__ = 'wraith.wireless@yandex.com' +__status__ = 'Development' + diff --git a/pyric/net/wireless/nl80211_c.py b/pyric/net/wireless/nl80211_c.py new file mode 100644 index 0000000..d5e882c --- /dev/null +++ b/pyric/net/wireless/nl80211_c.py @@ -0,0 +1,285 @@ +#!/usr/bin/env python + +""" nl80211_c.py: nl80211 attribute policy definitions + +Copyright (C) 2016 Dale V. Patterson (wraith.wireless@yandex.com) + +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 3 of the License, or (at your option) any later +version. + +Redistribution and use in source and binary forms, with or without modifications, +are permitted provided that the following conditions are met: + o Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + o Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + o Neither the name of the orginal author Dale V. Patterson nor the names of any + contributors may be used to endorse or promote products derived from this + software without specific prior written permission. + +A port of nla_policy definitions found in nl80211.c to python + +""" + +__name__ = 'nl80211_c' +__license__ = 'GPLv3' +__version__ = '0.0.3' +__date__ = 'April 2016' +__author__ = 'Dale Patterson' +__maintainer__ = 'Dale Patterson' +__email__ = 'wraith.wireless@yandex.com' +__status__ = 'Development' + +import pyric.net.netlink_h as nlh +import pyric.net.wireless.nl80211_h as nl80211h + +#static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = { +nl80211_policy = { + nl80211h.NL80211_ATTR_WIPHY:nlh.NLA_U32, + nl80211h.NL80211_ATTR_WIPHY_NAME:nlh.NLA_STRING, + nl80211h.NL80211_ATTR_WIPHY_TXQ_PARAMS:nlh.NLA_NESTED, + nl80211h.NL80211_ATTR_WIPHY_FREQ:nlh.NLA_U32, + nl80211h.NL80211_ATTR_WIPHY_CHANNEL_TYPE:nlh.NLA_U32, + nl80211h.NL80211_ATTR_CHANNEL_WIDTH:nlh.NLA_U32, + nl80211h.NL80211_ATTR_CENTER_FREQ1:nlh.NLA_U32, + nl80211h.NL80211_ATTR_CENTER_FREQ2:nlh.NLA_U32, + nl80211h.NL80211_ATTR_WIPHY_RETRY_SHORT:nlh.NLA_U8, + nl80211h.NL80211_ATTR_WIPHY_RETRY_LONG:nlh.NLA_U8, + nl80211h.NL80211_ATTR_WIPHY_FRAG_THRESHOLD:nlh.NLA_U32, + nl80211h.NL80211_ATTR_WIPHY_RTS_THRESHOLD:nlh.NLA_U32, + nl80211h.NL80211_ATTR_WIPHY_COVERAGE_CLASS:nlh.NLA_U8, + #nl80211h.NL80211_ATTR_WIPHY_DYN_ACK:nlh.NLA_FLAG, + nl80211h.NL80211_ATTR_IFTYPE:nlh.NLA_U32, + nl80211h.NL80211_ATTR_IFINDEX:nlh.NLA_U32, + nl80211h.NL80211_ATTR_IFNAME:nlh.NLA_STRING, + nl80211h.NL80211_ATTR_MAC:nlh.NLA_UNSPEC, + nl80211h.NL80211_ATTR_PREV_BSSID:nlh.NLA_UNSPEC, + nl80211h.NL80211_ATTR_KEY:nlh.NLA_NESTED, + nl80211h.NL80211_ATTR_KEY_DATA:nlh.NLA_UNSPEC, + nl80211h.NL80211_ATTR_KEY_IDX:nlh.NLA_U8, + nl80211h.NL80211_ATTR_KEY_CIPHER:nlh.NLA_U32, + nl80211h.NL80211_ATTR_KEY_DEFAULT:nlh.NLA_FLAG, + nl80211h.NL80211_ATTR_KEY_SEQ:nlh.NLA_UNSPEC, + nl80211h.NL80211_ATTR_KEY_TYPE:nlh.NLA_U32, + nl80211h.NL80211_ATTR_BEACON_INTERVAL:nlh.NLA_U32, + nl80211h.NL80211_ATTR_DTIM_PERIOD:nlh.NLA_U32, + nl80211h.NL80211_ATTR_BEACON_HEAD:nlh.NLA_UNSPEC, + nl80211h.NL80211_ATTR_BEACON_TAIL:nlh.NLA_UNSPEC, + nl80211h.NL80211_ATTR_STA_AID:nlh.NLA_U16, + nl80211h.NL80211_ATTR_STA_FLAGS:nlh.NLA_NESTED, + nl80211h.NL80211_ATTR_STA_LISTEN_INTERVAL:nlh.NLA_U16, + nl80211h.NL80211_ATTR_STA_SUPPORTED_RATES:nlh.NLA_UNSPEC, + nl80211h.NL80211_ATTR_STA_PLINK_ACTION:nlh.NLA_U8, + nl80211h.NL80211_ATTR_STA_VLAN:nlh.NLA_U32, + #nl80211h.NL80211_ATTR_MNTR_FLAGS:nlh.NLA_NESTED, + nl80211h.NL80211_ATTR_MNTR_FLAGS:nlh.NLA_U32, # it seems to work by adding this attribute for each flag + nl80211h.NL80211_ATTR_MESH_ID:nlh.NLA_UNSPEC, + nl80211h.NL80211_ATTR_MPATH_NEXT_HOP:nlh.NLA_U32, + nl80211h.NL80211_ATTR_REG_ALPHA2:nlh.NLA_STRING, + nl80211h.NL80211_ATTR_REG_RULES:nlh.NLA_NESTED, + nl80211h.NL80211_ATTR_BSS_CTS_PROT:nlh.NLA_U8, + nl80211h.NL80211_ATTR_BSS_SHORT_PREAMBLE:nlh.NLA_U8, + nl80211h.NL80211_ATTR_BSS_SHORT_SLOT_TIME:nlh.NLA_U8, + nl80211h.NL80211_ATTR_BSS_BASIC_RATES:nlh.NLA_UNSPEC, + nl80211h.NL80211_ATTR_BSS_HT_OPMODE:nlh.NLA_U16, + nl80211h.NL80211_ATTR_MESH_CONFIG:nlh.NLA_NESTED, + nl80211h.NL80211_ATTR_SUPPORT_MESH_AUTH:nlh.NLA_FLAG, + nl80211h.NL80211_ATTR_HT_CAPABILITY:nlh.NLA_UNSPEC, + nl80211h.NL80211_ATTR_MGMT_SUBTYPE:nlh.NLA_U8, + nl80211h.NL80211_ATTR_IE:nlh.NLA_UNSPEC, + nl80211h.NL80211_ATTR_SCAN_FREQUENCIES:nlh.NLA_NESTED, + nl80211h.NL80211_ATTR_SCAN_SSIDS:nlh.NLA_NESTED, + nl80211h.NL80211_ATTR_SSID:nlh.NLA_UNSPEC, + nl80211h.NL80211_ATTR_AUTH_TYPE:nlh.NLA_U32, + nl80211h.NL80211_ATTR_REASON_CODE:nlh.NLA_U16, + nl80211h.NL80211_ATTR_FREQ_FIXED:nlh.NLA_FLAG, + nl80211h.NL80211_ATTR_TIMED_OUT:nlh.NLA_FLAG, + nl80211h.NL80211_ATTR_USE_MFP:nlh.NLA_U32, + nl80211h.NL80211_ATTR_STA_FLAGS2:nlh.NLA_UNSPEC, + nl80211h.NL80211_ATTR_CONTROL_PORT:nlh.NLA_FLAG, + nl80211h.NL80211_ATTR_CONTROL_PORT_ETHERTYPE:nlh.NLA_U16, + nl80211h.NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT:nlh.NLA_FLAG, + nl80211h.NL80211_ATTR_PRIVACY:nlh.NLA_FLAG, + nl80211h.NL80211_ATTR_CIPHER_SUITE_GROUP:nlh.NLA_U32, + nl80211h.NL80211_ATTR_WPA_VERSIONS:nlh.NLA_U32, + nl80211h.NL80211_ATTR_PID:nlh.NLA_U32, + nl80211h.NL80211_ATTR_4ADDR:nlh.NLA_U8, + nl80211h.NL80211_ATTR_PMKID:nlh.NLA_UNSPEC, + nl80211h.NL80211_ATTR_DURATION:nlh.NLA_U32, + nl80211h.NL80211_ATTR_COOKIE:nlh.NLA_U64, + nl80211h.NL80211_ATTR_TX_RATES:nlh.NLA_NESTED, + nl80211h.NL80211_ATTR_FRAME:nlh.NLA_UNSPEC, + nl80211h.NL80211_ATTR_FRAME_MATCH:nlh.NLA_UNSPEC, + nl80211h.NL80211_ATTR_PS_STATE:nlh.NLA_U32, + nl80211h.NL80211_ATTR_CQM:nlh.NLA_NESTED, + nl80211h.NL80211_ATTR_LOCAL_STATE_CHANGE:nlh.NLA_FLAG, + nl80211h.NL80211_ATTR_AP_ISOLATE:nlh.NLA_U8, + nl80211h.NL80211_ATTR_WIPHY_TX_POWER_SETTING:nlh.NLA_U32, + nl80211h.NL80211_ATTR_WIPHY_TX_POWER_LEVEL:nlh.NLA_U32, + nl80211h.NL80211_ATTR_FRAME_TYPE:nlh.NLA_U16, + nl80211h.NL80211_ATTR_WIPHY_ANTENNA_TX:nlh.NLA_U32, + nl80211h.NL80211_ATTR_WIPHY_ANTENNA_RX:nlh.NLA_U32, + nl80211h.NL80211_ATTR_MCAST_RATE:nlh.NLA_U32, + nl80211h.NL80211_ATTR_OFFCHANNEL_TX_OK:nlh.NLA_FLAG, + nl80211h.NL80211_ATTR_KEY_DEFAULT_TYPES:nlh.NLA_NESTED, + nl80211h.NL80211_ATTR_WOWLAN_TRIGGERS:nlh.NLA_NESTED, + nl80211h.NL80211_ATTR_STA_PLINK_STATE:nlh.NLA_U8, + nl80211h.NL80211_ATTR_SCHED_SCAN_INTERVAL:nlh.NLA_U32, + nl80211h.NL80211_ATTR_REKEY_DATA:nlh.NLA_NESTED, + nl80211h.NL80211_ATTR_SCAN_SUPP_RATES:nlh.NLA_NESTED, + nl80211h.NL80211_ATTR_HIDDEN_SSID:nlh.NLA_U32, + nl80211h.NL80211_ATTR_IE_PROBE_RESP:nlh.NLA_UNSPEC, + nl80211h.NL80211_ATTR_IE_ASSOC_RESP:nlh.NLA_UNSPEC, + nl80211h.NL80211_ATTR_ROAM_SUPPORT:nlh.NLA_FLAG, + nl80211h.NL80211_ATTR_SCHED_SCAN_MATCH:nlh.NLA_NESTED, + nl80211h.NL80211_ATTR_TX_NO_CCK_RATE:nlh.NLA_FLAG, + nl80211h.NL80211_ATTR_TDLS_ACTION:nlh.NLA_U8, + nl80211h.NL80211_ATTR_TDLS_DIALOG_TOKEN:nlh.NLA_U8, + nl80211h.NL80211_ATTR_TDLS_OPERATION:nlh.NLA_U8, + nl80211h.NL80211_ATTR_TDLS_SUPPORT:nlh.NLA_FLAG, + nl80211h.NL80211_ATTR_TDLS_EXTERNAL_SETUP:nlh.NLA_FLAG, + #nl80211h.NL80211_ATTR_TDLS_INITIATOR:nlh.NLA_FLAG, + nl80211h.NL80211_ATTR_DONT_WAIT_FOR_ACK:nlh.NLA_FLAG, + nl80211h.NL80211_ATTR_PROBE_RESP:nlh.NLA_UNSPEC, + nl80211h.NL80211_ATTR_DFS_REGION:nlh.NLA_U8, + nl80211h.NL80211_ATTR_DISABLE_HT:nlh.NLA_FLAG, + nl80211h.NL80211_ATTR_HT_CAPABILITY_MASK:nlh.NLA_UNSPEC, + nl80211h.NL80211_ATTR_NOACK_MAP:nlh.NLA_U16, + nl80211h.NL80211_ATTR_INACTIVITY_TIMEOUT:nlh.NLA_U16, + nl80211h.NL80211_ATTR_BG_SCAN_PERIOD:nlh.NLA_U16, + nl80211h.NL80211_ATTR_WDEV:nlh.NLA_U64, + nl80211h.NL80211_ATTR_USER_REG_HINT_TYPE:nlh.NLA_U32, + nl80211h.NL80211_ATTR_SAE_DATA:nlh.NLA_UNSPEC, + nl80211h.NL80211_ATTR_VHT_CAPABILITY:nlh.NLA_UNSPEC, + nl80211h.NL80211_ATTR_SCAN_FLAGS:nlh.NLA_U32, + nl80211h.NL80211_ATTR_P2P_CTWINDOW:nlh.NLA_U8, + nl80211h.NL80211_ATTR_P2P_OPPPS:nlh.NLA_U8, + nl80211h.NL80211_ATTR_ACL_POLICY:nlh.NLA_U32, + nl80211h.NL80211_ATTR_MAC_ADDRS:nlh.NLA_NESTED, + nl80211h.NL80211_ATTR_STA_CAPABILITY:nlh.NLA_U16, + nl80211h.NL80211_ATTR_STA_EXT_CAPABILITY:nlh.NLA_UNSPEC, + nl80211h.NL80211_ATTR_SPLIT_WIPHY_DUMP:nlh.NLA_FLAG, + nl80211h.NL80211_ATTR_DISABLE_VHT:nlh.NLA_FLAG, + nl80211h.NL80211_ATTR_VHT_CAPABILITY_MASK:nlh.NLA_UNSPEC, + nl80211h.NL80211_ATTR_MDID:nlh.NLA_U16, + nl80211h.NL80211_ATTR_IE_RIC:nlh.NLA_UNSPEC, + nl80211h.NL80211_ATTR_PEER_AID:nlh.NLA_U16, + nl80211h.NL80211_ATTR_CH_SWITCH_COUNT:nlh.NLA_U32, + nl80211h.NL80211_ATTR_CH_SWITCH_BLOCK_TX:nlh.NLA_FLAG, + nl80211h.NL80211_ATTR_CSA_IES:nlh.NLA_NESTED, + nl80211h.NL80211_ATTR_CSA_C_OFF_BEACON:nlh.NLA_UNSPEC, + nl80211h.NL80211_ATTR_CSA_C_OFF_PRESP:nlh.NLA_UNSPEC, + nl80211h.NL80211_ATTR_STA_SUPPORTED_CHANNELS:nlh.NLA_UNSPEC, + nl80211h.NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES:nlh.NLA_UNSPEC, + nl80211h.NL80211_ATTR_HANDLE_DFS:nlh.NLA_FLAG, + # not present in nl80211.c + nl80211h.NL80211_ATTR_SUPPORTED_IFTYPES:nlh.NLA_NESTED, + nl80211h.NL80211_ATTR_SOFTWARE_IFTYPES:nlh.NLA_NESTED, + nl80211h.NL80211_ATTR_WIPHY_BANDS:nlh.NLA_NESTED, + nl80211h.NL80211_ATTR_SUPPORTED_COMMANDS:nlh.NLA_NESTED, + nl80211h.NL80211_ATTR_MAX_NUM_SCAN_SSIDS:nlh.NLA_U8 + #Not defined in nl80211_h + #nl80211h.NL80211_ATTR_OPMODE_NOTIF:nlh.NLA_U8, + #nl80211h.NL80211_ATTR_VENDOR_ID:nlh.NLA_U32, + #nl80211h.NL80211_ATTR_VENDOR_SUBCMD:nlh.NLA_U32, + #nl80211h.NL80211_ATTR_VENDOR_DATA:nlh.NLA_UNSPEC, + #nl80211h.NL80211_ATTR_QOS_MAP:nlh.NLA_UNSPEC, + #nl80211h.NL80211_ATTR_MAC_HINT:nlh.NLA_UNSPEC, + #nl80211h.NL80211_ATTR_WIPHY_FREQ_HINT:nlh.NLA_U32, + #nl80211h.NL80211_ATTR_TDLS_PEER_CAPABILITY:nlh.NLA_U32, + #nl80211h.NL80211_ATTR_SOCKET_OWNER:nlh.NLA_FLAG, + #nl80211h.NL80211_ATTR_CSA_C_OFFSETS_TX:nlh.NLA_UNSPEC, + #nl80211h.NL80211_ATTR_USE_RRM:nlh.NLA_FLAG, + #nl80211h.NL80211_ATTR_TSID:nlh.NLA_U8, + #nl80211h.NL80211_ATTR_USER_PRIO:nlh.NLA_U8, + #nl80211h.NL80211_ATTR_ADMITTED_TIME:nlh.NLA_U16, + #nl80211h.NL80211_ATTR_SMPS_MODE:nlh.NLA_U8, + #nl80211h.NL80211_ATTR_MAC_MASK:nlh.NLA_UNSPEC, + #nl80211h.NL80211_ATTR_WIPHY_SELF_MANAGED_REG:nlh.NLA_FLAG, + #nl80211h.NL80211_ATTR_NETNS_FD:nlh.NLA_U32, + #nl80211h.NL80211_ATTR_SCHED_SCAN_DELAY:nlh.NLA_U32, + #nl80211h.NL80211_ATTR_REG_INDOOR:nlh.NLA_FLAG, + #nl80211h.NL80211_ATTR_PBSS:nlh.NLA_FLAG +} + + +# policy for the key attributes +#static const struct nla_policy nl80211_key_policy[NL80211_KEY_MAX + 1] = { +nl80211_key_policy = { + nl80211h.NL80211_KEY_DATA:nlh.NLA_UNSPEC, + nl80211h.NL80211_KEY_IDX:nlh.NLA_U8, + nl80211h.NL80211_KEY_CIPHER:nlh.NLA_U32, + nl80211h.NL80211_KEY_SEQ:nlh.NLA_UNSPEC, + nl80211h.NL80211_KEY_DEFAULT:nlh.NLA_FLAG, + nl80211h.NL80211_KEY_DEFAULT_MGMT:nlh.NLA_FLAG, + nl80211h.NL80211_KEY_TYPE:nlh.NLA_U32, + nl80211h.NL80211_KEY_DEFAULT_TYPES:nlh.NLA_NESTED +} + +# policy for the key default flags +#static const struct nla_policy +nl80211_key_default_policy = { + nl80211h.NL80211_KEY_DEFAULT_TYPE_UNICAST:nlh.NLA_FLAG, + nl80211h.NL80211_KEY_DEFAULT_TYPE_MULTICAST:nlh.NLA_FLAG +} + +#/* policy for WoWLAN attributes */ +#static const struct nla_policy nl80211_wowlan_policy[NUM_NL80211_WOWLAN_TRIG] = { +nl80211_wowlan_trig_policy = { + nl80211h.NL80211_WOWLAN_TRIG_ANY:nlh.NLA_FLAG, + nl80211h.NL80211_WOWLAN_TRIG_DISCONNECT:nlh.NLA_FLAG, + nl80211h.NL80211_WOWLAN_TRIG_MAGIC_PKT:nlh.NLA_FLAG, + nl80211h.NL80211_WOWLAN_TRIG_PKT_PATTERN:nlh.NLA_NESTED, + nl80211h.NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE:nlh.NLA_FLAG, + nl80211h.NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST:nlh.NLA_FLAG, + nl80211h.NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE:nlh.NLA_FLAG, + nl80211h.NL80211_WOWLAN_TRIG_RFKILL_RELEASE:nlh.NLA_FLAG, + nl80211h.NL80211_WOWLAN_TRIG_TCP_CONNECTION:nlh.NLA_NESTED + #nl80211h.NL80211_WOWLAN_TRIG_NET_DETECT:nlh.NLA_NESTED +} + +#static const struct nla_policy nl80211_wowlan_tcp_policy[NUM_NL80211_WOWLAN_TCP] = { +nl80211_wowlan_tcp_policy = { + nl80211h.NL80211_WOWLAN_TCP_SRC_IPV4:nlh.NLA_U32, + nl80211h.NL80211_WOWLAN_TCP_DST_IPV4:nlh.NLA_U32, + nl80211h.NL80211_WOWLAN_TCP_DST_MAC:nlh.NLA_UNSPEC, + nl80211h.NL80211_WOWLAN_TCP_SRC_PORT:nlh.NLA_U16, + nl80211h.NL80211_WOWLAN_TCP_DST_PORT:nlh.NLA_U16, + nl80211h.NL80211_WOWLAN_TCP_DATA_PAYLOAD:nlh.NLA_UNSPEC, + nl80211h.NL80211_WOWLAN_TCP_DATA_PAYLOAD_SEQ:nlh.NLA_UNSPEC, + nl80211h.NL80211_WOWLAN_TCP_DATA_PAYLOAD_TOKEN:nlh.NLA_UNSPEC, + nl80211h.NL80211_WOWLAN_TCP_DATA_INTERVAL:nlh.NLA_U32, + nl80211h.NL80211_WOWLAN_TCP_WAKE_PAYLOAD:nlh.NLA_UNSPEC, + nl80211h.NL80211_WOWLAN_TCP_WAKE_MASK:nlh.NLA_UNSPEC +} + +#/* policy for coalesce rule attributes */ +#static const struct nla_policy nl80211_coalesce_policy[NUM_NL80211_ATTR_COALESCE_RULE] = { +nl80211_coalesce_policy={ + nl80211h.NL80211_ATTR_COALESCE_RULE_DELAY:nlh.NLA_U32, + nl80211h.NL80211_ATTR_COALESCE_RULE_CONDITION:nlh.NLA_U32, + nl80211h.NL80211_ATTR_COALESCE_RULE_PKT_PATTERN:nlh.NLA_NESTED +} + +#/* policy for GTK rekey offload attributes */ +#static const struct nla_policy nl80211_rekey_policy[NUM_NL80211_REKEY_DATA] = { +nl80211_rekey_policy = { + nl80211h.NL80211_REKEY_DATA_KEK:nlh.NLA_UNSPEC, + nl80211h.NL80211_REKEY_DATA_KCK:nlh.NLA_UNSPEC, + nl80211h.NL80211_REKEY_DATA_REPLAY_CTR:nlh.NLA_UNSPEC +} + +#static const struct nla_policy nl80211_match_policy[NL80211_SCHED_SCAN_MATCH_ATTR_MAX + 1] = { +nl80211_sched_scan_match_policy = { + nl80211h.NL80211_SCHED_SCAN_MATCH_ATTR_SSID:nlh.NLA_UNSPEC, + nl80211h.NL80211_SCHED_SCAN_MATCH_ATTR_RSSI:nlh.NLA_U32 +} + +#static const struct nla_policy nl80211_plan_policy[NL80211_SCHED_SCAN_PLAN_MAX + 1] = { +#nl80211_sched_scan_plan_policy = { +# nl80211h.NL80211_SCHED_SCAN_PLAN_INTERVAL:nlh.NLA_U32, +# nl80211h.NL80211_SCHED_SCAN_PLAN_ITERATIONS:nlh.NLA_U32 +#} diff --git a/pyric/net/wireless/nl80211_h.py b/pyric/net/wireless/nl80211_h.py new file mode 100644 index 0000000..ca393e7 --- /dev/null +++ b/pyric/net/wireless/nl80211_h.py @@ -0,0 +1,3451 @@ +#!/usr/bin/env python + +""" nl80211_h.py: 802.11 netlink interface public header + +/* + * 802.11 netlink interface public header + * + * Copyright 2006-2010 Johannes Berg + * Copyright 2008 Michael Wu + * Copyright 2008 Luis Carlos Cobo + * Copyright 2008 Michael Buesch + * Copyright 2008 = 2009 Luis R. Rodriguez + * Copyright 2008 Jouni Malinen + * Copyright 2008 Colin McCabe + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +Copyright (C) 2016 Dale V. Patterson (wraith.wireless@yandex.com) + +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 3 of the License, or (at your option) any later +version. + +Redistribution and use in source and binary forms, with or without modifications, +are permitted provided that the following conditions are met: + o Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + o Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + o Neither the name of the orginal author Dale V. Patterson nor the names of any + contributors may be used to endorse or promote products derived from this + software without specific prior written permission. + +NOTE: + 1. Most of these constants are not used but are left for possible future use + 2. I have removed *_AFTER_LAST and only kept MAX_* for enums for those nums +""" + +__name__ = 'nl80211_h' +__license__ = 'GPLv3' +__version__ = '0.0.3' +__date__ = 'April 2016' +__author__ = 'Dale Patterson' +__maintainer__ = 'Dale Patterson' +__email__ = 'wraith.wireless@yandex.com' +__status__ = 'Development' + +import struct + +NL80211_GENL_NAME = 'nl80211' + +""" +/** + * enum nl80211_commands - supported nl80211 commands + * + * @NL80211_CMD_UNSPEC: unspecified command to catch errors + * @NL80211_CMD_GET_WIPHY: request information about a wiphy or dump request + * to get a list of all present wiphys. + * @NL80211_CMD_SET_WIPHY: set wiphy parameters, needs %NL80211_ATTR_WIPHY or + * %NL80211_ATTR_IFINDEX; can be used to set %NL80211_ATTR_WIPHY_NAME, + * %NL80211_ATTR_WIPHY_TXQ_PARAMS, %NL80211_ATTR_WIPHY_FREQ (and the + * attributes determining the channel width; this is used for setting + * monitor mode channel), %NL80211_ATTR_WIPHY_RETRY_SHORT, + * %NL80211_ATTR_WIPHY_RETRY_LONG, %NL80211_ATTR_WIPHY_FRAG_THRESHOLD, + * and/or %NL80211_ATTR_WIPHY_RTS_THRESHOLD. + * However, for setting the channel, see %NL80211_CMD_SET_CHANNEL + * instead, the support here is for backward compatibility only. + * @NL80211_CMD_NEW_WIPHY: Newly created wiphy, response to get request + * or rename notification. Has attributes %NL80211_ATTR_WIPHY and + * %NL80211_ATTR_WIPHY_NAME. + * @NL80211_CMD_DEL_WIPHY: Wiphy deleted. Has attributes + * %NL80211_ATTR_WIPHY and %NL80211_ATTR_WIPHY_NAME. + * @NL80211_CMD_GET_INTERFACE: Request an interface's configuration; + * either a dump request on a %NL80211_ATTR_WIPHY or a specific get + * on an %NL80211_ATTR_IFINDEX is supported. + * @NL80211_CMD_SET_INTERFACE: Set type of a virtual interface, requires + * %NL80211_ATTR_IFINDEX and %NL80211_ATTR_IFTYPE. + * @NL80211_CMD_NEW_INTERFACE: Newly created virtual interface or response + * to %NL80211_CMD_GET_INTERFACE. Has %NL80211_ATTR_IFINDEX, + * %NL80211_ATTR_WIPHY and %NL80211_ATTR_IFTYPE attributes. Can also + * be sent from userspace to request creation of a new virtual interface, + * then requires attributes %NL80211_ATTR_WIPHY, %NL80211_ATTR_IFTYPE and + * %NL80211_ATTR_IFNAME. + * @NL80211_CMD_DEL_INTERFACE: Virtual interface was deleted, has attributes + * %NL80211_ATTR_IFINDEX and %NL80211_ATTR_WIPHY. Can also be sent from + * userspace to request deletion of a virtual interface, then requires + * attribute %NL80211_ATTR_IFINDEX. + * @NL80211_CMD_GET_KEY: Get sequence counter information for a key specified + * by %NL80211_ATTR_KEY_IDX and/or %NL80211_ATTR_MAC. + * @NL80211_CMD_SET_KEY: Set key attributes %NL80211_ATTR_KEY_DEFAULT, + * %NL80211_ATTR_KEY_DEFAULT_MGMT, or %NL80211_ATTR_KEY_THRESHOLD. + * @NL80211_CMD_NEW_KEY: add a key with given %NL80211_ATTR_KEY_DATA, + * %NL80211_ATTR_KEY_IDX, %NL80211_ATTR_MAC, %NL80211_ATTR_KEY_CIPHER, + * and %NL80211_ATTR_KEY_SEQ attributes. + * @NL80211_CMD_DEL_KEY: delete a key identified by %NL80211_ATTR_KEY_IDX + * or %NL80211_ATTR_MAC. + * @NL80211_CMD_GET_BEACON: (not used) + * @NL80211_CMD_SET_BEACON: change the beacon on an access point interface + * using the %NL80211_ATTR_BEACON_HEAD and %NL80211_ATTR_BEACON_TAIL + * attributes. For drivers that generate the beacon and probe responses + * internally, the following attributes must be provided: %NL80211_ATTR_IE, + * %NL80211_ATTR_IE_PROBE_RESP and %NL80211_ATTR_IE_ASSOC_RESP. + * @NL80211_CMD_START_AP: Start AP operation on an AP interface, parameters + * are like for %NL80211_CMD_SET_BEACON, and additionally parameters that + * do not change are used, these include %NL80211_ATTR_BEACON_INTERVAL, + * %NL80211_ATTR_DTIM_PERIOD, %NL80211_ATTR_SSID, + * %NL80211_ATTR_HIDDEN_SSID, %NL80211_ATTR_CIPHERS_PAIRWISE, + * %NL80211_ATTR_CIPHER_GROUP, %NL80211_ATTR_WPA_VERSIONS, + * %NL80211_ATTR_AKM_SUITES, %NL80211_ATTR_PRIVACY, + * %NL80211_ATTR_AUTH_TYPE, %NL80211_ATTR_INACTIVITY_TIMEOUT, + * %NL80211_ATTR_ACL_POLICY and %NL80211_ATTR_MAC_ADDRS. + * The channel to use can be set on the interface or be given using the + * %NL80211_ATTR_WIPHY_FREQ and the attributes determining channel width. + * @NL80211_CMD_NEW_BEACON: old alias for %NL80211_CMD_START_AP + * @NL80211_CMD_STOP_AP: Stop AP operation on the given interface + * @NL80211_CMD_DEL_BEACON: old alias for %NL80211_CMD_STOP_AP + * @NL80211_CMD_GET_STATION: Get station attributes for station identified by + * %NL80211_ATTR_MAC on the interface identified by %NL80211_ATTR_IFINDEX. + * @NL80211_CMD_SET_STATION: Set station attributes for station identified by + * %NL80211_ATTR_MAC on the interface identified by %NL80211_ATTR_IFINDEX. + * @NL80211_CMD_NEW_STATION: Add a station with given attributes to the + * the interface identified by %NL80211_ATTR_IFINDEX. + * @NL80211_CMD_DEL_STATION: Remove a station identified by %NL80211_ATTR_MAC + * or, if no MAC address given, all stations, on the interface identified + * by %NL80211_ATTR_IFINDEX. + * @NL80211_CMD_GET_MPATH: Get mesh path attributes for mesh path to + * destination %NL80211_ATTR_MAC on the interface identified by + * %NL80211_ATTR_IFINDEX. + * @NL80211_CMD_SET_MPATH: Set mesh path attributes for mesh path to + * destination %NL80211_ATTR_MAC on the interface identified by + * %NL80211_ATTR_IFINDEX. + * @NL80211_CMD_NEW_MPATH: Create a new mesh path for the destination given by + * %NL80211_ATTR_MAC via %NL80211_ATTR_MPATH_NEXT_HOP. + * @NL80211_CMD_DEL_MPATH: Delete a mesh path to the destination given by + * %NL80211_ATTR_MAC. + * @NL80211_CMD_NEW_PATH: Add a mesh path with given attributes to the + * the interface identified by %NL80211_ATTR_IFINDEX. + * @NL80211_CMD_DEL_PATH: Remove a mesh path identified by %NL80211_ATTR_MAC + * or, if no MAC address given, all mesh paths, on the interface identified + * by %NL80211_ATTR_IFINDEX. + * @NL80211_CMD_SET_BSS: Set BSS attributes for BSS identified by + * %NL80211_ATTR_IFINDEX. + * @NL80211_CMD_GET_REG: ask the wireless core to send us its currently set + * regulatory domain. + * @NL80211_CMD_SET_REG: Set current regulatory domain. CRDA sends this command + * after being queried by the kernel. CRDA replies by sending a regulatory + * domain structure which consists of %NL80211_ATTR_REG_ALPHA set to our + * current alpha2 if it found a match. It also provides + * NL80211_ATTR_REG_RULE_FLAGS, and a set of regulatory rules. Each + * regulatory rule is a nested set of attributes given by + * %NL80211_ATTR_REG_RULE_FREQ_[START|END] and + * %NL80211_ATTR_FREQ_RANGE_MAX_BW with an attached power rule given by + * %NL80211_ATTR_REG_RULE_POWER_MAX_ANT_GAIN and + * %NL80211_ATTR_REG_RULE_POWER_MAX_EIRP. + * @NL80211_CMD_REQ_SET_REG: ask the wireless core to set the regulatory domain + * to the specified ISO/IEC 3166-1 alpha2 country code. The core will + * store this as a valid request and then query userspace for it. + * @NL80211_CMD_GET_MESH_CONFIG: Get mesh networking properties for the + * interface identified by %NL80211_ATTR_IFINDEX + * @NL80211_CMD_SET_MESH_CONFIG: Set mesh networking properties for the + * interface identified by %NL80211_ATTR_IFINDEX + * @NL80211_CMD_SET_MGMT_EXTRA_IE: Set extra IEs for management frames. The + * interface is identified with %NL80211_ATTR_IFINDEX and the management + * frame subtype with %NL80211_ATTR_MGMT_SUBTYPE. The extra IE data to be + * added to the end of the specified management frame is specified with + * %NL80211_ATTR_IE. If the command succeeds, the requested data will be + * added to all specified management frames generated by + * kernel/firmware/driver. + * Note: This command has been removed and it is only reserved at this + * point to avoid re-using existing command number. The functionality this + * command was planned for has been provided with cleaner design with the + * option to specify additional IEs in NL80211_CMD_TRIGGER_SCAN, + * NL80211_CMD_AUTHENTICATE, NL80211_CMD_ASSOCIATE, + * NL80211_CMD_DEAUTHENTICATE, and NL80211_CMD_DISASSOCIATE. + * @NL80211_CMD_GET_SCAN: get scan results + * @NL80211_CMD_TRIGGER_SCAN: trigger a new scan with the given parameters + * %NL80211_ATTR_TX_NO_CCK_RATE is used to decide whether to send the + * probe requests at CCK rate or not. + * @NL80211_CMD_NEW_SCAN_RESULTS: scan notification (as a reply to + * NL80211_CMD_GET_SCAN and on the "scan" multicast group) + * @NL80211_CMD_SCAN_ABORTED: scan was aborted, for unspecified reasons, + * partial scan results may be available + * @NL80211_CMD_START_SCHED_SCAN: start a scheduled scan at certain + * intervals, as specified by %NL80211_ATTR_SCHED_SCAN_INTERVAL. + * Like with normal scans, if SSIDs (%NL80211_ATTR_SCAN_SSIDS) + * are passed, they are used in the probe requests. For + * broadcast, a broadcast SSID must be passed (ie. an empty + * string). If no SSID is passed, no probe requests are sent and + * a passive scan is performed. %NL80211_ATTR_SCAN_FREQUENCIES, + * if passed, define which channels should be scanned; if not + * passed, all channels allowed for the current regulatory domain + * are used. Extra IEs can also be passed from the userspace by + * using the %NL80211_ATTR_IE attribute. + * @NL80211_CMD_STOP_SCHED_SCAN: stop a scheduled scan. Returns -ENOENT + * if scheduled scan is not running. + * @NL80211_CMD_SCHED_SCAN_RESULTS: indicates that there are scheduled scan + * results available. + * @NL80211_CMD_SCHED_SCAN_STOPPED: indicates that the scheduled scan has + * stopped. The driver may issue this event at any time during a + * scheduled scan. One reason for stopping the scan is if the hardware + * does not support starting an association or a normal scan while running + * a scheduled scan. This event is also sent when the + * %NL80211_CMD_STOP_SCHED_SCAN command is received or when the interface + * is brought down while a scheduled scan was running. + * @NL80211_CMD_GET_SURVEY: get survey resuls, e.g. channel occupation or noise lvl + * @NL80211_CMD_NEW_SURVEY_RESULTS: survey data notification (as a reply to + * NL80211_CMD_GET_SURVEY and on the "scan" multicast group) + * @NL80211_CMD_SET_PMKSA: Add a PMKSA cache entry, using %NL80211_ATTR_MAC + * (for the BSSID) and %NL80211_ATTR_PMKID. + * @NL80211_CMD_DEL_PMKSA: Delete a PMKSA cache entry, using %NL80211_ATTR_MAC + * (for the BSSID) and %NL80211_ATTR_PMKID. + * @NL80211_CMD_FLUSH_PMKSA: Flush all PMKSA cache entries. + * @NL80211_CMD_REG_CHANGE: indicates to userspace the regulatory domain + * has been changed and provides details of the request information + * that caused the change such as who initiated the regulatory request + * (%NL80211_ATTR_REG_INITIATOR), the wiphy_idx + * (%NL80211_ATTR_REG_ALPHA2) on which the request was made from if + * the initiator was %NL80211_REGDOM_SET_BY_COUNTRY_IE or + * %NL80211_REGDOM_SET_BY_DRIVER, the type of regulatory domain + * set (%NL80211_ATTR_REG_TYPE), if the type of regulatory domain is + * %NL80211_REG_TYPE_COUNTRY the alpha2 to which we have moved on + * to (%NL80211_ATTR_REG_ALPHA2). + * @NL80211_CMD_REG_BEACON_HINT: indicates to userspace that an AP beacon + * has been found while world roaming thus enabling active scan or + * any mode of operation that initiates TX (beacons) on a channel + * where we would not have been able to do either before. As an example + * if you are world roaming (regulatory domain set to world or if your + * driver is using a custom world roaming regulatory domain) and while + * doing a passive scan on the 5 GHz band you find an AP there (if not + * on a DFS channel) you will now be able to actively scan for that AP + * or use AP mode on your card on that same channel. Note that this will + * never be used for channels 1-11 on the 2 GHz band as they are always + * enabled world wide. This beacon hint is only sent if your device had + * either disabled active scanning or beaconing on a channel. We send to + * userspace the wiphy on which we removed a restriction from + * (%NL80211_ATTR_WIPHY) and the channel on which this occurred + * before (%NL80211_ATTR_FREQ_BEFORE) and after (%NL80211_ATTR_FREQ_AFTER) + * the beacon hint was processed. + * @NL80211_CMD_AUTHENTICATE: authentication request and notification. + * This command is used both as a command (request to authenticate) and + * as an event on the "mlme" multicast group indicating completion of the + * authentication process. + * When used as a command, %NL80211_ATTR_IFINDEX is used to identify the + * interface. %NL80211_ATTR_MAC is used to specify PeerSTAAddress (and + * BSSID in case of station mode). %NL80211_ATTR_SSID is used to specify + * the SSID (mainly for association, but is included in authentication + * request, too, to help BSS selection. %NL80211_ATTR_WIPHY_FREQ is used + * to specify the frequence of the channel in MHz. %NL80211_ATTR_AUTH_TYPE + * is used to specify the authentication type. %NL80211_ATTR_IE is used to + * define IEs (VendorSpecificInfo, but also including RSN IE and FT IEs) + * to be added to the frame. + * When used as an event, this reports reception of an Authentication + * frame in station and IBSS modes when the local MLME processed the + * frame, i.e., it was for the local STA and was received in correct + * state. This is similar to MLME-AUTHENTICATE.confirm primitive in the + * MLME SAP interface (kernel providing MLME, userspace SME). The + * included %NL80211_ATTR_FRAME attribute contains the management frame + * (including both the header and frame body, but not FCS). This event is + * also used to indicate if the authentication attempt timed out. In that + * case the %NL80211_ATTR_FRAME attribute is replaced with a + * %NL80211_ATTR_TIMED_OUT flag (and %NL80211_ATTR_MAC to indicate which + * pending authentication timed out). + * @NL80211_CMD_ASSOCIATE: association request and notification; like + * NL80211_CMD_AUTHENTICATE but for Association and Reassociation + * (similar to MLME-ASSOCIATE.request, MLME-REASSOCIATE.request, + * MLME-ASSOCIATE.confirm or MLME-REASSOCIATE.confirm primitives). + * @NL80211_CMD_DEAUTHENTICATE: deauthentication request and notification; like + * NL80211_CMD_AUTHENTICATE but for Deauthentication frames (similar to + * MLME-DEAUTHENTICATION.request and MLME-DEAUTHENTICATE.indication + * primitives). + * @NL80211_CMD_DISASSOCIATE: disassociation request and notification; like + * NL80211_CMD_AUTHENTICATE but for Disassociation frames (similar to + * MLME-DISASSOCIATE.request and MLME-DISASSOCIATE.indication primitives). + * @NL80211_CMD_MICHAEL_MIC_FAILURE: notification of a locally detected Michael + * MIC (part of TKIP) failure; sent on the "mlme" multicast group; the + * event includes %NL80211_ATTR_MAC to describe the source MAC address of + * the frame with invalid MIC, %NL80211_ATTR_KEY_TYPE to show the key + * type, %NL80211_ATTR_KEY_IDX to indicate the key identifier, and + * %NL80211_ATTR_KEY_SEQ to indicate the TSC value of the frame; this + * event matches with MLME-MICHAELMICFAILURE.indication() primitive + * @NL80211_CMD_JOIN_IBSS: Join a new IBSS -- given at least an SSID and a + * FREQ attribute (for the initial frequency if no peer can be found) + * and optionally a MAC (as BSSID) and FREQ_FIXED attribute if those + * should be fixed rather than automatically determined. Can only be + * executed on a network interface that is UP, and fixed BSSID/FREQ + * may be rejected. Another optional parameter is the beacon interval, + * given in the %NL80211_ATTR_BEACON_INTERVAL attribute, which if not + * given defaults to 100 TU (102.4ms). + * @NL80211_CMD_LEAVE_IBSS: Leave the IBSS -- no special arguments, the IBSS is + * determined by the network interface. + * @NL80211_CMD_TESTMODE: testmode command, takes a wiphy (or ifindex) attribute + * to identify the device, and the TESTDATA blob attribute to pass through + * to the driver. + * @NL80211_CMD_CONNECT: connection request and notification; this command + * requests to connect to a specified network but without separating + * auth and assoc steps. For this, you need to specify the SSID in a + * %NL80211_ATTR_SSID attribute, and can optionally specify the association + * IEs in %NL80211_ATTR_IE, %NL80211_ATTR_AUTH_TYPE, %NL80211_ATTR_USE_MFP, + * %NL80211_ATTR_MAC, %NL80211_ATTR_WIPHY_FREQ, %NL80211_ATTR_CONTROL_PORT, + * %NL80211_ATTR_CONTROL_PORT_ETHERTYPE and + * %NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT. + * Background scan period can optionally be + * specified in %NL80211_ATTR_BG_SCAN_PERIOD, + * if not specified default background scan configuration + * in driver is used and if period value is 0, bg scan will be disabled. + * This attribute is ignored if driver does not support roam scan. + * It is also sent as an event, with the BSSID and response IEs when the + * connection is established or failed to be established. This can be + * determined by the STATUS_CODE attribute. + * @NL80211_CMD_ROAM: request that the card roam (currently not implemented), + * sent as an event when the card/driver roamed by itself. + * @NL80211_CMD_DISCONNECT: drop a given connection; also used to notify + * userspace that a connection was dropped by the AP or due to other + * reasons, for this the %NL80211_ATTR_DISCONNECTED_BY_AP and + * %NL80211_ATTR_REASON_CODE attributes are used. + * @NL80211_CMD_SET_WIPHY_NETNS: Set a wiphy's netns. Note that all devices + * associated with this wiphy must be down and will follow. + * @NL80211_CMD_REMAIN_ON_CHANNEL: Request to remain awake on the specified + * channel for the specified amount of time. This can be used to do + * off-channel operations like transmit a Public Action frame and wait for + * a response while being associated to an AP on another channel. + * %NL80211_ATTR_IFINDEX is used to specify which interface (and thus + * radio) is used. %NL80211_ATTR_WIPHY_FREQ is used to specify the + * frequency for the operation. + * %NL80211_ATTR_DURATION is used to specify the duration in milliseconds + * to remain on the channel. This command is also used as an event to + * notify when the requested duration starts (it may take a while for the + * driver to schedule this time due to other concurrent needs for the + * radio). + * When called, this operation returns a cookie (%NL80211_ATTR_COOKIE) + * that will be included with any events pertaining to this request; + * the cookie is also used to cancel the request. + * @NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL: This command can be used to cancel a + * pending remain-on-channel duration if the desired operation has been + * completed prior to expiration of the originally requested duration. + * %NL80211_ATTR_WIPHY or %NL80211_ATTR_IFINDEX is used to specify the + * radio. The %NL80211_ATTR_COOKIE attribute must be given as well to + * uniquely identify the request. + * This command is also used as an event to notify when a requested + * remain-on-channel duration has expired. + * @NL80211_CMD_SET_TX_BITRATE_MASK: Set the mask of rates to be used in TX + * rate selection. %NL80211_ATTR_IFINDEX is used to specify the interface + * and @NL80211_ATTR_TX_RATES the set of allowed rates. + * @NL80211_CMD_REGISTER_FRAME: Register for receiving certain mgmt frames + * (via @NL80211_CMD_FRAME) for processing in userspace. This command + * requires an interface index, a frame type attribute (optional for + * backward compatibility reasons, if not given assumes action frames) + * and a match attribute containing the first few bytes of the frame + * that should match, e.g. a single byte for only a category match or + * four bytes for vendor frames including the OUI. The registration + * cannot be dropped, but is removed automatically when the netlink + * socket is closed. Multiple registrations can be made. + * @NL80211_CMD_REGISTER_ACTION: Alias for @NL80211_CMD_REGISTER_FRAME for + * backward compatibility + * @NL80211_CMD_FRAME: Management frame TX request and RX notification. This + * command is used both as a request to transmit a management frame and + * as an event indicating reception of a frame that was not processed in + * kernel code, but is for us (i.e., which may need to be processed in a + * user space application). %NL80211_ATTR_FRAME is used to specify the + * frame contents (including header). %NL80211_ATTR_WIPHY_FREQ is used + * to indicate on which channel the frame is to be transmitted or was + * received. If this channel is not the current channel (remain-on-channel + * or the operational channel) the device will switch to the given channel + * and transmit the frame, optionally waiting for a response for the time + * specified using %NL80211_ATTR_DURATION. When called, this operation + * returns a cookie (%NL80211_ATTR_COOKIE) that will be included with the + * TX status event pertaining to the TX request. + * %NL80211_ATTR_TX_NO_CCK_RATE is used to decide whether to send the + * management frames at CCK rate or not in 2GHz band. + * @NL80211_CMD_FRAME_WAIT_CANCEL: When an off-channel TX was requested, this + * command may be used with the corresponding cookie to cancel the wait + * time if it is known that it is no longer necessary. + * @NL80211_CMD_ACTION: Alias for @NL80211_CMD_FRAME for backward compatibility. + * @NL80211_CMD_FRAME_TX_STATUS: Report TX status of a management frame + * transmitted with %NL80211_CMD_FRAME. %NL80211_ATTR_COOKIE identifies + * the TX command and %NL80211_ATTR_FRAME includes the contents of the + * frame. %NL80211_ATTR_ACK flag is included if the recipient acknowledged + * the frame. + * @NL80211_CMD_ACTION_TX_STATUS: Alias for @NL80211_CMD_FRAME_TX_STATUS for + * backward compatibility. + * @NL80211_CMD_SET_POWER_SAVE: Set powersave, using %NL80211_ATTR_PS_STATE + * @NL80211_CMD_GET_POWER_SAVE: Get powersave status in %NL80211_ATTR_PS_STATE + * @NL80211_CMD_SET_CQM: Connection quality monitor configuration. This command + * is used to configure connection quality monitoring notification trigger + * levels. + * @NL80211_CMD_NOTIFY_CQM: Connection quality monitor notification. This + * command is used as an event to indicate the that a trigger level was + * reached. + * @NL80211_CMD_SET_CHANNEL: Set the channel (using %NL80211_ATTR_WIPHY_FREQ + * and the attributes determining channel width) the given interface + * (identifed by %NL80211_ATTR_IFINDEX) shall operate on. + * In case multiple channels are supported by the device, the mechanism + * with which it switches channels is implementation-defined. + * When a monitor interface is given, it can only switch channel while + * no other interfaces are operating to avoid disturbing the operation + * of any other interfaces, and other interfaces will again take + * precedence when they are used. + * @NL80211_CMD_SET_WDS_PEER: Set the MAC address of the peer on a WDS interface. + * @NL80211_CMD_JOIN_MESH: Join a mesh. The mesh ID must be given, and initial + * mesh config parameters may be given. + * @NL80211_CMD_LEAVE_MESH: Leave the mesh network -- no special arguments, the + * network is determined by the network interface. + * @NL80211_CMD_UNPROT_DEAUTHENTICATE: Unprotected deauthentication frame + * notification. This event is used to indicate that an unprotected + * deauthentication frame was dropped when MFP is in use. + * @NL80211_CMD_UNPROT_DISASSOCIATE: Unprotected disassociation frame + * notification. This event is used to indicate that an unprotected + * disassociation frame was dropped when MFP is in use. + * @NL80211_CMD_NEW_PEER_CANDIDATE: Notification on the reception of a + * beacon or probe response from a compatible mesh peer. This is only + * sent while no station information (sta_info) exists for the new peer + * candidate and when @NL80211_MESH_SETUP_USERSPACE_AUTH, + * @NL80211_MESH_SETUP_USERSPACE_AMPE, or + * @NL80211_MESH_SETUP_USERSPACE_MPM is set. On reception of this + * notification, userspace may decide to create a new station + * (@NL80211_CMD_NEW_STATION). To stop this notification from + * reoccurring, the userspace authentication daemon may want to create the + * new station with the AUTHENTICATED flag unset and maybe change it later + * depending on the authentication result. + * @NL80211_CMD_GET_WOWLAN: get Wake-on-Wireless-LAN (WoWLAN) settings. + * @NL80211_CMD_SET_WOWLAN: set Wake-on-Wireless-LAN (WoWLAN) settings. + * Since wireless is more complex than wired ethernet, it supports + * various triggers. These triggers can be configured through this + * command with the %NL80211_ATTR_WOWLAN_TRIGGERS attribute. For + * more background information, see + * http://wireless.kernel.org/en/users/Documentation/WoWLAN. + * The @NL80211_CMD_SET_WOWLAN command can also be used as a notification + * from the driver reporting the wakeup reason. In this case, the + * @NL80211_ATTR_WOWLAN_TRIGGERS attribute will contain the reason + * for the wakeup, if it was caused by wireless. If it is not present + * in the wakeup notification, the wireless device didn't cause the + * wakeup but reports that it was woken up. + * @NL80211_CMD_SET_REKEY_OFFLOAD: This command is used give the driver + * the necessary information for supporting GTK rekey offload. This + * feature is typically used during WoWLAN. The configuration data + * is contained in %NL80211_ATTR_REKEY_DATA (which is nested and + * contains the data in sub-attributes). After rekeying happened, + * this command may also be sent by the driver as an MLME event to + * inform userspace of the new replay counter. + * @NL80211_CMD_PMKSA_CANDIDATE: This is used as an event to inform userspace + * of PMKSA caching dandidates. + * @NL80211_CMD_TDLS_OPER: Perform a high-level TDLS command (e.g. link setup). + * In addition, this can be used as an event to request userspace to take + * actions on TDLS links (set up a new link or tear down an existing one). + * In such events, %NL80211_ATTR_TDLS_OPERATION indicates the requested + * operation, %NL80211_ATTR_MAC contains the peer MAC address, and + * %NL80211_ATTR_REASON_CODE the reason code to be used (only with + * %NL80211_TDLS_TEARDOWN). + * @NL80211_CMD_TDLS_MGMT: Send a TDLS management frame. + * @NL80211_CMD_UNEXPECTED_FRAME: Used by an application controlling an AP + * (or GO) interface (i.e. hostapd) to ask for unexpected frames to + * implement sending deauth to stations that send unexpected class 3 + * frames. Also used as the event sent by the kernel when such a frame + * is received. + * For the event, the %NL80211_ATTR_MAC attribute carries the TA and + * other attributes like the interface index are present. + * If used as the command it must have an interface index and you can + * only unsubscribe from the event by closing the socket. Subscription + * is also for %NL80211_CMD_UNEXPECTED_4ADDR_FRAME events. + * @NL80211_CMD_UNEXPECTED_4ADDR_FRAME: Sent as an event indicating that the + * associated station identified by %NL80211_ATTR_MAC sent a 4addr frame + * and wasn't already in a 4-addr VLAN. The event will be sent similarly + * to the %NL80211_CMD_UNEXPECTED_FRAME event, to the same listener. + * @NL80211_CMD_PROBE_CLIENT: Probe an associated station on an AP interface + * by sending a null data frame to it and reporting when the frame is + * acknowleged. This is used to allow timing out inactive clients. Uses + * %NL80211_ATTR_IFINDEX and %NL80211_ATTR_MAC. The command returns a + * direct reply with an %NL80211_ATTR_COOKIE that is later used to match + * up the event with the request. The event includes the same data and + * has %NL80211_ATTR_ACK set if the frame was ACKed. + * @NL80211_CMD_REGISTER_BEACONS: Register this socket to receive beacons from + * other BSSes when any interfaces are in AP mode. This helps implement + * OLBC handling in hostapd. Beacons are reported in %NL80211_CMD_FRAME + * messages. Note that per PHY only one application may register. + * @NL80211_CMD_SET_NOACK_MAP: sets a bitmap for the individual TIDs whether + * No Acknowledgement Policy should be applied. + * @NL80211_CMD_CH_SWITCH_NOTIFY: An AP or GO may decide to switch channels + * independently of the userspace SME, send this event indicating + * %NL80211_ATTR_IFINDEX is now on %NL80211_ATTR_WIPHY_FREQ and the + * attributes determining channel width. + * @NL80211_CMD_START_P2P_DEVICE: Start the given P2P Device, identified by + * its %NL80211_ATTR_WDEV identifier. It must have been created with + * %NL80211_CMD_NEW_INTERFACE previously. After it has been started, the + * P2P Device can be used for P2P operations, e.g. remain-on-channel and + * public action frame TX. + * @NL80211_CMD_STOP_P2P_DEVICE: Stop the given P2P Device, identified by + * its %NL80211_ATTR_WDEV identifier. + * @NL80211_CMD_CONN_FAILED: connection request to an AP failed; used to + * notify userspace that AP has rejected the connection request from a + * station, due to particular reason. %NL80211_ATTR_CONN_FAILED_REASON + * is used for this. + * @NL80211_CMD_SET_MCAST_RATE: Change the rate used to send multicast frames + * for IBSS or MESH vif. + * @NL80211_CMD_SET_MAC_ACL: sets ACL for MAC address based access control. + * This is to be used with the drivers advertising the support of MAC + * address based access control. List of MAC addresses is passed in + * %NL80211_ATTR_MAC_ADDRS and ACL policy is passed in + * %NL80211_ATTR_ACL_POLICY. Driver will enable ACL with this list, if it + * is not already done. The new list will replace any existing list. Driver + * will clear its ACL when the list of MAC addresses passed is empty. This + * command is used in AP/P2P GO mode. Driver has to make sure to clear its + * ACL list during %NL80211_CMD_STOP_AP. + * @NL80211_CMD_RADAR_DETECT: Start a Channel availability check (CAC). Once + * a radar is detected or the channel availability scan (CAC) has finished + * or was aborted, or a radar was detected, usermode will be notified with + * this event. This command is also used to notify userspace about radars + * while operating on this channel. + * %NL80211_ATTR_RADAR_EVENT is used to inform about the type of the + * event. + * @NL80211_CMD_GET_PROTOCOL_FEATURES: Get global nl80211 protocol features, + * i.e. features for the nl80211 protocol rather than device features. + * Returns the features in the %NL80211_ATTR_PROTOCOL_FEATURES bitmap. + * @NL80211_CMD_UPDATE_FT_IES: Pass down the most up-to-date Fast Transition + * Information Element to the WLAN driver + * @NL80211_CMD_FT_EVENT: Send a Fast transition event from the WLAN driver + * to the supplicant. This will carry the target AP's MAC address along + * with the relevant Information Elements. This event is used to report + * received FT IEs (MDIE, FTIE, RSN IE, TIE, RICIE). + * @NL80211_CMD_CRIT_PROTOCOL_START: Indicates user-space will start running + * a critical protocol that needs more reliability in the connection to + * complete. + * @NL80211_CMD_CRIT_PROTOCOL_STOP: Indicates the connection reliability can + * return back to normal. + * @NL80211_CMD_GET_COALESCE: Get currently supported coalesce rules. + * @NL80211_CMD_SET_COALESCE: Configure coalesce rules or clear existing rules. + * @NL80211_CMD_CHANNEL_SWITCH: Perform a channel switch by announcing the + * the new channel information (Channel Switch Announcement - CSA) + * in the beacon for some time (as defined in the + * %NL80211_ATTR_CH_SWITCH_COUNT parameter) and then change to the + * new channel. Userspace provides the new channel information (using + * %NL80211_ATTR_WIPHY_FREQ and the attributes determining channel + * width). %NL80211_ATTR_CH_SWITCH_BLOCK_TX may be supplied to inform + * other station that transmission must be blocked until the channel + * switch is complete. + * @NL80211_CMD_MAX: highest used command number + */ +""" +NL80211_CMD_UNSPEC = 0 +NL80211_CMD_GET_WIPHY = 1 +NL80211_CMD_SET_WIPHY = 2 +NL80211_CMD_NEW_WIPHY = 3 +NL80211_CMD_DEL_WIPHY = 4 +NL80211_CMD_GET_INTERFACE = 5 +NL80211_CMD_SET_INTERFACE = 6 +NL80211_CMD_NEW_INTERFACE = 7 +NL80211_CMD_DEL_INTERFACE = 8 +NL80211_CMD_GET_KEY = 9 +NL80211_CMD_SET_KEY = 10 +NL80211_CMD_NEW_KEY = 11 +NL80211_CMD_DEL_KEY = 12 +NL80211_CMD_GET_BEACON = 13 +NL80211_CMD_SET_BEACON = 14 +NL80211_CMD_START_AP = 15 +NL80211_CMD_NEW_BEACON = NL80211_CMD_START_AP +NL80211_CMD_STOP_AP = 16 +NL80211_CMD_DEL_BEACON = NL80211_CMD_STOP_AP +NL80211_CMD_GET_STATION = 17 +NL80211_CMD_SET_STATION = 18 +NL80211_CMD_NEW_STATION = 19 +NL80211_CMD_DEL_STATION = 20 +NL80211_CMD_GET_MPATH = 21 +NL80211_CMD_SET_MPATH = 22 +NL80211_CMD_NEW_MPATH = 23 +NL80211_CMD_DEL_MPATH = 24 +NL80211_CMD_SET_BSS = 25 +NL80211_CMD_SET_REG = 26 +NL80211_CMD_REQ_SET_REG = 27 +NL80211_CMD_GET_MESH_CONFIG = 28 +NL80211_CMD_SET_MESH_CONFIG = 29 +NL80211_CMD_SET_MGMT_EXTRA_IE = 30 # reserved; not used +NL80211_CMD_GET_REG = 31 +NL80211_CMD_GET_SCAN = 32 +NL80211_CMD_TRIGGER_SCAN = 33 +NL80211_CMD_NEW_SCAN_RESULTS = 34 +NL80211_CMD_SCAN_ABORTED = 35 +NL80211_CMD_REG_CHANGE = 36 +NL80211_CMD_AUTHENTICATE = 37 +NL80211_CMD_ASSOCIATE = 38 +NL80211_CMD_DEAUTHENTICATE = 39 +NL80211_CMD_DISASSOCIATE = 40 +NL80211_CMD_MICHAEL_MIC_FAILURE = 41 +NL80211_CMD_REG_BEACON_HINT = 42 +NL80211_CMD_JOIN_IBSS = 43 +NL80211_CMD_LEAVE_IBSS = 44 +NL80211_CMD_TESTMODE = 45 +NL80211_CMD_CONNECT = 46 +NL80211_CMD_ROAM = 47 +NL80211_CMD_DISCONNECT = 48 +NL80211_CMD_SET_WIPHY_NETNS = 49 +NL80211_CMD_GET_SURVEY = 50 +NL80211_CMD_NEW_SURVEY_RESULTS = 51 +NL80211_CMD_SET_PMKSA = 52 +NL80211_CMD_DEL_PMKSA = 53 +NL80211_CMD_FLUSH_PMKSA = 54 +NL80211_CMD_REMAIN_ON_CHANNEL = 55 +NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL = 56 +NL80211_CMD_SET_TX_BITRATE_MASK = 57 +NL80211_CMD_REGISTER_FRAME = 58 +NL80211_CMD_REGISTER_ACTION = NL80211_CMD_REGISTER_FRAME +NL80211_CMD_FRAME = 59 +NL80211_CMD_ACTION = NL80211_CMD_FRAME +NL80211_CMD_FRAME_TX_STATUS = 60 +NL80211_CMD_ACTION_TX_STATUS = NL80211_CMD_FRAME_TX_STATUS +NL80211_CMD_SET_POWER_SAVE = 61 +NL80211_CMD_GET_POWER_SAVE = 62 +NL80211_CMD_SET_CQM = 63 +NL80211_CMD_NOTIFY_CQM = 64 +NL80211_CMD_SET_CHANNEL = 65 +NL80211_CMD_SET_WDS_PEER = 66 +NL80211_CMD_FRAME_WAIT_CANCEL = 67 +NL80211_CMD_JOIN_MESH = 68 +NL80211_CMD_LEAVE_MESH = 69 +NL80211_CMD_UNPROT_DEAUTHENTICATE = 70 +NL80211_CMD_UNPROT_DISASSOCIATE = 71 +NL80211_CMD_NEW_PEER_CANDIDATE = 72 +NL80211_CMD_GET_WOWLAN = 73 +NL80211_CMD_SET_WOWLAN = 74 +NL80211_CMD_START_SCHED_SCAN = 75 +NL80211_CMD_STOP_SCHED_SCAN = 76 +NL80211_CMD_SCHED_SCAN_RESULTS = 77 +NL80211_CMD_SCHED_SCAN_STOPPED = 78 +NL80211_CMD_SET_REKEY_OFFLOAD = 79 +NL80211_CMD_PMKSA_CANDIDATE = 80 +NL80211_CMD_TDLS_OPER = 81 +NL80211_CMD_TDLS_MGMT = 82 +NL80211_CMD_UNEXPECTED_FRAME = 83 +NL80211_CMD_PROBE_CLIENT = 84 +NL80211_CMD_REGISTER_BEACONS = 85 +NL80211_CMD_UNEXPECTED_4ADDR_FRAME = 86 +NL80211_CMD_SET_NOACK_MAP = 87 +NL80211_CMD_CH_SWITCH_NOTIFY = 88 +NL80211_CMD_START_P2P_DEVICE = 89 +NL80211_CMD_STOP_P2P_DEVICE = 90 +NL80211_CMD_CONN_FAILED = 91 +NL80211_CMD_SET_MCAST_RATE = 92 +NL80211_CMD_SET_MAC_ACL = 93 +NL80211_CMD_RADAR_DETECT = 94 +NL80211_CMD_GET_PROTOCOL_FEATURES = 95 +NL80211_CMD_UPDATE_FT_IES = 96 +NL80211_CMD_FT_EVENT = 97 +NL80211_CMD_CRIT_PROTOCOL_START = 98 +NL80211_CMD_CRIT_PROTOCOL_STOP = 99 +NL80211_CMD_GET_COALESCE = 100 +NL80211_CMD_SET_COALESCE = 101 +NL80211_CMD_CHANNEL_SWITCH = 102 +# add new commands above here +MAX_NL80211_CMD = 102 + +# source-level API compatibility +NL80211_CMD_GET_MESH_PARAMS = NL80211_CMD_GET_MESH_CONFIG +NL80211_CMD_SET_MESH_PARAMS = NL80211_CMD_SET_MESH_CONFIG +#NL80211_MESH_SETUP_VENDOR_PATH_SEL_IE = NL80211_MESH_SETUP_IE + +""" +/** + * enum nl80211_attrs - nl80211 netlink attributes + * + * @NL80211_ATTR_UNSPEC: unspecified attribute to catch errors + * @NL80211_ATTR_WIPHY: index of wiphy to operate on, cf. + * /sys/class/ieee80211//index + * @NL80211_ATTR_WIPHY_NAME: wiphy name (used for renaming) + * @NL80211_ATTR_WIPHY_TXQ_PARAMS: a nested array of TX queue parameters + * @NL80211_ATTR_WIPHY_FREQ: frequency of the selected channel in MHz, + * defines the channel together with the (deprecated) + * %NL80211_ATTR_WIPHY_CHANNEL_TYPE attribute or the attributes + * %NL80211_ATTR_CHANNEL_WIDTH and if needed %NL80211_ATTR_CENTER_FREQ1 + * and %NL80211_ATTR_CENTER_FREQ2 + * @NL80211_ATTR_CHANNEL_WIDTH: u32 attribute containing one of the values + * of &enum nl80211_chan_width, describing the channel width. See the + * documentation of the enum for more information. + * @NL80211_ATTR_CENTER_FREQ1: Center frequency of the first part of the + * channel, used for anything but 20 MHz bandwidth + * @NL80211_ATTR_CENTER_FREQ2: Center frequency of the second part of the + * channel, used only for 80+80 MHz bandwidth + * @NL80211_ATTR_WIPHY_CHANNEL_TYPE: included with NL80211_ATTR_WIPHY_FREQ + * if HT20 or HT40 are to be used (i.e., HT disabled if not included): + * NL80211_CHAN_NO_HT = HT not allowed (same as not including) + * NL80211_CHAN_HT20 = HT20 only + * NL80211_CHAN_HT40MINUS = secondary channel is below the primary channel + * NL80211_CHAN_HT40PLUS = secondary channel is above the primary channel + * This attribute is now deprecated. + * @NL80211_ATTR_WIPHY_RETRY_SHORT: TX retry limit for frames whose length is + * less than or equal to the RTS threshold; allowed range: 1..255; + * dot11ShortRetryLimit; u8 + * @NL80211_ATTR_WIPHY_RETRY_LONG: TX retry limit for frames whose length is + * greater than the RTS threshold; allowed range: 1..255; + * dot11ShortLongLimit; u8 + * @NL80211_ATTR_WIPHY_FRAG_THRESHOLD: fragmentation threshold, i.e., maximum + * length in octets for frames; allowed range: 256..8000, disable + * fragmentation with (u32)-1; dot11FragmentationThreshold; u32 + * @NL80211_ATTR_WIPHY_RTS_THRESHOLD: RTS threshold (TX frames with length + * larger than or equal to this use RTS/CTS handshake); allowed range: + * 0..65536, disable with (u32)-1; dot11RTSThreshold; u32 + * @NL80211_ATTR_WIPHY_COVERAGE_CLASS: Coverage Class as defined by IEEE 802.11 + * section 7.3.2.9; dot11CoverageClass; u8 + * @NL80211_ATTR_IFINDEX: network interface index of the device to operate on + * @NL80211_ATTR_IFNAME: network interface name + * @NL80211_ATTR_IFTYPE: type of virtual interface, see &enum nl80211_iftype + * @NL80211_ATTR_WDEV: wireless device identifier, used for pseudo-devices + * that don't have a netdev (u64) + * @NL80211_ATTR_MAC: MAC address (various uses) + * @NL80211_ATTR_KEY_DATA: (temporal) key data; for TKIP this consists of + * 16 bytes encryption key followed by 8 bytes each for TX and RX MIC keys + * @NL80211_ATTR_KEY_IDX: key ID (u8, 0-3) + * @NL80211_ATTR_KEY_CIPHER: key cipher suite (u32, as defined by IEEE 802.11 + * section 7.3.2.25.1, e.g. 0x000FAC04) + * @NL80211_ATTR_KEY_SEQ: transmit key sequence number (IV/PN) for TKIP and + * CCMP keys, each six bytes in little endian + * @NL80211_ATTR_KEY_DEFAULT: Flag attribute indicating the key is default key + * @NL80211_ATTR_KEY_DEFAULT_MGMT: Flag attribute indicating the key is the + * default management key + * @NL80211_ATTR_CIPHER_SUITES_PAIRWISE: For crypto settings for connect or + * other commands, indicates which pairwise cipher suites are used + * @NL80211_ATTR_CIPHER_SUITE_GROUP: For crypto settings for connect or + * other commands, indicates which group cipher suite is used + * @NL80211_ATTR_BEACON_INTERVAL: beacon interval in TU + * @NL80211_ATTR_DTIM_PERIOD: DTIM period for beaconing + * @NL80211_ATTR_BEACON_HEAD: portion of the beacon before the TIM IE + * @NL80211_ATTR_BEACON_TAIL: portion of the beacon after the TIM IE + * @NL80211_ATTR_STA_AID: Association ID for the station (u16) + * @NL80211_ATTR_STA_FLAGS: flags, nested element with NLA_FLAG attributes of + * &enum nl80211_sta_flags (deprecated, use %NL80211_ATTR_STA_FLAGS2) + * @NL80211_ATTR_STA_LISTEN_INTERVAL: listen interval as defined by + * IEEE 802.11 7.3.1.6 (u16). + * @NL80211_ATTR_STA_SUPPORTED_RATES: supported rates, array of supported + * rates as defined by IEEE 802.11 7.3.2.2 but without the length + * restriction (at most %NL80211_MAX_SUPP_RATES). + * @NL80211_ATTR_STA_VLAN: interface index of VLAN interface to move station + * to, or the AP interface the station was originally added to to. + * @NL80211_ATTR_STA_INFO: information about a station, part of station info + * given for %NL80211_CMD_GET_STATION, nested attribute containing + * info as possible, see &enum nl80211_sta_info. + * @NL80211_ATTR_WIPHY_BANDS: Information about an operating bands, + * consisting of a nested array. + * @NL80211_ATTR_MESH_ID: mesh id (1-32 bytes). + * @NL80211_ATTR_STA_PLINK_ACTION: action to perform on the mesh peer link + * (see &enum nl80211_plink_action). + * @NL80211_ATTR_MPATH_NEXT_HOP: MAC address of the next hop for a mesh path. + * @NL80211_ATTR_MPATH_INFO: information about a mesh_path, part of mesh path + * info given for %NL80211_CMD_GET_MPATH, nested attribute described at + * &enum nl80211_mpath_info. + * @NL80211_ATTR_MNTR_FLAGS: flags, nested element with NLA_FLAG attributes of + * &enum nl80211_mntr_flags. + * @NL80211_ATTR_REG_ALPHA2: an ISO-3166-alpha2 country code for which the + * current regulatory domain should be set to or is already set to. + * For example, 'CR', for Costa Rica. This attribute is used by the kernel + * to query the CRDA to retrieve one regulatory domain. This attribute can + * also be used by userspace to query the kernel for the currently set + * regulatory domain. We chose an alpha2 as that is also used by the + * IEEE-802.11 country information element to identify a country. + * Users can also simply ask the wireless core to set regulatory domain + * to a specific alpha2. + * @NL80211_ATTR_REG_RULES: a nested array of regulatory domain regulatory + * rules. + * @NL80211_ATTR_BSS_CTS_PROT: whether CTS protection is enabled (u8, 0 or 1) + * @NL80211_ATTR_BSS_SHORT_PREAMBLE: whether short preamble is enabled + * (u8, 0 or 1) + * @NL80211_ATTR_BSS_SHORT_SLOT_TIME: whether short slot time enabled + * (u8, 0 or 1) + * @NL80211_ATTR_BSS_BASIC_RATES: basic rates, array of basic + * rates in format defined by IEEE 802.11 7.3.2.2 but without the length + * restriction (at most %NL80211_MAX_SUPP_RATES). + * @NL80211_ATTR_HT_CAPABILITY: HT Capability information element (from + * association request when used with NL80211_CMD_NEW_STATION) + * @NL80211_ATTR_SUPPORTED_IFTYPES: nested attribute containing all + * supported interface types, each a flag attribute with the number + * of the interface mode. + * @NL80211_ATTR_MGMT_SUBTYPE: Management frame subtype for + * %NL80211_CMD_SET_MGMT_EXTRA_IE. + * @NL80211_ATTR_IE: Information element(s) data (used, e.g., with + * %NL80211_CMD_SET_MGMT_EXTRA_IE). + * @NL80211_ATTR_MAX_NUM_SCAN_SSIDS: number of SSIDs you can scan with + * a single scan request, a wiphy attribute. + * @NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS: number of SSIDs you can + * scan with a single scheduled scan request, a wiphy attribute. + * @NL80211_ATTR_MAX_SCAN_IE_LEN: maximum length of information elements + * that can be added to a scan request + * @NL80211_ATTR_MAX_SCHED_SCAN_IE_LEN: maximum length of information + * elements that can be added to a scheduled scan request + * @NL80211_ATTR_MAX_MATCH_SETS: maximum number of sets that can be + * used with @NL80211_ATTR_SCHED_SCAN_MATCH, a wiphy attribute. + * @NL80211_ATTR_SCAN_FREQUENCIES: nested attribute with frequencies (in MHz) + * @NL80211_ATTR_SCAN_SSIDS: nested attribute with SSIDs, leave out for passive + * scanning and include a zero-length SSID (wildcard) for wildcard scan + * @NL80211_ATTR_BSS: scan result BSS + * @NL80211_ATTR_REG_INITIATOR: indicates who requested the regulatory domain + * currently in effect. This could be any of the %NL80211_REGDOM_SET_BY_* + * @NL80211_ATTR_REG_TYPE: indicates the type of the regulatory domain currently + * set. This can be one of the nl80211_reg_type (%NL80211_REGDOM_TYPE_*) + * @NL80211_ATTR_SUPPORTED_COMMANDS: wiphy attribute that specifies + * an array of command numbers (i.e. a mapping index to command number) + * that the driver for the given wiphy supports. + * @NL80211_ATTR_FRAME: frame data (binary attribute), including frame header + * and body, but not FCS; used, e.g., with NL80211_CMD_AUTHENTICATE and + * NL80211_CMD_ASSOCIATE events + * @NL80211_ATTR_SSID: SSID (binary attribute, 0..32 octets) + * @NL80211_ATTR_AUTH_TYPE: AuthenticationType, see &enum nl80211_auth_type, + * represented as a u32 + * @NL80211_ATTR_REASON_CODE: ReasonCode for %NL80211_CMD_DEAUTHENTICATE and + * %NL80211_CMD_DISASSOCIATE, u16 + * @NL80211_ATTR_KEY_TYPE: Key Type, see &enum nl80211_key_type, a u32 + * @NL80211_ATTR_FREQ_BEFORE: A channel which has suffered a regulatory change + * due to considerations from a beacon hint. This attribute reflects + * the state of the channel _before_ the beacon hint processing. This + * attributes consists of a nested attribute containing + * NL80211_FREQUENCY_ATTR_* + * @NL80211_ATTR_FREQ_AFTER: A channel which has suffered a regulatory change + * due to considerations from a beacon hint. This attribute reflects + * the state of the channel _after_ the beacon hint processing. This + * attributes consists of a nested attribute containing + * NL80211_FREQUENCY_ATTR_* + * @NL80211_ATTR_CIPHER_SUITES: a set of u32 values indicating the supported + * cipher suites + * @NL80211_ATTR_FREQ_FIXED: a flag indicating the IBSS should not try to look + * for other networks on different channels + * @NL80211_ATTR_TIMED_OUT: a flag indicating than an operation timed out; this + * is used, e.g., with %NL80211_CMD_AUTHENTICATE event + * @NL80211_ATTR_USE_MFP: Whether management frame protection (IEEE 802.11w) is + * used for the association (&enum nl80211_mfp, represented as a u32); + * this attribute can be used + * with %NL80211_CMD_ASSOCIATE and %NL80211_CMD_CONNECT requests + * @NL80211_ATTR_STA_FLAGS2: Attribute containing a + * &struct nl80211_sta_flag_update. + * @NL80211_ATTR_CONTROL_PORT: A flag indicating whether user space controls + * IEEE 802.1X port, i.e., sets/clears %NL80211_STA_FLAG_AUTHORIZED, in + * station mode. If the flag is included in %NL80211_CMD_ASSOCIATE + * request, the driver will assume that the port is unauthorized until + * authorized by user space. Otherwise, port is marked authorized by + * default in station mode. + * @NL80211_ATTR_CONTROL_PORT_ETHERTYPE: A 16-bit value indicating the + * ethertype that will be used for key negotiation. It can be + * specified with the associate and connect commands. If it is not + * specified, the value defaults to 0x888E (PAE, 802.1X). This + * attribute is also used as a flag in the wiphy information to + * indicate that protocols other than PAE are supported. + * @NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT: When included along with + * %NL80211_ATTR_CONTROL_PORT_ETHERTYPE, indicates that the custom + * ethertype frames used for key negotiation must not be encrypted. + * @NL80211_ATTR_TESTDATA: Testmode data blob, passed through to the driver. + * We recommend using nested, driver-specific attributes within this. + * @NL80211_ATTR_DISCONNECTED_BY_AP: A flag indicating that the DISCONNECT + * event was due to the AP disconnecting the station, and not due to + * a local disconnect request. + * @NL80211_ATTR_STATUS_CODE: StatusCode for the %NL80211_CMD_CONNECT + * event (u16) + * @NL80211_ATTR_PRIVACY: Flag attribute, used with connect(), indicating + * that protected APs should be used. This is also used with NEW_BEACON to + * indicate that the BSS is to use protection. + * @NL80211_ATTR_CIPHERS_PAIRWISE: Used with CONNECT, ASSOCIATE, and NEW_BEACON + * to indicate which unicast key ciphers will be used with the connection + * (an array of u32). + * @NL80211_ATTR_CIPHER_GROUP: Used with CONNECT, ASSOCIATE, and NEW_BEACON to + * indicate which group key cipher will be used with the connection, a u32 + * @NL80211_ATTR_WPA_VERSIONS: Used with CONNECT, ASSOCIATE, and NEW_BEACON to + * indicate which WPA version(s) the AP we want to associate with is using + * (a u32 with flags from &enum nl80211_wpa_versions). + * @NL80211_ATTR_AKM_SUITES: Used with CONNECT, ASSOCIATE, and NEW_BEACON to + * indicate which key management algorithm(s) to use (an array of u32). + * @NL80211_ATTR_REQ_IE: (Re)association request information elements as + * sent out by the card, for ROAM and successful CONNECT events. + * @NL80211_ATTR_RESP_IE: (Re)association response information elements as + * sent by peer, for ROAM and successful CONNECT events. + * @NL80211_ATTR_PREV_BSSID: previous BSSID, to be used by in ASSOCIATE + * commands to specify using a reassociate frame + * @NL80211_ATTR_KEY: key information in a nested attribute with + * %NL80211_KEY_* sub-attributes + * @NL80211_ATTR_KEYS: array of keys for static WEP keys for connect() + * and join_ibss(), key information is in a nested attribute each + * with %NL80211_KEY_* sub-attributes + * @NL80211_ATTR_PID: Process ID of a network namespace. + * @NL80211_ATTR_GENERATION: Used to indicate consistent snapshots for + * dumps. This number increases whenever the object list being + * dumped changes, and as such userspace can verify that it has + * obtained a complete and consistent snapshot by verifying that + * all dump messages contain the same generation number. If it + * changed then the list changed and the dump should be repeated + * completely from scratch. + * @NL80211_ATTR_4ADDR: Use 4-address frames on a virtual interface + * @NL80211_ATTR_SURVEY_INFO: survey information about a channel, part of + * the survey response for %NL80211_CMD_GET_SURVEY, nested attribute + * containing info as possible, see &enum survey_info. + * @NL80211_ATTR_PMKID: PMK material for PMKSA caching. + * @NL80211_ATTR_MAX_NUM_PMKIDS: maximum number of PMKIDs a firmware can + * cache, a wiphy attribute. + * @NL80211_ATTR_DURATION: Duration of an operation in milliseconds, u32. + * @NL80211_ATTR_MAX_REMAIN_ON_CHANNEL_DURATION: Device attribute that + * specifies the maximum duration that can be requested with the + * remain-on-channel operation, in milliseconds, u32. + * @NL80211_ATTR_COOKIE: Generic 64-bit cookie to identify objects. + * @NL80211_ATTR_TX_RATES: Nested set of attributes + * (enum nl80211_tx_rate_attributes) describing TX rates per band. The + * enum nl80211_band value is used as the index (nla_type() of the nested + * data. If a band is not included, it will be configured to allow all + * rates based on negotiated supported rates information. This attribute + * is used with %NL80211_CMD_SET_TX_BITRATE_MASK. + * @NL80211_ATTR_FRAME_MATCH: A binary attribute which typically must contain + * at least one byte, currently used with @NL80211_CMD_REGISTER_FRAME. + * @NL80211_ATTR_FRAME_TYPE: A u16 indicating the frame type/subtype for the + * @NL80211_CMD_REGISTER_FRAME command. + * @NL80211_ATTR_TX_FRAME_TYPES: wiphy capability attribute, which is a + * nested attribute of %NL80211_ATTR_FRAME_TYPE attributes, containing + * information about which frame types can be transmitted with + * %NL80211_CMD_FRAME. + * @NL80211_ATTR_RX_FRAME_TYPES: wiphy capability attribute, which is a + * nested attribute of %NL80211_ATTR_FRAME_TYPE attributes, containing + * information about which frame types can be registered for RX. + * @NL80211_ATTR_ACK: Flag attribute indicating that the frame was + * acknowledged by the recipient. + * @NL80211_ATTR_PS_STATE: powersave state, using &enum nl80211_ps_state values. + * @NL80211_ATTR_CQM: connection quality monitor configuration in a + * nested attribute with %NL80211_ATTR_CQM_* sub-attributes. + * @NL80211_ATTR_LOCAL_STATE_CHANGE: Flag attribute to indicate that a command + * is requesting a local authentication/association state change without + * invoking actual management frame exchange. This can be used with + * NL80211_CMD_AUTHENTICATE, NL80211_CMD_DEAUTHENTICATE, + * NL80211_CMD_DISASSOCIATE. + * @NL80211_ATTR_AP_ISOLATE: (AP mode) Do not forward traffic between stations + * connected to this BSS. + * @NL80211_ATTR_WIPHY_TX_POWER_SETTING: Transmit power setting type. See + * &enum nl80211_tx_power_setting for possible values. + * @NL80211_ATTR_WIPHY_TX_POWER_LEVEL: Transmit power level in signed mBm units. + * This is used in association with @NL80211_ATTR_WIPHY_TX_POWER_SETTING + * for non-automatic settings. + * @NL80211_ATTR_SUPPORT_IBSS_RSN: The device supports IBSS RSN, which mostly + * means support for per-station GTKs. + * @NL80211_ATTR_WIPHY_ANTENNA_TX: Bitmap of allowed antennas for transmitting. + * This can be used to mask out antennas which are not attached or should + * not be used for transmitting. If an antenna is not selected in this + * bitmap the hardware is not allowed to transmit on this antenna. + * Each bit represents one antenna, starting with antenna 1 at the first + * bit. Depending on which antennas are selected in the bitmap, 802.11n + * drivers can derive which chainmasks to use (if all antennas belonging to + * a particular chain are disabled this chain should be disabled) and if + * a chain has diversity antennas wether diversity should be used or not. + * HT capabilities (STBC, TX Beamforming, Antenna selection) can be + * derived from the available chains after applying the antenna mask. + * Non-802.11n drivers can derive wether to use diversity or not. + * Drivers may reject configurations or RX/TX mask combinations they cannot + * support by returning -EINVAL. + * @NL80211_ATTR_WIPHY_ANTENNA_RX: Bitmap of allowed antennas for receiving. + * This can be used to mask out antennas which are not attached or should + * not be used for receiving. If an antenna is not selected in this bitmap + * the hardware should not be configured to receive on this antenna. + * For a more detailed description see @NL80211_ATTR_WIPHY_ANTENNA_TX. + * @NL80211_ATTR_WIPHY_ANTENNA_AVAIL_TX: Bitmap of antennas which are available + * for configuration as TX antennas via the above parameters. + * @NL80211_ATTR_WIPHY_ANTENNA_AVAIL_RX: Bitmap of antennas which are available + * for configuration as RX antennas via the above parameters. + * @NL80211_ATTR_MCAST_RATE: Multicast tx rate (in 100 kbps) for IBSS + * @NL80211_ATTR_OFFCHANNEL_TX_OK: For management frame TX, the frame may be + * transmitted on another channel when the channel given doesn't match + * the current channel. If the current channel doesn't match and this + * flag isn't set, the frame will be rejected. This is also used as an + * nl80211 capability flag. + * @NL80211_ATTR_BSS_HT_OPMODE: HT operation mode (u16) + * @NL80211_ATTR_KEY_DEFAULT_TYPES: A nested attribute containing flags + * attributes, specifying what a key should be set as default as. + * See &enum nl80211_key_default_types. + * @NL80211_ATTR_MESH_SETUP: Optional mesh setup parameters. These cannot be + * changed once the mesh is active. + * @NL80211_ATTR_MESH_CONFIG: Mesh configuration parameters, a nested attribute + * containing attributes from &enum nl80211_meshconf_params. + * @NL80211_ATTR_SUPPORT_MESH_AUTH: Currently, this means the underlying driver + * allows auth frames in a mesh to be passed to userspace for processing via + * the @NL80211_MESH_SETUP_USERSPACE_AUTH flag. + * @NL80211_ATTR_STA_PLINK_STATE: The state of a mesh peer link as defined in + * &enum nl80211_plink_state. Used when userspace is driving the peer link + * management state machine. @NL80211_MESH_SETUP_USERSPACE_AMPE or + * @NL80211_MESH_SETUP_USERSPACE_MPM must be enabled. + * @NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED: indicates, as part of the wiphy + * capabilities, the supported WoWLAN triggers + * @NL80211_ATTR_WOWLAN_TRIGGERS: used by %NL80211_CMD_SET_WOWLAN to + * indicate which WoW triggers should be enabled. This is also + * used by %NL80211_CMD_GET_WOWLAN to get the currently enabled WoWLAN + * triggers. + * @NL80211_ATTR_SCHED_SCAN_INTERVAL: Interval between scheduled scan + * cycles, in msecs. + * @NL80211_ATTR_SCHED_SCAN_MATCH: Nested attribute with one or more + * sets of attributes to match during scheduled scans. Only BSSs + * that match any of the sets will be reported. These are + * pass-thru filter rules. + * For a match to succeed, the BSS must match all attributes of a + * set. Since not every hardware supports matching all types of + * attributes, there is no guarantee that the reported BSSs are + * fully complying with the match sets and userspace needs to be + * able to ignore them by itself. + * Thus, the implementation is somewhat hardware-dependent, but + * this is only an optimization and the userspace application + * needs to handle all the non-filtered results anyway. + * If the match attributes don't make sense when combined with + * the values passed in @NL80211_ATTR_SCAN_SSIDS (eg. if an SSID + * is included in the probe request, but the match attributes + * will never let it go through), -EINVAL may be returned. + * If ommited, no filtering is done. + * @NL80211_ATTR_INTERFACE_COMBINATIONS: Nested attribute listing the supported + * interface combinations. In each nested item, it contains attributes + * defined in &enum nl80211_if_combination_attrs. + * @NL80211_ATTR_SOFTWARE_IFTYPES: Nested attribute (just like + * %NL80211_ATTR_SUPPORTED_IFTYPES) containing the interface types that + * are managed in software: interfaces of these types aren't subject to + * any restrictions in their number or combinations. + * @NL80211_ATTR_REKEY_DATA: nested attribute containing the information + * necessary for GTK rekeying in the device, see &enum nl80211_rekey_data. + * @NL80211_ATTR_SCAN_SUPP_RATES: rates per to be advertised as supported in scan, + * nested array attribute containing an entry for each band, with the entry + * being a list of supported rates as defined by IEEE 802.11 7.3.2.2 but + * without the length restriction (at most %NL80211_MAX_SUPP_RATES). + * @NL80211_ATTR_HIDDEN_SSID: indicates whether SSID is to be hidden from Beacon + * and Probe Response (when response to wildcard Probe Request); see + * &enum nl80211_hidden_ssid, represented as a u32 + * @NL80211_ATTR_IE_PROBE_RESP: Information element(s) for Probe Response frame. + * This is used with %NL80211_CMD_NEW_BEACON and %NL80211_CMD_SET_BEACON to + * provide extra IEs (e.g., WPS/P2P IE) into Probe Response frames when the + * driver (or firmware) replies to Probe Request frames. + * @NL80211_ATTR_IE_ASSOC_RESP: Information element(s) for (Re)Association + * Response frames. This is used with %NL80211_CMD_NEW_BEACON and + * %NL80211_CMD_SET_BEACON to provide extra IEs (e.g., WPS/P2P IE) into + * (Re)Association Response frames when the driver (or firmware) replies to + * (Re)Association Request frames. + * @NL80211_ATTR_STA_WME: Nested attribute containing the wme configuration + * of the station, see &enum nl80211_sta_wme_attr. + * @NL80211_ATTR_SUPPORT_AP_UAPSD: the device supports uapsd when working + * as AP. + * @NL80211_ATTR_ROAM_SUPPORT: Indicates whether the firmware is capable of + * roaming to another AP in the same ESS if the signal lever is low. + * @NL80211_ATTR_PMKSA_CANDIDATE: Nested attribute containing the PMKSA caching + * candidate information, see &enum nl80211_pmksa_candidate_attr. + * @NL80211_ATTR_TX_NO_CCK_RATE: Indicates whether to use CCK rate or not + * for management frames transmission. In order to avoid p2p probe/action + * frames are being transmitted at CCK rate in 2GHz band, the user space + * applications use this attribute. + * This attribute is used with %NL80211_CMD_TRIGGER_SCAN and + * %NL80211_CMD_FRAME commands. + * @NL80211_ATTR_TDLS_ACTION: Low level TDLS action code (e.g. link setup + * request, link setup confirm, link teardown, etc.). Values are + * described in the TDLS (802.11z) specification. + * @NL80211_ATTR_TDLS_DIALOG_TOKEN: Non-zero token for uniquely identifying a + * TDLS conversation between two devices. + * @NL80211_ATTR_TDLS_OPERATION: High level TDLS operation; see + * &enum nl80211_tdls_operation, represented as a u8. + * @NL80211_ATTR_TDLS_SUPPORT: A flag indicating the device can operate + * as a TDLS peer sta. + * @NL80211_ATTR_TDLS_EXTERNAL_SETUP: The TDLS discovery/setup and teardown + * procedures should be performed by sending TDLS packets via + * %NL80211_CMD_TDLS_MGMT. Otherwise %NL80211_CMD_TDLS_OPER should be + * used for asking the driver to perform a TDLS operation. + * @NL80211_ATTR_DEVICE_AP_SME: This u32 attribute may be listed for devices + * that have AP support to indicate that they have the AP SME integrated + * with support for the features listed in this attribute, see + * &enum nl80211_ap_sme_features. + * @NL80211_ATTR_DONT_WAIT_FOR_ACK: Used with %NL80211_CMD_FRAME, this tells + * the driver to not wait for an acknowledgement. Note that due to this, + * it will also not give a status callback nor return a cookie. This is + * mostly useful for probe responses to save airtime. + * @NL80211_ATTR_FEATURE_FLAGS: This u32 attribute contains flags from + * &enum nl80211_feature_flags and is advertised in wiphy information. + * @NL80211_ATTR_PROBE_RESP_OFFLOAD: Indicates that the HW responds to probe + * requests while operating in AP-mode. + * This attribute holds a bitmap of the supported protocols for + * offloading (see &enum nl80211_probe_resp_offload_support_attr). + * @NL80211_ATTR_PROBE_RESP: Probe Response template data. Contains the entire + * probe-response frame. The DA field in the 802.11 header is zero-ed out, + * to be filled by the FW. + * @NL80211_ATTR_DISABLE_HT: Force HT capable interfaces to disable + * this feature. Currently, only supported in mac80211 drivers. + * @NL80211_ATTR_HT_CAPABILITY_MASK: Specify which bits of the + * ATTR_HT_CAPABILITY to which attention should be paid. + * Currently, only mac80211 NICs support this feature. + * The values that may be configured are: + * MCS rates, MAX-AMSDU, HT-20-40 and HT_CAP_SGI_40 + * AMPDU density and AMPDU factor. + * All values are treated as suggestions and may be ignored + * by the driver as required. The actual values may be seen in + * the station debugfs ht_caps file. + * @NL80211_ATTR_DFS_REGION: region for regulatory rules which this country + * abides to when initiating radiation on DFS channels. A country maps + * to one DFS region. + * @NL80211_ATTR_NOACK_MAP: This u16 bitmap contains the No Ack Policy of + * up to 16 TIDs. + * @NL80211_ATTR_INACTIVITY_TIMEOUT: timeout value in seconds, this can be + * used by the drivers which has MLME in firmware and does not have support + * to report per station tx/rx activity to free up the staion entry from + * the list. This needs to be used when the driver advertises the + * capability to timeout the stations. + * @NL80211_ATTR_RX_SIGNAL_DBM: signal strength in dBm (as a 32-bit int); + * this attribute is (depending on the driver capabilities) added to + * received frames indicated with %NL80211_CMD_FRAME. + * @NL80211_ATTR_BG_SCAN_PERIOD: Background scan period in seconds + * or 0 to disable background scan. + * @NL80211_ATTR_USER_REG_HINT_TYPE: type of regulatory hint passed from + * userspace. If unset it is assumed the hint comes directly from + * a user. If set code could specify exactly what type of source + * was used to provide the hint. For the different types of + * allowed user regulatory hints see nl80211_user_reg_hint_type. + * @NL80211_ATTR_CONN_FAILED_REASON: The reason for which AP has rejected + * the connection request from a station. nl80211_connect_failed_reason + * enum has different reasons of connection failure. + * @NL80211_ATTR_SAE_DATA: SAE elements in Authentication frames. This starts + * with the Authentication transaction sequence number field. + * @NL80211_ATTR_VHT_CAPABILITY: VHT Capability information element (from + * association request when used with NL80211_CMD_NEW_STATION) + * @NL80211_ATTR_SCAN_FLAGS: scan request control flags (u32) + * @NL80211_ATTR_P2P_CTWINDOW: P2P GO Client Traffic Window (u8), used with + * the START_AP and SET_BSS commands + * @NL80211_ATTR_P2P_OPPPS: P2P GO opportunistic PS (u8), used with the + * START_AP and SET_BSS commands. This can have the values 0 or 1; + * if not given in START_AP 0 is assumed, if not given in SET_BSS + * no change is made. + * @NL80211_ATTR_LOCAL_MESH_POWER_MODE: local mesh STA link-specific power mode + * defined in &enum nl80211_mesh_power_mode. + * @NL80211_ATTR_ACL_POLICY: ACL policy, see &enum nl80211_acl_policy, + * carried in a u32 attribute + * @NL80211_ATTR_MAC_ADDRS: Array of nested MAC addresses, used for MAC ACL + * @NL80211_ATTR_MAC_ACL_MAX: u32 attribute to advertise the maximum + * number of MAC addresses that a device can support for MAC ACL + * @NL80211_ATTR_RADAR_EVENT: Type of radar event for notification to userspace, + * contains a value of enum nl80211_radar_event (u32). + * @NL80211_ATTR_EXT_CAPA: 802.11 extended capabilities that the kernel driver + * has and handles. The format is the same as the IE contents. See + * 802.11-2012 8.4.2.29 for more information. + * @NL80211_ATTR_EXT_CAPA_MASK: Extended capabilities that the kernel driver + * has set in the %NL80211_ATTR_EXT_CAPA value, for multibit fields. + * @NL80211_ATTR_STA_CAPABILITY: Station capabilities (u16) are advertised to + * the driver, e.g., to enable TDLS power save (PU-APSD). + * @NL80211_ATTR_STA_EXT_CAPABILITY: Station extended capabilities are + * advertised to the driver, e.g., to enable TDLS off channel operations + * and PU-APSD. + * @NL80211_ATTR_PROTOCOL_FEATURES: global nl80211 feature flags, see + * &enum nl80211_protocol_features, the attribute is a u32. + * @NL80211_ATTR_SPLIT_WIPHY_DUMP: flag attribute, userspace supports + * receiving the data for a single wiphy split across multiple + * messages, given with wiphy dump message + * @NL80211_ATTR_MDID: Mobility Domain Identifier + * @NL80211_ATTR_IE_RIC: Resource Information Container Information element + * @NL80211_ATTR_CRIT_PROT_ID: critical protocol identifier requiring increased + * reliability, see &enum nl80211_crit_proto_id (u16). + * @NL80211_ATTR_MAX_CRIT_PROT_DURATION: duration in milliseconds in which + * the connection should have increased reliability (u16). + * @NL80211_ATTR_PEER_AID: Association ID for the peer TDLS station (u16). + * This is similar to @NL80211_ATTR_STA_AID but with a difference of being + * allowed to be used with the first @NL80211_CMD_SET_STATION command to + * update a TDLS peer STA entry. + * @NL80211_ATTR_COALESCE_RULE: Coalesce rule information. + * @NL80211_ATTR_CH_SWITCH_COUNT: u32 attribute specifying the number of TBTT's + * until the channel switch event. + * @NL80211_ATTR_CH_SWITCH_BLOCK_TX: flag attribute specifying that transmission + * must be blocked on the current channel (before the channel switch + * operation). + * @NL80211_ATTR_CSA_IES: Nested set of attributes containing the IE information + * for the time while performing a channel switch. + * @NL80211_ATTR_CSA_C_OFF_BEACON: Offset of the channel switch counter + * field in the beacons tail (%NL80211_ATTR_BEACON_TAIL). + * @NL80211_ATTR_CSA_C_OFF_PRESP: Offset of the channel switch counter + * field in the probe response (%NL80211_ATTR_PROBE_RESP). + * @NL80211_ATTR_RXMGMT_FLAGS: flags for nl80211_send_mgmt(), u32. + * As specified in the &enum nl80211_rxmgmt_flags. + * @NL80211_ATTR_STA_SUPPORTED_CHANNELS: array of supported channels. + * @NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES: array of supported + * supported operating classes. + * @NL80211_ATTR_HANDLE_DFS: A flag indicating whether user space + * controls DFS operation in IBSS mode. If the flag is included in + * %NL80211_CMD_JOIN_IBSS request, the driver will allow use of DFS + * channels and reports radar events to userspace. Userspace is required + * to react to radar events, e.g. initiate a channel switch or leave the + * IBSS network. + * @NL80211_ATTR_MAX: highest attribute number currently defined + */ +""" + +# don't change the order or add anything between, this is ABI! +NL80211_ATTR_UNSPEC = 0 +NL80211_ATTR_WIPHY = 1 +NL80211_ATTR_WIPHY_NAME = 2 +NL80211_ATTR_IFINDEX = 3 +NL80211_ATTR_IFNAME = 4 +NL80211_ATTR_IFTYPE = 5 +NL80211_ATTR_MAC = 6 +NL80211_ATTR_KEY_DATA = 7 +NL80211_ATTR_KEY_IDX = 8 +NL80211_ATTR_KEY_CIPHER = 9 +NL80211_ATTR_KEY_SEQ = 10 +NL80211_ATTR_KEY_DEFAULT = 11 +NL80211_ATTR_BEACON_INTERVAL = 12 +NL80211_ATTR_DTIM_PERIOD = 13 +NL80211_ATTR_BEACON_HEAD = 14 +NL80211_ATTR_BEACON_TAIL = 15 +NL80211_ATTR_STA_AID = 16 +NL80211_ATTR_STA_FLAGS = 17 +NL80211_ATTR_STA_LISTEN_INTERVAL = 18 +NL80211_ATTR_STA_SUPPORTED_RATES = 19 +NL80211_ATTR_STA_VLAN = 20 +NL80211_ATTR_STA_INFO = 21 +NL80211_ATTR_WIPHY_BANDS = 22 +NL80211_ATTR_MNTR_FLAGS = 23 +NL80211_ATTR_MESH_ID = 24 +NL80211_ATTR_STA_PLINK_ACTION = 25 +NL80211_ATTR_MPATH_NEXT_HOP = 26 +NL80211_ATTR_MPATH_INFO = 27 +NL80211_ATTR_BSS_CTS_PROT = 28 +NL80211_ATTR_BSS_SHORT_PREAMBLE = 29 +NL80211_ATTR_BSS_SHORT_SLOT_TIME = 30 +NL80211_ATTR_HT_CAPABILITY = 31 +NL80211_ATTR_SUPPORTED_IFTYPES = 32 +NL80211_ATTR_REG_ALPHA2 = 33 +NL80211_ATTR_REG_RULES = 34 +NL80211_ATTR_MESH_CONFIG = 35 +NL80211_ATTR_BSS_BASIC_RATES = 36 +NL80211_ATTR_WIPHY_TXQ_PARAMS = 37 +NL80211_ATTR_WIPHY_FREQ = 38 +NL80211_ATTR_WIPHY_CHANNEL_TYPE = 39 +NL80211_ATTR_KEY_DEFAULT_MGMT = 40 +NL80211_ATTR_MGMT_SUBTYPE = 41 +NL80211_ATTR_IE = 42 +NL80211_ATTR_MAX_NUM_SCAN_SSIDS = 43 +NL80211_ATTR_SCAN_FREQUENCIES = 44 +NL80211_ATTR_SCAN_SSIDS = 45 +NL80211_ATTR_GENERATION = 46 # replaces old SCAN_GENERATION +NL80211_ATTR_BSS = 47 +NL80211_ATTR_REG_INITIATOR = 48 +NL80211_ATTR_REG_TYPE = 49 +NL80211_ATTR_SUPPORTED_COMMANDS = 50 +NL80211_ATTR_FRAME = 51 +NL80211_ATTR_SSID = 52 +NL80211_ATTR_AUTH_TYPE = 53 +NL80211_ATTR_REASON_CODE = 54 +NL80211_ATTR_KEY_TYPE = 55 +NL80211_ATTR_MAX_SCAN_IE_LEN = 56 +NL80211_ATTR_CIPHER_SUITES = 57 +NL80211_ATTR_FREQ_BEFORE = 58 +NL80211_ATTR_FREQ_AFTER = 59 +NL80211_ATTR_FREQ_FIXED = 60 +NL80211_ATTR_WIPHY_RETRY_SHORT = 61 +NL80211_ATTR_WIPHY_RETRY_LONG = 62 +NL80211_ATTR_WIPHY_FRAG_THRESHOLD = 63 +NL80211_ATTR_WIPHY_RTS_THRESHOLD = 64 +NL80211_ATTR_TIMED_OUT = 65 +NL80211_ATTR_USE_MFP = 66 +NL80211_ATTR_STA_FLAGS2 = 67 +NL80211_ATTR_CONTROL_PORT = 68 +NL80211_ATTR_TESTDATA = 69 +NL80211_ATTR_PRIVACY = 70 +NL80211_ATTR_DISCONNECTED_BY_AP = 71 +NL80211_ATTR_STATUS_CODE = 72 +NL80211_ATTR_CIPHER_SUITES_PAIRWISE = 73 +NL80211_ATTR_CIPHER_SUITE_GROUP = 74 +NL80211_ATTR_WPA_VERSIONS = 75 +NL80211_ATTR_AKM_SUITES = 76 +NL80211_ATTR_REQ_IE = 77 +NL80211_ATTR_RESP_IE = 78 +NL80211_ATTR_PREV_BSSID = 79 +NL80211_ATTR_KEY = 80 +NL80211_ATTR_KEYS = 81 +NL80211_ATTR_PID = 82 +NL80211_ATTR_4ADDR = 83 +NL80211_ATTR_SURVEY_INFO = 84 +NL80211_ATTR_PMKID = 85 +NL80211_ATTR_MAX_NUM_PMKIDS = 86 +NL80211_ATTR_DURATION = 87 +NL80211_ATTR_COOKIE = 88 +NL80211_ATTR_WIPHY_COVERAGE_CLASS = 89 +NL80211_ATTR_TX_RATES = 90 +NL80211_ATTR_FRAME_MATCH = 91 +NL80211_ATTR_ACK = 92 +NL80211_ATTR_PS_STATE = 93 +NL80211_ATTR_CQM = 94 +NL80211_ATTR_LOCAL_STATE_CHANGE = 95 +NL80211_ATTR_AP_ISOLATE = 96 +NL80211_ATTR_WIPHY_TX_POWER_SETTING = 97 +NL80211_ATTR_WIPHY_TX_POWER_LEVEL = 98 +NL80211_ATTR_TX_FRAME_TYPES = 99 +NL80211_ATTR_RX_FRAME_TYPES = 100 +NL80211_ATTR_FRAME_TYPE = 101 +NL80211_ATTR_CONTROL_PORT_ETHERTYPE = 102 +NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT = 103 +NL80211_ATTR_SUPPORT_IBSS_RSN = 104 +NL80211_ATTR_WIPHY_ANTENNA_TX = 105 +NL80211_ATTR_WIPHY_ANTENNA_RX = 106 +NL80211_ATTR_MCAST_RATE = 107 +NL80211_ATTR_OFFCHANNEL_TX_OK = 108 +NL80211_ATTR_BSS_HT_OPMODE = 109 +NL80211_ATTR_KEY_DEFAULT_TYPES = 110 +NL80211_ATTR_MAX_REMAIN_ON_CHANNEL_DURATION = 111 +NL80211_ATTR_MESH_SETUP = 112 +NL80211_ATTR_WIPHY_ANTENNA_AVAIL_TX = 113 +NL80211_ATTR_WIPHY_ANTENNA_AVAIL_RX = 114 +NL80211_ATTR_SUPPORT_MESH_AUTH = 115 +NL80211_ATTR_STA_PLINK_STATE = 116 +NL80211_ATTR_WOWLAN_TRIGGERS = 117 +NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED = 118 +NL80211_ATTR_SCHED_SCAN_INTERVAL = 119 +NL80211_ATTR_INTERFACE_COMBINATIONS = 120 +NL80211_ATTR_SOFTWARE_IFTYPES = 121 +NL80211_ATTR_REKEY_DATA = 122 +NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS = 123 +NL80211_ATTR_MAX_SCHED_SCAN_IE_LEN = 124 +NL80211_ATTR_SCAN_SUPP_RATES = 125 +NL80211_ATTR_HIDDEN_SSID = 126 +NL80211_ATTR_IE_PROBE_RESP = 127 +NL80211_ATTR_IE_ASSOC_RESP = 128 +NL80211_ATTR_STA_WME = 129 +NL80211_ATTR_SUPPORT_AP_UAPSD = 130 +NL80211_ATTR_ROAM_SUPPORT = 131 +NL80211_ATTR_SCHED_SCAN_MATCH = 132 +NL80211_ATTR_MAX_MATCH_SETS = 133 +NL80211_ATTR_PMKSA_CANDIDATE = 134 +NL80211_ATTR_TX_NO_CCK_RATE = 135 +NL80211_ATTR_TDLS_ACTION = 136 +NL80211_ATTR_TDLS_DIALOG_TOKEN = 137 +NL80211_ATTR_TDLS_OPERATION = 138 +NL80211_ATTR_TDLS_SUPPORT = 139 +NL80211_ATTR_TDLS_EXTERNAL_SETUP = 140 +NL80211_ATTR_DEVICE_AP_SME = 141 +NL80211_ATTR_DONT_WAIT_FOR_ACK = 142 +NL80211_ATTR_FEATURE_FLAGS = 143 +NL80211_ATTR_PROBE_RESP_OFFLOAD = 144 +NL80211_ATTR_PROBE_RESP = 145 +NL80211_ATTR_DFS_REGION = 146 +NL80211_ATTR_DISABLE_HT = 147 +NL80211_ATTR_HT_CAPABILITY_MASK = 148 +NL80211_ATTR_NOACK_MAP = 149 +NL80211_ATTR_INACTIVITY_TIMEOUT = 150 +NL80211_ATTR_RX_SIGNAL_DBM = 151 +NL80211_ATTR_BG_SCAN_PERIOD = 152 +NL80211_ATTR_WDEV = 153 +NL80211_ATTR_USER_REG_HINT_TYPE = 154 +NL80211_ATTR_CONN_FAILED_REASON = 155 +NL80211_ATTR_SAE_DATA = 156 +NL80211_ATTR_VHT_CAPABILITY = 157 +NL80211_ATTR_SCAN_FLAGS = 158 +NL80211_ATTR_CHANNEL_WIDTH = 159 +NL80211_ATTR_CENTER_FREQ1 = 160 +NL80211_ATTR_CENTER_FREQ2 = 161 +NL80211_ATTR_P2P_CTWINDOW = 162 +NL80211_ATTR_P2P_OPPPS = 163 +NL80211_ATTR_LOCAL_MESH_POWER_MODE = 164 +NL80211_ATTR_ACL_POLICY = 165 +NL80211_ATTR_MAC_ADDRS = 166 +NL80211_ATTR_MAC_ACL_MAX = 167 +NL80211_ATTR_RADAR_EVENT = 168 +NL80211_ATTR_EXT_CAPA = 169 +NL80211_ATTR_EXT_CAPA_MASK = 170 +NL80211_ATTR_STA_CAPABILITY = 171 +NL80211_ATTR_STA_EXT_CAPABILITY = 172 +NL80211_ATTR_PROTOCOL_FEATURES = 173 +NL80211_ATTR_SPLIT_WIPHY_DUMP = 174 +NL80211_ATTR_DISABLE_VHT = 175 +NL80211_ATTR_VHT_CAPABILITY_MASK = 176 +NL80211_ATTR_MDID = 177 +NL80211_ATTR_IE_RIC = 178 +NL80211_ATTR_CRIT_PROT_ID = 179 +NL80211_ATTR_MAX_CRIT_PROT_DURATION = 180 +NL80211_ATTR_PEER_AID = 181 +NL80211_ATTR_COALESCE_RULE = 182 +NL80211_ATTR_CH_SWITCH_COUNT = 183 +NL80211_ATTR_CH_SWITCH_BLOCK_TX = 184 +NL80211_ATTR_CSA_IES = 185 +NL80211_ATTR_CSA_C_OFF_BEACON = 186 +NL80211_ATTR_CSA_C_OFF_PRESP = 187 +NL80211_ATTR_RXMGMT_FLAGS = 188 +NL80211_ATTR_STA_SUPPORTED_CHANNELS = 189 +NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES = 190 +NL80211_ATTR_HANDLE_DFS = 191 +# add attributes here, update the policy in nl80211.c +__NL80211_ATTR_AFTER_LAST = 192 +NL80211_ATTR_MAX = __NL80211_ATTR_AFTER_LAST - 1 + +# source-level API compatibility +NL80211_ATTR_SCAN_GENERATION = NL80211_ATTR_GENERATION +NL80211_ATTR_MESH_PARAMS = NL80211_ATTR_MESH_CONFIG + +# Allow user space programs to use #ifdef on new attributes by defining them here +NL80211_CMD_CONNECT = NL80211_CMD_CONNECT +NL80211_ATTR_HT_CAPABILITY = NL80211_ATTR_HT_CAPABILITY +NL80211_ATTR_BSS_BASIC_RATES = NL80211_ATTR_BSS_BASIC_RATES +NL80211_ATTR_WIPHY_TXQ_PARAMS = NL80211_ATTR_WIPHY_TXQ_PARAMS +NL80211_ATTR_WIPHY_FREQ = NL80211_ATTR_WIPHY_FREQ +NL80211_ATTR_WIPHY_CHANNEL_TYPE = NL80211_ATTR_WIPHY_CHANNEL_TYPE +NL80211_ATTR_MGMT_SUBTYPE = NL80211_ATTR_MGMT_SUBTYPE +NL80211_ATTR_IE = NL80211_ATTR_IE +NL80211_ATTR_REG_INITIATOR = NL80211_ATTR_REG_INITIATOR +NL80211_ATTR_REG_TYPE = NL80211_ATTR_REG_TYPE +NL80211_ATTR_FRAME = NL80211_ATTR_FRAME +NL80211_ATTR_SSID = NL80211_ATTR_SSID +NL80211_ATTR_AUTH_TYPE = NL80211_ATTR_AUTH_TYPE +NL80211_ATTR_REASON_CODE = NL80211_ATTR_REASON_CODE +NL80211_ATTR_CIPHER_SUITES_PAIRWISE = NL80211_ATTR_CIPHER_SUITES_PAIRWISE +NL80211_ATTR_CIPHER_SUITE_GROUP = NL80211_ATTR_CIPHER_SUITE_GROUP +NL80211_ATTR_WPA_VERSIONS = NL80211_ATTR_WPA_VERSIONS +NL80211_ATTR_AKM_SUITES = NL80211_ATTR_AKM_SUITES +NL80211_ATTR_KEY = NL80211_ATTR_KEY +NL80211_ATTR_KEYS = NL80211_ATTR_KEYS +NL80211_ATTR_FEATURE_FLAGS = NL80211_ATTR_FEATURE_FLAGS + +NL80211_MAX_SUPP_RATES = 32 +NL80211_MAX_SUPP_HT_RATES = 77 +NL80211_MAX_SUPP_REG_RULES = 32 +NL80211_TKIP_DATA_OFFSET_ENCR_KEY = 0 +NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY = 16 +NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY = 24 +NL80211_HT_CAPABILITY_LEN = 26 +NL80211_VHT_CAPABILITY_LEN = 12 + +NL80211_MAX_NR_CIPHER_SUITES = 5 +NL80211_MAX_NR_AKM_SUITES = 2 + +NL80211_MIN_REMAIN_ON_CHANNEL_TIME = 10 + +# default RSSI threshold for scan results if none specified. +NL80211_SCAN_RSSI_THOLD_OFF = -300 + +NL80211_CQM_TXE_MAX_INTVL = 1800 + +""" +/** + * enum nl80211_iftype - (virtual) interface types + * + * @NL80211_IFTYPE_UNSPECIFIED: unspecified type, driver decides + * @NL80211_IFTYPE_ADHOC: independent BSS member + * @NL80211_IFTYPE_STATION: managed BSS member + * @NL80211_IFTYPE_AP: access point + * @NL80211_IFTYPE_AP_VLAN: VLAN interface for access points; VLAN interfaces + * are a bit special in that they must always be tied to a pre-existing + * AP type interface. + * @NL80211_IFTYPE_WDS: wireless distribution interface + * @NL80211_IFTYPE_MONITOR: monitor interface receiving all frames + * @NL80211_IFTYPE_MESH_POINT: mesh point + * @NL80211_IFTYPE_P2P_CLIENT: P2P client + * @NL80211_IFTYPE_P2P_GO: P2P group owner + * @NL80211_IFTYPE_P2P_DEVICE: P2P device interface type, this is not a netdev + * and therefore can't be created in the normal ways, use the + * %NL80211_CMD_START_P2P_DEVICE and %NL80211_CMD_STOP_P2P_DEVICE + * commands to create and destroy one + * @NL80211_IFTYPE_MAX: highest interface type number currently defined + * @NUM_NL80211_IFTYPES: number of defined interface types + * + * These values are used with the %NL80211_ATTR_IFTYPE + * to set the type of an interface. + * + */ +""" +# the below string names may not be the same as identified by other programs +NL80211_IFTYPES = ['unspecified','ibss','managed','AP','AP VLAN','wds', + 'monitor','mesh','p2p_client','p2p_go','p2p_device'] +NL80211_IFTYPE_UNSPECIFIED = 0 +NL80211_IFTYPE_ADHOC = 1 +NL80211_IFTYPE_STATION = 2 +NL80211_IFTYPE_AP = 3 +NL80211_IFTYPE_AP_VLAN = 4 +NL80211_IFTYPE_WDS = 5 +NL80211_IFTYPE_MONITOR = 6 +NL80211_IFTYPE_MESH_POINT = 7 +NL80211_IFTYPE_P2P_CLIENT = 8 +NL80211_IFTYPE_P2P_GO = 9 +NL80211_IFTYPE_P2P_DEVICE = 10 +NUM_NL80211_IFTYPES = len(NL80211_IFTYPES) + +""" +/** + * enum nl80211_sta_flags - station flags + * + * Station flags. When a station is added to an AP interface, it is + * assumed to be already associated (and hence authenticated.) + * + * @__NL80211_STA_FLAG_INVALID: attribute number 0 is reserved + * @NL80211_STA_FLAG_AUTHORIZED: station is authorized (802.1X) + * @NL80211_STA_FLAG_SHORT_PREAMBLE: station is capable of receiving frames + * with short barker preamble + * @NL80211_STA_FLAG_WME: station is WME/QoS capable + * @NL80211_STA_FLAG_MFP: station uses management frame protection + * @NL80211_STA_FLAG_AUTHENTICATED: station is authenticated + * @NL80211_STA_FLAG_TDLS_PEER: station is a TDLS peer -- this flag should + * only be used in managed mode (even in the flags mask). Note that the + * flag can't be changed, it is only valid while adding a station, and + * attempts to change it will silently be ignored (rather than rejected + * as errors.) + * @NL80211_STA_FLAG_ASSOCIATED: station is associated; used with drivers + * that support %NL80211_FEATURE_FULL_AP_CLIENT_STATE to transition a + * previously added station into associated state + * @NL80211_STA_FLAG_MAX: highest station flag number currently defined + * @__NL80211_STA_FLAG_AFTER_LAST: internal use + */ +""" +__NL80211_STA_FLAG_INVALID = 0 +NL80211_STA_FLAG_AUTHORIZED = 1 +NL80211_STA_FLAG_SHORT_PREAMBLE = 2 +NL80211_STA_FLAG_WME = 3 +NL80211_STA_FLAG_MFP = 4 +NL80211_STA_FLAG_AUTHENTICATED = 5 +NL80211_STA_FLAG_TDLS_PEER = 6 +NL80211_STA_FLAG_ASSOCIATED = 7 +NUM_NL80211_STA_FLAG = 7 + +NL80211_STA_FLAG_MAX_OLD_API = NL80211_STA_FLAG_TDLS_PEER + +""" +/** + * struct nl80211_sta_flag_update - station flags mask/set + * @mask: mask of station flags to set + * @set: which values to set them to + * + * Both mask and set contain bits as per &enum nl80211_sta_flags. + */ + +struct nl80211_sta_flag_update { + __u32 mask; + __u32 set; +} __attribute__((packed)); +""" +dot11_nl80211_sta_flag_update = "II" +DOT11STAFLAGUPDATELEN = struct.calcsize(dot11_nl80211_sta_flag_update) +def nl80211_sta_flag_update(mask,setto): + """ + create a nl80211_sta_flag_update + :param mask: mask of station flags to set + :param setto: which values to set them to + """ + return struct.pack(dot11_nl80211_sta_flag_update,mask,setto) + +""" +/** + * enum nl80211_rate_info - bitrate information + * + * These attribute types are used with %NL80211_STA_INFO_TXRATE + * when getting information about the bitrate of a station. + * There are 2 attributes for bitrate, a legacy one that represents + * a 16-bit value, and new one that represents a 32-bit value. + * If the rate value fits into 16 bit, both attributes are reported + * with the same value. If the rate is too high to fit into 16 bits + * (>6.5535Gbps) only 32-bit attribute is included. + * User space tools encouraged to use the 32-bit attribute and fall + * back to the 16-bit one for compatibility with older kernels. + * + * @__NL80211_RATE_INFO_INVALID: attribute number 0 is reserved + * @NL80211_RATE_INFO_BITRATE: total bitrate (u16, 100kbit/s) + * @NL80211_RATE_INFO_MCS: mcs index for 802.11n (u8) + * @NL80211_RATE_INFO_40_MHZ_WIDTH: 40 MHz dualchannel bitrate + * @NL80211_RATE_INFO_SHORT_GI: 400ns guard interval + * @NL80211_RATE_INFO_BITRATE32: total bitrate (u32, 100kbit/s) + * @NL80211_RATE_INFO_MAX: highest rate_info number currently defined + * @NL80211_RATE_INFO_VHT_MCS: MCS index for VHT (u8) + * @NL80211_RATE_INFO_VHT_NSS: number of streams in VHT (u8) + * @NL80211_RATE_INFO_80_MHZ_WIDTH: 80 MHz VHT rate + * @NL80211_RATE_INFO_80P80_MHZ_WIDTH: 80+80 MHz VHT rate + * @NL80211_RATE_INFO_160_MHZ_WIDTH: 160 MHz VHT rate + * @__NL80211_RATE_INFO_AFTER_LAST: internal use + */ +""" +__NL80211_RATE_INFO_INVALID = 0 +NL80211_RATE_INFO_BITRATE = 1 +NL80211_RATE_INFO_MCS = 2 +NL80211_RATE_INFO_40_MHZ_WIDTH = 3 +NL80211_RATE_INFO_SHORT_GI = 4 +NL80211_RATE_INFO_BITRATE32 = 5 +NL80211_RATE_INFO_VHT_MCS = 6 +NL80211_RATE_INFO_VHT_NSS = 7 +NL80211_RATE_INFO_80_MHZ_WIDTH = 8 +NL80211_RATE_INFO_80P80_MHZ_WIDTH = 9 +NL80211_RATE_INFO_160_MHZ_WIDTH = 10 +NUM_NL80211_RATE_INFO = 10 + +""" +/** + * enum nl80211_sta_bss_param - BSS information collected by STA + * + * These attribute types are used with %NL80211_STA_INFO_BSS_PARAM + * when getting information about the bitrate of a station. + * + * @__NL80211_STA_BSS_PARAM_INVALID: attribute number 0 is reserved + * @NL80211_STA_BSS_PARAM_CTS_PROT: whether CTS protection is enabled (flag) + * @NL80211_STA_BSS_PARAM_SHORT_PREAMBLE: whether short preamble is enabled + * (flag) + * @NL80211_STA_BSS_PARAM_SHORT_SLOT_TIME: whether short slot time is enabled + * (flag) + * @NL80211_STA_BSS_PARAM_DTIM_PERIOD: DTIM period for beaconing (u8) + * @NL80211_STA_BSS_PARAM_BEACON_INTERVAL: Beacon interval (u16) + * @NL80211_STA_BSS_PARAM_MAX: highest sta_bss_param number currently defined + * @__NL80211_STA_BSS_PARAM_AFTER_LAST: internal use + */ +""" +__NL80211_STA_BSS_PARAM_INVALID = 0 +NL80211_STA_BSS_PARAM_CTS_PROT = 1 +NL80211_STA_BSS_PARAM_SHORT_PREAMBLE = 2 +NL80211_STA_BSS_PARAM_SHORT_SLOT_TIME = 3 +NL80211_STA_BSS_PARAM_DTIM_PERIOD = 4 +NL80211_STA_BSS_PARAM_BEACON_INTERVAL = 5 +NUM_NL80211_STA_BSS_PARAM = 5 + +""" +/** + * enum nl80211_sta_info - station information + * + * These attribute types are used with %NL80211_ATTR_STA_INFO + * when getting information about a station. + * + * @__NL80211_STA_INFO_INVALID: attribute number 0 is reserved + * @NL80211_STA_INFO_INACTIVE_TIME: time since last activity (u32, msecs) + * @NL80211_STA_INFO_RX_BYTES: total received bytes (u32, from this station) + * @NL80211_STA_INFO_TX_BYTES: total transmitted bytes (u32, to this station) + * @NL80211_STA_INFO_RX_BYTES64: total received bytes (u64, from this station) + * @NL80211_STA_INFO_TX_BYTES64: total transmitted bytes (u64, to this station) + * @NL80211_STA_INFO_SIGNAL: signal strength of last received PPDU (u8, dBm) + * @NL80211_STA_INFO_TX_BITRATE: current unicast tx rate, nested attribute + * containing info as possible, see &enum nl80211_rate_info + * @NL80211_STA_INFO_RX_PACKETS: total received packet (u32, from this station) + * @NL80211_STA_INFO_TX_PACKETS: total transmitted packets (u32, to this + * station) + * @NL80211_STA_INFO_TX_RETRIES: total retries (u32, to this station) + * @NL80211_STA_INFO_TX_FAILED: total failed packets (u32, to this station) + * @NL80211_STA_INFO_SIGNAL_AVG: signal strength average (u8, dBm) + * @NL80211_STA_INFO_LLID: the station's mesh LLID + * @NL80211_STA_INFO_PLID: the station's mesh PLID + * @NL80211_STA_INFO_PLINK_STATE: peer link state for the station + * (see %enum nl80211_plink_state) + * @NL80211_STA_INFO_RX_BITRATE: last unicast data frame rx rate, nested + * attribute, like NL80211_STA_INFO_TX_BITRATE. + * @NL80211_STA_INFO_BSS_PARAM: current station's view of BSS, nested attribute + * containing info as possible, see &enum nl80211_sta_bss_param + * @NL80211_STA_INFO_CONNECTED_TIME: time since the station is last connected + * @NL80211_STA_INFO_STA_FLAGS: Contains a struct nl80211_sta_flag_update. + * @NL80211_STA_INFO_BEACON_LOSS: count of times beacon loss was detected (u32) + * @NL80211_STA_INFO_T_OFFSET: timing offset with respect to this STA (s64) + * @NL80211_STA_INFO_LOCAL_PM: local mesh STA link-specific power mode + * @NL80211_STA_INFO_PEER_PM: peer mesh STA link-specific power mode + * @NL80211_STA_INFO_NONPEER_PM: neighbor mesh STA power save mode towards + * non-peer STA + * @NL80211_STA_INFO_CHAIN_SIGNAL: per-chain signal strength of last PPDU + * Contains a nested array of signal strength attributes (u8, dBm) + * @NL80211_STA_INFO_CHAIN_SIGNAL_AVG: per-chain signal strength average + * Same format as NL80211_STA_INFO_CHAIN_SIGNAL. + * @__NL80211_STA_INFO_AFTER_LAST: internal + * @NL80211_STA_INFO_MAX: highest possible station info attribute + */ + """ +__NL80211_STA_INFO_INVALID = 0 +NL80211_STA_INFO_INACTIVE_TIME = 1 +NL80211_STA_INFO_RX_BYTES = 2 +NL80211_STA_INFO_TX_BYTES = 3 +NL80211_STA_INFO_LLID = 4 +NL80211_STA_INFO_PLID = 5 +NL80211_STA_INFO_PLINK_STATE = 6 +NL80211_STA_INFO_SIGNAL = 7 +NL80211_STA_INFO_TX_BITRATE = 8 +NL80211_STA_INFO_RX_PACKETS = 9 +NL80211_STA_INFO_TX_PACKETS = 10 +NL80211_STA_INFO_TX_RETRIES = 11 +NL80211_STA_INFO_TX_FAILED = 12 +NL80211_STA_INFO_SIGNAL_AVG = 13 +NL80211_STA_INFO_RX_BITRATE = 14 +NL80211_STA_INFO_BSS_PARAM = 15 +NL80211_STA_INFO_CONNECTED_TIME = 16 +NL80211_STA_INFO_STA_FLAGS = 17 +NL80211_STA_INFO_BEACON_LOSS = 18 +NL80211_STA_INFO_T_OFFSET = 19 +NL80211_STA_INFO_LOCAL_PM = 20 +NL80211_STA_INFO_PEER_PM = 21 +NL80211_STA_INFO_NONPEER_PM = 22 +NL80211_STA_INFO_RX_BYTES64 = 23 +NL80211_STA_INFO_TX_BYTES64 = 24 +NL80211_STA_INFO_CHAIN_SIGNAL = 25 +NL80211_STA_INFO_CHAIN_SIGNAL_AVG = 26 +NUM_NL80211_STA_INFO = 26 + +""" +/** + * enum nl80211_mpath_flags - nl80211 mesh path flags + * + * @NL80211_MPATH_FLAG_ACTIVE: the mesh path is active + * @NL80211_MPATH_FLAG_RESOLVING: the mesh path discovery process is running + * @NL80211_MPATH_FLAG_SN_VALID: the mesh path contains a valid SN + * @NL80211_MPATH_FLAG_FIXED: the mesh path has been manually set + * @NL80211_MPATH_FLAG_RESOLVED: the mesh path discovery process succeeded + */ +""" +NL80211_MPATH_FLAG_ACTIVE = 1 << 0 +NL80211_MPATH_FLAG_RESOLVING = 1 << 1 +NL80211_MPATH_FLAG_SN_VALID = 1 << 2 +NL80211_MPATH_FLAG_FIXED = 1 << 3 +NL80211_MPATH_FLAG_RESOLVED = 1 << 4 + +""" +/** + * enum nl80211_mpath_info - mesh path information + * + * These attribute types are used with %NL80211_ATTR_MPATH_INFO when getting + * information about a mesh path. + * + * @__NL80211_MPATH_INFO_INVALID: attribute number 0 is reserved + * @NL80211_MPATH_INFO_FRAME_QLEN: number of queued frames for this destination + * @NL80211_MPATH_INFO_SN: destination sequence number + * @NL80211_MPATH_INFO_METRIC: metric (cost) of this mesh path + * @NL80211_MPATH_INFO_EXPTIME: expiration time for the path, in msec from now + * @NL80211_MPATH_INFO_FLAGS: mesh path flags, enumerated in + * &enum nl80211_mpath_flags; + * @NL80211_MPATH_INFO_DISCOVERY_TIMEOUT: total path discovery timeout, in msec + * @NL80211_MPATH_INFO_DISCOVERY_RETRIES: mesh path discovery retries + * @NL80211_MPATH_INFO_MAX: highest mesh path information attribute number + * currently defind + * @__NL80211_MPATH_INFO_AFTER_LAST: internal use + */ +""" +__NL80211_MPATH_INFO_INVALID = 0 +NL80211_MPATH_INFO_FRAME_QLEN = 1 +NL80211_MPATH_INFO_SN = 2 +NL80211_MPATH_INFO_METRIC = 3 +NL80211_MPATH_INFO_EXPTIME = 4 +NL80211_MPATH_INFO_FLAGS = 5 +NL80211_MPATH_INFO_DISCOVERY_TIMEOUT = 6 +NL80211_MPATH_INFO_DISCOVERY_RETRIES = 7 +NUM_NL80211_MPATH_INFO = 7 + +""" +/** + * enum nl80211_band_attr - band attributes + * @__NL80211_BAND_ATTR_INVALID: attribute number 0 is reserved + * @NL80211_BAND_ATTR_FREQS: supported frequencies in this band, + * an array of nested frequency attributes + * @NL80211_BAND_ATTR_RATES: supported bitrates in this band, + * an array of nested bitrate attributes + * @NL80211_BAND_ATTR_HT_MCS_SET: 16-byte attribute containing the MCS set as + * defined in 802.11n + * @NL80211_BAND_ATTR_HT_CAPA: HT capabilities, as in the HT information IE + * @NL80211_BAND_ATTR_HT_AMPDU_FACTOR: A-MPDU factor, as in 11n + * @NL80211_BAND_ATTR_HT_AMPDU_DENSITY: A-MPDU density, as in 11n + * @NL80211_BAND_ATTR_VHT_MCS_SET: 32-byte attribute containing the MCS set as + * defined in 802.11ac + * @NL80211_BAND_ATTR_VHT_CAPA: VHT capabilities, as in the HT information IE + * @NL80211_BAND_ATTR_MAX: highest band attribute currently defined + * @__NL80211_BAND_ATTR_AFTER_LAST: internal use + */ +""" +__NL80211_BAND_ATTR_INVALID = 0 +NL80211_BAND_ATTR_FREQS = 1 +NL80211_BAND_ATTR_RATES = 2 +NL80211_BAND_ATTR_HT_MCS_SET = 3 +NL80211_BAND_ATTR_HT_CAPA = 4 +NL80211_BAND_ATTR_HT_AMPDU_FACTOR = 5 +NL80211_BAND_ATTR_HT_AMPDU_DENSITY = 6 +NL80211_BAND_ATTR_VHT_MCS_SET = 7 +NL80211_BAND_ATTR_VHT_CAPA = 8 +NUM_NL80211_BAND_ATTR = 8 + +NL80211_BAND_ATTR_HT_CAPA = NL80211_BAND_ATTR_HT_CAPA + +""" +/** + * enum nl80211_frequency_attr - frequency attributes + * @__NL80211_FREQUENCY_ATTR_INVALID: attribute number 0 is reserved + * @NL80211_FREQUENCY_ATTR_FREQ: Frequency in MHz + * @NL80211_FREQUENCY_ATTR_DISABLED: Channel is disabled in current + * regulatory domain. + * @NL80211_FREQUENCY_ATTR_PASSIVE_SCAN: Only passive scanning is + * permitted on this channel in current regulatory domain. + * @NL80211_FREQUENCY_ATTR_NO_IBSS: IBSS networks are not permitted + * on this channel in current regulatory domain. + * @NL80211_FREQUENCY_ATTR_RADAR: Radar detection is mandatory + * on this channel in current regulatory domain. + * @NL80211_FREQUENCY_ATTR_MAX_TX_POWER: Maximum transmission power in mBm + * (100 * dBm). + * @NL80211_FREQUENCY_ATTR_DFS_STATE: current state for DFS + * (enum nl80211_dfs_state) + * @NL80211_FREQUENCY_ATTR_DFS_TIME: time in miliseconds for how long + * this channel is in this DFS state. + * @NL80211_FREQUENCY_ATTR_NO_HT40_MINUS: HT40- isn't possible with this + * channel as the control channel + * @NL80211_FREQUENCY_ATTR_NO_HT40_PLUS: HT40+ isn't possible with this + * channel as the control channel + * @NL80211_FREQUENCY_ATTR_NO_80MHZ: any 80 MHz channel using this channel + * as the primary or any of the secondary channels isn't possible, + * this includes 80+80 channels + * @NL80211_FREQUENCY_ATTR_NO_160MHZ: any 160 MHz (but not 80+80) channel + * using this channel as the primary or any of the secondary channels + * isn't possible + * @NL80211_FREQUENCY_ATTR_MAX: highest frequency attribute number + * currently defined + * @__NL80211_FREQUENCY_ATTR_AFTER_LAST: internal use + */ +""" +__NL80211_FREQUENCY_ATTR_INVALID = 0 +NL80211_FREQUENCY_ATTR_FREQ = 1 +NL80211_FREQUENCY_ATTR_DISABLED = 2 +NL80211_FREQUENCY_ATTR_PASSIVE_SCAN = 3 +NL80211_FREQUENCY_ATTR_NO_IBSS = 4 +NL80211_FREQUENCY_ATTR_RADAR = 5 +NL80211_FREQUENCY_ATTR_MAX_TX_POWER = 6 +NL80211_FREQUENCY_ATTR_DFS_STATE = 7 +NL80211_FREQUENCY_ATTR_DFS_TIME = 8 +NL80211_FREQUENCY_ATTR_NO_HT40_MINUS = 9 +NL80211_FREQUENCY_ATTR_NO_HT40_PLUS = 10 +NL80211_FREQUENCY_ATTR_NO_80MHZ = 11 +NL80211_FREQUENCY_ATTR_NO_160MHZ = 12 +NUM_NL80211_FREQUENCY_ATTR = 12 + +NL80211_FREQUENCY_ATTR_MAX_TX_POWER = NL80211_FREQUENCY_ATTR_MAX_TX_POWER + +""" +/** + * enum nl80211_bitrate_attr - bitrate attributes + * @__NL80211_BITRATE_ATTR_INVALID: attribute number 0 is reserved + * @NL80211_BITRATE_ATTR_RATE: Bitrate in units of 100 kbps + * @NL80211_BITRATE_ATTR_2GHZ_SHORTPREAMBLE: Short preamble supported + * in 2.4 GHz band. + * @NL80211_BITRATE_ATTR_MAX: highest bitrate attribute number + * currently defined + * @__NL80211_BITRATE_ATTR_AFTER_LAST: internal use + */ +""" +__NL80211_BITRATE_ATTR_INVALID = 0 +NL80211_BITRATE_ATTR_RATE = 1 +NL80211_BITRATE_ATTR_2GHZ_SHORTPREAMBLE = 2 +NUM_NL80211_BITRATE_ATTR = 2 + +""" +/** + * enum nl80211_initiator - Indicates the initiator of a reg domain request + * @NL80211_REGDOM_SET_BY_CORE: Core queried CRDA for a dynamic world + * regulatory domain. + * @NL80211_REGDOM_SET_BY_USER: User asked the wireless core to set the + * regulatory domain. + * @NL80211_REGDOM_SET_BY_DRIVER: a wireless drivers has hinted to the + * wireless core it thinks its knows the regulatory domain we should be in. + * @NL80211_REGDOM_SET_BY_COUNTRY_IE: the wireless core has received an + * 802.11 country information element with regulatory information it + * thinks we should consider. cfg80211 only processes the country + * code from the IE, and relies on the regulatory domain information + * structure passed by userspace (CRDA) from our wireless-regdb. + * If a channel is enabled but the country code indicates it should + * be disabled we disable the channel and re-enable it upon disassociation. + */ +""" +NL80211_REGDOM_SET_BY_CORE = 1 +NL80211_REGDOM_SET_BY_USER = 2 +NL80211_REGDOM_SET_BY_DRIVER = 3 +NL80211_REGDOM_SET_BY_COUNTRY_IE = 4 + +""" +/** + * enum nl80211_reg_type - specifies the type of regulatory domain + * @NL80211_REGDOM_TYPE_COUNTRY: the regulatory domain set is one that pertains + * to a specific country. When this is set you can count on the + * ISO / IEC 3166 alpha2 country code being valid. + * @NL80211_REGDOM_TYPE_WORLD: the regulatory set domain is the world regulatory + * domain. + * @NL80211_REGDOM_TYPE_CUSTOM_WORLD: the regulatory domain set is a custom + * driver specific world regulatory domain. These do not apply system-wide + * and are only applicable to the individual devices which have requested + * them to be applied. + * @NL80211_REGDOM_TYPE_INTERSECTION: the regulatory domain set is the product + * of an intersection between two regulatory domains -- the previously + * set regulatory domain on the system and the last accepted regulatory + * domain request to be processed. + */ + """ +NL80211_REGDOM_TYPE_COUNTRY = 0 +NL80211_REGDOM_TYPE_WORLD = 1 +NL80211_REGDOM_TYPE_CUSTOM_WORLD = 2 +NL80211_REGDOM_TYPE_INTERSECTION = 2 + +""" +/** + * enum nl80211_reg_rule_attr - regulatory rule attributes + * @__NL80211_REG_RULE_ATTR_INVALID: attribute number 0 is reserved + * @NL80211_ATTR_REG_RULE_FLAGS: a set of flags which specify additional + * considerations for a given frequency range. These are the + * &enum nl80211_reg_rule_flags. + * @NL80211_ATTR_FREQ_RANGE_START: starting frequencry for the regulatory + * rule in KHz. This is not a center of frequency but an actual regulatory + * band edge. + * @NL80211_ATTR_FREQ_RANGE_END: ending frequency for the regulatory rule + * in KHz. This is not a center a frequency but an actual regulatory + * band edge. + * @NL80211_ATTR_FREQ_RANGE_MAX_BW: maximum allowed bandwidth for this + * frequency range, in KHz. + * @NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN: the maximum allowed antenna gain + * for a given frequency range. The value is in mBi (100 * dBi). + * If you don't have one then don't send this. + * @NL80211_ATTR_POWER_RULE_MAX_EIRP: the maximum allowed EIRP for + * a given frequency range. The value is in mBm (100 * dBm). + * @NL80211_REG_RULE_ATTR_MAX: highest regulatory rule attribute number + * currently defined + * @__NL80211_REG_RULE_ATTR_AFTER_LAST: internal use + */ +""" +__NL80211_REG_RULE_ATTR_INVALID = 0 +NL80211_ATTR_REG_RULE_FLAGS = 1 +NL80211_ATTR_FREQ_RANGE_START = 2 +NL80211_ATTR_FREQ_RANGE_END = 3 +NL80211_ATTR_FREQ_RANGE_MAX_BW = 4 +NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN = 5 +NL80211_ATTR_POWER_RULE_MAX_EIRP = 6 +NUM_NL80211_REG_RULE_ATTR = 6 + +""" +/** + * enum nl80211_sched_scan_match_attr - scheduled scan match attributes + * @__NL80211_SCHED_SCAN_MATCH_ATTR_INVALID: attribute number 0 is reserved + * @NL80211_SCHED_SCAN_MATCH_ATTR_SSID: SSID to be used for matching, + * only report BSS with matching SSID. + * @NL80211_SCHED_SCAN_MATCH_ATTR_RSSI: RSSI threshold (in dBm) for reporting a + * BSS in scan results. Filtering is turned off if not specified. + * @NL80211_SCHED_SCAN_MATCH_ATTR_MAX: highest scheduled scan filter + * attribute number currently defined + * @__NL80211_SCHED_SCAN_MATCH_ATTR_AFTER_LAST: internal use + */ + """ +__NL80211_SCHED_SCAN_MATCH_ATTR_INVALID = 1 +NL80211_SCHED_SCAN_MATCH_ATTR_SSID = 2 +NL80211_SCHED_SCAN_MATCH_ATTR_RSSI = 3 +NUM_NL80211_SCHED_SCAN_MATCH_ATTR = 3 + +# only for backward compatibility +NL80211_ATTR_SCHED_SCAN_MATCH_SSID = NL80211_SCHED_SCAN_MATCH_ATTR_SSID + +""" +/** + * enum nl80211_reg_rule_flags - regulatory rule flags + * + * @NL80211_RRF_NO_OFDM: OFDM modulation not allowed + * @NL80211_RRF_NO_CCK: CCK modulation not allowed + * @NL80211_RRF_NO_INDOOR: indoor operation not allowed + * @NL80211_RRF_NO_OUTDOOR: outdoor operation not allowed + * @NL80211_RRF_DFS: DFS support is required to be used + * @NL80211_RRF_PTP_ONLY: this is only for Point To Point links + * @NL80211_RRF_PTMP_ONLY: this is only for Point To Multi Point links + * @NL80211_RRF_PASSIVE_SCAN: passive scan is required + * @NL80211_RRF_NO_IBSS: no IBSS is allowed + */ +""" +NL80211_RRF_NO_OFDM = 1<<0 +NL80211_RRF_NO_CCK = 1<<1 +NL80211_RRF_NO_INDOOR = 1<<2 +NL80211_RRF_NO_OUTDOOR = 1<<3 +NL80211_RRF_DFS = 1<<4 +NL80211_RRF_PTP_ONLY = 1<<5 +NL80211_RRF_PTMP_ONLY = 1<<6 +NL80211_RRF_PASSIVE_SCAN = 1<<7 +NL80211_RRF_NO_IBSS = 1<<8 + +""" +/** + * enum nl80211_dfs_regions - regulatory DFS regions + * + * @NL80211_DFS_UNSET: Country has no DFS master region specified + * @NL80211_DFS_FCC: Country follows DFS master rules from FCC + * @NL80211_DFS_ETSI: Country follows DFS master rules from ETSI + * @NL80211_DFS_JP: Country follows DFS master rules from JP/MKK/Telec + */ +""" +NL80211_DFS_UNSET = 0 +NL80211_DFS_FCC = 1 +NL80211_DFS_ETSI = 2 +NL80211_DFS_JP = 3 + +""" +/** + * enum nl80211_user_reg_hint_type - type of user regulatory hint + * + * @NL80211_USER_REG_HINT_USER: a user sent the hint. This is always + * assumed if the attribute is not set. + * @NL80211_USER_REG_HINT_CELL_BASE: the hint comes from a cellular + * base station. Device drivers that have been tested to work + * properly to support this type of hint can enable these hints + * by setting the NL80211_FEATURE_CELL_BASE_REG_HINTS feature + * capability on the struct wiphy. The wireless core will + * ignore all cell base station hints until at least one device + * present has been registered with the wireless core that + * has listed NL80211_FEATURE_CELL_BASE_REG_HINTS as a + * supported feature. + */ +""" +NL80211_USER_REG_HINT_USER = 0 +NL80211_USER_REG_HINT_CELL_BASE = 1 + +""" +/** + * enum nl80211_survey_info - survey information + * + * These attribute types are used with %NL80211_ATTR_SURVEY_INFO + * when getting information about a survey. + * + * @__NL80211_SURVEY_INFO_INVALID: attribute number 0 is reserved + * @NL80211_SURVEY_INFO_FREQUENCY: center frequency of channel + * @NL80211_SURVEY_INFO_NOISE: noise level of channel (u8, dBm) + * @NL80211_SURVEY_INFO_IN_USE: channel is currently being used + * @NL80211_SURVEY_INFO_CHANNEL_TIME: amount of time (in ms) that the radio + * spent on this channel + * @NL80211_SURVEY_INFO_CHANNEL_TIME_BUSY: amount of the time the primary + * channel was sensed busy (either due to activity or energy detect) + * @NL80211_SURVEY_INFO_CHANNEL_TIME_EXT_BUSY: amount of time the extension + * channel was sensed busy + * @NL80211_SURVEY_INFO_CHANNEL_TIME_RX: amount of time the radio spent + * receiving data + * @NL80211_SURVEY_INFO_CHANNEL_TIME_TX: amount of time the radio spent + * transmitting data + * @NL80211_SURVEY_INFO_MAX: highest survey info attribute number + * currently defined + * @__NL80211_SURVEY_INFO_AFTER_LAST: internal use + */ +""" +__NL80211_SURVEY_INFO_INVALID = 0 +NL80211_SURVEY_INFO_FREQUENCY = 1 +NL80211_SURVEY_INFO_NOISE = 2 +NL80211_SURVEY_INFO_IN_USE = 3 +NL80211_SURVEY_INFO_CHANNEL_TIME = 4 +NL80211_SURVEY_INFO_CHANNEL_TIME_BUSY = 5 +NL80211_SURVEY_INFO_CHANNEL_TIME_EXT_BUSY = 6 +NL80211_SURVEY_INFO_CHANNEL_TIME_RX = 7 +NL80211_SURVEY_INFO_CHANNEL_TIME_TX = 8 +NUM_NL80211_SURVEY_INFO = 8 + +""" +/** + * enum nl80211_mntr_flags - monitor configuration flags + * + * Monitor configuration flags. + * + * @__NL80211_MNTR_FLAG_INVALID: reserved + * + * @NL80211_MNTR_FLAG_FCSFAIL: pass frames with bad FCS + * @NL80211_MNTR_FLAG_PLCPFAIL: pass frames with bad PLCP + * @NL80211_MNTR_FLAG_CONTROL: pass control frames + * @NL80211_MNTR_FLAG_OTHER_BSS: disable BSSID filtering + * @NL80211_MNTR_FLAG_COOK_FRAMES: report frames after processing. + * overrides all other flags. + * @NL80211_MNTR_FLAG_ACTIVE: use the configured MAC address + * and ACK incoming unicast packets. + * + * @__NL80211_MNTR_FLAG_AFTER_LAST: internal use + * @NL80211_MNTR_FLAG_MAX: highest possible monitor flag + */ +""" +NL80211_MNTR_FLAGS = ['invalid','fcsfail','plcpfail','control', + 'other bss','cook','active'] +__NL80211_MNTR_FLAG_INVALID = 0 +NL80211_MNTR_FLAG_FCSFAIL = 1 +NL80211_MNTR_FLAG_PLCPFAIL = 2 +NL80211_MNTR_FLAG_CONTROL = 3 +NL80211_MNTR_FLAG_OTHER_BSS = 4 +NL80211_MNTR_FLAG_COOK_FRAMES = 5 +NL80211_MNTR_FLAG_ACTIVE = 6 +NUM_NL80211_MNTR_FLAG_MAX = 6 + +""" +/** + * enum nl80211_mesh_power_mode - mesh power save modes + * + * @NL80211_MESH_POWER_UNKNOWN: The mesh power mode of the mesh STA is + * not known or has not been set yet. + * @NL80211_MESH_POWER_ACTIVE: Active mesh power mode. The mesh STA is + * in Awake state all the time. + * @NL80211_MESH_POWER_LIGHT_SLEEP: Light sleep mode. The mesh STA will + * alternate between Active and Doze states, but will wake up for + * neighbor's beacons. + * @NL80211_MESH_POWER_DEEP_SLEEP: Deep sleep mode. The mesh STA will + * alternate between Active and Doze states, but may not wake up + * for neighbor's beacons. + * + * @__NL80211_MESH_POWER_AFTER_LAST - internal use + * @NL80211_MESH_POWER_MAX - highest possible power save level + */ +""" +NL80211_MESH_POWER_UNKNOWN = 0 +NL80211_MESH_POWER_ACTIVE = 1 +NL80211_MESH_POWER_LIGHT_SLEEP = 2 +NL80211_MESH_POWER_DEEP_SLEEP = 3 +NUM_NL80211_MESH_POWER = 3 + +""" +/** + * enum nl80211_meshconf_params - mesh configuration parameters + * + * Mesh configuration parameters. These can be changed while the mesh is + * active. + * + * @__NL80211_MESHCONF_INVALID: internal use + * + * @NL80211_MESHCONF_RETRY_TIMEOUT: specifies the initial retry timeout in + * millisecond units, used by the Peer Link Open message + * + * @NL80211_MESHCONF_CONFIRM_TIMEOUT: specifies the initial confirm timeout, in + * millisecond units, used by the peer link management to close a peer link + * + * @NL80211_MESHCONF_HOLDING_TIMEOUT: specifies the holding timeout, in + * millisecond units + * + * @NL80211_MESHCONF_MAX_PEER_LINKS: maximum number of peer links allowed + * on this mesh interface + * + * @NL80211_MESHCONF_MAX_RETRIES: specifies the maximum number of peer link + * open retries that can be sent to establish a new peer link instance in a + * mesh + * + * @NL80211_MESHCONF_TTL: specifies the value of TTL field set at a source mesh + * point. + * + * @NL80211_MESHCONF_AUTO_OPEN_PLINKS: whether we should automatically open + * peer links when we detect compatible mesh peers. Disabled if + * @NL80211_MESH_SETUP_USERSPACE_MPM or @NL80211_MESH_SETUP_USERSPACE_AMPE are + * set. + * + * @NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES: the number of action frames + * containing a PREQ that an MP can send to a particular destination (path + * target) + * + * @NL80211_MESHCONF_PATH_REFRESH_TIME: how frequently to refresh mesh paths + * (in milliseconds) + * + * @NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT: minimum length of time to wait + * until giving up on a path discovery (in milliseconds) + * + * @NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT: The time (in TUs) for which mesh + * points receiving a PREQ shall consider the forwarding information from + * the root to be valid. (TU = time unit) + * + * @NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL: The minimum interval of time (in + * TUs) during which an MP can send only one action frame containing a PREQ + * reference element + * + * @NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME: The interval of time (in TUs) + * that it takes for an HWMP information element to propagate across the + * mesh + * + * @NL80211_MESHCONF_HWMP_ROOTMODE: whether root mode is enabled or not + * + * @NL80211_MESHCONF_ELEMENT_TTL: specifies the value of TTL field set at a + * source mesh point for path selection elements. + * + * @NL80211_MESHCONF_HWMP_RANN_INTERVAL: The interval of time (in TUs) between + * root announcements are transmitted. + * + * @NL80211_MESHCONF_GATE_ANNOUNCEMENTS: Advertise that this mesh station has + * access to a broader network beyond the MBSS. This is done via Root + * Announcement frames. + * + * @NL80211_MESHCONF_HWMP_PERR_MIN_INTERVAL: The minimum interval of time (in + * TUs) during which a mesh STA can send only one Action frame containing a + * PERR element. + * + * @NL80211_MESHCONF_FORWARDING: set Mesh STA as forwarding or non-forwarding + * or forwarding entity (default is TRUE - forwarding entity) + * + * @NL80211_MESHCONF_RSSI_THRESHOLD: RSSI threshold in dBm. This specifies the + * threshold for average signal strength of candidate station to establish + * a peer link. + * + * @NL80211_MESHCONF_SYNC_OFFSET_MAX_NEIGHBOR: maximum number of neighbors + * to synchronize to for 11s default synchronization method + * (see 11C.12.2.2) + * + * @NL80211_MESHCONF_HT_OPMODE: set mesh HT protection mode. + * + * @NL80211_MESHCONF_ATTR_MAX: highest possible mesh configuration attribute + * + * @NL80211_MESHCONF_HWMP_PATH_TO_ROOT_TIMEOUT: The time (in TUs) for + * which mesh STAs receiving a proactive PREQ shall consider the forwarding + * information to the root mesh STA to be valid. + * + * @NL80211_MESHCONF_HWMP_ROOT_INTERVAL: The interval of time (in TUs) between + * proactive PREQs are transmitted. + * + * @NL80211_MESHCONF_HWMP_CONFIRMATION_INTERVAL: The minimum interval of time + * (in TUs) during which a mesh STA can send only one Action frame + * containing a PREQ element for root path confirmation. + * + * @NL80211_MESHCONF_POWER_MODE: Default mesh power mode for new peer links. + * type &enum nl80211_mesh_power_mode (u32) + * + * @NL80211_MESHCONF_AWAKE_WINDOW: awake window duration (in TUs) + * + * @NL80211_MESHCONF_PLINK_TIMEOUT: If no tx activity is seen from a STA we've + * established peering with for longer than this time (in seconds), then + * remove it from the STA's list of peers. Default is 30 minutes. + * + * @__NL80211_MESHCONF_ATTR_AFTER_LAST: internal use + */ +""" +__NL80211_MESHCONF_INVALID = 0 +NL80211_MESHCONF_RETRY_TIMEOUT = 1 +NL80211_MESHCONF_CONFIRM_TIMEOUT = 2 +NL80211_MESHCONF_HOLDING_TIMEOUT = 3 +NL80211_MESHCONF_MAX_PEER_LINKS = 4 +NL80211_MESHCONF_MAX_RETRIES = 5 +NL80211_MESHCONF_TTL = 6 +NL80211_MESHCONF_AUTO_OPEN_PLINKS = 7 +NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES = 8 +NL80211_MESHCONF_PATH_REFRESH_TIME = 9 +NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT = 10 +NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT = 11 +NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL = 12 +NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME = 13 +NL80211_MESHCONF_HWMP_ROOTMODE = 14 +NL80211_MESHCONF_ELEMENT_TTL = 15 +NL80211_MESHCONF_HWMP_RANN_INTERVAL = 16 +NL80211_MESHCONF_GATE_ANNOUNCEMENTS = 17 +NL80211_MESHCONF_HWMP_PERR_MIN_INTERVAL = 18 +NL80211_MESHCONF_FORWARDING = 19 +NL80211_MESHCONF_RSSI_THRESHOLD = 20 +NL80211_MESHCONF_SYNC_OFFSET_MAX_NEIGHBOR = 21 +NL80211_MESHCONF_HT_OPMODE = 22 +NL80211_MESHCONF_HWMP_PATH_TO_ROOT_TIMEOUT = 23 +NL80211_MESHCONF_HWMP_ROOT_INTERVAL = 24 +NL80211_MESHCONF_HWMP_CONFIRMATION_INTERVAL = 25 +NL80211_MESHCONF_POWER_MODE = 26 +NL80211_MESHCONF_AWAKE_WINDOW = 27 +NL80211_MESHCONF_PLINK_TIMEOUT = 28 +NUM_NL80211_MESHCONF_ATTR = 28 + +""" +/** + * enum nl80211_mesh_setup_params - mesh setup parameters + * + * Mesh setup parameters. These are used to start/join a mesh and cannot be + * changed while the mesh is active. + * + * @__NL80211_MESH_SETUP_INVALID: Internal use + * + * @NL80211_MESH_SETUP_ENABLE_VENDOR_PATH_SEL: Enable this option to use a + * vendor specific path selection algorithm or disable it to use the + * default HWMP. + * + * @NL80211_MESH_SETUP_ENABLE_VENDOR_METRIC: Enable this option to use a + * vendor specific path metric or disable it to use the default Airtime + * metric. + * + * @NL80211_MESH_SETUP_IE: Information elements for this mesh, for instance, a + * robust security network ie, or a vendor specific information element + * that vendors will use to identify the path selection methods and + * metrics in use. + * + * @NL80211_MESH_SETUP_USERSPACE_AUTH: Enable this option if an authentication + * daemon will be authenticating mesh candidates. + * + * @NL80211_MESH_SETUP_USERSPACE_AMPE: Enable this option if an authentication + * daemon will be securing peer link frames. AMPE is a secured version of + * Mesh Peering Management (MPM) and is implemented with the assistance of + * a userspace daemon. When this flag is set, the kernel will send peer + * management frames to a userspace daemon that will implement AMPE + * functionality (security capabilities selection, key confirmation, and + * key management). When the flag is unset (default), the kernel can + * autonomously complete (unsecured) mesh peering without the need of a + * userspace daemon. + * + * @NL80211_MESH_SETUP_ENABLE_VENDOR_SYNC: Enable this option to use a + * vendor specific synchronization method or disable it to use the default + * neighbor offset synchronization + * + * @NL80211_MESH_SETUP_USERSPACE_MPM: Enable this option if userspace will + * implement an MPM which handles peer allocation and state. + * + * @NL80211_MESH_SETUP_AUTH_PROTOCOL: Inform the kernel of the authentication + * method (u8, as defined in IEEE 8.4.2.100.6, e.g. 0x1 for SAE). + * Default is no authentication method required. + * + * @NL80211_MESH_SETUP_ATTR_MAX: highest possible mesh setup attribute number + * + * @__NL80211_MESH_SETUP_ATTR_AFTER_LAST: Internal use + */ +""" +__NL80211_MESH_SETUP_INVALID = 0 +NL80211_MESH_SETUP_ENABLE_VENDOR_PATH_SEL = 1 +NL80211_MESH_SETUP_ENABLE_VENDOR_METRIC = 2 +NL80211_MESH_SETUP_IE = 3 +NL80211_MESH_SETUP_USERSPACE_AUTH = 4 +NL80211_MESH_SETUP_USERSPACE_AMPE = 5 +NL80211_MESH_SETUP_ENABLE_VENDOR_SYNC = 6 +NL80211_MESH_SETUP_USERSPACE_MPM = 7 +NL80211_MESH_SETUP_AUTH_PROTOCOL = 8 +NUM_NL80211_MESH_SETUP_ATTR = 8 + +""" +/** + * enum nl80211_txq_attr - TX queue parameter attributes + * @__NL80211_TXQ_ATTR_INVALID: Attribute number 0 is reserved + * @NL80211_TXQ_ATTR_AC: AC identifier (NL80211_AC_*) + * @NL80211_TXQ_ATTR_TXOP: Maximum burst time in units of 32 usecs, 0 meaning + * disabled + * @NL80211_TXQ_ATTR_CWMIN: Minimum contention window [a value of the form + * 2^n-1 in the range 1..32767] + * @NL80211_TXQ_ATTR_CWMAX: Maximum contention window [a value of the form + * 2^n-1 in the range 1..32767] + * @NL80211_TXQ_ATTR_AIFS: Arbitration interframe space [0..255] + * @__NL80211_TXQ_ATTR_AFTER_LAST: Internal + * @NL80211_TXQ_ATTR_MAX: Maximum TXQ attribute number + */ +""" +__NL80211_TXQ_ATTR_INVALID = 0 +NL80211_TXQ_ATTR_AC = 1 +NL80211_TXQ_ATTR_TXOP = 2 +NL80211_TXQ_ATTR_CWMIN = 3 +NL80211_TXQ_ATTR_CWMAX = 4 +NL80211_TXQ_ATTR_AIFS = 5 +NUM_NL80211_TXQ_ATTR = 5 + +NL80211_AC_VO = 0 +NL80211_AC_VI = 1 +NL80211_AC_BE = 2 +NL80211_AC_BK = 3 +NL80211_NUM_ACS = 3 + +# backward compat +NL80211_TXQ_ATTR_QUEUE = NL80211_TXQ_ATTR_AC +NL80211_TXQ_Q_VO = NL80211_AC_VO +NL80211_TXQ_Q_VI = NL80211_AC_VI +NL80211_TXQ_Q_BE = NL80211_AC_BE +NL80211_TXQ_Q_BK = NL80211_AC_BK + +""" +/** + * enum nl80211_channel_type - channel type + * @NL80211_CHAN_NO_HT: 20 MHz, non-HT channel + * @NL80211_CHAN_HT20: 20 MHz HT channel + * @NL80211_CHAN_HT40MINUS: HT40 channel, secondary channel + * below the control channel + * @NL80211_CHAN_HT40PLUS: HT40 channel, secondary channel + * above the control channel + */ +""" +NL80211_CHAN_WIDTHS = [None,'HT20','HT40-','HT40+'] +NL80211_CHAN_NO_HT = 0 +NL80211_CHAN_HT20 = 1 +NL80211_CHAN_HT40MINUS = 2 +NL80211_CHAN_HT40PLUS = 3 + +""" +/** + * enum nl80211_chan_width - channel width definitions + * + * These values are used with the %NL80211_ATTR_CHANNEL_WIDTH + * attribute. + * + * @NL80211_CHAN_WIDTH_20_NOHT: 20 MHz, non-HT channel + * @NL80211_CHAN_WIDTH_20: 20 MHz HT channel + * @NL80211_CHAN_WIDTH_40: 40 MHz channel, the %NL80211_ATTR_CENTER_FREQ1 + * attribute must be provided as well + * @NL80211_CHAN_WIDTH_80: 80 MHz channel, the %NL80211_ATTR_CENTER_FREQ1 + * attribute must be provided as well + * @NL80211_CHAN_WIDTH_80P80: 80+80 MHz channel, the %NL80211_ATTR_CENTER_FREQ1 + * and %NL80211_ATTR_CENTER_FREQ2 attributes must be provided as well + * @NL80211_CHAN_WIDTH_160: 160 MHz channel, the %NL80211_ATTR_CENTER_FREQ1 + * attribute must be provided as well + * @NL80211_CHAN_WIDTH_5: 5 MHz OFDM channel + * @NL80211_CHAN_WIDTH_10: 10 MHz OFDM channel + */ +""" +NL80211_CHAN_WIDTH_20_NOHT = 0 +NL80211_CHAN_WIDTH_20 = 1 +NL80211_CHAN_WIDTH_40 = 2 +NL80211_CHAN_WIDTH_80 = 3 +NL80211_CHAN_WIDTH_80P80 = 4 +NL80211_CHAN_WIDTH_160 = 5 +NL80211_CHAN_WIDTH_5 = 6 +NL80211_CHAN_WIDTH_10 = 7 + +""" +/** + * enum nl80211_bss_scan_width - control channel width for a BSS + * + * These values are used with the %NL80211_BSS_CHAN_WIDTH attribute. + * + * @NL80211_BSS_CHAN_WIDTH_20: control channel is 20 MHz wide or compatible + * @NL80211_BSS_CHAN_WIDTH_10: control channel is 10 MHz wide + * @NL80211_BSS_CHAN_WIDTH_5: control channel is 5 MHz wide + */ +""" +NL80211_BSS_CHAN_WIDTH_20 = 0 +NL80211_BSS_CHAN_WIDTH_10 = 1 +NL80211_BSS_CHAN_WIDTH_5 = 2 + +""" +/** + * enum nl80211_bss - netlink attributes for a BSS + * + * @__NL80211_BSS_INVALID: invalid + * @NL80211_BSS_BSSID: BSSID of the BSS (6 octets) + * @NL80211_BSS_FREQUENCY: frequency in MHz (u32) + * @NL80211_BSS_TSF: TSF of the received probe response/beacon (u64) + * @NL80211_BSS_BEACON_INTERVAL: beacon interval of the (I)BSS (u16) + * @NL80211_BSS_CAPABILITY: capability field (CPU order, u16) + * @NL80211_BSS_INFORMATION_ELEMENTS: binary attribute containing the + * raw information elements from the probe response/beacon (bin); + * if the %NL80211_BSS_BEACON_IES attribute is present, the IEs here are + * from a Probe Response frame; otherwise they are from a Beacon frame. + * However, if the driver does not indicate the source of the IEs, these + * IEs may be from either frame subtype. + * @NL80211_BSS_SIGNAL_MBM: signal strength of probe response/beacon + * in mBm (100 * dBm) (s32) + * @NL80211_BSS_SIGNAL_UNSPEC: signal strength of the probe response/beacon + * in unspecified units, scaled to 0..100 (u8) + * @NL80211_BSS_STATUS: status, if this BSS is "used" + * @NL80211_BSS_SEEN_MS_AGO: age of this BSS entry in ms + * @NL80211_BSS_BEACON_IES: binary attribute containing the raw information + * elements from a Beacon frame (bin); not present if no Beacon frame has + * yet been received + * @NL80211_BSS_CHAN_WIDTH: channel width of the control channel + * (u32, enum nl80211_bss_scan_width) + * @__NL80211_BSS_AFTER_LAST: internal + * @NL80211_BSS_MAX: highest BSS attribute + */ +""" +__NL80211_BSS_INVALID = 0 +NL80211_BSS_BSSID = 1 +NL80211_BSS_FREQUENCY = 2 +NL80211_BSS_TSF = 3 +NL80211_BSS_BEACON_INTERVAL = 4 +NL80211_BSS_CAPABILITY = 5 +NL80211_BSS_INFORMATION_ELEMENTS = 6 +NL80211_BSS_SIGNAL_MBM = 7 +NL80211_BSS_SIGNAL_UNSPEC = 8 +NL80211_BSS_STATUS = 9 +NL80211_BSS_SEEN_MS_AGO = 10 +NL80211_BSS_BEACON_IES = 11 +NL80211_BSS_CHAN_WIDTH = 12 +NUM_NL80211_BSS = 12 + +""" +/** + * enum nl80211_bss_status - BSS "status" + * @NL80211_BSS_STATUS_AUTHENTICATED: Authenticated with this BSS. + * @NL80211_BSS_STATUS_ASSOCIATED: Associated with this BSS. + * @NL80211_BSS_STATUS_IBSS_JOINED: Joined to this IBSS. + * + * The BSS status is a BSS attribute in scan dumps, which + * indicates the status the interface has wrt. this BSS. + */ +""" +NL80211_BSS_STATUS_AUTHENTICATED = 0 +NL80211_BSS_STATUS_ASSOCIATED = 1 +NL80211_BSS_STATUS_IBSS_JOINED = 2 + +""" +/** + * enum nl80211_auth_type - AuthenticationType + * + * @NL80211_AUTHTYPE_OPEN_SYSTEM: Open System authentication + * @NL80211_AUTHTYPE_SHARED_KEY: Shared Key authentication (WEP only) + * @NL80211_AUTHTYPE_FT: Fast BSS Transition (IEEE 802.11r) + * @NL80211_AUTHTYPE_NETWORK_EAP: Network EAP (some Cisco APs and mainly LEAP) + * @NL80211_AUTHTYPE_SAE: Simultaneous authentication of equals + * @__NL80211_AUTHTYPE_NUM: internal + * @NL80211_AUTHTYPE_MAX: maximum valid auth algorithm + * @NL80211_AUTHTYPE_AUTOMATIC: determine automatically (if necessary by + * trying multiple times); this is invalid in netlink -- leave out + * the attribute for this on CONNECT commands. + */ +""" +NL80211_AUTHTYPE_OPEN_SYSTEM = 0 +NL80211_AUTHTYPE_SHARED_KEY = 1 +NL80211_AUTHTYPE_FT = 2 +NL80211_AUTHTYPE_NETWORK_EAP = 3 +NL80211_AUTHTYPE_SAE = 4 +NUM_NL80211_AUTHTYPE = 5 +#NL80211_AUTHTYPE_AUTOMATIC = 7 invalid in netlink + +""" +/** + * enum nl80211_key_type - Key Type + * @NL80211_KEYTYPE_GROUP: Group (broadcast/multicast) key + * @NL80211_KEYTYPE_PAIRWISE: Pairwise (unicast/individual) key + * @NL80211_KEYTYPE_PEERKEY: PeerKey (DLS) + * @NUM_NL80211_KEYTYPES: number of defined key types + */ +""" +NL80211_KEYTYPE_GROUP = 0 +NL80211_KEYTYPE_PAIRWISE = 1 +NL80211_KEYTYPE_PEERKEY = 2 +NUM_NL80211_KEYTYPES = 3 + +""" +/** + * enum nl80211_mfp - Management frame protection state + * @NL80211_MFP_NO: Management frame protection not used + * @NL80211_MFP_REQUIRED: Management frame protection required + */ +""" +NL80211_MFP_NO = 1 +NL80211_MFP_REQUIRED = 2 + +NL80211_WPA_VERSION_1 = 1 << 0 +NL80211_WPA_VERSION_2 = 1 << 1 + +""" +/** + * enum nl80211_key_default_types - key default types + * @__NL80211_KEY_DEFAULT_TYPE_INVALID: invalid + * @NL80211_KEY_DEFAULT_TYPE_UNICAST: key should be used as default + * unicast key + * @NL80211_KEY_DEFAULT_TYPE_MULTICAST: key should be used as default + * multicast key + * @NUM_NL80211_KEY_DEFAULT_TYPES: number of default types + */ +""" +__NL80211_KEY_DEFAULT_TYPE_INVALID = 1 +NL80211_KEY_DEFAULT_TYPE_UNICAST = 2 +NL80211_KEY_DEFAULT_TYPE_MULTICAST = 3 +NUM_NL80211_KEY_DEFAULT_TYPES = 4 + +""" +/** + * enum nl80211_key_attributes - key attributes + * @__NL80211_KEY_INVALID: invalid + * @NL80211_KEY_DATA: (temporal) key data; for TKIP this consists of + * 16 bytes encryption key followed by 8 bytes each for TX and RX MIC + * keys + * @NL80211_KEY_IDX: key ID (u8, 0-3) + * @NL80211_KEY_CIPHER: key cipher suite (u32, as defined by IEEE 802.11 + * section 7.3.2.25.1, e.g. 0x000FAC04) + * @NL80211_KEY_SEQ: transmit key sequence number (IV/PN) for TKIP and + * CCMP keys, each six bytes in little endian + * @NL80211_KEY_DEFAULT: flag indicating default key + * @NL80211_KEY_DEFAULT_MGMT: flag indicating default management key + * @NL80211_KEY_TYPE: the key type from enum nl80211_key_type, if not + * specified the default depends on whether a MAC address was + * given with the command using the key or not (u32) + * @NL80211_KEY_DEFAULT_TYPES: A nested attribute containing flags + * attributes, specifying what a key should be set as default as. + * See &enum nl80211_key_default_types. + * @__NL80211_KEY_AFTER_LAST: internal + * @NL80211_KEY_MAX: highest key attribute + */ +""" +__NL80211_KEY_INVALID = 0 +NL80211_KEY_DATA = 1 +NL80211_KEY_IDX = 2 +NL80211_KEY_CIPHER = 3 +NL80211_KEY_SEQ = 4 +NL80211_KEY_DEFAULT = 5 +NL80211_KEY_DEFAULT_MGMT = 6 +NL80211_KEY_TYPE = 7 +NL80211_KEY_DEFAULT_TYPES = 8 +MAX_NL80211_KEY = 8 + +""" +/** + * enum nl80211_tx_rate_attributes - TX rate set attributes + * @__NL80211_TXRATE_INVALID: invalid + * @NL80211_TXRATE_LEGACY: Legacy (non-MCS) rates allowed for TX rate selection + * in an array of rates as defined in IEEE 802.11 7.3.2.2 (u8 values with + * 1 = 500 kbps) but without the IE length restriction (at most + * %NL80211_MAX_SUPP_RATES in a single array). + * @NL80211_TXRATE_MCS: HT (MCS) rates allowed for TX rate selection + * in an array of MCS numbers. + * @__NL80211_TXRATE_AFTER_LAST: internal + * @NL80211_TXRATE_MAX: highest TX rate attribute + */ +""" +__NL80211_TXRATE_INVALID = 0 +NL80211_TXRATE_LEGACY = 1 +NL80211_TXRATE_MCS = 2 +MAX_NL80211_TXRATE = 2 + +""" +/** + * enum nl80211_band - Frequency band + * @NL80211_BAND_2GHZ: 2.4 GHz ISM band + * @NL80211_BAND_5GHZ: around 5 GHz band (4.9 - 5.7 GHz) + * @NL80211_BAND_60GHZ: around 60 GHz band (58.32 - 64.80 GHz) + */ +""" +NL80211_BAND_2GHZ = 0 +NL80211_BAND_5GHZ = 1 +NL80211_BAND_60GHZ = 2 + +""" +/** + * enum nl80211_ps_state - powersave state + * @NL80211_PS_DISABLED: powersave is disabled + * @NL80211_PS_ENABLED: powersave is enabled + */ +""" +NL80211_PS_DISABLED = 0 +NL80211_PS_ENABLED = 1 + +""" +/** + * enum nl80211_attr_cqm - connection quality monitor attributes + * @__NL80211_ATTR_CQM_INVALID: invalid + * @NL80211_ATTR_CQM_RSSI_THOLD: RSSI threshold in dBm. This value specifies + * the threshold for the RSSI level at which an event will be sent. Zero + * to disable. + * @NL80211_ATTR_CQM_RSSI_HYST: RSSI hysteresis in dBm. This value specifies + * the minimum amount the RSSI level must change after an event before a + * new event may be issued (to reduce effects of RSSI oscillation). + * @NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT: RSSI threshold event + * @NL80211_ATTR_CQM_PKT_LOSS_EVENT: a u32 value indicating that this many + * consecutive packets were not acknowledged by the peer + * @NL80211_ATTR_CQM_TXE_RATE: TX error rate in %. Minimum % of TX failures + * during the given %NL80211_ATTR_CQM_TXE_INTVL before an + * %NL80211_CMD_NOTIFY_CQM with reported %NL80211_ATTR_CQM_TXE_RATE and + * %NL80211_ATTR_CQM_TXE_PKTS is generated. + * @NL80211_ATTR_CQM_TXE_PKTS: number of attempted packets in a given + * %NL80211_ATTR_CQM_TXE_INTVL before %NL80211_ATTR_CQM_TXE_RATE is + * checked. + * @NL80211_ATTR_CQM_TXE_INTVL: interval in seconds. Specifies the periodic + * interval in which %NL80211_ATTR_CQM_TXE_PKTS and + * %NL80211_ATTR_CQM_TXE_RATE must be satisfied before generating an + * %NL80211_CMD_NOTIFY_CQM. Set to 0 to turn off TX error reporting. + * @__NL80211_ATTR_CQM_AFTER_LAST: internal + * @NL80211_ATTR_CQM: highest key attribute + */ +""" +__NL80211_ATTR_CQM_INVALID = 0 +NL80211_ATTR_CQM_RSSI_THOLD = 1 +NL80211_ATTR_CQM_RSSI_HYST = 2 +NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT = 3 +NL80211_ATTR_CQM_PKT_LOSS_EVENT = 4 +NL80211_ATTR_CQM_TXE_RATE = 5 +NL80211_ATTR_CQM_TXE_PKTS = 6 +NL80211_ATTR_CQM_TXE_INTVL = 7 +MAX_NL80211_ATTR_CQM = 7 + +""" +/** + * enum nl80211_cqm_rssi_threshold_event - RSSI threshold event + * @NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW: The RSSI level is lower than the + * configured threshold + * @NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH: The RSSI is higher than the + * configured threshold + * @NL80211_CQM_RSSI_BEACON_LOSS_EVENT: The device experienced beacon loss. + * (Note that deauth/disassoc will still follow if the AP is not + * available. This event might get used as roaming event, etc.) + */ +""" +NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW = 1 +NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH = 1 +NL80211_CQM_RSSI_BEACON_LOSS_EVENT = 2 + +""" +/** + * enum nl80211_tx_power_setting - TX power adjustment + * @NL80211_TX_POWER_AUTOMATIC: automatically determine transmit power + * @NL80211_TX_POWER_LIMITED: limit TX power by the mBm parameter + * @NL80211_TX_POWER_FIXED: fix TX power to the mBm parameter + */ +""" +NL80211_TX_POWER_AUTOMATIC = 0 +NL80211_TX_POWER_LIMITED = 1 +NL80211_TX_POWER_FIXED = 2 + +""" +/** + * enum nl80211_packet_pattern_attr - packet pattern attribute + * @__NL80211_PKTPAT_INVALID: invalid number for nested attribute + * @NL80211_PKTPAT_PATTERN: the pattern, values where the mask has + * a zero bit are ignored + * @NL80211_PKTPAT_MASK: pattern mask, must be long enough to have + * a bit for each byte in the pattern. The lowest-order bit corresponds + * to the first byte of the pattern, but the bytes of the pattern are + * in a little-endian-like format, i.e. the 9th byte of the pattern + * corresponds to the lowest-order bit in the second byte of the mask. + * For example: The match 00:xx:00:00:xx:00:00:00:00:xx:xx:xx (where + * xx indicates "don't care") would be represented by a pattern of + * twelve zero bytes, and a mask of "0xed,0x01". + * Note that the pattern matching is done as though frames were not + * 802.11 frames but 802.3 frames, i.e. the frame is fully unpacked + * first (including SNAP header unpacking) and then matched. + * @NL80211_PKTPAT_OFFSET: packet offset, pattern is matched after + * these fixed number of bytes of received packet + * @NUM_NL80211_PKTPAT: number of attributes + * @MAX_NL80211_PKTPAT: max attribute number + */ +""" +__NL80211_PKTPAT_INVALID = 0 +NL80211_PKTPAT_MASK = 1 +NL80211_PKTPAT_PATTERN = 2 +NL80211_PKTPAT_OFFSET = 3 +NUM_NL80211_PKTPAT = 4 +MAX_NL80211_PKTPAT = 3 + +""" +/** + * struct nl80211_pattern_support - packet pattern support information + * @max_patterns: maximum number of patterns supported + * @min_pattern_len: minimum length of each pattern + * @max_pattern_len: maximum length of each pattern + * @max_pkt_offset: maximum Rx packet offset + * + * This struct is carried in %NL80211_WOWLAN_TRIG_PKT_PATTERN when + * that is part of %NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED or in + * %NL80211_ATTR_COALESCE_RULE_PKT_PATTERN when that is part of + * %NL80211_ATTR_COALESCE_RULE in the capability information given + * by the kernel to userspace. + */ +""" +dot11_nl80211_pattern_support = "IIII" +DOT11SPATTERNSUPPORT = struct.calcsize(dot11_nl80211_pattern_support) +def nl80211_pattern_support(max_patterns,min_len,max_len,max_offset): + """ + create a nl80211_pattern_support + :param max_patterns: maximum # of patterns supported + :param min_len: minimum pattern length + :param max_len: maximum length + :param max_offset: maximum packet offset + :returns: a packed nl80211_pattern_support + """ + return struct.pack(dot11_nl80211_pattern_support,max_patterns, + min_len, + max_len, + max_offset) + +# backward compatibility +__NL80211_WOWLAN_PKTPAT_INVALID = __NL80211_PKTPAT_INVALID +NL80211_WOWLAN_PKTPAT_MASK = NL80211_PKTPAT_MASK +NL80211_WOWLAN_PKTPAT_PATTERN = NL80211_PKTPAT_PATTERN +NL80211_WOWLAN_PKTPAT_OFFSET = NL80211_PKTPAT_OFFSET +NUM_NL80211_WOWLAN_PKTPAT = NUM_NL80211_PKTPAT +MAX_NL80211_WOWLAN_PKTPAT = MAX_NL80211_PKTPAT +nl80211_wowlan_pattern_support = nl80211_pattern_support + +""" +/** + * enum nl80211_wowlan_triggers - WoWLAN trigger definitions + * @__NL80211_WOWLAN_TRIG_INVALID: invalid number for nested attributes + * @NL80211_WOWLAN_TRIG_ANY: wake up on any activity, do not really put + * the chip into a special state -- works best with chips that have + * support for low-power operation already (flag) + * @NL80211_WOWLAN_TRIG_DISCONNECT: wake up on disconnect, the way disconnect + * is detected is implementation-specific (flag) + * @NL80211_WOWLAN_TRIG_MAGIC_PKT: wake up on magic packet (6x 0xff, followed + * by 16 repetitions of MAC addr, anywhere in payload) (flag) + * @NL80211_WOWLAN_TRIG_PKT_PATTERN: wake up on the specified packet patterns + * which are passed in an array of nested attributes, each nested attribute + * defining a with attributes from &struct nl80211_wowlan_trig_pkt_pattern. + * Each pattern defines a wakeup packet. Packet offset is associated with + * each pattern which is used while matching the pattern. The matching is + * done on the MSDU, i.e. as though the packet was an 802.3 packet, so the + * pattern matching is done after the packet is converted to the MSDU. + * + * In %NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED, it is a binary attribute + * carrying a &struct nl80211_pattern_support. + * + * When reporting wakeup. it is a u32 attribute containing the 0-based + * index of the pattern that caused the wakeup, in the patterns passed + * to the kernel when configuring. + * @NL80211_WOWLAN_TRIG_GTK_REKEY_SUPPORTED: Not a real trigger, and cannot be + * used when setting, used only to indicate that GTK rekeying is supported + * by the device (flag) + * @NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE: wake up on GTK rekey failure (if + * done by the device) (flag) + * @NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST: wake up on EAP Identity Request + * packet (flag) + * @NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE: wake up on 4-way handshake (flag) + * @NL80211_WOWLAN_TRIG_RFKILL_RELEASE: wake up when rfkill is released + * (on devices that have rfkill in the device) (flag) + * @NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211: For wakeup reporting only, contains + * the 802.11 packet that caused the wakeup, e.g. a deauth frame. The frame + * may be truncated, the @NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211_LEN + * attribute contains the original length. + * @NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211_LEN: Original length of the 802.11 + * packet, may be bigger than the @NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211 + * attribute if the packet was truncated somewhere. + * @NL80211_WOWLAN_TRIG_WAKEUP_PKT_8023: For wakeup reporting only, contains the + * 802.11 packet that caused the wakeup, e.g. a magic packet. The frame may + * be truncated, the @NL80211_WOWLAN_TRIG_WAKEUP_PKT_8023_LEN attribute + * contains the original length. + * @NL80211_WOWLAN_TRIG_WAKEUP_PKT_8023_LEN: Original length of the 802.3 + * packet, may be bigger than the @NL80211_WOWLAN_TRIG_WAKEUP_PKT_8023 + * attribute if the packet was truncated somewhere. + * @NL80211_WOWLAN_TRIG_TCP_CONNECTION: TCP connection wake, see DOC section + * "TCP connection wakeup" for more details. This is a nested attribute + * containing the exact information for establishing and keeping alive + * the TCP connection. + * @NL80211_WOWLAN_TRIG_TCP_WAKEUP_MATCH: For wakeup reporting only, the + * wakeup packet was received on the TCP connection + * @NL80211_WOWLAN_TRIG_WAKEUP_TCP_CONNLOST: For wakeup reporting only, the + * TCP connection was lost or failed to be established + * @NL80211_WOWLAN_TRIG_WAKEUP_TCP_NOMORETOKENS: For wakeup reporting only, + * the TCP connection ran out of tokens to use for data to send to the + * service + * @NUM_NL80211_WOWLAN_TRIG: number of wake on wireless triggers + * @MAX_NL80211_WOWLAN_TRIG: highest wowlan trigger attribute number + * + * These nested attributes are used to configure the wakeup triggers and + * to report the wakeup reason(s). + */ +""" +__NL80211_WOWLAN_TRIG_INVALID = 0 +NL80211_WOWLAN_TRIG_ANY = 1 +NL80211_WOWLAN_TRIG_DISCONNECT = 2 +NL80211_WOWLAN_TRIG_MAGIC_PKT = 3 +NL80211_WOWLAN_TRIG_PKT_PATTERN = 4 +NL80211_WOWLAN_TRIG_GTK_REKEY_SUPPORTED = 5 +NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE = 6 +NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST = 7 +NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE = 8 +NL80211_WOWLAN_TRIG_RFKILL_RELEASE = 9 +NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211 = 10 +NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211_LEN = 11 +NL80211_WOWLAN_TRIG_WAKEUP_PKT_8023 = 12 +NL80211_WOWLAN_TRIG_WAKEUP_PKT_8023_LEN = 13 +NL80211_WOWLAN_TRIG_TCP_CONNECTION = 14 +NL80211_WOWLAN_TRIG_WAKEUP_TCP_MATCH = 15 +NL80211_WOWLAN_TRIG_WAKEUP_TCP_CONNLOST = 16 +NL80211_WOWLAN_TRIG_WAKEUP_TCP_NOMORETOKENS = 17 +NUM_NL80211_WOWLAN_TRIG = 18 +MAX_NL80211_WOWLAN_TRIG = 17 + +""" +/** + * DOC: TCP connection wakeup + * + * Some devices can establish a TCP connection in order to be woken up by a + * packet coming in from outside their network segment, or behind NAT. If + * configured, the device will establish a TCP connection to the given + * service, and periodically send data to that service. The first data + * packet is usually transmitted after SYN/ACK, also ACKing the SYN/ACK. + * The data packets can optionally include a (little endian) sequence + * number (in the TCP payload!) that is generated by the device, and, also + * optionally, a token from a list of tokens. This serves as a keep-alive + * with the service, and for NATed connections, etc. + * + * During this keep-alive period, the server doesn't send any data to the + * client. When receiving data, it is compared against the wakeup pattern + * (and mask) and if it matches, the host is woken up. Similarly, if the + * connection breaks or cannot be established to start with, the host is + * also woken up. + * + * Developer's note: ARP offload is required for this, otherwise TCP + * response packets might not go through correctly. + */ +""" +""" +/** + * struct nl80211_wowlan_tcp_data_seq - WoWLAN TCP data sequence + * @start: starting value + * @offset: offset of sequence number in packet + * @len: length of the sequence value to write, 1 through 4 + * + * Note: don't confuse with the TCP sequence number(s), this is for the + * keepalive packet payload. The actual value is written into the packet + * in little endian. + */ +struct nl80211_wowlan_tcp_data_seq { + __u32 start, offset, len; +}; +""" +dot11_nl80211_wowlan_tcp_data_seq = 'III' +NL80211WOWLANTCPDATASEQLEN = struct.calcsize(dot11_nl80211_wowlan_tcp_data_seq) +def dot11_nl80211_wowlan_tcp_data_seq(start,offset,slen): + """ + creates a dot11_nl80211_wowlan_tcp_data_seq + :param start: start value + :param offset: seq # offset + :param slen: seq value length + :returns: packed dot11_nl80211_wowlan_tcp_data_seq + """ + return struct.pack(dot11_nl80211_wowlan_tcp_data_seq,start,offset,slen) + +""" +/** + * struct nl80211_wowlan_tcp_data_token - WoWLAN TCP data token config + * @offset: offset of token in packet + * @len: length of each token + * @token_stream: stream of data to be used for the tokens, the length must + * be a multiple of @len for this to make sense + */ +struct nl80211_wowlan_tcp_data_token { + __u32 offset, len; + __u8 token_stream[]; +}; +""" + +""" +/** + * struct nl80211_wowlan_tcp_data_token_feature - data token features + * @min_len: minimum token length + * @max_len: maximum token length + * @bufsize: total available token buffer size (max size of @token_stream) + */ +struct nl80211_wowlan_tcp_data_token_feature { + __u32 min_len, max_len, bufsize; +}; +""" +dot11_nl80211_wowlan_tcp_data_token_feature = 'III' +NL80211WOWLANTCPDATATOKENFEATURELEN = struct.calcsize(dot11_nl80211_wowlan_tcp_data_token_feature) +def dot11_nl80211_wowlan_tcp_data_token_feature(min_len,max_len,bufsize): + """ + creates a dot11_nl80211_wowlan_tcp_data_seq + :param min_len: min. token length + :param max_len: max. token length + :param bufsize: max size of token stream + :returns: packed dot11_nl80211_wowlan_tcp_data_seq + """ + return struct.pack(dot11_nl80211_wowlan_tcp_data_token_feature,min_len,max_len,bufsize) + +""" +/** + * enum nl80211_wowlan_tcp_attrs - WoWLAN TCP connection parameters + * @__NL80211_WOWLAN_TCP_INVALID: invalid number for nested attributes + * @NL80211_WOWLAN_TCP_SRC_IPV4: source IPv4 address (in network byte order) + * @NL80211_WOWLAN_TCP_DST_IPV4: destination IPv4 address + * (in network byte order) + * @NL80211_WOWLAN_TCP_DST_MAC: destination MAC address, this is given because + * route lookup when configured might be invalid by the time we suspend, + * and doing a route lookup when suspending is no longer possible as it + * might require ARP querying. + * @NL80211_WOWLAN_TCP_SRC_PORT: source port (u16); optional, if not given a + * socket and port will be allocated + * @NL80211_WOWLAN_TCP_DST_PORT: destination port (u16) + * @NL80211_WOWLAN_TCP_DATA_PAYLOAD: data packet payload, at least one byte. + * For feature advertising, a u32 attribute holding the maximum length + * of the data payload. + * @NL80211_WOWLAN_TCP_DATA_PAYLOAD_SEQ: data packet sequence configuration + * (if desired), a &struct nl80211_wowlan_tcp_data_seq. For feature + * advertising it is just a flag + * @NL80211_WOWLAN_TCP_DATA_PAYLOAD_TOKEN: data packet token configuration, + * see &struct nl80211_wowlan_tcp_data_token and for advertising see + * &struct nl80211_wowlan_tcp_data_token_feature. + * @NL80211_WOWLAN_TCP_DATA_INTERVAL: data interval in seconds, maximum + * interval in feature advertising (u32) + * @NL80211_WOWLAN_TCP_WAKE_PAYLOAD: wake packet payload, for advertising a + * u32 attribute holding the maximum length + * @NL80211_WOWLAN_TCP_WAKE_MASK: Wake packet payload mask, not used for + * feature advertising. The mask works like @NL80211_PKTPAT_MASK + * but on the TCP payload only. + * @NUM_NL80211_WOWLAN_TCP: number of TCP attributes + * @MAX_NL80211_WOWLAN_TCP: highest attribute number + */ +""" +__NL80211_WOWLAN_TCP_INVALID = 0 +NL80211_WOWLAN_TCP_SRC_IPV4 = 1 +NL80211_WOWLAN_TCP_DST_IPV4 = 2 +NL80211_WOWLAN_TCP_DST_MAC = 3 +NL80211_WOWLAN_TCP_SRC_PORT = 4 +NL80211_WOWLAN_TCP_DST_PORT = 5 +NL80211_WOWLAN_TCP_DATA_PAYLOAD = 6 +NL80211_WOWLAN_TCP_DATA_PAYLOAD_SEQ = 7 +NL80211_WOWLAN_TCP_DATA_PAYLOAD_TOKEN = 8 +NL80211_WOWLAN_TCP_DATA_INTERVAL = 9 +NL80211_WOWLAN_TCP_WAKE_PAYLOAD = 10 +NL80211_WOWLAN_TCP_WAKE_MASK = 11 +NUM_NL80211_WOWLAN_TCP = 12 +MAX_NL80211_WOWLAN_TCP = 11 + +""" +/** + * struct nl80211_coalesce_rule_support - coalesce rule support information + * @max_rules: maximum number of rules supported + * @pat: packet pattern support information + * @max_delay: maximum supported coalescing delay in msecs + * + * This struct is carried in %NL80211_ATTR_COALESCE_RULE in the + * capability information given by the kernel to userspace. + */ +struct nl80211_coalesce_rule_support { + __u32 max_rules; + struct nl80211_pattern_support pat; + __u32 max_delay; +} __attribute__((packed)); +""" +dot11_nl80211_coalesce_rule_support = "I16sI" # 16s holds the byte string for pat +NL80211_COALESCE_RULE_SUPPORT = struct.calcsize(dot11_nl80211_coalesce_rule_support) +def dot11_nl80211_coalesce_rule_support(max_rules,pat,max_delay): + """ + creates a dot11_nl80211_coalesce_rule_support + :param max_rules: max # of supported rules + :param pat: a packed nl80211_pattern support struct + :param max_delay: max coalescing delay (msecs) + :returns: a packed dot11_nl80211_coalesce_rule_support + """ + return struct.pack(dot11_nl80211_coalesce_rule_support,max_rules,pat,max_delay) + +""" +/** + * enum nl80211_attr_coalesce_rule - coalesce rule attribute + * @__NL80211_COALESCE_RULE_INVALID: invalid number for nested attribute + * @NL80211_ATTR_COALESCE_RULE_DELAY: delay in msecs used for packet coalescing + * @NL80211_ATTR_COALESCE_RULE_CONDITION: condition for packet coalescence, + * see &enum nl80211_coalesce_condition. + * @NL80211_ATTR_COALESCE_RULE_PKT_PATTERN: packet offset, pattern is matched + * after these fixed number of bytes of received packet + * @NUM_NL80211_ATTR_COALESCE_RULE: number of attributes + * @NL80211_ATTR_COALESCE_RULE_MAX: max attribute number + */ +""" +__NL80211_COALESCE_RULE_INVALID = 0 +NL80211_ATTR_COALESCE_RULE_DELAY = 1 +NL80211_ATTR_COALESCE_RULE_CONDITION = 2 +NL80211_ATTR_COALESCE_RULE_PKT_PATTERN = 3 +NUM_NL80211_ATTR_COALESCE_RULE = 4 +MAX_NL80211_ATTR_COALESCE_RULE = 3 + +""" +/** + * enum nl80211_coalesce_condition - coalesce rule conditions + * @NL80211_COALESCE_CONDITION_MATCH: coalaesce Rx packets when patterns + * in a rule are matched. + * @NL80211_COALESCE_CONDITION_NO_MATCH: coalesce Rx packets when patterns + * in a rule are not matched. + */ +""" +NL80211_COALESCE_CONDITION_MATCH = 0 +NL80211_COALESCE_CONDITION_NO_MATCH = 1 + +""" +/** + * enum nl80211_iface_limit_attrs - limit attributes + * @NL80211_IFACE_LIMIT_UNSPEC: (reserved) + * @NL80211_IFACE_LIMIT_MAX: maximum number of interfaces that + * can be chosen from this set of interface types (u32) + * @NL80211_IFACE_LIMIT_TYPES: nested attribute containing a + * flag attribute for each interface type in this set + * @NUM_NL80211_IFACE_LIMIT: number of attributes + * @MAX_NL80211_IFACE_LIMIT: highest attribute number + */ +""" +NL80211_IFACE_LIMIT_UNSPEC = 1 +NL80211_IFACE_LIMIT_MAX = 2 +NL80211_IFACE_LIMIT_TYPES = 3 +NUM_NL80211_IFACE_LIMIT = 4 +MAX_NL80211_IFACE_LIMIT = 3 + +""" +/** + * enum nl80211_if_combination_attrs -- interface combination attributes + * + * @NL80211_IFACE_COMB_UNSPEC: (reserved) + * @NL80211_IFACE_COMB_LIMITS: Nested attributes containing the limits + * for given interface types, see &enum nl80211_iface_limit_attrs. + * @NL80211_IFACE_COMB_MAXNUM: u32 attribute giving the total number of + * interfaces that can be created in this group. This number doesn't + * apply to interfaces purely managed in software, which are listed + * in a separate attribute %NL80211_ATTR_INTERFACES_SOFTWARE. + * @NL80211_IFACE_COMB_STA_AP_BI_MATCH: flag attribute specifying that + * beacon intervals within this group must be all the same even for + * infrastructure and AP/GO combinations, i.e. the GO(s) must adopt + * the infrastructure network's beacon interval. + * @NL80211_IFACE_COMB_NUM_CHANNELS: u32 attribute specifying how many + * different channels may be used within this group. + * @NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS: u32 attribute containing the bitmap + * of supported channel widths for radar detection. + * @NUM_NL80211_IFACE_COMB: number of attributes + * @MAX_NL80211_IFACE_COMB: highest attribute number + * + * Examples: + * limits = [ #{STA} <= 1, #{AP} <= 1 ], matching BI, channels = 1, max = 2 + * => allows an AP and a STA that must match BIs + * + * numbers = [ #{AP, P2P-GO} <= 8 ], channels = 1, max = 8 + * => allows 8 of AP/GO + * + * numbers = [ #{STA} <= 2 ], channels = 2, max = 2 + * => allows two STAs on different channels + * + * numbers = [ #{STA} <= 1, #{P2P-client,P2P-GO} <= 3 ], max = 4 + * => allows a STA plus three P2P interfaces + * + * The list of these four possiblities could completely be contained + * within the %NL80211_ATTR_INTERFACE_COMBINATIONS attribute to indicate + * that any of these groups must match. + * + * "Combinations" of just a single interface will not be listed here, + * a single interface of any valid interface type is assumed to always + * be possible by itself. This means that implicitly, for each valid + * interface type, the following group always exists: + * numbers = [ #{} <= 1 ], channels = 1, max = 1 + */ +""" +NL80211_IFACE_COMB_UNSPEC = 0 +NL80211_IFACE_COMB_LIMITS = 1 +NL80211_IFACE_COMB_MAXNUM = 2 +NL80211_IFACE_COMB_STA_AP_BI_MATCH = 3 +NL80211_IFACE_COMB_NUM_CHANNELS = 4 +NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS = 5 +NUM_NL80211_IFACE_COMB = 6 +MAX_NL80211_IFACE_COMB = 5 + +""" +/** + * enum nl80211_plink_state - state of a mesh peer link finite state machine + * + * @NL80211_PLINK_LISTEN: initial state, considered the implicit + * state of non existant mesh peer links + * @NL80211_PLINK_OPN_SNT: mesh plink open frame has been sent to + * this mesh peer + * @NL80211_PLINK_OPN_RCVD: mesh plink open frame has been received + * from this mesh peer + * @NL80211_PLINK_CNF_RCVD: mesh plink confirm frame has been + * received from this mesh peer + * @NL80211_PLINK_ESTAB: mesh peer link is established + * @NL80211_PLINK_HOLDING: mesh peer link is being closed or cancelled + * @NL80211_PLINK_BLOCKED: all frames transmitted from this mesh + * plink are discarded + * @NUM_NL80211_PLINK_STATES: number of peer link states + * @MAX_NL80211_PLINK_STATES: highest numerical value of plink states + */ +""" +NL80211_PLINK_LISTEN = 0 +NL80211_PLINK_OPN_SNT = 1 +NL80211_PLINK_OPN_RCVD = 2 +NL80211_PLINK_CNF_RCVD = 3 +NL80211_PLINK_ESTAB = 4 +NL80211_PLINK_HOLDING = 5 +NL80211_PLINK_BLOCKED = 6 +NUM_NL80211_PLINK_STATES = 7 +MAX_NL80211_PLINK_STATES = 6 + +""" +/** + * enum nl80211_plink_action - actions to perform in mesh peers + * + * @NL80211_PLINK_ACTION_NO_ACTION: perform no action + * @NL80211_PLINK_ACTION_OPEN: start mesh peer link establishment + * @NL80211_PLINK_ACTION_BLOCK: block traffic from this mesh peer + * @NUM_NL80211_PLINK_ACTIONS: number of possible actions + */ +""" +NL80211_PLINK_ACTION_NO_ACTION = 0 +NL80211_PLINK_ACTION_OPEN = 1 +NL80211_PLINK_ACTION_BLOCK = 2 +NUM_NL80211_PLINK_ACTIONS = 3 + +NL80211_KCK_LEN = 16 +NL80211_KEK_LEN = 16 +NL80211_REPLAY_CTR_LEN = 8 + +""" +/** + * enum nl80211_rekey_data - attributes for GTK rekey offload + * @__NL80211_REKEY_DATA_INVALID: invalid number for nested attributes + * @NL80211_REKEY_DATA_KEK: key encryption key (binary) + * @NL80211_REKEY_DATA_KCK: key confirmation key (binary) + * @NL80211_REKEY_DATA_REPLAY_CTR: replay counter (binary) + * @NUM_NL80211_REKEY_DATA: number of rekey attributes (internal) + * @MAX_NL80211_REKEY_DATA: highest rekey attribute (internal) + */ +""" +__NL80211_REKEY_DATA_INVALID = 0 +NL80211_REKEY_DATA_KEK = 1 +NL80211_REKEY_DATA_KCK = 2 +NL80211_REKEY_DATA_REPLAY_CTR = 3 +NUM_NL80211_REKEY_DATA = 4 +MAX_NL80211_REKEY_DATA = 3 + +""" +/** + * enum nl80211_hidden_ssid - values for %NL80211_ATTR_HIDDEN_SSID + * @NL80211_HIDDEN_SSID_NOT_IN_USE: do not hide SSID (i.e., broadcast it in + * Beacon frames) + * @NL80211_HIDDEN_SSID_ZERO_LEN: hide SSID by using zero-length SSID element + * in Beacon frames + * @NL80211_HIDDEN_SSID_ZERO_CONTENTS: hide SSID by using correct length of SSID + * element in Beacon frames but zero out each byte in the SSID + */ +""" +NL80211_HIDDEN_SSID_NOT_IN_USE = 1 +NL80211_HIDDEN_SSID_ZERO_LEN = 2 +NL80211_HIDDEN_SSID_ZERO_CONTENTS = 3 + +""" +/** + * enum nl80211_sta_wme_attr - station WME attributes + * @__NL80211_STA_WME_INVALID: invalid number for nested attribute + * @NL80211_STA_WME_UAPSD_QUEUES: bitmap of uapsd queues. the format + * is the same as the AC bitmap in the QoS info field. + * @NL80211_STA_WME_MAX_SP: max service period. the format is the same + * as the MAX_SP field in the QoS info field (but already shifted down). + * @__NL80211_STA_WME_AFTER_LAST: internal + * @NL80211_STA_WME_MAX: highest station WME attribute + */ +""" +__NL80211_STA_WME_INVALID = 0 +NL80211_STA_WME_UAPSD_QUEUES = 1 +NL80211_STA_WME_MAX_SP = 2 +MAX_NL80211_STA_WME = 2 + +""" +/** + * enum nl80211_pmksa_candidate_attr - attributes for PMKSA caching candidates + * @__NL80211_PMKSA_CANDIDATE_INVALID: invalid number for nested attributes + * @NL80211_PMKSA_CANDIDATE_INDEX: candidate index (u32; the smaller, the higher + * priority) + * @NL80211_PMKSA_CANDIDATE_BSSID: candidate BSSID (6 octets) + * @NL80211_PMKSA_CANDIDATE_PREAUTH: RSN pre-authentication supported (flag) + * @NUM_NL80211_PMKSA_CANDIDATE: number of PMKSA caching candidate attributes + * (internal) + * @MAX_NL80211_PMKSA_CANDIDATE: highest PMKSA caching candidate attribute + * (internal) + */ +""" +__NL80211_PMKSA_CANDIDATE_INVALID = 0 +NL80211_PMKSA_CANDIDATE_INDEX = 1 +NL80211_PMKSA_CANDIDATE_BSSID = 2 +NL80211_PMKSA_CANDIDATE_PREAUTH = 3 +NUM_NL80211_PMKSA_CANDIDATE = 4 +MAX_NL80211_PMKSA_CANDIDATE = 3 + +""" +/** + * enum nl80211_tdls_operation - values for %NL80211_ATTR_TDLS_OPERATION + * @NL80211_TDLS_DISCOVERY_REQ: Send a TDLS discovery request + * @NL80211_TDLS_SETUP: Setup TDLS link + * @NL80211_TDLS_TEARDOWN: Teardown a TDLS link which is already established + * @NL80211_TDLS_ENABLE_LINK: Enable TDLS link + * @NL80211_TDLS_DISABLE_LINK: Disable TDLS link + */ +""" +NL80211_TDLS_DISCOVERY_REQ = 0 +NL80211_TDLS_SETUP = 1 +NL80211_TDLS_TEARDOWN = 2 +NL80211_TDLS_ENABLE_LINK = 3 +NL80211_TDLS_DISABLE_LINK = 4 + +""" +/* + * enum nl80211_ap_sme_features - device-integrated AP features + * Reserved for future use, no bits are defined in + * NL80211_ATTR_DEVICE_AP_SME yet. +enum nl80211_ap_sme_features { +}; + */ +""" + +""" +/** + * enum nl80211_feature_flags - device/driver features + * @NL80211_FEATURE_SK_TX_STATUS: This driver supports reflecting back + * TX status to the socket error queue when requested with the + * socket option. + * @NL80211_FEATURE_HT_IBSS: This driver supports IBSS with HT datarates. + * @NL80211_FEATURE_INACTIVITY_TIMER: This driver takes care of freeing up + * the connected inactive stations in AP mode. + * @NL80211_FEATURE_CELL_BASE_REG_HINTS: This driver has been tested + * to work properly to suppport receiving regulatory hints from + * cellular base stations. + * @NL80211_FEATURE_P2P_DEVICE_NEEDS_CHANNEL: If this is set, an active + * P2P Device (%NL80211_IFTYPE_P2P_DEVICE) requires its own channel + * in the interface combinations, even when it's only used for scan + * and remain-on-channel. This could be due to, for example, the + * remain-on-channel implementation requiring a channel context. + * @NL80211_FEATURE_SAE: This driver supports simultaneous authentication of + * equals (SAE) with user space SME (NL80211_CMD_AUTHENTICATE) in station + * mode + * @NL80211_FEATURE_LOW_PRIORITY_SCAN: This driver supports low priority scan + * @NL80211_FEATURE_SCAN_FLUSH: Scan flush is supported + * @NL80211_FEATURE_AP_SCAN: Support scanning using an AP vif + * @NL80211_FEATURE_VIF_TXPOWER: The driver supports per-vif TX power setting + * @NL80211_FEATURE_NEED_OBSS_SCAN: The driver expects userspace to perform + * OBSS scans and generate 20/40 BSS coex reports. This flag is used only + * for drivers implementing the CONNECT API, for AUTH/ASSOC it is implied. + * @NL80211_FEATURE_P2P_GO_CTWIN: P2P GO implementation supports CT Window + * setting + * @NL80211_FEATURE_P2P_GO_OPPPS: P2P GO implementation supports opportunistic + * powersave + * @NL80211_FEATURE_FULL_AP_CLIENT_STATE: The driver supports full state + * transitions for AP clients. Without this flag (and if the driver + * doesn't have the AP SME in the device) the driver supports adding + * stations only when they're associated and adds them in associated + * state (to later be transitioned into authorized), with this flag + * they should be added before even sending the authentication reply + * and then transitioned into authenticated, associated and authorized + * states using station flags. + * Note that even for drivers that support this, the default is to add + * stations in authenticated/associated state, so to add unauthenticated + * stations the authenticated/associated bits have to be set in the mask. + * @NL80211_FEATURE_ADVERTISE_CHAN_LIMITS: cfg80211 advertises channel limits + * (HT40, VHT 80/160 MHz) if this flag is set + * @NL80211_FEATURE_USERSPACE_MPM: This driver supports a userspace Mesh + * Peering Management entity which may be implemented by registering for + * beacons or NL80211_CMD_NEW_PEER_CANDIDATE events. The mesh beacon is + * still generated by the driver. + * @NL80211_FEATURE_ACTIVE_MONITOR: This driver supports an active monitor + * interface. An active monitor interface behaves like a normal monitor + * interface, but gets added to the driver. It ensures that incoming + * unicast packets directed at the configured interface address get ACKed. + */ +""" +NL80211_FEATURE_SK_TX_STATUS = 1<<0 +NL80211_FEATURE_HT_IBSS = 1<<1 +NL80211_FEATURE_INACTIVITY_TIMER = 1<<2 +NL80211_FEATURE_CELL_BASE_REG_HINTS = 1<<3 +NL80211_FEATURE_P2P_DEVICE_NEEDS_CHANNEL = 1<<4 +NL80211_FEATURE_SAE = 1<<5 +NL80211_FEATURE_LOW_PRIORITY_SCAN = 1<<6 +NL80211_FEATURE_SCAN_FLUSH = 1<<7 +NL80211_FEATURE_AP_SCAN = 1<<8 +NL80211_FEATURE_VIF_TXPOWER = 1<<9 +NL80211_FEATURE_NEED_OBSS_SCAN = 1<<10 +NL80211_FEATURE_P2P_GO_CTWIN = 1<<11 +NL80211_FEATURE_P2P_GO_OPPPS = 1<<12 +# bit 13 is reserved +NL80211_FEATURE_ADVERTISE_CHAN_LIMITS = 1<<14 +NL80211_FEATURE_FULL_AP_CLIENT_STATE = 1<<15 +NL80211_FEATURE_USERSPACE_MPM = 1<<16 +NL80211_FEATURE_ACTIVE_MONITOR = 1<<17 + +""" +/** + * enum nl80211_probe_resp_offload_support_attr - optional supported + * protocols for probe-response offloading by the driver/FW. + * To be used with the %NL80211_ATTR_PROBE_RESP_OFFLOAD attribute. + * Each enum value represents a bit in the bitmap of supported + * protocols. Typically a subset of probe-requests belonging to a + * supported protocol will be excluded from offload and uploaded + * to the host. + * + * @NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS: Support for WPS ver. 1 + * @NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2: Support for WPS ver. 2 + * @NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P: Support for P2P + * @NL80211_PROBE_RESP_OFFLOAD_SUPPORT_80211U: Support for 802.11u + */ +""" +NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS = 1<<0 +NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2 = 1<<1 +NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P = 1<<2 +NL80211_PROBE_RESP_OFFLOAD_SUPPORT_80211U = 1<<3 + +""" +/** + * enum nl80211_connect_failed_reason - connection request failed reasons + * @NL80211_CONN_FAIL_MAX_CLIENTS: Maximum number of clients that can be + * handled by the AP is reached. + * @NL80211_CONN_FAIL_BLOCKED_CLIENT: Connection request is rejected due to ACL. + */ +""" +NL80211_CONN_FAIL_MAX_CLIENTS = 0 +NL80211_CONN_FAIL_BLOCKED_CLIENT = 1 + +""" +/** + * enum nl80211_scan_flags - scan request control flags + * + * Scan request control flags are used to control the handling + * of NL80211_CMD_TRIGGER_SCAN and NL80211_CMD_START_SCHED_SCAN + * requests. + * + * @NL80211_SCAN_FLAG_LOW_PRIORITY: scan request has low priority + * @NL80211_SCAN_FLAG_FLUSH: flush cache before scanning + * @NL80211_SCAN_FLAG_AP: force a scan even if the interface is configured + * as AP and the beaconing has already been configured. This attribute is + * dangerous because will destroy stations performance as a lot of frames + * will be lost while scanning off-channel, therefore it must be used only + * when really needed + */ +""" +NL80211_SCAN_FLAG_LOW_PRIORITY = 1<<0 +NL80211_SCAN_FLAG_FLUSH = 1<<1 +NL80211_SCAN_FLAG_AP = 1<<2 + +""" +/** + * enum nl80211_acl_policy - access control policy + * + * Access control policy is applied on a MAC list set by + * %NL80211_CMD_START_AP and %NL80211_CMD_SET_MAC_ACL, to + * be used with %NL80211_ATTR_ACL_POLICY. + * + * @NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED: Deny stations which are + * listed in ACL, i.e. allow all the stations which are not listed + * in ACL to authenticate. + * @NL80211_ACL_POLICY_DENY_UNLESS_LISTED: Allow the stations which are listed + * in ACL, i.e. deny all the stations which are not listed in ACL. + */ +""" +NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED = 0 +NL80211_ACL_POLICY_DENY_UNLESS_LISTED = 1 + +""" +/** + * enum nl80211_radar_event - type of radar event for DFS operation + * + * Type of event to be used with NL80211_ATTR_RADAR_EVENT to inform userspace + * about detected radars or success of the channel available check (CAC) + * + * @NL80211_RADAR_DETECTED: A radar pattern has been detected. The channel is + * now unusable. + * @NL80211_RADAR_CAC_FINISHED: Channel Availability Check has been finished, + * the channel is now available. + * @NL80211_RADAR_CAC_ABORTED: Channel Availability Check has been aborted, no + * change to the channel status. + * @NL80211_RADAR_NOP_FINISHED: The Non-Occupancy Period for this channel is + * over, channel becomes usable. + */ +""" +NL80211_RADAR_DETECTED = 0 +NL80211_RADAR_CAC_FINISHED = 1 +NL80211_RADAR_CAC_ABORTED = 2 +NL80211_RADAR_NOP_FINISHED = 3 + +""" +/** + * enum nl80211_dfs_state - DFS states for channels + * + * Channel states used by the DFS code. + * + * @NL80211_DFS_USABLE: The channel can be used, but channel availability + * check (CAC) must be performed before using it for AP or IBSS. + * @NL80211_DFS_UNAVAILABLE: A radar has been detected on this channel, it + * is therefore marked as not available. + * @NL80211_DFS_AVAILABLE: The channel has been CAC checked and is available. + */ +""" +NL80211_DFS_USABLE = 0 +NL80211_DFS_UNAVAILABLE = 1 +NL80211_DFS_AVAILABLE = 2 + +""" +/** + * enum enum nl80211_protocol_features - nl80211 protocol features + * @NL80211_PROTOCOL_FEATURE_SPLIT_WIPHY_DUMP: nl80211 supports splitting + * wiphy dumps (if requested by the application with the attribute + * %NL80211_ATTR_SPLIT_WIPHY_DUMP. Also supported is filtering the + * wiphy dump by %NL80211_ATTR_WIPHY, %NL80211_ATTR_IFINDEX or + * %NL80211_ATTR_WDEV. + */ +""" +NL80211_PROTOCOL_FEATURE_SPLIT_WIPHY_DUMP = 1<<0 + +""" +/** + * enum nl80211_crit_proto_id - nl80211 critical protocol identifiers + * + * @NL80211_CRIT_PROTO_UNSPEC: protocol unspecified. + * @NL80211_CRIT_PROTO_DHCP: BOOTP or DHCPv6 protocol. + * @NL80211_CRIT_PROTO_EAPOL: EAPOL protocol. + * @NL80211_CRIT_PROTO_APIPA: APIPA protocol. + * @NUM_NL80211_CRIT_PROTO: must be kept last. + */ +""" +NL80211_CRIT_PROTO_UNSPEC = 0 +NL80211_CRIT_PROTO_DHCP = 1 +NL80211_CRIT_PROTO_EAPOL = 2 +NL80211_CRIT_PROTO_APIPA = 3 +# add other protocols before this one +NUM_NL80211_CRIT_PROTO = 4 + +# maximum duration for critical protocol measures +NL80211_CRIT_PROTO_MAX_DURATION = 5000 # msec + +""" +/** + * enum nl80211_rxmgmt_flags - flags for received management frame. + * + * Used by cfg80211_rx_mgmt() + * + * @NL80211_RXMGMT_FLAG_ANSWERED: frame was answered by device/driver. + */ +""" +NL80211_RXMGMT_FLAG_ANSWERED = 1<<0 \ No newline at end of file diff --git a/pyric/pyw.py b/pyric/pyw.py new file mode 100644 index 0000000..b2304d8 --- /dev/null +++ b/pyric/pyw.py @@ -0,0 +1,992 @@ +#!/usr/bin/env python + +""" pyw.py: python iw + +Copyright (C) 2016 Dale V. Patterson (wraith.wireless@yandex.com) + +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 3 of the License, or (at your option) any later +version. + +Redistribution and use in source and binary forms, with or without modifications, +are permitted provided that the following conditions are met: + o Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + o Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + o Neither the name of the orginal author Dale V. Patterson nor the names of any + contributors may be used to endorse or promote products derived from this + software without specific prior written permission. + +Provides a python version of a subset of the iw command & additionally, a smaller +subset of ifconfig/iwconfig. + +Each command/function (excluding interfaces & isinterface which do not rely on +ioctl/netlink sockets) comes in two flavors - one-time & persistent. + 1) one-time: similar to iw. The command, creates the netlink socket (or ioctl), + composes the message, sends the message & receives the response, parses + the results, closes the socket & returns the results to the caller. At + no time does the caller need to be aware of any underlying netlink processes + or structures. + 2) persistent: communication & parsing only. The onus of socket creation and + deletion is on the caller which allows them to create one (or more) socket(s). + The pyw functions will only handle message construction, message sending and + receiving & message parsing. + +Callers that intend to use pyw functionality often & repeatedly may prefer to +use a persistent netlink/ioctl socket. Socket creation & deletion are relatively +fast however, if a program is repeatedly using pyw function(s) (such as a scanner +that is changing channels mulitple times per second) it makes sense for the caller +to create a socket one time only & use the same socket. However, if the caller +is only using pyw periodically and/or does not want to bothered with socket +maintenance, the one-time flavor would be better. + +Previously (v 0.0.*), two functions were used, one named & one named +ex (which took an additional argument, namely the socket). This yielded +additional code, was unwieldy to use & did not look "pretty". + +pyw v 0.1.* uses (for lack of a better naming convention) templates & a stub +to accomplish this. + +A stripped-down function template (for netlink) is defined as: + +def fcttemplate(arg0,arg1,...,argn,*argv): + # parameter validation if necessary + try: + nlsock = argv[0] + except IndexError: + return _nlstub_(fcttemplate,arg0,arg1,...argn) + + # command execution + ... + return results + +If argv has a netlink socket at index 0, the template will jump to execution. If +there is no socket, execute the stub to create one. (Also, if something other than +a socket is at argv[0], an error will rise during execution.) at The stub function +is then defined as: + +def _nlstub_(fct,*argv): + nlsock = None + try: + nlsock = nlsock = nl.nl_socket_alloc() + argv = list(argv) + [nlsock] + return fct(*argv) + except pyric.error: raise # catch & release + finally: + if nlsock: nl.nl_socket_free(nlsock) + +which creates a NLSocket & "recalls" the template with the socket now in *argv. so, +callers can now call for example, + +regset('US') + +for one-time execution, or + +regset('US',) + +for persistent execution. + +Additional changes in pyw v 0.1.* + 1) All functions (excluding wireless core related) will use a Card object which + encapsulates the physical index, device name and interface index (ifindex) + under a tuple rather than a device name or physical index or ifindex as this + will not require the caller to remember if a dev or a phy or a ifindex is + needed. The only exception to this is devinfo which by necessity will accept + a Card or a device name + 2) All functions allow pyric errors to pass through. + 3) sets the tx/rx buffer depending on the function +""" + +__name__ = 'pyw' +__license__ = 'GPLv3' +__version__ = '0.1.3' +__date__ = 'May 2016' +__author__ = 'Dale Patterson' +__maintainer__ = 'Dale Patterson' +__email__ = 'wraith.wireless@yandex.com' +__status__ = 'Development' + +import struct # ioctl unpacking +import pyric,errno # pyric exception & error codes +from pyric import device # device related +from pyric import channels # channel related +from pyric.docs.nlhelp import cmdbynum # get command name +import pyric.net.netlink_h as nlh # netlink definition +import pyric.net.genetlink_h as genlh # genetlink definition +import pyric.net.wireless.nl80211_h as nl80211h # 802.11 definition +import pyric.net.sockios_h as sioch # sockios constants +import pyric.net.if_h as ifh # ifreq structure +import pyric.lib.libnl as nl # netlink functions +import pyric.lib.libio as io # sockios functions + +_FAM80211ID_ = None + +# redefine interface types and monitor flags +IFTYPES = nl80211h.NL80211_IFTYPES +MNTRFLAGS = nl80211h.NL80211_MNTR_FLAGS + +class Card(tuple): + """ + Wrapper around a tuple t = (physical index,device name, interface index) + Exposes the following properties: (callable by '.'): + phy: physical index + dev: device name + idx: interface index (ifindex) + """ + def __new__(cls,p,d,i): return super(Card,cls).__new__(cls,tuple((p,d,i))) + def __repr__(self): + return "Card(phy={0},dev={1},ifindex={2})".format(self.phy,self.dev,self.idx) + @property + def phy(self): return self[0] + @property + def dev(self): return self[1] + @property + def idx(self): return self[2] + +################################################################################ +#### WIRELESS CORE #### +################################################################################ + +def interfaces(): + """ + retrieves all network interfaces (APX ifconfig) + :returns: a list of device names of current network interfaces cards + """ + fin = None + try: + # read in devices from /proc/net/dev. After splitting on newlines, the + # first 2 lines are headers and the last line is empty so we remove them + fin = open(device.dpath,'r') + ds = fin.read().split('\n')[2:-1] + except IOError: + return [] + finally: + if fin: fin.close() + + # the remaining lines are : p1 p2 ... p3, split on ':' & strip whitespace + return [d.split(':')[0].strip() for d in ds] + +def isinterface(dev): + """ + determines if device name belongs to a network card (APX ifconfig ) + :param dev: device name + :returns: {True if dev is a device|False otherwise} + """ + return dev in interfaces() + +def winterfaces(*argv): + """ + retrieve all wireless interfaces (APX iwconfig) + :param argv: ioctl socket at argv[0] (or empty) + :returns: list of device names of current wireless NICs + """ + try: + iosock = argv[0] + except IndexError: + return _iostub_(winterfaces) + + wifaces = [] + for dev in interfaces(): + try: + #_ = io.io_transfer(iosock,sioch.SIOCGIWNAME,ifh.ifreq(dev)) + #wifaces.append(dev) + if iswireless(dev,iosock): wifaces.append(dev) + except pyric.error as e: + # ENODEV & EOPNOTSUPP mean not wireless, reraise any others + if e.errno == errno.ENODEV or e.errno == errno.EOPNOTSUPP: pass + else: raise + return wifaces + +def iswireless(dev,*argv): + """ + determines if given device is wireless (APX iwconfig ) + :param dev: device name + :param argv: ioctl socket at argv[0] (or empty) + :returns: {True:device is wireless|False:device is not wireless/not present} + """ + try: + iosock = argv[0] + except IndexError: + return _iostub_(iswireless,dev) + + try: + # if the call succeeds, found to be wireless + _ = io.io_transfer(iosock,sioch.SIOCGIWNAME,ifh.ifreq(dev)) + return True + except AttributeError as e: + raise pyric.error(errno.EINVAL,"Invalid parameter {0}".format(e)) + except pyric.error as e: + # ENODEV or ENOTSUPP means not wireless, reraise any others + if e.errno == errno.ENODEV or e.errno == errno.EOPNOTSUPP: return False + else: raise + +def regget(*argv): + """ + gets the current regulatory domain (iw reg get) + :param argv: netlink socket at argv[0] (or empty) + :returns: the two charactor regulatory domain + """ + try: + nlsock = argv[0] + except IndexError: + return _nlstub_(regget) + + msg = nl.nlmsg_new(nltype=_familyid_(nlsock), + cmd=nl80211h.NL80211_CMD_GET_REG, + flags=nlh.NLM_F_REQUEST | nlh.NLM_F_ACK) + nl.nl_sendmsg(nlsock,msg) + rmsg = nl.nl_recvmsg(nlsock) + return nl.nla_find(rmsg,nl80211h.NL80211_ATTR_REG_ALPHA2) + +def regset(rd,*argv): + """ + REQUIRES ROOT PRIVILEGES + sets the current regulatory domain (iw reg set ) + :param rd: regulatory domain code + :param argv: netlink socket at argv[0] (or empty) + :returns: the two charactor regulatory domain + """ + if len(rd) != 2: raise pyric.error(errno.EINVAL,"Invalid reg. domain") + try: + nlsock = argv[0] + except IndexError: + return _nlstub_(regset,rd) + + msg = nl.nlmsg_new(nltype=_familyid_(nlsock), + cmd=nl80211h.NL80211_CMD_REQ_SET_REG, + flags=nlh.NLM_F_REQUEST | nlh.NLM_F_ACK) + nl.nla_put_string(msg,rd.upper(),nl80211h.NL80211_ATTR_REG_ALPHA2) + nl.nl_sendmsg(nlsock,msg) + nl.nl_recvmsg(nlsock) # throws exception on failure + return True # we got here-it worked (or there were no complaints) + + +################################################################################ +#### WIRELESS INTERFACE FUNCTIONS #### +################################################################################ + +def getcard(dev,*argv): + """ + get the Card object from device name + :param dev: device name + :returns: a Card with device name dev + """ + try: + nlsock = argv[0] + except IndexError: + return _nlstub_(getcard,dev) + + return devinfo(dev,nlsock)['card'] + +def validcard(card,*argv): + """ + determines if card is still valid i.e. another program has not changed it + :param card: Card object + :param argv: netlink socket at argv[0] (or empty) + :returns: True if card is still valid, False otherwise + """ + try: + nlsock = argv[0] + except IndexError: + return _nlstub_(validcard,card) + try: + return card == devinfo(card.dev,nlsock)['card'] + except pyric.error as e: + if e.errno == errno.ENODEV: return False + else: raise + +def macget(card,*argv): + """ + gets the interface's hw address (APX ifconfig | grep HWaddr) + :param card: Card object + :param argv: ioctl socket at argv[0] (or empty) + :returns: device mac + """ + try: + iosock = argv[0] + except IndexError: + return _iostub_(macget,card) + + try: + flag = sioch.SIOCGIFHWADDR + ret = io.io_transfer(iosock,flag,ifh.ifreq(card.dev,flag)) + return _hex2mac_(ret[18:24]) + # sometimes get value 803 as family, cannot find any reference to this + # until then, just hope we get a mac as we should + #fam = struct.unpack_from(ifh.sa_addr, ret, ifh.IFNAMELEN)[0] + #if fam == ifh.ARPHRD_ETHER or fam == ifh.AF_UNSPEC: # confirm we got a hwaddr back + # return _hex2mac_(ret[18:24]) + #else: + # raise pyric.error(errno.EAFNOSUPPORT, "Invalid return addr family {0}".format(fam)) + except AttributeError as e: + raise pyric.error(errno.EINVAL,"Invalid parameter {0}".format(e)) + except struct.error as e: + raise pyric.error(pyric.EUNDEF,"Error parsing results {0}".format(e)) + +def macset(card,mac,*argv): + """ + REQUIRES ROOT PRIVILEGES/CARD DOWN + get/set nic's hwaddr (ifconfig hw ether ) + :param card: Card object + :param mac: macaddr to set + :param argv: ioctl socket at argv[0] (or empty) + :returns: mac address after operation + TODO: add parameter check on mac address + """ + try: + iosock = argv[0] + except IndexError: + return _iostub_(macset,card,mac) + + try: + flag = sioch.SIOCSIFHWADDR + params = [ifh.ARPHRD_ETHER,mac] + ret = io.io_transfer(iosock,flag,ifh.ifreq(card.dev,flag,params)) + return _hex2mac_(ret[18:24]) + # see macget + #fam = struct.unpack_from(ifh.sa_addr,ret,ifh.IFNAMELEN)[0] + #if fam == ifh.ARPHRD_ETHER or fam == ifh.AF_UNSPEC: # confirm we got a hwaddr back + # return _hex2mac_(ret[18:24]) + #else: + # raise pyric.error(errno.EAFNOSUPPORT, "Invalid return addr family") + except AttributeError as e: + raise pyric.error(errno.EINVAL,"Invalid parameter {0}".format(e)) + except struct.error as e: + raise pyric.error(pyric.EUNDEF,"error parsing results {0}".format(e)) + +def up(card,*argv): + """ + REQUIRES ROOT PRIVILEGES + turns dev on (ifconfig up) + :param card: Card object + :param argv: ioctl socket at argv[0] (or empty) + :returns: True on succes, throws exception otherwise + """ + try: + iosock = argv[0] + except IndexError: + return _iostub_(up,card) + + dev = card.dev + flags = _flagsget_(dev,iosock) + if not _issetf_(flags,ifh.IFF_UP): + _flagsset_(dev,_setf_(flags,ifh.IFF_UP),iosock) + return True + +def down(card,*argv): + """ + REQUIRES ROOT PRIVILEGES + turns def off (ifconfig down) + :param card: Card object + :param argv: ioctl socket at argv[0] (or empty) + :returns: True on succes, throws exception otherwise + """ + try: + iosock = argv[0] + except IndexError: + return _iostub_(down,card) + + dev = card.dev + flags = _flagsget_(dev,iosock) + if _issetf_(flags,ifh.IFF_UP): + _flagsset_(dev,_unsetf_(flags,ifh.IFF_UP),iosock) + return True + +def txget(card,*argv): + """ + gets the device's transimission power (iwconfig | grep Tx-Power) + :param card: Card object + :param argv: ioctl socket at argv[0] (or empty) + :returns: transmission power + """ + try: + iosock = argv[0] + except IndexError: + return _iostub_(txget,card) + + try: + flag = sioch.SIOCGIWTXPOW + ret = io.io_transfer(iosock,flag,ifh.ifreq(card.dev,flag)) + return struct.unpack_from(ifh.ifr_iwtxpwr,ret,ifh.IFNAMELEN)[0] + except AttributeError as e: + raise pyric.error(errno.EINVAL,"Invalid parameter {0}".format(e)) + except IndexError: + return None + except struct.error as e: + raise pyric.error(pyric.EUNDEF,"Error parsing results {0}".format(e)) + +def devstds(card,*argv): + """ + gets card's wireless standards (iwconfig | grep IEEE + :param card: Card object + :param argv: ioctl socket at argv[0] (or empty) + :returns: returns a list standards (letter designators) + """ + try: + iosock = argv[0] + except IndexError: + return _iostub_(devstds,card) + + try: + flag = sioch.SIOCGIWNAME + ret = io.io_transfer(iosock,flag,ifh.ifreq(card.dev,flag)) + stds = ret[ifh.IFNAMELEN:] # get the standards + stds = stds[:stds.find('\x00')] # remove nulls + stds = stds.replace('IEEE 802.11','') # remove IEEE 802.11 + return [std for std in stds] + except AttributeError as e: + raise pyric.error(errno.EINVAL,"Invalid paramter {0}".format(e)) + except IndexError: return None + except struct.error as e: + raise pyric.error(pyric.EUNDEF,"Error parsing results {0}".format(e)) + +def devmodes(card,*argv): + """ + gets supported modes card can operate in + :param card: Card object + :param argv: netlink socket at argv[0] (or empty) + :returns: list of card's supported modes + """ + try: + nlsock = argv[0] + except IndexError: + return _nlstub_(devmodes,card) + + return phyinfo(card,nlsock)['modes'] + +def devcmds(card,*argv): + """ + get supported commands card can execute + :param card: Card object + :param argv: netlink socket at argv[0] (or empty) + :returns: supported commands + """ + try: + nlsock = argv[0] + except IndexError: + return _nlstub_(devcmds,card) + + return phyinfo(card,nlsock)['commands'] + +def devinfo(card,*argv): + """ + get info for device (iw dev info) + :param card: Card object or dev + :param argv: netlink socket at argv[0] (or empty) + :returns: dict with the following key:value pairs + card -> Card(phy,dev,ifindex) + mode -> i.e. monitor or managed + wdev -> wireless device id + mac -> hw address + RF (if associated) -> frequency + CF (if assoicate) -> center frequency + CHW -> channel width i.e. NOHT,HT40- etc + """ + try: + nlsock = argv[0] + except IndexError: + return _nlstub_(devinfo,card) + + # if we have a Card, pull out dev name, ifindex itherwise get ifindex + try: + dev = card.dev + idx = card.idx + except AttributeError: + dev = card + idx = _ifindex_(dev) + + msg = nl.nlmsg_new(nltype=_familyid_(nlsock), + cmd=nl80211h.NL80211_CMD_GET_INTERFACE, + flags=nlh.NLM_F_REQUEST | nlh.NLM_F_ACK) + nl.nla_put_u32(msg,idx,nl80211h.NL80211_ATTR_IFINDEX) + nl.nl_sendmsg(nlsock,msg) + rmsg = nl.nl_recvmsg(nlsock) + + # pull out attributes + info = {'card':Card(nl.nla_find(rmsg,nl80211h.NL80211_ATTR_WIPHY),dev,idx), + 'mode':IFTYPES[nl.nla_find(rmsg,nl80211h.NL80211_ATTR_IFTYPE)], + 'wdev':nl.nla_find(rmsg,nl80211h.NL80211_ATTR_WDEV), + 'mac':_hex2mac_(nl.nla_find(rmsg,nl80211h.NL80211_ATTR_MAC)), + 'RF':nl.nla_find(rmsg,nl80211h.NL80211_ATTR_WIPHY_FREQ), + 'CF':nl.nla_find(rmsg,nl80211h.NL80211_ATTR_CENTER_FREQ1), + 'CHW':None} + chw = nl.nla_find(rmsg,nl80211h.NL80211_ATTR_CHANNEL_WIDTH) + if chw: info['CHW'] = channels.CHWIDTHS[chw] + return info + +def phyinfo(card,*argv): + """ + get info for phy (iw phy info) + :param card: Card + :param argv: netlink socket at argv[0] (or empty) + :returns: dict with the following key:value pairs + modes -> list of supported modes + bands -> list of supported bands (still working on unpacking) + scan_ssids -> max number of scan SSIDS + retry_short -> retry short limit + retry_long -> retry long limit + frag_thresh -> frag threshold + rts_thresh -> rts threshold + cov_class -> coverage class + swmodes -> supported software modes + commands -> supported commands + + NOTE: function is still in experimental stage, still working through how + the nested attributes should be treated. ATT have found that: + modes,swmodes are big-endian unsigned shorts corresponding to nl80211_iftype + commands are a tuple of big-endian unsigned shorts t=(idx,cmd) where + idx is the current index in the list of supported commands and + cmd correpsonds to nl80211_commands + """ + try: + nlsock = argv[0] + except IndexError: + return _nlstub_(phyinfo,card) + + # iw sends a @NL80211_ATTR_SPLIT_WIPHY_DUMP, we don't & get full return at once + msg = nl.nlmsg_new(nltype=_familyid_(nlsock), + cmd=nl80211h.NL80211_CMD_GET_WIPHY, + flags=nlh.NLM_F_REQUEST | nlh.NLM_F_ACK) + nl.nla_put_u32(msg,card.phy,nl80211h.NL80211_ATTR_WIPHY) + nl.nl_sendmsg(nlsock,msg) + rmsg = nl.nl_recvmsg(nlsock) + + # pull out attributes + info = {'scan_ssids':None,'modes':None,'bands':None,'retry_short':None, + 'retry_long':None,'frag_thresh':None,'rts_thresh':None, + 'cov_class':None,'swmodes':None,'commands':None} + # singular attributes + info['bands'] = nl.nla_find(rmsg,nl80211h.NL80211_ATTR_WIPHY_BANDS) + info['retry_short'] = nl.nla_find(rmsg,nl80211h.NL80211_ATTR_WIPHY_RETRY_SHORT) + info['retry_long'] = nl.nla_find(rmsg,nl80211h.NL80211_ATTR_WIPHY_RETRY_LONG) + info['retry_short'] = nl.nla_find(rmsg,nl80211h.NL80211_ATTR_WIPHY_RETRY_SHORT) + info['frag_thresh'] = nl.nla_find(rmsg,nl80211h.NL80211_ATTR_WIPHY_FRAG_THRESHOLD) + info['rts_thresh'] = nl.nla_find(rmsg,nl80211h.NL80211_ATTR_WIPHY_RTS_THRESHOLD) + info['cov_class'] = nl.nla_find(rmsg,nl80211h.NL80211_ATTR_WIPHY_COVERAGE_CLASS) + info['scan_ssids'] = nl.nla_find(rmsg,nl80211h.NL80211_ATTR_MAX_NUM_SCAN_SSIDS) + # nested attributes (for whatever reason, these use big-endian) + modes = nl.nla_find(rmsg,nl80211h.NL80211_ATTR_SUPPORTED_IFTYPES) + info['modes'] = [_iftypes_(struct.unpack('>H',mode)[0]) for mode in modes] + modes = nl.nla_find(rmsg,nl80211h.NL80211_ATTR_SOFTWARE_IFTYPES) + info['swmodes'] = [_iftypes_(struct.unpack('>H', mode)[0]) for mode in modes] + cmds = nl.nla_find(rmsg,nl80211h.NL80211_ATTR_SUPPORTED_COMMANDS) + info['commands'] = [] + for cmd in cmds: + try: + cmd = cmdbynum(struct.unpack_from('>HH',cmd,0)[1]) + if type(cmd) is type([]): cmd = cmd[0] + info['commands'].append(cmd[13:].lower()) + except KeyError: + info['commands'].append("unknown cmd ({0})".format(cmd)) + return info + +def ifaces(card,*argv): + """ + returns all interfaces sharing the same phy as card (APX iw dev | grep phy#) + :param card: Card object + :param argv: netlink socket at argv[0] (or empty) + :returns: a list of tuples t = (Card,mode) for each device having the same + phyiscal index as that of card + """ + try: + nlsock = argv[0] + except IndexError: + return _nlstub_(ifaces,card) + + ifs = [] + for dev in winterfaces(): + info = devinfo(dev,nlsock) + if info['card'].phy == card.phy: ifs.append((info['card'],info['mode'])) + return ifs + +def chget(card,*argv): + """ + gets the current channel for device (iw dev info | grep channel) + :param card: Card object + :param argv: netlink socket at argv[0] (or empty) + NOTE: + o ATT will only work if dev is associated w/ AP + """ + try: + nlsock = argv[0] + except IndexError: + return _nlstub_(chget,card) + return channels.rf2ch(devinfo(card.dev,nlsock)['RF']) + +def freqset(card,rf,chw=None,*argv): + """ + REQUIRES ROOT PRIVILEGES + set the frequency and width + :param card: Card object + :param rf: frequency + :param chw: channel width oneof {[None|'HT20'|'HT40-'|'HT40+'} + :param argv: netlink socket at argv[0] (or empty) + :returns: True on success + """ + if rf not in channels.freqs(): raise pyric.error(errno.EINVAL,"Invalid frequency") + if chw not in channels.CHWIDTHS: raise pyric.error(errno.EINVAL,"Invalid channel width") + try: + nlsock = argv[0] + except IndexError: + return _nlstub_(freqset,card,rf,chw) + + msg = nl.nlmsg_new(nltype=_familyid_(nlsock), + cmd=nl80211h.NL80211_CMD_SET_WIPHY, + flags=nlh.NLM_F_REQUEST | nlh.NLM_F_ACK) + nl.nla_put_u32(msg,card.phy,nl80211h.NL80211_ATTR_WIPHY) + nl.nla_put_u32(msg,rf,nl80211h.NL80211_ATTR_WIPHY_FREQ) + nl.nla_put_u32(msg,channels.CHWIDTHS.index(chw), + nl80211h.NL80211_ATTR_WIPHY_CHANNEL_TYPE) + nl.nl_sendmsg(nlsock,msg) + nl.nl_recvmsg(nlsock) + return True + +def chset(card,ch,chw,*argv): + """ + REQUIRES ROOT PRIVILEGES + sets current channel on device (iw phy set channel ) + :param card: Card object + :param ch: channel number + :param chw: channel width oneof {[None|'HT20'|'HT40-'|'HT40+'} + :param argv: netlink socket at argv[0] (or empty) + :returns: True on success + NOTE: + o ATT can throw a device busy for several reason. Most likely due to + the network manager etc. + o On my system at least (Ubuntu), creating a new dev in monitor mode and + deleting all other existing managed interfaces allows for the new virtual + device's channels to be changed + """ + if ch not in channels.channels(): raise pyric.error(errno.EINVAL,"Invalid channel") + if chw not in channels.CHWIDTHS: raise pyric.error(errno.EINVAL,"Invalid channel width") + try: + nlsock = argv[0] + except IndexError: + return _nlstub_(chset,card,ch,chw) + + return freqset(card,channels.ch2rf(ch),chw,nlsock) + +def modeset(card,mode,flags=None,*argv): + """ + REQUIRES ROOT PRIVILEGES/CARD DOWN + sets card to mode (with optional flags if mode is monitor) + (APX iw dev set type [flags]) + NOTE: as far + :param card: Card object + :param mode: 'name' of mode to operate in (must be one of in {'unspecified'| + 'ibss'|'managed'|'AP'|'AP VLAN'|'wds'|'monitor'|'mesh'|'p2p'} + :param flags: list of monitor flags (can only be used if card is being set + to monitor mode) + :param argv: netlink socket at argv[0] (or empty) + :returns: True on success + """ + if mode not in IFTYPES: raise pyric.error(errno.EINVAL, 'Invalid mode') + if flags: + if mode != 'monitor': + raise pyric.error(errno.EINVAL, + 'Can only set flags in monitor mode') + for flag in flags: + if flag not in MNTRFLAGS: + raise pyric.error(errno.EINVAL, 'Invalid flag: {0}', + format(flag)) + else: flags = [] + + try: + nlsock = argv[0] + except IndexError: + return _nlstub_(modeset,card,mode,flags) + + msg = nl.nlmsg_new(nltype=_familyid_(nlsock), + cmd=nl80211h.NL80211_CMD_SET_INTERFACE, + flags=nlh.NLM_F_REQUEST | nlh.NLM_F_ACK) + nl.nla_put_u32(msg,card.idx,nl80211h.NL80211_ATTR_IFINDEX) + nl.nla_put_u32(msg,IFTYPES.index(mode),nl80211h.NL80211_ATTR_IFTYPE) + for flag in flags: + nl.nla_put_u32(msg,MNTRFLAGS.index(flag),nl80211h.NL80211_ATTR_MNTR_FLAGS) + nl.nl_sendmsg(nlsock,msg) + nl.nl_recvmsg(nlsock) + return True + +def modeget(card,*argv): + """ + get current mode of card + :param card: Card object + :param argv: netlink socket at argv[0] (or empty) + :return: + """ + try: + nlsock = argv[0] + except IndexError: + return _nlstub_(modeget,card) + + return devinfo(card,nlsock)['mode'] + +def devadd(card,vdev,mode,flags=None,*argv): + """ + REQUIRES ROOT PRIVILEGES + adds a virtual interface on device having type mode (iw phy + interface add type + :param card: Card object + :param vdev: device name of new interface + :param mode: 'name' of mode to operate in (must be one of in {'unspecified'| + 'ibss'|'managed'|'AP'|'AP VLAN'|'wds'|'monitor'|'mesh'|'p2p'} + :param flags: list of monitor flags (can only be used if vnic is being created in + monitor mode) + :param argv: netlink socket at argv[0] (or empty) + :returns: the new Card + """ + if mode not in IFTYPES: raise pyric.error(errno.EINVAL,'Invalid mode') + if flags: + if mode != 'monitor': + raise pyric.error(errno.EINVAL,'Can only set flags in monitor mode') + for flag in flags: + if flag not in MNTRFLAGS: + raise pyric.error(errno.EINVAL,'Invalid flag: {0}',format(flag)) + else: flags = [] + + try: + nlsock = argv[0] + except IndexError: + return _nlstub_(devadd,card,vdev,mode,flags) + + msg = nl.nlmsg_new(nltype=_familyid_(nlsock), + cmd=nl80211h.NL80211_CMD_NEW_INTERFACE, + flags=nlh.NLM_F_REQUEST | nlh.NLM_F_ACK) + nl.nla_put_u32(msg,card.phy,nl80211h.NL80211_ATTR_WIPHY) + nl.nla_put_string(msg,vdev,nl80211h.NL80211_ATTR_IFNAME) + nl.nla_put_u32(msg,IFTYPES.index(mode),nl80211h.NL80211_ATTR_IFTYPE) + for flag in flags: + nl.nla_put_u32(msg,MNTRFLAGS.index(flag),nl80211h.NL80211_ATTR_MNTR_FLAGS) + nl.nl_sendmsg(nlsock,msg) + rmsg = nl.nl_recvmsg(nlsock) # success returns new device attributes + return Card(card.phy,vdev,nl.nla_find(rmsg,nl80211h.NL80211_ATTR_IFINDEX)) + +def devdel(card,*argv): + """ + REQUIRES ROOT PRIVILEGES + deletes the device (dev del + :param card: Card object + :param argv: netlink socket at argv[0] (or empty) + :returns: True on success + NOTE: the original card is no longer valid (i.e. the phy will still be present but + the device name and ifindex are no longer 'present' in the system + """ + try: + nlsock = argv[0] + except IndexError: + return _nlstub_(devdel,card) + + msg = nl.nlmsg_new(nltype=_familyid_(nlsock), + cmd=nl80211h.NL80211_CMD_DEL_INTERFACE, + flags=nlh.NLM_F_REQUEST | nlh.NLM_F_ACK) + nl.nla_put_u32(msg,card.idx,nl80211h.NL80211_ATTR_IFINDEX) + nl.nl_sendmsg(nlsock,msg) + nl.nl_recvmsg(nlsock) + return True + +################################################################################ +#### FILE PRIVATE #### +################################################################################ + +def _hex2mac_(v): + """:returns: a ':' separated mac address from byte stream v""" + return ":".join(['{0:02x}'.format(ord(c)) for c in v]) + +def _issetf_(flags,flag): + """ + determines if flag is set + :param flags: current flag value + :param flag: flag to check + :return: True if flag is set + """ + return (flags & flag) == flag + +def _setf_(flags,flag): + """ + sets flag, adding to flags + :param flags: current flag value + :param flag: flag to set + :return: new flag value + """ + return flags | flag + +def _unsetf_(flags,flag): + """ + unsets flag, adding to flags + :param flags: current flag value + :param flag: flag to unset + :return: new flag value + """ + return flags & ~flag + +def _familyid_(nlsock): + """ + extended version: get the family id + :param nlsock: netlink socket + :returns: the family id of nl80211 + NOTE: + In addition to the family id, we get: + CTRL_ATTR_FAMILY_NAME = nl80211\x00 + CTRL_ATTR_VERSION = \x01\x00\x00\x00 = 1 + CTRL_ATTR_HDRSIZE = \x00\x00\x00\x00 = 0 + CTRL_ATTR_MAXATTR = \xbf\x00\x00\x00 = 191 + CTRL_ATTR_OPS + CTRL_ATTR_MCAST_GROUPS + but for now, these are not used + """ + global _FAM80211ID_ + if _FAM80211ID_ is None: + # family id is not instantiated, do so now + msg = nl.nlmsg_new(nltype=genlh.GENL_ID_CTRL, + cmd=genlh.CTRL_CMD_GETFAMILY, + flags=nlh.NLM_F_REQUEST | nlh.NLM_F_ACK) + nl.nla_put_string(msg,nl80211h.NL80211_GENL_NAME, + genlh.CTRL_ATTR_FAMILY_NAME) + nl.nl_sendmsg(nlsock,msg) + rmsg = nl.nl_recvmsg(nlsock) + _FAM80211ID_ = nl.nla_find(rmsg,genlh.CTRL_ATTR_FAMILY_ID) + return _FAM80211ID_ + +def _ifindex_(dev,*argv): + """ + gets the ifindex for device + :param dev: device name: + :param argv: ioctl socket at argv[0] (or empty) + :returns: ifindex of device + NOTE: the ifindex can aslo be found in /sys/class/net//ifindex + """ + try: + iosock = argv[0] + except IndexError: + return _iostub_(_ifindex_,dev) + + try: + flag = sioch.SIOCGIFINDEX + ret = io.io_transfer(iosock,flag,ifh.ifreq(dev,flag)) + return struct.unpack_from(ifh.ifr_ifindex,ret,ifh.IFNAMELEN)[0] + except AttributeError as e: + raise pyric.error(errno.EINVAL,"Invalid parameter {0}".format(e)) + except struct.error as e: + raise pyric.error(pyric.EUNDEF,"error parsing results {0}".format(e)) + +def _flagsget_(dev,*argv): + """ + gets the device's flags + :param dev: device name: + :param argv: ioctl socket at argv[0] (or empty) + :returns: device flags + """ + try: + iosock = argv[0] + except IndexError: + return _iostub_(_flagsget_,dev) + + try: + flag = sioch.SIOCGIFFLAGS + ret = io.io_transfer(iosock,flag,ifh.ifreq(dev,flag)) + return struct.unpack_from(ifh.ifr_flags,ret,ifh.IFNAMELEN)[0] + except AttributeError as e: + raise pyric.error(errno.EINVAL,"Invalid parameter {0}".format(e)) + except struct.error as e: + raise pyric.error(pyric.EUNDEF,"error parsing results {0}".format(e)) + +def _flagsset_(dev,flags,*argv): + """ + gets the device's flags + :param dev: device name: + :param flags: flags to set + :param argv: ioctl socket at argv[0] (or empty) + :returns: device flags after operation + """ + try: + iosock = argv[0] + except IndexError: + return _iostub_(_flagsset_,dev,flags) + + try: + flag = sioch.SIOCSIFFLAGS + ret = io.io_transfer(iosock,flag,ifh.ifreq(dev,flag,[flags])) + return struct.unpack_from(ifh.ifr_flags,ret,ifh.IFNAMELEN)[0] + except AttributeError as e: + raise pyric.error(errno.EINVAL,"Invalid parameter {0}".format(e)) + except struct.error as e: + raise pyric.error(pyric.EUNDEF,"error parsing results {0}".format(e)) + +def _iftypes_(i): + """ + wraps the IFTYPES list to handle index errors + :param i: + :returns: the string IFTYPE corresponding to i + """ + try: + return IFTYPES[i] + except IndexError: + return 'Unknown mode ({0})' % i + +#### TRANSLATION FUNCTIONS #### + +def _iostub_(fct,*argv): + """ + translates from traditional ioctl to extended ex + :param fct: function to translate to + :param argv: parameters to the function + :returns: the results of fct + """ + iosock = io.io_socket_alloc() + try: + argv = list(argv) + [iosock] + return fct(*argv) + except pyric.error: + raise # catch and rethrow + finally: + io.io_socket_free(iosock) + +def _nlstub_(fct,*argv): + """ + translates from traditional netlink to extended ex + :param fct: function to translate to + :param argv: parameters to the function + :returns: rresults of fucntion + """ + nlsock = None + try: + nlsock = nl.nl_socket_alloc(timeout=2) + argv = list(argv) + [nlsock] + return fct(*argv) + except pyric.error: + raise + finally: + if nlsock: nl.nl_socket_free(nlsock) + +#### NOT USED #### + +def _fut_chset(card,ch,chw,*argv): + """ + set current channel on device (iw phy set channel + :param card: Card object + :param ch: channel number + :param chw: channel width oneof {None|'HT20'|'HT40-'|'HT40+'} + :param argv: netlink socket at argv[0] (or empty) + :returns: True on success + uses the newer NL80211_CMD_SET_CHANNEL vice iw's depecrated version which + uses *_SET_WIPHY however, ATT does not work raise Errno 22 Invalid Argument + """ + if ch not in channels.channels(): raise pyric.error(errno.EINVAL,"Invalid channel") + if chw not in channels.CHWIDTHS: raise pyric.error(errno.EINVAL,"Invalid channel width") + try: + nlsock = argv[0] + except IndexError: + return _nlstub_(_fut_chset,card,ch,chw) + + msg = nl.nlmsg_new(nltype=_familyid_(nlsock), + cmd=nl80211h.NL80211_CMD_SET_CHANNEL, + flags=nlh.NLM_F_REQUEST | nlh.NLM_F_ACK) + nl.nla_put_u32(msg,card.phy,nl80211h.NL80211_ATTR_WIPHY) + nl.nla_put_u32(msg,channels.ch2rf(ch),nl80211h.NL80211_ATTR_WIPHY_FREQ) + nl.nla_put_u32(msg,channels.CHWIDTHS.index(chw),nl80211h.NL80211_ATTR_WIPHY_CHANNEL_TYPE) + nl.nl_sendmsg(nlsock,msg) + nl.nl_recvmsg(nlsock) + return True \ No newline at end of file diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 0000000..8235868 --- /dev/null +++ b/setup.cfg @@ -0,0 +1,4 @@ +[bdist_wheel] + +universal=1 +description-file = README.md \ No newline at end of file diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..447aae3 --- /dev/null +++ b/setup.py @@ -0,0 +1,72 @@ +#!/usr/bin/env python + +""" setup.py: install PyRIC + +Copyright (C) 2016 Dale V. Patterson (wraith.wireless@yandex.com) + +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 3 of the License, or (at your option) any later +version. + +Redistribution and use in source and binary forms, with or without modifications, +are permitted provided that the following conditions are met: + o Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + o Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + o Neither the name of the orginal author Dale V. Patterson nor the names of any + contributors may be used to endorse or promote products derived from this + software without specific prior written permission. + +""" + +#__name__ = 'setup' +__license__ = 'GPLv3' +__version__ = '0.0.2' +__date__ = 'May 2016' +__author__ = 'Dale Patterson' +__maintainer__ = 'Dale Patterson' +__email__ = 'wraith.wireless@yandex.com' +__status__ = 'Development' + +from setuptools import setup, find_packages +#from codecs import open +#from os import path +import pyric + + +long_desc = """ +A simple interface to the underlying nl80211 kernel support that handles the +complex operations of netlink seamlessy while maintaining a minimum of "code +walking" to understand, modify and add future operations. Not a full blown port +of iw (and ifconfig, iwconfig) functionality to Python but sufficient to +programmatically create a wireless pentest environment""" + +setup(name='PyRIC', + version=pyric.__version__, + description="PyRIC: python port of a subset of iw", + long_description=long_desc, + url='http://wraith-wireless.github.io/pyric', + download_url="https://github.com/wraith-wireless/pyric/archive/"+pyric.__version__+".tar.gz", + author=pyric.__author__, + author_email=pyric.__email__, + maintainer=pyric.__maintainer__, + maintainer_email=pyric.__email__, + license=pyric.__license__, + classifiers=['Development Status :: 4 - Beta', + 'License :: OSI Approved :: GNU General Public License v3 (GPLv3)', + 'Intended Audience :: Developers', + 'Topic :: Software Development', + 'Topic :: Software Development :: Libraries', + 'Topic :: Security', + 'Topic :: System :: Networking', + 'Topic :: Utilities', + 'Operating System :: POSIX :: Linux', + 'Programming Language :: Python' + ], + keywords='nl80211 iw developement wireless pentest', + packages=find_packages(), + package_data={'pyric':['docs/*.help']} +)