Codebase list python-pyric / fresh-snapshots/main
Merge new upstream release 0.1.6+git20191210.bc0dce3. Kali Janitor 3 years ago
15 changed file(s) with 223 addition(s) and 1821 deletion(s). Raw diff Collapse all Expand all
+0
-116
.gitignore less more
0 # modified from https://github.com/github/gitignore/blob/master/Python.gitignore
1 #Copyright (c) 2016 GitHub, Inc.
2 #
3 #Permission is hereby granted, free of charge, to any person obtaining a
4 #copy of this software and associated documentation files (the "Software"),
5 #to deal in the Software without restriction, including without limitation
6 #the rights to use, copy, modify, merge, publish, distribute, sublicense,
7 #and/or sell copies of the Software, and to permit persons to whom the
8 #Software is furnished to do so, subject to the following conditions:
9 #
10 #The above copyright notice and this permission notice shall be included in
11 #all copies or substantial portions of the Software.
12 #
13 #THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 #IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 #FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 #AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 #LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18 #FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
19 #
20 #DEALINGS IN THE SOFTWARE.
21
22
23 # Byte-compiled / optimized / DLL files
24 __pycache__/
25 *.py[cod]
26 *$py.class
27
28 # C extensions
29 *.so
30
31 # Distribution / packaging
32 .Python
33 env/
34 build/
35 develop-eggs/
36 dist/
37 downloads/
38 eggs/
39 .eggs/
40 # lib -> commented out as we use lib
41 lib64/
42 parts/
43 sdist/
44 var/
45 *.egg-info/
46 .installed.cfg
47 *.egg
48
49 # PyCharm
50 .idea
51 .git
52
53 # PyInstaller
54 # Usually these files are written by a python script from a template
55 # before PyInstaller builds the exe, so as to inject date/other infos into it.
56 *.manifest
57 *.spec
58
59 # Installer logs
60 pip-log.txt
61 pip-delete-this-directory.txt
62
63 # Unit test / coverage reports
64 htmlcov/
65 .tox/
66 .coverage
67 .coverage.*
68 .cache
69 nosetests.xml
70 coverage.xml
71 *,cover
72 .hypothesis/
73
74 # Translations
75 *.mo
76 *.pot
77
78 # Django stuff:
79 *.log
80 local_settings.py
81
82 # Flask stuff:
83 instance/
84 .webassets-cache
85
86 # Scrapy stuff:
87 .scrapy
88
89 # Sphinx documentation
90 docs/_build/
91
92 # PyBuilder
93 target/
94
95 # IPython Notebook
96 .ipynb_checkpoints
97
98 # pyenv
99 .python-version
100
101 # celery beat schedule file
102 celerybeat-schedule
103
104 # dotenv
105 .env
106
107 # virtualenv
108 venv/
109 ENV/
110
111 # Spyder project settings
112 .spyderproject
113
114 # Rope project settings
115 .ropeproject
0 Metadata-Version: 1.2
1 Name: PyRIC
2 Version: 0.1.6.4
3 Summary: Python Wireless Library
4 Home-page: http://wraith-wireless.github.io/PyRIC/
5 Author: Dale Patterson
6 Author-email: [email protected]
7 Maintainer: Dale Patterson
8 Maintainer-email: [email protected]
9 License: GPLv3
10 Download-URL: https://github.com/wraith-wireless/pyric/archive/0.1.6.4.tar.gz
11 Description:
12 # PyRIC 0.1.6.4: Python Radio Interface Controller
13 ## Linux wireless library for the Python Wireless Developer and Pentester
14
15 ## DESCRIPTION:
16 PyRIC (is a Linux only) library providing wireless developers and pentesters the
17 ability to identify, enumerate and manipulate their system's wireless cards
18 programmatically in Python. Pentesting applications and scripts written in Python
19 have increased dramatically in recent years. However, these tools still rely on
20 Linux command lines tools for setup/preparation and restoration of the system for
21 use. Until now. Why use subprocess.Popen, regular expressions and str.find to
22 interact with your wireless cards? PyRIC is:
23
24 1. Pythonic: no ctypes, SWIG etc. PyRIC redefines C header files as Python and
25 uses sockets to communicate with the kernel.
26 2. Self-sufficient: No third-party files used. PyRIC is completely self-contained.
27 3. Fast: (relatively speaking) PyRIC is faster than using command line tools
28 through subprocess.Popen
29 4. Parseless: Get the output you want without parsing output from command line
30 tools. Never worry about newer iw versions and having to rewrite your parsers.
31 5. Easy: If you can use iw, you can use PyRIC.
32
33 ## CURRENT STATE
34 ATT, PyRIC pyw provides the following:
35 * enumerate interfaces and wireless interfaces
36 * identify a cards chipset and driver
37 * get/set hardware address
38 * get/set ip4 address, netmask and or broadcast
39 * turn card on/off
40 * get supported standards
41 * get supported commands
42 * get supported modes
43 * get dev info
44 * get phy info
45 * get link info
46 * get/set regulatory domain
47 * get/set mode
48 * get/set coverage class, RTS threshold, Fragmentation threshold & retry limits
49 * add/delete interfaces
50 * enumerate ISM and UNII channels
51 * block/unblock rfkill devices
52 * check 'connectivity', disconnect from AP
53
54 In utils, several helpers can be found that can be used to:
55 * enumerate channels and frequencies and convert between the two
56 * manipulate mac addresses and generate random ones
57 * fetch and parse the IEEE oui text file
58 * further rfkill operations to include listing all rfkill devices
59
60 At it's heart, PyRIC is a Python port of (a subset of) iw and by extension, a
61 Python port of Netlink w.r.t nl80211 functionality. The original goal of PyRIC
62 was to provide a simple interface to the underlying nl80211 kernel support,
63 handling the complex operations of Netlink seamlessy while maintaining a minimum
64 of "code walking" to understand, modify and extend. But, why stop there? Since
65 it's initial inception, PyRIC has grown. PyRIC puts iw, ifconfig, rfkill, udevadm,
66 airmon-ng and macchanger in your hands (or your program).
67
68 Keywords: Linux Python nl80211 iw iwconfig ifconfig wireless WLAN WiFi pentest
69 Platform: UNKNOWN
70 Classifier: Development Status :: 5 - Production/Stable
71 Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
72 Classifier: Intended Audience :: Developers
73 Classifier: Intended Audience :: System Administrators
74 Classifier: Topic :: Security
75 Classifier: Topic :: Software Development
76 Classifier: Topic :: Software Development :: Libraries
77 Classifier: Topic :: Security
78 Classifier: Topic :: System :: Networking
79 Classifier: Topic :: Utilities
80 Classifier: Operating System :: POSIX :: Linux
81 Classifier: Programming Language :: Python
82 Classifier: Programming Language :: Python :: 2.7
83 Classifier: Programming Language :: Python :: 3.0
84 Classifier: Programming Language :: Python :: 3.5
0 Metadata-Version: 1.2
1 Name: PyRIC
2 Version: 0.1.6.4
3 Summary: Python Wireless Library
4 Home-page: http://wraith-wireless.github.io/PyRIC/
5 Author: Dale Patterson
6 Author-email: [email protected]
7 Maintainer: Dale Patterson
8 Maintainer-email: [email protected]
9 License: GPLv3
10 Download-URL: https://github.com/wraith-wireless/pyric/archive/0.1.6.4.tar.gz
11 Description:
12 # PyRIC 0.1.6.4: Python Radio Interface Controller
13 ## Linux wireless library for the Python Wireless Developer and Pentester
14
15 ## DESCRIPTION:
16 PyRIC (is a Linux only) library providing wireless developers and pentesters the
17 ability to identify, enumerate and manipulate their system's wireless cards
18 programmatically in Python. Pentesting applications and scripts written in Python
19 have increased dramatically in recent years. However, these tools still rely on
20 Linux command lines tools for setup/preparation and restoration of the system for
21 use. Until now. Why use subprocess.Popen, regular expressions and str.find to
22 interact with your wireless cards? PyRIC is:
23
24 1. Pythonic: no ctypes, SWIG etc. PyRIC redefines C header files as Python and
25 uses sockets to communicate with the kernel.
26 2. Self-sufficient: No third-party files used. PyRIC is completely self-contained.
27 3. Fast: (relatively speaking) PyRIC is faster than using command line tools
28 through subprocess.Popen
29 4. Parseless: Get the output you want without parsing output from command line
30 tools. Never worry about newer iw versions and having to rewrite your parsers.
31 5. Easy: If you can use iw, you can use PyRIC.
32
33 ## CURRENT STATE
34 ATT, PyRIC pyw provides the following:
35 * enumerate interfaces and wireless interfaces
36 * identify a cards chipset and driver
37 * get/set hardware address
38 * get/set ip4 address, netmask and or broadcast
39 * turn card on/off
40 * get supported standards
41 * get supported commands
42 * get supported modes
43 * get dev info
44 * get phy info
45 * get link info
46 * get/set regulatory domain
47 * get/set mode
48 * get/set coverage class, RTS threshold, Fragmentation threshold & retry limits
49 * add/delete interfaces
50 * enumerate ISM and UNII channels
51 * block/unblock rfkill devices
52 * check 'connectivity', disconnect from AP
53
54 In utils, several helpers can be found that can be used to:
55 * enumerate channels and frequencies and convert between the two
56 * manipulate mac addresses and generate random ones
57 * fetch and parse the IEEE oui text file
58 * further rfkill operations to include listing all rfkill devices
59
60 At it's heart, PyRIC is a Python port of (a subset of) iw and by extension, a
61 Python port of Netlink w.r.t nl80211 functionality. The original goal of PyRIC
62 was to provide a simple interface to the underlying nl80211 kernel support,
63 handling the complex operations of Netlink seamlessy while maintaining a minimum
64 of "code walking" to understand, modify and extend. But, why stop there? Since
65 it's initial inception, PyRIC has grown. PyRIC puts iw, ifconfig, rfkill, udevadm,
66 airmon-ng and macchanger in your hands (or your program).
67
68 Keywords: Linux Python nl80211 iw iwconfig ifconfig wireless WLAN WiFi pentest
69 Platform: UNKNOWN
70 Classifier: Development Status :: 5 - Production/Stable
71 Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
72 Classifier: Intended Audience :: Developers
73 Classifier: Intended Audience :: System Administrators
74 Classifier: Topic :: Security
75 Classifier: Topic :: Software Development
76 Classifier: Topic :: Software Development :: Libraries
77 Classifier: Topic :: Security
78 Classifier: Topic :: System :: Networking
79 Classifier: Topic :: Utilities
80 Classifier: Operating System :: POSIX :: Linux
81 Classifier: Programming Language :: Python
82 Classifier: Programming Language :: Python :: 2.7
83 Classifier: Programming Language :: Python :: 3.0
84 Classifier: Programming Language :: Python :: 3.5
0 CHANGES
1 LICENSE
2 MANIFEST.in
3 README.md
4 TODO
5 setup.cfg
6 setup.py
7 PyRIC.egg-info/PKG-INFO
8 PyRIC.egg-info/SOURCES.txt
9 PyRIC.egg-info/dependency_links.txt
10 PyRIC.egg-info/top_level.txt
11 docs/PyRIC.pdf
12 examples/info.py
13 examples/pentest.py
14 pyric/__init__.py
15 pyric/pyw.py
16 pyric/lib/__init__.py
17 pyric/lib/libio.py
18 pyric/lib/libnl.py
19 pyric/net/__init__.py
20 pyric/net/genetlink_h.py
21 pyric/net/if_h.py
22 pyric/net/netlink_h.py
23 pyric/net/policy.py
24 pyric/net/sockios_h.py
25 pyric/net/wireless/__init__.py
26 pyric/net/wireless/nl80211_c.py
27 pyric/net/wireless/nl80211_h.py
28 pyric/net/wireless/rfkill_h.py
29 pyric/net/wireless/wlan.py
30 pyric/nlhelp/__init__.py
31 pyric/nlhelp/attributes.help
32 pyric/nlhelp/commands.help
33 pyric/nlhelp/nlsearch.py
34 pyric/scripts/__init__.py
35 pyric/scripts/ouiupdate.py
36 pyric/utils/__init__.py
37 pyric/utils/channels.py
38 pyric/utils/hardware.py
39 pyric/utils/ouifetch.py
40 pyric/utils/rfkill.py
41 pyric/utils/data/oui.txt
+0
-6
__init__.py less more
0 # PyRIC v 1.6 root Distribution directory
1 # Do not import from this directory i.e from PyRIC import foobar
2 # To install
3 # use pip ('sudo pip install PyRIC')
4 # or download latest tarbal and untar.
5 # excute either sudo python setup.py or rund from the PyRIC/pyric directory
0 python-pyric (0.1.6+git20191210.bc0dce3-1) UNRELEASED; urgency=low
1 -- Kali Janitor <[email protected]> Mon, 29 Mar 2021 11:01:34 -0000
2
03 python-pyric (0.1.6+git20191210-0kali1) kali-dev; urgency=medium
14
25 [ Raphaël Hertzog ]
+0
-48
docs/PyRIC.bib less more
0 # PyRIC.bib for v 1.4
1 @Misc{libnl,
2 Title = {Netlink Library (libnl)},
3 Author = {Thomas Graf},
4 Month = {May},
5 Year = {2011},
6 Date = {2011-05-09},
7 Language = {english},
8 Organization = {Swiss Internet User Group},
9 Shorthand = {libnl},
10 Url = {http://www.carisma.slowglass.com/~tgr/libnl/doc/core.html},
11 Version = {3.2}
12 }
13
14 @Article{spae,
15 Title = {Communicating between the kernel and user-space in Linux using Netlink sockets},
16 Author = {Pablo Neira Ayuso, Rafael M. Gasca, Laurent Lefevre},
17 Journal = {Software - Practice And Experience},
18 Year = {2010},
19 Month = {August},
20 Pages = {797-810},
21 Volume = {40}
22 }
23
24 @Misc{wraith,
25 Title = {Wireless Reconnaissance And Intelligent Target Harvesting},
26 Author = {Dale V. Patterson},
27 Month = {April},
28 Year = {2016},
29 Date = {2016-04-03},
30 Language = {english},
31 Shorthand = {wraith},
32 Url = {https://github.com/wraith-wireless/wraith},
33 Version = {0.0.6}
34 }
35
36 @Misc{gplv3,
37 Title = {GNU General Public License},
38 Month = {June},
39 Year = {2007},
40 Date = {2007-06-29},
41 Language = {english},
42 Organization = {Free Software Foundation},
43 Pagination = {section},
44 Shorthand = {GPL},
45 Url = {http://www.gnu.org/licenses/gpl.html},
46 Version = {3}
47 }
+0
-1174
docs/PyRIC.tex less more
0 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1 % Copyright (C) 2016 Dale V. Patterson ([email protected])
2 %
3 %This program is free software: you can redistribute it and/or modify it under
4 %the terms of the GNU General Public License as published by the Free Software
5 %Foundation, either version 3 of the License, or (at your option) any later
6 %version.
7 %
8 %Redistribution and use in source and binary forms, with or without modifications,
9 %are permitted provided that the following conditions are met:
10 % o Redistributions of source code must retain the above copyright notice, this
11 % list of conditions and the following disclaimer.
12 % o Redistributions in binary form must reproduce the above copyright notice,
13 % this list of conditions and the following disclaimer in the documentation
14 % and/or other materials provided with the distribution.
15 % o Neither the name of the orginal author Dale V. Patterson nor the names of any
16 % contributors may be used to endorse or promote products derived from this
17 % software without specific prior written permission.
18 %
19 % __name__ = 'User Guide'
20 %__license__ = 'GPLv3'
21 %__version__ = '0.0.7'
22 %__date__ = 'December 2016'
23 %__author__ = 'Dale Patterson'
24 %__maintainer__ = 'Dale Patterson'
25 %__email__ = '[email protected]'
26 %__status__ = 'Production'
27 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
28
29 \documentclass[11pt]{article}
30 \usepackage[utf8]{inputenc}
31 \setlength{\parindent}{0pt}
32 \usepackage{graphicx}
33 \usepackage{listings}
34 \usepackage{caption}
35 \usepackage{geometry}
36 \usepackage{color}
37 \usepackage{graphicx}
38 \usepackage[titletoc,toc,title]{appendix}
39 \usepackage[T1]{fontenc}
40
41 \definecolor{codegreen}{rgb}{0,0.6,0}
42 \definecolor{codegray}{rgb}{0.5,0.5,0.5}
43 \definecolor{codepurple}{rgb}{0.58,0,0.82}
44 \definecolor{backcolour}{rgb}{0.95,0.95,0.92}
45
46 \geometry{left=1.0in,right=1.0in,top=1.0in,bottom=1.0in }
47
48 \lstset{
49 frame=top,
50 frame=bottom,
51 basicstyle=\small\normalfont\ ,
52 stepnumber=1,
53 numbersep=10pt,
54 tabsize=2,
55 extendedchars=true,
56 breaklines=true,
57 captionpos=b,
58 mathescape=true,
59 showspaces=false,
60 showtabs=false,
61 xleftmargin=17pt,
62 framexleftmargin=17pt,
63 framexrightmargin=17pt,
64 framexbottommargin=5pt,
65 framextopmargin=5pt,
66 showstringspaces=false,
67 backgroundcolor=\color{backcolour},
68 commentstyle=\color{codegreen},
69 keywordstyle=\color{magenta},
70 numberstyle=\tiny\color{codegray},
71 stringstyle=\color{codepurple},
72 basicstyle=\footnotesize
73 }
74
75 \title{\includegraphics[scale=1]{logo}\\ PyRIC v0.1.6.4: User Manual}
76 \author{Dale V. Patterson\\ [email protected]}
77
78 \begin{document}
79 \maketitle
80 \tableofcontents
81
82 \section{About PyRIC}\label{sec:About}
83 PyRIC (is a Linux only) library providing wireless developers and pentesters the
84 ability to identify, enumerate and manipulate their system's wireless cards
85 programmatically in Python. Pentesting applications and scripts written in Python
86 have increased dramatically in recent years. However, these tools still rely on
87 Linux command lines tools to setup and prepare and restore the system for use.
88 Until now. Why use subprocess.Popen, regular expressions and str.find to interact
89 with your wireless cards? PyRIC puts iw, ifconfig, rfkill, udevadm, airmon-ng and
90 macchanger in your hands (or your program). \\
91
92 PyRIC is designed with Python 2.7 in mind but has now been made compatible with
93 Python 3.5. It will also work on Python 3.0 but you will have to hard code the
94 command line options in the two examples as Python 3.0 does not include the module
95 argparse
96
97 PyRIC is:
98 \begin{enumerate}
99 \item \textbf{Pythonic}: No ctypes, SWIG etc. PyRIC redefines C header files as
100 Python and uses sockets to communicate with kernel.
101 \item \textbf{Self-sufficient}: No third-party files used, PyRIC is completely self-
102 contained
103 \item \textbf{Fast}: (relatively speaking) PyRIC is faster than using iw through
104 subprocess.Popen
105 \item \textbf{Parseless}: Get the output you without parsing output from iw. Never
106 worry about iw updates and rewriting your parsers.
107 \item \textbf{Easy}: If you can use iw, you can use PyRIC
108 \end{enumerate}
109
110 At it's heart, PyRIC is a Python port of (a subset of) iw and by extension, a
111 Python port of Netlink w.r.t nl80211 functionality. The original goal of PyRIC
112 was to provide a simple interface to the underlying nl80211 kernel support,
113 handling the complex operations of Netlink seamlessy while maintaining a minimum
114 of "code walking" to understand, modify and extend. But, why stop there? Since
115 it's initial inception, PyRIC has grown to include ioctl support to replicate
116 features of ifconfig such as getting or setting the mac address and has recently
117 implemented rkill support to soft block or unblock wireless cards.\\
118
119 While users can utilize libnl.py to communicate directly with the kernel, the
120 true utility of PyRIC is pyw.py. Like iw, pyw provides an interface/buffer
121 between the caller and the kernel, handling all message construction, parsing
122 and data transfer transparently and without requiring any Netlink knowledge or
123 experience. \\
124
125 At this time, PyRIC can:
126 \begin{itemize}
127 \item enumerate interfaces and wireless interfaces,
128 \item identify a cards driver, chipset and manufacturer,
129 \item get/set hardware address,
130 \item get/set ip4 address, netmask and or broadcast,
131 \item turn card on/off,
132 \item get supported standards, commands or modes,
133 \item get if info,
134 \item get dev info,
135 \item get phy info,
136 \item get link info,
137 \item get STA (connected AP) info,
138 \item get/set regulatory domain,
139 \item get/set mode,
140 \item get/set coverage class, RTS threshold, Fragmentation threshold and retry
141 limits,
142 \item add/delete interfaces,
143 \item determine if a card is connected,
144 \item get link info for a connected card,
145 \item enumerate ISM and UNII channels,
146 \item block/unblock rfkill devices.
147 \end{itemize}
148 And, through libnl.py and libio.py, users can extend the above functionality by
149 creating additional commands.
150
151 \subsection{Background}
152 PyRIC arose out of a need in Wraith (https://github.com/wraith-wireless/wraith)
153 for Python nl80211/netlink and ioctl functionality. Originally, Wraith used
154 ifconfig, iwconfig and iw via subprocess.Popen and parsed the output. There
155 are obvious shortfalls with this method, especially in terms of iw that is
156 actively changing (revisions break the parser) and I started looking for an
157 open source alternative. There are several open source projects out there
158 such as pyroute, pymnl (and the python files included in the libnl source) but
159 they generally have either not been maintained recently or come with warnings.
160 I desired a simple interface to the underlying nl80211 kernel support that
161 handles the complex operations of netlink seamlessy while maintaining a minimum
162 of "code walking" to understand, modify and extend. I decided to write my own
163 because I do not need complete netlink functionality, only that provided by
164 generic netlink and within the nl80221 family. Additionally, for Wraith, I do
165 not need a full blown port of iw et. al. functionality to Python but only
166 require the ability to turn a wireless nic on/off, get/set the hwaddr, get/set
167 the channel, determine some properties of the card and add/delete interfaces.
168
169 So, why did I do this and why is it done "this" way? When I first started to
170 explore the idea of moving away from iw output parsing, I looked at the source
171 for iw, and existing Python ports. Just to figure out how to get the family id
172 for nl80211 required reading through five different source files with no
173 comments. To that extent, I have attempted to keep subclassing to a minimum,
174 the total number of classes to a minimum, combine files where possible and where
175 it makes since and keep the number of files required to be open simultaneously
176 in order to understand the methodology and follow the program to a minimum. One
177 can understand the PyRIC program flow with only two files open at any time namely,
178 pyw and libnl. In fact, only an understanding of pyw is required to add additional
179 commands although an understanding of libnl.py is helpful especially, if for
180 example, the code is to be extended to handle multicast or callbacks.
181
182 \subsection{Naming Conventions}
183 The terms interface, device and radio are all used interchangeably throughout to
184 refer to a network interface controller (NIC). The following terms will always
185 have one meaning:
186 \begin{itemize}
187 \item \textbf{dev} - the device name i.e. wlan0 or eth0 of a NIC,
188 \item \textbf{phy} - the physical index of a NIC i.e. the 0 in phy0,
189 \item \textbf{ifindex} - the interface index of a NIC,
190 \item \textbf{card} or \textbf{Card} - a NIC abstraction, an object used in pyw
191 functions see the following section for a description.
192 \end{itemize}
193
194 \subsection{Cards}
195 A Card is merely a wrapper around a tuple t = (phy index,device name,ifindex).
196 Since the underlying Netlink calls sometimes require the physical index, sometimes
197 the device name, and sometimes the ifindex, pyw functions\footnote{Not all functions
198 accept only a Card, devinfo() accepts either a Card or a dev, devadd accepts either a
199 Card or a ifindex and phyadd accepts only a physical index} take a Card object which
200 doesn't require callers to know which identifier to use for each function. There are
201 four primary methods to creating a Card:
202 \begin{enumerate}
203 \item \textbf{pyw.getcard} returns a Card object from a given dev,
204 \item \textbf{pyw.devinfo} returns the dict info where info['card'] is the Card
205 object. (This function will take either a card or a ifindex),
206 \item \textbf{pyw.devadd} returns a new Card object (this function will only take
207 a phy),
208 \item \textbf{pyw.ifaces} returns a list of tuples t = (Card,mode) sharing the
209 same phy as a given dev.
210 \end{enumerate}
211
212 A side affect of using Cards is that many of the netlink calls require the ifindex.
213 The ifindex is found through the use of ioctl, meaning two sockets have to be
214 created and two messages have to be sent, received and parsed in order to execute
215 the command. With Cards, the ifindex is requested for only once. \\
216
217 Keep in mind that any identifier (phy, dev, ifindex) can be invalidated outside
218 of your control. Another program can rename your interface, that is change the
219 dev without your knowledge. Depending on what functions are being used this may
220 not be noticed right away as the phy will remain the same. Also for usb devices,
221 (if the usb is disconnected and reconnected) will have the same dev but the phy
222 and ifindex will be different.
223
224 \subsection{Benchmarks}
225 PyRIC makes use of several "extensions" to speed up pyw functions:
226 \begin{enumerate}
227 \item \textbf{Persistent sockets}: pyw provides the caller with functions and
228 the ability to pass their own netlink (or ioctl socket) to pyw functions
229 \item \textbf{One-time request for the nl80211 family id}: pyw stores the family
230 id in a global variable
231 \item \textbf{Consolidation} different "reference" values are consolidated in one
232 class (see the previous section)
233 \end{enumerate}
234
235 \begin{table}
236 \begin{center}
237 \begin{tabular}{| l | r | r | r | r|}
238 \hline
239 chset & Total & Avg & Longest & Shortest \\
240 \hline
241 Popen(iw) & 588.3059 & 0.0588 & 0.0682 & 0.0021 \\
242 \hline
243 one-time & 560.3559 & 0.0560 & 0.0645 & 0.0003 \\
244 \hline
245 persistent & 257.8293 & 0.0257 & 0.0354 & 0.0004 \\
246 \hline
247 \end{tabular}
248 \caption{Benchmark: Popen(iw) vs pyw}
249 \end{center}
250 \label{tab:benchmark}
251 \end{table}
252
253 While small, these changes can improve the performance of any programs using pyw.
254 Table 1 shows benchmarks for hop time on an Alfa AWUS036NH conducted 10000 times.
255 Note that we are not implying that PyRIC is faster than iw. Rather, the table
256 shows that PyRIC is faster than using Popen to execute iw. Using one-time sockets,
257 there is a difference of 28 seconds over Popen and iw with a small decrease in
258 the average hoptime. Not a big difference. However, the performance increased
259 dramatically when persistent netlink sockets are used with the total time and
260 average hop time nearly halved.
261
262 \section{Installing PyRIC}\label{sec:installing}
263 The easiest way to install PyRIC is through PyPI:\\
264
265 \texttt{sudo pip install PyRIC}\\
266
267 You can also install PyRIC from source. The tarball can be downloaded from:
268
269 \begin{itemize}
270 \item PyPi: https://pypi.python.org/pypi/PyRIC,
271 \item PyRIC Web: http://wraith-wireless.github.io/PyRIC, or
272 \item Github: https://github.com/wraith-wireless/PyRIC.
273 \end{itemize}
274
275 After downloading, extract and run:\\
276
277 \texttt{sudo python setup.py install}\\
278
279 If you just want to test PyRIC out, download your choice from above. After
280 extraction, move the pyric folder (the package directory) to your location of
281 choice and from there start Python and import pyw. It is very important that you
282 do not try and run it from PyRIC which is the distribution directory. This will
283 break the imports pyw.py uses. \\
284
285 You will only be able to test PyRIC from the pyric directory but, if you want to,
286 you can add it to your Python path and run it from any program or any location.
287 To do so, assume you untared PyRIC to /home/bob/PyRIC. Create a text file named
288 pyric.pth with one line \\
289
290 /home/bob/PyRIC \\
291
292 and save this file to /usr/lib/python2.7/dist-packages (or
293 /usr/lib/python3/dist-packages if you want to try it in Python 3).
294
295 \begin{table}
296 \begin{center}
297 \begin{tabular}{| l | r | r | r |}
298 \hline
299 Source & Stability & Recency & Installation \\
300 \hline
301 pip & 5 & 3 & 5\\
302 \hline
303 PyPI & 5 & 3 & 4\\
304 \hline
305 PyRIC Web & 4 & 4 & 4\\
306 \hline
307 Github & 3 & 5 & 3\\
308 \hline
309 \end{tabular}
310 \caption{Stability vs Recency vs Installation}
311 \end{center}
312 \label{tab:install}
313 \end{table}
314
315 \section{Using PyRIC}\label{sec:using}
316 As stated previously, PyRIC provides a set of functions to interact with your
317 system's radio(s) and the ability to interact directly with the kernel through
318 netlink and ioctl sockets.
319
320 \subsection{Interacting with the Wireless Core and Wireless NICs: pyw.py}
321 If you can use iw, you can use pyw. The easist way to explain how to use pyw is
322 with an example. Imagine your wireless network, on ch 6, has been experiencing
323 difficulties lately and you want to capture some traffic to analyse it. Listing
324 \ref{lst:pentest} shows how to set up a wireless pentest environment. \\
325
326 \begin{lstlisting}[caption={Setting up a Wireless Pentest Environment},
327 label={lst:pentest},
328 language=Python]
329 1: import pyric # pyric error (and ecode EUNDEF)
330 2: from pyric import pyw # for iw functionality
331 3: from pyric.utils.channels import rf2ch # rf to channel conversion
332 4:
333 5: dev = 'wlan0'
334 6: dinfo = pyw.devinfo(dev)
335 7: card = dinfo['card']
336 8:
337 9: pyw.down(card)
338 10: pyw.macset(card,'00:03:93:57:54:46')
339 11:
340 12: pdev = 'pent0'
341 13: pcard = pyw.devadd(card, pdev, 'monitor')
342 14: for iface in pyw.ifaces(card):
343 15: if iface[0].dev != pcard.dev:
344 16: pyw.devdel(iface[0])
345 17: pyw.up(pcard)
346 18:
347 19: pyw.chset(pcard,6,None)
348 20:
349 21: # DO stuff here
350 22:
351 23: card = pyw.devadd(pcard,card.dev,dinfo['mode'])
352 24: pyw.devdel(pcard)
353 25: pyw.macset(card,dinfo['mac'])
354 26: pyw.up(card)
355 \end{lstlisting}
356
357 Listing \ref{lst:pentest} shows basic pyw functions and is the basic shell used in
358 another project, Wraith\cite{wraith}, to instantiate a wireless (802.11) sensor -
359 (for a full listing of all pyw functions see Appendix \ref{sec:pywapi}) - with
360 scanning capabilities. \\
361
362 Lines 1 and 2 should always be included as they import the pyric error and pyw
363 functions. Line 3 imports the rf2ch conversion function. \\
364
365 In lines 5 through 10, a Card is created from the device wlan0. The info dict is save
366 IOT to restore later. Next, the mac address of wlan0 is changed. Note, the device has
367 to be brought down first. \\
368
369 Starting on line 12, a device named 'pent0' is created in monitor mode. First, a new
370 Card, pcard is create in monitor mode. Then, all interfaces on the same phy are
371 deleted \footnote{we have found that it is better to delete all interfaces on the
372 same phy ensuring that external processes don't interfere with the new device}. The
373 new Card is brought up and set to channel 6 NOHT.\\
374
375 Restoring the device starts on line 23, where the virtual interface is deleted,
376 the previous interface is restored, the mac address is reset and the old Card is
377 brought up. \\
378
379 An extended version of Listing \ref{lst:pentest} can be found in the examples
380 directory.
381
382 \subsubsection{One-time vs Persistent Sockets}
383 The example in Listing \ref{lst:pentest} uses one-time sockets (netlink and
384 ioctl). When using iw, there are several things that occur prior to the actual
385 command or request being submitted. First, iw creates a netlink socket. Then,
386 iw will request the family id for nl80211. The relative time spent doing this
387 is neglible but, it is redundant and it may become noticeable in programs that
388 repeatedly use the Netlink service. Once comlete, iw closes the socket. In some
389 cases, the ifindex of the device is needed and iw will also initiate an ioctl
390 call to retrieve it. PyRIC eliminates these redundancies by using a global
391 variable in pyw that stores the family id after the first time it is requested
392 and by providing callers the option to use persistent sockets.
393 \begin{itemize}
394 \item \textbf{One-time Sockets} Similar to iw. The command, creates the netlink
395 socket (or ioctl socket), composes the message, sends the message and receives
396 the response, parses the results, closes the socket and returns the results to
397 the caller. At no time does the caller need to be aware of any underlying Netlink
398 processes or structures.
399 \item \textbf{Persistent Sockets} Communication and parsing only. The onus of
400 socket creation and deletion is on the caller which allows them to create one
401 (or more) socket(s). The pyw functions will only handle message construction,
402 message sending and receiving and message parsing.
403 \end{itemize}
404 The caller needs to be cognizant of whether the function requires a netlink or
405 ioctl socket. Passing the wrong type will result in an error. \\
406
407 NOTE: One must remember that there is an upper limit to the number of open netlink
408 sockets. It is advised to use one-time functions as much as possible and save the
409 use of persistent sockets for use in code that repeatedly makes use of netlink. \\
410
411 The latest version of pyw.py (v 0.1.*) implements this functionality through the
412 use of what I call templates\footnote{I use templates and stubs for the lack
413 of any better naming convention}, Listing \ref{lst:template} and stubs Listing
414 \ref{lst:stub}.
415
416 \begin{lstlisting}[caption={A Basic Netlink Function Template},
417 label={lst:template},
418 language=Python]
419 def fcttemplate(arg0,arg1,..,argn,nlsock=None):
420 # put parameter validation (if any) here
421 if nlsock is None: _nlstub_(fcttemplate,arg0,arg1,...,argn)
422
423 # command execution
424 ...
425 return results
426 \end{lstlisting}
427
428 The template function in Listing \ref{lst:template} checks if nlsock is instantiatd
429 \footnote{ioctl calls operate in the same manner}. If so, it proceeds to execution.
430 If there is no socket, the stub is executed which creates one. If something other
431 than a netlink socket is at argv[0], an error will be raised during execution. \\
432
433 \begin{lstlisting}[caption={Function \_nlstub\_},
434 label={lst:stub},
435 language=Python]
436 def _nlstub_(fct,*argv):
437 nlsock = None
438 try:
439 nlsock = nlsock = nl.nl_socket_alloc()
440 argv = list(argv) + nlsock=None
441 return fct(*argv)
442 except pyric.error:
443 raise # catch & release
444 finally:
445 if nlsock: nl.nl_socket_free(nlsock)
446 \end{lstlisting}
447
448 The stub function, Listing \ref{lst:stub} allocates a netlink socket, executes
449 the original (now with a netlink socket) and then destroys the netlink socket.\\
450
451 \begin{lstlisting}[caption={Using Persistent Sockets},
452 label={lst:persistent},
453 language=Python]
454 1: import pyric # pyric errors
455 2: from pyric import pyw # for iw functionality
456 3: from pyric.lib import libnl as nl # for netlink sockets
457 4:
458 5: nlsock = nl.nl_socket_alloc(timeout=1)
459 6: card = pyw.getcard('wlan0',nlsock)
460 7: print pyw.devmodes(card,nlsock)
461 8: nl.nl_socket_free(nlsock)
462 \end{lstlisting}
463
464 Listing \ref{lst:persistent}, shows the creation of a persistent netlink socket
465 that is used in the creation of a card and in retrieved the card's supported
466 modes. \\
467
468 Use Python's built in help features on pyw functions or see Appendex \ref{sec:pywapi}
469 to determine what type of socket is needed.
470
471 \subsection{Additional Tools}
472 In the utils directory, PyRIC includes channels.py, hardware.py, rfkill.py and
473 ouifetch.py. These provide a port of rfkill, channel/frequency enumeration and
474 device chipset, driver retrieval as well as some mac address functions. More
475 information can be found in the Appendices and in README.md.
476
477 \subsection{Interacting with the Kernel: libnl.py and libio.py}
478 The kernel interfaces, libnl.py and libio.py are located in the lib directory.
479 They handle socket creation/deletion, message creation/parsing and kernel
480 communication. Aside from creating and deleting persistent sockets, there is
481 little need to access their functions unless you plan on extending pyw
482 functionality. As such, a further discussion of libnl.py and libio.py can be
483 found in the next section.
484
485 \section{Extending PyRIC}\label{sec:extending}
486 You may find that pyw does not offer some of the functionality you need. Using
487 libnl.py and/or libnl.io, additional functionality can be added to your program.\\
488
489 It is helpful if the reader has a basic knowledge of netlinks. For a review, see
490 "Communicating between the kernel and user-space in Linux using Netlink Sockets"
491 \cite{spae}.
492
493 \subsection{Porting C}
494 All Python ports of C header files can be found in the net directory. C Enums
495 and \#defines are ported using constants. C structs are ported using three
496 Python structures and the Python struct package:
497 \begin{enumerate}
498 \item a format string for packing and unpacking the struct
499 \item a constant specifying the size of the struct in bytes
500 \item a function taking the attributes of the struct as arguments and returning
501 a packed string
502 \end{enumerate}
503 Listing \ref{lst:cstruct} shows the C definition of the nlmsghdr found in netlink.h.
504
505 \begin{lstlisting}[caption={C Struct nlmsghdr},
506 label={lst:cstruct},
507 language=C]
508 struct nlmsghdr {
509 __u32 nlmsg_len;
510 __u16 nlmsg_type;
511 __u16 nlmsg_flags;
512 __u32 nlmsg_seq;
513 __u32 nlmsg_pid;
514 };
515 \end{lstlisting}
516
517 And Listing \ref{lst:pstruct} shows the ported version in Python.
518
519 \begin{lstlisting}[caption={Corresponding Python Definition},
520 label={lst:pstruct},
521 language=Python]
522 nl_nlmsghdr = "IHHII"
523 NLMSGHDRLEN = struct.calcsize(nl_nlmsghdr)
524 def nlmsghdr(mlen,nltype,flags,seq,pid):
525 return struct.pack(nl_nlmsghdr,NLMSGHDRLEN+mlen,nltype,flags,seq,pid)
526 \end{lstlisting}
527
528 When using pyw, dealing with these structures is handled transparently by libnl.py
529 and libio.py. When extending or customizing pyw, a basic understanding of the
530 definitions in netlink\_h.py, genetlink\_h.py and if\_h.py.
531
532 \subsection{Input/Output Control (ioctl)}
533 PyRIC provides more than just iw-related functions, it also implements functions
534 from ifconfig and iwconfig. These command line tools still use ioctl (or the proc
535 directory). For example, interfaces() reads from '/proc/net/dev' to retrieve all
536 system interfaces and winterfaces() use ioctl to check if a device is wireless.
537 Input/Output control calls have only been used when there was no viable alternative
538 and, it should not be necessary to have to add any further ioctl commands. If you
539 find that you need an ioctl related command, search through if\_h.py for the
540 appropriate structure and add it's definitions to ifreq.
541
542 \subsection{Netlink and nl80211}
543 Documentation on Netlink, and nl80211 in particular, is so minimal as to be
544 neglible. The clusterfuck of code and lack of comments in the iw source tree
545 make it impossible to use as any sort of roadmap. Fortunately Thomas Graf's
546 site\cite{libnl} has excellent coverage of libnl, the Netlink library. Using
547 this as a reference, a simple Netlink parser was put together which later became
548 libnl.py. Using the command line tool strace and libnl.py, Netlink messages could
549 be dissected and analyzed.\\
550
551 Let us consider adding a virtual interface with the command:\\
552
553 \texttt{sudo iw phy0 interface add test0 type monitor}\\
554
555 First, we need to see what is going on under the covers. Using strace:\\
556
557 \texttt{strace -f -x -s 4096 iw phy0 interface add test0 type monitor}\\
558
559 from a terminal will give a you a lot of output, most irrelevant (to us). Scroll
560 through this until the netlink socket creation as highlighted in Figure
561 \ref{fig:nlsock}. You can see that a socket of type PF\_NETLINK is created and
562 the send/receive buffers are set to 32768.
563 \begin{center}
564 \begin{figure}[h]
565 \includegraphics{nlsock}
566 \caption{Netlink socket creation}
567 \label{fig:nlsock}
568 \end{figure}
569 \end{center}
570 What we want to analyze are the messages sent and received over the netlink
571 socket. In Figure \ref{fig:nlsock}, iw is requesting the family id for nl80211.
572 This id will be used in subsequent requests related to nl80211 as we will see
573 shortly. The return message gives the nl80211 family id as 26 and returns other
574 nl80211 attributes. This is handled by the private function \_familyid\_ in
575 pyw.py.
576
577 Figure \ref{fig:nlsend} shows the add interface message being sent to the kernel.
578 \begin{center}
579 \begin{figure}[h]
580 \includegraphics{nlsend}
581 \caption{Netlink sendmsg}
582 \label{fig:nlsend}
583 \end{figure}
584 \end{center}
585 We are interested in the byte sequence following msg\_iov(1). Copy this and paste
586 into in a python variable as in Listing \ref{lst:nlparse} and pass it to the
587 function nlmsg\_fromstream which parses the byte stream and returns the GENLMsg.\\
588
589 \begin{lstlisting}[caption={Parsing netlink messages},
590 label={lst:nlparse},
591 language=Python]
592 >>> from pyric.lib import libnl as nl
593 >>> sent = "\x30\x00\x00\x00\x1a...\x00\x00"
594 >>> msg = nl.nlmsg_fromstream(sent)
595 >>> msg
596 nlmsghdr(len=48,type=26,flags=5,seq=1463268720,pid=10982)
597 genlmsghdr(cmd=7)
598 attributes:
599 0: type=1,datatype=3
600 value=0
601 1: type=4,datatype=5
602 value=test0
603 2: type=5,datatype=3
604 value=6
605 \end{lstlisting}
606
607 The first thing to notice is nlmsghdr type = 26, which of course is nl80211 family
608 id. The rest of the nlmsghdr components len, flags, seq, and pid are handled by
609 libnl.py although you can supply your own flags if desired. At this time, you can
610 manually look up what values the cmd, type and datatype correspond to in
611 nl80211\_h.py and netlink\_h.py or you can use the tools provided in nlhelp.py.\\
612
613 \begin{lstlisting}[caption={Parsing netlink messages continued},
614 label={lst:nlparse2},
615 language=Python]
616 >>> from pyric.net.netlink_h import NLA_DATATYPES
617 >>> from pyric.docs import nlhelp
618 >>> nlhelp.cmdbynum(7)
619 u'@NL80211_CMD_NEW_INTERFACE'
620 >>>
621 >>> for attr in msg.attrs:
622 ... print nlhelp.attrbynum(attr[0]), NLA_DATATYPES[attr[2]], attr[1]
623 ...
624 @NL80211_ATTR_WIPHY u32 0
625 @NL80211_ATTR_IFNAME string test0
626 @NL80211_ATTR_IFTYPE u32 6
627 >>>
628 >>> from pyric.net.wireless.nl80211_h import NL80211_IFTYPES
629 >>> NL80211_IFTYPES[6]
630 'monitor'
631 \end{lstlisting}
632
633 In Listing \ref{lst:nlparse2} command number 7 corresponds to
634 NL80211\_CMD\_NEW\_INTERFACE and the attributes that need to be passed to the
635 kernel are NL80211\_ATTR\_WIPHY, NL80211\_ATTR\_IFNAME and NL80211\_ATTR\_IFTYPE.
636 The IFTYPE is also known as the mode i.e. 'monitor' which can be found in
637 nl80211\_h.py NL80211\_IFTYPES. We don't parse the return message from the kernel
638 but, it follows the same SOP. In this case, it returns the attributes of the new
639 virtual interface. \\
640
641 With this information, we can now code our function. Recall the fcttemplate as
642 defined in Listing \ref{lst:template} and fill in the command execution as shown
643 in Listing \ref{lst:coding}. \\
644
645 \begin{lstlisting}[caption={Coding the function},
646 label={lst:coding},
647 language=Python]
648 # construct the message
649 msg = nl.nlmsg_new(nltype=_familyid_(nlsock),
650 cmd=nl80211h.NL80211_CMD_NEW_INTERFACE,
651 flags=nlh.NLM_F_REQUEST | nlh.NLM_F_ACK)
652 nl.nla_put_u32(msg,card.phy,nl80211h.NL80211_ATTR_WIPHY)
653 nl.nla_put_string(msg,vdev,nl80211h.NL80211_ATTR_IFNAME)
654 nl.nla_put_u32(msg,IFTYPES.index(mode),nl80211h.NL80211_ATTR_IFTYPE)
655
656 # send, receive and parse return results, returning the new Card
657 nl.nl_sendmsg(nlsock,msg)
658 rmsg = nl.nl_recvmsg(nlsock) # success returns new device attributes
659 return Card(card.phy,vdev,nl.nla_find(rmsg,nl80211h.NL80211_ATTR_IFINDEX))
660 \end{lstlisting}
661
662 We construct a new GENLMsg passing the nl80211 family id, the command we got
663 earlier and flags specifying that this is a request and we want to get an ACK
664 back\footnote{libnl.py always forces an ACK and handles the underlying process
665 of receiving it}. Now, add each attribute to the message. Note the order: value,
666 then attribute. With the message constructed, send it to the kernel, get the
667 results, parse and return them.\\
668
669 Rather simple, in fact the hardest part is figuring out what to send to the kernel.
670 Everything else is handled behind the scenes by libnl.py.
671
672 \begin{appendices}
673 \section{API: pyw.py}\label{sec:pywapi}
674
675 \subsection{Constants}
676 \begin{itemize}
677 \item \textbf{\_FAM80211ID\_}: Global netlink family id of nl80211. Do not touch
678 \item \textbf{IFTYPES}: redefined (from nl80211\_h.py) interface modes
679 \item \textbf{MNTRFLAGS}: redefined (from nl80211\_h.py) monitor mode flags
680 \item \textbf{TXPOWERSETTINGS}: redefined (from nl80211\_h.py) power level settings
681 \end{itemize}
682
683 \subsection{Objects/Classes}
684 \textbf{Card} A wrapper around a tuple
685 \texttt{t = (physical index,device name,interface index)}
686 which exposes the following properties through '.':
687 \begin{itemize}
688 \item \textbf{phy}: physical index
689 \item \textbf{dev}: device name
690 \item \textbf{idx}: interface index (ifindex)
691 \end{itemize}
692 Because the underlying Netlink calls will sometimes require the physical index,
693 sometimes the device name, and sometimes the ifindex, pyw functions accept a Card,
694 object. This allows callers to use pyw functions without having to remember which
695 identifier the function requires. However, in some cases the function requires
696 a dev or accepts both. See the next section on functions.\\
697
698 While callers could create their own Cards, it is recommend to use one of the
699 following
700 \begin{itemize}
701 \item \textbf{pyw.getcard} returns a Card object from a given dev
702 \item \textbf{pyw.devinfo} returns the dict info where info['card'] is the Card
703 object. This function will take either a card or a dev
704 \item \textbf{pyw.devadd} returns a new Card object
705 \item \textbf{pyw.devadd} returns a new Card object
706 \item \textbf{pyw.ifaces} returns a list of tuples t = (Card,mode) sharing the
707 same phy as a given device to do so. It is also recommended to periodically
708 validate the Card. On some cheaper usb wireless nics, there are periodic
709 disconnects which results in a new phy and ifindex.
710 \end{itemize}
711
712 \subsection{Functions}
713 \begin{itemize}
714 \item interfaces(): (ifconfig), type: filesystem, returns list of all network
715 device names
716 \item isinterface(dev): (ifconfig <dev>) type: filesystem, checks that dev is a
717 device name
718 \item winterfaces(iosock=None): (iwconfig), type: ioctl, list wireless device
719 names
720 \item iswireless(dev,iosock=None): (iwconfig <dev>), type: ioctl, check dev is a
721 wireless interface
722 \item phylist(): (iw phy | grep wiphy) type: N/A, list phy indexes and phy names
723 present on system
724 \item regget(nlsock=None: (iw reg get), type: netlink, get regulatory domain
725 \item regset(rd,nlsock=None): (iw reg set <rd>), type: netlink, set regulatory domain
726 to rd
727 \item getcard(dev,nlsock=None) (N/A), type: hybrid netlink and ioctl: get a Card
728 object for dev
729 \item validcard(card,nlsock=None): (N/A), type: (hyrbrid netlink and ioctl), verify
730 card is still valid
731 \item macget(card,iosock=None): (ifconfig), type: ioctl, determine if card is up
732 or down
733 \item macset(card,mac,iosock=None): (ifconfig card.<dev> hw ether <mac>), type:
734 ioctl, set card's hw address to mac
735 \item isup(card,iosock=None): (ifconfig card.<dev>)
736 \item up(card,iosock=None) (ifconfig card.<dev> up), type: ioctl, bring card up
737 \item down(card,iosock=None): (ifconfig card.<dev> down), type: ioctl, bring card
738 down
739 \item isblocked(card): (rfkill list <rfkill\_idx>): type N/A returns tuple
740 (Soft Block State, Hard Block State)
741 \item block(card): (rfkill block <rfkill\_idx>) type: N/A, soft blocks card
742 \item unblock(card): (rfkill unblock <rfkill\_idx>) type: N/A, removes the soft
743 block on card
744 \item pwrsaveget(card,nlsock=None) (iw dev card.<dev> get power\_save) type: netlink
745 get card's power save state True = on, False = off
746 \item pwrsaveset(card,on,nlsock=None) (iw dev card.<dev> set power\_save <on>) type:
747 netlink, set card's power save state True = on, False = off
748 \item covclassget(card,nlsock=None) (iw phy card.<phy> get coverage <cc>) type:
749 netlink get card's coverage class
750 \item covclassset(card,cc,nlsock=None) (iw phy card.<phy> set coverage <cc>) type:
751 netlink set card's coverage class
752 \item retryshortget(card,nlsock=None) (iw phy card.<phy> info | grep 'retry short')
753 type:netlink get card's retry short limit
754 \item retryshortset(card,lim,nlsock=None) (iw phy card.<phy> set retry short <lim>)
755 type:netlink set card's retry short limit. NOTE: although 255 is specified as the
756 max limit for this and the long retry, kernel v4 will not allow it.
757 \item retrylongget(card,nlsock=None) (iw phy card.<phy> info | grep 'retry long')
758 type:netlink get card's retry long limit
759 \item retrylongset(card,lim,nlsock=None) (iw phy card.<phy> set retry long <lim>)
760 type:netlink set card's retry long limit
761 \item rtsthreshget(card,nlsock=None) (iw phy card.<phy> info | grep rts) type:
762 netlink set card's RTS threshold
763 \item rtsthreshset(card,thresh,nlsock=None) (iw phy card.<phy> set rts <thresh>) type:
764 netlink set card's RTS threshold
765 \item fragthreshget(card,nlsock=None) (iw phy card.<phy> info | grep frag) type:
766 netlink get card's fragmentation threshold
767 \item fragthreshset(card,thresh,nlsock=None) (iw phy card.<phy> set frag <thresh>) type:
768 netlink set card's fragmentation threshold
769 \item ifaddrget(card,iosock=None): (ifconfig card.<dev>), type: ioctl, get ip4 address,
770 netmask and broadcast address of card
771 \item ifaddrset(card,ipaddr,netmask,broadcast,iosock=None): (ifconfig card/<dev>
772 <ipaddr> netmask <netmask> broadcast <broadcast>), type: ioctl, set the interface
773 addresses of the card
774 \item inetset(card,ipaddr,iosock=None): (ifconfig card.<dev> <ipaddr>), type: ioctl,
775 set the card's ip4 address
776 \item maskset(card,netmask,iosock=None): (ifconfig card.<dev> netmask <netmask>),
777 type: ioctl, set the card's netmask
778 \item bcastset(card,broadcast,iosock=None): (ifconfig card.<dev> broadcast
779 <broadcast>), type: ioctl, set the card's broadcast address
780 \item devfreqs(card,nlsock=None): (iw phy card.phy info), type: netlink, get card's
781 supported frequencies
782 \item devchs(card,nlsock=None): (iw phy card.phy info), type: netlink, get card's
783 supported channels
784 \item devstds(card,nlsock=None): (iwconfig card.<dev> | grep IEEE), type: nlsock,
785 returns a list of card's 802.11 supported standards by letter designator
786 \item devmodes(card,nlsock=None): (iw phy card.phy info | grep interface), type:
787 netlink, get card's supported modes
788 \item devcmds(card,nlsock=None): (iw phy card.phy info | grep commands), type:
789 netlink, get card's supported commands
790 \item ifinfo(card,iosock=None): (ifconfig card.<dev>), type: ioctl, get hardware
791 related info for card
792 \item devinfo(card,nlsock=None): (iw dev card.<dev> info), type: netlink, get info
793 for dev
794 \item phyinfo(card,nlsock=None): (iw phy card.<phy> info), type: netlink, get info
795 for phy
796 \item ifaces(card,nlsock=None): (APX iw card.dev | grep phy\#), type: netlink, get all
797 cards (w/ modes) of interfaces sharing the same phy as card
798 \item txset(card,pwr,lvl,nlsock=None) (iw phy phy0 set txpower <lvl> <pwr>), type:
799 netlink,sets the tx power to pwr (in dBm) with level setting lvl
800 \item txget(card,iosock=None): (iwconfig card.<dev> | grep Tx-Power card), type:
801 ioctl, get card's transmission power
802 \item chget(card,nlsock=None): (iw dev <card.dev> info | grep channel), type:
803 netlink, get card's current channel
804 \item chset(card,ch,chw=None,nlsock=None): iw phy <card.phy> set channel <ch> <chw>),
805 type: netlink, set card's current channel to ch with width chw
806 \item freqget(card,nlsock=None): (iw dev <card.dev> info | grep channel), type:
807 netlink, get card's current frequency
808 \item freqset(card,rf,chw=None,nlsock=None): iw phy <card.phy> set freq <rf> <chw>),
809 type: netlink, set card's current frequency to rf with width chw
810 \item devmodes(card,iosock=None): (iw phy card.<phy>), type: netlink, get modes
811 supported by card
812 \item modeset(card,mode,flags=None,nlsock=None): (iw dev card.<dev> set type <mode>
813 [flags]), type: netlink, set card's mode to mode with flags (if mode is monitor)
814 \item modeget(card,nlsock=None): (iw dev card.<dev> info | grep mode), type: netlink,
815 get card's mode
816 \item devset(card,ndev,nlsock=None): (N/A) sets the dev (name) of card to ndev
817 \item phyadd(phy,vnic,mode,flags=None,nlsock=None): (iw phy <phy> interface add <vnic>
818 type <mode> flags <flags>)\footnote{There is a bug in some kernel v4.4.0-x
819 where the given dev name is ignored and a system chosen one is used instead. See
820 https://wraithwireless.wordpress.com. Whenever possible, use devadd to create
821 interfaces instead.}, type: netlink, creates a new virtual interface with dev vdev,
822 in mode and using flags. Note: flags are only supported when creating a monitor mode
823 \item devadd(card (or ifindex),vnic,mode,[flags],nlsock=None): (iw phy card.<dev>
824 interface add <vnic> type <mode> flags <flags>), type: netlink, creates a new virtual
825 interface with dev vdev, in mode and using flags. Note: flags are only supported
826 when creating a monitor mode. This function accepts either a Card object or a
827 ifindex.
828 \item devdel(card,nlsock=None): (iw card.<dev> del), type: netlink, deletes card
829 \begin{itemize}
830 \item isconnected(card,nlsock=None): (iw dev card.<dev> info | grep channel), type:
831 netlink, determines if card is connected
832 \item connect(card,ssid,bssid=None,rf=None,nlsock=None): (iw dev card.<dev> connect <ssid>
833 <rf> <bssid>) connects to AP SSID with BSSID
834 \item disconnect(card, nlsock=None): (iw dev card.<dev> disconnect), type: netlink,
835 disconnects card from AP
836 \item link(card, nlsock=None): (iw dev card.<dev> link), type: netlink, displays
837 link specific details, i.e. AP details that card is connected to
838 \item stainfo(card, mac, nlsock=None): (iw dev card.<dev> link) type: netlink, displays
839 tx, rx metrics of the AP that card is connected to
840 \item \_hex2mac\_(v): returns a ':' separated mac address from byte stream v
841 \item \_mac2hex\_(v): returns a hex string corresponding to mac address v
842 \item \_hex2ip4\_(v): returns a '.' separated ip4 address from byte stream v
843 \item \_validip4\_(addr): determines if addr is a valid ip4 address
844 \item \_validmac\_(addr): determines if addr is a valid mac address
845 \item \_issetf\_(flags,flag): determines if flag is set in flags
846 \item \_setf\_(flags,flag): set flag in flags to on
847 \item \_unsetf\_(flags,flag): set flag in flags to off
848 \item \_familyid\_(nlsock): returns and sets the Netlink family id for nl80211,
849 only called once per module import
850 \item \_ifindex\_(dev,iosock=None): returns dev's ifindex
851 \item \_flagsget\_(dev,iosock=None): get's the dev's interface flags
852 \item \_flagsset\_(dev,flags,iosock=None): set's the dev's interface flags
853 \item \_iftypes\_(i): returns the mode corresponding to i
854 \item \_bands\_(band): futher parses band attribute returns dict of bands
855 containting rf information and rate information
856 \item \_band\_rates\_(rs): extracts list of rates from the unpacked rates rs
857 \item \_band\_rfs\_(rfs): extracts list of RFs (and other data) from the unpacked
858 frequencies rfs
859 \item \_unparsed\_rfs\_(band): (legacy) returns a list of frequencies from the
860 unparsed byte string band
861 \item \_commands\_(command): converts the list of numeric commands to a list of
862 commands as strings
863 \item \_ciphers\_(cipher): returns a list of ciphers from the packed byte string
864 cipher
865 \item \_rateinfo\_(ri): returns parsed rate info from the packed byte string ri
866 \item \_iostub\_(fct,*argv): ioctl stub function, calls fct with parameter list
867 argv and an allocated ioctl socket
868 \item \_nlstub\_(fct,*argv): netlink stub function, calls fct with parameter list
869 argv and an allocated netlink socket
870 \end{itemize}
871 \end{itemize}
872
873 \section{API: channels.py}\label{sec:channels.api}
874 Channel, Frequency enumeration and conversions can be found in channels.py.
875
876 \subsection{Constants}
877 \begin{enumerate}
878 \item \textbf{CHTYPES}: imported channel types from nl80211\_h
879 \item \textbf{CHWIDTHS}: imported channel widths from nl80211\_h
880 \item \textbf{ISM\_24\_C2F}: Dict containing ISM channel (key) to frequency (value)
881 pairs
882 \item \textbf{ISM\_24\_F2C}: Dict containing ISM frequency (key) to channel (value)
883 pairs
884 \item \textbf{UNII\_5\_C2F}: Dict containing UNII 5Ghz channel (key) to frequency
885 (value) pairs
886 \item \textbf{UNII\_5\_F2C}: Dict containing UNII 5Ghz frequency (key) to channel
887 (value) pairs
888 \item \textbf{UNII\_4\_C2F}: Dict containing UNII upper 4Ghz channel (key) to
889 frequency (value) pairs
890 \item \textbf{UNII\_4\_F2C}: Dict containing UNII upper 4Ghz frequency (key) to
891 channel (value) pairs
892 \end{enumerate}
893
894 \subsection{Functions}
895 \begin{enumerate}
896 \item channels(): returns a list of all channels
897 \item freqs(): returns a list of all frequencies
898 \item ch2rf(c): convert channel c to frequency
899 \item rf2ch(f): convert frequency f to channel
900 \end{enumerate}
901
902 \section{API: hardware.py}\label{sec:hardwareapi}
903 Hardware related: driver, chipset, manufacturer and mac address utility functions
904 can be found in device.py.
905
906 \subsection{Constants}
907 \begin{enumerate}
908 \item \textbf{dpath}: path to system device details
909 \item \textbf{drvpath}: path to device drivers
910 \end{enumerate}
911
912 \subsection{Functions}
913 \begin{enumerate}
914 \item oui(mac): returns the oui portion of address <mac>
915 \item ulm(mac): returns the ulm portion of address <mac>
916 \item manufacturer(ouis,mac): returns the manufacturer name of <mac> given the
917 dict of <ouis>
918 \item randhw([ouis]): returns a random mac address. If the dict ouis is specified
919 will select a random oui from the dict otherwise will generate one
920 \item ifcard(dev): returns the device driver and chipset
921 \item ifdriver(dev): returns the device driver
922 \item ifchipset(driver): returns the chipset associated with driver
923 \end{enumerate}
924
925 \section{API: ouifetch.py}
926 The file ouifetch.py retrieves and saves a tab seperated file of oui to
927 manufacturer name for use by hardware.py functions. From a command line, type: \\
928
929 \subsection{Constants}
930 \begin{enumerate}
931 \item \textbf{OUIURL}: url of IEEE oui file
932 \item \textbf{OUIPATH}: path to default location PyRIC oui.txt file
933 \end{enumerate}
934
935 \subsection{Functions}
936 \begin{enumerate}
937 \item load([opath]): returns a dict of oui:manufacturer key->value pairs stored
938 in the text file at opath. If opath is not specified, uses the default
939 \item fetch([opath]): retrieves oui.txt from the IEEE website, parses the files
940 and stores the results in a PyRIC friendly format in opath. If opath is not
941 specified, uses the default. User must have root permissions in order to write
942 to default opath
943 \end{enumerate}
944
945 \section{API: rfkill.py}\label{sec:rfkillapi}
946 A port of the command line tool rfkill, rfkill.py writes and reads rfkill\_event
947 structures to /dev/rfkill using fcntl providing functionality to block and unblock
948 devices.
949
950 \subsection{Constants}
951 \begin{enumerate}
952 \item \textbf{RFKILL\_STATE}: list of boolean values corresponding to blocked,
953 unblocked
954 \end{enumerate}
955
956 \subsection{Functions}
957 \begin{enumerate}
958 \item rfkill\_list(): corresponds to rkill list, returns a dict of dicts name ->
959 \{idx, type, soft, hard\}. If type is 'wireless', then name will be of the form
960 phy<n> such that n is the physical index of the wireless card
961 \item rfkill\_block(idx): soft blocks the device at rfkill index idx
962 \item rfkill\_blockby(rtype): soft blocks all devices of type rtype
963 \item rfkill\_unblock(idx): turns off the soft block at rfkill index idx
964 \item rfkill\_unblockby(rtype): turns off the soft blocks of all devices of type
965 rtype
966 \item soft\_blocked{idx}: determines soft block state of device at rfkill index idx
967 \item hard\_blocked{idx}: determines hard block state of device at rfkill index idx
968 \item getidx(phy): returns the rfkill index of the device with physical index phy
969 \item getname(idx): returns the name of the device at rfkill index idx
970 \item gettype(idx): returns the type of the device at rfkill index idx
971 \end{enumerate}
972
973 \section{API: libnl.py}\label{sec:libnlapi}
974 Providing libnl similar functionality, libnl.py provides the interface between
975 pyw and the underlying nl80211 core. It relates similarily to libnl by providing
976 functions handling netlink messages and sockets and where possible uses similarly
977 named functions as those libnl to ease any transitions from C to PyRIC. However,
978 several liberties have been taken as libnl.py handles only nl80211 generic netlink
979 messages.
980
981 \subsection{Constants}
982 \begin{itemize}
983 \item \textbf{BUFSZ} default rx and tx buffer size
984 \end{itemize}
985
986 \subsection{Classes/Objects}
987 The two classes in libnl.py, NLSocket and GENLMsg, discussed in the following
988 sections subclass Python's builtin dict. This has been done IOT to take advantage
989 of dict's already existing functions and primarily their mutability and Python's
990 'pass by name' i.e. modifications in a function will be reflected in the caller.
991 This makes the classes very similar to the use C pointers to structs in libnl.
992
993 \subsubsection{NLSocket}
994 NLSocket is a wrapper around a netlink socket which exposes the following
995 properties through '.':
996 \begin{itemize}
997 \item \textbf{sock}: the actual socket
998 \item \textbf{fd}: the socket's file descriptor (deprecated)
999 \item \textbf{tx}: size of the send buffer
1000 \item \textbf{rx}: size of the receive buffer
1001 \item \textbf{pid}: port id
1002 \item \textbf{grpm}: group mask
1003 \item \textbf{seq}: sequence number
1004 \item \textbf{timeout}: socket timeout
1005 \end{itemize}
1006 and has the following methods:
1007 \begin{itemize}
1008 \item incr(): increment sequence number
1009 \item send(pkt): sends pkt returning bytes sent
1010 \item recv(): returns received message (will block unless timeout is set)
1011 \item close(): close the socket
1012 \end{itemize}
1013
1014 NLSockets are created with nl\_socket\_alloc and must be freed with nl\_socket\_free.
1015 See Section \ref{sec:libnlfct}.
1016
1017 \subsubsection{GENLMsg}
1018 GENLMsg is a wrapper around a dict with the following key->value pairs:
1019 \begin{itemize}
1020 \item \textbf{len}: total message length including the header
1021 \item \textbf{nltype}: netlink type
1022 \item \textbf{flags}: message flags
1023 \item \textbf{seq}: seq. \#
1024 \item \textbf{pid}: port id
1025 \item \textbf{cmd}: generic netlink command
1026 \item \textbf{attrs}: list of message attributes. Each attribute is a tuple t =
1027 (attribute,value,datatype) where:
1028 \begin{itemize}
1029 \item \textbf{attribute}: netlink attribute type i.e. CTRL\_ATTR\_FAMILY\_ID
1030 \item \textbf{value}: the unpacked attribute value
1031 \item \textbf{datatype}: datatype of the attribute as defined in nelink\_h i.e.
1032 NLA\_U8
1033 \end{itemize}
1034 \end{itemize}
1035 NOTE: as discussed below, on sending, the seq. \# and port id are overridden with
1036 values of the netlink socket.\\
1037
1038 GENLMsg exposes the following properties:
1039 \begin{itemize}
1040 \item \textbf{len}: length of the message (get only)
1041 \item \textbf{vers}: returns 1 (default version) (get only)
1042 \item \textbf{nltype}: message content i.e. generic or nl80211 (get or set)
1043 \item \textbf{flags}: message flags (get or set)
1044 \item \textbf{seq}: current sequence \# (get or set)
1045 \item \textbf{pid}: port id (get or set)
1046 \item \textbf{cmd}: netlink command (get or set)
1047 \item \textbf{attrs}: attribute list (get only)
1048 \item \textbf{numattrs}: number of attributes (get only)
1049 \end{itemize}
1050
1051 GENLMsg has the following methods:
1052 \begin{itemize}
1053 \item \_\_repr\_\_(): returns a string representation useful for debugging
1054 \item tostream(): returns a packed netlink message
1055
1056 There are two methods of creating a GENLMsg. Create a new message (to send) with
1057 nlmsg\_new and create a message from a received packet with nlmsg\_fromstream.
1058 These are discussed below.
1059
1060 \subsection{Functions}\label{sec:libnlfct}
1061 \begin{itemize}
1062 \item \textbf{Netlink Socket Related}
1063 \begin{itemize}
1064 \item nl\_socket\_alloc(pid,grps,seq,rx,tx,timeout): creates a netlink socket
1065 with port id = pid, group mask = grps, initial seq. \# = seq, send and receive
1066 buffer size = tx and rx respectively and blocking timeout = timeout
1067 \item nl\_socket\_free(sock): closes the socket
1068 \item nl\_socket\_pid(sock): (deprecated for NLSocket.pid) returns the port id
1069 \item nl\_socket\_grpmask(sock): (deprecated for NLSocket.grpmask) returns the
1070 group mask
1071 \item nl\_sendmsg(sock,msg,override=False): sends the netlink msg over socket.
1072 NOTE: NLSockets will automatically set the port id and seq. \# regardless of
1073 their value in the message. If override is True, the message's pid and seq. \#
1074 will be used instead.
1075 \item nl\_recvmsg(sock): returns a GENLMsg or blocks unless the socket's timeout
1076 is set. Should only be called once per every nl\_sendmsg.
1077 \end{itemize}
1078 \item \textbf{Netlink Message Related}
1079 \begin{itemize}
1080 \item nlmsg\_new(nltype=None,cmd=None,pid=None,flags=None,attrs=None): creates a
1081 new GENLMsg with zero or more attributes defined.
1082 \item nlmsg\_fromstream(stream): parses the message in stream returning the
1083 corresponding GENLMsg
1084 \item nla\_parse(msg,l,mtype,stream,idx): parses the attributes in stream appending
1085 them to the attribute list of message where msg = the GENLMsg, l = the total
1086 length of the message, mtype = the message content (i.e. netlink type) stream is
1087 the original byte stream and idx is the index of the start of the attribute list
1088 \item nla\_parse\_nested(nested): returns the list of packed nested attributes
1089 extracted from the stream nested. Callers must unpack and parse the returned
1090 attributes themselves
1091 \item nla\_put(msg,v,a,t): appends the attribute a, with value v and datatype t
1092 to the msg's attribute list
1093 \item nla\_put\_<DATATYPE>(msg,v,a): eight specialized functions that append
1094 attribute a with the value v and type <DATATYPE> to msg's attribute list
1095 \item nla\_putat(msg,i,v,a,d): puts attribute a, with value v and datatype d at
1096 index i in msg's attribute list.
1097 \item nla\_pop(msg,i): removes the attribute tuple at index i, returning the popped
1098 tuple
1099 \item nla\_find(msg,a,value=True): returns the first attribute a in msg's attribute
1100 list. If value returns only the value otherwise returns the attribute tuple
1101 \item nla\_get(msg,i,value=True): returns the attribute at index i. If value returns
1102 only the value otherwise returns the attribute tuple
1103 \item \_nla\_strip(v): (private) strips padding bytes from the end of v
1104 \item \_attrpack(a,v,d): (private) packs the attribute tuple
1105 \end{itemize}
1106 \item \_maxbufsz\_(): (private) returns the maximum allowable socket buffer size
1107 \end{itemize}
1108 \end{itemize}
1109
1110 \section{API: libio.py}\label{sec:libioapi}
1111 A very basic interface to ioctl, libio provides socket creation, deletion and
1112 transfer.
1113
1114 \subsection{Functions}
1115 \begin{enumerate}
1116 \item io\_socket\_alloc(): returns an ioctl socket
1117 \item io\_socket\_free(iosock): closes the ioctl socket iosock
1118 \item io\_transfer\_(iosock,flag,ifreq): sends the ifreq structure with sockios
1119 control call flag to the kernel and returns the received ifreq structure
1120 \end{enumerate}
1121
1122 \section{Copyright and License}\label{sec:copy}
1123 PYRIC: Python Radio Interface Controller v0.1.6.4\\
1124
1125 Copyright (C) 2016 Dale V. Patterson ([email protected])\\
1126
1127 This program is free software: you can redistribute it and/or modify it under
1128 the terms of the GNU General Public License\cite{gplv3} as published by the Free
1129 Software Foundation, either version 3 of the License, or (at your option) any
1130 later version.\\
1131
1132 Redistribution and use in source and binary forms, with or without modifications,
1133 are permitted provided that the following conditions are met:
1134 \begin{itemize}
1135 \item Redistributions of source code must retain the above copyright notice, this
1136 list of conditions and the following disclaimer.
1137 \item Redistributions in binary form must reproduce the above copyright notice,
1138 this list of conditions and the following disclaimer in the documentation and/or
1139 other materials provided with the distribution.
1140 \item Neither the name of the orginal author Dale V. Patterson nor the names of
1141 any contributors may be used to endorse or promote products derived from this
1142 software without specific prior written permission.
1143 \end{itemize}
1144
1145 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS "AS IS" AND
1146 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
1147 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
1148 IN NO EVENT SHALL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
1149 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
1150 OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
1151 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
1152 STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
1153 OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\\
1154
1155 PyRIC is free software but use, duplication or disclosure by the United States
1156 Government is subject to the restrictions set forth in DFARS 252.227-7014.\\
1157
1158 Use of this software is governed by all applicable federal, state and local
1159 laws of the United States and subject to the laws of the country where you reside.
1160 The copyright owner and contributors will be not be held liable for use of this
1161 software in furtherance of or with intent to commit any fraudulent or other illegal
1162 activities, or otherwise in violation of any applicable law, regulation or legal
1163 agreement.\\
1164
1165 See http://www.gnu.org/licenses/licenses.html for a copy of the GNU General Public
1166 License.
1167 \end{appendices}
1168
1169 \bibliographystyle{acm}
1170 \bibliography{PyRIC}
1171 %\addcontentsline{toc}{chapter}{Bibliography}
1172
1173 \end{document}
docs/logo.png less more
Binary diff not shown
docs/nlsend.png less more
Binary diff not shown
docs/nlsock.png less more
Binary diff not shown
0 # pip installation and distribution to install type sudo pip install PyRIC
0 [bdist_wheel]
1 universal = 1
12
2 [bdist_wheel]
3 universal=1
3 [egg_info]
4 tag_build =
5 tag_date = 0
6
+0
-474
tests/pyw.unittest.py less more
0 #!/usr/bin/env python
1 """ pyw.unittest.py: unittest
2
3 Define unittest functions for pyw
4
5 Assumptions:
6 o user has root privileges
7 o user has set up global variables to system
8 o private functions are tested via methods
9 o persistent sockets are tested via one-time methods that is, one-time socket
10 calls result in netlink socket creation, usage and deletion
11
12 usage:
13 sudo python pyw.unittest.py -v
14
15 Results as of 24-July-16
16
17 sudo python pyw.unittest.py
18 Testing PyRIC v0.1.5 pyw v0.1.8 on Python 2.7.12
19 ...................................................................................
20 ----------------------------------------------------------------------
21 Ran 83 tests in 5.919s
22
23 OK
24
25 NOTE:
26 1) functions disconnect and link require a connection, they are tested/confirmed
27 manually
28 2) function devadd (and subsequently devset) are commented out. There is a
29 peculiar behavior in netlink/nl80211 (appearing in kernel 4.4.0-x) where
30 regardless of the name passed to create a new device as in
31 iw phy <phy> interface add <new dev> type <new mode>
32 pyw.devadd(<card>, <new name>, <new mode>)
33 the kernel or driver or whoever will instead assign a predicatable name
34 of the form:
35 wlx00c0ca59afa7
36 devadd has been fixed but this is currently not reflected in the below unittests
37 it has been manually tested and confirmed
38 """
39 from __future__ import print_function # python 2to3 compability
40
41 #__name__ = 'pyw.unittest'
42 __license__ = 'GPLv3'
43 __version__ = '0.0.3'
44 __date__ = 'July 2016'
45 __author__ = 'Dale Patterson'
46 __maintainer__ = 'Dale Patterson'
47 __email__ = '[email protected]'
48 __status__ = 'Production'
49
50 import unittest
51 import time
52 import pyric
53 from pyric import error
54 import pyric.pyw as pyw
55 import pyric.utils.channels as channels
56 import pyric.net.wireless.wlan as wlan
57 import sys
58
59 # modify below to fit your system
60 pri = {'dev':'alfa0',
61 'mac':'00:c0:ca:59:af:a6',
62 'ifindex':18,
63 'phy':7,
64 'driver':'rt2800usb',
65 'chipset':'Ralink RT2870/3070',
66 'mode':'managed',
67 'tx':20,
68 'freqs':[2412,2417,2422,2427,2432,2437,2442,2447,2452,2457,2462,2467,2472,2484],
69 #'freqs':[2412,2417,2422,2427,2432,2437,2442,2447,2452,2457,2462,2467,2472,
70 # 5180,5200,5220,5240,5260,5280,5300,5320, 5500,5520,5540,5560,
71 # 5580,5600,5620,5640,5660,5680,5700,5745,5765,5785,5805, 5825],
72 'stds':['b','g','n'],
73 'modes':['ibss', 'managed', 'AP', 'AP VLAN', 'wds','monitor', 'mesh'],
74 'ip':'10.0.0.2',
75 'bcast':'10.0.0.255',
76 'mask':'255.255.255.0'}
77 newhw = '00:c0:ca:60:b0:a7'
78 newip = '10.0.0.3'
79 nics = ['eth0','lo','wlan0','alfa0']
80 enics = ['eth0','lo']
81 wnics = ['wlan0','alfa0']
82 inics = ['foo0','bar0']
83 regdom = '00'
84 newregdom = 'BO'
85
86 # test functions interfaces and isinterface
87 class InterfaceTestCase(unittest.TestCase):
88 def test_enuminterfaces(self):
89 for nic in nics: self.assertTrue(nic in pyw.interfaces())
90 def test_isinterface(self):
91 for nic in pyw.interfaces(): self.assertTrue(pyw.isinterface(nic))
92 def test_not_isinterface(self):
93 for inic in inics: self.assertFalse(pyw.isinterface(inic))
94 def test_ininterfaces(self):
95 for nic in nics: self.assertIn(nic,pyw.interfaces())
96
97 # test functions winterfaces and iswireless
98 class WInterfaceTestCase(unittest.TestCase):
99 def test_enumwinterfaces(self):
100 for wnic in wnics: self.assertTrue(wnic in pyw.winterfaces())
101 def test_iswinterface(self):
102 for wnic in pyw.winterfaces(): self.assertTrue(pyw.iswireless(wnic))
103 def test_not_iswinterface(self):
104 for nic in inics + enics: self.assertFalse(pyw.iswireless(nic))
105 def test_inwinterfaces(self):
106 for wnic in pyw.winterfaces(): self.assertIn(wnic,pyw.winterfaces())
107
108 # test regget, regset
109 class RegDomTestCase(unittest.TestCase):
110 def test_regget(self): self.assertEqual(regdom,pyw.regget())
111 def test_regset(self):
112 self.assertEqual(None,pyw.regset(newregdom))
113 time.sleep(0.25) # give sleep time
114 self.assertEqual(newregdom,pyw.regget())
115 self.assertEqual(None,pyw.regset(regdom))
116 time.sleep(0.25) # give sleep time
117 self.assertEqual(regdom, pyw.regget())
118
119 # test getcard,validcard
120 class GetCardTestCase(unittest.TestCase):
121 def test_getcard(self):
122 for wnic in wnics: self.assertIsNotNone(pyw.getcard(wnic))
123 def test_notacard(self):
124 for enic in enics: self.assertRaises(error,pyw.getcard,enic)
125 def test_validcard(self):
126 for wnic in wnics: self.assertTrue(pyw.validcard(pyw.getcard(wnic)))
127
128 # super class for test cases requiring a Card object
129 class CardTestCase(unittest.TestCase):
130 def setUp(self): self.card = pyw.getcard(pri['dev'])
131 def tearDown(self): pass
132
133
134 # test macget
135 class MacGetTestCase(CardTestCase):
136 def test_macget(self):
137 self.assertEquals(pri['mac'],pyw.macget(self.card))
138 def test_invalidcardarg(self):
139 self.assertRaises(error,pyw.macget,'bad0')
140
141 # test macset
142 class MacSetTestCase(CardTestCase):
143 def setUp(self):
144 CardTestCase.setUp(self)
145 pyw.down(self.card)
146 def tearDown(self):
147 pyw.up(self.card)
148 def test_macset(self):
149 self.assertEqual(newhw,pyw.macset(self.card,newhw))
150 self.assertEqual(pri['mac'],pyw.macset(self.card,pri['mac']))
151 def test_invalidcardarg(self):
152 self.assertRaises(error,pyw.macset,'bad0',newhw)
153 def test_invalidmacarg(self):
154 self.assertRaises(error,pyw.macset,self.card,'00:0A')
155
156 # test inetget/inetset
157 # testing both together as the test card is never associated thus
158 # never has an ip etc
159 # NOTE: through inetset, we get the side-effect of testing ip4set, netmaskset,
160 # broadcastset
161 class InetGetSetTestCase(CardTestCase):
162 def test_inetgetset(self):
163 self.assertEquals(None,pyw.ifaddrset(self.card,pri['ip'],pri['mask'],pri['bcast']))
164 self.assertEqual(pri['ip'],pyw.ifaddrget(self.card)[0])
165 def test_invalidcardarg(self):
166 self.assertRaises(error,pyw.ifaddrget,'bad0')
167 self.assertRaises(error,pyw.ifaddrset,'bad0',pri['ip'],pri['mask'],pri['bcast'])
168 def test_invalidiparg(self):
169 self.assertRaises(error,pyw.ifaddrset,self.card,'192.168',pri['mask'],pri['bcast'])
170 def test_invalidmaskarg(self):
171 self.assertRaises(error,pyw.ifaddrset,self.card,pri['ip'],'255.255',pri['bcast'])
172 def test_invalidbcastarg(self):
173 self.assertRaises(error,pyw.ifaddrset,self.card,pri['ip'],pri['mask'],'192.168')
174
175 # isup, test only card check
176 class IsUpTestCase(CardTestCase):
177 def test_invalidcardarg(self): self.assertRaises(error,pyw.isup,'bad0')
178
179 # test up/isup
180 class UpTestCase(CardTestCase):
181 def test_up(self):
182 self.assertEquals(None,pyw.up(self.card))
183 self.assertTrue(pyw.isup(self.card))
184 def test_invalidcardarg(self): self.assertRaises(error,pyw.up,'bad0')
185
186 # test down
187 class DownTestCase(CardTestCase):
188 def test_down(self):
189 self.assertEqual(None,pyw.down(self.card))
190 self.assertFalse(pyw.isup(self.card))
191 def test_invalidcardarg(self): self.assertRaises(error,pyw.down,'bad0')
192
193 # isblocked, test only valid card arg see below
194 class IsBlockedTestCase(unittest.TestCase):
195 def test_invalidcardarg(self): self.assertRaises(error,pyw.isup,'bad0')
196
197 # test block/isblocked
198 class BlockTestCase(CardTestCase):
199 def test_block(self):
200 self.assertEquals(None,pyw.block(self.card))
201 self.assertTrue(pyw.isblocked(self.card))
202 self.assertEquals(None,pyw.unblock(self.card))
203 def test_invalidcardarg(self): self.assertRaises(error,pyw.block,'bad0')
204
205 # test block/isblocked
206 class UnblockTestCase(CardTestCase):
207 def test_unblock(self):
208 self.assertEquals(None,pyw.unblock(self.card))
209 self.assertFalse(pyw.isblocked(self.card)[0])
210 def test_invalidcardarg(self): self.assertRaises(error,pyw.block,'bad0')
211
212 # test get/set power_save
213 class GetSetPwrSave(CardTestCase):
214 def test_getsetpwrsave(self):
215 pyw.pwrsaveset(self.card,True)
216 self.assertTrue(pyw.pwrsaveget(self.card))
217 pyw.pwrsaveset(self.card, False)
218 self.assertFalse(pyw.pwrsaveget(self.card))
219 pyw.pwrsaveset(self.card,True)
220 def testinvalidcardarg(self):
221 self.assertRaises(error,pyw.pwrsaveget,'bad0')
222 self.assertRaises(error,pyw.pwrsaveset,'bad0',True)
223 def testinvalidonval(self):
224 self.assertRaises(error,pyw.pwrsaveset,self.card,'b')
225
226 # test covclass
227 # NOTE: cannot currently test set as my cards do not support it
228 # NOTE: covclassget uses phyinfo - if that works covclassget works
229
230 # test get/set retryshort
231 class RetryShortTestCase(CardTestCase):
232 def test_retryshort(self):
233 rs = pyw.retryshortget(self.card)
234 self.assertEqual(None,pyw.retryshortset(self.card,5))
235 self.assertEqual(5,pyw.retryshortget(self.card))
236 self.assertEqual(None,pyw.retryshortset(self.card,rs))
237 self.assertEqual(rs,pyw.retryshortget(self.card))
238 def test_invalidcardarg(self):
239 self.assertRaises(error,pyw.retryshortget,'bad0')
240 self.assertRaises(error,pyw.retryshortset,'bad0',0)
241 def test_invalidlim(self):
242 self.assertRaises(error,pyw.retryshortset,self.card,wlan.RETRY_MIN-1)
243 self.assertRaises(error,pyw.retryshortset,self.card,wlan.RETRY_MAX+1)
244
245 # test get/set retrylong
246 class RetryLongTestCase(CardTestCase):
247 def test_retrylong(self):
248 rs = pyw.retrylongget(self.card)
249 self.assertEqual(None,pyw.retrylongset(self.card,5))
250 self.assertEqual(5,pyw.retrylongget(self.card))
251 self.assertEqual(None,pyw.retrylongset(self.card,rs))
252 self.assertEqual(rs,pyw.retrylongget(self.card))
253 def test_invalidcardarg(self):
254 self.assertRaises(error,pyw.retrylongget,'bad0')
255 self.assertRaises(error,pyw.retrylongset,'bad0',0)
256 def test_invalidlim(self):
257 self.assertRaises(error,pyw.retrylongset,self.card,wlan.RETRY_MIN-1)
258 self.assertRaises(error,pyw.retrylongset,self.card,wlan.RETRY_MAX+1)
259
260 # test get/set RTS thresh
261 class RTSThreshTestCase(CardTestCase):
262 def test_rtsthresh(self):
263 rt = pyw.rtsthreshget(self.card)
264 self.assertEqual(None,pyw.rtsthreshset(self.card,5))
265 self.assertEqual(5,pyw.rtsthreshget(self.card))
266 self.assertEqual(None,pyw.rtsthreshset(self.card,'off'))
267 self.assertEqual('off',pyw.rtsthreshget(self.card))
268 self.assertEqual(None,pyw.rtsthreshset(self.card,rt))
269 def test_invalidcardarg(self):
270 self.assertRaises(error,pyw.rtsthreshget,'bad0')
271 self.assertRaises(error,pyw.rtsthreshset,'bad0',5)
272 def test_invalidthresh(self):
273 self.assertRaises(error,pyw.rtsthreshset,self.card,wlan.RTS_THRESH_MIN-1)
274 self.assertRaises(error,pyw.rtsthreshset,self.card,wlan.RTS_THRESH_MAX+1)
275 self.assertRaises(error, pyw.rtsthreshset,self.card,'on')
276
277 # test get/set RTS thresh
278 class FragThreshTestCase(CardTestCase):
279 def test_fragthresh(self):
280 ft = pyw.fragthreshget(self.card)
281 self.assertEqual(None,pyw.fragthreshset(self.card,800))
282 self.assertEqual(800,pyw.fragthreshget(self.card))
283 self.assertEqual(None,pyw.fragthreshset(self.card,'off'))
284 self.assertEqual('off',pyw.fragthreshget(self.card))
285 self.assertEqual(None,pyw.fragthreshset(self.card,ft))
286 def test_invalidcardarg(self):
287 self.assertRaises(error,pyw.fragthreshget,'bad0')
288 self.assertRaises(error,pyw.fragthreshset,'bad0',800)
289 def test_invalidthresh(self):
290 self.assertRaises(error,pyw.fragthreshset,self.card,wlan.FRAG_THRESH_MIN-1)
291 self.assertRaises(error,pyw.fragthreshset,self.card,wlan.FRAG_THRESH_MAX+1)
292 self.assertRaises(error,pyw.fragthreshset,self.card,'on')
293
294 # test get freqs
295 class DevFreqsTestCase(CardTestCase):
296 def test_devfreqs(self):
297 self.assertListEqual(pri['freqs'],pyw.devfreqs(self.card))
298 def test_invalidcardarg(self):
299 self.assertRaises(error,pyw.devfreqs,'bad0')
300
301 # test get chs
302 class DevCHsTestCase(CardTestCase):
303 def test_devchs(self):
304 [channels.rf2ch(rf) for rf in pri['freqs']]
305 self.assertListEqual([channels.rf2ch(rf) for rf in pri['freqs']],
306 pyw.devchs(self.card))
307 def test_invalidcardarg(self):
308 self.assertRaises(error,pyw.devchs,'bad0')
309
310 # test get stds
311 class DevSTDsTestCase(CardTestCase):
312 def test_devchs(self):
313 self.assertListEqual(pri['stds'],pyw.devstds(self.card))
314 def test_invalidcardarg(self):
315 self.assertRaises(error,pyw.devstds,'bad0')
316
317 # test get modes
318 class DevModesTestCase(CardTestCase):
319 def test_devmodes(self):
320 self.assertListEqual(pri['modes'],pyw.devmodes(self.card))
321 def test_invalidcardarg(self):
322 self.assertRaises(error,pyw.devmodes,'bad0')
323
324 # test get cmds
325 class DevCMDsTestCase(CardTestCase):
326 def test_devcmds(self):
327 self.assertIsInstance(pyw.devmodes(self.card),list)
328 def test_invalidcardarg(self):
329 self.assertRaises(error,pyw.devmodes,'bad0')
330
331 # test devinfo - the key-value pairs of devinfo are tested via others
332 class DevInfoTestCase(CardTestCase):
333 def test_devinfobycard(self):
334 self.assertIsInstance(pyw.devinfo(self.card),dict)
335 def test_devinfobydev(self):
336 self.assertIsInstance(pyw.devinfo(pri['dev']),dict)
337 def test_invalidcardarg(self):
338 self.assertRaises(error,pyw.devinfo,'bad0')
339
340 # test phyinfo
341 class PhyInfoTestCase(CardTestCase):
342 def test_phyinfo(self):
343 self.assertIsInstance(pyw.phyinfo(self.card),dict)
344 def test_invalidcardarg(self):
345 self.assertRaises(error,pyw.phyinfo,'bad0')
346
347 # test txset
348 # currently txset is not supported by my cards
349
350 # test txget
351 class TXGetTestCase(CardTestCase):
352 def test_txget(self):
353 self.assertEquals(pri['tx'],pyw.txget(self.card))
354 def test_invalidcardarg(self):
355 self.assertRaises(error,pyw.txget,'bad0')
356
357 # test chget/chset
358 # since we are using a non-associated card, we will get None for chget
359 # testing chset simulatenously allows us to test chset then chget
360 # NOTE: we don't test for specific ch in chget, just in the infitesimal chance
361 # that somehow the ch was reset etc
362 class CHGetSetTestCase(CardTestCase):
363 def test_chsetget(self):
364 pyw.down(self.card)
365 pyw.modeset(self.card,'monitor')
366 pyw.up(self.card)
367 self.assertEqual(None,pyw.chset(self.card,1))
368 self.assertIsInstance(pyw.chget(self.card),int)
369 pyw.down(self.card)
370 pyw.modeset(self.card,'managed')
371 pyw.up(self.card)
372 def test_invalidcardarg(self):
373 self.assertRaises(error,pyw.chset,pri['dev'],1)
374 self.assertRaises(error,pyw.chget,'bad0')
375 def test_invalidcharg(self):
376 self.assertRaises(error,pyw.chset,self.card,0,None)
377 def test_invalidchwarg(self):
378 self.assertRaises(error,pyw.chget,self.card,1,'HT30+')
379
380 # test freqset
381 # because freqset was already tested in chgetset, we only test invalid args
382 class FreqSetTestCase(CardTestCase):
383 def test_invalidrfarg(self):
384 # we test both an invalid RF and an RF the card does not support
385 self.assertRaises(error,pyw.freqset,self.card,2410)
386 self.assertRaises(error,pyw.freqset,self.card,4960)
387
388 # test modeget
389 class ModeGetTestCase(CardTestCase):
390 def test_modeget(self):
391 self.assertEquals('managed',pyw.modeget(self.card))
392 def test_invalidcardarg(self):
393 self.assertRaises(error,pyw.modeget,'bad0')
394
395 # test modeset
396 class ModeSetTestCase(CardTestCase):
397 def test_modeset(self):
398 pyw.down(self.card)
399 self.assertEquals(None,pyw.modeset(self.card,'monitor'))
400 self.assertEquals(None,pyw.modeset(self.card,'managed'))
401 pyw.up(self.card)
402 def test_invalidcardarg(self):
403 self.assertRaises(error,pyw.modeset,'bad0','monitor')
404 def test_invalidmodearg(self):
405 self.assertRaises(error,pyw.modeset,self.card,'foobar')
406 def test_invalidmonitorflagarg(self):
407 self.assertRaises(error,pyw.modeset,self.card,'monitor','bad')
408 self.assertRaises(error,pyw.modeset,self.card,'managed','fcsfail')
409
410 # test ifaces
411 class IfacesTestCase(CardTestCase):
412 def test_ifaces(self):
413 self.assertIsInstance(pyw.ifaces(self.card),list)
414 def test_invalidcardarg(self):
415 self.assertRaises(error,pyw.ifaces,'bad0')
416
417 # test devadd/devdel
418 """
419 class DevAddDelTestCase(CardTestCase):
420 def test_devadddel(self):
421 card = pyw.devadd(self.card,'test0','monitor')
422 self.assertTrue(card.dev in pyw.winterfaces())
423 pyw.devdel(card)
424 self.assertFalse(card.dev in pyw.winterfaces())
425 def test_invalidcardarg(self):
426 self.assertRaises(error,pyw.devadd,'bad0','test0','monitor')
427 self.assertRaises(error,pyw.devdel,'bad0')
428 def test_invalidmodearg(self):
429 self.assertRaises(error,pyw.devadd,self.card,'test0','foobar')
430 def test_invalidflagsarg(self):
431 self.assertRaises(error,pyw.devadd,self.card,'test0','monitor','foobar')
432 self.assertRaises(error,pyw.devadd,self.card,'test0','managed','fcsfail')
433
434 # test devset
435 class DevSetTestCase(CardTestCase):
436 def test_devset(self):
437 card = pyw.devset(self.card,'unittest0')
438 self.assertTrue(pyw.iswireless('unittest0'))
439 self.assertFalse(pyw.iswireless(pri['dev']))
440 pyw.devset(card,pri['dev'])
441 self.assertFalse(pyw.iswireless('unittest0'))
442 def test_invalidcardarg(self):
443 self.assertRaises(error,pyw.devset,'bad0','managed')
444 def test_invalidndevarg(self):
445 self.assertRaises(error,pyw.devset,self.card,None)
446 """
447 class IsConnectedTestCase(CardTestCase):
448 def test_isconnected(self):
449 self.assertFalse(pyw.isconnected(self.card))
450 def test_invalidcardarg(self):
451 self.assertRaises(error, pyw.isconnected, 'bad0')
452
453 class PhyListTestCase(unittest.TestCase):
454 def test_phylist(self):
455 self.assertTrue((pri['phy'],'phy{0}'.format(pri['phy'])) in pyw.phylist())
456
457 class IfInfoTestCase(CardTestCase):
458 def test_ifinfo(self):
459 iinfo = pyw.ifinfo(self.card)
460 self.assertTrue(pri['driver'] == iinfo['driver'])
461 self.assertTrue(pri['chipset'] == iinfo['chipset'])
462 def test_invalidcardarg(self):
463 self.assertRaises(error, pyw.ifinfo, 'bad0')
464
465 def pyvers():
466 return "{0}.{1}.{2}".format(sys.version_info.major,
467 sys.version_info.minor,
468 sys.version_info.micro)
469 if __name__ == '__main__':
470 print("Testing PyRIC v{0} pyw v{1} on Python {2}".format(pyric.version,
471 pyw.__version__,
472 pyvers()))
473 unittest.main()