Hak5 WiFi Coconut 1.0.0 import

release-1.0.0 v1.0.0
Mike Kershaw / Dragorn 2022-08-04 10:44:30 -04:00
parent 705f07945d
commit 4c91eaec02
63 changed files with 26986 additions and 30 deletions

30
.gitignore vendored
View File

@ -1,11 +1,19 @@
CMakeLists.txt.user *.o
CMakeCache.txt *.swp
CMakeFiles *.swo
CMakeScripts *.d
Testing *.log
Makefile *.pcap
cmake_install.cmake *~
install_manifest.txt *.exe
compile_commands.json
CTestTestfile.cmake a.out
_deps
.vs/*
out/*
*/out/*
build/*
*/build/*
.cache/*

96
CMakeLists.txt Normal file
View File

@ -0,0 +1,96 @@
# Based on the hackrf cmakefiles, in turn based on the libftdi cmake
cmake_minimum_required(VERSION 2.8)
project(userspace-wifi C)
set(PACKAGE userspace-wifi)
include(${PROJECT_SOURCE_DIR}/cmake/set_release.cmake)
add_definitions(-DRELEASE="${RELEASE}")
set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake/modules)
if (MSVC)
include_directories(getopt)
add_definitions(/D _CRT_SECURE_NO_WARNINGS)
if (FIND_DEBUG)
add_definitions(/D FIND_DEBUG)
endif()
else()
add_definitions(-Wall)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99")
if (FIND_DEBUG)
add_definitions(-DFIND_DEBUG=1)
endif()
endif()
set(prefix ${CMAKE_INSTALL_PREFIX})
if(MSVC)
find_package(PThread REQUIRED)
include_directories(${PTHREAD_INCLUDE_DIR})
set(INT_THREAD_LIBS ${PTHREADS_LIBRARY})
find_package(LibUSB-1.0 REQUIRED)
include_directories(${LIBUSB_1_INCLUDE_DIR})
link_directories(${LIBUSB_1_LIBRARY_DIR})
set(INT_LIBUSB_LIBS ${LIBUSB_1_LIBRARIES})
set (firmwaredir .)
else()
find_package(Threads REQUIRED)
set(INT_THREAD_LIBS ${THREADS_LIBRARY})
find_package(USB1 REQUIRED)
include_directories(${LIBUSB_INCLUDE_DIR})
set(INT_LIBUSB_LIBS ${LIBUSB_LIBRARIES})
set (firmwaredir \${prefix}/share/wifiuserspace/firmware)
endif()
add_subdirectory(libwifiuserspace)
include_directories(${PROJECT_SOURCE_DIR}/libwifiuserspace)
SET(TOOLS
wifi_coconut_capture
wifi_coconut
)
if (MSVC)
add_library(libgetopt_static STATIC
getopt/getopt.c
)
endif()
LIST(APPEND TOOLS_LINK_LIBS wifiuserspace-static)
LIST(APPEND TOOLS_LINK_LIBS ${INT_THREAD_LIBS})
LIST(APPEND TOOLS_LINK_LIBS ${INT_LIBUSB_LIBS})
LIST(APPEND TOOLS_LINK_LIBS ${CMAKE_THREAD_LIBS_INIT})
include_directories(${PROJECT_SOURCE_DIR})
if (MSVC)
LIST(APPEND TOOLS_LINK_LIBS libgetopt_static)
add_custom_target(copydlls)
endif()
add_executable(wifi_coconut_capture
wifi_capture.c
)
add_executable(wifi_coconut
wifi_coconut.c
wifi_coconut/wifi_coconut.c
)
foreach(tool ${TOOLS})
target_link_libraries(${tool} ${TOOLS_LINK_LIBS})
install(TARGETS ${tool} RUNTIME DESTINATION bin)
endforeach(tool)
INSTALL(
DIRECTORY ${PROJECT_SOURCE_DIR}/libwifiuserspace/firmware/
DESTINATION ${firmwaredir}
)

22
CMakeSettings.json Normal file
View File

@ -0,0 +1,22 @@
{
"configurations": [
{
"name": "x64-Debug",
"generator": "Ninja",
"configurationType": "Debug",
"inheritEnvironments": [ "clang_cl_x64" ],
"buildRoot": "${projectDir}\\out\\build\\${name}",
"installRoot": "${projectDir}\\out\\install\\${name}",
"cmakeCommandArgs": "",
"buildCommandArgs": "-v",
"ctestCommandArgs": "",
"variables": [
{
"name": "CMAKE_TOOLCHAIN_FILE",
"value": "C:\\vcpkg\\scripts\\buildsystems\\vcpkg.cmake",
"type": "STRING"
},
]
}
]
}

58
LICENSE
View File

@ -1,12 +1,31 @@
GNU GENERAL PUBLIC LICENSE Valid-License-Identifier: GPL-2.0
Version 2, June 1991 Valid-License-Identifier: GPL-2.0-only
Valid-License-Identifier: GPL-2.0+
Valid-License-Identifier: GPL-2.0-or-later
SPDX-URL: https://spdx.org/licenses/GPL-2.0.html
Usage-Guide:
To use this license in source code, put one of the following SPDX
tag/value pairs into a comment according to the placement
guidelines in the licensing rules documentation.
For 'GNU General Public License (GPL) version 2 only' use:
SPDX-License-Identifier: GPL-2.0
or
SPDX-License-Identifier: GPL-2.0-only
For 'GNU General Public License (GPL) version 2 or any later version' use:
SPDX-License-Identifier: GPL-2.0+
or
SPDX-License-Identifier: GPL-2.0-or-later
License-Text:
Copyright (C) 1989, 1991 Free Software Foundation, Inc., GNU GENERAL PUBLIC LICENSE
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed. of this license document, but changing it is not allowed.
Preamble Preamble
The licenses for most software are designed to take away your The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public freedom to share and change it. By contrast, the GNU General Public
@ -15,7 +34,7 @@ software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to the GNU Library General Public License instead.) You can apply it to
your programs, too. your programs, too.
When we speak of free software, we are referring to freedom, not When we speak of free software, we are referring to freedom, not
@ -55,8 +74,8 @@ patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and The precise terms and conditions for copying, distribution and
modification follow. modification follow.
GNU GENERAL PUBLIC LICENSE GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains 0. This License applies to any program or other work which contains
@ -110,7 +129,7 @@ above, provided that you also meet all of these conditions:
License. (Exception: if the Program itself is interactive but License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on does not normally print such an announcement, your work based on
the Program is not required to print an announcement.) the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program, identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in and can be reasonably considered independent and separate works in
@ -168,7 +187,7 @@ access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not distribution of the source code, even though third parties are not
compelled to copy the source along with the object code. compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program 4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is otherwise to copy, modify, sublicense or distribute the Program is
@ -225,7 +244,7 @@ impose that choice.
This section is intended to make thoroughly clear what is believed to This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License. be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in 8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License original copyright holder who places the Program under this License
@ -255,7 +274,7 @@ make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally. of promoting the sharing and reuse of software generally.
NO WARRANTY NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
@ -277,9 +296,9 @@ YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES. POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it possible use to the public, the best way to achieve this is to make it
@ -303,9 +322,10 @@ the "copyright" line and a pointer to where the full notice is found.
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License along You should have received a copy of the GNU General Public License
with this program; if not, write to the Free Software Foundation, Inc., along with this program; if not, write to the Free Software
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Also add information on how to contact you by electronic and paper mail. Also add information on how to contact you by electronic and paper mail.
@ -335,5 +355,5 @@ necessary. Here is a sample; alter the names:
This General Public License does not permit incorporating your program into This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General library. If this is what you want to do, use the GNU Library General
Public License instead of this License. Public License instead of this License.

2
LICENSE.firmware Normal file
View File

@ -0,0 +1,2 @@
Firmware binaries are licensed according to their corresponding vendor
licenses, found in the firmware/ directory.

8
README.md Normal file
View File

@ -0,0 +1,8 @@
# Hak5 Wi-Fi Coconut
A user-space driver for USB Wi-Fi NICs and the Hak5 Wi-Fi Coconut
## Documentation
See the full documentation at [docs.hak5.org](https://docs.hak5.org/wifi-coconut) for info about usage, pre-built binaries, and compiling instructions for different platforms!

View File

@ -0,0 +1,236 @@
# Updated FindThreads.cmake that supports pthread-win32
# Downloaded from http://www.vtk.org/Bug/bug_view_advanced_page.php?bug_id=6399
# - This module determines the thread library of the system.
#
# The following variables are set
# CMAKE_THREAD_LIBS_INIT - the thread library
# CMAKE_USE_SPROC_INIT - are we using sproc?
# CMAKE_USE_WIN32_THREADS_INIT - using WIN32 threads?
# CMAKE_USE_PTHREADS_INIT - are we using pthreads
# CMAKE_HP_PTHREADS_INIT - are we using hp pthreads
#
# If use of pthreads-win32 is desired, the following variables
# can be set.
#
# THREADS_USE_PTHREADS_WIN32 -
# Setting this to true searches for the pthreads-win32
# port (since CMake 2.8.0)
#
# THREADS_PTHREADS_WIN32_EXCEPTION_SCHEME
# C = no exceptions (default)
# (NOTE: This is the default scheme on most POSIX thread
# implementations and what you should probably be using)
# CE = C++ Exception Handling
# SE = Structure Exception Handling (MSVC only)
# (NOTE: Changing this option from the default may affect
# the portability of your application. See pthreads-win32
# documentation for more details.)
#
#======================================================
# Example usage where threading library
# is provided by the system:
#
# find_package(Threads REQUIRED)
# add_executable(foo foo.cc)
# target_link_libraries(foo ${CMAKE_THREAD_LIBS_INIT})
#
# Example usage if pthreads-win32 is desired on Windows
# or a system provided thread library:
#
# set(THREADS_USE_PTHREADS_WIN32 true)
# find_package(Threads REQUIRED)
# include_directories(${THREADS_PTHREADS_INCLUDE_DIR})
#
# add_executable(foo foo.cc)
# target_link_libraries(foo ${CMAKE_THREAD_LIBS_INIT})
#
INCLUDE (CheckIncludeFiles)
INCLUDE (CheckLibraryExists)
SET(Threads_FOUND FALSE)
IF(WIN32 AND NOT CYGWIN AND THREADS_USE_PTHREADS_WIN32)
SET(_Threads_ptwin32 true)
ENDIF()
# Do we have sproc?
IF(CMAKE_SYSTEM MATCHES IRIX)
CHECK_INCLUDE_FILES("sys/types.h;sys/prctl.h" CMAKE_HAVE_SPROC_H)
ENDIF()
IF(CMAKE_HAVE_SPROC_H)
# We have sproc
SET(CMAKE_USE_SPROC_INIT 1)
ELSEIF(_Threads_ptwin32)
IF(NOT DEFINED THREADS_PTHREADS_WIN32_EXCEPTION_SCHEME)
# Assign the default scheme
SET(THREADS_PTHREADS_WIN32_EXCEPTION_SCHEME "C")
ELSE()
# Validate the scheme specified by the user
IF(NOT THREADS_PTHREADS_WIN32_EXCEPTION_SCHEME STREQUAL "C" AND
NOT THREADS_PTHREADS_WIN32_EXCEPTION_SCHEME STREQUAL "CE" AND
NOT THREADS_PTHREADS_WIN32_EXCEPTION_SCHEME STREQUAL "SE")
MESSAGE(FATAL_ERROR "See documentation for FindPthreads.cmake, only C, CE, and SE modes are allowed")
ENDIF()
IF(NOT MSVC AND THREADS_PTHREADS_WIN32_EXCEPTION_SCHEME STREQUAL "SE")
MESSAGE(FATAL_ERROR "Structured Exception Handling is only allowed for MSVC")
ENDIF(NOT MSVC AND THREADS_PTHREADS_WIN32_EXCEPTION_SCHEME STREQUAL "SE")
ENDIF()
FIND_PATH(THREADS_PTHREADS_INCLUDE_DIR NAMES pthread.h)
# Determine the library filename
IF(MSVC)
SET(_Threads_pthreads_libname
pthreadsV${THREADS_PTHREADS_WIN32_EXCEPTION_SCHEME}2)
ELSEIF(MINGW)
SET(_Threads_pthreads_libname
pthreadsG${THREADS_PTHREADS_WIN32_EXCEPTION_SCHEME}2)
ELSE()
MESSAGE(FATAL_ERROR "This should never happen")
ENDIF()
FIND_LIBRARY(THREADS_PTHREADS_WIN32_LIBRARY
NAMES ${_Threads_pthreads_libname}
)
IF(THREADS_PTHREADS_INCLUDE_DIR AND THREADS_PTHREADS_WIN32_LIBRARY)
MARK_AS_ADVANCED(THREADS_PTHREADS_INCLUDE_DIR)
SET(CMAKE_THREAD_LIBS_INIT ${THREADS_PTHREADS_WIN32_LIBRARY})
SET(CMAKE_HAVE_THREADS_LIBRARY 1)
SET(Threads_FOUND TRUE)
ENDIF()
MARK_AS_ADVANCED(THREADS_PTHREADS_WIN32_LIBRARY)
ELSE()
# Do we have pthreads?
CHECK_INCLUDE_FILES("pthread.h" CMAKE_HAVE_PTHREAD_H)
IF(CMAKE_HAVE_PTHREAD_H)
#
# We have pthread.h
# Let's check for the library now.
#
SET(CMAKE_HAVE_THREADS_LIBRARY)
IF(NOT THREADS_HAVE_PTHREAD_ARG)
# Do we have -lpthreads
CHECK_LIBRARY_EXISTS(pthreads pthread_create "" CMAKE_HAVE_PTHREADS_CREATE)
IF(CMAKE_HAVE_PTHREADS_CREATE)
SET(CMAKE_THREAD_LIBS_INIT "-lpthreads")
SET(CMAKE_HAVE_THREADS_LIBRARY 1)
SET(Threads_FOUND TRUE)
ENDIF()
# Ok, how about -lpthread
CHECK_LIBRARY_EXISTS(pthread pthread_create "" CMAKE_HAVE_PTHREAD_CREATE)
IF(CMAKE_HAVE_PTHREAD_CREATE)
SET(CMAKE_THREAD_LIBS_INIT "-lpthread")
SET(Threads_FOUND TRUE)
SET(CMAKE_HAVE_THREADS_LIBRARY 1)
ENDIF()
IF(CMAKE_SYSTEM MATCHES "SunOS.*")
# On sun also check for -lthread
CHECK_LIBRARY_EXISTS(thread thr_create "" CMAKE_HAVE_THR_CREATE)
IF(CMAKE_HAVE_THR_CREATE)
SET(CMAKE_THREAD_LIBS_INIT "-lthread")
SET(CMAKE_HAVE_THREADS_LIBRARY 1)
SET(Threads_FOUND TRUE)
ENDIF()
ENDIF(CMAKE_SYSTEM MATCHES "SunOS.*")
ENDIF(NOT THREADS_HAVE_PTHREAD_ARG)
IF(NOT CMAKE_HAVE_THREADS_LIBRARY)
# If we did not found -lpthread, -lpthread, or -lthread, look for -pthread
IF("THREADS_HAVE_PTHREAD_ARG" MATCHES "^THREADS_HAVE_PTHREAD_ARG")
MESSAGE(STATUS "Check if compiler accepts -pthread")
TRY_RUN(THREADS_PTHREAD_ARG THREADS_HAVE_PTHREAD_ARG
${CMAKE_BINARY_DIR}
${CMAKE_ROOT}/Modules/CheckForPthreads.c
CMAKE_FLAGS -DLINK_LIBRARIES:STRING=-pthread
COMPILE_OUTPUT_VARIABLE OUTPUT)
IF(THREADS_HAVE_PTHREAD_ARG)
IF(THREADS_PTHREAD_ARG MATCHES "^2$")
SET(Threads_FOUND TRUE)
MESSAGE(STATUS "Check if compiler accepts -pthread - yes")
ELSE()
MESSAGE(STATUS "Check if compiler accepts -pthread - no")
FILE(APPEND
${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
"Determining if compiler accepts -pthread returned ${THREADS_PTHREAD_ARG} instead of 2. The compiler had the following output:\n${OUTPUT}\n\n")
ENDIF()
ELSE()
MESSAGE(STATUS "Check if compiler accepts -pthread - no")
FILE(APPEND
${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
"Determining if compiler accepts -pthread failed with the following output:\n${OUTPUT}\n\n")
ENDIF()
ENDIF("THREADS_HAVE_PTHREAD_ARG" MATCHES "^THREADS_HAVE_PTHREAD_ARG")
IF(THREADS_HAVE_PTHREAD_ARG)
SET(Threads_FOUND TRUE)
SET(CMAKE_THREAD_LIBS_INIT "-pthread")
ENDIF()
ENDIF(NOT CMAKE_HAVE_THREADS_LIBRARY)
ENDIF(CMAKE_HAVE_PTHREAD_H)
ENDIF()
IF(CMAKE_THREAD_LIBS_INIT)
SET(CMAKE_USE_PTHREADS_INIT 1)
SET(Threads_FOUND TRUE)
ENDIF()
IF(CMAKE_SYSTEM MATCHES "Windows"
AND NOT THREADS_USE_PTHREADS_WIN32)
SET(CMAKE_USE_WIN32_THREADS_INIT 1)
SET(Threads_FOUND TRUE)
ENDIF()
IF(CMAKE_USE_PTHREADS_INIT)
IF(CMAKE_SYSTEM MATCHES "HP-UX-*")
# Use libcma if it exists and can be used. It provides more
# symbols than the plain pthread library. CMA threads
# have actually been deprecated:
# http://docs.hp.com/en/B3920-90091/ch12s03.html#d0e11395
# http://docs.hp.com/en/947/d8.html
# but we need to maintain compatibility here.
# The CMAKE_HP_PTHREADS setting actually indicates whether CMA threads
# are available.
CHECK_LIBRARY_EXISTS(cma pthread_attr_create "" CMAKE_HAVE_HP_CMA)
IF(CMAKE_HAVE_HP_CMA)
SET(CMAKE_THREAD_LIBS_INIT "-lcma")
SET(CMAKE_HP_PTHREADS_INIT 1)
SET(Threads_FOUND TRUE)
ENDIF(CMAKE_HAVE_HP_CMA)
SET(CMAKE_USE_PTHREADS_INIT 1)
ENDIF()
IF(CMAKE_SYSTEM MATCHES "OSF1-V*")
SET(CMAKE_USE_PTHREADS_INIT 0)
SET(CMAKE_THREAD_LIBS_INIT )
ENDIF()
IF(CMAKE_SYSTEM MATCHES "CYGWIN_NT*")
SET(CMAKE_USE_PTHREADS_INIT 1)
SET(Threads_FOUND TRUE)
SET(CMAKE_THREAD_LIBS_INIT )
SET(CMAKE_USE_WIN32_THREADS_INIT 0)
ENDIF()
ENDIF(CMAKE_USE_PTHREADS_INIT)
INCLUDE(FindPackageHandleStandardArgs)
IF(_Threads_ptwin32)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(Threads DEFAULT_MSG
THREADS_PTHREADS_WIN32_LIBRARY THREADS_PTHREADS_INCLUDE_DIR)
ELSE()
FIND_PACKAGE_HANDLE_STANDARD_ARGS(Threads DEFAULT_MSG Threads_FOUND)
ENDIF()

View File

@ -0,0 +1,43 @@
# - Try to find the freetype library
# Once done this defines
#
# LIBUSB_FOUND - system has libusb
# LIBUSB_INCLUDE_DIR - the libusb include directory
# LIBUSB_LIBRARIES - Link these to use libusb
# Copyright (c) 2006, 2008 Laurent Montel, <montel@kde.org>
#
# Redistribution and use is allowed according to the terms of the BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
if (LIBUSB_INCLUDE_DIR AND LIBUSB_LIBRARIES)
# in cache already
set(LIBUSB_FOUND TRUE)
else (LIBUSB_INCLUDE_DIR AND LIBUSB_LIBRARIES)
IF (NOT WIN32)
# use pkg-config to get the directories and then use these values
# in the FIND_PATH() and FIND_LIBRARY() calls
find_package(PkgConfig)
pkg_check_modules(PC_LIBUSB libusb-1.0)
ENDIF(NOT WIN32)
set(LIBUSB_LIBRARY_NAME usb-1.0)
IF(${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD")
set(LIBUSB_LIBRARY_NAME usb)
ENDIF(${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD")
FIND_PATH(LIBUSB_INCLUDE_DIR libusb.h
PATHS ${PC_LIBUSB_INCLUDEDIR} ${PC_LIBUSB_INCLUDE_DIRS})
FIND_LIBRARY(LIBUSB_LIBRARIES NAMES ${LIBUSB_LIBRARY_NAME}
PATHS ${PC_LIBUSB_LIBDIR} ${PC_LIBUSB_LIBRARY_DIRS})
include(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(LIBUSB DEFAULT_MSG LIBUSB_LIBRARIES LIBUSB_INCLUDE_DIR)
MARK_AS_ADVANCED(LIBUSB_INCLUDE_DIR LIBUSB_LIBRARIES)
endif (LIBUSB_INCLUDE_DIR AND LIBUSB_LIBRARIES)

View File

@ -0,0 +1,96 @@
# - Try to find libusb-1.0
# Once done this will define
#
# LIBUSB_1_FOUND - system has libusb
# LIBUSB_1_INCLUDE_DIRS - the libusb include directory
# LIBUSB_1_LIBRARIES - Link these to use libusb
# LIBUSB_1_DEFINITIONS - Compiler switches required for using libusb
#
# Adapted from cmake-modules Google Code project
#
# Copyright (c) 2006 Andreas Schneider <mail@cynapses.org>
#
# (Changes for libusb) Copyright (c) 2008 Kyle Machulis <kyle@nonpolynomial.com>
#
# Redistribution and use is allowed according to the terms of the New BSD license.
#
# CMake-Modules Project New BSD License
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice, this
# list of conditions and the following disclaimer.
#
# * 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.
#
# * Neither the name of the CMake-Modules Project nor the names of its
# 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 HOLDERS 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 THE COPYRIGHT OWNER OR CONTRIBUTORS 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.
#
if (LIBUSB_1_LIBRARIES AND LIBUSB_1_INCLUDE_DIRS)
# in cache already
set(LIBUSB_FOUND TRUE)
else (LIBUSB_1_LIBRARIES AND LIBUSB_1_INCLUDE_DIRS)
find_path(LIBUSB_1_INCLUDE_DIR
NAMES
libusb.h
PATHS
/usr/include
/usr/local/include
/sw/include
PATH_SUFFIXES
libusb-1.0
)
find_library(LIBUSB_1_LIBRARY
NAMES
usb-1.0 usb libusb-1.0
PATHS
/usr/lib
/usr/local/lib
/sw/lib
)
set(LIBUSB_1_INCLUDE_DIRS
${LIBUSB_1_INCLUDE_DIR}
)
set(LIBUSB_1_LIBRARIES
${LIBUSB_1_LIBRARY}
)
if (LIBUSB_1_INCLUDE_DIRS AND LIBUSB_1_LIBRARIES)
set(LIBUSB_1_FOUND TRUE)
endif (LIBUSB_1_INCLUDE_DIRS AND LIBUSB_1_LIBRARIES)
if (LIBUSB_1_FOUND)
if (NOT libusb_1_FIND_QUIETLY)
message(STATUS "Found libusb-1.0:")
message(STATUS " - Includes: ${LIBUSB_1_INCLUDE_DIRS}")
message(STATUS " - Libraries: ${LIBUSB_1_LIBRARIES}")
endif (NOT libusb_1_FIND_QUIETLY)
else (LIBUSB_1_FOUND)
if (libusb_1_FIND_REQUIRED)
message(FATAL_ERROR "Could not find libusb")
endif (libusb_1_FIND_REQUIRED)
endif (LIBUSB_1_FOUND)
# show the LIBUSB_1_INCLUDE_DIRS and LIBUSB_1_LIBRARIES variables only in the advanced view
mark_as_advanced(LIBUSB_1_INCLUDE_DIRS LIBUSB_1_LIBRARIES)
endif (LIBUSB_1_LIBRARIES AND LIBUSB_1_INCLUDE_DIRS)

28
cmake/set_release.cmake Normal file
View File

@ -0,0 +1,28 @@
# Get the current git version to set a release number
#set(RELEASE "")
if(NOT DEFINED RELEASE)
execute_process(
COMMAND git log -n 1 --format=%h
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
RESULT_VARIABLE GIT_EXIT_VALUE
ERROR_QUIET
OUTPUT_VARIABLE GIT_VERSION
OUTPUT_STRIP_TRAILING_WHITESPACE
)
if (GIT_EXIT_VALUE)
set(RELEASE "unknown")
else (GIT_EXIT_VALUE)
execute_process(
COMMAND git status -s --untracked-files=no
OUTPUT_VARIABLE DIRTY
)
if ( NOT "${DIRTY}" STREQUAL "" )
set(DIRTY_FLAG "*")
else()
set(DIRTY_FLAG "")
endif()
set(RELEASE "git-${GIT_VERSION}${DIRTY_FLAG}")
endif (GIT_EXIT_VALUE)
endif()

1086
getopt/getopt.c Normal file

File diff suppressed because it is too large Load Diff

180
getopt/getopt.h Normal file
View File

@ -0,0 +1,180 @@
/* Declarations for getopt.
Copyright (C) 1989-1994, 1996-1999, 2001 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#ifndef _GETOPT_H
#ifndef __need_getopt
# define _GETOPT_H 1
#endif
/* If __GNU_LIBRARY__ is not already defined, either we are being used
standalone, or this is the first header included in the source file.
If we are being used with glibc, we need to include <features.h>, but
that does not exist if we are standalone. So: if __GNU_LIBRARY__ is
not defined, include <ctype.h>, which will pull in <features.h> for us
if it's from glibc. (Why ctype.h? It's guaranteed to exist and it
doesn't flood the namespace with stuff the way some other headers do.) */
#if !defined __GNU_LIBRARY__
# include <ctype.h>
#endif
#ifdef __cplusplus
extern "C" {
#endif
/* For communication from `getopt' to the caller.
When `getopt' finds an option that takes an argument,
the argument value is returned here.
Also, when `ordering' is RETURN_IN_ORDER,
each non-option ARGV-element is returned here. */
extern char *optarg;
/* Index in ARGV of the next element to be scanned.
This is used for communication to and from the caller
and for communication between successive calls to `getopt'.
On entry to `getopt', zero means this is the first call; initialize.
When `getopt' returns -1, this is the index of the first of the
non-option elements that the caller should itself scan.
Otherwise, `optind' communicates from one call to the next
how much of ARGV has been scanned so far. */
extern int optind;
/* Callers store zero here to inhibit the error message `getopt' prints
for unrecognized options. */
extern int opterr;
/* Set to an option character which was unrecognized. */
extern int optopt;
#ifndef __need_getopt
/* Describe the long-named options requested by the application.
The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector
of `struct option' terminated by an element containing a name which is
zero.
The field `has_arg' is:
no_argument (or 0) if the option does not take an argument,
required_argument (or 1) if the option requires an argument,
optional_argument (or 2) if the option takes an optional argument.
If the field `flag' is not NULL, it points to a variable that is set
to the value given in the field `val' when the option is found, but
left unchanged if the option is not found.
To have a long-named option do something other than set an `int' to
a compiled-in constant, such as set a value from `optarg', set the
option's `flag' field to zero and its `val' field to a nonzero
value (the equivalent single-letter option character, if there is
one). For long options that have a zero `flag' field, `getopt'
returns the contents of the `val' field. */
struct option
{
# if (defined __STDC__ && __STDC__) || defined __cplusplus
const char *name;
# else
char *name;
# endif
/* has_arg can't be an enum because some compilers complain about
type mismatches in all the code that assumes it is an int. */
int has_arg;
int *flag;
int val;
};
/* Names for the values of the `has_arg' field of `struct option'. */
# define no_argument 0
# define required_argument 1
# define optional_argument 2
#endif /* need getopt */
/* Get definitions and prototypes for functions to process the
arguments in ARGV (ARGC of them, minus the program name) for
options given in OPTS.
Return the option character from OPTS just read. Return -1 when
there are no more options. For unrecognized options, or options
missing arguments, `optopt' is set to the option letter, and '?' is
returned.
The OPTS string is a list of characters which are recognized option
letters, optionally followed by colons, specifying that that letter
takes an argument, to be placed in `optarg'.
If a letter in OPTS is followed by two colons, its argument is
optional. This behavior is specific to the GNU `getopt'.
The argument `--' causes premature termination of argument
scanning, explicitly telling `getopt' that there are no more
options.
If OPTS begins with `--', then non-option arguments are treated as
arguments to the option '\0'. This behavior is specific to the GNU
`getopt'. */
#if (defined __STDC__ && __STDC__) || defined __cplusplus
# ifdef __GNU_LIBRARY__
/* Many other libraries have conflicting prototypes for getopt, with
differences in the consts, in stdlib.h. To avoid compilation
errors, only prototype getopt for the GNU C library. */
extern int getopt (int __argc, char *const *__argv, const char *__shortopts);
# else /* not __GNU_LIBRARY__ */
extern int getopt ();
# endif /* __GNU_LIBRARY__ */
# ifndef __need_getopt
extern int getopt_long (int __argc, char *const *__argv, const char *__shortopts,
const struct option *__longopts, int *__longind);
extern int getopt_long_only (int __argc, char *const *__argv,
const char *__shortopts,
const struct option *__longopts, int *__longind);
/* Internal only. Users should not call this directly. */
extern int _getopt_internal (int __argc, char *const *__argv,
const char *__shortopts,
const struct option *__longopts, int *__longind,
int __long_only);
# endif
#else /* not __STDC__ */
extern int getopt ();
# ifndef __need_getopt
extern int getopt_long ();
extern int getopt_long_only ();
extern int _getopt_internal ();
# endif
#endif /* __STDC__ */
#ifdef __cplusplus
}
#endif
/* Make sure we later can get all the definitions and declarations. */
#undef __need_getopt
#endif /* getopt.h */

View File

@ -0,0 +1,109 @@
# Based on the hackrf cmakefiles, in turn based on the libftdi cmake
cmake_minimum_required(VERSION 2.8)
project(libwifiuserspace C)
set(PACKAGE libwifiuserspace)
include(${PROJECT_SOURCE_DIR}/../cmake/set_release.cmake)
add_definitions(-DRELEASE="${RELEASE}")
set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/../cmake/modules)
if(MSVC)
find_package(PThread REQUIRED)
include_directories(${PTHREAD_INCLUDE_DIR})
set(INT_THREAD_LIBS ${PTHREADS_LIBRARY})
find_package(LibUSB-1.0 REQUIRED)
include_directories(${LIBUSB_1_INCLUDE_DIR})
link_directories(${LIBUSB_1_LIBRARY_DIR})
set(INT_LIBUSB_LIBS ${LIBUSB_1_LIBRARIES})
set(sharedir "./")
set(INSTALL_LIB_DIR "./")
set(INSTALL_DEFAULT_BINDIR "./")
else()
find_package(Threads REQUIRED)
set(INT_THREAD_LIBS ${THREADS_LIBRARY})
find_package(USB1 REQUIRED)
include_directories(${LIBUSB_INCLUDE_DIR})
set(INT_LIBUSB_LIBS ${LIBUSB_LIBRARIES})
set (sharedir \${prefix}/share/wifiuserspace/firmware)
set(INSTALL_LIB_DIR \${lib}suffix)
set(INSTALL_DEFAULT_BINDIR "bin")
endif()
add_definitions(-DFIRMWAREDIR="${prefix}/share/wifiuserspace/firmware")
set(c_sources
${CMAKE_CURRENT_SOURCE_DIR}/rt2800usb/rt2800lib.c
${CMAKE_CURRENT_SOURCE_DIR}/rt2800usb/rt2800usb.c
${CMAKE_CURRENT_SOURCE_DIR}/rt2800usb/rt2x00.c
${CMAKE_CURRENT_SOURCE_DIR}/rt2800usb/rt2x00mac.c
${CMAKE_CURRENT_SOURCE_DIR}/rt2800usb/rt2x00usb.c
${CMAKE_CURRENT_SOURCE_DIR}/kernel/cfg80211.c
${CMAKE_CURRENT_SOURCE_DIR}/kernel/crc_ccit.c
${CMAKE_CURRENT_SOURCE_DIR}/userspace/userspace.c
CACHE INTERNAL "List of C sources")
set(c_kernel_headers
${CMAKE_CURRENT_SOURCE_DIR}/kernel/kernel.h
${CMAKE_CURRENT_SOURCE_DIR}/kernel/types.h
${CMAKE_CURRENT_SOURCE_DIR}/kernel/usb.h
CACHE INTERNAL "List of userspace-kernel headers")
set(c_userspace_headers
${CMAKE_CURRENT_SOURCE_DIR}/userspace/userspace.h
CACHE INTERNAL "List of userspace API eaders")
add_library(wifiuserspace SHARED ${c_sources})
set_target_properties(wifiuserspace PROPERTIES VERSION 2019.09.0 SOVERSION 0)
add_library(wifiuserspace-static STATIC ${c_sources})
if (MSVC)
set_target_properties(wifiuserspace-static PROPERTIES OUTPUT_NAME "wifiuserspace_static")
else()
set_target_properties(wifiuserspace-static PROPERTIES OUTPUT_NAME "wifiuserspace")
endif()
set_target_properties(wifiuserspace PROPERTIES CLEAN_DIRECT_OUTPUT 1)
set_target_properties(wifiuserspace-static PROPERTIES CLEAN_DIRECT_OUTPUT 1)
target_link_libraries(wifiuserspace ${INT_THREAD_LIBS} ${INT_LIBUSB_LIBS} ${CMAKE_THREAD_LIBS_INIT})
target_link_libraries(wifiuserspace-static ${INT_THREAD_LIBS} ${INT_LIBUSB_LIBS} ${CMAKE_THREAD_LIBS_INIT})
if(INSTALL_LIBUSERSPACE)
if(MSVC)
# Static linkage only on win32
else()
install(TARGETS wifiuserspace
LIBRARY DESTINATION ${INSTALL_LIB_DIR}
COMPONENT sharedlibs
)
install(TARGETS wifiuserspace-static
ARCHIVE DESTINATION ${INSTALL_LIB_DIR}
COMPONENT staticlibs
)
install(FILES ${c_kernel_headers}
DESTINATION include/${PROJECT_NAME}
COMPONENT headers
)
install(FILES ${c_userspace_headers}
DESTINATION include/${PROJECT_NAME}
COMPONENT headers
)
endif()
INSTALL(
DIRECTORY ${PROJECT_SOURCE_DIR}/firmware/
DESTINATION ${sharedir}
)
endif(INSTALL_LIBUSERSPACE)
include_directories(${PROJECT_SOURCE_DIR})

View File

@ -0,0 +1,39 @@
Copyright (c) 2013, Ralink, A MediaTek Company
All rights reserved.
Redistribution. Redistribution and use in binary form, without
modification, are permitted provided that the following conditions are
met:
* Redistributions must reproduce the above copyright notice and the
following disclaimer in the documentation and/or other materials
provided with the distribution.
* Neither the name of Ralink Technology Corporation nor the names of its
suppliers may be used to endorse or promote products derived from this
software without specific prior written permission.
* No reverse engineering, decompilation, or disassembly of this software
is permitted.
Limited patent license. Ralink Technology Corporation grants a world-wide,
royalty-free, non-exclusive license under patents it now or hereafter
owns or controls to make, have made, use, import, offer to sell and
sell ("Utilize") this software, but solely to the extent that any
such patent is necessary to Utilize the software alone, or in
combination with an operating system licensed under an approved Open
Source license as listed by the Open Source Initiative at
http://opensource.org/licenses. The patent license shall not apply to
any other combinations which include this software. No hardware per
se is licensed hereunder.
DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 THE
COPYRIGHT OWNER OR CONTRIBUTORS 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.

Binary file not shown.

View File

@ -0,0 +1,78 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Userspace port (c) 2019 Hak5
*/
#ifndef __USERSPACE_AVERAGE_H__
#define __USERSPACE_AVERAGE_H__
#include "kernel/types.h"
#include "kernel/kernel.h"
#include "kernel/log2.h"
/*
* Exponentially weighted moving average (EWMA)
*
* This implements a fixed-precision EWMA algorithm, with both the
* precision and fall-off coefficient determined at compile-time
* and built into the generated helper funtions.
*
* The first argument to the macro is the name that will be used
* for the struct and helper functions.
*
* The second argument, the precision, expresses how many bits are
* used for the fractional part of the fixed-precision values.
*
* The third argument, the weight reciprocal, determines how the
* new values will be weighed vs. the old state, new values will
* get weight 1/weight_rcp and old values 1-1/weight_rcp. Note
* that this parameter must be a power of two for efficiency.
*/
#define DECLARE_EWMA(name, _precision, _weight_rcp) \
struct ewma_##name { \
unsigned long internal; \
}; \
static inline void ewma_##name##_init(struct ewma_##name *e) \
{ \
BUILD_BUG_ON(!__builtin_constant_p(_precision)); \
BUILD_BUG_ON(!__builtin_constant_p(_weight_rcp)); \
/* \
* Even if you want to feed it just 0/1 you should have \
* some bits for the non-fractional part... \
*/ \
BUILD_BUG_ON((_precision) > 30); \
BUILD_BUG_ON_NOT_POWER_OF_2(_weight_rcp); \
e->internal = 0; \
} \
static inline unsigned long \
ewma_##name##_read(struct ewma_##name *e) \
{ \
BUILD_BUG_ON(!__builtin_constant_p(_precision)); \
BUILD_BUG_ON(!__builtin_constant_p(_weight_rcp)); \
BUILD_BUG_ON((_precision) > 30); \
BUILD_BUG_ON_NOT_POWER_OF_2(_weight_rcp); \
return e->internal >> (_precision); \
} \
static inline void ewma_##name##_add(struct ewma_##name *e, \
unsigned long val) \
{ \
unsigned long internal = READ_ONCE(e->internal); \
unsigned long weight_rcp = ilog2(_weight_rcp); \
unsigned long precision = _precision; \
\
BUILD_BUG_ON(!__builtin_constant_p(_precision)); \
BUILD_BUG_ON(!__builtin_constant_p(_weight_rcp)); \
BUILD_BUG_ON((_precision) > 30); \
BUILD_BUG_ON_NOT_POWER_OF_2(_weight_rcp); \
\
WRITE_ONCE(e->internal, internal ? \
(((internal << weight_rcp) - internal) + \
(val << precision)) >> weight_rcp : \
(val << precision)); \
}
#endif /* ifndef USERSPACE_AVERAGE_H */

View File

@ -0,0 +1,98 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Userspace port (c) 2019 Hak5
*/
#ifndef __USERSPACE_BITOPS_H__
#define __USERSPACE_BITOPS_H__
#include "kernel/bits.h"
#include "kernel/types.h"
#define BITS_PER_TYPE(type) (sizeof(type) * BITS_PER_BYTE)
#define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_TYPE(long))
/**
* __test_and_clear_bit - Clear a bit and return its old value
* @nr: Bit to clear
* @addr: Address to count from
*
* This operation is non-atomic and can be reordered.
* If two examples of this operation race, one can appear to succeed
* but actually fail. You must protect multiple accesses with a lock.
*/
static inline int __test_and_clear_bit(int nr, volatile unsigned long *addr)
{
unsigned long mask = BIT_MASK(nr);
unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
unsigned long old = *p;
*p = old & ~mask;
return (old & mask) != 0;
}
#define test_and_clear_bit(nr, addr) __test_and_clear_bit((nr), (addr))
/*
* Kluge swab16
*/
static inline __u16 ___swab16(__u16 x)
{
return x<<8 | x>>8;
}
#define swab16(x) ___swab16(x)
/*
* Kluge FLS from generic
*/
/**
* fls - find last (most-significant) bit set
* @x: the word to search
*
* This is defined the same way as ffs.
* Note fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32.
*/
static int __fls(unsigned int x)
{
int r = 32;
if (!x)
return 0;
if (!(x & 0xffff0000u)) {
x <<= 16;
r -= 16;
}
if (!(x & 0xff000000u)) {
x <<= 8;
r -= 8;
}
if (!(x & 0xf0000000u)) {
x <<= 4;
r -= 4;
}
if (!(x & 0xc0000000u)) {
x <<= 2;
r -= 2;
}
if (!(x & 0x80000000u)) {
x <<= 1;
r -= 1;
}
return r;
}
static int __fls64(__u64 x)
{
__u32 h = x >> 32;
if (h)
return __fls(h) + 32;
return __fls(x);
}
#define __fls_long(x) __fls64(x)
#endif /* ifndef USERSPACE_BITOPS_H */

View File

@ -0,0 +1,39 @@
/*
* GPL-2.0-or-later
*
* Userspace port (C) 2019 Hak5 Inc
*
*/
#ifndef __BITS_H__
#define __BITS_H__
#include <stdbool.h>
#define BIT(nr) (1UL << (nr))
#define BIT_ULL(nr) (1ULL << (nr))
#define BIT_MASK(nr) (1UL << ((nr) % BITS_PER_LONG))
#define BIT_WORD(nr) ((nr) / BITS_PER_LONG)
#define BIT_ULL_MASK(nr) (1ULL << ((nr) % BITS_PER_LONG_LONG))
#define BIT_ULL_WORD(nr) ((nr) / BITS_PER_LONG_LONG)
#define BITS_PER_BYTE 8
#define BITS_PER_LONG (8 * BITS_PER_BYTE)
static inline void set_bit(int bit, unsigned long *x) {
*x |= (1UL << bit);
}
static inline void clear_bit(int bit, unsigned long *x) {
*x &= ~(1UL << bit);
}
static inline bool test_bit(int bit, unsigned long *x) {
return (*x & (1UL << bit));
}
#define __clear_bit(n, r) clear_bit((n), (r))
#define __get_bit(n, r) get_bit((n), (r))
#define __set_bit(n, r) set_bit((n), (r))
#endif /* ifndef BITS_H */

View File

@ -0,0 +1,64 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Wireless utility functions
*
* Copyright 2007-2009 Johannes Berg <johannes@sipsolutions.net>
* Copyright 2013-2014 Intel Mobile Communications GmbH
* Copyright 2017 Intel Deutschland GmbH
* Copyright (C) 2018-2019 Intel Corporation
*/
/*
* Userspace port (c) 2019 Hak5
*/
#include "cfg80211.h"
#include "kernel.h"
int ieee80211_channel_to_frequency(int chan, enum nl80211_band band)
{
/* see 802.11 17.3.8.3.2 and Annex J
* there are overlapping channel numbers in 5GHz and 2GHz bands */
if (chan <= 0)
return 0; /* not supported */
switch (band) {
case NL80211_BAND_2GHZ:
if (chan == 14)
return 2484;
else if (chan < 14)
return 2407 + chan * 5;
break;
case NL80211_BAND_5GHZ:
if (chan >= 182 && chan <= 196)
return 4000 + chan * 5;
else
return 5000 + chan * 5;
break;
case NL80211_BAND_60GHZ:
if (chan < 7)
return 56160 + chan * 2160;
break;
default:
;
}
return 0; /* not supported */
}
EXPORT_SYMBOL(ieee80211_channel_to_frequency);
int ieee80211_frequency_to_channel(int freq)
{
/* see 802.11 17.3.8.3.2 and Annex J */
if (freq == 2484)
return 14;
else if (freq < 2484)
return (freq - 2407) / 5;
else if (freq >= 4910 && freq <= 4980)
return (freq - 4000) / 5;
else if (freq <= 45000) /* DMG band lower limit */
return (freq - 5000) / 5;
else if (freq >= 58320 && freq <= 70200)
return (freq - 56160) / 2160;
else
return 0;
}
EXPORT_SYMBOL(ieee80211_frequency_to_channel);

View File

@ -0,0 +1,309 @@
/*
* 802.11 device and configuration interface
*
* Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net>
* Copyright 2013-2014 Intel Mobile Communications GmbH
* Copyright 2015-2017 Intel Deutschland GmbH
* Copyright (C) 2018-2019 Intel Corporation
*/
/*
* Userspace port (c) 2019 Hak5
*/
#ifndef __USERSPACE_CFG80211_H__
#define __USERSPACE_CFG80211_H__
#include <stdbool.h>
#include "kernel/bits.h"
#include "kernel/types.h"
#include "kernel/nl80211.h"
#include "kernel/ieee80211.h"
/**
* struct ieee80211_channel - channel definition
*
* This structure describes a single channel for use
* with cfg80211.
*
* @center_freq: center frequency in MHz
* @hw_value: hardware-specific value for the channel
* @flags: channel flags from &enum ieee80211_channel_flags.
* @orig_flags: channel flags at registration time, used by regulatory
* code to support devices with additional restrictions
* @band: band this channel belongs to.
* @max_antenna_gain: maximum antenna gain in dBi
* @max_power: maximum transmission power (in dBm)
* @max_reg_power: maximum regulatory transmission power (in dBm)
* @beacon_found: helper to regulatory code to indicate when a beacon
* has been found on this channel. Use regulatory_hint_found_beacon()
* to enable this, this is useful only on 5 GHz band.
* @orig_mag: internal use
* @orig_mpwr: internal use
* @dfs_state: current state of this channel. Only relevant if radar is required
* on this channel.
* @dfs_state_entered: timestamp (jiffies) when the dfs state was entered.
* @dfs_cac_ms: DFS CAC time in milliseconds, this is valid for DFS channels.
*/
struct ieee80211_channel {
enum nl80211_band band;
u32 center_freq;
u16 hw_value;
u32 flags;
int max_antenna_gain;
int max_power;
int max_reg_power;
bool beacon_found;
u32 orig_flags;
int orig_mag, orig_mpwr;
enum nl80211_dfs_state dfs_state;
unsigned long dfs_state_entered;
unsigned int dfs_cac_ms;
};
/**
* struct cfg80211_chan_def - channel definition
* @chan: the (control) channel
* @width: channel width
* @center_freq1: center frequency of first segment
* @center_freq2: center frequency of second segment
* (only with 80+80 MHz)
*/
struct cfg80211_chan_def {
struct ieee80211_channel *chan;
enum nl80211_chan_width width;
u32 center_freq1;
u32 center_freq2;
}
;
/**
* struct ieee80211_rate - bitrate definition
*
* This structure describes a bitrate that an 802.11 PHY can
* operate with. The two values @hw_value and @hw_value_short
* are only for driver use when pointers to this structure are
* passed around.
*
* @flags: rate-specific flags
* @bitrate: bitrate in units of 100 Kbps
* @hw_value: driver/hardware value for this rate
* @hw_value_short: driver/hardware value for this rate when
* short preamble is used
*/
struct ieee80211_rate {
u32 flags;
u16 bitrate;
u16 hw_value, hw_value_short;
};
/**
* struct ieee80211_sta_ht_cap - STA's HT capabilities
*
* This structure describes most essential parameters needed
* to describe 802.11n HT capabilities for an STA.
*
* @ht_supported: is HT supported by the STA
* @cap: HT capabilities map as described in 802.11n spec
* @ampdu_factor: Maximum A-MPDU length factor
* @ampdu_density: Minimum A-MPDU spacing
* @mcs: Supported MCS rates
*/
struct ieee80211_sta_ht_cap {
u16 cap; /* use IEEE80211_HT_CAP_ */
bool ht_supported;
u8 ampdu_factor;
u8 ampdu_density;
struct ieee80211_mcs_info mcs;
};
/**
* struct ieee80211_sta_vht_cap - STA's VHT capabilities
*
* This structure describes most essential parameters needed
* to describe 802.11ac VHT capabilities for an STA.
*
* @vht_supported: is VHT supported by the STA
* @cap: VHT capabilities map as described in 802.11ac spec
* @vht_mcs: Supported VHT MCS rates
*/
struct ieee80211_sta_vht_cap {
bool vht_supported;
u32 cap; /* use IEEE80211_VHT_CAP_ */
struct ieee80211_vht_mcs_info vht_mcs;
};
#define IEEE80211_HE_PPE_THRES_MAX_LEN 25
/**
* struct ieee80211_sta_he_cap - STA's HE capabilities
*
* This structure describes most essential parameters needed
* to describe 802.11ax HE capabilities for a STA.
*
* @has_he: true iff HE data is valid.
* @he_cap_elem: Fixed portion of the HE capabilities element.
* @he_mcs_nss_supp: The supported NSS/MCS combinations.
* @ppe_thres: Holds the PPE Thresholds data.
*/
struct ieee80211_sta_he_cap {
bool has_he;
struct ieee80211_he_cap_elem he_cap_elem;
struct ieee80211_he_mcs_nss_supp he_mcs_nss_supp;
u8 ppe_thres[IEEE80211_HE_PPE_THRES_MAX_LEN];
};
#define IEEE80211_MAX_CHAINS 4
/**
* enum station_info_rate_flags - bitrate info flags
*
* Used by the driver to indicate the specific rate transmission
* type for 802.11n transmissions.
*
* @RATE_INFO_FLAGS_MCS: mcs field filled with HT MCS
* @RATE_INFO_FLAGS_VHT_MCS: mcs field filled with VHT MCS
* @RATE_INFO_FLAGS_SHORT_GI: 400ns guard interval
* @RATE_INFO_FLAGS_60G: 60GHz MCS
* @RATE_INFO_FLAGS_HE_MCS: HE MCS information
*/
enum rate_info_flags {
RATE_INFO_FLAGS_MCS = BIT(0),
RATE_INFO_FLAGS_VHT_MCS = BIT(1),
RATE_INFO_FLAGS_SHORT_GI = BIT(2),
RATE_INFO_FLAGS_60G = BIT(3),
RATE_INFO_FLAGS_HE_MCS = BIT(4),
};
/**
* enum rate_info_bw - rate bandwidth information
*
* Used by the driver to indicate the rate bandwidth.
*
* @RATE_INFO_BW_5: 5 MHz bandwidth
* @RATE_INFO_BW_10: 10 MHz bandwidth
* @RATE_INFO_BW_20: 20 MHz bandwidth
* @RATE_INFO_BW_40: 40 MHz bandwidth
* @RATE_INFO_BW_80: 80 MHz bandwidth
* @RATE_INFO_BW_160: 160 MHz bandwidth
* @RATE_INFO_BW_HE_RU: bandwidth determined by HE RU allocation
*/
enum rate_info_bw {
RATE_INFO_BW_20 = 0,
RATE_INFO_BW_5,
RATE_INFO_BW_10,
RATE_INFO_BW_40,
RATE_INFO_BW_80,
RATE_INFO_BW_160,
RATE_INFO_BW_HE_RU,
};
/**
* struct rate_info - bitrate information
*
* Information about a receiving or transmitting bitrate
*
* @flags: bitflag of flags from &enum rate_info_flags
* @mcs: mcs index if struct describes an HT/VHT/HE rate
* @legacy: bitrate in 100kbit/s for 802.11abg
* @nss: number of streams (VHT & HE only)
* @bw: bandwidth (from &enum rate_info_bw)
* @he_gi: HE guard interval (from &enum nl80211_he_gi)
* @he_dcm: HE DCM value
* @he_ru_alloc: HE RU allocation (from &enum nl80211_he_ru_alloc,
* only valid if bw is %RATE_INFO_BW_HE_RU)
*/
struct rate_info {
u8 flags;
u8 mcs;
u16 legacy;
u8 nss;
u8 bw;
u8 he_gi;
u8 he_dcm;
u8 he_ru_alloc;
};
/**
* ieee80211_channel_to_frequency - convert channel number to frequency
* @chan: channel number
* @band: band, necessary due to channel number overlap
* Return: The corresponding frequency (in MHz), or 0 if the conversion failed.
*/
int ieee80211_channel_to_frequency(int chan, enum nl80211_band band);
/**
* ieee80211_frequency_to_channel - convert frequency to channel number
* @freq: center frequency
* Return: The corresponding channel, or 0 if the conversion failed.
*/
int ieee80211_frequency_to_channel(int freq);
/**
* enum ieee80211_rate_flags - rate flags
*
* Hardware/specification flags for rates. These are structured
* in a way that allows using the same bitrate structure for
* different bands/PHY modes.
*
* @IEEE80211_RATE_SHORT_PREAMBLE: Hardware can send with short
* preamble on this bitrate; only relevant in 2.4GHz band and
* with CCK rates.
* @IEEE80211_RATE_MANDATORY_A: This bitrate is a mandatory rate
* when used with 802.11a (on the 5 GHz band); filled by the
* core code when registering the wiphy.
* @IEEE80211_RATE_MANDATORY_B: This bitrate is a mandatory rate
* when used with 802.11b (on the 2.4 GHz band); filled by the
* core code when registering the wiphy.
* @IEEE80211_RATE_MANDATORY_G: This bitrate is a mandatory rate
* when used with 802.11g (on the 2.4 GHz band); filled by the
* core code when registering the wiphy.
* @IEEE80211_RATE_ERP_G: This is an ERP rate in 802.11g mode.
* @IEEE80211_RATE_SUPPORTS_5MHZ: Rate can be used in 5 MHz mode
* @IEEE80211_RATE_SUPPORTS_10MHZ: Rate can be used in 10 MHz mode
*/
enum ieee80211_rate_flags {
IEEE80211_RATE_SHORT_PREAMBLE = 1<<0,
IEEE80211_RATE_MANDATORY_A = 1<<1,
IEEE80211_RATE_MANDATORY_B = 1<<2,
IEEE80211_RATE_MANDATORY_G = 1<<3,
IEEE80211_RATE_ERP_G = 1<<4,
IEEE80211_RATE_SUPPORTS_5MHZ = 1<<5,
IEEE80211_RATE_SUPPORTS_10MHZ = 1<<6,
};
/**
* struct ieee80211_supported_band - frequency band definition
*
* This structure describes a frequency band a wiphy
* is able to operate in.
*
* @channels: Array of channels the hardware can operate in
* in this band.
* @band: the band this structure represents
* @n_channels: Number of channels in @channels
* @bitrates: Array of bitrates the hardware can operate with
* in this band. Must be sorted to give a valid "supported
* rates" IE, i.e. CCK rates first, then OFDM.
* @n_bitrates: Number of bitrates in @bitrates
* @ht_cap: HT capabilities in this band
* @vht_cap: VHT capabilities in this band
* @n_iftype_data: number of iftype data entries
* @iftype_data: interface type data entries. Note that the bits in
* @types_mask inside this structure cannot overlap (i.e. only
* one occurrence of each type is allowed across all instances of
* iftype_data).
*/
struct ieee80211_supported_band {
struct ieee80211_channel *channels;
struct ieee80211_rate *bitrates;
enum nl80211_band band;
int n_channels;
int n_bitrates;
struct ieee80211_sta_ht_cap ht_cap;
struct ieee80211_sta_vht_cap vht_cap;
u16 n_iftype_data;
const struct ieee80211_sband_iftype_data *iftype_data;
};
#endif /* ifndef USERSPACE_CFG80211_H */

View File

@ -0,0 +1,119 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* linux/lib/crc-ccitt.c
*/
/*
* Userspace port (c) 2019 Hak5
*/
#include "crc_ccit.h"
/*
* This mysterious table is just the CRC of each possible byte. It can be
* computed using the standard bit-at-a-time methods. The polynomial can
* be seen in entry 128, 0x8408. This corresponds to x^0 + x^5 + x^12.
* Add the implicit x^16, and you have the standard CRC-CCITT.
*/
u16 const crc_ccitt_table[256] = {
0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
};
/*
* Similar table to calculate CRC16 variant known as CRC-CCITT-FALSE
* Reflected bits order, does not augment final value.
*/
u16 const crc_ccitt_false_table[256] = {
0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7,
0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF,
0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6,
0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE,
0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485,
0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D,
0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4,
0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC,
0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823,
0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B,
0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12,
0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A,
0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41,
0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49,
0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70,
0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78,
0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F,
0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067,
0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E,
0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256,
0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D,
0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C,
0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634,
0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB,
0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3,
0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A,
0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92,
0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9,
0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1,
0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8,
0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0
};
/**
* crc_ccitt - recompute the CRC (CRC-CCITT variant) for the data
* buffer
* @crc: previous CRC value
* @buffer: data pointer
* @len: number of bytes in the buffer
*/
u16 crc_ccitt(u16 crc, u8 const *buffer, size_t len)
{
while (len--)
crc = crc_ccitt_byte(crc, *buffer++);
return crc;
}
/**
* crc_ccitt_false - recompute the CRC (CRC-CCITT-FALSE variant)
* for the data buffer
* @crc: previous CRC value
* @buffer: data pointer
* @len: number of bytes in the buffer
*/
u16 crc_ccitt_false(u16 crc, u8 const *buffer, size_t len)
{
while (len--)
crc = crc_ccitt_false_byte(crc, *buffer++);
return crc;
}

View File

@ -0,0 +1,31 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Userspace port (c) 2019 Hak5
*/
#ifndef __USERSPACE_CCIT_H__
#define __USERSPACE_CCIT_H__
#include <stdlib.h>
#include "kernel/types.h"
extern u16 const crc_ccitt_table[256];
extern u16 const crc_ccitt_false_table[256];
extern u16 crc_ccitt(u16 crc, const u8 *buffer, size_t len);
extern u16 crc_ccitt_false(u16 crc, const u8 *buffer, size_t len);
static inline u16 crc_ccitt_byte(u16 crc, const u8 c)
{
return (crc >> 8) ^ crc_ccitt_table[(crc ^ c) & 0xff];
}
static inline u16 crc_ccitt_false_byte(u16 crc, const u8 c)
{
return (crc << 8) ^ crc_ccitt_false_table[(crc >> 8) ^ c];
}
#endif /* ifndef USERSPACE_CCIT_H */

View File

@ -0,0 +1,92 @@
/*
*
* GPL-2.0-or-later
*
* Userspace port (C) 2019 Hak5 Inc
*
*/
#ifndef __USERSPACE_ENDIAN_H__
#define __USERSPACE_ENDIAN_H__
/** compatibility header for endian.h
* This is a simple compatibility shim to convert
* BSD/Linux endian macros to the Mac OS X equivalents.
* It is public domain.
* */
/* Derived from
*
* https://gist.githubusercontent.com/yinyin/2027912/raw/6b3e394dc6a37817410d66d6ba4d7cd6b8d5d03d/endian.h
*
*/
#if (defined(_WIN16) || defined(_WIN32) || defined(_WIN64) || defined(__WIN32__)) && !defined(__WINDOWS__)
#define __WINDOWS__
#endif
#if defined(__APPLE__)
#include <libkern/OSByteOrder.h>
#define htobe16(x) OSSwapHostToBigInt16(x)
#define htole16(x) OSSwapHostToLittleInt16(x)
#define be16toh(x) OSSwapBigToHostInt16(x)
#define le16toh(x) OSSwapLittleToHostInt16(x)
#define htobe32(x) OSSwapHostToBigInt32(x)
#define htole32(x) OSSwapHostToLittleInt32(x)
#define be32toh(x) OSSwapBigToHostInt32(x)
#define le32toh(x) OSSwapLittleToHostInt32(x)
#define htobe64(x) OSSwapHostToBigInt64(x)
#define htole64(x) OSSwapHostToLittleInt64(x)
#define be64toh(x) OSSwapBigToHostInt64(x)
#define le64toh(x) OSSwapLittleToHostInt64(x)
#elif defined(__WINDOWS__)
#include <winsock.h>
#define htobe16(x) htons(x)
#define htole16(x) (x)
#define be16toh(x) ntohs(x)
#define le16toh(x) (x)
#define htobe32(x) htonl(x)
#define htole32(x) (x)
#define be32toh(x) ntohl(x)
#define le32toh(x) (x)
#define htobe64(x) htonll(x)
#define htole64(x) (x)
#define be64toh(x) ntohll(x)
#define le64toh(x) (x)
#else
#include <endian.h>
#endif
#define cpu_to_le16(x) \
htole16(x)
#define le16_to_cpu(x) \
le16toh(x)
#define cpu_to_le32(x) \
htole32(x)
#define le32_to_cpu(x) \
le32toh(x)
#define cpu_to_be16(x) \
htobe16(x)
#define be16_to_cpu(x) \
be16toh(x)
#define cpu_to_be32(x) \
htobe32(x)
#define be32_to_cpu(x) \
be32toh(x)
#endif /* ifndef ENDIAN_H */

View File

@ -0,0 +1,80 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* INET An implementation of the TCP/IP protocol suite for the LINUX
* operating system. NET is implemented using the BSD Socket
* interface as the means of communication with the user level.
*
* Definitions for the Ethernet handlers.
*
* Version: @(#)eth.h 1.0.4 05/13/93
*
* Authors: Ross Biro
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
*
* Relocated to include/linux where it belongs by Alan Cox
* <gw4pts@gw4pts.ampr.org>
*/
/*
* Userspace port (c) 2019 Hak5
*/
#ifndef __USERSPACE_ETHERDEVICE_H__
#define __USERSPACE_ETHERDEVICE_H__
#include <stdbool.h>
#include "kernel/endian.h"
#include "kernel/if_ether.h"
#include "kernel/kernel.h"
#include "kernel/types.h"
/* Reserved Ethernet Addresses per IEEE 802.1Q */
static const u8 eth_reserved_addr_base[ETH_ALEN] __aligned(2) =
{ 0x01, 0x80, 0xc2, 0x00, 0x00, 0x00 };
#define eth_stp_addr eth_reserved_addr_base
/**
* is_link_local_ether_addr - Determine if given Ethernet address is link-local
* @addr: Pointer to a six-byte array containing the Ethernet address
*
* Return true if address is link local reserved addr (01:80:c2:00:00:0X) per
* IEEE 802.1Q 8.6.3 Frame filtering.
*
* Please note: addr must be aligned to u16.
*/
static inline bool is_link_local_ether_addr(const u8 *addr)
{
__be16 *a = (__be16 *)addr;
static const __be16 *b = (const __be16 *)eth_reserved_addr_base;
__be16 m = cpu_to_be16(0xfff0);
#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
return (((*(const u32 *)addr) ^ (*(const u32 *)b)) |
(__force int)((a[2] ^ b[2]) & m)) == 0;
#else
return ((a[0] ^ b[0]) | (a[1] ^ b[1]) | ((a[2] ^ b[2]) & m)) == 0;
#endif
}
/**
* is_zero_ether_addr - Determine if give Ethernet address is all zeros.
* @addr: Pointer to a six-byte array containing the Ethernet address
*
* Return true if the address is all zeroes.
*
* Please note: addr must be aligned to u16.
*/
static inline bool is_zero_ether_addr(const u8 *addr)
{
#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
return ((*(const u32 *)addr) | (*(const u16 *)(addr + 4))) == 0;
#else
return (*(const u16 *)(addr + 0) |
*(const u16 *)(addr + 2) |
*(const u16 *)(addr + 4)) == 0;
#endif
}
#endif /* ifndef USERSPACE_ETHERDEVICE_H */

View File

@ -0,0 +1,310 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* IEEE 802.11 defines
*
* Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen
* <jkmaline@cc.hut.fi>
* Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi>
* Copyright (c) 2005, Devicescape Software, Inc.
* Copyright (c) 2006, Michael Wu <flamingice@sourmilk.net>
* Copyright (c) 2013 - 2014 Intel Mobile Communications GmbH
* Copyright (c) 2016 - 2017 Intel Deutschland GmbH
* Copyright (c) 2018 - 2019 Intel Corporation
*/
/*
*
* Userspace port (C) 2019 Hak5 Inc
*
*/
#ifndef __USERSPACE_IEEE80211_H__
#define __USERSPACE_IEEE80211_H__
#include "kernel/kernel.h"
#include "kernel/nl80211.h"
#include "kernel/types.h"
#define WLAN_SA_QUERY_TR_ID_LEN 2
#define WLAN_MEMBERSHIP_LEN 8
#define WLAN_USER_POSITION_LEN 16
/* miscellaneous IEEE 802.11 constants */
#define IEEE80211_MAX_FRAG_THRESHOLD 2352
#define IEEE80211_MAX_RTS_THRESHOLD 2353
#define IEEE80211_MAX_AID 2007
#define IEEE80211_MAX_TIM_LEN 251
#define IEEE80211_MAX_MESH_PEERINGS 63
/* Maximum size for the MA-UNITDATA primitive, 802.11 standard section
6.2.1.1.2.
802.11e clarifies the figure in section 7.1.2. The frame body is
up to 2304 octets long (maximum MSDU size) plus any crypt overhead. */
#define IEEE80211_MAX_DATA_LEN 2304
/* 802.11ad extends maximum MSDU size for DMG (freq > 40Ghz) networks
* to 7920 bytes, see 8.2.3 General frame format
*/
#define IEEE80211_MAX_DATA_LEN_DMG 7920
/* 30 byte 4 addr hdr, 2 byte QoS, 2304 byte MSDU, 12 byte crypt, 4 byte FCS */
#define IEEE80211_MAX_FRAME_LEN 2352
/* Maximal size of an A-MSDU that can be transported in a HT BA session */
#define IEEE80211_MAX_MPDU_LEN_HT_BA 4095
/* Maximal size of an A-MSDU */
#define IEEE80211_MAX_MPDU_LEN_HT_3839 3839
#define IEEE80211_MAX_MPDU_LEN_HT_7935 7935
#define IEEE80211_MAX_MPDU_LEN_VHT_3895 3895
#define IEEE80211_MAX_MPDU_LEN_VHT_7991 7991
#define IEEE80211_MAX_MPDU_LEN_VHT_11454 11454
#define IEEE80211_MAX_SSID_LEN 32
#define IEEE80211_MAX_MESH_ID_LEN 32
#define IEEE80211_FIRST_TSPEC_TSID 8
#define IEEE80211_NUM_TIDS 16
/* number of user priorities 802.11 uses */
#define IEEE80211_NUM_UPS 8
/* number of ACs */
#define IEEE80211_NUM_ACS 4
#define IEEE80211_QOS_CTL_LEN 2
/* 1d tag mask */
#define IEEE80211_QOS_CTL_TAG1D_MASK 0x0007
/* TID mask */
#define IEEE80211_QOS_CTL_TID_MASK 0x000f
/* EOSP */
#define IEEE80211_QOS_CTL_EOSP 0x0010
/* ACK policy */
#define IEEE80211_QOS_CTL_ACK_POLICY_NORMAL 0x0000
#define IEEE80211_QOS_CTL_ACK_POLICY_NOACK 0x0020
#define IEEE80211_QOS_CTL_ACK_POLICY_NO_EXPL 0x0040
#define IEEE80211_QOS_CTL_ACK_POLICY_BLOCKACK 0x0060
#define IEEE80211_QOS_CTL_ACK_POLICY_MASK 0x0060
/* A-MSDU 802.11n */
#define IEEE80211_QOS_CTL_A_MSDU_PRESENT 0x0080
/* Mesh Control 802.11s */
#define IEEE80211_QOS_CTL_MESH_CONTROL_PRESENT 0x0100
/* Mesh Power Save Level */
#define IEEE80211_QOS_CTL_MESH_PS_LEVEL 0x0200
/* Mesh Receiver Service Period Initiated */
#define IEEE80211_QOS_CTL_RSPI 0x0400
/* U-APSD queue for WMM IEs sent by AP */
#define IEEE80211_WMM_IE_AP_QOSINFO_UAPSD (1<<7)
#define IEEE80211_WMM_IE_AP_QOSINFO_PARAM_SET_CNT_MASK 0x0f
/* U-APSD queues for WMM IEs sent by STA */
#define IEEE80211_WMM_IE_STA_QOSINFO_AC_VO (1<<0)
#define IEEE80211_WMM_IE_STA_QOSINFO_AC_VI (1<<1)
#define IEEE80211_WMM_IE_STA_QOSINFO_AC_BK (1<<2)
#define IEEE80211_WMM_IE_STA_QOSINFO_AC_BE (1<<3)
#define IEEE80211_WMM_IE_STA_QOSINFO_AC_MASK 0x0f
/* U-APSD max SP length for WMM IEs sent by STA */
#define IEEE80211_WMM_IE_STA_QOSINFO_SP_ALL 0x00
#define IEEE80211_WMM_IE_STA_QOSINFO_SP_2 0x01
#define IEEE80211_WMM_IE_STA_QOSINFO_SP_4 0x02
#define IEEE80211_WMM_IE_STA_QOSINFO_SP_6 0x03
#define IEEE80211_WMM_IE_STA_QOSINFO_SP_MASK 0x03
#define IEEE80211_WMM_IE_STA_QOSINFO_SP_SHIFT 5
#define IEEE80211_HT_CTL_LEN 4
/* 802.11 BAR control masks */
#define IEEE80211_BAR_CTRL_ACK_POLICY_NORMAL 0x0000
#define IEEE80211_BAR_CTRL_MULTI_TID 0x0002
#define IEEE80211_BAR_CTRL_CBMTID_COMPRESSED_BA 0x0004
#define IEEE80211_BAR_CTRL_TID_INFO_MASK 0xf000
#define IEEE80211_BAR_CTRL_TID_INFO_SHIFT 12
#define IEEE80211_HT_MCS_MASK_LEN 10
/**
* struct ieee80211_mcs_info - MCS information
* @rx_mask: RX mask
* @rx_highest: highest supported RX rate. If set represents
* the highest supported RX data rate in units of 1 Mbps.
* If this field is 0 this value should not be used to
* consider the highest RX data rate supported.
* @tx_params: TX parameters
*/
struct ieee80211_mcs_info {
u8 rx_mask[IEEE80211_HT_MCS_MASK_LEN];
__le16 rx_highest;
u8 tx_params;
u8 reserved[3];
} __packed;
/* 802.11n HT capability MSC set */
#define IEEE80211_HT_MCS_RX_HIGHEST_MASK 0x3ff
#define IEEE80211_HT_MCS_TX_DEFINED 0x01
#define IEEE80211_HT_MCS_TX_RX_DIFF 0x02
/* value 0 == 1 stream etc */
#define IEEE80211_HT_MCS_TX_MAX_STREAMS_MASK 0x0C
#define IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT 2
#define IEEE80211_HT_MCS_TX_MAX_STREAMS 4
#define IEEE80211_HT_MCS_TX_UNEQUAL_MODULATION 0x10
/*
* 802.11n D5.0 20.3.5 / 20.6 says:
* - indices 0 to 7 and 32 are single spatial stream
* - 8 to 31 are multiple spatial streams using equal modulation
* [8..15 for two streams, 16..23 for three and 24..31 for four]
* - remainder are multiple spatial streams using unequal modulation
*/
#define IEEE80211_HT_MCS_UNEQUAL_MODULATION_START 33
#define IEEE80211_HT_MCS_UNEQUAL_MODULATION_START_BYTE \
(IEEE80211_HT_MCS_UNEQUAL_MODULATION_START / 8)
/**
* struct ieee80211_ht_cap - HT capabilities
*
* This structure is the "HT capabilities element" as
* described in 802.11n D5.0 7.3.2.57
*/
struct ieee80211_ht_cap {
__le16 cap_info;
u8 ampdu_params_info;
/* 16 bytes MCS information */
struct ieee80211_mcs_info mcs;
__le16 extended_ht_cap_info;
__le32 tx_BF_cap_info;
u8 antenna_selection_info;
} __packed;
/* 802.11n HT capabilities masks (for cap_info) */
#define IEEE80211_HT_CAP_LDPC_CODING 0x0001
#define IEEE80211_HT_CAP_SUP_WIDTH_20_40 0x0002
#define IEEE80211_HT_CAP_SM_PS 0x000C
#define IEEE80211_HT_CAP_SM_PS_SHIFT 2
#define IEEE80211_HT_CAP_GRN_FLD 0x0010
#define IEEE80211_HT_CAP_SGI_20 0x0020
#define IEEE80211_HT_CAP_SGI_40 0x0040
#define IEEE80211_HT_CAP_TX_STBC 0x0080
#define IEEE80211_HT_CAP_RX_STBC 0x0300
#define IEEE80211_HT_CAP_RX_STBC_SHIFT 8
#define IEEE80211_HT_CAP_DELAY_BA 0x0400
#define IEEE80211_HT_CAP_MAX_AMSDU 0x0800
#define IEEE80211_HT_CAP_DSSSCCK40 0x1000
#define IEEE80211_HT_CAP_RESERVED 0x2000
#define IEEE80211_HT_CAP_40MHZ_INTOLERANT 0x4000
#define IEEE80211_HT_CAP_LSIG_TXOP_PROT 0x8000
/* 802.11n HT extended capabilities masks (for extended_ht_cap_info) */
#define IEEE80211_HT_EXT_CAP_PCO 0x0001
#define IEEE80211_HT_EXT_CAP_PCO_TIME 0x0006
#define IEEE80211_HT_EXT_CAP_PCO_TIME_SHIFT 1
#define IEEE80211_HT_EXT_CAP_MCS_FB 0x0300
#define IEEE80211_HT_EXT_CAP_MCS_FB_SHIFT 8
#define IEEE80211_HT_EXT_CAP_HTC_SUP 0x0400
#define IEEE80211_HT_EXT_CAP_RD_RESPONDER 0x0800
/* 802.11n HT capability AMPDU settings (for ampdu_params_info) */
#define IEEE80211_HT_AMPDU_PARM_FACTOR 0x03
#define IEEE80211_HT_AMPDU_PARM_DENSITY 0x1C
#define IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT 2
/**
* struct ieee80211_vht_mcs_info - VHT MCS information
* @rx_mcs_map: RX MCS map 2 bits for each stream, total 8 streams
* @rx_highest: Indicates highest long GI VHT PPDU data rate
* STA can receive. Rate expressed in units of 1 Mbps.
* If this field is 0 this value should not be used to
* consider the highest RX data rate supported.
* The top 3 bits of this field indicate the Maximum NSTS,total
* (a beamformee capability.)
* @tx_mcs_map: TX MCS map 2 bits for each stream, total 8 streams
* @tx_highest: Indicates highest long GI VHT PPDU data rate
* STA can transmit. Rate expressed in units of 1 Mbps.
* If this field is 0 this value should not be used to
* consider the highest TX data rate supported.
* The top 2 bits of this field are reserved, the
* 3rd bit from the top indiciates VHT Extended NSS BW
* Capability.
*/
struct ieee80211_vht_mcs_info {
__le16 rx_mcs_map;
__le16 rx_highest;
__le16 tx_mcs_map;
__le16 tx_highest;
} __packed;
/**
* struct ieee80211_he_cap_elem - HE capabilities element
*
* This structure is the "HE capabilities element" fixed fields as
* described in P802.11ax_D4.0 section 9.4.2.242.2 and 9.4.2.242.3
*/
struct ieee80211_he_cap_elem {
u8 mac_cap_info[6];
u8 phy_cap_info[11];
} __packed;
/**
* enum ieee80211_he_mcs_support - HE MCS support definitions
* @IEEE80211_HE_MCS_SUPPORT_0_7: MCSes 0-7 are supported for the
* number of streams
* @IEEE80211_HE_MCS_SUPPORT_0_9: MCSes 0-9 are supported
* @IEEE80211_HE_MCS_SUPPORT_0_11: MCSes 0-11 are supported
* @IEEE80211_HE_MCS_NOT_SUPPORTED: This number of streams isn't supported
*
* These definitions are used in each 2-bit subfield of the rx_mcs_*
* and tx_mcs_* fields of &struct ieee80211_he_mcs_nss_supp, which are
* both split into 8 subfields by number of streams. These values indicate
* which MCSes are supported for the number of streams the value appears
* for.
*/
enum ieee80211_he_mcs_support {
IEEE80211_HE_MCS_SUPPORT_0_7 = 0,
IEEE80211_HE_MCS_SUPPORT_0_9 = 1,
IEEE80211_HE_MCS_SUPPORT_0_11 = 2,
IEEE80211_HE_MCS_NOT_SUPPORTED = 3,
};
/**
* struct ieee80211_he_mcs_nss_supp - HE Tx/Rx HE MCS NSS Support Field
*
* This structure holds the data required for the Tx/Rx HE MCS NSS Support Field
* described in P802.11ax_D2.0 section 9.4.2.237.4
*
* @rx_mcs_80: Rx MCS map 2 bits for each stream, total 8 streams, for channel
* widths less than 80MHz.
* @tx_mcs_80: Tx MCS map 2 bits for each stream, total 8 streams, for channel
* widths less than 80MHz.
* @rx_mcs_160: Rx MCS map 2 bits for each stream, total 8 streams, for channel
* width 160MHz.
* @tx_mcs_160: Tx MCS map 2 bits for each stream, total 8 streams, for channel
* width 160MHz.
* @rx_mcs_80p80: Rx MCS map 2 bits for each stream, total 8 streams, for
* channel width 80p80MHz.
* @tx_mcs_80p80: Tx MCS map 2 bits for each stream, total 8 streams, for
* channel width 80p80MHz.
*/
struct ieee80211_he_mcs_nss_supp {
__le16 rx_mcs_80;
__le16 tx_mcs_80;
__le16 rx_mcs_160;
__le16 tx_mcs_160;
__le16 rx_mcs_80p80;
__le16 tx_mcs_80p80;
} __packed;
/* for operation_mode */
#define IEEE80211_HT_OP_MODE_PROTECTION 0x0003
#define IEEE80211_HT_OP_MODE_PROTECTION_NONE 0
#define IEEE80211_HT_OP_MODE_PROTECTION_NONMEMBER 1
#define IEEE80211_HT_OP_MODE_PROTECTION_20MHZ 2
#define IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED 3
#define IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT 0x0004
#define IEEE80211_HT_OP_MODE_NON_HT_STA_PRSNT 0x0010
#define IEEE80211_HT_OP_MODE_CCFS2_SHIFT 5
#define IEEE80211_HT_OP_MODE_CCFS2_MASK 0x1fe0
#endif /* ifndef USERSPACE_IEEE80211_H */

View File

@ -0,0 +1,368 @@
/*
* Copyright (c) 2017 Intel Deutschland GmbH
* Copyright (c) 2018-2019 Intel Corporation
*
* 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.
*/
#ifndef __RADIOTAP_H
#define __RADIOTAP_H
#include "kernel/kernel.h"
#include "kernel/types.h"
#include "kernel/le_byteshift.h"
/**
* struct ieee82011_radiotap_header - base radiotap header
*/
struct ieee80211_radiotap_header {
/**
* @it_version: radiotap version, always 0
*/
uint8_t it_version;
/**
* @it_pad: padding (or alignment)
*/
uint8_t it_pad;
/**
* @it_len: overall radiotap header length
*/
__le16 it_len;
/**
* @it_present: (first) present word
*/
__le32 it_present;
} __packed;
/* version is always 0 */
#define PKTHDR_RADIOTAP_VERSION 0
/* see the radiotap website for the descriptions */
enum ieee80211_radiotap_presence {
IEEE80211_RADIOTAP_TSFT = 0,
IEEE80211_RADIOTAP_FLAGS = 1,
IEEE80211_RADIOTAP_RATE = 2,
IEEE80211_RADIOTAP_CHANNEL = 3,
IEEE80211_RADIOTAP_FHSS = 4,
IEEE80211_RADIOTAP_DBM_ANTSIGNAL = 5,
IEEE80211_RADIOTAP_DBM_ANTNOISE = 6,
IEEE80211_RADIOTAP_LOCK_QUALITY = 7,
IEEE80211_RADIOTAP_TX_ATTENUATION = 8,
IEEE80211_RADIOTAP_DB_TX_ATTENUATION = 9,
IEEE80211_RADIOTAP_DBM_TX_POWER = 10,
IEEE80211_RADIOTAP_ANTENNA = 11,
IEEE80211_RADIOTAP_DB_ANTSIGNAL = 12,
IEEE80211_RADIOTAP_DB_ANTNOISE = 13,
IEEE80211_RADIOTAP_RX_FLAGS = 14,
IEEE80211_RADIOTAP_TX_FLAGS = 15,
IEEE80211_RADIOTAP_RTS_RETRIES = 16,
IEEE80211_RADIOTAP_DATA_RETRIES = 17,
/* 18 is XChannel, but it's not defined yet */
IEEE80211_RADIOTAP_MCS = 19,
IEEE80211_RADIOTAP_AMPDU_STATUS = 20,
IEEE80211_RADIOTAP_VHT = 21,
IEEE80211_RADIOTAP_TIMESTAMP = 22,
IEEE80211_RADIOTAP_HE = 23,
IEEE80211_RADIOTAP_HE_MU = 24,
IEEE80211_RADIOTAP_ZERO_LEN_PSDU = 26,
IEEE80211_RADIOTAP_LSIG = 27,
/* valid in every it_present bitmap, even vendor namespaces */
IEEE80211_RADIOTAP_RADIOTAP_NAMESPACE = 29,
IEEE80211_RADIOTAP_VENDOR_NAMESPACE = 30,
IEEE80211_RADIOTAP_EXT = 31
};
/* for IEEE80211_RADIOTAP_FLAGS */
enum ieee80211_radiotap_flags {
IEEE80211_RADIOTAP_F_CFP = 0x01,
IEEE80211_RADIOTAP_F_SHORTPRE = 0x02,
IEEE80211_RADIOTAP_F_WEP = 0x04,
IEEE80211_RADIOTAP_F_FRAG = 0x08,
IEEE80211_RADIOTAP_F_FCS = 0x10,
IEEE80211_RADIOTAP_F_DATAPAD = 0x20,
IEEE80211_RADIOTAP_F_BADFCS = 0x40,
IEEE80211_RADIOTAP_F_SHORTGI = 0x80,
};
/* for IEEE80211_RADIOTAP_CHANNEL */
enum ieee80211_radiotap_channel_flags {
IEEE80211_CHAN_CCK = 0x0020,
IEEE80211_CHAN_OFDM = 0x0040,
IEEE80211_CHAN_2GHZ = 0x0080,
IEEE80211_CHAN_5GHZ = 0x0100,
IEEE80211_CHAN_DYN = 0x0400,
IEEE80211_CHAN_HALF = 0x4000,
IEEE80211_CHAN_QUARTER = 0x8000,
};
/* for IEEE80211_RADIOTAP_RX_FLAGS */
enum ieee80211_radiotap_rx_flags {
IEEE80211_RADIOTAP_F_RX_BADPLCP = 0x0002,
};
/* for IEEE80211_RADIOTAP_TX_FLAGS */
enum ieee80211_radiotap_tx_flags {
IEEE80211_RADIOTAP_F_TX_FAIL = 0x0001,
IEEE80211_RADIOTAP_F_TX_CTS = 0x0002,
IEEE80211_RADIOTAP_F_TX_RTS = 0x0004,
IEEE80211_RADIOTAP_F_TX_NOACK = 0x0008,
};
/* for IEEE80211_RADIOTAP_MCS "have" flags */
enum ieee80211_radiotap_mcs_have {
IEEE80211_RADIOTAP_MCS_HAVE_BW = 0x01,
IEEE80211_RADIOTAP_MCS_HAVE_MCS = 0x02,
IEEE80211_RADIOTAP_MCS_HAVE_GI = 0x04,
IEEE80211_RADIOTAP_MCS_HAVE_FMT = 0x08,
IEEE80211_RADIOTAP_MCS_HAVE_FEC = 0x10,
IEEE80211_RADIOTAP_MCS_HAVE_STBC = 0x20,
};
enum ieee80211_radiotap_mcs_flags {
IEEE80211_RADIOTAP_MCS_BW_MASK = 0x03,
IEEE80211_RADIOTAP_MCS_BW_20 = 0,
IEEE80211_RADIOTAP_MCS_BW_40 = 1,
IEEE80211_RADIOTAP_MCS_BW_20L = 2,
IEEE80211_RADIOTAP_MCS_BW_20U = 3,
IEEE80211_RADIOTAP_MCS_SGI = 0x04,
IEEE80211_RADIOTAP_MCS_FMT_GF = 0x08,
IEEE80211_RADIOTAP_MCS_FEC_LDPC = 0x10,
IEEE80211_RADIOTAP_MCS_STBC_MASK = 0x60,
IEEE80211_RADIOTAP_MCS_STBC_1 = 1,
IEEE80211_RADIOTAP_MCS_STBC_2 = 2,
IEEE80211_RADIOTAP_MCS_STBC_3 = 3,
IEEE80211_RADIOTAP_MCS_STBC_SHIFT = 5,
};
/* for IEEE80211_RADIOTAP_AMPDU_STATUS */
enum ieee80211_radiotap_ampdu_flags {
IEEE80211_RADIOTAP_AMPDU_REPORT_ZEROLEN = 0x0001,
IEEE80211_RADIOTAP_AMPDU_IS_ZEROLEN = 0x0002,
IEEE80211_RADIOTAP_AMPDU_LAST_KNOWN = 0x0004,
IEEE80211_RADIOTAP_AMPDU_IS_LAST = 0x0008,
IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_ERR = 0x0010,
IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_KNOWN = 0x0020,
IEEE80211_RADIOTAP_AMPDU_EOF = 0x0040,
IEEE80211_RADIOTAP_AMPDU_EOF_KNOWN = 0x0080,
};
/* for IEEE80211_RADIOTAP_VHT */
enum ieee80211_radiotap_vht_known {
IEEE80211_RADIOTAP_VHT_KNOWN_STBC = 0x0001,
IEEE80211_RADIOTAP_VHT_KNOWN_TXOP_PS_NA = 0x0002,
IEEE80211_RADIOTAP_VHT_KNOWN_GI = 0x0004,
IEEE80211_RADIOTAP_VHT_KNOWN_SGI_NSYM_DIS = 0x0008,
IEEE80211_RADIOTAP_VHT_KNOWN_LDPC_EXTRA_OFDM_SYM = 0x0010,
IEEE80211_RADIOTAP_VHT_KNOWN_BEAMFORMED = 0x0020,
IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH = 0x0040,
IEEE80211_RADIOTAP_VHT_KNOWN_GROUP_ID = 0x0080,
IEEE80211_RADIOTAP_VHT_KNOWN_PARTIAL_AID = 0x0100,
};
enum ieee80211_radiotap_vht_flags {
IEEE80211_RADIOTAP_VHT_FLAG_STBC = 0x01,
IEEE80211_RADIOTAP_VHT_FLAG_TXOP_PS_NA = 0x02,
IEEE80211_RADIOTAP_VHT_FLAG_SGI = 0x04,
IEEE80211_RADIOTAP_VHT_FLAG_SGI_NSYM_M10_9 = 0x08,
IEEE80211_RADIOTAP_VHT_FLAG_LDPC_EXTRA_OFDM_SYM = 0x10,
IEEE80211_RADIOTAP_VHT_FLAG_BEAMFORMED = 0x20,
};
enum ieee80211_radiotap_vht_coding {
IEEE80211_RADIOTAP_CODING_LDPC_USER0 = 0x01,
IEEE80211_RADIOTAP_CODING_LDPC_USER1 = 0x02,
IEEE80211_RADIOTAP_CODING_LDPC_USER2 = 0x04,
IEEE80211_RADIOTAP_CODING_LDPC_USER3 = 0x08,
};
/* for IEEE80211_RADIOTAP_TIMESTAMP */
enum ieee80211_radiotap_timestamp_unit_spos {
IEEE80211_RADIOTAP_TIMESTAMP_UNIT_MASK = 0x000F,
IEEE80211_RADIOTAP_TIMESTAMP_UNIT_MS = 0x0000,
IEEE80211_RADIOTAP_TIMESTAMP_UNIT_US = 0x0001,
IEEE80211_RADIOTAP_TIMESTAMP_UNIT_NS = 0x0003,
IEEE80211_RADIOTAP_TIMESTAMP_SPOS_MASK = 0x00F0,
IEEE80211_RADIOTAP_TIMESTAMP_SPOS_BEGIN_MDPU = 0x0000,
IEEE80211_RADIOTAP_TIMESTAMP_SPOS_PLCP_SIG_ACQ = 0x0010,
IEEE80211_RADIOTAP_TIMESTAMP_SPOS_EO_PPDU = 0x0020,
IEEE80211_RADIOTAP_TIMESTAMP_SPOS_EO_MPDU = 0x0030,
IEEE80211_RADIOTAP_TIMESTAMP_SPOS_UNKNOWN = 0x00F0,
};
enum ieee80211_radiotap_timestamp_flags {
IEEE80211_RADIOTAP_TIMESTAMP_FLAG_64BIT = 0x00,
IEEE80211_RADIOTAP_TIMESTAMP_FLAG_32BIT = 0x01,
IEEE80211_RADIOTAP_TIMESTAMP_FLAG_ACCURACY = 0x02,
};
struct ieee80211_radiotap_he {
__le16 data1, data2, data3, data4, data5, data6;
};
enum ieee80211_radiotap_he_bits {
IEEE80211_RADIOTAP_HE_DATA1_FORMAT_MASK = 3,
IEEE80211_RADIOTAP_HE_DATA1_FORMAT_SU = 0,
IEEE80211_RADIOTAP_HE_DATA1_FORMAT_EXT_SU = 1,
IEEE80211_RADIOTAP_HE_DATA1_FORMAT_MU = 2,
IEEE80211_RADIOTAP_HE_DATA1_FORMAT_TRIG = 3,
IEEE80211_RADIOTAP_HE_DATA1_BSS_COLOR_KNOWN = 0x0004,
IEEE80211_RADIOTAP_HE_DATA1_BEAM_CHANGE_KNOWN = 0x0008,
IEEE80211_RADIOTAP_HE_DATA1_UL_DL_KNOWN = 0x0010,
IEEE80211_RADIOTAP_HE_DATA1_DATA_MCS_KNOWN = 0x0020,
IEEE80211_RADIOTAP_HE_DATA1_DATA_DCM_KNOWN = 0x0040,
IEEE80211_RADIOTAP_HE_DATA1_CODING_KNOWN = 0x0080,
IEEE80211_RADIOTAP_HE_DATA1_LDPC_XSYMSEG_KNOWN = 0x0100,
IEEE80211_RADIOTAP_HE_DATA1_STBC_KNOWN = 0x0200,
IEEE80211_RADIOTAP_HE_DATA1_SPTL_REUSE_KNOWN = 0x0400,
IEEE80211_RADIOTAP_HE_DATA1_SPTL_REUSE2_KNOWN = 0x0800,
IEEE80211_RADIOTAP_HE_DATA1_SPTL_REUSE3_KNOWN = 0x1000,
IEEE80211_RADIOTAP_HE_DATA1_SPTL_REUSE4_KNOWN = 0x2000,
IEEE80211_RADIOTAP_HE_DATA1_BW_RU_ALLOC_KNOWN = 0x4000,
IEEE80211_RADIOTAP_HE_DATA1_DOPPLER_KNOWN = 0x8000,
IEEE80211_RADIOTAP_HE_DATA2_PRISEC_80_KNOWN = 0x0001,
IEEE80211_RADIOTAP_HE_DATA2_GI_KNOWN = 0x0002,
IEEE80211_RADIOTAP_HE_DATA2_NUM_LTF_SYMS_KNOWN = 0x0004,
IEEE80211_RADIOTAP_HE_DATA2_PRE_FEC_PAD_KNOWN = 0x0008,
IEEE80211_RADIOTAP_HE_DATA2_TXBF_KNOWN = 0x0010,
IEEE80211_RADIOTAP_HE_DATA2_PE_DISAMBIG_KNOWN = 0x0020,
IEEE80211_RADIOTAP_HE_DATA2_TXOP_KNOWN = 0x0040,
IEEE80211_RADIOTAP_HE_DATA2_MIDAMBLE_KNOWN = 0x0080,
IEEE80211_RADIOTAP_HE_DATA2_RU_OFFSET = 0x3f00,
IEEE80211_RADIOTAP_HE_DATA2_RU_OFFSET_KNOWN = 0x4000,
IEEE80211_RADIOTAP_HE_DATA2_PRISEC_80_SEC = 0x8000,
IEEE80211_RADIOTAP_HE_DATA3_BSS_COLOR = 0x003f,
IEEE80211_RADIOTAP_HE_DATA3_BEAM_CHANGE = 0x0040,
IEEE80211_RADIOTAP_HE_DATA3_UL_DL = 0x0080,
IEEE80211_RADIOTAP_HE_DATA3_DATA_MCS = 0x0f00,
IEEE80211_RADIOTAP_HE_DATA3_DATA_DCM = 0x1000,
IEEE80211_RADIOTAP_HE_DATA3_CODING = 0x2000,
IEEE80211_RADIOTAP_HE_DATA3_LDPC_XSYMSEG = 0x4000,
IEEE80211_RADIOTAP_HE_DATA3_STBC = 0x8000,
IEEE80211_RADIOTAP_HE_DATA4_SU_MU_SPTL_REUSE = 0x000f,
IEEE80211_RADIOTAP_HE_DATA4_MU_STA_ID = 0x7ff0,
IEEE80211_RADIOTAP_HE_DATA4_TB_SPTL_REUSE1 = 0x000f,
IEEE80211_RADIOTAP_HE_DATA4_TB_SPTL_REUSE2 = 0x00f0,
IEEE80211_RADIOTAP_HE_DATA4_TB_SPTL_REUSE3 = 0x0f00,
IEEE80211_RADIOTAP_HE_DATA4_TB_SPTL_REUSE4 = 0xf000,
IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC = 0x000f,
IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_20MHZ = 0,
IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_40MHZ = 1,
IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_80MHZ = 2,
IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_160MHZ = 3,
IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_26T = 4,
IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_52T = 5,
IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_106T = 6,
IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_242T = 7,
IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_484T = 8,
IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_996T = 9,
IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_2x996T = 10,
IEEE80211_RADIOTAP_HE_DATA5_GI = 0x0030,
IEEE80211_RADIOTAP_HE_DATA5_GI_0_8 = 0,
IEEE80211_RADIOTAP_HE_DATA5_GI_1_6 = 1,
IEEE80211_RADIOTAP_HE_DATA5_GI_3_2 = 2,
IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE = 0x00c0,
IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_UNKNOWN = 0,
IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_1X = 1,
IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_2X = 2,
IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_4X = 3,
IEEE80211_RADIOTAP_HE_DATA5_NUM_LTF_SYMS = 0x0700,
IEEE80211_RADIOTAP_HE_DATA5_PRE_FEC_PAD = 0x3000,
IEEE80211_RADIOTAP_HE_DATA5_TXBF = 0x4000,
IEEE80211_RADIOTAP_HE_DATA5_PE_DISAMBIG = 0x8000,
IEEE80211_RADIOTAP_HE_DATA6_NSTS = 0x000f,
IEEE80211_RADIOTAP_HE_DATA6_DOPPLER = 0x0010,
IEEE80211_RADIOTAP_HE_DATA6_TB_PPDU_BW_KNOWN = 0x0020,
IEEE80211_RADIOTAP_HE_DATA6_TB_PPDU_BW = 0x00c0,
IEEE80211_RADIOTAP_HE_DATA6_TB_PPDU_BW_20MHZ = 0,
IEEE80211_RADIOTAP_HE_DATA6_TB_PPDU_BW_40MHZ = 1,
IEEE80211_RADIOTAP_HE_DATA6_TB_PPDU_BW_80MHZ = 2,
IEEE80211_RADIOTAP_HE_DATA6_TB_PPDU_BW_160MHZ = 3,
IEEE80211_RADIOTAP_HE_DATA6_TXOP = 0x7f00,
IEEE80211_RADIOTAP_HE_DATA6_MIDAMBLE_PDCTY = 0x8000,
};
struct ieee80211_radiotap_he_mu {
__le16 flags1, flags2;
u8 ru_ch1[4];
u8 ru_ch2[4];
};
enum ieee80211_radiotap_he_mu_bits {
IEEE80211_RADIOTAP_HE_MU_FLAGS1_SIG_B_MCS = 0x000f,
IEEE80211_RADIOTAP_HE_MU_FLAGS1_SIG_B_MCS_KNOWN = 0x0010,
IEEE80211_RADIOTAP_HE_MU_FLAGS1_SIG_B_DCM = 0x0020,
IEEE80211_RADIOTAP_HE_MU_FLAGS1_SIG_B_DCM_KNOWN = 0x0040,
IEEE80211_RADIOTAP_HE_MU_FLAGS1_CH2_CTR_26T_RU_KNOWN = 0x0080,
IEEE80211_RADIOTAP_HE_MU_FLAGS1_CH1_RU_KNOWN = 0x0100,
IEEE80211_RADIOTAP_HE_MU_FLAGS1_CH2_RU_KNOWN = 0x0200,
IEEE80211_RADIOTAP_HE_MU_FLAGS1_CH1_CTR_26T_RU_KNOWN = 0x1000,
IEEE80211_RADIOTAP_HE_MU_FLAGS1_CH1_CTR_26T_RU = 0x2000,
IEEE80211_RADIOTAP_HE_MU_FLAGS1_SIG_B_COMP_KNOWN = 0x4000,
IEEE80211_RADIOTAP_HE_MU_FLAGS1_SIG_B_SYMS_USERS_KNOWN = 0x8000,
IEEE80211_RADIOTAP_HE_MU_FLAGS2_BW_FROM_SIG_A_BW = 0x0003,
IEEE80211_RADIOTAP_HE_MU_FLAGS2_BW_FROM_SIG_A_BW_20MHZ = 0x0000,
IEEE80211_RADIOTAP_HE_MU_FLAGS2_BW_FROM_SIG_A_BW_40MHZ = 0x0001,
IEEE80211_RADIOTAP_HE_MU_FLAGS2_BW_FROM_SIG_A_BW_80MHZ = 0x0002,
IEEE80211_RADIOTAP_HE_MU_FLAGS2_BW_FROM_SIG_A_BW_160MHZ = 0x0003,
IEEE80211_RADIOTAP_HE_MU_FLAGS2_BW_FROM_SIG_A_BW_KNOWN = 0x0004,
IEEE80211_RADIOTAP_HE_MU_FLAGS2_SIG_B_COMP = 0x0008,
IEEE80211_RADIOTAP_HE_MU_FLAGS2_SIG_B_SYMS_USERS = 0x00f0,
IEEE80211_RADIOTAP_HE_MU_FLAGS2_PUNC_FROM_SIG_A_BW = 0x0300,
IEEE80211_RADIOTAP_HE_MU_FLAGS2_PUNC_FROM_SIG_A_BW_KNOWN= 0x0400,
IEEE80211_RADIOTAP_HE_MU_FLAGS2_CH2_CTR_26T_RU = 0x0800,
};
enum ieee80211_radiotap_lsig_data1 {
IEEE80211_RADIOTAP_LSIG_DATA1_RATE_KNOWN = 0x0001,
IEEE80211_RADIOTAP_LSIG_DATA1_LENGTH_KNOWN = 0x0002,
};
enum ieee80211_radiotap_lsig_data2 {
IEEE80211_RADIOTAP_LSIG_DATA2_RATE = 0x000f,
IEEE80211_RADIOTAP_LSIG_DATA2_LENGTH = 0xfff0,
};
struct ieee80211_radiotap_lsig {
__le16 data1, data2;
};
enum ieee80211_radiotap_zero_len_psdu_type {
IEEE80211_RADIOTAP_ZERO_LEN_PSDU_SOUNDING = 0,
IEEE80211_RADIOTAP_ZERO_LEN_PSDU_NOT_CAPTURED = 1,
IEEE80211_RADIOTAP_ZERO_LEN_PSDU_VENDOR = 0xff,
};
/**
* ieee80211_get_radiotap_len - get radiotap header length
*/
static inline u16 ieee80211_get_radiotap_len(const char *data)
{
struct ieee80211_radiotap_header *hdr = (struct ieee80211_radiotap_header *)data;
return get_unaligned_le16(&hdr->it_len);
}
#endif /* __RADIOTAP_H */

View File

@ -0,0 +1,31 @@
/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */
/*
* 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 Ethernet IEEE 802.3 interface.
*
* Version: @(#)if_ether.h 1.0.1a 02/08/94
*
* Author: Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
* Donald Becker, <becker@super.org>
* Alan Cox, <alan@lxorguk.ukuu.org.uk>
* Steve Whitehouse, <gw7rrm@eeshack3.swan.ac.uk>
*
* 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.
*/
/*
* Userspace port (c) 2019 Hak5
*/
#ifndef __USERSPACE_IF_ETHER_H__
#define __USERSPACE_IF_ETHER_H__
#define ETH_ALEN 6
#endif /* ifndef USERSPACE_IF_ETHER_H */

View File

@ -0,0 +1,265 @@
/*
* GPL-2.0-or-later
*
* Userspace port (C) 2019 Hak5 Inc
*
*/
#ifndef __USERSPACE_KERNEL_H__
#define __USERSPACE_KERNEL_H__
/*
* Define some kernel nomenclature and functions that we just transpose into
* normal gcc-isms, along with modified BUG_ON, WARN_ON, etc.
*/
#if !defined(_WIN32)
#define __packed __attribute__((packed))
#define __aligned(nr) __attribute__((aligned (nr)))
#else
#define __packed
#define __aligned(nr)
#endif
#define __rcu
#ifndef __attribute_const__
#define __attribute_const__
#endif
#if defined(_MSC_VER)
/* Hack all constant compares to be true for MSC */
#define __builtin_constant_p(x) (1)
/* Use ternary to simulate builtin choose expr */
#define __builtin_choose_expr(e, t, f) ((e) ? (t) : (f))
#endif
/*
* Just test
*/
#define unlikely(x) (x)
#define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)]))
#define BUILD_BUG_ON_ZERO(e) (sizeof(struct { int:-!!(e); }))
/* Force a compilation error if a constant expression is not a power of 2 */
#define __BUILD_BUG_ON_NOT_POWER_OF_2(n) \
BUILD_BUG_ON(((n) & ((n) - 1)) != 0)
#define BUILD_BUG_ON_NOT_POWER_OF_2(n) \
BUILD_BUG_ON((n) == 0 || (((n) & ((n) - 1)) != 0))
#define BUG_ON(condition) do { if (unlikely(condition)) BUG(); } while (0)
#define BUG() do { \
fprintf(stderr, "BUG: failure at %s:%d/%s()!\n", __FILE__, __LINE__, __func__); \
exit(-1); \
} while (0)
#define WARN_ONCE(condition, fmt, ...) \
do { if (condition) fprintf(stderr, "%s: WARNING - " fmt, __func__, ##__VA_ARGS__); } while (0)
#define WARN_ON_ONCE(condition) (condition)
#define WARN_ON(condition) do { if (unlikely(condition)) WARN(); } while (0)
#define WARN() do { \
fprintf(stderr, "WARNING: warning at %s:%d/%s()!\n", __FILE__, __LINE__, __func__); \
} while (0)
#define READ_ONCE(x) (x)
#define WRITE_ONCE(t, v) ((t) = (v))
/*
* We don't currently do kernel mutexes; this could be re-def'd to pthread
* mutexes if we need to
*/
#if 0
#define mutex_lock(x) pthread_mutex_lock((x))
#define mutex_unlock(x) pthread_mutex_unlock((x))
#else
#define mutex_lock(x)
#define mutex_unlock(x)
#endif
/*
* Just treat sleeps and delays as usleeps
*/
#define msleep(x) usleep(x * 1000)
#define udelay(x) usleep(x)
#define usleep_range(x, y) usleep(y)
/*
* Modified and simplified from the kernel macros
*/
#define __cmp(x, y, op) ((x) op (y) ? (x) : (y))
/**
* min_t - return minimum of two values, using the specified type
* @type: data type to use
* @x: first value
* @y: second value
*/
#define min_t(type, x, y) __cmp((type)(x), (type)(y), <)
/**
* max_t - return maximum of two values, using the specified type
* @type: data type to use
* @x: first value
* @y: second value
*/
#define max_t(type, x, y) __cmp((type)(x), (type)(y), >)
/**
* max - return maximum of two values of the same or compatible types
* @x: first value
* @y: second value
*/
#define max(x, y) __cmp(x, y, >)
/*
* This looks more complex than it should be. But we need to
* get the type for the ~ right in round_down (it needs to be
* as wide as the result!), and we want to evaluate the macro
* arguments just once each.
*/
#define __round_mask(x, y) ((__typeof__(x))((y)-1))
/**
* round_up - round up to next specified power of 2
* @x: the value to round
* @y: multiple to round up to (must be a power of 2)
*
* Rounds @x up to next multiple of @y (which must be a power of 2).
* To perform arbitrary rounding up, use roundup() below.
*/
#ifndef round_up
#define round_up(x, y) ((((x)-1) | __round_mask(x, y))+1)
#endif
/**
* round_down - round down to next specified power of 2
* @x: the value to round
* @y: multiple to round down to (must be a power of 2)
*
* Rounds @x down to next multiple of @y (which must be a power of 2).
* To perform arbitrary rounding down, use rounddown() below.
*/
#ifndef round_down
#define round_down(x, y) ((x) & ~__round_mask(x, y))
#endif
/**
* FIELD_SIZEOF - get the size of a struct's field
* @t: the target struct
* @f: the target struct's field
* Return: the size of @f in the struct definition without having a
* declared instance of @t.
*/
#define FIELD_SIZEOF(t, f) (sizeof(((t*)0)->f))
#define DIV_ROUND_UP __KERNEL_DIV_ROUND_UP
#define DIV_ROUND_DOWN_ULL(ll, d) \
({ unsigned long long _tmp = (ll); do_div(_tmp, d); _tmp; })
#define DIV_ROUND_UP_ULL(ll, d) \
DIV_ROUND_DOWN_ULL((unsigned long long)(ll) + (d) - 1, (d))
#if BITS_PER_LONG == 32
# define DIV_ROUND_UP_SECTOR_T(ll,d) DIV_ROUND_UP_ULL(ll, d)
#else
# define DIV_ROUND_UP_SECTOR_T(ll,d) DIV_ROUND_UP(ll,d)
#endif
/**
* roundup - round up to the next specified multiple
* @x: the value to up
* @y: multiple to round up to
*
* Rounds @x up to next multiple of @y. If @y will always be a power
* of 2, consider using the faster round_up().
*/
#define roundup(x, y) ( \
{ \
typeof(y) __y = y; \
(((x) + (__y - 1)) / __y) * __y; \
} \
)
/**
* rounddown - round down to next specified multiple
* @x: the value to round
* @y: multiple to round down to
*
* Rounds @x down to next multiple of @y. If @y will always be a power
* of 2, consider using the faster round_down().
*/
#define rounddown(x, y) ( \
{ \
typeof(x) __x = (x); \
__x - (__x % (y)); \
} \
)
/*
* Divide positive or negative dividend by positive or negative divisor
* and round to closest integer. Result is undefined for negative
* divisors if the dividend variable type is unsigned and for negative
* dividends if the divisor variable type is unsigned.
*/
#define DIV_ROUND_CLOSEST(x, divisor)( \
{ \
typeof(x) __x = x; \
typeof(divisor) __d = divisor; \
(((typeof(x))-1) > 0 || \
((typeof(divisor))-1) > 0 || \
(((__x) > 0) == ((__d) > 0))) ? \
(((__x) + ((__d) / 2)) / (__d)) : \
(((__x) - ((__d) / 2)) / (__d)); \
} \
)
/*
* Same as above but for u64 dividends. divisor must be a 32-bit
* number.
*/
#define DIV_ROUND_CLOSEST_ULL(x, divisor)( \
{ \
typeof(divisor) __d = divisor; \
unsigned long long _tmp = (x) + (__d) / 2; \
do_div(_tmp, __d); \
_tmp; \
} \
)
#define __KERNEL_DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d))
/* Are two types/vars the same type (ignoring qualifiers)? */
#define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b))
/* &a[0] degrades to a pointer: a different type from an array */
#define __must_be_array(a) BUILD_BUG_ON_ZERO(__same_type((a), &(a)[0]))
/**
* ARRAY_SIZE - get the number of elements in array @arr
* @arr: array to be sized
*/
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
/*
* Kluge in ENOTSUPP which isn't in userspace
*/
#define ENOTSUPP 524
/*
* Kluge in symbol masking
*/
#define EXPORT_SYMBOL_GPL(x)
#define EXPORT_SYMBOL(x)
#define GFP_KERNEL
/*
* Hack kalloc to malloc
*/
#define kcalloc(nelem, sz, type) malloc(nelem * sz)
#define kfree(n) free(n)
#endif /* ifndef KERNEL_H */

View File

@ -0,0 +1,76 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Userspace port (c) 2019 Hak5 LLC
*/
#ifndef _USERSPACE_LINUX_UNALIGNED_LE_BYTESHIFT_H
#define _USERSPACE_LINUX_UNALIGNED_LE_BYTESHIFT_H
#include "kernel/types.h"
static inline u16 __get_unaligned_le16(const u8 *p)
{
return p[0] | p[1] << 8;
}
static inline u32 __get_unaligned_le32(const u8 *p)
{
return p[0] | p[1] << 8 | p[2] << 16 | p[3] << 24;
}
static inline u64 __get_unaligned_le64(const u8 *p)
{
return (u64)__get_unaligned_le32(p + 4) << 32 |
__get_unaligned_le32(p);
}
static inline void __put_unaligned_le16(u16 val, u8 *p)
{
*p++ = val;
*p++ = val >> 8;
}
static inline void __put_unaligned_le32(u32 val, u8 *p)
{
__put_unaligned_le16(val >> 16, p + 2);
__put_unaligned_le16(val, p);
}
static inline void __put_unaligned_le64(u64 val, u8 *p)
{
__put_unaligned_le32(val >> 32, p + 4);
__put_unaligned_le32(val, p);
}
static inline u16 get_unaligned_le16(const void *p)
{
return __get_unaligned_le16((const u8 *)p);
}
static inline u32 get_unaligned_le32(const void *p)
{
return __get_unaligned_le32((const u8 *)p);
}
static inline u64 get_unaligned_le64(const void *p)
{
return __get_unaligned_le64((const u8 *)p);
}
static inline void put_unaligned_le16(u16 val, void *p)
{
__put_unaligned_le16(val, (u8 *) p);
}
static inline void put_unaligned_le32(u32 val, void *p)
{
__put_unaligned_le32(val, (u8 *) p);
}
static inline void put_unaligned_le64(u64 val, void *p)
{
__put_unaligned_le64(val, (u8 *) p);
}
#endif /* _USERSPACE_LINUX_UNALIGNED_LE_BYTESHIFT_H */

View File

@ -0,0 +1,229 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/* Integer base 2 logarithm calculation
*
* Copyright (C) 2006 Red Hat, Inc. All Rights Reserved.
* Written by David Howells (dhowells@redhat.com)
*/
/* Userspace port (c) 2019 Hak5
*/
#ifndef __USERSPACE_LOG2_H__
#define __USERSPACE_LOG2_H__
#include "types.h"
#include "bitops.h"
/*
* non-constant log of base 2 calculators
* - the arch may override these in asm/bitops.h if they can be implemented
* more efficiently than using fls() and fls64()
* - the arch is not required to handle n==0 if implementing the fallback
*/
#ifndef CONFIG_ARCH_HAS_ILOG2_U32
static inline const
int __ilog2_u32(u32 n)
{
return __fls(n) - 1;
}
#endif
#ifndef CONFIG_ARCH_HAS_ILOG2_U64
static inline const
int __ilog2_u64(u64 n)
{
return __fls64(n) - 1;
}
#endif
/**
* is_power_of_2() - check if a value is a power of two
* @n: the value to check
*
* Determine whether some value is a power of two, where zero is
* *not* considered a power of two.
* Return: true if @n is a power of 2, otherwise false.
*/
static inline const
bool is_power_of_2(unsigned long n)
{
return (n != 0 && ((n & (n - 1)) == 0));
}
/**
* __roundup_pow_of_two() - round up to nearest power of two
* @n: value to round up
*/
static inline const
unsigned long __roundup_pow_of_two(unsigned long n)
{
return 1UL << __fls_long(n - 1);
}
/**
* __rounddown_pow_of_two() - round down to nearest power of two
* @n: value to round down
*/
static inline const
unsigned long __rounddown_pow_of_two(unsigned long n)
{
return 1UL << (__fls_long(n) - 1);
}
/**
* const_ilog2 - log base 2 of 32-bit or a 64-bit constant unsigned value
* @n: parameter
*
* Use this where sparse expects a true constant expression, e.g. for array
* indices.
*/
#define const_ilog2(n) \
( \
__builtin_constant_p(n) ? ( \
(n) < 2 ? 0 : \
(n) & (1ULL << 63) ? 63 : \
(n) & (1ULL << 62) ? 62 : \
(n) & (1ULL << 61) ? 61 : \
(n) & (1ULL << 60) ? 60 : \
(n) & (1ULL << 59) ? 59 : \
(n) & (1ULL << 58) ? 58 : \
(n) & (1ULL << 57) ? 57 : \
(n) & (1ULL << 56) ? 56 : \
(n) & (1ULL << 55) ? 55 : \
(n) & (1ULL << 54) ? 54 : \
(n) & (1ULL << 53) ? 53 : \
(n) & (1ULL << 52) ? 52 : \
(n) & (1ULL << 51) ? 51 : \
(n) & (1ULL << 50) ? 50 : \
(n) & (1ULL << 49) ? 49 : \
(n) & (1ULL << 48) ? 48 : \
(n) & (1ULL << 47) ? 47 : \
(n) & (1ULL << 46) ? 46 : \
(n) & (1ULL << 45) ? 45 : \
(n) & (1ULL << 44) ? 44 : \
(n) & (1ULL << 43) ? 43 : \
(n) & (1ULL << 42) ? 42 : \
(n) & (1ULL << 41) ? 41 : \
(n) & (1ULL << 40) ? 40 : \
(n) & (1ULL << 39) ? 39 : \
(n) & (1ULL << 38) ? 38 : \
(n) & (1ULL << 37) ? 37 : \
(n) & (1ULL << 36) ? 36 : \
(n) & (1ULL << 35) ? 35 : \
(n) & (1ULL << 34) ? 34 : \
(n) & (1ULL << 33) ? 33 : \
(n) & (1ULL << 32) ? 32 : \
(n) & (1ULL << 31) ? 31 : \
(n) & (1ULL << 30) ? 30 : \
(n) & (1ULL << 29) ? 29 : \
(n) & (1ULL << 28) ? 28 : \
(n) & (1ULL << 27) ? 27 : \
(n) & (1ULL << 26) ? 26 : \
(n) & (1ULL << 25) ? 25 : \
(n) & (1ULL << 24) ? 24 : \
(n) & (1ULL << 23) ? 23 : \
(n) & (1ULL << 22) ? 22 : \
(n) & (1ULL << 21) ? 21 : \
(n) & (1ULL << 20) ? 20 : \
(n) & (1ULL << 19) ? 19 : \
(n) & (1ULL << 18) ? 18 : \
(n) & (1ULL << 17) ? 17 : \
(n) & (1ULL << 16) ? 16 : \
(n) & (1ULL << 15) ? 15 : \
(n) & (1ULL << 14) ? 14 : \
(n) & (1ULL << 13) ? 13 : \
(n) & (1ULL << 12) ? 12 : \
(n) & (1ULL << 11) ? 11 : \
(n) & (1ULL << 10) ? 10 : \
(n) & (1ULL << 9) ? 9 : \
(n) & (1ULL << 8) ? 8 : \
(n) & (1ULL << 7) ? 7 : \
(n) & (1ULL << 6) ? 6 : \
(n) & (1ULL << 5) ? 5 : \
(n) & (1ULL << 4) ? 4 : \
(n) & (1ULL << 3) ? 3 : \
(n) & (1ULL << 2) ? 2 : \
1) : \
-1)
/**
* ilog2 - log base 2 of 32-bit or a 64-bit unsigned value
* @n: parameter
*
* constant-capable log of base 2 calculation
* - this can be used to initialise global variables from constant data, hence
* the massive ternary operator construction
*
* selects the appropriately-sized optimised version depending on sizeof(n)
*/
#define ilog2(n) \
( \
__builtin_constant_p(n) ? \
const_ilog2(n) : \
(sizeof(n) <= 4) ? \
__ilog2_u32(n) : \
__ilog2_u64(n) \
)
/**
* roundup_pow_of_two - round the given value up to nearest power of two
* @n: parameter
*
* round the given value up to the nearest power of two
* - the result is undefined when n == 0
* - this can be used to initialise global variables from constant data
*/
#define roundup_pow_of_two(n) \
( \
__builtin_constant_p(n) ? ( \
(n == 1) ? 1 : \
(1UL << (ilog2((n) - 1) + 1)) \
) : \
__roundup_pow_of_two(n) \
)
/**
* rounddown_pow_of_two - round the given value down to nearest power of two
* @n: parameter
*
* round the given value down to the nearest power of two
* - the result is undefined when n == 0
* - this can be used to initialise global variables from constant data
*/
#define rounddown_pow_of_two(n) \
( \
__builtin_constant_p(n) ? ( \
(1UL << ilog2(n))) : \
__rounddown_pow_of_two(n) \
)
static inline __attribute_const__
int __order_base_2(unsigned long n)
{
return n > 1 ? ilog2(n - 1) + 1 : 0;
}
/**
* order_base_2 - calculate the (rounded up) base 2 order of the argument
* @n: parameter
*
* The first few values calculated by this routine:
* ob2(0) = 0
* ob2(1) = 0
* ob2(2) = 1
* ob2(3) = 2
* ob2(4) = 2
* ob2(5) = 3
* ... and so on.
*/
#define order_base_2(n) \
( \
__builtin_constant_p(n) ? ( \
((n) == 0 || (n) == 1) ? 0 : \
ilog2((n) - 1) + 1) : \
__order_base_2(n) \
)
#endif /* ifndef USERSPACE_LOG2_H */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,182 @@
/*
* 802.11 netlink interface public header
*
* Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net>
* Copyright 2008 Michael Wu <flamingice@sourmilk.net>
* Copyright 2008 Luis Carlos Cobo <luisca@cozybit.com>
* Copyright 2008 Michael Buesch <m@bues.ch>
* Copyright 2008, 2009 Luis R. Rodriguez <lrodriguez@atheros.com>
* Copyright 2008 Jouni Malinen <jouni.malinen@atheros.com>
* Copyright 2008 Colin McCabe <colin@cozybit.com>
* Copyright 2015-2017 Intel Deutschland GmbH
* Copyright (C) 2018-2019 Intel Corporation
*
* 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.
*
*/
/*
* Userspace port (c) 2019 Hak5
*/
#ifndef __USERSPACE_NL80211_H__
#define __USERSPACE_NL80211_H__
#include "kernel.h"
#include "types.h"
/**
* 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
*/
enum nl80211_chan_width {
NL80211_CHAN_WIDTH_20_NOHT,
NL80211_CHAN_WIDTH_20,
NL80211_CHAN_WIDTH_40,
NL80211_CHAN_WIDTH_80,
NL80211_CHAN_WIDTH_80P80,
NL80211_CHAN_WIDTH_160,
NL80211_CHAN_WIDTH_5,
NL80211_CHAN_WIDTH_10,
};
/**
* 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 - 69.12 GHz)
* @NUM_NL80211_BANDS: number of bands, avoid using this in userspace
* since newer kernel versions may support more bands
*/
enum nl80211_band {
NL80211_BAND_2GHZ,
NL80211_BAND_5GHZ,
NL80211_BAND_60GHZ,
NUM_NL80211_BANDS,
};
/**
* 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.
*/
enum nl80211_dfs_state {
NL80211_DFS_USABLE,
NL80211_DFS_UNAVAILABLE,
NL80211_DFS_AVAILABLE,
};
/**
* 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
*/
enum nl80211_tx_power_setting {
NL80211_TX_POWER_AUTOMATIC,
NL80211_TX_POWER_LIMITED,
NL80211_TX_POWER_FIXED,
};
/**
* 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_IF_TYPE_OCB: Outside Context of a BSS
* This mode corresponds to the MIB variable dot11OCBActivated=true
* @NL80211_IFTYPE_NAN: NAN device interface type (not a netdev)
* @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.
*
*/
enum nl80211_iftype {
NL80211_IFTYPE_UNSPECIFIED,
NL80211_IFTYPE_ADHOC,
NL80211_IFTYPE_STATION,
NL80211_IFTYPE_AP,
NL80211_IFTYPE_AP_VLAN,
NL80211_IFTYPE_WDS,
NL80211_IFTYPE_MONITOR,
NL80211_IFTYPE_MESH_POINT,
NL80211_IFTYPE_P2P_CLIENT,
NL80211_IFTYPE_P2P_GO,
NL80211_IFTYPE_P2P_DEVICE,
NL80211_IFTYPE_OCB,
NL80211_IFTYPE_NAN,
/* keep last */
NUM_NL80211_IFTYPES,
NL80211_IFTYPE_MAX = NUM_NL80211_IFTYPES - 1
}
;
/* Notice of Absence attribute - described in P2P spec 4.1.14 */
/* Typical max value used here */
#define IEEE80211_P2P_NOA_DESC_MAX 4
struct ieee80211_p2p_noa_desc {
u8 count;
__le32 duration;
__le32 interval;
__le32 start_time;
} __packed;
struct ieee80211_p2p_noa_attr {
u8 index;
u8 oppps_ctwindow;
struct ieee80211_p2p_noa_desc desc[IEEE80211_P2P_NOA_DESC_MAX];
} __packed;
#define IEEE80211_P2P_OPPPS_ENABLE_BIT BIT(7)
#define IEEE80211_P2P_OPPPS_CTWINDOW_MASK 0x7F
#endif /* ifndef USERSPACE_NL80211_H */

View File

@ -0,0 +1,49 @@
/*
* GPL-2.0-or-later
*
* Userspace port (C) 2019 Hak5 Inc
*
*/
#ifndef __USERSPACE_TYPES_H__
#define __USERSPACE_TYPES_H__
#include <stdint.h>
typedef uint8_t u8;
typedef uint16_t u16;
typedef uint32_t u32;
typedef uint64_t u64;
typedef int8_t s8;
typedef int16_t s16;
typedef int32_t s32;
typedef int64_t s64;
typedef uint8_t __u8;
typedef uint16_t __u16;
typedef uint32_t __u32;
typedef uint64_t __u64;
/*
* We lose the atomic stuff
*/
typedef int64_t atomic64_t;
typedef int64_t atomic_t;
/*
* We lose the automagic endian checking and have to make sure
* we do it ourselves properly.
*/
typedef uint16_t __le16;
typedef uint32_t __le32;
typedef uint16_t __be16;
typedef uint32_t __be32;
/*
* Not going to make a whole netdev defs file for one def
*/
typedef u64 netdev_features_t;
#endif /* ifndef TYPES_H */

View File

@ -0,0 +1,157 @@
/*
* Derived from Linux kernel usb.h
*
* GPL-2.0-or-later
*
* Userspace port (C) 2019 Hak5 Inc
*
*/
#ifndef __USB_H__
#define __USB_H__
#include "kernel/types.h"
#define USB_DEVICE_ID_MATCH_DEVICE \
(USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_PRODUCT)
#define USB_DEVICE_ID_MATCH_DEV_RANGE \
(USB_DEVICE_ID_MATCH_DEV_LO | USB_DEVICE_ID_MATCH_DEV_HI)
#define USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION \
(USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_DEV_RANGE)
#define USB_DEVICE_ID_MATCH_DEV_INFO \
(USB_DEVICE_ID_MATCH_DEV_CLASS | \
USB_DEVICE_ID_MATCH_DEV_SUBCLASS | \
USB_DEVICE_ID_MATCH_DEV_PROTOCOL)
#define USB_DEVICE_ID_MATCH_INT_INFO \
(USB_DEVICE_ID_MATCH_INT_CLASS | \
USB_DEVICE_ID_MATCH_INT_SUBCLASS | \
USB_DEVICE_ID_MATCH_INT_PROTOCOL)
/**
* USB_DEVICE - macro used to describe a specific usb device
* @vend: the 16 bit USB Vendor ID
* @prod: the 16 bit USB Product ID
*
* This macro is used to create a struct usb_device_id that matches a
* specific device.
*/
#define USB_DEVICE(vend, prod) \
.match_flags = USB_DEVICE_ID_MATCH_DEVICE, \
.idVendor = (vend), \
.idProduct = (prod)
/**
* struct usb_device_id - identifies USB devices for probing and hotplugging
* @match_flags: Bit mask controlling which of the other fields are used to
* match against new devices. Any field except for driver_info may be
* used, although some only make sense in conjunction with other fields.
* This is usually set by a USB_DEVICE_*() macro, which sets all
* other fields in this structure except for driver_info.
* @idVendor: USB vendor ID for a device; numbers are assigned
* by the USB forum to its members.
* @idProduct: Vendor-assigned product ID.
* @bcdDevice_lo: Low end of range of vendor-assigned product version numbers.
* This is also used to identify individual product versions, for
* a range consisting of a single device.
* @bcdDevice_hi: High end of version number range. The range of product
* versions is inclusive.
* @bDeviceClass: Class of device; numbers are assigned
* by the USB forum. Products may choose to implement classes,
* or be vendor-specific. Device classes specify behavior of all
* the interfaces on a device.
* @bDeviceSubClass: Subclass of device; associated with bDeviceClass.
* @bDeviceProtocol: Protocol of device; associated with bDeviceClass.
* @bInterfaceClass: Class of interface; numbers are assigned
* by the USB forum. Products may choose to implement classes,
* or be vendor-specific. Interface classes specify behavior only
* of a given interface; other interfaces may support other classes.
* @bInterfaceSubClass: Subclass of interface; associated with bInterfaceClass.
* @bInterfaceProtocol: Protocol of interface; associated with bInterfaceClass.
* @bInterfaceNumber: Number of interface; composite devices may use
* fixed interface numbers to differentiate between vendor-specific
* interfaces.
* @driver_info: Holds information used by the driver. Usually it holds
* a pointer to a descriptor understood by the driver, or perhaps
* device flags.
*
* In most cases, drivers will create a table of device IDs by using
* USB_DEVICE(), or similar macros designed for that purpose.
* They will then export it to userspace using MODULE_DEVICE_TABLE(),
* and provide it to the USB core through their usb_driver structure.
*
* See the usb_match_id() function for information about how matches are
* performed. Briefly, you will normally use one of several macros to help
* construct these entries. Each entry you provide will either identify
* one or more specific products, or will identify a class of products
* which have agreed to behave the same. You should put the more specific
* matches towards the beginning of your table, so that driver_info can
* record quirks of specific products.
*/
struct usb_device_id {
/* which fields to match against? */
__u16 match_flags;
/* Used for product specific matches; range is inclusive */
__u16 idVendor;
__u16 idProduct;
__u16 bcdDevice_lo;
__u16 bcdDevice_hi;
/* Used for device class matches */
__u8 bDeviceClass;
__u8 bDeviceSubClass;
__u8 bDeviceProtocol;
/* Used for interface class matches */
__u8 bInterfaceClass;
__u8 bInterfaceSubClass;
__u8 bInterfaceProtocol;
/* Used for vendor-specific interface matches */
__u8 bInterfaceNumber;
};
/* Some useful macros to use to create struct usb_device_id */
#define USB_DEVICE_ID_MATCH_VENDOR 0x0001
#define USB_DEVICE_ID_MATCH_PRODUCT 0x0002
#define USB_DEVICE_ID_MATCH_DEV_LO 0x0004
#define USB_DEVICE_ID_MATCH_DEV_HI 0x0008
#define USB_DEVICE_ID_MATCH_DEV_CLASS 0x0010
#define USB_DEVICE_ID_MATCH_DEV_SUBCLASS 0x0020
#define USB_DEVICE_ID_MATCH_DEV_PROTOCOL 0x0040
#define USB_DEVICE_ID_MATCH_INT_CLASS 0x0080
#define USB_DEVICE_ID_MATCH_INT_SUBCLASS 0x0100
#define USB_DEVICE_ID_MATCH_INT_PROTOCOL 0x0200
#define USB_DEVICE_ID_MATCH_INT_NUMBER 0x0400
/*
* USB directions
*
* This bit flag is used in endpoint descriptors' bEndpointAddress field.
* It's also one of three fields in control requests bRequestType.
*/
#define USB_DIR_OUT 0 /* to device */
#define USB_DIR_IN 0x80 /* to host */
/*
* USB types, the second of three bRequestType fields
*/
#define USB_TYPE_MASK (0x03 << 5)
#define USB_TYPE_STANDARD (0x00 << 5)
#define USB_TYPE_CLASS (0x01 << 5)
#define USB_TYPE_VENDOR (0x02 << 5)
#define USB_TYPE_RESERVED (0x03 << 5)
/*
* USB recipients, the third of three bRequestType fields
*/
#define USB_RECIP_MASK 0x1f
#define USB_RECIP_DEVICE 0x00
#define USB_RECIP_INTERFACE 0x01
#define USB_RECIP_ENDPOINT 0x02
#define USB_RECIP_OTHER 0x03
/* From Wireless USB 1.0 */
#define USB_RECIP_PORT 0x04
#define USB_RECIP_RPIPE 0x05
#endif /* ifndef USB_H */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,215 @@
/*
* Copyright (C) 2010 Willow Garage <http://www.willowgarage.com>
* Copyright (C) 2004 - 2010 Ivo van Doorn <IvDoorn@gmail.com>
* <http://rt2x00.serialmonkey.com>
*
* GPL-2.0-or-later
*
* Userspace port (C) 2019 Hak5 Inc
*
*/
#ifndef __RT2800LIB_H__
#define __RT2800LIB_H__
#include "kernel/types.h"
#include "kernel/mac80211.h"
#include "kernel/ieee80211.h"
#include "rt2x00.h"
#include "rt2800.h"
/* RT2800 driver data structure */
struct rt2800_drv_data {
u8 calibration_bw20;
u8 calibration_bw40;
char rx_calibration_bw20;
char rx_calibration_bw40;
char tx_calibration_bw20;
char tx_calibration_bw40;
u8 bbp25;
u8 bbp26;
u8 txmixer_gain_24g;
u8 txmixer_gain_5g;
u8 max_psdu;
unsigned int tbtt_tick;
unsigned int ampdu_factor_cnt[4];
};
struct rt2800_ops {
u32 (*register_read)(struct rt2x00_dev *rt2x00dev,
const unsigned int offset);
u32 (*register_read_lock)(struct rt2x00_dev *rt2x00dev,
const unsigned int offset);
void (*register_write)(struct rt2x00_dev *rt2x00dev,
const unsigned int offset, u32 value);
void (*register_write_lock)(struct rt2x00_dev *rt2x00dev,
const unsigned int offset, u32 value);
void (*register_multiread)(struct rt2x00_dev *rt2x00dev,
const unsigned int offset,
void *value, const u32 length);
void (*register_multiwrite)(struct rt2x00_dev *rt2x00dev,
const unsigned int offset,
const void *value, const u32 length);
int (*regbusy_read)(struct rt2x00_dev *rt2x00dev,
const unsigned int offset,
const struct rt2x00_field32 field, u32 *reg);
int (*read_eeprom)(struct rt2x00_dev *rt2x00dev);
bool (*hwcrypt_disabled)(struct rt2x00_dev *rt2x00dev);
int (*drv_write_firmware)(struct rt2x00_dev *rt2x00dev,
const u8 *data, const size_t len);
int (*drv_init_registers)(struct rt2x00_dev *rt2x00dev);
};
static inline u32 rt2800_register_read(struct rt2x00_dev *rt2x00dev,
const unsigned int offset) {
const struct rt2800_ops *rt2800ops = (const struct rt2800_ops *) rt2x00dev->ops->drv;
return rt2800ops->register_read(rt2x00dev, offset);
}
static inline u32 rt2800_register_read_lock(struct rt2x00_dev *rt2x00dev,
const unsigned int offset) {
const struct rt2800_ops *rt2800ops = (const struct rt2800_ops *) rt2x00dev->ops->drv;
return rt2800ops->register_read_lock(rt2x00dev, offset);
}
static inline void rt2800_register_write(struct rt2x00_dev *rt2x00dev,
const unsigned int offset,
u32 value) {
const struct rt2800_ops *rt2800ops = (const struct rt2800_ops *) rt2x00dev->ops->drv;
rt2800ops->register_write(rt2x00dev, offset, value);
}
static inline void rt2800_register_write_lock(struct rt2x00_dev *rt2x00dev,
const unsigned int offset,
u32 value) {
const struct rt2800_ops *rt2800ops = (const struct rt2800_ops *) rt2x00dev->ops->drv;
rt2800ops->register_write_lock(rt2x00dev, offset, value);
}
static inline void rt2800_register_multiread(struct rt2x00_dev *rt2x00dev,
const unsigned int offset,
void *value, const u32 length) {
const struct rt2800_ops *rt2800ops = (const struct rt2800_ops *) rt2x00dev->ops->drv;
rt2800ops->register_multiread(rt2x00dev, offset, value, length);
}
static inline void rt2800_register_multiwrite(struct rt2x00_dev *rt2x00dev,
const unsigned int offset,
const void *value,
const u32 length) {
const struct rt2800_ops *rt2800ops = (const struct rt2800_ops *) rt2x00dev->ops->drv;
rt2800ops->register_multiwrite(rt2x00dev, offset, value, length);
}
static inline int rt2800_regbusy_read(struct rt2x00_dev *rt2x00dev,
const unsigned int offset,
const struct rt2x00_field32 field,
u32 *reg) {
const struct rt2800_ops *rt2800ops = (const struct rt2800_ops *) rt2x00dev->ops->drv;
return rt2800ops->regbusy_read(rt2x00dev, offset, field, reg);
}
static inline int rt2800_read_eeprom(struct rt2x00_dev *rt2x00dev) {
const struct rt2800_ops *rt2800ops = (const struct rt2800_ops *) rt2x00dev->ops->drv;
return rt2800ops->read_eeprom(rt2x00dev);
}
static inline bool rt2800_hwcrypt_disabled(struct rt2x00_dev *rt2x00dev) {
const struct rt2800_ops *rt2800ops = (const struct rt2800_ops *) rt2x00dev->ops->drv;
return rt2800ops->hwcrypt_disabled(rt2x00dev);
}
static inline int rt2800_drv_write_firmware(struct rt2x00_dev *rt2x00dev,
const u8 *data, const size_t len) {
const struct rt2800_ops *rt2800ops = (const struct rt2800_ops *) rt2x00dev->ops->drv;
return rt2800ops->drv_write_firmware(rt2x00dev, data, len);
}
static inline int rt2800_drv_init_registers(struct rt2x00_dev *rt2x00dev) {
const struct rt2800_ops *rt2800ops = (const struct rt2800_ops *) rt2x00dev->ops->drv;
return rt2800ops->drv_init_registers(rt2x00dev);
}
int rt2800_efuse_detect(struct rt2x00_dev *rt2x00dev);
int rt2800_read_eeprom_efuse(struct rt2x00_dev *rt2x00dev);
int rt2800_rfkill_poll(struct rt2x00_dev *rt2x00dev);
int rt2800_config_shared_key(struct rt2x00_dev *rt2x00dev,
struct rt2x00lib_crypto *crypto,
struct ieee80211_key_conf *key);
int rt2800_config_pairwise_key(struct rt2x00_dev *rt2x00dev,
struct rt2x00lib_crypto *crypto,
struct ieee80211_key_conf *key);
int rt2800_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct ieee80211_sta *sta);
int rt2800_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct ieee80211_sta *sta);
void rt2800_config_filter(struct rt2x00_dev *rt2x00dev,
const unsigned int filter_flags);
void rt2800_config_ant(struct rt2x00_dev *rt2x00dev, struct antenna_setup *ant);
void rt2800_config(struct rt2x00_dev *rt2x00dev,
struct rt2x00lib_conf *libconf,
const unsigned int flags);
void rt2800_config_intf(struct rt2x00_dev *rt2x00dev, struct rt2x00_intf *intf,
struct rt2x00intf_conf *conf, const unsigned int flags);
void rt2800_config_erp(struct rt2x00_dev *rt2x00dev, struct rt2x00lib_erp *erp,
u32 changed);
void rt2800_link_stats(struct rt2x00_dev *rt2x00dev, struct link_qual *qual);
void rt2800_reset_tuner(struct rt2x00_dev *rt2x00dev, struct link_qual *qual);
void rt2800_link_tuner(struct rt2x00_dev *rt2x00dev, struct link_qual *qual,
const u32 count);
void rt2800_gain_calibration(struct rt2x00_dev *rt2x00dev);
void rt2800_vco_calibration(struct rt2x00_dev *rt2x00dev);
int rt2800_enable_radio(struct rt2x00_dev *rt2x00dev);
void rt2800_disable_radio(struct rt2x00_dev *rt2x00dev);
void rt2800_disable_wpdma(struct rt2x00_dev *rt2x00dev);
void rt2800_mcu_request(struct rt2x00_dev *rt2x00dev,
const u8 command, const u8 token,
const u8 arg0, const u8 arg1);
int rt2800_wait_csr_ready(struct rt2x00_dev *rt2x00dev);
int rt2800_wait_wpdma_ready(struct rt2x00_dev *rt2x00dev);
int rt2800_check_firmware(struct rt2x00_dev *rt2x00dev,
const u8 *data, const size_t len);
int rt2800_load_firmware(struct rt2x00_dev *rt2x00dev,
const u8 *data, const size_t len);
int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev);
int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev);
int rt2800_probe_rt(struct rt2x00_dev *rt2x00dev);
int rt2800_init_registers(struct rt2x00_dev *rt2x00dev);
static inline bool rt2800_clk_is_20mhz(struct rt2x00_dev *rt2x00dev)
{
/*
* clk is for SOC only, and we don't want to deal with all the kernel
* stuff. We never have a SOC chip in USB.
*/
return false;
}
#endif /* ifndef RT2800LIB_H */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,109 @@
/*
* Copyright (C) 2010 Willow Garage <http://www.willowgarage.com>
* Copyright (C) 2004 - 2010 Ivo van Doorn <IvDoorn@gmail.com>
* <http://rt2x00.serialmonkey.com>
*
* GPL-2.0-or-later
*
* Userspace port (C) 2019 Hak5 Inc
*
*/
#ifndef __RT2800USB_H__
#define __RT2800USB_H__
#include "rt2x00.h"
/*
* 8051 firmware image.
*/
#define FIRMWARE_RT2870 "rt2870.bin"
#define FIRMWARE_IMAGE_BASE 0x3000
/*
* DMA descriptor defines.
*/
#define TXINFO_DESC_SIZE (1 * sizeof(__le32))
#define RXINFO_DESC_SIZE (1 * sizeof(__le32))
/*
* TX Info structure
*/
/*
* Word0
* WIV: Wireless Info Valid. 1: Driver filled WI, 0: DMA needs to copy WI
* QSEL: Select on-chip FIFO ID for 2nd-stage output scheduler.
* 0:MGMT, 1:HCCA 2:EDCA
* USB_DMA_NEXT_VALID: Used ONLY in USB bulk Aggregation, NextValid
* DMA_TX_BURST: used ONLY in USB bulk Aggregation.
* Force USB DMA transmit frame from current selected endpoint
*/
#define TXINFO_W0_USB_DMA_TX_PKT_LEN FIELD32(0x0000ffff)
#define TXINFO_W0_WIV FIELD32(0x01000000)
#define TXINFO_W0_QSEL FIELD32(0x06000000)
#define TXINFO_W0_SW_USE_LAST_ROUND FIELD32(0x08000000)
#define TXINFO_W0_USB_DMA_NEXT_VALID FIELD32(0x40000000)
#define TXINFO_W0_USB_DMA_TX_BURST FIELD32(0x80000000)
/*
* RX Info structure
*/
/*
* Word 0
*/
#define RXINFO_W0_USB_DMA_RX_PKT_LEN FIELD32(0x0000ffff)
/*
* RX descriptor format for RX Ring.
*/
/*
* Word0
* UNICAST_TO_ME: This RX frame is unicast to me.
* MULTICAST: This is a multicast frame.
* BROADCAST: This is a broadcast frame.
* MY_BSS: this frame belongs to the same BSSID.
* CRC_ERROR: CRC error.
* CIPHER_ERROR: 0: decryption okay, 1:ICV error, 2:MIC error, 3:KEY not valid.
* AMSDU: rx with 802.3 header, not 802.11 header.
*/
#define RXD_W0_BA FIELD32(0x00000001)
#define RXD_W0_DATA FIELD32(0x00000002)
#define RXD_W0_NULLDATA FIELD32(0x00000004)
#define RXD_W0_FRAG FIELD32(0x00000008)
#define RXD_W0_UNICAST_TO_ME FIELD32(0x00000010)
#define RXD_W0_MULTICAST FIELD32(0x00000020)
#define RXD_W0_BROADCAST FIELD32(0x00000040)
#define RXD_W0_MY_BSS FIELD32(0x00000080)
#define RXD_W0_CRC_ERROR FIELD32(0x00000100)
#define RXD_W0_CIPHER_ERROR FIELD32(0x00000600)
#define RXD_W0_AMSDU FIELD32(0x00000800)
#define RXD_W0_HTC FIELD32(0x00001000)
#define RXD_W0_RSSI FIELD32(0x00002000)
#define RXD_W0_L2PAD FIELD32(0x00004000)
#define RXD_W0_AMPDU FIELD32(0x00008000)
#define RXD_W0_DECRYPTED FIELD32(0x00010000)
#define RXD_W0_PLCP_RSSI FIELD32(0x00020000)
#define RXD_W0_CIPHER_ALG FIELD32(0x00040000)
#define RXD_W0_LAST_AMSDU FIELD32(0x00080000)
#define RXD_W0_PLCP_SIGNAL FIELD32(0xfff00000)
/*
* Firmware functions
*/
int rt2800usb_autorun_detect(struct rt2x00_dev *rt2x00dev);
/*
* Probe a usb device to determine if it's a viable rt2800 device;
* returns 1 on success and populates **probe_dev,
* returns 0 on no match
* returns negative on error
*/
int rt2800usb_probe_device(struct libusb_device_descriptor *desc,
struct userspace_wifi_probe_dev **probe_dev);
#endif /* ifndef RT2800USB_H */

View File

@ -0,0 +1,28 @@
/*
* Copyright (C) 2010 Willow Garage <http://www.willowgarage.com>
* Copyright (C) 2004 - 2010 Ivo van Doorn <IvDoorn@gmail.com>
* <http://rt2x00.serialmonkey.com>
*
* GPL-2.0-or-later
*
* Userspace port (C) 2019 Hak5 Inc
*
*/
/*
* This is a user-space port of components of the rt2x00usb library,
* implementing generic usb device routines.
*/
#include <errno.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include "kernel/bits.h"
#include "kernel/endian.h"
#include "kernel/kernel.h"
#include "rt2800usb/rt2x00.h"
#include "rt2800usb/rt2x00usb.h"

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,80 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
Copyright (C) 2004 - 2009 Gertjan van Wingerde <gwingerde@gmail.com>
<http://rt2x00.serialmonkey.com>
*/
/*
* Userspace port (c) 2019 Hak5
*/
/*
Module: rt2x00lib
Abstract: Data structures and definitions for the rt2x00lib module.
*/
#ifndef __RT2x00LIB_H__
#define __RT2x00LIB_H__
#include "kernel/nl80211.h"
#include "kernel/types.h"
/*
* rt2x00_rate: Per rate device information
*/
struct rt2x00_rate {
unsigned short flags;
#define DEV_RATE_CCK 0x0001
#define DEV_RATE_OFDM 0x0002
#define DEV_RATE_SHORT_PREAMBLE 0x0004
unsigned short bitrate; /* In 100kbit/s */
unsigned short ratemask;
unsigned short plcp;
unsigned short mcs;
};
extern const struct rt2x00_rate rt2x00_supported_rates[12];
static inline const struct rt2x00_rate *rt2x00_get_rate(const u16 hw_value)
{
return &rt2x00_supported_rates[hw_value & 0xff];
}
#define RATE_MCS(__mode, __mcs) \
((((__mode) & 0x00ff) << 8) | ((__mcs) & 0x00ff))
static inline int rt2x00_get_rate_mcs(const u16 mcs_value)
{
return (mcs_value & 0x00ff);
}
/*
* Initialization handlers.
*/
int rt2x00lib_start(struct rt2x00_dev *rt2x00dev);
void rt2x00lib_stop(struct rt2x00_dev *rt2x00dev);
/*
* Configuration handlers.
*/
int rt2x00mac_add_interface(struct ieee80211_hw *hw,
struct ieee80211_vif *vif);
void rt2x00lib_config_intf(struct rt2x00_dev *rt2x00dev,
struct rt2x00_intf *intf,
enum nl80211_iftype type,
const u8 *mac, const u8 *bssid);
void rt2x00lib_config_erp(struct rt2x00_dev *rt2x00dev,
struct rt2x00_intf *intf,
struct ieee80211_bss_conf *conf,
u32 changed);
void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev,
struct antenna_setup ant);
void rt2x00lib_config(struct rt2x00_dev *rt2x00dev,
struct ieee80211_conf *conf,
const unsigned int changed_flags);
#endif /* ifndef RT2x00LIB_H */

View File

@ -0,0 +1,120 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
<http://rt2x00.serialmonkey.com>
*/
/*
* Userspace port (c) 2019 Hak5
*/
/*
Module: rt2x00mac
Abstract: rt2x00 generic mac80211 routines.
*/
#include <errno.h>
#include "kernel/ieee80211.h"
#include "kernel/kernel.h"
#include "rt2800usb/rt2x00.h"
#include "rt2800usb/rt2x00lib.h"
int rt2x00mac_start(struct ieee80211_hw *hw)
{
struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *) hw->priv;
if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
return 0;
return rt2x00lib_start(rt2x00dev);
}
EXPORT_SYMBOL_GPL(rt2x00mac_start);
void rt2x00mac_stop(struct ieee80211_hw *hw)
{
struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *) hw->priv;
if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
return;
rt2x00lib_stop(rt2x00dev);
}
EXPORT_SYMBOL_GPL(rt2x00mac_stop);
int rt2x00mac_add_interface(struct ieee80211_hw *hw,
struct ieee80211_vif *vif)
{
struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *) hw->priv;
struct rt2x00_intf *intf = vif_to_intf(vif);
/*
* Don't allow interfaces to be added
* the device has disappeared.
*/
if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) ||
!test_bit(DEVICE_STATE_STARTED, &rt2x00dev->flags)) {
rt2x00_err(rt2x00dev, "Device not started before adding vif\n");
return -ENODEV;
}
/*
* We are now absolutely sure the interface can be created,
* increase interface count and start initialization.
*/
/*
* The MAC address must be configured after the device
* has been initialized. Otherwise the device can reset
* the MAC registers.
* The BSSID address must only be configured in AP mode,
* however we should not send an empty BSSID address for
* STA interfaces at this time, since this can cause
* invalid behavior in the device.
*/
rt2x00lib_config_intf(rt2x00dev, intf, vif->type,
vif->addr, NULL);
return 0;
}
EXPORT_SYMBOL_GPL(rt2x00mac_add_interface);
void rt2x00lib_config_intf(struct rt2x00_dev *rt2x00dev,
struct rt2x00_intf *intf,
enum nl80211_iftype type,
const u8 *mac, const u8 *bssid)
{
/*
* Trimmed down for userspace
*/
struct rt2x00intf_conf conf;
unsigned int flags = 0;
conf.type = type;
switch (type) {
case NL80211_IFTYPE_ADHOC:
conf.sync = TSF_SYNC_ADHOC;
break;
case NL80211_IFTYPE_AP:
case NL80211_IFTYPE_MESH_POINT:
case NL80211_IFTYPE_WDS:
conf.sync = TSF_SYNC_AP_NONE;
break;
case NL80211_IFTYPE_STATION:
conf.sync = TSF_SYNC_INFRA;
break;
default:
conf.sync = TSF_SYNC_NONE;
break;
}
flags = CONFIG_UPDATE_TYPE | CONFIG_UPDATE_MAC | CONFIG_UPDATE_BSSID;
rt2x00dev->ops->lib->config_intf(rt2x00dev, intf, &conf, flags);
}

View File

@ -0,0 +1,98 @@
/*
* Copyright (C) 2010 Willow Garage <http://www.willowgarage.com>
* Copyright (C) 2004 - 2010 Ivo van Doorn <IvDoorn@gmail.com>
* <http://rt2x00.serialmonkey.com>
*
* GPL-2.0-or-later
*
* Userspace port (C) 2019 Hak5 Inc
*
*/
#ifndef __RT2X00QUEUE_H__
#define __RT2X00QUEUE_H__
#include "kernel/bits.h"
#include "kernel/mac80211.h"
#include "kernel/types.h"
/**
* DOC: Entry frame size
*
* Ralink PCI devices demand the Frame size to be a multiple of 128 bytes,
* for USB devices this restriction does not apply, but the value of
* 2432 makes sense since it is big enough to contain the maximum fragment
* size according to the ieee802.11 specs.
* The aggregation size depends on support from the driver, but should
* be something around 3840 bytes.
*/
#define DATA_FRAME_SIZE 2432
#define MGMT_FRAME_SIZE 256
#define AGGREGATION_SIZE 3840
/**
* enum rxdone_entry_desc_flags: Flags for &struct rxdone_entry_desc
*
* @RXDONE_SIGNAL_PLCP: Signal field contains the plcp value.
* @RXDONE_SIGNAL_BITRATE: Signal field contains the bitrate value.
* @RXDONE_SIGNAL_MCS: Signal field contains the mcs value.
* @RXDONE_MY_BSS: Does this frame originate from device's BSS.
* @RXDONE_CRYPTO_IV: Driver provided IV/EIV data.
* @RXDONE_CRYPTO_ICV: Driver provided ICV data.
* @RXDONE_L2PAD: 802.11 payload has been padded to 4-byte boundary.
*/
enum rxdone_entry_desc_flags {
RXDONE_SIGNAL_PLCP = BIT(0),
RXDONE_SIGNAL_BITRATE = BIT(1),
RXDONE_SIGNAL_MCS = BIT(2),
RXDONE_MY_BSS = BIT(3),
RXDONE_CRYPTO_IV = BIT(4),
RXDONE_CRYPTO_ICV = BIT(5),
RXDONE_L2PAD = BIT(6),
};
/**
* RXDONE_SIGNAL_MASK - Define to mask off all &rxdone_entry_desc_flags flags
* except for the RXDONE_SIGNAL_* flags. This is useful to convert the dev_flags
* from &rxdone_entry_desc to a signal value type.
*/
#define RXDONE_SIGNAL_MASK \
( RXDONE_SIGNAL_PLCP | RXDONE_SIGNAL_BITRATE | RXDONE_SIGNAL_MCS )
/**
* struct rxdone_entry_desc: RX Entry descriptor
*
* Summary of information that has been read from the RX frame descriptor.
*
* @timestamp: RX Timestamp
* @signal: Signal of the received frame.
* @rssi: RSSI of the received frame.
* @size: Data size of the received frame.
* @flags: MAC80211 receive flags (See &enum mac80211_rx_flags).
* @dev_flags: Ralink receive flags (See &enum rxdone_entry_desc_flags).
* @rate_mode: Rate mode (See @enum rate_modulation).
* @cipher: Cipher type used during decryption.
* @cipher_status: Decryption status.
* @iv: IV/EIV data used during decryption.
* @icv: ICV data used during decryption.
*/
struct rxdone_entry_desc {
u64 timestamp;
int signal;
int rssi;
int size;
int flags;
int dev_flags;
u16 rate_mode;
u16 enc_flags;
enum mac80211_rx_encoding encoding;
enum rate_info_bw bw;
u8 cipher;
u8 cipher_status;
__le32 iv[2];
__le32 icv;
};
#endif /* ifndef RT2X00QUEUE_H */

View File

@ -0,0 +1,255 @@
/*
* Copyright (C) 2010 Willow Garage <http://www.willowgarage.com>
* Copyright (C) 2004 - 2010 Ivo van Doorn <IvDoorn@gmail.com>
* <http://rt2x00.serialmonkey.com>
*
* GPL-2.0-or-later
*
* Userspace port (C) 2019 Hak5 Inc
*
*/
#ifndef __RT2X00REG_H__
#define __RT2X00REG_H__
#include "kernel/bits.h"
#include "kernel/endian.h"
#include "kernel/kernel.h"
#include "kernel/types.h"
/*
* RX crypto status
*/
enum rx_crypto {
RX_CRYPTO_SUCCESS = 0,
RX_CRYPTO_FAIL_ICV = 1,
RX_CRYPTO_FAIL_MIC = 2,
RX_CRYPTO_FAIL_KEY = 3,
};
/*
* Antenna values
*/
enum antenna {
ANTENNA_SW_DIVERSITY = 0,
ANTENNA_A = 1,
ANTENNA_B = 2,
ANTENNA_HW_DIVERSITY = 3,
};
/*
* Led mode values.
*/
enum led_mode {
LED_MODE_DEFAULT = 0,
LED_MODE_TXRX_ACTIVITY = 1,
LED_MODE_SIGNAL_STRENGTH = 2,
LED_MODE_ASUS = 3,
LED_MODE_ALPHA = 4,
};
/*
* TSF sync values
*/
enum tsf_sync {
TSF_SYNC_NONE = 0,
TSF_SYNC_INFRA = 1,
TSF_SYNC_ADHOC = 2,
TSF_SYNC_AP_NONE = 3,
};
/*
* Device states
*/
enum dev_state {
STATE_DEEP_SLEEP = 0,
STATE_SLEEP = 1,
STATE_STANDBY = 2,
STATE_AWAKE = 3,
/*
* Additional device states, these values are
* not strict since they are not directly passed
* into the device.
*/
STATE_RADIO_ON,
STATE_RADIO_OFF,
STATE_RADIO_IRQ_ON,
STATE_RADIO_IRQ_OFF,
};
/*
* IFS backoff values
*/
enum ifs {
IFS_BACKOFF = 0,
IFS_SIFS = 1,
IFS_NEW_BACKOFF = 2,
IFS_NONE = 3,
};
/*
* IFS backoff values for HT devices
*/
enum txop {
TXOP_HTTXOP = 0,
TXOP_PIFS = 1,
TXOP_SIFS = 2,
TXOP_BACKOFF = 3,
};
/*
* Cipher types for hardware encryption
*/
enum cipher {
CIPHER_NONE = 0,
CIPHER_WEP64 = 1,
CIPHER_WEP128 = 2,
CIPHER_TKIP = 3,
CIPHER_AES = 4,
/*
* The following fields were added by rt61pci and rt73usb.
*/
CIPHER_CKIP64 = 5,
CIPHER_CKIP128 = 6,
CIPHER_TKIP_NO_MIC = 7, /* Don't send to device */
/*
* Max cipher type.
* Note that CIPHER_NONE isn't counted, and CKIP64 and CKIP128
* are excluded due to limitations in mac80211.
*/
CIPHER_MAX = 4,
};
/*
* Rate modulations
*/
enum rate_modulation {
RATE_MODE_CCK = 0,
RATE_MODE_OFDM = 1,
RATE_MODE_HT_MIX = 2,
RATE_MODE_HT_GREENFIELD = 3,
};
/*
* Firmware validation error codes
*/
enum firmware_errors {
FW_OK,
FW_BAD_CRC,
FW_BAD_LENGTH,
FW_BAD_VERSION,
};
/*
* Register handlers.
* We store the position of a register field inside a field structure,
* This will simplify the process of setting and reading a certain field
* inside the register while making sure the process remains byte order safe.
*/
struct rt2x00_field8 {
u8 bit_offset;
u8 bit_mask;
};
struct rt2x00_field16 {
u16 bit_offset;
u16 bit_mask;
};
struct rt2x00_field32 {
u32 bit_offset;
u32 bit_mask;
};
/*
* Power of two check, this will check
* if the mask that has been given contains and contiguous set of bits.
* Note that we cannot use the is_power_of_2() function since this
* check must be done at compile-time.
*/
#define is_power_of_two(x) ( !((x) & ((x)-1)) )
#define low_bit_mask(x) ( ((x)-1) & ~(x) )
#define is_valid_mask(x) is_power_of_two(1LU + (x) + low_bit_mask(x))
/*
* Macros to find first set bit in a variable.
* These macros behave the same as the __ffs() functions but
* the most important difference that this is done during
* compile-time rather then run-time.
*/
#define compile_ffs2(__x) \
__builtin_choose_expr(((__x) & 0x1), 0, 1)
#define compile_ffs4(__x) \
__builtin_choose_expr(((__x) & 0x3), \
(compile_ffs2((__x))), \
(compile_ffs2((__x) >> 2) + 2))
#define compile_ffs8(__x) \
__builtin_choose_expr(((__x) & 0xf), \
(compile_ffs4((__x))), \
(compile_ffs4((__x) >> 4) + 4))
#define compile_ffs16(__x) \
__builtin_choose_expr(((__x) & 0xff), \
(compile_ffs8((__x))), \
(compile_ffs8((__x) >> 8) + 8))
#define compile_ffs32(__x) \
__builtin_choose_expr(((__x) & 0xffff), \
(compile_ffs16((__x))), \
(compile_ffs16((__x) >> 16) + 16))
/*
* This macro will check the requirements for the FIELD{8,16,32} macros
* The mask should be a constant non-zero contiguous set of bits which
* does not exceed the given typelimit.
*/
#define FIELD_CHECK(__mask, __type) \
BUILD_BUG_ON(!(__mask) || \
!is_valid_mask(__mask) || \
(__mask) != (__type)(__mask)) \
/* Modified for MSVC happiness */
#define FIELD8(__mask) \
((struct rt2x00_field8){ \
compile_ffs8(__mask), (__mask) \
})
#define FIELD16(__mask) \
((struct rt2x00_field16) { \
compile_ffs16(__mask), (__mask) \
})
#define FIELD32(__mask) \
((struct rt2x00_field32) { \
compile_ffs32(__mask), (__mask) \
})
#define SET_FIELD(__reg, __type, __field, __value) \
*(__reg) = \
(*(__reg) & ~((__field).bit_mask)) | \
( ((__value) << ((__field).bit_offset)) & ((__field).bit_mask) )
#define GET_FIELD(__reg, __type, __field) \
(((__reg) & ((__field).bit_mask)) >> ((__field).bit_offset))
#define rt2x00_set_field32(__reg, __field, __value) \
SET_FIELD(__reg, struct rt2x00_field32, __field, __value)
#define rt2x00_get_field32(__reg, __field) \
GET_FIELD(__reg, struct rt2x00_field32, __field)
#define rt2x00_set_field16(__reg, __field, __value) \
SET_FIELD(__reg, struct rt2x00_field16, __field, __value)
#define rt2x00_get_field16(__reg, __field) \
GET_FIELD(__reg, struct rt2x00_field16, __field)
#define rt2x00_set_field8(__reg, __field, __value) \
SET_FIELD(__reg, struct rt2x00_field8, __field, __value)
#define rt2x00_get_field8(__reg, __field) \
GET_FIELD(__reg, struct rt2x00_field8, __field)
#endif /* ifndef RT2X00REG_H */

View File

@ -0,0 +1,410 @@
/*
* Copyright (C) 2010 Willow Garage <http://www.willowgarage.com>
* Copyright (C) 2004 - 2010 Ivo van Doorn <IvDoorn@gmail.com>
* <http://rt2x00.serialmonkey.com>
*
* GPL-2.0-or-later
*
* Userspace port (C) 2019 Hak5 Inc
*
*/
#include <errno.h>
#include <string.h>
#ifndef _WIN32
#include <unistd.h>
#else
#include <Windows.h>
#define usleep(x) Sleep((x) < 1000 ? 1 : (x) / 1000)
#endif
#include <stdlib.h>
#include "kernel/kernel.h"
#include "rt2800usb/rt2x00usb.h"
#include "rt2800usb/rt2x00reg.h"
#include "userspace/userspace.h"
/*
* Interfacing with the HW.
*/
int rt2x00usb_vendor_request(struct rt2x00_dev *rt2x00dev,
const u8 request, const u8 requesttype,
const u16 offset, const u16 value,
void *buffer, const u16 buffer_length,
const int timeout) {
struct libusb_device_handle *usb_dev = rt2x00dev->dev;
int fail_count = 0;
if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags)) {
rt2x00_err(rt2x00dev, "No device present\n");
return -ENODEV;
}
/*
* we use a simplified failure count instead of measuring time, so that
* we don't introduce timeout errors on multi-platform builds; we don't
* want to depend on linux (or posix) high-precision timespec
*/
if (rt2x00dev->control_transfer_buffer_sz < LIBUSB_CONTROL_SETUP_SIZE + buffer_length) {
if (rt2x00dev->control_transfer_buffer != NULL)
free(rt2x00dev->control_transfer_buffer);
rt2x00dev->control_transfer_buffer =
(unsigned char *) malloc(LIBUSB_CONTROL_SETUP_SIZE + buffer_length);
if (rt2x00dev->control_transfer_buffer == NULL) {
rt2x00_err(rt2x00dev, "No memory");
return -ENOMEM;
}
rt2x00dev->control_transfer_buffer_sz = LIBUSB_CONTROL_SETUP_SIZE + buffer_length;
}
/*
* We have to tie into the async io system with libusb here, we use a conditional
* variable to determine when our command completes
*/
if (rt2x00dev->control_transfer == NULL)
rt2x00dev->control_transfer = libusb_alloc_transfer(0);
libusb_fill_control_setup(rt2x00dev->control_transfer_buffer, requesttype, request, value, offset, buffer_length);
memcpy(rt2x00dev->control_transfer_buffer + LIBUSB_CONTROL_SETUP_SIZE, buffer, buffer_length);
libusb_fill_control_transfer(rt2x00dev->control_transfer, usb_dev, rt2x00dev->control_transfer_buffer,
rt2x00dev_control_cb, rt2x00dev, timeout / 2);
do {
rt2x00dev->usb_command_complete = false;
libusb_submit_transfer(rt2x00dev->control_transfer);
/* Wait for the cond to unlock */
while (1) {
pthread_mutex_lock(&rt2x00dev->usb_control_mutex);
pthread_cond_wait(&rt2x00dev->usb_control_cond, &rt2x00dev->usb_control_mutex);
if (!rt2x00dev->usb_command_complete)
continue;
pthread_mutex_unlock(&rt2x00dev->usb_control_mutex);
break;
}
if (rt2x00dev->control_transfer->status == LIBUSB_TRANSFER_COMPLETED) {
memcpy(buffer, rt2x00dev->control_transfer_buffer + LIBUSB_CONTROL_SETUP_SIZE, buffer_length);
pthread_mutex_unlock(&rt2x00dev->usb_control_mutex);
return 0;
}
if (rt2x00dev->control_transfer->status == LIBUSB_TRANSFER_NO_DEVICE) {
clear_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags);
pthread_mutex_unlock(&rt2x00dev->usb_control_mutex);
rt2x00_err(rt2x00dev, "Device no longer available");
return -ENODEV;
}
if (rt2x00dev->control_transfer->status == LIBUSB_TRANSFER_TIMED_OUT)
fail_count++;
} while (fail_count < 3);
rt2x00_err(rt2x00dev,
"Vendor Request 0x%02x failed for offset 0x%04x with error %d\n",
request, offset, rt2x00dev->control_transfer->status);
return -1;
}
int rt2x00usb_vendor_request_buff(struct rt2x00_dev *rt2x00dev,
const u8 request, const u8 requesttype,
const u16 offset, void *buffer,
const u16 buffer_length)
{
int status = 0;
unsigned char *tb;
u16 off, len, bsize;
mutex_lock(&rt2x00dev->csr_mutex);
tb = (unsigned char *)buffer;
off = offset;
len = buffer_length;
while (len && !status) {
bsize = min_t(u16, CSR_CACHE_SIZE, len);
status = rt2x00usb_vendor_req_buff_lock(rt2x00dev, request,
requesttype, off, tb,
bsize, REGISTER_TIMEOUT);
tb += bsize;
len -= bsize;
off += bsize;
}
mutex_unlock(&rt2x00dev->csr_mutex);
if (status != 0)
rt2x00_err(rt2x00dev, "Radio USB request failed: %s", libusb_error_name(status));
return status;
}
/*
* Userspace buff_lock doesn't do any locking
*/
int rt2x00usb_vendor_req_buff_lock(struct rt2x00_dev *rt2x00dev,
const u8 request, const u8 requesttype,
const u16 offset, void *buffer,
const u16 buffer_length, const int timeout)
{
int status;
/*
* Check for Cache availability.
*/
if (unlikely(!rt2x00dev->csr.cache || buffer_length > CSR_CACHE_SIZE)) {
rt2x00_err(rt2x00dev, "CSR cache not available\n");
return -ENOMEM;
}
if (requesttype == USB_VENDOR_REQUEST_OUT)
memcpy(rt2x00dev->csr.cache, buffer, buffer_length);
status = rt2x00usb_vendor_request(rt2x00dev, request, requesttype,
offset, 0, rt2x00dev->csr.cache,
buffer_length, timeout);
if (!status && requesttype == USB_VENDOR_REQUEST_IN)
memcpy(buffer, rt2x00dev->csr.cache, buffer_length);
if (status != 0)
rt2x00_err(rt2x00dev, "Radio CSR USB request failed: %s", libusb_error_name(status));
return status;
}
int rt2x00usb_regbusy_read(struct rt2x00_dev *rt2x00dev,
const unsigned int offset,
const struct rt2x00_field32 field,
u32 *reg) {
unsigned int i;
if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
return -ENODEV;
for (i = 0; i < REGISTER_USB_BUSY_COUNT; i++) {
*reg = rt2x00usb_register_read_lock(rt2x00dev, offset);
if (!rt2x00_get_field32(*reg, field))
return 1;
usleep(REGISTER_BUSY_DELAY);
}
rt2x00_err(rt2x00dev, "Indirect register access failed: offset=0x%.08x, value=0x%.08x\n",
offset, *reg);
*reg = ~0;
return 0;
}
struct rt2x00_async_read_data {
__le32 reg;
struct rt2x00_dev *rt2x00dev;
bool (*callback)(struct rt2x00_dev *, int, u32);
};
/*
* In the userspace port, async actually blocks and then calls the
* cb; we'll find out if this causes problems
*/
void rt2x00usb_register_read_async(struct rt2x00_dev *rt2x00dev,
const unsigned int offset,
bool (*callback)(struct rt2x00_dev*, int, u32)) {
struct libusb_device_handle *usb_dev = rt2x00dev->dev;
struct rt2x00_async_read_data *rd;
int status;
rd = (struct rt2x00_async_read_data *) malloc(sizeof(*rd));
if (!rd)
return;
rd->rt2x00dev = rt2x00dev;
rd->callback = callback;
/*
* Implement the equivalent to rt2x00usb_register_read_async_cb and call
* the provided cb directly; if the callback says to resubmit the request,
* do so
*/
do {
status = libusb_control_transfer(usb_dev, USB_VENDOR_REQUEST_IN, USB_MULTI_READ,
0, cpu_to_le16(offset), (unsigned char *) &rd->reg, cpu_to_le16(sizeof(u32)), REGISTER_TIMEOUT);
if (rd->callback(rd->rt2x00dev, status, le32_to_cpu(rd->reg)))
continue;
break;
} while (1);
}
static int rt2x00usb_find_endpoints(struct rt2x00_dev *rt2x00dev) {
struct libusb_config_descriptor *config = NULL;
struct libusb_device_descriptor desc;
int ret;
/*
* interface, config, endpoint, and altsetting iterators
*/
unsigned int i, c, e;
int a;
bool found_in, found_out;
ret = libusb_get_device_descriptor(rt2x00dev->base_dev, &desc);
if (ret != LIBUSB_SUCCESS) {
clear_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags);
return -EPIPE;
}
/*
* Walk through all available endpoints to search for "bulk in"
* and "bulk out" endpoints. When we find such endpoints collect
* the information we need from the descriptor and confirm they
* exist.
*
* We don't get to use kernel queues so for now we just confirm
* the device looks like we expect it to.
*/
for (c = 0; c < desc.bNumConfigurations; c++) {
ret = libusb_get_config_descriptor(rt2x00dev->base_dev, c, &config);
if (ret != LIBUSB_SUCCESS) {
clear_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags);
rt2x00_err(rt2x00dev, "unable to retrieve device descriptors");
return -EPIPE;
}
for (i = 0; i < config->bNumInterfaces; i++) {
/*
* We expect both out and in to be on the same interface
*/
found_in = false;
found_out = false;
for (a = 0; a < config->interface[i].num_altsetting; a++) {
for (e = 0; e < config->interface[i].altsetting[a].bNumEndpoints; e++) {
if ((config->interface[i].altsetting[a].endpoint[e].bmAttributes & LIBUSB_TRANSFER_TYPE_MASK) !=
LIBUSB_TRANSFER_TYPE_BULK)
continue;
if (!found_in &&
(config->interface[i].altsetting[a].endpoint[e].bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK) ==
LIBUSB_ENDPOINT_IN) {
rt2x00dev->usb_interface_num = i;
rt2x00dev->usb_bulk_in_endp = config->interface[i].altsetting[a].endpoint[e].bEndpointAddress;
found_in = true;
}
if (!found_out &&
(config->interface[i].altsetting[a].endpoint[e].bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK) ==
LIBUSB_ENDPOINT_OUT) {
rt2x00dev->usb_interface_num = i;
rt2x00dev->usb_bulk_out_endp = config->interface[i].altsetting[a].endpoint[e].bEndpointAddress;
found_out = true;
}
if (found_in && found_out)
break;
}
if (found_in && found_out)
break;
}
if (found_in && found_out)
break;
}
libusb_free_config_descriptor(config);
}
/*
* At least 1 endpoint for RX and 1 endpoint for TX must be available.
*/
if (!found_in || !found_out) {
rt2x00_err(rt2x00dev, "Bulk-in/Bulk-out endpoints not found\n");
return -EPIPE;
}
return 0;
}
int rt2x00usb_initialize(struct rt2x00_dev *rt2x00dev) {
int status;
/*
* Allocate the driver data memory, if necessary.
*/
if (rt2x00dev->ops->drv_data_size > 0) {
rt2x00dev->drv_data = malloc(rt2x00dev->ops->drv_data_size);
if (!rt2x00dev->drv_data) {
return -ENOMEM;
}
memset(rt2x00dev->drv_data, 0, rt2x00dev->ops->drv_data_size);
}
/*
* Find endpoints for each queue
*/
status = rt2x00usb_find_endpoints(rt2x00dev);
if (status)
return status;
return 0;
}
int rt2x00usb_alloc_reg(struct rt2x00_dev *rt2x00dev) {
rt2x00dev->csr.cache = malloc(CSR_CACHE_SIZE);
if (!rt2x00dev->csr.cache) {
return -ENOMEM;
}
rt2x00dev->eeprom = (__le16*) malloc(rt2x00dev->ops->eeprom_size);
if (!rt2x00dev->eeprom) {
free(rt2x00dev->csr.cache);
return -ENOMEM;
}
rt2x00dev->rf = (u32 *) malloc(rt2x00dev->ops->rf_size);
if (!rt2x00dev->rf) {
free(rt2x00dev->csr.cache);
free(rt2x00dev->eeprom);
return -ENOMEM;
}
return 0;
}
void rt2x00usb_free(struct rt2x00_dev *rt2x00dev) {
if (rt2x00dev == NULL)
return;
if (rt2x00dev->csr.cache)
free(rt2x00dev->csr.cache);
if (rt2x00dev->eeprom)
free(rt2x00dev->eeprom);
if (rt2x00dev->rf)
free(rt2x00dev->rf);
free(rt2x00dev);
return;
}

View File

@ -0,0 +1,296 @@
/*
* Copyright (C) 2010 Willow Garage <http://www.willowgarage.com>
* Copyright (C) 2004 - 2010 Ivo van Doorn <IvDoorn@gmail.com>
* <http://rt2x00.serialmonkey.com>
*
* GPL-2.0-or-later
*
* Userspace port (C) 2019 Hak5 Inc
*
*/
#ifndef __RT2x00USB_H__
#define __RT2x00USB_H__
#include "kernel/types.h"
#include "rt2800usb/rt2x00.h"
/**
* enum rt2x00usb_vendor_request: USB vendor commands.
*/
enum rt2x00usb_vendor_request {
USB_DEVICE_MODE = 1,
USB_SINGLE_WRITE = 2,
USB_SINGLE_READ = 3,
USB_MULTI_WRITE = 6,
USB_MULTI_READ = 7,
USB_EEPROM_WRITE = 8,
USB_EEPROM_READ = 9,
USB_LED_CONTROL = 10, /* RT73USB */
USB_RX_CONTROL = 12,
};
/**
* enum rt2x00usb_mode_offset: Device modes offset.
*/
enum rt2x00usb_mode_offset {
USB_MODE_RESET = 1,
USB_MODE_UNPLUG = 2,
USB_MODE_FUNCTION = 3,
USB_MODE_TEST = 4,
USB_MODE_SLEEP = 7, /* RT73USB */
USB_MODE_FIRMWARE = 8, /* RT73USB */
USB_MODE_WAKEUP = 9, /* RT73USB */
USB_MODE_AUTORUN = 17, /* RT2800USB */
};
/**
* rt2x00usb_vendor_request - Send register command to device
* @rt2x00dev: Pointer to &struct rt2x00_dev
* @request: USB vendor command (See &enum rt2x00usb_vendor_request)
* @requesttype: Request type &USB_VENDOR_REQUEST_*
* @offset: Register offset to perform action on
* @value: Value to write to device
* @buffer: Buffer where information will be read/written to by device
* @buffer_length: Size of &buffer
* @timeout: Operation timeout
*
* This is the main function to communicate with the device,
* the &buffer argument _must_ either be NULL or point to
* a buffer allocated by malloc. Failure to do so can lead
* to unexpected behavior depending on the architecture.
*/
int rt2x00usb_vendor_request(struct rt2x00_dev *rt2x00dev,
const u8 request, const u8 requesttype,
const u16 offset, const u16 value,
void *buffer, const u16 buffer_length,
const int timeout);
/**
* rt2x00usb_vendor_request_buff - Send register command to device (buffered)
* @rt2x00dev: Pointer to &struct rt2x00_dev
* @request: USB vendor command (See &enum rt2x00usb_vendor_request)
* @requesttype: Request type &USB_VENDOR_REQUEST_*
* @offset: Register offset to perform action on
* @buffer: Buffer where information will be read/written to by device
* @buffer_length: Size of &buffer
*
* This function will use a previously with malloc allocated cache
* to communicate with the device. The contents of the buffer pointer
* will be copied to this cache when writing, or read from the cache
* when reading.
* Buffers send to &rt2x00usb_vendor_request _must_ be allocated with
* kmalloc. Hence the reason for using a previously allocated cache
* which has been allocated properly.
*/
int rt2x00usb_vendor_request_buff(struct rt2x00_dev *rt2x00dev,
const u8 request, const u8 requesttype,
const u16 offset, void *buffer,
const u16 buffer_length);
/**
* rt2x00usb_vendor_request_buff - Send register command to device (buffered)
* @rt2x00dev: Pointer to &struct rt2x00_dev
* @request: USB vendor command (See &enum rt2x00usb_vendor_request)
* @requesttype: Request type &USB_VENDOR_REQUEST_*
* @offset: Register offset to perform action on
* @buffer: Buffer where information will be read/written to by device
* @buffer_length: Size of &buffer
* @timeout: Operation timeout
*
* A version of &rt2x00usb_vendor_request_buff which must be called
* if the usb_cache_mutex is already held.
*/
int rt2x00usb_vendor_req_buff_lock(struct rt2x00_dev *rt2x00dev,
const u8 request, const u8 requesttype,
const u16 offset, void *buffer,
const u16 buffer_length, const int timeout);
/**
* rt2x00usb_vendor_request_sw - Send single register command to device
* @rt2x00dev: Pointer to &struct rt2x00_dev
* @request: USB vendor command (See &enum rt2x00usb_vendor_request)
* @offset: Register offset to perform action on
* @value: Value to write to device
* @timeout: Operation timeout
*
* Simple wrapper around rt2x00usb_vendor_request to write a single
* command to the device. Since we don't use the buffer argument we
* don't have to worry about kmalloc here.
*/
static inline int rt2x00usb_vendor_request_sw(struct rt2x00_dev *rt2x00dev,
const u8 request,
const u16 offset,
const u16 value,
const int timeout) {
return rt2x00usb_vendor_request(rt2x00dev, request,
USB_VENDOR_REQUEST_OUT, offset,
value, NULL, 0, timeout);
}
/**
* rt2x00usb_eeprom_read - Read eeprom from device
* @rt2x00dev: Pointer to &struct rt2x00_dev
* @eeprom: Pointer to eeprom array to store the information in
* @length: Number of bytes to read from the eeprom
*
* Simple wrapper around rt2x00usb_vendor_request to read the eeprom
* from the device. Note that the eeprom argument _must_ be allocated using
* kmalloc for correct handling inside the kernel USB layer.
*/
static inline int rt2x00usb_eeprom_read(struct rt2x00_dev *rt2x00dev,
__le16 *eeprom, const u16 length) {
return rt2x00usb_vendor_request(rt2x00dev, USB_EEPROM_READ,
USB_VENDOR_REQUEST_IN, 0, 0,
eeprom, length, EEPROM_TIMEOUT);
}
/**
* rt2x00usb_register_read - Read 32bit register word
* @rt2x00dev: Device pointer, see &struct rt2x00_dev.
* @offset: Register offset
*
* This function is a simple wrapper for 32bit register access
* through rt2x00usb_vendor_request_buff().
*/
static inline u32 rt2x00usb_register_read(struct rt2x00_dev *rt2x00dev,
const unsigned int offset) {
__le32 reg = 0;
rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_READ,
USB_VENDOR_REQUEST_IN, offset,
&reg, sizeof(reg));
return le32_to_cpu(reg);
}
/**
* rt2x00usb_register_read_lock - Read 32bit register word
* @rt2x00dev: Device pointer, see &struct rt2x00_dev.
* @offset: Register offset
*
* This function is a simple wrapper for 32bit register access
* through rt2x00usb_vendor_req_buff_lock().
*/
static inline u32 rt2x00usb_register_read_lock(struct rt2x00_dev *rt2x00dev,
const unsigned int offset) {
__le32 reg = 0;
rt2x00usb_vendor_req_buff_lock(rt2x00dev, USB_MULTI_READ,
USB_VENDOR_REQUEST_IN, offset,
&reg, sizeof(reg), REGISTER_TIMEOUT);
return le32_to_cpu(reg);
}
/**
* rt2x00usb_register_multiread - Read 32bit register words
* @rt2x00dev: Device pointer, see &struct rt2x00_dev.
* @offset: Register offset
* @value: Pointer to where register contents should be stored
* @length: Length of the data
*
* This function is a simple wrapper for 32bit register access
* through rt2x00usb_vendor_request_buff().
*/
static inline void rt2x00usb_register_multiread(struct rt2x00_dev *rt2x00dev,
const unsigned int offset,
void *value, const u32 length) {
rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_READ,
USB_VENDOR_REQUEST_IN, offset,
value, length);
}
/**
* rt2x00usb_register_write - Write 32bit register word
* @rt2x00dev: Device pointer, see &struct rt2x00_dev.
* @offset: Register offset
* @value: Data which should be written
*
* This function is a simple wrapper for 32bit register access
* through rt2x00usb_vendor_request_buff().
*/
static inline void rt2x00usb_register_write(struct rt2x00_dev *rt2x00dev,
const unsigned int offset,
u32 value) {
__le32 reg = cpu_to_le32(value);
rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_WRITE,
USB_VENDOR_REQUEST_OUT, offset,
&reg, sizeof(reg));
}
/**
* rt2x00usb_register_write_lock - Write 32bit register word
* @rt2x00dev: Device pointer, see &struct rt2x00_dev.
* @offset: Register offset
* @value: Data which should be written
*
* This function is a simple wrapper for 32bit register access
* through rt2x00usb_vendor_req_buff_lock().
*/
static inline void rt2x00usb_register_write_lock(struct rt2x00_dev *rt2x00dev,
const unsigned int offset,
u32 value) {
__le32 reg = cpu_to_le32(value);
rt2x00usb_vendor_req_buff_lock(rt2x00dev, USB_MULTI_WRITE,
USB_VENDOR_REQUEST_OUT, offset,
&reg, sizeof(reg), REGISTER_TIMEOUT);
}
/**
* rt2x00usb_register_multiwrite - Write 32bit register words
* @rt2x00dev: Device pointer, see &struct rt2x00_dev.
* @offset: Register offset
* @value: Data which should be written
* @length: Length of the data
*
* This function is a simple wrapper for 32bit register access
* through rt2x00usb_vendor_request_buff().
*/
static inline void rt2x00usb_register_multiwrite(struct rt2x00_dev *rt2x00dev,
const unsigned int offset,
const void *value,
const u32 length) {
rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_WRITE,
USB_VENDOR_REQUEST_OUT, offset,
(void *)value, length);
}
/**
* rt2x00usb_regbusy_read - Read from register with busy check
* @rt2x00dev: Device pointer, see &struct rt2x00_dev.
* @offset: Register offset
* @field: Field to check if register is busy
* @reg: Pointer to where register contents should be stored
*
* This function will read the given register, and checks if the
* register is busy. If it is, it will sleep for a couple of
* microseconds before reading the register again. If the register
* is not read after a certain timeout, this function will return
* FALSE.
*/
int rt2x00usb_regbusy_read(struct rt2x00_dev *rt2x00dev,
const unsigned int offset,
const struct rt2x00_field32 field,
u32 *reg);
/**
* rt2x00usb_register_read_async - Asynchronously read 32bit register word
* @rt2x00dev: Device pointer, see &struct rt2x00_dev.
* @offset: Register offset
* @callback: Functon to call when read completes.
*
* Submit a control URB to read a 32bit register. This safe to
* be called from atomic context. The callback will be called
* when the URB completes. Otherwise the function is similar
* to rt2x00usb_register_read().
* When the callback function returns false, the memory will be cleaned up,
* when it returns true, the urb will be fired again.
*/
void rt2x00usb_register_read_async(struct rt2x00_dev *rt2x00dev,
const unsigned int offset,
bool (*callback)(struct rt2x00_dev*, int, u32));
int rt2x00usb_alloc_reg(struct rt2x00_dev *rt2x00dev);
void rt2x00usb_free(struct rt2x00_dev *rt2x00dev);
int rt2x00usb_initialize(struct rt2x00_dev *rt2x00dev);
#endif /* ifndef RT2x00USB_H */

View File

@ -0,0 +1,832 @@
/*
* GPL-2.0-or-later
*
* Userspace port (C) 2019 Hak5 Inc
*
*/
#include <errno.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#ifndef _WIN32
#include <sys/time.h>
#include <unistd.h>
#else
#include <Windows.h>
#define usleep(x) Sleep((x) < 1000 ? 1 : (x) / 1000)
#define sleep(x) Sleep(x * 1000)
#endif
#ifdef __APPLE__
#include <mach-o/dyld.h>
#endif
#include "userspace.h"
#include "rt2800usb/rt2800usb.h"
#ifdef _WIN32
/*
* Kluge a windows time into a user time
*/
int gettimeofday(struct timeval* tp, struct timezone* tzp) {
static const uint64_t EPOCH = ((uint64_t)116444736000000000ULL);
SYSTEMTIME system_time;
FILETIME file_time;
uint64_t time;
GetSystemTime(&system_time);
SystemTimeToFileTime(&system_time, &file_time);
time = ((uint64_t)file_time.dwLowDateTime);
time += ((uint64_t)file_time.dwHighDateTime) << 32;
tp->tv_sec = (long)((time - EPOCH) / 10000000L);
tp->tv_usec = (long)(system_time.wMilliseconds * 1000);
return 0;
}
#define timercmp(a, b, CMP) \
(((a)->tv_sec == (b)->tv_sec) ? \
((a)->tv_usec CMP (b)->tv_usec) : \
((a)->tv_sec CMP (b)->tv_sec))
#define timeradd(a, b, result) \
do { \
(result)->tv_sec = (a)->tv_sec + (b)->tv_sec; \
(result)->tv_usec = (a)->tv_usec + (b)->tv_usec; \
if ((result)->tv_usec >= 1000000) \
{ \
++(result)->tv_sec; \
(result)->tv_usec -= 1000000; \
} \
} while (0)
#define timersub(a, b, result) \
do { \
(result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \
(result)->tv_usec = (a)->tv_usec - (b)->tv_usec; \
if ((result)->tv_usec < 0) { \
--(result)->tv_sec; \
(result)->tv_usec += 1000000; \
} \
} while (0)
#endif
void *userspace_wifi_service_thread(void *ctx) {
struct userspace_wifi_context *context = (struct userspace_wifi_context *) ctx;
int r;
while (context->service_thread_enabled) {
r = libusb_handle_events_completed(context->libusb_context, NULL);
if (r != 0) {
userspace_wifi_error(context, NULL, r, "Failed to handle USB events: %s",
libusb_error_name(r));
}
}
return NULL;
}
void *userspace_wifi_cmd_service_thread(void *ctx) {
struct userspace_wifi_context *context = (struct userspace_wifi_context *) ctx;
struct userspace_wifi_command *command;
while (context->cmd_thread_enabled) {
pthread_mutex_lock(&context->cmd_wakeup_mutex);
pthread_cond_wait(&context->cmd_wakeup_cond, &context->cmd_wakeup_mutex);
while (1) {
pthread_mutex_lock(&context->cmd_mutex);
command = context->cmd_queue;
if (command != NULL) {
context->cmd_queue = command->next;
if (context->cmd_queue == NULL)
context->cmd_queue_last = NULL;
/* We must unlock BEFORE calling the callback */
pthread_mutex_unlock(&context->cmd_mutex);
(command->callback)(context, command->device, command->param);
free(command);
continue;
}
pthread_mutex_unlock(&context->cmd_mutex);
break;
}
pthread_mutex_unlock(&context->cmd_wakeup_mutex);
}
return NULL;
}
#ifdef __APPLE__
/* Find the last instance of the / in the path and slice everything
* after it off by chopping with a \0. Modifies the passed path. */
void chop_after_last_slash(char *path) {
char *last = path;
char *pos = NULL;
while ((pos = strstr(last + 1, "/")) != NULL) {
last = pos;
}
last[0] = 0;
}
#endif
/*
* Standard firmware loader which looks in the specified firmware dir (if any), various
* system directories, and the libwifiuserspace share directory
*/
int userspace_load_firmware_file(const struct userspace_wifi_context *context, const char *file_name,
const char **file_hints, size_t hints_len,
uint8_t **firmware_blob, size_t *blob_len) {
FILE *fwfile = NULL;
int fwfd = -1;
struct stat statbuf;
char fw_path[2048];
size_t i;
#ifdef __APPLE__
char exe_path[2048];
uint32_t exe_path_sz = 2048;
#endif
/* Start by looking at the context dir, if any */
if (context->firmware_directory != NULL) {
snprintf(fw_path, 2048, "%s/%s", context->firmware_directory, file_name);
if ((fwfile = fopen(fw_path, "rb")) != NULL)
goto got_file;
/* Look at all the hints */
for (i = 0; i < hints_len; i++) {
snprintf(fw_path, 2048, "%s/%s/%s", context->firmware_directory, file_hints[i], file_name);
if ((fwfile = fopen(fw_path, "rb")) != NULL)
goto got_file;
}
}
/* Look at the current directory */
snprintf(fw_path, 2048, "%s", file_name);
if ((fwfile = fopen(fw_path, "rb")) != NULL)
goto got_file;
/* Look at all the hints */
for (i = 0; i < hints_len; i++) {
snprintf(fw_path, 2048, "%s/%s", file_hints[i], file_name);
if ((fwfile = fopen(fw_path, "rb")) != NULL)
goto got_file;
}
/* Look at the share firmware dir */
snprintf(fw_path, 2048, "%s/%s", FIRMWAREDIR, file_name);
if ((fwfile = fopen(fw_path, "rb")) != NULL)
goto got_file;
/* Look at all the hints */
for (i = 0; i < hints_len; i++) {
snprintf(fw_path, 2048, "%s/%s/%s", FIRMWAREDIR, file_hints[i], file_name);
if ((fwfile = fopen(fw_path, "rb")) != NULL)
goto got_file;
}
/* Look at the stock linux firmware dir */
snprintf(fw_path, 2048, "%s/%s", "/lib/firmware/", file_name);
if ((fwfile = fopen(fw_path, "rb")) != NULL)
goto got_file;
/* Look at all the hints */
for (i = 0; i < hints_len; i++) {
snprintf(fw_path, 2048, "%s/%s/%s", "/lib/firmware/", file_hints[i], file_name);
if ((fwfile = fopen(fw_path, "rb")) != NULL)
goto got_file;
}
/* Look in our path in case we're on OSX and the firmware is in our framework */
#ifdef __APPLE__
if (_NSGetExecutablePath(exe_path, &exe_path_sz) == 0) {
chop_after_last_slash(exe_path);
snprintf(fw_path, 2048, "%s/%s/%s", exe_path, "../Resources/firmware/", file_name);
if ((fwfile = fopen(fw_path, "rb")) != NULL)
goto got_file;
/* Look at all the hints */
for (i = 0; i < hints_len; i++) {
snprintf(fw_path, 2048, "%s/%s/%s/%s", exe_path, "../Resources/firmware/", file_hints[i], file_name);
if ((fwfile = fopen(fw_path, "rb")) != NULL)
goto got_file;
}
}
#endif
goto no_file;
got_file:
fwfd = fileno(fwfile);
if (fstat(fwfd, &statbuf) != 0) {
fclose(fwfile);
userspace_wifi_error(context, NULL, -ENOENT, "Could not find firmware file '%s'",
file_name);
return -ENOENT;
}
#ifndef _WIN32
if (!S_ISREG(statbuf.st_mode)) {
fclose(fwfile);
userspace_wifi_error(context, NULL, -ENOENT, "Firmware file '%s' not a normal file",
file_name);
return -ENOENT;
}
#endif
(*firmware_blob) = (uint8_t *) malloc(statbuf.st_size);
if ((*firmware_blob) == NULL) {
fclose(fwfile);
goto no_mem;
}
*blob_len = statbuf.st_size;
fread((*firmware_blob), *blob_len, 1, fwfile);
fclose(fwfile);
return 0;
no_file:
userspace_wifi_error(context, NULL, -ENOENT, "Could not find firmware file '%s' in "
"any of the standard locations. Make sure you've installed the required "
"firmware files.", file_name);
return -ENOENT;
no_mem:
userspace_wifi_error(context, NULL, -ENOENT, "Could not allocate memory to load "
"firmware file '%s'", file_name);
return -ENOMEM;
}
int userspace_wifi_init(struct userspace_wifi_context **context) {
/* int status; */
*context = (struct userspace_wifi_context *) malloc(sizeof(struct userspace_wifi_context));
if (*context == NULL)
return -1;
memset(*context, 0, sizeof(struct userspace_wifi_context));
(*context)->devs = NULL;
(*context)->devs_cnt = 0;
(*context)->service_device_count = 0;
(*context)->load_firmware_file = &userspace_load_firmware_file;
/*
status = libusb_init(&(*context)->libusb_context);
if (status < 0)
return status;
*/
pthread_mutex_init(&(*context)->libusb_mutex, NULL);
(*context)->cmd_thread_enabled = true;
pthread_mutex_init(&(*context)->cmd_mutex, NULL);
pthread_mutex_init(&(*context)->cmd_wakeup_mutex, NULL);
pthread_cond_init(&(*context)->cmd_wakeup_cond, NULL);
pthread_create(&(*context)->cmd_thread, NULL, userspace_wifi_cmd_service_thread, (*context));
pthread_mutex_init(&(*context)->led_ts_mutex, NULL);
pthread_mutex_init(&(*context)->led_cond_mutex, NULL);
pthread_cond_init(&(*context)->led_cond, NULL);
(*context)->led_devs = NULL;
(*context)->led_thread_enable = false;
return 0;
}
void userspace_wifi_free(struct userspace_wifi_context *context) {
if (context != NULL) {
context->service_thread_enabled = false;
if (context->devs != NULL) {
libusb_free_device_list(context->devs, 1);
}
if (context->libusb_context != NULL)
libusb_exit(context->libusb_context);
if (context->service_thread_active) {
pthread_join(context->async_service_thread, NULL);
}
free(context);
}
}
int userspace_wifi_probe(struct userspace_wifi_context *context,
struct userspace_wifi_probe_dev **devices) {
struct userspace_wifi_probe_dev *probe_dev;
int i, ret;
struct libusb_device_descriptor desc;
struct libusb_device_handle *handle;
int probed_count = 0;
if (context->devs != NULL)
libusb_free_device_list(context->devs, 1);
if (context->libusb_context != NULL)
libusb_exit(context->libusb_context);
libusb_init(&context->libusb_context);
context->devs = NULL;
*devices = NULL;
context->devs_cnt = libusb_get_device_list(context->libusb_context, &(context->devs));
if (context->devs_cnt <= 0)
return context->devs_cnt;
/*
* Scan via each of the userspace drivers
*/
for (i = 0; context->devs[i]; ++i) {
ret = libusb_get_device_descriptor(context->devs[i], &desc);
if (ret != 0)
continue;
ret = libusb_open(context->devs[i], &handle);
if (ret != 0)
continue;
/*
* For each supported driver, probe until we get a match.
* For each match, add it to our count and our linked list
*/
if (rt2800usb_probe_device(&desc, &probe_dev) > 0) {
probe_dev->context = context;
probe_dev->dev = context->devs[i];
/*
* Collect as much info about the device as we can, we need it to
* identify grouped devices for some platforms
*/
probe_dev->usb_bus = libusb_get_bus_number(context->devs[i]);
probe_dev->usb_port = libusb_get_port_number(context->devs[i]);
probe_dev->usb_device = libusb_get_device_address(context->devs[i]);
ret = libusb_get_port_numbers(context->devs[i], probe_dev->usb_bus_path, 8);
if (ret > 0) {
probe_dev->usb_bus_path_len = ret;
}
if (desc.iSerialNumber) {
libusb_get_string_descriptor_ascii(handle, desc.iSerialNumber,
probe_dev->usb_serial, 64);
}
probe_dev->next = *devices;
*devices = probe_dev;
probe_dev = NULL;
probed_count++;
}
libusb_close(handle);
}
return probed_count;
}
void userspace_wifi_free_probe(struct userspace_wifi_probe_dev *devices) {
struct userspace_wifi_probe_dev *next;
while (devices != NULL) {
next = devices->next;
if (devices->driver_name)
free(devices->driver_name);
if (devices->device_type)
free(devices->device_type);
free(devices);
devices = next;
}
}
void userspace_wifi_for_each_probe(struct userspace_wifi_context *context,
struct userspace_wifi_probe_dev *devices,
int (*cb)(struct userspace_wifi_context *, struct userspace_wifi_probe_dev *)) {
struct userspace_wifi_probe_dev *next = devices;
int r;
while (next != NULL) {
r = (*cb)(context, next);
if (r)
return;
next = next->next;
}
}
void userspace_wifi_handle_usbio(struct userspace_wifi_context *context) {
context->service_thread_enabled = true;
int r;
while (context->service_thread_enabled) {
r = libusb_handle_events_completed(context->libusb_context, NULL);
if (r < 0) {
userspace_wifi_error(context, NULL, r, "Handling USB IO queue failed: %s",
libusb_error_name(r));
break;
}
}
}
int userspace_wifi_device_open(struct userspace_wifi_context *context,
struct userspace_wifi_probe_dev *probedevice,
struct userspace_wifi_dev **device) {
int r;
if (!context->service_thread_enabled) {
context->service_thread_enabled = true;
context->service_thread_active = true;
pthread_create(&context->async_service_thread, NULL, userspace_wifi_service_thread, context);
}
r = (*(probedevice->open_device))(probedevice, device);
if (r < 0) {
userspace_wifi_error(context, *device, r, "Opening device failed");
return r;
}
#if 0
if (!context->service_thread_active) {
context->service_thread_enabled = true;
context->service_thread_active = true;
context->service_device_count++;
pthread_create(&(context->async_service_thread), NULL, userspace_wifi_service_thread, context);
}
#endif
return r;
}
/*
* Queue work to the end of the worker queue
*/
void userspace_wifi_queue_work(struct userspace_wifi_context *context,
struct userspace_wifi_dev *device,
void (*callback)(struct userspace_wifi_context *context,
struct userspace_wifi_dev *device,
void *param), void *param) {
struct userspace_wifi_command *cmd =
(struct userspace_wifi_command *) malloc(sizeof(struct userspace_wifi_command));
cmd->next = NULL;
cmd->device = device;
cmd->callback = callback;
cmd->param = param;
pthread_mutex_lock(&context->cmd_mutex);
cmd->id = context->work_id++;
if (context->cmd_queue == NULL) {
context->cmd_queue = cmd;
context->cmd_queue_last = cmd;
} else {
context->cmd_queue_last->next = cmd;
context->cmd_queue_last = cmd;
}
/* Signal the worker thread */
pthread_cond_signal(&context->cmd_wakeup_cond);
pthread_mutex_unlock(&context->cmd_mutex);
}
void _userspace_wifi_start_capture_cb(struct userspace_wifi_context *context,
struct userspace_wifi_dev *device,
void *param) {
/*
* TODO handle error and backpropagate
*/
device->start_capture(device);
}
int userspace_wifi_device_start_capture(struct userspace_wifi_context *context,
struct userspace_wifi_dev *device) {
userspace_wifi_queue_work(context, device, &_userspace_wifi_start_capture_cb, NULL);
return 0;
}
void _userspace_wifi_stop_capture_cb(struct userspace_wifi_context *context,
struct userspace_wifi_dev *device,
void *param) {
device->start_capture(device);
}
int userspace_wifi_device_stop_capture(struct userspace_wifi_context *context,
struct userspace_wifi_dev *device) {
userspace_wifi_queue_work(context, device, &_userspace_wifi_stop_capture_cb, NULL);
return 0;
}
struct _userspace_wifi_channel_param {
int channel;
enum nl80211_chan_width width;
};
void _userspace_wifi_channel_cb(struct userspace_wifi_context *context,
struct userspace_wifi_dev *device,
void *param) {
struct _userspace_wifi_channel_param *ch = (struct _userspace_wifi_channel_param *) param;
int r;
/*
* TODO handle error and backpropagate
*/
r = device->set_channel(device, ch->channel, ch->width);
if (r < 0)
userspace_wifi_error(context, device, r, "Setting channel %d:%d failed: %d / %s",
ch->channel, ch->width, r, strerror(r));
free(ch);
}
int userspace_wifi_device_set_channel(struct userspace_wifi_context *context,
struct userspace_wifi_dev *dev,
int channel, enum nl80211_chan_width width) {
struct _userspace_wifi_channel_param *p =
(struct _userspace_wifi_channel_param *) malloc(sizeof(struct _userspace_wifi_channel_param));
if (p == NULL)
return -ENOMEM;
p->channel = channel;
p->width = width;
userspace_wifi_queue_work(context, dev, &_userspace_wifi_channel_cb, p);
return 0;
}
void _userspace_wifi_led_on(struct userspace_wifi_context *context,
struct userspace_wifi_dev *device,
void *param) {
device->set_led(device, true);
}
void _userspace_wifi_led_off(struct userspace_wifi_context *context,
struct userspace_wifi_dev *device,
void *param) {
device->set_led(device, false);
}
int userspace_wifi_device_set_led(struct userspace_wifi_context *context,
struct userspace_wifi_dev *dev, bool enable) {
if (enable)
userspace_wifi_queue_work(context, dev, &_userspace_wifi_led_on, NULL);
else
userspace_wifi_queue_work(context, dev, &_userspace_wifi_led_off, NULL);
return 0;
}
void *_userspace_wifi_led_thread(void *ctx) {
struct userspace_wifi_context *context = (struct userspace_wifi_context *) ctx;
struct userspace_wifi_dev_led *led;
struct timeval now;
struct timeval diff_ts;
struct timeval sleep_ts;
while (context->led_thread_enable) {
sleep_ts.tv_sec = 0;
sleep_ts.tv_usec = 0;
diff_ts.tv_sec = 0;
diff_ts.tv_usec = 0;
pthread_mutex_lock(&context->led_ts_mutex);
gettimeofday(&now, NULL);
led = context->led_devs;
while (led) {
if (led->trigger_ts.tv_sec == 0) {
led = led->next;
continue;
}
/*
* Did we miss the timer?
*/
if (timercmp(&led->trigger_ts, &now, <=)) {
/*
* Zero out the trigger
*/
led->trigger_ts.tv_sec = 0;
userspace_wifi_device_set_led(context, led->dev, led->restore_state);
led = led->next;
continue;
}
/*
* Otherwise we're still waiting; Figure out when to wake up. We want to find
* the most likely next timer.
*/
timersub(&led->trigger_ts, &now, &diff_ts);
if (timercmp(&sleep_ts, &diff_ts, <)) {
sleep_ts.tv_sec = diff_ts.tv_sec;
sleep_ts.tv_usec = diff_ts.tv_usec;
if (sleep_ts.tv_sec > 0) {
printf("something weird in sleep for device %d: %lu secs\n", led->dev->dev_id, sleep_ts.tv_sec);
}
}
led = led->next;
}
pthread_mutex_unlock(&context->led_ts_mutex);
/*
* Sleep the shortest amount of time and try all the timers again without
* waiting for a cond signal
*/
if (sleep_ts.tv_sec != 0 || sleep_ts.tv_usec != 0) {
sleep(sleep_ts.tv_sec);
usleep(sleep_ts.tv_usec);
continue;
}
/*
* Otherwise we've handled all extant timers, sleep the thread until we get a
* conditional kick
*/
pthread_mutex_lock(&context->led_cond_mutex);
pthread_cond_wait(&context->led_cond, &context->led_cond_mutex);
pthread_mutex_unlock(&context->led_cond_mutex);
}
return NULL;
}
void _userspace_wifi_start_led_thread(struct userspace_wifi_context *context) {
context->led_thread_enable = true;
pthread_create(&context->led_thread, NULL, _userspace_wifi_led_thread, context);
pthread_cond_signal(&context->led_cond);
}
void _userspace_wifi_kill_led_thread(struct userspace_wifi_context *context) {
context->led_thread_enable = false;
pthread_cond_signal(&context->led_cond);
pthread_join(context->led_thread, NULL);
}
int userspace_wifi_device_enable_led_control(struct userspace_wifi_context *context,
struct userspace_wifi_dev *device) {
struct userspace_wifi_dev_led *led =
(struct userspace_wifi_dev_led *) malloc(sizeof(struct userspace_wifi_dev_led));
if (led == NULL)
return -ENOMEM;
memset(led, 0, sizeof(struct userspace_wifi_dev_led));
device->led_control = led;
led->dev = device;
led->next = NULL;
pthread_mutex_lock(&context->led_ts_mutex);
led->next = context->led_devs;
context->led_devs = led;
if (!context->led_thread_enable)
_userspace_wifi_start_led_thread(context);
pthread_mutex_unlock(&context->led_ts_mutex);
return 0;
}
void userspace_wifi_device_disable_led_control(struct userspace_wifi_context *context,
struct userspace_wifi_dev *device) {
struct userspace_wifi_dev_led *led = NULL, *removal = NULL;
pthread_mutex_lock(&context->led_ts_mutex);
led = context->led_devs;
if (led == device->led_control) {
context->led_devs = led->next;
removal = led;
} else {
while (led) {
if (led->next == device->led_control) {
led->next = device->led_control->next;
removal = led;
break;
}
led = led->next;
}
}
if (!removal) {
pthread_mutex_unlock(&context->led_ts_mutex);
return;
}
free(removal);
device->led_control = NULL;
if (context->led_devs == NULL)
_userspace_wifi_kill_led_thread(context);
pthread_mutex_unlock(&context->led_ts_mutex);
}
int userspace_wifi_device_blink_led(struct userspace_wifi_context *context,
struct userspace_wifi_dev *device,
unsigned int duration_us, bool restore_state,
bool extend) {
struct timeval add_ts = {
.tv_sec = 0,
.tv_usec = duration_us
};
struct timeval now;
if (device->led_control == NULL)
return -ENODEV;
pthread_mutex_lock(&context->led_ts_mutex);
/*
* Only toggle the LED if we're not in a timer
*/
if (device->led_control->trigger_ts.tv_sec == 0) {
userspace_wifi_device_set_led(context, device, !restore_state);
}
/*
* If we're extending the timer or there is no timer
*/
if (extend || device->led_control->trigger_ts.tv_sec == 0) {
gettimeofday(&now, NULL);
timeradd(&now, &add_ts, &device->led_control->trigger_ts);
device->led_control->restore_state = restore_state;
/*
* Wake up the thread if it isn't already in a processing state
*/
pthread_cond_signal(&context->led_cond);
}
pthread_mutex_unlock(&context->led_ts_mutex);
return 0;
}

View File

@ -0,0 +1,434 @@
/*
* GPL-2.0-or-later
*
* Userspace port (C) 2019 Hak5 LLC
*
*/
#ifndef __USERSPACE_H__
#define __USERSPACE_H__
#include <pthread.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdarg.h>
#include <libusb.h>
#include "kernel/nl80211.h"
#include "kernel/types.h"
#include "kernel/usb.h"
/*
* Userspace wifi USB context; this is used to store a bunch of state info
* like the USB device list which we need to keep until we shut down
*/
/*
* Forward definitions of various stuff we need
*/
struct userspace_wifi_dev;
struct userspace_wifi_command;
struct userspace_wifi_dev_led;
struct userspace_wifi_rx_signal;
struct userspace_wifi_context {
struct libusb_context *libusb_context;
struct libusb_device **devs;
ssize_t devs_cnt;
/*
* Libusb async can't handle scheduling multiple things at once so we have to guard it
*/
pthread_mutex_t libusb_mutex;
pthread_t async_service_thread;
bool service_thread_enabled;
bool service_thread_active;
int service_device_count;
/*
* We can't perform operations on the service thread so we have to process them
* through a helper thread
*/
pthread_t cmd_thread;
bool cmd_thread_enabled;
pthread_mutex_t cmd_mutex;
pthread_mutex_t cmd_wakeup_mutex;
pthread_cond_t cmd_wakeup_cond;
struct userspace_wifi_command *cmd_queue;
struct userspace_wifi_command *cmd_queue_last;
unsigned long long work_id;
/*
* Optional, where to find the firmware. Can be set by the consumer
* to pass an alternate firmware directory. By default, firmware fetches
* look in the default directory set at install time.
*/
char *firmware_directory;
/*
* Helper function called BY the drivers, to load firmware of a given name. Can be
* overridden in the future. Can include 'hints' from the driver to help find
* nested firmware (for instance in the linux firmware tree).
*
* Returns 0 and firmware_blob as an allocated chunk and blob_len as length,
* or negative error
*/
int (*load_firmware_file)(const struct userspace_wifi_context *context,
const char *file_name, const char **file_hints, size_t hints_len,
uint8_t **firmware_blob, size_t *blob_len);
/*
* Helper functions supplied by the consumer, called by the
* driver
*/
/*
* Record used by the consumer to store state
*/
void *local_data;
/*
* Called on error, with a string and numerical error code. This being
* called indicates an unrecoverable error condition.
*
* error_str will be null terminated, but may be a pointer to a stack
* variable of the calling function. Any storage of this value must be
* copied (via strdup, etc)
*/
void (*handle_error)(const struct userspace_wifi_context *context,
struct userspace_wifi_dev *dev,
const char *error_str, int error_code);
/*
* Handle an incoming packet and l1 signal data
*/
int (*handle_packet_rx)(struct userspace_wifi_context *context,
struct userspace_wifi_dev *dev,
struct userspace_wifi_rx_signal *signal,
unsigned char *data, unsigned int len);
/*
* Blinking LEDs takes a surprising amount of work! We need to run
* another thread that knows when to turn them off.
*/
pthread_t led_thread;
bool led_thread_enable;
/*
* Trigger condition for waking up a sleeping LED control thread
*/
pthread_mutex_t led_cond_mutex;
pthread_cond_t led_cond;
/*
* Access control mutex for adding/removing devices from the LED control list
*/
pthread_mutex_t led_ts_mutex;
struct userspace_wifi_dev_led *led_devs;
};
/*
* We need to track each device we control for LEDs; we need to know when to turn
* the LED on or off, and what state to return it to.
*/
struct userspace_wifi_dev_led {
struct userspace_wifi_dev_led *next;
struct userspace_wifi_dev *dev;
struct timeval trigger_ts;
bool restore_state;
};
static inline void userspace_wifi_lock(struct userspace_wifi_context *context) {
pthread_mutex_lock(&context->libusb_mutex);
}
static inline void userspace_wifi_unlock(struct userspace_wifi_context *context) {
pthread_mutex_unlock(&context->libusb_mutex);
}
/*
* Command thread interactions take place using a generic structure which the command
* handlers fill in
*/
struct userspace_wifi_command {
struct userspace_wifi_command *next;
struct userspace_wifi_dev *device;
void (*callback)(struct userspace_wifi_context *context,
struct userspace_wifi_dev *device,
void *param);
void *param;
unsigned long long id;
};
void userspace_wifi_queue_work(struct userspace_wifi_context *context,
struct userspace_wifi_dev *dev,
void (*callback)(struct userspace_wifi_context *context,
struct userspace_wifi_dev *device,
void *param), void *param);
/*
* Userspace USB device list populated by the scanning function, and used
* to open a userspace USB Wi-Fi device
*/
struct userspace_wifi_probe_dev {
/*
* Context to pass along
*/
struct userspace_wifi_context *context;
/*
* Device that we matched against from the raw hw list
*/
const struct usb_device_id *device_id_match;
/*
* Libusb device we could open as a device_handle
*/
libusb_device *dev;
/*
* Arbitrary name and type
*/
char *driver_name;
char *device_type;
/*
* Bus and device location
*/
int usb_bus;
int usb_port;
int usb_device;
/*
* USB serial number of device
*/
unsigned char usb_serial[64];
/*
* USB bus path
*/
uint8_t usb_bus_path[8];
int usb_bus_path_len;
/*
* Opening function supplied by the driver that found us, opens a *dev into a userspace dev
*/
int (*open_device)(struct userspace_wifi_probe_dev *dev, struct userspace_wifi_dev **udev);
/*
* Linked list of N possible devices to open
*/
struct userspace_wifi_probe_dev *next;
};
/*
* Userspace USB wifi device after it's been opened, with helper functions added by the
* userspace driver
*/
struct userspace_wifi_dev {
/*
* overall context, needed for locks
*/
struct userspace_wifi_context *context;
/*
* Arbitrary device id
*/
int dev_id;
/*
* device hardware/eeprom MAC, if available
*/
uint8_t dev_mac[6];
/*
* USB serial number of device
*/
unsigned char usb_serial[64];
/*
* Record used by the driver (often to hold the usb device state)
*/
void *dev_data;
/*
* Libusb device we could open as a device_handle
*/
libusb_device *dev;
/*
* Do we continue queuing transfers?
*/
bool usb_transfer_active;
/*
* USB data buffer allocated by the driver
*/
unsigned char *usb_transfer_buffer;
/*
* USB async transfer record allocated by the driver
*/
struct libusb_transfer *usb_transfer;
/*
* Helper functions supplied by the driver
*/
int (*start_capture)(struct userspace_wifi_dev *dev);
void (*stop_capture)(struct userspace_wifi_dev *dev);
int (*set_channel)(struct userspace_wifi_dev *dev, int channel, enum nl80211_chan_width width);
int (*set_led)(struct userspace_wifi_dev *dev, bool enable);
/*
* Pointer to the LED control object, if one exists
*/
struct userspace_wifi_dev_led *led_control;
};
/*
* Signal data extracted from radio
*/
struct userspace_wifi_rx_signal {
bool crc_valid;
unsigned int channel;
enum nl80211_band band;
int signal;
enum nl80211_chan_width chan_width;
bool short_gi;
unsigned int mcs;
};
/*
* Initialize the userspace usb driver system; this calls libusb init and
* allocates a context in **context. This context should be freed and
* the system shut down with free_userspace_wifi_system
*/
int userspace_wifi_init(struct userspace_wifi_context **context);
/*
* Clean up the userspace usb driver system
*/
void userspace_wifi_free(struct userspace_wifi_context *context);
/*
* Scan for any supported wifi devices; returns negative error or total number
* of devices found in the probe, and populates **devices with a linked list
* of probe results.
*/
int userspace_wifi_probe(struct userspace_wifi_context *context,
struct userspace_wifi_probe_dev **devices);
/*
* Free the results of a probe list
*/
void userspace_wifi_free_probe(struct userspace_wifi_probe_dev *devices);
/*
* Call a function for each result of a probe list (obscuring the linked list
* internals).
* Callback should return 0 to continue or non-0 to break
*/
void userspace_wifi_for_each_probe(struct userspace_wifi_context *context,
struct userspace_wifi_probe_dev *devices,
int (*cb)(struct userspace_wifi_context *, struct userspace_wifi_probe_dev *));
/*
* Set an error handling callback
*/
static inline void userspace_wifi_set_error_cb(struct userspace_wifi_context *context,
void (*cb)(const struct userspace_wifi_context *, struct userspace_wifi_dev *,
const char *, int)) {
context->handle_error = cb;
}
/*
* Trigger an error
*/
static inline void userspace_wifi_error(const struct userspace_wifi_context *context,
struct userspace_wifi_dev *dev,
int errnum, const char *fmt, ...) {
char buf[2048];
va_list arg_ptr;
va_start(arg_ptr, fmt);
vsnprintf(buf, 2048, fmt, arg_ptr);
va_end(arg_ptr);
if (context->handle_error != NULL) {
(*context->handle_error)(context, dev, buf, errnum);
return;
}
fprintf(stderr, "ERROR: %s\n", buf);
}
/*
* Set a callback for handling packets
*/
static inline void userspace_wifi_set_packet_cb(struct userspace_wifi_context *context,
int (*cb)(struct userspace_wifi_context *context,
struct userspace_wifi_dev *dev,
struct userspace_wifi_rx_signal *signal,
unsigned char *data, unsigned int len)) {
context->handle_packet_rx = cb;
}
/*
* Open a userspace device via the open function supplied by the driver
* Returns 0 on success, non-zero on failure. On success, allocates a usb device in *device.
*/
int userspace_wifi_device_open(struct userspace_wifi_context *context,
struct userspace_wifi_probe_dev *probedevice,
struct userspace_wifi_dev **device);
int userspace_wifi_device_start_capture(struct userspace_wifi_context *context,
struct userspace_wifi_dev *dev);
int userspace_wifi_device_stop_capture(struct userspace_wifi_context *context,
struct userspace_wifi_dev *dev);
int userspace_wifi_device_set_channel(struct userspace_wifi_context *context,
struct userspace_wifi_dev *dev,
int channel, enum nl80211_chan_width width);
int userspace_wifi_device_set_led(struct userspace_wifi_context *context,
struct userspace_wifi_dev *dev, bool enable);
static inline void userspace_wifi_device_set_id(struct userspace_wifi_context *context,
struct userspace_wifi_dev *dev,
int id) {
dev->dev_id = id;
}
static inline int userspace_wifi_device_get_id(const struct userspace_wifi_context *context,
struct userspace_wifi_dev *dev) {
return dev->dev_id;
}
/*
* Enable LED controls for a specific device; this will enable the LED control thread
* if it is not already running.
*/
int userspace_wifi_device_enable_led_control(struct userspace_wifi_context *context,
struct userspace_wifi_dev *device);
void userspace_wifi_device_disable_led_control(struct userspace_wifi_context *context,
struct userspace_wifi_dev *device);
/*
* Blink a LED for duration_ms (setting led to !restore_state), then restore it.
* If extending, extend any existing timer by an additional duration_ms
*/
int userspace_wifi_device_blink_led(struct userspace_wifi_context *context,
struct userspace_wifi_dev *device,
unsigned int duration_ms, bool restore_state, bool extend);
#endif /* ifndef USERSPACE_H */

BIN
macos/AppIcon.icns Normal file

Binary file not shown.

18
macos/Info.plist Normal file
View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleIconFile</key>
<string>WiFiCoconut.icns</string>
<key>CFBundleIdentifier</key>
<string>org.hak5.wifi-coconut</string>
<key>CFBundleName</key>
<string>Wi-Fi Coconut</string>
<key>CFBundleVersion</key>
<string>1.0</string>
<key>CFBundleDisplayName</key>
<string>Wi-Fi Coconut</string>
</dict>
</plist>

12
macos/WiFiCoconut Executable file
View File

@ -0,0 +1,12 @@
#!/usr/bin/osascript
tell app "Terminal"
if not (exists window 1) then reopen
activate
set UnixPath to POSIX path of ((path to me as text) & "::")
set Coconut to "exec '" & UnixPath & "wifi_coconut'"
do script Coconut
end tell

30
macos/finish_release.zsh Executable file
View File

@ -0,0 +1,30 @@
#!/bin/zsh
# Ultimately this should be in a cmake target but getting cmake to build an app
# with multiple executable components is proving extremely difficult.
# Step one: Make the basic app structure
mkdir WiFiCoconut.app
mkdir WiFiCoconut.app/Contents
mkdir WiFiCoconut.app/Contents/MacOS
mkdir WiFiCoconut.app/Contents/Framework
mkdir WiFiCoconut.app/Contents/Resources
# Step two: Copy the pieces of the app together
cp wifi_coconut WiFiCoconut.app/Contents/MacOS
cp ../macos/WiFiCoconut WiFiCoconut.app/Contents/MacOS
cp /usr/local/lib/libusb-1.0.0.dylib WiFiCoconut.app/Contents/Framework
cp -r ../libwifiuserspace/firmware WiFiCoconut.app/Contents/Resources
cp ../macos/AppIcon.icns WiFiCoconut.app/Contents/Resources/WiFiCoconut.icns
cp ../macos/Info.plist WiFiCoconut.app/Contents/
cp ../LICENSE WiFiCoconut.app/Contents/Resources
cp ../LICENSE.firmware WiFiCoconut.app/Contents/Resources
# Step three: Rewrite the native code library path
install_name_tool \
-change /usr/local/opt/libusb/lib/libusb-1.0.0.dylib @executable_path/../Frameworks/libusb-1.0.0.dylib \
WiFiCoconut.app/Contents/MacOS/wifi_coconut
# At this point, WiFiCoconut.app should be built

View File

@ -0,0 +1,363 @@
/*
This file is part of Kismet
Kismet 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.
Kismet is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Kismet; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/* An extremely basic ring buffer implemented as a complete header in pure C;
* for use with datasource implementations in C */
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "simple_ringbuf_c.h"
/* Allocate a ring buffer
*
* Returns NULL if allocation failed
*/
kis_simple_ringbuf_t *kis_simple_ringbuf_create(size_t size) {
kis_simple_ringbuf_t *rb;
rb = (kis_simple_ringbuf_t *) malloc(sizeof(kis_simple_ringbuf_t));
if (rb == NULL)
return NULL;
rb->buffer = (uint8_t *) malloc(size);
if (rb->buffer == NULL) {
free(rb);
return NULL;
}
rb->buffer_sz = size;
rb->start_pos = 0;
rb->length = 0;
rb->mid_peek = 0;
rb->mid_commit = 0;
rb->free_peek = 0;
rb->free_commit = 0;
return rb;
}
/* Destroy a ring buffer
*/
void kis_simple_ringbuf_free(kis_simple_ringbuf_t *ringbuf) {
free(ringbuf->buffer);
free(ringbuf);
}
/* Clear ring buffer
*/
void kis_simple_ringbuf_clear(kis_simple_ringbuf_t *ringbuf) {
ringbuf->start_pos = 0;
ringbuf->length = 0;
}
/* Get available space
*/
size_t kis_simple_ringbuf_available(kis_simple_ringbuf_t *ringbuf) {
return ringbuf->buffer_sz - ringbuf->length;
}
/* Get used space
*/
size_t kis_simple_ringbuf_used(kis_simple_ringbuf_t *ringbuf) {
return ringbuf->length;
}
/* Get total space
* */
size_t kis_simple_ringbuf_size(kis_simple_ringbuf_t *ringbuf) {
return ringbuf->buffer_sz;
}
/* Append data
*
* Returns amount written
*/
size_t kis_simple_ringbuf_write(kis_simple_ringbuf_t *ringbuf,
void *data, size_t length) {
size_t copy_start;
if (kis_simple_ringbuf_available(ringbuf) < length)
return 0;
copy_start =
(ringbuf->start_pos + ringbuf->length) % ringbuf->buffer_sz;
/* Does the write op fit w/out looping? */
if (copy_start + length < ringbuf->buffer_sz) {
memcpy(ringbuf->buffer + copy_start, data, length);
ringbuf->length += length;
return length;
} else {
/* We have to split up, figure out the length of the two chunks */
size_t chunk_a = ringbuf->buffer_sz - copy_start;
size_t chunk_b = length - chunk_a;
memcpy(ringbuf->buffer + ringbuf->start_pos + ringbuf->length, data, chunk_a);
memcpy(ringbuf->buffer, (uint8_t *) data + chunk_a, chunk_b);
/* Increase the length of the buffer */
ringbuf->length += length;
return length;
}
return 0;
}
size_t kis_simple_ringbuf_reserve(kis_simple_ringbuf_t *ringbuf, void **data, size_t size) {
size_t copy_start;
if (kis_simple_ringbuf_available(ringbuf) < size)
return 0;
if (ringbuf->mid_commit) {
fprintf(stderr, "ERROR: kis_simple_ringbuf_t mid-commit when reserve called\n");
return 0;
}
copy_start =
(ringbuf->start_pos + ringbuf->length) % ringbuf->buffer_sz;
/* Does the write op fit w/out looping? */
if (copy_start + size < ringbuf->buffer_sz) {
ringbuf->mid_commit = 1;
ringbuf->free_commit = 0;
*data = ringbuf->buffer + copy_start;
return size;
} else {
*data = malloc(size);
if (*data == NULL) {
fprintf(stderr, "ERROR: Could not allocate split-op sz write buffer\n");
return 0;
}
ringbuf->mid_commit = 1;
ringbuf->free_commit = 1;
return size;
}
return 0;
}
size_t kis_simple_ringbuf_commit(kis_simple_ringbuf_t *ringbuf, void *data, size_t size) {
if (!ringbuf->mid_commit) {
fprintf(stderr, "ERROR: kis_simple_ringbuf_t not in a commit when commit called\n");
return 0;
}
size_t copy_start;
copy_start =
(ringbuf->start_pos + ringbuf->length) % ringbuf->buffer_sz;
if (!ringbuf->free_commit) {
ringbuf->mid_commit = 0;
ringbuf->length += size;
return size;
} else {
/* Does the write op fit w/out looping? */
if (copy_start + size < ringbuf->buffer_sz) {
memcpy(ringbuf->buffer + copy_start, data, size);
ringbuf->length += size;
return size;
} else {
/* We have to split up, figure out the length of the two chunks */
size_t chunk_a = ringbuf->buffer_sz - copy_start;
size_t chunk_b = size - chunk_a;
memcpy(ringbuf->buffer + ringbuf->start_pos + ringbuf->length, data, chunk_a);
memcpy(ringbuf->buffer, (uint8_t *) data + chunk_a, chunk_b);
/* Increase the length of the buffer */
ringbuf->length += size;
return size;
}
}
return 0;
}
/* Free a previously reserved chunk without committing it.
*/
void kis_simple_ringbuf_reserve_free(kis_simple_ringbuf_t *ringbuf, void *data) {
if (!ringbuf->mid_commit) {
fprintf(stderr, "ERROR: kis_simple_ringbuf_t not in a commit when commit_reserve_free called\n");
}
if (ringbuf->free_commit)
free(data);
ringbuf->mid_commit = 0;
}
/* Copies data into provided buffer. Advances ringbuf, clearing consumed data.
*
* If requested amount is not available, reads amount available and returns.
*
* Returns amount copied
*/
size_t kis_simple_ringbuf_read(kis_simple_ringbuf_t *ringbuf, void *ptr,
size_t size) {
/* Start with how much we have available - no matter what was
* requested, we can't read more than this */
size_t opsize = kis_simple_ringbuf_used(ringbuf);
if (opsize == 0)
return 0;
/* Only read the amount we requested, if more is available */
if (opsize > size)
opsize = size;
/* Simple contiguous read */
if (ringbuf->start_pos + opsize < ringbuf->buffer_sz) {
if (ptr != NULL)
memcpy(ptr, ringbuf->buffer + ringbuf->start_pos, opsize);
ringbuf->start_pos += opsize;
ringbuf->length -= opsize;
return opsize;
} else {
/* First chunk, start to end of buffer */
size_t chunk_a = ringbuf->buffer_sz - ringbuf->start_pos;
/* Second chunk, 0 to remaining data */
size_t chunk_b = opsize - chunk_a;
if (ptr != NULL) {
memcpy(ptr, ringbuf->buffer + ringbuf->start_pos, chunk_a);
memcpy((uint8_t *) ptr + chunk_a, ringbuf->buffer, chunk_b);
}
/* Fastforward around the ring to where we finished reading */
ringbuf->start_pos = chunk_b;
ringbuf->length -= opsize;
return opsize;
}
return 0;
}
/* Peeks at data by copying into provided buffer. Does NOT advance ringbuf
* or consume data.
*
* If requested amount of data is not available, peeks amount available and
* returns;
*
* Returns amount copied
*/
size_t kis_simple_ringbuf_peek(kis_simple_ringbuf_t *ringbuf, void *ptr,
size_t size) {
/* Start with how much we have available - no matter what was
* requested, we can't read more than this */
size_t opsize = kis_simple_ringbuf_used(ringbuf);
if (opsize == 0)
return 0;
/* Only read the amount we requested, if more is available */
if (opsize > size)
opsize = size;
/* Simple contiguous read */
if (ringbuf->start_pos + opsize < ringbuf->buffer_sz) {
memcpy(ptr, ringbuf->buffer + ringbuf->start_pos, opsize);
return opsize;
} else {
/* First chunk, start to end of buffer */
size_t chunk_a = ringbuf->buffer_sz - ringbuf->start_pos;
/* Second chunk, 0 to remaining data */
size_t chunk_b = opsize - chunk_a;
memcpy(ptr, ringbuf->buffer + ringbuf->start_pos, chunk_a);
memcpy((uint8_t *) ptr + chunk_a, ringbuf->buffer, chunk_b);
return opsize;
}
return 0;
}
size_t kis_simple_ringbuf_peek_zc(kis_simple_ringbuf_t *ringbuf, void **ptr, size_t size) {
/* Start with how much we have available - no matter what was
* requested, we can't read more than this */
size_t opsize = kis_simple_ringbuf_used(ringbuf);
if (ringbuf->mid_peek) {
fprintf(stderr, "ERROR: simple_ringbuf_peek_zc mid-peek already\n");
return 0;
}
if (opsize == 0)
return 0;
/* Only read the amount we requested, if more is available */
if (opsize > size)
opsize = size;
/* Simple contiguous read */
if (ringbuf->start_pos + opsize < ringbuf->buffer_sz) {
ringbuf->mid_peek = 1;
ringbuf->free_peek = 0;
*ptr = ringbuf->buffer + ringbuf->start_pos;
return opsize;
} else {
/* First chunk, start to end of buffer */
size_t chunk_a = ringbuf->buffer_sz - ringbuf->start_pos;
/* Second chunk, 0 to remaining data */
size_t chunk_b = opsize - chunk_a;
*ptr = malloc(opsize);
if (*ptr == NULL) {
fprintf(stderr, "ERROR: simple_ringbuf_peek_zc could not allocate buffer for split peek\n");
return 0;
}
ringbuf->mid_peek = 1;
ringbuf->free_peek = 1;
memcpy(*ptr, ringbuf->buffer + ringbuf->start_pos, chunk_a);
memcpy((uint8_t *) *ptr + chunk_a, ringbuf->buffer, chunk_b);
return opsize;
}
return 0;
}
void kis_simple_ringbuf_peek_free(kis_simple_ringbuf_t *ringbuf, void *ptr) {
if (!ringbuf->mid_peek) {
fprintf(stderr, "ERROR: kis_simple_ringbuf_peek_free called with no peeked data\n");
return;
}
if (ringbuf->free_peek)
free(ptr);
ringbuf->mid_peek = 0;
}

View File

@ -0,0 +1,129 @@
/*
This file is part of Kismet
Kismet 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.
Kismet is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Kismet; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/* An extremely basic ring buffer implemented in pure C; for use with datasource
* implementations in C */
#ifndef __RINGBUF_C_H__
#define __RINGBUF_C_H__
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#ifndef _WIN32
#include <unistd.h>
#endif
struct kis_simple_ringbuf {
uint8_t *buffer;
size_t buffer_sz;
size_t start_pos; /* Where reading starts from */
size_t length; /* Amount of data in the buffer */
int mid_peek, mid_commit; /* Are we in a peek or reserve? */
int free_peek, free_commit; /* Do we need to free the peek or reserved buffers */
};
typedef struct kis_simple_ringbuf kis_simple_ringbuf_t;
/* Allocate a ring buffer
*
* Returns NULL if allocation failed
*/
kis_simple_ringbuf_t *kis_simple_ringbuf_create(size_t size);
/* Destroy a ring buffer
*/
void kis_simple_ringbuf_free(kis_simple_ringbuf_t *ringbuf);
/* Clear ring buffer
*/
void kis_simple_ringbuf_clear(kis_simple_ringbuf_t *ringbuf);
/* Get available space
*/
size_t kis_simple_ringbuf_available(kis_simple_ringbuf_t *ringbuf);
/* Get used space
*/
size_t kis_simple_ringbuf_used(kis_simple_ringbuf_t *ringbuf);
/* Get total size
*/
size_t kis_simple_ringbuf_size(kis_simple_ringbuf_t *ringbuf);
/* Append data
*
* Returns amount written
*/
size_t kis_simple_ringbuf_write(kis_simple_ringbuf_t *ringbuf,
void *data, size_t length);
/* Reserve a writeable chunk, striving to make it a zero-copy operation. Only
* one chunk may be reserved at a time. A reserved chunk must be written
* with kis_simple_ringbuf_commit or discard with kis_simple_ringbuf_reserve_free
*
* Returns amount available. Returns 0 if that amount cannot be reserved because
* the buffer is full.
*/
size_t kis_simple_ringbuf_reserve(kis_simple_ringbuf_t *ringbuf, void **data, size_t size);
/* Commit a previously reserved chunk. Commits the specified number of bytes.
*
* Returns the amount committed.
*/
size_t kis_simple_ringbuf_commit(kis_simple_ringbuf_t *ringbuf, void *data, size_t size);
/* Free a previously reserved chunk without committing it.
*/
void kis_simple_ringbuf_reserve_free(kis_simple_ringbuf_t *ringbuf, void *data);
/* Copies data into provided buffer. Advances ringbuf, clearing consumed data.
*
* If requested amount is not available, reads amount available and returns.
*
* Returns amount copied
*/
size_t kis_simple_ringbuf_read(kis_simple_ringbuf_t *ringbuf, void *ptr, size_t size);
/* Peeks at data by copying into provided buffer. Does NOT advance ringbuf
* or consume data.
*
* If requested amount of data is not available, peeks amount available and
* returns;
*
* Returns amount copied
*/
size_t kis_simple_ringbuf_peek(kis_simple_ringbuf_t *ringbuf, void *ptr, size_t size);
/* Peeks at data, using a zero-copy method if possible. Does NOT advance ringbuf
* or consume data.
*
* Peeked data MUST BE 'returned' via kis_simple_ringbuf_peek_free.
*
* Returns amount peeked.
*/
size_t kis_simple_ringbuf_peek_zc(kis_simple_ringbuf_t *ringbuf, void **ptr, size_t size);
/* Frees peeked zc data. Must be called after peeking.
*
*/
void kis_simple_ringbuf_peek_free(kis_simple_ringbuf_t *ringbuf, void *ptr);
#endif

500
wifi_capture.c Normal file
View File

@ -0,0 +1,500 @@
/*
* GPL-2.0-or-later
*
* Userspace port (C) 2019 Hak5 LLC
*
*/
#include <errno.h>
#include <getopt.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#ifndef _WIN32
#include <sys/time.h>
#include <unistd.h>
#else
#include <Windows.h>
#define sleep(x) Sleep(x*1000)
#define usleep(x) Sleep((x) < 1000 ? 1 : (x) / 1000)
#endif
#include "kernel/cfg80211.h"
#include "kernel/endian.h"
#include "kernel/ieee80211.h"
#include "kernel/ieee80211_radiotap.h"
#include <libusb.h>
#include "userspace/userspace.h"
struct wifi_test_context {
/*
* USB context
*/
struct userspace_wifi_context *context;
/*
* Device we plan to open
*/
struct userspace_wifi_probe_dev* probedev;
/*
* The device we're operating on
*/
struct userspace_wifi_dev *dev;
/*
* Runtime options
*/
bool disable_leds;
bool disable_blink;
bool invert_leds;
bool no_radiotap;
bool quiet;
bool diagnostics_mode;
bool diagnostics_only;
int device_number;
int channel;
/*
* pcap logging
*/
bool enable_pcap_log;
FILE *dump_filep;
int num_packets;
pthread_mutex_t pcap_mutex;
};
int open_wifi_device(struct wifi_test_context *test_context) {
int r;
r = userspace_wifi_device_open(test_context->context, test_context->probedev, &test_context->dev);
if (r != 0) {
printf("Failed to open device: %d %s\n", r, strerror(r));
return -1;
}
userspace_wifi_device_set_channel(test_context->context,
test_context->dev,
test_context->channel,
NL80211_CHAN_WIDTH_20_NOHT);
if (test_context->disable_leds)
userspace_wifi_device_set_led(test_context->context, test_context->dev, false);
else
userspace_wifi_device_set_led(test_context->context, test_context->dev, true);
if (!test_context->disable_blink)
userspace_wifi_device_enable_led_control(test_context->context, test_context->dev);
return 0;
}
int start_wifi_capture(struct wifi_test_context* test_context) {
/*
* If LEDs are inverted, turn off LEDs once we've enumerated all the radios.
*/
if (test_context->invert_leds)
userspace_wifi_device_set_led(test_context->context, test_context->dev, false);
userspace_wifi_device_start_capture(test_context->context, test_context->dev);
return 0;
}
#define DLT_IEEE802_11 105 /* IEEE 802.11 wireless */
#define DLT_IEEE802_11_RADIO 127 /* 802.11 plus radiotap radio header */
int open_pcap(const char *file, struct wifi_test_context *test_context) {
struct {
uint32_t magic_number; /* magic number */
uint16_t version_major; /* major version number */
uint16_t version_minor; /* minor version number */
int32_t thiszone; /* GMT to local correction */
uint32_t sigfigs; /* accuracy of timestamps */
uint32_t snaplen; /* max length of captured packets, in octets */
uint32_t network; /* data link type */
} pcap_hdr_t;
pcap_hdr_t.magic_number = 0xa1b2c3d4;
pcap_hdr_t.version_major = 2;
pcap_hdr_t.version_minor = 4;
pcap_hdr_t.thiszone = 0;
pcap_hdr_t.sigfigs = 0;
pcap_hdr_t.snaplen = 8192;
test_context->enable_pcap_log = true;
pthread_mutex_init(&test_context->pcap_mutex, NULL);
if (test_context->no_radiotap)
pcap_hdr_t.network = DLT_IEEE802_11;
else
pcap_hdr_t.network = DLT_IEEE802_11_RADIO;
if (strcmp(file, "-") == 0)
test_context->dump_filep = stdout;
else
test_context->dump_filep = fopen(file, "wb");
if (test_context->dump_filep == NULL) {
fprintf(stderr, "ERROR: Could not open dump: %d %s\n", errno, strerror(errno));
return -1;
}
fwrite(&pcap_hdr_t, sizeof(pcap_hdr_t), 1, test_context->dump_filep);
return 1;
}
int pcap_rx_packet(struct userspace_wifi_context *context,
struct userspace_wifi_dev *dev,
struct userspace_wifi_rx_signal *signal,
unsigned char *data, unsigned int len) {
struct wifi_test_context *test_context = (struct wifi_test_context *) context->local_data;
typedef struct {
uint32_t ts_sec; /* timestamp seconds */
uint32_t ts_usec; /* timestamp microseconds */
uint32_t incl_len; /* number of octets of packet saved in file */
uint32_t orig_len; /* actual length of packet */
} pcaprec_hdr_t;
pcaprec_hdr_t pcap_hdr;
struct timeval tv;
typedef struct {
uint16_t version;
uint16_t length;
uint32_t bitmap;
uint8_t flags;
uint8_t pad0;
uint16_t channel_freq;
uint16_t channel_flags;
uint8_t antsignal;
} _rtap_hdr;
_rtap_hdr rtap_hdr = {
.version = 0,
.length = htole16(sizeof(_rtap_hdr)),
.bitmap = htole32((1 << IEEE80211_RADIOTAP_FLAGS) |
(1 << IEEE80211_RADIOTAP_CHANNEL) |
(1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL)),
.flags = 0,
.channel_freq = htole16(ieee80211_channel_to_frequency(signal->channel, signal->band)),
.channel_flags = 0,
.antsignal = (u8) signal->signal,
};
if (!signal->crc_valid)
rtap_hdr.flags |= IEEE80211_RADIOTAP_F_BADFCS;
if (signal->short_gi)
rtap_hdr.flags |= IEEE80211_RADIOTAP_F_SHORTGI;
if (signal->band == NL80211_BAND_2GHZ)
rtap_hdr.channel_flags |= IEEE80211_CHAN_2GHZ;
else if (signal->band == NL80211_BAND_5GHZ)
rtap_hdr.channel_flags |= IEEE80211_CHAN_5GHZ;
/*
* Only blink if we're told to blink.
* Default LED state is "not inverted" (so on).
* If we're inverted, we let the timer override, so active LEDs stay
* ON longer as the timer gets extended; this looks better.
*/
if (!test_context->disable_blink)
userspace_wifi_device_blink_led(context, dev, 100000, !test_context->invert_leds, test_context->invert_leds);
if (test_context->diagnostics_mode) {
fprintf(stderr, "PACKET %u %u %d %02x %02x %02x %02x %02x %02x ...\n",
len, signal->channel, signal->signal, data[0], data[1], data[2], data[3], data[4], data[5]);
}
if (!test_context->enable_pcap_log)
return 1;
gettimeofday(&tv, NULL);
pcap_hdr.ts_sec = tv.tv_sec;
pcap_hdr.ts_usec = tv.tv_usec;
pthread_mutex_lock(&test_context->pcap_mutex);
if (test_context->no_radiotap) {
pcap_hdr.incl_len = pcap_hdr.orig_len = len;
fwrite(&pcap_hdr, sizeof(pcaprec_hdr_t), 1, test_context->dump_filep);
fwrite(data, len, 1, test_context->dump_filep);
} else {
pcap_hdr.incl_len = pcap_hdr.orig_len = sizeof(_rtap_hdr) + len;
fwrite(&pcap_hdr, sizeof(pcaprec_hdr_t), 1, test_context->dump_filep);
fwrite(&rtap_hdr, sizeof(_rtap_hdr), 1, test_context->dump_filep);
fwrite(data, len, 1, test_context->dump_filep);
}
test_context->num_packets++;
if (!test_context->quiet && test_context->num_packets % 100 == 0)
fprintf(stderr, "Got %d packets\n", test_context->num_packets);
pthread_mutex_unlock(&test_context->pcap_mutex);
return 1;
}
void print_device_list(struct userspace_wifi_probe_dev* devs) {
int dev_num = 0;
int i;
while (devs != NULL) {
fprintf(stderr, "DEVICE %d: Driver %s USB ID %x %x ",
dev_num, devs->driver_name, devs->device_id_match->idVendor, devs->device_id_match->idProduct);
for (i = 0; i < devs->usb_bus_path_len; i++) {
fprintf(stderr, "/%u", devs->usb_bus_path[i]);
}
fprintf(stderr, "\n");
dev_num++;
devs = devs->next;
}
}
struct userspace_wifi_probe_dev* find_device_by_number(int device_number, struct userspace_wifi_probe_dev* devs) {
int dev_num = 0;
if (devs == NULL)
return NULL;
if (device_number < 0)
return devs;
while (devs != NULL) {
if (dev_num == device_number)
return devs;
dev_num++;
devs = devs->next;
}
return NULL;
}
void print_usage(char *argv) {
printf("Userspace Wifi Test\n");
printf("Usage: %s [options] [output file]\n", argv);
printf("Options:\n");
printf(" --list List devices and exit\n"
" --device=X If you have multiple supported Wi-Fi devices, specify\n"
" which one to use\n"
" --channel=X Set Wi-Fi Channel (1-14)\n"
" --plain-dot11 Log plain 802.11 packets instead of radiotap\n"
" formatted packets with signal and channel\n"
" --disable-leds Go fully dark; don't enable any LEDs\n"
" --invert-leds Normally we enable all the LEDs\n"
" and blink during traffic; Invert only lights\n"
" when there is traffic.\n"
" --disable-blinking Disable blinking the LEDs on traffic\n"
" --quiet Disable most output\n"
" --diagnostics Diagnostic statistics mode\n"
" --diagnostics-only Enable diagnostics-only mode, disable pcap\n");
}
int main(int argc, char *argv[]) {
#define OPT_HELP 'h'
#define OPT_LIST 2
#define OPT_DEVNO 3
#define OPT_PLAINDOT11 5
#define OPT_DISABLELED 6
#define OPT_INVERTLED 7
#define OPT_DISABLEBLNK 8
#define OPT_QUIET 9
#define OPT_DIAG 10
#define OPT_DIAGONLY 11
#define OPT_CHANNEL 12
static struct option longopt[] = {
{ "help", no_argument, 0, OPT_HELP },
{ "list", no_argument, 0, OPT_LIST },
{ "device", required_argument, 0, OPT_DEVNO },
{ "plain-dot11", no_argument, 0, OPT_PLAINDOT11 },
{ "disable-leds", no_argument, 0, OPT_DISABLELED },
{ "invert-leds", no_argument, 0, OPT_INVERTLED },
{ "disable-blinking", no_argument, 0, OPT_DISABLEBLNK },
{ "quiet", no_argument, 0, OPT_QUIET },
{ "diagnostics", no_argument, 0, OPT_DIAG },
{ "diagnostics-only", no_argument, 0, OPT_DIAGONLY },
{ "channel", required_argument, 0, OPT_CHANNEL },
{ 0, 0, 0, 0 }
};
int option_idx = 0;
optind = 0;
opterr = 0;
int r;
bool list_only = false;
char *pcap_fname = NULL;
struct userspace_wifi_context *context;
struct userspace_wifi_probe_dev *probed;
int probed_count;
struct wifi_test_context test_context;
memset(&test_context, 0, sizeof(struct wifi_test_context));
test_context.device_number = -1;
test_context.channel = 1;
while ((r = getopt_long(argc, argv, "h", longopt, &option_idx)) != -1) {
switch (r) {
case OPT_HELP:
/* help */
print_usage(argv[0]);
exit(0);
break;
case OPT_LIST:
list_only = true;
break;
case OPT_DISABLELED:
test_context.disable_leds = true;
break;
case OPT_INVERTLED:
test_context.invert_leds = true;
break;
case OPT_DISABLEBLNK:
test_context.disable_blink = true;
break;
case OPT_QUIET:
test_context.quiet = true;
break;
case OPT_DEVNO:
if (sscanf(optarg, "%u", &test_context.device_number) != 1) {
print_usage(argv[0]);
fprintf(stderr, "\n");
fprintf(stderr, "Expected a number for --device, such as --device=5\n");
exit(1);
}
break;
case OPT_PLAINDOT11:
test_context.no_radiotap = true;
break;
case OPT_DIAG:
test_context.diagnostics_mode = true;
break;
case OPT_DIAGONLY:
test_context.diagnostics_only = true;
test_context.diagnostics_mode = true;
break;
case OPT_CHANNEL:
if (sscanf(optarg, "%u", &test_context.channel) != 1) {
print_usage(argv[0]);
fprintf(stderr, "\nExpected a number for --channel, such as --channel=6\n");
exit(1);
}
if (test_context.channel < 1 || test_context.channel > 14) {
print_usage(argv[0]);
fprintf(stderr, "\nExpected a channel between 1 and 14\n");
exit(1);
}
break;
}
}
if (!list_only && !test_context.diagnostics_only && optind >= argc) {
print_usage(argv[0]);
fprintf(stderr, "\n");
fprintf(stderr, "FATAL: Expected pcap file name\n");
exit(1);
} else if (!test_context.diagnostics_only && !list_only) {
pcap_fname = strdup(argv[optind]);
}
/*
* If LEDs are disabled, blinking is disabled
*/
if (test_context.disable_leds)
test_context.disable_blink = true;
r = userspace_wifi_init(&context);
if (r != 0) {
fprintf(stderr, "FATAL: Failed to initialize USB subsystem, %d\n", r);
exit(1);
}
context->local_data = &test_context;
test_context.context = context;
probed_count = userspace_wifi_probe(context, &probed);
if (probed_count == 0) {
#ifdef _WIN32
fprintf(stderr, "ERROR: No compatible USB Wi-Fi cards found. Make sure you have a supported Wi-Fi device "
"and that you have installed the required drivers via Zadig!\n");
#elif defined(__APPLE__)
/*
* Whine about root
*/
if (getuid() != 0) {
fprintf(stderr, "ERROR: No compatible USB Wi-Fi devices found. Not running as root. Root is often required for "
"raw USB access if you are not the primary user.\n");
} else {
fprintf(stderr, "ERROR: No compatible USB Wi-Fi devices found.\n");
}
#else
if (getuid() != 0) {
fprintf(stderr, "ERROR: No compatible USB Wi-Fi devices found. Not running as root. Root is typically required for "
"raw USB access; if you see no USB devices, try running as root\n");
} else {
fprintf(stderr, "ERROR No compatible USB Wi-Fi devices found.\n");
}
#endif
exit(1);
}
if (!test_context.quiet)
print_device_list(probed);
if (list_only)
goto end;
/* Look for the device we were asked for */
test_context.probedev = find_device_by_number(test_context.device_number, probed);
userspace_wifi_set_packet_cb(context, &pcap_rx_packet);
if (!test_context.diagnostics_only && !list_only) {
r = open_pcap(pcap_fname, &test_context);
if (r < 0) {
fprintf(stderr, "FATAL: Could not open pcap\n");
exit(1);
}
}
open_wifi_device(&test_context);
/*
* Activate capture
*/
if (!test_context.quiet)
fprintf(stderr, "Activating capture...\n");
start_wifi_capture(&test_context);
while (1) {
sleep(1);
}
end:
/* This makes win32 sad right now; not sure why
userspace_wifi_free_probe(probed);
userspace_wifi_free(context);
*/
return 0;
}

1023
wifi_coconut.c Normal file

File diff suppressed because it is too large Load Diff

654
wifi_coconut/wifi_coconut.c Normal file
View File

@ -0,0 +1,654 @@
/*
* GPL-2.0-or-later
*
* Userspace port (C) 2019 Hak5 LLC
*
*/
#include "wifi_coconut/wifi_coconut.h"
#include "userspace/userspace.h"
struct wifi_coconut_context *init_coconut_context() {
struct wifi_coconut_context *ctx =
(struct wifi_coconut_context *) malloc(sizeof(struct wifi_coconut_context));
if (ctx == NULL)
return NULL;
memset(ctx, 0, sizeof(struct wifi_coconut_context));
pthread_mutex_init(&ctx->diagnostics.mutex, NULL);
return ctx;
}
/*
* Map the bus positions to device numbers so we can open
* them in order.
*/
const int device_number_map[7][4] = {
{ 0, 1, 2, 3 },
{ 4, 5, 6, 7 },
{ 8, 9, 0, 0 },
{ 10, 0, 0, 0 },
{ 13, 0, 0, 0 },
{ 12, 0, 0, 0 },
{ 11, 0, 0, 0 },
};
int find_coconuts_cluster(struct wifi_coconut_context *coconut_context,
struct userspace_wifi_probe_dev *devicelist,
struct wifi_coconut **coconut) {
/*
* Potential coconuts we've found so far
*/
struct wifi_coconut *potential_coconuts = NULL;
struct wifi_coconut *coconut_iter = NULL;
struct wifi_coconut *matched_coconuts = NULL;
int root_number = 0;
int index_offt = 0;
struct userspace_wifi_probe_dev *device;
bool continue_descent = true;
int device_pos_num;
bool found_partial = false;
/*
* Fallback enumeration of just 14 rt2800 radios without looking at the bus path
*/
int num_raw_devices = 0;
struct userspace_wifi_probe_dev *raw_devices[14];
int i;
for (num_raw_devices = 0; num_raw_devices < 14; num_raw_devices++)
raw_devices[num_raw_devices] = NULL;
num_raw_devices = 0;
while (continue_descent) {
device = devicelist;
continue_descent = false;
while (device) {
device_pos_num = -1;
#ifdef FIND_DEBUG
printf("device %x %x bus len %d ", device->device_id_match->idVendor, device->device_id_match->idProduct, device->usb_bus_path_len);
for (int x = 0; x < device->usb_bus_path_len; x++)
printf("/%d", device->usb_bus_path[x]);
printf("\n");
#endif
/*
* Immediately exclude anything that isn't homed on a nested hub
* or doesn't have the right pid/vid; We don't need to check the
* driver string because of the vid/pid matching.
*/
if (device->usb_bus_path_len + index_offt < 2 ||
device->device_id_match->idVendor != 0x148f ||
device->device_id_match->idProduct != 0x5370) {
#ifdef FIND_DEBUG
printf("invalid device, bus len too short %d offt %d\n", device->usb_bus_path_len, index_offt);
#endif
device = device->next;
continue;
}
/*
* If we have any device which has enough of a path to continue
* past this cycle, flag to keep going when we're done.
*/
if (device->usb_bus_path_len - index_offt > 3) {
continue_descent = true;
device = device->next;
continue;
}
root_number = device->usb_bus_path[index_offt];
/* Look for a potential coconut that already matches root */
coconut_iter = potential_coconuts;
while (coconut_iter != NULL) {
if (coconut_iter->coconut_number == root_number)
break;
coconut_iter = coconut_iter->next;
}
/* Make a new potential record to populate if this is the first
* device of this root tree
*/
if (coconut_iter == NULL) {
/* Allocate a coconut if it doesn't exist */
coconut_iter = (struct wifi_coconut *) malloc(sizeof(*coconut_iter));
if (coconut_iter == NULL) {
goto failure;
}
memset(coconut_iter, 0, sizeof(*coconut_iter));
#ifdef FIND_DEBUG
printf("setting up coconut %d\n", root_number);
#endif
/*
* Set up the coconut
*/
coconut_iter->coconut_context = coconut_context;
coconut_iter->coconut_number = root_number;
coconut_iter->valid = true;
coconut_iter->bus_count[0] = 4;
coconut_iter->bus_count[1] = 4;
coconut_iter->bus_count[2] = 4;
coconut_iter->bus_count[3] = 2;
coconut_iter->next = potential_coconuts;
potential_coconuts = coconut_iter;
found_partial = true;
}
/* Is the coconut already in error? */
if (!coconut_iter->valid) {
device = device->next;
continue;
}
/* Is there room in this coconut? */
if (coconut_iter->device_num >= 14) {
coconut_iter->valid = false;
device = device->next;
continue;
}
/* Validate bus layout */
if (device->usb_bus_path_len - index_offt == 3) {
if (device->usb_bus_path[index_offt + 1] < 1 ||
device->usb_bus_path[index_offt + 1] > 3 ||
device->usb_bus_path[index_offt + 2] < 1 ||
device->usb_bus_path[index_offt + 2] > 4) {
device = device->next;
continue;
}
if (--coconut_iter->bus_count[device->usb_bus_path[index_offt + 1]] < 0) {
#ifdef FIND_DEBUG
printf("coconut no longer valid bus count [%d] negative\n", index_offt + 1);
#endif
coconut_iter->valid = false;
device = device->next;
continue;
}
device_pos_num = device_number_map[device->usb_bus_path[index_offt + 1] - 1][device->usb_bus_path[index_offt + 2] - 1];
} else if (device->usb_bus_path_len - index_offt == 2) {
if (device->usb_bus_path[index_offt + 1] < 4 ||
device->usb_bus_path[index_offt + 1] > 7) {
#ifdef FIND_DEBUG
printf("coconut no longer valid, path 2/4-7 violated\n");
#endif
coconut_iter->valid = false;
device = device->next;
continue;
}
if (--coconut_iter->bus_count[0] < 0) {
#ifdef FIND_DEBUG
printf("coconut no longer valid, bus count [0] negative\n");
#endif
coconut_iter->valid = false;
device = device->next;
continue;
}
device_pos_num = device_number_map[device->usb_bus_path[index_offt + 1] - 1][0];
}
if (device_pos_num < 0 || device_pos_num >= 14) {
#ifdef FIND_DEBUG
printf("Got invalid number %d\n", device_pos_num);
#endif
} else {
coconut_iter->probed_devices[device_pos_num] = device;
coconut_iter->device_num++;
}
device = device->next;
}
/* Merge any coconuts that were valid */
coconut_iter = potential_coconuts;
while (coconut_iter != NULL) {
struct wifi_coconut *tmp;
tmp = coconut_iter->next;
if (coconut_iter->valid && coconut_iter->device_num == 14) {
coconut_iter->next = matched_coconuts;
matched_coconuts = coconut_iter;
for (i = 0; i < 14; i++) {
if (coconut_iter->probed_devices[i] != NULL) {
memcpy(coconut_iter->first_usb_serial, coconut_iter->probed_devices[i]->usb_serial, 64);
break;
}
}
} else {
#ifdef FIND_DEBUG
printf("Invalid coconut, valid %u device num %u\n", coconut_iter->valid, coconut_iter->device_num);
#endif
free(coconut_iter);
}
coconut_iter = tmp;
}
/* Reset the potential list and increment down the path */
potential_coconuts = NULL;
index_offt++;
}
*coconut = matched_coconuts;
/* If we didn't find any coconuts on a nested bus, look for just 14 radios. some platforms
* like catalina are having real trouble exposing the bus tree through libusb right now.
*/
if (*coconut == NULL) {
device = devicelist;
while (device && num_raw_devices < 14) {
if (device->device_id_match->idVendor != 0x148f ||
device->device_id_match->idProduct != 0x5370) {
device = device->next;
continue;
}
raw_devices[num_raw_devices] = device;
num_raw_devices++;
device = device->next;
}
/* If we found at least 14 raw compatible devices, just make a coconut out of them
* and call it good enough */
if (num_raw_devices == 14) {
coconut_iter = (struct wifi_coconut *) malloc(sizeof(*coconut_iter));
if (coconut_iter == NULL) {
goto failure;
}
#ifdef FIND_DEBUG
printf("Creating catch-all coconut-0 for 14 devices not in the right order\n");
#endif
memset(coconut_iter, 0, sizeof(*coconut_iter));
/*
* Set up the coconut
*/
coconut_iter->coconut_context = coconut_context;
coconut_iter->coconut_number = 0;
coconut_iter->valid = true;
/*
* Copy the raw list of devices
*/
coconut_iter->device_num = 0;
for (coconut_iter->device_num = 0; coconut_iter->device_num < 14; coconut_iter->device_num++)
coconut_iter->probed_devices[coconut_iter->device_num] = raw_devices[coconut_iter->device_num];
coconut_iter->next = NULL;
*coconut = coconut_iter;
for (i = 0; i < 14; i++) {
if (coconut_iter->probed_devices[i] != NULL) {
memcpy(coconut_iter->first_usb_serial, coconut_iter->probed_devices[i]->usb_serial, 64);
break;
}
}
}
}
if (*coconut == NULL) {
if (found_partial)
return WIFI_COCONUT_FIND_CLUSTER_PARTIAL;
return WIFI_COCONUT_FIND_CLUSTER_NONE;
}
return WIFI_COCONUT_FIND_CLUSTER_OK;
failure:
#ifdef FIND_DEBUG
printf("coconut find fell into failure\n");
#endif
coconut_iter = potential_coconuts;
while (coconut_iter != NULL) {
struct wifi_coconut *tmp;
tmp = coconut_iter;
coconut_iter = coconut_iter->next;
free(tmp);
}
coconut_iter = matched_coconuts;
while (coconut_iter != NULL) {
struct wifi_coconut *tmp;
tmp = coconut_iter;
coconut_iter = coconut_iter->next;
free(tmp);
}
return -ENOMEM;
}
void free_coconuts(struct wifi_coconut *coconuts) {
struct wifi_coconut *next;
while (coconuts) {
next = coconuts->next;
free(coconuts);
coconuts = next;
}
}
void print_wifi_coconuts(struct wifi_coconut *coconuts) {
struct wifi_coconut *iter = coconuts;
while (iter != NULL) {
fprintf(stderr, "I've got a lovely bunch of coconuts! coconut-%d\n", iter->coconut_number);
iter = iter->next;
}
}
int coconut_search_and_open(struct wifi_coconut_context *coconut_context,
bool wait_for_coconut, int coconut_number,
int (*status_callback)(struct wifi_coconut_context *, void *, int, int, struct wifi_coconut *),
void *cb_aux) {
struct userspace_wifi_probe_dev *probed;
int probed_count;
struct wifi_coconut *coconuts = NULL, *ci = NULL;
int r, d, htch;
while (1) {
probed_count = userspace_wifi_probe(coconut_context->context, &probed);
if (probed_count == 0) {
if (status_callback != NULL) {
r = (*status_callback)(coconut_context, cb_aux, WIFI_COCONUT_SEARCH_STATE_NO_RADIOS, -1, NULL);
/* Override waiting for a coconut if the callback returns a 'do not
* continue'; such as running as non-root */
if (r < 0)
return WIFI_COCONUT_SEARCH_STATE_NO_RADIOS;
}
if (!wait_for_coconut)
return WIFI_COCONUT_SEARCH_STATE_NO_RADIOS;
sleep(1);
continue;
}
r = find_coconuts_cluster(coconut_context, probed, &coconuts);
if (coconuts == NULL) {
userspace_wifi_free_probe(probed);
probed = NULL;
/*
* We actually ignore the cluster return value here; we'd only
* have gotten this far if we found SOME usb radios, just not what
* we need.
*/
if (status_callback != NULL) {
r = (*status_callback)(coconut_context, cb_aux, WIFI_COCONUT_SEARCH_STATE_NO_COCONUT, -1, NULL);
/* Allow the callback to reject a continued wait */
if (r < 0)
return WIFI_COCONUT_SEARCH_STATE_NO_COCONUT;
}
if (!wait_for_coconut)
return WIFI_COCONUT_SEARCH_STATE_NO_COCONUT;
sleep(1);
continue;
}
if (status_callback != NULL) {
r = (*status_callback)(coconut_context, cb_aux, WIFI_COCONUT_SEARCH_STATE_LIST, -1, coconuts);
if (r < 0)
return WIFI_COCONUT_SEARCH_STATE_ERROR;
}
if (coconut_number >= 0) {
ci = coconuts;
while (ci != NULL) {
if (ci->coconut_number == coconut_number) {
coconut_context->coconut = ci;
coconut_context->coconut_number = coconut_number;
coconut_context->coconuts = coconuts;
break;
}
ci = ci->next;
}
} else {
coconut_context->coconut = coconuts;
coconut_context->coconuts = coconuts;
coconut_context->coconut_number = coconuts->coconut_number;
}
if (coconut_context->coconut == NULL) {
free_coconuts(coconuts);
userspace_wifi_free_probe(probed);
if (status_callback != NULL) {
r = (*status_callback)(coconut_context, cb_aux, WIFI_COCONUT_SEARCH_STATE_MISMATCH, -1, NULL);
if (r < 0)
return WIFI_COCONUT_SEARCH_STATE_MISMATCH;
}
if (!wait_for_coconut)
return WIFI_COCONUT_SEARCH_STATE_MISMATCH;
sleep(1);
continue;
}
/* Otherwise we've got a coconut assigned, drop out of the spinloop
* and move to opening */
break;
}
if (status_callback != NULL)
(*status_callback)(coconut_context, cb_aux, WIFI_COCONUT_SEARCH_STATE_FOUND, -1, NULL);
/* We might need to handle partial devices */
for (d = 0; d < 14; d++) {
if (coconut_context->coconut->probed_devices[d] == NULL) {
if (status_callback != NULL)
(*status_callback)(coconut_context, cb_aux, WIFI_COCONUT_SEARCH_STATE_NO_DEV, d, NULL);
continue;
}
/* TODO how do we handle channel mapping w partial devices? */
r = userspace_wifi_device_open(coconut_context->context,
coconut_context->coconut->probed_devices[d],
&coconut_context->coconut->active_devices[d]);
/*
* If we failed to open, and have a callback, call it and use that to
* decide if we abort opening entirely; otherwise, abort opening the
* rest of the coconut and fail out
*/
if (r < 0) {
if (status_callback != NULL) {
if ((*status_callback)(coconut_context, cb_aux, WIFI_COCONUT_SEARCH_STATE_DEV_ERROR, d, NULL) < 0) {
coconut_context->coconut = NULL;
free_coconuts(coconuts);
userspace_wifi_free_probe(probed);
return WIFI_COCONUT_SEARCH_STATE_ERROR;
}
continue;
} else {
coconut_context->coconut = NULL;
free_coconuts(coconuts);
userspace_wifi_free_probe(probed);
return WIFI_COCONUT_SEARCH_STATE_ERROR;
}
}
userspace_wifi_device_set_id(coconut_context->context,
coconut_context->coconut->active_devices[d], d);
if (!coconut_context->ht40 || d < 12) {
userspace_wifi_device_set_channel(coconut_context->context,
coconut_context->coconut->active_devices[d],
d + 1,
NL80211_CHAN_WIDTH_20);
} else {
if (d == 12)
htch = 1;
if (d == 13)
htch = 11;
userspace_wifi_device_set_channel(coconut_context->context,
coconut_context->coconut->active_devices[d],
htch,
NL80211_CHAN_WIDTH_40);
}
if (coconut_context->disable_leds)
userspace_wifi_device_set_led(coconut_context->context,
coconut_context->coconut->active_devices[d], false);
else
userspace_wifi_device_set_led(coconut_context->context,
coconut_context->coconut->active_devices[d], true);
if (!coconut_context->disable_blink)
userspace_wifi_device_enable_led_control(coconut_context->context,
coconut_context->coconut->active_devices[d]);
if (status_callback != NULL)
(*status_callback)(coconut_context, cb_aux, WIFI_COCONUT_SEARCH_STATE_DEV_OPENED, d, NULL);
}
if (status_callback != NULL)
(*status_callback)(coconut_context, cb_aux, WIFI_COCONUT_SEARCH_STATE_DONE, -1, NULL);
return WIFI_COCONUT_SEARCH_STATE_DONE;
}
/*
* Open all the devices in a wifi coconut, setting each one to a channel
*/
int open_wifi_coconut(struct wifi_coconut_context *coconut_context, struct wifi_coconut *coconut) {
int d;
int r;
int htch;
coconut_context->coconut = coconut;
if (!coconut_context->quiet)
printf("Opening coconut with %d devices\n", coconut->device_num);
for (d = 0; d < 14; d++) {
if (coconut_context->coconut->probed_devices[d] == NULL) {
if (!coconut_context->quiet)
printf("Device %d null!\n", d);
continue;
}
if (!coconut_context->quiet) {
if (!coconut_context->quiet) {
fprintf(stderr, "Opening Coconut-%d #%d... ", coconut->coconut_number, d + 1);
fflush(stderr);
}
}
r = userspace_wifi_device_open(coconut->coconut_context->context,
coconut->probed_devices[d], &coconut->active_devices[d]);
if (r != 0) {
if (!coconut_context->quiet)
printf("Failed to open device %d: %d %s\n", d, r, strerror(r));
return -1;
}
userspace_wifi_device_set_id(coconut->coconut_context->context,
coconut->active_devices[d], d);
if (!coconut_context->ht40 || d < 12) {
userspace_wifi_device_set_channel(coconut->coconut_context->context,
coconut->active_devices[d],
d + 1,
NL80211_CHAN_WIDTH_20);
} else {
if (d == 12)
htch = 1;
if (d == 13)
htch = 11;
userspace_wifi_device_set_channel(coconut->coconut_context->context,
coconut->active_devices[d],
htch,
NL80211_CHAN_WIDTH_40);
}
if (coconut_context->disable_leds)
userspace_wifi_device_set_led(coconut->coconut_context->context,
coconut->active_devices[d], false);
else
userspace_wifi_device_set_led(coconut->coconut_context->context,
coconut->active_devices[d], true);
if (!coconut_context->disable_blink)
userspace_wifi_device_enable_led_control(coconut->coconut_context->context,
coconut->active_devices[d]);
if (!coconut_context->quiet) {
fprintf(stderr, "OK!\n");
fflush(stderr);
}
}
return 0;
}
/*
* Activate all the devices in a wifi coconut
*/
int start_wifi_coconut_capture(struct wifi_coconut_context *coconut_context) {
int d;
for (d = 0; d < 14; d++) {
if (coconut_context->coconut->active_devices[d] == NULL) {
fprintf(stderr, "debug - missing active device %d\n", d);
continue;
}
/*
* If LEDs are inverted, turn off LEDs once we've enumerated all the radios.
*/
if (coconut_context->invert_leds)
userspace_wifi_device_set_led(coconut_context->context,
coconut_context->coconut->active_devices[d], false);
userspace_wifi_device_start_capture(coconut_context->context,
coconut_context->coconut->active_devices[d]);
}
return 0;
}

254
wifi_coconut/wifi_coconut.h Normal file
View File

@ -0,0 +1,254 @@
/*
* GPL-2.0-or-later
*
* Userspace port (C) 2019 Hak5 LLC
*
*/
#ifndef __WIFI_COCONUT_H__
#define __WIFI_COCONUT_H__
#include <errno.h>
#include <getopt.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#ifndef _WIN32
#include <sys/time.h>
#include <unistd.h>
#else
#include <Windows.h>
#define sleep(x) Sleep(x*1000)
#define usleep(x) Sleep((x) < 1000 ? 1 : (x) / 1000)
#endif
#include "kernel/cfg80211.h"
#include "kernel/endian.h"
#include "kernel/ieee80211.h"
#include "kernel/ieee80211_radiotap.h"
#include <libusb.h>
#include "userspace/userspace.h"
/*
* Diagnostics struct
*/
struct wifi_coconut_diagnostics {
pthread_mutex_t mutex;
unsigned int total_packets[14];
unsigned int total_data[14];
int total_min_signal[14];
int total_max_signal[14];
time_t last_sec;
int sec_packets[14];
int sec_data[14];
int sec_min_signal[14];
int sec_max_signal[14];
};
/*
* A wifi coconut always has 14 radios; each radio is configured for its
* own channel and the device reports packets as an aggregate
* A Wi-Fi Coconut device; can be a linked list or a single device
*/
struct wifi_coconut {
struct wifi_coconut *next;
struct wifi_coconut_context *coconut_context;
struct userspace_wifi_probe_dev *probed_devices[14];
struct userspace_wifi_dev *active_devices[14];
/*
* How many devices have we found / allocated, either during scan or in case we can't
* allocate all devices and decide to continue anyhow
*/
int device_num;
/* Per-bus counts */
int bus_count[4];
/*
* What number coconut is this (base hub id)
*/
int coconut_number;
/*
* What is the USB serial number of the first device in the coconut? This should be
* predictable on most platforms but macos catalina seems to have some problems with
* libusb
*/
unsigned char first_usb_serial[64];
/*
* Is this coconut valid or did we error out?
*/
bool valid;
};
/*
* Wifi coconut global context
*/
struct wifi_coconut_context {
/*
* USB context
*/
struct userspace_wifi_context *context;
/*
* All coconuts
* */
struct wifi_coconut *coconuts;
/*
* The coconut we're operating on
*/
struct wifi_coconut *coconut;
/*
* Diagnostics
*/
struct wifi_coconut_diagnostics diagnostics;
/*
* Runtime options
*/
bool disable_leds;
bool disable_blink;
bool invert_leds;
bool quiet;
bool ht40;
/*
* Target coconut device if we have multiple ones
*/
int coconut_number;
};
/*
* Search through a list of radios to try to find what looks like a
* wifi coconut.
*
* - A coconut will have 14 radios
* - All radios in a coconut are connected via hubs; they will either be
* on hub/subhub/radio or hub/radio
* - All radios in a coconut will be on the same base hub
* - All radios in a coconut will be rt2800usb
* - All radios in a coconut will be vid/pid 148f/5370
* - Radios will be organized as:
* {/foo}/base/1/[1..4]
* {/foo}/base/2/[1..4]
* {/foo}/base/3/[1..2]
* {/foo}/base/[4..7]
*
* We do a somewhat inefficient clustering of radios to try to find
* coconut groups.
*
* Coconuts will be numbered by their root hub ID because a user may
* plug in additional coconut devices later, which will get a higher
* root ID because of the USB topology
*
* We take control of the devicelist and parse it ourselves instead of
* using the for_each API.
*
*/
struct wifi_coconut_context *init_coconut_context();
/*
* Map the bus positions to device numbers so we can open
* them in order.
*/
const extern int device_number_map[7][4];
/*
* Find a coconut; returns negative on hard failure and one of the following
* on success or logical failure
*/
#define WIFI_COCONUT_FIND_CLUSTER_OK 0
#define WIFI_COCONUT_FIND_CLUSTER_NONE 1
#define WIFI_COCONUT_FIND_CLUSTER_PARTIAL 2
int find_coconuts_cluster(struct wifi_coconut_context *coconut_context,
struct userspace_wifi_probe_dev *devicelist,
struct wifi_coconut **coconut);
void free_coconuts(struct wifi_coconut *coconuts);
void print_wifi_coconuts(struct wifi_coconut *coconuts);
/*
* Open all the devices in a wifi coconut, setting each one to a channel
*/
int open_wifi_coconut(struct wifi_coconut_context *coconut_context, struct wifi_coconut *coconut);
/*
* Scan for coconuts. Optionally wait for a coconut to be found, and optionally
* call a callback function reporting the status of the search.
*
* When a coconut has been found, it will be assigned to the coconut context.
*
* When a proper coconut has been found, it will be opened. Final activation
* is deferred to the caller.
*
* This can be used by a tool to shim the searching methods.
*
* If a callback function is available it will be called with state updated
* during each phase, allowing it to format the user output as appropriate.
*
* In some situations, the callback function may return a 0 to continue operation
* or a negative to abort; these situations are:
* WIFI_COCONUT_SEARCH_STATE_NO_RADIOS (No usb devices found); allow the
* callback to cancel the normal behavior controlled by wait_for_coconut
* WIFI_COCONUT_SEARCH_STATE_NO_COCONUT (No complete coconut found); allow the
* callback to cancel the normal behavior controlled by wait_for_coconut
* WIFI_COCONUT_SEARCH_STATE_DEV_ERROR (Failure to open a device)
*/
/* Generic error */
#define WIFI_COCONUT_SEARCH_STATE_ERROR -1
/* Successful find and open of coconut */
#define WIFI_COCONUT_SEARCH_STATE_DONE 0
/* No USB radios of any sort detected */
#define WIFI_COCONUT_SEARCH_STATE_NO_RADIOS 1
/* No complete wifi coconut detected */
#define WIFI_COCONUT_SEARCH_STATE_NO_COCONUT 2
/* No coconut matching the specified coconut_number found */
#define WIFI_COCONUT_SEARCH_STATE_MISMATCH 3
/* Status update - target coconut has been found */
#define WIFI_COCONUT_SEARCH_STATE_FOUND 4
/* Status update - coconut device (in cb devnum) opened */
#define WIFI_COCONUT_SEARCH_STATE_DEV_OPENED 5
/* Status update - coconut device (in cb devnum) failed to open */
#define WIFI_COCONUT_SEARCH_STATE_DEV_ERROR 6
/* Status update - coconut device (in cb devnum) was not found */
#define WIFI_COCONUT_SEARCH_STATE_NO_DEV 7
/* Status update - one or more coconuts found, returned as list in cb coconut_list */
#define WIFI_COCONUT_SEARCH_STATE_LIST 8
int coconut_search_and_open(struct wifi_coconut_context *coconut_context,
bool wait_for_coconut, int coconut_number,
int (*status_callback)(struct wifi_coconut_context *, void *cb_aux,
int state, int devnum, struct wifi_coconut *coconut_list),
void *cb_aux);
/*
* Activate all the devices in a wifi coconut
*/
int start_wifi_coconut_capture(struct wifi_coconut_context *coconut_context);
#endif /* ifndef WIFI_COCONUT_H */

504
windows/LICENSE_LIBUSB.txt Normal file
View File

@ -0,0 +1,504 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 2.1, February 1999
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
[This is the first released version of the Lesser GPL. It also counts
as the successor of the GNU Library Public License, version 2, hence
the version number 2.1.]
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
Licenses are intended to guarantee your freedom to share and change
free software--to make sure the software is free for all its users.
This license, the Lesser General Public License, applies to some
specially designated software packages--typically libraries--of the
Free Software Foundation and other authors who decide to use it. You
can use it too, but we suggest you first think carefully about whether
this license or the ordinary General Public License is the better
strategy to use in any particular case, based on the explanations below.
When we speak of free software, we are referring to freedom of use,
not price. Our General Public Licenses are designed to make sure that
you have the freedom to distribute copies of free software (and charge
for this service if you wish); that you receive source code or can get
it if you want it; that you can change the software and use pieces of
it in new free programs; and that you are informed that you can do
these things.
To protect your rights, we need to make restrictions that forbid
distributors to deny you these rights or to ask you to surrender these
rights. These restrictions translate to certain responsibilities for
you if you distribute copies of the library or if you modify it.
For example, if you distribute copies of the library, whether gratis
or for a fee, you must give the recipients all the rights that we gave
you. You must make sure that they, too, receive or can get the source
code. If you link other code with the library, you must provide
complete object files to the recipients, so that they can relink them
with the library after making changes to the library and recompiling
it. And you must show them these terms so they know their rights.
We protect your rights with a two-step method: (1) we copyright the
library, and (2) we offer you this license, which gives you legal
permission to copy, distribute and/or modify the library.
To protect each distributor, we want to make it very clear that
there is no warranty for the free library. Also, if the library is
modified by someone else and passed on, the recipients should know
that what they have is not the original version, so that the original
author's reputation will not be affected by problems that might be
introduced by others.
Finally, software patents pose a constant threat to the existence of
any free program. We wish to make sure that a company cannot
effectively restrict the users of a free program by obtaining a
restrictive license from a patent holder. Therefore, we insist that
any patent license obtained for a version of the library must be
consistent with the full freedom of use specified in this license.
Most GNU software, including some libraries, is covered by the
ordinary GNU General Public License. This license, the GNU Lesser
General Public License, applies to certain designated libraries, and
is quite different from the ordinary General Public License. We use
this license for certain libraries in order to permit linking those
libraries into non-free programs.
When a program is linked with a library, whether statically or using
a shared library, the combination of the two is legally speaking a
combined work, a derivative of the original library. The ordinary
General Public License therefore permits such linking only if the
entire combination fits its criteria of freedom. The Lesser General
Public License permits more lax criteria for linking other code with
the library.
We call this license the "Lesser" General Public License because it
does Less to protect the user's freedom than the ordinary General
Public License. It also provides other free software developers Less
of an advantage over competing non-free programs. These disadvantages
are the reason we use the ordinary General Public License for many
libraries. However, the Lesser license provides advantages in certain
special circumstances.
For example, on rare occasions, there may be a special need to
encourage the widest possible use of a certain library, so that it becomes
a de-facto standard. To achieve this, non-free programs must be
allowed to use the library. A more frequent case is that a free
library does the same job as widely used non-free libraries. In this
case, there is little to gain by limiting the free library to free
software only, so we use the Lesser General Public License.
In other cases, permission to use a particular library in non-free
programs enables a greater number of people to use a large body of
free software. For example, permission to use the GNU C Library in
non-free programs enables many more people to use the whole GNU
operating system, as well as its variant, the GNU/Linux operating
system.
Although the Lesser General Public License is Less protective of the
users' freedom, it does ensure that the user of a program that is
linked with the Library has the freedom and the wherewithal to run
that program using a modified version of the Library.
The precise terms and conditions for copying, distribution and
modification follow. Pay close attention to the difference between a
"work based on the library" and a "work that uses the library". The
former contains code derived from the library, whereas the latter must
be combined with the library in order to run.
GNU LESSER GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any software library or other
program which contains a notice placed by the copyright holder or
other authorized party saying it may be distributed under the terms of
this Lesser General Public License (also called "this License").
Each licensee is addressed as "you".
A "library" means a collection of software functions and/or data
prepared so as to be conveniently linked with application programs
(which use some of those functions and data) to form executables.
The "Library", below, refers to any such software library or work
which has been distributed under these terms. A "work based on the
Library" means either the Library or any derivative work under
copyright law: that is to say, a work containing the Library or a
portion of it, either verbatim or with modifications and/or translated
straightforwardly into another language. (Hereinafter, translation is
included without limitation in the term "modification".)
"Source code" for a work means the preferred form of the work for
making modifications to it. For a library, complete source code means
all the source code for all modules it contains, plus any associated
interface definition files, plus the scripts used to control compilation
and installation of the library.
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running a program using the Library is not restricted, and output from
such a program is covered only if its contents constitute a work based
on the Library (independent of the use of the Library in a tool for
writing it). Whether that is true depends on what the Library does
and what the program that uses the Library does.
1. You may copy and distribute verbatim copies of the Library's
complete source code as you receive it, in any medium, provided that
you conspicuously and appropriately publish on each copy an
appropriate copyright notice and disclaimer of warranty; keep intact
all the notices that refer to this License and to the absence of any
warranty; and distribute a copy of this License along with the
Library.
You may charge a fee for the physical act of transferring a copy,
and you may at your option offer warranty protection in exchange for a
fee.
2. You may modify your copy or copies of the Library or any portion
of it, thus forming a work based on the Library, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) The modified work must itself be a software library.
b) You must cause the files modified to carry prominent notices
stating that you changed the files and the date of any change.
c) You must cause the whole of the work to be licensed at no
charge to all third parties under the terms of this License.
d) If a facility in the modified Library refers to a function or a
table of data to be supplied by an application program that uses
the facility, other than as an argument passed when the facility
is invoked, then you must make a good faith effort to ensure that,
in the event an application does not supply such function or
table, the facility still operates, and performs whatever part of
its purpose remains meaningful.
(For example, a function in a library to compute square roots has
a purpose that is entirely well-defined independent of the
application. Therefore, Subsection 2d requires that any
application-supplied function or table used by this function must
be optional: if the application does not supply it, the square
root function must still compute square roots.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Library,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Library, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote
it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Library.
In addition, mere aggregation of another work not based on the Library
with the Library (or with a work based on the Library) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may opt to apply the terms of the ordinary GNU General Public
License instead of this License to a given copy of the Library. To do
this, you must alter all the notices that refer to this License, so
that they refer to the ordinary GNU General Public License, version 2,
instead of to this License. (If a newer version than version 2 of the
ordinary GNU General Public License has appeared, then you can specify
that version instead if you wish.) Do not make any other change in
these notices.
Once this change is made in a given copy, it is irreversible for
that copy, so the ordinary GNU General Public License applies to all
subsequent copies and derivative works made from that copy.
This option is useful when you wish to copy part of the code of
the Library into a program that is not a library.
4. You may copy and distribute the Library (or a portion or
derivative of it, under Section 2) in object code or executable form
under the terms of Sections 1 and 2 above provided that you accompany
it with the complete corresponding machine-readable source code, which
must be distributed under the terms of Sections 1 and 2 above on a
medium customarily used for software interchange.
If distribution of object code is made by offering access to copy
from a designated place, then offering equivalent access to copy the
source code from the same place satisfies the requirement to
distribute the source code, even though third parties are not
compelled to copy the source along with the object code.
5. A program that contains no derivative of any portion of the
Library, but is designed to work with the Library by being compiled or
linked with it, is called a "work that uses the Library". Such a
work, in isolation, is not a derivative work of the Library, and
therefore falls outside the scope of this License.
However, linking a "work that uses the Library" with the Library
creates an executable that is a derivative of the Library (because it
contains portions of the Library), rather than a "work that uses the
library". The executable is therefore covered by this License.
Section 6 states terms for distribution of such executables.
When a "work that uses the Library" uses material from a header file
that is part of the Library, the object code for the work may be a
derivative work of the Library even though the source code is not.
Whether this is true is especially significant if the work can be
linked without the Library, or if the work is itself a library. The
threshold for this to be true is not precisely defined by law.
If such an object file uses only numerical parameters, data
structure layouts and accessors, and small macros and small inline
functions (ten lines or less in length), then the use of the object
file is unrestricted, regardless of whether it is legally a derivative
work. (Executables containing this object code plus portions of the
Library will still fall under Section 6.)
Otherwise, if the work is a derivative of the Library, you may
distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.
6. As an exception to the Sections above, you may also combine or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
under terms of your choice, provided that the terms permit
modification of the work for the customer's own use and reverse
engineering for debugging such modifications.
You must give prominent notice with each copy of the work that the
Library is used in it and that the Library and its use are covered by
this License. You must supply a copy of this License. If the work
during execution displays copyright notices, you must include the
copyright notice for the Library among them, as well as a reference
directing the user to the copy of this License. Also, you must do one
of these things:
a) Accompany the work with the complete corresponding
machine-readable source code for the Library including whatever
changes were used in the work (which must be distributed under
Sections 1 and 2 above); and, if the work is an executable linked
with the Library, with the complete machine-readable "work that
uses the Library", as object code and/or source code, so that the
user can modify the Library and then relink to produce a modified
executable containing the modified Library. (It is understood
that the user who changes the contents of definitions files in the
Library will not necessarily be able to recompile the application
to use the modified definitions.)
b) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (1) uses at run time a
copy of the library already present on the user's computer system,
rather than copying library functions into the executable, and (2)
will operate properly with a modified version of the library, if
the user installs one, as long as the modified version is
interface-compatible with the version that the work was made with.
c) Accompany the work with a written offer, valid for at
least three years, to give the same user the materials
specified in Subsection 6a, above, for a charge no more
than the cost of performing this distribution.
d) If distribution of the work is made by offering access to copy
from a designated place, offer equivalent access to copy the above
specified materials from the same place.
e) Verify that the user has already received a copy of these
materials or that you have already sent this user a copy.
For an executable, the required form of the "work that uses the
Library" must include any data and utility programs needed for
reproducing the executable from it. However, as a special exception,
the materials to be distributed need not include anything that is
normally distributed (in either source or binary form) with the major
components (compiler, kernel, and so on) of the operating system on
which the executable runs, unless that component itself accompanies
the executable.
It may happen that this requirement contradicts the license
restrictions of other proprietary libraries that do not normally
accompany the operating system. Such a contradiction means you cannot
use both them and the Library together in an executable that you
distribute.
7. You may place library facilities that are a work based on the
Library side-by-side in a single library together with other library
facilities not covered by this License, and distribute such a combined
library, provided that the separate distribution of the work based on
the Library and of the other library facilities is otherwise
permitted, and provided that you do these two things:
a) Accompany the combined library with a copy of the same work
based on the Library, uncombined with any other library
facilities. This must be distributed under the terms of the
Sections above.
b) Give prominent notice with the combined library of the fact
that part of it is a work based on the Library, and explaining
where to find the accompanying uncombined form of the same work.
8. You may not copy, modify, sublicense, link with, or distribute
the Library except as expressly provided under this License. Any
attempt otherwise to copy, modify, sublicense, link with, or
distribute the Library is void, and will automatically terminate your
rights under this License. However, parties who have received copies,
or rights, from you under this License will not have their licenses
terminated so long as such parties remain in full compliance.
9. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Library or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Library (or any work based on the
Library), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Library or works based on it.
10. Each time you redistribute the Library (or any work based on the
Library), the recipient automatically receives a license from the
original licensor to copy, distribute, link with or modify the Library
subject to these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties with
this License.
11. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Library at all. For example, if a patent
license would not permit royalty-free redistribution of the Library by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Library.
If any portion of this section is held invalid or unenforceable under any
particular circumstance, the balance of the section is intended to apply,
and the section as a whole is intended to apply in other circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
12. If the distribution and/or use of the Library is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Library under this License may add
an explicit geographical distribution limitation excluding those countries,
so that distribution is permitted only in or among countries not thus
excluded. In such case, this License incorporates the limitation as if
written in the body of this License.
13. The Free Software Foundation may publish revised and/or new
versions of the Lesser General Public License from time to time.
Such new versions will be similar in spirit to the present version,
but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Library
specifies a version number of this License which applies to it and
"any later version", you have the option of following the terms and
conditions either of that version or of any later version published by
the Free Software Foundation. If the Library does not specify a
license version number, you may choose any version ever published by
the Free Software Foundation.
14. If you wish to incorporate parts of the Library into other free
programs whose distribution conditions are incompatible with these,
write to the author to ask for permission. For software which is
copyrighted by the Free Software Foundation, write to the Free
Software Foundation; we sometimes make exceptions for this. Our
decision will be guided by the two goals of preserving the free status
of all derivatives of our free software and of promoting the sharing
and reuse of software generally.
NO WARRANTY
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Libraries
If you develop a new library, and you want it to be of the greatest
possible use to the public, we recommend making it free software that
everyone can redistribute and change. You can do so by permitting
redistribution under these terms (or, alternatively, under the terms of the
ordinary General Public License).
To apply these terms, attach the following notices to the library. It is
safest to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least the
"copyright" line and a pointer to where the full notice is found.
<one line to give the library's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Also add information on how to contact you by electronic and paper mail.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the library, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
<signature of Ty Coon>, 1 April 1990
Ty Coon, President of Vice
That's all there is to it!

View File

@ -0,0 +1,148 @@
pthreads-win32 License -
a POSIX threads library for Microsoft Windows
This file is Copyrighted
------------------------
This file is covered under the following Copyright:
Copyright © 2001,2006 Ross P. Johnson
All rights reserved.
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Pthreads-win32 is covered by the GNU Lesser General Public License
------------------------------------------------------------------
Pthreads-win32 is open 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.
Pthreads-win32 is several binary link libraries, several modules,
associated interface definition files and scripts used to control
its compilation and installation.
Pthreads-win32 is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
A copy of the GNU Lesser General Public License is distributed with
pthreads-win32 under the filename:
COPYING.LIB
You should have received a copy of the version 2.1 GNU Lesser General
Public License with pthreads-win32; if not, write to:
Free Software Foundation, Inc.
59 Temple Place
Suite 330
Boston, MA 02111-1307
USA
The contact addresses for pthreads-win32 is as follows:
Web: https://sources.redhat.com/pthreads-win32
Email: Ross Johnson
Please use: Firstname.Lastname@homemail.com.au
Pthreads-win32 copyrights and exception files
---------------------------------------------
With the exception of the files listed below, Pthreads-win32
is covered under the following GNU Lesser General Public License
Copyrights:
Pthreads-win32 - POSIX Threads Library for Win32
Copyright © 1998 John E. Bossom
Copyright © 1999,2006 Pthreads-win32 contributors
The current list of contributors is contained
in the file CONTRIBUTORS included with the source
code distribution. The current list of CONTRIBUTORS
can also be seen at the following WWW location:
https://sources.redhat.com/pthreads-win32/contributors.html
Contact Email: Ross Johnson
Please use: Firstname.Lastname@homemail.com.au
These files are not covered under one of the Copyrights listed above:
COPYING
COPYING.LIB
tests/rwlock7.c
This file, COPYING, is distributed under the Copyright found at the
top of this file. It is important to note that you may distribute
verbatim copies of this file but you may not modify this file.
The file COPYING.LIB, which contains a copy of the version 2.1
GNU Lesser General Public License, is itself copyrighted by the
Free Software Foundation, Inc. Please note that the Free Software
Foundation, Inc. does NOT have a copyright over Pthreads-win32,
only the COPYING.LIB that is supplied with pthreads-win32.
The file tests/rwlock7.c is derived from code written by
Dave Butenhof for his book 'Programming With POSIX(R) Threads'.
The original code was obtained by free download from his website
https://home.earthlink.net/~anneart/family/Threads/source.html
and did not contain a copyright or author notice. It is assumed to
be freely distributable.
In all cases one may use and distribute these exception files freely.
And because one may freely distribute the LGPL covered files, the
entire pthreads-win32 source may be freely used and distributed.
General Copyleft and License info
---------------------------------
For general information on Copylefts, see:
https://www.gnu.org/copyleft/
For information on GNU Lesser General Public Licenses, see:
https://www.gnu.org/copyleft/lesser.html
https://www.gnu.org/copyleft/lesser.txt
Why pthreads-win32 did not use the GNU General Public License
-------------------------------------------------------------
The goal of the pthreads-win32 project has been to
provide a quality and complete implementation of the POSIX
threads API for Microsoft Windows within the limits imposed
by virtue of it being a stand-alone library and not
linked directly to other POSIX compliant libraries. For
example, some functions and features, such as those based
on POSIX signals, are missing.
Pthreads-win32 is a library, available in several different
versions depending on supported compilers, and may be used
as a dynamically linked module or a statically linked set of
binary modules. It is not an application on it's own.
It was fully intended that pthreads-win32 be usable with
commercial software not covered by either the GPL or the LGPL
licenses. Pthreads-win32 has many contributors to it's
code base, many of whom have done so because they have
used the library in commercial or proprietry software
projects.
Releasing pthreads-win32 under the LGPL ensures that the
library can be used widely, while at the same time ensures
that bug fixes and improvements to the pthreads-win32 code
itself is returned to benefit all current and future users
of the library.
Although pthreads-win32 makes it possible for applications
that use POSIX threads to be ported to Win32 platforms, the
broader goal of the project is to encourage the use of open
standards, and in particular, to make it just a little easier
for developers writing Win32 applications to consider
widening the potential market for their products.

65
windows/README.txt Executable file
View File

@ -0,0 +1,65 @@
Wi-Fi Coconut Win64
** Requirements **
You MUST INSTALL THE ZADIG USB DRIVERS BEFORE CONNECTING YOUR WI-FI COCONUT
or THERE IS A RISK OF HARDWARE DAMAGE.
** Installing **
1. Download Zadig from https://zadig.akeo.ie
2. Run the Zadig tool
3. From the menus, select Device->Create New Device
4. Enter "RT2800" in the name field (the large field next to the
checkbox named "Edit")
5. Under USB ID enter:
148F 5370
Leave the third field next to USB ID blank.
6. Click "Install Driver". Zadig may appear to hang - just wait!
Zadig will then install the USB drivers required for raw
access to the radio.
NOTE: Installing the Zadig drivers for the rt2800 family of Wi-Fi cards
will disable any other Wi-Fi cards using this chipset. These Wi-Fi cards
are USB ONLY and this will typically not affect the built-in Wi-Fi card
on your system, however if your device ONLY HAS USB for Wi-Fi you should
MAKE SURE IT DOES NOT USE THE rt2800 CHIPSET.
IF YOU ARE UNSURE, we recommend TAKING A SYSTEM SNAPSHOT before installing
the Zadig drivers!
** Running **
1. Plug in coconut
2. Open a terminal, navigate to coconut download
3. Run .\wifi_coconut.exe --help for info
Useful commands:
.\wifi_coconut.exe --diagnostics-only
.\wifi_coconut.exe foo.pcap
.\wifi_coconut.exe --diagnostics foo.pcap
** Controlling LEDs **
By default the Wi-Fi Coconut enables all LEDs. LEDs blink when there is traffic on
the corresponding channel.
The Wi-Fi Coconut can be used in "stealth mode" by disabling LEDs entirely:
.\wifi_coconut.exe --disable-leds foo.pcap
The LEDs can be inverted, so that they are normally off and blink only when there is
traffic:
.\wifi_coconut.exe --invert-leds foo.pcap
If blinking LEDs causes a health issue or is annoying, LED blinking can be disabled
with:
.\wifi_coconut.exe --disable-blinking
The LEDs will still light up as the radio is enabled, but will not strobe.

View File

@ -0,0 +1,6 @@
xcopy ..\libwifiuserspace\firmware\* Release\
copy ..\windows\README.txt Release\.
copy ..\windows\LICENSE_LIBUSB.txt Release\.
copy ..\windows\LICENSE_PTHREADS.txt Release\.
copy ..\LICENSE Release\License.txt